diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp index 2ec0994e846e94..de103e011c7085 100644 --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -262,7 +262,8 @@ fetchTemplateParameters(const TemplateParameterList *Params, if (NTTP->hasDefaultArgument()) { P.Default.emplace(); llvm::raw_string_ostream Out(*P.Default); - NTTP->getDefaultArgument()->printPretty(Out, nullptr, PP); + NTTP->getDefaultArgument().getArgument().print(PP, Out, + /*IncludeType=*/false); } } else if (const auto *TTPD = dyn_cast(Param)) { P.Type = printType(TTPD, PP); diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index 98db1cb5789909..616f92691ec323 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -704,9 +704,9 @@ class ASTNodeTraverser if (const auto *E = D->getPlaceholderTypeConstraint()) Visit(E); if (D->hasDefaultArgument()) - Visit(D->getDefaultArgument(), SourceRange(), - D->getDefaultArgStorage().getInheritedFrom(), - D->defaultArgumentWasInherited() ? "inherited from" : "previous"); + dumpTemplateArgumentLoc( + D->getDefaultArgument(), D->getDefaultArgStorage().getInheritedFrom(), + D->defaultArgumentWasInherited() ? "inherited from" : "previous"); } void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D) { diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 07b08b5ed43ca4..5b6a6b40b28ef8 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -1360,7 +1360,8 @@ class NonTypeTemplateParmDecl final /// The default template argument, if any, and whether or not /// it was inherited. - using DefArgStorage = DefaultArgStorage; + using DefArgStorage = + DefaultArgStorage; DefArgStorage DefaultArgument; // FIXME: Collapse this into TemplateParamPosition; or, just move depth/index @@ -1430,7 +1431,10 @@ class NonTypeTemplateParmDecl final bool hasDefaultArgument() const { return DefaultArgument.isSet(); } /// Retrieve the default argument, if any. - Expr *getDefaultArgument() const { return DefaultArgument.get(); } + const TemplateArgumentLoc &getDefaultArgument() const { + static const TemplateArgumentLoc NoneLoc; + return DefaultArgument.isSet() ? *DefaultArgument.get() : NoneLoc; + } /// Retrieve the location of the default argument, if any. SourceLocation getDefaultArgumentLoc() const; @@ -1444,7 +1448,8 @@ class NonTypeTemplateParmDecl final /// Set the default argument for this template parameter, and /// whether that default argument was inherited from another /// declaration. - void setDefaultArgument(Expr *DefArg) { DefaultArgument.set(DefArg); } + void setDefaultArgument(const ASTContext &C, + const TemplateArgumentLoc &DefArg); void setInheritedDefaultArgument(const ASTContext &C, NonTypeTemplateParmDecl *Parm) { DefaultArgument.setInherited(C, Parm); diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 659e4cdd1037b1..a4b8d6ef61d564 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2320,7 +2320,7 @@ DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, { // A non-type template parameter, e.g. "S" in template class Foo ... TRY_TO(TraverseDeclaratorHelper(D)); if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) - TRY_TO(TraverseStmt(D->getDefaultArgument())); + TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument())); }) DEF_TRAVERSE_DECL(ParmVarDecl, { diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index f9902a978aa34a..a2398fef623ea2 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -6503,8 +6503,10 @@ bool ASTContext::isSameDefaultTemplateArgument(const NamedDecl *X, if (!NTTPX->hasDefaultArgument() || !NTTPY->hasDefaultArgument()) return false; - Expr *DefaultArgumentX = NTTPX->getDefaultArgument()->IgnoreImpCasts(); - Expr *DefaultArgumentY = NTTPY->getDefaultArgument()->IgnoreImpCasts(); + Expr *DefaultArgumentX = + NTTPX->getDefaultArgument().getArgument().getAsExpr()->IgnoreImpCasts(); + Expr *DefaultArgumentY = + NTTPY->getDefaultArgument().getArgument().getAsExpr()->IgnoreImpCasts(); llvm::FoldingSetNodeID XID, YID; DefaultArgumentX->Profile(XID, *this, /*Canonical=*/true); DefaultArgumentY->Profile(YID, *this, /*Canonical=*/true); diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp index 7b0d5f9cc1a93d..91bc1b22acfc7f 100644 --- a/clang/lib/AST/ASTDiagnostic.cpp +++ b/clang/lib/AST/ASTDiagnostic.cpp @@ -1238,7 +1238,7 @@ class TemplateDiff { E = Iter->getAsExpr(); } } else if (!Default->isParameterPack()) { - E = Default->getDefaultArgument(); + E = Default->getDefaultArgument().getArgument().getAsExpr(); } if (!Iter.hasDesugaredTA()) return; diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index a47dd72a5679cd..cab5ee60479564 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -5949,10 +5949,11 @@ ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { return ToD; if (D->hasDefaultArgument()) { - ExpectedExpr ToDefaultArgOrErr = import(D->getDefaultArgument()); + Expected ToDefaultArgOrErr = + import(D->getDefaultArgument()); if (!ToDefaultArgOrErr) return ToDefaultArgOrErr.takeError(); - ToD->setDefaultArgument(*ToDefaultArgOrErr); + ToD->setDefaultArgument(Importer.getToContext(), *ToDefaultArgOrErr); } return ToD; diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index bf32aafc3d0af4..0cf4e64f83b8df 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -1898,7 +1898,7 @@ void DeclPrinter::VisitNonTypeTemplateParmDecl( if (NTTP->hasDefaultArgument()) { Out << " = "; - NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy, Indentation, - "\n", &Context); + NTTP->getDefaultArgument().getArgument().print(Policy, Out, + /*IncludeType=*/false); } } diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 46bb3e8e51389f..95ffd4784641fc 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -795,14 +795,21 @@ NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID, SourceRange NonTypeTemplateParmDecl::getSourceRange() const { if (hasDefaultArgument() && !defaultArgumentWasInherited()) return SourceRange(getOuterLocStart(), - getDefaultArgument()->getSourceRange().getEnd()); + getDefaultArgument().getSourceRange().getEnd()); return DeclaratorDecl::getSourceRange(); } SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const { - return hasDefaultArgument() - ? getDefaultArgument()->getSourceRange().getBegin() - : SourceLocation(); + return hasDefaultArgument() ? getDefaultArgument().getSourceRange().getBegin() + : SourceLocation(); +} + +void NonTypeTemplateParmDecl::setDefaultArgument( + const ASTContext &C, const TemplateArgumentLoc &DefArg) { + if (DefArg.getArgument().isNull()) + DefaultArgument.set(nullptr); + else + DefaultArgument.set(new (C) TemplateArgumentLoc(DefArg)); } //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index efd3a639d746b3..3bbb3a905e9b91 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -1044,7 +1044,7 @@ void JSONNodeDumper::VisitNonTypeTemplateParmDecl( if (D->hasDefaultArgument()) JOS.attributeObject("defaultArg", [=] { - Visit(D->getDefaultArgument(), SourceRange(), + Visit(D->getDefaultArgument().getArgument(), SourceRange(), D->getDefaultArgStorage().getInheritedFrom(), D->defaultArgumentWasInherited() ? "inherited from" : "previous"); }); diff --git a/clang/lib/AST/ODRDiagsEmitter.cpp b/clang/lib/AST/ODRDiagsEmitter.cpp index 97b6c14d9ede61..37f0f68c92355f 100644 --- a/clang/lib/AST/ODRDiagsEmitter.cpp +++ b/clang/lib/AST/ODRDiagsEmitter.cpp @@ -1523,8 +1523,11 @@ bool ODRDiagsEmitter::diagnoseMismatch( } if (HasFirstDefaultArgument && HasSecondDefaultArgument) { - Expr *FirstDefaultArgument = FirstNTTPD->getDefaultArgument(); - Expr *SecondDefaultArgument = SecondNTTPD->getDefaultArgument(); + TemplateArgument FirstDefaultArgument = + FirstNTTPD->getDefaultArgument().getArgument(); + TemplateArgument SecondDefaultArgument = + SecondNTTPD->getDefaultArgument().getArgument(); + if (computeODRHash(FirstDefaultArgument) != computeODRHash(SecondDefaultArgument)) { DiagTemplateError(FunctionTemplateParameterDifferentDefaultArgument) diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 18b1e17e0fee5d..246e56231539ae 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -480,7 +480,7 @@ class ODRDeclVisitor : public ConstDeclVisitor { D->hasDefaultArgument() && !D->defaultArgumentWasInherited(); Hash.AddBoolean(hasDefaultArgument); if (hasDefaultArgument) { - AddStmt(D->getDefaultArgument()); + AddTemplateArgument(D->getDefaultArgument().getArgument()); } Hash.AddBoolean(D->isParameterPack()); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 981f09410401b0..5ed56b367a46a7 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -2281,8 +2281,9 @@ bool clang::isSubstitutedDefaultArgument(ASTContext &Ctx, TemplateArgument Arg, Ctx, Arg, TTPD->getDefaultArgument().getArgument(), Args, Depth); } else if (auto *NTTPD = dyn_cast(Param)) { return NTTPD->hasDefaultArgument() && - isSubstitutedTemplateArgument(Ctx, Arg, NTTPD->getDefaultArgument(), - Args, Depth); + isSubstitutedTemplateArgument( + Ctx, Arg, NTTPD->getDefaultArgument().getArgument(), Args, + Depth); } return false; } diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index d88e4e0df8ef89..904b9315f26ef4 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -1023,8 +1023,9 @@ DeclarationFragmentsBuilder::getFragmentsForTemplateParameters( if (NTP->hasDefaultArgument()) { SmallString<8> ExprStr; raw_svector_ostream Output(ExprStr); - NTP->getDefaultArgument()->printPretty( - Output, nullptr, NTP->getASTContext().getPrintingPolicy()); + NTP->getDefaultArgument().getArgument().print( + NTP->getASTContext().getPrintingPolicy(), Output, + /*IncludeType=*/false); Fragments.append(" = ", DeclarationFragments::FragmentKind::Text) .append(ExprStr, DeclarationFragments::FragmentKind::Text); } diff --git a/clang/lib/Index/IndexDecl.cpp b/clang/lib/Index/IndexDecl.cpp index 058f4aef918a8f..a7fa6c5e6898ec 100644 --- a/clang/lib/Index/IndexDecl.cpp +++ b/clang/lib/Index/IndexDecl.cpp @@ -711,7 +711,8 @@ class IndexingDeclVisitor : public ConstDeclVisitor { } else if (const auto *NTTP = dyn_cast(TP)) { IndexCtx.indexTypeSourceInfo(NTTP->getTypeSourceInfo(), Parent); if (NTTP->hasDefaultArgument()) - IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent); + handleTemplateArgumentLoc(NTTP->getDefaultArgument(), Parent, + TP->getLexicalDeclContext()); } else if (const auto *TTPD = dyn_cast(TP)) { if (TTPD->hasDefaultArgument()) handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent, diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index fa8c852ea9e9f2..a2b29a7bdf505c 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -442,10 +442,12 @@ void HLSLExternalSemaSource::defineHLSLVectorAlias() { AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 1, &AST.Idents.get("element_count", tok::TokenKind::identifier), AST.IntTy, false, AST.getTrivialTypeSourceInfo(AST.IntTy)); - Expr *LiteralExpr = - IntegerLiteral::Create(AST, llvm::APInt(AST.getIntWidth(AST.IntTy), 4), - AST.IntTy, SourceLocation()); - SizeParam->setDefaultArgument(LiteralExpr); + llvm::APInt Val(AST.getIntWidth(AST.IntTy), 4); + TemplateArgument Default(AST, llvm::APSInt(std::move(Val)), AST.IntTy, + /*IsDefaulted=*/true); + SizeParam->setDefaultArgument( + AST, SemaPtr->getTrivialTemplateArgumentLoc(Default, AST.IntTy, + SourceLocation(), SizeParam)); TemplateParams.emplace_back(SizeParam); auto *ParamList = diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index f930bd8651d51d..268f079980a6c3 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1599,7 +1599,9 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, if (DiagnoseUnexpandedParameterPack(Default, UPPC_DefaultArgument)) return Param; - Param->setDefaultArgument(Default); + Param->setDefaultArgument( + Context, getTrivialTemplateArgumentLoc(TemplateArgument(Default), + QualType(), SourceLocation())); } return Param; @@ -1805,6 +1807,8 @@ static void SetNestedNameSpecifier(Sema &S, TagDecl *T, // Returns the template parameter list with all default template argument // information. static TemplateParameterList *GetTemplateParameterList(TemplateDecl *TD) { + if (TD->isImplicit()) + return TD->getTemplateParameters(); // Make sure we get the template parameter list from the most // recent declaration, since that is the only one that is guaranteed to // have all the default template argument information. @@ -1825,7 +1829,8 @@ static TemplateParameterList *GetTemplateParameterList(TemplateDecl *TD) { // template friend struct C; // }; // template struct S; - while (D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None && + while ((D->isImplicit() || + D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None) && D->getPreviousDecl()) D = D->getPreviousDecl(); return cast(D)->getTemplateParameters(); @@ -3630,9 +3635,9 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // Check the presence of a default argument here. if (NewNonTypeParm->hasDefaultArgument() && - DiagnoseDefaultTemplateArgument(*this, TPC, - NewNonTypeParm->getLocation(), - NewNonTypeParm->getDefaultArgument()->getSourceRange())) { + DiagnoseDefaultTemplateArgument( + *this, TPC, NewNonTypeParm->getLocation(), + NewNonTypeParm->getDefaultArgument().getSourceRange())) { NewNonTypeParm->removeDefaultArgument(); } @@ -6107,16 +6112,17 @@ static bool SubstDefaultTemplateArgument( /// parameters that precede \p Param in the template parameter list. /// /// \returns the substituted template argument, or NULL if an error occurred. -static ExprResult SubstDefaultTemplateArgument( +static bool SubstDefaultTemplateArgument( Sema &SemaRef, TemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation RAngleLoc, NonTypeTemplateParmDecl *Param, ArrayRef SugaredConverted, - ArrayRef CanonicalConverted) { + ArrayRef CanonicalConverted, + TemplateArgumentLoc &Output) { Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, Param, Template, SugaredConverted, SourceRange(TemplateLoc, RAngleLoc)); if (Inst.isInvalid()) - return ExprError(); + return true; // Only substitute for the innermost template argument list. MultiLevelTemplateArgumentList TemplateArgLists(Template, SugaredConverted, @@ -6127,7 +6133,8 @@ static ExprResult SubstDefaultTemplateArgument( Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext()); EnterExpressionEvaluationContext ConstantEvaluated( SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); - return SemaRef.SubstExpr(Param->getDefaultArgument(), TemplateArgLists); + return SemaRef.SubstTemplateArgument(Param->getDefaultArgument(), + TemplateArgLists, Output); } /// Substitute template arguments into the default template argument for @@ -6219,14 +6226,12 @@ TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable( return TemplateArgumentLoc(); HasDefaultArg = true; - ExprResult Arg = SubstDefaultTemplateArgument( - *this, Template, TemplateLoc, RAngleLoc, NonTypeParm, SugaredConverted, - CanonicalConverted); - if (Arg.isInvalid()) + TemplateArgumentLoc Output; + if (SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc, + NonTypeParm, SugaredConverted, + CanonicalConverted, Output)) return TemplateArgumentLoc(); - - Expr *ArgE = Arg.getAs(); - return TemplateArgumentLoc(TemplateArgument(ArgE), ArgE); + return Output; } TemplateTemplateParmDecl *TempTempParm @@ -6803,14 +6808,10 @@ bool Sema::CheckTemplateArgumentList( return diagnoseMissingArgument(*this, TemplateLoc, Template, NTTP, NewArgs); - ExprResult E = SubstDefaultTemplateArgument( - *this, Template, TemplateLoc, RAngleLoc, NTTP, SugaredConverted, - CanonicalConverted); - if (E.isInvalid()) + if (SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc, + NTTP, SugaredConverted, + CanonicalConverted, Arg)) return true; - - Expr *Ex = E.getAs(); - Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex); } else { TemplateTemplateParmDecl *TempParm = cast(*Param); @@ -9523,10 +9524,10 @@ DeclResult Sema::ActOnClassTemplateSpecialization( } } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast(Param)) { - if (Expr *DefArg = NTTP->getDefaultArgument()) { + if (NTTP->hasDefaultArgument()) { Diag(NTTP->getDefaultArgumentLoc(), diag::err_default_arg_in_partial_spec) - << DefArg->getSourceRange(); + << NTTP->getDefaultArgument().getSourceRange(); NTTP->removeDefaultArgument(); } } else { diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 0c348633576d64..76f47e9cb2560d 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -527,8 +527,8 @@ static NamedDecl *getTemplateParameterWithDefault(Sema &S, NamedDecl *A, R->setDefaultArgument( S.Context, S.getTrivialTemplateArgumentLoc(Default, QualType(), SourceLocation())); - if (R->hasTypeConstraint()) { - auto *C = R->getTypeConstraint(); + if (T->hasTypeConstraint()) { + auto *C = T->getTypeConstraint(); R->setTypeConstraint(C->getConceptReference(), C->getImmediatelyDeclaredConstraint()); } @@ -536,14 +536,14 @@ static NamedDecl *getTemplateParameterWithDefault(Sema &S, NamedDecl *A, } case Decl::NonTypeTemplateParm: { auto *T = cast(A); - // FIXME: Ditto, as above for TemplateTypeParm case. - if (T->isParameterPack()) - return A; auto *R = NonTypeTemplateParmDecl::Create( S.Context, A->getDeclContext(), SourceLocation(), SourceLocation(), T->getDepth(), T->getIndex(), T->getIdentifier(), T->getType(), - /*ParameterPack=*/false, T->getTypeSourceInfo()); - R->setDefaultArgument(Default.getAsExpr()); + T->isParameterPack(), T->getTypeSourceInfo()); + R->setDefaultArgument(S.Context, + S.getTrivialTemplateArgumentLoc( + Default, Default.getNonTypeTemplateArgumentType(), + SourceLocation())); if (auto *PTC = T->getPlaceholderTypeConstraint()) R->setPlaceholderTypeConstraint(PTC); return R; @@ -583,37 +583,53 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, return TemplateDeductionResult::Success; auto NewDeduced = DeducedTemplateArgument(Arg); - // Provisional resolution for CWG2398: If Arg is also a template template - // param, and it names a template specialization, then we deduce a - // synthesized template template parameter based on A, but using the TS's - // arguments as defaults. - if (auto *TempArg = dyn_cast_or_null( - Arg.getAsTemplateDecl())) { + // Provisional resolution for CWG2398: If Arg names a template + // specialization, then we deduce a synthesized template template parameter + // based on A, but using the TS's arguments as defaults. + if (DefaultArguments.size() != 0) { assert(Arg.getKind() == TemplateName::Template); - assert(!TempArg->isExpandedParameterPack()); - + TemplateDecl *TempArg = Arg.getAsTemplateDecl(); TemplateParameterList *As = TempArg->getTemplateParameters(); - if (DefaultArguments.size() != 0) { - assert(DefaultArguments.size() <= As->size()); - SmallVector Params(As->size()); - for (unsigned I = 0; I < DefaultArguments.size(); ++I) - Params[I] = getTemplateParameterWithDefault(S, As->getParam(I), - DefaultArguments[I]); - for (unsigned I = DefaultArguments.size(); I < As->size(); ++I) - Params[I] = As->getParam(I); - // FIXME: We could unique these, and also the parameters, but we don't - // expect programs to contain a large enough amount of these deductions - // for that to be worthwhile. - auto *TPL = TemplateParameterList::Create( - S.Context, SourceLocation(), SourceLocation(), Params, - SourceLocation(), As->getRequiresClause()); - NewDeduced = DeducedTemplateArgument( - TemplateName(TemplateTemplateParmDecl::Create( - S.Context, TempArg->getDeclContext(), SourceLocation(), - TempArg->getDepth(), TempArg->getPosition(), - TempArg->isParameterPack(), TempArg->getIdentifier(), - TempArg->wasDeclaredWithTypename(), TPL))); + assert(DefaultArguments.size() <= As->size()); + + SmallVector Params(As->size()); + for (unsigned I = 0; I < DefaultArguments.size(); ++I) + Params[I] = getTemplateParameterWithDefault(S, As->getParam(I), + DefaultArguments[I]); + for (unsigned I = DefaultArguments.size(); I < As->size(); ++I) + Params[I] = As->getParam(I); + // FIXME: We could unique these, and also the parameters, but we don't + // expect programs to contain a large enough amount of these deductions + // for that to be worthwhile. + auto *TPL = TemplateParameterList::Create( + S.Context, SourceLocation(), SourceLocation(), Params, + SourceLocation(), As->getRequiresClause()); + + TemplateDecl *TD; + switch (TempArg->getKind()) { + case Decl::TemplateTemplateParm: { + auto *A = cast(TempArg); + assert(!A->isExpandedParameterPack()); + TD = TemplateTemplateParmDecl::Create( + S.Context, A->getDeclContext(), SourceLocation(), A->getDepth(), + A->getPosition(), A->isParameterPack(), A->getIdentifier(), + A->wasDeclaredWithTypename(), TPL); + break; + } + case Decl::ClassTemplate: { + auto *A = cast(TempArg); + auto *CT = ClassTemplateDecl::Create(S.Context, A->getDeclContext(), + SourceLocation(), A->getDeclName(), + TPL, A->getTemplatedDecl()); + CT->setPreviousDecl(A); + TD = CT; + break; + } + default: + llvm_unreachable("Unexpected Template Kind"); } + TD->setImplicit(true); + NewDeduced = DeducedTemplateArgument(TemplateName(TD)); } DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context, diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 38a300332068fa..09812946bd3833 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3123,9 +3123,10 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { EnterExpressionEvaluationContext ConstantEvaluated( SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult Value = SemaRef.SubstExpr(D->getDefaultArgument(), TemplateArgs); - if (!Value.isInvalid()) - Param->setDefaultArgument(Value.get()); + TemplateArgumentLoc Result; + if (!SemaRef.SubstTemplateArgument(D->getDefaultArgument(), TemplateArgs, + Result)) + Param->setDefaultArgument(SemaRef.Context, Result); } // Introduce this template parameter's instantiation into the instantiation diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index d7a9e31b477f88..61cc99d4df6871 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2717,7 +2717,8 @@ void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { // Rest of NonTypeTemplateParmDecl. D->ParameterPack = Record.readInt(); if (Record.readInt()) - D->setDefaultArgument(Record.readExpr()); + D->setDefaultArgument(Reader.getContext(), + Record.readTemplateArgumentLoc()); } } diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index b2a214e935aadd..bbd16dbdb8ffff 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1941,7 +1941,7 @@ void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { !D->defaultArgumentWasInherited(); Record.push_back(OwnsDefaultArg); if (OwnsDefaultArg) - Record.AddStmt(D->getDefaultArgument()); + Record.AddTemplateArgumentLoc(D->getDefaultArgument()); Code = serialization::DECL_NON_TYPE_TEMPLATE_PARM; } } diff --git a/clang/test/AST/ast-dump-decl.cpp b/clang/test/AST/ast-dump-decl.cpp index 554cdcf83fcdfc..e062d4f068a403 100644 --- a/clang/test/AST/ast-dump-decl.cpp +++ b/clang/test/AST/ast-dump-decl.cpp @@ -459,7 +459,7 @@ namespace testClassTemplateDecl { // CHECK: ClassTemplateDecl 0x{{.+}} <{{.+}}:[[@LINE-148]]:3, col:31> col:31 TestTemplateDefaultNonType{{$}} // CHECK-NEXT: |-NonTypeTemplateParmDecl 0x{{.+}} col:16 'int' depth 0 index 0 I{{$}} -// CHECK-NEXT: | `-TemplateArgument expr{{$}} +// CHECK-NEXT: | `-TemplateArgument expr{{$}} // CHECK-NEXT: | `-IntegerLiteral 0x{{.+}} 'int' 42{{$}} // CHECK-NEXT: `-CXXRecordDecl 0x{{.+}} col:31 struct TestTemplateDefaultNonType{{$}} @@ -671,7 +671,7 @@ namespace TestNonTypeTemplateParmDecl { // CHECK: NamespaceDecl{{.*}} TestNonTypeTemplateParmDecl // CHECK-NEXT: FunctionTemplateDecl // CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 0 I -// CHECK-NEXT: TemplateArgument expr +// CHECK-NEXT: TemplateArgument {{.*}} expr // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1 // CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 1 ... J diff --git a/clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp b/clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp index a5b39fe5c51f70..bc39431253880c 100644 --- a/clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp @@ -28,13 +28,14 @@ namespace StdExample { { /* ... */ } template class TT> - void f(TT); // expected-note {{candidate template ignored}} + void f(TT); template class TT> void g(TT>); int h() { - f(v); // expected-error {{no matching function for call to 'f'}} + f(v); // OK: TT = vector, Alloc is used as the default argument for the + // second parameter. g(v); // OK: TT = vector } diff --git a/clang/test/SemaTemplate/cwg2398.cpp b/clang/test/SemaTemplate/cwg2398.cpp index e3b5e575374d3f..4cc946735a1e27 100644 --- a/clang/test/SemaTemplate/cwg2398.cpp +++ b/clang/test/SemaTemplate/cwg2398.cpp @@ -65,13 +65,10 @@ namespace class_template { template struct B; template