clang  3.7.0
Macros | Typedefs | Functions | Variables
BugReporter.cpp File Reference
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/ProgramPoint.h"
#include "clang/Basic/SourceManager.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>
#include <queue>
Include dependency graph for BugReporter.cpp:

Go to the source code of this file.

Macros

#define DEBUG_TYPE   "BugReporter"
 

Typedefs

typedef llvm::DenseMap< const
PathPieces *, const
LocationContext * > 
LocationContextMap
 
typedef std::pair
< PathDiagnosticCallPiece
*, const ExplodedNode * > 
StackDiagPair
 
typedef SmallVector
< StackDiagPair, 6 > 
StackDiagVector
 
typedef llvm::DenseSet< const
Expr * > 
InterestingExprs
 
typedef llvm::DenseSet< const
PathDiagnosticCallPiece * > 
OptimizedCallsSet
 

Functions

 STATISTIC (MaxBugClassSize,"The maximum number of bug reports in the same equivalence class")
 
 STATISTIC (MaxValidBugClassSize,"The maximum number of bug reports in the same equivalence class ""where at least one report is valid (not suppressed)")
 
static const StmtGetPreviousStmt (const ExplodedNode *N)
 
static const StmtGetCurrentOrPreviousStmt (const ExplodedNode *N)
 
static PathDiagnosticEventPieceeventsDescribeSameCondition (PathDiagnosticEventPiece *X, PathDiagnosticEventPiece *Y)
 
static void removeRedundantMsgs (PathPieces &path)
 
static bool removeUnneededCalls (PathPieces &pieces, BugReport *R, LocationContextMap &LCM)
 
static bool hasImplicitBody (const Decl *D)
 
static void adjustCallLocations (PathPieces &Pieces, PathDiagnosticLocation *LastCallLocation=nullptr)
 
static void removeEdgesToDefaultInitializers (PathPieces &Pieces)
 
static void removePiecesWithInvalidLocations (PathPieces &Pieces)
 
static const StmtgetEnclosingParent (const Stmt *S, const ParentMap &PM)
 
static PathDiagnosticLocation getEnclosingStmtLocation (const Stmt *S, SourceManager &SMgr, const ParentMap &P, const LocationContext *LC, bool allowNestedContexts)
 
static bool GenerateVisitorsOnlyPathDiagnostic (PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, ArrayRef< std::unique_ptr< BugReporterVisitor >> visitors)
 
static void updateStackPiecesWithMessage (PathDiagnosticPiece *P, StackDiagVector &CallStack)
 
static void CompactPathDiagnostic (PathPieces &path, const SourceManager &SM)
 
static bool GenerateMinimalPathDiagnostic (PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, LocationContextMap &LCM, ArrayRef< std::unique_ptr< BugReporterVisitor >> visitors)
 
static bool IsControlFlowExpr (const Stmt *S)
 
static void reversePropagateIntererstingSymbols (BugReport &R, InterestingExprs &IE, const ProgramState *State, const Expr *Ex, const LocationContext *LCtx)
 
static void reversePropagateInterestingSymbols (BugReport &R, InterestingExprs &IE, const ProgramState *State, const LocationContext *CalleeCtx, const LocationContext *CallerCtx)
 
static bool isLoop (const Stmt *Term)
 
static bool isJumpToFalseBranch (const BlockEdge *BE)
 
static bool isLoopJumpPastBody (const Stmt *Term, const BlockEdge *BE)
 
static bool isContainedByStmt (ParentMap &PM, const Stmt *S, const Stmt *SubS)
 
static const StmtgetStmtBeforeCond (ParentMap &PM, const Stmt *Term, const ExplodedNode *N)
 
static bool isInLoopBody (ParentMap &PM, const Stmt *S, const Stmt *Term)
 
static bool GenerateExtensivePathDiagnostic (PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, LocationContextMap &LCM, ArrayRef< std::unique_ptr< BugReporterVisitor >> visitors)
 
