https://github.com/NeKon69 updated https://github.com/llvm/llvm-project/pull/198784
>From f95dcf6ef9be88c85f4a94735e93077046ecfe68 Mon Sep 17 00:00:00 2001 From: NeKon69 <[email protected]> Date: Wed, 20 May 2026 16:30:14 +0300 Subject: [PATCH 1/2] remove function --- clang/lib/Analysis/LifetimeSafety/Checker.cpp | 57 ++++--------------- .../test/Sema/warn-lifetime-safety-fixits.cpp | 9 ++- .../Sema/warn-lifetime-safety-suggestions.cpp | 24 ++++---- 3 files changed, 27 insertions(+), 63 deletions(-) diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp b/clang/lib/Analysis/LifetimeSafety/Checker.cpp index d6a15139aa4ea..4b9d195411179 100644 --- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp +++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp @@ -353,66 +353,31 @@ class LifetimeChecker { Scope}; } - /// Returns the declaration of a function that is visible across translation - /// units, if such a declaration exists and is different from the definition. - static const FunctionDecl *getCrossTUDecl(const FunctionDecl &FD, - SourceManager &SM) { - if (!FD.isExternallyVisible()) - return nullptr; - const FileID DefinitionFile = SM.getFileID(FD.getLocation()); - for (const FunctionDecl *Redecl : FD.redecls()) - if (SM.getFileID(Redecl->getLocation()) != DefinitionFile) - return Redecl; - - return nullptr; - } - - static const FunctionDecl *getCrossTUDecl(const ParmVarDecl &PVD, - SourceManager &SM) { - if (const auto *FD = dyn_cast<FunctionDecl>(PVD.getDeclContext())) - return getCrossTUDecl(*FD, SM); - return nullptr; - } - - static void suggestWithScopeForParmVar(LifetimeSafetySemaHelper *SemaHelper, - const ParmVarDecl *PVD, - SourceManager &SM, - EscapingTarget EscapeTarget) { + void suggestWithScopeForParmVar(const ParmVarDecl *PVD, + EscapingTarget EscapeTarget) { if (llvm::isa<const VarDecl *>(EscapeTarget)) return; - if (const FunctionDecl *CrossTUDecl = getCrossTUDecl(*PVD, SM)) - SemaHelper->suggestLifetimeboundToParmVar( - WarningScope::CrossTU, - CrossTUDecl->getParamDecl(PVD->getFunctionScopeIndex()), - EscapeTarget); - else - SemaHelper->suggestLifetimeboundToParmVar(WarningScope::IntraTU, PVD, - EscapeTarget); + auto [Parm, Scope] = getCanonicalDeclForAttr(cast<FunctionDecl>(FD), PVD); + SemaHelper->suggestLifetimeboundToParmVar(Scope, Parm, EscapeTarget); } - static void - suggestWithScopeForImplicitThis(LifetimeSafetySemaHelper *SemaHelper, - const CXXMethodDecl *MD, SourceManager &SM, - const Expr *EscapeExpr) { - if (const FunctionDecl *CrossTUDecl = getCrossTUDecl(*MD, SM)) - SemaHelper->suggestLifetimeboundToImplicitThis( - WarningScope::CrossTU, cast<CXXMethodDecl>(CrossTUDecl), EscapeExpr); - else - SemaHelper->suggestLifetimeboundToImplicitThis(WarningScope::IntraTU, MD, - EscapeExpr); + void suggestWithScopeForImplicitThis(const CXXMethodDecl *MD, + const Expr *EscapeExpr) { + auto [MethodDecl, Scope] = getCanonicalDeclForAttr(MD); + SemaHelper->suggestLifetimeboundToImplicitThis(Scope, MethodDecl, + EscapeExpr); } void suggestAnnotations() { if (!SemaHelper) return; - SourceManager &SM = AST.getSourceManager(); for (auto [Target, EscapeTarget] : AnnotationWarningsMap) { if (const auto *PVD = Target.dyn_cast<const ParmVarDecl *>()) - suggestWithScopeForParmVar(SemaHelper, PVD, SM, EscapeTarget); + suggestWithScopeForParmVar(PVD, EscapeTarget); else if (const auto *MD = Target.dyn_cast<const CXXMethodDecl *>()) { if (const auto *EscapeExpr = EscapeTarget.dyn_cast<const Expr *>()) - suggestWithScopeForImplicitThis(SemaHelper, MD, SM, EscapeExpr); + suggestWithScopeForImplicitThis(MD, EscapeExpr); else llvm_unreachable("Implicit this can only escape via Expr (return)"); } diff --git a/clang/test/Sema/warn-lifetime-safety-fixits.cpp b/clang/test/Sema/warn-lifetime-safety-fixits.cpp index 88d8bd379de8b..d9c7e8d3f0519 100644 --- a/clang/test/Sema/warn-lifetime-safety-fixits.cpp +++ b/clang/test/Sema/warn-lifetime-safety-fixits.cpp @@ -69,12 +69,11 @@ int *arr_default(int a[2] = nullptr) { return a; } -// FIXME: Iterate over redecls and add [[clang::lifetimebound]] View multi_decl(View a); +// CHECK: :[[@LINE-1]]:17: warning: parameter in intra-TU function should be marked +// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:23-[[@LINE-2]]:23}:" {{\[\[}}clang::lifetimebound]]" View multi_decl(View a); View multi_decl(View a) { - // CHECK: :[[@LINE-1]]:17: warning: parameter in intra-TU function should be marked - // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:23-[[@LINE-2]]:23}:" {{\[\[}}clang::lifetimebound]]" return a; } @@ -145,10 +144,10 @@ struct OutOfLine { OutOfLine() {} ~OutOfLine() {} const OutOfLine &get() const; + // CHECK: :[[@LINE-1]]:31: warning: implicit this in intra-TU function should be marked + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:31-[[@LINE-2]]:31}:" {{\[\[}}clang::lifetimebound]]" }; const OutOfLine &OutOfLine::get() const { - // CHECK: :[[@LINE-1]]:40: warning: implicit this in intra-TU function should be marked - // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:40-[[@LINE-2]]:40}:" {{\[\[}}clang::lifetimebound]]" return *this; } diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp index 973c610eb58ab..5122e634e594f 100644 --- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp +++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp @@ -46,8 +46,8 @@ inline View inline_header_return_view(View a) { // expected-warning {{parameter return a; // expected-note {{param returned here}} } -View redeclared_in_header(View a); -inline View redeclared_in_header(View a) { // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}} +View redeclared_in_header(View a); // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}} +inline View redeclared_in_header(View a) { return a; // expected-note {{param returned here}} } @@ -177,8 +177,8 @@ View reassigned_to_another_parameter( return a; // expected-note {{param returned here}} } -View intra_tu_func_redecl(View a); -View intra_tu_func_redecl(View a) { // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}. +View intra_tu_func_redecl(View a); // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}. +View intra_tu_func_redecl(View a) { return a; // expected-note {{param returned here}} } } @@ -282,25 +282,25 @@ MyObj* return_pointer_by_func(MyObj* a) { // expected-warning {{paramete } // namespace correct_order_inference namespace incorrect_order_inference_view { -View return_view_callee(View a); +View return_view_callee(View a); // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}. View return_view_caller(View a) { // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}. return return_view_callee(a); // expected-note {{param returned here}} } -View return_view_callee(View a) { // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}. +View return_view_callee(View a) { return a; // expected-note {{param returned here}} } } // namespace incorrect_order_inference_view namespace incorrect_order_inference_object { -MyObj* return_object_callee(MyObj* a); +MyObj* return_object_callee(MyObj* a); // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}. MyObj* return_object_caller(MyObj* a) { // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}. return return_object_callee(a); // expected-note {{param returned here}} } -MyObj* return_object_callee(MyObj* a) { // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}. +MyObj* return_object_callee(MyObj* a) { return a; // expected-note {{param returned here}} } } // namespace incorrect_order_inference_object @@ -322,13 +322,13 @@ View inference_top_level_return_stack_view() { } // namespace simple_annotation_inference namespace inference_in_order_with_redecls { -View inference_callee_return_identity(View a); -View inference_callee_return_identity(View a) { // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}. +View inference_callee_return_identity(View a); // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}. +View inference_callee_return_identity(View a) { return a; // expected-note {{param returned here}} } -View inference_caller_forwards_callee(View a); -View inference_caller_forwards_callee(View a) { // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}. +View inference_caller_forwards_callee(View a); // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}. +View inference_caller_forwards_callee(View a) { return inference_callee_return_identity(a); // expected-note {{param returned here}} } >From 8c31e0f4a28d0c2dd91d91e23fd97131f45d2808 Mon Sep 17 00:00:00 2001 From: NeKon69 <[email protected]> Date: Wed, 20 May 2026 17:55:45 +0300 Subject: [PATCH 2/2] revert the change and warn on both crosstu declarations and canonical declarations --- clang/lib/Analysis/LifetimeSafety/Checker.cpp | 43 +++++++++++++++++-- .../Sema/warn-lifetime-safety-suggestions.cpp | 9 ++++ 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp b/clang/lib/Analysis/LifetimeSafety/Checker.cpp index 4b9d195411179..f6b116b2d03a6 100644 --- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp +++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp @@ -353,20 +353,55 @@ class LifetimeChecker { Scope}; } + /// Returns the declaration of a function that is visible across translation + /// units, if such a declaration exists and is different from the definition. + static const FunctionDecl *getCrossTUDecl(const FunctionDecl &FD, + SourceManager &SM) { + if (!FD.isExternallyVisible()) + return nullptr; + const FileID DefinitionFile = SM.getFileID(FD.getLocation()); + for (const FunctionDecl *Redecl : FD.redecls()) + if (SM.getFileID(Redecl->getLocation()) != DefinitionFile) + return Redecl; + + return nullptr; + } + + static const FunctionDecl *getCrossTUDecl(const ParmVarDecl &PVD, + SourceManager &SM) { + if (const auto *FD = dyn_cast<FunctionDecl>(PVD.getDeclContext())) + return getCrossTUDecl(*FD, SM); + return nullptr; + } + void suggestWithScopeForParmVar(const ParmVarDecl *PVD, EscapingTarget EscapeTarget) { if (llvm::isa<const VarDecl *>(EscapeTarget)) return; - auto [Parm, Scope] = getCanonicalDeclForAttr(cast<FunctionDecl>(FD), PVD); - SemaHelper->suggestLifetimeboundToParmVar(Scope, Parm, EscapeTarget); + auto [CanonicalPVD, Scope] = + getCanonicalDeclForAttr(cast<FunctionDecl>(FD), PVD); + const auto *CrossTUFD = getCrossTUDecl(*PVD, AST.getSourceManager()); + const auto *CrossTUParm = + CrossTUFD ? CrossTUFD->getParamDecl(PVD->getFunctionScopeIndex()) + : nullptr; + + SemaHelper->suggestLifetimeboundToParmVar(Scope, CanonicalPVD, + EscapeTarget); + if (CrossTUParm && CrossTUParm != CanonicalPVD) + SemaHelper->suggestLifetimeboundToParmVar(WarningScope::CrossTU, + CrossTUParm, EscapeTarget); } void suggestWithScopeForImplicitThis(const CXXMethodDecl *MD, const Expr *EscapeExpr) { - auto [MethodDecl, Scope] = getCanonicalDeclForAttr(MD); - SemaHelper->suggestLifetimeboundToImplicitThis(Scope, MethodDecl, + auto [CanonicalDecl, Scope] = getCanonicalDeclForAttr(MD); + const auto *CrossTUDecl = getCrossTUDecl(*MD, AST.getSourceManager()); + SemaHelper->suggestLifetimeboundToImplicitThis(Scope, CanonicalDecl, EscapeExpr); + if (CrossTUDecl && CrossTUDecl != CanonicalDecl) + SemaHelper->suggestLifetimeboundToImplicitThis( + WarningScope::CrossTU, cast<CXXMethodDecl>(CrossTUDecl), EscapeExpr); } void suggestAnnotations() { diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp index 5122e634e594f..30d1896450236 100644 --- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp +++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp @@ -31,6 +31,8 @@ struct [[gsl::Pointer()]] View { View definition_before_header(View a); // expected-warning {{parameter in cross-TU function should be marked [[clang::lifetimebound]]}} +View redeclared_before_header_include(View a); // expected-warning {{parameter in cross-TU function should be marked [[clang::lifetimebound]]}} + View return_view_directly(View a); // expected-warning {{parameter in cross-TU function should be marked [[clang::lifetimebound]]}} View conditional_return_view( @@ -67,6 +69,9 @@ struct ReturnThisPointer { //--- test_source.cpp +struct View; +View redeclared_before_header_include(View a); // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}} + #include "test_header.h" #include "Inputs/lifetime-analysis.h" @@ -74,6 +79,10 @@ View definition_before_header(View a) { return a; // expected-note {{param returned here}} } +View redeclared_before_header_include(View a) { + return a; // expected-note 2 {{param returned here}} +} + View return_view_directly(View a) { return a; // expected-note {{param returned here}} } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
