[clang] 5d69937 - [Clang] make canonical AutoType constraints-free
Yuanfang Chen via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 4 11:56:18 PDT 2022
Author: Yuanfang Chen
Date: 2022-10-04T11:56:03-07:00
New Revision: 5d69937b9f9c8e102663c2edcbdbe5335858b215
URL: https://github.com/llvm/llvm-project/commit/5d69937b9f9c8e102663c2edcbdbe5335858b215
DIFF: https://github.com/llvm/llvm-project/commit/5d69937b9f9c8e102663c2edcbdbe5335858b215.diff
LOG: [Clang] make canonical AutoType constraints-free
As @mizvekov suggested in D134772. This works great for D128750 when
dealing with AutoType's.
Reviewed By: mizvekov, erichkeane
Differential Revision: https://reviews.llvm.org/D135088
Added:
Modified:
clang/lib/AST/ASTContext.cpp
clang/lib/AST/DeclTemplate.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/test/CXX/dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index d609fe8cbed09..461a108915c3a 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -696,7 +696,11 @@ ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID,
if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
ID.AddInteger(1);
ID.AddBoolean(NTTP->isParameterPack());
+ const Expr *TC = NTTP->getPlaceholderTypeConstraint();
+ ID.AddBoolean(TC != nullptr);
ID.AddPointer(NTTP->getType().getCanonicalType().getAsOpaquePtr());
+ if (TC)
+ TC->Profile(ID, C, /*Canonical=*/true);
if (NTTP->isExpandedParameterPack()) {
ID.AddBoolean(true);
ID.AddInteger(NTTP->getNumExpansionTypes());
@@ -5751,9 +5755,6 @@ QualType ASTContext::getAutoTypeInternal(
!TypeConstraintConcept && !IsDependent)
return getAutoDeductType();
- if (TypeConstraintConcept)
- TypeConstraintConcept = TypeConstraintConcept->getCanonicalDecl();
-
// Look in the folding set for an existing type.
void *InsertPos = nullptr;
llvm::FoldingSetNodeID ID;
@@ -5764,20 +5765,15 @@ QualType ASTContext::getAutoTypeInternal(
QualType Canon;
if (!IsCanon) {
- if (DeducedType.isNull()) {
- SmallVector<TemplateArgument, 4> CanonArgs;
- bool AnyNonCanonArgs =
- ::getCanonicalTemplateArguments(*this, TypeConstraintArgs, CanonArgs);
- if (AnyNonCanonArgs) {
- Canon = getAutoTypeInternal(QualType(), Keyword, IsDependent, IsPack,
- TypeConstraintConcept, CanonArgs, true);
- // Find the insert position again.
- [[maybe_unused]] auto *Nothing =
- AutoTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(!Nothing && "canonical type broken");
- }
- } else {
+ 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");
}
}
@@ -6333,7 +6329,9 @@ bool ASTContext::isSameTemplateParameter(const NamedDecl *X,
if (auto *TX = dyn_cast<NonTypeTemplateParmDecl>(X)) {
auto *TY = cast<NonTypeTemplateParmDecl>(Y);
return TX->isParameterPack() == TY->isParameterPack() &&
- TX->getASTContext().hasSameType(TX->getType(), TY->getType());
+ TX->getASTContext().hasSameType(TX->getType(), TY->getType()) &&
+ isSameConstraintExpr(TX->getPlaceholderTypeConstraint(),
+ TY->getPlaceholderTypeConstraint());
}
auto *TX = cast<TemplateTemplateParmDecl>(X);
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 6bb5a493485ef..7159a87a69271 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -529,6 +529,9 @@ static void ProfileTemplateParameterList(ASTContext &C,
ID.AddInteger(0);
ID.AddBoolean(NTTP->isParameterPack());
NTTP->getType().getCanonicalType().Profile(ID);
+ ID.AddBoolean(NTTP->hasPlaceholderTypeConstraint());
+ if (const Expr *E = NTTP->getPlaceholderTypeConstraint())
+ E->Profile(ID, C, /*Canonical=*/true);
continue;
}
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(D)) {
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 82171f64a1d7b..5cc5dc1c449a6 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -8666,10 +8666,11 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
// C++2a [class.spaceship]p2 [P2002R0]:
// Let R be the declared return type [...]. If R is auto, [...]. Otherwise,
// R shall not contain a placeholder type.
- if (DCK == DefaultedComparisonKind::ThreeWay &&
- FD->getDeclaredReturnType()->getContainedDeducedType() &&
- !Context.hasSameType(FD->getDeclaredReturnType(),
- Context.getAutoDeductType())) {
+ if (QualType RT = FD->getDeclaredReturnType();
+ DCK == DefaultedComparisonKind::ThreeWay &&
+ RT->getContainedDeducedType() &&
+ (!Context.hasSameType(RT, Context.getAutoDeductType()) ||
+ RT->getContainedAutoType()->isConstrained())) {
Diag(FD->getLocation(),
diag::err_defaulted_comparison_deduced_return_type_not_auto)
<< (int)DCK << FD->getDeclaredReturnType() << Context.AutoDeductTy
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index b3a02ef152e67..e9ceec9a0ec14 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -7943,12 +7943,26 @@ static bool MatchTemplateParameterKind(
: Kind),
TemplateArgLoc))
return false;
- } else if (Kind != Sema::TPL_TemplateTemplateArgumentMatch) {
+ }
+
+ if (Kind != Sema::TPL_TemplateTemplateArgumentMatch &&
+ !isa<TemplateTemplateParmDecl>(Old)) {
const Expr *NewC = nullptr, *OldC = nullptr;
- if (const auto *TC = cast<TemplateTypeParmDecl>(New)->getTypeConstraint())
- NewC = TC->getImmediatelyDeclaredConstraint();
- if (const auto *TC = cast<TemplateTypeParmDecl>(Old)->getTypeConstraint())
- OldC = TC->getImmediatelyDeclaredConstraint();
+
+ if (isa<TemplateTypeParmDecl>(New)) {
+ if (const auto *TC = cast<TemplateTypeParmDecl>(New)->getTypeConstraint())
+ NewC = TC->getImmediatelyDeclaredConstraint();
+ if (const auto *TC = cast<TemplateTypeParmDecl>(Old)->getTypeConstraint())
+ OldC = TC->getImmediatelyDeclaredConstraint();
+ } else if (isa<NonTypeTemplateParmDecl>(New)) {
+ if (const Expr *E = cast<NonTypeTemplateParmDecl>(New)
+ ->getPlaceholderTypeConstraint())
+ NewC = E;
+ if (const Expr *E = cast<NonTypeTemplateParmDecl>(Old)
+ ->getPlaceholderTypeConstraint())
+ OldC = E;
+ } else
+ llvm_unreachable("unexpected template parameter type");
auto Diagnose = [&] {
S.Diag(NewC ? NewC->getBeginLoc() : New->getBeginLoc(),
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 4941027423217..557ea02001bb7 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
@@ -82,18 +82,12 @@ namespace PR48617 {
template <typename...> class A {};
template <typename... Ts> C<Ts...> auto e(A<Ts...>) { return 0; }
-
- // FIXME: The error here does not make sense.
template auto e<>(A<>);
- // expected-error at -1 {{explicit instantiation of 'e' does not refer to a function template}}
- // expected-note at -5 {{candidate template ignored: failed template argument deduction}}
-
- // FIXME: Should be able to instantiate this with no errors.
- template C<int> auto e<int>(A<int>);
- // expected-error at -1 {{explicit instantiation of 'e' does not refer to a function template}}
- // expected-note at -10 {{candidate template ignored: could not match 'C<int, Ts...> auto' against 'C<int> auto'}}
-
- template C<> auto e<>(A<>);
+ template auto e<int>(A<int>);
+
+ template <typename... Ts> C<Ts...> auto d(A<Ts...>) { return 0; }
+ template C<> auto d<>(A<>);
+ template C<int> auto d<int>(A<int>);
template <typename... Ts> A<Ts...> c(Ts...);
int f = e(c(1, 2));
More information about the cfe-commits
mailing list