#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "PrettyStackTraceLocationContext.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/Type.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/ConstructionContext.h"
#include "clang/Analysis/ProgramPoint.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/JsonSupport.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/ImmutableSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DOTGraphTraits.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
usingnamespaceclang;
usingnamespaceento;
#define DEBUG_TYPE …
STATISTIC(NumRemoveDeadBindings,
"The # of times RemoveDeadBindings is called");
STATISTIC(NumMaxBlockCountReached,
"The # of aborted paths due to reaching the maximum block count in "
"a top level function");
STATISTIC(NumMaxBlockCountReachedInInlined,
"The # of aborted paths due to reaching the maximum block count in "
"an inlined function");
STATISTIC(NumTimesRetriedWithoutInlining,
"The # of times we re-evaluated a call without inlining");
namespace {
class ConstructedObjectKey { … };
}
ObjectsUnderConstructionMap;
REGISTER_TRAIT_WITH_PROGRAMSTATE(…)
IndexOfElementToConstructMap;
REGISTER_TRAIT_WITH_PROGRAMSTATE(…)
PendingInitLoopMap;
REGISTER_TRAIT_WITH_PROGRAMSTATE(…)
PendingArrayDestructionMap;
REGISTER_TRAIT_WITH_PROGRAMSTATE(…)
static const char* TagProviderName = …;
ExprEngine::ExprEngine(cross_tu::CrossTranslationUnitContext &CTU,
AnalysisManager &mgr, SetOfConstDecls *VisitedCalleesIn,
FunctionSummariesTy *FS, InliningModes HowToInlineIn)
: … { … }
ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) { … }
ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(
ProgramStateRef State, const LocationContext *LC,
const Expr *InitWithAdjustments, const Expr *Result,
const SubRegion **OutRegionWithAdjustments) { … }
ProgramStateRef ExprEngine::setIndexOfElementToConstruct(
ProgramStateRef State, const CXXConstructExpr *E,
const LocationContext *LCtx, unsigned Idx) { … }
std::optional<unsigned>
ExprEngine::getPendingInitLoop(ProgramStateRef State, const CXXConstructExpr *E,
const LocationContext *LCtx) { … }
ProgramStateRef ExprEngine::removePendingInitLoop(ProgramStateRef State,
const CXXConstructExpr *E,
const LocationContext *LCtx) { … }
ProgramStateRef ExprEngine::setPendingInitLoop(ProgramStateRef State,
const CXXConstructExpr *E,
const LocationContext *LCtx,
unsigned Size) { … }
std::optional<unsigned>
ExprEngine::getIndexOfElementToConstruct(ProgramStateRef State,
const CXXConstructExpr *E,
const LocationContext *LCtx) { … }
ProgramStateRef
ExprEngine::removeIndexOfElementToConstruct(ProgramStateRef State,
const CXXConstructExpr *E,
const LocationContext *LCtx) { … }
std::optional<unsigned>
ExprEngine::getPendingArrayDestruction(ProgramStateRef State,
const LocationContext *LCtx) { … }
ProgramStateRef ExprEngine::setPendingArrayDestruction(
ProgramStateRef State, const LocationContext *LCtx, unsigned Idx) { … }
ProgramStateRef
ExprEngine::removePendingArrayDestruction(ProgramStateRef State,
const LocationContext *LCtx) { … }
ProgramStateRef
ExprEngine::addObjectUnderConstruction(ProgramStateRef State,
const ConstructionContextItem &Item,
const LocationContext *LC, SVal V) { … }
std::optional<SVal>
ExprEngine::getObjectUnderConstruction(ProgramStateRef State,
const ConstructionContextItem &Item,
const LocationContext *LC) { … }
ProgramStateRef
ExprEngine::finishObjectConstruction(ProgramStateRef State,
const ConstructionContextItem &Item,
const LocationContext *LC) { … }
ProgramStateRef ExprEngine::elideDestructor(ProgramStateRef State,
const CXXBindTemporaryExpr *BTE,
const LocationContext *LC) { … }
ProgramStateRef
ExprEngine::cleanupElidedDestructor(ProgramStateRef State,
const CXXBindTemporaryExpr *BTE,
const LocationContext *LC) { … }
bool ExprEngine::isDestructorElided(ProgramStateRef State,
const CXXBindTemporaryExpr *BTE,
const LocationContext *LC) { … }
bool ExprEngine::areAllObjectsFullyConstructed(ProgramStateRef State,
const LocationContext *FromLC,
const LocationContext *ToLC) { … }
ProgramStateRef ExprEngine::processAssume(ProgramStateRef state,
SVal cond, bool assumption) { … }
ProgramStateRef
ExprEngine::processRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> Explicits,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call) { … }
static void
printObjectsUnderConstructionJson(raw_ostream &Out, ProgramStateRef State,
const char *NL, const LocationContext *LCtx,
unsigned int Space = 0, bool IsDot = false) { … }
static void printIndicesOfElementsToConstructJson(
raw_ostream &Out, ProgramStateRef State, const char *NL,
const LocationContext *LCtx, unsigned int Space = 0, bool IsDot = false) { … }
static void printPendingInitLoopJson(raw_ostream &Out, ProgramStateRef State,
const char *NL,
const LocationContext *LCtx,
unsigned int Space = 0,
bool IsDot = false) { … }
static void
printPendingArrayDestructionsJson(raw_ostream &Out, ProgramStateRef State,
const char *NL, const LocationContext *LCtx,
unsigned int Space = 0, bool IsDot = false) { … }
template <typename Trait, typename Printer, typename... Args>
static void printStateTraitWithLocationContextJson(
raw_ostream &Out, ProgramStateRef State, const LocationContext *LCtx,
const char *NL, unsigned int Space, bool IsDot,
const char *jsonPropertyName, Printer printer, Args &&...args) { … }
void ExprEngine::printJson(raw_ostream &Out, ProgramStateRef State,
const LocationContext *LCtx, const char *NL,
unsigned int Space, bool IsDot) const { … }
void ExprEngine::processEndWorklist() { … }
void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred,
unsigned StmtIdx, NodeBuilderContext *Ctx) { … }
static bool shouldRemoveDeadBindings(AnalysisManager &AMgr,
const Stmt *S,
const ExplodedNode *Pred,
const LocationContext *LC) { … }
void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
const Stmt *ReferenceStmt,
const LocationContext *LC,
const Stmt *DiagnosticStmt,
ProgramPoint::Kind K) { … }
const ProgramPointTag *ExprEngine::cleanupNodeTag() { … }
void ExprEngine::ProcessStmt(const Stmt *currStmt, ExplodedNode *Pred) { … }
void ExprEngine::ProcessLoopExit(const Stmt* S, ExplodedNode *Pred) { … }
void ExprEngine::ProcessInitializer(const CFGInitializer CFGInit,
ExplodedNode *Pred) { … }
std::pair<ProgramStateRef, uint64_t>
ExprEngine::prepareStateForArrayDestruction(const ProgramStateRef State,
const MemRegion *Region,
const QualType &ElementTy,
const LocationContext *LCtx,
SVal *ElementCountVal) { … }
void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
ExplodedNode *Pred) { … }
void ExprEngine::ProcessNewAllocator(const CXXNewExpr *NE,
ExplodedNode *Pred) { … }
void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) { … }
void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) { … }
void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D,
ExplodedNode *Pred, ExplodedNodeSet &Dst) { … }
void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D,
ExplodedNode *Pred, ExplodedNodeSet &Dst) { … }
void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) { … }
void ExprEngine::processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
NodeBuilderContext &BldCtx,
ExplodedNode *Pred,
ExplodedNodeSet &Dst,
const CFGBlock *DstT,
const CFGBlock *DstF) { … }
void ExprEngine::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE,
ExplodedNodeSet &PreVisit,
ExplodedNodeSet &Dst) { … }
ProgramStateRef ExprEngine::escapeValues(ProgramStateRef State,
ArrayRef<SVal> Vs,
PointerEscapeKind K,
const CallEvent *Call) const { … }
void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
ExplodedNodeSet &DstTop) { … }
bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
const LocationContext *CalleeLC) { … }
void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
NodeBuilderWithSinks &nodeBuilder,
ExplodedNode *Pred) { … }
static SVal RecoverCastedSymbol(ProgramStateRef state,
const Stmt *Condition,
const LocationContext *LCtx,
ASTContext &Ctx) { … }
#ifndef NDEBUG
static const Stmt *getRightmostLeaf(const Stmt *Condition) {
while (Condition) {
const auto *BO = dyn_cast<BinaryOperator>(Condition);
if (!BO || !BO->isLogicalOp()) {
return Condition;
}
Condition = BO->getRHS()->IgnoreParens();
}
return nullptr;
}
#endif
static const Stmt *ResolveCondition(const Stmt *Condition,
const CFGBlock *B) { … }
ObjCForLctxPair;
REGISTER_MAP_WITH_PROGRAMSTATE(…) …
ProgramStateRef ExprEngine::setWhetherHasMoreIteration(
ProgramStateRef State, const ObjCForCollectionStmt *O,
const LocationContext *LC, bool HasMoreIteraton) { … }
ProgramStateRef
ExprEngine::removeIterationState(ProgramStateRef State,
const ObjCForCollectionStmt *O,
const LocationContext *LC) { … }
bool ExprEngine::hasMoreIteration(ProgramStateRef State,
const ObjCForCollectionStmt *O,
const LocationContext *LC) { … }
static std::optional<std::pair<ProgramStateRef, ProgramStateRef>>
assumeCondition(const Stmt *Condition, ExplodedNode *N) { … }
void ExprEngine::processBranch(const Stmt *Condition,
NodeBuilderContext& BldCtx,
ExplodedNode *Pred,
ExplodedNodeSet &Dst,
const CFGBlock *DstT,
const CFGBlock *DstF) { … }
REGISTER_TRAIT_WITH_PROGRAMSTATE(…) …
void ExprEngine::processStaticInitializer(const DeclStmt *DS,
NodeBuilderContext &BuilderCtx,
ExplodedNode *Pred,
ExplodedNodeSet &Dst,
const CFGBlock *DstT,
const CFGBlock *DstF) { … }
void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) { … }
void ExprEngine::processBeginOfFunction(NodeBuilderContext &BC,
ExplodedNode *Pred,
ExplodedNodeSet &Dst,
const BlockEdge &L) { … }
void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
ExplodedNode *Pred,
const ReturnStmt *RS) { … }
void ExprEngine::processSwitch(SwitchNodeBuilder& builder) { … }
void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) { … }
void ExprEngine::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *Ex,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) { … }
void ExprEngine::VisitArraySubscriptExpr(const ArraySubscriptExpr *A,
ExplodedNode *Pred,
ExplodedNodeSet &Dst){ … }
void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
ExplodedNodeSet &Dst) { … }
void ExprEngine::VisitAtomicExpr(const AtomicExpr *AE, ExplodedNode *Pred,
ExplodedNodeSet &Dst) { … }
ProgramStateRef ExprEngine::processPointerEscapedOnBind(
ProgramStateRef State, ArrayRef<std::pair<SVal, SVal>> LocAndVals,
const LocationContext *LCtx, PointerEscapeKind Kind,
const CallEvent *Call) { … }
ProgramStateRef
ExprEngine::processPointerEscapedOnBind(ProgramStateRef State, SVal Loc,
SVal Val, const LocationContext *LCtx) { … }
ProgramStateRef
ExprEngine::notifyCheckersOfPointerEscape(ProgramStateRef State,
const InvalidatedSymbols *Invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
const CallEvent *Call,
RegionAndSymbolInvalidationTraits &ITraits) { … }
void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
ExplodedNode *Pred,
SVal location, SVal Val,
bool atDeclInit, const ProgramPoint *PP) { … }
void ExprEngine::evalStore(ExplodedNodeSet &Dst, const Expr *AssignE,
const Expr *LocationE,
ExplodedNode *Pred,
ProgramStateRef state, SVal location, SVal Val,
const ProgramPointTag *tag) { … }
void ExprEngine::evalLoad(ExplodedNodeSet &Dst,
const Expr *NodeEx,
const Expr *BoundEx,
ExplodedNode *Pred,
ProgramStateRef state,
SVal location,
const ProgramPointTag *tag,
QualType LoadTy) { … }
void ExprEngine::evalLocation(ExplodedNodeSet &Dst,
const Stmt *NodeEx,
const Stmt *BoundEx,
ExplodedNode *Pred,
ProgramStateRef state,
SVal location,
bool isLoad) { … }
std::pair<const ProgramPointTag *, const ProgramPointTag*>
ExprEngine::geteagerlyAssumeBinOpBifurcationTags() { … }
void ExprEngine::evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst,
ExplodedNodeSet &Src,
const Expr *Ex) { … }
void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,
ExplodedNodeSet &Dst) { … }
void ExprEngine::VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred,
ExplodedNodeSet &Dst) { … }
namespace llvm {
template<>
struct DOTGraphTraits<ExplodedGraph*> : public DefaultDOTGraphTraits { … };
}
void ExprEngine::ViewGraph(bool trim) { … }
void ExprEngine::ViewGraph(ArrayRef<const ExplodedNode *> Nodes) { … }
std::string ExprEngine::DumpGraph(bool trim, StringRef Filename) { … }
std::string ExprEngine::DumpGraph(ArrayRef<const ExplodedNode *> Nodes,
StringRef Filename) { … }
void *ProgramStateTrait<ReplayWithoutInlining>::GDMIndex() { … }
void ExprEngine::anchor() { … }