diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp new file mode 100644 index 000000000000..0e8cbc60689a --- /dev/null +++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp @@ -0,0 +1,229 @@ +//===- AnalysisOrderChecker - Print callbacks called ------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This checker prints callbacks that are called during analysis. +// This is required to ensure that callbacks are fired in order +// and do not duplicate or get lost. +// Feel free to extend this checker with any callback you need to check. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ExprCXX.h" +#include "clang/Analysis/CFGStmtMap.h" +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace clang; +using namespace ento; + +namespace { + +class AnalysisOrderChecker + : public Checker< + check::PreStmt<CastExpr>, check::PostStmt<CastExpr>, + check::PreStmt<ArraySubscriptExpr>, + check::PostStmt<ArraySubscriptExpr>, check::PreStmt<CXXNewExpr>, + check::PostStmt<CXXNewExpr>, check::PreStmt<CXXDeleteExpr>, + check::PostStmt<CXXDeleteExpr>, check::PreStmt<CXXConstructExpr>, + check::PostStmt<CXXConstructExpr>, check::PreStmt<OffsetOfExpr>, + check::PostStmt<OffsetOfExpr>, check::PreCall, check::PostCall, + check::EndFunction, check::EndAnalysis, check::NewAllocator, + check::Bind, check::PointerEscape, check::RegionChanges, + check::LiveSymbols, eval::Call> { + + bool isCallbackEnabled(const AnalyzerOptions &Opts, + StringRef CallbackName) const { + return Opts.getCheckerBooleanOption(this, "*") || + Opts.getCheckerBooleanOption(this, CallbackName); + } + + bool isCallbackEnabled(CheckerContext &C, StringRef CallbackName) const { + AnalyzerOptions &Opts = C.getAnalysisManager().getAnalyzerOptions(); + return isCallbackEnabled(Opts, CallbackName); + } + + bool isCallbackEnabled(ProgramStateRef State, StringRef CallbackName) const { + AnalyzerOptions &Opts = State->getStateManager().getOwningEngine() + .getAnalysisManager().getAnalyzerOptions(); + return isCallbackEnabled(Opts, CallbackName); + } + +public: + void checkPreStmt(const CastExpr *CE, CheckerContext &C) const { + if (isCallbackEnabled(C, "PreStmtCastExpr")) + llvm::errs() << "PreStmt<CastExpr> (Kind : " << CE->getCastKindName() + << ")\n"; + } + + void checkPostStmt(const CastExpr *CE, CheckerContext &C) const { + if (isCallbackEnabled(C, "PostStmtCastExpr")) + llvm::errs() << "PostStmt<CastExpr> (Kind : " << CE->getCastKindName() + << ")\n"; + } + + void checkPreStmt(const ArraySubscriptExpr *SubExpr, + CheckerContext &C) const { + if (isCallbackEnabled(C, "PreStmtArraySubscriptExpr")) + llvm::errs() << "PreStmt<ArraySubscriptExpr>\n"; + } + + void checkPostStmt(const ArraySubscriptExpr *SubExpr, + CheckerContext &C) const { + if (isCallbackEnabled(C, "PostStmtArraySubscriptExpr")) + llvm::errs() << "PostStmt<ArraySubscriptExpr>\n"; + } + + void checkPreStmt(const CXXNewExpr *NE, CheckerContext &C) const { + if (isCallbackEnabled(C, "PreStmtCXXNewExpr")) + llvm::errs() << "PreStmt<CXXNewExpr>\n"; + } + + void checkPostStmt(const CXXNewExpr *NE, CheckerContext &C) const { + if (isCallbackEnabled(C, "PostStmtCXXNewExpr")) + llvm::errs() << "PostStmt<CXXNewExpr>\n"; + } + + void checkPreStmt(const CXXDeleteExpr *NE, CheckerContext &C) const { + if (isCallbackEnabled(C, "PreStmtCXXDeleteExpr")) + llvm::errs() << "PreStmt<CXXDeleteExpr>\n"; + } + + void checkPostStmt(const CXXDeleteExpr *NE, CheckerContext &C) const { + if (isCallbackEnabled(C, "PostStmtCXXDeleteExpr")) + llvm::errs() << "PostStmt<CXXDeleteExpr>\n"; + } + + void checkPreStmt(const CXXConstructExpr *NE, CheckerContext &C) const { + if (isCallbackEnabled(C, "PreStmtCXXConstructExpr")) + llvm::errs() << "PreStmt<CXXConstructExpr>\n"; + } + + void checkPostStmt(const CXXConstructExpr *NE, CheckerContext &C) const { + if (isCallbackEnabled(C, "PostStmtCXXConstructExpr")) + llvm::errs() << "PostStmt<CXXConstructExpr>\n"; + } + + void checkPreStmt(const OffsetOfExpr *OOE, CheckerContext &C) const { + if (isCallbackEnabled(C, "PreStmtOffsetOfExpr")) + llvm::errs() << "PreStmt<OffsetOfExpr>\n"; + } + + void checkPostStmt(const OffsetOfExpr *OOE, CheckerContext &C) const { + if (isCallbackEnabled(C, "PostStmtOffsetOfExpr")) + llvm::errs() << "PostStmt<OffsetOfExpr>\n"; + } + + bool evalCall(const CallEvent &Call, CheckerContext &C) const { + if (isCallbackEnabled(C, "EvalCall")) { + llvm::errs() << "EvalCall"; + if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl())) + llvm::errs() << " (" << ND->getQualifiedNameAsString() << ')'; + llvm::errs() << " {argno: " << Call.getNumArgs() << '}'; + llvm::errs() << " [" << Call.getKindAsString() << ']'; + llvm::errs() << '\n'; + return true; + } + return false; + } + + void checkPreCall(const CallEvent &Call, CheckerContext &C) const { + if (isCallbackEnabled(C, "PreCall")) { + llvm::errs() << "PreCall"; + if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl())) + llvm::errs() << " (" << ND->getQualifiedNameAsString() << ')'; + llvm::errs() << " [" << Call.getKindAsString() << ']'; + llvm::errs() << '\n'; + } + } + + void checkPostCall(const CallEvent &Call, CheckerContext &C) const { + if (isCallbackEnabled(C, "PostCall")) { + llvm::errs() << "PostCall"; + if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl())) + llvm::errs() << " (" << ND->getQualifiedNameAsString() << ')'; + llvm::errs() << " [" << Call.getKindAsString() << ']'; + llvm::errs() << '\n'; + } + } + + void checkEndFunction(const ReturnStmt *S, CheckerContext &C) const { + if (isCallbackEnabled(C, "EndFunction")) { + llvm::errs() << "EndFunction\nReturnStmt: " << (S ? "yes" : "no") << "\n"; + if (!S) + return; + + llvm::errs() << "CFGElement: "; + CFGStmtMap *Map = C.getCurrentAnalysisDeclContext()->getCFGStmtMap(); + CFGElement LastElement = Map->getBlock(S)->back(); + + if (LastElement.getAs<CFGStmt>()) + llvm::errs() << "CFGStmt\n"; + else if (LastElement.getAs<CFGAutomaticObjDtor>()) + llvm::errs() << "CFGAutomaticObjDtor\n"; + } + } + + void checkEndAnalysis(ExplodedGraph &G, BugReporter &BR, + ExprEngine &Eng) const { + if (isCallbackEnabled(BR.getAnalyzerOptions(), "EndAnalysis")) + llvm::errs() << "EndAnalysis\n"; + } + + void checkNewAllocator(const CXXAllocatorCall &Call, + CheckerContext &C) const { + if (isCallbackEnabled(C, "NewAllocator")) + llvm::errs() << "NewAllocator\n"; + } + + void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &C) const { + if (isCallbackEnabled(C, "Bind")) + llvm::errs() << "Bind\n"; + } + + void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SymReaper) const { + if (isCallbackEnabled(State, "LiveSymbols")) + llvm::errs() << "LiveSymbols\n"; + } + + ProgramStateRef + checkRegionChanges(ProgramStateRef State, + const InvalidatedSymbols *Invalidated, + ArrayRef<const MemRegion *> ExplicitRegions, + ArrayRef<const MemRegion *> Regions, + const LocationContext *LCtx, const CallEvent *Call) const { + if (isCallbackEnabled(State, "RegionChanges")) + llvm::errs() << "RegionChanges\n"; + return State; + } + + ProgramStateRef checkPointerEscape(ProgramStateRef State, + const InvalidatedSymbols &Escaped, + const CallEvent *Call, + PointerEscapeKind Kind) const { + if (isCallbackEnabled(State, "PointerEscape")) + llvm::errs() << "PointerEscape\n"; + return State; + } +}; +} // end anonymous namespace + +//===----------------------------------------------------------------------===// +// Registration. +//===----------------------------------------------------------------------===// + +void ento::registerAnalysisOrderChecker(CheckerManager &mgr) { + mgr.registerChecker<AnalysisOrderChecker>(); +} + +bool ento::shouldRegisterAnalysisOrderChecker(const CheckerManager &mgr) { + return true; +} |