Author: Benedek Kaibas Date: 2026-07-12T13:58:52+01:00 New Revision: f99f2a582e947af3f20580fa2674ca0c6bde1b2c
URL: https://github.com/llvm/llvm-project/commit/f99f2a582e947af3f20580fa2674ca0c6bde1b2c DIFF: https://github.com/llvm/llvm-project/commit/f99f2a582e947af3f20580fa2674ca0c6bde1b2c.diff LOG: [analyzer] Implement LifetimeModeling checker and refactor UseAfterLifetimeEnd (#205951) Added: clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.h Modified: clang/include/clang/StaticAnalyzer/Checkers/Checkers.td clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt clang/lib/StaticAnalyzer/Checkers/UseAfterLifetimeEnd.cpp clang/test/Analysis/debug-lifetime-bound.cpp clang/test/Analysis/lifetime-bound.cpp Removed: ################################################################################ diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index 949e20d1fb98d..0f8b3bb1e1d18 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -795,9 +795,15 @@ def SmartPtrChecker: Checker<"SmartPtr">, Dependencies<[SmartPtrModeling]>, Documentation<HasDocumentation>; +def LifetimeModeling : Checker<"LifetimeModeling">, + HelpText<"Model lifetime annotations for other checkers">, + Documentation<NotDocumented>, + Hidden; + def UseAfterLifetimeEnd : Checker<"UseAfterLifetimeEnd">, HelpText<"Check for uses of references or pointers that " "outlive their bound object">, + Dependencies<[LifetimeModeling]>, Documentation<NotDocumented>; } // end: "alpha.cplusplus" @@ -1588,10 +1594,9 @@ def CheckerDocumentationChecker : Checker<"CheckerDocumentation">, HelpText<"Defines an empty checker callback for all possible handlers.">, Documentation<NotDocumented>; -def DebugUseAfterLifetimeEnd : Checker<"DebugUseAfterLifetimeEnd">, - HelpText<"Prints the bindings recorded by the UseAfterLifetimeEnd checker. " - "Use with clang_analyzer_dumpLifetimeOriginsOf().">, - WeakDependencies<[UseAfterLifetimeEnd]>, +def DebugLifetimeModeling : Checker<"DebugLifetimeModeling">, + HelpText<"Dump the set of regions the bound variable originates from">, + Dependencies<[LifetimeModeling]>, Documentation<NotDocumented>; } // end "debug" diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt index 46c0c36fda736..8f61b7d88e8d2 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt +++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt @@ -55,6 +55,7 @@ add_clang_library(clangStaticAnalyzerCheckers IteratorModeling.cpp IteratorRangeChecker.cpp IvarInvalidationChecker.cpp + LifetimeModeling.cpp LLVMConventionsChecker.cpp LocalizationChecker.cpp MacOSKeychainAPIChecker.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp new file mode 100644 index 0000000000000..a2f58e0710801 --- /dev/null +++ b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp @@ -0,0 +1,214 @@ +#include "LifetimeModeling.h" +#include "clang/AST/Attr.h" +#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeAnnotations.h" +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "llvm/Support/raw_ostream.h" + +using namespace clang; +using namespace ento; + +REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(LifetimeSourceSet, const MemRegion *) +REGISTER_MAP_WITH_PROGRAMSTATE(LifetimeBoundMap, SVal, LifetimeSourceSet) + +namespace { + +class LifetimeModeling : public Checker<check::PostCall, check::DeadSymbols> { +public: + void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, + const char *Sep) const override; + void checkPostCall(const CallEvent &Call, CheckerContext &C) const; + void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; +}; + +} // namespace + +static bool isDanglingStackSource(const MemRegion *Source, + ProgramStateRef State, CheckerContext &C) { + // FIXME: The checker currently handles stack-region sources. Other + // region kinds require separate methodology. For example, heap + // regions do not go out of scope at the end of a stack frame, so + // in order to detect those type of dangling sources the function + // needs to be expanded to an event-driven approach as well. + if (const auto *StackSpace = + Source->getMemorySpaceAs<StackSpaceRegion>(State)) { + const StackFrame *SF = StackSpace->getStackFrame(); + const StackFrame *CurrentSF = C.getStackFrame(); + if (SF == CurrentSF || !SF->isParentOf(CurrentSF)) + return true; + } + return false; +} + +std::vector<const MemRegion *> lifetime_modeling::getDanglingRegionsAfterReturn( + SVal Val, ProgramStateRef State, CheckerContext &C) { + std::vector<const MemRegion *> Regions; + if (auto *SourceSet = State->get<LifetimeBoundMap>(Val)) { + for (const MemRegion *Region : *SourceSet) { + if (isDanglingStackSource(Region, State, C)) + Regions.push_back(Region); + } + } + return Regions; +} + +static ProgramStateRef bindSource(ProgramStateRef State, SVal RetVal, + const MemRegion *Source) { + LifetimeSourceSet::Factory &F = State->get_context<LifetimeSourceSet>(); + const LifetimeSourceSet *LSet = State->get<LifetimeBoundMap>(RetVal); + + LifetimeSourceSet Set = LSet ? *LSet : F.getEmptySet(); + Set = F.add(Set, Source); + State = State->set<LifetimeBoundMap>(RetVal, Set); + return State; +} + +void LifetimeModeling::checkPostCall(const CallEvent &Call, + CheckerContext &C) const { + ProgramStateRef State = C.getState(); + + const auto *FC = dyn_cast<AnyFunctionCall>(&Call); + if (!FC) + return; + + const FunctionDecl *FD = FC->getDecl(); + if (!FD) + return; + + SVal RetVal = Call.getReturnValue(); + + for (const ParmVarDecl *PVD : FD->parameters()) { + if (PVD->hasAttr<LifetimeBoundAttr>()) { + unsigned Idx = PVD->getFunctionScopeIndex(); + SVal Arg = Call.getArgSVal(Idx); + if (const MemRegion *ArgValRegion = Arg.getAsRegion()) + State = bindSource(State, RetVal, ArgValRegion); + } + } + + const auto *IC = dyn_cast<CXXInstanceCall>(&Call); + if (IC && lifetimes::implicitObjectParamIsLifetimeBound(FD)) { + if (const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion()) + State = bindSource(State, RetVal, ThisRegion); + } + C.addTransition(State); +} + +void LifetimeModeling::checkDeadSymbols(SymbolReaper &SymReaper, + CheckerContext &C) const { + ProgramStateRef State = C.getState(); + LifetimeBoundMapTy LBMap = State->get<LifetimeBoundMap>(); + + for (SVal Val : llvm::make_first_range(LBMap)) { + if (const auto *R = Val.getAsRegion(); R && SymReaper.isLiveRegion(R)) + continue; + + if (SymbolRef S = Val.getAsSymbol(/*IncludeBaseRegions=*/true); + S && SymReaper.isLive(S)) + continue; + + State = State->remove<LifetimeBoundMap>(Val); + } + C.addTransition(State); +} + +void LifetimeModeling::printState(raw_ostream &Out, ProgramStateRef State, + const char *NL, const char *Sep) const { + auto LBMap = State->get<LifetimeBoundMap>(); + + if (LBMap.isEmpty()) + return; + + Out << Sep << "LifetimeBound bindings:" << NL; + for (auto &&[OriginSym, SourceSet] : LBMap) { + for (const auto *Region : SourceSet) + Out << " Origin " << OriginSym << " contains Loan " << Region << NL; + } +} + +// FIXME: Eventually move the debug checker to its own source file once +// it has more functionality. +namespace { +class DebugLifetimeModeling : public Checker<eval::Call> { +public: + bool evalCall(const CallEvent &Call, CheckerContext &C) const; + void analyzerDumpLifetimeOriginsOf(const CallEvent &Call, + CheckerContext &C) const; + const BugType BugMsg{this, "DebugLifetimeModeling", "DebugLifetimeModeling"}; + using FnCheck = void (DebugLifetimeModeling::*)(const CallEvent &Call, + CheckerContext &C) const; + + const CallDescriptionMap<FnCheck> Callbacks = { + {{CDM::SimpleFunc, {"clang_analyzer_dumpLifetimeOriginsOf"}}, + &DebugLifetimeModeling::analyzerDumpLifetimeOriginsOf}, + }; +}; + +} // namespace + +bool DebugLifetimeModeling::evalCall(const CallEvent &Call, + CheckerContext &C) const { + if (!isa_and_nonnull<CallExpr>(Call.getOriginExpr())) + return false; + + const FnCheck *Handler = Callbacks.lookup(Call); + if (!Handler) + return false; + + (this->*(*Handler))(Call, C); + return true; +} + +void DebugLifetimeModeling::analyzerDumpLifetimeOriginsOf( + const CallEvent &Call, CheckerContext &C) const { + ProgramStateRef State = C.getState(); + + if (Call.getNumArgs() != 1) { + if (ExplodedNode *N = C.generateNonFatalErrorNode()) { + auto BR = std::make_unique<PathSensitiveBugReport>( + BugMsg, + "clang_analyzer_dumpLifetimeOriginsOf requires exactly 1 argument", + N); + C.emitReport(std::move(BR)); + } + return; + } + + SVal ArgSVal = Call.getArgSVal(0); + const LifetimeSourceSet *SourceSet = State->get<LifetimeBoundMap>(ArgSVal); + + if (!SourceSet) + return; + + if (ExplodedNode *N = C.generateNonFatalErrorNode()) { + llvm::SmallVector<std::string> RegionNames = + to_vector(map_range(llvm::make_pointee_range(*SourceSet), + std::mem_fn(&MemRegion::getString))); + llvm::sort(RegionNames); + + llvm::SmallString<128> Str; + llvm::raw_svector_ostream OS(Str); + OS << " Origin " << ArgSVal << " bound to "; + llvm::interleaveComma(RegionNames, OS); + C.emitReport(std::make_unique<PathSensitiveBugReport>(BugMsg, OS.str(), N)); + } +} + +void ento::registerLifetimeModeling(CheckerManager &Mgr) { + Mgr.registerChecker<LifetimeModeling>(); +} + +bool ento::shouldRegisterLifetimeModeling(const CheckerManager &Mgr) { + return true; +} + +void ento::registerDebugLifetimeModeling(CheckerManager &Mgr) { + Mgr.registerChecker<DebugLifetimeModeling>(); +} + +bool ento::shouldRegisterDebugLifetimeModeling(const CheckerManager &Mgr) { + return true; +} diff --git a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.h b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.h new file mode 100644 index 0000000000000..e13942eb1856b --- /dev/null +++ b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.h @@ -0,0 +1,18 @@ +#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_LIFETIMEMODELING_H +#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_LIFETIMEMODELING_H + +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include <vector> + +namespace clang::ento::lifetime_modeling { +/// Returns the set of lifetime sources bound to \p Source that are dangling +/// stack regions. +std::vector<const MemRegion *> +getDanglingRegionsAfterReturn(SVal Source, ProgramStateRef State, + CheckerContext &C); + +} // namespace clang::ento::lifetime_modeling + +#endif // LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_LIFETIMEMODELING_H diff --git a/clang/lib/StaticAnalyzer/Checkers/UseAfterLifetimeEnd.cpp b/clang/lib/StaticAnalyzer/Checkers/UseAfterLifetimeEnd.cpp index db776f1c1c49d..6a2933900c01f 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UseAfterLifetimeEnd.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UseAfterLifetimeEnd.cpp @@ -1,123 +1,27 @@ -#include "clang/AST/Attr.h" -#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeAnnotations.h" +#include "LifetimeModeling.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/Checker.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" -#include "llvm/Support/raw_ostream.h" using namespace clang; using namespace ento; -REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(LifetimeSourceSet, const MemRegion *) -REGISTER_MAP_WITH_PROGRAMSTATE(LifetimeBoundMap, SVal, LifetimeSourceSet) - namespace { -class UseAfterLifetimeEnd - : public Checker<check::PostCall, check::EndFunction, check::DeadSymbols> { +class UseAfterLifetimeEnd : public Checker<check::EndFunction> { public: - void checkPostCall(const CallEvent &Call, CheckerContext &C) const; - void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, - const char *Sep) const override; - void reportDanglingSource(const MemRegion *Region, ExplodedNode *N, + void reportDanglingSource(const MemRegion *Source, ExplodedNode *N, CheckerContext &C) const; - void checkReturnedBorrower(SVal Val, ProgramStateRef State, - CheckerContext &C) const; void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const; - void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; const BugType BugMsg{this, "UseAfterLifetimeEnd", "LifetimeBound"}; }; } // namespace -static ProgramStateRef bindValues(ProgramStateRef State, SVal RetVal, - const MemRegion *Source) { - LifetimeSourceSet::Factory &F = State->get_context<LifetimeSourceSet>(); - - const LifetimeSourceSet *LSet = State->get<LifetimeBoundMap>(RetVal); - LifetimeSourceSet Set = LSet ? *LSet : F.getEmptySet(); - Set = F.add(Set, Source); - State = State->set<LifetimeBoundMap>(RetVal, Set); - return State; -} - -void UseAfterLifetimeEnd::checkPostCall(const CallEvent &Call, - CheckerContext &C) const { - ProgramStateRef State = C.getState(); - - const auto *FC = dyn_cast<AnyFunctionCall>(&Call); - if (!FC) - return; - - const FunctionDecl *FD = FC->getDecl(); - if (!FD) - return; - - SVal RetVal = Call.getReturnValue(); - - for (const ParmVarDecl *PVD : FD->parameters()) { - if (PVD->hasAttr<LifetimeBoundAttr>()) { - unsigned Idx = PVD->getFunctionScopeIndex(); - SVal Arg = Call.getArgSVal(Idx); - if (const MemRegion *ArgValRegion = Arg.getAsRegion()) - State = bindValues(State, RetVal, ArgValRegion); - } - } - - if (const auto *IC = dyn_cast<CXXInstanceCall>(&Call)) { - if (lifetimes::implicitObjectParamIsLifetimeBound(FD)) { - if (const MemRegion *AttrRegion = IC->getCXXThisVal().getAsRegion()) { - State = bindValues(State, RetVal, AttrRegion); - } - } - } - C.addTransition(State); -} - -static bool hasDanglingSource(const MemRegion *Source, ProgramStateRef State, - CheckerContext &C) { - // FIXME: The checker currently handles stack-region sources. Other - // region kinds require separate methodology. For example, heap - // regions do not go out of scope at the end of a stack frame, so - // in order to detect those type of dangling sources the function - // needs to be expanded to an event-driven approach as well. - if (const auto *StackSpace = - Source->getMemorySpaceAs<StackSpaceRegion>(State)) { - const StackFrame *SF = StackSpace->getStackFrame(); - const StackFrame *CurrentSF = C.getStackFrame(); - if (SF == CurrentSF || !SF->isParentOf(CurrentSF)) - return true; - } - return false; -} - -void UseAfterLifetimeEnd::checkReturnedBorrower(SVal Val, ProgramStateRef State, - CheckerContext &C) const { - if (auto *SourceSet = State->get<LifetimeBoundMap>(Val)) { - ExplodedNode *N = nullptr; - for (const MemRegion *Region : *SourceSet) { - if (hasDanglingSource(Region, State, C)) { - if (!N) - N = C.generateNonFatalErrorNode(); - if (!N) - return; - reportDanglingSource(Region, N, C); - } - } - } -} - void UseAfterLifetimeEnd::checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const { if (!RS) return; ProgramStateRef State = C.getState(); - auto LBMap = State->get<LifetimeBoundMap>(); - - if (LBMap.isEmpty()) - return; const Expr *RetExpr = RS->getRetValue(); if (!RetExpr) @@ -125,122 +29,30 @@ void UseAfterLifetimeEnd::checkEndFunction(const ReturnStmt *RS, RetExpr = RetExpr->IgnoreParens(); SVal RetVal = C.getSVal(RetExpr); - checkReturnedBorrower(RetVal, State, C); + + std::vector<const MemRegion *> RetValRegion = + lifetime_modeling::getDanglingRegionsAfterReturn(RetVal, State, C); + if (RetValRegion.empty()) + return; + + if (ExplodedNode *N = + C.generateNonFatalErrorNode(State, C.getPredecessor())) { + for (const MemRegion *R : RetValRegion) + reportDanglingSource(R, N, C); + } } -void UseAfterLifetimeEnd::reportDanglingSource(const MemRegion *Region, +void UseAfterLifetimeEnd::reportDanglingSource(const MemRegion *Source, ExplodedNode *N, CheckerContext &C) const { auto BR = std::make_unique<PathSensitiveBugReport>( BugMsg, - (llvm::Twine("Returning value bound to '") + Region->getString() + + (llvm::Twine("Returning value bound to '") + Source->getString() + "' that will go out of scope"), N); C.emitReport(std::move(BR)); } -void UseAfterLifetimeEnd::checkDeadSymbols(SymbolReaper &SymReaper, - CheckerContext &C) const { - ProgramStateRef State = C.getState(); - LifetimeBoundMapTy LBMap = State->get<LifetimeBoundMap>(); - - for (SVal Val : llvm::make_first_range(LBMap)) { - if (const MemRegion *ValRegion = Val.getAsRegion()) { - if (!SymReaper.isLiveRegion(ValRegion)) - State = State->remove<LifetimeBoundMap>(Val); - } else if (SymbolRef ValRef = - Val.getAsSymbol(/*IncludeBaseRegions=*/true)) { - if (!SymReaper.isLive(ValRef)) - State = State->remove<LifetimeBoundMap>(Val); - } - } - - C.addTransition(State); -} - -void UseAfterLifetimeEnd::printState(raw_ostream &Out, ProgramStateRef State, - const char *NL, const char *Sep) const { - auto LBMap = State->get<LifetimeBoundMap>(); - - if (LBMap.isEmpty()) - return; - - Out << Sep << "LifetimeBound bindings:" << NL; - for (auto &&[OriginSym, SourceSet] : LBMap) { - for (const auto *Region : SourceSet) - Out << " Origin " << OriginSym << " contains Loan " << Region << NL; - } -} - -namespace { -class DebugUseAfterLifetimeEnd : public Checker<eval::Call> { -public: - bool evalCall(const CallEvent &Call, CheckerContext &C) const; - void analyzerDumpLifetimeOriginsOf(const CallEvent &Call, - CheckerContext &C) const; - - const BugType BugMsg{this, "DebugUseAfterLifetimeEnd", - "DebugUseAfterLifetimeEnd"}; - using FnCheck = void (DebugUseAfterLifetimeEnd::*)(const CallEvent &Call, - CheckerContext &C) const; - - const CallDescriptionMap<FnCheck> Callbacks = { - {{CDM::SimpleFunc, {"clang_analyzer_dumpLifetimeOriginsOf"}}, - &DebugUseAfterLifetimeEnd::analyzerDumpLifetimeOriginsOf}, - }; -}; - -} // namespace - -bool DebugUseAfterLifetimeEnd::evalCall(const CallEvent &Call, - CheckerContext &C) const { - const auto *CE = dyn_cast_if_present<CallExpr>(Call.getOriginExpr()); - if (!CE) - return false; - - const FnCheck *Handler = Callbacks.lookup(Call); - if (!Handler) - return false; - - (this->*(*Handler))(Call, C); - return true; -} - -void DebugUseAfterLifetimeEnd::analyzerDumpLifetimeOriginsOf( - const CallEvent &Call, CheckerContext &C) const { - ProgramStateRef State = C.getState(); - - if (Call.getNumArgs() != 1) { - if (ExplodedNode *N = C.generateNonFatalErrorNode()) { - auto BR = std::make_unique<PathSensitiveBugReport>( - BugMsg, - "clang_analyzer_dumpLifetimeOriginsOf requires exactly 1 argument", - N); - C.emitReport(std::move(BR)); - } - return; - } - - SVal ArgSVal = Call.getArgSVal(0); - const LifetimeSourceSet *SourceSet = State->get<LifetimeBoundMap>(ArgSVal); - - if (!SourceSet) - return; - - if (ExplodedNode *N = C.generateNonFatalErrorNode()) { - llvm::SmallVector<std::string> RegionNames = - to_vector(map_range(llvm::make_pointee_range(*SourceSet), - std::mem_fn(&MemRegion::getString))); - llvm::sort(RegionNames); - - llvm::SmallString<128> Str; - llvm::raw_svector_ostream OS(Str); - OS << " Origin " << ArgSVal << " bound to "; - llvm::interleaveComma(RegionNames, OS); - C.emitReport(std::make_unique<PathSensitiveBugReport>(BugMsg, OS.str(), N)); - } -} - void ento::registerUseAfterLifetimeEnd(CheckerManager &Mgr) { Mgr.registerChecker<UseAfterLifetimeEnd>(); } @@ -248,11 +60,3 @@ void ento::registerUseAfterLifetimeEnd(CheckerManager &Mgr) { bool ento::shouldRegisterUseAfterLifetimeEnd(const CheckerManager &Mgr) { return true; } - -void ento::registerDebugUseAfterLifetimeEnd(CheckerManager &Mgr) { - Mgr.registerChecker<DebugUseAfterLifetimeEnd>(); -} - -bool ento::shouldRegisterDebugUseAfterLifetimeEnd(const CheckerManager &Mgr) { - return true; -} diff --git a/clang/test/Analysis/debug-lifetime-bound.cpp b/clang/test/Analysis/debug-lifetime-bound.cpp index 8ef704195dcc6..b52d23c88071d 100644 --- a/clang/test/Analysis/debug-lifetime-bound.cpp +++ b/clang/test/Analysis/debug-lifetime-bound.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UseAfterLifetimeEnd,debug.DebugUseAfterLifetimeEnd -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UseAfterLifetimeEnd,debug.DebugLifetimeModeling -verify %s // expected-no-diagnostics diff --git a/clang/test/Analysis/lifetime-bound.cpp b/clang/test/Analysis/lifetime-bound.cpp index e99299b5d03bf..f8519b76798fd 100644 --- a/clang/test/Analysis/lifetime-bound.cpp +++ b/clang/test/Analysis/lifetime-bound.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UseAfterLifetimeEnd,debug.DebugUseAfterLifetimeEnd \ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UseAfterLifetimeEnd,debug.DebugLifetimeModeling \ // RUN: -analyzer-config cfg-lifetime=true -verify %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UseAfterLifetimeEnd,debug.DebugUseAfterLifetimeEnd \ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UseAfterLifetimeEnd,debug.DebugLifetimeModeling \ // RUN: -analyzer-config c++-container-inlining=false -analyzer-config cfg-lifetime=true -verify %s struct A {}; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
