Skip to content

Commit 9189ca8

Browse files
mizvekovtstellar
authored andcommitted
Backport: [clang] fix P3310 overload resolution flag propagation (#125791)
Class templates might be only instantiated when they are required to be complete, but checking the template args against the primary template is immediate. This result is cached so that later when the class is instantiated, checking against the primary template is not repeated. The 'MatchedPackOnParmToNonPackOnArg' flag is also produced upon checking against the primary template, so it needs to be cached in the specialziation as well. This fixes a bug which has not been in any release, so there are no release notes. Fixes #125290
1 parent 99947c5 commit 9189ca8

16 files changed

+6146
-45
lines changed

clang/include/clang/AST/DeclTemplate.h

+14-2
Original file line numberDiff line numberDiff line change
@@ -1841,15 +1841,23 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
18411841
LLVM_PREFERRED_TYPE(TemplateSpecializationKind)
18421842
unsigned SpecializationKind : 3;
18431843

1844+
/// Indicate that we have matched a parameter pack with a non pack
1845+
/// argument, when the opposite match is also allowed (strict pack match).
1846+
/// This needs to be cached as deduction is performed during declaration,
1847+
/// and we need the information to be preserved so that it is consistent
1848+
/// during instantiation.
1849+
bool MatchedPackOnParmToNonPackOnArg : 1;
1850+
18441851
protected:
18451852
ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
18461853
DeclContext *DC, SourceLocation StartLoc,
18471854
SourceLocation IdLoc,
18481855
ClassTemplateDecl *SpecializedTemplate,
18491856
ArrayRef<TemplateArgument> Args,
1857+
bool MatchedPackOnParmToNonPackOnArg,
18501858
ClassTemplateSpecializationDecl *PrevDecl);
18511859

1852-
explicit ClassTemplateSpecializationDecl(ASTContext &C, Kind DK);
1860+
ClassTemplateSpecializationDecl(ASTContext &C, Kind DK);
18531861

18541862
public:
18551863
friend class ASTDeclReader;
@@ -1859,7 +1867,7 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
18591867
Create(ASTContext &Context, TagKind TK, DeclContext *DC,
18601868
SourceLocation StartLoc, SourceLocation IdLoc,
18611869
ClassTemplateDecl *SpecializedTemplate,
1862-
ArrayRef<TemplateArgument> Args,
1870+
ArrayRef<TemplateArgument> Args, bool MatchedPackOnParmToNonPackOnArg,
18631871
ClassTemplateSpecializationDecl *PrevDecl);
18641872
static ClassTemplateSpecializationDecl *CreateDeserialized(ASTContext &C,
18651873
GlobalDeclID ID);
@@ -1930,6 +1938,10 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
19301938
SpecializationKind = TSK;
19311939
}
19321940

1941+
bool hasMatchedPackOnParmToNonPackOnArg() const {
1942+
return MatchedPackOnParmToNonPackOnArg;
1943+
}
1944+
19331945
/// Get the point of instantiation (if any), or null if none.
19341946
SourceLocation getPointOfInstantiation() const {
19351947
return PointOfInstantiation;

clang/include/clang/Sema/Sema.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -13491,8 +13491,8 @@ class Sema final : public SemaBase {
1349113491
bool InstantiateClassTemplateSpecialization(
1349213492
SourceLocation PointOfInstantiation,
1349313493
ClassTemplateSpecializationDecl *ClassTemplateSpec,
13494-
TemplateSpecializationKind TSK, bool Complain = true,
13495-
bool PrimaryHasMatchedPackOnParmToNonPackOnArg = false);
13494+
TemplateSpecializationKind TSK, bool Complain,
13495+
bool PrimaryHasMatchedPackOnParmToNonPackOnArg);
1349613496

1349713497
/// Instantiates the definitions of all of the member
1349813498
/// of the given class, which is an instantiation of a class template

clang/lib/AST/ASTImporter.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -6321,9 +6321,9 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl(
63216321
updateLookupTableForTemplateParameters(*ToTPList);
63226322
} else { // Not a partial specialization.
63236323
if (GetImportedOrCreateDecl(
6324-
D2, D, Importer.getToContext(), D->getTagKind(), DC,
6325-
*BeginLocOrErr, *IdLocOrErr, ClassTemplate, TemplateArgs,
6326-
PrevDecl))
6324+
D2, D, Importer.getToContext(), D->getTagKind(), DC, *BeginLocOrErr,
6325+
*IdLocOrErr, ClassTemplate, TemplateArgs,
6326+
D->hasMatchedPackOnParmToNonPackOnArg(), PrevDecl))
63276327
return D2;
63286328

63296329
// Update InsertPos, because preceding import calls may have invalidated

clang/lib/AST/DeclTemplate.cpp

