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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits