https://github.com/aaditya8979 updated 
https://github.com/llvm/llvm-project/pull/237624

>From 6cba304dd5be6cea3365401288a06e5b72ca1e47 Mon Sep 17 00:00:00 2001
From: openhands <[email protected]>
Date: Sun, 1 Nov 2026 01:15:44 +0530
Subject: [PATCH] [clang][LifetimeSafety] Fix crash in getLifetimeBoundFixIt
 for parenthesised declarators

TypeLoc::getAs<FunctionTypeLoc>() does not look through ParenTypeLoc,
so a method declared as 'auto (operator++)() & -> S &' caused an
assertion failure in getLifetimeBoundFixIt().  Switch to
getAsAdjusted<FunctionTypeLoc>() which strips wrapping type locs
including ParenTypeLoc.  Also guard the findPreviousToken() optional
result before dereferencing it.

Fixes #237332
---
 clang/lib/Sema/SemaLifetimeSafety.h           | 22 ++++++++++------
 .../LifetimeSafety/paren-decl-no-crash.cpp    | 25 +++++++++++++++++++
 2 files changed, 39 insertions(+), 8 deletions(-)
 create mode 100644 clang/test/Sema/LifetimeSafety/paren-decl-no-crash.cpp

diff --git a/clang/lib/Sema/SemaLifetimeSafety.h 
b/clang/lib/Sema/SemaLifetimeSafety.h
index 0df2ae84f92742..8f3428ba778360 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -715,14 +715,20 @@ class LifetimeSafetySemaHelperImpl final : public 
LifetimeSafetySemaHelper {
       // after '->', placing the attribute in an invalid position.
       // Instead use 'getLocalRangeEnd()' which gives the '->' location
       // for trailing returns, so find the last token before it.
-      const auto FTL = MDL.getAs<FunctionTypeLoc>();
-      assert(FTL);
-      InsertionPoint = Lexer::getLocForEndOfToken(
-          Lexer::findPreviousToken(FTL.getLocalRangeEnd(), 
S.getSourceManager(),
-                                   S.getLangOpts(),
-                                   /*IncludeComments=*/false)
-              ->getLocation(),
-          0, S.getSourceManager(), S.getLangOpts());
+      // A parenthesised declarator (e.g. 'auto (f)() & -> T') wraps the
+      // FunctionTypeLoc inside a ParenTypeLoc.  getAs<> does not look through
+      // ParenTypeLoc, so use getAsAdjusted<> which strips qualifying wrappers.
+      const auto FTL = MDL.getAsAdjusted<FunctionTypeLoc>();
+      if (!FTL)
+        // Cannot locate the function type loc; the InsertionPoint derived from
+        // getEndLoc() covers the trailing return type and is not a valid
+        // attribute site.  Emit the diagnostic without a fix-it.
+        return {InsertionPoint, {}};
+      if (auto PrevTok = Lexer::findPreviousToken(
+              FTL.getLocalRangeEnd(), S.getSourceManager(), S.getLangOpts(),
+              /*IncludeComments=*/false))
+        InsertionPoint = Lexer::getLocForEndOfToken(
+            PrevTok->getLocation(), 0, S.getSourceManager(), S.getLangOpts());
     }
     return {InsertionPoint,
             getLifetimeBoundFixItText(InsertionPoint, /*LeadingSpace=*/true,
diff --git a/clang/test/Sema/LifetimeSafety/paren-decl-no-crash.cpp 
b/clang/test/Sema/LifetimeSafety/paren-decl-no-crash.cpp
new file mode 100644
index 00000000000000..ffabd630a8a024
--- /dev/null
+++ b/clang/test/Sema/LifetimeSafety/paren-decl-no-crash.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -flifetime-safety-inference \
+// RUN:   -fexperimental-lifetime-safety-tu-analysis \
+// RUN:   -Wlifetime-safety-suggestions -Wno-dangling -verify %s
+
+// Verify that parenthesised declarator names with trailing return types don't
+// crash the lifetimebound fixit suggestion logic.  getLifetimeBoundFixIt() for
+// CXXMethodDecl used TypeLoc::getAs<FunctionTypeLoc>() to navigate into the
+// type, but parenthesised declarators (e.g. 'auto (f)() & -> T') wrap the
+// FunctionTypeLoc inside a ParenTypeLoc which getAs<> cannot see through.
+//
+// https://github.com/llvm/llvm-project/issues/237332
+
+struct S {
+  // Crash: parenthesised operator name + trailing return type.
+  auto (operator++)() & -> S & { return *this; } // expected-warning 
{{implicit this in intra-TU function should be marked [[clang::lifetimebound]]}}
+                                                  // expected-note@-1 {{param 
returned here}}
+
+  // Parenthesised operator name, conventional (non-trailing) return type.
+  S & (operator--)(int) { return *this; } // expected-warning {{implicit this 
in intra-TU function should be marked [[clang::lifetimebound]]}}
+                                          // expected-note@-1 {{param returned 
here}}
+
+  // Non-parenthesised trailing return -- was already working, must stay so.
+  auto operator++(int) -> S & { return *this; } // expected-warning {{implicit 
this in intra-TU function should be marked [[clang::lifetimebound]]}}
+                                                 // expected-note@-1 {{param 
returned here}}
+};

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

Reply via email to