From ed8c05cc99c3b21ca0667908881df6b10eebc5b5 Mon Sep 17 00:00:00 2001 From: Reka Kovacs Date: Mon, 16 Jul 2018 20:47:45 +0000 Subject: [PATCH] [analyzer] Make checkEndFunction() give access to the return statement. Differential Revision: https://reviews.llvm.org/D49387 llvm-svn: 337215 --- clang/include/clang/StaticAnalyzer/Core/Checker.h | 4 ++-- clang/include/clang/StaticAnalyzer/Core/CheckerManager.h | 8 +++++--- clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp | 4 ++-- .../lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp | 2 +- .../StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp | 5 +++-- clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp | 5 +++-- .../StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp | 5 +++-- .../StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp | 5 +++-- clang/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp | 5 +++-- .../Checkers/UninitializedObjectChecker.cpp | 4 ++-- clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp | 5 +++-- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp | 5 +++-- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 4 ++-- 13 files changed, 35 insertions(+), 26 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/Checker.h b/clang/include/clang/StaticAnalyzer/Core/Checker.h index a7f9a12b2c73d..45b7a61139ea7 100644 --- a/clang/include/clang/StaticAnalyzer/Core/Checker.h +++ b/clang/include/clang/StaticAnalyzer/Core/Checker.h @@ -254,9 +254,9 @@ class BeginFunction { class EndFunction { template - static void _checkEndFunction(void *checker, + static void _checkEndFunction(void *checker, const ReturnStmt *RS, CheckerContext &C) { - ((const CHECKER *)checker)->checkEndFunction(C); + ((const CHECKER *)checker)->checkEndFunction(RS, C); } public: diff --git a/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h b/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h index 99a8eb01fa73b..33a794061a384 100644 --- a/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -296,7 +296,8 @@ class CheckerManager { void runCheckersForEndFunction(NodeBuilderContext &BC, ExplodedNodeSet &Dst, ExplodedNode *Pred, - ExprEngine &Eng); + ExprEngine &Eng, + const ReturnStmt *RS); /// Run checkers for branch condition. void runCheckersForBranchCondition(const Stmt *condition, @@ -438,7 +439,8 @@ class CheckerManager { using CheckBeginFunctionFunc = CheckerFn; - using CheckEndFunctionFunc = CheckerFn; + using CheckEndFunctionFunc = + CheckerFn; using CheckBranchConditionFunc = CheckerFn; @@ -496,7 +498,7 @@ class CheckerManager { void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn); - void _registerForBeginFunction(CheckEndFunctionFunc checkfn); + void _registerForBeginFunction(CheckBeginFunctionFunc checkfn); void _registerForEndFunction(CheckEndFunctionFunc checkfn); void _registerForBranchCondition(CheckBranchConditionFunc checkfn); diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp b/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp index bfd4019ed8d72..f4d2e32cef111 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp @@ -126,7 +126,7 @@ class ObjCDeallocChecker const CallEvent *Call, PointerEscapeKind Kind) const; void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const; - void checkEndFunction(CheckerContext &Ctx) const; + void checkEndFunction(const ReturnStmt *RS, CheckerContext &Ctx) const; private: void diagnoseMissingReleases(CheckerContext &C) const; @@ -398,7 +398,7 @@ void ObjCDeallocChecker::checkPostObjCMessage( /// Check for missing releases even when -dealloc does not call /// '[super dealloc]'. void ObjCDeallocChecker::checkEndFunction( - CheckerContext &C) const { + const ReturnStmt *RS, CheckerContext &C) const { diagnoseMissingReleases(C); } diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp b/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp index 495486bf393cd..7862a4c256814 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp @@ -192,7 +192,7 @@ class CheckerDocumentation : public Checker< check::PreStmt, /// level or is inlined. /// /// check::EndFunction - void checkEndFunction(CheckerContext &Ctx) const {} + void checkEndFunction(const ReturnStmt *RS, CheckerContext &Ctx) const {} /// Called after all the paths in the ExplodedGraph reach end of path /// - the symbolic execution graph is fully explored. diff --git a/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp index 258eb05ca7363..19c1d077afa15 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp @@ -46,7 +46,7 @@ class MisusedMovedObjectChecker : public Checker { public: - void checkEndFunction(CheckerContext &C) const; + void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const; void checkPreCall(const CallEvent &MC, CheckerContext &C) const; void checkPostCall(const CallEvent &MC, CheckerContext &C) const; void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; @@ -222,7 +222,8 @@ ExplodedNode *MisusedMovedObjectChecker::reportBug(const MemRegion *Region, // Removing the function parameters' MemRegion from the state. This is needed // for PODs where the trivial destructor does not even created nor executed. -void MisusedMovedObjectChecker::checkEndFunction(CheckerContext &C) const { +void MisusedMovedObjectChecker::checkEndFunction(const ReturnStmt *RS, + CheckerContext &C) const { auto State = C.getState(); TrackedRegionMapTy Objects = State->get(); if (Objects.isEmpty()) diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index 54e87d4094f2e..2c1e139330d68 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -2743,7 +2743,7 @@ class RetainCountChecker void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; void checkBeginFunction(CheckerContext &C) const; - void checkEndFunction(CheckerContext &C) const; + void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const; ProgramStateRef updateSymbol(ProgramStateRef state, SymbolRef sym, RefVal V, ArgEffect E, RefVal::Kind &hasErr, @@ -3991,7 +3991,8 @@ void RetainCountChecker::checkBeginFunction(CheckerContext &Ctx) const { Ctx.addTransition(state); } -void RetainCountChecker::checkEndFunction(CheckerContext &Ctx) const { +void RetainCountChecker::checkEndFunction(const ReturnStmt *RS, + CheckerContext &Ctx) const { ProgramStateRef state = Ctx.getState(); RefBindingsTy B = state->get(); ExplodedNode *Pred = Ctx.getPredecessor(); diff --git a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp index 86936cadd5522..feae9e59b343a 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp @@ -47,7 +47,7 @@ class StackAddrEscapeChecker void checkPreCall(const CallEvent &Call, CheckerContext &C) const; void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const; - void checkEndFunction(CheckerContext &Ctx) const; + void checkEndFunction(const ReturnStmt *RS, CheckerContext &Ctx) const; private: void checkReturnedBlockCaptures(const BlockDataRegion &B, @@ -287,7 +287,8 @@ void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS, EmitStackError(C, R, RetE); } -void StackAddrEscapeChecker::checkEndFunction(CheckerContext &Ctx) const { +void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS, + CheckerContext &Ctx) const { if (!ChecksEnabled[CK_StackAddrEscapeChecker]) return; diff --git a/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp index eac743349d8a5..f4c0edbab3f0a 100644 --- a/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp @@ -85,7 +85,7 @@ class TestAfterDivZeroChecker public: void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const; void checkBranchCondition(const Stmt *Condition, CheckerContext &C) const; - void checkEndFunction(CheckerContext &C) const; + void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const; void setDivZeroMap(SVal Var, CheckerContext &C) const; bool hasDivZeroMap(SVal Var, const CheckerContext &C) const; bool isZero(SVal S, CheckerContext &C) const; @@ -180,7 +180,8 @@ void TestAfterDivZeroChecker::reportBug(SVal Val, CheckerContext &C) const { } } -void TestAfterDivZeroChecker::checkEndFunction(CheckerContext &C) const { +void TestAfterDivZeroChecker::checkEndFunction(const ReturnStmt *RS, + CheckerContext &C) const { ProgramStateRef State = C.getState(); DivZeroMapTy DivZeroes = State->get(); diff --git a/clang/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp index 8ad962875b060..ee185b813611a 100644 --- a/clang/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp @@ -30,7 +30,7 @@ class TraversalDumper : public Checker< check::BranchCondition, public: void checkBranchCondition(const Stmt *Condition, CheckerContext &C) const; void checkBeginFunction(CheckerContext &C) const; - void checkEndFunction(CheckerContext &C) const; + void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const; }; } @@ -56,7 +56,8 @@ void TraversalDumper::checkBeginFunction(CheckerContext &C) const { llvm::outs() << "--BEGIN FUNCTION--\n"; } -void TraversalDumper::checkEndFunction(CheckerContext &C) const { +void TraversalDumper::checkEndFunction(const ReturnStmt *RS, + CheckerContext &C) const { llvm::outs() << "--END FUNCTION--\n"; } diff --git a/clang/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp index 5c94a5bd33711..398228a9d8871 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp @@ -47,7 +47,7 @@ class UninitializedObjectChecker : public Checker { UninitializedObjectChecker() : BT_uninitField(new BuiltinBug(this, "Uninitialized fields")) {} - void checkEndFunction(CheckerContext &C) const; + void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const; }; /// Represents a field chain. A field chain is a vector of fields where the @@ -241,7 +241,7 @@ static StringRef getVariableName(const FieldDecl *Field); //===----------------------------------------------------------------------===// void UninitializedObjectChecker::checkEndFunction( - CheckerContext &Context) const { + const ReturnStmt *RS, CheckerContext &Context) const { const auto *CtorDecl = dyn_cast_or_null( Context.getLocationContext()->getDecl()); diff --git a/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp index ec5afa5134a02..5b602468cdd4b 100644 --- a/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp @@ -48,7 +48,7 @@ class VirtualCallChecker DefaultBool IsPureOnly; void checkBeginFunction(CheckerContext &C) const; - void checkEndFunction(CheckerContext &C) const; + void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const; void checkPreCall(const CallEvent &Call, CheckerContext &C) const; private: @@ -167,7 +167,8 @@ void VirtualCallChecker::checkBeginFunction(CheckerContext &C) const { } // The EndFunction callback when leave a constructor or a destructor. -void VirtualCallChecker::checkEndFunction(CheckerContext &C) const { +void VirtualCallChecker::checkEndFunction(const ReturnStmt *RS, + CheckerContext &C) const { registerCtorDtorCallInState(false, C); } diff --git a/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp b/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp index e355fa28eafce..712872a15d8a0 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp @@ -439,7 +439,8 @@ void CheckerManager::runCheckersForBeginFunction(ExplodedNodeSet &Dst, void CheckerManager::runCheckersForEndFunction(NodeBuilderContext &BC, ExplodedNodeSet &Dst, ExplodedNode *Pred, - ExprEngine &Eng) { + ExprEngine &Eng, + const ReturnStmt *RS) { // We define the builder outside of the loop bacause if at least one checkers // creates a sucsessor for Pred, we do not need to generate an // autotransition for it. @@ -449,7 +450,7 @@ void CheckerManager::runCheckersForEndFunction(NodeBuilderContext &BC, Pred->getLocationContext(), checkFn.Checker); CheckerContext C(Bldr, Eng, Pred, L); - checkFn(C); + checkFn(RS, C); } } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 27f7553e7ae78..188316c096e38 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -2297,9 +2297,9 @@ void ExprEngine::processEndOfFunction(NodeBuilderContext& BC, // Notify checkers. for (const auto I : AfterRemovedDead) - getCheckerManager().runCheckersForEndFunction(BC, Dst, I, *this); + getCheckerManager().runCheckersForEndFunction(BC, Dst, I, *this, RS); } else { - getCheckerManager().runCheckersForEndFunction(BC, Dst, Pred, *this); + getCheckerManager().runCheckersForEndFunction(BC, Dst, Pred, *this, RS); } Engine.enqueueEndOfFunction(Dst, RS);