[clang] [clang] Correctly implement CWG 2672 (PR #75001)
Younan Zhang via cfe-commits
cfe-commits at lists.llvm.org
Sun Dec 10 07:34:12 PST 2023
https://github.com/zyn0217 created https://github.com/llvm/llvm-project/pull/75001
This is a follow-up patch for [D156993](https://reviews.llvm.org/D156993), that marks only the lambda body as non-immediate context.
Fixes https://github.com/llvm/llvm-project/issues/71684
>From 8681b3c9f5e19b6ae977321d5d4154113273c2a0 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Sun, 12 Nov 2023 13:21:03 +0800
Subject: [PATCH] [clang] Correctly implement CWG 2672
This is a follow-up patch for [D156993](https://reviews.llvm.org/D156993),
that marks only the lambda body as non-immediate context.
Fixes https://github.com/llvm/llvm-project/issues/71684
---
clang/lib/Sema/SemaTemplateInstantiate.cpp | 11 +-------
clang/lib/Sema/TreeTransform.h | 7 +++++
clang/test/CXX/drs/dr26xx.cpp | 2 +-
.../expr.prim.lambda/default-arguments.cpp | 6 ++--
.../expr.prim/expr.prim.lambda/p11-1y.cpp | 2 --
.../expr/expr.prim/expr.prim.lambda/p23.cpp | 1 -
.../expr/expr.prim/expr.prim.lambda/p4.cpp | 3 +-
clang/test/CXX/temp/temp.deduct/p9.cpp | 8 ++----
clang/test/SemaCXX/cxx1y-init-captures.cpp | 8 +++---
clang/test/SemaCXX/cxx1z-lambda-star-this.cpp | 4 +--
clang/test/SemaCXX/lambda-expressions.cpp | 4 +--
clang/test/SemaCXX/lambda-pack-expansion.cpp | 1 -
clang/test/SemaCXX/vartemplate-lambda.cpp | 1 -
.../SemaCXX/warn-unused-lambda-capture.cpp | 28 +++++++++----------
.../SemaTemplate/instantiate-local-class.cpp | 4 +--
15 files changed, 37 insertions(+), 53 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index df6b40999e645c..88bd44f7d6934d 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -35,7 +35,6 @@
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
#include "clang/Sema/TemplateInstCallback.h"
-#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TimeProfiler.h"
@@ -1142,8 +1141,7 @@ std::optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
case CodeSynthesisContext::DeducedTemplateArgumentSubstitution:
// We're either substituting explicitly-specified template arguments,
// deduced template arguments. SFINAE applies unless we are in a lambda
- // expression, see [temp.deduct]p9.
- [[fallthrough]];
+ // body, see [temp.deduct]p9.
case CodeSynthesisContext::ConstraintSubstitution:
case CodeSynthesisContext::RequirementInstantiation:
case CodeSynthesisContext::RequirementParameterInstantiation:
@@ -1444,13 +1442,6 @@ namespace {
LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
Sema::ConstraintEvalRAII<TemplateInstantiator> RAII(*this);
- Sema::CodeSynthesisContext C;
- C.Kind = clang::Sema::CodeSynthesisContext::LambdaExpressionSubstitution;
- C.PointOfInstantiation = E->getBeginLoc();
- SemaRef.pushCodeSynthesisContext(C);
- auto PopCtx =
- llvm::make_scope_exit([this] { SemaRef.popCodeSynthesisContext(); });
-
ExprResult Result = inherited::TransformLambdaExpr(E);
if (Result.isInvalid())
return Result;
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 1ad843d0bf4e0c..55e5c3c9dedc56 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -13648,10 +13648,17 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
getSema().PushExpressionEvaluationContext(
Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
+ Sema::CodeSynthesisContext C;
+ C.Kind = clang::Sema::CodeSynthesisContext::LambdaExpressionSubstitution;
+ C.PointOfInstantiation = E->getBody()->getBeginLoc();
+ getSema().pushCodeSynthesisContext(C);
+
// Instantiate the body of the lambda expression.
StmtResult Body =
Invalid ? StmtError() : getDerived().TransformLambdaBody(E, E->getBody());
+ getSema().popCodeSynthesisContext();
+
// ActOnLambda* will pop the function scope for us.
FuncScopeCleanup.disable();
diff --git a/clang/test/CXX/drs/dr26xx.cpp b/clang/test/CXX/drs/dr26xx.cpp
index dd4bb1ff6ae2e1..8a22dbeb98a3d5 100644
--- a/clang/test/CXX/drs/dr26xx.cpp
+++ b/clang/test/CXX/drs/dr26xx.cpp
@@ -211,7 +211,7 @@ void f(...);
template <class T>
void bar(T) requires requires {
- decltype([]() -> T {})::foo();
+ []() -> decltype(T::foo()) {};
};
void bar(...);
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp
index c5d08ec404a7c3..72265d77700aaf 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp
@@ -35,8 +35,7 @@ struct NoDefaultCtor {
template<typename T>
void defargs_in_template_unused(T t) {
auto l1 = [](const T& value = T()) { }; // expected-error{{no matching constructor for initialization of 'NoDefaultCtor'}} \
- // expected-note {{in instantiation of default function argument expression for 'operator()<NoDefaultCtor>' required here}} \
- // expected-note {{while substituting into a lambda expression here}}
+ // expected-note {{in instantiation of default function argument expression for 'operator()<NoDefaultCtor>' required here}}
l1(t);
}
@@ -46,8 +45,7 @@ template void defargs_in_template_unused(NoDefaultCtor); // expected-note{{in i
template<typename T>
void defargs_in_template_used() {
auto l1 = [](const T& value = T()) { }; // expected-error{{no matching constructor for initialization of 'NoDefaultCtor'}} \
- // expected-note {{in instantiation of default function argument expression for 'operator()<NoDefaultCtor>' required here}} \
- // expected-note {{while substituting into a lambda expression here}}
+ // expected-note {{in instantiation of default function argument expression for 'operator()<NoDefaultCtor>' required here}}
l1();
}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp
index ed36a33850ce45..8e13cc8a7ff564 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp
@@ -35,7 +35,6 @@ auto init_kind_2 = [ec = ExplicitCopy()] {}; // expected-error {{no matching con
template<typename T> void init_kind_template() {
auto init_kind_1 = [ec(T())] {};
auto init_kind_2 = [ec = T()] {}; // expected-error {{no matching constructor}}
- // expected-note at -1 {{while substituting into a lambda expression here}}
}
template void init_kind_template<int>();
template void init_kind_template<ExplicitCopy>(); // expected-note {{instantiation of}}
@@ -53,7 +52,6 @@ auto bad_init_6 = [a{overload_fn}] {}; // expected-error {{cannot deduce type fo
auto bad_init_7 = [a{{1}}] {}; // expected-error {{cannot deduce type for lambda capture 'a' from nested initializer list}}
template<typename...T> void pack_1(T...t) { (void)[a(t...)] {}; } // expected-error {{initializer missing for lambda capture 'a'}}
- // expected-note at -1 {{while substituting into a lambda expression here}}
template void pack_1<>(); // expected-note {{instantiation of}}
// No lifetime-extension of the temporary here.
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp
index a5278c27bf25c2..028fcee5fda433 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp
@@ -85,7 +85,6 @@ void init_capture_pack_err(Args ...args) {
template<typename ...Args>
void init_capture_pack_multi(Args ...args) {
[as(args...)] {} (); // expected-error {{initializer missing for lambda capture 'as'}} expected-error {{multiple}}
- // expected-note at -1 2{{while substituting into a lambda expression}}
}
template void init_capture_pack_multi(); // expected-note {{instantiation}}
template void init_capture_pack_multi(int);
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
index d933f765004304..e95a0965a2a35c 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
@@ -55,12 +55,11 @@ void test_result_type(int N) { // expected-note {{declared here}}
template <typename T>
void test_result_type_tpl(int N) { // expected-note 2{{declared here}}
auto l1 = []() -> T {}; // expected-error{{incomplete result type 'Incomplete' in lambda expression}}
- // expected-note at -1{{while substituting into a lambda expression here}}
typedef int vla[N]; // expected-warning 2{{variable length arrays in C++ are a Clang extension}} \
expected-note 2{{function parameter 'N' with unknown value cannot be used in a constant expression}}
auto l2 = []() -> vla {}; // expected-error{{function cannot return array type 'vla' (aka 'int[N]')}}
}
void test_result_type_call() {
- test_result_type_tpl<Incomplete>(10); // expected-note 2{{requested here}}
+ test_result_type_tpl<Incomplete>(10); // expected-note {{requested here}}
}
diff --git a/clang/test/CXX/temp/temp.deduct/p9.cpp b/clang/test/CXX/temp/temp.deduct/p9.cpp
index 23bcd2a1892e7a..7b661c275211b9 100644
--- a/clang/test/CXX/temp/temp.deduct/p9.cpp
+++ b/clang/test/CXX/temp/temp.deduct/p9.cpp
@@ -28,18 +28,14 @@ template <class T>
auto h(T) -> decltype([x = T::invalid]() { });
void h(...);
void test_h() {
- h(0); // expected-error at -3 {{type 'int' cannot be used prior to '::'}}
- // expected-note at -1 {{while substituting deduced template arguments}}
- // expected-note at -5 {{while substituting into a lambda expression here}}
+ h(0);
}
template <class T>
auto i(T) -> decltype([]() -> typename T::invalid { });
void i(...);
void test_i() {
- i(0); // expected-error at -3 {{type 'int' cannot be used prior to '::'}}
- // expected-note at -1 {{while substituting deduced template arguments}}
- // expected-note at -5 {{while substituting into a lambda expression here}}
+ i(0);
}
diff --git a/clang/test/SemaCXX/cxx1y-init-captures.cpp b/clang/test/SemaCXX/cxx1y-init-captures.cpp
index 4cb53cc8bfc1c5..5340c6c7d0bf34 100644
--- a/clang/test/SemaCXX/cxx1y-init-captures.cpp
+++ b/clang/test/SemaCXX/cxx1y-init-captures.cpp
@@ -21,17 +21,17 @@ namespace variadic_expansion {
return a;
}() ...);
};
- auto N2 = [x = y, //expected-note3{{begins here}} expected-note 6 {{default capture by}} expected-note 2 {{substituting into a lambda}}
+ auto N2 = [x = y, //expected-note3{{begins here}} expected-note 6 {{default capture by}}
&z = y, n = f(t...),
- o = f([&a(t)](T& ... t)->decltype(auto) { return a; }(t...)...)](T& ... s) { // expected-note 6 {{capture 't' by}}
- fv([&a(t)]()->decltype(auto) { //expected-error 3{{captured}} expected-note 2{{substituting into a lambda}}
+ o = f([&a(t)](T& ... t)->decltype(auto) { return a; }(t...)...)](T& ... s) { // expected-note 6 {{capture 't' by}} expected-note {{substituting into a lambda}}
+ fv([&a(t)]()->decltype(auto) { //expected-error 3{{captured}}
return a;
}() ...);
};
}
- void h(int i, char c) { g(i, c); } //expected-note 2{{in instantiation}}
+ void h(int i, char c) { g(i, c); } // expected-note {{requested here}}
}
namespace odr_use_within_init_capture {
diff --git a/clang/test/SemaCXX/cxx1z-lambda-star-this.cpp b/clang/test/SemaCXX/cxx1z-lambda-star-this.cpp
index 0cee41ff5ed384..95bc32b603ddf0 100644
--- a/clang/test/SemaCXX/cxx1z-lambda-star-this.cpp
+++ b/clang/test/SemaCXX/cxx1z-lambda-star-this.cpp
@@ -46,7 +46,7 @@ class B {
template <class T = int>
void foo() {
(void)[this] { return x; };
- (void)[*this] { return x; }; //expected-error2{{call to deleted}} expected-note {{while substituting into a lambda}}
+ (void)[*this] { return x; }; //expected-error2{{call to deleted}}
}
B() = default;
@@ -63,7 +63,7 @@ class B {
public:
template <class T = int>
auto foo() {
- const auto &L = [*this](auto a) mutable { //expected-error{{call to deleted}} expected-note {{while substituting into a lambda}}
+ const auto &L = [*this](auto a) mutable { //expected-error{{call to deleted}}
d += a;
return [this](auto b) { return d += b; };
};
diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp
index 1797eef320b865..41cf5a46c38922 100644
--- a/clang/test/SemaCXX/lambda-expressions.cpp
+++ b/clang/test/SemaCXX/lambda-expressions.cpp
@@ -393,7 +393,7 @@ struct S {
namespace PR18473 {
template<typename T> void f() {
T t(0);
- (void) [=]{ int n = t; }; // expected-error {{deleted}} expected-note {{while substituting into a lambda}}
+ (void) [=]{ int n = t; }; // expected-error {{deleted}}
}
template void f<int>();
@@ -476,7 +476,7 @@ namespace error_in_transform_prototype {
void f(T t) {
// expected-error at +2 {{type 'int' cannot be used prior to '::' because it has no members}}
// expected-error at +1 {{no member named 'ns' in 'error_in_transform_prototype::S'}}
- auto x = [](typename T::ns::type &k) {}; // expected-note 2 {{while substituting into a lambda}}
+ auto x = [](typename T::ns::type &k) {};
}
class S {};
void foo() {
diff --git a/clang/test/SemaCXX/lambda-pack-expansion.cpp b/clang/test/SemaCXX/lambda-pack-expansion.cpp
index 936e7c6b0e5c5a..e3e968e2704ed9 100644
--- a/clang/test/SemaCXX/lambda-pack-expansion.cpp
+++ b/clang/test/SemaCXX/lambda-pack-expansion.cpp
@@ -8,7 +8,6 @@ struct X {
void take_by_copy(auto &...args) {
[...args = args] {}(); // expected-error {{call to deleted constructor}}
- // expected-note at -1 {{substituting into a lambda}}
}
void take_by_ref(auto &...args) {
diff --git a/clang/test/SemaCXX/vartemplate-lambda.cpp b/clang/test/SemaCXX/vartemplate-lambda.cpp
index d2b53b53dcd492..8b232abe976b63 100644
--- a/clang/test/SemaCXX/vartemplate-lambda.cpp
+++ b/clang/test/SemaCXX/vartemplate-lambda.cpp
@@ -8,7 +8,6 @@ template<typename T> auto v1 = [](int a = T()) { return a; }();
// expected-error at -1{{cannot initialize a parameter of type 'int' with an rvalue of type 'int *'}}
// expected-note at -2{{in instantiation of default function argument expression for 'operator()<int *>' required here}}
// expected-note at -3{{passing argument to parameter 'a' here}}
-// expected-note at -4{{substituting into a lambda}}
struct S {
template<class T>
diff --git a/clang/test/SemaCXX/warn-unused-lambda-capture.cpp b/clang/test/SemaCXX/warn-unused-lambda-capture.cpp
index 4214a3c6ce09a5..73459496e4cd9a 100644
--- a/clang/test/SemaCXX/warn-unused-lambda-capture.cpp
+++ b/clang/test/SemaCXX/warn-unused-lambda-capture.cpp
@@ -145,38 +145,38 @@ void test_templated() {
auto explicit_by_value_used_generic = [i](auto c) { return i + 1; };
auto explicit_by_value_used_void = [i] { (void)i; };
- auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}} expected-note {{substituting into a lambda}}
- auto explicit_by_value_unused_sizeof = [i] { return sizeof(i); }; // expected-warning{{lambda capture 'i' is not required to be captured for this use}} expected-note {{substituting into a lambda}}
- auto explicit_by_value_unused_decltype = [i] { decltype(i) j = 0; }; // expected-warning{{lambda capture 'i' is not used}} expected-note {{substituting into a lambda}}
- auto explicit_by_value_unused_const = [k] { return k + 1; }; // expected-warning{{lambda capture 'k' is not required to be captured for this use}} expected-note {{substituting into a lambda}}
- auto explicit_by_value_unused_const_generic = [k](auto c) { return k + 1; }; // expected-warning{{lambda capture 'k' is not required to be captured for this use}} expected-note {{substituting into a lambda}}
+ auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}}
+ auto explicit_by_value_unused_sizeof = [i] { return sizeof(i); }; // expected-warning{{lambda capture 'i' is not required to be captured for this use}}
+ auto explicit_by_value_unused_decltype = [i] { decltype(i) j = 0; }; // expected-warning{{lambda capture 'i' is not used}}
+ auto explicit_by_value_unused_const = [k] { return k + 1; }; // expected-warning{{lambda capture 'k' is not required to be captured for this use}}
+ auto explicit_by_value_unused_const_generic = [k](auto c) { return k + 1; }; // expected-warning{{lambda capture 'k' is not required to be captured for this use}}
auto explicit_by_reference_used = [&i] { i++; };
- auto explicit_by_reference_unused = [&i] {}; // expected-warning{{lambda capture 'i' is not used}} expected-note {{substituting into a lambda}}
+ auto explicit_by_reference_unused = [&i] {}; // expected-warning{{lambda capture 'i' is not used}}
auto explicit_initialized_reference_used = [&j = i] { return j + 1; };
- auto explicit_initialized_reference_unused = [&j = i]{}; // expected-warning{{lambda capture 'j' is not used}} expected-note {{substituting into a lambda}}
+ auto explicit_initialized_reference_unused = [&j = i]{}; // expected-warning{{lambda capture 'j' is not used}}
auto explicit_initialized_value_used = [j = 1] { return j + 1; };
- auto explicit_initialized_value_unused = [j = 1] {}; // expected-warning{{lambda capture 'j' is not used}} expected-note {{substituting into a lambda}}
+ auto explicit_initialized_value_unused = [j = 1] {}; // expected-warning{{lambda capture 'j' is not used}}
auto explicit_initialized_value_non_trivial_constructor = [j = NonTrivialConstructor()]{};
auto explicit_initialized_value_non_trivial_destructor = [j = NonTrivialDestructor()]{};
- auto explicit_initialized_value_trivial_init = [j = Trivial()]{}; // expected-warning{{lambda capture 'j' is not used}} expected-note {{substituting into a lambda}}
+ auto explicit_initialized_value_trivial_init = [j = Trivial()]{}; // expected-warning{{lambda capture 'j' is not used}}
auto explicit_initialized_value_non_trivial_init = [j = Trivial(42)]{};
auto explicit_initialized_value_with_side_effect = [j = side_effect()]{};
auto explicit_initialized_value_generic_used = [i = 1](auto c) mutable { i++; };
- auto explicit_initialized_value_generic_unused = [i = 1](auto c) mutable {}; // expected-warning{{lambda capture 'i' is not used}} expected-note {{substituting into a lambda}}
+ auto explicit_initialized_value_generic_unused = [i = 1](auto c) mutable {}; // expected-warning{{lambda capture 'i' is not used}}
auto nested = [&i] { // expected-note {{substituting into a lambda}}
auto explicit_by_value_used = [i] { return i + 1; };
- auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}} expected-note {{substituting into a lambda}}
+ auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}}
};
Trivial trivial;
- auto explicit_by_value_trivial = [trivial] {}; // expected-warning{{lambda capture 'trivial' is not used}} expected-note {{substituting into a lambda}}
+ auto explicit_by_value_trivial = [trivial] {}; // expected-warning{{lambda capture 'trivial' is not used}}
NonTrivialConstructor cons;
- auto explicit_by_value_non_trivial_constructor = [cons] {}; // expected-warning{{lambda capture 'cons' is not used}} expected-note {{substituting into a lambda}}
+ auto explicit_by_value_non_trivial_constructor = [cons] {}; // expected-warning{{lambda capture 'cons' is not used}}
NonTrivialCopyConstructor copy_cons;
auto explicit_by_value_non_trivial_copy_constructor = [copy_cons] {};
@@ -189,7 +189,7 @@ void test_templated() {
}
void test_use_template() {
- test_templated<int>(); // expected-note 13{{in instantiation of function template specialization 'test_templated<int>' requested here}}
+ test_templated<int>(); // expected-note 3 {{requested here}}
}
namespace pr35555 {
diff --git a/clang/test/SemaTemplate/instantiate-local-class.cpp b/clang/test/SemaTemplate/instantiate-local-class.cpp
index f9553e334c7043..47591045fd26e5 100644
--- a/clang/test/SemaTemplate/instantiate-local-class.cpp
+++ b/clang/test/SemaTemplate/instantiate-local-class.cpp
@@ -473,8 +473,7 @@ namespace rdar23721638 {
template <typename T> void bar() {
auto lambda = [](T a = "") {}; // expected-error {{conversion function from 'const char[1]' to 'rdar23721638::A' invokes a deleted function}} \
// expected-note {{in instantiation of default function argument expression for 'operator()<rdar23721638::A>' required here}} \
- // expected-note {{passing argument to parameter 'a' here}} \
- // expected-note {{while substituting into a lambda}}
+ // expected-note {{passing argument to parameter 'a' here}}
lambda();
}
template void bar<A>(); // expected-note {{in instantiation}}
@@ -497,7 +496,6 @@ namespace PR45000 {
// expected-error at -1 {{cannot initialize a parameter of type 'int' with an rvalue of type 'std::nullptr_t'}}
// expected-note at -2 {{in instantiation of default function argument expression for 'operator()<int>' required here}}
// expected-note at -3 {{passing argument to parameter 'x' here}}
- // expected-note at -4 {{while substituting into a lambda}}
void g() { f<int>(); }
// expected-note at -1 {{in instantiation of default function argument expression for 'f<int>' required here}}
More information about the cfe-commits
mailing list