diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 4ad562f2579c6..6189a69a4fa8b 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -84,6 +84,9 @@ C++ Specific Potentially Breaking Changes static_assert((b.*mp)() == 1); // newly rejected static_assert((c.*mp)() == 1); // accepted +- ``VarTemplateSpecializationDecl::getTemplateArgsAsWritten()`` method now + returns ``nullptr`` for implicitly instantiated declarations. + ABI Changes in This Version --------------------------- diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index c3fb57774c8dc..224095070cbe3 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -11662,7 +11662,8 @@ class Sema final : public SemaBase { DeclResult CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation TemplateNameLoc, - const TemplateArgumentListInfo &TemplateArgs); + const TemplateArgumentListInfo &TemplateArgs, + bool SetWrittenArgs); /// Form a reference to the specialization of the given variable template /// corresponding to the specified argument list, or a null-but-valid result @@ -14022,7 +14023,6 @@ class Sema final : public SemaBase { VarTemplateSpecializationDecl *BuildVarTemplateInstantiation( VarTemplateDecl *VarTemplate, VarDecl *FromVar, const TemplateArgumentList *PartialSpecArgs, - const TemplateArgumentListInfo &TemplateArgsInfo, SmallVectorImpl &Converted, SourceLocation PointOfInstantiation, LateInstantiatedAttrVec *LateAttrs = nullptr, diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h index fe907078af275..115c19d4f1540 100644 --- a/clang/include/clang/Sema/Template.h +++ b/clang/include/clang/Sema/Template.h @@ -723,9 +723,8 @@ enum class TemplateSubstitutionKind : char { bool SubstQualifier(const TagDecl *OldDecl, TagDecl *NewDecl); - Decl *VisitVarTemplateSpecializationDecl( + VarTemplateSpecializationDecl *VisitVarTemplateSpecializationDecl( VarTemplateDecl *VarTemplate, VarDecl *FromVar, - const TemplateArgumentListInfo &TemplateArgsInfo, ArrayRef Converted, VarTemplateSpecializationDecl *PrevDecl = nullptr); diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 4a31a139eaf4f..aedfc5e88b1c6 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -1126,8 +1126,9 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, return ExprError(); } - DeclResult VDecl = CheckVarTemplateId(VarTempl, TemplateKWLoc, - MemberNameInfo.getLoc(), *TemplateArgs); + DeclResult VDecl = + CheckVarTemplateId(VarTempl, TemplateKWLoc, MemberNameInfo.getLoc(), + *TemplateArgs, /*SetWrittenArgs=*/false); if (VDecl.isInvalid()) return ExprError(); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 3d8416ac7dc1b..3533871ad4dad 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4542,7 +4542,8 @@ static bool IsLibstdcxxStdFormatKind(Preprocessor &PP, VarDecl *Var) { DeclResult Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation TemplateNameLoc, - const TemplateArgumentListInfo &TemplateArgs) { + const TemplateArgumentListInfo &TemplateArgs, + bool SetWrittenArgs) { assert(Template && "A variable template id without template?"); // Check that the template argument list is well-formed for this template. @@ -4725,10 +4726,12 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, // in DoMarkVarDeclReferenced(). // FIXME: LateAttrs et al.? VarTemplateSpecializationDecl *Decl = BuildVarTemplateInstantiation( - Template, InstantiationPattern, PartialSpecArgs, TemplateArgs, - CTAI.CanonicalConverted, TemplateNameLoc /*, LateAttrs, StartingScope*/); + Template, InstantiationPattern, PartialSpecArgs, CTAI.CanonicalConverted, + TemplateNameLoc /*, LateAttrs, StartingScope*/); if (!Decl) return true; + if (SetWrittenArgs) + Decl->setTemplateArgsAsWritten(TemplateArgs); if (AmbiguousPartialSpec) { // Partial ordering did not produce a clear winner. Complain. @@ -4760,7 +4763,7 @@ ExprResult Sema::CheckVarTemplateId( const TemplateArgumentListInfo *TemplateArgs) { DeclResult Decl = CheckVarTemplateId(Template, TemplateLoc, NameInfo.getLoc(), - *TemplateArgs); + *TemplateArgs, /*SetWrittenArgs=*/false); if (Decl.isInvalid()) return ExprError(); @@ -10707,8 +10710,9 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, TemplateArgumentListInfo TemplateArgs = makeTemplateArgumentListInfo(*this, *D.getName().TemplateId); - DeclResult Res = CheckVarTemplateId(PrevTemplate, TemplateLoc, - D.getIdentifierLoc(), TemplateArgs); + DeclResult Res = + CheckVarTemplateId(PrevTemplate, TemplateLoc, D.getIdentifierLoc(), + TemplateArgs, /*SetWrittenArgs=*/true); if (Res.isInvalid()) return true; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index ee1b520fa46e9..910f99d3eb160 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4542,14 +4542,17 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( PrevDecl->getPointOfInstantiation(), Ignored)) return nullptr; - return VisitVarTemplateSpecializationDecl(InstVarTemplate, D, - VarTemplateArgsInfo, - CTAI.CanonicalConverted, PrevDecl); + if (VarTemplateSpecializationDecl *VTSD = VisitVarTemplateSpecializationDecl( + InstVarTemplate, D, CTAI.CanonicalConverted, PrevDecl)) { + VTSD->setTemplateArgsAsWritten(VarTemplateArgsInfo); + return VTSD; + } + return nullptr; } -Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( +VarTemplateSpecializationDecl * +TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( VarTemplateDecl *VarTemplate, VarDecl *D, - const TemplateArgumentListInfo &TemplateArgsInfo, ArrayRef Converted, VarTemplateSpecializationDecl *PrevDecl) { @@ -4570,7 +4573,6 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( VarTemplateSpecializationDecl *Var = VarTemplateSpecializationDecl::Create( SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(), VarTemplate, DI->getType(), DI, D->getStorageClass(), Converted); - Var->setTemplateArgsAsWritten(TemplateArgsInfo); if (!PrevDecl) { void *InsertPos = nullptr; VarTemplate->findSpecialization(Converted, InsertPos); @@ -5880,7 +5882,6 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation( VarTemplateDecl *VarTemplate, VarDecl *FromVar, const TemplateArgumentList *PartialSpecArgs, - const TemplateArgumentListInfo &TemplateArgsInfo, SmallVectorImpl &Converted, SourceLocation PointOfInstantiation, LateInstantiatedAttrVec *LateAttrs, LocalInstantiationScope *StartingScope) { @@ -5922,9 +5923,8 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation( // TODO: Set LateAttrs and StartingScope ... - return cast_or_null( - Instantiator.VisitVarTemplateSpecializationDecl( - VarTemplate, FromVar, TemplateArgsInfo, Converted)); + return Instantiator.VisitVarTemplateSpecializationDecl(VarTemplate, FromVar, + Converted); } VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl( @@ -6340,10 +6340,15 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, TemplateArgInfo.addArgument(Arg); } - Var = cast_or_null(Instantiator.VisitVarTemplateSpecializationDecl( - VarSpec->getSpecializedTemplate(), Def, TemplateArgInfo, - VarSpec->getTemplateArgs().asArray(), VarSpec)); + VarTemplateSpecializationDecl *VTSD = + Instantiator.VisitVarTemplateSpecializationDecl( + VarSpec->getSpecializedTemplate(), Def, + VarSpec->getTemplateArgs().asArray(), VarSpec); + Var = VTSD; + if (Var) { + VTSD->setTemplateArgsAsWritten(TemplateArgInfo); + llvm::PointerUnion PatternPtr = VarSpec->getSpecializedTemplateOrPartial(); diff --git a/clang/unittests/AST/DeclTest.cpp b/clang/unittests/AST/DeclTest.cpp index 4c83ff9142e87..e76edbfe95b68 100644 --- a/clang/unittests/AST/DeclTest.cpp +++ b/clang/unittests/AST/DeclTest.cpp @@ -586,3 +586,22 @@ namespace x::y { ASSERT_NE(FD, nullptr); ASSERT_EQ(FD->getQualifiedNameAsString(), "x::y::Foo::Foo"); } + +TEST(Decl, NoWrittenArgsInImplicitlyInstantiatedVarSpec) { + const char *Code = R"cpp( + template + int VarTpl; + + void fn() { + (void)VarTpl; + } + )cpp"; + + auto AST = tooling::buildASTFromCode(Code); + ASTContext &Ctx = AST->getASTContext(); + + const auto *VTSD = selectFirst( + "id", match(varDecl(isTemplateInstantiation()).bind("id"), Ctx)); + ASSERT_NE(VTSD, nullptr); + EXPECT_EQ(VTSD->getTemplateArgsAsWritten(), nullptr); +}