diff options
Diffstat (limited to 'lib/Sema')
-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 |
6 files changed, 259 insertions, 149 deletions
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) { - assert(isa<TemplateDecl>(Arg->getDecl()) && "Only template decls allowed"); - TemplateDecl *Template = cast<TemplateDecl>(Arg->getDecl()); + const TemplateArgumentLoc &Arg) { + TemplateName Name = Arg.getArgument().getAsTemplate(); + TemplateDecl *Template = Name.getAsTemplateDecl(); + if (!Template) { + // Any dependent template name is fine. + assert(Name.isDependent() && "Non-dependent template isn't a declaration?"); + return false; + } // C++ [temp.arg.template]p1: // A template-argument for a template template-parameter shall be @@ -2376,7 +2446,7 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param, !isa<TemplateTemplateParmDecl>(Template)) { assert(isa<FunctionTemplateDecl>(Template) && "Only function templates are possible here"); - Diag(Arg->getLocStart(), diag::err_template_arg_not_class_template); + Diag(Arg.getLocation(), diag::err_template_arg_not_class_template); Diag(Template->getLocation(), diag::note_template_arg_refers_here_func) << Template; } @@ -2384,7 +2454,7 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param, return !TemplateParameterListsAreEqual(Template->getTemplateParameters(), Param->getTemplateParameters(), true, true, - Arg->getSourceRange().getBegin()); + Arg.getLocation()); } /// \brief Determine whether the given template parameter lists are @@ -2735,16 +2805,9 @@ bool Sema::CheckClassTemplatePartialSpecializationArgs( } else if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>( TemplateParams->getParam(I))) { - // FIXME: We should settle on either Declaration storage or - // Expression storage for template template parameters. + TemplateName Name = ArgList[I].getAsTemplate(); TemplateTemplateParmDecl *ArgDecl - = dyn_cast_or_null<TemplateTemplateParmDecl>( - ArgList[I].getAsDecl()); - if (!ArgDecl) - if (DeclRefExpr *DRE - = dyn_cast_or_null<DeclRefExpr>(ArgList[I].getAsExpr())) - ArgDecl = dyn_cast<TemplateTemplateParmDecl>(DRE->getDecl()); - + = dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl()); if (!ArgDecl || ArgDecl->getIndex() != TTP->getIndex() || ArgDecl->getDepth() != TTP->getDepth()) @@ -2871,12 +2934,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, } } else { TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(Param); - if (Expr *DefArg = TTP->getDefaultArgument()) { - Diag(TTP->getDefaultArgumentLoc(), + if (TTP->hasDefaultArgument()) { + Diag(TTP->getDefaultArgument().getLocation(), diag::err_default_arg_in_partial_spec) - << DefArg->getSourceRange(); - TTP->setDefaultArgument(0); - DefArg->Destroy(Context); + << TTP->getDefaultArgument().getSourceRange(); + TTP->setDefaultArgument(TemplateArgumentLoc()); } } } @@ -4580,6 +4642,14 @@ Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params, break; } + case TemplateArgument::Template: { + std::string Str; + llvm::raw_string_ostream OS(Str); + Args[I].getAsTemplate().print(OS, Context.PrintingPolicy); + Result += OS.str(); + break; + } + case TemplateArgument::Integral: { Result += Args[I].getAsIntegral()->toString(10); break; diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 7b5ad7fc64..2eb3af2b60 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -785,13 +785,32 @@ DeduceTemplateArguments(ASTContext &Context, break; case TemplateArgument::Type: - assert(Arg.getKind() == TemplateArgument::Type && "Type/value mismatch"); - return DeduceTemplateArguments(Context, TemplateParams, Param.getAsType(), - Arg.getAsType(), Info, Deduced, 0); - + if (Arg.getKind() == TemplateArgument::Type) + return DeduceTemplateArguments(Context, TemplateParams, Param.getAsType(), + Arg.getAsType(), Info, Deduced, 0); + Info.FirstArg = Param; + Info.SecondArg = Arg; + return Sema::TDK_NonDeducedMismatch; + + case TemplateArgument::Template: +#if 0 + // FIXME: We need template argument deduction for template template + // parameters. + if (Arg.getKind() == TemplateArgument::Template) + return DeduceTemplateArguments(Context, TemplateParams, + Param.getAsTemplate(), + Arg.getAsTemplate(), Info, Deduced, 0); +#endif + Info.FirstArg = Param; + Info.SecondArg = Arg; + return Sema::TDK_NonDeducedMismatch; + case TemplateArgument::Declaration: - // FIXME: Implement this check - assert(false && "Unimplemented template argument deduction case"); + if (Arg.getKind() == TemplateArgument::Declaration && + Param.getAsDecl()->getCanonicalDecl() == + Arg.getAsDecl()->getCanonicalDecl()) + return Sema::TDK_Success; + Info.FirstArg = Param; Info.SecondArg = Arg; return Sema::TDK_NonDeducedMismatch; @@ -885,13 +904,21 @@ static bool isSameTemplateArg(ASTContext &Context, return X.getAsDecl()->getCanonicalDecl() == Y.getAsDecl()->getCanonicalDecl(); + case TemplateArgument::Template: + return Context.getCanonicalTemplateName(X.getAsTemplate()) + .getAsVoidPointer() == + Context.getCanonicalTemplateName(Y.getAsTemplate()) + .getAsVoidPointer(); + case TemplateArgument::Integral: return *X.getAsIntegral() == *Y.getAsIntegral(); - case TemplateArgument::Expression: - // FIXME: We assume that all expressions are distinct, but we should - // really check their canonical forms. - return false; + case TemplateArgument::Expression: { + llvm::FoldingSetNodeID XID, YID; + X.getAsExpr()->Profile(XID, Context, true); + Y.getAsExpr()->Profile(YID, Context, true); + return XID == YID; + } case TemplateArgument::Pack: if (X.pack_size() != Y.pack_size()) @@ -1030,15 +1057,6 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, Info.FirstArg = Partial->getTemplateArgs()[I]; return TDK_SubstitutionFailure; } - } else if (TemplateTemplateParmDecl *TTP - = dyn_cast<TemplateTemplateParmDecl>(Param)) { - // FIXME: template template arguments should really resolve to decls - DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(InstExpr); - if (!DRE || CheckTemplateArgument(TTP, DRE)) { - Info.Param = makeTemplateParameter(Param); - Info.FirstArg = Partial->getTemplateArgs()[I]; - return TDK_SubstitutionFailure; - } } } @@ -2153,6 +2171,9 @@ MarkUsedTemplateParameters(Sema &SemaRef, return; } + if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) + MarkUsedTemplateParameters(SemaRef, QTN->getQualifier(), OnlyDeduced, + Depth, Used); if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) MarkUsedTemplateParameters(SemaRef, DTN->getQualifier(), OnlyDeduced, Depth, Used); @@ -2309,6 +2330,7 @@ MarkUsedTemplateParameters(Sema &SemaRef, switch (TemplateArg.getKind()) { case TemplateArgument::Null: case TemplateArgument::Integral: + case TemplateArgument::Declaration: break; case TemplateArgument::Type: @@ -2316,12 +2338,9 @@ MarkUsedTemplateParameters(Sema &SemaRef, Depth, Used); break; - case TemplateArgument::Declaration: - if (TemplateTemplateParmDecl *TTP - = dyn_cast<TemplateTemplateParmDecl>(TemplateArg.getAsDecl())) { - if (TTP->getDepth() == Depth) - Used[TTP->getIndex()] = true; - } + case TemplateArgument::Template: + MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsTemplate(), + OnlyDeduced, Depth, Used); break; case TemplateArgument::Expression: diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 9e8dc2ea2c..74f521e3cf 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -452,10 +452,11 @@ Decl *TemplateInstantiator::TransformDecl(Decl *D) { if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) { if (TTP->getDepth() < TemplateArgs.getNumLevels()) { - assert(TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsDecl() && + TemplateName Template + = TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsTemplate(); + assert(!Template.isNull() && Template.getAsTemplateDecl() && "Wrong kind of template template argument"); - return cast<TemplateDecl>(TemplateArgs(TTP->getDepth(), - TTP->getPosition()).getAsDecl()); + return Template.getAsTemplateDecl(); } // If the corresponding template argument is NULL or non-existent, it's @@ -466,9 +467,8 @@ Decl *TemplateInstantiator::TransformDecl(Decl *D) { TTP->getPosition())) return D; - // FIXME: Implement depth reduction of template template parameters - assert(false && - "Reducing depth of template template parameters is not yet implemented"); + // Fall through to find the instantiated declaration for this template + // template parameter. } return SemaRef.FindInstantiatedDecl(cast<NamedDecl>(D), TemplateArgs); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 799d01b0ed..2095fba616 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1957,6 +1957,10 @@ void TreeTransform<Derived>::InventTemplateArgumentLoc( break; + case TemplateArgument::Template: + Output = TemplateArgumentLoc(Arg, SourceRange(), Loc); + break; + case TemplateArgument::Expression: Output = TemplateArgumentLoc(Arg, Arg.getAsExpr()); break; @@ -1997,7 +2001,7 @@ bool TreeTransform<Derived>::TransformTemplateArgument( DeclarationName Name; if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl())) Name = ND->getDeclName(); - TemporaryBase Rebase(*this, SourceLocation(), Name); + TemporaryBase Rebase(*this, Input.getLocation(), Name); Decl *D = getDerived().TransformDecl(Arg.getAsDecl()); if (!D) return true; @@ -2018,6 +2022,19 @@ bool TreeTransform<Derived>::TransformTemplateArgument( return false; } + case TemplateArgument::Template: { + TemporaryBase Rebase(*this, Input.getLocation(), DeclarationName()); + TemplateName Template + = getDerived().TransformTemplateName(Arg.getAsTemplate()); + if (Template.isNull()) + return true; + + Output = TemplateArgumentLoc(TemplateArgument(Template), + Input.getTemplateQualifierRange(), + Input.getTemplateNameLoc()); + return false; + } + case TemplateArgument::Expression: { // Template argument expressions are not potentially evaluated. EnterExpressionEvaluationContext Unevaluated(getSema(), |