[PATCH] D149264: GH62362: Handle constraints on "Using" inherited constructors

Erich Keane via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 26 09:28:55 PDT 2023


erichkeane created this revision.
erichkeane added a reviewer: clang-language-wg.
Herald added a project: All.
erichkeane requested review of this revision.

Two similar bugs were filed, both captured in GH62362.  The problem
happens when collecting the instantiation args for a constructor with a
constraint is inherited by a child class.

When the inheriting class itself was NOT a template, the implicit
constructor that modeled the inherited constructor is in the declaration
context of the inherited type, however it is marked as implicit and as
an inheriting constructor.  In order to make sure we get the correct
instantiation args, this patch recognizes this pattern, and causes us to
pick up the instantiation args from the inherited constructor.  This
also corrects the 'declaration context' to be the
ClassTemplateSpecializationDecl of the inherited class, which has the
correct instantiation args.

however, if the inheriting class is already a template, the correct
constructor is actually already picked up, in the correct specialization
of the parent class.  However, in the case of an explicit
specialization, we were skipping the template instantiation args. I
found that removing this early-return here actually broke no lit tests,
however I still limited the removal of this early return to concept
checks.

Fixes: #62362


https://reviews.llvm.org/D149264

Files:
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/test/SemaTemplate/concepts.cpp


Index: clang/test/SemaTemplate/concepts.cpp
===================================================================
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -816,3 +816,26 @@
 static_assert(Parent<int>::TakesBinary<int, 0ULL>::i == 0);
 }
 
+namespace GH62362 {
+template<typename T>
+concept C = true;
+
+template <typename T> struct Test {
+    Test()
+          requires(C<T>);
+};
+
+struct Bar : public Test<int> {
+      using Test<int>::Test;
+};
+
+template <>
+struct Test<void> : public Test<int> {
+    using Test<int>::Test;
+};
+
+void foo() {
+      Bar();
+          Test<void>();
+}
+}
Index: clang/lib/Sema/SemaTemplateInstantiate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -135,11 +135,13 @@
 Response
 HandleClassTemplateSpec(const ClassTemplateSpecializationDecl *ClassTemplSpec,
                         MultiLevelTemplateArgumentList &Result,
-                        bool SkipForSpecialization) {
+                        bool SkipForSpecialization,
+                        bool ForConstraintInstantiation) {
   if (!ClassTemplSpec->isClassScopeExplicitSpecialization()) {
     // We're done when we hit an explicit specialization.
     if (ClassTemplSpec->getSpecializationKind() == TSK_ExplicitSpecialization &&
-        !isa<ClassTemplatePartialSpecializationDecl>(ClassTemplSpec))
+        !isa<ClassTemplatePartialSpecializationDecl>(ClassTemplSpec) &&
+        !ForConstraintInstantiation)
       return Response::Done();
 
     if (!SkipForSpecialization)
@@ -208,6 +210,18 @@
   return Response::UseNextDecl(Function);
 }
 
+Response HandleConstructor(const CXXConstructorDecl *Ctor,
+                           MultiLevelTemplateArgumentList &Result,
+                           const FunctionDecl *Pattern, bool RelativeToPrimary,
+                           bool ForConstraintInstantiation) {
+  if (Ctor->isImplicit() && Ctor->isInheritingConstructor() &&
+      Ctor->getInheritedConstructor().getConstructor())
+    Ctor = Ctor->getInheritedConstructor().getConstructor();
+
+  return HandleFunction(Ctor, Result, Pattern, RelativeToPrimary,
+                        ForConstraintInstantiation);
+}
+
 Response HandleRecordDecl(const CXXRecordDecl *Rec,
                           MultiLevelTemplateArgumentList &Result,
                           ASTContext &Context,
@@ -308,8 +322,11 @@
       R = HandleVarTemplateSpec(VarTemplSpec, Result, SkipForSpecialization);
     } else if (const auto *ClassTemplSpec =
                    dyn_cast<ClassTemplateSpecializationDecl>(CurDecl)) {
-      R = HandleClassTemplateSpec(ClassTemplSpec, Result,
-                                  SkipForSpecialization);
+      R = HandleClassTemplateSpec(ClassTemplSpec, Result, SkipForSpecialization,
+                                  ForConstraintInstantiation);
+    } else if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(CurDecl)) {
+      R = HandleConstructor(Ctor, Result, Pattern, RelativeToPrimary,
+                            ForConstraintInstantiation);
     } else if (const auto *Function = dyn_cast<FunctionDecl>(CurDecl)) {
       R = HandleFunction(Function, Result, Pattern, RelativeToPrimary,
                          ForConstraintInstantiation);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D149264.517205.patch
Type: text/x-patch
Size: 3362 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20230426/ce16e9e7/attachment-0001.bin>


More information about the cfe-commits mailing list