[clang] 22aa368 - [C++20] Support for lambdas in unevaluated context

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Mon Jun 28 06:02:08 PDT 2021


Author: Corentin Jabot
Date: 2021-06-28T09:01:56-04:00
New Revision: 22aa3680eaccb9b77ca224711c4da3a354aa2d45

URL: https://github.com/llvm/llvm-project/commit/22aa3680eaccb9b77ca224711c4da3a354aa2d45
DIFF: https://github.com/llvm/llvm-project/commit/22aa3680eaccb9b77ca224711c4da3a354aa2d45.diff

LOG: [C++20] Support for lambdas in unevaluated context

Partially implement P0315R4.

This patch allow lambda in unevaluated context.
It does not implement temp.deduct/9.

Added: 
    clang/test/SemaCXX/lambda-unevaluated.cpp

Modified: 
    clang/lib/Sema/SemaConcept.cpp
    clang/lib/Sema/SemaExpr.cpp
    clang/test/SemaCXX/anonymous-struct.cpp
    clang/www/cxx_status.html

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 552534824588e..f2c70d0a56efb 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -43,9 +43,12 @@ class LogicalBinOp {
       LHS = BO->getLHS();
       RHS = BO->getRHS();
     } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
-      Op = OO->getOperator();
-      LHS = OO->getArg(0);
-      RHS = OO->getArg(1);
+      // If OO is not || or && it might not have exactly 2 arguments.
+      if (OO->getNumArgs() == 2) {
+        Op = OO->getOperator();
+        LHS = OO->getArg(0);
+        RHS = OO->getArg(1);
+      }
     }
   }
 

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 2d0f314f380fe..728d7b61d4a86 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -16722,8 +16722,10 @@ void Sema::PopExpressionEvaluationContext() {
 
   if (!Rec.Lambdas.empty()) {
     using ExpressionKind = ExpressionEvaluationContextRecord::ExpressionKind;
-    if (Rec.ExprContext == ExpressionKind::EK_TemplateArgument || Rec.isUnevaluated() ||
-        (Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus17)) {
+    if (!getLangOpts().CPlusPlus20 &&
+        (Rec.ExprContext == ExpressionKind::EK_TemplateArgument ||
+         Rec.isUnevaluated() ||
+         (Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus17))) {
       unsigned D;
       if (Rec.isUnevaluated()) {
         // C++11 [expr.prim.lambda]p2:

diff  --git a/clang/test/SemaCXX/anonymous-struct.cpp b/clang/test/SemaCXX/anonymous-struct.cpp
index 1b6207d19e44d..0a5395e15780b 100644
--- a/clang/test/SemaCXX/anonymous-struct.cpp
+++ b/clang/test/SemaCXX/anonymous-struct.cpp
@@ -49,7 +49,7 @@ typedef struct // expected-warning {{anonymous non-C-compatible type given name
 : B { // expected-note {{type is not C-compatible due to this base class}}
 } C; // expected-note {{type is given name 'C' for linkage purposes by this typedef declaration}}
 
-#if __cplusplus > 201703L
+#if __cplusplus > 201703L && __cplusplus < 202002L
 typedef struct { // expected-warning {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration; add a tag name here}}
   static_assert([]{ return true; }()); // expected-note {{type is not C-compatible due to this lambda expression}}
 } Lambda1; // expected-note {{type is given name 'Lambda1' for linkage purposes by this typedef declaration}}

diff  --git a/clang/test/SemaCXX/lambda-unevaluated.cpp b/clang/test/SemaCXX/lambda-unevaluated.cpp
new file mode 100644
index 0000000000000..07fa0d94bc8e4
--- /dev/null
+++ b/clang/test/SemaCXX/lambda-unevaluated.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -std=c++20 %s -verify
+
+
+template <auto> struct Nothing {};
+Nothing<[]() { return 0; }()> nothing;
+
+template <typename> struct NothingT {};
+Nothing<[]() { return 0; }> nothingT;
+
+template <typename T>
+concept True = [] { return true; }();
+static_assert(True<int>);
+
+static_assert(sizeof([] { return 0; }));
+static_assert(sizeof([] { return 0; }()));
+
+void f()  noexcept(noexcept([] { return 0; }()));
+
+using a = decltype([] { return 0; });
+using b = decltype([] { return 0; }());
+using c = decltype([]() noexcept(noexcept([] { return 0; }())) { return 0; });
+using d = decltype(sizeof([] { return 0; }));
+
+template <auto T>
+int unique_test1();
+static_assert(&unique_test1<[](){}> != &unique_test1<[](){}>);
+
+template <class T>
+auto g(T) -> decltype([]() { T::invalid; } ());
+auto e = g(0); // expected-error{{no matching function for call}}
+// expected-note at -2 {{substitution failure}}

diff  --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index a478a4487d150..b7f2501cbc534 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -1011,7 +1011,7 @@ <h2 id="cxx20">C++20 implementation status</h2>
     <tr>
       <td>Lambdas in unevaluated contexts</td>
       <td><a href="https://wg21.link/p0315r4">P0315R4</a></td>
-      <td class="none" align="center">No</td>
+      <td class="partial" align="center">Clang 13</td>
     </tr>
     <!-- Jacksonville papers -->
     <tr>


        


More information about the cfe-commits mailing list