[clang] 3524a9f - Retain constraints in the canonical form of an auto type.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 30 17:00:51 PDT 2023


Author: Richard Smith
Date: 2023-03-30T17:00:16-07:00
New Revision: 3524a9f84a0a1a106aa649a775066ba4d9e8ae0d

URL: https://github.com/llvm/llvm-project/commit/3524a9f84a0a1a106aa649a775066ba4d9e8ae0d
DIFF: https://github.com/llvm/llvm-project/commit/3524a9f84a0a1a106aa649a775066ba4d9e8ae0d.diff

LOG: 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.

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/AST/ASTContext.cpp
    clang/lib/AST/TemplateBase.cpp
    clang/lib/AST/Type.cpp
    clang/lib/Sema/SemaTemplateDeduction.cpp
    clang/test/CXX/dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp

Removed: 
    


################################################################################
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 <https://github.com/llvm/llvm-project/issues/50866>`_)
 - Fix ordering of function templates by constraints when they have template
   template parameters with 
diff erent 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<TemplateArgument *>(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 <typename...> concept C = true;
   template <typename...> class A {};
 
-  template <typename... Ts> C<Ts...> auto e(A<Ts...>) { return 0; }
-  template auto e<>(A<>);
-  template auto e<int>(A<int>);
+  template <typename... Ts> C<Ts...> auto e(A<Ts...>) { 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<int>(A<int>); // expected-error {{does not refer to a function template}}
 
   template <typename... Ts> C<Ts...> auto d(A<Ts...>) { return 0; }
   template C<> auto d<>(A<>);


        


More information about the cfe-commits mailing list