[clang] fix P3310 overload resolution flag propagation (#125372)

This commit is contained in:
Matheus Izvekov 2025-02-04 12:17:49 -03:00 committed by GitHub
parent f4c2e5df6f
commit f4958723b2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 6141 additions and 44 deletions

View File

@ -1841,15 +1841,23 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
LLVM_PREFERRED_TYPE(TemplateSpecializationKind)
unsigned SpecializationKind : 3;
/// Indicate that we have matched a parameter pack with a non pack
/// argument, when the opposite match is also allowed (strict pack match).
/// This needs to be cached as deduction is performed during declaration,
/// and we need the information to be preserved so that it is consistent
/// during instantiation.
bool MatchedPackOnParmToNonPackOnArg : 1;
protected:
ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc,
ClassTemplateDecl *SpecializedTemplate,
ArrayRef<TemplateArgument> Args,
bool MatchedPackOnParmToNonPackOnArg,
ClassTemplateSpecializationDecl *PrevDecl);
explicit ClassTemplateSpecializationDecl(ASTContext &C, Kind DK);
ClassTemplateSpecializationDecl(ASTContext &C, Kind DK);
public:
friend class ASTDeclReader;
@ -1859,7 +1867,7 @@ public:
Create(ASTContext &Context, TagKind TK, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
ClassTemplateDecl *SpecializedTemplate,
ArrayRef<TemplateArgument> Args,
ArrayRef<TemplateArgument> Args, bool MatchedPackOnParmToNonPackOnArg,
ClassTemplateSpecializationDecl *PrevDecl);
static ClassTemplateSpecializationDecl *CreateDeserialized(ASTContext &C,
GlobalDeclID ID);
@ -1930,6 +1938,10 @@ public:
SpecializationKind = TSK;
}
bool hasMatchedPackOnParmToNonPackOnArg() const {
return MatchedPackOnParmToNonPackOnArg;
}
/// Get the point of instantiation (if any), or null if none.
SourceLocation getPointOfInstantiation() const {
return PointOfInstantiation;

View File

@ -13499,8 +13499,8 @@ public:
bool InstantiateClassTemplateSpecialization(
SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,
TemplateSpecializationKind TSK, bool Complain = true,
bool PrimaryHasMatchedPackOnParmToNonPackOnArg = false);
TemplateSpecializationKind TSK, bool Complain,
bool PrimaryHasMatchedPackOnParmToNonPackOnArg);
/// Instantiates the definitions of all of the member
/// of the given class, which is an instantiation of a class template

View File

@ -6321,9 +6321,9 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl(
updateLookupTableForTemplateParameters(*ToTPList);
} else { // Not a partial specialization.
if (GetImportedOrCreateDecl(
D2, D, Importer.getToContext(), D->getTagKind(), DC,
*BeginLocOrErr, *IdLocOrErr, ClassTemplate, TemplateArgs,
PrevDecl))
D2, D, Importer.getToContext(), D->getTagKind(), DC, *BeginLocOrErr,
*IdLocOrErr, ClassTemplate, TemplateArgs,
D->hasMatchedPackOnParmToNonPackOnArg(), PrevDecl))
return D2;
// Update InsertPos, because preceding import calls may have invalidated

View File

