diff options
Diffstat (limited to 'lib')
-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 |
15 files changed, 392 insertions, 229 deletions
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(); +} + +/// \brief Translates template arguments as provided by the parser +/// into template arguments used by semantic analysis. +void Sema::translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn, + llvm::SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) { + TemplateArgs.reserve(TemplateArgsIn.size()); + + for (unsigned I = 0, Last = TemplateArgsIn.size(); I != Last; ++I) + TemplateArgs.push_back(translateTemplateArgument(*this, TemplateArgsIn[I])); +} + /// ActOnTypeParameter - Called when a C++ template type parameter /// (e.g., "typename T") has been parsed. Typename specifies whether /// the keyword "typename" was used to declare the type parameter @@ -518,34 +558,22 @@ Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S, /// parameter. void Sema::ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParamD, SourceLocation EqualLoc, - ExprArg DefaultE) { + const ParsedTemplateArgument &Default) { TemplateTemplateParmDecl *TemplateParm = cast<TemplateTemplateParmDecl>(TemplateParamD.getAs<Decl>()); - - // Since a template-template parameter's default argument is an - // id-expression, it must be a DeclRefExpr. - DeclRefExpr *Default - = cast<DeclRefExpr>(static_cast<Expr *>(DefaultE.get())); - + // C++ [temp.param]p14: // A template-parameter shall not be used in its own default argument. // FIXME: Implement this check! Needs a recursive walk over the types. // Check the well-formedness of the template argument. - if (!isa<TemplateDecl>(Default->getDecl())) { - Diag(Default->getSourceRange().getBegin(), - diag::err_template_arg_must_be_template) - << Default->getSourceRange(); - TemplateParm->setInvalidDecl(); - return; - } - if (CheckTemplateArgument(TemplateParm, Default)) { + TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default); + if (CheckTemplateArgument(TemplateParm, DefaultArg)) { TemplateParm->setInvalidDecl(); return; } - DefaultE.release(); - TemplateParm->setDefaultArgument(Default); + TemplateParm->setDefaultArgument(DefaultArg); } /// ActOnTemplateParameterList - Builds a TemplateParameterList that @@ -924,8 +952,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, = OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : 0; if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() && NewTemplateParm->hasDefaultArgument()) { - OldDefaultLoc = OldTemplateParm->getDefaultArgumentLoc(); - NewDefaultLoc = NewTemplateParm->getDefaultArgumentLoc(); + OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation(); + NewDefaultLoc = NewTemplateParm->getDefaultArgument().getLocation(); SawDefaultArgument = true; RedundantDefaultArg = true; PreviousDefaultArgLoc = NewDefaultLoc; @@ -937,10 +965,12 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // that points to a previous template template parameter. NewTemplateParm->setDefaultArgument( OldTemplateParm->getDefaultArgument()); - PreviousDefaultArgLoc = OldTemplateParm->getDefaultArgumentLoc(); + PreviousDefaultArgLoc + = OldTemplateParm->getDefaultArgument().getLocation(); } else if (NewTemplateParm->hasDefaultArgument()) { SawDefaultArgument = true; - PreviousDefaultArgLoc = NewTemplateParm->getDefaultArgumentLoc(); + PreviousDefaultArgLoc + = NewTemplateParm->getDefaultArgument().getLocation(); } else if (SawDefaultArgument) MissingDefaultArg = true; } @@ -1119,50 +1149,6 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, return ParamLists[NumParamLists - 1]; } -/// \brief Translates template arguments as provided by the parser -/// into template arguments used by semantic analysis. -void Sema::translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn, - llvm::SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) { - TemplateArgs.reserve(TemplateArgsIn.size()); - - 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(Arg.getAsType(), &DI); - if (!DI) DI = Context.getTrivialDeclaratorInfo(T, Arg.getLocation()); - TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(T), DI)); - break; - } - - case ParsedTemplateArgument::NonType: { - Expr *E = static_cast<Expr *>(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)); - } - } - } -} - QualType Sema::CheckTemplateIdType(TemplateName Name, SourceLocation TemplateLoc, SourceLocation LAngleLoc, @@ -1538,7 +1524,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef, /// \param RAngleLoc the location of the right angle bracket ('>') that /// terminates the template-id. /// -/// \param Param the template template parameter whose default we are +/// \param Param the non-type template parameter whose default we are /// substituting into. /// /// \param Converted the list of template arguments provided for template @@ -1566,6 +1552,52 @@ SubstDefaultTemplateArgument(Sema &SemaRef, return SemaRef.SubstExpr(Param->getDefaultArgument(), AllTemplateArgs); } +/// \brief Substitute template arguments into the default template argument for +/// the given template template parameter. +/// +/// \param SemaRef the semantic analysis object for which we are performing +/// the substitution. +/// +/// \param Template the template that we are synthesizing template arguments +/// for. +/// +/// \param TemplateLoc the location of the template name that started the +/// template-id we are checking. +/// +/// \param RAngleLoc the location of the right angle bracket ('>') that +/// terminates the template-id. +/// +/// \param Param the template template parameter whose default we are +/// substituting into. +/// +/// \param Converted the list of template arguments provided for template +/// parameters that precede \p Param in the template parameter list. +/// +/// \returns the substituted template argument, or NULL if an error occurred. +static TemplateName +SubstDefaultTemplateArgument(Sema &SemaRef, + TemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + TemplateTemplateParmDecl *Param, + TemplateArgumentListBuilder &Converted) { + TemplateArgumentList TemplateArgs(SemaRef.Context, Converted, + /*TakeArgs=*/false); + + MultiLevelTemplateArgumentList AllTemplateArgs + = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs); + + Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, + Template, Converted.getFlatArguments(), + Converted.flatSize(), + SourceRange(TemplateLoc, RAngleLoc)); + + return SemaRef.SubstTemplateName( + Param->getDefaultArgument().getArgument().getAsTemplate(), + Param->getDefaultArgument().getTemplateNameLoc(), + AllTemplateArgs); +} + /// \brief Check that the given template argument list is well-formed /// for specializing the given template. bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, @@ -1666,9 +1698,17 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, if (!TempParm->hasDefaultArgument()) break; - // FIXME: Subst default argument - Arg = TemplateArgumentLoc(TemplateArgument(TempParm->getDefaultArgument()), - TempParm->getDefaultArgument()); + TemplateName Name = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + TempParm, + Converted); + if (Name.isNull()) + return true; + + Arg = TemplateArgumentLoc(TemplateArgument(Name), + TempParm->getDefaultArgument().getTemplateQualifierRange(), + TempParm->getDefaultArgument().getTemplateNameLoc()); } } else { // Retrieve the template argument produced by the user. @@ -1743,6 +1783,41 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, Converted.Append(Arg.getArgument()); break; + case TemplateArgument::Template: + // We were given a template template argument. It may not be ill-formed; + // see below. + if (DependentTemplateName *DTN + = Arg.getArgument().getAsTemplate().getAsDependentTemplateName()) { + // We have a template argument such as \c T::template X, which we + // parsed as a template template argument. However, since we now + // know that we need a non-type template argument, convert this + // template name into an expression. + Expr *E = new (Context) UnresolvedDeclRefExpr(DTN->getIdentifier(), + Context.DependentTy, + Arg.getTemplateNameLoc(), + Arg.getTemplateQualifierRange(), + DTN->getQualifier(), + /*isAddressOfOperand=*/false); + + TemplateArgument Result; + if (CheckTemplateArgument(NTTP, NTTPType, E, Result)) + Invalid = true; + else + Converted.Append(Result); + + break; + } + + // We have a template argument that actually does refer to a class + // template, template alias, or template template parameter, and + // therefore cannot be a non-type template argument. + Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr) + << Arg.getSourceRange(); + + Diag((*Param)->getLocation(), diag::note_template_param_here); + Invalid = true; + break; + case TemplateArgument::Type: { // We have a non-type template parameter but the template // argument is a type. @@ -1780,38 +1855,28 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, assert(false && "Should never see a NULL template argument here"); break; - case TemplateArgument::Expression: { - Expr *ArgExpr = Arg.getArgument().getAsExpr(); - if (ArgExpr && isa<DeclRefExpr>(ArgExpr) && - isa<TemplateDecl>(cast<DeclRefExpr>(ArgExpr)->getDecl())) { - if (CheckTemplateArgument(TempParm, cast<DeclRefExpr>(ArgExpr))) - Invalid = true; - - // Add the converted template argument. - Decl *D - = cast<DeclRefExpr>(ArgExpr)->getDecl()->getCanonicalDecl(); - Converted.Append(TemplateArgument(D)); - continue; - } - } - // fall through - - case TemplateArgument::Type: { + case TemplateArgument::Template: + if (CheckTemplateArgument(TempParm, Arg)) + Invalid = true; + else + Converted.Append(Arg.getArgument()); + break; + + case TemplateArgument::Expression: + case TemplateArgument::Type: // We have a template template parameter but the template // argument does not refer to a template. Diag(Arg.getLocation(), diag::err_template_arg_must_be_template); Invalid = true; break; - } case TemplateArgument::Declaration: - // We've already checked this template argument, so just copy - // it to the list of converted arguments. - Converted.Append(Arg.getArgument()); + llvm::llvm_unreachable( + "Declaration argument with template template parameter"); break; - case TemplateArgument::Integral: - assert(false && "Integral argument with template template parameter"); + llvm::llvm_unreachable( + "Integral argument with template template parameter"); break; case TemplateArgument::Pack: @@ -2357,9 +2422,14 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, /// This routine implements the semantics of C++ [temp.arg.template]. /// It returns true if an error occurred, and false otherwise. bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param, - DeclRefExpr *Arg) { |