diff options
| author | Roman Divacky <rdivacky@FreeBSD.org> | 2009-11-18 14:59:57 +0000 |
|---|---|---|
| committer | Roman Divacky <rdivacky@FreeBSD.org> | 2009-11-18 14:59:57 +0000 |
| commit | b3d5a323a5ca92ea73443499cee2f15db1ff0fb3 (patch) | |
| tree | 60a1694bec5a44d15456acc880cb2f91619f66aa /lib/Parse | |
| parent | 8f57cb0305232cb53fff00ef151ca716766f3437 (diff) | |
Notes
Diffstat (limited to 'lib/Parse')
| -rw-r--r-- | lib/Parse/AttributeList.cpp | 1 | ||||
| -rw-r--r-- | lib/Parse/DeclSpec.cpp | 10 | ||||
| -rw-r--r-- | lib/Parse/MinimalAction.cpp | 7 | ||||
| -rw-r--r-- | lib/Parse/ParseDecl.cpp | 1 | ||||
| -rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 17 | ||||
| -rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 67 | ||||
| -rw-r--r-- | lib/Parse/ParseObjc.cpp | 51 | ||||
| -rw-r--r-- | lib/Parse/ParseTemplate.cpp | 163 | ||||
| -rw-r--r-- | lib/Parse/Parser.cpp | 1 |
9 files changed, 211 insertions, 107 deletions
diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp index 344ce9e90e55..dde4bc866ac5 100644 --- a/lib/Parse/AttributeList.cpp +++ b/lib/Parse/AttributeList.cpp @@ -59,6 +59,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { .Case("mode", AT_mode) .Case("used", AT_used) .Case("alias", AT_alias) + .Case("cdecl", AT_cdecl) .Case("const", AT_const) .Case("packed", AT_packed) .Case("malloc", AT_malloc) diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp index 0a4e036e4399..f00f33fcb948 100644 --- a/lib/Parse/DeclSpec.cpp +++ b/lib/Parse/DeclSpec.cpp @@ -13,6 +13,7 @@ #include "clang/Parse/DeclSpec.h" #include "clang/Parse/ParseDiagnostic.h" +#include "clang/Parse/Template.h" #include "clang/Lex/Preprocessor.h" #include "clang/Basic/LangOptions.h" #include "llvm/ADT/STLExtras.h" @@ -26,6 +27,15 @@ static DiagnosticBuilder Diag(Diagnostic &D, SourceLocation Loc, return D.Report(FullSourceLoc(Loc, SrcMgr), DiagID); } + +void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) { + assert(TemplateId && "NULL template-id annotation?"); + Kind = IK_TemplateId; + this->TemplateId = TemplateId; + StartLocation = TemplateId->TemplateNameLoc; + EndLocation = TemplateId->RAngleLoc; +} + /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. /// "TheDeclarator" is the declarator that this will be added to. DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp index bf05b2baccd4..7681eac6ed8a 100644 --- a/lib/Parse/MinimalAction.cpp +++ b/lib/Parse/MinimalAction.cpp @@ -49,7 +49,8 @@ Action::DeclPtrTy Action::ActOnUsingDeclaration(Scope *CurScope, const CXXScopeSpec &SS, UnqualifiedId &Name, AttributeList *AttrList, - bool IsTypeName) { + bool IsTypeName, + SourceLocation TypenameLoc) { // FIXME: Parser seems to assume that Action::ActOn* takes ownership over // passed AttributeList, however other actions don't free it, is it @@ -213,7 +214,9 @@ MinimalAction::ActOnStartClassInterface(SourceLocation AtInterfaceLoc, /// Scope will always be top level file scope. Action::DeclPtrTy MinimalAction::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, - IdentifierInfo **IdentList, unsigned NumElts) { + IdentifierInfo **IdentList, + SourceLocation *IdentLocs, + unsigned NumElts) { for (unsigned i = 0; i != NumElts; ++i) { // Allocate and add the 'TypeNameInfo' "decl". getTable(TypeNameInfoTablePtr)->AddEntry(true, IdentList[i]); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 99752b59507f..2bfda30a951b 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -14,6 +14,7 @@ #include "clang/Parse/Parser.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Scope.h" +#include "clang/Parse/Template.h" #include "ExtensionRAIIObject.h" #include "llvm/ADT/SmallSet.h" using namespace clang; diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 154c2923486e..914bfc9db89d 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -16,6 +16,7 @@ #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/DeclSpec.h" #include "clang/Parse/Scope.h" +#include "clang/Parse/Template.h" #include "ExtensionRAIIObject.h" using namespace clang; @@ -282,11 +283,13 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context, SourceLocation &DeclEnd, AccessSpecifier AS) { CXXScopeSpec SS; + SourceLocation TypenameLoc; bool IsTypeName; // Ignore optional 'typename'. // FIXME: This is wrong; we should parse this as a typename-specifier. if (Tok.is(tok::kw_typename)) { + TypenameLoc = Tok.getLocation(); ConsumeToken(); IsTypeName = true; } @@ -329,7 +332,7 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context, tok::semi); return Actions.ActOnUsingDeclaration(CurScope, AS, UsingLoc, SS, Name, - AttrList, IsTypeName); + AttrList, IsTypeName, TypenameLoc); } /// ParseStaticAssertDeclaration - Parse C++0x static_assert-declaratoion. @@ -586,13 +589,10 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Eat the template argument list and try to continue parsing this as // a class (or template thereof). TemplateArgList TemplateArgs; - TemplateArgIsTypeList TemplateArgIsType; - TemplateArgLocationList TemplateArgLocations; SourceLocation LAngleLoc, RAngleLoc; if (ParseTemplateIdAfterTemplateName(TemplateTy(), NameLoc, &SS, true, LAngleLoc, - TemplateArgs, TemplateArgIsType, - TemplateArgLocations, RAngleLoc)) { + TemplateArgs, RAngleLoc)) { // We couldn't parse the template argument list at all, so don't // try to give any location information for the list. LAngleLoc = RAngleLoc = SourceLocation(); @@ -704,7 +704,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // or explicit instantiation. ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateId->getTemplateArgs(), - TemplateId->getTemplateArgIsType(), TemplateId->NumArgs); if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && TUK == Action::TUK_Declaration) { @@ -720,7 +719,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, - TemplateId->getTemplateArgLocations(), TemplateId->RAngleLoc, Attr); } else if (TUK == Action::TUK_Reference) { @@ -729,7 +727,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, - TemplateId->getTemplateArgLocations(), TemplateId->RAngleLoc); TypeResult = Actions.ActOnTagTemplateIdType(TypeResult, TUK, @@ -777,7 +774,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, - TemplateId->getTemplateArgLocations(), TemplateId->RAngleLoc, Attr, Action::MultiTemplateParamsArg(Actions, @@ -1304,7 +1300,8 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, // Check for extraneous top-level semicolon. if (Tok.is(tok::semi)) { - Diag(Tok, diag::ext_extra_struct_semi); + Diag(Tok, diag::ext_extra_struct_semi) + << CodeModificationHint::CreateRemoval(SourceRange(Tok.getLocation())); ConsumeToken(); continue; } diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index a00dfb0b4c36..b2ecc9e827f1 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -14,6 +14,7 @@ #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/DeclSpec.h" +#include "clang/Parse/Template.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; @@ -108,52 +109,43 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, if (!HasScopeSpecifier && !ObjectType) break; + TentativeParsingAction TPA(*this); SourceLocation TemplateKWLoc = ConsumeToken(); UnqualifiedId TemplateName; if (Tok.is(tok::identifier)) { - TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); - - // If the next token is not '<', we may have a stray 'template' keyword. - // Complain and suggest removing the template keyword, but otherwise - // allow parsing to continue. - if (NextToken().isNot(tok::less)) { - Diag(NextToken().getLocation(), - diag::err_less_after_template_name_in_nested_name_spec) - << Tok.getIdentifierInfo()->getName() - << CodeModificationHint::CreateRemoval(SourceRange(TemplateKWLoc)); - break; - } - // Consume the identifier. + TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); ConsumeToken(); } else if (Tok.is(tok::kw_operator)) { if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType, - TemplateName)) + TemplateName)) { + TPA.Commit(); break; + } if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId) { Diag(TemplateName.getSourceRange().getBegin(), diag::err_id_after_template_in_nested_name_spec) << TemplateName.getSourceRange(); - break; - } else if (Tok.isNot(tok::less)) { - std::string OperatorName = "operator "; - OperatorName += getOperatorSpelling( - TemplateName.OperatorFunctionId.Operator); - Diag(Tok.getLocation(), - diag::err_less_after_template_name_in_nested_name_spec) - << OperatorName - << TemplateName.getSourceRange(); + TPA.Commit(); break; } } else { - Diag(Tok.getLocation(), - diag::err_id_after_template_in_nested_name_spec) - << SourceRange(TemplateKWLoc); + TPA.Revert(); break; } + // If the next token is not '<', we have a qualified-id that refers + // to a template name, such as T::template apply, but is not a + // template-id. + if (Tok.isNot(tok::less)) { + TPA.Revert(); + break; + } + + // Commit to parsing the template-id. + TPA.Commit(); TemplateTy Template = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName, ObjectType); @@ -381,13 +373,7 @@ Parser::OwningExprResult Parser::ParseCXXCasts() { OwningExprResult Result = ParseExpression(); // Match the ')'. - if (Result.isInvalid()) - SkipUntil(tok::r_paren); - - if (Tok.is(tok::r_paren)) - RParenLoc = ConsumeParen(); - else - MatchRHSPunctuation(tok::r_paren, LParenLoc); + RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); if (!Result.isInvalid() && !CastTy.isInvalid()) Result = Actions.ActOnCXXNamedCast(OpLoc, Kind, @@ -820,13 +806,9 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, // Parse the enclosed template argument list. SourceLocation LAngleLoc, RAngleLoc; TemplateArgList TemplateArgs; - TemplateArgIsTypeList TemplateArgIsType; - TemplateArgLocationList TemplateArgLocations; if (ParseTemplateIdAfterTemplateName(Template, Id.StartLocation, &SS, true, LAngleLoc, TemplateArgs, - TemplateArgIsType, - TemplateArgLocations, RAngleLoc)) return true; @@ -851,15 +833,10 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, TemplateId->Kind = TNK; TemplateId->LAngleLoc = LAngleLoc; TemplateId->RAngleLoc = RAngleLoc; - void **Args = TemplateId->getTemplateArgs(); - bool *ArgIsType = TemplateId->getTemplateArgIsType(); - SourceLocation *ArgLocs = TemplateId->getTemplateArgLocations(); + ParsedTemplateArgument *Args = TemplateId->getTemplateArgs(); for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); - Arg != ArgEnd; ++Arg) { + Arg != ArgEnd; ++Arg) Args[Arg] = TemplateArgs[Arg]; - ArgIsType[Arg] = TemplateArgIsType[Arg]; - ArgLocs[Arg] = TemplateArgLocations[Arg]; - } Id.setTemplateId(TemplateId); return false; @@ -867,14 +844,12 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, // Bundle the template arguments together. ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(), - TemplateArgIsType.data(), TemplateArgs.size()); // Constructor and destructor names. Action::TypeResult Type = Actions.ActOnTemplateIdType(Template, NameLoc, LAngleLoc, TemplateArgsPtr, - &TemplateArgLocations[0], RAngleLoc); if (Type.isInvalid()) return true; diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index b043dd99f304..65bd79d6b4f2 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -61,6 +61,8 @@ Parser::DeclPtrTy Parser::ParseObjCAtDirectives() { Parser::DeclPtrTy Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { ConsumeToken(); // the identifier "class" llvm::SmallVector<IdentifierInfo *, 8> ClassNames; + llvm::SmallVector<SourceLocation, 8> ClassLocs; + while (1) { if (Tok.isNot(tok::identifier)) { @@ -69,6 +71,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { return DeclPtrTy(); } ClassNames.push_back(Tok.getIdentifierInfo()); + ClassLocs.push_back(Tok.getLocation()); ConsumeToken(); if (Tok.isNot(tok::comma)) @@ -81,8 +84,9 @@ Parser::DeclPtrTy Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class")) return DeclPtrTy(); - return Actions.ActOnForwardClassDeclaration(atLoc, - &ClassNames[0], ClassNames.size()); + return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(), + ClassLocs.data(), + ClassNames.size()); } /// @@ -123,6 +127,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration( Diag(Tok, diag::err_expected_ident); // missing class or category name. return DeclPtrTy(); } + // We have a class or category name - consume it. IdentifierInfo *nameId = Tok.getIdentifierInfo(); SourceLocation nameLoc = ConsumeToken(); @@ -829,6 +834,12 @@ ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &Protocols, llvm::SmallVector<IdentifierLocPair, 8> ProtocolIdents; while (1) { + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents.data(), + ProtocolIdents.size()); + ConsumeToken(); + } + if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); SkipUntil(tok::greater); @@ -895,7 +906,8 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl, // Check for extraneous top-level semicolon. if (Tok.is(tok::semi)) { - Diag(Tok, diag::ext_extra_struct_semi); + Diag(Tok, diag::ext_extra_struct_semi) + << CodeModificationHint::CreateRemoval(SourceRange(Tok.getLocation())); ConsumeToken(); continue; } @@ -982,6 +994,11 @@ Parser::DeclPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, "ParseObjCAtProtocolDeclaration(): Expected @protocol"); ConsumeToken(); // the "protocol" identifier + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteObjCProtocolDecl(CurScope); + ConsumeToken(); + } + if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); // missing protocol name. return DeclPtrTy(); @@ -1092,6 +1109,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration( atLoc, nameId, nameLoc, categoryId, categoryLoc); ObjCImpDecl = ImplCatType; + PendingObjCImpDecl.push_back(ObjCImpDecl); return DeclPtrTy(); } // We have a class implementation @@ -1114,7 +1132,8 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration( if (Tok.is(tok::l_brace)) // we have ivars ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/, atLoc); ObjCImpDecl = ImplClsType; - + PendingObjCImpDecl.push_back(ObjCImpDecl); + return DeclPtrTy(); } @@ -1126,12 +1145,21 @@ Parser::DeclPtrTy Parser::ParseObjCAtEndDeclaration(SourceLocation atLoc) { if (ObjCImpDecl) { Actions.ActOnAtEnd(atLoc, ObjCImpDecl); ObjCImpDecl = DeclPtrTy(); + PendingObjCImpDecl.pop_back(); } else Diag(atLoc, diag::warn_expected_implementation); // missing @implementation return Result; } +Parser::DeclGroupPtrTy Parser::RetrievePendingObjCImpDecl() { + if (PendingObjCImpDecl.empty()) + return Actions.ConvertDeclToDeclGroup(DeclPtrTy()); + DeclPtrTy ImpDecl = PendingObjCImpDecl.pop_back_val(); + Actions.ActOnAtEnd(SourceLocation(), ImpDecl); + return Actions.ConvertDeclToDeclGroup(ImpDecl); +} + /// compatibility-alias-decl: /// @compatibility_alias alias-name class-name ';' /// @@ -1201,6 +1229,8 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { } if (Tok.isNot(tok::semi)) Diag(Tok, diag::err_expected_semi_after) << "@synthesize"; + else + ConsumeToken(); // consume ';' return DeclPtrTy(); } @@ -1406,8 +1436,10 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() { // parse optional ';' if (Tok.is(tok::semi)) { - if (ObjCImpDecl) - Diag(Tok, diag::warn_semicolon_before_method_nody); + if (ObjCImpDecl) { + Diag(Tok, diag::warn_semicolon_before_method_body) + << CodeModificationHint::CreateRemoval(SourceRange(Tok.getLocation())); + } ConsumeToken(); } @@ -1546,6 +1578,13 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, SourceLocation NameLoc, IdentifierInfo *ReceiverName, ExprArg ReceiverExpr) { + if (Tok.is(tok::code_completion)) { + if (ReceiverName) + Actions.CodeCompleteObjCClassMessage(CurScope, ReceiverName, NameLoc); + else + Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get()); + ConsumeToken(); + } // Parse objc-selector SourceLocation Loc; IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc); diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 99578837c21c..16b1c800800f 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -15,6 +15,7 @@ #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/DeclSpec.h" #include "clang/Parse/Scope.h" +#include "clang/Parse/Template.h" #include "llvm/Support/Compiler.h" using namespace clang; @@ -484,12 +485,17 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { // Get the a default value, if given. if (Tok.is(tok::equal)) { SourceLocation EqualLoc = ConsumeToken(); - OwningExprResult DefaultExpr = ParseCXXIdExpression(); - if (DefaultExpr.isInvalid()) + ParsedTemplateArgument Default = ParseTemplateTemplateArgument(); + if (Default.isInvalid()) { + Diag(Tok.getLocation(), + diag::err_default_template_template_parameter_not_template); + static tok::TokenKind EndToks[] = { + tok::comma, tok::greater, tok::greatergreater + }; + SkipUntil(EndToks, 3, true, true); return Param; - else if (Param) - Actions.ActOnTemplateTemplateParameterDefault(Param, EqualLoc, - move(DefaultExpr)); + } else if (Param) + Actions.ActOnTemplateTemplateParameterDefault(Param, EqualLoc, Default); } return Param; @@ -582,8 +588,6 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, bool ConsumeLastToken, SourceLocation &LAngleLoc, TemplateArgList &TemplateArgs, - TemplateArgIsTypeList &TemplateArgIsType, - TemplateArgLocationList &TemplateArgLocations, SourceLocation &RAngleLoc) { assert(Tok.is(tok::less) && "Must have already parsed the template-name"); @@ -595,8 +599,7 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, { GreaterThanIsOperatorScope G(GreaterThanIsOperator, false); if (Tok.isNot(tok::greater)) - Invalid = ParseTemplateArgumentList(TemplateArgs, TemplateArgIsType, - TemplateArgLocations); + Invalid = ParseTemplateArgumentList(TemplateArgs); if (Invalid) { // Try to find the closing '>'. @@ -688,14 +691,10 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, // Parse the enclosed template argument list. SourceLocation LAngleLoc, RAngleLoc; TemplateArgList TemplateArgs; - TemplateArgIsTypeList TemplateArgIsType; - TemplateArgLocationList TemplateArgLocations; bool Invalid = ParseTemplateIdAfterTemplateName(Template, TemplateNameLoc, SS, false, LAngleLoc, TemplateArgs, - TemplateArgIsType, - TemplateArgLocations, RAngleLoc); if (Invalid) { @@ -707,7 +706,6 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, } ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(), - TemplateArgIsType.data(), TemplateArgs.size()); // Build the annotation token. @@ -715,7 +713,6 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, Action::TypeResult Type = Actions.ActOnTemplateIdType(Template, TemplateNameLoc, LAngleLoc, TemplateArgsPtr, - &TemplateArgLocations[0], RAngleLoc); if (Type.isInvalid()) { // If we failed to parse the template ID but skipped ahead to a >, we're not @@ -751,14 +748,9 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, TemplateId->Kind = TNK; TemplateId->LAngleLoc = LAngleLoc; TemplateId->RAngleLoc = RAngleLoc; - void **Args = TemplateId->getTemplateArgs(); - bool *ArgIsType = TemplateId->getTemplateArgIsType(); - SourceLocation *ArgLocs = TemplateId->getTemplateArgLocations(); - for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg) { + ParsedTemplateArgument *Args = TemplateId->getTemplateArgs(); + for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg) Args[Arg] = TemplateArgs[Arg]; - ArgIsType[Arg] = TemplateArgIsType[Arg]; - ArgLocs[Arg] = TemplateArgLocations[Arg]; - } Tok.setAnnotationValue(TemplateId); if (TemplateKWLoc.isValid()) Tok.setLocation(TemplateKWLoc); @@ -794,7 +786,6 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) { ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateId->getTemplateArgs(), - TemplateId->getTemplateArgIsType(), TemplateId->NumArgs); Action::TypeResult Type @@ -802,7 +793,6 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) { TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, - TemplateId->getTemplateArgLocations(), TemplateId->RAngleLoc); // Create the new "type" annotation token. Tok.setKind(tok::annot_typename); @@ -817,33 +807,125 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) { TemplateId->Destroy(); } +/// \brief Determine whether the given token can end a template argument. +static bool isEndOfTemplateArgument(Token Tok) { + return Tok.is(tok::comma) || Tok.is(tok::greater) || + Tok.is(tok::greatergreater); +} + +/// \brief Parse a C++ template template argument. +ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { + if (!Tok.is(tok::identifier) && !Tok.is(tok::coloncolon) && + !Tok.is(tok::annot_cxxscope)) + return ParsedTemplateArgument(); + + // C++0x [temp.arg.template]p1: + // A template-argument for a template template-parameter shall be the name + // of a class template or a template alias, expressed as id-expression. + // + // We parse an id-expression that refers to a class template or template + // alias. The grammar we parse is: + // + // nested-name-specifier[opt] template[opt] identifier + // + // followed by a token that terminates a template argument, such as ',', + // '>', or (in some cases) '>>'. + CXXScopeSpec SS; // nested-name-specifier, if present + ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, + /*EnteringContext=*/false); + + if (SS.isSet() && Tok.is(tok::kw_template)) { + // Parse the optional 'template' keyword following the + // nested-name-specifier. + SourceLocation TemplateLoc = ConsumeToken(); + + if (Tok.is(tok::identifier)) { + // We appear to have a dependent template name. + UnqualifiedId Name; + Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); + ConsumeToken(); // the identifier + + // If the next token signals the end of a template argument, + // then we have a dependent template name that could be a template + // template argument. + if (isEndOfTemplateArgument(Tok)) { + TemplateTy Template + = Actions.ActOnDependentTemplateName(TemplateLoc, SS, Name, + /*ObjectType=*/0); + if (Template.get()) + return ParsedTemplateArgument(SS, Template, Name.StartLocation); + } + } + } else if (Tok.is(tok::identifier)) { + // We may have a (non-dependent) template name. + TemplateTy Template; + UnqualifiedId Name; + Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); + ConsumeToken(); // the identifier + + if (isEndOfTemplateArgument(Tok)) { + TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, Name, + /*ObjectType=*/0, + /*EnteringContext=*/false, + Template); + if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) { + // We have an id-expression that refers to a class template or + // (C++0x) template alias. + return ParsedTemplateArgument(SS, Template, Name.StartLocation); + } + } + } + + // We don't have a template template argument. + return ParsedTemplateArgument(); +} + /// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]). /// /// template-argument: [C++ 14.2] /// constant-expression /// type-id /// id-expression -void *Parser::ParseTemplateArgument(bool &ArgIsType) { +ParsedTemplateArgument Parser::ParseTemplateArgument() { // C++ [temp.arg]p2: // In a template-argument, an ambiguity between a type-id and an // expression is resolved to a type-id, regardless of the form of // the corresponding template-parameter. // - // Therefore, we initially try to parse a type-id. + // Therefore, we initially try to parse a type-id. if (isCXXTypeId(TypeIdAsTemplateArgument)) { - ArgIsType = true; + SourceLocation Loc = Tok.getLocation(); TypeResult TypeArg = ParseTypeName(); if (TypeArg.isInvalid()) - return 0; - return TypeArg.get(); + return ParsedTemplateArgument(); + + return ParsedTemplateArgument(ParsedTemplateArgument::Type, TypeArg.get(), + Loc); } + + // Try to parse a template template argument. + { + TentativeParsingAction TPA(*this); + ParsedTemplateArgument TemplateTemplateArgument + = ParseTemplateTemplateArgument(); + if (!TemplateTemplateArgument.isInvalid()) { + TPA.Commit(); + return TemplateTemplateArgument; + } + + // Revert this tentative parse to parse a non-type template argument. + TPA.Revert(); + } + + // Parse a non-type template argument. + SourceLocation Loc = Tok.getLocation(); OwningExprResult ExprArg = ParseConstantExpression(); if (ExprArg.isInvalid() || !ExprArg.get()) - return 0; + return ParsedTemplateArgument(); - ArgIsType = false; - return ExprArg.release(); + return ParsedTemplateArgument(ParsedTemplateArgument::NonType, + ExprArg.release(), Loc); } /// ParseTemplateArgumentList - Parse a C++ template-argument-list @@ -853,22 +935,17 @@ void *Parser::ParseTemplateArgument(bool &ArgIsType) { /// template-argument /// template-argument-list ',' template-argument bool -Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs, - TemplateArgIsTypeList &TemplateArgIsType, - TemplateArgLocationList &TemplateArgLocations) { +Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) { while (true) { - bool IsType = false; - SourceLocation Loc = Tok.getLocation(); - void *Arg = ParseTemplateArgument(IsType); - if (Arg) { - TemplateArgs.push_back(Arg); - TemplateArgIsType.push_back(IsType); - TemplateArgLocations.push_back(Loc); - } else { + ParsedTemplateArgument Arg = ParseTemplateArgument(); + if (Arg.isInvalid()) { SkipUntil(tok::comma, tok::greater, true, true); return true; } + // Save this template argument. + TemplateArgs.push_back(Arg); + // If the next token is a comma, consume it and keep reading // arguments. if (Tok.isNot(tok::comma)) break; diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 335a6cf36254..a9152745b3f7 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -15,6 +15,7 @@ #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/DeclSpec.h" #include "clang/Parse/Scope.h" +#include "clang/Parse/Template.h" #include "llvm/Support/raw_ostream.h" #include "ExtensionRAIIObject.h" #include "ParsePragma.h" |