static void addEdgeToPath (PathPieces &path, PathDiagnosticLocation &PrevLoc, PathDiagnosticLocation NewLoc, const LocationContext *LC)
 Adds a sanitized control-flow diagnostic edge to a path. More...
 
static const StmtgetTerminatorCondition (const CFGBlock *B)
 
static bool GenerateAlternateExtensivePathDiagnostic (PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, LocationContextMap &LCM, ArrayRef< std::unique_ptr< BugReporterVisitor >> visitors)
 
static const StmtgetLocStmt (PathDiagnosticLocation L)
 
static const StmtgetStmtParent (const Stmt *S, const ParentMap &PM)
 
static bool isConditionForTerminator (const Stmt *S, const Stmt *Cond)
 
static bool isIncrementOrInitInForLoop (const Stmt *S, const Stmt *FL)
 
static void addContextEdges (PathPieces &pieces, SourceManager &SM, const ParentMap &PM, const LocationContext *LCtx)
 
static void simplifySimpleBranches (PathPieces &pieces)
 Move edges from a branch condition to a branch target when the condition is simple. More...
 
static Optional< size_tgetLengthOnSingleLine (SourceManager &SM, SourceRange Range)
 
static Optional< size_tgetLengthOnSingleLine (SourceManager &SM, const Stmt *S)
 
static void removeContextCycles (PathPieces &Path, SourceManager &SM, ParentMap &PM)
 
static bool lexicalContains (ParentMap &PM, const Stmt *X, const Stmt *Y)
 Return true if X is contained by Y. More...
 
static void removePunyEdges (PathPieces &path, SourceManager &SM, ParentMap &PM)
 
static void removeIdenticalEvents (PathPieces &path)
 
static bool optimizeEdges (PathPieces &path, SourceManager &SM, OptimizedCallsSet &OCS, LocationContextMap &LCM)
 
static void dropFunctionEntryEdge (PathPieces &Path, LocationContextMap &LCM, SourceManager &SM)
 
static BugReportFindReportInEquivalenceClass (BugReportEquivClass &EQ, SmallVectorImpl< BugReport * > &bugReports)
 

Variables

static const char StrEnteringLoop [] = "Entering loop body"
 
static const char StrLoopBodyZero [] = "Loop body executed 0 times"
 
static const char StrLoopRangeEmpty []
 
static const char StrLoopCollectionEmpty []
 

Macro Definition Documentation

#define DEBUG_TYPE   "BugReporter"

Definition at line 41 of file BugReporter.cpp.

Typedef Documentation

Definition at line 1235 of file BugReporter.cpp.

typedef llvm::DenseMap<const PathPieces *, const LocationContext *> LocationContextMap

A map from PathDiagnosticPiece to the LocationContext of the inlined function call it represents.

Definition at line 151 of file BugReporter.cpp.

Definition at line 1955 of file BugReporter.cpp.

typedef std::pair<PathDiagnosticCallPiece*, const ExplodedNode*> StackDiagPair

Definition at line 528 of file BugReporter.cpp.

Definition at line 529 of file BugReporter.cpp.

Function Documentation

static void addContextEdges ( PathPieces pieces,
SourceManager SM,
const ParentMap PM,
const LocationContext LCtx 
)
static

Adds synthetic edges from top-level statements to their subexpressions.

This avoids a "swoosh" effect, where an edge from a top-level statement A points to a sub-expression B.1 that's not at the start of B. In these cases, we'd like to see an edge from A to B, then another one from B to B.1.

Definition at line 1962 of file BugReporter.cpp.

References clang::ento::PathDiagnosticLocation::asStmt(), getEnclosingStmtLocation(), clang::ento::PathDiagnosticControlFlowPiece::getEndLocation(), getLocStmt(), clang::ento::PathDiagnosticControlFlowPiece::getStartLocation(), getStmtParent(), clang::ento::PathDiagnosticLocation::isValid(), clang::ento::PathDiagnosticControlFlowPiece::setEndLocation(), and clang::ento::PathDiagnosticControlFlowPiece::setStartLocation().

