llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-temporal-safety Author: Aaditya Agarwal (aaditya8979) <details> <summary>Changes</summary> Fixes #<!-- -->237332. When a method is declared with a parenthesised name and a trailing return type (e.g. `auto (operator++)() & -> S &`), the TypeLoc wraps FunctionTypeLoc inside a ParenTypeLoc. getAs<FunctionTypeLoc>() does not look through ParenTypeLoc, hitting the assert. Fix: use getAsAdjusted<FunctionTypeLoc>() which strips wrapping type locs. Also guard findPreviousToken()'s optional return before dereferencing. I used AI tools (Google Gemini) for assistance with parts of this patch. --- Full diff: https://github.com/llvm/llvm-project/pull/237624.diff 2 Files Affected: - (modified) clang/lib/Sema/SemaLifetimeSafety.h (+13-8) - (added) clang/test/Sema/LifetimeSafety/paren-decl-no-crash.cpp (+25) ``````````diff diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h index 0df2ae84f92742..7a5c52dd17b5ff 100644 --- a/clang/lib/Sema/SemaLifetimeSafety.h +++ b/clang/lib/Sema/SemaLifetimeSafety.h @@ -715,14 +715,19 @@ 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) + return {InsertionPoint, + getLifetimeBoundFixItText(InsertionPoint, /*LeadingSpace=*/true, + /*AllowGNUAttrMacro=*/false)}; + 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}} +}; `````````` </details> https://github.com/llvm/llvm-project/pull/237624 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
