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

via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 17 12:37:07 PST 2026


Author: Samrudh Nelli
Date: 2026-02-17T21:37:03+01:00
New Revision: de03ec740b22485e2b84234abbfdc3e67592b946

URL: https://github.com/llvm/llvm-project/commit/de03ec740b22485e2b84234abbfdc3e67592b946
DIFF: https://github.com/llvm/llvm-project/commit/de03ec740b22485e2b84234abbfdc3e67592b946.diff

LOG: [Clang] Fix incorrect mutability of decltype((x)) in lambda return types (#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

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Parse/ParseExprCXX.cpp
    clang/test/SemaCXX/lambda-expressions.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5416b25b3927c..86cee7d1b6f9b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -283,6 +283,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)
 - Fixed a crash when evaluating uninitialized GCC vector/ext_vector_type vectors in ``constexpr``. (#GH180044)
 
 Bug Fixes to AST Handling

diff  --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 842b52375eb14..b3d50daf66b10 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -1417,6 +1417,11 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
       ConsumeToken();
     }
 
+    // We have called ActOnLambdaClosureQualifiers for parentheses-less cases
+    // above.
+    if (HasParentheses)
+      Actions.ActOnLambdaClosureQualifiers(Intro, MutableLoc);
+
     SourceLocation FunLocalRangeEnd = DeclEndLoc;
 
     // Parse trailing-return-type[opt].
@@ -1445,11 +1450,6 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
                       TrailingReturnType, TrailingReturnTypeLoc, &DS),
                   std::move(Attributes), DeclEndLoc);
 
-    // We have called ActOnLambdaClosureQualifiers for parentheses-less cases
-    // above.
-    if (HasParentheses)
-      Actions.ActOnLambdaClosureQualifiers(Intro, MutableLoc);
-
     if (HasParentheses && Tok.is(tok::kw_requires))
       ParseTrailingRequiresClause(D);
   }

diff  --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp
index f9d7cfcbbd18d..00c52efb78a7d 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}}
+  };
+}
+}


        


More information about the cfe-commits mailing list