Referenced by optimizeEdges().

static void addEdgeToPath ( PathPieces path,
PathDiagnosticLocation PrevLoc,
PathDiagnosticLocation  NewLoc,
const LocationContext LC 
)
static
static void adjustCallLocations ( PathPieces Pieces,
PathDiagnosticLocation LastCallLocation = nullptr 
)
static
static void CompactPathDiagnostic ( PathPieces path,
const SourceManager SM 
)
static

CompactPathDiagnostic - This function postprocesses a PathDiagnostic object and collapses PathDiagosticPieces that are expanded by macros.

Definition at line 2964 of file BugReporter.cpp.

References clang::ento::PathDiagnosticLocation::asLocation(), clang::ento::PathDiagnosticLocation::createSingleLocation(), clang::SourceManager::getExpansionLoc(), clang::ento::PathDiagnosticPiece::getLocation(), clang::SourceLocation::isFileID(), and clang::SourceLocation::isMacroID().

Referenced by GenerateMinimalPathDiagnostic().

static void dropFunctionEntryEdge ( PathPieces Path,
LocationContextMap LCM,
SourceManager SM 
)
static

Drop the very first edge in a path, which should be a function entry edge.

If the first edge is not a function entry edge (say, because the first statement had an invalid source location), this function does nothing.

Definition at line 2503 of file BugReporter.cpp.

References clang::ento::PathDiagnosticLocation::createBegin(), and clang::ento::PathDiagnosticControlFlowPiece::getStartLocation().

Referenced by clang::ento::GRBugReporter::generatePathDiagnostic().

static PathDiagnosticEventPiece* eventsDescribeSameCondition ( PathDiagnosticEventPiece X,
PathDiagnosticEventPiece Y 
)
static
static BugReport* FindReportInEquivalenceClass ( BugReportEquivClass EQ,
SmallVectorImpl< BugReport * > &  bugReports 
)
static
static bool GenerateAlternateExtensivePathDiagnostic ( PathDiagnostic PD,
PathDiagnosticBuilder &  PDB,
const ExplodedNode N,
LocationContextMap LCM,
ArrayRef< std::unique_ptr< BugReporterVisitor >>  visitors 
)
static

Definition at line 1627 of file BugReporter.cpp.

References addEdgeToPath(), AttributeLangSupport::C, clang::ento::PathDiagnosticCallPiece::callReturn, clang::ento::PathDiagnosticCallPiece::construct(), clang::ento::PathDiagnosticLocation::createBegin(), clang::ento::PathDiagnosticLocation::createEndBrace(), clang::ento::PathDiagnostic::getActivePath(), clang::ProgramPoint::getAs(), clang::LocationContext::getDecl(), clang::ento::ExplodedNode::getFirstPred(), clang::ento::ExplodedNode::getLocation(), clang::ento::PathDiagnosticSpotPiece::getLocation(), clang::ento::PathDiagnosticCallPiece::getLocation(), clang::ento::PathDiagnostic::getLocation(), clang::ento::ExplodedNode::getLocationContext(), clang::ento::ExplodedNode::getState(), getStmtBeforeCond(), clang::CFGBlock::getTerminator(), getTerminatorCondition(), clang::ento::PathDiagnosticLocation::invalidate(), isInLoopBody(), isJumpToFalseBranch(), isLoop(), clang::ento::BugReport::isValid(), clang::ento::PathDiagnostic::isWithinCall(), p, P, clang::ento::PathDiagnosticCallPiece::path, clang::ento::PathDiagnostic::popActivePath(), clang::ento::PathDiagnostic::pushActivePath(), reversePropagateIntererstingSymbols(), reversePropagateInterestingSymbols(), clang::ento::PathDiagnosticCallPiece::setCallee(), clang::ento::PathDiagnosticEventPiece::setPrunable(), SM, StrEnteringLoop, StrLoopBodyZero, StrLoopCollectionEmpty, StrLoopRangeEmpty, and updateStackPiecesWithMessage().

