diff options
author | Anna Zaks <ganna@apple.com> | 2012-03-16 23:24:20 +0000 |
---|---|---|
committer | Anna Zaks <ganna@apple.com> | 2012-03-16 23:24:20 +0000 |
commit | 56a938ff85a444eb3d30d2634d92ce5b1f6fae56 (patch) | |
tree | 9d85719ed51903e12e39c5f7d4db93f727f37763 /include | |
parent | 076add680e281709cf081052be0dcb822dc8f37d (diff) |
[analyzer] Create symbol-aware stack hints (building upon r152837).
The symbol-aware stack hint combines the checker-provided message
with the information about how the symbol was passed to the callee: as
a parameter or a return value.
For malloc, the generated messages look like this :
"Returning from 'foo'; released memory via 1st parameter"
"Returning from 'foo'; allocated memory via 1st parameter"
"Returning from 'foo'; allocated memory returned"
"Returning from 'foo'; reallocation of 1st parameter failed"
(We are yet to handle cases when the symbol is a field in a struct or
an array element.)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152962 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r-- | include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h | 71 |
1 files changed, 61 insertions, 10 deletions
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index fea02caafd..b40bc71010 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -41,6 +41,8 @@ class Stmt; namespace ento { class ExplodedNode; +class SymExpr; +typedef const SymExpr* SymbolRef; //===----------------------------------------------------------------------===// // High-level interface for handlers of path-sensitive diagnostics. @@ -357,6 +359,52 @@ public: virtual void Profile(llvm::FoldingSetNodeID &ID) const; }; +/// \brief Interface for classes constructing Stack hints. +/// +/// If a PathDiagnosticEvent occurs in a different frame than the final +/// diagnostic the hints can be used to summarise the effect of the call. +class StackHintGenerator { +public: + virtual ~StackHintGenerator() = 0; + + /// \brief Construct the Diagnostic message for the given ExplodedNode. + virtual std::string getMessage(const ExplodedNode *N) = 0; +}; + +/// \brief Constructs a Stack hint for the given symbol. +/// +/// The class knows how to construct the stack hint message based on +/// traversing the CallExpr associated with the call and checking if the given +/// symbol is returned or is one of the arguments. +/// The hint can be customized by redefining 'getMessageForX()' methods. +class StackHintGeneratorForSymbol : public StackHintGenerator { +private: + SymbolRef Sym; + std::string Msg; + +public: + StackHintGeneratorForSymbol(SymbolRef S, StringRef M) : Sym(S), Msg(M) {} + virtual ~StackHintGeneratorForSymbol() {} + + /// \brief Search the call expression for the symbol Sym and dispatch the + /// 'getMessageForX()' methods to construct a specific message. + virtual std::string getMessage(const ExplodedNode *N); + + /// Prints the ordinal form of the given integer, + /// only valid for ValNo : ValNo > 0. + void printOrdinal(unsigned ValNo, llvm::raw_svector_ostream &Out); + + /// Produces the message of the following form: + /// 'Msg via Nth parameter' + virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex); + virtual std::string getMessageForReturn(const CallExpr *CallExpr) { + return Msg + " returned"; + } + virtual std::string getMessageForSymbolNotFound() { + return Msg; + } +}; + class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece { llvm::Optional<bool> IsPrunable; @@ -364,16 +412,14 @@ class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece { /// supply a message that will be used to construct an extra hint on the /// returns from all the calls on the stack from this event to the final /// diagnostic. - /// TODO: This should be a callback that constructs a string given the - /// ExplodedNode, which would allow the checkers to refer to the expression. - std::string CallStackMessage; + llvm::OwningPtr<StackHintGenerator> CallStackHint; public: PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, StringRef s, bool addPosRange = true, - StringRef callStackMsg = "") + StackHintGenerator *stackHint = 0) : PathDiagnosticSpotPiece(pos, s, Event, addPosRange), - CallStackMessage(callStackMsg) {} + CallStackHint(stackHint) {} ~PathDiagnosticEventPiece(); @@ -391,11 +437,16 @@ public: return IsPrunable.hasValue() ? IsPrunable.getValue() : false; } - StringRef getCallStackMessage() { - if (!CallStackMessage.empty()) - return CallStackMessage; - else - return StringRef(); + bool hasCallStackHint() { + return (CallStackHint != 0); + } + + /// Produce the hint for the given node. The node contains + /// information about the call for which the diagnostic can be generated. + StringRef getCallStackMessage(const ExplodedNode *N) { + if (CallStackHint) + return CallStackHint->getMessage(N); + return ""; } static inline bool classof(const PathDiagnosticPiece *P) { |