https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/233375
>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 1/2] [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 ef6920fdc485c1..ff4945f014db16 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 d9bd060f7a0bf9..2e717fe05a24ec 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 0c9a92cdd0c320..ed2423542d2aff 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 ab79384a104765..4404eb7c6df237 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 5661a41465eb63..1aad414a5c3d89 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 00000000000000..a5ec348dcf4391 --- /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 ae65bda025e232..00000000000000 --- 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 101d0155e3b987..7b6bd8d1699c50 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 { >From 07848efb8f981f59b284b8016ed7219340c1ae58 Mon Sep 17 00:00:00 2001 From: Younan Zhang <[email protected]> Date: Mon, 19 Oct 2026 18:11:49 +0800 Subject: [PATCH 2/2] Revert #221440 --- clang/lib/Sema/SemaTemplate.cpp | 5 ++--- clang/test/SemaCXX/GH220525.cpp | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 5a61cb852d15e5..f8cc0c7228a78a 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -10664,13 +10664,12 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, false, TypeResult(), /*IsTypeSpecifier*/ false, /*IsTemplateParamOrArg*/ false, /*OOK=*/OffsetOfKind::Outside) .get(); + assert(!IsDependent && + "explicit instantiation of dependent name not yet handled"); if (!TagD) return true; - assert(!IsDependent && - "explicit instantiation of dependent name not yet handled"); - TagDecl *Tag = cast<TagDecl>(TagD); assert(!Tag->isEnum() && "shouldn't see enumerations here"); diff --git a/clang/test/SemaCXX/GH220525.cpp b/clang/test/SemaCXX/GH220525.cpp index 5f34e67d708869..b687b2891c8176 100644 --- a/clang/test/SemaCXX/GH220525.cpp +++ b/clang/test/SemaCXX/GH220525.cpp @@ -1,7 +1,6 @@ // RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s namespace foo { - template<typename T> struct S {}; // expected-note {{template parameter is declared here}} + template<typename T> struct S {}; } -template struct foo::S<foo>::bar; // expected-error {{template argument for template type parameter must be a type}} \ - // expected-error {{unexpected namespace name 'foo': expected expression}} +template struct foo::S<foo>::bar; // expected-error {{unexpected namespace name 'foo': expected expression}} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
