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
