diff options
author | Anna Zaks <ganna@apple.com> | 2012-04-20 21:59:08 +0000 |
---|---|---|
committer | Anna Zaks <ganna@apple.com> | 2012-04-20 21:59:08 +0000 |
commit | 0b3ade86a1c60cf0c7b56aa238aff458eb7f5974 (patch) | |
tree | 870a9b3597eaabc3fd9a6a3c18b91b0f450b5a17 /include/clang/Analysis/ProgramPoint.h | |
parent | 39b73411313b1204601755e8c4813853f30b9a33 (diff) |
[analyzer] Run remove dead bindings right before leaving a function.
This is needed to ensure that we always report issues in the correct
function. For example, leaks are identified when we call remove dead
bindings. In order to make sure we report a callee's leak in the callee,
we have to run the operation in the callee's context.
This change required quite a bit of infrastructure work since:
- We used to only run remove dead bindings before a given statement;
here we need to run it after the last statement in the function. For
this, we added additional Program Point and special mode in the
SymbolReaper to remove all symbols in context lower than the current
one.
- The call exit operation turned into a sequence of nodes, which are
now guarded by CallExitBegin and CallExitEnd nodes for clarity and
convenience.
(Sorry for the long diff.)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155244 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang/Analysis/ProgramPoint.h')
-rw-r--r-- | include/clang/Analysis/ProgramPoint.h | 74 |
1 files changed, 62 insertions, 12 deletions
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index aa7a33c956..377f1bc256 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -45,14 +45,16 @@ public: PostLoadKind, PreStoreKind, PostStoreKind, - PostPurgeDeadSymbolsKind, + PostStmtPurgeDeadSymbolsKind, + PreStmtPurgeDeadSymbolsKind, PostConditionKind, PostLValueKind, PostInitializerKind, CallEnterKind, - CallExitKind, + CallExitBeginKind, + CallExitEndKind, MinPostStmtKind = PostStmtKind, - MaxPostStmtKind = CallExitKind, + MaxPostStmtKind = CallExitEndKind, EpsilonKind}; private: @@ -113,6 +115,14 @@ public: return (Kind) x; } + /// \brief Is this a program point corresponding to purge/removal of dead + /// symbols and bindings. + bool isPurgeKind() { + Kind K = getKind(); + return (K == PostStmtPurgeDeadSymbolsKind || + K == PreStmtPurgeDeadSymbolsKind); + } + const ProgramPointTag *getTag() const { return Tag; } const LocationContext *getLocationContext() const { @@ -340,14 +350,29 @@ public: } }; -class PostPurgeDeadSymbols : public PostStmt { +/// \class Represents a point after we ran remove dead bindings BEFORE +/// processing the given statement. +class PreStmtPurgeDeadSymbols : public PostStmt { public: - PostPurgeDeadSymbols(const Stmt *S, const LocationContext *L, + PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag = 0) - : PostStmt(S, PostPurgeDeadSymbolsKind, L, tag) {} + : PostStmt(S, PreStmtPurgeDeadSymbolsKind, L, tag) { } static bool classof(const ProgramPoint* Location) { - return Location->getKind() == PostPurgeDeadSymbolsKind; + return Location->getKind() == PreStmtPurgeDeadSymbolsKind; + } +}; + +/// \class Represents a point after we ran remove dead bindings AFTER +/// processing the given statement. +class PostStmtPurgeDeadSymbols : public PostStmt { +public: + PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L, + const ProgramPointTag *tag = 0) + : PostStmt(S, PostStmtPurgeDeadSymbolsKind, L, tag) { } + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostStmtPurgeDeadSymbolsKind; } }; @@ -383,6 +408,7 @@ public: } }; +/// \class Represents a point when we begin processing an inlined call. class CallEnter : public StmtPoint { public: CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx, @@ -402,14 +428,38 @@ public: } }; -class CallExit : public StmtPoint { +/// \class Represents a point when we start the call exit sequence (for +/// inlined call). +/// +/// The call exit is simulated with a sequence of nodes, which occur between +/// CallExitBegin and CallExitEnd. The following operations occur between the +/// two program points: +/// - CallExitBegin +/// - Bind the return value +/// - Run Remove dead bindings (to clean up the dead symbols from the callee). +/// - CallExitEnd +class CallExitBegin : public StmtPoint { +public: + // CallExitBegin uses the callee's location context. + CallExitBegin(const Stmt *S, const LocationContext *L) + : StmtPoint(S, 0, CallExitBeginKind, L, 0) {} + + static bool classof(const ProgramPoint *Location) { + return Location->getKind() == CallExitBeginKind; + } +}; + +/// \class Represents a point when we finish the call exit sequence (for +/// inlined call). +/// \sa CallExitBegin +class CallExitEnd : public StmtPoint { public: - // CallExit uses the callee's location context. - CallExit(const Stmt *S, const LocationContext *L) - : StmtPoint(S, 0, CallExitKind, L, 0) {} + // CallExitEnd uses the caller's location context. + CallExitEnd(const Stmt *S, const LocationContext *L) + : StmtPoint(S, 0, CallExitEndKind, L, 0) {} static bool classof(const ProgramPoint *Location) { - return Location->getKind() == CallExitKind; + return Location->getKind() == CallExitEndKind; } }; |