@ -957,18 +957,20 @@ FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create(
// ClassTemplateSpecializationDecl Implementation
//===----------------------------------------------------------------------===//
ClassTemplateSpecializationDecl::
ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc,
ClassTemplateDecl *SpecializedTemplate,
ArrayRef<TemplateArgument> Args,
ClassTemplateSpecializationDecl *PrevDecl)
ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(
ASTContext &Context, Kind DK, TagKind TK, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args,
bool MatchedPackOnParmToNonPackOnArg,
ClassTemplateSpecializationDecl *PrevDecl)
: CXXRecordDecl(DK, TK, Context, DC, StartLoc, IdLoc,
SpecializedTemplate->getIdentifier(), PrevDecl),
SpecializedTemplate(SpecializedTemplate),
TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
SpecializationKind(TSK_Undeclared) {
SpecializedTemplate(SpecializedTemplate),
TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
SpecializationKind(TSK_Undeclared),
MatchedPackOnParmToNonPackOnArg(MatchedPackOnParmToNonPackOnArg) {
assert(DK == Kind::ClassTemplateSpecialization ||
MatchedPackOnParmToNonPackOnArg == false);
}
ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C,
@ -977,18 +979,14 @@ ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C,
SourceLocation(), nullptr, nullptr),
SpecializationKind(TSK_Undeclared) {}
ClassTemplateSpecializationDecl *
ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
DeclContext *DC,
SourceLocation StartLoc,
SourceLocation IdLoc,
ClassTemplateDecl *SpecializedTemplate,
ArrayRef<TemplateArgument> Args,
ClassTemplateSpecializationDecl *PrevDecl) {
auto *Result =
new (Context, DC) ClassTemplateSpecializationDecl(
Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
SpecializedTemplate, Args, PrevDecl);
ClassTemplateSpecializationDecl *ClassTemplateSpecializationDecl::Create(
ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate,
ArrayRef<TemplateArgument> Args, bool MatchedPackOnParmToNonPackOnArg,
ClassTemplateSpecializationDecl *PrevDecl) {
auto *Result = new (Context, DC) ClassTemplateSpecializationDecl(
Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
SpecializedTemplate, Args, MatchedPackOnParmToNonPackOnArg, PrevDecl);
Result->setMayHaveOutOfDateDef(false);
// If the template decl is incomplete, copy the external lexical storage from
@ -1175,7 +1173,10 @@ ClassTemplatePartialSpecializationDecl::ClassTemplatePartialSpecializationDecl(
ClassTemplatePartialSpecializationDecl *PrevDecl)
: ClassTemplateSpecializationDecl(
Context, ClassTemplatePartialSpecialization, TK, DC, StartLoc, IdLoc,
SpecializedTemplate, Args, PrevDecl),
// Tracking MatchedPackOnParmToNonPackOnArg for Partial
// Specializations is not needed.
SpecializedTemplate, Args, /*MatchedPackOnParmToNonPackOnArg=*/false,
PrevDecl),
TemplateParams(Params), InstantiatedFromMember(nullptr, false) {
if (AdoptTemplateParameterList(Params, this))
setInvalidDecl();

View File

@ -1003,6 +1003,11 @@ void JSONNodeDumper::VisitRecordDecl(const RecordDecl *RD) {
void JSONNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *RD) {
VisitRecordDecl(RD);
if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
if (CTSD->hasMatchedPackOnParmToNonPackOnArg())
JOS.attribute("strict-pack-match", true);
}
// All other information requires a complete definition.
if (!RD->isCompleteDefinition())
return;

View File

@ -2525,8 +2525,11 @@ void TextNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
OS << " instantiated_from";
dumpPointer(Instance);
}
if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D))
if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
dumpTemplateSpecializationKind(CTSD->getSpecializationKind());
if (CTSD->hasMatchedPackOnParmToNonPackOnArg())
OS << " strict-pack-match";
}
dumpNestedNameSpecifier(D->getQualifier());

View File

@ -3651,7 +3651,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
ClassTemplate->getDeclContext(),
ClassTemplate->getTemplatedDecl()->getBeginLoc(),
ClassTemplate->getLocation(), ClassTemplate, CTAI.CanonicalConverted,
nullptr);
CTAI.MatchedPackOnParmToNonPackOnArg, nullptr);
ClassTemplate->AddSpecialization(Decl, InsertPos);
if (ClassTemplate->isOutOfLine())
Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext());
@ -8526,7 +8526,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
// this explicit specialization or friend declaration.
Specialization = ClassTemplateSpecializationDecl::Create(
Context, Kind, DC, KWLoc, TemplateNameLoc, ClassTemplate,
CTAI.CanonicalConverted, PrevDecl);
CTAI.CanonicalConverted, CTAI.MatchedPackOnParmToNonPackOnArg,
PrevDecl);
Specialization->setTemplateArgsAsWritten(TemplateArgs);
SetNestedNameSpecifier(*this, Specialization, SS);
if (TemplateParameterLists.size() > 0) {
@ -9869,7 +9870,8 @@ DeclResult Sema::ActOnExplicitInstantiation(
// this explicit specialization.
Specialization = ClassTemplateSpecializationDecl::Create(
Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc,
ClassTemplate, CTAI.CanonicalConverted, PrevDecl);
ClassTemplate, CTAI.CanonicalConverted,
CTAI.MatchedPackOnParmToNonPackOnArg, PrevDecl);
SetNestedNameSpecifier(*this, Specialization, SS);
// A MSInheritanceAttr attached to the previous declaration must be

View File

@ -3341,8 +3341,6 @@ FinishTemplateArgumentDeduction(
return ConstraintsNotSatisfied
? TemplateDeductionResult::ConstraintsNotSatisfied
: TemplateDeductionResult::SubstitutionFailure;
if (InstCTAI.MatchedPackOnParmToNonPackOnArg)
Info.setMatchedPackOnParmToNonPackOnArg();
TemplateParameterList *TemplateParams = Template->getTemplateParameters();
for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {

View File

@ -4038,7 +4038,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
ClassTemplateSpecializationDecl::Create(
SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(),
D->getLocation(), InstClassTemplate, CTAI.CanonicalConverted,
PrevDecl);
CTAI.MatchedPackOnParmToNonPackOnArg, PrevDecl);
InstD->setTemplateArgsAsWritten(InstTemplateArgs);
// Add this partial specialization to the set of class template partial

View File

@ -9399,7 +9399,8 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
runWithSufficientStackSpace(Loc, [&] {
Diagnosed = InstantiateClassTemplateSpecialization(
Loc, ClassTemplateSpec, TSK_ImplicitInstantiation,
/*Complain=*/Diagnoser);
/*Complain=*/Diagnoser,
ClassTemplateSpec->hasMatchedPackOnParmToNonPackOnArg());
});
Instantiated = true;
}

