[clang] 051cc46 - [C++20] Determine the dependency of unevaluated lambdas more accurately

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 6 05:57:05 PST 2023


Author: Liming Liu
Date: 2023-01-06T05:56:25-08:00
New Revision: 051cc460ba9117c9f62c09235bdf6f5ae1248dd4

URL: https://github.com/llvm/llvm-project/commit/051cc460ba9117c9f62c09235bdf6f5ae1248dd4
DIFF: https://github.com/llvm/llvm-project/commit/051cc460ba9117c9f62c09235bdf6f5ae1248dd4.diff

LOG: [C++20] Determine the dependency of unevaluated lambdas more accurately

During template instantiation, the instantiator will enter constant
evaluated
context before instantiate a template argument originated from an
expression,
and this impedes the instantiator from creating lambdas with independent
types.

This patch solves the problem via widening the condition that the
instantiator
marks lambdas as never dependent, and fixes the issue #57960

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

Added: 
    clang/test/CodeGenCXX/cxx20-unevaluated-lambda-crash.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Sema/Sema.h
    clang/lib/Sema/TreeTransform.h
    clang/test/SemaCXX/lambda-unevaluated.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b69067139ffa5..f2cfac238613c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -338,6 +338,8 @@ Bug Fixes
 - In C mode, when ``e1`` has ``__attribute__((noreturn))`` but ``e2`` doesn't,
   ``(c ? e1 : e2)`` is no longer considered noreturn.
   `Issue 59792 <https://github.com/llvm/llvm-project/issues/59792>`_
+- Fix an issue that makes Clang crash on lambda template parameters. This fixes
+  `Issue 57960 <https://github.com/llvm/llvm-project/issues/57960>`_
 
 Improvements to Clang's diagnostics
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index bac06b8fbfbeb..3d9d96c904a0a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9624,6 +9624,12 @@ class Sema final {
     return ExprEvalContexts.back().isUnevaluated();
   }
 
+  bool isConstantEvaluatedContext() const {
+    assert(!ExprEvalContexts.empty() &&
+           "Must be in an expression evaluation context");
+    return ExprEvalContexts.back().isConstantEvaluated();
+  }
+
   bool isImmediateFunctionContext() const {
     assert(!ExprEvalContexts.empty() &&
            "Must be in an expression evaluation context");

diff  --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 2ebd936b359f7..075066472df0c 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -13234,10 +13234,11 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
   // context that isn't a DeclContext (such as a variable template), or when
   // substituting an unevaluated lambda inside of a function's parameter's type
   // - as parameter types are not instantiated from within a function's DC. We
-  // use isUnevaluatedContext() to distinguish the function parameter case.
+  // use evaluation contexts to distinguish the function parameter case.
   CXXRecordDecl::LambdaDependencyKind DependencyKind =
       CXXRecordDecl::LDK_Unknown;
-  if (getSema().isUnevaluatedContext() &&
+  if ((getSema().isUnevaluatedContext() ||
+       getSema().isConstantEvaluatedContext()) &&
       (getSema().CurContext->isFileContext() ||
        !getSema().CurContext->getParent()->isDependentContext()))
     DependencyKind = CXXRecordDecl::LDK_NeverDependent;

diff  --git a/clang/test/CodeGenCXX/cxx20-unevaluated-lambda-crash.cpp b/clang/test/CodeGenCXX/cxx20-unevaluated-lambda-crash.cpp
new file mode 100644
index 0000000000000..9cc6ebe93af48
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx20-unevaluated-lambda-crash.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 %s -emit-llvm -o - | FileCheck %s
+
+// CHECK-LABEL: define linkonce_odr void @"_ZN10Issue579601EIiEENS_1FILNS_3$_0EEEEv"()
+namespace Issue57960 {
+template<auto>
+class F {};
+
+template<typename D>
+F<[]{}> E() {
+    return {};
+}
+
+static auto f = E<int>();
+}

diff  --git a/clang/test/SemaCXX/lambda-unevaluated.cpp b/clang/test/SemaCXX/lambda-unevaluated.cpp
index fb58b3e0f2021..6d8c3b88c2eaf 100644
--- a/clang/test/SemaCXX/lambda-unevaluated.cpp
+++ b/clang/test/SemaCXX/lambda-unevaluated.cpp
@@ -61,9 +61,7 @@ void use_f() { f<int>({}); } // expected-error {{ambiguous}}
 // Same.
 template<int N> void g(const char (*)[([]{ return N; })()]) {} // expected-note {{candidate}}
 template<int N> void g(const char (*)[([]{ return N; })()]) {} // expected-note {{candidate}}
-// FIXME: We instantiate the lambdas into the context of the function template,
-//  so we think they're dependent and can't evaluate a call to them.
-void use_g() { g<6>(&"hello"); } // expected-error {{no matching function}}
+void use_g() { g<6>(&"hello"); } // expected-error {{ambiguous}}
 }
 
 namespace GH51416 {


        


More information about the cfe-commits mailing list