Referenced by clang::ento::GRBugReporter::generatePathDiagnostic().

static bool GenerateExtensivePathDiagnostic ( PathDiagnostic PD,
PathDiagnosticBuilder &  PDB,
const ExplodedNode N,
LocationContextMap LCM,
ArrayRef< std::unique_ptr< BugReporterVisitor >>  visitors 
)
static
static bool GenerateMinimalPathDiagnostic ( PathDiagnostic PD,
PathDiagnosticBuilder &  PDB,
const ExplodedNode N,
LocationContextMap LCM,
ArrayRef< std::unique_ptr< BugReporterVisitor >>  visitors 
)
static
static bool GenerateVisitorsOnlyPathDiagnostic ( PathDiagnostic PD,
PathDiagnosticBuilder &  PDB,
const ExplodedNode N,
ArrayRef< std::unique_ptr< BugReporterVisitor >>  visitors 
)
static
static const Stmt* GetCurrentOrPreviousStmt ( const ExplodedNode N)
inlinestatic
static const Stmt* getEnclosingParent ( const Stmt S,
const ParentMap PM 
)
static
static PathDiagnosticLocation getEnclosingStmtLocation ( const Stmt S,
SourceManager SMgr,
const ParentMap P,
const LocationContext LC,
bool  allowNestedContexts 
)
static

Definition at line 426 of file BugReporter.cpp.

References getEnclosingParent(), and clang::BinaryOperator::isLogicalOp().

Referenced by addContextEdges().

static Optional<size_t> getLengthOnSingleLine ( SourceManager SM,
SourceRange  Range 
)
static

Returns the number of bytes in the given (character-based) SourceRange.

If the locations in the range are not on the same line, returns None.

Note that this does not do a precise user-visible character or column count.

Definition at line 2115 of file BugReporter.cpp.

References clang::SourceRange::getBegin(), clang::SourceManager::getBuffer(), clang::SourceRange::getEnd(), clang::SourceManager::getExpansionLoc(), clang::SourceManager::getExpansionRange(), clang::SourceManager::getFileID(), clang::SourceManager::getFileOffset(), and clang::None.

Referenced by getLengthOnSingleLine(), optimizeEdges(), removeContextCycles(), and removePunyEdges().

static Optional<size_t> getLengthOnSingleLine ( SourceManager SM,
const Stmt S 
)
static
See Also
getLengthOnSingleLine(SourceManager, SourceRange)

Definition at line 2145 of file BugReporter.cpp.

References getLengthOnSingleLine().

static const Stmt* getLocStmt ( PathDiagnosticLocation  L)
static
static const Stmt* GetPreviousStmt ( const ExplodedNode N)
static
static const Stmt* getStmtBeforeCond ( ParentMap PM,
const Stmt Term,
const ExplodedNode N 
)
static
static const Stmt* getStmtParent ( const Stmt S,
const ParentMap PM 
)
static

Definition at line 1883 of file BugReporter.cpp.

References clang::ParentMap::getParentIgnoreParens(), and S.

Referenced by addContextEdges(), and optimizeEdges().

static const Stmt* getTerminatorCondition ( const CFGBlock B)
static

A customized wrapper for CFGBlock::getTerminatorCondition() which returns the element for ObjCForCollectionStmts.

Definition at line 1612 of file BugReporter.cpp.

References clang::CFGBlock::getTerminatorCondition(), and S.

Referenced by GenerateAlternateExtensivePathDiagnostic().

static bool hasImplicitBody ( const Decl D)
static

Returns true if the given decl has been implicitly given a body, either by the analyzer or by the compiler proper.

Definition at line 210 of file BugReporter.cpp.

References clang::Decl::hasBody(), and clang::Decl::isImplicit().

Referenced by adjustCallLocations().

static bool isConditionForTerminator ( const Stmt S,
const Stmt Cond 
)
static
static bool isContainedByStmt ( ParentMap PM,
const Stmt S,
const Stmt SubS 
)
static

