aboutsummaryrefslogtreecommitdiff
path: root/include/clang/StaticAnalyzer
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-04-16 16:02:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-04-16 16:02:28 +0000
commit7442d6faa2719e4e7d33a7021c406c5a4facd74d (patch)
treec72b9241553fc9966179aba84f90f17bfa9235c3 /include/clang/StaticAnalyzer
parentb52119637f743680a99710ce5fdb6646da2772af (diff)
downloadsrc-7442d6faa2719e4e7d33a7021c406c5a4facd74d.tar.gz
src-7442d6faa2719e4e7d33a7021c406c5a4facd74d.zip
Vendor import of clang trunk r300422:vendor/clang/clang-trunk-r300422
Notes
Notes: svn path=/vendor/clang/dist/; revision=317019 svn path=/vendor/clang/clang-trunk-r300422/; revision=317020; tag=vendor/clang/clang-trunk-r300422
Diffstat (limited to 'include/clang/StaticAnalyzer')
-rw-r--r--include/clang/StaticAnalyzer/Checkers/Checkers.td10
-rw-r--r--include/clang/StaticAnalyzer/Core/Analyses.def1
-rw-r--r--include/clang/StaticAnalyzer/Core/Checker.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerManager.h10
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h10
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h16
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h5
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h21
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h283
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h9
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h5
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h59
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h92
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Store.h31
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h10
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h10
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h64
17 files changed, 461 insertions, 181 deletions
diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 69578910499f..790ba5c121c9 100644
--- a/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -45,7 +45,6 @@ def CplusplusAlpha : Package<"cplusplus">, InPackage<Alpha>, Hidden;
def CplusplusOptIn : Package<"cplusplus">, InPackage<OptIn>;
def Valist : Package<"valist">;
-def ValistAlpha : Package<"valist">, InPackage<Alpha>, Hidden;
def DeadCode : Package<"deadcode">;
def DeadCodeAlpha : Package<"deadcode">, InPackage<Alpha>, Hidden;
@@ -280,6 +279,11 @@ def VirtualCallChecker : Checker<"VirtualCall">,
let ParentPackage = CplusplusAlpha in {
+def MisusedMovedObjectChecker: Checker<"MisusedMovedObject">,
+ HelpText<"Method calls on a moved-from object and copying a moved-from "
+ "object will be reported">,
+ DescFile<"MisusedMovedObjectChecker.cpp">;
+
def IteratorPastEndChecker : Checker<"IteratorPastEnd">,
HelpText<"Check iterators used past end">,
DescFile<"IteratorPastEndChecker.cpp">;
@@ -291,7 +295,7 @@ def IteratorPastEndChecker : Checker<"IteratorPastEnd">,
// Valist checkers.
//===----------------------------------------------------------------------===//
-let ParentPackage = ValistAlpha in {
+let ParentPackage = Valist in {
def UninitializedChecker : Checker<"Uninitialized">,
HelpText<"Check for usages of uninitialized (or already released) va_lists.">,
@@ -305,7 +309,7 @@ def CopyToSelfChecker : Checker<"CopyToSelf">,
HelpText<"Check for va_lists which are copied onto itself.">,
DescFile<"ValistChecker.cpp">;
-} // end : "alpha.valist"
+} // end : "valist"
//===----------------------------------------------------------------------===//
// Deadcode checkers.
diff --git a/include/clang/StaticAnalyzer/Core/Analyses.def b/include/clang/StaticAnalyzer/Core/Analyses.def
index 3355f4b6949c..04bf41bfde4f 100644
--- a/include/clang/StaticAnalyzer/Core/Analyses.def
+++ b/include/clang/StaticAnalyzer/Core/Analyses.def
@@ -22,6 +22,7 @@ ANALYSIS_STORE(RegionStore, "region", "Use region-based analyzer store", CreateR
#endif
ANALYSIS_CONSTRAINTS(RangeConstraints, "range", "Use constraint tracking of concrete value ranges", CreateRangeConstraintManager)
+ANALYSIS_CONSTRAINTS(Z3Constraints, "z3", "Use Z3 contraint solver", CreateZ3ConstraintManager)
#ifndef ANALYSIS_DIAGNOSTICS
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)
diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h
index dd7a6c863be0..f9477762c758 100644
--- a/include/clang/StaticAnalyzer/Core/Checker.h
+++ b/include/clang/StaticAnalyzer/Core/Checker.h
@@ -321,9 +321,11 @@ class RegionChanges {
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> Explicits,
ArrayRef<const MemRegion *> Regions,
+ const LocationContext *LCtx,
const CallEvent *Call) {
- return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
- Explicits, Regions, Call);
+ return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated,
+ Explicits, Regions,
+ LCtx, Call);
}
public:
diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h
index 0316c8fb173b..52ed260346bf 100644
--- a/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -338,6 +338,7 @@ public:
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
+ const LocationContext *LCtx,
const CallEvent *Call);
/// \brief Run checkers when pointers escape.
@@ -443,10 +444,11 @@ public:
typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc;
typedef CheckerFn<ProgramStateRef (ProgramStateRef,
- const InvalidatedSymbols *symbols,
- ArrayRef<const MemRegion *> ExplicitRegions,
- ArrayRef<const MemRegion *> Regions,
- const CallEvent *Call)>
+ const InvalidatedSymbols *symbols,
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions,
+ const LocationContext *LCtx,
+ const CallEvent *Call)>
CheckRegionChangesFunc;
typedef CheckerFn<ProgramStateRef (ProgramStateRef,
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
index 0d1a120c9dd4..fb427f618575 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
@@ -20,6 +20,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
namespace clang {
namespace ento {
@@ -29,8 +30,9 @@ class CompoundValData : public llvm::FoldingSetNode {
llvm::ImmutableList<SVal> L;
public:
- CompoundValData(QualType t, llvm::ImmutableList<SVal> l)
- : T(t), L(l) {}
+ CompoundValData(QualType t, llvm::ImmutableList<SVal> l) : T(t), L(l) {
+ assert(NonLoc::isCompoundType(t));
+ }
typedef llvm::ImmutableList<SVal>::iterator iterator;
iterator begin() const { return L.begin(); }
@@ -47,7 +49,9 @@ class LazyCompoundValData : public llvm::FoldingSetNode {
const TypedValueRegion *region;
public:
LazyCompoundValData(const StoreRef &st, const TypedValueRegion *r)
- : store(st), region(r) {}
+ : store(st), region(r) {
+ assert(NonLoc::isCompoundType(r->getValueType()));
+ }
const void *getStore() const { return store.getStore(); }
const TypedValueRegion *getRegion() const { return region; }
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index 89610ef5c17d..fa7ee62ab704 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -55,6 +55,7 @@ class CallEventManager;
class CallDescription {
friend CallEvent;
mutable IdentifierInfo *II;
+ mutable bool IsLookupDone;
StringRef FuncName;
unsigned RequiredArgs;
@@ -68,7 +69,8 @@ public:
/// call. Omit this parameter to match every occurance of call with a given
/// name regardless the number of arguments.
CallDescription(StringRef FuncName, unsigned RequiredArgs = NoArgRequirement)
- : II(nullptr), FuncName(FuncName), RequiredArgs(RequiredArgs) {}
+ : II(nullptr), IsLookupDone(false), FuncName(FuncName),
+ RequiredArgs(RequiredArgs) {}
/// \brief Get the name of the function that this object matches.
StringRef getFunctionName() const { return FuncName; }
@@ -381,7 +383,9 @@ public:
// Iterator access to formal parameters and their types.
private:
- typedef std::const_mem_fun_t<QualType, ParmVarDecl> get_type_fun;
+ struct GetTypeFn {
+ QualType operator()(ParmVarDecl *PD) const { return PD->getType(); }
+ };
public:
/// Return call's formal parameters.
@@ -391,7 +395,7 @@ public:
/// correspond with the argument value returned by \c getArgSVal(0).
virtual ArrayRef<ParmVarDecl*> parameters() const = 0;
- typedef llvm::mapped_iterator<ArrayRef<ParmVarDecl*>::iterator, get_type_fun>
+ typedef llvm::mapped_iterator<ArrayRef<ParmVarDecl*>::iterator, GetTypeFn>
param_type_iterator;
/// Returns an iterator over the types of the call's formal parameters.
@@ -400,13 +404,11 @@ public:
/// definition because it represents a public interface, and probably has
/// more annotations.
param_type_iterator param_type_begin() const {
- return llvm::map_iterator(parameters().begin(),
- get_type_fun(&ParmVarDecl::getType));
+ return llvm::map_iterator(parameters().begin(), GetTypeFn());
}
/// \sa param_type_begin()
param_type_iterator param_type_end() const {
- return llvm::map_iterator(parameters().end(),
- get_type_fun(&ParmVarDecl::getType));
+ return llvm::map_iterator(parameters().end(), GetTypeFn());
}
// For debugging purposes only
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
index 6651382d9e95..c01600d5c969 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
@@ -139,6 +139,8 @@ public:
return nullptr;
}
+ /// Scan all symbols referenced by the constraints. If the symbol is not
+ /// alive, remove it.
virtual ProgramStateRef removeDeadBindings(ProgramStateRef state,
SymbolReaper& SymReaper) = 0;
@@ -182,6 +184,9 @@ std::unique_ptr<ConstraintManager>
CreateRangeConstraintManager(ProgramStateManager &statemgr,
SubEngine *subengine);
+std::unique_ptr<ConstraintManager>
+CreateZ3ConstraintManager(ProgramStateManager &statemgr, SubEngine *subengine);
+
} // end GR namespace
} // end clang namespace
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 591b112d60ac..067d70610868 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -237,7 +237,7 @@ public:
const CFGBlock *DstF) override;
/// Called by CoreEngine. Used to processing branching behavior
- /// at static initalizers.
+ /// at static initializers.
void processStaticInitializer(const DeclStmt *DS,
NodeBuilderContext& BuilderCtx,
ExplodedNode *Pred,
@@ -293,6 +293,7 @@ public:
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
+ const LocationContext *LCtx,
const CallEvent *Call) override;
/// printState - Called by ProgramStateManager to print checker-specific data.
@@ -522,7 +523,9 @@ protected:
/// Call PointerEscape callback when a value escapes as a result of bind.
ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State,
- SVal Loc, SVal Val) override;
+ SVal Loc,
+ SVal Val,
+ const LocationContext *LCtx) override;
/// Call PointerEscape callback when a value escapes as a result of
/// region invalidation.
/// \param[in] ITraits Specifies invalidation traits for regions/symbols.
@@ -618,16 +621,16 @@ private:
void performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
const CallEvent &Call);
- /// If the value of the given expression is a NonLoc, copy it into a new
- /// temporary object region, and replace the value of the expression with
- /// that.
+ /// If the value of the given expression \p InitWithAdjustments is a NonLoc,
+ /// copy it into a new temporary object region, and replace the value of the
+ /// expression with that.
///
- /// If \p ResultE is provided, the new region will be bound to this expression
- /// instead of \p E.
+ /// If \p Result is provided, the new region will be bound to this expression
+ /// instead of \p InitWithAdjustments.
ProgramStateRef createTemporaryRegionIfNeeded(ProgramStateRef State,
const LocationContext *LC,
- const Expr *E,
- const Expr *ResultE = nullptr);
+ const Expr *InitWithAdjustments,
+ const Expr *Result = nullptr);
/// For a DeclStmt or CXXInitCtorInitializer, walk backward in the current CFG
/// block to find the constructor expression that directly constructed into
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index da4b964424c3..29b1c4cdca04 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -182,6 +182,7 @@ protected:
MemSpaceRegion(MemRegionManager *mgr, Kind k) : MemRegion(k), Mgr(mgr) {
assert(classof(this));
+ assert(mgr);
}
MemRegionManager* getMemRegionManager() const override { return Mgr; }
@@ -215,9 +216,12 @@ public:
class GlobalsSpaceRegion : public MemSpaceRegion {
virtual void anchor();
+
protected:
- GlobalsSpaceRegion(MemRegionManager *mgr, Kind k)
- : MemSpaceRegion(mgr, k) {}
+ GlobalsSpaceRegion(MemRegionManager *mgr, Kind k) : MemSpaceRegion(mgr, k) {
+ assert(classof(this));
+ }
+
public:
static bool classof(const MemRegion *R) {
Kind k = R->getKind();
@@ -236,7 +240,9 @@ class StaticGlobalSpaceRegion : public GlobalsSpaceRegion {
const CodeTextRegion *CR;
StaticGlobalSpaceRegion(MemRegionManager *mgr, const CodeTextRegion *cr)
- : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {}
+ : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {
+ assert(cr);
+ }
public:
void Profile(llvm::FoldingSetNodeID &ID) const override;
@@ -257,9 +263,13 @@ public:
/// RegionStoreManager::invalidateRegions (instead of finding all the dependent
/// globals, we invalidate the whole parent region).
class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion {
+ virtual void anchor() override;
+
protected:
NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k)
- : GlobalsSpaceRegion(mgr, k) {}
+ : GlobalsSpaceRegion(mgr, k) {
+ assert(classof(this));
+ }
public:
@@ -326,7 +336,6 @@ public:
};
class HeapSpaceRegion : public MemSpaceRegion {
- virtual void anchor();
friend class MemRegionManager;
HeapSpaceRegion(MemRegionManager *mgr)
@@ -341,10 +350,10 @@ public:
};
class UnknownSpaceRegion : public MemSpaceRegion {
- virtual void anchor();
friend class MemRegionManager;
UnknownSpaceRegion(MemRegionManager *mgr)
- : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {}
+ : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {}
+
public:
void dumpToStream(raw_ostream &os) const override;
@@ -355,13 +364,15 @@ public:
};
class StackSpaceRegion : public MemSpaceRegion {
-private:
+ virtual void anchor();
+
const StackFrameContext *SFC;
protected:
StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc)
: MemSpaceRegion(mgr, k), SFC(sfc) {
assert(classof(this));
+ assert(sfc);
}
public:
@@ -376,7 +387,6 @@ public:
};
class StackLocalsSpaceRegion : public StackSpaceRegion {
- virtual void anchor();
friend class MemRegionManager;
StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
: StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {}
@@ -391,7 +401,6 @@ public:
class StackArgumentsSpaceRegion : public StackSpaceRegion {
private:
- virtual void anchor();
friend class MemRegionManager;
StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
: StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {}
@@ -408,11 +417,15 @@ public:
/// SubRegion - A region that subsets another larger region. Most regions
/// are subclasses of SubRegion.
class SubRegion : public MemRegion {
-private:
virtual void anchor();
+
protected:
const MemRegion* superRegion;
- SubRegion(const MemRegion* sReg, Kind k) : MemRegion(k), superRegion(sReg) {}
+ SubRegion(const MemRegion *sReg, Kind k) : MemRegion(k), superRegion(sReg) {
+ assert(classof(this));
+ assert(sReg);
+ }
+
public:
const MemRegion* getSuperRegion() const {
return superRegion;
@@ -440,13 +453,18 @@ public:
/// by a call to 'alloca'.
class AllocaRegion : public SubRegion {
friend class MemRegionManager;
-protected:
+
unsigned Cnt; // Block counter. Used to distinguish different pieces of
// memory allocated by alloca at the same call site.
const Expr *Ex;
- AllocaRegion(const Expr *ex, unsigned cnt, const MemRegion *superRegion)
- : SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) {}
+ AllocaRegion(const Expr *ex, unsigned cnt, const MemSpaceRegion *superRegion)
+ : SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) {
+ assert(Ex);
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr *Ex,
+ unsigned Cnt, const MemRegion *superRegion);
public:
@@ -458,9 +476,6 @@ public:
void Profile(llvm::FoldingSetNodeID& ID) const override;
- static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr *Ex,
- unsigned Cnt, const MemRegion *superRegion);
-
void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion* R) {
@@ -470,10 +485,12 @@ public:
/// TypedRegion - An abstract class representing regions that are typed.
class TypedRegion : public SubRegion {
-public:
- void anchor() override;
+ virtual void anchor() override;
+
protected:
- TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {}
+ TypedRegion(const MemRegion *sReg, Kind k) : SubRegion(sReg, k) {
+ assert(classof(this));
+ }
public:
virtual QualType getLocationType() const = 0;
@@ -492,10 +509,12 @@ public:
/// TypedValueRegion - An abstract class representing regions having a typed value.
class TypedValueRegion : public TypedRegion {
-public:
- void anchor() override;
+ virtual void anchor() override;
+
protected:
- TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) {}
+ TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) {
+ assert(classof(this));
+ }
public:
virtual QualType getValueType() const = 0;
@@ -524,10 +543,13 @@ public:
class CodeTextRegion : public TypedRegion {
-public:
- void anchor() override;
+ virtual void anchor() override;
+
protected:
- CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {}
+ CodeTextRegion(const MemSpaceRegion *sreg, Kind k) : TypedRegion(sreg, k) {
+ assert(classof(this));
+ }
+
public:
bool isBoundable() const override { return false; }
@@ -539,13 +561,19 @@ public:
/// FunctionCodeRegion - A region that represents code texts of function.
class FunctionCodeRegion : public CodeTextRegion {
+ friend class MemRegionManager;
+
const NamedDecl *FD;
-public:
- FunctionCodeRegion(const NamedDecl *fd, const MemRegion* sreg)
+
+ FunctionCodeRegion(const NamedDecl *fd, const CodeSpaceRegion* sreg)
: CodeTextRegion(sreg, FunctionCodeRegionKind), FD(fd) {
assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd));
}
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const NamedDecl *FD,
+ const MemRegion*);
+
+public:
QualType getLocationType() const override {
const ASTContext &Ctx = getContext();
if (const FunctionDecl *D = dyn_cast<FunctionDecl>(FD)) {
@@ -568,9 +596,6 @@ public:
void Profile(llvm::FoldingSetNodeID& ID) const override;
- static void ProfileRegion(llvm::FoldingSetNodeID& ID, const NamedDecl *FD,
- const MemRegion*);
-
static bool classof(const MemRegion* R) {
return R->getKind() == FunctionCodeRegionKind;
}
@@ -591,8 +616,16 @@ class BlockCodeRegion : public CodeTextRegion {
CanQualType locTy;
BlockCodeRegion(const BlockDecl *bd, CanQualType lTy,
- AnalysisDeclContext *ac, const MemRegion* sreg)
- : CodeTextRegion(sreg, BlockCodeRegionKind), BD(bd), AC(ac), locTy(lTy) {}
+ AnalysisDeclContext *ac, const CodeSpaceRegion* sreg)
+ : CodeTextRegion(sreg, BlockCodeRegionKind), BD(bd), AC(ac), locTy(lTy) {
+ assert(bd);
+ assert(ac);
+ assert(lTy->getTypePtr()->isBlockPointerType());
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD,
+ CanQualType, const AnalysisDeclContext*,
+ const MemRegion*);
public:
QualType getLocationType() const override {
@@ -609,10 +642,6 @@ public:
void Profile(llvm::FoldingSetNodeID& ID) const override;
- static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD,
- CanQualType, const AnalysisDeclContext*,
- const MemRegion*);
-
static bool classof(const MemRegion* R) {
return R->getKind() == BlockCodeRegionKind;
}
@@ -626,6 +655,7 @@ public:
/// variables.
class BlockDataRegion : public TypedRegion {
friend class MemRegionManager;
+
const BlockCodeRegion *BC;
const LocationContext *LC; // Can be null */
unsigned BlockCount;
@@ -633,10 +663,19 @@ class BlockDataRegion : public TypedRegion {
void *OriginalVars;
BlockDataRegion(const BlockCodeRegion *bc, const LocationContext *lc,
- unsigned count, const MemRegion *sreg)
- : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc),
- BlockCount(count),
- ReferencedVars(nullptr), OriginalVars(nullptr) {}
+ unsigned count, const MemSpaceRegion *sreg)
+ : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc),
+ BlockCount(count), ReferencedVars(nullptr), OriginalVars(nullptr) {
+ assert(bc);
+ assert(lc);
+ assert(isa<GlobalImmutableSpaceRegion>(sreg) ||
+ isa<StackLocalsSpaceRegion>(sreg) ||
+ isa<UnknownSpaceRegion>(sreg));
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockCodeRegion *,
+ const LocationContext *, unsigned,
+ const MemRegion *);
public:
const BlockCodeRegion *getCodeRegion() const { return BC; }
@@ -686,10 +725,6 @@ public:
void Profile(llvm::FoldingSetNodeID& ID) const override;
- static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockCodeRegion *,
- const LocationContext *, unsigned,
- const MemRegion *);
-
static bool classof(const MemRegion* R) {
return R->getKind() == BlockDataRegionKind;
}
@@ -705,13 +740,20 @@ private:
/// map the concept of symbolic values into the domain of regions. Symbolic
/// regions do not need to be typed.
class SymbolicRegion : public SubRegion {
-protected:
+ friend class MemRegionManager;
+
const SymbolRef sym;
-public:
- SymbolicRegion(const SymbolRef s, const MemRegion* sreg)
- : SubRegion(sreg, SymbolicRegionKind), sym(s) {}
+ SymbolicRegion(const SymbolRef s, const MemSpaceRegion *sreg)
+ : SubRegion(sreg, SymbolicRegionKind), sym(s) {
+ assert(s);
+ assert(s->getType()->isAnyPointerType() ||
+ s->getType()->isReferenceType() ||
+ s->getType()->isBlockPointerType());
+ assert(isa<UnknownSpaceRegion>(sreg) || isa<HeapSpaceRegion>(sreg));
+ }
+public:
SymbolRef getSymbol() const {
return sym;
}
@@ -736,11 +778,13 @@ public:
/// StringRegion - Region associated with a StringLiteral.
class StringRegion : public TypedValueRegion {
friend class MemRegionManager;
+
const StringLiteral* Str;
-protected:
- StringRegion(const StringLiteral* str, const MemRegion* sreg)
- : TypedValueRegion(sreg, StringRegionKind), Str(str) {}
+ StringRegion(const StringLiteral *str, const GlobalInternalSpaceRegion *sreg)
+ : TypedValueRegion(sreg, StringRegionKind), Str(str) {
+ assert(str);
+ }
static void ProfileRegion(llvm::FoldingSetNodeID& ID,
const StringLiteral* Str,
@@ -772,12 +816,15 @@ public:
/// The region associated with an ObjCStringLiteral.
class ObjCStringRegion : public TypedValueRegion {
friend class MemRegionManager;
+
const ObjCStringLiteral* Str;
-protected:
-
- ObjCStringRegion(const ObjCStringLiteral* str, const MemRegion* sreg)
- : TypedValueRegion(sreg, ObjCStringRegionKind), Str(str) {}
-
+
+ ObjCStringRegion(const ObjCStringLiteral *str,
+ const GlobalInternalSpaceRegion *sreg)
+ : TypedValueRegion(sreg, ObjCStringRegionKind), Str(str) {
+ assert(str);
+ }
+
static void ProfileRegion(llvm::FoldingSetNodeID& ID,
const ObjCStringLiteral* Str,
const MemRegion* superRegion);
@@ -807,12 +854,17 @@ public:
/// Compound literals are essentially temporaries that are stack allocated
/// or in the global constant pool.
class CompoundLiteralRegion : public TypedValueRegion {
-private:
friend class MemRegionManager;
+
const CompoundLiteralExpr *CL;
- CompoundLiteralRegion(const CompoundLiteralExpr *cl, const MemRegion* sReg)
- : TypedValueRegion(sReg, CompoundLiteralRegionKind), CL(cl) {}
+ CompoundLiteralRegion(const CompoundLiteralExpr *cl,
+ const MemSpaceRegion *sReg)
+ : TypedValueRegion(sReg, CompoundLiteralRegionKind), CL(cl) {
+ assert(cl);
+ assert(isa<GlobalInternalSpaceRegion>(sReg) ||
+ isa<StackLocalsSpaceRegion>(sReg));
+ }
static void ProfileRegion(llvm::FoldingSetNodeID& ID,
const CompoundLiteralExpr *CL,
@@ -839,8 +891,11 @@ class DeclRegion : public TypedValueRegion {
protected:
const Decl *D;
- DeclRegion(const Decl *d, const MemRegion* sReg, Kind k)
- : TypedValueRegion(sReg, k), D(d) {}
+ DeclRegion(const Decl *d, const MemRegion *sReg, Kind k)
+ : TypedValueRegion(sReg, k), D(d) {
+ assert(classof(this));
+ assert(d);
+ }
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl *D,
const MemRegion* superRegion, Kind k);
@@ -859,17 +914,24 @@ class VarRegion : public DeclRegion {
friend class MemRegionManager;
// Constructors and private methods.
- VarRegion(const VarDecl *vd, const MemRegion* sReg)
- : DeclRegion(vd, sReg, VarRegionKind) {}
+ VarRegion(const VarDecl *vd, const MemRegion *sReg)
+ : DeclRegion(vd, sReg, VarRegionKind) {
+ // VarRegion appears in unknown space when it's a block variable as seen
+ // from a block using it, when this block is analyzed at top-level.
+ // Other block variables appear within block data regions,
+ // which, unlike everything else on this list, are not memory spaces.
+ assert(isa<GlobalsSpaceRegion>(sReg) || isa<StackSpaceRegion>(sReg) ||
+ isa<BlockDataRegion>(sReg) || isa<UnknownSpaceRegion>(sReg));
+ }
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl *VD,
const MemRegion *superRegion) {
DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind);
}
+public:
void Profile(llvm::FoldingSetNodeID& ID) const override;
-public:
const VarDecl *getDecl() const { return cast<VarDecl>(D); }
const StackFrameContext *getStackFrame() const;
@@ -895,17 +957,19 @@ public:
/// referred to by 'this', but rather 'this' itself.
class CXXThisRegion : public TypedValueRegion {
friend class MemRegionManager;
+
CXXThisRegion(const PointerType *thisPointerTy,
- const MemRegion *sReg)
- : TypedValueRegion(sReg, CXXThisRegionKind), ThisPointerTy(thisPointerTy) {}
+ const StackArgumentsSpaceRegion *sReg)
+ : TypedValueRegion(sReg, CXXThisRegionKind),
+ ThisPointerTy(thisPointerTy) {}
static void ProfileRegion(llvm::FoldingSetNodeID &ID,
const PointerType *PT,
const MemRegion *sReg);
+public:
void Profile(llvm::FoldingSetNodeID &ID) const override;
-public:
QualType getValueType() const override {
return QualType(ThisPointerTy, 0);
}
@@ -923,9 +987,14 @@ private:
class FieldRegion : public DeclRegion {
friend class MemRegionManager;
- FieldRegion(const FieldDecl *fd, const MemRegion* sReg)
+ FieldRegion(const FieldDecl *fd, const SubRegion* sReg)
: DeclRegion(fd, sReg, FieldRegionKind) {}
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl *FD,
+ const MemRegion* superRegion) {
+ DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind);
+ }
+
public:
const FieldDecl *getDecl() const { return cast<FieldDecl>(D); }
@@ -936,11 +1005,6 @@ public:
DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
- static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl *FD,
- const MemRegion* superRegion) {
- DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind);
- }
-
static bool classof(const MemRegion* R) {
return R->getKind() == FieldRegionKind;
}
@@ -954,10 +1018,9 @@ public:
};
class ObjCIvarRegion : public DeclRegion {
-
friend class MemRegionManager;
- ObjCIvarRegion(const ObjCIvarDecl *ivd, const MemRegion* sReg);
+ ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg);
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const ObjCIvarDecl *ivd,
const MemRegion* superRegion);
@@ -982,7 +1045,6 @@ public:
class ElementRegion;
class RegionRawOffset {
-private:
friend class ElementRegion;
const MemRegion *Region;
@@ -1007,9 +1069,9 @@ class ElementRegion : public TypedValueRegion {
QualType ElementType;
NonLoc Index;
- ElementRegion(QualType elementType, NonLoc Idx, const MemRegion* sReg)
- : TypedValueRegion(sReg, ElementRegionKind),
- ElementType(elementType), Index(Idx) {
+ ElementRegion(QualType elementType, NonLoc Idx, const SubRegion *sReg)
+ : TypedValueRegion(sReg, ElementRegionKind),
+ ElementType(elementType), Index(Idx) {
assert((!Idx.getAs<nonloc::ConcreteInt>() ||
Idx.castAs<nonloc::ConcreteInt>().getValue().isSigned()) &&
"The index must be signed");
@@ -1047,12 +1109,16 @@ class CXXTempObjectRegion : public TypedValueRegion {
Expr const *Ex;
- CXXTempObjectRegion(Expr const *E, MemRegion const *sReg)
- : TypedValueRegion(sReg, CXXTempObjectRegionKind), Ex(E) {}
+ CXXTempObjectRegion(Expr const *E, MemSpaceRegion const *sReg)
+ : TypedValueRegion(sReg, CXXTempObjectRegionKind), Ex(E) {
+ assert(E);
+ assert(isa<StackLocalsSpaceRegion>(sReg) ||
+ isa<GlobalInternalSpaceRegion>(sReg));
+ }
static void ProfileRegion(llvm::FoldingSetNodeID &ID,
Expr const *E, const MemRegion *sReg);
-
+
public:
const Expr *getExpr() const { return Ex; }
@@ -1077,8 +1143,10 @@ class CXXBaseObjectRegion : public TypedValueRegion {
llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Data;
CXXBaseObjectRegion(const CXXRecordDecl *RD, bool IsVirtual,
- const MemRegion *SReg)
- : TypedValueRegion(SReg, CXXBaseObjectRegionKind), Data(RD, IsVirtual) {}
+ const SubRegion *SReg)
+ : TypedValueRegion(SReg, CXXBaseObjectRegionKind), Data(RD, IsVirtual) {
+ assert(RD);
+ }
static void ProfileRegion(llvm::FoldingSetNodeID &ID, const CXXRecordDecl *RD,
bool IsVirtual, const MemRegion *SReg);
@@ -1204,16 +1272,16 @@ public:
/// getVarRegion - Retrieve or create the memory region associated with
/// a specified VarDecl and super region.
- const VarRegion* getVarRegion(const VarDecl *D, const MemRegion *superR);
-
+ const VarRegion *getVarRegion(const VarDecl *D, const MemRegion *superR);
+
/// getElementRegion - Retrieve the memory region associated with the
/// associated element type, index, and super region.
const ElementRegion *getElementRegion(QualType elementType, NonLoc Idx,
- const MemRegion *superRegion,
+ const SubRegion *superRegion,
ASTContext &Ctx);
const ElementRegion *getElementRegionWithSuper(const ElementRegion *ER,
- const MemRegion *superRegion) {
+ const SubRegion *superRegion) {
return getElementRegion(ER->getElementType(), ER->getIndex(),
superRegion, ER->getContext());
}
@@ -1223,10 +1291,10 @@ public:
/// memory region (which typically represents the memory representing
/// a structure or class).
const FieldRegion *getFieldRegion(const FieldDecl *fd,
- const MemRegion* superRegion);
+ const SubRegion* superRegion);
const FieldRegion *getFieldRegionWithSuper(const FieldRegion *FR,
- const MemRegion *superRegion) {
+ const SubRegion *superRegion) {
return getFieldRegion(FR->getDecl(), superRegion);
}
@@ -1235,7 +1303,7 @@ public:
/// to the containing region (which typically represents the Objective-C
/// object).
const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl *ivd,
- const MemRegion* superRegion);
+ const SubRegion* superRegion);
const CXXTempObjectRegion *getCXXTempObjectRegion(Expr const *Ex,
LocationContext const *LC);
@@ -1245,14 +1313,14 @@ public:
///
/// The type of \p Super is assumed be a class deriving from \p BaseClass.
const CXXBaseObjectRegion *
- getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const MemRegion *Super,
+ getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const SubRegion *Super,
bool IsVirtual);
/// Create a CXXBaseObjectRegion with the same CXXRecordDecl but a different
/// super region.
const CXXBaseObjectRegion *
getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg,
- const MemRegion *superRegion) {
+ const SubRegion *superRegion) {
return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion,
baseReg->isVirtual());
}
@@ -1276,17 +1344,22 @@ public:
const CXXTempObjectRegion *getCXXStaticTempObjectRegion(const Expr *Ex);
private:
- template <typename RegionTy, typename A1>
- RegionTy* getSubRegion(const A1 a1, const MemRegion* superRegion);
-
- template <typename RegionTy, typename A1, typename A2>
- RegionTy* getSubRegion(const A1 a1, const A2 a2,
- const MemRegion* superRegion);
+ template <typename RegionTy, typename SuperTy,
+ typename Arg1Ty>
+ RegionTy* getSubRegion(const Arg1Ty arg1,
+ const SuperTy* superRegion);
+
+ template <typename RegionTy, typename SuperTy,
+ typename Arg1Ty, typename Arg2Ty>
+ RegionTy* getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
+ const SuperTy* superRegion);
+
+ template <typename RegionTy, typename SuperTy,
+ typename Arg1Ty, typename Arg2Ty, typename Arg3Ty>
+ RegionTy* getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
+ const Arg3Ty arg3,
+ const SuperTy* superRegion);
- template <typename RegionTy, typename A1, typename A2, typename A3>
- RegionTy* getSubRegion(const A1 a1, const A2 a2, const A3 a3,
- const MemRegion* superRegion);
-
template <typename REG>
const REG* LazyAllocate(REG*& region);
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index 463b375fda30..2910ef4212cc 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -229,11 +229,12 @@ public:
ProgramStateRef bindLoc(Loc location,
SVal V,
+ const LocationContext *LCtx,
bool notifyChanges = true) const;
- ProgramStateRef bindLoc(SVal location, SVal V) const;
+ ProgramStateRef bindLoc(SVal location, SVal V, const LocationContext *LCtx) const;
- ProgramStateRef bindDefault(SVal loc, SVal V) const;
+ ProgramStateRef bindDefault(SVal loc, SVal V, const LocationContext *LCtx) const;
ProgramStateRef killBinding(Loc LV) const;
@@ -681,9 +682,9 @@ ProgramState::assumeInclusiveRange(DefinedOrUnknownSVal Val,
this, Val.castAs<NonLoc>(), From, To);
}
-inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V) const {
+inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V, const LocationContext *LCtx) const {
if (Optional<Loc> L = LV.getAs<Loc>())
- return bindLoc(*L, V);
+ return bindLoc(*L, V, LCtx);
return this;
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index a4c01fc45334..14aa3af37620 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -112,6 +112,11 @@ public:
/// 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 val) = 0;
+
+ /// Simplify symbolic expressions within a given SVal. Return an SVal
+ /// that represents the same value, but is hopefully easier to work with
+ /// than the original SVal.
+ virtual SVal simplifySVal(ProgramStateRef State, SVal Val) = 0;
/// Constructs a symbolic expression for two non-location values.
SVal makeSymExprValNN(ProgramStateRef state, BinaryOperator::Opcode op,
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
index cc3c02a02c64..935f0018324a 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -41,6 +41,22 @@ class MemRegionManager;
class ProgramStateManager;
class SValBuilder;
+namespace nonloc {
+/// Sub-kinds for NonLoc values.
+enum Kind {
+#define NONLOC_SVAL(Id, Parent) Id ## Kind,
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
+};
+}
+
+namespace loc {
+/// Sub-kinds for Loc values.
+enum Kind {
+#define LOC_SVAL(Id, Parent) Id ## Kind,
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
+};
+}
+
/// SVal - This represents a symbolic expression, which can be either
/// an L-value or an R-value.
///
@@ -75,10 +91,7 @@ public:
template<typename T>
T castAs() const {
assert(T::isKind(*this));
- T t;
- SVal& sv = t;
- sv = *this;
- return t;
+ return *static_cast<const T *>(this);
}
/// \brief Convert to the specified SVal type, returning None if this SVal is
@@ -87,10 +100,7 @@ public:
Optional<T> getAs() const {
if (!T::isKind(*this))
return None;
- T t;
- SVal& sv = t;
- sv = *this;
- return t;
+ return *static_cast<const T *>(this);
}
/// BufferTy - A temporary buffer to hold a set of SVals.
@@ -273,6 +283,11 @@ protected:
public:
void dumpToStream(raw_ostream &Out) const;
+ static inline bool isCompoundType(QualType T) {
+ return T->isArrayType() || T->isRecordType() ||
+ T->isComplexType() || T->isVectorType();
+ }
+
private:
friend class SVal;
static bool isKind(const SVal& V) {
@@ -307,15 +322,11 @@ private:
namespace nonloc {
-enum Kind {
-#define NONLOC_SVAL(Id, Parent) Id ## Kind,
-#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
-};
-
/// \brief Represents symbolic expression.
class SymbolVal : public NonLoc {
public:
- SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {}
+ SymbolVal() = delete;
+ SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) { assert(sym); }
SymbolRef getSymbol() const {
return (const SymExpr*) Data;
@@ -327,7 +338,6 @@ public:
private:
friend class SVal;
- SymbolVal() {}
static bool isKind(const SVal& V) {
return V.getBaseKind() == NonLocKind &&
V.getSubKind() == SymbolValKind;
@@ -373,7 +383,11 @@ class LocAsInteger : public NonLoc {
explicit LocAsInteger(const std::pair<SVal, uintptr_t> &data)
: NonLoc(LocAsIntegerKind, &data) {
- assert (data.first.getAs<Loc>());
+ // We do not need to represent loc::ConcreteInt as LocAsInteger,
+ // as it'd collapse into a nonloc::ConcreteInt instead.
+ assert(data.first.getBaseKind() == LocKind &&
+ (data.first.getSubKind() == loc::MemRegionValKind ||
+ data.first.getSubKind() == loc::GotoLabelKind));
}
public:
@@ -513,14 +527,11 @@ private:
namespace loc {
-enum Kind {
-#define LOC_SVAL(Id, Parent) Id ## Kind,
-#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
-};
-
class GotoLabel : public Loc {
public:
- explicit GotoLabel(LabelDecl *Label) : Loc(GotoLabelKind, Label) {}
+ explicit GotoLabel(const LabelDecl *Label) : Loc(GotoLabelKind, Label) {
+ assert(Label);
+ }
const LabelDecl *getLabel() const {
return static_cast<const LabelDecl*>(Data);
@@ -541,7 +552,9 @@ private:
class MemRegionVal : public Loc {
public:
- explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) {}
+ explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) {
+ assert(r);
+ }
/// \brief Get the underlining region.
const MemRegion* getRegion() const {
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h
new file mode 100644
index 000000000000..2c9802bbc536
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h
@@ -0,0 +1,92 @@
+//== SimpleConstraintManager.h ----------------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Simplified constraint manager backend.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SIMPLECONSTRAINTMANAGER_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SIMPLECONSTRAINTMANAGER_H
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+
+namespace clang {
+
+namespace ento {
+
+class SimpleConstraintManager : public ConstraintManager {
+ SubEngine *SU;
+ SValBuilder &SVB;
+
+public:
+ SimpleConstraintManager(SubEngine *subengine, SValBuilder &SB)
+ : SU(subengine), SVB(SB) {}
+
+ ~SimpleConstraintManager() override;
+
+ //===------------------------------------------------------------------===//
+ // Implementation for interface from ConstraintManager.
+ //===------------------------------------------------------------------===//
+
+ /// Ensures that the DefinedSVal conditional is expressed as a NonLoc by
+ /// creating boolean casts to handle Loc's.
+ ProgramStateRef assume(ProgramStateRef State, DefinedSVal Cond,
+ bool Assumption) override;
+
+ ProgramStateRef assumeInclusiveRange(ProgramStateRef State, NonLoc Value,
+ const llvm::APSInt &From,
+ const llvm::APSInt &To,
+ bool InRange) override;
+
+protected:
+ //===------------------------------------------------------------------===//
+ // Interface that subclasses must implement.
+ //===------------------------------------------------------------------===//
+
+ /// Given a symbolic expression that can be reasoned about, assume that it is
+ /// true/false and generate the new program state.
+ virtual ProgramStateRef assumeSym(ProgramStateRef State, SymbolRef Sym,
+ bool Assumption) = 0;
+
+ /// Given a symbolic expression within the range [From, To], assume that it is
+ /// true/false and generate the new program state.
+ /// This function is used to handle case ranges produced by a language
+ /// extension for switch case statements.
+ virtual ProgramStateRef assumeSymInclusiveRange(ProgramStateRef State,
+ SymbolRef Sym,
+ const llvm::APSInt &From,
+ const llvm::APSInt &To,
+ bool InRange) = 0;
+
+ /// Given a symbolic expression that cannot be reasoned about, assume that
+ /// it is zero/nonzero and add it directly to the solver state.
+ virtual ProgramStateRef assumeSymUnsupported(ProgramStateRef State,
+ SymbolRef Sym,
+ bool Assumption) = 0;
+
+ //===------------------------------------------------------------------===//
+ // Internal implementation.
+ //===------------------------------------------------------------------===//
+
+ BasicValueFactory &getBasicVals() const { return SVB.getBasicValueFactory(); }
+ SymbolManager &getSymbolManager() const { return SVB.getSymbolManager(); }
+
+private:
+ ProgramStateRef assume(ProgramStateRef State, NonLoc Cond, bool Assumption);
+
+ ProgramStateRef assumeAux(ProgramStateRef State, NonLoc Cond,
+ bool Assumption);
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
index fa7d3f72abf1..7619f22f4013 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -59,6 +59,30 @@ public:
/// \return The value bound to the location \c loc.
virtual SVal getBinding(Store store, Loc loc, QualType T = QualType()) = 0;
+ /// Return the default value bound to a region in a given store. The default
+ /// binding is the value of sub-regions that were not initialized separately
+ /// from their base region. For example, if the structure is zero-initialized
+ /// upon construction, this method retrieves the concrete zero value, even if
+ /// some or all fields were later overwritten manually. Default binding may be
+ /// an unknown, undefined, concrete, or symbolic value.
+ /// \param[in] store The store in which to make the lookup.
+ /// \param[in] R The region to find the default binding for.
+ /// \return The default value bound to the region in the store, if a default
+ /// binding exists.
+ virtual Optional<SVal> getDefaultBinding(Store store, const MemRegion *R) = 0;
+
+ /// Return the default value bound to a LazyCompoundVal. The default binding
+ /// is used to represent the value of any fields or elements within the
+ /// structure represented by the LazyCompoundVal which were not initialized
+ /// explicitly separately from the whole structure. Default binding may be an
+ /// unknown, undefined, concrete, or symbolic value.
+ /// \param[in] lcv The lazy compound value.
+ /// \return The default value bound to the LazyCompoundVal \c lcv, if a
+ /// default binding exists.
+ Optional<SVal> getDefaultBinding(nonloc::LazyCompoundVal lcv) {
+ return getDefaultBinding(lcv.getStore(), lcv.getRegion());
+ }
+
/// Return a state with the specified value bound to the given location.
/// \param[in] store The analysis state.
/// \param[in] loc The symbolic memory location.
@@ -136,7 +160,7 @@ public:
/// valid only if Failed flag is set to false.
SVal attemptDownCast(SVal Base, QualType DerivedPtrType, bool &Failed);
- const ElementRegion *GetElementZeroRegion(const MemRegion *R, QualType T);
+ const ElementRegion *GetElementZeroRegion(const SubRegion *R, QualType T);
/// castRegion - Used by ExprEngine::VisitCast to handle casts from
/// a MemRegion* to a specific location type. 'R' is the region being
@@ -235,8 +259,9 @@ public:
virtual void iterBindings(Store store, BindingsHandler& f) = 0;
protected:
- const MemRegion *MakeElementRegion(const MemRegion *baseRegion,
- QualType pointeeTy, uint64_t index = 0);
+ const ElementRegion *MakeElementRegion(const SubRegion *baseRegion,
+ QualType pointeeTy,
+ uint64_t index = 0);
/// CastRetrievedVal - Used by subclasses of StoreManager to implement
/// implicit casts that arise from loads from regions that are reinterpreted
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
index 581ef206cff3..8ccd34751bbe 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
@@ -83,7 +83,7 @@ public:
const CFGBlock *DstF) = 0;
/// Called by CoreEngine. Used to processing branching behavior
- /// at static initalizers.
+ /// at static initializers.
virtual void processStaticInitializer(const DeclStmt *DS,
NodeBuilderContext& BuilderCtx,
ExplodedNode *Pred,
@@ -131,17 +131,19 @@ public:
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
+ const LocationContext *LCtx,
const CallEvent *Call) = 0;
inline ProgramStateRef
processRegionChange(ProgramStateRef state,
- const MemRegion* MR) {
- return processRegionChanges(state, nullptr, MR, MR, nullptr);
+ const MemRegion* MR,
+ const LocationContext *LCtx) {
+ return processRegionChanges(state, nullptr, MR, MR, LCtx, nullptr);
}
virtual ProgramStateRef
- processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, SVal Val) = 0;
+ processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, SVal Val, const LocationContext *LCtx) = 0;
virtual ProgramStateRef
notifyCheckersOfPointerEscape(ProgramStateRef State,
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h
index 18bc60754b81..f72033955ec3 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h
@@ -42,6 +42,12 @@ private:
protected:
SymExpr(Kind k) : K(k) {}
+ static bool isValidTypeForSymbol(QualType T) {
+ // FIXME: Depending on whether we choose to deprecate structural symbols,
+ // this may become much stricter.
+ return !T.isNull() && !T->isVoidType();
+ }
+
public:
virtual ~SymExpr() {}
@@ -103,7 +109,9 @@ class SymbolData : public SymExpr {
const SymbolID Sym;
protected:
- SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) {}
+ SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) {
+ assert(classof(this));
+ }
public:
~SymbolData() override {}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index f00dce568e3a..e9701142cd9e 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -44,7 +44,10 @@ class SymbolRegionValue : public SymbolData {
public:
SymbolRegionValue(SymbolID sym, const TypedValueRegion *r)
- : SymbolData(SymbolRegionValueKind, sym), R(r) {}
+ : SymbolData(SymbolRegionValueKind, sym), R(r) {
+ assert(r);
+ assert(isValidTypeForSymbol(r->getValueType()));
+ }
const TypedValueRegion* getRegion() const { return R; }
@@ -81,7 +84,15 @@ public:
SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx,
QualType t, unsigned count, const void *symbolTag)
: SymbolData(SymbolConjuredKind, sym), S(s), T(t), Count(count),
- LCtx(lctx), SymbolTag(symbolTag) {}
+ LCtx(lctx), SymbolTag(symbolTag) {
+ // FIXME: 's' might be a nullptr if we're conducting invalidation
+ // that was caused by a destructor call on a temporary object,
+ // which has no statement associated with it.
+ // Due to this, we might be creating the same invalidation symbol for
+ // two different invalidation passes (for two different temporaries).
+ assert(lctx);
+ assert(isValidTypeForSymbol(t));
+ }
const Stmt *getStmt() const { return S; }
unsigned getCount() const { return Count; }
@@ -120,7 +131,11 @@ class SymbolDerived : public SymbolData {
public:
SymbolDerived(SymbolID sym, SymbolRef parent, const TypedValueRegion *r)
- : SymbolData(SymbolDerivedKind, sym), parentSymbol(parent), R(r) {}
+ : SymbolData(SymbolDerivedKind, sym), parentSymbol(parent), R(r) {
+ assert(parent);
+ assert(r);
+ assert(isValidTypeForSymbol(r->getValueType()));
+ }
SymbolRef getParentSymbol() const { return parentSymbol; }
const TypedValueRegion *getRegion() const { return R; }
@@ -155,7 +170,9 @@ class SymbolExtent : public SymbolData {
public:
SymbolExtent(SymbolID sym, const SubRegion *r)
- : SymbolData(SymbolExtentKind, sym), R(r) {}
+ : SymbolData(SymbolExtentKind, sym), R(r) {
+ assert(r);
+ }
const SubRegion *getRegion() const { return R; }
@@ -193,7 +210,13 @@ public:
SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t,
const LocationContext *LCtx, unsigned count, const void *tag)
: SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), LCtx(LCtx),
- Count(count), Tag(tag) {}
+ Count(count), Tag(tag) {
+ assert(r);
+ assert(s);
+ assert(isValidTypeForSymbol(t));
+ assert(LCtx);
+ assert(tag);
+ }
const MemRegion *getRegion() const { return R; }
const Stmt *getStmt() const { return S; }
@@ -236,8 +259,13 @@ class SymbolCast : public SymExpr {
QualType ToTy;
public:
- SymbolCast(const SymExpr *In, QualType From, QualType To) :
- SymExpr(SymbolCastKind), Operand(In), FromTy(From), ToTy(To) { }
+ SymbolCast(const SymExpr *In, QualType From, QualType To)
+ : SymExpr(SymbolCastKind), Operand(In), FromTy(From), ToTy(To) {
+ assert(In);
+ assert(isValidTypeForSymbol(From));
+ // FIXME: GenericTaintChecker creates symbols of void type.
+ // Otherwise, 'To' should also be a valid type.
+ }
QualType getType() const override { return ToTy; }
@@ -270,7 +298,10 @@ class BinarySymExpr : public SymExpr {
protected:
BinarySymExpr(Kind k, BinaryOperator::Opcode op, QualType t)
- : SymExpr(k), Op(op), T(t) {}
+ : SymExpr(k), Op(op), T(t) {
+ assert(classof(this));
+ assert(isValidTypeForSymbol(t));
+ }
public:
// FIXME: We probably need to make this out-of-line to avoid redundant
@@ -293,8 +324,10 @@ class SymIntExpr : public BinarySymExpr {
public:
SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
- const llvm::APSInt& rhs, QualType t)
- : BinarySymExpr(SymIntExprKind, op, t), LHS(lhs), RHS(rhs) {}
+ const llvm::APSInt &rhs, QualType t)
+ : BinarySymExpr(SymIntExprKind, op, t), LHS(lhs), RHS(rhs) {
+ assert(lhs);
+ }
void dumpToStream(raw_ostream &os) const override;
@@ -327,9 +360,11 @@ class IntSymExpr : public BinarySymExpr {
const SymExpr *RHS;
public:
- IntSymExpr(const llvm::APSInt& lhs, BinaryOperator::Opcode op,
+ IntSymExpr(const llvm::APSInt &lhs, BinaryOperator::Opcode op,
const SymExpr *rhs, QualType t)
- : BinarySymExpr(IntSymExprKind, op, t), LHS(lhs), RHS(rhs) {}
+ : BinarySymExpr(IntSymExprKind, op, t), LHS(lhs), RHS(rhs) {
+ assert(rhs);
+ }
void dumpToStream(raw_ostream &os) const override;
@@ -364,7 +399,10 @@ class SymSymExpr : public BinarySymExpr {
public:
SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs,
QualType t)
- : BinarySymExpr(SymSymExprKind, op, t), LHS(lhs), RHS(rhs) {}
+ : BinarySymExpr(SymSymExprKind, op, t), LHS(lhs), RHS(rhs) {
+ assert(lhs);
+ assert(rhs);
+ }
const SymExpr *getLHS() const { return LHS; }
const SymExpr *getRHS() const { return RHS; }