[clang] Run PreStmt/PostStmt checker for GCCAsmStmt (PR #95409)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 10 04:45:25 PDT 2024
https://github.com/T-Gruber updated https://github.com/llvm/llvm-project/pull/95409
>From 8fb59a5ab510cbe9d2f6322cb1c6252c8e0b7343 Mon Sep 17 00:00:00 2001
From: T-Gruber <tobi.gruber at gmx.de>
Date: Thu, 13 Jun 2024 15:41:28 +0200
Subject: [PATCH 1/6] Run PreStmt/PostStmt checker for GCCAsmStmt
---
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 1593 ++++++++---------
clang/unittests/StaticAnalyzer/CMakeLists.txt | 1 +
.../StaticAnalyzer/ExprEngineVisitTest.cpp | 92 +
3 files changed, 869 insertions(+), 817 deletions(-)
create mode 100644 clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 197d673107285..d99fa7a132f50 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -89,16 +89,15 @@ using namespace ento;
#define DEBUG_TYPE "ExprEngine"
-STATISTIC(NumRemoveDeadBindings,
- "The # of times RemoveDeadBindings is called");
+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");
+ "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");
+ "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");
+ "The # of times we re-evaluated a call without inlining");
//===----------------------------------------------------------------------===//
// Internal program state traits.
@@ -126,7 +125,7 @@ class ConstructedObjectKey {
public:
explicit ConstructedObjectKey(const ConstructionContextItem &Item,
- const LocationContext *LC)
+ const LocationContext *LC)
: Impl(Item, LC) {}
const ConstructionContextItem &getItem() const { return Impl.first; }
@@ -216,7 +215,7 @@ REGISTER_TRAIT_WITH_PROGRAMSTATE(PendingArrayDestruction,
// Engine construction and deletion.
//===----------------------------------------------------------------------===//
-static const char* TagProviderName = "ExprEngine";
+static const char *TagProviderName = "ExprEngine";
ExprEngine::ExprEngine(cross_tu::CrossTranslationUnitContext &CTU,
AnalysisManager &mgr, SetOfConstDecls *VisitedCalleesIn,
@@ -267,9 +266,9 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {
break;
SVal V = state->getSVal(loc::MemRegionVal(R));
- SVal Constraint_untested = evalBinOp(state, BO_GT, V,
- svalBuilder.makeZeroVal(T),
- svalBuilder.getConditionType());
+ SVal Constraint_untested =
+ evalBinOp(state, BO_GT, V, svalBuilder.makeZeroVal(T),
+ svalBuilder.getConditionType());
std::optional<DefinedOrUnknownSVal> Constraint =
Constraint_untested.getAs<DefinedOrUnknownSVal>();
@@ -281,8 +280,7 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {
state = newState;
}
break;
- }
- while (false);
+ } while (false);
if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
// Precondition: 'self' is always non-null upon entry to an Objective-C
@@ -657,28 +655,23 @@ bool ExprEngine::areAllObjectsFullyConstructed(ProgramStateRef State,
return true;
}
-
//===----------------------------------------------------------------------===//
// Top-level transfer function logic (Dispatcher).
//===----------------------------------------------------------------------===//
/// evalAssume - Called by ConstraintManager. Used to call checker-specific
/// logic for handling assumptions on symbolic values.
-ProgramStateRef ExprEngine::processAssume(ProgramStateRef state,
- SVal cond, bool assumption) {
+ProgramStateRef ExprEngine::processAssume(ProgramStateRef state, SVal cond,
+ bool assumption) {
return getCheckerManager().runCheckersForEvalAssume(state, cond, assumption);
}
-ProgramStateRef
-ExprEngine::processRegionChanges(ProgramStateRef state,
- const InvalidatedSymbols *invalidated,
- ArrayRef<const MemRegion *> Explicits,
- ArrayRef<const MemRegion *> Regions,
- const LocationContext *LCtx,
- const CallEvent *Call) {
- return getCheckerManager().runCheckersForRegionChanges(state, invalidated,
- Explicits, Regions,
- LCtx, Call);
+ProgramStateRef ExprEngine::processRegionChanges(
+ ProgramStateRef state, const InvalidatedSymbols *invalidated,
+ ArrayRef<const MemRegion *> Explicits, ArrayRef<const MemRegion *> Regions,
+ const LocationContext *LCtx, const CallEvent *Call) {
+ return getCheckerManager().runCheckersForRegionChanges(
+ state, invalidated, Explicits, Regions, LCtx, Call);
}
static void
@@ -970,38 +963,36 @@ void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred,
currBldrCtx = Ctx;
switch (E.getKind()) {
- case CFGElement::Statement:
- case CFGElement::Constructor:
- case CFGElement::CXXRecordTypedCall:
- ProcessStmt(E.castAs<CFGStmt>().getStmt(), Pred);
- return;
- case CFGElement::Initializer:
- ProcessInitializer(E.castAs<CFGInitializer>(), Pred);
- return;
- case CFGElement::NewAllocator:
- ProcessNewAllocator(E.castAs<CFGNewAllocator>().getAllocatorExpr(),
- Pred);
- return;
- case CFGElement::AutomaticObjectDtor:
- case CFGElement::DeleteDtor:
- case CFGElement::BaseDtor:
- case CFGElement::MemberDtor:
- case CFGElement::TemporaryDtor:
- ProcessImplicitDtor(E.castAs<CFGImplicitDtor>(), Pred);
- return;
- case CFGElement::LoopExit:
- ProcessLoopExit(E.castAs<CFGLoopExit>().getLoopStmt(), Pred);
- return;
- case CFGElement::LifetimeEnds:
- case CFGElement::CleanupFunction:
- case CFGElement::ScopeBegin:
- case CFGElement::ScopeEnd:
- return;
+ case CFGElement::Statement:
+ case CFGElement::Constructor:
+ case CFGElement::CXXRecordTypedCall:
+ ProcessStmt(E.castAs<CFGStmt>().getStmt(), Pred);
+ return;
+ case CFGElement::Initializer:
+ ProcessInitializer(E.castAs<CFGInitializer>(), Pred);
+ return;
+ case CFGElement::NewAllocator:
+ ProcessNewAllocator(E.castAs<CFGNewAllocator>().getAllocatorExpr(), Pred);
+ return;
+ case CFGElement::AutomaticObjectDtor:
+ case CFGElement::DeleteDtor:
+ case CFGElement::BaseDtor:
+ case CFGElement::MemberDtor:
+ case CFGElement::TemporaryDtor:
+ ProcessImplicitDtor(E.castAs<CFGImplicitDtor>(), Pred);
+ return;
+ case CFGElement::LoopExit:
+ ProcessLoopExit(E.castAs<CFGLoopExit>().getLoopStmt(), Pred);
+ return;
+ case CFGElement::LifetimeEnds:
+ case CFGElement::CleanupFunction:
+ case CFGElement::ScopeBegin:
+ case CFGElement::ScopeEnd:
+ return;
}
}
-static bool shouldRemoveDeadBindings(AnalysisManager &AMgr,
- const Stmt *S,
+static bool shouldRemoveDeadBindings(AnalysisManager &AMgr, const Stmt *S,
const ExplodedNode *Pred,
const LocationContext *LC) {
// Are we never purging state values?
@@ -1029,11 +1020,10 @@ static bool shouldRemoveDeadBindings(AnalysisManager &AMgr,
void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
const Stmt *ReferenceStmt,
const LocationContext *LC,
- const Stmt *DiagnosticStmt,
- ProgramPoint::Kind K) {
+ const Stmt *DiagnosticStmt, ProgramPoint::Kind K) {
assert((K == ProgramPoint::PreStmtPurgeDeadSymbolsKind ||
- ReferenceStmt == nullptr || isa<ReturnStmt>(ReferenceStmt))
- && "PostStmt is not generally supported by the SymbolReaper yet");
+ ReferenceStmt == nullptr || isa<ReturnStmt>(ReferenceStmt)) &&
+ "PostStmt is not generally supported by the SymbolReaper yet");
assert(LC && "Must pass the current (or expiring) LocationContext");
if (!DiagnosticStmt) {
@@ -1118,8 +1108,7 @@ void ExprEngine::ProcessStmt(const Stmt *currStmt, ExplodedNode *Pred) {
ExplodedNodeSet CleanedStates;
if (shouldRemoveDeadBindings(AMgr, currStmt, Pred,
Pred->getLocationContext())) {
- removeDead(Pred, CleanedStates, currStmt,
- Pred->getLocationContext());
+ removeDead(Pred, CleanedStates, currStmt, Pred->getLocationContext());
} else
CleanedStates.Add(Pred);
@@ -1136,7 +1125,7 @@ void ExprEngine::ProcessStmt(const Stmt *currStmt, ExplodedNode *Pred) {
Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
}
-void ExprEngine::ProcessLoopExit(const Stmt* S, ExplodedNode *Pred) {
+void ExprEngine::ProcessLoopExit(const Stmt *S, ExplodedNode *Pred) {
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
S->getBeginLoc(),
"Error evaluating end of the loop");
@@ -1145,7 +1134,7 @@ void ExprEngine::ProcessLoopExit(const Stmt* S, ExplodedNode *Pred) {
NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
ProgramStateRef NewState = Pred->getState();
- if(AMgr.options.ShouldUnrollLoops)
+ if (AMgr.options.ShouldUnrollLoops)
NewState = processLoopEnd(S, NewState);
LoopExit PP(S, Pred->getLocationContext());
@@ -1211,9 +1200,9 @@ void ExprEngine::ProcessInitializer(const CFGInitializer CFGInit,
// If we fail to get the value for some reason, use a symbolic value.
if (InitVal.isUnknownOrUndef()) {
SValBuilder &SVB = getSValBuilder();
- InitVal = SVB.conjureSymbolVal(BMI->getInit(), stackFrame,
- Field->getType(),
- currBldrCtx->blockCount());
+ InitVal =
+ SVB.conjureSymbolVal(BMI->getInit(), stackFrame, Field->getType(),
+ currBldrCtx->blockCount());
}
} else {
InitVal = State->getSVal(BMI->getInit(), stackFrame);
@@ -1314,8 +1303,7 @@ void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
}
-void ExprEngine::ProcessNewAllocator(const CXXNewExpr *NE,
- ExplodedNode *Pred) {
+void ExprEngine::ProcessNewAllocator(const CXXNewExpr *NE, ExplodedNode *Pred) {
ExplodedNodeSet Dst;
AnalysisManager &AMgr = getAnalysisManager();
AnalyzerOptions &Opts = AMgr.options;
@@ -1406,8 +1394,7 @@ void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,
/*IsBase=*/false, Pred, Dst, CallOpts);
}
-void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor,
- ExplodedNode *Pred,
+void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor, ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
ProgramStateRef State = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
@@ -1482,28 +1469,27 @@ void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor,
VisitCXXDestructor(DTy, ArgR, DE, /*IsBase=*/false, Pred, Dst, CallOpts);
}
-void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D,
- ExplodedNode *Pred, ExplodedNodeSet &Dst) {
+void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
const LocationContext *LCtx = Pred->getLocationContext();
const auto *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl());
- Loc ThisPtr = getSValBuilder().getCXXThis(CurDtor,
- LCtx->getStackFrame());
+ Loc ThisPtr = getSValBuilder().getCXXThis(CurDtor, LCtx->getStackFrame());
SVal ThisVal = Pred->getState()->getSVal(ThisPtr);
// Create the base object region.
const CXXBaseSpecifier *Base = D.getBaseSpecifier();
QualType BaseTy = Base->getType();
- SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy,
- Base->isVirtual());
+ SVal BaseVal =
+ getStoreManager().evalDerivedToBase(ThisVal, BaseTy, Base->isVirtual());
EvalCallOptions CallOpts;
VisitCXXDestructor(BaseTy, BaseVal.getAsRegion(), CurDtor->getBody(),
/*IsBase=*/true, Pred, Dst, CallOpts);
}
-void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D,
- ExplodedNode *Pred, ExplodedNodeSet &Dst) {
+void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
const auto *DtorDecl = D.getDestructorDecl(getContext());
const FieldDecl *Member = D.getFieldDecl();
QualType T = Member->getType();
@@ -1683,8 +1669,7 @@ void ExprEngine::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE,
}
ProgramStateRef ExprEngine::escapeValues(ProgramStateRef State,
- ArrayRef<SVal> Vs,
- PointerEscapeKind K,
+ ArrayRef<SVal> Vs, PointerEscapeKind K,
const CallEvent *Call) const {
class CollectReachableSymbolsCallback final : public SymbolVisitor {
InvalidatedSymbols &Symbols;
@@ -1719,709 +1704,707 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
assert(!isa<Expr>(S) || S == cast<Expr>(S)->IgnoreParens());
switch (S->getStmtClass()) {
- // C++, OpenMP and ARC stuff we don't support yet.
- case Stmt::CXXDependentScopeMemberExprClass:
- case Stmt::CXXTryStmtClass:
- case Stmt::CXXTypeidExprClass:
- case Stmt::CXXUuidofExprClass:
- case Stmt::CXXFoldExprClass:
- case Stmt::MSPropertyRefExprClass:
- case Stmt::MSPropertySubscriptExprClass:
- case Stmt::CXXUnresolvedConstructExprClass:
- case Stmt::DependentScopeDeclRefExprClass:
- case Stmt::ArrayTypeTraitExprClass:
- case Stmt::ExpressionTraitExprClass:
- case Stmt::UnresolvedLookupExprClass:
- case Stmt::UnresolvedMemberExprClass:
- case Stmt::TypoExprClass:
- case Stmt::RecoveryExprClass:
- case Stmt::CXXNoexceptExprClass:
- case Stmt::PackExpansionExprClass:
- case Stmt::PackIndexingExprClass:
- case Stmt::SubstNonTypeTemplateParmPackExprClass:
- case Stmt::FunctionParmPackExprClass:
- case Stmt::CoroutineBodyStmtClass:
- case Stmt::CoawaitExprClass:
- case Stmt::DependentCoawaitExprClass:
- case Stmt::CoreturnStmtClass:
- case Stmt::CoyieldExprClass:
- case Stmt::SEHTryStmtClass:
- case Stmt::SEHExceptStmtClass:
- case Stmt::SEHLeaveStmtClass:
- case Stmt::SEHFinallyStmtClass:
- case Stmt::OMPCanonicalLoopClass:
- case Stmt::OMPParallelDirectiveClass:
- case Stmt::OMPSimdDirectiveClass:
- case Stmt::OMPForDirectiveClass:
- case Stmt::OMPForSimdDirectiveClass:
- case Stmt::OMPSectionsDirectiveClass:
- case Stmt::OMPSectionDirectiveClass:
- case Stmt::OMPScopeDirectiveClass:
- case Stmt::OMPSingleDirectiveClass:
- case Stmt::OMPMasterDirectiveClass:
- case Stmt::OMPCriticalDirectiveClass:
- case Stmt::OMPParallelForDirectiveClass:
- case Stmt::OMPParallelForSimdDirectiveClass:
- case Stmt::OMPParallelSectionsDirectiveClass:
- case Stmt::OMPParallelMasterDirectiveClass:
- case Stmt::OMPParallelMaskedDirectiveClass:
- case Stmt::OMPTaskDirectiveClass:
- case Stmt::OMPTaskyieldDirectiveClass:
- case Stmt::OMPBarrierDirectiveClass:
- case Stmt::OMPTaskwaitDirectiveClass:
- case Stmt::OMPErrorDirectiveClass:
- case Stmt::OMPTaskgroupDirectiveClass:
- case Stmt::OMPFlushDirectiveClass:
- case Stmt::OMPDepobjDirectiveClass:
- case Stmt::OMPScanDirectiveClass:
- case Stmt::OMPOrderedDirectiveClass:
- case Stmt::OMPAtomicDirectiveClass:
- case Stmt::OMPTargetDirectiveClass:
- case Stmt::OMPTargetDataDirectiveClass:
- case Stmt::OMPTargetEnterDataDirectiveClass:
- case Stmt::OMPTargetExitDataDirectiveClass:
- case Stmt::OMPTargetParallelDirectiveClass:
- case Stmt::OMPTargetParallelForDirectiveClass:
- case Stmt::OMPTargetUpdateDirectiveClass:
- case Stmt::OMPTeamsDirectiveClass:
- case Stmt::OMPCancellationPointDirectiveClass:
- case Stmt::OMPCancelDirectiveClass:
- case Stmt::OMPTaskLoopDirectiveClass:
- case Stmt::OMPTaskLoopSimdDirectiveClass:
- case Stmt::OMPMasterTaskLoopDirectiveClass:
- case Stmt::OMPMaskedTaskLoopDirectiveClass:
- case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
- case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
- case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
- case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
- case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
- case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
- case Stmt::OMPDistributeDirectiveClass:
- case Stmt::OMPDistributeParallelForDirectiveClass:
- case Stmt::OMPDistributeParallelForSimdDirectiveClass:
- case Stmt::OMPDistributeSimdDirectiveClass:
- case Stmt::OMPTargetParallelForSimdDirectiveClass:
- case Stmt::OMPTargetSimdDirectiveClass:
- case Stmt::OMPTeamsDistributeDirectiveClass:
- case Stmt::OMPTeamsDistributeSimdDirectiveClass:
- case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
- case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
- case Stmt::OMPTargetTeamsDirectiveClass:
- case Stmt::OMPTargetTeamsDistributeDirectiveClass:
- case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
- case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
- case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
- case Stmt::OMPTileDirectiveClass:
- case Stmt::OMPInteropDirectiveClass:
- case Stmt::OMPDispatchDirectiveClass:
- case Stmt::OMPMaskedDirectiveClass:
- case Stmt::OMPGenericLoopDirectiveClass:
- case Stmt::OMPTeamsGenericLoopDirectiveClass:
- case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
- case Stmt::OMPParallelGenericLoopDirectiveClass:
- case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
- case Stmt::CapturedStmtClass:
- case Stmt::OpenACCComputeConstructClass:
- case Stmt::OpenACCLoopConstructClass:
- case Stmt::OMPUnrollDirectiveClass:
- case Stmt::OMPMetaDirectiveClass: {
- const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
- Engine.addAbortedBlock(node, currBldrCtx->getBlock());
- break;
- }
+ // C++, OpenMP and ARC stuff we don't support yet.
+ case Stmt::CXXDependentScopeMemberExprClass:
+ case Stmt::CXXTryStmtClass:
+ case Stmt::CXXTypeidExprClass:
+ case Stmt::CXXUuidofExprClass:
+ case Stmt::CXXFoldExprClass:
+ case Stmt::MSPropertyRefExprClass:
+ case Stmt::MSPropertySubscriptExprClass:
+ case Stmt::CXXUnresolvedConstructExprClass:
+ case Stmt::DependentScopeDeclRefExprClass:
+ case Stmt::ArrayTypeTraitExprClass:
+ case Stmt::ExpressionTraitExprClass:
+ case Stmt::UnresolvedLookupExprClass:
+ case Stmt::UnresolvedMemberExprClass:
+ case Stmt::TypoExprClass:
+ case Stmt::RecoveryExprClass:
+ case Stmt::CXXNoexceptExprClass:
+ case Stmt::PackExpansionExprClass:
+ case Stmt::PackIndexingExprClass:
+ case Stmt::SubstNonTypeTemplateParmPackExprClass:
+ case Stmt::FunctionParmPackExprClass:
+ case Stmt::CoroutineBodyStmtClass:
+ case Stmt::CoawaitExprClass:
+ case Stmt::DependentCoawaitExprClass:
+ case Stmt::CoreturnStmtClass:
+ case Stmt::CoyieldExprClass:
+ case Stmt::SEHTryStmtClass:
+ case Stmt::SEHExceptStmtClass:
+ case Stmt::SEHLeaveStmtClass:
+ case Stmt::SEHFinallyStmtClass:
+ case Stmt::OMPCanonicalLoopClass:
+ case Stmt::OMPParallelDirectiveClass:
+ case Stmt::OMPSimdDirectiveClass:
+ case Stmt::OMPForDirectiveClass:
+ case Stmt::OMPForSimdDirectiveClass:
+ case Stmt::OMPSectionsDirectiveClass:
+ case Stmt::OMPSectionDirectiveClass:
+ case Stmt::OMPScopeDirectiveClass:
+ case Stmt::OMPSingleDirectiveClass:
+ case Stmt::OMPMasterDirectiveClass:
+ case Stmt::OMPCriticalDirectiveClass:
+ case Stmt::OMPParallelForDirectiveClass:
+ case Stmt::OMPParallelForSimdDirectiveClass:
+ case Stmt::OMPParallelSectionsDirectiveClass:
+ case Stmt::OMPParallelMasterDirectiveClass:
+ case Stmt::OMPParallelMaskedDirectiveClass:
+ case Stmt::OMPTaskDirectiveClass:
+ case Stmt::OMPTaskyieldDirectiveClass:
+ case Stmt::OMPBarrierDirectiveClass:
+ case Stmt::OMPTaskwaitDirectiveClass:
+ case Stmt::OMPErrorDirectiveClass:
+ case Stmt::OMPTaskgroupDirectiveClass:
+ case Stmt::OMPFlushDirectiveClass:
+ case Stmt::OMPDepobjDirectiveClass:
+ case Stmt::OMPScanDirectiveClass:
+ case Stmt::OMPOrderedDirectiveClass:
+ case Stmt::OMPAtomicDirectiveClass:
+ case Stmt::OMPTargetDirectiveClass:
+ case Stmt::OMPTargetDataDirectiveClass:
+ case Stmt::OMPTargetEnterDataDirectiveClass:
+ case Stmt::OMPTargetExitDataDirectiveClass:
+ case Stmt::OMPTargetParallelDirectiveClass:
+ case Stmt::OMPTargetParallelForDirectiveClass:
+ case Stmt::OMPTargetUpdateDirectiveClass:
+ case Stmt::OMPTeamsDirectiveClass:
+ case Stmt::OMPCancellationPointDirectiveClass:
+ case Stmt::OMPCancelDirectiveClass:
+ case Stmt::OMPTaskLoopDirectiveClass:
+ case Stmt::OMPTaskLoopSimdDirectiveClass:
+ case Stmt::OMPMasterTaskLoopDirectiveClass:
+ case Stmt::OMPMaskedTaskLoopDirectiveClass:
+ case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
+ case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
+ case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
+ case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
+ case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
+ case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
+ case Stmt::OMPDistributeDirectiveClass:
+ case Stmt::OMPDistributeParallelForDirectiveClass:
+ case Stmt::OMPDistributeParallelForSimdDirectiveClass:
+ case Stmt::OMPDistributeSimdDirectiveClass:
+ case Stmt::OMPTargetParallelForSimdDirectiveClass:
+ case Stmt::OMPTargetSimdDirectiveClass:
+ case Stmt::OMPTeamsDistributeDirectiveClass:
+ case Stmt::OMPTeamsDistributeSimdDirectiveClass:
+ case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
+ case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
+ case Stmt::OMPTargetTeamsDirectiveClass:
+ case Stmt::OMPTargetTeamsDistributeDirectiveClass:
+ case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
+ case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
+ case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
+ case Stmt::OMPTileDirectiveClass:
+ case Stmt::OMPInteropDirectiveClass:
+ case Stmt::OMPDispatchDirectiveClass:
+ case Stmt::OMPMaskedDirectiveClass:
+ case Stmt::OMPGenericLoopDirectiveClass:
+ case Stmt::OMPTeamsGenericLoopDirectiveClass:
+ case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
+ case Stmt::OMPParallelGenericLoopDirectiveClass:
+ case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
+ case Stmt::CapturedStmtClass:
+ case Stmt::OpenACCComputeConstructClass:
+ case Stmt::OpenACCLoopConstructClass:
+ case Stmt::OMPUnrollDirectiveClass:
+ case Stmt::OMPMetaDirectiveClass: {
+ const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
+ Engine.addAbortedBlock(node, currBldrCtx->getBlock());
+ break;
+ }
- case Stmt::ParenExprClass:
- llvm_unreachable("ParenExprs already handled.");
- case Stmt::GenericSelectionExprClass:
- llvm_unreachable("GenericSelectionExprs already handled.");
- // Cases that should never be evaluated simply because they shouldn't
- // appear in the CFG.
- case Stmt::BreakStmtClass:
- case Stmt::CaseStmtClass:
- case Stmt::CompoundStmtClass:
- case Stmt::ContinueStmtClass:
- case Stmt::CXXForRangeStmtClass:
- case Stmt::DefaultStmtClass:
- case Stmt::DoStmtClass:
- case Stmt::ForStmtClass:
- case Stmt::GotoStmtClass:
- case Stmt::IfStmtClass:
- case Stmt::IndirectGotoStmtClass:
- case Stmt::LabelStmtClass:
- case Stmt::NoStmtClass:
- case Stmt::NullStmtClass:
- case Stmt::SwitchStmtClass:
- case Stmt::WhileStmtClass:
- case Expr::MSDependentExistsStmtClass:
- llvm_unreachable("Stmt should not be in analyzer evaluation loop");
- case Stmt::ImplicitValueInitExprClass:
- // These nodes are shared in the CFG and would case caching out.
- // Moreover, no additional evaluation required for them, the
- // analyzer can reconstruct these values from the AST.
- llvm_unreachable("Should be pruned from CFG");
-
- case Stmt::ObjCSubscriptRefExprClass:
- case Stmt::ObjCPropertyRefExprClass:
- llvm_unreachable("These are handled by PseudoObjectExpr");
-
- case Stmt::GNUNullExprClass: {
- // GNU __null is a pointer-width integer, not an actual pointer.
- ProgramStateRef state = Pred->getState();
- state = state->BindExpr(
- S, Pred->getLocationContext(),
- svalBuilder.makeIntValWithWidth(getContext().VoidPtrTy, 0));
- Bldr.generateNode(S, Pred, state);
- break;
- }
+ case Stmt::ParenExprClass:
+ llvm_unreachable("ParenExprs already handled.");
+ case Stmt::GenericSelectionExprClass:
+ llvm_unreachable("GenericSelectionExprs already handled.");
+ // Cases that should never be evaluated simply because they shouldn't
+ // appear in the CFG.
+ case Stmt::BreakStmtClass:
+ case Stmt::CaseStmtClass:
+ case Stmt::CompoundStmtClass:
+ case Stmt::ContinueStmtClass:
+ case Stmt::CXXForRangeStmtClass:
+ case Stmt::DefaultStmtClass:
+ case Stmt::DoStmtClass:
+ case Stmt::ForStmtClass:
+ case Stmt::GotoStmtClass:
+ case Stmt::IfStmtClass:
+ case Stmt::IndirectGotoStmtClass:
+ case Stmt::LabelStmtClass:
+ case Stmt::NoStmtClass:
+ case Stmt::NullStmtClass:
+ case Stmt::SwitchStmtClass:
+ case Stmt::WhileStmtClass:
+ case Expr::MSDependentExistsStmtClass:
+ llvm_unreachable("Stmt should not be in analyzer evaluation loop");
+ case Stmt::ImplicitValueInitExprClass:
+ // These nodes are shared in the CFG and would case caching out.
+ // Moreover, no additional evaluation required for them, the
+ // analyzer can reconstruct these values from the AST.
+ llvm_unreachable("Should be pruned from CFG");
+
+ case Stmt::ObjCSubscriptRefExprClass:
+ case Stmt::ObjCPropertyRefExprClass:
+ llvm_unreachable("These are handled by PseudoObjectExpr");
+
+ case Stmt::GNUNullExprClass: {
+ // GNU __null is a pointer-width integer, not an actual pointer.
+ ProgramStateRef state = Pred->getState();
+ state = state->BindExpr(
+ S, Pred->getLocationContext(),
+ svalBuilder.makeIntValWithWidth(getContext().VoidPtrTy, 0));
+ Bldr.generateNode(S, Pred, state);
+ break;
+ }
- case Stmt::ObjCAtSynchronizedStmtClass:
- Bldr.takeNodes(Pred);
- VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::ObjCAtSynchronizedStmtClass:
+ Bldr.takeNodes(Pred);
+ VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Expr::ConstantExprClass:
- case Stmt::ExprWithCleanupsClass:
- // Handled due to fully linearised CFG.
- break;
+ case Expr::ConstantExprClass:
+ case Stmt::ExprWithCleanupsClass:
+ // Handled due to fully linearised CFG.
+ break;
- case Stmt::CXXBindTemporaryExprClass: {
- Bldr.takeNodes(Pred);
- ExplodedNodeSet PreVisit;
- getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
- ExplodedNodeSet Next;
- VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), PreVisit, Next);
- getCheckerManager().runCheckersForPostStmt(Dst, Next, S, *this);
- Bldr.addNodes(Dst);
- break;
- }
+ case Stmt::CXXBindTemporaryExprClass: {
+ Bldr.takeNodes(Pred);
+ ExplodedNodeSet PreVisit;
+ getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+ ExplodedNodeSet Next;
+ VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), PreVisit, Next);
+ getCheckerManager().runCheckersForPostStmt(Dst, Next, S, *this);
+ Bldr.addNodes(Dst);
+ break;
+ }
- case Stmt::ArrayInitLoopExprClass:
- Bldr.takeNodes(Pred);
- VisitArrayInitLoopExpr(cast<ArrayInitLoopExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
- // Cases not handled yet; but will handle some day.
- case Stmt::DesignatedInitExprClass:
- case Stmt::DesignatedInitUpdateExprClass:
- case Stmt::ArrayInitIndexExprClass:
- case Stmt::ExtVectorElementExprClass:
- case Stmt::ImaginaryLiteralClass:
- case Stmt::ObjCAtCatchStmtClass:
- case Stmt::ObjCAtFinallyStmtClass:
- case Stmt::ObjCAtTryStmtClass:
- case Stmt::ObjCAutoreleasePoolStmtClass:
- case Stmt::ObjCEncodeExprClass:
- case Stmt::ObjCIsaExprClass:
- case Stmt::ObjCProtocolExprClass:
- case Stmt::ObjCSelectorExprClass:
- case Stmt::ParenListExprClass:
- case Stmt::ShuffleVectorExprClass:
- case Stmt::ConvertVectorExprClass:
- case Stmt::VAArgExprClass:
- case Stmt::CUDAKernelCallExprClass:
- case Stmt::OpaqueValueExprClass:
- case Stmt::AsTypeExprClass:
- case Stmt::ConceptSpecializationExprClass:
- case Stmt::CXXRewrittenBinaryOperatorClass:
- case Stmt::RequiresExprClass:
- case Expr::CXXParenListInitExprClass:
- // Fall through.
-
- // Cases we intentionally don't evaluate, since they don't need
- // to be explicitly evaluated.
- case Stmt::PredefinedExprClass:
- case Stmt::AddrLabelExprClass:
- case Stmt::AttributedStmtClass:
- case Stmt::IntegerLiteralClass:
- case Stmt::FixedPointLiteralClass:
- case Stmt::CharacterLiteralClass:
- case Stmt::CXXScalarValueInitExprClass:
- case Stmt::CXXBoolLiteralExprClass:
- case Stmt::ObjCBoolLiteralExprClass:
- case Stmt::ObjCAvailabilityCheckExprClass:
- case Stmt::FloatingLiteralClass:
- case Stmt::NoInitExprClass:
- case Stmt::SizeOfPackExprClass:
- case Stmt::StringLiteralClass:
- case Stmt::SourceLocExprClass:
- case Stmt::ObjCStringLiteralClass:
- case Stmt::CXXPseudoDestructorExprClass:
- case Stmt::SubstNonTypeTemplateParmExprClass:
- case Stmt::CXXNullPtrLiteralExprClass:
- case Stmt::ArraySectionExprClass:
- case Stmt::OMPArrayShapingExprClass:
- case Stmt::OMPIteratorExprClass:
- case Stmt::SYCLUniqueStableNameExprClass:
- case Stmt::TypeTraitExprClass: {
- Bldr.takeNodes(Pred);
- ExplodedNodeSet preVisit;
- getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
- getCheckerManager().runCheckersForPostStmt(Dst, preVisit, S, *this);
- Bldr.addNodes(Dst);
- break;
- }
+ case Stmt::ArrayInitLoopExprClass:
+ Bldr.takeNodes(Pred);
+ VisitArrayInitLoopExpr(cast<ArrayInitLoopExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
+ // Cases not handled yet; but will handle some day.
+ case Stmt::DesignatedInitExprClass:
+ case Stmt::DesignatedInitUpdateExprClass:
+ case Stmt::ArrayInitIndexExprClass:
+ case Stmt::ExtVectorElementExprClass:
+ case Stmt::ImaginaryLiteralClass:
+ case Stmt::ObjCAtCatchStmtClass:
+ case Stmt::ObjCAtFinallyStmtClass:
+ case Stmt::ObjCAtTryStmtClass:
+ case Stmt::ObjCAutoreleasePoolStmtClass:
+ case Stmt::ObjCEncodeExprClass:
+ case Stmt::ObjCIsaExprClass:
+ case Stmt::ObjCProtocolExprClass:
+ case Stmt::ObjCSelectorExprClass:
+ case Stmt::ParenListExprClass:
+ case Stmt::ShuffleVectorExprClass:
+ case Stmt::ConvertVectorExprClass:
+ case Stmt::VAArgExprClass:
+ case Stmt::CUDAKernelCallExprClass:
+ case Stmt::OpaqueValueExprClass:
+ case Stmt::AsTypeExprClass:
+ case Stmt::ConceptSpecializationExprClass:
+ case Stmt::CXXRewrittenBinaryOperatorClass:
+ case Stmt::RequiresExprClass:
+ case Expr::CXXParenListInitExprClass:
+ // Fall through.
+
+ // Cases we intentionally don't evaluate, since they don't need
+ // to be explicitly evaluated.
+ case Stmt::PredefinedExprClass:
+ case Stmt::AddrLabelExprClass:
+ case Stmt::AttributedStmtClass:
+ case Stmt::IntegerLiteralClass:
+ case Stmt::FixedPointLiteralClass:
+ case Stmt::CharacterLiteralClass:
+ case Stmt::CXXScalarValueInitExprClass:
+ case Stmt::CXXBoolLiteralExprClass:
+ case Stmt::ObjCBoolLiteralExprClass:
+ case Stmt::ObjCAvailabilityCheckExprClass:
+ case Stmt::FloatingLiteralClass:
+ case Stmt::NoInitExprClass:
+ case Stmt::SizeOfPackExprClass:
+ case Stmt::StringLiteralClass:
+ case Stmt::SourceLocExprClass:
+ case Stmt::ObjCStringLiteralClass:
+ case Stmt::CXXPseudoDestructorExprClass:
+ case Stmt::SubstNonTypeTemplateParmExprClass:
+ case Stmt::CXXNullPtrLiteralExprClass:
+ case Stmt::ArraySectionExprClass:
+ case Stmt::OMPArrayShapingExprClass:
+ case Stmt::OMPIteratorExprClass:
+ case Stmt::SYCLUniqueStableNameExprClass:
+ case Stmt::TypeTraitExprClass: {
+ Bldr.takeNodes(Pred);
+ ExplodedNodeSet preVisit;
+ getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
+ getCheckerManager().runCheckersForPostStmt(Dst, preVisit, S, *this);
+ Bldr.addNodes(Dst);
+ break;
+ }
- case Stmt::CXXDefaultArgExprClass:
- case Stmt::CXXDefaultInitExprClass: {
- Bldr.takeNodes(Pred);
- ExplodedNodeSet PreVisit;
- getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+ case Stmt::CXXDefaultArgExprClass:
+ case Stmt::CXXDefaultInitExprClass: {
+ Bldr.takeNodes(Pred);
+ ExplodedNodeSet PreVisit;
+ getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
- ExplodedNodeSet Tmp;
- StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
+ ExplodedNodeSet Tmp;
+ StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
- const Expr *ArgE;
- if (const auto *DefE = dyn_cast<CXXDefaultArgExpr>(S))
- ArgE = DefE->getExpr();
- else if (const auto *DefE = dyn_cast<CXXDefaultInitExpr>(S))
- ArgE = DefE->getExpr();
- else
- llvm_unreachable("unknown constant wrapper kind");
+ const Expr *ArgE;
+ if (const auto *DefE = dyn_cast<CXXDefaultArgExpr>(S))
+ ArgE = DefE->getExpr();
+ else if (const auto *DefE = dyn_cast<CXXDefaultInitExpr>(S))
+ ArgE = DefE->getExpr();
+ else
+ llvm_unreachable("unknown constant wrapper kind");
- bool IsTemporary = false;
- if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(ArgE)) {
- ArgE = MTE->getSubExpr();
- IsTemporary = true;
- }
+ bool IsTemporary = false;
+ if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(ArgE)) {
+ ArgE = MTE->getSubExpr();
+ IsTemporary = true;
+ }
- std::optional<SVal> ConstantVal = svalBuilder.getConstantVal(ArgE);
- if (!ConstantVal)
- ConstantVal = UnknownVal();
-
- const LocationContext *LCtx = Pred->getLocationContext();
- for (const auto I : PreVisit) {
- ProgramStateRef State = I->getState();
- State = State->BindExpr(S, LCtx, *ConstantVal);
- if (IsTemporary)
- State = createTemporaryRegionIfNeeded(State, LCtx,
- cast<Expr>(S),
- cast<Expr>(S));
- Bldr2.generateNode(S, I, State);
- }
+ std::optional<SVal> ConstantVal = svalBuilder.getConstantVal(ArgE);
+ if (!ConstantVal)
+ ConstantVal = UnknownVal();
- getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
- Bldr.addNodes(Dst);
- break;
+ const LocationContext *LCtx = Pred->getLocationContext();
+ for (const auto I : PreVisit) {
+ ProgramStateRef State = I->getState();
+ State = State->BindExpr(S, LCtx, *ConstantVal);
+ if (IsTemporary)
+ State = createTemporaryRegionIfNeeded(State, LCtx, cast<Expr>(S),
+ cast<Expr>(S));
+ Bldr2.generateNode(S, I, State);
}
- // Cases we evaluate as opaque expressions, conjuring a symbol.
- case Stmt::CXXStdInitializerListExprClass:
- case Expr::ObjCArrayLiteralClass:
- case Expr::ObjCDictionaryLiteralClass:
- case Expr::ObjCBoxedExprClass: {
- Bldr.takeNodes(Pred);
+ getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
+ Bldr.addNodes(Dst);
+ break;
+ }
- ExplodedNodeSet preVisit;
- getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
+ // Cases we evaluate as opaque expressions, conjuring a symbol.
+ case Stmt::CXXStdInitializerListExprClass:
+ case Expr::ObjCArrayLiteralClass:
+ case Expr::ObjCDictionaryLiteralClass:
+ case Expr::ObjCBoxedExprClass: {
+ Bldr.takeNodes(Pred);
- ExplodedNodeSet Tmp;
- StmtNodeBuilder Bldr2(preVisit, Tmp, *currBldrCtx);
-
- const auto *Ex = cast<Expr>(S);
- QualType resultType = Ex->getType();
-
- for (const auto N : preVisit) {
- const LocationContext *LCtx = N->getLocationContext();
- SVal result = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
- resultType,
- currBldrCtx->blockCount());
- ProgramStateRef State = N->getState()->BindExpr(Ex, LCtx, result);
-
- // Escape pointers passed into the list, unless it's an ObjC boxed
- // expression which is not a boxable C structure.
- if (!(isa<ObjCBoxedExpr>(Ex) &&
- !cast<ObjCBoxedExpr>(Ex)->getSubExpr()
- ->getType()->isRecordType()))
- for (auto Child : Ex->children()) {
- assert(Child);
- SVal Val = State->getSVal(Child, LCtx);
- State = escapeValues(State, Val, PSK_EscapeOther);
- }
+ ExplodedNodeSet preVisit;
+ getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
- Bldr2.generateNode(S, N, State);
- }
+ ExplodedNodeSet Tmp;
+ StmtNodeBuilder Bldr2(preVisit, Tmp, *currBldrCtx);
+
+ const auto *Ex = cast<Expr>(S);
+ QualType resultType = Ex->getType();
+
+ for (const auto N : preVisit) {
+ const LocationContext *LCtx = N->getLocationContext();
+ SVal result = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx, resultType,
+ currBldrCtx->blockCount());
+ ProgramStateRef State = N->getState()->BindExpr(Ex, LCtx, result);
+
+ // Escape pointers passed into the list, unless it's an ObjC boxed
+ // expression which is not a boxable C structure.
+ if (!(isa<ObjCBoxedExpr>(Ex) &&
+ !cast<ObjCBoxedExpr>(Ex)->getSubExpr()->getType()->isRecordType()))
+ for (auto Child : Ex->children()) {
+ assert(Child);
+ SVal Val = State->getSVal(Child, LCtx);
+ State = escapeValues(State, Val, PSK_EscapeOther);
+ }
- getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
- Bldr.addNodes(Dst);
- break;
+ Bldr2.generateNode(S, N, State);
}
- case Stmt::ArraySubscriptExprClass:
- Bldr.takeNodes(Pred);
- VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
+ Bldr.addNodes(Dst);
+ break;
+ }
- case Stmt::MatrixSubscriptExprClass:
- llvm_unreachable("Support for MatrixSubscriptExpr is not implemented.");
- break;
+ case Stmt::ArraySubscriptExprClass:
+ Bldr.takeNodes(Pred);
+ VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::GCCAsmStmtClass:
- Bldr.takeNodes(Pred);
- VisitGCCAsmStmt(cast<GCCAsmStmt>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::MatrixSubscriptExprClass:
+ llvm_unreachable("Support for MatrixSubscriptExpr is not implemented.");
+ break;
+
+ case Stmt::GCCAsmStmtClass: {
+ Bldr.takeNodes(Pred);
+ ExplodedNodeSet PreVisit;
+ getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+ ExplodedNodeSet PostVisit;
+ for (ExplodedNode *const N : PreVisit)
+ VisitGCCAsmStmt(cast<GCCAsmStmt>(S), N, PostVisit);
+ getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
+ Bldr.addNodes(Dst);
+ } break;
+
+ case Stmt::MSAsmStmtClass:
+ Bldr.takeNodes(Pred);
+ VisitMSAsmStmt(cast<MSAsmStmt>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
+
+ case Stmt::BlockExprClass:
+ Bldr.takeNodes(Pred);
+ VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::MSAsmStmtClass:
+ case Stmt::LambdaExprClass:
+ if (AMgr.options.ShouldInlineLambdas) {
Bldr.takeNodes(Pred);
- VisitMSAsmStmt(cast<MSAsmStmt>(S), Pred, Dst);
+ VisitLambdaExpr(cast<LambdaExpr>(S), Pred, Dst);
Bldr.addNodes(Dst);
- break;
+ } else {
+ const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
+ Engine.addAbortedBlock(node, currBldrCtx->getBlock());
+ }
+ break;
- case Stmt::BlockExprClass:
+ case Stmt::BinaryOperatorClass: {
+ const auto *B = cast<BinaryOperator>(S);
+ if (B->isLogicalOp()) {
Bldr.takeNodes(Pred);
- VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst);
+ VisitLogicalExpr(B, Pred, Dst);
Bldr.addNodes(Dst);
break;
-
- case Stmt::LambdaExprClass:
- if (AMgr.options.ShouldInlineLambdas) {
- Bldr.takeNodes(Pred);
- VisitLambdaExpr(cast<LambdaExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- } else {
- const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
- Engine.addAbortedBlock(node, currBldrCtx->getBlock());
- }
+ } else if (B->getOpcode() == BO_Comma) {
+ ProgramStateRef state = Pred->getState();
+ Bldr.generateNode(
+ B, Pred,
+ state->BindExpr(
+ B, Pred->getLocationContext(),
+ state->getSVal(B->getRHS(), Pred->getLocationContext())));
break;
+ }
- case Stmt::BinaryOperatorClass: {
- const auto *B = cast<BinaryOperator>(S);
- if (B->isLogicalOp()) {
- Bldr.takeNodes(Pred);
- VisitLogicalExpr(B, Pred, Dst);
- Bldr.addNodes(Dst);
- break;
- }
- else if (B->getOpcode() == BO_Comma) {
- ProgramStateRef state = Pred->getState();
- Bldr.generateNode(B, Pred,
- state->BindExpr(B, Pred->getLocationContext(),
- state->getSVal(B->getRHS(),
- Pred->getLocationContext())));
- break;
- }
+ Bldr.takeNodes(Pred);
- Bldr.takeNodes(Pred);
+ if (AMgr.options.ShouldEagerlyAssume &&
+ (B->isRelationalOp() || B->isEqualityOp())) {
+ ExplodedNodeSet Tmp;
+ VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);
+ evalEagerlyAssumeBinOpBifurcation(Dst, Tmp, cast<Expr>(S));
+ } else
+ VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
- if (AMgr.options.ShouldEagerlyAssume &&
- (B->isRelationalOp() || B->isEqualityOp())) {
- ExplodedNodeSet Tmp;
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);
- evalEagerlyAssumeBinOpBifurcation(Dst, Tmp, cast<Expr>(S));
- }
- else
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
+ }
- Bldr.addNodes(Dst);
- break;
- }
+ case Stmt::CXXOperatorCallExprClass: {
+ const auto *OCE = cast<CXXOperatorCallExpr>(S);
- case Stmt::CXXOperatorCallExprClass: {
- const auto *OCE = cast<CXXOperatorCallExpr>(S);
-
- // For instance method operators, make sure the 'this' argument has a
- // valid region.
- const Decl *Callee = OCE->getCalleeDecl();
- if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(Callee)) {
- if (MD->isImplicitObjectMemberFunction()) {
- ProgramStateRef State = Pred->getState();
- const LocationContext *LCtx = Pred->getLocationContext();
- ProgramStateRef NewState =
+ // For instance method operators, make sure the 'this' argument has a
+ // valid region.
+ const Decl *Callee = OCE->getCalleeDecl();
+ if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(Callee)) {
+ if (MD->isImplicitObjectMemberFunction()) {
+ ProgramStateRef State = Pred->getState();
+ const LocationContext *LCtx = Pred->getLocationContext();
+ ProgramStateRef NewState =
createTemporaryRegionIfNeeded(State, LCtx, OCE->getArg(0));
- if (NewState != State) {
- Pred = Bldr.generateNode(OCE, Pred, NewState, /*tag=*/nullptr,
- ProgramPoint::PreStmtKind);
- // Did we cache out?
- if (!Pred)
- break;
- }
+ if (NewState != State) {
+ Pred = Bldr.generateNode(OCE, Pred, NewState, /*tag=*/nullptr,
+ ProgramPoint::PreStmtKind);
+ // Did we cache out?
+ if (!Pred)
+ break;
}
}
- [[fallthrough]];
}
+ [[fallthrough]];
+ }
- case Stmt::CallExprClass:
- case Stmt::CXXMemberCallExprClass:
- case Stmt::UserDefinedLiteralClass:
- Bldr.takeNodes(Pred);
- VisitCallExpr(cast<CallExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
-
- case Stmt::CXXCatchStmtClass:
- Bldr.takeNodes(Pred);
- VisitCXXCatchStmt(cast<CXXCatchStmt>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
-
- case Stmt::CXXTemporaryObjectExprClass:
- case Stmt::CXXConstructExprClass:
- Bldr.takeNodes(Pred);
- VisitCXXConstructExpr(cast<CXXConstructExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
-
- case Stmt::CXXInheritedCtorInitExprClass:
- Bldr.takeNodes(Pred);
- VisitCXXInheritedCtorInitExpr(cast<CXXInheritedCtorInitExpr>(S), Pred,
- Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::CallExprClass:
+ case Stmt::CXXMemberCallExprClass:
+ case Stmt::UserDefinedLiteralClass:
+ Bldr.takeNodes(Pred);
+ VisitCallExpr(cast<CallExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::CXXNewExprClass: {
- Bldr.takeNodes(Pred);
+ case Stmt::CXXCatchStmtClass:
+ Bldr.takeNodes(Pred);
+ VisitCXXCatchStmt(cast<CXXCatchStmt>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- ExplodedNodeSet PreVisit;
- getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+ case Stmt::CXXTemporaryObjectExprClass:
+ case Stmt::CXXConstructExprClass:
+ Bldr.takeNodes(Pred);
+ VisitCXXConstructExpr(cast<CXXConstructExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- ExplodedNodeSet PostVisit;
- for (const auto i : PreVisit)
- VisitCXXNewExpr(cast<CXXNewExpr>(S), i, PostVisit);
+ case Stmt::CXXInheritedCtorInitExprClass:
+ Bldr.takeNodes(Pred);
+ VisitCXXInheritedCtorInitExpr(cast<CXXInheritedCtorInitExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
- Bldr.addNodes(Dst);
- break;
- }
+ case Stmt::CXXNewExprClass: {
+ Bldr.takeNodes(Pred);
- case Stmt::CXXDeleteExprClass: {
- Bldr.takeNodes(Pred);
- ExplodedNodeSet PreVisit;
- const auto *CDE = cast<CXXDeleteExpr>(S);
- getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
- ExplodedNodeSet PostVisit;
- getCheckerManager().runCheckersForPostStmt(PostVisit, PreVisit, S, *this);
+ ExplodedNodeSet PreVisit;
+ getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
- for (const auto i : PostVisit)
- VisitCXXDeleteExpr(CDE, i, Dst);
+ ExplodedNodeSet PostVisit;
+ for (const auto i : PreVisit)
+ VisitCXXNewExpr(cast<CXXNewExpr>(S), i, PostVisit);
- Bldr.addNodes(Dst);
- break;
- }
- // FIXME: ChooseExpr is really a constant. We need to fix
- // the CFG do not model them as explicit control-flow.
+ getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
+ Bldr.addNodes(Dst);
+ break;
+ }
- case Stmt::ChooseExprClass: { // __builtin_choose_expr
- Bldr.takeNodes(Pred);
- const auto *C = cast<ChooseExpr>(S);
- VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
- }
+ case Stmt::CXXDeleteExprClass: {
+ Bldr.takeNodes(Pred);
+ ExplodedNodeSet PreVisit;
+ const auto *CDE = cast<CXXDeleteExpr>(S);
+ getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+ ExplodedNodeSet PostVisit;
+ getCheckerManager().runCheckersForPostStmt(PostVisit, PreVisit, S, *this);
- case Stmt::CompoundAssignOperatorClass:
- Bldr.takeNodes(Pred);
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ for (const auto i : PostVisit)
+ VisitCXXDeleteExpr(CDE, i, Dst);
- case Stmt::CompoundLiteralExprClass:
- Bldr.takeNodes(Pred);
- VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ Bldr.addNodes(Dst);
+ break;
+ }
+ // FIXME: ChooseExpr is really a constant. We need to fix
+ // the CFG do not model them as explicit control-flow.
- case Stmt::BinaryConditionalOperatorClass:
- case Stmt::ConditionalOperatorClass: { // '?' operator
- Bldr.takeNodes(Pred);
- const auto *C = cast<AbstractConditionalOperator>(S);
- VisitGuardedExpr(C, C->getTrueExpr(), C->getFalseExpr(), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
- }
+ case Stmt::ChooseExprClass: { // __builtin_choose_expr
+ Bldr.takeNodes(Pred);
+ const auto *C = cast<ChooseExpr>(S);
+ VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
+ }
- case Stmt::CXXThisExprClass:
- Bldr.takeNodes(Pred);
- VisitCXXThisExpr(cast<CXXThisExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::CompoundAssignOperatorClass:
+ Bldr.takeNodes(Pred);
+ VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::DeclRefExprClass: {
- Bldr.takeNodes(Pred);
- const auto *DE = cast<DeclRefExpr>(S);
- VisitCommonDeclRefExpr(DE, DE->getDecl(), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
- }
+ case Stmt::CompoundLiteralExprClass:
+ Bldr.takeNodes(Pred);
+ VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::DeclStmtClass:
- Bldr.takeNodes(Pred);
- VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::BinaryConditionalOperatorClass:
+ case Stmt::ConditionalOperatorClass: { // '?' operator
+ Bldr.takeNodes(Pred);
+ const auto *C = cast<AbstractConditionalOperator>(S);
+ VisitGuardedExpr(C, C->getTrueExpr(), C->getFalseExpr(), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
+ }
- case Stmt::ImplicitCastExprClass:
- case Stmt::CStyleCastExprClass:
- case Stmt::CXXStaticCastExprClass:
- case Stmt::CXXDynamicCastExprClass:
- case Stmt::CXXReinterpretCastExprClass:
- case Stmt::CXXConstCastExprClass:
- case Stmt::CXXFunctionalCastExprClass:
- case Stmt::BuiltinBitCastExprClass:
- case Stmt::ObjCBridgedCastExprClass:
- case Stmt::CXXAddrspaceCastExprClass: {
- Bldr.takeNodes(Pred);
- const auto *C = cast<CastExpr>(S);
- ExplodedNodeSet dstExpr;
- VisitCast(C, C->getSubExpr(), Pred, dstExpr);
+ case Stmt::CXXThisExprClass:
+ Bldr.takeNodes(Pred);
+ VisitCXXThisExpr(cast<CXXThisExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- // Handle the postvisit checks.
- getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, C, *this);
- Bldr.addNodes(Dst);
- break;
- }
+ case Stmt::DeclRefExprClass: {
+ Bldr.takeNodes(Pred);
+ const auto *DE = cast<DeclRefExpr>(S);
+ VisitCommonDeclRefExpr(DE, DE->getDecl(), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
+ }
- case Expr::MaterializeTemporaryExprClass: {
- Bldr.takeNodes(Pred);
- const auto *MTE = cast<MaterializeTemporaryExpr>(S);
- ExplodedNodeSet dstPrevisit;
- getCheckerManager().runCheckersForPreStmt(dstPrevisit, Pred, MTE, *this);
- ExplodedNodeSet dstExpr;
- for (const auto i : dstPrevisit)
- CreateCXXTemporaryObject(MTE, i, dstExpr);
- getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, MTE, *this);
- Bldr.addNodes(Dst);
- break;
- }
+ case Stmt::DeclStmtClass:
+ Bldr.takeNodes(Pred);
+ VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::InitListExprClass:
- Bldr.takeNodes(Pred);
- VisitInitListExpr(cast<InitListExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::ImplicitCastExprClass:
+ case Stmt::CStyleCastExprClass:
+ case Stmt::CXXStaticCastExprClass:
+ case Stmt::CXXDynamicCastExprClass:
+ case Stmt::CXXReinterpretCastExprClass:
+ case Stmt::CXXConstCastExprClass:
+ case Stmt::CXXFunctionalCastExprClass:
+ case Stmt::BuiltinBitCastExprClass:
+ case Stmt::ObjCBridgedCastExprClass:
+ case Stmt::CXXAddrspaceCastExprClass: {
+ Bldr.takeNodes(Pred);
+ const auto *C = cast<CastExpr>(S);
+ ExplodedNodeSet dstExpr;
+ VisitCast(C, C->getSubExpr(), Pred, dstExpr);
+
+ // Handle the postvisit checks.
+ getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, C, *this);
+ Bldr.addNodes(Dst);
+ break;
+ }
- case Stmt::MemberExprClass:
- Bldr.takeNodes(Pred);
- VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Expr::MaterializeTemporaryExprClass: {
+ Bldr.takeNodes(Pred);
+ const auto *MTE = cast<MaterializeTemporaryExpr>(S);
+ ExplodedNodeSet dstPrevisit;
+ getCheckerManager().runCheckersForPreStmt(dstPrevisit, Pred, MTE, *this);
+ ExplodedNodeSet dstExpr;
+ for (const auto i : dstPrevisit)
+ CreateCXXTemporaryObject(MTE, i, dstExpr);
+ getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, MTE, *this);
+ Bldr.addNodes(Dst);
+ break;
+ }
- case Stmt::AtomicExprClass:
- Bldr.takeNodes(Pred);
- VisitAtomicExpr(cast<AtomicExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::InitListExprClass:
+ Bldr.takeNodes(Pred);
+ VisitInitListExpr(cast<InitListExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::ObjCIvarRefExprClass:
- Bldr.takeNodes(Pred);
- VisitLvalObjCIvarRefExpr(cast<ObjCIvarRefExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::MemberExprClass:
+ Bldr.takeNodes(Pred);
+ VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::ObjCForCollectionStmtClass:
- Bldr.takeNodes(Pred);
- VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::AtomicExprClass:
+ Bldr.takeNodes(Pred);
+ VisitAtomicExpr(cast<AtomicExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::ObjCMessageExprClass:
- Bldr.takeNodes(Pred);
- VisitObjCMessage(cast<ObjCMessageExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::ObjCIvarRefExprClass:
+ Bldr.takeNodes(Pred);
+ VisitLvalObjCIvarRefExpr(cast<ObjCIvarRefExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::ObjCAtThrowStmtClass:
- case Stmt::CXXThrowExprClass:
- // FIXME: This is not complete. We basically treat @throw as
- // an abort.
- Bldr.generateSink(S, Pred, Pred->getState());
- break;
+ case Stmt::ObjCForCollectionStmtClass:
+ Bldr.takeNodes(Pred);
+ VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::ReturnStmtClass:
- Bldr.takeNodes(Pred);
- VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::ObjCMessageExprClass:
+ Bldr.takeNodes(Pred);
+ VisitObjCMessage(cast<ObjCMessageExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::OffsetOfExprClass: {
- Bldr.takeNodes(Pred);
- ExplodedNodeSet PreVisit;
- getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+ case Stmt::ObjCAtThrowStmtClass:
+ case Stmt::CXXThrowExprClass:
+ // FIXME: This is not complete. We basically treat @throw as
+ // an abort.
+ Bldr.generateSink(S, Pred, Pred->getState());
+ break;
- ExplodedNodeSet PostVisit;
- for (const auto Node : PreVisit)
- VisitOffsetOfExpr(cast<OffsetOfExpr>(S), Node, PostVisit);
+ case Stmt::ReturnStmtClass:
+ Bldr.takeNodes(Pred);
+ VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
- Bldr.addNodes(Dst);
- break;
- }
+ case Stmt::OffsetOfExprClass: {
+ Bldr.takeNodes(Pred);
+ ExplodedNodeSet PreVisit;
+ getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
- case Stmt::UnaryExprOrTypeTraitExprClass:
- Bldr.takeNodes(Pred);
- VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
- Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ ExplodedNodeSet PostVisit;
+ for (const auto Node : PreVisit)
+ VisitOffsetOfExpr(cast<OffsetOfExpr>(S), Node, PostVisit);
- case Stmt::StmtExprClass: {
- const auto *SE = cast<StmtExpr>(S);
+ getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
+ Bldr.addNodes(Dst);
+ break;
+ }
- if (SE->getSubStmt()->body_empty()) {
- // Empty statement expression.
- assert(SE->getType() == getContext().VoidTy
- && "Empty statement expression must have void type.");
- break;
- }
+ case Stmt::UnaryExprOrTypeTraitExprClass:
+ Bldr.takeNodes(Pred);
+ VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- if (const auto *LastExpr =
- dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
- ProgramStateRef state = Pred->getState();
- Bldr.generateNode(SE, Pred,
- state->BindExpr(SE, Pred->getLocationContext(),
- state->getSVal(LastExpr,
- Pred->getLocationContext())));
- }
- break;
- }
+ case Stmt::StmtExprClass: {
+ const auto *SE = cast<StmtExpr>(S);
- case Stmt::UnaryOperatorClass: {
- Bldr.takeNodes(Pred);
- const auto *U = cast<UnaryOperator>(S);
- if (AMgr.options.ShouldEagerlyAssume && (U->getOpcode() == UO_LNot)) {
- ExplodedNodeSet Tmp;
- VisitUnaryOperator(U, Pred, Tmp);
- evalEagerlyAssumeBinOpBifurcation(Dst, Tmp, U);
- }
- else
- VisitUnaryOperator(U, Pred, Dst);
- Bldr.addNodes(Dst);
+ if (SE->getSubStmt()->body_empty()) {
+ // Empty statement expression.
+ assert(SE->getType() == getContext().VoidTy &&
+ "Empty statement expression must have void type.");
break;
}
- case Stmt::PseudoObjectExprClass: {
- Bldr.takeNodes(Pred);
+ if (const auto *LastExpr =
+ dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
ProgramStateRef state = Pred->getState();
- const auto *PE = cast<PseudoObjectExpr>(S);
- if (const Expr *Result = PE->getResultExpr()) {
- SVal V = state->getSVal(Result, Pred->getLocationContext());
- Bldr.generateNode(S, Pred,
- state->BindExpr(S, Pred->getLocationContext(), V));
- }
- else
- Bldr.generateNode(S, Pred,
- state->BindExpr(S, Pred->getLocationContext(),
- UnknownVal()));
-
- Bldr.addNodes(Dst);
- break;
+ Bldr.generateNode(
+ SE, Pred,
+ state->BindExpr(
+ SE, Pred->getLocationContext(),
+ state->getSVal(LastExpr, Pred->getLocationContext())));
}
+ break;
+ }
- case Expr::ObjCIndirectCopyRestoreExprClass: {
- // ObjCIndirectCopyRestoreExpr implies passing a temporary for
- // correctness of lifetime management. Due to limited analysis
- // of ARC, this is implemented as direct arg passing.
- Bldr.takeNodes(Pred);
- ProgramStateRef state = Pred->getState();
- const auto *OIE = cast<ObjCIndirectCopyRestoreExpr>(S);
- const Expr *E = OIE->getSubExpr();
- SVal V = state->getSVal(E, Pred->getLocationContext());
+ case Stmt::UnaryOperatorClass: {
+ Bldr.takeNodes(Pred);
+ const auto *U = cast<UnaryOperator>(S);
+ if (AMgr.options.ShouldEagerlyAssume && (U->getOpcode() == UO_LNot)) {
+ ExplodedNodeSet Tmp;
+ VisitUnaryOperator(U, Pred, Tmp);
+ evalEagerlyAssumeBinOpBifurcation(Dst, Tmp, U);
+ } else
+ VisitUnaryOperator(U, Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
+ }
+
+ case Stmt::PseudoObjectExprClass: {
+ Bldr.takeNodes(Pred);
+ ProgramStateRef state = Pred->getState();
+ const auto *PE = cast<PseudoObjectExpr>(S);
+ if (const Expr *Result = PE->getResultExpr()) {
+ SVal V = state->getSVal(Result, Pred->getLocationContext());
Bldr.generateNode(S, Pred,
- state->BindExpr(S, Pred->getLocationContext(), V));
- Bldr.addNodes(Dst);
- break;
- }
+ state->BindExpr(S, Pred->getLocationContext(), V));
+ } else
+ Bldr.generateNode(
+ S, Pred,
+ state->BindExpr(S, Pred->getLocationContext(), UnknownVal()));
+
+ Bldr.addNodes(Dst);
+ break;
+ }
+
+ case Expr::ObjCIndirectCopyRestoreExprClass: {
+ // ObjCIndirectCopyRestoreExpr implies passing a temporary for
+ // correctness of lifetime management. Due to limited analysis
+ // of ARC, this is implemented as direct arg passing.
+ Bldr.takeNodes(Pred);
+ ProgramStateRef state = Pred->getState();
+ const auto *OIE = cast<ObjCIndirectCopyRestoreExpr>(S);
+ const Expr *E = OIE->getSubExpr();
+ SVal V = state->getSVal(E, Pred->getLocationContext());
+ Bldr.generateNode(S, Pred,
+ state->BindExpr(S, Pred->getLocationContext(), V));
+ Bldr.addNodes(Dst);
+ break;
+ }
}
}
@@ -2470,7 +2453,7 @@ bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
// Note, changing the state ensures that we are not going to cache out.
ProgramStateRef NewNodeState = BeforeProcessingCall->getState();
NewNodeState =
- NewNodeState->set<ReplayWithoutInlining>(const_cast<Stmt *>(CE));
+ NewNodeState->set<ReplayWithoutInlining>(const_cast<Stmt *>(CE));
// Make the new node a successor of BeforeProcessingCall.
bool IsNew = false;
@@ -2484,7 +2467,7 @@ bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
// Add the new node to the work list.
Engine.enqueueStmtNode(NewNode, CalleeSF->getCallSiteBlock(),
- CalleeSF->getIndex());
+ CalleeSF->getIndex());
NumTimesRetriedWithoutInlining++;
return true;
}
@@ -2496,7 +2479,7 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
// If we reach a loop which has a known bound (and meets
// other constraints) then consider completely unrolling it.
- if(AMgr.options.ShouldUnrollLoops) {
+ if (AMgr.options.ShouldUnrollLoops) {
unsigned maxBlockVisitOnPath = AMgr.options.maxBlockVisitOnPath;
const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminatorStmt();
if (Term) {
@@ -2510,7 +2493,7 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
}
}
// Is we are inside an unrolled loop then no need the check the counters.
- if(isUnrolledState(Pred->getState()))
+ if (isUnrolledState(Pred->getState()))
return;
}
@@ -2534,14 +2517,14 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
if (BlockCount >= AMgr.options.maxBlockVisitOnPath) {
static SimpleProgramPointTag tag(TagProviderName, "Block count exceeded");
const ExplodedNode *Sink =
- nodeBuilder.generateSink(Pred->getState(), Pred, &tag);
+ nodeBuilder.generateSink(Pred->getState(), Pred, &tag);
// Check if we stopped at the top level function or not.
// Root node should have the location context of the top most function.
const LocationContext *CalleeLC = Pred->getLocation().getLocationContext();
const LocationContext *CalleeSF = CalleeLC->getStackFrame();
const LocationContext *RootLC =
- (*G.roots_begin())->getLocation().getLocationContext();
+ (*G.roots_begin())->getLocation().getLocationContext();
if (RootLC->getStackFrame() != CalleeSF) {
Engine.FunctionSummaries->markReachedMaxBlockCount(CalleeSF->getDecl());
@@ -2570,10 +2553,8 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
/// integers that promote their values (which are currently not tracked well).
/// This function returns the SVal bound to Condition->IgnoreCasts if all the
// cast(s) did was sign-extend the original value.
-static SVal RecoverCastedSymbol(ProgramStateRef state,
- const Stmt *Condition,
- const LocationContext *LCtx,
- ASTContext &Ctx) {
+static SVal RecoverCastedSymbol(ProgramStateRef state, const Stmt *Condition,
+ const LocationContext *LCtx, ASTContext &Ctx) {
const auto *Ex = dyn_cast<Expr>(Condition);
if (!Ex)
@@ -2634,8 +2615,7 @@ static const Stmt *getRightmostLeaf(const Stmt *Condition) {
// not evaluated, and is thus not in the SVal cache, we need to use that leaf
// expression to evaluate the truth value of the condition in the current state
// space.
-static const Stmt *ResolveCondition(const Stmt *Condition,
- const CFGBlock *B) {
+static const Stmt *ResolveCondition(const Stmt *Condition, const CFGBlock *B) {
if (const auto *Ex = dyn_cast<Expr>(Condition))
Condition = Ex->IgnoreParens();
@@ -2677,10 +2657,9 @@ ProgramStateRef ExprEngine::setWhetherHasMoreIteration(
return State->set<ObjCForHasMoreIterations>({O, LC}, HasMoreIteraton);
}
-ProgramStateRef
-ExprEngine::removeIterationState(ProgramStateRef State,
- const ObjCForCollectionStmt *O,
- const LocationContext *LC) {
+ProgramStateRef ExprEngine::removeIterationState(ProgramStateRef State,
+ const ObjCForCollectionStmt *O,
+ const LocationContext *LC) {
assert(State->contains<ObjCForHasMoreIterations>({O, LC}));
return State->remove<ObjCForHasMoreIterations>({O, LC});
}
@@ -2743,10 +2722,8 @@ assumeCondition(const Stmt *Condition, ExplodedNode *N) {
}
void ExprEngine::processBranch(const Stmt *Condition,
- NodeBuilderContext& BldCtx,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst,
- const CFGBlock *DstT,
+ NodeBuilderContext &BldCtx, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst, const CFGBlock *DstT,
const CFGBlock *DstF) {
assert((!Condition || !isa<CXXBindTemporaryExpr>(Condition)) &&
"CXXBindTemporaryExprs are handled by processBindTemporary.");
@@ -2820,12 +2797,9 @@ void ExprEngine::processBranch(const Stmt *Condition,
REGISTER_TRAIT_WITH_PROGRAMSTATE(InitializedGlobalsSet,
llvm::ImmutableSet<const VarDecl *>)
-void ExprEngine::processStaticInitializer(const DeclStmt *DS,
- NodeBuilderContext &BuilderCtx,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst,
- const CFGBlock *DstT,
- const CFGBlock *DstF) {
+void ExprEngine::processStaticInitializer(
+ const DeclStmt *DS, NodeBuilderContext &BuilderCtx, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF) {
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
currBldrCtx = &BuilderCtx;
@@ -2874,7 +2848,7 @@ void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
if (isa<UndefinedVal, loc::ConcreteInt>(V)) {
// Dispatch to the first target and mark it as a sink.
- //ExplodedNode* N = builder.generateNode(builder.begin(), state, true);
+ // ExplodedNode* N = builder.generateNode(builder.begin(), state, true);
// FIXME: add checker visit.
// UndefBranches.insert(N);
return;
@@ -2897,7 +2871,7 @@ void ExprEngine::processBeginOfFunction(NodeBuilderContext &BC,
/// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path
/// nodes when the control reaches the end of a function.
-void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
+void ExprEngine::processEndOfFunction(NodeBuilderContext &BC,
ExplodedNode *Pred,
const ReturnStmt *RS) {
ProgramStateRef State = Pred->getState();
@@ -2971,17 +2945,17 @@ void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
/// ProcessSwitch - Called by CoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a switch statement.
-void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
+void ExprEngine::processSwitch(SwitchNodeBuilder &builder) {
using iterator = SwitchNodeBuilder::iterator;
ProgramStateRef state = builder.getState();
const Expr *CondE = builder.getCondition();
- SVal CondV_untested = state->getSVal(CondE, builder.getLocationContext());
+ SVal CondV_untested = state->getSVal(CondE, builder.getLocationContext());
if (CondV_untested.isUndef()) {
- //ExplodedNode* N = builder.generateDefaultCaseNode(state, true);
- // FIXME: add checker
- //UndefBranches.insert(N);
+ // ExplodedNode* N = builder.generateDefaultCaseNode(state, true);
+ // FIXME: add checker
+ // UndefBranches.insert(N);
return;
}
@@ -2992,7 +2966,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
iterator I = builder.begin(), EI = builder.end();
bool defaultIsFeasible = I == EI;
- for ( ; I != EI; ++I) {
+ for (; I != EI; ++I) {
// Successor may be pruned out during CFG construction.
if (!I.getBlock())
continue;
@@ -3084,8 +3058,7 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
// Sema follows a sequence of complex rules to determine whether the
// variable should be captured.
if (const FieldDecl *FD = LambdaCaptureFields[VD]) {
- Loc CXXThis =
- svalBuilder.getCXXThis(MD, LocCtxt->getStackFrame());
+ Loc CXXThis = svalBuilder.getCXXThis(MD, LocCtxt->getStackFrame());
SVal CXXThisVal = state->getSVal(CXXThis);
VInfo = std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType());
}
@@ -3293,10 +3266,10 @@ void ExprEngine::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *Ex,
/// VisitArraySubscriptExpr - Transfer function for array accesses
void ExprEngine::VisitArraySubscriptExpr(const ArraySubscriptExpr *A,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst){
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
const Expr *Base = A->getBase()->IgnoreParens();
- const Expr *Idx = A->getIdx()->IgnoreParens();
+ const Expr *Idx = A->getIdx()->IgnoreParens();
ExplodedNodeSet CheckerPreStmt;
getCheckerManager().runCheckersForPreStmt(CheckerPreStmt, Pred, A, *this);
@@ -3309,8 +3282,9 @@ void ExprEngine::VisitArraySubscriptExpr(const ArraySubscriptExpr *A,
// The "like" case is for situations where C standard prohibits the type to
// be an lvalue, e.g. taking the address of a subscript of an expression of
// type "void *".
- bool IsGLValueLike = A->isGLValue() ||
- (A->getType().isCForbiddenLValueType() && !AMgr.getLangOpts().CPlusPlus);
+ bool IsGLValueLike =
+ A->isGLValue() ||
+ (A->getType().isCForbiddenLValueType() && !AMgr.getLangOpts().CPlusPlus);
for (auto *Node : CheckerPreStmt) {
const LocationContext *LCtx = Node->getLocationContext();
@@ -3325,11 +3299,10 @@ void ExprEngine::VisitArraySubscriptExpr(const ArraySubscriptExpr *A,
if (T->isVoidType())
T = getContext().CharTy;
- SVal V = state->getLValue(T,
- state->getSVal(Idx, LCtx),
+ SVal V = state->getLValue(T, state->getSVal(Idx, LCtx),
state->getSVal(Base, LCtx));
Bldr.generateNode(A, Node, state->BindExpr(A, LCtx, V), nullptr,
- ProgramPoint::PostLValueKind);
+ ProgramPoint::PostLValueKind);
} else if (IsVectorType) {
// FIXME: non-glvalue vector reads are not modelled.
Bldr.generateNode(A, Node, state, nullptr);
@@ -3404,8 +3377,8 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
// pointers as soon as they are used.
if (!M->isGLValue()) {
assert(M->getType()->isArrayType());
- const auto *PE =
- dyn_cast<ImplicitCastExpr>(I->getParentMap().getParentIgnoreParens(M));
+ const auto *PE = dyn_cast<ImplicitCastExpr>(
+ I->getParentMap().getParentIgnoreParens(M));
if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {
llvm_unreachable("should always be wrapped in ArrayToPointerDecay");
}
@@ -3454,18 +3427,17 @@ void ExprEngine::VisitAtomicExpr(const AtomicExpr *AE, ExplodedNode *Pred,
}
State = State->invalidateRegions(ValuesToInvalidate, AE,
- currBldrCtx->blockCount(),
- LCtx,
- /*CausedByPointerEscape*/true,
- /*Symbols=*/nullptr);
+ currBldrCtx->blockCount(), LCtx,
+ /*CausedByPointerEscape*/ true,
+ /*Symbols=*/nullptr);
SVal ResultVal = UnknownVal();
State = State->BindExpr(AE, LCtx, ResultVal);
- Bldr.generateNode(AE, I, State, nullptr,
- ProgramPoint::PostStmtKind);
+ Bldr.generateNode(AE, I, State, nullptr, ProgramPoint::PostStmtKind);
}
- getCheckerManager().runCheckersForPostStmt(Dst, AfterInvalidateSet, AE, *this);
+ getCheckerManager().runCheckersForPostStmt(Dst, AfterInvalidateSet, AE,
+ *this);
}
// A value escapes in four possible cases:
@@ -3524,21 +3496,16 @@ ExprEngine::processPointerEscapedOnBind(ProgramStateRef State, SVal Loc,
nullptr);
}
-ProgramStateRef
-ExprEngine::notifyCheckersOfPointerEscape(ProgramStateRef State,
- const InvalidatedSymbols *Invalidated,
- ArrayRef<const MemRegion *> ExplicitRegions,
- const CallEvent *Call,
+ProgramStateRef ExprEngine::notifyCheckersOfPointerEscape(
+ ProgramStateRef State, const InvalidatedSymbols *Invalidated,
+ ArrayRef<const MemRegion *> ExplicitRegions, const CallEvent *Call,
RegionAndSymbolInvalidationTraits &ITraits) {
if (!Invalidated || Invalidated->empty())
return State;
if (!Call)
- return getCheckerManager().runCheckersForPointerEscape(State,
- *Invalidated,
- nullptr,
- PSK_EscapeOther,
- &ITraits);
+ return getCheckerManager().runCheckersForPointerEscape(
+ State, *Invalidated, nullptr, PSK_EscapeOther, &ITraits);
// If the symbols were invalidated by a call, we want to find out which ones
// were invalidated directly due to being arguments to the call.
@@ -3556,13 +3523,15 @@ ExprEngine::notifyCheckersOfPointerEscape(ProgramStateRef State,
}
if (!SymbolsDirectlyInvalidated.empty())
- State = getCheckerManager().runCheckersForPointerEscape(State,
- SymbolsDirectlyInvalidated, Call, PSK_DirectEscapeOnCall, &ITraits);
+ State = getCheckerManager().runCheckersForPointerEscape(
+ State, SymbolsDirectlyInvalidated, Call, PSK_DirectEscapeOnCall,
+ &ITraits);
// Notify about the symbols that get indirectly invalidated by the call.
if (!SymbolsIndirectlyInvalidated.empty())
- State = getCheckerManager().runCheckersForPointerEscape(State,
- SymbolsIndirectlyInvalidated, Call, PSK_IndirectEscapeOnCall, &ITraits);
+ State = getCheckerManager().runCheckersForPointerEscape(
+ State, SymbolsIndirectlyInvalidated, Call, PSK_IndirectEscapeOnCall,
+ &ITraits);
return State;
}
@@ -3570,8 +3539,7 @@ ExprEngine::notifyCheckersOfPointerEscape(ProgramStateRef State,
/// evalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by evalStore and (soon) VisitDeclStmt, and others.
void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
- ExplodedNode *Pred,
- SVal location, SVal Val,
+ ExplodedNode *Pred, SVal location, SVal Val,
bool atDeclInit, const ProgramPoint *PP) {
const LocationContext *LC = Pred->getLocationContext();
PostStmt PS(StoreE, LC);
@@ -3588,8 +3556,8 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
// If the location is not a 'Loc', it will already be handled by
// the checkers. There is nothing left to do.
if (!isa<Loc>(location)) {
- const ProgramPoint L = PostStore(StoreE, LC, /*Loc*/nullptr,
- /*tag*/nullptr);
+ const ProgramPoint L = PostStore(StoreE, LC, /*Loc*/ nullptr,
+ /*tag*/ nullptr);
ProgramStateRef state = Pred->getState();
state = processPointerEscapedOnBind(state, location, Val, LC);
Bldr.generateNode(L, state, Pred);
@@ -3604,8 +3572,8 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
// When binding the value, pass on the hint that this is a initialization.
// For initializations, we do not need to inform clients of region
// changes.
- state = state->bindLoc(location.castAs<Loc>(),
- Val, LC, /* notifyChanges = */ !atDeclInit);
+ state = state->bindLoc(location.castAs<Loc>(), Val, LC,
+ /* notifyChanges = */ !atDeclInit);
const MemRegion *LocReg = nullptr;
if (std::optional<loc::MemRegionVal> LocRegVal =
@@ -3627,10 +3595,9 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
/// @param location The location to store the value
/// @param Val The value to be stored
void ExprEngine::evalStore(ExplodedNodeSet &Dst, const Expr *AssignE,
- const Expr *LocationE,
- ExplodedNode *Pred,
- ProgramStateRef state, SVal location, SVal Val,
- const ProgramPointTag *tag) {
+ const Expr *LocationE, ExplodedNode *Pred,
+ ProgramStateRef state, SVal location, SVal Val,
+ const ProgramPointTag *tag) {
// Proceed with the store. We use AssignE as the anchor for the PostStore
// ProgramPoint if it is non-NULL, and LocationE otherwise.
const Expr *StoreE = AssignE ? AssignE : LocationE;
@@ -3649,14 +3616,10 @@ void ExprEngine::evalStore(ExplodedNodeSet &Dst, const Expr *AssignE,
evalBind(Dst, StoreE, I, location, Val, false);
}
-void ExprEngine::evalLoad(ExplodedNodeSet &Dst,
- const Expr *NodeEx,
- const Expr *BoundEx,
- ExplodedNode *Pred,
- ProgramStateRef state,
- SVal location,
- const ProgramPointTag *tag,
- QualType LoadTy) {
+void ExprEngine::evalLoad(ExplodedNodeSet &Dst, const Expr *NodeEx,
+ const Expr *BoundEx, ExplodedNode *Pred,
+ ProgramStateRef state, SVal location,
+ const ProgramPointTag *tag, QualType LoadTy) {
assert(!isa<NonLoc>(location) && "location cannot be a NonLoc.");
assert(NodeEx);
assert(BoundEx);
@@ -3687,12 +3650,9 @@ void ExprEngine::evalLoad(ExplodedNodeSet &Dst,
}
}
-void ExprEngine::evalLocation(ExplodedNodeSet &Dst,
- const Stmt *NodeEx,
- const Stmt *BoundEx,
- ExplodedNode *Pred,
- ProgramStateRef state,
- SVal location,
+void ExprEngine::evalLocation(ExplodedNodeSet &Dst, const Stmt *NodeEx,
+ const Stmt *BoundEx, ExplodedNode *Pred,
+ ProgramStateRef state, SVal location,
bool isLoad) {
StmtNodeBuilder BldrTop(Pred, Dst, *currBldrCtx);
// Early checks for performance reason.
@@ -3717,18 +3677,17 @@ void ExprEngine::evalLocation(ExplodedNodeSet &Dst,
Bldr.generateNode(NodeEx, Pred, state, &tag);
}
ExplodedNodeSet Tmp;
- getCheckerManager().runCheckersForLocation(Tmp, Src, location, isLoad,
- NodeEx, BoundEx, *this);
+ getCheckerManager().runCheckersForLocation(Tmp, Src, location, isLoad, NodeEx,
+ BoundEx, *this);
BldrTop.addNodes(Tmp);
}
-std::pair<const ProgramPointTag *, const ProgramPointTag*>
+std::pair<const ProgramPointTag *, const ProgramPointTag *>
ExprEngine::geteagerlyAssumeBinOpBifurcationTags() {
- static SimpleProgramPointTag
- eagerlyAssumeBinOpBifurcationTrue(TagProviderName,
- "Eagerly Assume True"),
- eagerlyAssumeBinOpBifurcationFalse(TagProviderName,
- "Eagerly Assume False");
+ static SimpleProgramPointTag eagerlyAssumeBinOpBifurcationTrue(
+ TagProviderName, "Eagerly Assume True"),
+ eagerlyAssumeBinOpBifurcationFalse(TagProviderName,
+ "Eagerly Assume False");
return std::make_pair(&eagerlyAssumeBinOpBifurcationTrue,
&eagerlyAssumeBinOpBifurcationFalse);
}
@@ -3751,8 +3710,8 @@ void ExprEngine::evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst,
SVal V = state->getSVal(Ex, Pred->getLocationContext());
std::optional<nonloc::SymbolVal> SEV = V.getAs<nonloc::SymbolVal>();
if (SEV && SEV->isExpression()) {
- const std::pair<const ProgramPointTag *, const ProgramPointTag*> &tags =
- geteagerlyAssumeBinOpBifurcationTags();
+ const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags =
+ geteagerlyAssumeBinOpBifurcationTags();
ProgramStateRef StateTrue, StateFalse;
std::tie(StateTrue, StateFalse) = state->assume(*SEV);
@@ -3809,13 +3768,14 @@ void ExprEngine::VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred,
namespace llvm {
-template<>
-struct DOTGraphTraits<ExplodedGraph*> : public DefaultDOTGraphTraits {
- DOTGraphTraits (bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
+template <>
+struct DOTGraphTraits<ExplodedGraph *> : public DefaultDOTGraphTraits {
+ DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
static bool nodeHasBugReport(const ExplodedNode *N) {
BugReporter &BR = static_cast<ExprEngine &>(
- N->getState()->getStateManager().getOwningEngine()).getBugReporter();
+ N->getState()->getStateManager().getOwningEngine())
+ .getBugReporter();
for (const auto &Class : BR.equivalenceClasses()) {
for (const auto &Report : Class.getReports()) {
@@ -3858,7 +3818,7 @@ struct DOTGraphTraits<ExplodedGraph*> : public DefaultDOTGraphTraits {
return N->isTrivial();
}
- static std::string getNodeLabel(const ExplodedNode *N, ExplodedGraph *G){
+ static std::string getNodeLabel(const ExplodedNode *N, ExplodedGraph *G) {
std::string Buf;
llvm::raw_string_ostream Out(Buf);
@@ -3866,8 +3826,7 @@ struct DOTGraphTraits<ExplodedGraph*> : public DefaultDOTGraphTraits {
const unsigned int Space = 1;
ProgramStateRef State = N->getState();
- Out << "{ \"state_id\": " << State->getID()
- << ",\\l";
+ Out << "{ \"state_id\": " << State->getID() << ",\\l";
Indent(Out, Space, IsDot) << "\"program_points\": [\\l";
@@ -3882,9 +3841,9 @@ struct DOTGraphTraits<ExplodedGraph*> : public DefaultDOTGraphTraits {
Out << '\"' << Tag->getTagDescription() << '\"';
else
Out << "null";
- Out << ", \"node_id\": " << OtherNode->getID() <<
- ", \"is_sink\": " << OtherNode->isSink() <<
- ", \"has_report\": " << nodeHasBugReport(OtherNode) << " }";
+ Out << ", \"node_id\": " << OtherNode->getID()
+ << ", \"is_sink\": " << OtherNode->isSink()
+ << ", \"has_report\": " << nodeHasBugReport(OtherNode) << " }";
},
// Adds a comma and a new-line between each program point.
[&](const ExplodedNode *) { Out << ",\\l"; },
@@ -3953,4 +3912,4 @@ void *ProgramStateTrait<ReplayWithoutInlining>::GDMIndex() {
return &index;
}
-void ExprEngine::anchor() { }
+void ExprEngine::anchor() {}
diff --git a/clang/unittests/StaticAnalyzer/CMakeLists.txt b/clang/unittests/StaticAnalyzer/CMakeLists.txt
index ff34d5747cc81..e6cddc18905b9 100644
--- a/clang/unittests/StaticAnalyzer/CMakeLists.txt
+++ b/clang/unittests/StaticAnalyzer/CMakeLists.txt
@@ -10,6 +10,7 @@ add_clang_unittest(StaticAnalysisTests
CallDescriptionTest.cpp
CallEventTest.cpp
ConflictingEvalCallsTest.cpp
+ ExprEngineVisitTest.cpp
FalsePositiveRefutationBRVisitorTest.cpp
IsCLibraryFunctionTest.cpp
MemRegionDescriptiveNameTest.cpp
diff --git a/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp b/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp
new file mode 100644
index 0000000000000..b5d25e98dba55
--- /dev/null
+++ b/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp
@@ -0,0 +1,92 @@
+//===- ExprEngineVisitTest.cpp -----------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "CheckerRegistration.h"
+#include "clang/AST/Stmt.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+void emitErrorReport(CheckerContext &C, const BugType &Bug,
+ const std::string &Desc) {
+ if (ExplodedNode *Node = C.generateNonFatalErrorNode(C.getState())) {
+ auto Report = std::make_unique<PathSensitiveBugReport>(Bug, Desc, Node);
+ C.emitReport(std::move(Report));
+ }
+}
+
+class ExprEngineVisitPreChecker : public Checker<check::PreStmt<GCCAsmStmt>> {
+public:
+ void checkPreStmt(const GCCAsmStmt *ASM, CheckerContext &C) const {
+ emitErrorReport(C, Bug, "PreStmt<GCCAsmStmt>");
+ }
+
+private:
+ const BugType Bug{this, "GCCAsmStmtBug"};
+};
+
+class ExprEngineVisitPostChecker : public Checker<check::PostStmt<GCCAsmStmt>> {
+public:
+ void checkPostStmt(const GCCAsmStmt *ASM, CheckerContext &C) const {
+ emitErrorReport(C, Bug, "PostStmt<GCCAsmStmt>");
+ }
+
+private:
+ const BugType Bug{this, "GCCAsmStmtBug"};
+};
+
+void addExprEngineVisitPreChecker(AnalysisASTConsumer &AnalysisConsumer,
+ AnalyzerOptions &AnOpts) {
+ AnOpts.CheckersAndPackages = {{"ExprEngineVisitPreChecker", true}};
+ AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
+ Registry.addChecker<ExprEngineVisitPreChecker>("ExprEngineVisitPreChecker",
+ "Desc", "DocsURI");
+ });
+}
+
+void addExprEngineVisitPostChecker(AnalysisASTConsumer &AnalysisConsumer,
+ AnalyzerOptions &AnOpts) {
+ AnOpts.CheckersAndPackages = {{"ExprEngineVisitPostChecker", true}};
+ AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
+ Registry.addChecker<ExprEngineVisitPostChecker>(
+ "ExprEngineVisitPostChecker", "Desc", "DocsURI");
+ });
+}
+
+TEST(ExprEngineVisitTest, checkPreStmtGCCAsmStmt) {
+ std::string Diags;
+ EXPECT_TRUE(runCheckerOnCode<addExprEngineVisitPreChecker>(R"(
+ int a = 1;
+ void top() {
+ asm("");
+ }
+ )",
+ Diags));
+ EXPECT_EQ(Diags, "ExprEngineVisitPreChecker: PreStmt<GCCAsmStmt>\n");
+}
+
+TEST(ExprEngineVisitTest, checkPostStmtGCCAsmStmt) {
+ std::string Diags;
+ EXPECT_TRUE(runCheckerOnCode<addExprEngineVisitPostChecker>(R"(
+ int a = 1;
+ void top() {
+ asm("");
+ }
+ )",
+ Diags));
+ EXPECT_EQ(Diags, "ExprEngineVisitPostChecker: PostStmt<GCCAsmStmt>\n");
+}
+
+} // namespace
>From 380c80ab7bd1ee76e6620188eaafabddd39c01e7 Mon Sep 17 00:00:00 2001
From: T-Gruber <tobi.gruber at gmx.de>
Date: Thu, 13 Jun 2024 21:01:38 +0200
Subject: [PATCH 2/6] Restored format of previous commit
---
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 1598 +++++++++---------
1 file changed, 822 insertions(+), 776 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index d99fa7a132f50..4bfa0a599da67 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -89,15 +89,16 @@ using namespace ento;
#define DEBUG_TYPE "ExprEngine"
-STATISTIC(NumRemoveDeadBindings, "The # of times RemoveDeadBindings is called");
+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");
+ "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");
+ "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");
+ "The # of times we re-evaluated a call without inlining");
//===----------------------------------------------------------------------===//
// Internal program state traits.
@@ -125,7 +126,7 @@ class ConstructedObjectKey {
public:
explicit ConstructedObjectKey(const ConstructionContextItem &Item,
- const LocationContext *LC)
+ const LocationContext *LC)
: Impl(Item, LC) {}
const ConstructionContextItem &getItem() const { return Impl.first; }
@@ -215,7 +216,7 @@ REGISTER_TRAIT_WITH_PROGRAMSTATE(PendingArrayDestruction,
// Engine construction and deletion.
//===----------------------------------------------------------------------===//
-static const char *TagProviderName = "ExprEngine";
+static const char* TagProviderName = "ExprEngine";
ExprEngine::ExprEngine(cross_tu::CrossTranslationUnitContext &CTU,
AnalysisManager &mgr, SetOfConstDecls *VisitedCalleesIn,
@@ -266,9 +267,9 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {
break;
SVal V = state->getSVal(loc::MemRegionVal(R));
- SVal Constraint_untested =
- evalBinOp(state, BO_GT, V, svalBuilder.makeZeroVal(T),
- svalBuilder.getConditionType());
+ SVal Constraint_untested = evalBinOp(state, BO_GT, V,
+ svalBuilder.makeZeroVal(T),
+ svalBuilder.getConditionType());
std::optional<DefinedOrUnknownSVal> Constraint =
Constraint_untested.getAs<DefinedOrUnknownSVal>();
@@ -280,7 +281,8 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {
state = newState;
}
break;
- } while (false);
+ }
+ while (false);
if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
// Precondition: 'self' is always non-null upon entry to an Objective-C
@@ -655,23 +657,28 @@ bool ExprEngine::areAllObjectsFullyConstructed(ProgramStateRef State,
return true;
}
+
//===----------------------------------------------------------------------===//
// Top-level transfer function logic (Dispatcher).
//===----------------------------------------------------------------------===//
/// evalAssume - Called by ConstraintManager. Used to call checker-specific
/// logic for handling assumptions on symbolic values.
-ProgramStateRef ExprEngine::processAssume(ProgramStateRef state, SVal cond,
- bool assumption) {
+ProgramStateRef ExprEngine::processAssume(ProgramStateRef state,
+ SVal cond, bool assumption) {
return getCheckerManager().runCheckersForEvalAssume(state, cond, assumption);
}
-ProgramStateRef ExprEngine::processRegionChanges(
- ProgramStateRef state, const InvalidatedSymbols *invalidated,
- ArrayRef<const MemRegion *> Explicits, ArrayRef<const MemRegion *> Regions,
- const LocationContext *LCtx, const CallEvent *Call) {
- return getCheckerManager().runCheckersForRegionChanges(
- state, invalidated, Explicits, Regions, LCtx, Call);
+ProgramStateRef
+ExprEngine::processRegionChanges(ProgramStateRef state,
+ const InvalidatedSymbols *invalidated,
+ ArrayRef<const MemRegion *> Explicits,
+ ArrayRef<const MemRegion *> Regions,
+ const LocationContext *LCtx,
+ const CallEvent *Call) {
+ return getCheckerManager().runCheckersForRegionChanges(state, invalidated,
+ Explicits, Regions,
+ LCtx, Call);
}
static void
@@ -963,36 +970,38 @@ void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred,
currBldrCtx = Ctx;
switch (E.getKind()) {
- case CFGElement::Statement:
- case CFGElement::Constructor:
- case CFGElement::CXXRecordTypedCall:
- ProcessStmt(E.castAs<CFGStmt>().getStmt(), Pred);
- return;
- case CFGElement::Initializer:
- ProcessInitializer(E.castAs<CFGInitializer>(), Pred);
- return;
- case CFGElement::NewAllocator:
- ProcessNewAllocator(E.castAs<CFGNewAllocator>().getAllocatorExpr(), Pred);
- return;
- case CFGElement::AutomaticObjectDtor:
- case CFGElement::DeleteDtor:
- case CFGElement::BaseDtor:
- case CFGElement::MemberDtor:
- case CFGElement::TemporaryDtor:
- ProcessImplicitDtor(E.castAs<CFGImplicitDtor>(), Pred);
- return;
- case CFGElement::LoopExit:
- ProcessLoopExit(E.castAs<CFGLoopExit>().getLoopStmt(), Pred);
- return;
- case CFGElement::LifetimeEnds:
- case CFGElement::CleanupFunction:
- case CFGElement::ScopeBegin:
- case CFGElement::ScopeEnd:
- return;
+ case CFGElement::Statement:
+ case CFGElement::Constructor:
+ case CFGElement::CXXRecordTypedCall:
+ ProcessStmt(E.castAs<CFGStmt>().getStmt(), Pred);
+ return;
+ case CFGElement::Initializer:
+ ProcessInitializer(E.castAs<CFGInitializer>(), Pred);
+ return;
+ case CFGElement::NewAllocator:
+ ProcessNewAllocator(E.castAs<CFGNewAllocator>().getAllocatorExpr(),
+ Pred);
+ return;
+ case CFGElement::AutomaticObjectDtor:
+ case CFGElement::DeleteDtor:
+ case CFGElement::BaseDtor:
+ case CFGElement::MemberDtor:
+ case CFGElement::TemporaryDtor:
+ ProcessImplicitDtor(E.castAs<CFGImplicitDtor>(), Pred);
+ return;
+ case CFGElement::LoopExit:
+ ProcessLoopExit(E.castAs<CFGLoopExit>().getLoopStmt(), Pred);
+ return;
+ case CFGElement::LifetimeEnds:
+ case CFGElement::CleanupFunction:
+ case CFGElement::ScopeBegin:
+ case CFGElement::ScopeEnd:
+ return;
}
}
-static bool shouldRemoveDeadBindings(AnalysisManager &AMgr, const Stmt *S,
+static bool shouldRemoveDeadBindings(AnalysisManager &AMgr,
+ const Stmt *S,
const ExplodedNode *Pred,
const LocationContext *LC) {
// Are we never purging state values?
@@ -1020,10 +1029,11 @@ static bool shouldRemoveDeadBindings(AnalysisManager &AMgr, const Stmt *S,
void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
const Stmt *ReferenceStmt,
const LocationContext *LC,
- const Stmt *DiagnosticStmt, ProgramPoint::Kind K) {
+ const Stmt *DiagnosticStmt,
+ ProgramPoint::Kind K) {
assert((K == ProgramPoint::PreStmtPurgeDeadSymbolsKind ||
- ReferenceStmt == nullptr || isa<ReturnStmt>(ReferenceStmt)) &&
- "PostStmt is not generally supported by the SymbolReaper yet");
+ ReferenceStmt == nullptr || isa<ReturnStmt>(ReferenceStmt))
+ && "PostStmt is not generally supported by the SymbolReaper yet");
assert(LC && "Must pass the current (or expiring) LocationContext");
if (!DiagnosticStmt) {
@@ -1108,7 +1118,8 @@ void ExprEngine::ProcessStmt(const Stmt *currStmt, ExplodedNode *Pred) {
ExplodedNodeSet CleanedStates;
if (shouldRemoveDeadBindings(AMgr, currStmt, Pred,
Pred->getLocationContext())) {
- removeDead(Pred, CleanedStates, currStmt, Pred->getLocationContext());
+ removeDead(Pred, CleanedStates, currStmt,
+ Pred->getLocationContext());
} else
CleanedStates.Add(Pred);
@@ -1125,7 +1136,7 @@ void ExprEngine::ProcessStmt(const Stmt *currStmt, ExplodedNode *Pred) {
Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
}
-void ExprEngine::ProcessLoopExit(const Stmt *S, ExplodedNode *Pred) {
+void ExprEngine::ProcessLoopExit(const Stmt* S, ExplodedNode *Pred) {
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
S->getBeginLoc(),
"Error evaluating end of the loop");
@@ -1134,7 +1145,7 @@ void ExprEngine::ProcessLoopExit(const Stmt *S, ExplodedNode *Pred) {
NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
ProgramStateRef NewState = Pred->getState();
- if (AMgr.options.ShouldUnrollLoops)
+ if(AMgr.options.ShouldUnrollLoops)
NewState = processLoopEnd(S, NewState);
LoopExit PP(S, Pred->getLocationContext());
@@ -1200,9 +1211,9 @@ void ExprEngine::ProcessInitializer(const CFGInitializer CFGInit,
// If we fail to get the value for some reason, use a symbolic value.
if (InitVal.isUnknownOrUndef()) {
SValBuilder &SVB = getSValBuilder();
- InitVal =
- SVB.conjureSymbolVal(BMI->getInit(), stackFrame, Field->getType(),
- currBldrCtx->blockCount());
+ InitVal = SVB.conjureSymbolVal(BMI->getInit(), stackFrame,
+ Field->getType(),
+ currBldrCtx->blockCount());
}
} else {
InitVal = State->getSVal(BMI->getInit(), stackFrame);
@@ -1303,7 +1314,8 @@ void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
}
-void ExprEngine::ProcessNewAllocator(const CXXNewExpr *NE, ExplodedNode *Pred) {
+void ExprEngine::ProcessNewAllocator(const CXXNewExpr *NE,
+ ExplodedNode *Pred) {
ExplodedNodeSet Dst;
AnalysisManager &AMgr = getAnalysisManager();
AnalyzerOptions &Opts = AMgr.options;
@@ -1394,7 +1406,8 @@ void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,
/*IsBase=*/false, Pred, Dst, CallOpts);
}
-void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor, ExplodedNode *Pred,
+void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor,
+ ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
ProgramStateRef State = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
@@ -1469,27 +1482,28 @@ void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor, ExplodedNode *Pred,
VisitCXXDestructor(DTy, ArgR, DE, /*IsBase=*/false, Pred, Dst, CallOpts);
}
-void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D, ExplodedNode *Pred,
- ExplodedNodeSet &Dst) {
+void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst) {
const LocationContext *LCtx = Pred->getLocationContext();
const auto *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl());
- Loc ThisPtr = getSValBuilder().getCXXThis(CurDtor, LCtx->getStackFrame());
+ Loc ThisPtr = getSValBuilder().getCXXThis(CurDtor,
+ LCtx->getStackFrame());
SVal ThisVal = Pred->getState()->getSVal(ThisPtr);
// Create the base object region.
const CXXBaseSpecifier *Base = D.getBaseSpecifier();
QualType BaseTy = Base->getType();
- SVal BaseVal =
- getStoreManager().evalDerivedToBase(ThisVal, BaseTy, Base->isVirtual());
+ SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy,
+ Base->isVirtual());
EvalCallOptions CallOpts;
VisitCXXDestructor(BaseTy, BaseVal.getAsRegion(), CurDtor->getBody(),
/*IsBase=*/true, Pred, Dst, CallOpts);
}
-void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D, ExplodedNode *Pred,
- ExplodedNodeSet &Dst) {
+void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst) {
const auto *DtorDecl = D.getDestructorDecl(getContext());
const FieldDecl *Member = D.getFieldDecl();
QualType T = Member->getType();
@@ -1669,7 +1683,8 @@ void ExprEngine::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE,
}
ProgramStateRef ExprEngine::escapeValues(ProgramStateRef State,
- ArrayRef<SVal> Vs, PointerEscapeKind K,
+ ArrayRef<SVal> Vs,
+ PointerEscapeKind K,
const CallEvent *Call) const {
class CollectReachableSymbolsCallback final : public SymbolVisitor {
InvalidatedSymbols &Symbols;
@@ -1704,707 +1719,714 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
assert(!isa<Expr>(S) || S == cast<Expr>(S)->IgnoreParens());
switch (S->getStmtClass()) {
- // C++, OpenMP and ARC stuff we don't support yet.
- case Stmt::CXXDependentScopeMemberExprClass:
- case Stmt::CXXTryStmtClass:
- case Stmt::CXXTypeidExprClass:
- case Stmt::CXXUuidofExprClass:
- case Stmt::CXXFoldExprClass:
- case Stmt::MSPropertyRefExprClass:
- case Stmt::MSPropertySubscriptExprClass:
- case Stmt::CXXUnresolvedConstructExprClass:
- case Stmt::DependentScopeDeclRefExprClass:
- case Stmt::ArrayTypeTraitExprClass:
- case Stmt::ExpressionTraitExprClass:
- case Stmt::UnresolvedLookupExprClass:
- case Stmt::UnresolvedMemberExprClass:
- case Stmt::TypoExprClass:
- case Stmt::RecoveryExprClass:
- case Stmt::CXXNoexceptExprClass:
- case Stmt::PackExpansionExprClass:
- case Stmt::PackIndexingExprClass:
- case Stmt::SubstNonTypeTemplateParmPackExprClass:
- case Stmt::FunctionParmPackExprClass:
- case Stmt::CoroutineBodyStmtClass:
- case Stmt::CoawaitExprClass:
- case Stmt::DependentCoawaitExprClass:
- case Stmt::CoreturnStmtClass:
- case Stmt::CoyieldExprClass:
- case Stmt::SEHTryStmtClass:
- case Stmt::SEHExceptStmtClass:
- case Stmt::SEHLeaveStmtClass:
- case Stmt::SEHFinallyStmtClass:
- case Stmt::OMPCanonicalLoopClass:
- case Stmt::OMPParallelDirectiveClass:
- case Stmt::OMPSimdDirectiveClass:
- case Stmt::OMPForDirectiveClass:
- case Stmt::OMPForSimdDirectiveClass:
- case Stmt::OMPSectionsDirectiveClass:
- case Stmt::OMPSectionDirectiveClass:
- case Stmt::OMPScopeDirectiveClass:
- case Stmt::OMPSingleDirectiveClass:
- case Stmt::OMPMasterDirectiveClass:
- case Stmt::OMPCriticalDirectiveClass:
- case Stmt::OMPParallelForDirectiveClass:
- case Stmt::OMPParallelForSimdDirectiveClass:
- case Stmt::OMPParallelSectionsDirectiveClass:
- case Stmt::OMPParallelMasterDirectiveClass:
- case Stmt::OMPParallelMaskedDirectiveClass:
- case Stmt::OMPTaskDirectiveClass:
- case Stmt::OMPTaskyieldDirectiveClass:
- case Stmt::OMPBarrierDirectiveClass:
- case Stmt::OMPTaskwaitDirectiveClass:
- case Stmt::OMPErrorDirectiveClass:
- case Stmt::OMPTaskgroupDirectiveClass:
- case Stmt::OMPFlushDirectiveClass:
- case Stmt::OMPDepobjDirectiveClass:
- case Stmt::OMPScanDirectiveClass:
- case Stmt::OMPOrderedDirectiveClass:
- case Stmt::OMPAtomicDirectiveClass:
- case Stmt::OMPTargetDirectiveClass:
- case Stmt::OMPTargetDataDirectiveClass:
- case Stmt::OMPTargetEnterDataDirectiveClass:
- case Stmt::OMPTargetExitDataDirectiveClass:
- case Stmt::OMPTargetParallelDirectiveClass:
- case Stmt::OMPTargetParallelForDirectiveClass:
- case Stmt::OMPTargetUpdateDirectiveClass:
- case Stmt::OMPTeamsDirectiveClass:
- case Stmt::OMPCancellationPointDirectiveClass:
- case Stmt::OMPCancelDirectiveClass:
- case Stmt::OMPTaskLoopDirectiveClass:
- case Stmt::OMPTaskLoopSimdDirectiveClass:
- case Stmt::OMPMasterTaskLoopDirectiveClass:
- case Stmt::OMPMaskedTaskLoopDirectiveClass:
- case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
- case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
- case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
- case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
- case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
- case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
- case Stmt::OMPDistributeDirectiveClass:
- case Stmt::OMPDistributeParallelForDirectiveClass:
- case Stmt::OMPDistributeParallelForSimdDirectiveClass:
- case Stmt::OMPDistributeSimdDirectiveClass:
- case Stmt::OMPTargetParallelForSimdDirectiveClass:
- case Stmt::OMPTargetSimdDirectiveClass:
- case Stmt::OMPTeamsDistributeDirectiveClass:
- case Stmt::OMPTeamsDistributeSimdDirectiveClass:
- case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
- case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
- case Stmt::OMPTargetTeamsDirectiveClass:
- case Stmt::OMPTargetTeamsDistributeDirectiveClass:
- case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
- case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
- case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
- case Stmt::OMPTileDirectiveClass:
- case Stmt::OMPInteropDirectiveClass:
- case Stmt::OMPDispatchDirectiveClass:
- case Stmt::OMPMaskedDirectiveClass:
- case Stmt::OMPGenericLoopDirectiveClass:
- case Stmt::OMPTeamsGenericLoopDirectiveClass:
- case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
- case Stmt::OMPParallelGenericLoopDirectiveClass:
- case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
- case Stmt::CapturedStmtClass:
- case Stmt::OpenACCComputeConstructClass:
- case Stmt::OpenACCLoopConstructClass:
- case Stmt::OMPUnrollDirectiveClass:
- case Stmt::OMPMetaDirectiveClass: {
- const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
- Engine.addAbortedBlock(node, currBldrCtx->getBlock());
- break;
- }
+ // C++, OpenMP and ARC stuff we don't support yet.
+ case Stmt::CXXDependentScopeMemberExprClass:
+ case Stmt::CXXTryStmtClass:
+ case Stmt::CXXTypeidExprClass:
+ case Stmt::CXXUuidofExprClass:
+ case Stmt::CXXFoldExprClass:
+ case Stmt::MSPropertyRefExprClass:
+ case Stmt::MSPropertySubscriptExprClass:
+ case Stmt::CXXUnresolvedConstructExprClass:
+ case Stmt::DependentScopeDeclRefExprClass:
+ case Stmt::ArrayTypeTraitExprClass:
+ case Stmt::ExpressionTraitExprClass:
+ case Stmt::UnresolvedLookupExprClass:
+ case Stmt::UnresolvedMemberExprClass:
+ case Stmt::TypoExprClass:
+ case Stmt::RecoveryExprClass:
+ case Stmt::CXXNoexceptExprClass:
+ case Stmt::PackExpansionExprClass:
+ case Stmt::PackIndexingExprClass:
+ case Stmt::SubstNonTypeTemplateParmPackExprClass:
+ case Stmt::FunctionParmPackExprClass:
+ case Stmt::CoroutineBodyStmtClass:
+ case Stmt::CoawaitExprClass:
+ case Stmt::DependentCoawaitExprClass:
+ case Stmt::CoreturnStmtClass:
+ case Stmt::CoyieldExprClass:
+ case Stmt::SEHTryStmtClass:
+ case Stmt::SEHExceptStmtClass:
+ case Stmt::SEHLeaveStmtClass:
+ case Stmt::SEHFinallyStmtClass:
+ case Stmt::OMPCanonicalLoopClass:
+ case Stmt::OMPParallelDirectiveClass:
+ case Stmt::OMPSimdDirectiveClass:
+ case Stmt::OMPForDirectiveClass:
+ case Stmt::OMPForSimdDirectiveClass:
+ case Stmt::OMPSectionsDirectiveClass:
+ case Stmt::OMPSectionDirectiveClass:
+ case Stmt::OMPScopeDirectiveClass:
+ case Stmt::OMPSingleDirectiveClass:
+ case Stmt::OMPMasterDirectiveClass:
+ case Stmt::OMPCriticalDirectiveClass:
+ case Stmt::OMPParallelForDirectiveClass:
+ case Stmt::OMPParallelForSimdDirectiveClass:
+ case Stmt::OMPParallelSectionsDirectiveClass:
+ case Stmt::OMPParallelMasterDirectiveClass:
+ case Stmt::OMPParallelMaskedDirectiveClass:
+ case Stmt::OMPTaskDirectiveClass:
+ case Stmt::OMPTaskyieldDirectiveClass:
+ case Stmt::OMPBarrierDirectiveClass:
+ case Stmt::OMPTaskwaitDirectiveClass:
+ case Stmt::OMPErrorDirectiveClass:
+ case Stmt::OMPTaskgroupDirectiveClass:
+ case Stmt::OMPFlushDirectiveClass:
+ case Stmt::OMPDepobjDirectiveClass:
+ case Stmt::OMPScanDirectiveClass:
+ case Stmt::OMPOrderedDirectiveClass:
+ case Stmt::OMPAtomicDirectiveClass:
+ case Stmt::OMPTargetDirectiveClass:
+ case Stmt::OMPTargetDataDirectiveClass:
+ case Stmt::OMPTargetEnterDataDirectiveClass:
+ case Stmt::OMPTargetExitDataDirectiveClass:
+ case Stmt::OMPTargetParallelDirectiveClass:
+ case Stmt::OMPTargetParallelForDirectiveClass:
+ case Stmt::OMPTargetUpdateDirectiveClass:
+ case Stmt::OMPTeamsDirectiveClass:
+ case Stmt::OMPCancellationPointDirectiveClass:
+ case Stmt::OMPCancelDirectiveClass:
+ case Stmt::OMPTaskLoopDirectiveClass:
+ case Stmt::OMPTaskLoopSimdDirectiveClass:
+ case Stmt::OMPMasterTaskLoopDirectiveClass:
+ case Stmt::OMPMaskedTaskLoopDirectiveClass:
+ case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
+ case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
+ case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
+ case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
+ case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
+ case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
+ case Stmt::OMPDistributeDirectiveClass:
+ case Stmt::OMPDistributeParallelForDirectiveClass:
+ case Stmt::OMPDistributeParallelForSimdDirectiveClass:
+ case Stmt::OMPDistributeSimdDirectiveClass:
+ case Stmt::OMPTargetParallelForSimdDirectiveClass:
+ case Stmt::OMPTargetSimdDirectiveClass:
+ case Stmt::OMPTeamsDistributeDirectiveClass:
+ case Stmt::OMPTeamsDistributeSimdDirectiveClass:
+ case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
+ case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
+ case Stmt::OMPTargetTeamsDirectiveClass:
+ case Stmt::OMPTargetTeamsDistributeDirectiveClass:
+ case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
+ case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
+ case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
+ case Stmt::OMPTileDirectiveClass:
+ case Stmt::OMPInteropDirectiveClass:
+ case Stmt::OMPDispatchDirectiveClass:
+ case Stmt::OMPMaskedDirectiveClass:
+ case Stmt::OMPGenericLoopDirectiveClass:
+ case Stmt::OMPTeamsGenericLoopDirectiveClass:
+ case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
+ case Stmt::OMPParallelGenericLoopDirectiveClass:
+ case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
+ case Stmt::CapturedStmtClass:
+ case Stmt::OpenACCComputeConstructClass:
+ case Stmt::OpenACCLoopConstructClass:
+ case Stmt::OMPUnrollDirectiveClass:
+ case Stmt::OMPMetaDirectiveClass: {
+ const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
+ Engine.addAbortedBlock(node, currBldrCtx->getBlock());
+ break;
+ }
- case Stmt::ParenExprClass:
- llvm_unreachable("ParenExprs already handled.");
- case Stmt::GenericSelectionExprClass:
- llvm_unreachable("GenericSelectionExprs already handled.");
- // Cases that should never be evaluated simply because they shouldn't
- // appear in the CFG.
- case Stmt::BreakStmtClass:
- case Stmt::CaseStmtClass:
- case Stmt::CompoundStmtClass:
- case Stmt::ContinueStmtClass:
- case Stmt::CXXForRangeStmtClass:
- case Stmt::DefaultStmtClass:
- case Stmt::DoStmtClass:
- case Stmt::ForStmtClass:
- case Stmt::GotoStmtClass:
- case Stmt::IfStmtClass:
- case Stmt::IndirectGotoStmtClass:
- case Stmt::LabelStmtClass:
- case Stmt::NoStmtClass:
- case Stmt::NullStmtClass:
- case Stmt::SwitchStmtClass:
- case Stmt::WhileStmtClass:
- case Expr::MSDependentExistsStmtClass:
- llvm_unreachable("Stmt should not be in analyzer evaluation loop");
- case Stmt::ImplicitValueInitExprClass:
- // These nodes are shared in the CFG and would case caching out.
- // Moreover, no additional evaluation required for them, the
- // analyzer can reconstruct these values from the AST.
- llvm_unreachable("Should be pruned from CFG");
-
- case Stmt::ObjCSubscriptRefExprClass:
- case Stmt::ObjCPropertyRefExprClass:
- llvm_unreachable("These are handled by PseudoObjectExpr");
-
- case Stmt::GNUNullExprClass: {
- // GNU __null is a pointer-width integer, not an actual pointer.
- ProgramStateRef state = Pred->getState();
- state = state->BindExpr(
- S, Pred->getLocationContext(),
- svalBuilder.makeIntValWithWidth(getContext().VoidPtrTy, 0));
- Bldr.generateNode(S, Pred, state);
- break;
- }
+ case Stmt::ParenExprClass:
+ llvm_unreachable("ParenExprs already handled.");
+ case Stmt::GenericSelectionExprClass:
+ llvm_unreachable("GenericSelectionExprs already handled.");
+ // Cases that should never be evaluated simply because they shouldn't
+ // appear in the CFG.
+ case Stmt::BreakStmtClass:
+ case Stmt::CaseStmtClass:
+ case Stmt::CompoundStmtClass:
+ case Stmt::ContinueStmtClass:
+ case Stmt::CXXForRangeStmtClass:
+ case Stmt::DefaultStmtClass:
+ case Stmt::DoStmtClass:
+ case Stmt::ForStmtClass:
+ case Stmt::GotoStmtClass:
+ case Stmt::IfStmtClass:
+ case Stmt::IndirectGotoStmtClass:
+ case Stmt::LabelStmtClass:
+ case Stmt::NoStmtClass:
+ case Stmt::NullStmtClass:
+ case Stmt::SwitchStmtClass:
+ case Stmt::WhileStmtClass:
+ case Expr::MSDependentExistsStmtClass:
+ llvm_unreachable("Stmt should not be in analyzer evaluation loop");
+ case Stmt::ImplicitValueInitExprClass:
+ // These nodes are shared in the CFG and would case caching out.
+ // Moreover, no additional evaluation required for them, the
+ // analyzer can reconstruct these values from the AST.
+ llvm_unreachable("Should be pruned from CFG");
+
+ case Stmt::ObjCSubscriptRefExprClass:
+ case Stmt::ObjCPropertyRefExprClass:
+ llvm_unreachable("These are handled by PseudoObjectExpr");
+
+ case Stmt::GNUNullExprClass: {
+ // GNU __null is a pointer-width integer, not an actual pointer.
+ ProgramStateRef state = Pred->getState();
+ state = state->BindExpr(
+ S, Pred->getLocationContext(),
+ svalBuilder.makeIntValWithWidth(getContext().VoidPtrTy, 0));
+ Bldr.generateNode(S, Pred, state);
+ break;
+ }
- case Stmt::ObjCAtSynchronizedStmtClass:
- Bldr.takeNodes(Pred);
- VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::ObjCAtSynchronizedStmtClass:
+ Bldr.takeNodes(Pred);
+ VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Expr::ConstantExprClass:
- case Stmt::ExprWithCleanupsClass:
- // Handled due to fully linearised CFG.
- break;
+ case Expr::ConstantExprClass:
+ case Stmt::ExprWithCleanupsClass:
+ // Handled due to fully linearised CFG.
+ break;
- case Stmt::CXXBindTemporaryExprClass: {
- Bldr.takeNodes(Pred);
- ExplodedNodeSet PreVisit;
- getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
- ExplodedNodeSet Next;
- VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), PreVisit, Next);
- getCheckerManager().runCheckersForPostStmt(Dst, Next, S, *this);
- Bldr.addNodes(Dst);
- break;
- }
+ case Stmt::CXXBindTemporaryExprClass: {
+ Bldr.takeNodes(Pred);
+ ExplodedNodeSet PreVisit;
+ getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+ ExplodedNodeSet Next;
+ VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), PreVisit, Next);
+ getCheckerManager().runCheckersForPostStmt(Dst, Next, S, *this);
+ Bldr.addNodes(Dst);
+ break;
+ }
- case Stmt::ArrayInitLoopExprClass:
- Bldr.takeNodes(Pred);
- VisitArrayInitLoopExpr(cast<ArrayInitLoopExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
- // Cases not handled yet; but will handle some day.
- case Stmt::DesignatedInitExprClass:
- case Stmt::DesignatedInitUpdateExprClass:
- case Stmt::ArrayInitIndexExprClass:
- case Stmt::ExtVectorElementExprClass:
- case Stmt::ImaginaryLiteralClass:
- case Stmt::ObjCAtCatchStmtClass:
- case Stmt::ObjCAtFinallyStmtClass:
- case Stmt::ObjCAtTryStmtClass:
- case Stmt::ObjCAutoreleasePoolStmtClass:
- case Stmt::ObjCEncodeExprClass:
- case Stmt::ObjCIsaExprClass:
- case Stmt::ObjCProtocolExprClass:
- case Stmt::ObjCSelectorExprClass:
- case Stmt::ParenListExprClass:
- case Stmt::ShuffleVectorExprClass:
- case Stmt::ConvertVectorExprClass:
- case Stmt::VAArgExprClass:
- case Stmt::CUDAKernelCallExprClass:
- case Stmt::OpaqueValueExprClass:
- case Stmt::AsTypeExprClass:
- case Stmt::ConceptSpecializationExprClass:
- case Stmt::CXXRewrittenBinaryOperatorClass:
- case Stmt::RequiresExprClass:
- case Expr::CXXParenListInitExprClass:
- // Fall through.
-
- // Cases we intentionally don't evaluate, since they don't need
- // to be explicitly evaluated.
- case Stmt::PredefinedExprClass:
- case Stmt::AddrLabelExprClass:
- case Stmt::AttributedStmtClass:
- case Stmt::IntegerLiteralClass:
- case Stmt::FixedPointLiteralClass:
- case Stmt::CharacterLiteralClass:
- case Stmt::CXXScalarValueInitExprClass:
- case Stmt::CXXBoolLiteralExprClass:
- case Stmt::ObjCBoolLiteralExprClass:
- case Stmt::ObjCAvailabilityCheckExprClass:
- case Stmt::FloatingLiteralClass:
- case Stmt::NoInitExprClass:
- case Stmt::SizeOfPackExprClass:
- case Stmt::StringLiteralClass:
- case Stmt::SourceLocExprClass:
- case Stmt::ObjCStringLiteralClass:
- case Stmt::CXXPseudoDestructorExprClass:
- case Stmt::SubstNonTypeTemplateParmExprClass:
- case Stmt::CXXNullPtrLiteralExprClass:
- case Stmt::ArraySectionExprClass:
- case Stmt::OMPArrayShapingExprClass:
- case Stmt::OMPIteratorExprClass:
- case Stmt::SYCLUniqueStableNameExprClass:
- case Stmt::TypeTraitExprClass: {
- Bldr.takeNodes(Pred);
- ExplodedNodeSet preVisit;
- getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
- getCheckerManager().runCheckersForPostStmt(Dst, preVisit, S, *this);
- Bldr.addNodes(Dst);
- break;
- }
+ case Stmt::ArrayInitLoopExprClass:
+ Bldr.takeNodes(Pred);
+ VisitArrayInitLoopExpr(cast<ArrayInitLoopExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
+ // Cases not handled yet; but will handle some day.
+ case Stmt::DesignatedInitExprClass:
+ case Stmt::DesignatedInitUpdateExprClass:
+ case Stmt::ArrayInitIndexExprClass:
+ case Stmt::ExtVectorElementExprClass:
+ case Stmt::ImaginaryLiteralClass:
+ case Stmt::ObjCAtCatchStmtClass:
+ case Stmt::ObjCAtFinallyStmtClass:
+ case Stmt::ObjCAtTryStmtClass:
+ case Stmt::ObjCAutoreleasePoolStmtClass:
+ case Stmt::ObjCEncodeExprClass:
+ case Stmt::ObjCIsaExprClass:
+ case Stmt::ObjCProtocolExprClass:
+ case Stmt::ObjCSelectorExprClass:
+ case Stmt::ParenListExprClass:
+ case Stmt::ShuffleVectorExprClass:
+ case Stmt::ConvertVectorExprClass:
+ case Stmt::VAArgExprClass:
+ case Stmt::CUDAKernelCallExprClass:
+ case Stmt::OpaqueValueExprClass:
+ case Stmt::AsTypeExprClass:
+ case Stmt::ConceptSpecializationExprClass:
+ case Stmt::CXXRewrittenBinaryOperatorClass:
+ case Stmt::RequiresExprClass:
+ case Expr::CXXParenListInitExprClass:
+ // Fall through.
+
+ // Cases we intentionally don't evaluate, since they don't need
+ // to be explicitly evaluated.
+ case Stmt::PredefinedExprClass:
+ case Stmt::AddrLabelExprClass:
+ case Stmt::AttributedStmtClass:
+ case Stmt::IntegerLiteralClass:
+ case Stmt::FixedPointLiteralClass:
+ case Stmt::CharacterLiteralClass:
+ case Stmt::CXXScalarValueInitExprClass:
+ case Stmt::CXXBoolLiteralExprClass:
+ case Stmt::ObjCBoolLiteralExprClass:
+ case Stmt::ObjCAvailabilityCheckExprClass:
+ case Stmt::FloatingLiteralClass:
+ case Stmt::NoInitExprClass:
+ case Stmt::SizeOfPackExprClass:
+ case Stmt::StringLiteralClass:
+ case Stmt::SourceLocExprClass:
+ case Stmt::ObjCStringLiteralClass:
+ case Stmt::CXXPseudoDestructorExprClass:
+ case Stmt::SubstNonTypeTemplateParmExprClass:
+ case Stmt::CXXNullPtrLiteralExprClass:
+ case Stmt::ArraySectionExprClass:
+ case Stmt::OMPArrayShapingExprClass:
+ case Stmt::OMPIteratorExprClass:
+ case Stmt::SYCLUniqueStableNameExprClass:
+ case Stmt::TypeTraitExprClass: {
+ Bldr.takeNodes(Pred);
+ ExplodedNodeSet preVisit;
+ getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
+ getCheckerManager().runCheckersForPostStmt(Dst, preVisit, S, *this);
+ Bldr.addNodes(Dst);
+ break;
+ }
- case Stmt::CXXDefaultArgExprClass:
- case Stmt::CXXDefaultInitExprClass: {
- Bldr.takeNodes(Pred);
- ExplodedNodeSet PreVisit;
- getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+ case Stmt::CXXDefaultArgExprClass:
+ case Stmt::CXXDefaultInitExprClass: {
+ Bldr.takeNodes(Pred);
+ ExplodedNodeSet PreVisit;
+ getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
- ExplodedNodeSet Tmp;
- StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
+ ExplodedNodeSet Tmp;
+ StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
- const Expr *ArgE;
- if (const auto *DefE = dyn_cast<CXXDefaultArgExpr>(S))
- ArgE = DefE->getExpr();
- else if (const auto *DefE = dyn_cast<CXXDefaultInitExpr>(S))
- ArgE = DefE->getExpr();
- else
- llvm_unreachable("unknown constant wrapper kind");
+ const Expr *ArgE;
+ if (const auto *DefE = dyn_cast<CXXDefaultArgExpr>(S))
+ ArgE = DefE->getExpr();
+ else if (const auto *DefE = dyn_cast<CXXDefaultInitExpr>(S))
+ ArgE = DefE->getExpr();
+ else
+ llvm_unreachable("unknown constant wrapper kind");
- bool IsTemporary = false;
- if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(ArgE)) {
- ArgE = MTE->getSubExpr();
- IsTemporary = true;
- }
+ bool IsTemporary = false;
+ if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(ArgE)) {
+ ArgE = MTE->getSubExpr();
+ IsTemporary = true;
+ }
- std::optional<SVal> ConstantVal = svalBuilder.getConstantVal(ArgE);
- if (!ConstantVal)
- ConstantVal = UnknownVal();
+ std::optional<SVal> ConstantVal = svalBuilder.getConstantVal(ArgE);
+ if (!ConstantVal)
+ ConstantVal = UnknownVal();
+
+ const LocationContext *LCtx = Pred->getLocationContext();
+ for (const auto I : PreVisit) {
+ ProgramStateRef State = I->getState();
+ State = State->BindExpr(S, LCtx, *ConstantVal);
+ if (IsTemporary)
+ State = createTemporaryRegionIfNeeded(State, LCtx,
+ cast<Expr>(S),
+ cast<Expr>(S));
+ Bldr2.generateNode(S, I, State);
+ }
- const LocationContext *LCtx = Pred->getLocationContext();
- for (const auto I : PreVisit) {
- ProgramStateRef State = I->getState();
- State = State->BindExpr(S, LCtx, *ConstantVal);
- if (IsTemporary)
- State = createTemporaryRegionIfNeeded(State, LCtx, cast<Expr>(S),
- cast<Expr>(S));
- Bldr2.generateNode(S, I, State);
+ getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
+ Bldr.addNodes(Dst);
+ break;
}
- getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
- Bldr.addNodes(Dst);
- break;
- }
+ // Cases we evaluate as opaque expressions, conjuring a symbol.
+ case Stmt::CXXStdInitializerListExprClass:
+ case Expr::ObjCArrayLiteralClass:
+ case Expr::ObjCDictionaryLiteralClass:
+ case Expr::ObjCBoxedExprClass: {
+ Bldr.takeNodes(Pred);
- // Cases we evaluate as opaque expressions, conjuring a symbol.
- case Stmt::CXXStdInitializerListExprClass:
- case Expr::ObjCArrayLiteralClass:
- case Expr::ObjCDictionaryLiteralClass:
- case Expr::ObjCBoxedExprClass: {
- Bldr.takeNodes(Pred);
+ ExplodedNodeSet preVisit;
+ getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
- ExplodedNodeSet preVisit;
- getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
+ ExplodedNodeSet Tmp;
+ StmtNodeBuilder Bldr2(preVisit, Tmp, *currBldrCtx);
+
+ const auto *Ex = cast<Expr>(S);
+ QualType resultType = Ex->getType();
+
+ for (const auto N : preVisit) {
+ const LocationContext *LCtx = N->getLocationContext();
+ SVal result = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
+ resultType,
+ currBldrCtx->blockCount());
+ ProgramStateRef State = N->getState()->BindExpr(Ex, LCtx, result);
+
+ // Escape pointers passed into the list, unless it's an ObjC boxed
+ // expression which is not a boxable C structure.
+ if (!(isa<ObjCBoxedExpr>(Ex) &&
+ !cast<ObjCBoxedExpr>(Ex)->getSubExpr()
+ ->getType()->isRecordType()))
+ for (auto Child : Ex->children()) {
+ assert(Child);
+ SVal Val = State->getSVal(Child, LCtx);
+ State = escapeValues(State, Val, PSK_EscapeOther);
+ }
- ExplodedNodeSet Tmp;
- StmtNodeBuilder Bldr2(preVisit, Tmp, *currBldrCtx);
-
- const auto *Ex = cast<Expr>(S);
- QualType resultType = Ex->getType();
-
- for (const auto N : preVisit) {
- const LocationContext *LCtx = N->getLocationContext();
- SVal result = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx, resultType,
- currBldrCtx->blockCount());
- ProgramStateRef State = N->getState()->BindExpr(Ex, LCtx, result);
-
- // Escape pointers passed into the list, unless it's an ObjC boxed
- // expression which is not a boxable C structure.
- if (!(isa<ObjCBoxedExpr>(Ex) &&
- !cast<ObjCBoxedExpr>(Ex)->getSubExpr()->getType()->isRecordType()))
- for (auto Child : Ex->children()) {
- assert(Child);
- SVal Val = State->getSVal(Child, LCtx);
- State = escapeValues(State, Val, PSK_EscapeOther);
- }
+ Bldr2.generateNode(S, N, State);
+ }
- Bldr2.generateNode(S, N, State);
+ getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
+ Bldr.addNodes(Dst);
+ break;
}
- getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
- Bldr.addNodes(Dst);
- break;
- }
-
- case Stmt::ArraySubscriptExprClass:
- Bldr.takeNodes(Pred);
- VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
-
- case Stmt::MatrixSubscriptExprClass:
- llvm_unreachable("Support for MatrixSubscriptExpr is not implemented.");
- break;
+ case Stmt::ArraySubscriptExprClass:
+ Bldr.takeNodes(Pred);
+ VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::GCCAsmStmtClass: {
- Bldr.takeNodes(Pred);
- ExplodedNodeSet PreVisit;
- getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
- ExplodedNodeSet PostVisit;
- for (ExplodedNode *const N : PreVisit)
- VisitGCCAsmStmt(cast<GCCAsmStmt>(S), N, PostVisit);
- getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
- Bldr.addNodes(Dst);
- } break;
-
- case Stmt::MSAsmStmtClass:
- Bldr.takeNodes(Pred);
- VisitMSAsmStmt(cast<MSAsmStmt>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::MatrixSubscriptExprClass:
+ llvm_unreachable("Support for MatrixSubscriptExpr is not implemented.");
+ break;
- case Stmt::BlockExprClass:
- Bldr.takeNodes(Pred);
- VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::GCCAsmStmtClass: {
+ Bldr.takeNodes(Pred);
+ ExplodedNodeSet PreVisit;
+ getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+ ExplodedNodeSet PostVisit;
+ for (ExplodedNode *const N : PreVisit)
+ VisitGCCAsmStmt(cast<GCCAsmStmt>(S), N, PostVisit);
+ getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
+ Bldr.addNodes(Dst);
+ } break;
- case Stmt::LambdaExprClass:
- if (AMgr.options.ShouldInlineLambdas) {
+ case Stmt::MSAsmStmtClass:
Bldr.takeNodes(Pred);
- VisitLambdaExpr(cast<LambdaExpr>(S), Pred, Dst);
+ VisitMSAsmStmt(cast<MSAsmStmt>(S), Pred, Dst);
Bldr.addNodes(Dst);
- } else {
- const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
- Engine.addAbortedBlock(node, currBldrCtx->getBlock());
- }
- break;
+ break;
- case Stmt::BinaryOperatorClass: {
- const auto *B = cast<BinaryOperator>(S);
- if (B->isLogicalOp()) {
+ case Stmt::BlockExprClass:
Bldr.takeNodes(Pred);
- VisitLogicalExpr(B, Pred, Dst);
+ VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst);
Bldr.addNodes(Dst);
break;
- } else if (B->getOpcode() == BO_Comma) {
- ProgramStateRef state = Pred->getState();
- Bldr.generateNode(
- B, Pred,
- state->BindExpr(
- B, Pred->getLocationContext(),
- state->getSVal(B->getRHS(), Pred->getLocationContext())));
+
+ case Stmt::LambdaExprClass:
+ if (AMgr.options.ShouldInlineLambdas) {
+ Bldr.takeNodes(Pred);
+ VisitLambdaExpr(cast<LambdaExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ } else {
+ const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
+ Engine.addAbortedBlock(node, currBldrCtx->getBlock());
+ }
break;
- }
- Bldr.takeNodes(Pred);
+ case Stmt::BinaryOperatorClass: {
+ const auto *B = cast<BinaryOperator>(S);
+ if (B->isLogicalOp()) {
+ Bldr.takeNodes(Pred);
+ VisitLogicalExpr(B, Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
+ }
+ else if (B->getOpcode() == BO_Comma) {
+ ProgramStateRef state = Pred->getState();
+ Bldr.generateNode(B, Pred,
+ state->BindExpr(B, Pred->getLocationContext(),
+ state->getSVal(B->getRHS(),
+ Pred->getLocationContext())));
+ break;
+ }
- if (AMgr.options.ShouldEagerlyAssume &&
- (B->isRelationalOp() || B->isEqualityOp())) {
- ExplodedNodeSet Tmp;
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);
- evalEagerlyAssumeBinOpBifurcation(Dst, Tmp, cast<Expr>(S));
- } else
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
+ Bldr.takeNodes(Pred);
- Bldr.addNodes(Dst);
- break;
- }
+ if (AMgr.options.ShouldEagerlyAssume &&
+ (B->isRelationalOp() || B->isEqualityOp())) {
+ ExplodedNodeSet Tmp;
+ VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);
+ evalEagerlyAssumeBinOpBifurcation(Dst, Tmp, cast<Expr>(S));
+ }
+ else
+ VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
- case Stmt::CXXOperatorCallExprClass: {
- const auto *OCE = cast<CXXOperatorCallExpr>(S);
+ Bldr.addNodes(Dst);
+ break;
+ }
- // For instance method operators, make sure the 'this' argument has a
- // valid region.
- const Decl *Callee = OCE->getCalleeDecl();
- if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(Callee)) {
- if (MD->isImplicitObjectMemberFunction()) {
- ProgramStateRef State = Pred->getState();
- const LocationContext *LCtx = Pred->getLocationContext();
- ProgramStateRef NewState =
+ case Stmt::CXXOperatorCallExprClass: {
+ const auto *OCE = cast<CXXOperatorCallExpr>(S);
+
+ // For instance method operators, make sure the 'this' argument has a
+ // valid region.
+ const Decl *Callee = OCE->getCalleeDecl();
+ if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(Callee)) {
+ if (MD->isImplicitObjectMemberFunction()) {
+ ProgramStateRef State = Pred->getState();
+ const LocationContext *LCtx = Pred->getLocationContext();
+ ProgramStateRef NewState =
createTemporaryRegionIfNeeded(State, LCtx, OCE->getArg(0));
- if (NewState != State) {
- Pred = Bldr.generateNode(OCE, Pred, NewState, /*tag=*/nullptr,
- ProgramPoint::PreStmtKind);
- // Did we cache out?
- if (!Pred)
- break;
+ if (NewState != State) {
+ Pred = Bldr.generateNode(OCE, Pred, NewState, /*tag=*/nullptr,
+ ProgramPoint::PreStmtKind);
+ // Did we cache out?
+ if (!Pred)
+ break;
+ }
}
}
+ [[fallthrough]];
}
- [[fallthrough]];
- }
- case Stmt::CallExprClass:
- case Stmt::CXXMemberCallExprClass:
- case Stmt::UserDefinedLiteralClass:
- Bldr.takeNodes(Pred);
- VisitCallExpr(cast<CallExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::CallExprClass:
+ case Stmt::CXXMemberCallExprClass:
+ case Stmt::UserDefinedLiteralClass:
+ Bldr.takeNodes(Pred);
+ VisitCallExpr(cast<CallExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::CXXCatchStmtClass:
- Bldr.takeNodes(Pred);
- VisitCXXCatchStmt(cast<CXXCatchStmt>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::CXXCatchStmtClass:
+ Bldr.takeNodes(Pred);
+ VisitCXXCatchStmt(cast<CXXCatchStmt>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::CXXTemporaryObjectExprClass:
- case Stmt::CXXConstructExprClass:
- Bldr.takeNodes(Pred);
- VisitCXXConstructExpr(cast<CXXConstructExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::CXXTemporaryObjectExprClass:
+ case Stmt::CXXConstructExprClass:
+ Bldr.takeNodes(Pred);
+ VisitCXXConstructExpr(cast<CXXConstructExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::CXXInheritedCtorInitExprClass:
- Bldr.takeNodes(Pred);
- VisitCXXInheritedCtorInitExpr(cast<CXXInheritedCtorInitExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::CXXInheritedCtorInitExprClass:
+ Bldr.takeNodes(Pred);
+ VisitCXXInheritedCtorInitExpr(cast<CXXInheritedCtorInitExpr>(S), Pred,
+ Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::CXXNewExprClass: {
- Bldr.takeNodes(Pred);
+ case Stmt::CXXNewExprClass: {
+ Bldr.takeNodes(Pred);
- ExplodedNodeSet PreVisit;
- getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+ ExplodedNodeSet PreVisit;
+ getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
- ExplodedNodeSet PostVisit;
- for (const auto i : PreVisit)
- VisitCXXNewExpr(cast<CXXNewExpr>(S), i, PostVisit);
+ ExplodedNodeSet PostVisit;
+ for (const auto i : PreVisit)
+ VisitCXXNewExpr(cast<CXXNewExpr>(S), i, PostVisit);
- getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
- Bldr.addNodes(Dst);
- break;
- }
+ getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
+ Bldr.addNodes(Dst);
+ break;
+ }
- case Stmt::CXXDeleteExprClass: {
- Bldr.takeNodes(Pred);
- ExplodedNodeSet PreVisit;
- const auto *CDE = cast<CXXDeleteExpr>(S);
- getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
- ExplodedNodeSet PostVisit;
- getCheckerManager().runCheckersForPostStmt(PostVisit, PreVisit, S, *this);
+ case Stmt::CXXDeleteExprClass: {
+ Bldr.takeNodes(Pred);
+ ExplodedNodeSet PreVisit;
+ const auto *CDE = cast<CXXDeleteExpr>(S);
+ getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+ ExplodedNodeSet PostVisit;
+ getCheckerManager().runCheckersForPostStmt(PostVisit, PreVisit, S, *this);
- for (const auto i : PostVisit)
- VisitCXXDeleteExpr(CDE, i, Dst);
+ for (const auto i : PostVisit)
+ VisitCXXDeleteExpr(CDE, i, Dst);
- Bldr.addNodes(Dst);
- break;
- }
- // FIXME: ChooseExpr is really a constant. We need to fix
- // the CFG do not model them as explicit control-flow.
+ Bldr.addNodes(Dst);
+ break;
+ }
+ // FIXME: ChooseExpr is really a constant. We need to fix
+ // the CFG do not model them as explicit control-flow.
- case Stmt::ChooseExprClass: { // __builtin_choose_expr
- Bldr.takeNodes(Pred);
- const auto *C = cast<ChooseExpr>(S);
- VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
- }
+ case Stmt::ChooseExprClass: { // __builtin_choose_expr
+ Bldr.takeNodes(Pred);
+ const auto *C = cast<ChooseExpr>(S);
+ VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
+ }
- case Stmt::CompoundAssignOperatorClass:
- Bldr.takeNodes(Pred);
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::CompoundAssignOperatorClass:
+ Bldr.takeNodes(Pred);
+ VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::CompoundLiteralExprClass:
- Bldr.takeNodes(Pred);
- VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::CompoundLiteralExprClass:
+ Bldr.takeNodes(Pred);
+ VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::BinaryConditionalOperatorClass:
- case Stmt::ConditionalOperatorClass: { // '?' operator
- Bldr.takeNodes(Pred);
- const auto *C = cast<AbstractConditionalOperator>(S);
- VisitGuardedExpr(C, C->getTrueExpr(), C->getFalseExpr(), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
- }
+ case Stmt::BinaryConditionalOperatorClass:
+ case Stmt::ConditionalOperatorClass: { // '?' operator
+ Bldr.takeNodes(Pred);
+ const auto *C = cast<AbstractConditionalOperator>(S);
+ VisitGuardedExpr(C, C->getTrueExpr(), C->getFalseExpr(), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
+ }
- case Stmt::CXXThisExprClass:
- Bldr.takeNodes(Pred);
- VisitCXXThisExpr(cast<CXXThisExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::CXXThisExprClass:
+ Bldr.takeNodes(Pred);
+ VisitCXXThisExpr(cast<CXXThisExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::DeclRefExprClass: {
- Bldr.takeNodes(Pred);
- const auto *DE = cast<DeclRefExpr>(S);
- VisitCommonDeclRefExpr(DE, DE->getDecl(), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
- }
+ case Stmt::DeclRefExprClass: {
+ Bldr.takeNodes(Pred);
+ const auto *DE = cast<DeclRefExpr>(S);
+ VisitCommonDeclRefExpr(DE, DE->getDecl(), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
+ }
- case Stmt::DeclStmtClass:
- Bldr.takeNodes(Pred);
- VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::DeclStmtClass:
+ Bldr.takeNodes(Pred);
+ VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::ImplicitCastExprClass:
- case Stmt::CStyleCastExprClass:
- case Stmt::CXXStaticCastExprClass:
- case Stmt::CXXDynamicCastExprClass:
- case Stmt::CXXReinterpretCastExprClass:
- case Stmt::CXXConstCastExprClass:
- case Stmt::CXXFunctionalCastExprClass:
- case Stmt::BuiltinBitCastExprClass:
- case Stmt::ObjCBridgedCastExprClass:
- case Stmt::CXXAddrspaceCastExprClass: {
- Bldr.takeNodes(Pred);
- const auto *C = cast<CastExpr>(S);
- ExplodedNodeSet dstExpr;
- VisitCast(C, C->getSubExpr(), Pred, dstExpr);
-
- // Handle the postvisit checks.
- getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, C, *this);
- Bldr.addNodes(Dst);
- break;
- }
+ case Stmt::ImplicitCastExprClass:
+ case Stmt::CStyleCastExprClass:
+ case Stmt::CXXStaticCastExprClass:
+ case Stmt::CXXDynamicCastExprClass:
+ case Stmt::CXXReinterpretCastExprClass:
+ case Stmt::CXXConstCastExprClass:
+ case Stmt::CXXFunctionalCastExprClass:
+ case Stmt::BuiltinBitCastExprClass:
+ case Stmt::ObjCBridgedCastExprClass:
+ case Stmt::CXXAddrspaceCastExprClass: {
+ Bldr.takeNodes(Pred);
+ const auto *C = cast<CastExpr>(S);
+ ExplodedNodeSet dstExpr;
+ VisitCast(C, C->getSubExpr(), Pred, dstExpr);
- case Expr::MaterializeTemporaryExprClass: {
- Bldr.takeNodes(Pred);
- const auto *MTE = cast<MaterializeTemporaryExpr>(S);
- ExplodedNodeSet dstPrevisit;
- getCheckerManager().runCheckersForPreStmt(dstPrevisit, Pred, MTE, *this);
- ExplodedNodeSet dstExpr;
- for (const auto i : dstPrevisit)
- CreateCXXTemporaryObject(MTE, i, dstExpr);
- getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, MTE, *this);
- Bldr.addNodes(Dst);
- break;
- }
+ // Handle the postvisit checks.
+ getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, C, *this);
+ Bldr.addNodes(Dst);
+ break;
+ }
- case Stmt::InitListExprClass:
- Bldr.takeNodes(Pred);
- VisitInitListExpr(cast<InitListExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Expr::MaterializeTemporaryExprClass: {
+ Bldr.takeNodes(Pred);
+ const auto *MTE = cast<MaterializeTemporaryExpr>(S);
+ ExplodedNodeSet dstPrevisit;
+ getCheckerManager().runCheckersForPreStmt(dstPrevisit, Pred, MTE, *this);
+ ExplodedNodeSet dstExpr;
+ for (const auto i : dstPrevisit)
+ CreateCXXTemporaryObject(MTE, i, dstExpr);
+ getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, MTE, *this);
+ Bldr.addNodes(Dst);
+ break;
+ }
- case Stmt::MemberExprClass:
- Bldr.takeNodes(Pred);
- VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::InitListExprClass:
+ Bldr.takeNodes(Pred);
+ VisitInitListExpr(cast<InitListExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::AtomicExprClass:
- Bldr.takeNodes(Pred);
- VisitAtomicExpr(cast<AtomicExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::MemberExprClass:
+ Bldr.takeNodes(Pred);
+ VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::ObjCIvarRefExprClass:
- Bldr.takeNodes(Pred);
- VisitLvalObjCIvarRefExpr(cast<ObjCIvarRefExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::AtomicExprClass:
+ Bldr.takeNodes(Pred);
+ VisitAtomicExpr(cast<AtomicExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::ObjCForCollectionStmtClass:
- Bldr.takeNodes(Pred);
- VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::ObjCIvarRefExprClass:
+ Bldr.takeNodes(Pred);
+ VisitLvalObjCIvarRefExpr(cast<ObjCIvarRefExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::ObjCMessageExprClass:
- Bldr.takeNodes(Pred);
- VisitObjCMessage(cast<ObjCMessageExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::ObjCForCollectionStmtClass:
+ Bldr.takeNodes(Pred);
+ VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::ObjCAtThrowStmtClass:
- case Stmt::CXXThrowExprClass:
- // FIXME: This is not complete. We basically treat @throw as
- // an abort.
- Bldr.generateSink(S, Pred, Pred->getState());
- break;
+ case Stmt::ObjCMessageExprClass:
+ Bldr.takeNodes(Pred);
+ VisitObjCMessage(cast<ObjCMessageExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::ReturnStmtClass:
- Bldr.takeNodes(Pred);
- VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ case Stmt::ObjCAtThrowStmtClass:
+ case Stmt::CXXThrowExprClass:
+ // FIXME: This is not complete. We basically treat @throw as
+ // an abort.
+ Bldr.generateSink(S, Pred, Pred->getState());
+ break;
- case Stmt::OffsetOfExprClass: {
- Bldr.takeNodes(Pred);
- ExplodedNodeSet PreVisit;
- getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+ case Stmt::ReturnStmtClass:
+ Bldr.takeNodes(Pred);
+ VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- ExplodedNodeSet PostVisit;
- for (const auto Node : PreVisit)
- VisitOffsetOfExpr(cast<OffsetOfExpr>(S), Node, PostVisit);
+ case Stmt::OffsetOfExprClass: {
+ Bldr.takeNodes(Pred);
+ ExplodedNodeSet PreVisit;
+ getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
- getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
- Bldr.addNodes(Dst);
- break;
- }
+ ExplodedNodeSet PostVisit;
+ for (const auto Node : PreVisit)
+ VisitOffsetOfExpr(cast<OffsetOfExpr>(S), Node, PostVisit);
- case Stmt::UnaryExprOrTypeTraitExprClass:
- Bldr.takeNodes(Pred);
- VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S), Pred, Dst);
- Bldr.addNodes(Dst);
- break;
+ getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
+ Bldr.addNodes(Dst);
+ break;
+ }
+
+ case Stmt::UnaryExprOrTypeTraitExprClass:
+ Bldr.takeNodes(Pred);
+ VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
+ Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
- case Stmt::StmtExprClass: {
- const auto *SE = cast<StmtExpr>(S);
+ case Stmt::StmtExprClass: {
+ const auto *SE = cast<StmtExpr>(S);
- if (SE->getSubStmt()->body_empty()) {
- // Empty statement expression.
- assert(SE->getType() == getContext().VoidTy &&
- "Empty statement expression must have void type.");
+ if (SE->getSubStmt()->body_empty()) {
+ // Empty statement expression.
+ assert(SE->getType() == getContext().VoidTy
+ && "Empty statement expression must have void type.");
+ break;
+ }
+
+ if (const auto *LastExpr =
+ dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
+ ProgramStateRef state = Pred->getState();
+ Bldr.generateNode(SE, Pred,
+ state->BindExpr(SE, Pred->getLocationContext(),
+ state->getSVal(LastExpr,
+ Pred->getLocationContext())));
+ }
break;
}
- if (const auto *LastExpr =
- dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
- ProgramStateRef state = Pred->getState();
- Bldr.generateNode(
- SE, Pred,
- state->BindExpr(
- SE, Pred->getLocationContext(),
- state->getSVal(LastExpr, Pred->getLocationContext())));
+ case Stmt::UnaryOperatorClass: {
+ Bldr.takeNodes(Pred);
+ const auto *U = cast<UnaryOperator>(S);
+ if (AMgr.options.ShouldEagerlyAssume && (U->getOpcode() == UO_LNot)) {
+ ExplodedNodeSet Tmp;
+ VisitUnaryOperator(U, Pred, Tmp);
+ evalEagerlyAssumeBinOpBifurcation(Dst, Tmp, U);
+ }
+ else
+ VisitUnaryOperator(U, Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
}
- break;
- }
-
- case Stmt::UnaryOperatorClass: {
- Bldr.takeNodes(Pred);
- const auto *U = cast<UnaryOperator>(S);
- if (AMgr.options.ShouldEagerlyAssume && (U->getOpcode() == UO_LNot)) {
- ExplodedNodeSet Tmp;
- VisitUnaryOperator(U, Pred, Tmp);
- evalEagerlyAssumeBinOpBifurcation(Dst, Tmp, U);
- } else
- VisitUnaryOperator(U, Pred, Dst);
- Bldr.addNodes(Dst);
- break;
- }
- case Stmt::PseudoObjectExprClass: {
- Bldr.takeNodes(Pred);
- ProgramStateRef state = Pred->getState();
- const auto *PE = cast<PseudoObjectExpr>(S);
- if (const Expr *Result = PE->getResultExpr()) {
- SVal V = state->getSVal(Result, Pred->getLocationContext());
- Bldr.generateNode(S, Pred,
- state->BindExpr(S, Pred->getLocationContext(), V));
- } else
- Bldr.generateNode(
- S, Pred,
- state->BindExpr(S, Pred->getLocationContext(), UnknownVal()));
+ case Stmt::PseudoObjectExprClass: {
+ Bldr.takeNodes(Pred);
+ ProgramStateRef state = Pred->getState();
+ const auto *PE = cast<PseudoObjectExpr>(S);
+ if (const Expr *Result = PE->getResultExpr()) {
+ SVal V = state->getSVal(Result, Pred->getLocationContext());
+ Bldr.generateNode(S, Pred,
+ state->BindExpr(S, Pred->getLocationContext(), V));
+ }
+ else
+ Bldr.generateNode(S, Pred,
+ state->BindExpr(S, Pred->getLocationContext(),
+ UnknownVal()));
- Bldr.addNodes(Dst);
- break;
- }
+ Bldr.addNodes(Dst);
+ break;
+ }
- case Expr::ObjCIndirectCopyRestoreExprClass: {
- // ObjCIndirectCopyRestoreExpr implies passing a temporary for
- // correctness of lifetime management. Due to limited analysis
- // of ARC, this is implemented as direct arg passing.
- Bldr.takeNodes(Pred);
- ProgramStateRef state = Pred->getState();
- const auto *OIE = cast<ObjCIndirectCopyRestoreExpr>(S);
- const Expr *E = OIE->getSubExpr();
- SVal V = state->getSVal(E, Pred->getLocationContext());
- Bldr.generateNode(S, Pred,
- state->BindExpr(S, Pred->getLocationContext(), V));
- Bldr.addNodes(Dst);
- break;
- }
+ case Expr::ObjCIndirectCopyRestoreExprClass: {
+ // ObjCIndirectCopyRestoreExpr implies passing a temporary for
+ // correctness of lifetime management. Due to limited analysis
+ // of ARC, this is implemented as direct arg passing.
+ Bldr.takeNodes(Pred);
+ ProgramStateRef state = Pred->getState();
+ const auto *OIE = cast<ObjCIndirectCopyRestoreExpr>(S);
+ const Expr *E = OIE->getSubExpr();
+ SVal V = state->getSVal(E, Pred->getLocationContext());
+ Bldr.generateNode(S, Pred,
+ state->BindExpr(S, Pred->getLocationContext(), V));
+ Bldr.addNodes(Dst);
+ break;
+ }
}
}
@@ -2453,7 +2475,7 @@ bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
// Note, changing the state ensures that we are not going to cache out.
ProgramStateRef NewNodeState = BeforeProcessingCall->getState();
NewNodeState =
- NewNodeState->set<ReplayWithoutInlining>(const_cast<Stmt *>(CE));
+ NewNodeState->set<ReplayWithoutInlining>(const_cast<Stmt *>(CE));
// Make the new node a successor of BeforeProcessingCall.
bool IsNew = false;
@@ -2467,7 +2489,7 @@ bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
// Add the new node to the work list.
Engine.enqueueStmtNode(NewNode, CalleeSF->getCallSiteBlock(),
- CalleeSF->getIndex());
+ CalleeSF->getIndex());
NumTimesRetriedWithoutInlining++;
return true;
}
@@ -2479,7 +2501,7 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
// If we reach a loop which has a known bound (and meets
// other constraints) then consider completely unrolling it.
- if (AMgr.options.ShouldUnrollLoops) {
+ if(AMgr.options.ShouldUnrollLoops) {
unsigned maxBlockVisitOnPath = AMgr.options.maxBlockVisitOnPath;
const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminatorStmt();
if (Term) {
@@ -2493,7 +2515,7 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
}
}
// Is we are inside an unrolled loop then no need the check the counters.
- if (isUnrolledState(Pred->getState()))
+ if(isUnrolledState(Pred->getState()))
return;
}
@@ -2517,14 +2539,14 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
if (BlockCount >= AMgr.options.maxBlockVisitOnPath) {
static SimpleProgramPointTag tag(TagProviderName, "Block count exceeded");
const ExplodedNode *Sink =
- nodeBuilder.generateSink(Pred->getState(), Pred, &tag);
+ nodeBuilder.generateSink(Pred->getState(), Pred, &tag);
// Check if we stopped at the top level function or not.
// Root node should have the location context of the top most function.
const LocationContext *CalleeLC = Pred->getLocation().getLocationContext();
const LocationContext *CalleeSF = CalleeLC->getStackFrame();
const LocationContext *RootLC =
- (*G.roots_begin())->getLocation().getLocationContext();
+ (*G.roots_begin())->getLocation().getLocationContext();
if (RootLC->getStackFrame() != CalleeSF) {
Engine.FunctionSummaries->markReachedMaxBlockCount(CalleeSF->getDecl());
@@ -2553,8 +2575,10 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
/// integers that promote their values (which are currently not tracked well).
/// This function returns the SVal bound to Condition->IgnoreCasts if all the
// cast(s) did was sign-extend the original value.
-static SVal RecoverCastedSymbol(ProgramStateRef state, const Stmt *Condition,
- const LocationContext *LCtx, ASTContext &Ctx) {
+static SVal RecoverCastedSymbol(ProgramStateRef state,
+ const Stmt *Condition,
+ const LocationContext *LCtx,
+ ASTContext &Ctx) {
const auto *Ex = dyn_cast<Expr>(Condition);
if (!Ex)
@@ -2615,7 +2639,8 @@ static const Stmt *getRightmostLeaf(const Stmt *Condition) {
// not evaluated, and is thus not in the SVal cache, we need to use that leaf
// expression to evaluate the truth value of the condition in the current state
// space.
-static const Stmt *ResolveCondition(const Stmt *Condition, const CFGBlock *B) {
+static const Stmt *ResolveCondition(const Stmt *Condition,
+ const CFGBlock *B) {
if (const auto *Ex = dyn_cast<Expr>(Condition))
Condition = Ex->IgnoreParens();
@@ -2657,9 +2682,10 @@ ProgramStateRef ExprEngine::setWhetherHasMoreIteration(
return State->set<ObjCForHasMoreIterations>({O, LC}, HasMoreIteraton);
}
-ProgramStateRef ExprEngine::removeIterationState(ProgramStateRef State,
- const ObjCForCollectionStmt *O,
- const LocationContext *LC) {
+ProgramStateRef
+ExprEngine::removeIterationState(ProgramStateRef State,
+ const ObjCForCollectionStmt *O,
+ const LocationContext *LC) {
assert(State->contains<ObjCForHasMoreIterations>({O, LC}));
return State->remove<ObjCForHasMoreIterations>({O, LC});
}
@@ -2722,8 +2748,10 @@ assumeCondition(const Stmt *Condition, ExplodedNode *N) {
}
void ExprEngine::processBranch(const Stmt *Condition,
- NodeBuilderContext &BldCtx, ExplodedNode *Pred,
- ExplodedNodeSet &Dst, const CFGBlock *DstT,
+ NodeBuilderContext& BldCtx,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst,
+ const CFGBlock *DstT,
const CFGBlock *DstF) {
assert((!Condition || !isa<CXXBindTemporaryExpr>(Condition)) &&
"CXXBindTemporaryExprs are handled by processBindTemporary.");
@@ -2797,9 +2825,12 @@ void ExprEngine::processBranch(const Stmt *Condition,
REGISTER_TRAIT_WITH_PROGRAMSTATE(InitializedGlobalsSet,
llvm::ImmutableSet<const VarDecl *>)
-void ExprEngine::processStaticInitializer(
- const DeclStmt *DS, NodeBuilderContext &BuilderCtx, ExplodedNode *Pred,
- ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF) {
+void ExprEngine::processStaticInitializer(const DeclStmt *DS,
+ NodeBuilderContext &BuilderCtx,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst,
+ const CFGBlock *DstT,
+ const CFGBlock *DstF) {
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
currBldrCtx = &BuilderCtx;
@@ -2848,7 +2879,7 @@ void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
if (isa<UndefinedVal, loc::ConcreteInt>(V)) {
// Dispatch to the first target and mark it as a sink.
- // ExplodedNode* N = builder.generateNode(builder.begin(), state, true);
+ //ExplodedNode* N = builder.generateNode(builder.begin(), state, true);
// FIXME: add checker visit.
// UndefBranches.insert(N);
return;
@@ -2871,7 +2902,7 @@ void ExprEngine::processBeginOfFunction(NodeBuilderContext &BC,
/// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path
/// nodes when the control reaches the end of a function.
-void ExprEngine::processEndOfFunction(NodeBuilderContext &BC,
+void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
ExplodedNode *Pred,
const ReturnStmt *RS) {
ProgramStateRef State = Pred->getState();
@@ -2945,17 +2976,17 @@ void ExprEngine::processEndOfFunction(NodeBuilderContext &BC,
/// ProcessSwitch - Called by CoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a switch statement.
-void ExprEngine::processSwitch(SwitchNodeBuilder &builder) {
+void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
using iterator = SwitchNodeBuilder::iterator;
ProgramStateRef state = builder.getState();
const Expr *CondE = builder.getCondition();
- SVal CondV_untested = state->getSVal(CondE, builder.getLocationContext());
+ SVal CondV_untested = state->getSVal(CondE, builder.getLocationContext());
if (CondV_untested.isUndef()) {
- // ExplodedNode* N = builder.generateDefaultCaseNode(state, true);
- // FIXME: add checker
- // UndefBranches.insert(N);
+ //ExplodedNode* N = builder.generateDefaultCaseNode(state, true);
+ // FIXME: add checker
+ //UndefBranches.insert(N);
return;
}
@@ -2966,7 +2997,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder &builder) {
iterator I = builder.begin(), EI = builder.end();
bool defaultIsFeasible = I == EI;
- for (; I != EI; ++I) {
+ for ( ; I != EI; ++I) {
// Successor may be pruned out during CFG construction.
if (!I.getBlock())
continue;
@@ -3058,7 +3089,8 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
// Sema follows a sequence of complex rules to determine whether the
// variable should be captured.
if (const FieldDecl *FD = LambdaCaptureFields[VD]) {
- Loc CXXThis = svalBuilder.getCXXThis(MD, LocCtxt->getStackFrame());
+ Loc CXXThis =
+ svalBuilder.getCXXThis(MD, LocCtxt->getStackFrame());
SVal CXXThisVal = state->getSVal(CXXThis);
VInfo = std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType());
}
@@ -3266,10 +3298,10 @@ void ExprEngine::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *Ex,
/// VisitArraySubscriptExpr - Transfer function for array accesses
void ExprEngine::VisitArraySubscriptExpr(const ArraySubscriptExpr *A,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst) {
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst){
const Expr *Base = A->getBase()->IgnoreParens();
- const Expr *Idx = A->getIdx()->IgnoreParens();
+ const Expr *Idx = A->getIdx()->IgnoreParens();
ExplodedNodeSet CheckerPreStmt;
getCheckerManager().runCheckersForPreStmt(CheckerPreStmt, Pred, A, *this);
@@ -3282,9 +3314,8 @@ void ExprEngine::VisitArraySubscriptExpr(const ArraySubscriptExpr *A,
// The "like" case is for situations where C standard prohibits the type to
// be an lvalue, e.g. taking the address of a subscript of an expression of
// type "void *".
- bool IsGLValueLike =
- A->isGLValue() ||
- (A->getType().isCForbiddenLValueType() && !AMgr.getLangOpts().CPlusPlus);
+ bool IsGLValueLike = A->isGLValue() ||
+ (A->getType().isCForbiddenLValueType() && !AMgr.getLangOpts().CPlusPlus);
for (auto *Node : CheckerPreStmt) {
const LocationContext *LCtx = Node->getLocationContext();
@@ -3299,10 +3330,11 @@ void ExprEngine::VisitArraySubscriptExpr(const ArraySubscriptExpr *A,
if (T->isVoidType())
T = getContext().CharTy;
- SVal V = state->getLValue(T, state->getSVal(Idx, LCtx),
+ SVal V = state->getLValue(T,
+ state->getSVal(Idx, LCtx),
state->getSVal(Base, LCtx));
Bldr.generateNode(A, Node, state->BindExpr(A, LCtx, V), nullptr,
- ProgramPoint::PostLValueKind);
+ ProgramPoint::PostLValueKind);
} else if (IsVectorType) {
// FIXME: non-glvalue vector reads are not modelled.
Bldr.generateNode(A, Node, state, nullptr);
@@ -3377,8 +3409,8 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
// pointers as soon as they are used.
if (!M->isGLValue()) {
assert(M->getType()->isArrayType());
- const auto *PE = dyn_cast<ImplicitCastExpr>(
- I->getParentMap().getParentIgnoreParens(M));
+ const auto *PE =
+ dyn_cast<ImplicitCastExpr>(I->getParentMap().getParentIgnoreParens(M));
if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {
llvm_unreachable("should always be wrapped in ArrayToPointerDecay");
}
@@ -3427,17 +3459,18 @@ void ExprEngine::VisitAtomicExpr(const AtomicExpr *AE, ExplodedNode *Pred,
}
State = State->invalidateRegions(ValuesToInvalidate, AE,
- currBldrCtx->blockCount(), LCtx,
- /*CausedByPointerEscape*/ true,
- /*Symbols=*/nullptr);
+ currBldrCtx->blockCount(),
+ LCtx,
+ /*CausedByPointerEscape*/true,
+ /*Symbols=*/nullptr);
SVal ResultVal = UnknownVal();
State = State->BindExpr(AE, LCtx, ResultVal);
- Bldr.generateNode(AE, I, State, nullptr, ProgramPoint::PostStmtKind);
+ Bldr.generateNode(AE, I, State, nullptr,
+ ProgramPoint::PostStmtKind);
}
- getCheckerManager().runCheckersForPostStmt(Dst, AfterInvalidateSet, AE,
- *this);
+ getCheckerManager().runCheckersForPostStmt(Dst, AfterInvalidateSet, AE, *this);
}
// A value escapes in four possible cases:
@@ -3496,16 +3529,21 @@ ExprEngine::processPointerEscapedOnBind(ProgramStateRef State, SVal Loc,
nullptr);
}
-ProgramStateRef ExprEngine::notifyCheckersOfPointerEscape(
- ProgramStateRef State, const InvalidatedSymbols *Invalidated,
- ArrayRef<const MemRegion *> ExplicitRegions, const CallEvent *Call,
+ProgramStateRef
+ExprEngine::notifyCheckersOfPointerEscape(ProgramStateRef State,
+ const InvalidatedSymbols *Invalidated,
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ const CallEvent *Call,
RegionAndSymbolInvalidationTraits &ITraits) {
if (!Invalidated || Invalidated->empty())
return State;
if (!Call)
- return getCheckerManager().runCheckersForPointerEscape(
- State, *Invalidated, nullptr, PSK_EscapeOther, &ITraits);
+ return getCheckerManager().runCheckersForPointerEscape(State,
+ *Invalidated,
+ nullptr,
+ PSK_EscapeOther,
+ &ITraits);
// If the symbols were invalidated by a call, we want to find out which ones
// were invalidated directly due to being arguments to the call.
@@ -3523,15 +3561,13 @@ ProgramStateRef ExprEngine::notifyCheckersOfPointerEscape(
}
if (!SymbolsDirectlyInvalidated.empty())
- State = getCheckerManager().runCheckersForPointerEscape(
- State, SymbolsDirectlyInvalidated, Call, PSK_DirectEscapeOnCall,
- &ITraits);
+ State = getCheckerManager().runCheckersForPointerEscape(State,
+ SymbolsDirectlyInvalidated, Call, PSK_DirectEscapeOnCall, &ITraits);
// Notify about the symbols that get indirectly invalidated by the call.
if (!SymbolsIndirectlyInvalidated.empty())
- State = getCheckerManager().runCheckersForPointerEscape(
- State, SymbolsIndirectlyInvalidated, Call, PSK_IndirectEscapeOnCall,
- &ITraits);
+ State = getCheckerManager().runCheckersForPointerEscape(State,
+ SymbolsIndirectlyInvalidated, Call, PSK_IndirectEscapeOnCall, &ITraits);
return State;
}
@@ -3539,7 +3575,8 @@ ProgramStateRef ExprEngine::notifyCheckersOfPointerEscape(
/// evalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by evalStore and (soon) VisitDeclStmt, and others.
void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
- ExplodedNode *Pred, SVal location, SVal Val,
+ ExplodedNode *Pred,
+ SVal location, SVal Val,
bool atDeclInit, const ProgramPoint *PP) {
const LocationContext *LC = Pred->getLocationContext();
PostStmt PS(StoreE, LC);
@@ -3556,8 +3593,8 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
// If the location is not a 'Loc', it will already be handled by
// the checkers. There is nothing left to do.
if (!isa<Loc>(location)) {
- const ProgramPoint L = PostStore(StoreE, LC, /*Loc*/ nullptr,
- /*tag*/ nullptr);
+ const ProgramPoint L = PostStore(StoreE, LC, /*Loc*/nullptr,
+ /*tag*/nullptr);
ProgramStateRef state = Pred->getState();
state = processPointerEscapedOnBind(state, location, Val, LC);
Bldr.generateNode(L, state, Pred);
@@ -3572,8 +3609,8 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
// When binding the value, pass on the hint that this is a initialization.
// For initializations, we do not need to inform clients of region
// changes.
- state = state->bindLoc(location.castAs<Loc>(), Val, LC,
- /* notifyChanges = */ !atDeclInit);
+ state = state->bindLoc(location.castAs<Loc>(),
+ Val, LC, /* notifyChanges = */ !atDeclInit);
const MemRegion *LocReg = nullptr;
if (std::optional<loc::MemRegionVal> LocRegVal =
@@ -3595,9 +3632,10 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
/// @param location The location to store the value
/// @param Val The value to be stored
void ExprEngine::evalStore(ExplodedNodeSet &Dst, const Expr *AssignE,
- const Expr *LocationE, ExplodedNode *Pred,
- ProgramStateRef state, SVal location, SVal Val,
- const ProgramPointTag *tag) {
+ const Expr *LocationE,
+ ExplodedNode *Pred,
+ ProgramStateRef state, SVal location, SVal Val,
+ const ProgramPointTag *tag) {
// Proceed with the store. We use AssignE as the anchor for the PostStore
// ProgramPoint if it is non-NULL, and LocationE otherwise.
const Expr *StoreE = AssignE ? AssignE : LocationE;
@@ -3616,10 +3654,14 @@ void ExprEngine::evalStore(ExplodedNodeSet &Dst, const Expr *AssignE,
evalBind(Dst, StoreE, I, location, Val, false);
}
-void ExprEngine::evalLoad(ExplodedNodeSet &Dst, const Expr *NodeEx,
- const Expr *BoundEx, ExplodedNode *Pred,
- ProgramStateRef state, SVal location,
- const ProgramPointTag *tag, QualType LoadTy) {
+void ExprEngine::evalLoad(ExplodedNodeSet &Dst,
+ const Expr *NodeEx,
+ const Expr *BoundEx,
+ ExplodedNode *Pred,
+ ProgramStateRef state,
+ SVal location,
+ const ProgramPointTag *tag,
+ QualType LoadTy) {
assert(!isa<NonLoc>(location) && "location cannot be a NonLoc.");
assert(NodeEx);
assert(BoundEx);
@@ -3650,9 +3692,12 @@ void ExprEngine::evalLoad(ExplodedNodeSet &Dst, const Expr *NodeEx,
}
}
-void ExprEngine::evalLocation(ExplodedNodeSet &Dst, const Stmt *NodeEx,
- const Stmt *BoundEx, ExplodedNode *Pred,
- ProgramStateRef state, SVal location,
+void ExprEngine::evalLocation(ExplodedNodeSet &Dst,
+ const Stmt *NodeEx,
+ const Stmt *BoundEx,
+ ExplodedNode *Pred,
+ ProgramStateRef state,
+ SVal location,
bool isLoad) {
StmtNodeBuilder BldrTop(Pred, Dst, *currBldrCtx);
// Early checks for performance reason.
@@ -3677,17 +3722,18 @@ void ExprEngine::evalLocation(ExplodedNodeSet &Dst, const Stmt *NodeEx,
Bldr.generateNode(NodeEx, Pred, state, &tag);
}
ExplodedNodeSet Tmp;
- getCheckerManager().runCheckersForLocation(Tmp, Src, location, isLoad, NodeEx,
- BoundEx, *this);
+ getCheckerManager().runCheckersForLocation(Tmp, Src, location, isLoad,
+ NodeEx, BoundEx, *this);
BldrTop.addNodes(Tmp);
}
-std::pair<const ProgramPointTag *, const ProgramPointTag *>
+std::pair<const ProgramPointTag *, const ProgramPointTag*>
ExprEngine::geteagerlyAssumeBinOpBifurcationTags() {
- static SimpleProgramPointTag eagerlyAssumeBinOpBifurcationTrue(
- TagProviderName, "Eagerly Assume True"),
- eagerlyAssumeBinOpBifurcationFalse(TagProviderName,
- "Eagerly Assume False");
+ static SimpleProgramPointTag
+ eagerlyAssumeBinOpBifurcationTrue(TagProviderName,
+ "Eagerly Assume True"),
+ eagerlyAssumeBinOpBifurcationFalse(TagProviderName,
+ "Eagerly Assume False");
return std::make_pair(&eagerlyAssumeBinOpBifurcationTrue,
&eagerlyAssumeBinOpBifurcationFalse);
}
@@ -3710,8 +3756,8 @@ void ExprEngine::evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst,
SVal V = state->getSVal(Ex, Pred->getLocationContext());
std::optional<nonloc::SymbolVal> SEV = V.getAs<nonloc::SymbolVal>();
if (SEV && SEV->isExpression()) {
- const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags =
- geteagerlyAssumeBinOpBifurcationTags();
+ const std::pair<const ProgramPointTag *, const ProgramPointTag*> &tags =
+ geteagerlyAssumeBinOpBifurcationTags();
ProgramStateRef StateTrue, StateFalse;
std::tie(StateTrue, StateFalse) = state->assume(*SEV);
@@ -3768,14 +3814,13 @@ void ExprEngine::VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred,
namespace llvm {
-template <>
-struct DOTGraphTraits<ExplodedGraph *> : public DefaultDOTGraphTraits {
- DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
+template<>
+struct DOTGraphTraits<ExplodedGraph*> : public DefaultDOTGraphTraits {
+ DOTGraphTraits (bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
static bool nodeHasBugReport(const ExplodedNode *N) {
BugReporter &BR = static_cast<ExprEngine &>(
- N->getState()->getStateManager().getOwningEngine())
- .getBugReporter();
+ N->getState()->getStateManager().getOwningEngine()).getBugReporter();
for (const auto &Class : BR.equivalenceClasses()) {
for (const auto &Report : Class.getReports()) {
@@ -3818,7 +3863,7 @@ struct DOTGraphTraits<ExplodedGraph *> : public DefaultDOTGraphTraits {
return N->isTrivial();
}
- static std::string getNodeLabel(const ExplodedNode *N, ExplodedGraph *G) {
+ static std::string getNodeLabel(const ExplodedNode *N, ExplodedGraph *G){
std::string Buf;
llvm::raw_string_ostream Out(Buf);
@@ -3826,7 +3871,8 @@ struct DOTGraphTraits<ExplodedGraph *> : public DefaultDOTGraphTraits {
const unsigned int Space = 1;
ProgramStateRef State = N->getState();
- Out << "{ \"state_id\": " << State->getID() << ",\\l";
+ Out << "{ \"state_id\": " << State->getID()
+ << ",\\l";
Indent(Out, Space, IsDot) << "\"program_points\": [\\l";
@@ -3841,9 +3887,9 @@ struct DOTGraphTraits<ExplodedGraph *> : public DefaultDOTGraphTraits {
Out << '\"' << Tag->getTagDescription() << '\"';
else
Out << "null";
- Out << ", \"node_id\": " << OtherNode->getID()
- << ", \"is_sink\": " << OtherNode->isSink()
- << ", \"has_report\": " << nodeHasBugReport(OtherNode) << " }";
+ Out << ", \"node_id\": " << OtherNode->getID() <<
+ ", \"is_sink\": " << OtherNode->isSink() <<
+ ", \"has_report\": " << nodeHasBugReport(OtherNode) << " }";
},
// Adds a comma and a new-line between each program point.
[&](const ExplodedNode *) { Out << ",\\l"; },
@@ -3912,4 +3958,4 @@ void *ProgramStateTrait<ReplayWithoutInlining>::GDMIndex() {
return &index;
}
-void ExprEngine::anchor() {}
+void ExprEngine::anchor() { }
>From 32453aee0cb80d342a627505f3339b562630a13d Mon Sep 17 00:00:00 2001
From: T-Gruber <tobi.gruber at gmx.de>
Date: Thu, 13 Jun 2024 21:02:27 +0200
Subject: [PATCH 3/6] Removed unused locals in code snippets
---
clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp b/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp
index b5d25e98dba55..66cdac413301b 100644
--- a/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp
+++ b/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp
@@ -68,7 +68,6 @@ void addExprEngineVisitPostChecker(AnalysisASTConsumer &AnalysisConsumer,
TEST(ExprEngineVisitTest, checkPreStmtGCCAsmStmt) {
std::string Diags;
EXPECT_TRUE(runCheckerOnCode<addExprEngineVisitPreChecker>(R"(
- int a = 1;
void top() {
asm("");
}
@@ -80,7 +79,6 @@ TEST(ExprEngineVisitTest, checkPreStmtGCCAsmStmt) {
TEST(ExprEngineVisitTest, checkPostStmtGCCAsmStmt) {
std::string Diags;
EXPECT_TRUE(runCheckerOnCode<addExprEngineVisitPostChecker>(R"(
- int a = 1;
void top() {
asm("");
}
>From 945ac12275202e18e741bed63190f01baf2c2050 Mon Sep 17 00:00:00 2001
From: T-Gruber <tobi.gruber at gmx.de>
Date: Wed, 10 Jul 2024 10:35:36 +0200
Subject: [PATCH 4/6] Move break into braces
---
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 4bfa0a599da67..b541d8f637b21 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -2066,7 +2066,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
VisitGCCAsmStmt(cast<GCCAsmStmt>(S), N, PostVisit);
getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
Bldr.addNodes(Dst);
- } break;
+ break;
+ }
case Stmt::MSAsmStmtClass:
Bldr.takeNodes(Pred);
>From 28b646792249bad0a01d9724cc538df5d41736da Mon Sep 17 00:00:00 2001
From: T-Gruber <tobi.gruber at gmx.de>
Date: Wed, 10 Jul 2024 10:37:17 +0200
Subject: [PATCH 5/6] Adapted format of file header
---
clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp b/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp
index 66cdac413301b..e0006597f24d3 100644
--- a/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp
+++ b/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp
@@ -1,4 +1,4 @@
-//===- ExprEngineVisitTest.cpp -----------------------------------===//
+//===- ExprEngineVisitTest.cpp --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,6 +6,7 @@
//
//===----------------------------------------------------------------------===//
+
#include "CheckerRegistration.h"
#include "clang/AST/Stmt.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
>From 537c144979ce93befe25cabc8415446aba90ff81 Mon Sep 17 00:00:00 2001
From: T-Gruber <tobi.gruber at gmx.de>
Date: Wed, 10 Jul 2024 13:44:16 +0200
Subject: [PATCH 6/6] Reworked unittest
---
.../StaticAnalyzer/ExprEngineVisitTest.cpp | 38 +++++++++----------
1 file changed, 17 insertions(+), 21 deletions(-)
diff --git a/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp b/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp
index e0006597f24d3..a8579f9d0f90c 100644
--- a/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp
+++ b/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp
@@ -6,7 +6,6 @@
//
//===----------------------------------------------------------------------===//
-
#include "CheckerRegistration.h"
#include "clang/AST/Stmt.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
@@ -28,25 +27,22 @@ void emitErrorReport(CheckerContext &C, const BugType &Bug,
}
}
-class ExprEngineVisitPreChecker : public Checker<check::PreStmt<GCCAsmStmt>> {
-public:
- void checkPreStmt(const GCCAsmStmt *ASM, CheckerContext &C) const {
- emitErrorReport(C, Bug, "PreStmt<GCCAsmStmt>");
- }
-
-private:
- const BugType Bug{this, "GCCAsmStmtBug"};
-};
-
-class ExprEngineVisitPostChecker : public Checker<check::PostStmt<GCCAsmStmt>> {
-public:
- void checkPostStmt(const GCCAsmStmt *ASM, CheckerContext &C) const {
- emitErrorReport(C, Bug, "PostStmt<GCCAsmStmt>");
- }
+#define CREATE_EXPR_ENGINE_CHECKER(CHECKER_NAME, CALLBACK, STMT_TYPE, \
+ BUG_NAME) \
+ class CHECKER_NAME : public Checker<check::CALLBACK<STMT_TYPE>> { \
+ public: \
+ void check##CALLBACK(const STMT_TYPE *ASM, CheckerContext &C) const { \
+ emitErrorReport(C, Bug, "check" #CALLBACK "<" #STMT_TYPE ">"); \
+ } \
+ \
+ private: \
+ const BugType Bug{this, BUG_NAME}; \
+ };
-private:
- const BugType Bug{this, "GCCAsmStmtBug"};
-};
+CREATE_EXPR_ENGINE_CHECKER(ExprEngineVisitPreChecker, PreStmt, GCCAsmStmt,
+ "GCCAsmStmtBug")
+CREATE_EXPR_ENGINE_CHECKER(ExprEngineVisitPostChecker, PostStmt, GCCAsmStmt,
+ "GCCAsmStmtBug")
void addExprEngineVisitPreChecker(AnalysisASTConsumer &AnalysisConsumer,
AnalyzerOptions &AnOpts) {
@@ -74,7 +70,7 @@ TEST(ExprEngineVisitTest, checkPreStmtGCCAsmStmt) {
}
)",
Diags));
- EXPECT_EQ(Diags, "ExprEngineVisitPreChecker: PreStmt<GCCAsmStmt>\n");
+ EXPECT_EQ(Diags, "ExprEngineVisitPreChecker: checkPreStmt<GCCAsmStmt>\n");
}
TEST(ExprEngineVisitTest, checkPostStmtGCCAsmStmt) {
@@ -85,7 +81,7 @@ TEST(ExprEngineVisitTest, checkPostStmtGCCAsmStmt) {
}
)",
Diags));
- EXPECT_EQ(Diags, "ExprEngineVisitPostChecker: PostStmt<GCCAsmStmt>\n");
+ EXPECT_EQ(Diags, "ExprEngineVisitPostChecker: checkPostStmt<GCCAsmStmt>\n");
}
} // namespace
More information about the cfe-commits
mailing list