Skip to content

Commit 030e4d0

Browse files
authored
[Clang] Treat default template argument as constant expressions (#107073)
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
1 parent 12d678a commit 030e4d0

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ Bug Fixes to C++ Support
346346
- Fix handling of ``_`` as the name of a lambda's init capture variable. (#GH107024)
347347
- Fix an issue with dependent source location expressions (#GH106428), (#GH81155), (#GH80210), (#GH85373)
348348
- Fixed a bug in the substitution of empty pack indexing types. (#GH105903)
349+
- Clang no longer tries to capture non-odr used default arguments of template parameters of generic lambdas (#GH107048)
349350

350351
Bug Fixes to AST Handling
351352
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Parse/ParseTemplate.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,7 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
959959
++CurTemplateDepthTracker;
960960
EnterExpressionEvaluationContext ConstantEvaluated(
961961
Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
962-
DefaultArg = Actions.CorrectDelayedTyposInExpr(ParseInitializer());
962+
DefaultArg = Actions.ActOnConstantExpression(ParseInitializer());
963963
if (DefaultArg.isInvalid())
964964
SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch);
965965
}

clang/test/SemaCXX/cxx2a-template-lambdas.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,37 @@ void foo() {
9797

9898
}
9999
#endif
100+
101+
#if __cplusplus >= 202002L
102+
namespace {
103+
struct S {};
104+
constexpr S gs;
105+
void f() {
106+
constexpr int x{};
107+
const int y{};
108+
auto b = []<int=x, int=y>{};
109+
using A = decltype([]<int=x>{});
110+
111+
int z; // expected-note {{'z' declared here}}
112+
auto c = []<int t=z>{
113+
// expected-error@-1 {{no matching function for call to object of type}} \
114+
// expected-error@-1 {{variable 'z' cannot be implicitly captured in a lambda with no capture-default specified}} \
115+
// expected-note@-1 {{lambda expression begins here}} \
116+
// expected-note@-1 4{{capture}} \
117+
// expected-note@-1 {{candidate template ignored: substitution failure: reference to local variable 'z' declared in enclosing function}}
118+
return t;
119+
}();
120+
121+
auto class_type_global = []<S=gs>{};
122+
123+
static constexpr S static_s;
124+
auto class_type_static = []<S=static_s>{};
125+
126+
constexpr S s; // expected-note {{'s' declared here}}
127+
auto class_type = []<S=s>{};
128+
// expected-error@-1 {{variable 's' cannot be implicitly captured in a lambda with no capture-default specified}} \
129+
// expected-note@-1 {{lambda expression begins here}} \
130+
// expected-note@-1 4{{capture}}
131+
}
132+
}
133+
#endif

0 commit comments

Comments
 (0)