https://github.com/zyn0217 created 
https://github.com/llvm/llvm-project/pull/233375

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


>From fadc5a1c53c2dbbf8728dffaa83e850b9ebda0d4 Mon Sep 17 00:00:00 2001
From: Younan Zhang <[email protected]>
Date: Mon, 19 Oct 2026 16:49:54 +0800
Subject: [PATCH] [Clang] Recover invalid lambdas without numbering

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.
---
 clang/lib/Parse/ParseTemplate.cpp             |  3 +-
 clang/lib/Sema/SemaExprCXX.cpp                |  4 ++
 clang/lib/Sema/SemaLambda.cpp                 |  2 +-
 clang/test/AST/ByteCode/records.cpp           |  6 +-
 clang/test/AST/ast-dump-expr-errors.cpp       |  2 +-
 clang/test/SemaCXX/invalid-lambda.cpp         | 58 +++++++++++++++++++
 clang/test/SemaCXX/invalid-this-in-lambda.cpp |  4 --
 clang/test/SemaCXX/recovery-expr-type.cpp     |  5 +-
 8 files changed, 71 insertions(+), 13 deletions(-)
 create mode 100644 clang/test/SemaCXX/invalid-lambda.cpp
 delete mode 100644 clang/test/SemaCXX/invalid-this-in-lambda.cpp

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@-1 {{invalid use of 'this'}}
+  }
+};
+
+struct B {
+  void f() {
+    auto l = [](int g, decltype(g(this))){};
+    // expected-error@-1 {{called object type 'int'}}
+  }
+};
+
+}
+#endif
+
+#if __cplusplus == 201103L
+
+namespace GH150733 {
+auto L = [](auto a) {
+  // expected-error@-1 {{'auto' not allowed in lambda}}
+  auto M = [](decltype(a)) -> {
+    // expected-error@-1 {{expected a type}}
+  };
+};
+}
+
+#endif
+
+namespace GH170185 {
+
+struct Foo; // expected-note 2{{forward declaration}}
+
+template <Foo X>
+// expected-error@-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@-1 {{conversion from 'int' to 'int 
*' is not allowed}}
+S<P> s; // expected-note {{template template argument has different template 
parameters}}
+// expected-note@-3 {{previous template template parameter}} expected-note@-2 
{{declared here}}
 } // namespace GH202117
 
 namespace test17 {

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to