+24-23
Original file line numberDiff line numberDiff line change
@@ -957,18 +957,20 @@ FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create(
957957
// ClassTemplateSpecializationDecl Implementation
958958
//===----------------------------------------------------------------------===//
959959

960-
ClassTemplateSpecializationDecl::
961-
ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
962-
DeclContext *DC, SourceLocation StartLoc,
963-
SourceLocation IdLoc,
964-
ClassTemplateDecl *SpecializedTemplate,
965-
ArrayRef<TemplateArgument> Args,
966-
ClassTemplateSpecializationDecl *PrevDecl)
960+
ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(
961+
ASTContext &Context, Kind DK, TagKind TK, DeclContext *DC,
962+
SourceLocation StartLoc, SourceLocation IdLoc,
963+
ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args,
964+
bool MatchedPackOnParmToNonPackOnArg,
965+
ClassTemplateSpecializationDecl *PrevDecl)
967966
: CXXRecordDecl(DK, TK, Context, DC, StartLoc, IdLoc,
968967
SpecializedTemplate->getIdentifier(), PrevDecl),
969-
SpecializedTemplate(SpecializedTemplate),
970-
TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
971-
SpecializationKind(TSK_Undeclared) {
968+
SpecializedTemplate(SpecializedTemplate),
969+
TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
970+
SpecializationKind(TSK_Undeclared),
971+
MatchedPackOnParmToNonPackOnArg(MatchedPackOnParmToNonPackOnArg) {
972+
assert(DK == Kind::ClassTemplateSpecialization ||
973+
MatchedPackOnParmToNonPackOnArg == false);
972974
}
973975

974976
ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C,
@@ -977,18 +979,14 @@ ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C,
977979
SourceLocation(), nullptr, nullptr),
978980
SpecializationKind(TSK_Undeclared) {}
979981

980-
ClassTemplateSpecializationDecl *
981-
ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
982-
DeclContext *DC,
983-
SourceLocation StartLoc,
984-
SourceLocation IdLoc,
985-
ClassTemplateDecl *SpecializedTemplate,
986-
ArrayRef<TemplateArgument> Args,
987-
ClassTemplateSpecializationDecl *PrevDecl) {
988-
auto *Result =
989-
new (Context, DC) ClassTemplateSpecializationDecl(
990-
Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
991-
SpecializedTemplate, Args, PrevDecl);
982+
ClassTemplateSpecializationDecl *ClassTemplateSpecializationDecl::Create(
983+
ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
984+
SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate,
985+
ArrayRef<TemplateArgument> Args, bool MatchedPackOnParmToNonPackOnArg,
986+
ClassTemplateSpecializationDecl *PrevDecl) {
987+
auto *Result = new (Context, DC) ClassTemplateSpecializationDecl(
988+
Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
989+
SpecializedTemplate, Args, MatchedPackOnParmToNonPackOnArg, PrevDecl);
992990
Result->setMayHaveOutOfDateDef(false);
993991

994992
// If the template decl is incomplete, copy the external lexical storage from
@@ -1175,7 +1173,10 @@ ClassTemplatePartialSpecializationDecl::ClassTemplatePartialSpecializationDecl(
11751173
ClassTemplatePartialSpecializationDecl *PrevDecl)
11761174
: ClassTemplateSpecializationDecl(
11771175
Context, ClassTemplatePartialSpecialization, TK, DC, StartLoc, IdLoc,
1178-
SpecializedTemplate, Args, PrevDecl),
1176+
// Tracking MatchedPackOnParmToNonPackOnArg for Partial
1177+
// Specializations is not needed.
1178+
SpecializedTemplate, Args, /*MatchedPackOnParmToNonPackOnArg=*/false,
1179+
PrevDecl),
11791180
TemplateParams(Params), InstantiatedFromMember(nullptr, false) {
11801181
if (AdoptTemplateParameterList(Params, this))
11811182
setInvalidDecl();

clang/lib/AST/JSONNodeDumper.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,11 @@ void JSONNodeDumper::VisitRecordDecl(const RecordDecl *RD) {
10031003
void JSONNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *RD) {
10041004
VisitRecordDecl(RD);
10051005

1006+
if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
1007+
if (CTSD->hasMatchedPackOnParmToNonPackOnArg())
1008+
JOS.attribute("strict-pack-match", true);
1009+
}
1010+
10061011
// All other information requires a complete definition.
10071012
if (!RD->isCompleteDefinition())
10081013
return;

clang/lib/AST/TextNodeDumper.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -2525,8 +2525,11 @@ void TextNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
25252525
OS << " instantiated_from";
25262526
dumpPointer(Instance);
25272527
}
2528-
if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D))
2528+
if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
25292529
dumpTemplateSpecializationKind(CTSD->getSpecializationKind());
2530+
if (CTSD->hasMatchedPackOnParmToNonPackOnArg())
2531+
OS << " strict-pack-match";
2532+
}
25302533

