diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b69067139ffa5d..f2cfac238613ce 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 `_ +- Fix an issue that makes Clang crash on lambda template parameters. This fixes + `Issue 57960 `_ Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index bac06b8fbfbeb3..3d9d96c904a0a0 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 2ebd936b359f7c..075066472df0cc 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -13234,10 +13234,11 @@ TreeTransform::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 00000000000000..9cc6ebe93af489 --- /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 +class F {}; + +template +F<[]{}> E() { + return {}; +} + +static auto f = E(); +} diff --git a/clang/test/SemaCXX/lambda-unevaluated.cpp b/clang/test/SemaCXX/lambda-unevaluated.cpp index fb58b3e0f2021e..6d8c3b88c2eaf4 100644 --- a/clang/test/SemaCXX/lambda-unevaluated.cpp +++ b/clang/test/SemaCXX/lambda-unevaluated.cpp @@ -61,9 +61,7 @@ void use_f() { f({}); } // expected-error {{ambiguous}} // Same. template void g(const char (*)[([]{ return N; })()]) {} // expected-note {{candidate}} template 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 {