[clang] Run PreStmt/PostStmt checker for GCCAsmStmt (PR #95409)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jun 13 06:56:45 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
@llvm/pr-subscribers-clang-static-analyzer-1
Author: None (T-Gruber)
<details>
<summary>Changes</summary>
Run PreStmt and PostStmt checker for GCCAsmStmt.
Unittest to validate that corresponding callback functions are triggered.
---
Patch is 89.28 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/95409.diff
3 Files Affected:
- (modified) clang/lib/StaticAnalyzer/Core/ExprEngine.cpp (+776-817)
- (modified) clang/unittests/StaticAnalyzer/CMakeLists.txt (+1)
- (added) clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp (+92)
``````````diff
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::OMPParallelForD...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/95409
More information about the cfe-commits
mailing list