Definition at line 1327 of file BugReporter.cpp.

References clang::ParentMap::getParent().

Referenced by getStmtBeforeCond(), and isInLoopBody().

static bool IsControlFlowExpr ( const Stmt S)
static

Definition at line 891 of file BugReporter.cpp.

References clang::Expr::IgnoreParenCasts(), and S.

Referenced by GenerateExtensivePathDiagnostic().

static bool isIncrementOrInitInForLoop ( const Stmt S,
const Stmt FL 
)
static

Definition at line 1945 of file BugReporter.cpp.

References S.

Referenced by optimizeEdges().

static bool isInLoopBody ( ParentMap PM,
const Stmt S,
const Stmt Term 
)
static
static bool isJumpToFalseBranch ( const BlockEdge BE)
static
static bool isLoop ( const Stmt Term)
static
static bool isLoopJumpPastBody ( const Stmt Term,
const BlockEdge BE 
)
static

Return true if the terminator is a loop and the destination is the false branch.

Definition at line 1319 of file BugReporter.cpp.

References isJumpToFalseBranch(), and isLoop().

Referenced by GenerateExtensivePathDiagnostic().

static bool lexicalContains ( ParentMap PM,
const Stmt X,
const Stmt Y 
)
static

Return true if X is contained by Y.

Definition at line 2223 of file BugReporter.cpp.

References clang::ParentMap::getParent().

Referenced by optimizeEdges().

static bool optimizeEdges ( PathPieces path,
SourceManager SM,
OptimizedCallsSet OCS,
LocationContextMap LCM 
)
static
static void removeContextCycles ( PathPieces Path,
SourceManager SM,
ParentMap PM 
)
static

Eliminate two-edge cycles created by addContextEdges().

Once all the context edges are in place, there are plenty of cases where there's a single edge from a top-level statement to a subexpression, followed by a single path note, and then a reverse edge to get back out to the top level. If the statement is simple enough, the subexpression edges just add noise and make it harder to understand what's going on.

This function only removes edges in pairs, because removing only one edge might leave other edges dangling.

This will not remove edges in more complicated situations:

  • if there is more than one "hop" leading to or from a subexpression.
  • if there is an inlined call between the edges instead of a single event.
  • if the whole statement is large enough that having subexpression arrows might be helpful.

Definition at line 2166 of file BugReporter.cpp.

References clang::ento::PathDiagnosticControlFlowPiece::getEndLocation(), getLengthOnSingleLine(), getLocStmt(), and clang::ento::PathDiagnosticControlFlowPiece::getStartLocation().

Referenced by optimizeEdges().

static void removeEdgesToDefaultInitializers ( PathPieces Pieces)
static

Remove edges in and out of C++ default initializer expressions. These are for fields that have in-class initializers, as opposed to being initialized explicitly in a constructor or braced list.

Definition at line 253 of file BugReporter.cpp.

References AttributeLangSupport::C, End, and Next.

Referenced by clang::ento::GRBugReporter::generatePathDiagnostic().

static void removeIdenticalEvents ( PathPieces path)
static

Definition at line 2292 of file BugReporter.cpp.

References clang::ento::PathDiagnosticPiece::getString().

Referenced by optimizeEdges().

static void removePiecesWithInvalidLocations ( PathPieces Pieces)
static

Remove all pieces with invalid locations as these cannot be serialized. We might have pieces with invalid locations as a result of inlining Body Farm generated functions.

Definition at line 288 of file BugReporter.cpp.

References AttributeLangSupport::C.

Referenced by clang::ento::GRBugReporter::generatePathDiagnostic().

static void removePunyEdges ( PathPieces path,
SourceManager SM,
ParentMap PM 
)
static
static void removeRedundantMsgs ( PathPieces path)
static

