[clang] [Clang] Recover invalid lambdas without numbering (PR #233375)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 19 02:06:14 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Younan Zhang (zyn0217)
<details>
<summary>Changes</summary>
Those DecltypeExprs used to preserve RecoveryExprs which makes things complicated when we need to recover errors from a lambda expression.
This patch stops that, as well as fixes some other error handlings.
I don't think this is worth a release note entry - I just want to stop AI from messing around those things.
Fixes https://github.com/llvm/llvm-project/issues/150733
Fixes https://github.com/llvm/llvm-project/issues/175713
Fixes https://github.com/llvm/llvm-project/issues/170185
---
Full diff: https://github.com/llvm/llvm-project/pull/233375.diff
8 Files Affected:
- (modified) clang/lib/Parse/ParseTemplate.cpp (+2-1)
- (modified) clang/lib/Sema/SemaExprCXX.cpp (+4)
- (modified) clang/lib/Sema/SemaLambda.cpp (+1-1)
- (modified) clang/test/AST/ByteCode/records.cpp (+2-4)
- (modified) clang/test/AST/ast-dump-expr-errors.cpp (+1-1)
- (added) clang/test/SemaCXX/invalid-lambda.cpp (+58)
- (removed) clang/test/SemaCXX/invalid-this-in-lambda.cpp (-4)
- (modified) clang/test/SemaCXX/recovery-expr-type.cpp (+3-2)
``````````diff
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index ef6920fdc485c..ff4945f014db1 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -1375,7 +1375,8 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() {
else
ExprArg = ParseConstantExpressionInExprEvalContext(
TypoCorrectionTypeBehavior::AllowBoth);
- if (ExprArg.isInvalid() || !ExprArg.get()) {
+ if (ExprArg.isInvalid() || !ExprArg.get() ||
+ ExprArg.get()->containsErrors()) {
return ParsedTemplateArgument();
}
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index d9bd060f7a0bf..2e717fe05a24e 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -6930,6 +6930,10 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
ExpressionEvaluationContextRecord::EK_Decltype &&
"not in a decltype expression");
+ // Give up here so we don't try to evaluate it later.
+ if (isa<RecoveryExpr>(E))
+ return ExprError();
+
ExprResult Result = CheckPlaceholderExpr(E);
if (Result.isInvalid())
return ExprError();
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 0c9a92cdd0c32..ed2423542d2af 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -1488,7 +1488,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
const auto &FTI = ParamInfo.getFunctionTypeInfo();
LSI->ExplicitParams = FTI.getLParenLoc().isValid();
if (!FTIHasSingleVoidParameter(FTI)) {
- Params.reserve(Params.size());
+ Params.reserve(FTI.NumParams);
for (unsigned I = 0; I < FTI.NumParams; ++I) {
auto *Param = cast<ParmVarDecl>(FTI.Params[I].Param);
Param->setScopeInfo(0, Params.size());
diff --git a/clang/test/AST/ByteCode/records.cpp b/clang/test/AST/ByteCode/records.cpp
index ab79384a10476..4404eb7c6df23 100644
--- a/clang/test/AST/ByteCode/records.cpp
+++ b/clang/test/AST/ByteCode/records.cpp
@@ -2019,15 +2019,13 @@ namespace ErroneousVoidDecl {
template <typename F, typename C, typename N1, typename N2>
constexpr bool check(const C &c, N1 *n1, N2 *n2) {
- decltype(f(c, n1, n2)) *chk{}; // both-error {{no matching function}} \
- // ref-note {{destroying object 'chk' whose lifetime has already ended}}
+ decltype(f(c, n1, n2)) *chk{}; // both-error {{no matching function}}
return true;
}
template <int N> constexpr M<N> *bar() { return nullptr; }
static_assert(check<S>([](int n) constexpr {}, bar<1u>(), bar<1u>())); // both-note {{in instantiation}} \
- // ref-error {{not an integral constant expression}} \
- // ref-note {{in call to}}
+ // both-error {{not an integral constant expression}}
#endif
}
diff --git a/clang/test/AST/ast-dump-expr-errors.cpp b/clang/test/AST/ast-dump-expr-errors.cpp
index 5661a41465eb6..1aad414a5c3d8 100644
--- a/clang/test/AST/ast-dump-expr-errors.cpp
+++ b/clang/test/AST/ast-dump-expr-errors.cpp
@@ -42,5 +42,5 @@ int d = static_cast<int>(bar() + 1);
// Error type should result in an invalid decl.
-// CHECK: -VarDecl {{.*}} invalid f 'decltype(<recovery-expr>(bar))'
+// CHECK: -VarDecl {{.*}} invalid f 'int'
decltype(bar()) f;
diff --git a/clang/test/SemaCXX/invalid-lambda.cpp b/clang/test/SemaCXX/invalid-lambda.cpp
new file mode 100644
index 0000000000000..a5ec348dcf439
--- /dev/null
+++ b/clang/test/SemaCXX/invalid-lambda.cpp
@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++26 %s
+
+decltype([]()->decltype(this) { }) a; // expected-error {{invalid use of 'this' outside of a non-static member function}}
+
+#if __cplusplus >= 202302L
+namespace GH175173 {
+
+struct A {
+ void f(this A&) {
+ auto l = [](auto g, decltype(g(this))){};
+ // expected-error at -1 {{invalid use of 'this'}}
+ }
+};
+
+struct B {
+ void f() {
+ auto l = [](int g, decltype(g(this))){};
+ // expected-error at -1 {{called object type 'int'}}
+ }
+};
+
+}
+#endif
+
+#if __cplusplus == 201103L
+
+namespace GH150733 {
+auto L = [](auto a) {
+ // expected-error at -1 {{'auto' not allowed in lambda}}
+ auto M = [](decltype(a)) -> {
+ // expected-error at -1 {{expected a type}}
+ };
+};
+}
+
+#endif
+
+namespace GH170185 {
+
+struct Foo; // expected-note 2{{forward declaration}}
+
+template <Foo X>
+// expected-error at -1 {{non-type template parameter has incomplete type}}
+struct Arr;
+
+Foo f; // expected-error {{variable has incomplete type}}
+
+void foo() {
+ (void)[]() {
+ (void)[&](Arr<f>) {
+
+ };
+ }();
+}
+
+}
diff --git a/clang/test/SemaCXX/invalid-this-in-lambda.cpp b/clang/test/SemaCXX/invalid-this-in-lambda.cpp
deleted file mode 100644
index ae65bda025e23..0000000000000
--- a/clang/test/SemaCXX/invalid-this-in-lambda.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
-
-decltype([]()->decltype(this) { }) a; // expected-error {{invalid use of 'this' outside of a non-static member function}}
-
diff --git a/clang/test/SemaCXX/recovery-expr-type.cpp b/clang/test/SemaCXX/recovery-expr-type.cpp
index 101d0155e3b98..7b6bd8d1699c5 100644
--- a/clang/test/SemaCXX/recovery-expr-type.cpp
+++ b/clang/test/SemaCXX/recovery-expr-type.cpp
@@ -195,8 +195,9 @@ using V = U<S<T>>;
namespace GH202117 {
template<template<decltype(foo())> typename T> struct S {}; // expected-error {{use of undeclared identifier 'foo'}}
-template<int*> struct P;
-S<P> s;
+template<int*> struct P; // expected-error at -1 {{conversion from 'int' to 'int *' is not allowed}}
+S<P> s; // expected-note {{template template argument has different template parameters}}
+// expected-note at -3 {{previous template template parameter}} expected-note at -2 {{declared here}}
} // namespace GH202117
namespace test17 {
``````````
</details>
https://github.com/llvm/llvm-project/pull/233375
More information about the cfe-commits
mailing list