================
@@ -0,0 +1,273 @@
+#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, SymbolRef, LifetimeSourceSet)
+
+REGISTER_MAP_WITH_PROGRAMSTATE(LifetimeBoundMapVal, const MemRegion *,
+                               LifetimeSourceSet)
+
+namespace {
+class LifetimeAnnotations
+    : public Checker<check::PostCall, check::EndFunction, eval::Call> {
+public:
+  void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
+  void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
+                  const char *Sep) const override;
+  bool evalCall(const CallEvent &Call, CheckerContext &C) const;
+  void analyzerLifetimeBound(const CallEvent &Call, const CallExpr *,
+                             CheckerContext &C) const;
+  ProgramStateRef bindValues(ProgramStateRef State, SymbolRef RetValSym,
+                             SVal RetVal, const MemRegion *Source) const;
+  bool isSourceDangle(const MemRegion *Source, ProgramStateRef State,
+                      CheckerContext &C) const;
+  void reportDanglingSource(const MemRegion *Region, ExplodedNode *N,
+                            CheckerContext &C) const;
+
+  template <typename MapTy, typename KeyTy>
+  void checkReturnedBorrower(const MapTy &Map, const KeyTy RetKey,
+                             ProgramStateRef State, ExplodedNode *N,
+                             CheckerContext &C) const;
+  void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
+
+  const BugType BugMsg{this, "LifetimeAnnotations", "LifetimeBound"};
+
+  using FnCheck = void (LifetimeAnnotations::*)(const CallEvent &Call,
+                                                const CallExpr *,
+                                                CheckerContext &C) const;
+
+  const CallDescriptionMap<FnCheck> Callbacks = {
+      {{CDM::SimpleFunc, {"clang_analyzer_lifetime_bound"}},
+       &LifetimeAnnotations::analyzerLifetimeBound},
+  };
+};
+
+} // namespace
+
+ProgramStateRef LifetimeAnnotations::bindValues(ProgramStateRef State,
+                                                SymbolRef RetValSym,
+                                                SVal RetVal,
+                                                const MemRegion *Source) const 
{
+  LifetimeSourceSet::Factory &F =
+      State->getStateManager().get_context<LifetimeSourceSet>();
+
+  if (RetValSym) {
+    const LifetimeSourceSet *LBSet = State->get<LifetimeBoundMap>(RetValSym);
+    LifetimeSourceSet Set = LBSet ? *LBSet : F.getEmptySet();
+    Set = F.add(Set, Source);
+    State = State->set<LifetimeBoundMap>(RetValSym, Set);
+  } else if (const MemRegion *RetValRegion = RetVal.getAsRegion()) {
+    const LifetimeSourceSet *LBValSet =
+        State->get<LifetimeBoundMapVal>(RetValRegion);
+    LifetimeSourceSet Set = LBValSet ? *LBValSet : F.getEmptySet();
+    Set = F.add(Set, Source);
+    State = State->set<LifetimeBoundMapVal>(RetValRegion, Set);
+  }
+  return State;
+}
+
+void LifetimeAnnotations::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();
+  SymbolRef RetValSym = RetVal.getAsSymbol(/*IncludeBaseRegions=*/true);
+
+  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, RetValSym, RetVal, ArgValRegion);
+    }
+  }
+
+  if (const auto *IC = dyn_cast<CXXInstanceCall>(&Call)) {
+    if (clang::lifetimes::implicitObjectParamIsLifetimeBound(FD)) {
----------------
Xazax-hun wrote:

I wonder if you already need the `clang::` qualifier as you have a using 
namespace at the top.

```suggestion
    if (lifetimes::implicitObjectParamIsLifetimeBound(FD)) {
```

https://github.com/llvm/llvm-project/pull/200145
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to