diff --git a/clang/include/clang/Lex/Token.h b/clang/include/clang/Lex/Token.h index 8d910959b9fa..604eae1027aa 100644 --- a/clang/include/clang/Lex/Token.h +++ b/clang/include/clang/Lex/Token.h @@ -248,69 +248,6 @@ struct PPConditionalInfo { bool FoundElse; }; -/// TemplateIdAnnotation - Information about a template-id annotation -/// token, which contains the template declaration, template -/// arguments, whether those template arguments were types or -/// expressions, and the source locations for important tokens. All of -/// the information about template arguments is allocated directly -/// after this structure. -struct TemplateIdAnnotation { - /// TemplateNameLoc - The location of the template name within the - /// source. - SourceLocation TemplateNameLoc; - - /// FIXME: Temporarily stores the name of a specialization - IdentifierInfo *Name; - - /// FIXME: Temporarily stores the overloaded operator kind. - OverloadedOperatorKind Operator; - - /// The declaration of the template corresponding to the - /// template-name. This is an Action::DeclTy*. - void *Template; - - /// The kind of template that Template refers to. - TemplateNameKind Kind; - - /// The location of the '<' before the template argument - /// list. - SourceLocation LAngleLoc; - - /// The location of the '>' after the template argument - /// list. - SourceLocation RAngleLoc; - - /// NumArgs - The number of template arguments. - unsigned NumArgs; - - /// \brief Retrieves a pointer to the template arguments - void **getTemplateArgs() { return (void **)(this + 1); } - - /// \brief Retrieves a pointer to the array of template argument - /// locations. - SourceLocation *getTemplateArgLocations() { - return (SourceLocation *)(getTemplateArgs() + NumArgs); - } - - /// \brief Retrieves a pointer to the array of flags that states - /// whether the template arguments are types. - bool *getTemplateArgIsType() { - return (bool *)(getTemplateArgLocations() + NumArgs); - } - - static TemplateIdAnnotation* Allocate(unsigned NumArgs) { - TemplateIdAnnotation *TemplateId - = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) + - sizeof(void*) * NumArgs + - sizeof(SourceLocation) * NumArgs + - sizeof(bool) * NumArgs); - TemplateId->NumArgs = NumArgs; - return TemplateId; - } - - void Destroy() { free(this); } -}; - } // end namespace clang #endif diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index 929e18ba01da..4886970c7417 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -1632,7 +1632,6 @@ public: SourceLocation TemplateLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, - SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc) { return TypeResult(); }; @@ -1737,7 +1736,6 @@ public: SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, - SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc, AttributeList *Attr, MultiTemplateParamsArg TemplateParameterLists) { @@ -1817,7 +1815,6 @@ public: SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, - SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc, AttributeList *Attr) { return DeclResult(); diff --git a/clang/include/clang/Parse/DeclSpec.h b/clang/include/clang/Parse/DeclSpec.h index d539508e973b..7e7d0b3f28e8 100644 --- a/clang/include/clang/Parse/DeclSpec.h +++ b/clang/include/clang/Parse/DeclSpec.h @@ -25,7 +25,8 @@ namespace clang { class IdentifierInfo; class Preprocessor; class Declarator; - + struct TemplateIdAnnotation; + /// DeclSpec - This class captures information about "declaration specifiers", /// which encompasses storage-class-specifiers, type-specifiers, /// type-qualifiers, and function-specifiers. @@ -642,13 +643,7 @@ public: /// \param TemplateId the template-id annotation that describes the parsed /// template-id. This UnqualifiedId instance will take ownership of the /// \p TemplateId and will free it on destruction. - void setTemplateId(TemplateIdAnnotation *TemplateId) { - assert(TemplateId && "NULL template-id annotation?"); - Kind = IK_TemplateId; - this->TemplateId = TemplateId; - StartLocation = TemplateId->TemplateNameLoc; - EndLocation = TemplateId->RAngleLoc; - } + void setTemplateId(TemplateIdAnnotation *TemplateId); /// \brief Return the source range that covers this unqualified-id. SourceRange getSourceRange() const { diff --git a/clang/include/clang/Parse/Ownership.h b/clang/include/clang/Parse/Ownership.h index 9bd69c5fdb68..5eb9635f06a1 100644 --- a/clang/include/clang/Parse/Ownership.h +++ b/clang/include/clang/Parse/Ownership.h @@ -654,41 +654,33 @@ namespace clang { #endif }; + class ParsedTemplateArgument; + class ASTTemplateArgsPtr { #if !defined(DISABLE_SMART_POINTERS) ActionBase &Actions; #endif - void **Args; - bool *ArgIsType; + ParsedTemplateArgument *Args; mutable unsigned Count; #if !defined(DISABLE_SMART_POINTERS) - void destroy() { - if (!Count) - return; - - for (unsigned i = 0; i != Count; ++i) - if (Args[i] && !ArgIsType[i]) - Actions.DeleteExpr((ActionBase::ExprTy *)Args[i]); - - Count = 0; - } + void destroy(); #endif - + public: - ASTTemplateArgsPtr(ActionBase &actions, void **args, bool *argIsType, + ASTTemplateArgsPtr(ActionBase &actions, ParsedTemplateArgument *args, unsigned count) : #if !defined(DISABLE_SMART_POINTERS) Actions(actions), #endif - Args(args), ArgIsType(argIsType), Count(count) { } + Args(args), Count(count) { } // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'. ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) : #if !defined(DISABLE_SMART_POINTERS) Actions(Other.Actions), #endif - Args(Other.Args), ArgIsType(Other.ArgIsType), Count(Other.Count) { + Args(Other.Args), Count(Other.Count) { #if !defined(DISABLE_SMART_POINTERS) Other.Count = 0; #endif @@ -700,7 +692,6 @@ namespace clang { Actions = Other.Actions; #endif Args = Other.Args; - ArgIsType = Other.ArgIsType; Count = Other.Count; #if !defined(DISABLE_SMART_POINTERS) Other.Count = 0; @@ -712,22 +703,20 @@ namespace clang { ~ASTTemplateArgsPtr() { destroy(); } #endif - void **getArgs() const { return Args; } - bool *getArgIsType() const {return ArgIsType; } + ParsedTemplateArgument *getArgs() const { return Args; } unsigned size() const { return Count; } - void reset(void **args, bool *argIsType, unsigned count) { + void reset(ParsedTemplateArgument *args, unsigned count) { #if !defined(DISABLE_SMART_POINTERS) destroy(); #endif Args = args; - ArgIsType = argIsType; Count = count; } - void *operator[](unsigned Arg) const { return Args[Arg]; } + const ParsedTemplateArgument &operator[](unsigned Arg) const; - void **release() const { + ParsedTemplateArgument *release() const { #if !defined(DISABLE_SMART_POINTERS) Count = 0; #endif diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 1ca92edc9a8b..b163c81e18c5 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -331,7 +331,7 @@ private: /// either "commit the consumed tokens" or revert to the previously marked /// token position. Example: /// - /// TentativeParsingAction TPA; + /// TentativeParsingAction TPA(*this); /// ConsumeToken(); /// .... /// TPA.Revert(); @@ -1347,9 +1347,7 @@ private: DeclPtrTy ParseTemplateTemplateParameter(unsigned Depth, unsigned Position); DeclPtrTy ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position); // C++ 14.3: Template arguments [temp.arg] - typedef llvm::SmallVector TemplateArgList; - typedef llvm::SmallVector TemplateArgIsTypeList; - typedef llvm::SmallVector TemplateArgLocationList; + typedef llvm::SmallVector TemplateArgList; bool ParseTemplateIdAfterTemplateName(TemplateTy Template, SourceLocation TemplateNameLoc, @@ -1357,8 +1355,6 @@ private: bool ConsumeLastToken, SourceLocation &LAngleLoc, TemplateArgList &TemplateArgs, - TemplateArgIsTypeList &TemplateArgIsType, - TemplateArgLocationList &TemplateArgLocations, SourceLocation &RAngleLoc); bool AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, @@ -1367,10 +1363,8 @@ private: SourceLocation TemplateKWLoc = SourceLocation(), bool AllowTypeAnnotation = true); void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0); - bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs, - TemplateArgIsTypeList &TemplateArgIsType, - TemplateArgLocationList &TemplateArgLocations); - void *ParseTemplateArgument(bool &ArgIsType); + bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs); + ParsedTemplateArgument ParseTemplateArgument(); DeclPtrTy ParseExplicitInstantiation(SourceLocation ExternLoc, SourceLocation TemplateLoc, SourceLocation &DeclEnd); diff --git a/clang/include/clang/Parse/Template.h b/clang/include/clang/Parse/Template.h new file mode 100644 index 000000000000..8531bf66a80b --- /dev/null +++ b/clang/include/clang/Parse/Template.h @@ -0,0 +1,183 @@ +//===--- Template.h - Template Parsing Data Types -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides data structures that store the parsed representation of +// templates. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_PARSE_TEMPLATE_H +#define LLVM_CLANG_PARSE_TEMPLATE_H + +#include "clang/Parse/DeclSpec.h" +#include "clang/Parse/Ownership.h" +#include + +namespace clang { + /// \brief Represents the parsed form of a C++ template argument. + class ParsedTemplateArgument { + public: + /// \brief Describes the kind of template argument that was parsed. + enum KindType { + /// \brief A template type parameter, stored as a type. + Type, + /// \brief A non-type template parameter, stored as an expression. + NonType, + /// \brief A template template argument, stored as a template name. + Template + }; + + /// \brief Build an empty template argument. This template argument + ParsedTemplateArgument() : Kind(Type), Arg(0) { } + + /// \brief Create a template type argument or non-type template argument. + /// + /// \param Arg the template type argument or non-type template argument. + /// \param Loc the location of the type. + ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation Loc) + : Kind(Kind), Arg(Arg), Loc(Loc) { } + + /// \brief Create a template template argument. + /// + /// \param SS the C++ scope specifier that precedes the template name, if + /// any. + /// + /// \param Template the template to which this template template + /// argument refers. + /// + /// \param TemplateLoc the location of the template name. + ParsedTemplateArgument(const CXXScopeSpec &SS, + ActionBase::TemplateTy Template, + SourceLocation TemplateLoc) + : Kind(ParsedTemplateArgument::Template), Arg(Template.get()), + Loc(TemplateLoc), SS(SS) { } + + /// \brief Determine whether the given template argument is invalid. + bool isInvalid() { return Arg == 0; } + + /// \brief Determine what kind of template argument we have. + KindType getKind() const { return Kind; } + + /// \brief Retrieve the template type argument's type. + ActionBase::TypeTy *getAsType() const { + assert(Kind == Type && "Not a template type argument"); + return Arg; + } + + /// \brief Retrieve the non-type template argument's expression. + ActionBase::ExprTy *getAsExpr() const { + assert(Kind == NonType && "Not a non-type template argument"); + return Arg; + } + + /// \brief Retrieve the template template argument's template name. + ActionBase::TemplateTy getAsTemplate() const { + assert(Kind == Template && "Not a template template argument"); + return ActionBase::TemplateTy::make(Arg); + } + + /// \brief Retrieve the location of the template argument. + SourceLocation getLocation() const { return Loc; } + + /// \brief Retrieve the nested-name-specifier that precedes the template + /// name in a template template argument. + const CXXScopeSpec &getScopeSpec() const { + assert(Kind == Template && + "Only template template arguments can have a scope specifier"); + return SS; + } + + private: + KindType Kind; + + /// \brief The actual template argument representation, which may be + /// an \c ActionBase::TypeTy* (for a type), an ActionBase::ExprTy* (for an + /// expression), or an ActionBase::TemplateTy (for a template). + void *Arg; + + /// \brief the location of the template argument. + SourceLocation Loc; + + /// \brief The nested-name-specifier that can accompany a template template + /// argument. + CXXScopeSpec SS; + }; + + /// \brief Information about a template-id annotation + /// token. + /// + /// A template-id annotation token contains the template declaration, + /// template arguments, whether those template arguments were types, + /// expressions, or template names, and the source locations for important + /// tokens. All of the information about template arguments is allocated + /// directly after this structure. + struct TemplateIdAnnotation { + /// TemplateNameLoc - The location of the template name within the + /// source. + SourceLocation TemplateNameLoc; + + /// FIXME: Temporarily stores the name of a specialization + IdentifierInfo *Name; + + /// FIXME: Temporarily stores the overloaded operator kind. + OverloadedOperatorKind Operator; + + /// The declaration of the template corresponding to the + /// template-name. This is an Action::TemplateTy. + void *Template; + + /// The kind of template that Template refers to. + TemplateNameKind Kind; + + /// The location of the '<' before the template argument + /// list. + SourceLocation LAngleLoc; + + /// The location of the '>' after the template argument + /// list. + SourceLocation RAngleLoc; + + /// NumArgs - The number of template arguments. + unsigned NumArgs; + + /// \brief Retrieves a pointer to the template arguments + ParsedTemplateArgument *getTemplateArgs() { + return reinterpret_cast(this + 1); + } + + static TemplateIdAnnotation* Allocate(unsigned NumArgs) { + TemplateIdAnnotation *TemplateId + = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) + + sizeof(ParsedTemplateArgument) * NumArgs); + TemplateId->NumArgs = NumArgs; + return TemplateId; + } + + void Destroy() { free(this); } + }; + +#if !defined(DISABLE_SMART_POINTERS) + inline void ASTTemplateArgsPtr::destroy() { + if (!Count) + return; + + for (unsigned I = 0; I != Count; ++I) + if (Args[I].getKind() == ParsedTemplateArgument::NonType) + Actions.DeleteExpr(Args[I].getAsExpr()); + + Count = 0; + } +#endif + + inline const ParsedTemplateArgument & + ASTTemplateArgsPtr::operator[](unsigned Arg) const { + return Args[Arg]; + } +} + +#endif \ No newline at end of file diff --git a/clang/lib/Parse/DeclSpec.cpp b/clang/lib/Parse/DeclSpec.cpp index 0a4e036e4399..f00f33fcb948 100644 --- a/clang/lib/Parse/DeclSpec.cpp +++ b/clang/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/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 99752b59507f..2bfda30a951b 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/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/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index c006f8bc8036..baf9e4ba5996 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/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; @@ -586,13 +587,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 +702,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 +717,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 +725,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, - TemplateId->getTemplateArgLocations(), TemplateId->RAngleLoc); TypeResult = Actions.ActOnTagTemplateIdType(TypeResult, TUK, @@ -777,7 +772,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, - TemplateId->getTemplateArgLocations(), TemplateId->RAngleLoc, Attr, Action::MultiTemplateParamsArg(Actions, diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index fa8e64dc125b..a7e7648c1f56 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/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; @@ -814,13 +815,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; @@ -845,15 +842,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; @@ -861,14 +853,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/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 99578837c21c..4e7ceaa7c14b 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/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; @@ -582,8 +583,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 +594,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 +686,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 +701,6 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, } ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(), - TemplateArgIsType.data(), TemplateArgs.size()); // Build the annotation token. @@ -715,7 +708,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 +743,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 +781,6 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) { ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateId->getTemplateArgs(), - TemplateId->getTemplateArgIsType(), TemplateId->NumArgs); Action::TypeResult Type @@ -802,7 +788,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 +802,112 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) { TemplateId->Destroy(); } +/// \brief Determine whether the given token can end a template argument. +static const bool isEndOfTemplateArgument(Token Tok) { + return Tok.is(tok::comma) || Tok.is(tok::greater) || + Tok.is(tok::greatergreater); +} + /// 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); } + // 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 perform some tentative parsing at this point, to determine whether + // we have an id-expression that refers to a class template or template + // alias. The grammar we tentatively parse is: + // + // nested-name-specifier[opt] template[opt] identifier + // + // followed by a token that terminates a template argument, such as ',', + // '>', or (in some cases) '>>'. + if (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || + Tok.is(tok::annot_cxxscope)) { + TentativeParsingAction TPA(*this); + 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()) { + TPA.Commit(); + 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. + TPA.Commit(); + return ParsedTemplateArgument(SS, Template, Name.StartLocation); + } + } + } + + // We don't have a template template argument; revert everything we have + // tentatively parsed. + 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 +917,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/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 335a6cf36254..a9152745b3f7 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/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" diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index b9e8473105f6..90f580618a21 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -2472,8 +2472,7 @@ public: AccessSpecifier AS); void translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn, - SourceLocation *TemplateArgLocsIn, - llvm::SmallVector &TempArgs); + llvm::SmallVectorImpl &TempArgs); QualType CheckTemplateIdType(TemplateName Template, SourceLocation TemplateLoc, @@ -2486,7 +2485,6 @@ public: ActOnTemplateIdType(TemplateTy Template, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, - SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc); virtual TypeResult ActOnTagTemplateIdType(TypeResult Type, @@ -2508,7 +2506,6 @@ public: SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, - SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc); virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc, @@ -2529,7 +2526,6 @@ public: SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, - SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc, AttributeList *Attr, MultiTemplateParamsArg TemplateParameterLists); @@ -2570,7 +2566,6 @@ public: SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, - SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc, AttributeList *Attr); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 8bd934a561f6..d1eaa6bb60b0 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -24,6 +24,7 @@ #include "clang/AST/StmtObjC.h" #include "clang/Parse/DeclSpec.h" #include "clang/Parse/ParseDiagnostic.h" +#include "clang/Parse/Template.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -1669,7 +1670,7 @@ DeclarationName Sema::GetNameFromUnqualifiedId(UnqualifiedId &Name) { case UnqualifiedId::IK_TemplateId: { TemplateName TName - = TemplateName::getFromVoidPointer(Name.TemplateId->Template); + = TemplateName::getFromVoidPointer(Name.TemplateId->Template); if (TemplateDecl *Template = TName.getAsTemplateDecl()) return Template->getDeclName(); if (OverloadedFunctionDecl *Ovl = TName.getAsOverloadedFunctionDecl()) @@ -2835,10 +2836,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, TemplateIdAnnotation *TemplateId = D.getName().TemplateId; ASTTemplateArgsPtr TemplateArgsPtr(*this, TemplateId->getTemplateArgs(), - TemplateId->getTemplateArgIsType(), TemplateId->NumArgs); translateTemplateArguments(TemplateArgsPtr, - TemplateId->getTemplateArgLocations(), TemplateArgs); TemplateArgsPtr.release(); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 36f2734a1ad7..25d14a70be2c 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -18,9 +18,10 @@ #include "clang/AST/DeclVisitor.h" #include "clang/AST/TypeOrdering.h" #include "clang/AST/StmtVisitor.h" +#include "clang/Parse/DeclSpec.h" +#include "clang/Parse/Template.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Lex/Preprocessor.h" -#include "clang/Parse/DeclSpec.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" #include // for std::equal diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ec6ca2a9ac02..c29cfb7c5d22 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -25,6 +25,7 @@ #include "clang/Parse/DeclSpec.h" #include "clang/Parse/Designator.h" #include "clang/Parse/Scope.h" +#include "clang/Parse/Template.h" using namespace clang; @@ -622,14 +623,12 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, if (Name.getKind() == UnqualifiedId::IK_TemplateId) { ASTTemplateArgsPtr TemplateArgsPtr(*this, Name.TemplateId->getTemplateArgs(), - Name.TemplateId->getTemplateArgIsType(), Name.TemplateId->NumArgs); return ActOnTemplateIdExpr(SS, TemplateTy::make(Name.TemplateId->Template), Name.TemplateId->TemplateNameLoc, Name.TemplateId->LAngleLoc, TemplateArgsPtr, - Name.TemplateId->getTemplateArgLocations(), Name.TemplateId->RAngleLoc); } @@ -2501,12 +2500,10 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg Base, // Translate the parser's template argument list in our AST format. ASTTemplateArgsPtr TemplateArgsPtr(*this, Member.TemplateId->getTemplateArgs(), - Member.TemplateId->getTemplateArgIsType(), Member.TemplateId->NumArgs); llvm::SmallVector TemplateArgs; translateTemplateArguments(TemplateArgsPtr, - Member.TemplateId->getTemplateArgLocations(), TemplateArgs); TemplateArgsPtr.release(); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 0f7106135b2c..32a6d6c2438b 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -16,6 +16,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/Parse/DeclSpec.h" +#include "clang/Parse/Template.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/PartialDiagnostic.h" #include "llvm/Support/Compiler.h" @@ -1121,21 +1122,43 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, /// \brief Translates template arguments as provided by the parser /// into template arguments used by semantic analysis. void Sema::translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn, - SourceLocation *TemplateArgLocs, - llvm::SmallVector &TemplateArgs) { + llvm::SmallVectorImpl &TemplateArgs) { TemplateArgs.reserve(TemplateArgsIn.size()); - void **Args = TemplateArgsIn.getArgs(); - bool *ArgIsType = TemplateArgsIn.getArgIsType(); - for (unsigned Arg = 0, Last = TemplateArgsIn.size(); Arg != Last; ++Arg) { - if (ArgIsType[Arg]) { + for (unsigned I = 0, Last = TemplateArgsIn.size(); I != Last; ++I) { + const ParsedTemplateArgument &Arg = TemplateArgsIn[I]; + switch (Arg.getKind()) { + case ParsedTemplateArgument::Type: { DeclaratorInfo *DI; - QualType T = Sema::GetTypeFromParser(Args[Arg], &DI); - if (!DI) DI = Context.getTrivialDeclaratorInfo(T, TemplateArgLocs[Arg]); + QualType T = Sema::GetTypeFromParser(Arg.getAsType(), &DI); + if (!DI) DI = Context.getTrivialDeclaratorInfo(T, Arg.getLocation()); TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(T), DI)); - } else { - Expr *E = reinterpret_cast(Args[Arg]); + break; + } + + case ParsedTemplateArgument::NonType: { + Expr *E = static_cast(Arg.getAsExpr()); TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(E), E)); + break; + } + + case ParsedTemplateArgument::Template: { + TemplateName Template + = TemplateName::getFromVoidPointer(Arg.getAsTemplate().get()); + + // FIXME: This is an egregious hack. We turn a nicely-parsed template name + // into a DeclRefExpr, because that's how we previously parsed template + // template parameters. This will disappear as part of the upcoming + // implementation of template template parameters. + const CXXScopeSpec &SS = Arg.getScopeSpec(); + Expr *E = DeclRefExpr::Create(Context, + (NestedNameSpecifier *)SS.getScopeRep(), + SS.getRange(), + Template.getAsTemplateDecl(), + Arg.getLocation(), + Context.DependentTy, false, false); + TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(E), E)); + } } } } @@ -1228,13 +1251,12 @@ Action::TypeResult Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation *TemplateArgLocsIn, SourceLocation RAngleLoc) { TemplateName Template = TemplateD.getAsVal(); // Translate the parser's template argument list in our AST format. llvm::SmallVector TemplateArgs; - translateTemplateArguments(TemplateArgsIn, TemplateArgLocsIn, TemplateArgs); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); QualType Result = CheckTemplateIdType(Template, TemplateLoc, LAngleLoc, TemplateArgs.data(), @@ -1336,13 +1358,12 @@ Sema::OwningExprResult Sema::ActOnTemplateIdExpr(const CXXScopeSpec &SS, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation *TemplateArgSLs, SourceLocation RAngleLoc) { TemplateName Template = TemplateD.getAsVal(); // Translate the parser's template argument list in our AST format. llvm::SmallVector TemplateArgs; - translateTemplateArguments(TemplateArgsIn, TemplateArgSLs, TemplateArgs); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); TemplateArgsIn.release(); return BuildTemplateIdExpr((NestedNameSpecifier *)SS.getScopeRep(), @@ -2803,7 +2824,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc, AttributeList *Attr, MultiTemplateParamsArg TemplateParameterLists) { @@ -2898,7 +2918,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // Translate the parser's template argument list in our AST format. llvm::SmallVector TemplateArgs; - translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); // Check that the template argument list is well-formed for this // template. @@ -3704,7 +3724,6 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc, AttributeList *Attr) { // Find the class template we're specializing @@ -3743,7 +3762,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, // Translate the parser's template argument list in our AST format. llvm::SmallVector TemplateArgs; - translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); // Check that the template argument list is well-formed for this // template. @@ -4126,10 +4145,8 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, TemplateIdAnnotation *TemplateId = D.getName().TemplateId; ASTTemplateArgsPtr TemplateArgsPtr(*this, TemplateId->getTemplateArgs(), - TemplateId->getTemplateArgIsType(), TemplateId->NumArgs); translateTemplateArguments(TemplateArgsPtr, - TemplateId->getTemplateArgLocations(), TemplateArgs); HasExplicitTemplateArgs = true; TemplateArgsPtr.release();