================
@@ -0,0 +1,213 @@
+#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);
----------------
benedekaibas wrote:
Thank for catching it, forgot to adding it back after the refactor: Done here:
[3cbe0c7](https://github.com/llvm/llvm-project/pull/205951/commits/3cbe0c7e6ad9ebb387fb2dbf890a57b4d40a58e1)
https://github.com/llvm/llvm-project/pull/205951
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits