[clang] [llvm] [clang-tools-extra] [clang] reject to capture variable in `RequiresExprBodyDecl` (PR #78598)
Congcong Cai via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 6 06:19:06 PST 2024
https://github.com/HerrCai0907 updated https://github.com/llvm/llvm-project/pull/78598
>From 8fa3dc43e770025308da47f6aff309fa58c47fc3 Mon Sep 17 00:00:00 2001
From: Congcong Cai <congcongcai0907 at 163.com>
Date: Thu, 18 Jan 2024 23:12:23 +0800
Subject: [PATCH 1/4] [clang] reject to capture variable in
`RequiresExprBodyDecl`
Expression in `RequiresExprBodyDecl` is resolved as constants and should not be captured.
Fixes: #69307, #76593.
---
clang/lib/Sema/SemaExpr.cpp | 21 ++++++++++------
...uires-expression-with-capture-variable.cpp | 25 +++++++++++++++++++
2 files changed, 38 insertions(+), 8 deletions(-)
create mode 100644 clang/test/SemaCXX/requires-expression-with-capture-variable.cpp
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 6413a48f809ac..580e759f63495 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -19704,6 +19704,12 @@ static void buildLambdaCaptureFixit(Sema &Sema, LambdaScopeInfo *LSI,
}
}
+static DeclContext *ignoreReuquiresBodyDecl(DeclContext *DC) {
+ if (isa_and_present<RequiresExprBodyDecl>(DC))
+ return DC->getParent();
+ return DC;
+}
+
bool Sema::tryCaptureVariable(
ValueDecl *Var, SourceLocation ExprLoc, TryCaptureKind Kind,
SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType,
@@ -19711,15 +19717,15 @@ bool Sema::tryCaptureVariable(
// An init-capture is notionally from the context surrounding its
// declaration, but its parent DC is the lambda class.
DeclContext *VarDC = Var->getDeclContext();
- DeclContext *DC = CurContext;
-
// tryCaptureVariable is called every time a DeclRef is formed,
// it can therefore have non-negigible impact on performances.
// For local variables and when there is no capturing scope,
// we can bailout early.
- if (CapturingFunctionScopes == 0 && (!BuildAndDiagnose || VarDC == DC))
+ if (CapturingFunctionScopes == 0 && (!BuildAndDiagnose || VarDC == CurContext))
return true;
+ DeclContext *DC = ignoreReuquiresBodyDecl(CurContext);
+
const auto *VD = dyn_cast<VarDecl>(Var);
if (VD) {
if (VD->isInitCapture())
@@ -19789,11 +19795,10 @@ bool Sema::tryCaptureVariable(
// Only block literals, captured statements, and lambda expressions can
// capture; other scopes don't work.
- DeclContext *ParentDC =
- !IsInScopeDeclarationContext
- ? DC->getParent()
- : getParentOfCapturingContextOrNull(DC, Var, ExprLoc,
- BuildAndDiagnose, *this);
+ DeclContext *ParentDC = IsInScopeDeclarationContext
+ ? getParentOfCapturingContextOrNull(
+ DC, Var, ExprLoc, BuildAndDiagnose, *this)
+ : DC->getParent();
// We need to check for the parent *first* because, if we *have*
// private-captured a global variable, we need to recursively capture it in
// intermediate blocks, lambdas, etc.
diff --git a/clang/test/SemaCXX/requires-expression-with-capture-variable.cpp b/clang/test/SemaCXX/requires-expression-with-capture-variable.cpp
new file mode 100644
index 0000000000000..d01a54133f6c3
--- /dev/null
+++ b/clang/test/SemaCXX/requires-expression-with-capture-variable.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang -fsyntax-only -std=c++20 -Xclang -verify %s
+
+// expected-no-diagnostics
+
+auto GH69307_Func_1() {
+ constexpr auto b = 1;
+ return [&](auto c) -> int
+ requires requires { b + c; }
+ { return 1; };
+};
+auto GH69307_Func_Ret = GH69307_Func_1()(1);
+
+auto GH69307_Lambda_1 = []() {
+ return [&](auto c) -> int
+ requires requires { c; }
+ { return 1; };
+};
+auto GH69307_Lambda_1_Ret = GH69307_Lambda_1()(1);
+
+auto GH69307_Lambda_2 = [](auto c) {
+ return [&]() -> int
+ requires requires { c; }
+ { return 1; };
+};
+auto GH69307_Lambda_2_Ret = GH69307_Lambda_2(1)();
>From a99f16ff51702ff249cdf8a47de0cf24a08f694a Mon Sep 17 00:00:00 2001
From: Congcong Cai <congcongcai0907 at 163.com>
Date: Sat, 20 Jan 2024 13:40:12 +0800
Subject: [PATCH 2/4] another test
---
clang/test/SemaCXX/warn-unused-lambda-capture-cxx20.cpp | 7 +++++++
clang/test/SemaCXX/warn-unused-lambda-capture.cpp | 4 ++++
2 files changed, 11 insertions(+)
create mode 100644 clang/test/SemaCXX/warn-unused-lambda-capture-cxx20.cpp
diff --git a/clang/test/SemaCXX/warn-unused-lambda-capture-cxx20.cpp b/clang/test/SemaCXX/warn-unused-lambda-capture-cxx20.cpp
new file mode 100644
index 0000000000000..b787edb188ed8
--- /dev/null
+++ b/clang/test/SemaCXX/warn-unused-lambda-capture-cxx20.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -fsyntax-only -Wunused-lambda-capture -Wused-but-marked-unused -Wno-uninitialized -verify -std=c++20 %s
+
+void test() {
+ int i;
+ auto explicit_by_value_unused_requires = [i] (auto) requires requires { i; } {}; // expected-warning{{lambda capture 'i' is not required to be captured for this use}}
+ explicit_by_value_unused_requires(1);
+}
diff --git a/clang/test/SemaCXX/warn-unused-lambda-capture.cpp b/clang/test/SemaCXX/warn-unused-lambda-capture.cpp
index 73459496e4cd9..98a3f4623098a 100644
--- a/clang/test/SemaCXX/warn-unused-lambda-capture.cpp
+++ b/clang/test/SemaCXX/warn-unused-lambda-capture.cpp
@@ -44,6 +44,10 @@ void test() {
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 required to be captured for this use}}
auto explicit_by_value_unused_const = [k] { return k + 1; }; // expected-warning{{lambda capture 'k' is not required to be captured for this use}}
+#if __cplusplus >= 202002L
+ auto explicit_by_value_unused_requires = [i] (auto) requires requires { i; } {}; // expected-warning{{lambda capture 'i' is not required to be captured for this use}}
+ explicit_by_value_unused_requires(1);
+#endif
auto explicit_by_reference_used = [&i] { i++; };
auto explicit_by_reference_unused = [&i] {}; // expected-warning{{lambda capture 'i' is not used}}
>From b27d0ac058ca00257c42a3e2598b4701c8ae812d Mon Sep 17 00:00:00 2001
From: Congcong Cai <congcongcai0907 at 163.com>
Date: Sat, 20 Jan 2024 13:56:10 +0800
Subject: [PATCH 3/4] format
---
clang/lib/Sema/SemaExpr.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 580e759f63495..04cfe5435eb23 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -19721,7 +19721,8 @@ bool Sema::tryCaptureVariable(
// it can therefore have non-negigible impact on performances.
// For local variables and when there is no capturing scope,
// we can bailout early.
- if (CapturingFunctionScopes == 0 && (!BuildAndDiagnose || VarDC == CurContext))
+ if (CapturingFunctionScopes == 0 &&
+ (!BuildAndDiagnose || VarDC == CurContext))
return true;
DeclContext *DC = ignoreReuquiresBodyDecl(CurContext);
>From 6cda60056a26f8d489fce1146775b8be8e1fde18 Mon Sep 17 00:00:00 2001
From: Congcong Cai <congcongcai0907 at 163.com>
Date: Tue, 6 Feb 2024 22:18:43 +0800
Subject: [PATCH 4/4] add test
---
clang/lib/Sema/SemaExpr.cpp | 10 +++------
...uires-expression-with-capture-variable.cpp | 21 +++++++++++++------
2 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index da168d1676943..88333b5e66fc5 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -19706,12 +19706,6 @@ static void buildLambdaCaptureFixit(Sema &Sema, LambdaScopeInfo *LSI,
}
}
-static DeclContext *ignoreReuquiresBodyDecl(DeclContext *DC) {
- if (isa_and_present<RequiresExprBodyDecl>(DC))
- return DC->getParent();
- return DC;
-}
-
bool Sema::tryCaptureVariable(
ValueDecl *Var, SourceLocation ExprLoc, TryCaptureKind Kind,
SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType,
@@ -19727,7 +19721,9 @@ bool Sema::tryCaptureVariable(
(!BuildAndDiagnose || VarDC == CurContext))
return true;
- DeclContext *DC = ignoreReuquiresBodyDecl(CurContext);
+ DeclContext *DC = isa_and_present<RequiresExprBodyDecl>(CurContext)
+ ? CurContext->getParent()
+ : CurContext;
const auto *VD = dyn_cast<VarDecl>(Var);
if (VD) {
diff --git a/clang/test/SemaCXX/requires-expression-with-capture-variable.cpp b/clang/test/SemaCXX/requires-expression-with-capture-variable.cpp
index d01a54133f6c3..5f3d0fc90da5b 100644
--- a/clang/test/SemaCXX/requires-expression-with-capture-variable.cpp
+++ b/clang/test/SemaCXX/requires-expression-with-capture-variable.cpp
@@ -2,24 +2,33 @@
// expected-no-diagnostics
-auto GH69307_Func_1() {
+auto GH69307_correct() {
+ constexpr auto b = 1;
+ // no need to capture
+ return [](auto c) -> int
+ requires requires { b + c; }
+ { return 1; };
+};
+auto GH69307_correct_ret = GH69307_correct()(1);
+
+auto GH69307_func() {
constexpr auto b = 1;
return [&](auto c) -> int
requires requires { b + c; }
{ return 1; };
};
-auto GH69307_Func_Ret = GH69307_Func_1()(1);
+auto GH69307_func_ret = GH69307_func()(1);
-auto GH69307_Lambda_1 = []() {
+auto GH69307_lambda_1 = []() {
return [&](auto c) -> int
requires requires { c; }
{ return 1; };
};
-auto GH69307_Lambda_1_Ret = GH69307_Lambda_1()(1);
+auto GH69307_lambda_1_ret = GH69307_lambda_1()(1);
-auto GH69307_Lambda_2 = [](auto c) {
+auto GH69307_lambda_2 = [](auto c) {
return [&]() -> int
requires requires { c; }
{ return 1; };
};
-auto GH69307_Lambda_2_Ret = GH69307_Lambda_2(1)();
+auto GH69307_lambda_2_ret = GH69307_lambda_2(1)();
More information about the cfe-commits
mailing list