View File

@ -2532,6 +2532,7 @@ RedeclarableResult ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs);
D->PointOfInstantiation = readSourceLocation();
D->SpecializationKind = (TemplateSpecializationKind)Record.readInt();
D->MatchedPackOnParmToNonPackOnArg = Record.readBool();
bool writtenAsCanonicalDecl = Record.readInt();
if (writtenAsCanonicalDecl) {

View File

@ -1843,6 +1843,7 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl(
Record.AddTemplateArgumentList(&D->getTemplateArgs());
Record.AddSourceLocation(D->getPointOfInstantiation());
Record.push_back(D->getSpecializationKind());
Record.push_back(D->hasMatchedPackOnParmToNonPackOnArg());
Record.push_back(D->isCanonicalDecl());
if (D->isCanonicalDecl()) {

File diff suppressed because it is too large Load Diff

View File

@ -83,6 +83,12 @@ def main():
action="store",
default="",
)
parser.add_argument(
"--prefix",
help="The FileCheck prefix",
action="store",
default="CHECK",
)
update_or_generate_group = parser.add_mutually_exclusive_group()
update_or_generate_group.add_argument(
"--update", help="Update the file in-place", action="store_true"
@ -113,11 +119,18 @@ def main():
cmdline_opts=args.opts,
do_update=args.update,
force_update=args.update_manual,
prefix=args.prefix,
)
def process_file(
source_file, clang_binary, cmdline_filters, cmdline_opts, do_update, force_update
source_file,
clang_binary,
cmdline_filters,
cmdline_opts,
do_update,
force_update,
prefix,
):
note_firstline = (
"// NOTE: CHECK lines have been autogenerated by " "gen_ast_dump_json_test.py"
@ -227,14 +240,14 @@ def process_file(
for out_ast in out_asts:
append_str = json.dumps(out_ast, indent=1, ensure_ascii=False)
out_str = "\n\n"
out_str += "// CHECK-NOT: {{^}}Dumping\n"
out_str += f"// {prefix}-NOT: {{{{^}}}}Dumping\n"
index = 0
for append_line in append_str.splitlines()[2:]:
if index == 0:
out_str += "// CHECK: %s\n" % (append_line.rstrip())
out_str += f"// {prefix}: %s\n" % (append_line.rstrip())
index += 1
else:
out_str += "// CHECK-NEXT: %s\n" % (append_line.rstrip())
out_str += f"// {prefix}-NEXT: %s\n" % (append_line.rstrip())
f.write(out_str)
f.flush()

View File

@ -585,6 +585,23 @@ namespace regression2 {
template <typename, int> struct Matrix;
template struct D<Matrix<double, 3>>;
} // namespace regression2
namespace regression3 {
struct None {};
template<class T> struct Node { using type = T; };
template <template<class> class TT, class T>
struct A {
static_assert(!__is_same(T, None));
using type2 = typename A<TT, typename T::type>::type2;
};
template <template<class> class TT> struct A<TT, None> {
using type2 = void;
};
template <class...> class B {};
template struct A<B, Node<None>>;
} // namespace regression3
namespace nttp_auto {
namespace t1 {