summaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core')
-rw-r--r--lib/StaticAnalyzer/Core/AnalyzerOptions.cpp19
-rw-r--r--lib/StaticAnalyzer/Core/BasicValueFactory.cpp12
-rw-r--r--lib/StaticAnalyzer/Core/BlockCounter.cpp3
-rw-r--r--lib/StaticAnalyzer/Core/BugReporter.cpp175
-rw-r--r--lib/StaticAnalyzer/Core/BugReporterVisitors.cpp193
-rw-r--r--lib/StaticAnalyzer/Core/CMakeLists.txt18
-rw-r--r--lib/StaticAnalyzer/Core/CallEvent.cpp122
-rw-r--r--lib/StaticAnalyzer/Core/Checker.cpp19
-rw-r--r--lib/StaticAnalyzer/Core/CheckerManager.cpp12
-rw-r--r--lib/StaticAnalyzer/Core/CheckerRegistry.cpp7
-rw-r--r--lib/StaticAnalyzer/Core/CoreEngine.cpp59
-rw-r--r--lib/StaticAnalyzer/Core/Environment.cpp12
-rw-r--r--lib/StaticAnalyzer/Core/ExplodedGraph.cpp28
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp311
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineC.cpp89
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCXX.cpp168
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp66
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineObjC.cpp6
-rw-r--r--lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp105
-rw-r--r--lib/StaticAnalyzer/Core/MemRegion.cpp64
-rw-r--r--lib/StaticAnalyzer/Core/PathDiagnostic.cpp94
-rw-r--r--lib/StaticAnalyzer/Core/PlistDiagnostics.cpp140
-rw-r--r--lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h2
-rw-r--r--lib/StaticAnalyzer/Core/ProgramState.cpp5
-rw-r--r--lib/StaticAnalyzer/Core/RangeConstraintManager.cpp54
-rw-r--r--lib/StaticAnalyzer/Core/RegionStore.cpp67
-rw-r--r--lib/StaticAnalyzer/Core/SValBuilder.cpp4
-rw-r--r--lib/StaticAnalyzer/Core/SVals.cpp12
-rw-r--r--lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp2
-rw-r--r--lib/StaticAnalyzer/Core/SimpleConstraintManager.h4
-rw-r--r--lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp47
-rw-r--r--lib/StaticAnalyzer/Core/Store.cpp10
-rw-r--r--lib/StaticAnalyzer/Core/SymbolManager.cpp12
33 files changed, 1037 insertions, 904 deletions
diff --git a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
index 9dcf58babd278..7944c7eb00037 100644
--- a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
+++ b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
@@ -39,7 +39,7 @@ IPAKind AnalyzerOptions::getIPAMode() {
// Use the User Mode to set the default IPA value.
// Note, we have to add the string to the Config map for the ConfigDumper
// checker to function properly.
- const char *DefaultIPA = 0;
+ const char *DefaultIPA = nullptr;
UserModeKind HighLevelMode = getUserMode();
if (HighLevelMode == UMK_Shallow)
DefaultIPA = "inlining";
@@ -134,8 +134,14 @@ bool AnalyzerOptions::mayInlineTemplateFunctions() {
/*Default=*/true);
}
-bool AnalyzerOptions::mayInlineCXXContainerCtorsAndDtors() {
- return getBooleanOption(InlineCXXContainerCtorsAndDtors,
+bool AnalyzerOptions::mayInlineCXXAllocator() {
+ return getBooleanOption(InlineCXXAllocator,
+ "c++-allocator-inlining",
+ /*Default=*/false);
+}
+
+bool AnalyzerOptions::mayInlineCXXContainerMethods() {
+ return getBooleanOption(InlineCXXContainerMethods,
"c++-container-inlining",
/*Default=*/false);
}
@@ -183,6 +189,13 @@ bool AnalyzerOptions::shouldReportIssuesInMainSourceFile() {
/* Default = */ false);
}
+
+bool AnalyzerOptions::shouldWriteStableReportFilename() {
+ return getBooleanOption(StableReportFilename,
+ "stable-report-filename",
+ /* Default = */ false);
+}
+
int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal) {
SmallString<10> StrBuf;
llvm::raw_svector_ostream OS(StrBuf);
diff --git a/lib/StaticAnalyzer/Core/BasicValueFactory.cpp b/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
index a6c400f3704d2..0e90566839ca7 100644
--- a/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
+++ b/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
@@ -173,12 +173,12 @@ BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op,
// FIXME: Expand these checks to include all undefined behavior.
if (V2.isSigned() && V2.isNegative())
- return NULL;
+ return nullptr;
uint64_t Amt = V2.getZExtValue();
- if (Amt > V1.getBitWidth())
- return NULL;
+ if (Amt >= V1.getBitWidth())
+ return nullptr;
return &getValue( V1.operator<<( (unsigned) Amt ));
}
@@ -191,12 +191,12 @@ BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op,
// FIXME: Expand these checks to include all undefined behavior.
if (V2.isSigned() && V2.isNegative())
- return NULL;
+ return nullptr;
uint64_t Amt = V2.getZExtValue();
- if (Amt > V1.getBitWidth())
- return NULL;
+ if (Amt >= V1.getBitWidth())
+ return nullptr;
return &getValue( V1.operator>>( (unsigned) Amt ));
}
diff --git a/lib/StaticAnalyzer/Core/BlockCounter.cpp b/lib/StaticAnalyzer/Core/BlockCounter.cpp
index 74d761e1ecc1d..c1ac03d5ab97d 100644
--- a/lib/StaticAnalyzer/Core/BlockCounter.cpp
+++ b/lib/StaticAnalyzer/Core/BlockCounter.cpp
@@ -34,8 +34,7 @@ public:
}
bool operator<(const CountKey &RHS) const {
- return (CallSite == RHS.CallSite) ? (BlockID < RHS.BlockID)
- : (CallSite < RHS.CallSite);
+ return std::tie(CallSite, BlockID) < std::tie(RHS.CallSite, RHS.BlockID);
}
void Profile(llvm::FoldingSetNodeID &ID) const {
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index 1940fa79fda3b..141a48ba10b35 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -12,16 +12,14 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "BugReporter"
-
#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/StmtObjC.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"
@@ -30,16 +28,18 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/OwningPtr.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>
using namespace clang;
using namespace ento;
+#define DEBUG_TYPE "BugReporter"
+
STATISTIC(MaxBugClassSize,
"The maximum number of bug reports in the same equivalence class");
STATISTIC(MaxValidBugClassSize,
@@ -59,7 +59,7 @@ static const Stmt *GetPreviousStmt(const ExplodedNode *N) {
if (const Stmt *S = PathDiagnosticLocation::getStmt(N))
return S;
- return 0;
+ return nullptr;
}
static inline const Stmt*
@@ -83,15 +83,15 @@ eventsDescribeSameCondition(PathDiagnosticEventPiece *X,
const void *tagLesser = TrackConstraintBRVisitor::getTag();
if (X->getLocation() != Y->getLocation())
- return 0;
-
+ return nullptr;
+
if (X->getTag() == tagPreferred && Y->getTag() == tagLesser)
return X;
if (Y->getTag() == tagPreferred && X->getTag() == tagLesser)
return Y;
-
- return 0;
+
+ return nullptr;
}
/// An optimization pass over PathPieces that removes redundant diagnostics
@@ -125,7 +125,7 @@ static void removeRedundantMsgs(PathPieces &path) {
break;
if (PathDiagnosticEventPiece *nextEvent =
- dyn_cast<PathDiagnosticEventPiece>(path.front().getPtr())) {
+ dyn_cast<PathDiagnosticEventPiece>(path.front().get())) {
PathDiagnosticEventPiece *event =
cast<PathDiagnosticEventPiece>(piece);
// Check to see if we should keep one of the two pieces. If we
@@ -214,8 +214,9 @@ static bool hasImplicitBody(const Decl *D) {
/// Recursively scan through a path and make sure that all call pieces have
/// valid locations.
-static void adjustCallLocations(PathPieces &Pieces,
- PathDiagnosticLocation *LastCallLocation = 0) {
+static void
+adjustCallLocations(PathPieces &Pieces,
+ PathDiagnosticLocation *LastCallLocation = nullptr) {
for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E; ++I) {
PathDiagnosticCallPiece *Call = dyn_cast<PathDiagnosticCallPiece>(*I);
@@ -265,7 +266,7 @@ static void removeEdgesToDefaultInitializers(PathPieces &Pieces) {
I = Pieces.erase(I);
continue;
} else if (End && isa<CXXDefaultInitExpr>(End)) {
- PathPieces::iterator Next = llvm::next(I);
+ PathPieces::iterator Next = std::next(I);
if (Next != E) {
if (PathDiagnosticControlFlowPiece *NextCF =
dyn_cast<PathDiagnosticControlFlowPiece>(*Next)) {
@@ -311,7 +312,7 @@ class NodeMapClosure : public BugReport::NodeResolver {
public:
NodeMapClosure(InterExplodedGraphMap &m) : M(m) {}
- const ExplodedNode *getOriginalNode(const ExplodedNode *N) {
+ const ExplodedNode *getOriginalNode(const ExplodedNode *N) override {
return M.lookup(N);
}
};
@@ -345,7 +346,7 @@ public:
return getParentMap().getParent(S);
}
- virtual NodeMapClosure& getNodeResolver() { return NMC; }
+ NodeMapClosure& getNodeResolver() override { return NMC; }
PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S);
@@ -405,7 +406,7 @@ static const Stmt *getEnclosingParent(const Stmt *S, const ParentMap &PM) {
const Stmt *Parent = PM.getParentIgnoreParens(S);
if (!Parent)
- return 0;
+ return nullptr;
switch (Parent->getStmtClass()) {
case Stmt::ForStmtClass:
@@ -418,7 +419,7 @@ static const Stmt *getEnclosingParent(const Stmt *S, const ParentMap &PM) {
break;
}
- return 0;
+ return nullptr;
}
static PathDiagnosticLocation
@@ -564,7 +565,7 @@ static bool GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
SourceManager& SMgr = PDB.getSourceManager();
const LocationContext *LC = PDB.LC;
const ExplodedNode *NextNode = N->pred_empty()
- ? NULL : *(N->pred_begin());
+ ? nullptr : *(N->pred_begin());
StackDiagVector CallStack;
@@ -1263,8 +1264,8 @@ static void reversePropagateIntererstingSymbols(BugReport &R,
SVal ChildV = State->getSVal(child, LCtx);
R.markInteresting(ChildV);
}
- break;
}
+ break;
}
}
@@ -1351,11 +1352,11 @@ static const Stmt *getStmtBeforeCond(ParentMap &PM, const Stmt *Term,
}
N = N->getFirstPred();
}
- return 0;
+ return nullptr;
}
static bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term) {
- const Stmt *LoopBody = 0;
+ const Stmt *LoopBody = nullptr;
switch (Term->getStmtClass()) {
case Stmt::CXXForRangeStmtClass: {
const CXXForRangeStmt *FR = cast<CXXForRangeStmt>(Term);
@@ -1401,7 +1402,7 @@ static bool GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
StackDiagVector CallStack;
InterestingExprs IE;
- const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin());
+ const ExplodedNode *NextNode = N->pred_empty() ? nullptr : *(N->pred_begin());
while (NextNode) {
N = NextNode;
NextNode = N->getFirstPred();
@@ -1411,7 +1412,7 @@ static bool GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
if (Optional<PostStmt> PS = P.getAs<PostStmt>()) {
if (const Expr *Ex = PS->getStmtAs<Expr>())
reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
- N->getState().getPtr(), Ex,
+ N->getState().get(), Ex,
N->getLocationContext());
}
@@ -1419,7 +1420,7 @@ static bool GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
const Stmt *S = CE->getCalleeContext()->getCallSite();
if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) {
reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
- N->getState().getPtr(), Ex,
+ N->getState().get(), Ex,
N->getLocationContext());
}
@@ -1490,7 +1491,7 @@ static bool GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
const LocationContext *CalleeCtx = PDB.LC;
if (CallerCtx != CalleeCtx) {
reversePropagateInterestingSymbols(*PDB.getBugReport(), IE,
- N->getState().getPtr(),
+ N->getState().get(),
CalleeCtx, CallerCtx);
}
}
@@ -1498,7 +1499,7 @@ static bool GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
// Are we jumping to the head of a loop? Add a special diagnostic.
if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) {
PathDiagnosticLocation L(Loop, SM, PDB.LC);
- const CompoundStmt *CS = NULL;
+ const CompoundStmt *CS = nullptr;
if (const ForStmt *FS = dyn_cast<ForStmt>(Loop))
CS = dyn_cast<CompoundStmt>(FS->getBody());
@@ -1673,7 +1674,7 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD,
PathDiagnosticCallPiece *C;
if (VisitedEntireCall) {
- PathDiagnosticPiece *P = PD.getActivePath().front().getPtr();
+ PathDiagnosticPiece *P = PD.getActivePath().front().get();
C = cast<PathDiagnosticCallPiece>(P);
} else {
const Decl *Caller = CE->getLocationContext()->getDecl();
@@ -1683,11 +1684,11 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD,
// reset the mapping from active to location context.
assert(PD.getActivePath().size() == 1 &&
PD.getActivePath().front() == C);
- LCM[&PD.getActivePath()] = 0;
+ LCM[&PD.getActivePath()] = nullptr;
// Record the location context mapping for the path within
// the call.
- assert(LCM[&C->path] == 0 ||
+ assert(LCM[&C->path] == nullptr ||
LCM[&C->path] == CE->getCalleeContext());
LCM[&C->path] = CE->getCalleeContext();
@@ -1727,7 +1728,7 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD,
// Propagate the interesting symbols accordingly.
if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) {
reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
- N->getState().getPtr(), Ex,
+ N->getState().get(), Ex,
N->getLocationContext());
}
@@ -1755,7 +1756,7 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD,
// interesting symbols correctly.
if (const Expr *Ex = PS->getStmtAs<Expr>())
reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
- N->getState().getPtr(), Ex,
+ N->getState().get(), Ex,
N->getLocationContext());
// Add an edge. If this is an ObjCForCollectionStmt do
@@ -1778,7 +1779,7 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD,
const LocationContext *CalleeCtx = PDB.LC;
if (CallerCtx != CalleeCtx) {
reversePropagateInterestingSymbols(*PDB.getBugReport(), IE,
- N->getState().getPtr(),
+ N->getState().get(),
CalleeCtx, CallerCtx);
}
}
@@ -1786,7 +1787,7 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD,
// Are we jumping to the head of a loop? Add a special diagnostic.
if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) {
PathDiagnosticLocation L(Loop, SM, PDB.LC);
- const Stmt *Body = NULL;
+ const Stmt *Body = nullptr;
if (const ForStmt *FS = dyn_cast<ForStmt>(Loop))
Body = FS->getBody();
@@ -1827,7 +1828,7 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD,
bool IsInLoopBody =
isInLoopBody(PM, getStmtBeforeCond(PM, TermCond, N), Term);
- const char *str = 0;
+ const char *str = nullptr;
if (isJumpToFalseBranch(&*BE)) {
if (!IsInLoopBody) {
@@ -1890,13 +1891,13 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD,
static const Stmt *getLocStmt(PathDiagnosticLocation L) {
if (!L.isValid())
- return 0;
+ return nullptr;
return L.asStmt();
}
static const Stmt *getStmtParent(const Stmt *S, const ParentMap &PM) {
if (!S)
- return 0;
+ return nullptr;
while (true) {
S = PM.getParentIgnoreParens(S);
@@ -1988,7 +1989,7 @@ static void addContextEdges(PathPieces &pieces, SourceManager &SM,
SmallVector<PathDiagnosticLocation, 4> SrcContexts;
PathDiagnosticLocation NextSrcContext = SrcLoc;
- const Stmt *InnerStmt = 0;
+ const Stmt *InnerStmt = nullptr;
while (NextSrcContext.isValid() && NextSrcContext.asStmt() != InnerStmt) {
SrcContexts.push_back(NextSrcContext);
InnerStmt = NextSrcContext.asStmt();
@@ -2073,7 +2074,7 @@ static void simplifySimpleBranches(PathPieces &pieces) {
if (NextI == E)
break;
- PathDiagnosticControlFlowPiece *PieceNextI = 0;
+ PathDiagnosticControlFlowPiece *PieceNextI = nullptr;
while (true) {
if (NextI == E)
@@ -2579,8 +2580,8 @@ const Decl *BugReport::getDeclWithIssue() const {
const ExplodedNode *N = getErrorNode();
if (!N)
- return 0;
-
+ return nullptr;
+
const LocationContext *LC = N->getLocationContext();
return LC->getCurrentStackFrame()->getDecl();
}
@@ -2703,10 +2704,10 @@ void BugReport::popInterestingSymbolsAndRegions() {
const Stmt *BugReport::getStmt() const {
if (!ErrorNode)
- return 0;
+ return nullptr;
ProgramPoint ProgP = ErrorNode->getLocation();
- const Stmt *S = NULL;
+ const Stmt *S = nullptr;
if (Optional<BlockEntrance> BE = ProgP.getAs<BlockEntrance>()) {
CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit();
@@ -2742,12 +2743,10 @@ PathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const {
assert(!Location.isValid() &&
"Either Location or ErrorNode should be specified but not both.");
return PathDiagnosticLocation::createEndOfPath(ErrorNode, SM);
- } else {
- assert(Location.isValid());
- return Location;
}
- return PathDiagnosticLocation();
+ assert(Location.isValid());
+ return Location;
}
//===----------------------------------------------------------------------===//
@@ -2802,9 +2801,7 @@ void BugReporter::FlushReports() {
// EmitBasicReport.
// FIXME: There are leaks from checkers that assume that the BugTypes they
// create will be destroyed by the BugReporter.
- for (llvm::StringMap<BugType*>::iterator
- I = StrBugTypes.begin(), E = StrBugTypes.end(); I != E; ++I)
- delete I->second;
+ llvm::DeleteContainerSeconds(StrBugTypes);
// Remove all references to the BugType objects.
BugTypes = F.getEmptySet();
@@ -2820,7 +2817,7 @@ namespace {
class ReportGraph {
public:
InterExplodedGraphMap BackMap;
- OwningPtr<ExplodedGraph> Graph;
+ std::unique_ptr<ExplodedGraph> Graph;
const ExplodedNode *ErrorNode;
size_t Index;
};
@@ -2835,7 +2832,7 @@ class TrimmedGraph {
typedef std::pair<const ExplodedNode *, size_t> NodeIndexPair;
SmallVector<NodeIndexPair, 32> ReportNodes;
- OwningPtr<ExplodedGraph> G;
+ std::unique_ptr<ExplodedGraph> G;
/// A helper class for sorting ExplodedNodes by priority.
template <bool Descending>
@@ -2906,7 +2903,7 @@ TrimmedGraph::TrimmedGraph(const ExplodedGraph *OriginalGraph,
PriorityMapTy::iterator PriorityEntry;
bool IsNew;
- llvm::tie(PriorityEntry, IsNew) =
+ std::tie(PriorityEntry, IsNew) =
PriorityMap.insert(std::make_pair(Node, Priority));
++Priority;
@@ -2935,7 +2932,7 @@ bool TrimmedGraph::popNextReportGraph(ReportGraph &GraphWrapper) {
return false;
const ExplodedNode *OrigN;
- llvm::tie(OrigN, GraphWrapper.Index) = ReportNodes.pop_back_val();
+ std::tie(OrigN, GraphWrapper.Index) = ReportNodes.pop_back_val();
assert(PriorityMap.find(OrigN) != PriorityMap.end() &&
"error node not accessible from root");
@@ -2947,7 +2944,7 @@ bool TrimmedGraph::popNextReportGraph(ReportGraph &GraphWrapper) {
// Now walk from the error node up the BFS path, always taking the
// predeccessor with the lowest number.
- ExplodedNode *Succ = 0;
+ ExplodedNode *Succ = nullptr;
while (true) {
// Create the equivalent node in the new graph with the same state
// and location.
@@ -2998,7 +2995,7 @@ static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) {
for (PathPieces::const_iterator I = path.begin(), E = path.end();
I!=E; ++I) {
- PathDiagnosticPiece *piece = I->getPtr();
+ PathDiagnosticPiece *piece = I->get();
// Recursively compact calls.
if (PathDiagnosticCallPiece *call=dyn_cast<PathDiagnosticCallPiece>(piece)){
@@ -3095,7 +3092,7 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD,
} else {
// Keep the errorNodes list in sync with the bugReports list.
HasInvalid = true;
- errorNodes.push_back(0);
+ errorNodes.push_back(nullptr);
}
}
@@ -3153,21 +3150,21 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD,
// Generate the very last diagnostic piece - the piece is visible before
// the trace is expanded.
- PathDiagnosticPiece *LastPiece = 0;
+ std::unique_ptr<PathDiagnosticPiece> LastPiece;
for (BugReport::visitor_iterator I = visitors.begin(), E = visitors.end();
I != E; ++I) {
if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) {
assert (!LastPiece &&
"There can only be one final piece in a diagnostic.");
- LastPiece = Piece;
+ LastPiece.reset(Piece);
}
}
if (ActiveScheme != PathDiagnosticConsumer::None) {
if (!LastPiece)
- LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R);
+ LastPiece.reset(BugReporterVisitor::getDefaultEndPath(PDB, N, *R));
assert(LastPiece);
- PD.setEndOfPath(LastPiece);
+ PD.setEndOfPath(LastPiece.release());
}
// Make sure we get a clean location context map so we don't
@@ -3247,6 +3244,9 @@ void BugReporter::Register(BugType *BT) {
}
void BugReporter::emitReport(BugReport* R) {
+ // To guarantee memory release.
+ std::unique_ptr<BugReport> UniqueR(R);
+
// Defensive checking: throw the bug away if it comes from a BodyFarm-
// generated body. We do this very early because report processing relies
// on the report's location being valid.
@@ -3277,12 +3277,12 @@ void BugReporter::emitReport(BugReport* R) {
BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos);
if (!EQ) {
- EQ = new BugReportEquivClass(R);
+ EQ = new BugReportEquivClass(UniqueR.release());
EQClasses.InsertNode(EQ, InsertPos);
EQClassesVector.push_back(EQ);
}
else
- EQ->AddReport(R);
+ EQ->AddReport(UniqueR.release());
}
@@ -3329,7 +3329,7 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ,
// DFS traversal of the ExplodedGraph to find a non-sink node. We could write
// this as a recursive function, but we don't want to risk blowing out the
// stack for very long paths.
- BugReport *exampleReport = 0;
+ BugReport *exampleReport = nullptr;
for (; I != E; ++I) {
const ExplodedNode *errorNode = I->getErrorNode();
@@ -3403,10 +3403,8 @@ void BugReporter::FlushReport(BugReportEquivClass& EQ) {
SmallVector<BugReport*, 10> bugReports;
BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports);
if (exampleReport) {
- const PathDiagnosticConsumers &C = getPathDiagnosticConsumers();
- for (PathDiagnosticConsumers::const_iterator I=C.begin(),
- E=C.end(); I != E; ++I) {
- FlushReport(exampleReport, **I, bugReports);
+ for (PathDiagnosticConsumer *PDC : getPathDiagnosticConsumers()) {
+ FlushReport(exampleReport, *PDC, bugReports);
}
}
}
@@ -3419,14 +3417,13 @@ void BugReporter::FlushReport(BugReport *exampleReport,
// Probably doesn't make a difference in practice.
BugType& BT = exampleReport->getBugType();
- OwningPtr<PathDiagnostic>
- D(new PathDiagnostic(exampleReport->getDeclWithIssue(),
- exampleReport->getBugType().getName(),
- exampleReport->getDescription(),
- exampleReport->getShortDescription(/*Fallback=*/false),
- BT.getCategory(),
- exampleReport->getUniqueingLocation(),
- exampleReport->getUniqueingDecl()));
+ std::unique_ptr<PathDiagnostic> D(new PathDiagnostic(
+ exampleReport->getBugType().getCheckName(),
+ exampleReport->getDeclWithIssue(), exampleReport->getBugType().getName(),
+ exampleReport->getDescription(),
+ exampleReport->getShortDescription(/*Fallback=*/false), BT.getCategory(),
+ exampleReport->getUniqueingLocation(),
+ exampleReport->getUniqueingDecl()));
MaxBugClassSize = std::max(bugReports.size(),
static_cast<size_t>(MaxBugClassSize));
@@ -3455,7 +3452,7 @@ void BugReporter::FlushReport(BugReport *exampleReport,
PathDiagnosticPiece *piece =
new PathDiagnosticEventPiece(L, exampleReport->getDescription());
BugReport::ranges_iterator Beg, End;
- llvm::tie(Beg, End) = exampleReport->getRanges();
+ std::tie(Beg, End) = exampleReport->getRanges();
for ( ; Beg != End; ++Beg)
piece->addRange(*Beg);
D->setEndOfPath(piece);
@@ -3468,17 +3465,25 @@ void BugReporter::FlushReport(BugReport *exampleReport,
D->addMeta(*i);
}
- PD.HandlePathDiagnostic(D.take());
+ PD.HandlePathDiagnostic(D.release());
}
void BugReporter::EmitBasicReport(const Decl *DeclWithIssue,
- StringRef name,
- StringRef category,
+ const CheckerBase *Checker,
+ StringRef Name, StringRef Category,
+ StringRef Str, PathDiagnosticLocation Loc,
+ ArrayRef<SourceRange> Ranges) {
+ EmitBasicReport(DeclWithIssue, Checker->getCheckName(), Name, Category, Str,
+ Loc, Ranges);
+}
+void BugReporter::EmitBasicReport(const Decl *DeclWithIssue,
+ CheckName CheckName,
+ StringRef name, StringRef category,
StringRef str, PathDiagnosticLocation Loc,
ArrayRef<SourceRange> Ranges) {
// 'BT' is owned by BugReporter.
- BugType *BT = getBugTypeForName(name, category);
+ BugType *BT = getBugTypeForName(CheckName, name, category);
BugReport *R = new BugReport(*BT, str, Loc);
R->setDeclWithIssue(DeclWithIssue);
for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
@@ -3487,22 +3492,22 @@ void BugReporter::EmitBasicReport(const Decl *DeclWithIssue,
emitReport(R);
}
-BugType *BugReporter::getBugTypeForName(StringRef name,
+BugType *BugReporter::getBugTypeForName(CheckName CheckName, StringRef name,
StringRef category) {
SmallString<136> fullDesc;
- llvm::raw_svector_ostream(fullDesc) << name << ":" << category;
+ llvm::raw_svector_ostream(fullDesc) << CheckName.getName() << ":" << name
+ << ":" << category;
llvm::StringMapEntry<BugType *> &
entry = StrBugTypes.GetOrCreateValue(fullDesc);
BugType *BT = entry.getValue();
if (!BT) {
- BT = new BugType(name, category);
+ BT = new BugType(CheckName, name, category);
entry.setValue(BT);
}
return BT;
}
-
-void PathPieces::dump() const {
+LLVM_DUMP_METHOD void PathPieces::dump() const {
unsigned index = 0;
for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
llvm::errs() << "[" << index++ << "] ";
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index e1a92b30c6be6..0503acec051a0 100644
--- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -45,7 +45,7 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) {
// a[0], p->f, *p
const Expr *E = dyn_cast<Expr>(S);
if (!E)
- return 0;
+ return nullptr;
E = E->IgnoreParenCasts();
while (true) {
@@ -79,21 +79,21 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) {
break;
}
- return NULL;
+ return nullptr;
}
const Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) {
const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S))
return BE->getRHS();
- return NULL;
+ return nullptr;
}
const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) {
const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S))
return RS->getRetValue();
- return NULL;
+ return nullptr;
}
//===----------------------------------------------------------------------===//
@@ -104,7 +104,7 @@ PathDiagnosticPiece*
BugReporterVisitor::getEndPath(BugReporterContext &BRC,
const ExplodedNode *EndPathNode,
BugReport &BR) {
- return 0;
+ return nullptr;
}
PathDiagnosticPiece*
@@ -115,7 +115,7 @@ BugReporterVisitor::getDefaultEndPath(BugReporterContext &BRC,
PathDiagnosticLocation::createEndOfPath(EndPathNode,BRC.getSourceManager());
BugReport::ranges_iterator Beg, End;
- llvm::tie(Beg, End) = BR.getRanges();
+ std::tie(Beg, End) = BR.getRanges();
// Only add the statement itself as a range if we didn't specify any
// special ranges for this report.
@@ -156,7 +156,7 @@ public:
return static_cast<void *>(&Tag);
}
- virtual void Profile(llvm::FoldingSetNodeID &ID) const {
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
ID.AddPointer(ReturnVisitor::getTag());
ID.AddPointer(StackFrame);
ID.AddBoolean(EnableNullFPSuppression);
@@ -237,22 +237,22 @@ public:
BugReport &BR) {
// Only print a message at the interesting return statement.
if (N->getLocationContext() != StackFrame)
- return 0;
+ return nullptr;
Optional<StmtPoint> SP = N->getLocationAs<StmtPoint>();
if (!SP)
- return 0;
+ return nullptr;
const ReturnStmt *Ret = dyn_cast<ReturnStmt>(SP->getStmt());
if (!Ret)
- return 0;
+ return nullptr;
// Okay, we're at the right return statement, but do we have the return
// value available?
ProgramStateRef State = N->getState();
SVal V = State->getSVal(Ret, StackFrame);
if (V.isUnknownOrUndef())
- return 0;
+ return nullptr;
// Don't print any more notes after this one.
Mode = Satisfied;
@@ -273,7 +273,7 @@ public:
// Ignore aggregate rvalues.
if (V.getAs<nonloc::LazyCompoundVal>() ||
V.getAs<nonloc::CompoundVal>())
- return 0;
+ return nullptr;
RetE = RetE->IgnoreParenCasts();
@@ -283,7 +283,7 @@ public:
BR.markInteresting(V);
ReturnVisitor::addVisitorIfNecessary(N, RetE, BR,
EnableNullFPSuppression);
- return 0;
+ return nullptr;
}
// If we're returning 0, we should track where that 0 came from.
@@ -343,10 +343,10 @@ public:
// Are we at the entry node for this call?
Optional<CallEnter> CE = N->getLocationAs<CallEnter>();
if (!CE)
- return 0;
+ return nullptr;
if (CE->getCalleeContext() != StackFrame)
- return 0;
+ return nullptr;
Mode = Satisfied;
@@ -380,20 +380,20 @@ public:
// (We will still look at the other arguments, though.)
}
- return 0;
+ return nullptr;
}
PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
const ExplodedNode *PrevN,
BugReporterContext &BRC,
- BugReport &BR) {
+ BugReport &BR) override {
switch (Mode) {
case Initial:
return visitNodeInitial(N, PrevN, BRC, BR);
case MaybeUnsuppress:
return visitNodeMaybeUnsuppress(N, PrevN, BRC, BR);
case Satisfied:
- return 0;
+ return nullptr;
}
llvm_unreachable("Invalid visit mode!");
@@ -401,10 +401,10 @@ public:
PathDiagnosticPiece *getEndPath(BugReporterContext &BRC,
const ExplodedNode *N,
- BugReport &BR) {
+ BugReport &BR) override {
if (EnableNullFPSuppression)
BR.markInvalid(ReturnVisitor::getTag(), StackFrame);
- return 0;
+ return nullptr;
}
};
} // end anonymous namespace
@@ -453,10 +453,10 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
BugReport &BR) {
if (Satisfied)
- return NULL;
+ return nullptr;
- const ExplodedNode *StoreSite = 0;
- const Expr *InitE = 0;
+ const ExplodedNode *StoreSite = nullptr;
+ const Expr *InitE = nullptr;
bool IsParam = false;
// First see if we reached the declaration of the region.
@@ -484,12 +484,12 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
// the same binding was re-assigned here.
if (!StoreSite) {
if (Succ->getState()->getSVal(R) != V)
- return NULL;
+ return nullptr;
if (Pred->getState()->getSVal(R) == V) {
Optional<PostStore> PS = Succ->getLocationAs<PostStore>();
if (!PS || PS->getLocationValue() != R)
- return NULL;
+ return nullptr;
}
StoreSite = Succ;
@@ -526,7 +526,7 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
}
if (!StoreSite)
- return NULL;
+ return nullptr;
Satisfied = true;
// If we have an expression that provided the value, try to track where it
@@ -550,7 +550,7 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
if (Optional<PostStmt> PS = StoreSite->getLocationAs<PostStmt>()) {
const Stmt *S = PS->getStmt();
- const char *action = 0;
+ const char *action = nullptr;
const DeclStmt *DS = dyn_cast<DeclStmt>(S);
const VarRegion *VR = dyn_cast<VarRegion>(R);
@@ -703,7 +703,7 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
L = PathDiagnosticLocation::create(P, BRC.getSourceManager());
if (!L.isValid() || !L.asLocation().isValid())
- return NULL;
+ return nullptr;
return new PathDiagnosticEventPiece(L, os.str());
}
@@ -724,7 +724,7 @@ const char *TrackConstraintBRVisitor::getTag() {
bool TrackConstraintBRVisitor::isUnderconstrained(const ExplodedNode *N) const {
if (IsZeroCheck)
return N->getState()->isNull(Constraint).isUnderconstrained();
- return N->getState()->assume(Constraint, !Assumption);
+ return (bool)N->getState()->assume(Constraint, !Assumption);
}
PathDiagnosticPiece *
@@ -733,7 +733,7 @@ TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N,
BugReporterContext &BRC,
BugReport &BR) {
if (IsSatisfied)
- return NULL;
+ return nullptr;
// Start tracking after we see the first state in which the value is
// constrained.
@@ -741,7 +741,7 @@ TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N,
if (!isUnderconstrained(N))
IsTrackingTurnedOn = true;
if (!IsTrackingTurnedOn)
- return 0;
+ return nullptr;
// Check if in the previous state it was feasible for this constraint
// to *not* be true.
@@ -765,21 +765,21 @@ TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N,
}
if (os.str().empty())
- return NULL;
+ return nullptr;
// Construct a new PathDiagnosticPiece.
ProgramPoint P = N->getLocation();
PathDiagnosticLocation L =
PathDiagnosticLocation::create(P, BRC.getSourceManager());
if (!L.isValid())
- return NULL;
-
+ return nullptr;
+
PathDiagnosticEventPiece *X = new PathDiagnosticEventPiece(L, os.str());
X->setTag(getTag());
return X;
}
- return NULL;
+ return nullptr;
}
SuppressInlineDefensiveChecksVisitor::
@@ -813,14 +813,14 @@ SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ,
BugReporterContext &BRC,
BugReport &BR) {
if (IsSatisfied)
- return 0;
+ return nullptr;
// Start tracking after we see the first state in which the value is null.
if (!IsTrackingTurnedOn)
if (Succ->getState()->isNull(V).isConstrainedTrue())
IsTrackingTurnedOn = true;
if (!IsTrackingTurnedOn)
- return 0;
+ return nullptr;
// Check if in the previous state it was feasible for this value
// to *not* be null.
@@ -835,7 +835,7 @@ SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ,
if (CurLC != ReportLC && !CurLC->isParentOf(ReportLC))
BR.markInvalid("Suppress IDC", CurLC);
}
- return 0;
+ return nullptr;
}
static const MemRegion *getLocationRegionIfReference(const Expr *E,
@@ -843,7 +843,7 @@ static const MemRegion *getLocationRegionIfReference(const Expr *E,
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) {
if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
if (!VD->getType()->isReferenceType())
- return 0;
+ return nullptr;
ProgramStateManager &StateMgr = N->getState()->getStateManager();
MemRegionManager &MRMgr = StateMgr.getRegionManager();
return MRMgr.getVarRegion(VD, N->getLocationContext());
@@ -856,7 +856,7 @@ static const MemRegion *getLocationRegionIfReference(const Expr *E,
// Wrapper w = { *(int *)0 };
// w.ref = 1;
- return 0;
+ return nullptr;
}
static const Expr *peelOffOuterExpr(const Expr *Ex,
@@ -869,7 +869,7 @@ static const Expr *peelOffOuterExpr(const Expr *Ex,
// Peel off the ternary operator.
if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(Ex)) {
- // Find a node where the branching occured and find out which branch
+ // Find a node where the branching occurred and find out which branch
// we took (true/false) by looking at the ExplodedGraph.
const ExplodedNode *NI = N;
do {
@@ -906,7 +906,7 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
S = PeeledEx;
}
- const Expr *Inner = 0;
+ const Expr *Inner = nullptr;
if (const Expr *Ex = dyn_cast<Expr>(S)) {
Ex = Ex->IgnoreParenCasts();
if (ExplodedGraph::isInterestingLValueExpr(Ex) || CallEvent::isCallStmt(Ex))
@@ -948,7 +948,7 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
// See if the expression we're interested refers to a variable.
// If so, we can track both its contents and constraints on its value.
if (Inner && ExplodedGraph::isInterestingLValueExpr(Inner)) {
- const MemRegion *R = 0;
+ const MemRegion *R = nullptr;
// Find the ExplodedNode where the lvalue (the value of 'Ex')
// was computed. We need this for getting the location value.
@@ -1060,14 +1060,14 @@ const Expr *NilReceiverBRVisitor::getNilReceiver(const Stmt *S,
const ExplodedNode *N) {
const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S);
if (!ME)
- return 0;
+ return nullptr;
if (const Expr *Receiver = ME->getInstanceReceiver()) {
ProgramStateRef state = N->getState();
SVal V = state->getSVal(Receiver, N->getLocationContext());
if (state->isNull(V).isConstrainedTrue())
return Receiver;
}
- return 0;
+ return nullptr;
}
PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
@@ -1076,18 +1076,20 @@ PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
BugReport &BR) {
Optional<PreStmt> P = N->getLocationAs<PreStmt>();
if (!P)
- return 0;
+ return nullptr;
const Stmt *S = P->getStmt();
const Expr *Receiver = getNilReceiver(S, N);
if (!Receiver)
- return 0;
+ return nullptr;
llvm::SmallString<256> Buf;
llvm::raw_svector_ostream OS(Buf);
if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
- OS << "'" << ME->getSelector().getAsString() << "' not called";
+ OS << "'";
+ ME->getSelector().print(OS);
+ OS << "' not called";
}
else {
OS << "No method is called";
@@ -1179,15 +1181,15 @@ PathDiagnosticPiece *ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N,
// were generated by the analyzer engine proper, not checkers.
if (CurrentState->getGDM().getRoot() ==
PrevState->getGDM().getRoot())
- return 0;
-
+ return nullptr;
+
// If an assumption was made on a branch, it should be caught
// here by looking at the state transition.
if (Optional<BlockEdge> BE = progPoint.getAs<BlockEdge>()) {
const CFGBlock *srcBlk = BE->getSrc();
if (const Stmt *term = srcBlk->getTerminator())
return VisitTerminator(term, N, srcBlk, BE->getDst(), BR, BRC);
- return 0;
+ return nullptr;
}
if (Optional<PostStmt> PS = progPoint.getAs<PostStmt>()) {
@@ -1204,11 +1206,11 @@ PathDiagnosticPiece *ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N,
if (tag == tags.second)
return VisitTrueTest(cast<Expr>(PS->getStmt()), false,
BRC, BR, N);
-
- return 0;
+
+ return nullptr;
}
-
- return 0;
+
+ return nullptr;
}
PathDiagnosticPiece *
@@ -1218,11 +1220,11 @@ ConditionBRVisitor::VisitTerminator(const Stmt *Term,
const CFGBlock *dstBlk,
BugReport &R,
BugReporterContext &BRC) {
- const Expr *Cond = 0;
-
+ const Expr *Cond = nullptr;
+
switch (Term->getStmtClass()) {
default:
- return 0;
+ return nullptr;
case Stmt::IfStmtClass:
Cond = cast<IfStmt>(Term)->getCond();
break;
@@ -1250,7 +1252,7 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
Ex = Ex->IgnoreParenCasts();
switch (Ex->getStmtClass()) {
default:
- return 0;
+ return nullptr;
case Stmt::BinaryOperatorClass:
return VisitTrueTest(Cond, cast<BinaryOperator>(Ex), tookTrue, BRC,
R, N);
@@ -1264,7 +1266,7 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
Ex = UO->getSubExpr();
continue;
}
- return 0;
+ return nullptr;
}
}
}
@@ -1283,13 +1285,13 @@ bool ConditionBRVisitor::patternMatch(const Expr *Ex, raw_ostream &Out,
if (quotes) {
Out << '\'';
const LocationContext *LCtx = N->getLocationContext();
- const ProgramState *state = N->getState().getPtr();
+ const ProgramState *state = N->getState().get();
if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()),
LCtx).getAsRegion()) {
if (report.isInteresting(R))
prunable = false;
else {
- const ProgramState *state = N->getState().getPtr();
+ const ProgramState *state = N->getState().get();
SVal V = state->getSVal(R);
if (report.isInteresting(V))
prunable = false;
@@ -1359,8 +1361,8 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
// both the LHS and RHS.
if (LhsString.empty() || RhsString.empty() ||
!BinaryOperator::isComparisonOp(Op))
- return 0;
-
+ return nullptr;
+
// Should we invert the strings if the LHS is not a variable name?
SmallString<256> buf;
llvm::raw_svector_ostream Out(buf);
@@ -1385,7 +1387,7 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
case BO_LE: Op = BO_GT; break;
case BO_GE: Op = BO_LT; break;
default:
- return 0;
+ return nullptr;
}
switch (Op) {
@@ -1435,7 +1437,7 @@ ConditionBRVisitor::VisitConditionVariable(StringRef LhsString,
else if (Ty->isIntegralOrEnumerationType())
Out << (tookTrue ? "non-zero" : "zero");
else
- return 0;
+ return nullptr;
const LocationContext *LCtx = N->getLocationContext();
PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
@@ -1444,7 +1446,7 @@ ConditionBRVisitor::VisitConditionVariable(StringRef LhsString,
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) {
if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
- const ProgramState *state = N->getState().getPtr();
+ const ProgramState *state = N->getState().get();
if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
if (report.isInteresting(R))
event->setPrunable(false);
@@ -1465,8 +1467,8 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
if (!VD)
- return 0;
-
+ return nullptr;
+
SmallString<256> Buf;
llvm::raw_svector_ostream Out(Buf);
@@ -1481,14 +1483,14 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
else if (VDTy->isScalarType())
Out << (tookTrue ? "not equal to 0" : "0");
else
- return 0;
-
+ return nullptr;
+
const LocationContext *LCtx = N->getLocationContext();
PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
PathDiagnosticEventPiece *event =
new PathDiagnosticEventPiece(Loc, Out.str());
- const ProgramState *state = N->getState().getPtr();
+ const ProgramState *state = N->getState().get();
if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
if (report.isInteresting(R))
event->setPrunable(false);
@@ -1512,7 +1514,7 @@ static bool isInStdNamespace(const Decl *D) {
while (const NamespaceDecl *Parent = dyn_cast<NamespaceDecl>(ND->getParent()))
ND = Parent;
- return ND->getName() == "std";
+ return ND->isStdNamespace();
}
@@ -1532,8 +1534,8 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
// Note that this will not help for any other data structure libraries, like
// TR1, Boost, or llvm/ADT.
if (Options.shouldSuppressFromCXXStandardLibrary()) {
- BR.markInvalid(getTag(), 0);
- return 0;
+ BR.markInvalid(getTag(), nullptr);
+ return nullptr;
} else {
// If the the complete 'std' suppression is not enabled, suppress reports
@@ -1545,8 +1547,8 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
const CXXRecordDecl *CD = MD->getParent();
if (CD->getName() == "list") {
- BR.markInvalid(getTag(), 0);
- return 0;
+ BR.markInvalid(getTag(), nullptr);
+ return nullptr;
}
}
@@ -1556,25 +1558,18 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
// std::u16string s; s += u'a';
// because we cannot reason about the internal invariants of the
// datastructure.
- const LocationContext *LCtx = N->getLocationContext();
- do {
+ for (const LocationContext *LCtx = N->getLocationContext(); LCtx;
+ LCtx = LCtx->getParent()) {
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
if (!MD)
- break;
+ continue;
const CXXRecordDecl *CD = MD->getParent();
if (CD->getName() == "basic_string") {
- BR.markInvalid(getTag(), 0);
- return 0;
- } else if (CD->getName().find("allocator") == StringRef::npos) {
- // Only keep searching if the current method is in a class with the
- // word "allocator" in its name, e.g. std::allocator or
- // allocator_traits.
- break;
+ BR.markInvalid(getTag(), nullptr);
+ return nullptr;
}
-
- LCtx = LCtx->getParent();
- } while (LCtx);
+ }
}
}
@@ -1585,12 +1580,12 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
while (Loc.isMacroID()) {
Loc = Loc.getSpellingLoc();
if (SM.getFilename(Loc).endswith("sys/queue.h")) {
- BR.markInvalid(getTag(), 0);
- return 0;
+ BR.markInvalid(getTag(), nullptr);
+ return nullptr;
}
}
- return 0;
+ return nullptr;
}
PathDiagnosticPiece *
@@ -1605,14 +1600,16 @@ UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N,
// We are only interested in visiting CallEnter nodes.
Optional<CallEnter> CEnter = ProgLoc.getAs<CallEnter>();
if (!CEnter)
- return 0;
+ return nullptr;
// Check if one of the arguments is the region the visitor is tracking.
CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager();
CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State);
unsigned Idx = 0;
- for (CallEvent::param_iterator I = Call->param_begin(),
- E = Call->param_end(); I != E; ++I, ++Idx) {
+ ArrayRef<ParmVarDecl*> parms = Call->parameters();
+
+ for (ArrayRef<ParmVarDecl*>::iterator I = parms.begin(), E = parms.end();
+ I != E; ++I, ++Idx) {
const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion();
// Are we tracking the argument or its subregion?
@@ -1639,8 +1636,8 @@ UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N,
SVal BoundVal = State->getSVal(R);
if (BoundVal.isUndef() || BoundVal.isZeroConstant()) {
BR.markInteresting(CEnter->getCalleeContext());
- return 0;
+ return nullptr;
}
}
- return 0;
+ return nullptr;
}
diff --git a/lib/StaticAnalyzer/Core/CMakeLists.txt b/lib/StaticAnalyzer/Core/CMakeLists.txt
index 013f8a56b4330..59a6b6fbc5951 100644
--- a/lib/StaticAnalyzer/Core/CMakeLists.txt
+++ b/lib/StaticAnalyzer/Core/CMakeLists.txt
@@ -39,21 +39,11 @@ add_clang_library(clangStaticAnalyzerCore
Store.cpp
SubEngine.cpp
SymbolManager.cpp
- )
-
-add_dependencies(clangStaticAnalyzerCore
- ClangAttrClasses
- ClangAttrList
- ClangCommentNodes
- ClangDeclNodes
- ClangDiagnosticCommon
- ClangStmtNodes
- )
-target_link_libraries(clangStaticAnalyzerCore
+ LINK_LIBS
+ clangAST
+ clangAnalysis
clangBasic
clangLex
- clangAST
- clangFrontend
- clangRewriteCore
+ clangRewrite
)
diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp
index a3b34f4790a97..7e0670a06608a 100644
--- a/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -68,8 +68,7 @@ static bool isCallbackArg(SVal V, QualType T) {
if (const RecordType *RT = T->getAsStructureType()) {
const RecordDecl *RD = RT->getDecl();
- for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
- I != E; ++I) {
+ for (const auto *I : RD->fields()) {
QualType FieldT = I->getType();
if (FieldT->isBlockPointerType() || FieldT->isFunctionPointerType())
return true;
@@ -140,6 +139,11 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
ProgramStateRef Orig) const {
ProgramStateRef Result = (Orig ? Orig : getState());
+ // Don't invalidate anything if the callee is marked pure/const.
+ if (const Decl *callee = getDecl())
+ if (callee->hasAttr<PureAttr>() || callee->hasAttr<ConstAttr>())
+ return Result;
+
SmallVector<SVal, 8> ValuesToInvalidate;
RegionAndSymbolInvalidationTraits ETraits;
@@ -168,7 +172,7 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
return Result->invalidateRegions(ValuesToInvalidate, getOriginExpr(),
BlockCount, getLocationContext(),
/*CausedByPointerEscape*/ true,
- /*Symbols=*/0, this, &ETraits);
+ /*Symbols=*/nullptr, this, &ETraits);
}
ProgramPoint CallEvent::getProgramPoint(bool IsPreVisit,
@@ -209,14 +213,12 @@ SVal CallEvent::getReturnValue() const {
return getSVal(E);
}
-void CallEvent::dump() const {
- dump(llvm::errs());
-}
+LLVM_DUMP_METHOD void CallEvent::dump() const { dump(llvm::errs()); }
void CallEvent::dump(raw_ostream &Out) const {
ASTContext &Ctx = getState()->getStateManager().getContext();
if (const Expr *E = getOriginExpr()) {
- E->printPretty(Out, 0, Ctx.getPrintingPolicy());
+ E->printPretty(Out, nullptr, Ctx.getPrintingPolicy());
Out << "\n";
return;
}
@@ -241,9 +243,9 @@ bool CallEvent::isCallStmt(const Stmt *S) {
QualType CallEvent::getDeclaredResultType(const Decl *D) {
assert(D);
if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D))
- return FD->getResultType();
+ return FD->getReturnType();
if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(D))
- return MD->getResultType();
+ return MD->getReturnType();
if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
// Blocks are difficult because the return type may not be stored in the
// BlockDecl itself. The AST should probably be enhanced, but for now we
@@ -256,7 +258,7 @@ QualType CallEvent::getDeclaredResultType(const Decl *D) {
if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten()) {
QualType Ty = TSI->getType();
if (const FunctionType *FT = Ty->getAs<FunctionType>())
- Ty = FT->getResultType();
+ Ty = FT->getReturnType();
if (!Ty->isDependentType())
return Ty;
}
@@ -284,14 +286,14 @@ static void addParameterValuesToBindings(const StackFrameContext *CalleeCtx,
CallEvent::BindingsTy &Bindings,
SValBuilder &SVB,
const CallEvent &Call,
- CallEvent::param_iterator I,
- CallEvent::param_iterator E) {
+ ArrayRef<ParmVarDecl*> parameters) {
MemRegionManager &MRMgr = SVB.getRegionManager();
// If the function has fewer parameters than the call has arguments, we simply
// do not bind any values to them.
unsigned NumArgs = Call.getNumArgs();
unsigned Idx = 0;
+ ArrayRef<ParmVarDecl*>::iterator I = parameters.begin(), E = parameters.end();
for (; I != E && Idx < NumArgs; ++I, ++Idx) {
const ParmVarDecl *ParamDecl = *I;
assert(ParamDecl && "Formal parameter has no decl?");
@@ -306,21 +308,11 @@ static void addParameterValuesToBindings(const StackFrameContext *CalleeCtx,
// FIXME: Variadic arguments are not handled at all right now.
}
-
-CallEvent::param_iterator AnyFunctionCall::param_begin() const {
- const FunctionDecl *D = getDecl();
- if (!D)
- return 0;
-
- return D->param_begin();
-}
-
-CallEvent::param_iterator AnyFunctionCall::param_end() const {
+ArrayRef<ParmVarDecl*> AnyFunctionCall::parameters() const {
const FunctionDecl *D = getDecl();
if (!D)
- return 0;
-
- return D->param_end();
+ return None;
+ return D->parameters();
}
void AnyFunctionCall::getInitialStackFrameContents(
@@ -329,7 +321,7 @@ void AnyFunctionCall::getInitialStackFrameContents(
const FunctionDecl *D = cast<FunctionDecl>(CalleeCtx->getDecl());
SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this,
- D->param_begin(), D->param_end());
+ D->parameters());
}
bool AnyFunctionCall::argumentsMayEscape() const {
@@ -389,7 +381,7 @@ bool AnyFunctionCall::argumentsMayEscape() const {
}
-const FunctionDecl *SimpleCall::getDecl() const {
+const FunctionDecl *SimpleFunctionCall::getDecl() const {
const FunctionDecl *D = getOriginExpr()->getDirectCallee();
if (D)
return D;
@@ -484,7 +476,7 @@ RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const {
// that ExprEngine can decide what to do with it.
if (DynType.canBeASubClass())
return RuntimeDefinition(Definition, R->StripCasts());
- return RuntimeDefinition(Definition, /*DispatchRegion=*/0);
+ return RuntimeDefinition(Definition, /*DispatchRegion=*/nullptr);
}
void CXXInstanceCall::getInitialStackFrameContents(
@@ -550,18 +542,11 @@ const BlockDataRegion *BlockCall::getBlockRegion() const {
return dyn_cast_or_null<BlockDataRegion>(DataReg);
}
-CallEvent::param_iterator BlockCall::param_begin() const {
- const BlockDecl *D = getBlockDecl();
+ArrayRef<ParmVarDecl*> BlockCall::parameters() const {
+ const BlockDecl *D = getDecl();
if (!D)
- return 0;
- return D->param_begin();
-}
-
-CallEvent::param_iterator BlockCall::param_end() const {
- const BlockDecl *D = getBlockDecl();
- if (!D)
- return 0;
- return D->param_end();
+ return nullptr;
+ return D->parameters();
}
void BlockCall::getExtraInvalidatedValues(ValueList &Values) const {
@@ -575,7 +560,7 @@ void BlockCall::getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
const BlockDecl *D = cast<BlockDecl>(CalleeCtx->getDecl());
SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this,
- D->param_begin(), D->param_end());
+ D->parameters());
}
@@ -604,8 +589,6 @@ void CXXConstructorCall::getInitialStackFrameContents(
}
}
-
-
SVal CXXDestructorCall::getCXXThisVal() const {
if (Data)
return loc::MemRegionVal(DtorDataTy::getFromOpaqueValue(Data).getPointer());
@@ -621,21 +604,11 @@ RuntimeDefinition CXXDestructorCall::getRuntimeDefinition() const {
return CXXInstanceCall::getRuntimeDefinition();
}
-
-CallEvent::param_iterator ObjCMethodCall::param_begin() const {
+ArrayRef<ParmVarDecl*> ObjCMethodCall::parameters() const {
const ObjCMethodDecl *D = getDecl();
if (!D)
- return 0;
-
- return D->param_begin();
-}
-
-CallEvent::param_iterator ObjCMethodCall::param_end() const {
- const ObjCMethodDecl *D = getDecl();
- if (!D)
- return 0;
-
- return D->param_end();
+ return ArrayRef<ParmVarDecl*>();
+ return D->parameters();
}
void
@@ -694,13 +667,13 @@ SourceRange ObjCMethodCall::getSourceRange() const {
typedef llvm::PointerIntPair<const PseudoObjectExpr *, 2> ObjCMessageDataTy;
const PseudoObjectExpr *ObjCMethodCall::getContainingPseudoObjectExpr() const {
- assert(Data != 0 && "Lazy lookup not yet performed.");
+ assert(Data && "Lazy lookup not yet performed.");
assert(getMessageKind() != OCM_Message && "Explicit message send.");
return ObjCMessageDataTy::getFromOpaqueValue(Data).getPointer();
}
ObjCMessageKind ObjCMethodCall::getMessageKind() const {
- if (Data == 0) {
+ if (!Data) {
// Find the parent, ignoring implicit casts.
ParentMap &PM = getLocationContext()->getParentMap();
@@ -738,7 +711,7 @@ ObjCMessageKind ObjCMethodCall::getMessageKind() const {
}
const_cast<ObjCMethodCall *>(this)->Data
- = ObjCMessageDataTy(0, 1).getOpaqueValue();
+ = ObjCMessageDataTy(nullptr, 1).getOpaqueValue();
assert(getMessageKind() == OCM_Message);
return OCM_Message;
}
@@ -774,7 +747,7 @@ bool ObjCMethodCall::canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl,
// Find the first declaration in the class hierarchy that declares
// the selector.
- ObjCMethodDecl *D = 0;
+ ObjCMethodDecl *D = nullptr;
while (true) {
D = IDecl->lookupMethod(Sel, true);
@@ -813,10 +786,10 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const {
if (E->isInstanceMessage()) {
// Find the the receiver type.
- const ObjCObjectPointerType *ReceiverT = 0;
+ const ObjCObjectPointerType *ReceiverT = nullptr;
bool CanBeSubClassed = false;
QualType SupersType = E->getSuperType();
- const MemRegion *Receiver = 0;
+ const MemRegion *Receiver = nullptr;
if (!SupersType.isNull()) {
// Super always means the type of immediate predecessor to the method
@@ -865,14 +838,22 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const {
Optional<const ObjCMethodDecl *> &Val = PMC[std::make_pair(IDecl, Sel)];
// Query lookupPrivateMethod() if the cache does not hit.
- if (!Val.hasValue())
+ if (!Val.hasValue()) {
Val = IDecl->lookupPrivateMethod(Sel);
+ // If the method is a property accessor, we should try to "inline" it
+ // even if we don't actually have an implementation.
+ if (!*Val)
+ if (const ObjCMethodDecl *CompileTimeMD = E->getMethodDecl())
+ if (CompileTimeMD->isPropertyAccessor())
+ Val = IDecl->lookupInstanceMethod(Sel);
+ }
+
const ObjCMethodDecl *MD = Val.getValue();
if (CanBeSubClassed)
return RuntimeDefinition(MD, Receiver);
else
- return RuntimeDefinition(MD, 0);
+ return RuntimeDefinition(MD, nullptr);
}
} else {
@@ -888,13 +869,24 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const {
return RuntimeDefinition();
}
+bool ObjCMethodCall::argumentsMayEscape() const {
+ if (isInSystemHeader() && !isInstanceMessage()) {
+ Selector Sel = getSelector();
+ if (Sel.getNumArgs() == 1 &&
+ Sel.getIdentifierInfoForSlot(0)->isStr("valueWithPointer"))
+ return true;
+ }
+
+ return CallEvent::argumentsMayEscape();
+}
+
void ObjCMethodCall::getInitialStackFrameContents(
const StackFrameContext *CalleeCtx,
BindingsTy &Bindings) const {
const ObjCMethodDecl *D = cast<ObjCMethodDecl>(CalleeCtx->getDecl());
SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this,
- D->param_begin(), D->param_end());
+ D->parameters());
SVal SelfVal = getReceiverSVal();
if (!SelfVal.isUnknown()) {
@@ -923,7 +915,7 @@ CallEventManager::getSimpleCall(const CallExpr *CE, ProgramStateRef State,
// Otherwise, it's a normal function call, static member function call, or
// something we can't reason about.
- return create<FunctionCall>(CE, State, LCtx);
+ return create<SimpleFunctionCall>(CE, State, LCtx);
}
diff --git a/lib/StaticAnalyzer/Core/Checker.cpp b/lib/StaticAnalyzer/Core/Checker.cpp
index 07e0aac2d4298..1a3965acaf421 100644
--- a/lib/StaticAnalyzer/Core/Checker.cpp
+++ b/lib/StaticAnalyzer/Core/Checker.cpp
@@ -18,8 +18,23 @@ using namespace clang;
using namespace ento;
StringRef CheckerBase::getTagDescription() const {
- // FIXME: We want to return the package + name of the checker here.
- return "A Checker";
+ return getCheckName().getName();
+}
+
+CheckName CheckerBase::getCheckName() const { return Name; }
+
+CheckerProgramPointTag::CheckerProgramPointTag(StringRef CheckerName,
+ StringRef Msg)
+ : SimpleProgramPointTag(CheckerName, Msg) {}
+
+CheckerProgramPointTag::CheckerProgramPointTag(const CheckerBase *Checker,
+ StringRef Msg)
+ : SimpleProgramPointTag(Checker->getCheckName().getName(), Msg) {}
+
+raw_ostream& clang::ento::operator<<(raw_ostream &Out,
+ const CheckerBase &Checker) {
+ Out << Checker.getCheckName().getName();
+ return Out;
}
void Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
diff --git a/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp
index c1ae7e9d812c9..2684cc78be750 100644
--- a/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -58,7 +58,7 @@ void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
assert(D);
unsigned DeclKind = D->getKind();
- CachedDeclCheckers *checkers = 0;
+ CachedDeclCheckers *checkers = nullptr;
CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
if (CCI != CachedDeclCheckersMap.end()) {
checkers = &(CCI->second);
@@ -109,7 +109,7 @@ static void expandGraphWithCheckers(CHECK_CTX checkCtx,
const ExplodedNodeSet *PrevSet = &Src;
for (; I != E; ++I) {
- ExplodedNodeSet *CurrSet = 0;
+ ExplodedNodeSet *CurrSet = nullptr;
if (I+1 == E)
CurrSet = &Dst;
else {
@@ -477,7 +477,7 @@ CheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
// If any checker declares the state infeasible (or if it starts that way),
// bail out.
if (!state)
- return NULL;
+ return nullptr;
state = RegionChangesCheckers[i].CheckFn(state, invalidated,
ExplicitRegions, Regions, Call);
}
@@ -491,7 +491,7 @@ CheckerManager::runCheckersForPointerEscape(ProgramStateRef State,
const CallEvent *Call,
PointerEscapeKind Kind,
RegionAndSymbolInvalidationTraits *ETraits) {
- assert((Call != NULL ||
+ assert((Call != nullptr ||
(Kind != PSK_DirectEscapeOnCall &&
Kind != PSK_IndirectEscapeOnCall)) &&
"Call must not be NULL when escaping on call");
@@ -499,7 +499,7 @@ CheckerManager::runCheckersForPointerEscape(ProgramStateRef State,
// If any checker declares the state infeasible (or if it starts that
// way), bail out.
if (!State)
- return NULL;
+ return nullptr;
State = PointerEscapeCheckers[i](State, Escaped, Call, Kind, ETraits);
}
return State;
@@ -513,7 +513,7 @@ CheckerManager::runCheckersForEvalAssume(ProgramStateRef state,
// If any checker declares the state infeasible (or if it starts that way),
// bail out.
if (!state)
- return NULL;
+ return nullptr;
state = EvalAssumeCheckers[i](state, Cond, Assumption);
}
return state;
diff --git a/lib/StaticAnalyzer/Core/CheckerRegistry.cpp b/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
index 47299030cc450..b64e30b31007a 100644
--- a/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
+++ b/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
@@ -45,7 +45,7 @@ static void collectCheckers(const CheckerRegistry::CheckerInfoList &checkers,
const llvm::StringMap<size_t> &packageSizes,
CheckerOptInfo &opt, CheckerInfoSet &collected) {
// Use a binary search to find the possible start of the package.
- CheckerRegistry::CheckerInfo packageInfo(NULL, opt.getName(), "");
+ CheckerRegistry::CheckerInfo packageInfo(nullptr, opt.getName(), "");
CheckerRegistry::CheckerInfoList::const_iterator e = checkers.end();
CheckerRegistry::CheckerInfoList::const_iterator i =
std::lower_bound(checkers.begin(), e, packageInfo, checkerNameLT);
@@ -84,10 +84,10 @@ void CheckerRegistry::addChecker(InitializationFunction fn, StringRef name,
// Record the presence of the checker in its packages.
StringRef packageName, leafName;
- llvm::tie(packageName, leafName) = name.rsplit(PackageSeparator);
+ std::tie(packageName, leafName) = name.rsplit(PackageSeparator);
while (!leafName.empty()) {
Packages[packageName] += 1;
- llvm::tie(packageName, leafName) = packageName.rsplit(PackageSeparator);
+ std::tie(packageName, leafName) = packageName.rsplit(PackageSeparator);
}
}
@@ -106,6 +106,7 @@ void CheckerRegistry::initializeManager(CheckerManager &checkerMgr,
// Initialize the CheckerManager with all enabled checkers.
for (CheckerInfoSet::iterator
i = enabledCheckers.begin(), e = enabledCheckers.end(); i != e; ++i) {
+ checkerMgr.setCurrentCheckName(CheckName((*i)->FullName));
(*i)->Initialize(checkerMgr);
}
}
diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp
index b09b2c2ddfabd..4623c358a9e2c 100644
--- a/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -12,8 +12,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "CoreEngine"
-
#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
#include "clang/AST/Expr.h"
#include "clang/AST/StmtCXX.h"
@@ -26,6 +24,8 @@
using namespace clang;
using namespace ento;
+#define DEBUG_TYPE "CoreEngine"
+
STATISTIC(NumSteps,
"The # of steps executed.");
STATISTIC(NumReachedMaxSteps,
@@ -43,22 +43,22 @@ namespace {
class DFS : public WorkList {
SmallVector<WorkListUnit,20> Stack;
public:
- virtual bool hasWork() const {
+ bool hasWork() const override {
return !Stack.empty();
}
- virtual void enqueue(const WorkListUnit& U) {
+ void enqueue(const WorkListUnit& U) override {
Stack.push_back(U);
}
- virtual WorkListUnit dequeue() {
+ WorkListUnit dequeue() override {
assert (!Stack.empty());
const WorkListUnit& U = Stack.back();
Stack.pop_back(); // This technically "invalidates" U, but we are fine.
return U;
}
-
- virtual bool visitItemsInWorkList(Visitor &V) {
+
+ bool visitItemsInWorkList(Visitor &V) override {
for (SmallVectorImpl<WorkListUnit>::iterator
I = Stack.begin(), E = Stack.end(); I != E; ++I) {
if (V.visit(*I))
@@ -71,21 +71,21 @@ public:
class BFS : public WorkList {
std::deque<WorkListUnit> Queue;
public:
- virtual bool hasWork() const {
+ bool hasWork() const override {
return !Queue.empty();
}
- virtual void enqueue(const WorkListUnit& U) {
+ void enqueue(const WorkListUnit& U) override {
Queue.push_back(U);
}
- virtual WorkListUnit dequeue() {
+ WorkListUnit dequeue() override {
WorkListUnit U = Queue.front();
Queue.pop_front();
return U;
}
-
- virtual bool visitItemsInWorkList(Visitor &V) {
+
+ bool visitItemsInWorkList(Visitor &V) override {
for (std::deque<WorkListUnit>::iterator
I = Queue.begin(), E = Queue.end(); I != E; ++I) {
if (V.visit(*I))
@@ -109,18 +109,18 @@ namespace {
std::deque<WorkListUnit> Queue;
SmallVector<WorkListUnit,20> Stack;
public:
- virtual bool hasWork() const {
+ bool hasWork() const override {
return !Queue.empty() || !Stack.empty();
}
- virtual void enqueue(const WorkListUnit& U) {
+ void enqueue(const WorkListUnit& U) override {
if (U.getNode()->getLocation().getAs<BlockEntrance>())
Queue.push_front(U);
else
Stack.push_back(U);
}
- virtual WorkListUnit dequeue() {
+ WorkListUnit dequeue() override {
// Process all basic blocks to completion.
if (!Stack.empty()) {
const WorkListUnit& U = Stack.back();
@@ -135,7 +135,7 @@ namespace {
Queue.pop_front();
return U;
}
- virtual bool visitItemsInWorkList(Visitor &V) {
+ bool visitItemsInWorkList(Visitor &V) override {
for (SmallVectorImpl<WorkListUnit>::iterator
I = Stack.begin(), E = Stack.end(); I != E; ++I) {
if (V.visit(*I))
@@ -192,9 +192,9 @@ bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
if (!InitState)
// Generate the root.
- generateNode(StartLoc, SubEng.getInitialState(L), 0);
+ generateNode(StartLoc, SubEng.getInitialState(L), nullptr);
else
- generateNode(StartLoc, InitState, 0);
+ generateNode(StartLoc, InitState, nullptr);
}
// Check if we have a steps limit
@@ -532,11 +532,16 @@ void CoreEngine::enqueueStmtNode(ExplodedNode *N,
return;
}
+ if ((*Block)[Idx].getKind() == CFGElement::NewAllocator) {
+ WList->enqueue(N, Block, Idx+1);
+ return;
+ }
+
// At this point, we know we're processing a normal statement.
CFGStmt CS = (*Block)[Idx].castAs<CFGStmt>();
PostStmt Loc(CS.getStmt(), N->getLocationContext());
- if (Loc == N->getLocation()) {
+ if (Loc == N->getLocation().withTag(nullptr)) {
// Note: 'N' should be a fresh node because otherwise it shouldn't be
// a member of Deferred.
WList->enqueue(N, Block, Idx+1);
@@ -562,7 +567,7 @@ ExplodedNode *CoreEngine::generateCallExitBeginNode(ExplodedNode *N) {
bool isNew;
ExplodedNode *Node = G->getNode(Loc, N->getState(), false, &isNew);
Node->addPredecessor(N, *G);
- return isNew ? Node : 0;
+ return isNew ? Node : nullptr;
}
@@ -611,7 +616,7 @@ ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc,
Frontier.erase(FromN);
if (!IsNew)
- return 0;
+ return nullptr;
if (!MarkAsSink)
Frontier.Add(N);
@@ -635,7 +640,7 @@ ExplodedNode *BranchNodeBuilder::generateNode(ProgramStateRef State,
ExplodedNode *NodePred) {
// If the branch has been marked infeasible we should not generate a node.
if (!isFeasible(branch))
- return NULL;
+ return nullptr;
ProgramPoint Loc = BlockEdge(C.Block, branch ? DstT:DstF,
NodePred->getLocationContext());
@@ -654,7 +659,7 @@ IndirectGotoNodeBuilder::generateNode(const iterator &I,
Succ->addPredecessor(Pred, *Eng.G);
if (!IsNew)
- return 0;
+ return nullptr;
if (!IsSink)
Eng.WList->enqueue(Succ);
@@ -673,7 +678,7 @@ SwitchNodeBuilder::generateCaseStmtNode(const iterator &I,
false, &IsNew);
Succ->addPredecessor(Pred, *Eng.G);
if (!IsNew)
- return 0;
+ return nullptr;
Eng.WList->enqueue(Succ);
return Succ;
@@ -690,8 +695,8 @@ SwitchNodeBuilder::generateDefaultCaseNode(ProgramStateRef St,
// Sanity check for default blocks that are unreachable and not caught
// by earlier stages.
if (!DefaultBlock)
- return NULL;
-
+ return nullptr;
+
bool IsNew;
ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, DefaultBlock,
Pred->getLocationContext()), St,
@@ -699,7 +704,7 @@ SwitchNodeBuilder::generateDefaultCaseNode(ProgramStateRef St,
Succ->addPredecessor(Pred, *Eng.G);
if (!IsNew)
- return 0;
+ return nullptr;
if (!IsSink)
Eng.WList->enqueue(Succ);
diff --git a/lib/StaticAnalyzer/Core/Environment.cpp b/lib/StaticAnalyzer/Core/Environment.cpp
index 7b133f6bf645f..ae5a4cc8b4aad 100644
--- a/lib/StaticAnalyzer/Core/Environment.cpp
+++ b/lib/StaticAnalyzer/Core/Environment.cpp
@@ -54,7 +54,8 @@ static const Stmt *ignoreTransparentExprs(const Stmt *S) {
EnvironmentEntry::EnvironmentEntry(const Stmt *S, const LocationContext *L)
: std::pair<const Stmt *,
const StackFrameContext *>(ignoreTransparentExprs(S),
- L ? L->getCurrentStackFrame() : 0) {}
+ L ? L->getCurrentStackFrame()
+ : nullptr) {}
SVal Environment::lookupExpr(const EnvironmentEntry &E) const {
const SVal* X = ExprBindings.lookup(E);
@@ -123,11 +124,11 @@ class MarkLiveCallback : public SymbolVisitor {
SymbolReaper &SymReaper;
public:
MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {}
- bool VisitSymbol(SymbolRef sym) {
+ bool VisitSymbol(SymbolRef sym) override {
SymReaper.markLive(sym);
return true;
}
- bool VisitMemRegion(const MemRegion *R) {
+ bool VisitMemRegion(const MemRegion *R) override {
SymReaper.markLive(R);
return true;
}
@@ -204,11 +205,12 @@ void Environment::print(raw_ostream &Out, const char *NL,
}
const Stmt *S = En.getStmt();
-
+ assert(S != nullptr && "Expected non-null Stmt");
+
Out << " (" << (const void*) En.getLocationContext() << ','
<< (const void*) S << ") ";
LangOptions LO; // FIXME.
- S->printPretty(Out, 0, PrintingPolicy(LO));
+ S->printPretty(Out, nullptr, PrintingPolicy(LO));
Out << " : " << I.getData();
}
}
diff --git a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
index e9c4a35de6e8d..1c9a282b82987 100644
--- a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
+++ b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
@@ -34,7 +34,7 @@ using namespace ento;
ExplodedNode::Auditor::~Auditor() {}
#ifndef NDEBUG
-static ExplodedNode::Auditor* NodeAuditor = 0;
+static ExplodedNode::Auditor* NodeAuditor = nullptr;
#endif
void ExplodedNode::SetAuditor(ExplodedNode::Auditor* A) {
@@ -90,8 +90,9 @@ bool ExplodedGraph::shouldCollect(const ExplodedNode *node) {
// (7) The LocationContext is the same as the predecessor.
// (8) Expressions that are *not* lvalue expressions.
// (9) The PostStmt isn't for a non-consumed Stmt or Expr.
- // (10) The successor is not a CallExpr StmtPoint (so that we would
- // be able to find it when retrying a call with no inlining).
+ // (10) The successor is neither a CallExpr StmtPoint nor a CallEnter or
+ // PreImplicitCall (so that we would be able to find it when retrying a
+ // call with no inlining).
// FIXME: It may be safe to reclaim PreCall and PostCall nodes as well.
// Conditions 1 and 2.
@@ -153,6 +154,10 @@ bool ExplodedGraph::shouldCollect(const ExplodedNode *node) {
if (CallEvent::isCallStmt(SP->getStmt()))
return false;
+ // Condition 10, continuation.
+ if (SuccLoc.getAs<CallEnter>() || SuccLoc.getAs<PreImplicitCall>())
+ return false;
+
return true;
}
@@ -271,11 +276,11 @@ unsigned ExplodedNode::NodeGroup::size() const {
ExplodedNode * const *ExplodedNode::NodeGroup::begin() const {
if (getFlag())
- return 0;
+ return nullptr;
const GroupStorage &Storage = reinterpret_cast<const GroupStorage &>(P);
if (Storage.isNull())
- return 0;
+ return nullptr;
if (ExplodedNodeVector *V = Storage.dyn_cast<ExplodedNodeVector *>())
return V->begin();
return Storage.getAddrOfPtr1();
@@ -283,11 +288,11 @@ ExplodedNode * const *ExplodedNode::NodeGroup::begin() const {
ExplodedNode * const *ExplodedNode::NodeGroup::end() const {
if (getFlag())
- return 0;
+ return nullptr;
const GroupStorage &Storage = reinterpret_cast<const GroupStorage &>(P);
if (Storage.isNull())
- return 0;
+ return nullptr;
if (ExplodedNodeVector *V = Storage.dyn_cast<ExplodedNodeVector *>())
return V->end();
return Storage.getAddrOfPtr1() + 1;
@@ -299,7 +304,7 @@ ExplodedNode *ExplodedGraph::getNode(const ProgramPoint &L,
bool* IsNew) {
// Profile 'State' to determine if we already have an existing node.
llvm::FoldingSetNodeID profile;
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
NodeTy::Profile(profile, L, State, IsSink);
NodeTy* V = Nodes.FindNodeOrInsertPos(profile, InsertPos);
@@ -337,7 +342,7 @@ ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
InterExplodedGraphMap *InverseMap) const{
if (Nodes.empty())
- return 0;
+ return nullptr;
typedef llvm::DenseSet<const ExplodedNode*> Pass1Ty;
Pass1Ty Pass1;
@@ -380,7 +385,7 @@ ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
// We didn't hit a root? Return with a null pointer for the new graph.
if (WL2.empty())
- return 0;
+ return nullptr;
// Create an empty graph.
ExplodedGraph* G = MakeEmptyGraph();
@@ -395,7 +400,8 @@ ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
// Create the corresponding node in the new graph and record the mapping
// from the old node to the new node.
- ExplodedNode *NewN = G->getNode(N->getLocation(), N->State, N->isSink(), 0);
+ ExplodedNode *NewN = G->getNode(N->getLocation(), N->State, N->isSink(),
+ nullptr);
Pass2[N] = NewN;
// Also record the reverse mapping from the new node to the old node.
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 9907d0cbf9b85..4e4095c5e0d84 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -13,8 +13,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "ExprEngine"
-
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "PrettyStackTraceLocationContext.h"
#include "clang/AST/CharUnits.h"
@@ -40,6 +38,8 @@ using namespace clang;
using namespace ento;
using llvm::APSInt;
+#define DEBUG_TYPE "ExprEngine"
+
STATISTIC(NumRemoveDeadBindings,
"The # of times RemoveDeadBindings is called");
STATISTIC(NumMaxBlockCountReached,
@@ -55,6 +55,8 @@ STATISTIC(NumTimesRetriedWithoutInlining,
// Engine construction and deletion.
//===----------------------------------------------------------------------===//
+static const char* TagProviderName = "ExprEngine";
+
ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled,
SetOfConstDecls *VisitedCalleesIn,
FunctionSummariesTy *FS,
@@ -68,7 +70,7 @@ ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled,
this),
SymMgr(StateMgr.getSymbolManager()),
svalBuilder(StateMgr.getSValBuilder()),
- currStmtIdx(0), currBldrCtx(0),
+ currStmtIdx(0), currBldrCtx(nullptr),
ObjCNoRet(mgr.getASTContext()),
ObjCGCEnabled(gcEnabled), BR(mgr, *this),
VisitedCallees(VisitedCalleesIn),
@@ -118,7 +120,7 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {
SVal V = state->getSVal(loc::MemRegionVal(R));
SVal Constraint_untested = evalBinOp(state, BO_GT, V,
svalBuilder.makeZeroVal(T),
- getContext().IntTy);
+ svalBuilder.getConditionType());
Optional<DefinedOrUnknownSVal> Constraint =
Constraint_untested.getAs<DefinedOrUnknownSVal>();
@@ -153,7 +155,7 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {
// top-level function. This is our starting assumption for
// analyzing an "open" program.
const StackFrameContext *SFC = InitLoc->getCurrentStackFrame();
- if (SFC->getParent() == 0) {
+ if (SFC->getParent() == nullptr) {
loc::MemRegionVal L = svalBuilder.getCXXThis(MD, SFC);
SVal V = state->getSVal(L);
if (Optional<Loc> LV = V.getAs<Loc>()) {
@@ -209,7 +211,7 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State,
// Create a temporary object region for the inner expression (which may have
// a more derived type) and bind the value into it.
- const TypedValueRegion *TR = NULL;
+ const TypedValueRegion *TR = nullptr;
if (const MaterializeTemporaryExpr *MT =
dyn_cast<MaterializeTemporaryExpr>(Result)) {
StorageDuration SD = MT->getStorageDuration();
@@ -286,6 +288,10 @@ void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred,
case CFGElement::Initializer:
ProcessInitializer(E.castAs<CFGInitializer>().getInitializer(), Pred);
return;
+ case CFGElement::NewAllocator:
+ ProcessNewAllocator(E.castAs<CFGNewAllocator>().getAllocatorExpr(),
+ Pred);
+ return;
case CFGElement::AutomaticObjectDtor:
case CFGElement::DeleteDtor:
case CFGElement::BaseDtor:
@@ -329,7 +335,7 @@ void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
const Stmt *DiagnosticStmt,
ProgramPoint::Kind K) {
assert((K == ProgramPoint::PreStmtPurgeDeadSymbolsKind ||
- ReferenceStmt == 0 || isa<ReturnStmt>(ReferenceStmt))
+ ReferenceStmt == nullptr || isa<ReturnStmt>(ReferenceStmt))
&& "PostStmt is not generally supported by the SymbolReaper yet");
assert(LC && "Must pass the current (or expiring) LocationContext");
@@ -350,7 +356,7 @@ void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
LC = LC->getParent();
}
- const StackFrameContext *SFC = LC ? LC->getCurrentStackFrame() : 0;
+ const StackFrameContext *SFC = LC ? LC->getCurrentStackFrame() : nullptr;
SymbolReaper SymReaper(SFC, ReferenceStmt, SymMgr, getStoreManager());
getCheckerManager().runCheckersForLiveSymbols(CleanedState, SymReaper);
@@ -362,7 +368,7 @@ void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
// Process any special transfer function for dead symbols.
// A tag to track convenience transitions, which can be removed at cleanup.
- static SimpleProgramPointTag cleanupTag("ExprEngine : Clean Node");
+ static SimpleProgramPointTag cleanupTag(TagProviderName, "Clean Node");
if (!SymReaper.hasDeadSymbols()) {
// Generate a CleanedNode that has the environment and store cleaned
// up. Since no symbols are dead, we can optimize and not clean out
@@ -547,6 +553,25 @@ void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
}
+void ExprEngine::ProcessNewAllocator(const CXXNewExpr *NE,
+ ExplodedNode *Pred) {
+ ExplodedNodeSet Dst;
+ AnalysisManager &AMgr = getAnalysisManager();
+ AnalyzerOptions &Opts = AMgr.options;
+ // TODO: We're not evaluating allocators for all cases just yet as
+ // we're not handling the return value correctly, which causes false
+ // positives when the alpha.cplusplus.NewDeleteLeaks check is on.
+ if (Opts.mayInlineCXXAllocator())
+ VisitCXXNewAllocatorCall(NE, Pred, Dst);
+ else {
+ NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
+ const LocationContext *LCtx = Pred->getLocationContext();
+ PostImplicitCall PP(NE->getOperatorNew(), NE->getLocStart(), LCtx);
+ Bldr.generateNode(PP, Pred->getState(), Pred);
+ }
+ Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
+}
+
void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
@@ -598,7 +623,6 @@ void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor,
void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D,
ExplodedNode *Pred, ExplodedNodeSet &Dst) {
const LocationContext *LCtx = Pred->getLocationContext();
- ProgramStateRef State = Pred->getState();
const CXXDestructorDecl *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl());
Loc ThisPtr = getSValBuilder().getCXXThis(CurDtor,
@@ -640,7 +664,7 @@ void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D,
// FIXME: Inlining of temporary destructors is not supported yet anyway, so we
// just put a NULL region for now. This will need to be changed later.
- VisitCXXDestructor(varType, NULL, D.getBindTemporaryExpr(),
+ VisitCXXDestructor(varType, nullptr, D.getBindTemporaryExpr(),
/*IsBase=*/ false, Pred, Dst);
}
@@ -664,8 +688,6 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::MSPropertyRefExprClass:
case Stmt::CXXUnresolvedConstructExprClass:
case Stmt::DependentScopeDeclRefExprClass:
- case Stmt::UnaryTypeTraitExprClass:
- case Stmt::BinaryTypeTraitExprClass:
case Stmt::TypeTraitExprClass:
case Stmt::ArrayTypeTraitExprClass:
case Stmt::ExpressionTraitExprClass:
@@ -677,6 +699,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::FunctionParmPackExprClass:
case Stmt::SEHTryStmtClass:
case Stmt::SEHExceptStmtClass:
+ case Stmt::SEHLeaveStmtClass:
case Stmt::LambdaExprClass:
case Stmt::SEHFinallyStmtClass: {
const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
@@ -709,6 +732,20 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Expr::MSDependentExistsStmtClass:
case Stmt::CapturedStmtClass:
case Stmt::OMPParallelDirectiveClass:
+ case Stmt::OMPSimdDirectiveClass:
+ case Stmt::OMPForDirectiveClass:
+ case Stmt::OMPSectionsDirectiveClass:
+ case Stmt::OMPSectionDirectiveClass:
+ case Stmt::OMPSingleDirectiveClass:
+ case Stmt::OMPMasterDirectiveClass:
+ case Stmt::OMPCriticalDirectiveClass:
+ case Stmt::OMPParallelForDirectiveClass:
+ case Stmt::OMPParallelSectionsDirectiveClass:
+ case Stmt::OMPTaskDirectiveClass:
+ case Stmt::OMPTaskyieldDirectiveClass:
+ case Stmt::OMPBarrierDirectiveClass:
+ case Stmt::OMPTaskwaitDirectiveClass:
+ case Stmt::OMPFlushDirectiveClass:
llvm_unreachable("Stmt should not be in analyzer evaluation loop");
case Stmt::ObjCSubscriptRefExprClass:
@@ -848,7 +885,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
it != et; ++it) {
ExplodedNode *N = *it;
const LocationContext *LCtx = N->getLocationContext();
- SVal result = svalBuilder.conjureSymbolVal(0, Ex, LCtx, resultType,
+ SVal result = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
+ resultType,
currBldrCtx->blockCount());
ProgramStateRef state = N->getState()->BindExpr(Ex, LCtx, result);
Bldr2.generateNode(S, N, state);
@@ -928,7 +966,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
ProgramStateRef NewState =
createTemporaryRegionIfNeeded(State, LCtx, OCE->getArg(0));
if (NewState != State) {
- Pred = Bldr.generateNode(OCE, Pred, NewState, /*Tag=*/0,
+ Pred = Bldr.generateNode(OCE, Pred, NewState, /*Tag=*/nullptr,
ProgramPoint::PreStmtKind);
// Did we cache out?
if (!Pred)
@@ -1187,14 +1225,14 @@ bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
const StackFrameContext *CalleeSF = CalleeLC->getCurrentStackFrame();
const StackFrameContext *CallerSF = CalleeSF->getParent()->getCurrentStackFrame();
assert(CalleeSF && CallerSF);
- ExplodedNode *BeforeProcessingCall = 0;
+ ExplodedNode *BeforeProcessingCall = nullptr;
const Stmt *CE = CalleeSF->getCallSite();
// Find the first node before we started processing the call expression.
while (N) {
ProgramPoint L = N->getLocation();
BeforeProcessingCall = N;
- N = N->pred_empty() ? NULL : *(N->pred_begin());
+ N = N->pred_empty() ? nullptr : *(N->pred_begin());
// Skip the nodes corresponding to the inlined code.
if (L.getLocationContext()->getCurrentStackFrame() != CallerSF)
@@ -1253,7 +1291,7 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
// FIXME: Refactor this into a checker.
if (nodeBuilder.getContext().blockCount() >= AMgr.options.maxBlockVisitOnPath) {
- static SimpleProgramPointTag tag("ExprEngine : Block count exceeded");
+ static SimpleProgramPointTag tag(TagProviderName, "Block count exceeded");
const ExplodedNode *Sink =
nodeBuilder.generateSink(Pred->getState(), Pred, &tag);
@@ -1329,6 +1367,33 @@ static SVal RecoverCastedSymbol(ProgramStateManager& StateMgr,
return state->getSVal(Ex, LCtx);
}
+#ifndef NDEBUG
+static const Stmt *getRightmostLeaf(const Stmt *Condition) {
+ while (Condition) {
+ const BinaryOperator *BO = dyn_cast<BinaryOperator>(Condition);
+ if (!BO || !BO->isLogicalOp()) {
+ return Condition;
+ }
+ Condition = BO->getRHS()->IgnoreParens();
+ }
+ return nullptr;
+}
+#endif
+
+// Returns the condition the branch at the end of 'B' depends on and whose value
+// has been evaluated within 'B'.
+// In most cases, the terminator condition of 'B' will be evaluated fully in
+// the last statement of 'B'; in those cases, the resolved condition is the
+// given 'Condition'.
+// If the condition of the branch is a logical binary operator tree, the CFG is
+// optimized: in that case, we know that the expression formed by all but the
+// rightmost leaf of the logical binary operator tree must be true, and thus
+// the branch condition is at this point equivalent to the truth value of that
+// rightmost leaf; the CFG block thus only evaluates this rightmost leaf
+// expression in its final statement. As the full condition in that case was
+// not evaluated, and is thus not in the SVal cache, we need to use that leaf
+// expression to evaluate the truth value of the condition in the current state
+// space.
static const Stmt *ResolveCondition(const Stmt *Condition,
const CFGBlock *B) {
if (const Expr *Ex = dyn_cast<Expr>(Condition))
@@ -1338,6 +1403,12 @@ static const Stmt *ResolveCondition(const Stmt *Condition,
if (!BO || !BO->isLogicalOp())
return Condition;
+ // FIXME: This is a workaround until we handle temporary destructor branches
+ // correctly; currently, temporary destructor branches lead to blocks that
+ // only have a terminator (and no statements). These blocks violate the
+ // invariant this function assumes.
+ if (B->getTerminator().isTemporaryDtorsBranch()) return Condition;
+
// For logical operations, we still have the case where some branches
// use the traditional "merge" approach and others sink the branch
// directly into the basic blocks representing the logical operation.
@@ -1352,18 +1423,9 @@ static const Stmt *ResolveCondition(const Stmt *Condition,
Optional<CFGStmt> CS = Elem.getAs<CFGStmt>();
if (!CS)
continue;
- if (CS->getStmt() != Condition)
- break;
- return Condition;
- }
-
- assert(I != E);
-
- while (Condition) {
- BO = dyn_cast<BinaryOperator>(Condition);
- if (!BO || !BO->isLogicalOp())
- return Condition;
- Condition = BO->getRHS()->IgnoreParens();
+ const Stmt *LastStmt = CS->getStmt();
+ assert(LastStmt == Condition || LastStmt == getRightmostLeaf(Condition));
+ return LastStmt;
}
llvm_unreachable("could not resolve condition");
}
@@ -1443,7 +1505,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
DefinedSVal V = X.castAs<DefinedSVal>();
ProgramStateRef StTrue, StFalse;
- tie(StTrue, StFalse) = PrevState->assume(V);
+ std::tie(StTrue, StFalse) = PrevState->assume(V);
// Process the true branch.
if (builder.isFeasible(true)) {
@@ -1461,7 +1523,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
builder.markInfeasible(false);
}
}
- currBldrCtx = 0;
+ currBldrCtx = nullptr;
}
/// The GDM component containing the set of global variables which have been
@@ -1490,7 +1552,7 @@ void ExprEngine::processStaticInitializer(const DeclStmt *DS,
builder.generateNode(state, initHasRun, Pred);
builder.markInfeasible(!initHasRun);
- currBldrCtx = 0;
+ currBldrCtx = nullptr;
}
/// processIndirectGoto - Called by CoreEngine. Used to generate successor
@@ -1631,7 +1693,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
}
else {
defaultIsFeasible = false;
- DefaultSt = NULL;
+ DefaultSt = nullptr;
}
}
@@ -1692,7 +1754,7 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
V = UnknownVal();
}
- Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), 0,
+ Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
ProgramPoint::PostLValueKind);
return;
}
@@ -1704,7 +1766,7 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
}
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
SVal V = svalBuilder.getFunctionPointer(FD);
- Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), 0,
+ Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
ProgramPoint::PostLValueKind);
return;
}
@@ -1715,7 +1777,7 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
SVal V = svalBuilder.conjureSymbolVal(Ex, LCtx, getContext().VoidPtrTy,
currBldrCtx->blockCount());
state = state->assume(V.castAs<DefinedOrUnknownSVal>(), true);
- Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), 0,
+ Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
ProgramPoint::PostLValueKind);
return;
}
@@ -1745,82 +1807,91 @@ void ExprEngine::VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *A,
state->getSVal(Idx, LCtx),
state->getSVal(Base, LCtx));
assert(A->isGLValue());
- Bldr.generateNode(A, *it, state->BindExpr(A, LCtx, V), 0,
+ Bldr.generateNode(A, *it, state->BindExpr(A, LCtx, V), nullptr,
ProgramPoint::PostLValueKind);
}
}
/// VisitMemberExpr - Transfer function for member expressions.
void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
- ExplodedNodeSet &TopDst) {
+ ExplodedNodeSet &Dst) {
- StmtNodeBuilder Bldr(Pred, TopDst, *currBldrCtx);
- ExplodedNodeSet Dst;
+ // FIXME: Prechecks eventually go in ::Visit().
+ ExplodedNodeSet CheckedSet;
+ getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, M, *this);
+
+ ExplodedNodeSet EvalSet;
ValueDecl *Member = M->getMemberDecl();
// Handle static member variables and enum constants accessed via
// member syntax.
if (isa<VarDecl>(Member) || isa<EnumConstantDecl>(Member)) {
- Bldr.takeNodes(Pred);
- VisitCommonDeclRefExpr(M, Member, Pred, Dst);
- Bldr.addNodes(Dst);
- return;
- }
-
- ProgramStateRef state = Pred->getState();
- const LocationContext *LCtx = Pred->getLocationContext();
- Expr *BaseExpr = M->getBase();
+ ExplodedNodeSet Dst;
+ for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
+ I != E; ++I) {
+ VisitCommonDeclRefExpr(M, Member, Pred, EvalSet);
+ }
+ } else {
+ StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx);
+ ExplodedNodeSet Tmp;
- // Handle C++ method calls.
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member)) {
- if (MD->isInstance())
- state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr);
+ for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
+ I != E; ++I) {
+ ProgramStateRef state = (*I)->getState();
+ const LocationContext *LCtx = (*I)->getLocationContext();
+ Expr *BaseExpr = M->getBase();
- SVal MDVal = svalBuilder.getFunctionPointer(MD);
- state = state->BindExpr(M, LCtx, MDVal);
+ // Handle C++ method calls.
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member)) {
+ if (MD->isInstance())
+ state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr);
- Bldr.generateNode(M, Pred, state);
- return;
- }
+ SVal MDVal = svalBuilder.getFunctionPointer(MD);
+ state = state->BindExpr(M, LCtx, MDVal);
- // Handle regular struct fields / member variables.
- state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr);
- SVal baseExprVal = state->getSVal(BaseExpr, LCtx);
-
- FieldDecl *field = cast<FieldDecl>(Member);
- SVal L = state->getLValue(field, baseExprVal);
-
- if (M->isGLValue() || M->getType()->isArrayType()) {
-
- // We special case rvalue of array type because the analyzer cannot reason
- // about it, since we expect all regions to be wrapped in Locs. So we will
- // treat these as lvalues assuming that they will decay to pointers as soon
- // as they are used.
- if (!M->isGLValue()) {
- assert(M->getType()->isArrayType());
- const ImplicitCastExpr *PE =
- dyn_cast<ImplicitCastExpr>(Pred->getParentMap().getParent(M));
- if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {
- assert(false &&
- "We assume that array is always wrapped in ArrayToPointerDecay");
- L = UnknownVal();
+ Bldr.generateNode(M, *I, state);
+ continue;
}
- }
- if (field->getType()->isReferenceType()) {
- if (const MemRegion *R = L.getAsRegion())
- L = state->getSVal(R);
- else
- L = UnknownVal();
- }
+ // Handle regular struct fields / member variables.
+ state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr);
+ SVal baseExprVal = state->getSVal(BaseExpr, LCtx);
+
+ FieldDecl *field = cast<FieldDecl>(Member);
+ SVal L = state->getLValue(field, baseExprVal);
+
+ if (M->isGLValue() || M->getType()->isArrayType()) {
+ // We special-case rvalues of array type because the analyzer cannot
+ // reason about them, since we expect all regions to be wrapped in Locs.
+ // We instead treat these as lvalues and assume that they will decay to
+ // pointers as soon as they are used.
+ if (!M->isGLValue()) {
+ assert(M->getType()->isArrayType());
+ const ImplicitCastExpr *PE =
+ dyn_cast<ImplicitCastExpr>((*I)->getParentMap().getParent(M));
+ if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {
+ llvm_unreachable("should always be wrapped in ArrayToPointerDecay");
+ }
+ }
- Bldr.generateNode(M, Pred, state->BindExpr(M, LCtx, L), 0,
- ProgramPoint::PostLValueKind);
- } else {
- Bldr.takeNodes(Pred);
- evalLoad(Dst, M, M, Pred, state, L);
- Bldr.addNodes(Dst);
+ if (field->getType()->isReferenceType()) {
+ if (const MemRegion *R = L.getAsRegion())
+ L = state->getSVal(R);
+ else
+ L = UnknownVal();
+ }
+
+ Bldr.generateNode(M, *I, state->BindExpr(M, LCtx, L), nullptr,
+ ProgramPoint::PostLValueKind);
+ } else {
+ Bldr.takeNodes(*I);
+ evalLoad(Tmp, M, M, *I, state, L);
+ Bldr.addNodes(Tmp);
+ }
+ }
}
+
+ getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, M, *this);
}
namespace {
@@ -1830,7 +1901,7 @@ public:
CollectReachableSymbolsCallback(ProgramStateRef State) {}
const InvalidatedSymbols &getSymbols() const { return Symbols; }
- bool VisitSymbol(SymbolRef Sym) {
+ bool VisitSymbol(SymbolRef Sym) override {
Symbols.insert(Sym);
return true;
}
@@ -1876,9 +1947,9 @@ ProgramStateRef ExprEngine::processPointerEscapedOnBind(ProgramStateRef State,
const InvalidatedSymbols &EscapedSymbols = Scanner.getSymbols();
State = getCheckerManager().runCheckersForPointerEscape(State,
EscapedSymbols,
- /*CallEvent*/ 0,
+ /*CallEvent*/ nullptr,
PSK_EscapeOnBind,
- 0);
+ nullptr);
return State;
}
@@ -1897,7 +1968,7 @@ ExprEngine::notifyCheckersOfPointerEscape(ProgramStateRef State,
if (!Call)
return getCheckerManager().runCheckersForPointerEscape(State,
*Invalidated,
- 0,
+ nullptr,
PSK_EscapeOther,
&ITraits);
@@ -1954,7 +2025,8 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
// If the location is not a 'Loc', it will already be handled by
// the checkers. There is nothing left to do.
if (!location.getAs<Loc>()) {
- const ProgramPoint L = PostStore(StoreE, LC, /*Loc*/0, /*tag*/0);
+ const ProgramPoint L = PostStore(StoreE, LC, /*Loc*/nullptr,
+ /*tag*/nullptr);
ProgramStateRef state = Pred->getState();
state = processPointerEscapedOnBind(state, location, Val);
Bldr.generateNode(L, state, Pred);
@@ -1975,13 +2047,13 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
state = state->bindLoc(location.castAs<Loc>(),
Val, /* notifyChanges = */ !atDeclInit);
- const MemRegion *LocReg = 0;
+ const MemRegion *LocReg = nullptr;
if (Optional<loc::MemRegionVal> LocRegVal =
location.getAs<loc::MemRegionVal>()) {
LocReg = LocRegVal->getRegion();
}
-
- const ProgramPoint L = PostStore(StoreE, LC, LocReg, 0);
+
+ const ProgramPoint L = PostStore(StoreE, LC, LocReg, nullptr);
Bldr.generateNode(L, state, PredI);
}
}
@@ -2037,7 +2109,7 @@ void ExprEngine::evalLoad(ExplodedNodeSet &Dst,
QualType ValTy = TR->getValueType();
if (const ReferenceType *RT = ValTy->getAs<ReferenceType>()) {
static SimpleProgramPointTag
- loadReferenceTag("ExprEngine : Load Reference");
+ loadReferenceTag(TagProviderName, "Load Reference");
ExplodedNodeSet Tmp;
evalLoadCommon(Tmp, NodeEx, BoundEx, Pred, state,
location, &loadReferenceTag,
@@ -2120,7 +2192,7 @@ void ExprEngine::evalLocation(ExplodedNodeSet &Dst,
// instead "int *p" is noted as
// "Variable 'p' initialized to a null pointer value"
- static SimpleProgramPointTag tag("ExprEngine: Location");
+ static SimpleProgramPointTag tag(TagProviderName, "Location");
Bldr.generateNode(NodeEx, Pred, state, &tag);
}
ExplodedNodeSet Tmp;
@@ -2132,8 +2204,10 @@ void ExprEngine::evalLocation(ExplodedNodeSet &Dst,
std::pair<const ProgramPointTag *, const ProgramPointTag*>
ExprEngine::geteagerlyAssumeBinOpBifurcationTags() {
static SimpleProgramPointTag
- eagerlyAssumeBinOpBifurcationTrue("ExprEngine : Eagerly Assume True"),
- eagerlyAssumeBinOpBifurcationFalse("ExprEngine : Eagerly Assume False");
+ eagerlyAssumeBinOpBifurcationTrue(TagProviderName,
+ "Eagerly Assume True"),
+ eagerlyAssumeBinOpBifurcationFalse(TagProviderName,
+ "Eagerly Assume False");
return std::make_pair(&eagerlyAssumeBinOpBifurcationTrue,
&eagerlyAssumeBinOpBifurcationFalse);
}
@@ -2161,7 +2235,7 @@ void ExprEngine::evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst,
geteagerlyAssumeBinOpBifurcationTags();
ProgramStateRef StateTrue, StateFalse;
- tie(StateTrue, StateFalse) = state->assume(*SEV);
+ std::tie(StateTrue, StateFalse) = state->assume(*SEV);
// First assume that the condition is true.
if (StateTrue) {
@@ -2192,9 +2266,8 @@ void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,
ProgramStateRef state = Pred->getState();
- for (GCCAsmStmt::const_outputs_iterator OI = A->begin_outputs(),
- OE = A->end_outputs(); OI != OE; ++OI) {
- SVal X = state->getSVal(*OI, Pred->getLocationContext());
+ for (const Expr *O : A->outputs()) {
+ SVal X = state->getSVal(O, Pred->getLocationContext());
assert (!X.getAs<NonLoc>()); // Should be an Lval, or unknown, undef.
if (Optional<Loc> LV = X.getAs<Loc>())
@@ -2368,11 +2441,12 @@ struct DOTGraphTraits<ExplodedNode*> :
if (const CaseStmt *C = dyn_cast<CaseStmt>(Label)) {
Out << "\\lcase ";
LangOptions LO; // FIXME.
- C->getLHS()->printPretty(Out, 0, PrintingPolicy(LO));
+ if (C->getLHS())
+ C->getLHS()->printPretty(Out, nullptr, PrintingPolicy(LO));
if (const Stmt *RHS = C->getRHS()) {
Out << " .. ";
- RHS->printPretty(Out, 0, PrintingPolicy(LO));
+ RHS->printPretty(Out, nullptr, PrintingPolicy(LO));
}
Out << ":";
@@ -2411,10 +2485,11 @@ struct DOTGraphTraits<ExplodedNode*> :
default: {
const Stmt *S = Loc.castAs<StmtPoint>().getStmt();
+ assert(S != nullptr && "Expecting non-null Stmt");
Out << S->getStmtClassName() << ' ' << (const void*) S << ' ';
LangOptions LO; // FIXME.
- S->printPretty(Out, 0, PrintingPolicy(LO));
+ S->printPretty(Out, nullptr, PrintingPolicy(LO));
printLocation(Out, S->getLocStart());
if (Loc.getAs<PreStmt>())
@@ -2452,7 +2527,7 @@ struct DOTGraphTraits<ExplodedNode*> :
}
ProgramStateRef state = N->getState();
- Out << "\\|StateID: " << (const void*) state.getPtr()
+ Out << "\\|StateID: " << (const void*) state.get()
<< " NodeID: " << (const void*) N << "\\|";
state->printDOT(Out);
@@ -2504,8 +2579,8 @@ void ExprEngine::ViewGraph(bool trim) {
llvm::ViewGraph(*G.roots_begin(), "ExprEngine");
- GraphPrintCheckerState = NULL;
- GraphPrintSourceManager = NULL;
+ GraphPrintCheckerState = nullptr;
+ GraphPrintSourceManager = nullptr;
}
#endif
}
@@ -2515,14 +2590,14 @@ void ExprEngine::ViewGraph(ArrayRef<const ExplodedNode*> Nodes) {
GraphPrintCheckerState = this;
GraphPrintSourceManager = &getContext().getSourceManager();
- OwningPtr<ExplodedGraph> TrimmedG(G.trim(Nodes));
+ std::unique_ptr<ExplodedGraph> TrimmedG(G.trim(Nodes));
if (!TrimmedG.get())
llvm::errs() << "warning: Trimmed ExplodedGraph is empty.\n";
else
llvm::ViewGraph(*TrimmedG->roots_begin(), "TrimmedExprEngine");
- GraphPrintCheckerState = NULL;
- GraphPrintSourceManager = NULL;
+ GraphPrintCheckerState = nullptr;
+ GraphPrintSourceManager = nullptr;
#endif
}
diff --git a/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 983fda00a2ffc..ffda52709dc2f 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -47,7 +47,8 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// FIXME: Handle structs.
if (RightV.isUnknown()) {
unsigned Count = currBldrCtx->blockCount();
- RightV = svalBuilder.conjureSymbolVal(0, B->getRHS(), LCtx, Count);
+ RightV = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx,
+ Count);
}
// Simulate the effects of a "store": bind the value of the RHS
// to the L-Value represented by the LHS.
@@ -81,6 +82,12 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
}
}
+ // Although we don't yet model pointers-to-members, we do need to make
+ // sure that the members of temporaries have a valid 'this' pointer for
+ // other checks.
+ if (B->getOpcode() == BO_PtrMemD)
+ state = createTemporaryRegionIfNeeded(state, LCtx, LHS);
+
// Process non-assignments except commas or short-circuited
// logical expressions (LAnd and LOr).
SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType());
@@ -151,7 +158,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// The symbolic value is actually for the type of the left-hand side
// expression, not the computation type, as this is the value the
// LValue on the LHS will bind to.
- LHSVal = svalBuilder.conjureSymbolVal(0, B->getRHS(), LCtx, LTy,
+ LHSVal = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx, LTy,
currBldrCtx->blockCount());
// However, we need to convert the symbol to the computation type.
Result = svalBuilder.evalCast(LHSVal, CTy, LTy);
@@ -211,8 +218,8 @@ void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
Bldr.generateNode(BE, Pred,
State->BindExpr(BE, Pred->getLocationContext(), V),
- 0, ProgramPoint::PostLValueKind);
-
+ nullptr, ProgramPoint::PostLValueKind);
+
// FIXME: Move all post/pre visits to ::Visit().
getCheckerManager().runCheckersForPostStmt(Dst, Tmp, BE, *this);
}
@@ -286,6 +293,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
case CK_Dependent:
case CK_ArrayToPointerDecay:
case CK_BitCast:
+ case CK_AddressSpaceConversion:
case CK_IntegralCast:
case CK_NullToPointer:
case CK_IntegralToPointer:
@@ -360,7 +368,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
// If we don't know if the cast succeeded, conjure a new symbol.
if (val.isUnknown()) {
DefinedOrUnknownSVal NewSym =
- svalBuilder.conjureSymbolVal(0, CastE, LCtx, resultType,
+ svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType,
currBldrCtx->blockCount());
state = state->BindExpr(CastE, LCtx, NewSym);
} else
@@ -388,7 +396,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
QualType resultType = CastE->getType();
if (CastE->isGLValue())
resultType = getContext().getPointerType(resultType);
- SVal result = svalBuilder.conjureSymbolVal(0, CastE, LCtx,
+ SVal result = svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx,
resultType,
currBldrCtx->blockCount());
state = state->BindExpr(CastE, LCtx, result);
@@ -486,7 +494,7 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
Ty = getContext().getPointerType(Ty);
}
- InitVal = svalBuilder.conjureSymbolVal(0, InitEx, LC, Ty,
+ InitVal = svalBuilder.conjureSymbolVal(nullptr, InitEx, LC, Ty,
currBldrCtx->blockCount());
}
@@ -554,7 +562,7 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
} else {
DefinedOrUnknownSVal DefinedRHS = RHSVal.castAs<DefinedOrUnknownSVal>();
ProgramStateRef StTrue, StFalse;
- llvm::tie(StTrue, StFalse) = N->getState()->assume(DefinedRHS);
+ std::tie(StTrue, StFalse) = N->getState()->assume(DefinedRHS);
if (StTrue) {
if (StFalse) {
// We can't constrain the value to 0 or 1.
@@ -633,7 +641,7 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex,
StmtNodeBuilder B(Pred, Dst, *currBldrCtx);
ProgramStateRef state = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
- const CFGBlock *SrcBlock = 0;
+ const CFGBlock *SrcBlock = nullptr;
// Find the predecessor block.
ProgramStateRef SrcState = state;
@@ -678,7 +686,8 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex,
}
if (!hasValue)
- V = svalBuilder.conjureSymbolVal(0, Ex, LCtx, currBldrCtx->blockCount());
+ V = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
+ currBldrCtx->blockCount());
// Generate a new node with the binding from the appropriate path.
B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V, true));
@@ -707,34 +716,43 @@ void ExprEngine::
VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
- StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
+ // FIXME: Prechecks eventually go in ::Visit().
+ ExplodedNodeSet CheckedSet;
+ getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, Ex, *this);
+
+ ExplodedNodeSet EvalSet;
+ StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx);
QualType T = Ex->getTypeOfArgument();
-
- if (Ex->getKind() == UETT_SizeOf) {
- if (!T->isIncompleteType() && !T->isConstantSizeType()) {
- assert(T->isVariableArrayType() && "Unknown non-constant-sized type.");
-
- // FIXME: Add support for VLA type arguments and VLA expressions.
- // When that happens, we should probably refactor VLASizeChecker's code.
- return;
- }
- else if (T->getAs<ObjCObjectType>()) {
- // Some code tries to take the sizeof an ObjCObjectType, relying that
- // the compiler has laid out its representation. Just report Unknown
- // for these.
- return;
+
+ for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
+ I != E; ++I) {
+ if (Ex->getKind() == UETT_SizeOf) {
+ if (!T->isIncompleteType() && !T->isConstantSizeType()) {
+ assert(T->isVariableArrayType() && "Unknown non-constant-sized type.");
+
+ // FIXME: Add support for VLA type arguments and VLA expressions.
+ // When that happens, we should probably refactor VLASizeChecker's code.
+ continue;
+ } else if (T->getAs<ObjCObjectType>()) {
+ // Some code tries to take the sizeof an ObjCObjectType, relying that
+ // the compiler has laid out its representation. Just report Unknown
+ // for these.
+ continue;
+ }
}
+
+ APSInt Value = Ex->EvaluateKnownConstInt(getContext());
+ CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue());
+
+ ProgramStateRef state = (*I)->getState();
+ state = state->BindExpr(Ex, (*I)->getLocationContext(),
+ svalBuilder.makeIntVal(amt.getQuantity(),
+ Ex->getType()));
+ Bldr.generateNode(Ex, *I, state);
}
-
- APSInt Value = Ex->EvaluateKnownConstInt(getContext());
- CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue());
-
- ProgramStateRef state = Pred->getState();
- state = state->BindExpr(Ex, Pred->getLocationContext(),
- svalBuilder.makeIntVal(amt.getQuantity(),
- Ex->getType()));
- Bldr.generateNode(Ex, Pred, state);
+
+ getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, Ex, *this);
}
void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
@@ -919,7 +937,8 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
// Conjure a new symbol if necessary to recover precision.
if (Result.isUnknown()){
DefinedOrUnknownSVal SymVal =
- svalBuilder.conjureSymbolVal(0, Ex, LCtx, currBldrCtx->blockCount());
+ svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
+ currBldrCtx->blockCount());
Result = SymVal;
// If the value is a location, ++/-- should always preserve
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index eba4f94d80e66..2a766218aaeb1 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -91,12 +91,6 @@ void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
/// If the type is not an array type at all, the original value is returned.
static SVal makeZeroElementRegion(ProgramStateRef State, SVal LValue,
QualType &Ty) {
- // FIXME: This check is just a temporary workaround, because
- // ProcessTemporaryDtor sends us NULL regions. It will not be necessary once
- // we can properly process temporary destructors.
- if (!LValue.getAsRegion())
- return LValue;
-
SValBuilder &SVB = State->getStateManager().getSValBuilder();
ASTContext &Ctx = SVB.getContext();
@@ -108,13 +102,85 @@ static SVal makeZeroElementRegion(ProgramStateRef State, SVal LValue,
return LValue;
}
+
+static const MemRegion *getRegionForConstructedObject(
+ const CXXConstructExpr *CE, ExplodedNode *Pred, ExprEngine &Eng,
+ unsigned int CurrStmtIdx) {
+ const LocationContext *LCtx = Pred->getLocationContext();
+ ProgramStateRef State = Pred->getState();
+ const NodeBuilderContext &CurrBldrCtx = Eng.getBuilderContext();
+
+ // See if we're constructing an existing region by looking at the next
+ // element in the CFG.
+ const CFGBlock *B = CurrBldrCtx.getBlock();
+ unsigned int NextStmtIdx = CurrStmtIdx + 1;
+ if (NextStmtIdx < B->size()) {
+ CFGElement Next = (*B)[NextStmtIdx];
+
+ // Is this a destructor? If so, we might be in the middle of an assignment
+ // to a local or member: look ahead one more element to see what we find.
+ while (Next.getAs<CFGImplicitDtor>() && NextStmtIdx + 1 < B->size()) {
+ ++NextStmtIdx;
+ Next = (*B)[NextStmtIdx];
+ }
+
+ // Is this a constructor for a local variable?
+ if (Optional<CFGStmt> StmtElem = Next.getAs<CFGStmt>()) {
+ if (const DeclStmt *DS = dyn_cast<DeclStmt>(StmtElem->getStmt())) {
+ if (const VarDecl *Var = dyn_cast<VarDecl>(DS->getSingleDecl())) {
+ if (Var->getInit() && Var->getInit()->IgnoreImplicit() == CE) {
+ SVal LValue = State->getLValue(Var, LCtx);
+ QualType Ty = Var->getType();
+ LValue = makeZeroElementRegion(State, LValue, Ty);
+ return LValue.getAsRegion();
+ }
+ }
+ }
+ }
+
+ // Is this a constructor for a member?
+ if (Optional<CFGInitializer> InitElem = Next.getAs<CFGInitializer>()) {
+ const CXXCtorInitializer *Init = InitElem->getInitializer();
+ assert(Init->isAnyMemberInitializer());
+
+ const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
+ Loc ThisPtr = Eng.getSValBuilder().getCXXThis(CurCtor,
+ LCtx->getCurrentStackFrame());
+ SVal ThisVal = State->getSVal(ThisPtr);
+
+ const ValueDecl *Field;
+ SVal FieldVal;
+ if (Init->isIndirectMemberInitializer()) {
+ Field = Init->getIndirectMember();
+ FieldVal = State->getLValue(Init->getIndirectMember(), ThisVal);
+ } else {
+ Field = Init->getMember();
+ FieldVal = State->getLValue(Init->getMember(), ThisVal);
+ }
+
+ QualType Ty = Field->getType();
+ FieldVal = makeZeroElementRegion(State, FieldVal, Ty);
+ return FieldVal.getAsRegion();
+ }
+
+ // FIXME: This will eventually need to handle new-expressions as well.
+ // Don't forget to update the pre-constructor initialization code in
+ // ExprEngine::VisitCXXConstructExpr.
+ }
+
+ // If we couldn't find an existing region to construct into, assume we're
+ // constructing a temporary.
+ MemRegionManager &MRMgr = Eng.getSValBuilder().getRegionManager();
+ return MRMgr.getCXXTempObjectRegion(CE, LCtx);
+}
+
void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
ExplodedNode *Pred,
ExplodedNodeSet &destNodes) {
const LocationContext *LCtx = Pred->getLocationContext();
ProgramStateRef State = Pred->getState();
- const MemRegion *Target = 0;
+ const MemRegion *Target = nullptr;
// FIXME: Handle arrays, which run the same constructor for every element.
// For now, we just run the first constructor (which should still invalidate
@@ -122,62 +188,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
switch (CE->getConstructionKind()) {
case CXXConstructExpr::CK_Complete: {
- // See if we're constructing an existing region by looking at the next
- // element in the CFG.
- const CFGBlock *B = currBldrCtx->getBlock();
- if (currStmtIdx + 1 < B->size()) {
- CFGElement Next = (*B)[currStmtIdx+1];
-
- // Is this a constructor for a local variable?
- if (Optional<CFGStmt> StmtElem = Next.getAs<CFGStmt>()) {
- if (const DeclStmt *DS = dyn_cast<DeclStmt>(StmtElem->getStmt())) {
- if (const VarDecl *Var = dyn_cast<VarDecl>(DS->getSingleDecl())) {
- if (Var->getInit()->IgnoreImplicit() == CE) {
- SVal LValue = State->getLValue(Var, LCtx);
- QualType Ty = Var->getType();
- LValue = makeZeroElementRegion(State, LValue, Ty);
- Target = LValue.getAsRegion();
- }
- }
- }
- }
-
- // Is this a constructor for a member?
- if (Optional<CFGInitializer> InitElem = Next.getAs<CFGInitializer>()) {
- const CXXCtorInitializer *Init = InitElem->getInitializer();
- assert(Init->isAnyMemberInitializer());
-
- const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
- Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor,
- LCtx->getCurrentStackFrame());
- SVal ThisVal = State->getSVal(ThisPtr);
-
- const ValueDecl *Field;
- SVal FieldVal;
- if (Init->isIndirectMemberInitializer()) {
- Field = Init->getIndirectMember();
- FieldVal = State->getLValue(Init->getIndirectMember(), ThisVal);
- } else {
- Field = Init->getMember();
- FieldVal = State->getLValue(Init->getMember(), ThisVal);
- }
-
- QualType Ty = Field->getType();
- FieldVal = makeZeroElementRegion(State, FieldVal, Ty);
- Target = FieldVal.getAsRegion();
- }
-
- // FIXME: This will eventually need to handle new-expressions as well.
- // Don't forget to update the pre-constructor initialization code below.
- }
-
- // If we couldn't find an existing region to construct into, assume we're
- // constructing a temporary.
- if (!Target) {
- MemRegionManager &MRMgr = getSValBuilder().getRegionManager();
- Target = MRMgr.getCXXTempObjectRegion(CE, LCtx);
- }
-
+ Target = getRegionForConstructedObject(CE, Pred, *this, currStmtIdx);
break;
}
case CXXConstructExpr::CK_VirtualBase:
@@ -251,7 +262,8 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
// since it's then possible to be initializing one part of a multi-
// dimensional array.
State = State->bindDefault(loc::MemRegionVal(Target), ZeroVal);
- Bldr.generateNode(CE, *I, State, /*tag=*/0, ProgramPoint::PreStmtKind);
+ Bldr.generateNode(CE, *I, State, /*tag=*/nullptr,
+ ProgramPoint::PreStmtKind);
}
}
}
@@ -329,6 +341,32 @@ void ExprEngine::VisitCXXDestructor(QualType ObjectType,
*Call, *this);
}
+void ExprEngine::VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ ProgramStateRef State = Pred->getState();
+ const LocationContext *LCtx = Pred->getLocationContext();
+ PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
+ CNE->getStartLoc(),
+ "Error evaluating New Allocator Call");
+ CallEventManager &CEMgr = getStateManager().getCallEventManager();
+ CallEventRef<CXXAllocatorCall> Call =
+ CEMgr.getCXXAllocatorCall(CNE, State, LCtx);
+
+ ExplodedNodeSet DstPreCall;
+ getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,
+ *Call, *this);
+
+ ExplodedNodeSet DstInvalidated;
+ StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+ for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
+ I != E; ++I)
+ defaultEvalCall(Bldr, *I, *Call);
+ getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
+ *Call, *this);
+}
+
+
void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
// FIXME: Much of this should eventually migrate to CXXAllocatorCall.
@@ -360,7 +398,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
if (IsStandardGlobalOpNewFunction)
symVal = svalBuilder.getConjuredHeapSymbolVal(CNE, LCtx, blockCount);
else
- symVal = svalBuilder.conjureSymbolVal(0, CNE, LCtx, CNE->getType(),
+ symVal = svalBuilder.conjureSymbolVal(nullptr, CNE, LCtx, CNE->getType(),
blockCount);
ProgramStateRef State = Pred->getState();
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index 06328e4ffce99..3f608ba79ebc3 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -11,8 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "ExprEngine"
-
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "PrettyStackTraceLocationContext.h"
#include "clang/AST/CXXInheritance.h"
@@ -28,6 +26,8 @@
using namespace clang;
using namespace ento;
+#define DEBUG_TYPE "ExprEngine"
+
STATISTIC(NumOfDynamicDispatchPathSplits,
"The # of times we split the path due to imprecise dynamic dispatch info");
@@ -49,7 +49,7 @@ void ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) {
assert(Entry->empty());
assert(Entry->succ_size() == 1);
- // Get the solitary sucessor.
+ // Get the solitary successor.
const CFGBlock *Succ = *(Entry->succ_begin());
// Construct an edge representing the starting location in the callee.
@@ -69,8 +69,8 @@ void ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) {
// corresponding Block.
static std::pair<const Stmt*,
const CFGBlock*> getLastStmt(const ExplodedNode *Node) {
- const Stmt *S = 0;
- const CFGBlock *Blk = 0;
+ const Stmt *S = nullptr;
+ const CFGBlock *Blk = nullptr;
const StackFrameContext *SF =
Node->getLocation().getLocationContext()->getCurrentStackFrame();
@@ -108,12 +108,12 @@ static std::pair<const Stmt*,
}
if (Node->pred_empty())
- return std::pair<const Stmt*, const CFGBlock*>((Stmt*)0, (CFGBlock*)0);
+ return std::make_pair(nullptr, nullptr);
Node = *Node->pred_begin();
}
- return std::pair<const Stmt*, const CFGBlock*>(S, Blk);
+ return std::make_pair(S, Blk);
}
/// Adjusts a return value when the called function's return type does not
@@ -160,9 +160,9 @@ void ExprEngine::removeDeadOnEndOfFunction(NodeBuilderContext& BC,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
// Find the last statement in the function and the corresponding basic block.
- const Stmt *LastSt = 0;
- const CFGBlock *Blk = 0;
- llvm::tie(LastSt, Blk) = getLastStmt(Pred);
+ const Stmt *LastSt = nullptr;
+ const CFGBlock *Blk = nullptr;
+ std::tie(LastSt, Blk) = getLastStmt(Pred);
if (!Blk || !LastSt) {
Dst.Add(Pred);
return;
@@ -229,9 +229,9 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
const Stmt *CE = calleeCtx->getCallSite();
ProgramStateRef state = CEBNode->getState();
// Find the last statement in the function and the corresponding basic block.
- const Stmt *LastSt = 0;
- const CFGBlock *Blk = 0;
- llvm::tie(LastSt, Blk) = getLastStmt(CEBNode);
+ const Stmt *LastSt = nullptr;
+ const CFGBlock *Blk = nullptr;
+ std::tie(LastSt, Blk) = getLastStmt(CEBNode);
// Generate a CallEvent /before/ cleaning the state, so that we can get the
// correct value for 'this' (if necessary).
@@ -282,7 +282,7 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
// they occurred.
ExplodedNodeSet CleanedNodes;
if (LastSt && Blk && AMgr.options.AnalysisPurgeOpt != PurgeNone) {
- static SimpleProgramPointTag retValBind("ExprEngine : Bind Return Value");
+ static SimpleProgramPointTag retValBind("ExprEngine", "Bind Return Value");
PostStmt Loc(LastSt, calleeCtx, &retValBind);
bool isNew;
ExplodedNode *BindedRetNode = G.getNode(Loc, state, false, &isNew);
@@ -296,10 +296,10 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
// context, telling it to clean up everything in the callee's context
// (and its children). We use the callee's function body as a diagnostic
// statement, with which the program point will be associated.
- removeDead(BindedRetNode, CleanedNodes, 0, calleeCtx,
+ removeDead(BindedRetNode, CleanedNodes, nullptr, calleeCtx,
calleeCtx->getAnalysisDeclContext()->getBody(),
ProgramPoint::PostStmtPurgeDeadSymbolsKind);
- currBldrCtx = 0;
+ currBldrCtx = nullptr;
} else {
CleanedNodes.Add(CEBNode);
}
@@ -387,14 +387,14 @@ static bool IsInStdNamespace(const FunctionDecl *FD) {
const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC);
if (!ND)
return false;
-
+
while (const DeclContext *Parent = ND->getParent()) {
if (!isa<NamespaceDecl>(Parent))
break;
ND = cast<NamespaceDecl>(Parent);
}
- return ND->getName() == "std";
+ return ND->isStdNamespace();
}
// The GDM component containing the dynamic dispatch bifurcation info. When
@@ -471,7 +471,7 @@ static ProgramStateRef getInlineFailedState(ProgramStateRef State,
const Stmt *CallE) {
const void *ReplayState = State->get<ReplayWithoutInlining>();
if (!ReplayState)
- return 0;
+ return nullptr;
assert(ReplayState == CallE && "Backtracked to the wrong call.");
(void)CallE;
@@ -565,7 +565,7 @@ ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call,
QualType ResultTy = Call.getResultType();
SValBuilder &SVB = getSValBuilder();
unsigned Count = currBldrCtx->blockCount();
- SVal R = SVB.conjureSymbolVal(0, E, LCtx, ResultTy, Count);
+ SVal R = SVB.conjureSymbolVal(nullptr, E, LCtx, ResultTy, Count);
return State->BindExpr(E, LCtx, R);
}
@@ -664,6 +664,8 @@ static CallInlinePolicy mayInlineCallKind(const CallEvent &Call,
break;
}
case CE_CXXAllocator:
+ if (Opts.mayInlineCXXAllocator())
+ break;
// Do not inline allocators until we model deallocators.
// This is unfortunate, but basically necessary for smart pointers and such.
return CIP_DisallowedAlways;
@@ -706,18 +708,16 @@ static bool isContainerClass(const ASTContext &Ctx, const CXXRecordDecl *RD) {
hasMember(Ctx, RD, "iterator_category");
}
-/// Returns true if the given function refers to a constructor or destructor of
-/// a C++ container or iterator.
+/// Returns true if the given function refers to a method of a C++ container
+/// or iterator.
///
-/// We generally do a poor job modeling most containers right now, and would
-/// prefer not to inline their setup and teardown.
-static bool isContainerCtorOrDtor(const ASTContext &Ctx,
- const FunctionDecl *FD) {
- if (!(isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD)))
- return false;
-
- const CXXRecordDecl *RD = cast<CXXMethodDecl>(FD)->getParent();
- return isContainerClass(Ctx, RD);
+/// We generally do a poor job modeling most containers right now, and might
+/// prefer not to inline their methods.
+static bool isContainerMethod(const ASTContext &Ctx,
+ const FunctionDecl *FD) {
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
+ return isContainerClass(Ctx, MD->getParent());
+ return false;
}
/// Returns true if the given function is the destructor of a class named
@@ -763,9 +763,9 @@ static bool mayInlineDecl(AnalysisDeclContext *CalleeADC,
// Conditionally control the inlining of methods on objects that look
// like C++ containers.
- if (!Opts.mayInlineCXXContainerCtorsAndDtors())
+ if (!Opts.mayInlineCXXContainerMethods())
if (!Ctx.getSourceManager().isInMainFile(FD->getLocation()))
- if (isContainerCtorOrDtor(Ctx, FD))
+ if (isContainerMethod(Ctx, FD))
return false;
// Conditionally control the inlining of the destructor of C++ shared_ptr.
diff --git a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
index d276d92446149..a6611e050dc9b 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
@@ -77,7 +77,7 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
if (const DeclStmt *DS = dyn_cast<DeclStmt>(elem)) {
const VarDecl *elemD = cast<VarDecl>(DS->getSingleDecl());
- assert(elemD->getInit() == 0);
+ assert(elemD->getInit() == nullptr);
elementV = state->getLValue(elemD, Pred->getLocationContext());
}
else {
@@ -85,7 +85,7 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
}
ExplodedNodeSet dstLocation;
- evalLocation(dstLocation, S, elem, Pred, state, elementV, NULL, false);
+ evalLocation(dstLocation, S, elem, Pred, state, elementV, nullptr, false);
ExplodedNodeSet Tmp;
StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
@@ -165,7 +165,7 @@ void ExprEngine::VisitObjCMessage(const ObjCMessageExpr *ME,
recVal.castAs<DefinedOrUnknownSVal>();
ProgramStateRef notNilState, nilState;
- llvm::tie(notNilState, nilState) = State->assume(receiverVal);
+ std::tie(notNilState, nilState) = State->assume(receiverVal);
// There are three cases: can be nil or non-nil, must be nil, must be
// non-nil. We ignore must be nil, and merge the rest two into non-nil.
diff --git a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
index 365f6ab70de74..b1e9f06cae000 100644
--- a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
+++ b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
@@ -20,11 +20,13 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Rewrite/Core/HTMLRewrite.h"
#include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
+#include <sstream>
using namespace clang;
using namespace ento;
@@ -39,15 +41,16 @@ class HTMLDiagnostics : public PathDiagnosticConsumer {
std::string Directory;
bool createdDir, noDir;
const Preprocessor &PP;
+ AnalyzerOptions &AnalyzerOpts;
public:
- HTMLDiagnostics(const std::string& prefix, const Preprocessor &pp);
+ HTMLDiagnostics(AnalyzerOptions &AnalyzerOpts, const std::string& prefix, const Preprocessor &pp);
- virtual ~HTMLDiagnostics() { FlushDiagnostics(NULL); }
+ virtual ~HTMLDiagnostics() { FlushDiagnostics(nullptr); }
- virtual void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
- FilesMade *filesMade);
+ void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
+ FilesMade *filesMade) override;
- virtual StringRef getName() const {
+ StringRef getName() const override {
return "HTMLDiagnostics";
}
@@ -68,16 +71,17 @@ public:
} // end anonymous namespace
-HTMLDiagnostics::HTMLDiagnostics(const std::string& prefix,
+HTMLDiagnostics::HTMLDiagnostics(AnalyzerOptions &AnalyzerOpts,
+ const std::string& prefix,
const Preprocessor &pp)
- : Directory(prefix), createdDir(false), noDir(false), PP(pp) {
+ : Directory(prefix), createdDir(false), noDir(false), PP(pp), AnalyzerOpts(AnalyzerOpts) {
}
void ento::createHTMLDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
PathDiagnosticConsumers &C,
const std::string& prefix,
const Preprocessor &PP) {
- C.push_back(new HTMLDiagnostics(prefix, PP));
+ C.push_back(new HTMLDiagnostics(AnalyzerOpts, prefix, PP));
}
//===----------------------------------------------------------------------===//
@@ -95,13 +99,11 @@ void HTMLDiagnostics::FlushDiagnosticsImpl(
void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
FilesMade *filesMade) {
-
+
// Create the HTML directory if it is missing.
if (!createdDir) {
createdDir = true;
- bool existed;
- if (llvm::error_code ec =
- llvm::sys::fs::create_directories(Directory, existed)) {
+ if (std::error_code ec = llvm::sys::fs::create_directories(Directory)) {
llvm::errs() << "warning: could not create directory '"
<< Directory << "': " << ec.message() << '\n';
@@ -128,11 +130,30 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
// Create a new rewriter to generate HTML.
Rewriter R(const_cast<SourceManager&>(SMgr), PP.getLangOpts());
+ // Get the function/method name
+ SmallString<128> declName("unknown");
+ int offsetDecl = 0;
+ if (const Decl *DeclWithIssue = D.getDeclWithIssue()) {
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(DeclWithIssue)) {
+ declName = ND->getDeclName().getAsString();
+ }
+
+ if (const Stmt *Body = DeclWithIssue->getBody()) {
+ // Retrieve the relative position of the declaration which will be used
+ // for the file name
+ FullSourceLoc L(
+ SMgr.getExpansionLoc((*path.rbegin())->getLocation().asLocation()),
+ SMgr);
+ FullSourceLoc FunL(SMgr.getExpansionLoc(Body->getLocStart()), SMgr);
+ offsetDecl = L.getExpansionLineNumber() - FunL.getExpansionLineNumber();
+ }
+ }
+
// Process the path.
unsigned n = path.size();
unsigned max = n;
- for (PathPieces::const_reverse_iterator I = path.rbegin(),
+ for (PathPieces::const_reverse_iterator I = path.rbegin(),
E = path.rend();
I != E; ++I, --n)
HandlePiece(R, FID, **I, n, max);
@@ -165,6 +186,9 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
DirName += '/';
}
+ int LineNumber = (*path.rbegin())->getLocation().asLocation().getExpansionLineNumber();
+ int ColumnNumber = (*path.rbegin())->getLocation().asLocation().getExpansionColumnNumber();
+
// Add the name of the file as an <h1> tag.
{
@@ -178,9 +202,9 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
<< html::EscapeText(Entry->getName())
<< "</td></tr>\n<tr><td class=\"rowname\">Location:</td><td>"
"<a href=\"#EndPath\">line "
- << (*path.rbegin())->getLocation().asLocation().getExpansionLineNumber()
+ << LineNumber
<< ", column "
- << (*path.rbegin())->getLocation().asLocation().getExpansionColumnNumber()
+ << ColumnNumber
<< "</a></td></tr>\n"
"<tr><td class=\"rowname\">Description:</td><td>"
<< D.getVerboseDescription() << "</td></tr>\n";
@@ -217,12 +241,16 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
os << "\n<!-- BUGFILE " << DirName << Entry->getName() << " -->\n";
+ os << "\n<!-- FILENAME " << llvm::sys::path::filename(Entry->getName()) << " -->\n";
+
+ os << "\n<!-- FUNCTIONNAME " << declName << " -->\n";
+
os << "\n<!-- BUGLINE "
- << path.back()->getLocation().asLocation().getExpansionLineNumber()
+ << LineNumber
<< " -->\n";
os << "\n<!-- BUGCOLUMN "
- << path.back()->getLocation().asLocation().getExpansionColumnNumber()
+ << ColumnNumber
<< " -->\n";
os << "\n<!-- BUGPATHLENGTH " << path.size() << " -->\n";
@@ -249,13 +277,42 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
// Create a path for the target HTML file.
int FD;
SmallString<128> Model, ResultPath;
- llvm::sys::path::append(Model, Directory, "report-%%%%%%.html");
- if (llvm::error_code EC =
+ if (!AnalyzerOpts.shouldWriteStableReportFilename()) {
+ llvm::sys::path::append(Model, Directory, "report-%%%%%%.html");
+
+ if (std::error_code EC =
llvm::sys::fs::createUniqueFile(Model.str(), FD, ResultPath)) {
- llvm::errs() << "warning: could not create file in '" << Directory
- << "': " << EC.message() << '\n';
- return;
+ llvm::errs() << "warning: could not create file in '" << Directory
+ << "': " << EC.message() << '\n';
+ return;
+ }
+
+ } else {
+ int i = 1;
+ std::error_code EC;
+ do {
+ // Find a filename which is not already used
+ std::stringstream filename;
+ Model = "";
+ filename << "report-"
+ << llvm::sys::path::filename(Entry->getName()).str()
+ << "-" << declName.c_str()
+ << "-" << offsetDecl
+ << "-" << i << ".html";
+ llvm::sys::path::append(Model, Directory,
+ filename.str());
+ EC = llvm::sys::fs::openFileForWrite(Model.str(),
+ FD,
+ llvm::sys::fs::F_RW |
+ llvm::sys::fs::F_Excl);
+ if (EC && EC != std::errc::file_exists) {
+ llvm::errs() << "warning: could not create file '" << Model.str()
+ << "': " << EC.message() << '\n';
+ return;
+ }
+ i++;
+ } while (EC);
}
llvm::raw_fd_ostream os(FD, true);
@@ -309,7 +366,7 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
// Create the html for the message.
- const char *Kind = 0;
+ const char *Kind = nullptr;
switch (P.getKind()) {
case PathDiagnosticPiece::Call:
llvm_unreachable("Calls should already be handled");
@@ -460,7 +517,7 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
<< (num + 1)
<< ")\">&#x2192;</a></div></td>";
}
-
+
os << "</tr></table>";
}
}
diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp
index 162cd33264952..22711f54239ae 100644
--- a/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -148,7 +148,7 @@ MemRegionManager::~MemRegionManager() {
bool SubRegion::isSubRegionOf(const MemRegion* R) const {
const MemRegion* r = getSuperRegion();
- while (r != 0) {
+ while (r != nullptr) {
if (r == R)
return true;
if (const SubRegion* sr = dyn_cast<SubRegion>(r))
@@ -173,7 +173,7 @@ MemRegionManager* SubRegion::getMemRegionManager() const {
const StackFrameContext *VarRegion::getStackFrame() const {
const StackSpaceRegion *SSR = dyn_cast<StackSpaceRegion>(getMemorySpace());
- return SSR ? SSR->getStackFrame() : NULL;
+ return SSR ? SSR->getStackFrame() : nullptr;
}
//===----------------------------------------------------------------------===//
@@ -508,11 +508,13 @@ void ObjCIvarRegion::dumpToStream(raw_ostream &os) const {
}
void StringRegion::dumpToStream(raw_ostream &os) const {
- Str->printPretty(os, 0, PrintingPolicy(getContext().getLangOpts()));
+ assert(Str != nullptr && "Expecting non-null StringLiteral");
+ Str->printPretty(os, nullptr, PrintingPolicy(getContext().getLangOpts()));
}
void ObjCStringRegion::dumpToStream(raw_ostream &os) const {
- Str->printPretty(os, 0, PrintingPolicy(getContext().getLangOpts()));
+ assert(Str != nullptr && "Expecting non-null ObjCStringLiteral");
+ Str->printPretty(os, nullptr, PrintingPolicy(getContext().getLangOpts()));
}
void SymbolicRegion::dumpToStream(raw_ostream &os) const {
@@ -757,12 +759,12 @@ getStackOrCaptureRegionForDeclContext(const LocationContext *LC,
LC = LC->getParent();
}
- return (const StackFrameContext*)0;
+ return (const StackFrameContext *)nullptr;
}
const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
const LocationContext *LC) {
- const MemRegion *sReg = 0;
+ const MemRegion *sReg = nullptr;
if (D->hasGlobalStorage() && !D->isStaticLocal()) {
@@ -850,7 +852,7 @@ const BlockDataRegion *
MemRegionManager::getBlockDataRegion(const BlockTextRegion *BC,
const LocationContext *LC,
unsigned blockCount) {
- const MemRegion *sReg = 0;
+ const MemRegion *sReg = nullptr;
const BlockDecl *BD = BC->getDecl();
if (!BD->hasCaptures()) {
// This handles 'static' blocks.
@@ -877,14 +879,14 @@ MemRegionManager::getBlockDataRegion(const BlockTextRegion *BC,
const CXXTempObjectRegion *
MemRegionManager::getCXXStaticTempObjectRegion(const Expr *Ex) {
return getSubRegion<CXXTempObjectRegion>(
- Ex, getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind, NULL));
+ Ex, getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind, nullptr));
}
const CompoundLiteralRegion*
MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
const LocationContext *LC) {
- const MemRegion *sReg = 0;
+ const MemRegion *sReg = nullptr;
if (CL->isFileScope())
sReg = getGlobalsRegion();
@@ -975,10 +977,8 @@ static bool isValidBaseClass(const CXXRecordDecl *BaseClass,
if (IsVirtual)
return Class->isVirtuallyDerivedFrom(BaseClass);
- for (CXXRecordDecl::base_class_const_iterator I = Class->bases_begin(),
- E = Class->bases_end();
- I != E; ++I) {
- if (I->getType()->getAsCXXRecordDecl()->getCanonicalDecl() == BaseClass)
+ for (const auto &I : Class->bases()) {
+ if (I.getType()->getAsCXXRecordDecl()->getCanonicalDecl() == BaseClass)
return true;
}
@@ -1113,7 +1113,7 @@ const SymbolicRegion *MemRegion::getSymbolicBase() const {
return SymR;
SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
}
- return 0;
+ return nullptr;
}
// FIXME: Merge with the implementation of the same method in Store.cpp
@@ -1130,7 +1130,7 @@ static bool IsCompleteType(ASTContext &Ctx, QualType Ty) {
RegionRawOffset ElementRegion::getAsArrayOffset() const {
CharUnits offset = CharUnits::Zero();
const ElementRegion *ER = this;
- const MemRegion *superR = NULL;
+ const MemRegion *superR = nullptr;
ASTContext &C = getContext();
// FIXME: Handle multi-dimensional arrays.
@@ -1162,7 +1162,7 @@ RegionRawOffset ElementRegion::getAsArrayOffset() const {
continue;
}
- return NULL;
+ return nullptr;
}
assert(superR && "super region cannot be NULL");
@@ -1176,10 +1176,8 @@ static bool isImmediateBase(const CXXRecordDecl *Child,
// Note that we do NOT canonicalize the base class here, because
// ASTRecordLayout doesn't either. If that leads us down the wrong path,
// so be it; at least we won't crash.
- for (CXXRecordDecl::base_class_const_iterator I = Child->bases_begin(),
- E = Child->bases_end();
- I != E; ++I) {
- if (I->getType()->getAsCXXRecordDecl() == Base)
+ for (const auto &I : Child->bases()) {
+ if (I.getType()->getAsCXXRecordDecl() == Base)
return true;
}
@@ -1188,7 +1186,7 @@ static bool isImmediateBase(const CXXRecordDecl *Child,
RegionOffset MemRegion::getAsOffset() const {
const MemRegion *R = this;
- const MemRegion *SymbolicOffsetBase = 0;
+ const MemRegion *SymbolicOffsetBase = nullptr;
int64_t Offset = 0;
while (1) {
@@ -1360,10 +1358,10 @@ RegionOffset MemRegion::getAsOffset() const {
std::pair<const VarRegion *, const VarRegion *>
BlockDataRegion::getCaptureRegions(const VarDecl *VD) {
MemRegionManager &MemMgr = *getMemRegionManager();
- const VarRegion *VR = 0;
- const VarRegion *OriginalVR = 0;
+ const VarRegion *VR = nullptr;
+ const VarRegion *OriginalVR = nullptr;
- if (!VD->getAttr<BlocksAttr>() && VD->hasLocalStorage()) {
+ if (!VD->hasAttr<BlocksAttr>() && VD->hasLocalStorage()) {
VR = MemMgr.getVarRegion(VD, this);
OriginalVR = MemMgr.getVarRegion(VD, LC);
}
@@ -1386,7 +1384,7 @@ void BlockDataRegion::LazyInitializeReferencedVars() {
AnalysisDeclContext *AC = getCodeRegion()->getAnalysisDeclContext();
AnalysisDeclContext::referenced_decls_iterator I, E;
- llvm::tie(I, E) = AC->getReferencedBlockVars(BC->getDecl());
+ std::tie(I, E) = AC->getReferencedBlockVars(BC->getDecl());
if (I == E) {
ReferencedVars = (void*) 0x1;
@@ -1404,9 +1402,9 @@ void BlockDataRegion::LazyInitializeReferencedVars() {
new (BVOriginal) VarVec(BC, E - I);
for ( ; I != E; ++I) {
- const VarRegion *VR = 0;
- const VarRegion *OriginalVR = 0;
- llvm::tie(VR, OriginalVR) = getCaptureRegions(*I);
+ const VarRegion *VR = nullptr;
+ const VarRegion *OriginalVR = nullptr;
+ std::tie(VR, OriginalVR) = getCaptureRegions(*I);
assert(VR);
assert(OriginalVR);
BV->push_back(VR, BC);
@@ -1425,8 +1423,8 @@ BlockDataRegion::referenced_vars_begin() const {
static_cast<BumpVector<const MemRegion*>*>(ReferencedVars);
if (Vec == (void*) 0x1)
- return BlockDataRegion::referenced_vars_iterator(0, 0);
-
+ return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr);
+
BumpVector<const MemRegion*> *VecOriginal =
static_cast<BumpVector<const MemRegion*>*>(OriginalVars);
@@ -1442,8 +1440,8 @@ BlockDataRegion::referenced_vars_end() const {
static_cast<BumpVector<const MemRegion*>*>(ReferencedVars);
if (Vec == (void*) 0x1)
- return BlockDataRegion::referenced_vars_iterator(0, 0);
-
+ return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr);
+
BumpVector<const MemRegion*> *VecOriginal =
static_cast<BumpVector<const MemRegion*>*>(OriginalVars);
@@ -1458,7 +1456,7 @@ const VarRegion *BlockDataRegion::getOriginalRegion(const VarRegion *R) const {
if (I.getCapturedRegion() == R)
return I.getOriginalRegion();
}
- return 0;
+ return nullptr;
}
//===----------------------------------------------------------------------===//
diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index b504db6349ee6..fd25bd8e3af3a 100644
--- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/DeclCXX.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/Basic/SourceManager.h"
@@ -66,7 +67,7 @@ PathPieces::~PathPieces() {}
void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
bool ShouldFlattenMacros) const {
for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
- PathDiagnosticPiece *Piece = I->getPtr();
+ PathDiagnosticPiece *Piece = I->get();
switch (Piece->getKind()) {
case PathDiagnosticPiece::Call: {
@@ -106,12 +107,13 @@ void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
PathDiagnostic::~PathDiagnostic() {}
-PathDiagnostic::PathDiagnostic(const Decl *declWithIssue,
+PathDiagnostic::PathDiagnostic(StringRef CheckName, const Decl *declWithIssue,
StringRef bugtype, StringRef verboseDesc,
StringRef shortDesc, StringRef category,
PathDiagnosticLocation LocationToUnique,
const Decl *DeclToUnique)
- : DeclWithIssue(declWithIssue),
+ : CheckName(CheckName),
+ DeclWithIssue(declWithIssue),
BugType(StripTrailingDots(bugtype)),
VerboseDesc(StripTrailingDots(verboseDesc)),
ShortDesc(StripTrailingDots(shortDesc)),
@@ -127,7 +129,7 @@ getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP,
// If the call is within a macro, don't do anything (for now).
if (CallLoc.isMacroID())
- return 0;
+ return nullptr;
assert(SMgr.isInMainFile(CallLoc) &&
"The call piece should be in the main file.");
@@ -138,7 +140,7 @@ getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP,
const PathPieces &Path = CP->path;
if (Path.empty())
- return 0;
+ return nullptr;
// Check if the last piece in the callee path is a call to a function outside
// of the main file.
@@ -148,14 +150,14 @@ getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP,
}
// Otherwise, the last piece is in the main file.
- return 0;
+ return nullptr;
}
void PathDiagnostic::resetDiagnosticLocationToMainFile() {
if (path.empty())
return;
- PathDiagnosticPiece *LastP = path.back().getPtr();
+ PathDiagnosticPiece *LastP = path.back().get();
assert(LastP);
const SourceManager &SMgr = LastP->getLocation().getManager();
@@ -196,8 +198,8 @@ PathDiagnosticConsumer::~PathDiagnosticConsumer() {
}
void PathDiagnosticConsumer::HandlePathDiagnostic(PathDiagnostic *D) {
- OwningPtr<PathDiagnostic> OwningD(D);
-
+ std::unique_ptr<PathDiagnostic> OwningD(D);
+
if (!D || D->path.empty())
return;
@@ -220,7 +222,7 @@ void PathDiagnosticConsumer::HandlePathDiagnostic(PathDiagnostic *D) {
for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E;
++I) {
- const PathDiagnosticPiece *piece = I->getPtr();
+ const PathDiagnosticPiece *piece = I->get();
FullSourceLoc L = piece->getLocation().asLocation().getExpansionLoc();
if (FID.isInvalid()) {
@@ -258,7 +260,7 @@ void PathDiagnosticConsumer::HandlePathDiagnostic(PathDiagnostic *D) {
// Profile the node to see if we already have something matching it
llvm::FoldingSetNodeID profile;
D->Profile(profile);
- void *InsertPos = 0;
+ void *InsertPos = nullptr;
if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
// Keep the PathDiagnostic with the shorter path.
@@ -274,8 +276,8 @@ void PathDiagnosticConsumer::HandlePathDiagnostic(PathDiagnostic *D) {
Diags.RemoveNode(orig);
delete orig;
}
-
- Diags.InsertNode(OwningD.take());
+
+ Diags.InsertNode(OwningD.release());
}
static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y);
@@ -415,17 +417,6 @@ static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) {
return b.getValue();
}
-namespace {
-struct CompareDiagnostics {
- // Compare if 'X' is "<" than 'Y'.
- bool operator()(const PathDiagnostic *X, const PathDiagnostic *Y) const {
- if (X == Y)
- return false;
- return compare(*X, *Y);
- }
-};
-}
-
void PathDiagnosticConsumer::FlushDiagnostics(
PathDiagnosticConsumer::FilesMade *Files) {
if (flushed)
@@ -443,8 +434,11 @@ void PathDiagnosticConsumer::FlushDiagnostics(
// Sort the diagnostics so that they are always emitted in a deterministic
// order.
if (!BatchDiags.empty())
- std::sort(BatchDiags.begin(), BatchDiags.end(), CompareDiagnostics());
-
+ std::sort(BatchDiags.begin(), BatchDiags.end(),
+ [](const PathDiagnostic *X, const PathDiagnostic *Y) {
+ return X != Y && compare(*X, *Y);
+ });
+
FlushDiagnosticsImpl(BatchDiags, Files);
// Delete the flushed diagnostics.
@@ -458,6 +452,11 @@ void PathDiagnosticConsumer::FlushDiagnostics(
Diags.clear();
}
+PathDiagnosticConsumer::FilesMade::~FilesMade() {
+ for (PDFileEntry &Entry : *this)
+ Entry.~PDFileEntry();
+}
+
void PathDiagnosticConsumer::FilesMade::addDiagnostic(const PathDiagnostic &PD,
StringRef ConsumerName,
StringRef FileName) {
@@ -487,7 +486,7 @@ PathDiagnosticConsumer::FilesMade::getFiles(const PathDiagnostic &PD) {
void *InsertPos;
PDFileEntry *Entry = FindNodeOrInsertPos(NodeID, InsertPos);
if (!Entry)
- return 0;
+ return nullptr;
return &Entry->files;
}
@@ -571,6 +570,7 @@ getLocationForCaller(const StackFrameContext *SFC,
return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM);
}
case CFGElement::TemporaryDtor:
+ case CFGElement::NewAllocator:
llvm_unreachable("not yet implemented!");
}
@@ -610,6 +610,14 @@ PathDiagnosticLocation
}
PathDiagnosticLocation
+ PathDiagnosticLocation::createConditionalColonLoc(
+ const ConditionalOperator *CO,
+ const SourceManager &SM) {
+ return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK);
+}
+
+
+PathDiagnosticLocation
PathDiagnosticLocation::createMemberLoc(const MemberExpr *ME,
const SourceManager &SM) {
return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK);
@@ -654,7 +662,7 @@ PathDiagnosticLocation
PathDiagnosticLocation::create(const ProgramPoint& P,
const SourceManager &SMng) {
- const Stmt* S = 0;
+ const Stmt* S = nullptr;
if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
const CFGBlock *BSrc = BE->getSrc();
S = BSrc->getTerminatorCondition();
@@ -695,7 +703,7 @@ const Stmt *PathDiagnosticLocation::getStmt(const ExplodedNode *N) {
if (Optional<PostInitializer> PIPP = P.getAs<PostInitializer>())
return PIPP->getInitializer()->getInit();
- return 0;
+ return nullptr;
}
const Stmt *PathDiagnosticLocation::getNextStmt(const ExplodedNode *N) {
@@ -722,7 +730,7 @@ const Stmt *PathDiagnosticLocation::getNextStmt(const ExplodedNode *N) {
}
}
- return 0;
+ return nullptr;
}
PathDiagnosticLocation
@@ -731,8 +739,12 @@ PathDiagnosticLocation
assert(N && "Cannot create a location with a null node.");
const Stmt *S = getStmt(N);
- if (!S)
+ if (!S) {
+ // If this is an implicit call, return the implicit call point location.
+ if (Optional<PreImplicitCall> PIE = N->getLocationAs<PreImplicitCall>())
+ return PathDiagnosticLocation(PIE->getLocation(), SM);
S = getNextStmt(N);
+ }
if (S) {
ProgramPoint P = N->getLocation();
@@ -853,13 +865,13 @@ PathDiagnosticRange
void PathDiagnosticLocation::flatten() {
if (K == StmtK) {
K = RangeK;
- S = 0;
- D = 0;
+ S = nullptr;
+ D = nullptr;
}
else if (K == DeclK) {
K = SingleLocK;
- S = 0;
- D = 0;
+ S = nullptr;
+ D = nullptr;
}
}
@@ -969,7 +981,7 @@ static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
IntrusiveRefCntPtr<PathDiagnosticEventPiece>
PathDiagnosticCallPiece::getCallEnterEvent() const {
if (!Callee)
- return 0;
+ return nullptr;
SmallString<256> buf;
llvm::raw_svector_ostream Out(buf);
@@ -984,12 +996,12 @@ PathDiagnosticCallPiece::getCallEnterEvent() const {
IntrusiveRefCntPtr<PathDiagnosticEventPiece>
PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const {
if (!callEnterWithin.asLocation().isValid())
- return 0;
+ return nullptr;
if (Callee->isImplicit() || !Callee->hasBody())
- return 0;
+ return nullptr;
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee))
if (MD->isDefaulted())
- return 0;
+ return nullptr;
SmallString<256> buf;
llvm::raw_svector_ostream Out(buf);
@@ -1003,7 +1015,7 @@ PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const {
IntrusiveRefCntPtr<PathDiagnosticEventPiece>
PathDiagnosticCallPiece::getCallExitEvent() const {
if (NoExit)
- return 0;
+ return nullptr;
SmallString<256> buf;
llvm::raw_svector_ostream Out(buf);
@@ -1025,7 +1037,7 @@ PathDiagnosticCallPiece::getCallExitEvent() const {
static void compute_path_size(const PathPieces &pieces, unsigned &size) {
for (PathPieces::const_iterator it = pieces.begin(),
et = pieces.end(); it != et; ++it) {
- const PathDiagnosticPiece *piece = it->getPtr();
+ const PathDiagnosticPiece *piece = it->get();
if (const PathDiagnosticCallPiece *cp =
dyn_cast<PathDiagnosticCallPiece>(piece)) {
compute_path_size(cp->path, size);
diff --git a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
index 5dca811722ac9..ba3ad2ef16c5e 100644
--- a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
+++ b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
@@ -13,6 +13,7 @@
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/PlistSupport.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Version.h"
#include "clang/Lex/Preprocessor.h"
@@ -21,12 +22,9 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"
-#include "llvm/Support/raw_ostream.h"
using namespace clang;
using namespace ento;
-
-typedef llvm::DenseMap<FileID, unsigned> FIDMap;
-
+using namespace markup;
namespace {
class PlistDiagnostics : public PathDiagnosticConsumer {
@@ -42,15 +40,17 @@ namespace {
virtual ~PlistDiagnostics() {}
void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
- FilesMade *filesMade);
-
- virtual StringRef getName() const {
+ FilesMade *filesMade) override;
+
+ virtual StringRef getName() const override {
return "PlistDiagnostics";
}
- PathGenerationScheme getGenerationScheme() const { return Extensive; }
- bool supportsLogicalOpControlFlow() const { return true; }
- virtual bool supportsCrossFileDiagnostics() const {
+ PathGenerationScheme getGenerationScheme() const override {
+ return Extensive;
+ }
+ bool supportsLogicalOpControlFlow() const override { return true; }
+ bool supportsCrossFileDiagnostics() const override {
return SupportsCrossFileDiagnostics;
}
};
@@ -80,84 +80,6 @@ void ento::createPlistMultiFileDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
PP.getLangOpts(), true));
}
-static void AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V,
- const SourceManager* SM, SourceLocation L) {
-
- FileID FID = SM->getFileID(SM->getExpansionLoc(L));
- FIDMap::iterator I = FIDs.find(FID);
- if (I != FIDs.end()) return;
- FIDs[FID] = V.size();
- V.push_back(FID);
-}
-
-static unsigned GetFID(const FIDMap& FIDs, const SourceManager &SM,
- SourceLocation L) {
- FileID FID = SM.getFileID(SM.getExpansionLoc(L));
- FIDMap::const_iterator I = FIDs.find(FID);
- assert(I != FIDs.end());
- return I->second;
-}
-
-static raw_ostream &Indent(raw_ostream &o, const unsigned indent) {
- for (unsigned i = 0; i < indent; ++i) o << ' ';
- return o;
-}
-
-static void EmitLocation(raw_ostream &o, const SourceManager &SM,
- const LangOptions &LangOpts,
- SourceLocation L, const FIDMap &FM,
- unsigned indent, bool extend = false) {
-
- FullSourceLoc Loc(SM.getExpansionLoc(L), const_cast<SourceManager&>(SM));
-
- // Add in the length of the token, so that we cover multi-char tokens.
- unsigned offset =
- extend ? Lexer::MeasureTokenLength(Loc, SM, LangOpts) - 1 : 0;
-
- Indent(o, indent) << "<dict>\n";
- Indent(o, indent) << " <key>line</key><integer>"
- << Loc.getExpansionLineNumber() << "</integer>\n";
- Indent(o, indent) << " <key>col</key><integer>"
- << Loc.getExpansionColumnNumber() + offset << "</integer>\n";
- Indent(o, indent) << " <key>file</key><integer>"
- << GetFID(FM, SM, Loc) << "</integer>\n";
- Indent(o, indent) << "</dict>\n";
-}
-
-static void EmitLocation(raw_ostream &o, const SourceManager &SM,
- const LangOptions &LangOpts,
- const PathDiagnosticLocation &L, const FIDMap& FM,
- unsigned indent, bool extend = false) {
- EmitLocation(o, SM, LangOpts, L.asLocation(), FM, indent, extend);
-}
-
-static void EmitRange(raw_ostream &o, const SourceManager &SM,
- const LangOptions &LangOpts,
- PathDiagnosticRange R, const FIDMap &FM,
- unsigned indent) {
- Indent(o, indent) << "<array>\n";
- EmitLocation(o, SM, LangOpts, R.getBegin(), FM, indent+1);
- EmitLocation(o, SM, LangOpts, R.getEnd(), FM, indent+1, !R.isPoint);
- Indent(o, indent) << "</array>\n";
-}
-
-static raw_ostream &EmitString(raw_ostream &o, StringRef s) {
- o << "<string>";
- for (StringRef::const_iterator I = s.begin(), E = s.end(); I != E; ++I) {
- char c = *I;
- switch (c) {
- default: o << c; break;
- case '&': o << "&amp;"; break;
- case '<': o << "&lt;"; break;
- case '>': o << "&gt;"; break;
- case '\'': o << "&apos;"; break;
- case '\"': o << "&quot;"; break;
- }
- }
- o << "</string>";
- return o;
-}
-
static void ReportControlFlow(raw_ostream &o,
const PathDiagnosticControlFlowPiece& P,
const FIDMap& FM,
@@ -185,11 +107,13 @@ static void ReportControlFlow(raw_ostream &o,
// logic for clients.
Indent(o, indent) << "<key>start</key>\n";
SourceLocation StartEdge = I->getStart().asRange().getBegin();
- EmitRange(o, SM, LangOpts, SourceRange(StartEdge, StartEdge), FM, indent+1);
+ EmitRange(o, SM, LangOpts, CharSourceRange::getTokenRange(StartEdge), FM,
+ indent + 1);
Indent(o, indent) << "<key>end</key>\n";
SourceLocation EndEdge = I->getEnd().asRange().getBegin();
- EmitRange(o, SM, LangOpts, SourceRange(EndEdge, EndEdge), FM, indent+1);
+ EmitRange(o, SM, LangOpts, CharSourceRange::getTokenRange(EndEdge), FM,
+ indent + 1);
--indent;
Indent(o, indent) << "</dict>\n";
@@ -241,15 +165,16 @@ static void ReportEvent(raw_ostream &o, const PathDiagnosticPiece& P,
++indent;
for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
I != E; ++I) {
- EmitRange(o, SM, LangOpts, *I, FM, indent+1);
+ EmitRange(o, SM, LangOpts, CharSourceRange::getTokenRange(*I), FM,
+ indent + 1);
}
--indent;
Indent(o, indent) << "</array>\n";
}
// Output the call depth.
- Indent(o, indent) << "<key>depth</key>"
- << "<integer>" << depth << "</integer>\n";
+ Indent(o, indent) << "<key>depth</key>";
+ EmitInteger(o, depth) << '\n';
// Output the text.
assert(!P.getString().empty());
@@ -367,7 +292,7 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
// ranges of the diagnostics.
FIDMap FM;
SmallVector<FileID, 10> Fids;
- const SourceManager* SM = 0;
+ const SourceManager* SM = nullptr;
if (!Diags.empty())
SM = &(*(*Diags.begin())->path.begin())->getLocation().getManager();
@@ -386,13 +311,13 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E;
++I) {
- const PathDiagnosticPiece *piece = I->getPtr();
- AddFID(FM, Fids, SM, piece->getLocation().asLocation());
+ const PathDiagnosticPiece *piece = I->get();
+ AddFID(FM, Fids, *SM, piece->getLocation().asLocation());
ArrayRef<SourceRange> Ranges = piece->getRanges();
for (ArrayRef<SourceRange>::iterator I = Ranges.begin(),
E = Ranges.end(); I != E; ++I) {
- AddFID(FM, Fids, SM, I->getBegin());
- AddFID(FM, Fids, SM, I->getEnd());
+ AddFID(FM, Fids, *SM, I->getBegin());
+ AddFID(FM, Fids, *SM, I->getEnd());
}
if (const PathDiagnosticCallPiece *call =
@@ -400,7 +325,7 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
IntrusiveRefCntPtr<PathDiagnosticEventPiece>
callEnterWithin = call->getCallEnterWithinCallerEvent();
if (callEnterWithin)
- AddFID(FM, Fids, SM, callEnterWithin->getLocation().asLocation());
+ AddFID(FM, Fids, *SM, callEnterWithin->getLocation().asLocation());
WorkList.push_back(&call->path);
}
@@ -414,17 +339,13 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
// Open the file.
std::string ErrMsg;
- llvm::raw_fd_ostream o(OutputFile.c_str(), ErrMsg);
+ llvm::raw_fd_ostream o(OutputFile.c_str(), ErrMsg, llvm::sys::fs::F_Text);
if (!ErrMsg.empty()) {
llvm::errs() << "warning: could not create file: " << OutputFile << '\n';
return;
}
- // Write the plist header.
- o << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" "
- "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
- "<plist version=\"1.0\">\n";
+ EmitPlistHeader(o);
// Write the root object: a <dict> containing...
// - "clang_version", the string representation of clang version
@@ -436,11 +357,8 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
o << " <key>files</key>\n"
" <array>\n";
- for (SmallVectorImpl<FileID>::iterator I=Fids.begin(), E=Fids.end();
- I!=E; ++I) {
- o << " ";
- EmitString(o, SM->getFileEntryForID(*I)->getName()) << '\n';
- }
+ for (FileID FID : Fids)
+ EmitString(o << " ", SM->getFileEntryForID(FID)->getName()) << '\n';
o << " </array>\n"
" <key>diagnostics</key>\n"
@@ -535,7 +453,7 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
// Output the location of the bug.
o << " <key>location</key>\n";
- EmitLocation(o, *SM, LangOpts, D->getLocation(), FM, 2);
+ EmitLocation(o, *SM, LangOpts, D->getLocation().asLocation(), FM, 2);
// Output the diagnostic to the sub-diagnostic client, if any.
if (!filesMade->empty()) {
diff --git a/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h b/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h
index ed64fcbec761e..c2af36f407044 100644
--- a/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h
+++ b/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h
@@ -33,7 +33,7 @@ public:
assert(LCtx);
}
- virtual void print(raw_ostream &OS) const {
+ void print(raw_ostream &OS) const override {
OS << "While analyzing stack: \n";
LCtx->dumpStack(OS, "\t");
}
diff --git a/lib/StaticAnalyzer/Core/ProgramState.cpp b/lib/StaticAnalyzer/Core/ProgramState.cpp
index 6e23668144063..1714a2744a1aa 100644
--- a/lib/StaticAnalyzer/Core/ProgramState.cpp
+++ b/lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -175,7 +175,6 @@ ProgramState::invalidateRegionsImpl(ValueList Values,
const CallEvent *Call) const {
ProgramStateManager &Mgr = getStateManager();
SubEngine* Eng = Mgr.getOwningEngine();
- InvalidatedSymbols ConstIS;
InvalidatedSymbols Invalidated;
if (!IS)
@@ -208,7 +207,7 @@ ProgramState::invalidateRegionsImpl(ValueList Values,
const StoreRef &newStore =
Mgr.StoreMgr->invalidateRegions(getStore(), Values, E, Count, LCtx, Call,
- *IS, *ITraits, NULL, NULL);
+ *IS, *ITraits, nullptr, nullptr);
return makeWithStore(newStore);
}
@@ -388,7 +387,7 @@ ProgramStateRef ProgramStateManager::getPersistentState(ProgramState &State) {
if (ProgramState *I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
return I;
- ProgramState *newState = 0;
+ ProgramState *newState = nullptr;
if (!freeStates.empty()) {
newState = freeStates.back();
freeStates.pop_back();
diff --git a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index 3606e099cec2e..77578d378fb34 100644
--- a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -45,7 +45,7 @@ public:
return *second;
}
const llvm::APSInt *getConcreteValue() const {
- return &From() == &To() ? &From() : NULL;
+ return &From() == &To() ? &From() : nullptr;
}
void Profile(llvm::FoldingSetNodeID &ID) const {
@@ -98,7 +98,7 @@ public:
/// constant then this method returns that value. Otherwise, it returns
/// NULL.
const llvm::APSInt* getConcreteValue() const {
- return ranges.isSingleton() ? ranges.begin()->getConcreteValue() : 0;
+ return ranges.isSingleton() ? ranges.begin()->getConcreteValue() : nullptr;
}
private:
@@ -290,35 +290,37 @@ public:
ProgramStateRef assumeSymNE(ProgramStateRef state, SymbolRef sym,
const llvm::APSInt& Int,
- const llvm::APSInt& Adjustment);
+ const llvm::APSInt& Adjustment) override;
ProgramStateRef assumeSymEQ(ProgramStateRef state, SymbolRef sym,
const llvm::APSInt& Int,
- const llvm::APSInt& Adjustment);
+ const llvm::APSInt& Adjustment) override;
ProgramStateRef assumeSymLT(ProgramStateRef state, SymbolRef sym,
const llvm::APSInt& Int,
- const llvm::APSInt& Adjustment);
+ const llvm::APSInt& Adjustment) override;
ProgramStateRef assumeSymGT(ProgramStateRef state, SymbolRef sym,
const llvm::APSInt& Int,
- const llvm::APSInt& Adjustment);
+ const llvm::APSInt& Adjustment) override;
ProgramStateRef assumeSymGE(ProgramStateRef state, SymbolRef sym,
const llvm::APSInt& Int,
- const llvm::APSInt& Adjustment);
+ const llvm::APSInt& Adjustment) override;
ProgramStateRef assumeSymLE(ProgramStateRef state, SymbolRef sym,
const llvm::APSInt& Int,
- const llvm::APSInt& Adjustment);
+ const llvm::APSInt& Adjustment) override;
- const llvm::APSInt* getSymVal(ProgramStateRef St, SymbolRef sym) const;
- ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym);
+ const llvm::APSInt* getSymVal(ProgramStateRef St,
+ SymbolRef sym) const override;
+ ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override;
- ProgramStateRef removeDeadBindings(ProgramStateRef St, SymbolReaper& SymReaper);
+ ProgramStateRef removeDeadBindings(ProgramStateRef St,
+ SymbolReaper& SymReaper) override;
void print(ProgramStateRef St, raw_ostream &Out,
- const char* nl, const char *sep);
+ const char* nl, const char *sep) override;
private:
RangeSet::Factory F;
@@ -334,7 +336,7 @@ ento::CreateRangeConstraintManager(ProgramStateManager &StMgr, SubEngine *Eng) {
const llvm::APSInt* RangeConstraintManager::getSymVal(ProgramStateRef St,
SymbolRef sym) const {
const ConstraintRangeTy::data_type *T = St->get<ConstraintRange>(sym);
- return T ? T->getConcreteValue() : NULL;
+ return T ? T->getConcreteValue() : nullptr;
}
ConditionTruthVal RangeConstraintManager::checkNull(ProgramStateRef State,
@@ -430,7 +432,7 @@ RangeConstraintManager::assumeSymNE(ProgramStateRef St, SymbolRef Sym,
// [Int-Adjustment+1, Int-Adjustment-1]
// Notice that the lower bound is greater than the upper bound.
RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Upper, Lower);
- return New.isEmpty() ? NULL : St->set<ConstraintRange>(Sym, New);
+ return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
ProgramStateRef
@@ -440,12 +442,12 @@ RangeConstraintManager::assumeSymEQ(ProgramStateRef St, SymbolRef Sym,
// Before we do any real work, see if the value can even show up.
APSIntType AdjustmentType(Adjustment);
if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within)
- return NULL;
+ return nullptr;
// [Int-Adjustment, Int-Adjustment]
llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment;
RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, AdjInt, AdjInt);
- return New.isEmpty() ? NULL : St->set<ConstraintRange>(Sym, New);
+ return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
ProgramStateRef
@@ -456,7 +458,7 @@ RangeConstraintManager::assumeSymLT(ProgramStateRef St, SymbolRef Sym,
APSIntType AdjustmentType(Adjustment);
switch (AdjustmentType.testInRange(Int, true)) {
case APSIntType::RTR_Below:
- return NULL;
+ return nullptr;
case APSIntType::RTR_Within:
break;
case APSIntType::RTR_Above:
@@ -467,14 +469,14 @@ RangeConstraintManager::assumeSymLT(ProgramStateRef St, SymbolRef Sym,
llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
llvm::APSInt Min = AdjustmentType.getMinValue();
if (ComparisonVal == Min)
- return NULL;
+ return nullptr;
llvm::APSInt Lower = Min-Adjustment;
llvm::APSInt Upper = ComparisonVal-Adjustment;
--Upper;
RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
- return New.isEmpty() ? NULL : St->set<ConstraintRange>(Sym, New);
+ return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
ProgramStateRef
@@ -489,21 +491,21 @@ RangeConstraintManager::assumeSymGT(ProgramStateRef St, SymbolRef Sym,
case APSIntType::RTR_Within:
break;
case APSIntType::RTR_Above:
- return NULL;
+ return nullptr;
}
// Special case for Int == Max. This is always false.
llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
llvm::APSInt Max = AdjustmentType.getMaxValue();
if (ComparisonVal == Max)
- return NULL;
+ return nullptr;
llvm::APSInt Lower = ComparisonVal-Adjustment;
llvm::APSInt Upper = Max-Adjustment;
++Lower;
RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
- return New.isEmpty() ? NULL : St->set<ConstraintRange>(Sym, New);
+ return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
ProgramStateRef
@@ -518,7 +520,7 @@ RangeConstraintManager::assumeSymGE(ProgramStateRef St, SymbolRef Sym,
case APSIntType::RTR_Within:
break;
case APSIntType::RTR_Above:
- return NULL;
+ return nullptr;
}
// Special case for Int == Min. This is always feasible.
@@ -532,7 +534,7 @@ RangeConstraintManager::assumeSymGE(ProgramStateRef St, SymbolRef Sym,
llvm::APSInt Upper = Max-Adjustment;
RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
- return New.isEmpty() ? NULL : St->set<ConstraintRange>(Sym, New);
+ return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
ProgramStateRef
@@ -543,7 +545,7 @@ RangeConstraintManager::assumeSymLE(ProgramStateRef St, SymbolRef Sym,
APSIntType AdjustmentType(Adjustment);
switch (AdjustmentType.testInRange(Int, true)) {
case APSIntType::RTR_Below:
- return NULL;
+ return nullptr;
case APSIntType::RTR_Within:
break;
case APSIntType::RTR_Above:
@@ -561,7 +563,7 @@ RangeConstraintManager::assumeSymLE(ProgramStateRef St, SymbolRef Sym,
llvm::APSInt Upper = ComparisonVal-Adjustment;
RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
- return New.isEmpty() ? NULL : St->set<ConstraintRange>(Sym, New);
+ return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
//===------------------------------------------------------------------------===
diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp
index 0b519768aa049..3bbbb3430792b 100644
--- a/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -104,7 +104,7 @@ public:
Data == X.Data;
}
- LLVM_ATTRIBUTE_USED void dump() const;
+ void dump() const;
};
} // end anonymous namespace
@@ -133,9 +133,7 @@ namespace llvm {
};
} // end llvm namespace
-void BindingKey::dump() const {
- llvm::errs() << *this;
-}
+LLVM_DUMP_METHOD void BindingKey::dump() const { llvm::errs() << *this; }
//===----------------------------------------------------------------------===//
// Actual Store type.
@@ -224,9 +222,7 @@ public:
}
}
- LLVM_ATTRIBUTE_USED void dump() const {
- dump(llvm::errs(), "\n");
- }
+ LLVM_DUMP_METHOD void dump() const { dump(llvm::errs(), "\n"); }
};
} // end anonymous namespace
@@ -266,7 +262,7 @@ RegionBindingsRef RegionBindingsRef::addBinding(const MemRegion *R,
const SVal *RegionBindingsRef::lookup(BindingKey K) const {
const ClusterBindings *Cluster = lookup(K.getBaseRegion());
if (!Cluster)
- return 0;
+ return nullptr;
return Cluster->lookup(K);
}
@@ -376,9 +372,9 @@ public:
/// version of that lvalue (i.e., a pointer to the first element of
/// the array). This is called by ExprEngine when evaluating
/// casts from arrays to pointers.
- SVal ArrayToPointer(Loc Array, QualType ElementTy);
+ SVal ArrayToPointer(Loc Array, QualType ElementTy) override;
- StoreRef getInitialStore(const LocationContext *InitLoc) {
+ StoreRef getInitialStore(const LocationContext *InitLoc) override {
return StoreRef(RBFactory.getEmptyMap().getRootWithoutRetain(), *this);
}
@@ -400,24 +396,24 @@ public:
InvalidatedSymbols &IS,
RegionAndSymbolInvalidationTraits &ITraits,
InvalidatedRegions *Invalidated,
- InvalidatedRegions *InvalidatedTopLevel);
+ InvalidatedRegions *InvalidatedTopLevel) override;
bool scanReachableSymbols(Store S, const MemRegion *R,
- ScanReachableSymbols &Callbacks);
+ ScanReachableSymbols &Callbacks) override;
RegionBindingsRef removeSubRegionBindings(RegionBindingsConstRef B,
const SubRegion *R);
public: // Part of public interface to class.
- virtual StoreRef Bind(Store store, Loc LV, SVal V) {
+ StoreRef Bind(Store store, Loc LV, SVal V) override {
return StoreRef(bind(getRegionBindings(store), LV, V).asStore(), *this);
}
RegionBindingsRef bind(RegionBindingsConstRef B, Loc LV, SVal V);
// BindDefault is only used to initialize a region with a default value.
- StoreRef BindDefault(Store store, const MemRegion *R, SVal V) {
+ StoreRef BindDefault(Store store, const MemRegion *R, SVal V) override {
RegionBindingsRef B = getRegionBindings(store);
assert(!B.lookup(R, BindingKey::Direct));
@@ -471,20 +467,20 @@ public: // Part of public interface to class.
/// \brief Create a new store with the specified binding removed.
/// \param ST the original store, that is the basis for the new store.
/// \param L the location whose binding should be removed.
- virtual StoreRef killBinding(Store ST, Loc L);
+ StoreRef killBinding(Store ST, Loc L) override;
- void incrementReferenceCount(Store store) {
+ void incrementReferenceCount(Store store) override {
getRegionBindings(store).manualRetain();
}
/// If the StoreManager supports it, decrement the reference count of
/// the specified Store object. If the reference count hits 0, the memory
/// associated with the object is recycled.
- void decrementReferenceCount(Store store) {
+ void decrementReferenceCount(Store store) override {
getRegionBindings(store).manualRelease();
}
-
- bool includedInBindings(Store store, const MemRegion *region) const;
+
+ bool includedInBindings(Store store, const MemRegion *region) const override;
/// \brief Return the value bound to specified location in a given state.
///
@@ -499,7 +495,7 @@ public: // Part of public interface to class.
/// return undefined
/// else
/// return symbolic
- virtual SVal getBinding(Store S, Loc L, QualType T) {
+ SVal getBinding(Store S, Loc L, QualType T) override {
return getBinding(getRegionBindings(S), L, T);
}
@@ -564,15 +560,16 @@ public: // Part of public interface to class.
/// removeDeadBindings - Scans the RegionStore of 'state' for dead values.
/// It returns a new Store with these values removed.
StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx,
- SymbolReaper& SymReaper);
-
+ SymbolReaper& SymReaper) override;
+
//===------------------------------------------------------------------===//
// Region "extents".
//===------------------------------------------------------------------===//
// FIXME: This method will soon be eliminated; see the note in Store.h.
DefinedOrUnknownSVal getSizeInElements(ProgramStateRef state,
- const MemRegion* R, QualType EleTy);
+ const MemRegion* R,
+ QualType EleTy) override;
//===------------------------------------------------------------------===//
// Utility methods.
@@ -585,9 +582,9 @@ public: // Part of public interface to class.
}
void print(Store store, raw_ostream &Out, const char* nl,
- const char *sep);
+ const char *sep) override;
- void iterBindings(Store store, BindingsHandler& f) {
+ void iterBindings(Store store, BindingsHandler& f) override {
RegionBindingsRef B = getRegionBindings(store);
for (RegionBindingsRef::iterator I = B.begin(), E = B.end(); I != E; ++I) {
const ClusterBindings &Cluster = I.getData();
@@ -1016,7 +1013,7 @@ void invalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
BI != BE; ++BI) {
const VarRegion *VR = BI.getCapturedRegion();
const VarDecl *VD = VR->getDecl();
- if (VD->getAttr<BlocksAttr>() || !VD->hasLocalStorage()) {
+ if (VD->hasAttr<BlocksAttr>() || !VD->hasLocalStorage()) {
AddToWorkList(VR);
}
else if (Loc::isLocType(VR->getValueType())) {
@@ -1628,9 +1625,9 @@ RegionStoreManager::getBindingForFieldOrElementCommon(RegionBindingsConstRef B,
// getBindingForField if 'R' has a direct binding.
// Lazy binding?
- Store lazyBindingStore = NULL;
- const SubRegion *lazyBindingRegion = NULL;
- llvm::tie(lazyBindingStore, lazyBindingRegion) = findLazyBinding(B, R, R);
+ Store lazyBindingStore = nullptr;
+ const SubRegion *lazyBindingRegion = nullptr;
+ std::tie(lazyBindingStore, lazyBindingRegion) = findLazyBinding(B, R, R);
if (lazyBindingRegion)
return getLazyBinding(lazyBindingRegion,
getRegionBindings(lazyBindingStore));
@@ -1791,7 +1788,7 @@ RegionStoreManager::getInterestingValues(nonloc::LazyCompoundVal LCV) {
// values to return.
const ClusterBindings *Cluster = B.lookup(LazyR->getBaseRegion());
if (!Cluster)
- return (LazyBindingsMap[LCV.getCVData()] = llvm_move(List));
+ return (LazyBindingsMap[LCV.getCVData()] = std::move(List));
SmallVector<BindingPair, 32> Bindings;
collectSubRegionBindings(Bindings, svalBuilder, *Cluster, LazyR,
@@ -1813,7 +1810,7 @@ RegionStoreManager::getInterestingValues(nonloc::LazyCompoundVal LCV) {
List.push_back(V);
}
- return (LazyBindingsMap[LCV.getCVData()] = llvm_move(List));
+ return (LazyBindingsMap[LCV.getCVData()] = std::move(List));
}
NonLoc RegionStoreManager::createLazyBinding(RegionBindingsConstRef B,
@@ -2066,9 +2063,7 @@ RegionStoreManager::tryBindSmallStruct(RegionBindingsConstRef B,
if (Class->getNumBases() != 0 || Class->getNumVBases() != 0)
return None;
- for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
- I != E; ++I) {
- const FieldDecl *FD = *I;
+ for (const auto *FD : RD->fields()) {
if (FD->isUnnamedBitfield())
continue;
@@ -2081,7 +2076,7 @@ RegionStoreManager::tryBindSmallStruct(RegionBindingsConstRef B,
if (!(Ty->isScalarType() || Ty->isReferenceType()))
return None;
- Fields.push_back(*I);
+ Fields.push_back(FD);
}
RegionBindingsRef NewB = B;
@@ -2296,7 +2291,7 @@ bool removeDeadBindingsWorker::UpdatePostponed() {
if (const SymbolicRegion *SR = *I) {
if (SymReaper.isLive(SR->getSymbol())) {
changed |= AddToWorkList(SR);
- *I = NULL;
+ *I = nullptr;
}
}
}
diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp
index adc54659911ae..3ed2bde1e4f84 100644
--- a/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -362,7 +362,7 @@ SVal SValBuilder::evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
DefinedOrUnknownSVal SValBuilder::evalEQ(ProgramStateRef state,
DefinedOrUnknownSVal lhs,
DefinedOrUnknownSVal rhs) {
- return evalBinOp(state, BO_EQ, lhs, rhs, Context.IntTy)
+ return evalBinOp(state, BO_EQ, lhs, rhs, getConditionType())
.castAs<DefinedOrUnknownSVal>();
}
@@ -376,7 +376,7 @@ static bool shouldBeModeledWithNoOp(ASTContext &Context, QualType ToTy,
ToTy = Context.getUnqualifiedArrayType(ToTy, Quals1);
FromTy = Context.getUnqualifiedArrayType(FromTy, Quals2);
- // Make sure that non cvr-qualifiers the other qualifiers (e.g., address
+ // Make sure that non-cvr-qualifiers the other qualifiers (e.g., address
// spaces) are identical.
Quals1.removeCVRQualifiers();
Quals2.removeCVRQualifiers();
diff --git a/lib/StaticAnalyzer/Core/SVals.cpp b/lib/StaticAnalyzer/Core/SVals.cpp
index 650691535f7e6..8de939f47d86f 100644
--- a/lib/StaticAnalyzer/Core/SVals.cpp
+++ b/lib/StaticAnalyzer/Core/SVals.cpp
@@ -56,7 +56,7 @@ const FunctionDecl *SVal::getAsFunctionDecl() const {
return FD;
}
- return 0;
+ return nullptr;
}
/// \brief If this SVal is a location (subclasses Loc) and wraps a symbol,
@@ -78,7 +78,7 @@ SymbolRef SVal::getAsLocSymbol(bool IncludeBaseRegions) const {
dyn_cast<SymbolicRegion>(R->StripCasts()))
return SymR->getSymbol();
}
- return 0;
+ return nullptr;
}
/// Get the symbol in the SVal or its base region.
@@ -86,7 +86,7 @@ SymbolRef SVal::getLocSymbolInBase() const {
Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>();
if (!X)
- return 0;
+ return nullptr;
const MemRegion *R = X->getRegion();
@@ -97,7 +97,7 @@ SymbolRef SVal::getLocSymbolInBase() const {
R = SR->getSuperRegion();
}
- return 0;
+ return nullptr;
}
// TODO: The next 3 functions have to be simplified.
@@ -139,12 +139,12 @@ const MemRegion *SVal::getAsRegion() const {
if (Optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
return X->getLoc().getAsRegion();
- return 0;
+ return nullptr;
}
const MemRegion *loc::MemRegionVal::stripCasts(bool StripBaseCasts) const {
const MemRegion *R = getRegion();
- return R ? R->StripCasts(StripBaseCasts) : NULL;
+ return R ? R->StripCasts(StripBaseCasts) : nullptr;
}
const void *nonloc::LazyCompoundVal::getStore() const {
diff --git a/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp b/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
index e6653ae6e4b56..35930e47f82a0 100644
--- a/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
+++ b/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
@@ -181,7 +181,7 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
case nonloc::ConcreteIntKind: {
bool b = Cond.castAs<nonloc::ConcreteInt>().getValue() != 0;
bool isFeasible = b ? Assumption : !Assumption;
- return isFeasible ? state : NULL;
+ return isFeasible ? state : nullptr;
}
case nonloc::LocAsIntegerKind:
diff --git a/lib/StaticAnalyzer/Core/SimpleConstraintManager.h b/lib/StaticAnalyzer/Core/SimpleConstraintManager.h
index 28a9a4ded9dec..21e2283511ae7 100644
--- a/lib/StaticAnalyzer/Core/SimpleConstraintManager.h
+++ b/lib/StaticAnalyzer/Core/SimpleConstraintManager.h
@@ -34,7 +34,7 @@ public:
//===------------------------------------------------------------------===//
ProgramStateRef assume(ProgramStateRef state, DefinedSVal Cond,
- bool Assumption);
+ bool Assumption) override;
ProgramStateRef assume(ProgramStateRef state, NonLoc Cond, bool Assumption);
@@ -82,7 +82,7 @@ protected:
BasicValueFactory &getBasicVals() const { return SVB.getBasicValueFactory(); }
SymbolManager &getSymbolManager() const { return SVB.getSymbolManager(); }
- bool canReasonAbout(SVal X) const;
+ bool canReasonAbout(SVal X) const override;
ProgramStateRef assumeAux(ProgramStateRef state,
NonLoc Cond,
diff --git a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
index cc0ee0b5c7a91..df9e4d6f91997 100644
--- a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -21,9 +21,9 @@ using namespace ento;
namespace {
class SimpleSValBuilder : public SValBuilder {
protected:
- virtual SVal dispatchCast(SVal val, QualType castTy);
- virtual SVal evalCastFromNonLoc(NonLoc val, QualType castTy);
- virtual SVal evalCastFromLoc(Loc val, QualType castTy);
+ SVal dispatchCast(SVal val, QualType castTy) override;
+ SVal evalCastFromNonLoc(NonLoc val, QualType castTy) override;
+ SVal evalCastFromLoc(Loc val, QualType castTy) override;
public:
SimpleSValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
@@ -31,19 +31,19 @@ public:
: SValBuilder(alloc, context, stateMgr) {}
virtual ~SimpleSValBuilder() {}
- virtual SVal evalMinus(NonLoc val);
- virtual SVal evalComplement(NonLoc val);
- virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op,
- NonLoc lhs, NonLoc rhs, QualType resultTy);
- virtual SVal evalBinOpLL(ProgramStateRef state, BinaryOperator::Opcode op,
- Loc lhs, Loc rhs, QualType resultTy);
- virtual SVal evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op,
- Loc lhs, NonLoc rhs, QualType resultTy);
+ SVal evalMinus(NonLoc val) override;
+ SVal evalComplement(NonLoc val) override;
+ SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op,
+ NonLoc lhs, NonLoc rhs, QualType resultTy) override;
+ SVal evalBinOpLL(ProgramStateRef state, BinaryOperator::Opcode op,
+ Loc lhs, Loc rhs, QualType resultTy) override;
+ SVal evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op,
+ Loc lhs, NonLoc rhs, QualType resultTy) override;
/// getKnownValue - evaluates a given SVal. If the SVal has only one possible
/// (integer) value, that value is returned. Otherwise, returns NULL.
- virtual const llvm::APSInt *getKnownValue(ProgramStateRef state, SVal V);
-
+ const llvm::APSInt *getKnownValue(ProgramStateRef state, SVal V) override;
+
SVal MakeSymIntVal(const SymExpr *LHS, BinaryOperator::Opcode op,
const llvm::APSInt &RHS, QualType resultTy);
};
@@ -97,7 +97,7 @@ SVal SimpleSValBuilder::evalCastFromNonLoc(NonLoc val, QualType castTy) {
return UnknownVal();
}
- // If value is a non integer constant, produce unknown.
+ // If value is a non-integer constant, produce unknown.
if (!val.getAs<nonloc::ConcreteInt>())
return UnknownVal();
@@ -108,7 +108,7 @@ SVal SimpleSValBuilder::evalCastFromNonLoc(NonLoc val, QualType castTy) {
}
// Only handle casts from integers to integers - if val is an integer constant
- // being cast to a non integer type, produce unknown.
+ // being cast to a non-integer type, produce unknown.
if (!isLocType && !castTy->isIntegralOrEnumerationType())
return UnknownVal();
@@ -158,7 +158,7 @@ SVal SimpleSValBuilder::evalCastFromLoc(Loc val, QualType castTy) {
}
case loc::GotoLabelKind:
- // Labels and non symbolic memory regions are always true.
+ // Labels and non-symbolic memory regions are always true.
return makeTruthVal(true, castTy);
}
}
@@ -569,11 +569,10 @@ static SVal evalBinOpFieldRegionFieldRegion(const FieldRegion *LeftFR,
// members and the units in which bit-fields reside have addresses that
// increase in the order in which they are declared."
bool leftFirst = (op == BO_LT || op == BO_LE);
- for (RecordDecl::field_iterator I = RD->field_begin(),
- E = RD->field_end(); I!=E; ++I) {
- if (*I == LeftFD)
+ for (const auto *I : RD->fields()) {
+ if (I == LeftFD)
return SVB.makeTruthVal(leftFirst, resultTy);
- if (*I == RightFD)
+ if (I == RightFD)
return SVB.makeTruthVal(!leftFirst, resultTy);
}
@@ -818,7 +817,7 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
RegionOffset LeftOffset = LeftMR->getAsOffset();
RegionOffset RightOffset = RightMR->getAsOffset();
- if (LeftOffset.getRegion() != NULL &&
+ if (LeftOffset.getRegion() != nullptr &&
LeftOffset.getRegion() == RightOffset.getRegion() &&
!LeftOffset.hasSymbolicOffset() && !RightOffset.hasSymbolicOffset()) {
int64_t left = LeftOffset.getOffset();
@@ -901,7 +900,7 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
if (const MemRegion *region = lhs.getAsRegion()) {
rhs = convertToArrayIndex(rhs).castAs<NonLoc>();
SVal index = UnknownVal();
- const MemRegion *superR = 0;
+ const MemRegion *superR = nullptr;
QualType elementType;
if (const ElementRegion *elemReg = dyn_cast<ElementRegion>(region)) {
@@ -929,7 +928,7 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
const llvm::APSInt *SimpleSValBuilder::getKnownValue(ProgramStateRef state,
SVal V) {
if (V.isUnknownOrUndef())
- return NULL;
+ return nullptr;
if (Optional<loc::ConcreteInt> X = V.getAs<loc::ConcreteInt>())
return &X->getValue();
@@ -941,5 +940,5 @@ const llvm::APSInt *SimpleSValBuilder::getKnownValue(ProgramStateRef state,
return state->getConstraintManager().getSymVal(state, Sym);
// FIXME: Add support for SymExprs.
- return NULL;
+ return nullptr;
}
diff --git a/lib/StaticAnalyzer/Core/Store.cpp b/lib/StaticAnalyzer/Core/Store.cpp
index 0beb9dbbc5be6..e38be3e0b7dd9 100644
--- a/lib/StaticAnalyzer/Core/Store.cpp
+++ b/lib/StaticAnalyzer/Core/Store.cpp
@@ -88,7 +88,7 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy)
// We don't know what to make of it. Return a NULL region, which
// will be interpretted as UnknownVal.
- return NULL;
+ return nullptr;
}
// Now assume we are casting from pointer to pointer. Other cases should
@@ -166,7 +166,7 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy)
// If we cannot compute a raw offset, throw up our hands and return
// a NULL MemRegion*.
if (!baseR)
- return NULL;
+ return nullptr;
CharUnits off = rawOff.getOffset();
@@ -193,7 +193,7 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy)
// Compute the index for the new ElementRegion.
int64_t newIndex = 0;
- const MemRegion *newSuperR = 0;
+ const MemRegion *newSuperR = nullptr;
// We can only compute sizeof(PointeeTy) if it is a complete type.
if (IsCompleteType(Ctx, PointeeTy)) {
@@ -300,7 +300,7 @@ static const CXXRecordDecl *getCXXRecordType(const MemRegion *MR) {
return TVR->getValueType()->getAsCXXRecordDecl();
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
return SR->getSymbol()->getType()->getPointeeCXXRecordDecl();
- return 0;
+ return nullptr;
}
SVal StoreManager::evalDynamicCast(SVal Base, QualType TargetType,
@@ -401,7 +401,7 @@ SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) {
return Base;
Loc BaseL = Base.castAs<Loc>();
- const MemRegion* BaseR = 0;
+ const MemRegion* BaseR = nullptr;
switch (BaseL.getSubKind()) {
case loc::MemRegionKind:
diff --git a/lib/StaticAnalyzer/Core/SymbolManager.cpp b/lib/StaticAnalyzer/Core/SymbolManager.cpp
index 1b56f82dc60fc..cca0461a47486 100644
--- a/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ b/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -326,11 +326,7 @@ QualType SymbolRegionValue::getType() const {
}
SymbolManager::~SymbolManager() {
- for (SymbolDependTy::const_iterator I = SymbolDependencies.begin(),
- E = SymbolDependencies.end(); I != E; ++I) {
- delete I->second;
- }
-
+ llvm::DeleteContainerSeconds(SymbolDependencies);
}
bool SymbolManager::canSymbolicate(QualType T) {
@@ -351,7 +347,7 @@ bool SymbolManager::canSymbolicate(QualType T) {
void SymbolManager::addSymbolDependency(const SymbolRef Primary,
const SymbolRef Dependent) {
SymbolDependTy::iterator I = SymbolDependencies.find(Primary);
- SymbolRefSmallVectorTy *dependencies = 0;
+ SymbolRefSmallVectorTy *dependencies = nullptr;
if (I == SymbolDependencies.end()) {
dependencies = new SymbolRefSmallVectorTy();
SymbolDependencies[Primary] = dependencies;
@@ -365,7 +361,7 @@ const SymbolRefSmallVectorTy *SymbolManager::getDependentSymbols(
const SymbolRef Primary) {
SymbolDependTy::const_iterator I = SymbolDependencies.find(Primary);
if (I == SymbolDependencies.end())
- return 0;
+ return nullptr;
return I->second;
}
@@ -491,7 +487,7 @@ bool SymbolReaper::isLive(SymbolRef sym) {
bool
SymbolReaper::isLive(const Stmt *ExprVal, const LocationContext *ELCtx) const {
- if (LCtx == 0)
+ if (LCtx == nullptr)
return false;
if (LCtx != ELCtx) {