aboutsummaryrefslogtreecommitdiffstats
path: root/include/clang/StaticAnalyzer/Core/PathSensitive
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-10-23 17:52:09 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-10-23 17:52:09 +0000
commit519fc96c475680de2cc49e7811dbbfadb912cbcc (patch)
tree310ca684459b7e9ae13c9a3b9abf308b3a634afe /include/clang/StaticAnalyzer/Core/PathSensitive
parent2298981669bf3bd63335a4be179bc0f96823a8f4 (diff)
downloadsrc-vendor/clang.tar.gz
src-vendor/clang.zip
Vendor import of stripped clang trunk r375505, the last commit beforevendor/clang/clang-trunk-r375505vendor/clang
the upstream Subversion repository was made read-only, and the LLVM project migrated to GitHub: https://llvm.org/svn/llvm-project/cfe/trunk@375505
Notes
Notes: svn path=/vendor/clang/dist/; revision=353942 svn path=/vendor/clang/clang-r375505/; revision=353943; tag=vendor/clang/clang-trunk-r375505
Diffstat (limited to 'include/clang/StaticAnalyzer/Core/PathSensitive')
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h9
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h27
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h17
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/DynamicCastInfo.h55
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h73
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h46
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h63
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h54
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h10
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h4
11 files changed, 253 insertions, 111 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
index b0dda78a00a9..d605a6a667f6 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -15,9 +15,9 @@
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ANALYSISMANAGER_H
#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
namespace clang {
@@ -32,7 +32,6 @@ class AnalysisManager : public BugReporterData {
AnalysisDeclContextManager AnaCtxMgr;
ASTContext &Ctx;
- DiagnosticsEngine &Diags;
const LangOptions &LangOpts;
PathDiagnosticConsumers PathConsumers;
@@ -45,7 +44,7 @@ class AnalysisManager : public BugReporterData {
public:
AnalyzerOptions &options;
- AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
+ AnalysisManager(ASTContext &ctx,
const PathDiagnosticConsumers &Consumers,
StoreManagerCreator storemgr,
ConstraintManagerCreator constraintmgr,
@@ -84,10 +83,6 @@ public:
return getASTContext().getSourceManager();
}
- DiagnosticsEngine &getDiagnostic() override {
- return Diags;
- }
-
const LangOptions &getLangOpts() const {
return LangOpts;
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index db84102983af..fc1cc9138826 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -347,7 +347,7 @@ public:
ProgramStateRef invalidateRegions(unsigned BlockCount,
ProgramStateRef Orig = nullptr) const;
- using FrameBindingTy = std::pair<Loc, SVal>;
+ using FrameBindingTy = std::pair<SVal, SVal>;
using BindingsTy = SmallVectorImpl<FrameBindingTy>;
/// Populates the given SmallVector with the bindings in the callee's stack
@@ -386,11 +386,12 @@ public:
/// during analysis if the call is inlined, but it may still be useful
/// in intermediate calculations even if the call isn't inlined.
/// May fail; returns null on failure.
- const StackFrameContext *getCalleeStackFrame() const;
+ const StackFrameContext *getCalleeStackFrame(unsigned BlockCount) const;
/// Returns memory location for a parameter variable within the callee stack
/// frame. May fail; returns null on failure.
- const VarRegion *getParameterLocation(unsigned Index) const;
+ const VarRegion *getParameterLocation(unsigned Index,
+ unsigned BlockCount) const;
/// Returns true if on the current path, the argument was constructed by
/// calling a C++ constructor over it. This is an internal detail of the
@@ -1063,8 +1064,19 @@ class CallDescription {
// e.g. "{a, b}" represent the qualified names, like "a::b".
std::vector<const char *> QualifiedName;
Optional<unsigned> RequiredArgs;
+ Optional<size_t> RequiredParams;
int Flags;
+ // A constructor helper.
+ static Optional<size_t> readRequiredParams(Optional<unsigned> RequiredArgs,
+ Optional<size_t> RequiredParams) {
+ if (RequiredParams)
+ return RequiredParams;
+ if (RequiredArgs)
+ return static_cast<size_t>(*RequiredArgs);
+ return None;
+ }
+
public:
/// Constructs a CallDescription object.
///
@@ -1077,14 +1089,17 @@ public:
/// call. Omit this parameter to match every occurrence of call with a given
/// name regardless the number of arguments.
CallDescription(int Flags, ArrayRef<const char *> QualifiedName,
- Optional<unsigned> RequiredArgs = None)
+ Optional<unsigned> RequiredArgs = None,
+ Optional<size_t> RequiredParams = None)
: QualifiedName(QualifiedName), RequiredArgs(RequiredArgs),
+ RequiredParams(readRequiredParams(RequiredArgs, RequiredParams)),
Flags(Flags) {}
/// Construct a CallDescription with default flags.
CallDescription(ArrayRef<const char *> QualifiedName,
- Optional<unsigned> RequiredArgs = None)
- : CallDescription(0, QualifiedName, RequiredArgs) {}
+ Optional<unsigned> RequiredArgs = None,
+ Optional<size_t> RequiredParams = None)
+ : CallDescription(0, QualifiedName, RequiredArgs, RequiredParams) {}
/// Get the name of the function that this object matches.
StringRef getFunctionName() const { return QualifiedName.back(); }
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
index 981133e66977..7f4df0d88def 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -103,7 +103,7 @@ public:
return Eng.getBugReporter();
}
- SourceManager &getSourceManager() {
+ const SourceManager &getSourceManager() {
return getBugReporter().getSourceManager();
}
@@ -234,7 +234,7 @@ public:
}
/// A shorthand version of getNoteTag that doesn't require you to accept
- /// the BugReporterContext arguments when you don't need it.
+ /// the 'BugReporterContext' argument when you don't need it.
///
/// @param Cb Callback only with 'BugReport &' parameter.
/// @param IsPrunable Whether the note is prunable. It allows BugReporter
@@ -247,6 +247,19 @@ public:
IsPrunable);
}
+ /// A shorthand version of getNoteTag that doesn't require you to accept
+ /// the arguments when you don't need it.
+ ///
+ /// @param Cb Callback without parameters.
+ /// @param IsPrunable Whether the note is prunable. It allows BugReporter
+ /// to omit the note from the report if it would make the displayed
+ /// bug path significantly shorter.
+ const NoteTag *getNoteTag(std::function<std::string()> &&Cb,
+ bool IsPrunable = false) {
+ return getNoteTag([Cb](BugReporterContext &, BugReport &) { return Cb(); },
+ IsPrunable);
+ }
+
/// A shorthand version of getNoteTag that accepts a plain note.
///
/// @param Note The note.
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicCastInfo.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicCastInfo.h
new file mode 100644
index 000000000000..f5a710c77a6a
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicCastInfo.h
@@ -0,0 +1,55 @@
+//===- DynamicCastInfo.h - Runtime cast information -------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICCASTINFO_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICCASTINFO_H
+
+#include "clang/AST/Type.h"
+
+namespace clang {
+namespace ento {
+
+class DynamicCastInfo {
+public:
+ enum CastResult { Success, Failure };
+
+ DynamicCastInfo(QualType from, QualType to, CastResult resultKind)
+ : From(from), To(to), ResultKind(resultKind) {}
+
+ QualType from() const { return From; }
+ QualType to() const { return To; }
+
+ bool equals(QualType from, QualType to) const {
+ return From == from && To == to;
+ }
+
+ bool succeeds() const { return ResultKind == CastResult::Success; }
+ bool fails() const { return ResultKind == CastResult::Failure; }
+
+ bool operator==(const DynamicCastInfo &RHS) const {
+ return From == RHS.From && To == RHS.To;
+ }
+ bool operator<(const DynamicCastInfo &RHS) const {
+ return From < RHS.From && To < RHS.To;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.Add(From);
+ ID.Add(To);
+ ID.AddInteger(ResultKind);
+ }
+
+private:
+ QualType From, To;
+ CastResult ResultKind;
+};
+
+} // namespace ento
+} // namespace clang
+
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICCASTINFO_H
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h
new file mode 100644
index 000000000000..356401d77561
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h
@@ -0,0 +1,73 @@
+//===- DynamicType.h - Dynamic type related APIs ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines APIs that track and query dynamic type information. This
+// information can be used to devirtualize calls during the symbolic execution
+// or do type checking.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPE_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPE_H
+
+#include "clang/AST/Type.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicCastInfo.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/Optional.h"
+#include <utility>
+
+namespace clang {
+namespace ento {
+
+/// Get dynamic type information for the region \p MR.
+DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State, const MemRegion *MR);
+
+/// Get raw dynamic type information for the region \p MR.
+const DynamicTypeInfo *getRawDynamicTypeInfo(ProgramStateRef State,
+ const MemRegion *MR);
+
+/// Get dynamic cast information from \p CastFromTy to \p CastToTy of \p MR.
+const DynamicCastInfo *getDynamicCastInfo(ProgramStateRef State,
+ const MemRegion *MR,
+ QualType CastFromTy,
+ QualType CastToTy);
+
+/// Set dynamic type information of the region; return the new state.
+ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *MR,
+ DynamicTypeInfo NewTy);
+
+/// Set dynamic type information of the region; return the new state.
+ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *MR,
+ QualType NewTy, bool CanBeSubClassed = true);
+
+/// Set dynamic type and cast information of the region; return the new state.
+ProgramStateRef setDynamicTypeAndCastInfo(ProgramStateRef State,
+ const MemRegion *MR,
+ QualType CastFromTy,
+ QualType CastToTy,
+ bool IsCastSucceeds);
+
+/// Removes the dead type informations from \p State.
+ProgramStateRef removeDeadTypes(ProgramStateRef State, SymbolReaper &SR);
+
+/// Removes the dead cast informations from \p State.
+ProgramStateRef removeDeadCasts(ProgramStateRef State, SymbolReaper &SR);
+
+void printDynamicTypeInfoJson(raw_ostream &Out, ProgramStateRef State,
+ const char *NL = "\n", unsigned int Space = 0,
+ bool IsDot = false);
+
+} // namespace ento
+} // namespace clang
+
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPE_H
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h
index 9bb1e2137566..6262c4a1ce37 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h
@@ -1,10 +1,11 @@
-//== DynamicTypeInfo.h - Runtime type information ----------------*- C++ -*--=//
+//===- DynamicTypeInfo.h - Runtime type information -------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEINFO_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEINFO_H
@@ -16,36 +17,37 @@ namespace ento {
/// Stores the currently inferred strictest bound on the runtime type
/// of a region in a given state along the analysis path.
class DynamicTypeInfo {
-private:
- QualType T;
- bool CanBeASubClass;
-
public:
+ DynamicTypeInfo() : DynTy(QualType()) {}
- DynamicTypeInfo() : T(QualType()) {}
- DynamicTypeInfo(QualType WithType, bool CanBeSub = true)
- : T(WithType), CanBeASubClass(CanBeSub) {}
+ DynamicTypeInfo(QualType Ty, bool CanBeSub = true)
+ : DynTy(Ty), CanBeASubClass(CanBeSub) {}
+
+ /// Returns false if the type information is precise (the type 'DynTy' is
+ /// the only type in the lattice), true otherwise.
+ bool canBeASubClass() const { return CanBeASubClass; }
- /// Return false if no dynamic type info is available.
- bool isValid() const { return !T.isNull(); }
+ /// Returns true if the dynamic type info is available.
+ bool isValid() const { return !DynTy.isNull(); }
/// Returns the currently inferred upper bound on the runtime type.
- QualType getType() const { return T; }
+ QualType getType() const { return DynTy; }
- /// Returns false if the type information is precise (the type T is
- /// the only type in the lattice), true otherwise.
- bool canBeASubClass() const { return CanBeASubClass; }
+ bool operator==(const DynamicTypeInfo &RHS) const {
+ return DynTy == RHS.DynTy && CanBeASubClass == RHS.CanBeASubClass;
+ }
void Profile(llvm::FoldingSetNodeID &ID) const {
- ID.Add(T);
- ID.AddInteger((unsigned)CanBeASubClass);
- }
- bool operator==(const DynamicTypeInfo &X) const {
- return T == X.T && CanBeASubClass == X.CanBeASubClass;
+ ID.Add(DynTy);
+ ID.AddBoolean(CanBeASubClass);
}
+
+private:
+ QualType DynTy;
+ bool CanBeASubClass;
};
-} // end ento
-} // end clang
+} // namespace ento
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEINFO_H
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
deleted file mode 100644
index a84b24872061..000000000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//===- DynamicTypeMap.h - Dynamic type map ----------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides APIs for tracking dynamic type information.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
-
-#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
-#include "llvm/ADT/ImmutableMap.h"
-#include "clang/AST/Type.h"
-
-namespace clang {
-namespace ento {
-
-class MemRegion;
-
-/// The GDM component containing the dynamic type info. This is a map from a
-/// symbol to its most likely type.
-struct DynamicTypeMap {};
-
-using DynamicTypeMapTy = llvm::ImmutableMap<const MemRegion *, DynamicTypeInfo>;
-
-template <>
-struct ProgramStateTrait<DynamicTypeMap>
- : public ProgramStatePartialTrait<DynamicTypeMapTy> {
- static void *GDMIndex();
-};
-
-/// Get dynamic type information for a region.
-DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State,
- const MemRegion *Reg);
-
-/// Set dynamic type information of the region; return the new state.
-ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg,
- DynamicTypeInfo NewTy);
-
-/// Set dynamic type information of the region; return the new state.
-inline ProgramStateRef setDynamicTypeInfo(ProgramStateRef State,
- const MemRegion *Reg, QualType NewTy,
- bool CanBeSubClassed = true) {
- return setDynamicTypeInfo(State, Reg,
- DynamicTypeInfo(NewTy, CanBeSubClassed));
-}
-
-void printDynamicTypeInfoJson(raw_ostream &Out, ProgramStateRef State,
- const char *NL = "\n", unsigned int Space = 0,
- bool IsDot = false);
-
-} // namespace ento
-} // namespace clang
-
-#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index 727d04cba278..e87772c04b9b 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -131,10 +131,12 @@ class ExplodedNode : public llvm::FoldingSetNode {
/// Succs - The successors of this node.
NodeGroup Succs;
+ int64_t Id;
+
public:
explicit ExplodedNode(const ProgramPoint &loc, ProgramStateRef state,
- bool IsSink)
- : Location(loc), State(std::move(state)), Succs(IsSink) {
+ int64_t Id, bool IsSink)
+ : Location(loc), State(std::move(state)), Succs(IsSink), Id(Id) {
assert(isSink() == IsSink);
}
@@ -153,7 +155,11 @@ public:
CFG &getCFG() const { return *getLocationContext()->getCFG(); }
- ParentMap &getParentMap() const {return getLocationContext()->getParentMap();}
+ const CFGBlock *getCFGBlock() const;
+
+ const ParentMap &getParentMap() const {
+ return getLocationContext()->getParentMap();
+ }
template <typename T>
T &getAnalysis() const {
@@ -219,12 +225,20 @@ public:
// Iterators over successor and predecessor vertices.
using succ_iterator = ExplodedNode * const *;
+ using succ_range = llvm::iterator_range<succ_iterator>;
+
using const_succ_iterator = const ExplodedNode * const *;
+ using const_succ_range = llvm::iterator_range<const_succ_iterator>;
+
using pred_iterator = ExplodedNode * const *;
+ using pred_range = llvm::iterator_range<pred_iterator>;
+
using const_pred_iterator = const ExplodedNode * const *;
+ using const_pred_range = llvm::iterator_range<const_pred_iterator>;
pred_iterator pred_begin() { return Preds.begin(); }
pred_iterator pred_end() { return Preds.end(); }
+ pred_range preds() { return {Preds.begin(), Preds.end()}; }
const_pred_iterator pred_begin() const {
return const_cast<ExplodedNode*>(this)->pred_begin();
@@ -232,9 +246,11 @@ public:
const_pred_iterator pred_end() const {
return const_cast<ExplodedNode*>(this)->pred_end();
}
+ const_pred_range preds() const { return {Preds.begin(), Preds.end()}; }
succ_iterator succ_begin() { return Succs.begin(); }
succ_iterator succ_end() { return Succs.end(); }
+ succ_range succs() { return {Succs.begin(), Succs.end()}; }
const_succ_iterator succ_begin() const {
return const_cast<ExplodedNode*>(this)->succ_begin();
@@ -242,8 +258,9 @@ public:
const_succ_iterator succ_end() const {
return const_cast<ExplodedNode*>(this)->succ_end();
}
+ const_succ_range succs() const { return {Succs.begin(), Succs.end()}; }
- int64_t getID(ExplodedGraph *G) const;
+ int64_t getID() const { return Id; }
/// The node is trivial if it has only one successor, only one predecessor,
/// it's predecessor has only one successor,
@@ -252,6 +269,30 @@ public:
/// Trivial nodes may be skipped while printing exploded graph.
bool isTrivial() const;
+ /// If the node's program point corresponds to a statement, retrieve that
+ /// statement. Useful for figuring out where to put a warning or a note.
+ /// If the statement belongs to a body-farmed definition,
+ /// retrieve the call site for that definition.
+ const Stmt *getStmtForDiagnostics() const;
+
+ /// Find the next statement that was executed on this node's execution path.
+ /// Useful for explaining control flow that follows the current node.
+ /// If the statement belongs to a body-farmed definition, retrieve the
+ /// call site for that definition.
+ const Stmt *getNextStmtForDiagnostics() const;
+
+ /// Find the statement that was executed immediately before this node.
+ /// Useful when the node corresponds to a CFG block entrance.
+ /// If the statement belongs to a body-farmed definition, retrieve the
+ /// call site for that definition.
+ const Stmt *getPreviousStmtForDiagnostics() const;
+
+ /// Find the statement that was executed at or immediately before this node.
+ /// Useful when any nearby statement will do.
+ /// If the statement belongs to a body-farmed definition, retrieve the
+ /// call site for that definition.
+ const Stmt *getCurrentOrPreviousStmtForDiagnostics() const;
+
private:
void replaceSuccessor(ExplodedNode *node) { Succs.replaceNode(node); }
void replacePredecessor(ExplodedNode *node) { Preds.replaceNode(node); }
@@ -285,7 +326,7 @@ protected:
BumpVectorContext BVC;
/// NumNodes - The number of nodes in the graph.
- unsigned NumNodes = 0;
+ int64_t NumNodes = 0;
/// A list of recently allocated nodes that can potentially be recycled.
NodeVector ChangedNodes;
@@ -319,10 +360,11 @@ public:
/// ExplodedGraph for further processing.
ExplodedNode *createUncachedNode(const ProgramPoint &L,
ProgramStateRef State,
+ int64_t Id,
bool IsSink = false);
std::unique_ptr<ExplodedGraph> MakeEmptyGraph() const {
- return llvm::make_unique<ExplodedGraph>();
+ return std::make_unique<ExplodedGraph>();
}
/// addRoot - Add an untyped node to the set of roots.
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 2629d7121de4..2d0967616ff2 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -145,9 +145,9 @@ private:
ObjCNoReturn ObjCNoRet;
/// The BugReporter associated with this engine. It is important that
- /// this object be placed at the very end of member variables so that its
- /// destructor is called before the rest of the ExprEngine is destroyed.
- GRBugReporter BR;
+ /// this object be placed at the very end of member variables so that its
+ /// destructor is called before the rest of the ExprEngine is destroyed.
+ PathSensitiveBugReporter BR;
/// The functions which have been analyzed through inlining. This is owned by
/// AnalysisConsumer. It can be null.
@@ -530,7 +530,7 @@ public:
void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest,
const Stmt *S, bool IsBaseDtor,
ExplodedNode *Pred, ExplodedNodeSet &Dst,
- const EvalCallOptions &Options);
+ EvalCallOptions &Options);
void VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,
ExplodedNode *Pred,
@@ -666,7 +666,7 @@ public:
const LocationContext *LCtx,
ProgramStateRef State);
- /// Evaluate a call, running pre- and post-call checks and allowing checkers
+ /// Evaluate a call, running pre- and post-call checkers and allowing checkers
/// to be responsible for handling the evaluation of the call itself.
void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
const CallEvent &Call);
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index 071e35085a5f..71cbbe28fc25 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -169,6 +169,7 @@ public:
Kind getKind() const { return kind; }
template<typename RegionTy> const RegionTy* getAs() const;
+ template<typename RegionTy> const RegionTy* castAs() const;
virtual bool isBoundable() const { return false; }
@@ -1231,6 +1232,11 @@ const RegionTy* MemRegion::getAs() const {
return nullptr;
}
+template<typename RegionTy>
+const RegionTy* MemRegion::castAs() const {
+ return cast<RegionTy>(this);
+}
+
//===----------------------------------------------------------------------===//
// MemRegionManager - Factory object for creating regions.
//===----------------------------------------------------------------------===//
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index d38058f9af56..07920790c80a 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -507,6 +507,10 @@ public:
return *svalBuilder;
}
+ const SValBuilder &getSValBuilder() const {
+ return *svalBuilder;
+ }
+
SymbolManager &getSymbolManager() {
return svalBuilder->getSymbolManager();
}