lime created this revision.
lime added reviewers: cor3ntin, shafik, erichkeane, aaron.ballman, 
clang-language-wg.
lime added a project: clang.
Herald added a project: All.
lime requested review of this revision.
Herald added a subscriber: cfe-commits.

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


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D140554

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/TreeTransform.h
  clang/test/CodeGenCXX/cxx20-unevaluated-lambda-crash.cpp
  clang/test/SemaCXX/lambda-unevaluated.cpp


Index: clang/test/SemaCXX/lambda-unevaluated.cpp
===================================================================
--- clang/test/SemaCXX/lambda-unevaluated.cpp
+++ clang/test/SemaCXX/lambda-unevaluated.cpp
@@ -61,9 +61,7 @@
 // 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 {
Index: clang/test/CodeGenCXX/cxx20-unevaluated-lambda-crash.cpp
===================================================================
--- /dev/null
+++ 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>();
+}
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -13244,10 +13244,11 @@
   // 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 context 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;
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -9621,6 +9621,12 @@
     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");


Index: clang/test/SemaCXX/lambda-unevaluated.cpp
===================================================================
--- clang/test/SemaCXX/lambda-unevaluated.cpp
+++ clang/test/SemaCXX/lambda-unevaluated.cpp
@@ -61,9 +61,7 @@
 // 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 {
Index: clang/test/CodeGenCXX/cxx20-unevaluated-lambda-crash.cpp
===================================================================
--- /dev/null
+++ 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>();
+}
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -13244,10 +13244,11 @@
   // 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 context 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;
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -9621,6 +9621,12 @@
     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");
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to