Skip to content

Commit 525e68e

Browse files
authored
Don't mark lambda non-dependent if nested in a generic lambda. (#149121)
Fixes #118187 Fixes #156579 An instantiated `LambdaExpr` can currently be marked as `LDK_NeverDependent` if it's nested within a generic lambda. If that `LambdaExpr` in fact depends on template parameters introduced by the enclosing generic lambda, then its dependence will be misreported as "never dependent" and spurious diagnostics can result. The fix here proposed is a bit ugly, but the condition that it's being bolted onto already seems like a bit of a hack, so this seems no worse for wear. Note that #89702 surfaced this change because it caused the inner lambda expression to (correctly) be considered in a constant-evaluated context. The affected check for whether to mark the inner lambda as `LDK_NeverDependent` therefore started to apply, whereas it didn't before. **Tested**: `check-clang` and `check-cxx`.
1 parent 0859ac5 commit 525e68e

File tree

3 files changed

+25
-1
lines changed

3 files changed

+25
-1
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ Bug Fixes to C++ Support
557557
- Diagnose unresolved overload sets in non-dependent compound requirements. (#GH51246) (#GH97753)
558558
- Fix a crash when extracting unavailable member type from alias in template deduction. (#GH165560)
559559
- Fix incorrect diagnostics for lambdas with init-captures inside braced initializers. (#GH163498)
560+
- Fixed spurious diagnoses of certain nested lambda expressions. (#GH149121) (#GH156579)
560561

561562
Bug Fixes to AST Handling
562563
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/TreeTransform.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15628,6 +15628,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
1562815628
DC = DC->getParent();
1562915629
if ((getSema().isUnevaluatedContext() ||
1563015630
getSema().isConstantEvaluatedContext()) &&
15631+
!(dyn_cast_or_null<CXXRecordDecl>(DC->getParent()) &&
15632+
cast<CXXRecordDecl>(DC->getParent())->isGenericLambda()) &&
1563115633
(DC->isFileContext() || !DC->getParent()->isDependentContext()))
1563215634
DependencyKind = CXXRecordDecl::LDK_NeverDependent;
1563315635

clang/test/SemaCXX/cxx2a-consteval.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1319,6 +1319,27 @@ namespace GH139160{
13191319
B result = (B){10, get_value(make_struct())}; // expected-error {{initializer element is not a compile-time constant}}
13201320
// expected-error@-1 {{call to consteval function 'GH139160::get_value' is not a constant expression}}
13211321
// expected-note@-2 {{non-constexpr function 'make_struct' cannot be used in a constant expression}}
1322-
};
1322+
} // namespace GH139160
1323+
1324+
namespace GH118187 {
1325+
1326+
template <typename T> int t() {
1327+
return []<typename U>() consteval {
1328+
return [](U v) { return v; }(123);
1329+
}.template operator()<int>();
1330+
}
13231331

1332+
int v = t<int>();
1333+
} // namespace GH118187
13241334

1335+
namespace GH156579 {
1336+
template <class>
1337+
auto f{[] (auto...) {
1338+
if constexpr ([] (auto) { return true; }(0))
1339+
return 0;
1340+
}};
1341+
1342+
void g() {
1343+
f<int>();
1344+
}
1345+
} // namespace GH156579

0 commit comments

Comments
 (0)