An optimization pass over PathPieces that removes redundant diagnostics generated by both ConditionBRVisitor and TrackConstraintBRVisitor. Both BugReporterVisitors use different methods to generate diagnostics, with one capable of emitting diagnostics in some cases but not in others. This can lead to redundant diagnostic pieces at the same point in a path.

Definition at line 102 of file BugReporter.cpp.

References clang::ento::PathDiagnosticPiece::Call, clang::ento::PathDiagnosticPiece::ControlFlow, clang::ento::PathDiagnosticPiece::Event, eventsDescribeSameCondition(), and clang::ento::PathDiagnosticPiece::Macro.

Referenced by clang::ento::GRBugReporter::generatePathDiagnostic().

static bool removeUnneededCalls ( PathPieces pieces,
BugReport R,
LocationContextMap LCM 
)
static

Recursively scan through a path and prune out calls and macros pieces that aren't needed. Return true if afterwards the path contains "interesting stuff" which means it shouldn't be pruned from the parent path.

Definition at line 156 of file BugReporter.cpp.

References clang::ento::PathDiagnosticPiece::Call, clang::ento::PathDiagnosticPiece::ControlFlow, clang::ento::PathDiagnosticPiece::Event, clang::ento::BugReport::isInteresting(), clang::ento::PathDiagnosticEventPiece::isPrunable(), clang::ento::PathDiagnosticPiece::Macro, clang::ento::PathDiagnosticCallPiece::path, and clang::ento::PathDiagnosticMacroPiece::subPieces.

Referenced by clang::ento::GRBugReporter::generatePathDiagnostic().

static void reversePropagateIntererstingSymbols ( BugReport R,
InterestingExprs IE,
const ProgramState State,
const Expr Ex,
const LocationContext LCtx 
)
static
static void reversePropagateInterestingSymbols ( BugReport R,
InterestingExprs IE,
const ProgramState State,
const LocationContext CalleeCtx,
const LocationContext CallerCtx 
)
static
static void simplifySimpleBranches ( PathPieces pieces)
static

Move edges from a branch condition to a branch target when the condition is simple.

This restructures some of the work of addContextEdges. That function creates edges this may destroy, but they work together to create a more aesthetically set of edges around branches. After the call to addContextEdges, we may have (1) an edge to the branch, (2) an edge from the branch to the branch condition, and (3) an edge from the branch condition to the branch target. We keep (1), but may wish to remove (2) and move the source of (3) to the branch if the branch condition is simple.

Definition at line 2043 of file BugReporter.cpp.

References clang::ento::PathDiagnosticControlFlowPiece::getEndLocation(), getLocStmt(), clang::ento::PathDiagnosticControlFlowPiece::getStartLocation(), clang::ento::PathDiagnosticPiece::getString(), isConditionForTerminator(), clang::ento::PathDiagnosticControlFlowPiece::setStartLocation(), StrEnteringLoop, StrLoopBodyZero, StrLoopCollectionEmpty, and StrLoopRangeEmpty.

Referenced by optimizeEdges().

STATISTIC ( MaxBugClassSize  ,
"The maximum number of bug reports in the same equivalence class"   
)
STATISTIC ( MaxValidBugClassSize  ,
"The maximum number of bug reports in the same equivalence class ""where at least one report is valid (not suppressed)"   
)
static void updateStackPiecesWithMessage ( PathDiagnosticPiece P,
StackDiagVector CallStack 
)
static

Variable Documentation

const char StrEnteringLoop[] = "Entering loop body"
static
const char StrLoopBodyZero[] = "Loop body executed 0 times"
static
const char StrLoopCollectionEmpty[]
static
Initial value:
=
"Loop body skipped when collection is empty"

Definition at line 1624 of file BugReporter.cpp.

Referenced by GenerateAlternateExtensivePathDiagnostic(), and simplifySimpleBranches().

const char StrLoopRangeEmpty[]
static
Initial value:
=
"Loop body skipped when range is empty"

Definition at line 1622 of file BugReporter.cpp.

Referenced by GenerateAlternateExtensivePathDiagnostic(), and simplifySimpleBranches().