#include "clang/Parse/Parser.h"
#include "RAIIObjectsForParser.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
using namespace clang;
Decl *
Parser::ParseDeclarationStartingWithTemplate(unsigned Context,
SourceLocation &DeclEnd,
AccessSpecifier AS,
AttributeList *AccessAttrs) {
ObjCDeclContextSwitch ObjCDC(*this);
if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) {
return ParseExplicitInstantiation(Context,
SourceLocation(), ConsumeToken(),
DeclEnd, AS);
}
return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS,
AccessAttrs);
}
Decl *
Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
SourceLocation &DeclEnd,
AccessSpecifier AS,
AttributeList *AccessAttrs) {
assert((Tok.is(tok::kw_export) || Tok.is(tok::kw_template)) &&
"Token does not start a template declaration.");
ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
ParsingDeclRAIIObject
ParsingTemplateParams(*this, ParsingDeclRAIIObject::NoParent);
bool isSpecialization = true;
bool LastParamListWasEmpty = false;
TemplateParameterLists ParamLists;
TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
do {
SourceLocation ExportLoc;
if (Tok.is(tok::kw_export)) {
ExportLoc = ConsumeToken();
}
SourceLocation TemplateLoc;
if (Tok.is(tok::kw_template)) {
TemplateLoc = ConsumeToken();
} else {
Diag(Tok.getLocation(), diag::err_expected_template);
return 0;
}
SourceLocation LAngleLoc, RAngleLoc;
SmallVector<Decl*, 4> TemplateParams;
if (ParseTemplateParameters(CurTemplateDepthTracker.getDepth(),
TemplateParams, LAngleLoc, RAngleLoc)) {
SkipUntil(tok::r_brace, true, true);
if (Tok.is(tok::semi))
ConsumeToken();
return 0;
}
ParamLists.push_back(
Actions.ActOnTemplateParameterList(CurTemplateDepthTracker.getDepth(),
ExportLoc,
TemplateLoc, LAngleLoc,
TemplateParams.data(),
TemplateParams.size(), RAngleLoc));
if (!TemplateParams.empty()) {
isSpecialization = false;
++CurTemplateDepthTracker;
} else {
LastParamListWasEmpty = true;
}
} while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
return ParseSingleDeclarationAfterTemplate(Context,
ParsedTemplateInfo(&ParamLists,
isSpecialization,
LastParamListWasEmpty),
ParsingTemplateParams,
DeclEnd, AS, AccessAttrs);
}
Decl *
Parser::ParseSingleDeclarationAfterTemplate(
unsigned Context,
const ParsedTemplateInfo &TemplateInfo,
ParsingDeclRAIIObject &DiagsFromTParams,
SourceLocation &DeclEnd,
AccessSpecifier AS,
AttributeList *AccessAttrs) {
assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
"Template information required");
if (Context == Declarator::MemberContext) {
ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo,
&DiagsFromTParams);
return 0;
}
ParsedAttributesWithRange prefixAttrs(AttrFactory);
MaybeParseCXX11Attributes(prefixAttrs);
if (Tok.is(tok::kw_using))
return ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd,
prefixAttrs);
ParsingDeclSpec DS(*this, &DiagsFromTParams);
ParseDeclarationSpecifiers(DS, TemplateInfo, AS,
getDeclSpecContextFromDeclaratorContext(Context));
if (Tok.is(tok::semi)) {
ProhibitAttributes(prefixAttrs);
DeclEnd = ConsumeToken();
Decl *Decl = Actions.ParsedFreeStandingDeclSpec(
getCurScope(), AS, DS,
TemplateInfo.TemplateParams ? *TemplateInfo.TemplateParams
: MultiTemplateParamsArg(),
TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation);
DS.complete(Decl);
return Decl;
}
if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
ProhibitAttributes(prefixAttrs);
else
DS.takeAttributesFrom(prefixAttrs);
ParsingDeclarator DeclaratorInfo(*this, DS, (Declarator::TheContext)Context);
ParseDeclarator(DeclaratorInfo);
if (!DeclaratorInfo.hasName()) {
SkipUntil(tok::r_brace, true, true);
if (Tok.is(tok::semi))
ConsumeToken();
return 0;
}
LateParsedAttrList LateParsedAttrs(true);
if (DeclaratorInfo.isFunctionDeclarator())
MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs);
if (DeclaratorInfo.isFunctionDeclarator() &&
isStartOfFunctionDefinition(DeclaratorInfo)) {
if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
Diag(DS.getStorageClassSpecLoc(), diag::err_function_declared_typedef)
<< FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
DS.ClearStorageClassSpecs();
}
if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
if (DeclaratorInfo.getName().getKind() != UnqualifiedId::IK_TemplateId) {
Diag(Tok, diag::err_template_defn_explicit_instantiation) << 0;
return ParseFunctionDefinition(DeclaratorInfo, ParsedTemplateInfo(),
&LateParsedAttrs);
} else {
SourceLocation LAngleLoc
= PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
Diag(DeclaratorInfo.getIdentifierLoc(),
diag::err_explicit_instantiation_with_definition)
<< SourceRange(TemplateInfo.TemplateLoc)
<< FixItHint::CreateInsertion(LAngleLoc, "<>");
TemplateParameterLists FakedParamLists;
FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, 0, 0,
LAngleLoc));
return ParseFunctionDefinition(
DeclaratorInfo, ParsedTemplateInfo(&FakedParamLists,
true,
true),
&LateParsedAttrs);
}
}
return ParseFunctionDefinition(DeclaratorInfo, TemplateInfo,
&LateParsedAttrs);
}
Decl *ThisDecl = ParseDeclarationAfterDeclarator(DeclaratorInfo,
TemplateInfo);
if (Tok.is(tok::comma)) {
Diag(Tok, diag::err_multiple_template_declarators)
<< (int)TemplateInfo.Kind;
SkipUntil(tok::semi, true, false);
return ThisDecl;
}
ExpectAndConsumeSemi(diag::err_expected_semi_declaration);
if (LateParsedAttrs.size() > 0)
ParseLexedAttributeList(LateParsedAttrs, ThisDecl, true, false);
DeclaratorInfo.complete(ThisDecl);
return ThisDecl;
}
bool Parser::ParseTemplateParameters(unsigned Depth,
SmallVectorImpl<Decl*> &TemplateParams,
SourceLocation &LAngleLoc,
SourceLocation &RAngleLoc) {
if (!Tok.is(tok::less)) {
Diag(Tok.getLocation(), diag::err_expected_less_after) << "template";
return true;
}
LAngleLoc = ConsumeToken();
bool Failed = false;
if (!Tok.is(tok::greater) && !Tok.is(tok::greatergreater))
Failed = ParseTemplateParameterList(Depth, TemplateParams);
if (Tok.is(tok::greatergreater)) {
Tok.setKind(tok::greater);
RAngleLoc = Tok.getLocation();
Tok.setLocation(Tok.getLocation().getLocWithOffset(1));
} else if (Tok.is(tok::greater))
RAngleLoc = ConsumeToken();
else if (Failed) {
Diag(Tok.getLocation(), diag::err_expected_greater);
return true;
}
return false;
}
bool
Parser::ParseTemplateParameterList(unsigned Depth,
SmallVectorImpl<Decl*> &TemplateParams) {
while (1) {
if (Decl *TmpParam
= ParseTemplateParameter(Depth, TemplateParams.size())) {
TemplateParams.push_back(TmpParam);
} else {
SkipUntil(tok::comma, tok::greater, tok::greatergreater, true, true);
}
if (Tok.is(tok::comma)) {
ConsumeToken();
} else if (Tok.is(tok::greater) || Tok.is(tok::greatergreater)) {
break;
} else {
Diag(Tok.getLocation(), diag::err_expected_comma_greater);
SkipUntil(tok::comma, tok::greater, tok::greatergreater, true, true);
return false;
}
}
return true;
}
bool Parser::isStartOfTemplateTypeParameter() {
if (Tok.is(tok::kw_class)) {
switch (NextToken().getKind()) {
case tok::equal:
case tok::comma:
case tok::greater:
case tok::greatergreater:
case tok::ellipsis:
return true;
case tok::identifier:
break;
default:
return false;
}
switch (GetLookAheadToken(2).getKind()) {
case tok::equal:
case tok::comma:
case tok::greater:
case tok::greatergreater:
return true;
default:
return false;
}
}
if (Tok.isNot(tok::kw_typename))
return false;
Token Next = NextToken();
if (Next.getKind() == tok::identifier)
Next = GetLookAheadToken(2);
switch (Next.getKind()) {
case tok::equal:
case tok::comma:
case tok::greater:
case tok::greatergreater:
case tok::ellipsis:
return true;
default:
return false;
}
}
Decl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
if (isStartOfTemplateTypeParameter())
return ParseTypeParameter(Depth, Position);
if (Tok.is(tok::kw_template))
return ParseTemplateTemplateParameter(Depth, Position);
return ParseNonTypeTemplateParameter(Depth, Position);
}
Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
assert((Tok.is(tok::kw_class) || Tok.is(tok::kw_typename)) &&
"A type-parameter starts with 'class' or 'typename'");
bool TypenameKeyword = Tok.is(tok::kw_typename);
SourceLocation KeyLoc = ConsumeToken();
bool Ellipsis = false;
SourceLocation EllipsisLoc;
if (Tok.is(tok::ellipsis)) {
Ellipsis = true;
EllipsisLoc = ConsumeToken();
Diag(EllipsisLoc,
getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_variadic_templates
: diag::ext_variadic_templates);
}
SourceLocation NameLoc;
IdentifierInfo* ParamName = 0;
if (Tok.is(tok::identifier)) {
ParamName = Tok.getIdentifierInfo();
NameLoc = ConsumeToken();
} else if (Tok.is(tok::equal) || Tok.is(tok::comma) ||
Tok.is(tok::greater) || Tok.is(tok::greatergreater)) {
} else {
Diag(Tok.getLocation(), diag::err_expected_ident);
return 0;
}
SourceLocation EqualLoc;
ParsedType DefaultArg;
if (Tok.is(tok::equal)) {
EqualLoc = ConsumeToken();
DefaultArg = ParseTypeName(0,
Declarator::TemplateTypeArgContext).get();
}
return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, Ellipsis,
EllipsisLoc, KeyLoc, ParamName, NameLoc,
Depth, Position, EqualLoc, DefaultArg);
}
Decl *
Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
assert(Tok.is(tok::kw_template) && "Expected 'template' keyword");
SourceLocation TemplateLoc = ConsumeToken();
SmallVector<Decl*,8> TemplateParams;
SourceLocation LAngleLoc, RAngleLoc;
{
ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
if (ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc,
RAngleLoc)) {
return 0;
}
}
if (!Tok.is(tok::kw_class)) {
bool Replace = Tok.is(tok::kw_typename) || Tok.is(tok::kw_struct);
const Token& Next = Replace ? NextToken() : Tok;
if (Next.is(tok::identifier) || Next.is(tok::comma) ||
Next.is(tok::greater) || Next.is(tok::greatergreater) ||
Next.is(tok::ellipsis))
Diag(Tok.getLocation(), diag::err_class_on_template_template_param)
<< (Replace ? FixItHint::CreateReplacement(Tok.getLocation(), "class")
: FixItHint::CreateInsertion(Tok.getLocation(), "class "));
else
Diag(Tok.getLocation(), diag::err_class_on_template_template_param);
if (Replace)
ConsumeToken();
} else
ConsumeToken();
SourceLocation EllipsisLoc;
if (Tok.is(tok::ellipsis)) {
EllipsisLoc = ConsumeToken();
Diag(EllipsisLoc,
getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_variadic_templates
: diag::ext_variadic_templates);
}
SourceLocation NameLoc;
IdentifierInfo* ParamName = 0;
if (Tok.is(tok::identifier)) {
ParamName = Tok.getIdentifierInfo();
NameLoc = ConsumeToken();
} else if (Tok.is(tok::equal) || Tok.is(tok::comma) ||
Tok.is(tok::greater) || Tok.is(tok::greatergreater)) {
} else {
Diag(Tok.getLocation(), diag::err_expected_ident);
return 0;
}
TemplateParameterList *ParamList =
Actions.ActOnTemplateParameterList(Depth, SourceLocation(),
TemplateLoc, LAngleLoc,
TemplateParams.data(),
TemplateParams.size(),
RAngleLoc);
SourceLocation EqualLoc;
ParsedTemplateArgument DefaultArg;
if (Tok.is(tok::equal)) {
EqualLoc = ConsumeToken();
DefaultArg = ParseTemplateTemplateArgument();
if (DefaultArg.isInvalid()) {
Diag(Tok.getLocation(),
diag::err_default_template_template_parameter_not_template);
SkipUntil(tok::comma, tok::greater, tok::greatergreater, true, true);
}
}
return Actions.ActOnTemplateTemplateParameter(getCurScope(), TemplateLoc,
ParamList, EllipsisLoc,
ParamName, NameLoc, Depth,
Position, EqualLoc, DefaultArg);
}
Decl *
Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
DeclSpec DS(AttrFactory);
ParseDeclarationSpecifiers(DS);
Declarator ParamDecl(DS, Declarator::TemplateParamContext);
ParseDeclarator(ParamDecl);
if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {
Diag(Tok.getLocation(), diag::err_expected_template_parameter);
return 0;
}
SourceLocation EqualLoc;
ExprResult DefaultArg;
if (Tok.is(tok::equal)) {
EqualLoc = ConsumeToken();
GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
DefaultArg = ParseAssignmentExpression();
if (DefaultArg.isInvalid())
SkipUntil(tok::comma, tok::greater, true, true);
}
return Actions.ActOnNonTypeTemplateParameter(getCurScope(), ParamDecl,
Depth, Position, EqualLoc,
DefaultArg.take());
}
bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
bool ConsumeLastToken) {
tok::TokenKind RemainingToken;
const char *ReplacementStr = "> >";
switch (Tok.getKind()) {
default:
Diag(Tok.getLocation(), diag::err_expected_greater);
return true;
case tok::greater:
RAngleLoc = Tok.getLocation();
if (ConsumeLastToken)
ConsumeToken();
return false;
case tok::greatergreater:
RemainingToken = tok::greater;
break;
case tok::greatergreatergreater:
RemainingToken = tok::greatergreater;
break;
case tok::greaterequal:
RemainingToken = tok::equal;
ReplacementStr = "> =";
break;
case tok::greatergreaterequal:
RemainingToken = tok::greaterequal;
break;
}
RAngleLoc = Tok.getLocation();
CharSourceRange ReplacementRange =
CharSourceRange::getCharRange(RAngleLoc,
Lexer::AdvanceToTokenCharacter(RAngleLoc, 2, PP.getSourceManager(),
getLangOpts()));
FixItHint Hint1 = FixItHint::CreateReplacement(ReplacementRange,
ReplacementStr);
FixItHint Hint2;
Token Next = NextToken();
if ((RemainingToken == tok::greater ||
RemainingToken == tok::greatergreater) &&
(Next.is(tok::greater) || Next.is(tok::greatergreater) ||
Next.is(tok::greatergreatergreater) || Next.is(tok::equal) ||
Next.is(tok::greaterequal) || Next.is(tok::greatergreaterequal) ||
Next.is(tok::equalequal)) &&
areTokensAdjacent(Tok, Next))
Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " ");
unsigned DiagId = diag::err_two_right_angle_brackets_need_space;
if (getLangOpts().CPlusPlus11 && Tok.is(tok::greatergreater))
DiagId = diag::warn_cxx98_compat_two_right_angle_brackets;
else if (Tok.is(tok::greaterequal))
DiagId = diag::err_right_angle_bracket_equal_needs_space;
Diag(Tok.getLocation(), DiagId) << Hint1 << Hint2;
if (RemainingToken == tok::equal && Next.is(tok::equal) &&
areTokensAdjacent(Tok, Next)) {
ConsumeToken();
Tok.setKind(tok::equalequal);
Tok.setLength(Tok.getLength() + 1);
} else {
Tok.setKind(RemainingToken);
Tok.setLength(Tok.getLength() - 1);
}
Tok.setLocation(Lexer::AdvanceToTokenCharacter(RAngleLoc, 1,
PP.getSourceManager(),
getLangOpts()));
if (!ConsumeLastToken) {
PP.EnterToken(Tok);
Tok.setKind(tok::greater);
Tok.setLength(1);
Tok.setLocation(RAngleLoc);
}
return false;
}
bool
Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template,
SourceLocation TemplateNameLoc,
const CXXScopeSpec &SS,
bool ConsumeLastToken,
SourceLocation &LAngleLoc,
TemplateArgList &TemplateArgs,
SourceLocation &RAngleLoc) {
assert(Tok.is(tok::less) && "Must have already parsed the template-name");
LAngleLoc = ConsumeToken();
bool Invalid = false;
{
GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
if (Tok.isNot(tok::greater) && Tok.isNot(tok::greatergreater))
Invalid = ParseTemplateArgumentList(TemplateArgs);
if (Invalid) {
SkipUntil(tok::greater, true, !ConsumeLastToken);
return true;
}
}
return ParseGreaterThanInTemplateList(RAngleLoc, ConsumeLastToken);
}
bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
UnqualifiedId &TemplateName,
bool AllowTypeAnnotation) {
assert(getLangOpts().CPlusPlus && "Can only annotate template-ids in C++");
assert(Template && Tok.is(tok::less) &&
"Parser isn't at the beginning of a template-id");
SourceLocation TemplateNameLoc = TemplateName.getSourceRange().getBegin();
SourceLocation LAngleLoc, RAngleLoc;
TemplateArgList TemplateArgs;
bool Invalid = ParseTemplateIdAfterTemplateName(Template,
TemplateNameLoc,
SS, false, LAngleLoc,
TemplateArgs,
RAngleLoc);
if (Invalid) {
if (Tok.is(tok::greater))
ConsumeToken();
return true;
}
ASTTemplateArgsPtr TemplateArgsPtr(TemplateArgs);
if (TNK == TNK_Type_template && AllowTypeAnnotation) {
TypeResult Type
= Actions.ActOnTemplateIdType(SS, TemplateKWLoc,
Template, TemplateNameLoc,
LAngleLoc, TemplateArgsPtr, RAngleLoc);
if (Type.isInvalid()) {
if (Tok.is(tok::greater))
ConsumeToken();
return true;
}
Tok.setKind(tok::annot_typename);
setTypeAnnotation(Tok, Type.get());
if (SS.isNotEmpty())
Tok.setLocation(SS.getBeginLoc());
else if (TemplateKWLoc.isValid())
Tok.setLocation(TemplateKWLoc);
else
Tok.setLocation(TemplateNameLoc);
} else {
Tok.setKind(tok::annot_template_id);
TemplateIdAnnotation *TemplateId
= TemplateIdAnnotation::Allocate(TemplateArgs.size(), TemplateIds);
TemplateId->TemplateNameLoc = TemplateNameLoc;
if (TemplateName.getKind() == UnqualifiedId::IK_Identifier) {
TemplateId->Name = TemplateName.Identifier;
TemplateId->Operator = OO_None;
} else {
TemplateId->Name = 0;
TemplateId->Operator = TemplateName.OperatorFunctionId.Operator;
}
TemplateId->SS = SS;
TemplateId->TemplateKWLoc = TemplateKWLoc;
TemplateId->Template = Template;
TemplateId->Kind = TNK;
TemplateId->LAngleLoc = LAngleLoc;
TemplateId->RAngleLoc = RAngleLoc;
ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
Args[Arg] = ParsedTemplateArgument(TemplateArgs[Arg]);
Tok.setAnnotationValue(TemplateId);
if (TemplateKWLoc.isValid())
Tok.setLocation(TemplateKWLoc);
else
Tok.setLocation(TemplateNameLoc);
}
Tok.setAnnotationEndLoc(RAngleLoc);
PP.AnnotateCachedTokens(Tok);
return false;
}
void Parser::AnnotateTemplateIdTokenAsType() {
assert(Tok.is(tok::annot_template_id) && "Requires template-id tokens");
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
assert((TemplateId->Kind == TNK_Type_template ||
TemplateId->Kind == TNK_Dependent_template_name) &&
"Only works for type and dependent templates");
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
TemplateId->NumArgs);
TypeResult Type
= Actions.ActOnTemplateIdType(TemplateId->SS,
TemplateId->TemplateKWLoc,
TemplateId->Template,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
TemplateId->RAngleLoc);
Tok.setKind(tok::annot_typename);
setTypeAnnotation(Tok, Type.isInvalid() ? ParsedType() : Type.get());
if (TemplateId->SS.isNotEmpty()) Tok.setLocation(TemplateId->SS.getBeginLoc());
PP.AnnotateCachedTokens(Tok);
}
static bool isEndOfTemplateArgument(Token Tok) {
return Tok.is(tok::comma) || Tok.is(tok::greater) ||
Tok.is(tok::greatergreater);
}
ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
if (!Tok.is(tok::identifier) && !Tok.is(tok::coloncolon) &&
!Tok.is(tok::annot_cxxscope))
return ParsedTemplateArgument();
CXXScopeSpec SS; ParseOptionalCXXScopeSpecifier(SS, ParsedType(),
false);
ParsedTemplateArgument Result;
SourceLocation EllipsisLoc;
if (SS.isSet() && Tok.is(tok::kw_template)) {
SourceLocation TemplateKWLoc = ConsumeToken();
if (Tok.is(tok::identifier)) {
UnqualifiedId Name;
Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
ConsumeToken();
if (Tok.is(tok::ellipsis))
EllipsisLoc = ConsumeToken();
TemplateTy Template;
if (isEndOfTemplateArgument(Tok) &&
Actions.ActOnDependentTemplateName(getCurScope(),
SS, TemplateKWLoc, Name,
ParsedType(),
false,
Template))
Result = ParsedTemplateArgument(SS, Template, Name.StartLocation);
}
} else if (Tok.is(tok::identifier)) {
TemplateTy Template;
UnqualifiedId Name;
Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
ConsumeToken();
if (Tok.is(tok::ellipsis))
EllipsisLoc = ConsumeToken();
if (isEndOfTemplateArgument(Tok)) {
bool MemberOfUnknownSpecialization;
TemplateNameKind TNK = Actions.isTemplateName(getCurScope(), SS,
false,
Name,
ParsedType(),
false,
Template,
MemberOfUnknownSpecialization);
if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {
Result = ParsedTemplateArgument(SS, Template, Name.StartLocation);
}
}
}
if (EllipsisLoc.isValid() && !Result.isInvalid())
Result = Actions.ActOnPackExpansion(Result, EllipsisLoc);
return Result;
}
ParsedTemplateArgument Parser::ParseTemplateArgument() {
if (isCXXTypeId(TypeIdAsTemplateArgument)) {
SourceLocation Loc = Tok.getLocation();
TypeResult TypeArg = ParseTypeName(0,
Declarator::TemplateTypeArgContext);
if (TypeArg.isInvalid())
return ParsedTemplateArgument();
return ParsedTemplateArgument(ParsedTemplateArgument::Type,
TypeArg.get().getAsOpaquePtr(),
Loc);
}
{
TentativeParsingAction TPA(*this);
ParsedTemplateArgument TemplateTemplateArgument
= ParseTemplateTemplateArgument();
if (!TemplateTemplateArgument.isInvalid()) {
TPA.Commit();
return TemplateTemplateArgument;
}
TPA.Revert();
}
SourceLocation Loc = Tok.getLocation();
ExprResult ExprArg = ParseConstantExpression(MaybeTypeCast);
if (ExprArg.isInvalid() || !ExprArg.get())
return ParsedTemplateArgument();
return ParsedTemplateArgument(ParsedTemplateArgument::NonType,
ExprArg.release(), Loc);
}
bool Parser::IsTemplateArgumentList(unsigned Skip) {
struct AlwaysRevertAction : TentativeParsingAction {
AlwaysRevertAction(Parser &P) : TentativeParsingAction(P) { }
~AlwaysRevertAction() { Revert(); }
} Tentative(*this);
while (Skip) {
ConsumeToken();
--Skip;
}
if (!Tok.is(tok::less))
return false;
ConsumeToken();
if (Tok.is(tok::greater))
return true;
while (isCXXDeclarationSpecifier() == TPResult::True())
ConsumeToken();
return Tok.is(tok::greater) || Tok.is(tok::comma);
}
bool
Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
EnterExpressionEvaluationContext EvalContext(Actions,Sema::ConstantEvaluated);
while (true) {
ParsedTemplateArgument Arg = ParseTemplateArgument();
if (Tok.is(tok::ellipsis)) {
SourceLocation EllipsisLoc = ConsumeToken();
Arg = Actions.ActOnPackExpansion(Arg, EllipsisLoc);
}
if (Arg.isInvalid()) {
SkipUntil(tok::comma, tok::greater, true, true);
return true;
}
TemplateArgs.push_back(Arg);
if (Tok.isNot(tok::comma)) break;
ConsumeToken();
}
return false;
}
Decl *Parser::ParseExplicitInstantiation(unsigned Context,
SourceLocation ExternLoc,
SourceLocation TemplateLoc,
SourceLocation &DeclEnd,
AccessSpecifier AS) {
ParsingDeclRAIIObject
ParsingTemplateParams(*this, ParsingDeclRAIIObject::NoParent);
return ParseSingleDeclarationAfterTemplate(Context,
ParsedTemplateInfo(ExternLoc,
TemplateLoc),
ParsingTemplateParams,
DeclEnd, AS);
}
SourceRange Parser::ParsedTemplateInfo::getSourceRange() const {
if (TemplateParams)
return getTemplateParamsRange(TemplateParams->data(),
TemplateParams->size());
SourceRange R(TemplateLoc);
if (ExternLoc.isValid())
R.setBegin(ExternLoc);
return R;
}
void Parser::LateTemplateParserCallback(void *P, LateParsedTemplate &LPT) {
((Parser *)P)->ParseLateTemplatedFuncDef(LPT);
}
void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
if (!LPT.D)
return;
FunctionTemplateDecl *FunTmplD = dyn_cast<FunctionTemplateDecl>(LPT.D);
FunctionDecl *FunD =
FunTmplD ? FunTmplD->getTemplatedDecl() : cast<FunctionDecl>(LPT.D);
TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
Sema::ContextRAII GlobalSavedContext(Actions, Actions.CurContext);
SmallVector<ParseScope*, 4> TemplateParamScopeStack;
SmallVector<DeclContext*, 4> DeclContextsToReenter;
DeclContext *DD = FunD->getLexicalParent();
while (DD && !DD->isTranslationUnit()) {
DeclContextsToReenter.push_back(DD);
DD = DD->getLexicalParent();
}
SmallVectorImpl<DeclContext *>::reverse_iterator II =
DeclContextsToReenter.rbegin();
for (; II != DeclContextsToReenter.rend(); ++II) {
if (ClassTemplatePartialSpecializationDecl *MD =
dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(*II)) {
TemplateParamScopeStack.push_back(
new ParseScope(this, Scope::TemplateParamScope));
Actions.ActOnReenterTemplateScope(getCurScope(), MD);
++CurTemplateDepthTracker;
} else if (CXXRecordDecl *MD = dyn_cast_or_null<CXXRecordDecl>(*II)) {
bool IsClassTemplate = MD->getDescribedClassTemplate() != 0;
TemplateParamScopeStack.push_back(
new ParseScope(this, Scope::TemplateParamScope,
IsClassTemplate));
Actions.ActOnReenterTemplateScope(getCurScope(),
MD->getDescribedClassTemplate());
if (IsClassTemplate)
++CurTemplateDepthTracker;
}
TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope));
Actions.PushDeclContext(Actions.getCurScope(), *II);
}
TemplateParamScopeStack.push_back(
new ParseScope(this, Scope::TemplateParamScope));
DeclaratorDecl *Declarator = dyn_cast<DeclaratorDecl>(FunD);
if (Declarator && Declarator->getNumTemplateParameterLists() != 0) {
Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator);
++CurTemplateDepthTracker;
}
Actions.ActOnReenterTemplateScope(getCurScope(), LPT.D);
++CurTemplateDepthTracker;
assert(!LPT.Toks.empty() && "Empty body!");
LPT.Toks.push_back(Tok);
PP.EnterTokenStream(LPT.Toks.data(), LPT.Toks.size(), true, false);
ConsumeAnyToken(true);
assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
&& "Inline method not starting with '{', ':' or 'try'");
ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
Sema::ContextRAII FunctionSavedContext(Actions, Actions.getContainingDC(FunD));
Actions.ActOnStartOfFunctionDef(getCurScope(), FunD);
if (Tok.is(tok::kw_try)) {
ParseFunctionTryBlock(LPT.D, FnScope);
} else {
if (Tok.is(tok::colon))
ParseConstructorInitializer(LPT.D);
else
Actions.ActOnDefaultCtorInitializers(LPT.D);
if (Tok.is(tok::l_brace)) {
assert((!FunTmplD || FunTmplD->getTemplateParameters()->getDepth() <
TemplateParameterDepth) &&
"TemplateParameterDepth should be greater than the depth of "
"current template being instantiated!");
ParseFunctionStatementBody(LPT.D, FnScope);
Actions.UnmarkAsLateParsedTemplate(FunD);
} else
Actions.ActOnFinishFunctionBody(LPT.D, 0);
}
FnScope.Exit();
SmallVectorImpl<ParseScope *>::reverse_iterator I =
TemplateParamScopeStack.rbegin();
for (; I != TemplateParamScopeStack.rend(); ++I)
delete *I;
}
void Parser::LexTemplateFunctionForLateParsing(CachedTokens &Toks) {
tok::TokenKind kind = Tok.getKind();
if (!ConsumeAndStoreFunctionPrologue(Toks)) {
ConsumeAndStoreUntil(tok::r_brace, Toks, false);
}
if (kind == tok::kw_try) {
while (Tok.is(tok::kw_catch)) {
ConsumeAndStoreUntil(tok::l_brace, Toks, false);
ConsumeAndStoreUntil(tok::r_brace, Toks, false);
}
}
}