diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index dc8daa605fac7..4640ecccb9ad4 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -289,6 +289,8 @@ Bug Fixes to C++ Support (`#50866 `_) - Fix ordering of function templates by constraints when they have template template parameters with different nested constraints. +- Fix type equivalence comparison between auto types to take constraints into + account. Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 841a0995238e5..612fcd4897c8f 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -5794,12 +5794,19 @@ QualType ASTContext::getAutoTypeInternal( if (!DeducedType.isNull()) { Canon = DeducedType.getCanonicalType(); } else if (TypeConstraintConcept) { - Canon = getAutoTypeInternal(QualType(), Keyword, IsDependent, IsPack, - nullptr, {}, true); - // Find the insert position again. - [[maybe_unused]] auto *Nothing = - AutoTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(!Nothing && "canonical type broken"); + bool AnyNonCanonArgs = false; + ConceptDecl *CanonicalConcept = TypeConstraintConcept->getCanonicalDecl(); + auto CanonicalConceptArgs = ::getCanonicalTemplateArguments( + *this, TypeConstraintArgs, AnyNonCanonArgs); + if (CanonicalConcept != TypeConstraintConcept || AnyNonCanonArgs) { + Canon = + getAutoTypeInternal(QualType(), Keyword, IsDependent, IsPack, + CanonicalConcept, CanonicalConceptArgs, true); + // Find the insert position again. + [[maybe_unused]] auto *Nothing = + AutoTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!Nothing && "canonical type broken"); + } } } diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp index f3d74b27e3267..c21e9c861875b 100644 --- a/clang/lib/AST/TemplateBase.cpp +++ b/clang/lib/AST/TemplateBase.cpp @@ -329,7 +329,7 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, ID.AddInteger(TemplateArg.NumExpansions); LLVM_FALLTHROUGH; case Template: - getAsTemplateOrTemplatePattern().Profile(ID); + ID.AddPointer(TemplateArg.Name); break; case Integral: diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 464939427a770..276b5aa59f759 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -4590,8 +4590,14 @@ AutoType::AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword, auto *ArgBuffer = const_cast(getTypeConstraintArguments().data()); for (const TemplateArgument &Arg : TypeConstraintArgs) { - addDependence( - toSyntacticDependence(toTypeDependence(Arg.getDependence()))); + // If we have a deduced type, our constraints never affect semantic + // dependence. Prior to deduction, however, our canonical type depends + // on the template arguments, so we are a dependent type if any of them + // is dependent. + TypeDependence ArgDependence = toTypeDependence(Arg.getDependence()); + if (!DeducedAsType.isNull()) + ArgDependence = toSyntacticDependence(ArgDependence); + addDependence(ArgDependence); new (ArgBuffer++) TemplateArgument(Arg); } diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 611ebc9859388..2f13505d8ed71 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -1613,7 +1613,9 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( llvm_unreachable("Type nodes handled above"); case Type::Auto: - // FIXME: Implement deduction in dependent case. + // FIXME: It's not clear whether we should deduce the template arguments + // of a constrained deduced type. For now we treat them as a non-deduced + // context. if (P->isDependentType()) return Sema::TDK_Success; [[fallthrough]]; diff --git a/clang/test/CXX/dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp b/clang/test/CXX/dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp index 557ea02001bb7..a8f2ed3af2905 100644 --- a/clang/test/CXX/dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp +++ b/clang/test/CXX/dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp @@ -81,9 +81,9 @@ namespace PR48617 { template concept C = true; template class A {}; - template C auto e(A) { return 0; } - template auto e<>(A<>); - template auto e(A); + template C auto e(A) { return 0; } // expected-note 2{{failed template argument deduction}} + template auto e<>(A<>); // expected-error {{does not refer to a function template}} + template auto e(A); // expected-error {{does not refer to a function template}} template C auto d(A) { return 0; } template C<> auto d<>(A<>);