From: Ted Kremenek Date: Wed, 2 Apr 2008 05:15:22 +0000 (+0000) Subject: Added initial hacked support for display path diagnostics with X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=503d613235543c1adf7ea49fce56cffa1e65d5fb;p=clang Added initial hacked support for display path diagnostics with GRSimpleVals warnings. Cleaning up, but now we get multiple bubbles (branches are annotated). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49077 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/GRSimpleVals.cpp b/lib/Analysis/GRSimpleVals.cpp index 5944c12e58..4baad54e94 100644 --- a/lib/Analysis/GRSimpleVals.cpp +++ b/lib/Analysis/GRSimpleVals.cpp @@ -23,13 +23,24 @@ using namespace clang; namespace clang { +template +static inline ExplodedNode* GetNode(ITERATOR I) { + return *I; +} + +template <> +static inline ExplodedNode* +GetNode(GRExprEngine::undef_arg_iterator I) { + return I->first; +} + template static inline ProgramPoint GetLocation(ITERATOR I) { return (*I)->getLocation(); } template <> -inline ProgramPoint GetLocation(GRExprEngine::undef_arg_iterator I) { +static inline ProgramPoint GetLocation(GRExprEngine::undef_arg_iterator I) { return I->first->getLocation(); } @@ -44,7 +55,93 @@ static inline Stmt* GetStmt(const ProgramPoint& P) { assert (false && "Unsupported ProgramPoint."); return NULL; } + + +//===----------------------------------------------------------------------===// +// Path Warnings. +//===----------------------------------------------------------------------===// + +static inline SourceLocation GetSourceLoc(ProgramPoint P) { + + if (const PostStmt* PS = dyn_cast(&P)) { + return PS->getStmt()->getLocStart(); + } + else if (const BlockEdge* BE = dyn_cast(&P)) { + return BE->getSrc()->getTerminator()->getLocStart(); + } + + return SourceLocation(); +} + +static inline +FullSourceLoc GetFullSourceLoc(SourceManager& SMgr, ProgramPoint P) { + return FullSourceLoc(GetSourceLoc(P), SMgr); +} + +template +static void EmitPathWarning(Diagnostic& Diag, PathDiagnosticClient* PD, + SourceManager& SrcMgr, const std::string& msg, + ITERATOR I) { + + + PathDiagnostic D; + + { // Add the end message. + + ProgramPoint P = GetLocation(I); + D.push_back(new PathDiagnosticPiece(GetFullSourceLoc(SrcMgr, P), msg)); + } + + // Walk up the path. + + ExplodedNode *N = GetNode(I); + + while (N) { + + if (N->pred_empty()) + break; + + N = *(N->pred_begin()); // Grab the first predecessor. + + ProgramPoint P = N->getLocation(); + + if (const BlockEdge* BE = dyn_cast(&P)) { + + CFGBlock* Src = BE->getSrc(); + CFGBlock* Dst = BE->getDst(); + + // FIXME: Better handling for switches. + + if (Src->succ_size() == 2) { + + Stmt* T = Src->getTerminator(); + + if (!Src) + continue; + + if (*(Src->succ_begin()+1) == Dst) { + D.push_front(new PathDiagnosticPiece(FullSourceLoc(T->getLocStart(), + SrcMgr), + "Taking false branch.")); + + } + else { + D.push_front(new PathDiagnosticPiece(FullSourceLoc(T->getLocStart(), + SrcMgr), + "Taking true branch.")); + } + } + } + } + + // Emit the path. + PD->HandlePathDiagnostic(D); +} +//===----------------------------------------------------------------------===// +// Pathless Warnings +//===----------------------------------------------------------------------===// + template static void EmitDiag(Diagnostic& Diag, PathDiagnosticClient* PD, SourceManager& SrcMgr, @@ -76,7 +173,7 @@ void EmitWarning(Diagnostic& Diag, PathDiagnosticClient* PD, ITERATOR I, ITERATOR E, const char* msg) { std::ostringstream Out; - std::string Str; + std::string Str(msg); if (!PD) { Out << "[CHECKER] " << msg; @@ -107,10 +204,17 @@ void EmitWarning(Diagnostic& Diag, PathDiagnosticClient* PD, CachedErrors.insert(p); } - EmitDiag(Diag, PD, SrcMgr, ErrorDiag, I); + if (PD) + EmitPathWarning(Diag, PD, SrcMgr, Str, I); + else + EmitDiag(Diag, PD, SrcMgr, ErrorDiag, I); } } +//===----------------------------------------------------------------------===// +// Analysis Driver. +//===----------------------------------------------------------------------===// + unsigned RunGRSimpleVals(CFG& cfg, Decl& CD, ASTContext& Ctx, Diagnostic& Diag, PathDiagnosticClient* PD, bool Visualize, bool TrimGraph) {