[clang] [Clang] Fix incorrect mutability of decltype((x)) in lambda return types (PR #180690)

Samrudh Nelli via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 9 23:09:26 PST 2026


https://github.com/SamrudhNelli created https://github.com/llvm/llvm-project/pull/180690

Previously, the parser did not update the lambda's mutability state before parsing the trailing return type. This caused decltype((x)) to incorrectly deduce a non-const reference even in a non-mutable lambda.
Fixes #180460 

>From e6344701149989a2f40973c6b76c7b2fb398215c Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Tue, 10 Feb 2026 12:32:45 +0530
Subject: [PATCH] [Clang] Fix incorrect mutability of decltype((x)) in lambda
 return types

Previously, the parser did not update the lambda's mutability state
before parsing the trailing return type. This caused decltype((x))
to incorrectly deduce a non-const reference even in a non-mutable lambda.
---
 clang/docs/ReleaseNotes.rst               |  2 ++
 clang/lib/Parse/ParseExprCXX.cpp          |  3 +++
 clang/test/SemaCXX/lambda-expressions.cpp | 13 +++++++++++++
 3 files changed, 18 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a1bb1bd2467b7..f7a1a97cc1caf 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -262,6 +262,8 @@ Bug Fixes to C++ Support
 - Fixed a crash when instantiating ``requires`` expressions involving substitution failures in C++ concepts. (#GH176402)
 - Fixed a crash when a default argument is passed to an explicit object parameter. (#GH176639)
 - Fixed a crash when diagnosing an invalid static member function with an explicit object parameter (#GH177741)
+- Fixed a bug where captured variables in non-mutable lambdas were incorrectly treated as mutable 
+  when used inside decltype in the return type. (#GH180460)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 842b52375eb14..0fb050cce329c 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -1383,6 +1383,9 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
     addStaticToLambdaDeclSpecifier(*this, StaticLoc, DS);
     addConstexprToLambdaDeclSpecifier(*this, ConstexprLoc, DS);
     addConstevalToLambdaDeclSpecifier(*this, ConstevalLoc, DS);
+    if (clang::sema::LambdaScopeInfo *LSI = Actions.getCurLambda()) {
+      LSI->Mutable = MutableLoc.isValid();
+    }
   }
 
   Actions.ActOnLambdaClosureParameters(getCurScope(), ParamInfo);
diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp
index f9d7cfcbbd18d..ee6ae81107082 100644
--- a/clang/test/SemaCXX/lambda-expressions.cpp
+++ b/clang/test/SemaCXX/lambda-expressions.cpp
@@ -799,3 +799,16 @@ template auto t::operator()<int>(int a) const; // expected-note {{in instantiati
 
 }
 #endif
+
+namespace GH180460 {
+// Trailing return type incorrectly treated 'x' as mutable.
+void test_lambda_return_type() {
+  float x = 0.0f;
+
+  [=]() -> decltype((x)) {
+    decltype(x) y1 = x;
+    decltype((x)) y2 = y1;       // expected-note{{binding reference variable 'y2' here}}
+    return y2;                   // expected-warning{{reference to stack memory associated with local variable 'y1' returned}}
+  };
+}
+}
\ No newline at end of file



More information about the cfe-commits mailing list