mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-17 00:36:34 +00:00
[clang] fix P3310 overload resolution flag propagation (#125372)
This commit is contained in:
parent
f4c2e5df6f
commit
f4958723b2
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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
@ -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()
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user