Skip to content

Commit 3524a9f

Browse files
committed
Retain constraints in the canonical form of an auto type.
This is necessary in order for type equality checking, for example across redeclarations, to require constraints to match. This is also a prerequisite for including the constraints in manglings. In passing, fix a bug where TemplateArgument::Profile would produce the same profile for two structurally different template names, which caused this change to re-expose the crash previously addressed by D133072, which it turns out had not quite addressed all problematic cases.
1 parent bc62fb9 commit 3524a9f

File tree

6 files changed

+30
-13
lines changed

6 files changed

+30
-13
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,8 @@ Bug Fixes to C++ Support
289289
(`#50866 <https://github.com/llvm/llvm-project/issues/50866>`_)
290290
- Fix ordering of function templates by constraints when they have template
291291
template parameters with different nested constraints.
292+
- Fix type equivalence comparison between auto types to take constraints into
293+
account.
292294

293295
Bug Fixes to AST Handling
294296
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/AST/ASTContext.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5794,12 +5794,19 @@ QualType ASTContext::getAutoTypeInternal(
57945794
if (!DeducedType.isNull()) {
57955795
Canon = DeducedType.getCanonicalType();
57965796
} else if (TypeConstraintConcept) {
5797-
Canon = getAutoTypeInternal(QualType(), Keyword, IsDependent, IsPack,
5798-
nullptr, {}, true);
5799-
// Find the insert position again.
5800-
[[maybe_unused]] auto *Nothing =
5801-
AutoTypes.FindNodeOrInsertPos(ID, InsertPos);
5802-
assert(!Nothing && "canonical type broken");
5797+
bool AnyNonCanonArgs = false;
5798+
ConceptDecl *CanonicalConcept = TypeConstraintConcept->getCanonicalDecl();
5799+
auto CanonicalConceptArgs = ::getCanonicalTemplateArguments(
5800+
*this, TypeConstraintArgs, AnyNonCanonArgs);
5801+
if (CanonicalConcept != TypeConstraintConcept || AnyNonCanonArgs) {
5802+
Canon =
5803+
getAutoTypeInternal(QualType(), Keyword, IsDependent, IsPack,
5804+
CanonicalConcept, CanonicalConceptArgs, true);
5805+
// Find the insert position again.
5806+
[[maybe_unused]] auto *Nothing =
5807+
AutoTypes.FindNodeOrInsertPos(ID, InsertPos);
5808+
assert(!Nothing && "canonical type broken");
5809+
}
58035810
}
58045811
}
58055812

clang/lib/AST/TemplateBase.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
329329
ID.AddInteger(TemplateArg.NumExpansions);
330330
LLVM_FALLTHROUGH;
331331
case Template:
332-
getAsTemplateOrTemplatePattern().Profile(ID);
332+
ID.AddPointer(TemplateArg.Name);
333333
break;
334334

335335
case Integral:

clang/lib/AST/Type.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4590,8 +4590,14 @@ AutoType::AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword,
45904590
auto *ArgBuffer =
45914591
const_cast<TemplateArgument *>(getTypeConstraintArguments().data());
45924592
for (const TemplateArgument &Arg : TypeConstraintArgs) {
4593-
addDependence(
4594-
toSyntacticDependence(toTypeDependence(Arg.getDependence())));
4593+
// If we have a deduced type, our constraints never affect semantic
4594+
// dependence. Prior to deduction, however, our canonical type depends
4595+
// on the template arguments, so we are a dependent type if any of them
4596+
// is dependent.
4597+
TypeDependence ArgDependence = toTypeDependence(Arg.getDependence());
4598+
if (!DeducedAsType.isNull())
4599+
ArgDependence = toSyntacticDependence(ArgDependence);
4600+
addDependence(ArgDependence);
45954601

45964602
new (ArgBuffer++) TemplateArgument(Arg);
45974603
}

clang/lib/Sema/SemaTemplateDeduction.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1613,7 +1613,9 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
16131613
llvm_unreachable("Type nodes handled above");
16141614

16151615
case Type::Auto:
1616-
// FIXME: Implement deduction in dependent case.
1616+
// FIXME: It's not clear whether we should deduce the template arguments
1617+
// of a constrained deduced type. For now we treat them as a non-deduced
1618+
// context.
16171619
if (P->isDependentType())
16181620
return Sema::TDK_Success;
16191621
[[fallthrough]];

clang/test/CXX/dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ namespace PR48617 {
8181
template <typename...> concept C = true;
8282
template <typename...> class A {};
8383

84-
template <typename... Ts> C<Ts...> auto e(A<Ts...>) { return 0; }
85-
template auto e<>(A<>);
86-
template auto e<int>(A<int>);
84+
template <typename... Ts> C<Ts...> auto e(A<Ts...>) { return 0; } // expected-note 2{{failed template argument deduction}}
85+
template auto e<>(A<>); // expected-error {{does not refer to a function template}}
86+
template auto e<int>(A<int>); // expected-error {{does not refer to a function template}}
8787

8888
template <typename... Ts> C<Ts...> auto d(A<Ts...>) { return 0; }
8989
template C<> auto d<>(A<>);

0 commit comments

Comments
 (0)