25312534
dumpNestedNameSpecifier(D->getQualifier());
25322535

clang/lib/Sema/SemaTemplate.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -3651,7 +3651,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
36513651
ClassTemplate->getDeclContext(),
36523652
ClassTemplate->getTemplatedDecl()->getBeginLoc(),
36533653
ClassTemplate->getLocation(), ClassTemplate, CTAI.CanonicalConverted,
3654-
nullptr);
3654+
CTAI.MatchedPackOnParmToNonPackOnArg, nullptr);
36553655
ClassTemplate->AddSpecialization(Decl, InsertPos);
36563656
if (ClassTemplate->isOutOfLine())
36573657
Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext());
@@ -8566,7 +8566,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
85668566
// this explicit specialization or friend declaration.
85678567
Specialization = ClassTemplateSpecializationDecl::Create(
85688568
Context, Kind, DC, KWLoc, TemplateNameLoc, ClassTemplate,
8569-
CTAI.CanonicalConverted, PrevDecl);
8569+
CTAI.CanonicalConverted, CTAI.MatchedPackOnParmToNonPackOnArg,
8570+
PrevDecl);
85708571
Specialization->setTemplateArgsAsWritten(TemplateArgs);
85718572
SetNestedNameSpecifier(*this, Specialization, SS);
85728573
if (TemplateParameterLists.size() > 0) {
@@ -9909,7 +9910,8 @@ DeclResult Sema::ActOnExplicitInstantiation(
99099910
// this explicit specialization.
99109911
Specialization = ClassTemplateSpecializationDecl::Create(
99119912
Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc,
9912-
ClassTemplate, CTAI.CanonicalConverted, PrevDecl);
9913+
ClassTemplate, CTAI.CanonicalConverted,
9914+
CTAI.MatchedPackOnParmToNonPackOnArg, PrevDecl);
99139915
SetNestedNameSpecifier(*this, Specialization, SS);
99149916

99159917
// A MSInheritanceAttr attached to the previous declaration must be

clang/lib/Sema/SemaTemplateDeduction.cpp

-2
Original file line numberDiff line numberDiff line change
@@ -3341,8 +3341,6 @@ FinishTemplateArgumentDeduction(
33413341
return ConstraintsNotSatisfied
33423342
? TemplateDeductionResult::ConstraintsNotSatisfied
33433343
: TemplateDeductionResult::SubstitutionFailure;
3344-
if (InstCTAI.MatchedPackOnParmToNonPackOnArg)
3345-
Info.setMatchedPackOnParmToNonPackOnArg();
33463344

33473345
TemplateParameterList *TemplateParams = Template->getTemplateParameters();
33483346
for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -4007,7 +4007,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
40074007
ClassTemplateSpecializationDecl::Create(
40084008
SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(),
40094009
D->getLocation(), InstClassTemplate, CTAI.CanonicalConverted,
4010-
PrevDecl);
4010+
CTAI.MatchedPackOnParmToNonPackOnArg, PrevDecl);
40114011
InstD->setTemplateArgsAsWritten(InstTemplateArgs);
40124012

40134013
// Add this partial specialization to the set of class template partial

clang/lib/Sema/SemaType.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -9399,7 +9399,8 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
93999399
runWithSufficientStackSpace(Loc, [&] {
94009400
Diagnosed = InstantiateClassTemplateSpecialization(
94019401
Loc, ClassTemplateSpec, TSK_ImplicitInstantiation,
9402-
/*Complain=*/Diagnoser);
9402+
/*Complain=*/Diagnoser,
9403+
ClassTemplateSpec->hasMatchedPackOnParmToNonPackOnArg());
94039404
});
94049405
Instantiated = true;
94059406
}

clang/lib/Serialization/ASTReaderDecl.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -2532,6 +2532,7 @@ RedeclarableResult ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
25322532
D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs);
25332533
D->PointOfInstantiation = readSourceLocation();
25342534
D->SpecializationKind = (TemplateSpecializationKind)Record.readInt();
2535+
D->MatchedPackOnParmToNonPackOnArg = Record.readBool();
25352536

25362537
bool writtenAsCanonicalDecl = Record.readInt();
25372538
if (writtenAsCanonicalDecl) {

clang/lib/Serialization/ASTWriterDecl.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -1843,6 +1843,7 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl(
18431843
Record.AddTemplateArgumentList(&D->getTemplateArgs());
18441844
Record.AddSourceLocation(D->getPointOfInstantiation());
18451845
Record.push_back(D->getSpecializationKind());
1846+
Record.push_back(D->hasMatchedPackOnParmToNonPackOnArg());
18461847
Record.push_back(D->isCanonicalDecl());
18471848

18481849
if (D->isCanonicalDecl()) {

0 commit comments

Comments
 (0)