[clang] 2f9d8b0 - PR50306: When instantiating a generic lambda with a constrained 'auto',

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Wed May 12 18:45:54 PDT 2021


Author: Richard Smith
Date: 2021-05-12T18:45:33-07:00
New Revision: 2f9d8b08ea658b612065cbf7d4b0fbd7f28bb36a

URL: https://github.com/llvm/llvm-project/commit/2f9d8b08ea658b612065cbf7d4b0fbd7f28bb36a
DIFF: https://github.com/llvm/llvm-project/commit/2f9d8b08ea658b612065cbf7d4b0fbd7f28bb36a.diff

LOG: PR50306: When instantiating a generic lambda with a constrained 'auto',
properly track that it has constraints.

Previously an instantiation of a constrained generic lambda would behave
as if unconstrained because we incorrectly cached a "has no constraints"
value that we computed before the constraints from 'auto' parameters
were attached.

Added: 
    

Modified: 
    clang/lib/AST/DeclTemplate.cpp
    clang/test/SemaTemplate/concepts.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 4b3a4062d642..ba4a5359f937 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -68,12 +68,21 @@ TemplateParameterList::TemplateParameterList(const ASTContext& C,
       if (!IsPack &&
           TTP->getTemplateParameters()->containsUnexpandedParameterPack())
         ContainsUnexpandedParameterPack = true;
-    } else if (const TypeConstraint *TC =
-        cast<TemplateTypeParmDecl>(P)->getTypeConstraint()) {
-      if (TC->getImmediatelyDeclaredConstraint()
-          ->containsUnexpandedParameterPack())
-        ContainsUnexpandedParameterPack = true;
-      HasConstrainedParameters = true;
+    } else if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
+      // FIXME: The type parameter might have a constraint that has not been
+      // attached yet. If so, we can compute the wrong value for
+      // 'ContainsUnexpandedParameterPack' here. Note that this only happens
+      // for implicit parameters, for which the ParmVarDecl will correctly
+      // track that it contains an unexpanded parameter pack, so this should
+      // not be problematic in practice.
+      if (const TypeConstraint *TC = TTP->getTypeConstraint()) {
+        if (TC->getImmediatelyDeclaredConstraint()
+            ->containsUnexpandedParameterPack())
+          ContainsUnexpandedParameterPack = true;
+      }
+      HasConstrainedParameters = TTP->hasTypeConstraint();
+    } else {
+      llvm_unreachable("unexpcted template parameter type");
     }
     // FIXME: If a default argument contains an unexpanded parameter pack, the
     // template parameter list does too.

diff  --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp
index 2a46dec5afb7..753a84c35e1f 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -65,3 +65,12 @@ namespace P0857R0 {
   template<typename T> requires C<T> struct Y {};
   X<Y> xy; // expected-error {{no template named 'X'}}
 }
+
+namespace PR50306 {
+  template<typename T> concept NotInt = sizeof(T) != sizeof(int); // expected-note {{because}}
+  template<typename T> void f() {
+    [](NotInt auto) {}(T()); // expected-error {{no matching function}} expected-note {{constraints not satisfied}} expected-note {{because}}
+  }
+  template void f<char>(); // OK
+  template void f<int>(); // expected-note {{in instantiation of}}
+}


        


More information about the cfe-commits mailing list