================
@@ -0,0 +1,163 @@
+#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"
+#include "AllocationState.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeAnnotations.h"
+
+
+using namespace clang;
+using namespace ento;
+using namespace clang::lifetimes;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(LifetimeBoundMap, SymbolRef,
+ const MemRegion *);
+REGISTER_MAP_WITH_PROGRAMSTATE(LifetimeBoundMapVal, const MemRegion *, const
MemRegion *);
+
+
+class LifetimeAnnotations : public Checker<check::PostCall, 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;
+
+ const BugType BugMsg{this, "LifetimeAnnotations", "LifetimeBound"};
+};
+
+typedef void (LifetimeAnnotations::*FnCheck)(const CallEvent &Call, const
CallExpr *,
+ CheckerContext &) const;
+CallDescriptionMap<FnCheck> Callbacks = {
+ {{CDM::SimpleFunc, {"clang_analyzer_lifetime_bound"}},
+ &LifetimeAnnotations::analyzerLifetimeBound},
+};
+
+void LifetimeAnnotations::checkPostCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+
+ const auto *FC = dyn_cast_if_present<AnyFunctionCall>(&Call);
+ if (!FC)
+ return;
+
+ const FunctionDecl *FD = FC->getDecl();
+ if (!FD)
+ return;
+
+ SVal RetVal = Call.getReturnValue();
+ SymbolRef RetValSym = RetVal.getAsSymbol(/*IncludeBaseRegions=*/true);
+ unsigned LBParamIdx = FD->getNumParams();
+ // FIXME: Use range based for loop instead. Currently that would require
+ // to also change how we create ArgVal which would need a new logic to
+ // be implemented.
+ for (unsigned I = 0, E = FD->getNumParams(); I != E; I++) {
+ if (FD->getParamDecl(I)->hasAttr<LifetimeBoundAttr>()) {
+ LBParamIdx = I;
+ // FIXME: If multiple parameters are annotated this logic would
+ // prevent the analyzer to read after the first parameter.
+ break;
+ }
+ }
+
+ if (LBParamIdx != FD->getNumParams()) {
+ SVal ArgVal = Call.getArgSVal(LBParamIdx);
+ if (const MemRegion *ArgValRegion = ArgVal.getAsRegion()) {
+ if (RetValSym)
+ State = State->set<LifetimeBoundMap>(RetValSym, ArgValRegion);
+ if (const MemRegion *RetValRegion = RetVal.getAsRegion())
----------------
isuckatcs wrote:
`else if`? Do we want to insert it into both maps? If yes, we could probably
keep the 1st map only.
https://github.com/llvm/llvm-project/pull/200145
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits