[clang] 38cf47f - [clang] Error on substitution failure within lambda body inside a requires-expression

via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 8 01:10:50 PDT 2023


Author: Podchishchaeva, Mariya
Date: 2023-08-08T01:08:38-07:00
New Revision: 38cf47f037b2504a57ba5673f507241af1d6e19d

URL: https://github.com/llvm/llvm-project/commit/38cf47f037b2504a57ba5673f507241af1d6e19d
DIFF: https://github.com/llvm/llvm-project/commit/38cf47f037b2504a57ba5673f507241af1d6e19d.diff

LOG: [clang] Error on substitution failure within lambda body inside a requires-expression

Per CWG 2672 substitution failure within the body of a lambda inside a
requires-expression should be a hard error.

Fixes https://github.com/llvm/llvm-project/issues/64138

Reviewed By: cor3ntin

Differential Revision: https://reviews.llvm.org/D156993

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Sema/SemaTemplateInstantiate.cpp
    clang/test/CXX/drs/dr26xx.cpp
    clang/test/SemaCXX/lambda-unevaluated.cpp
    clang/www/cxx_dr_status.html

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index babade1c70b067..d3757c833ef83a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -157,6 +157,10 @@ Bug Fixes to C++ Support
   (`#35574 <https://github.com/llvm/llvm-project/issues/35574>_`) and
   (`#27224 <https://github.com/llvm/llvm-project/issues/27224>_`).
 
+- Clang emits an error on substitution failure within lambda body inside a
+  requires-expression. This fixes:
+  (`#64138 <https://github.com/llvm/llvm-project/issues/64138>_`).
+
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
 - Fixed an import failure of recursive friend class template.

diff  --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 8702e2ca3a1b3b..e7318880af8d3b 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1074,7 +1074,6 @@ std::optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
   if (InNonInstantiationSFINAEContext)
     return std::optional<TemplateDeductionInfo *>(nullptr);
 
-  bool SawLambdaSubstitution = false;
   for (SmallVectorImpl<CodeSynthesisContext>::const_reverse_iterator
          Active = CodeSynthesisContexts.rbegin(),
          ActiveEnd = CodeSynthesisContexts.rend();
@@ -1101,10 +1100,8 @@ std::optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
       // A lambda-expression appearing in a function type or a template
       // parameter is not considered part of the immediate context for the
       // purposes of template argument deduction.
-
-      // We need to check parents.
-      SawLambdaSubstitution = true;
-      break;
+      // CWG2672: A lambda-expression body is never in the immediate context.
+      return std::nullopt;
 
     case CodeSynthesisContext::DefaultTemplateArgumentInstantiation:
     case CodeSynthesisContext::PriorTemplateArgumentSubstitution:
@@ -1120,8 +1117,6 @@ std::optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
       // We're either substituting explicitly-specified template arguments,
       // deduced template arguments. SFINAE applies unless we are in a lambda
       // expression, see [temp.deduct]p9.
-      if (SawLambdaSubstitution)
-        return std::nullopt;
       [[fallthrough]];
     case CodeSynthesisContext::ConstraintSubstitution:
     case CodeSynthesisContext::RequirementInstantiation:

diff  --git a/clang/test/CXX/drs/dr26xx.cpp b/clang/test/CXX/drs/dr26xx.cpp
index e4b6156235ecc0..8dd07b63deb436 100644
--- a/clang/test/CXX/drs/dr26xx.cpp
+++ b/clang/test/CXX/drs/dr26xx.cpp
@@ -150,3 +150,24 @@ static_assert(__is_same(decltype(i), I<char, 4>));
 
 J j = { "ghi" };  // expected-error {{no viable constructor or deduction guide}}
 }
+
+namespace dr2672 { // dr2672: 18 open
+template <class T>
+void f(T) requires requires { []() { T::invalid; } (); }; // expected-error{{type 'int' cannot be used prior to '::'}}
+                                                          // expected-note at -1{{while substituting into a lambda expression here}}
+                                                          // expected-note at -2{{in instantiation of requirement here}}
+                                                          // expected-note at -3{{while substituting template arguments into constraint expression here}}
+void f(...);
+
+template <class T>
+void bar(T) requires requires {
+   decltype([]() -> T {})::foo();
+};
+void bar(...);
+
+void m() {
+  f(0); // expected-note {{while checking constraint satisfaction for template 'f<int>' required here}}
+        // expected-note at -1 {{in instantiation of function template specialization}}
+  bar(0);
+}
+}

diff  --git a/clang/test/SemaCXX/lambda-unevaluated.cpp b/clang/test/SemaCXX/lambda-unevaluated.cpp
index 179c7327ebdff4..10d4c2228ec9be 100644
--- a/clang/test/SemaCXX/lambda-unevaluated.cpp
+++ b/clang/test/SemaCXX/lambda-unevaluated.cpp
@@ -155,17 +155,24 @@ struct WithFoo { static void foo(); };
 
 template <class T>
 concept lambda_works = requires {
-    []() { T::foo(); };
+    []() { T::foo(); }; // expected-error{{type 'int' cannot be used prior to '::'}}
+                        // expected-note at -1{{while substituting into a lambda expression here}}
+                        // expected-note at -2{{in instantiation of requirement here}}
+                        // expected-note at -4{{while substituting template arguments into constraint expression here}}
 };
 
-static_assert(!lambda_works<int>);
+static_assert(!lambda_works<int>); // expected-note {{while checking the satisfaction of concept 'lambda_works<int>' requested here}}
 static_assert(lambda_works<WithFoo>);
 
 template <class T>
-int* func(T) requires requires { []() { T::foo(); }; };
+int* func(T) requires requires { []() { T::foo(); }; }; // expected-error{{type 'int' cannot be used prior to '::'}}
+                                                        // expected-note at -1{{while substituting into a lambda expression here}}
+                                                        // expected-note at -2{{in instantiation of requirement here}}
+                                                        // expected-note at -3{{while substituting template arguments into constraint expression here}}
 double* func(...);
 
-static_assert(__is_same(decltype(func(0)), double*));
+static_assert(__is_same(decltype(func(0)), double*)); // expected-note {{while checking constraint satisfaction for template 'func<int>' required here}}
+                                                      // expected-note at -1 {{in instantiation of function template specialization 'lambda_in_constraints::func<int>'}}
 static_assert(__is_same(decltype(func(WithFoo())), int*));
 
 template <class T>

diff  --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index c950b5b08d1afa..d044679d617a90 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -15839,7 +15839,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
     <td><a href="https://cplusplus.github.io/CWG/issues/2672.html">2672</a></td>
     <td>open</td>
     <td>Lambda body SFINAE is still required, contrary to intent and note</td>
-    <td align="center">Not resolved</td>
+    <td class="unreleased" align="center">Clang 18</td>
   </tr>
   <tr id="2673">
     <td><a href="https://cplusplus.github.io/CWG/issues/2673.html">2673</a></td>


        


More information about the cfe-commits mailing list