diff options
-rw-r--r-- | include/clang/AST/DeclTemplate.h | 17 | ||||
-rw-r--r-- | include/clang/AST/TemplateBase.h | 100 | ||||
-rw-r--r-- | include/clang/AST/TypeLoc.h | 4 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticParseKinds.td | 4 | ||||
-rw-r--r-- | include/clang/Parse/Action.h | 2 | ||||
-rw-r--r-- | include/clang/Parse/Parser.h | 1 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 4 | ||||
-rw-r--r-- | lib/AST/DeclTemplate.cpp | 7 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 4 | ||||
-rw-r--r-- | lib/AST/TemplateBase.cpp | 13 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 3 | ||||
-rw-r--r-- | lib/AST/TypePrinter.cpp | 5 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 8 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 6 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 163 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 7 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 9 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 292 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 69 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 19 | ||||
-rw-r--r-- | test/SemaTemplate/temp_arg_nontype.cpp | 3 | ||||
-rw-r--r-- | test/SemaTemplate/temp_arg_template.cpp | 7 |
23 files changed, 502 insertions, 257 deletions
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index f1a27933a1..14f666005c 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -699,13 +699,13 @@ class TemplateTemplateParmDecl : public TemplateDecl, protected TemplateParmPosition { /// \brief The default template argument, if any. - Expr *DefaultArgument; + TemplateArgumentLoc DefaultArgument; TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, TemplateParameterList *Params) : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), - TemplateParmPosition(D, P), DefaultArgument(0) + TemplateParmPosition(D, P), DefaultArgument() { } public: @@ -720,16 +720,17 @@ public: /// \brief Determine whether this template parameter has a default /// argument. - bool hasDefaultArgument() const { return DefaultArgument; } + bool hasDefaultArgument() const { + return !DefaultArgument.getArgument().isNull(); + } /// \brief Retrieve the default argument, if any. - Expr *getDefaultArgument() const { return DefaultArgument; } - - /// \brief Retrieve the location of the default argument, if any. - SourceLocation getDefaultArgumentLoc() const; + const TemplateArgumentLoc &getDefaultArgument() const { + return DefaultArgument; + } /// \brief Set the default argument for this template parameter. - void setDefaultArgument(Expr *DefArg) { + void setDefaultArgument(const TemplateArgumentLoc &DefArg) { DefaultArgument = DefArg; } diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index bb14c62d77..6db095872b 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -18,6 +18,7 @@ #include "llvm/ADT/APSInt.h" #include "llvm/Support/ErrorHandling.h" #include "clang/AST/Type.h" +#include "clang/AST/TemplateName.h" namespace llvm { class FoldingSetNodeID; @@ -48,21 +49,27 @@ class TemplateArgument { public: /// \brief The type of template argument we're storing. enum ArgKind { + /// \brief Represents an empty template argument, e.g., one that has not + /// been deduced. Null = 0, /// The template argument is a type. Its value is stored in the /// TypeOrValue field. - Type = 1, - /// The template argument is a declaration - Declaration = 2, - /// The template argument is an integral value stored in an llvm::APSInt. - Integral = 3, + Type, + /// The template argument is a declaration that was provided for a pointer + /// or reference non-type template parameter. + Declaration, + /// The template argument is an integral value stored in an llvm::APSInt + /// that was provided for an integral non-type template parameter. + Integral, + /// The template argument is a template name that was provided for a + /// template template parameter. + Template, /// The template argument is a value- or type-dependent expression /// stored in an Expr*. - Expression = 4, - + Expression, /// The template argument is actually a parameter pack. Arguments are stored /// in the Args struct. - Pack = 5 + Pack } Kind; /// \brief Construct an empty, invalid template argument. @@ -82,12 +89,21 @@ public: } /// \brief Construct an integral constant template argument. - TemplateArgument(const llvm::APSInt &Value, QualType Type) - : Kind(Integral) { + TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) { new (Integer.Value) llvm::APSInt(Value); Integer.Type = Type.getAsOpaquePtr(); } + /// \brief Construct a template argument that is a template. + /// + /// This form of template argument is generally used for template template + /// parameters. However, the template name could be a dependent template + /// name that ends up being instantiated to a function template whose address + /// is taken. + TemplateArgument(TemplateName Name) : Kind(Template) { + TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer()); + } + /// \brief Construct a template argument that is an expression. /// /// This form of template argument only occurs in template argument @@ -172,6 +188,15 @@ public: return reinterpret_cast<Decl *>(TypeOrValue); } + /// \brief Retrieve the template argument as a template name. + TemplateName getAsTemplate() const { + if (Kind != Template) + return TemplateName(); + + return TemplateName::getFromVoidPointer( + reinterpret_cast<void *> (TypeOrValue)); + } + /// \brief Retrieve the template argument as an integral value. llvm::APSInt *getAsIntegral() { if (Kind != Integral) @@ -242,13 +267,18 @@ private: union { Expr *Expression; DeclaratorInfo *Declarator; + struct { + unsigned QualifierRange[2]; + unsigned TemplateNameLoc; + } Template; }; #ifndef NDEBUG enum Kind { K_None, K_DeclaratorInfo, - K_Expression + K_Expression, + K_Template } Kind; #endif @@ -273,6 +303,17 @@ public: , Kind(K_Expression) #endif {} + + TemplateArgumentLocInfo(SourceRange QualifierRange, + SourceLocation TemplateNameLoc) +#ifndef NDEBUG + : Kind(K_Template) +#endif + { + Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding(); + Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding(); + Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); + } DeclaratorInfo *getAsDeclaratorInfo() const { assert(Kind == K_DeclaratorInfo); @@ -284,6 +325,18 @@ public: return Expression; } + SourceRange getTemplateQualifierRange() const { + assert(Kind == K_Template); + return SourceRange( + SourceLocation::getFromRawEncoding(Template.QualifierRange[0]), + SourceLocation::getFromRawEncoding(Template.QualifierRange[1])); + } + + SourceLocation getTemplateNameLoc() const { + assert(Kind == K_Template); + return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc); + } + #ifndef NDEBUG void validateForArgument(const TemplateArgument &Arg) { switch (Arg.getKind()) { @@ -294,6 +347,9 @@ public: case TemplateArgument::Declaration: assert(Kind == K_Expression); break; + case TemplateArgument::Template: + assert(Kind == K_Template); + break; case TemplateArgument::Integral: case TemplateArgument::Pack: assert(Kind == K_None); @@ -329,8 +385,18 @@ public: assert(Argument.getKind() == TemplateArgument::Expression); } - /// \brief - Fetches the start location of the argument. + TemplateArgumentLoc(const TemplateArgument &Argument, + SourceRange QualifierRange, + SourceLocation TemplateNameLoc) + : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) { + assert(Argument.getKind() == TemplateArgument::Template); + } + + /// \brief - Fetches the primary location of the argument. SourceLocation getLocation() const { + if (Argument.getKind() == TemplateArgument::Template) + return getTemplateNameLoc(); + return getSourceRange().getBegin(); } @@ -359,6 +425,16 @@ public: assert(Argument.getKind() == TemplateArgument::Declaration); return LocInfo.getAsExpr(); } + + SourceRange getTemplateQualifierRange() const { + assert(Argument.getKind() == TemplateArgument::Template); + return LocInfo.getTemplateQualifierRange(); + } + + SourceLocation getTemplateNameLoc() const { + assert(Argument.getKind() == TemplateArgument::Template); + return LocInfo.getTemplateNameLoc(); + } }; } diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index da7857822e..a06b9b82d0 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -919,6 +919,10 @@ public: Info = TemplateArgumentLocInfo((DeclaratorInfo*) 0); break; + case TemplateArgument::Template: + Info = TemplateArgumentLocInfo(SourceRange(), SourceLocation()); + break; + case TemplateArgument::Integral: case TemplateArgument::Pack: case TemplateArgument::Null: diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 036d887865..28c46cd2d7 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -289,6 +289,10 @@ def err_explicit_spec_non_template : Error< def err_variadic_templates : Error< "variadic templates are only allowed in C++0x">; +def err_default_template_template_parameter_not_template : Error< + "default template argument for a template template parameter must be a class " + "template">; + // C++ declarations def err_friend_decl_defines_class : Error< "cannot define a type in a friend declaration">; diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 4886970c74..ceeb9c40e5 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -1577,7 +1577,7 @@ public: /// parameter. virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam, SourceLocation EqualLoc, - ExprArg Default) { + const ParsedTemplateArgument &Default) { } /// ActOnTemplateParameterList - Called when a complete template diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index dd939a98bf..548d746859 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1371,6 +1371,7 @@ private: bool AllowTypeAnnotation = true); void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0); bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs); + ParsedTemplateArgument ParseTemplateTemplateArgument(); ParsedTemplateArgument ParseTemplateArgument(); DeclPtrTy ParseExplicitInstantiation(SourceLocation ExternLoc, SourceLocation TemplateLoc, diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index bb3559b50f..b5d9cac9fa 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2357,12 +2357,14 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) { return Arg; case TemplateArgument::Expression: - // FIXME: Build canonical expression? return Arg; case TemplateArgument::Declaration: return TemplateArgument(Arg.getAsDecl()->getCanonicalDecl()); + case TemplateArgument::Template: + return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate())); + case TemplateArgument::Integral: return TemplateArgument(*Arg.getAsIntegral(), getCanonicalType(Arg.getIntegralType())); diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 9ebc91afe1..0c14714812 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -220,7 +220,7 @@ QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) { TemplateArgs.push_back(TemplateArgument(E)); } else { TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param); - TemplateArgs.push_back(TemplateArgument(TTP)); + TemplateArgs.push_back(TemplateArgument(TemplateName(TTP))); } } @@ -285,11 +285,6 @@ TemplateTemplateParmDecl::Create(ASTContext &C, DeclContext *DC, return new (C) TemplateTemplateParmDecl(DC, L, D, P, Id, Params); } -SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const { - return DefaultArgument? DefaultArgument->getSourceRange().getBegin() - : SourceLocation(); -} - //===----------------------------------------------------------------------===// // TemplateArgumentListBuilder Implementation //===----------------------------------------------------------------------===// diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 02e0c74bb6..4458c2b9cd 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -695,6 +695,10 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) { VisitType(Arg.getAsType()); break; + case TemplateArgument::Template: + VisitTemplateName(Arg.getAsTemplate()); + break; + case TemplateArgument::Declaration: VisitDecl(Arg.getAsDecl()); break; diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp index 94e1ca1e06..18a574c89c 100644 --- a/lib/AST/TemplateBase.cpp +++ b/lib/AST/TemplateBase.cpp @@ -58,6 +58,10 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); break; + case Template: + ID.AddPointer(getAsTemplate().getAsVoidPointer()); + break; + case Integral: getAsIntegral()->Profile(ID); getIntegralType().Profile(ID); @@ -82,10 +86,19 @@ SourceRange TemplateArgumentLoc::getSourceRange() const { switch (Argument.getKind()) { case TemplateArgument::Expression: return getSourceExpression()->getSourceRange(); + case TemplateArgument::Declaration: return getSourceDeclExpression()->getSourceRange(); + case TemplateArgument::Type: return getSourceDeclaratorInfo()->getTypeLoc().getFullSourceRange(); + + case TemplateArgument::Template: + if (getTemplateQualifierRange().isValid()) + return SourceRange(getTemplateQualifierRange().getBegin(), + getTemplateNameLoc()); + return SourceRange(getTemplateNameLoc()); + case TemplateArgument::Integral: case TemplateArgument::Pack: case TemplateArgument::Null: diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 844589fd3e..5ecc33cd8f 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -807,6 +807,9 @@ static bool isDependent(const TemplateArgument &Arg) { case TemplateArgument::Type: return Arg.getAsType()->isDependentType(); + case TemplateArgument::Template: + return Arg.getAsTemplate().isDependent(); + case TemplateArgument::Declaration: case TemplateArgument::Integral: // Never dependent diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 807f7d86c5..ed12006211 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -576,6 +576,11 @@ static void PrintTemplateArgument(std::string &Buffer, Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString(); break; + case TemplateArgument::Template: { + llvm::raw_string_ostream s(Buffer); + Arg.getAsTemplate().print(s, Policy); + } + case TemplateArgument::Integral: Buffer = Arg.getAsIntegral()->toString(10, true); break; diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 5cee9884ce..394d35891d 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -2185,6 +2185,14 @@ PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, return ReadDeclExpr(); case TemplateArgument::Type: return GetDeclaratorInfo(Record, Index); + case TemplateArgument::Template: { + SourceLocation + QualStart = SourceLocation::getFromRawEncoding(Record[Index++]), + QualEnd = SourceLocation::getFromRawEncoding(Record[Index++]), + TemplateNameLoc = SourceLocation::getFromRawEncoding(Record[Index++]); + return TemplateArgumentLocInfo(SourceRange(QualStart, QualEnd), + TemplateNameLoc); + } case TemplateArgument::Null: case TemplateArgument::Integral: case TemplateArgument::Declaration: diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 82922a93b5..2dcb8b0cee 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -2122,6 +2122,12 @@ void PCHWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg, case TemplateArgument::Type: AddDeclaratorInfo(Arg.getLocInfo().getAsDeclaratorInfo(), Record); break; + case TemplateArgument::Template: + Record.push_back( + Arg.getTemplateQualifierRange().getBegin().getRawEncoding()); + Record.push_back(Arg.getTemplateQualifierRange().getEnd().getRawEncoding()); + Record.push_back(Arg.getTemplateNameLoc().getRawEncoding()); + break; case TemplateArgument::Null: case TemplateArgument::Integral: case TemplateArgument::Declaration: diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index cf7d511697..b5063ee44b 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -485,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; @@ -808,33 +813,16 @@ static bool isEndOfTemplateArgument(Token Tok) { Tok.is(tok::greatergreater); } -/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]). -/// -/// template-argument: [C++ 14.2] -/// constant-expression -/// type-id -/// id-expression -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. - if (isCXXTypeId(TypeIdAsTemplateArgument)) { - SourceLocation Loc = Tok.getLocation(); - TypeResult TypeArg = ParseTypeName(); - if (TypeArg.isInvalid()) - return ParsedTemplateArgument(); - - return ParsedTemplateArgument(ParsedTemplateArgument::Type, TypeArg.get(), - Loc); - } +/// \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 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: @@ -843,63 +831,92 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() { // // 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; + 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)) { - 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. + 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(); + + return ParsedTemplateArgument(); +} + +/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]). +/// +/// template-argument: [C++ 14.2] +/// constant-expression +/// type-id +/// id-expression +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. + if (isCXXTypeId(TypeIdAsTemplateArgument)) { + SourceLocation Loc = Tok.getLocation(); + TypeResult TypeArg = ParseTypeName(); + if (TypeArg.isInvalid()) + return ParsedTemplateArgument(); - // We don't have a template template argument; revert everything we have - // tentatively parsed. - TPA.Revert(); + return ParsedTemplateArgument(ParsedTemplateArgument::Type, TypeArg.get(), + Loc); } + // Try to parse a template template argument. + ParsedTemplateArgument TemplateTemplateArgument + = ParseTemplateTemplateArgument(); + if (!TemplateTemplateArgument.isInvalid()) + return TemplateTemplateArgument; + // Parse a non-type template argument. SourceLocation Loc = Tok.getLocation(); OwningExprResult ExprArg = ParseConstantExpression(); diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 90f580618a..6c88995a1b 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2446,7 +2446,7 @@ public: unsigned Position); virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam, SourceLocation EqualLoc, - ExprArg Default); + const ParsedTemplateArgument &Default); virtual TemplateParamsTy * ActOnTemplateParameterList(unsigned Depth, @@ -2606,13 +2606,14 @@ public: bool CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType InstantiatedParamType, Expr *&Arg, TemplateArgument &Converted); - bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, DeclRefExpr *Arg); + bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, + const TemplateArgumentLoc &Arg); bool TemplateParameterListsAreEqual(TemplateParameterList *New, TemplateParameterList *Old, bool Complain, bool IsTemplateTemplateParm = false, SourceLocation TemplateArgLoc - = SourceLocation()); + = SourceLocation()); bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams); diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 13a66aaca0..4f261383ad 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -1219,12 +1219,13 @@ addAssociatedClassesAndNamespaces(const TemplateArgument &Arg, AssociatedClasses); break; - case TemplateArgument::Declaration: + case TemplateArgument::Template: { // [...] the namespaces in which any template template arguments are // defined; and the classes in which any member templates used as // template template arguments are defined. + TemplateName Template = Arg.getAsTemplate(); if (ClassTemplateDecl *ClassTemplate - = dyn_cast<ClassTemplateDecl>(Arg.getAsDecl())) { + = dyn_cast<ClassTemplateDecl>(Template.getAsTemplateDecl())) { DeclContext *Ctx = ClassTemplate->getDeclContext(); if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx)) AssociatedClasses.insert(EnclosingClass); @@ -1234,7 +1235,9 @@ addAssociatedClassesAndNamespaces(const TemplateArgument &Arg, CollectNamespace(AssociatedNamespaces, Ctx); } break; - + } + + case TemplateArgument::Declaration: case TemplateArgument::Integral: case TemplateArgument::Expression: // [Note: non-type template arguments do not contribute to the set of diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 32a6d6c243..ce2ffc1ac1 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -284,6 +284,46 @@ TemplateDecl *Sema::AdjustDeclIfTemplate(DeclPtrTy &D) { return 0; } +static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, + const ParsedTemplateArgument &Arg) { + + switch (Arg.getKind()) { + case ParsedTemplateArgument::Type: { + DeclaratorInfo *DI; + QualType T = SemaRef.GetTypeFromParser(Arg.getAsType(), &DI); + if (!DI) + DI = SemaRef.Context.getTrivialDeclaratorInfo(T, Arg.getLocation()); + return TemplateArgumentLoc(TemplateArgument(T), DI); + } + + case ParsedTemplateArgument::NonType: { + Expr *E = static_cast<Expr *>(Arg.getAsExpr()); + return TemplateArgumentLoc(TemplateArgument(E), E); + } + + case ParsedTemplateArgument::Template: { + TemplateName Template + = TemplateName::getFromVoidPointer(Arg.getAsTemplate().get()); + return TemplateArgumentLoc(TemplateArgument(Template), + Arg.getScopeSpec().getRange(), + Arg.getLocation()); + } + } + + llvm::llvm_unreachable("Unhandled parsed template argument"); + return TemplateArgumentLoc(); +} + +/// |