[clang] [Clang] Treat default template argument as constant expressions (PR #107073)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 4 01:38:17 PDT 2024
https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/107073
>From 5edd9a9abe019af2a14ccf9fbf43858f4141071b Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Tue, 3 Sep 2024 11:25:27 +0200
Subject: [PATCH 1/3] [Clang] Treat default template argument as constant
expressions
We only check that a default argument is a converted constant
expression when using the default argument.
However, when parsing a default argument, we need to make sure
to parse it as a constant expression such as not ODR-use variables.
(otherwise, we would try to capture default template arguments
of generic lambdas)
Fixes #107048
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Parse/ParseTemplate.cpp | 2 ++
clang/test/SemaCXX/cxx2a-template-lambdas.cpp | 19 +++++++++++++++++++
3 files changed, 22 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index fc940db4813948..e15414b994a36b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -339,6 +339,7 @@ Bug Fixes to C++ Support
- Template parameter names are considered in the name lookup of out-of-line class template
specialization right before its declaration context. (#GH64082)
- Fixed a constraint comparison bug for friend declarations. (#GH78101)
+- Clang no longer tries to capture default argument of template arguments of generic lambdas (#GH107048)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index 6ecfc15757f3d4..b80999f1b92e7f 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -960,6 +960,8 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
EnterExpressionEvaluationContext ConstantEvaluated(
Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
DefaultArg = Actions.CorrectDelayedTyposInExpr(ParseInitializer());
+ if (DefaultArg.isUsable())
+ DefaultArg = Actions.ActOnConstantExpression(DefaultArg);
if (DefaultArg.isInvalid())
SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch);
}
diff --git a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp
index fff524e77d3bf4..ec373f30876295 100644
--- a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp
+++ b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp
@@ -97,3 +97,22 @@ void foo() {
}
#endif
+
+#if __cplusplus >= 202002L
+void GH107048() {
+ constexpr int x{};
+ const int y{};
+ auto b = []<int=x, int=y>{};
+ using A = decltype([]<int=x>{});
+
+ int z; // expected-note {{'z' declared here}}
+ auto c = []<int t=z>{
+ // expected-error at -1 {{no matching function for call to object of type}} \
+ // expected-error at -1 {{variable 'z' cannot be implicitly captured in a lambda with no capture-default specified}} \
+ // expected-note at -1 {{lambda expression begins here}} \
+ // expected-note at -1 4{{capture}} \
+ // expected-note at -1 {{candidate template ignored: substitution failure: reference to local variable 'z' declared in enclosing function}}
+ return t;
+ }();
+}
+#endif
>From b98c94e765656dcf1120ad1ec72b9c4c191ffefd Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Tue, 3 Sep 2024 14:29:29 +0200
Subject: [PATCH 2/3] address review comments
---
clang/lib/Parse/ParseTemplate.cpp | 4 +---
clang/test/SemaCXX/cxx2a-template-lambdas.cpp | 9 ++++++++-
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index b80999f1b92e7f..de29652abbfd95 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -959,9 +959,7 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
++CurTemplateDepthTracker;
EnterExpressionEvaluationContext ConstantEvaluated(
Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
- DefaultArg = Actions.CorrectDelayedTyposInExpr(ParseInitializer());
- if (DefaultArg.isUsable())
- DefaultArg = Actions.ActOnConstantExpression(DefaultArg);
+ DefaultArg = Actions.ActOnConstantExpression(ParseInitializer());
if (DefaultArg.isInvalid())
SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch);
}
diff --git a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp
index ec373f30876295..34718f9e180f50 100644
--- a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp
+++ b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp
@@ -106,7 +106,7 @@ void GH107048() {
using A = decltype([]<int=x>{});
int z; // expected-note {{'z' declared here}}
- auto c = []<int t=z>{
+ auto c = []<int t=z>{
// expected-error at -1 {{no matching function for call to object of type}} \
// expected-error at -1 {{variable 'z' cannot be implicitly captured in a lambda with no capture-default specified}} \
// expected-note at -1 {{lambda expression begins here}} \
@@ -114,5 +114,12 @@ void GH107048() {
// expected-note at -1 {{candidate template ignored: substitution failure: reference to local variable 'z' declared in enclosing function}}
return t;
}();
+
+ struct S {};
+ constexpr S s; // expected-note {{'s' declared here}}
+ auto class_type = []<S=s>{};
+ // expected-error at -1 {{variable 's' cannot be implicitly captured in a lambda with no capture-default specified}} \
+ // expected-note at -1 {{lambda expression begins here}} \
+ // expected-note at -1 4{{capture}}
}
#endif
>From 00672c5ce874a2823507d69125c1a5e47c2a0f4e Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Wed, 4 Sep 2024 09:16:54 +0200
Subject: [PATCH 3/3] add tests
---
clang/test/SemaCXX/cxx2a-template-lambdas.cpp | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp
index 34718f9e180f50..00ba291fbd1981 100644
--- a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp
+++ b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp
@@ -99,7 +99,10 @@ void foo() {
#endif
#if __cplusplus >= 202002L
-void GH107048() {
+namespace {
+struct S {};
+constexpr S gs;
+void f() {
constexpr int x{};
const int y{};
auto b = []<int=x, int=y>{};
@@ -115,11 +118,16 @@ void GH107048() {
return t;
}();
- struct S {};
+ auto class_type_global = []<S=gs>{};
+
+ static constexpr S static_s;
+ auto class_type_static = []<S=static_s>{};
+
constexpr S s; // expected-note {{'s' declared here}}
auto class_type = []<S=s>{};
// expected-error at -1 {{variable 's' cannot be implicitly captured in a lambda with no capture-default specified}} \
// expected-note at -1 {{lambda expression begins here}} \
// expected-note at -1 4{{capture}}
}
+}
#endif
More information about the cfe-commits
mailing list