[analyzer] Add numerous assertions to SVal, SymExpr, and MemRegion classes.

Clean up vtable anchors (remove anchors for regions that have regular
out-of-line virtual methods, add anchors for regions that don't have those).

Fix private/public methods (all constructors should now be private for leaf
classes, protected for abstract classes).

No functional change intended, only extra sanity checks and cleanups.

Differential Revision: https://reviews.llvm.org/D26837

llvm-svn: 300187
This commit is contained in:
Artem Dergachev 2017-04-13 09:48:05 +00:00
parent d0656a3af1
commit b3241f41b2
6 changed files with 231 additions and 120 deletions

View File

@ -20,6 +20,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
namespace clang { namespace clang {
namespace ento { namespace ento {
@ -29,8 +30,9 @@ class CompoundValData : public llvm::FoldingSetNode {
llvm::ImmutableList<SVal> L; llvm::ImmutableList<SVal> L;
public: public:
CompoundValData(QualType t, llvm::ImmutableList<SVal> l) CompoundValData(QualType t, llvm::ImmutableList<SVal> l) : T(t), L(l) {
: T(t), L(l) {} assert(NonLoc::isCompoundType(t));
}
typedef llvm::ImmutableList<SVal>::iterator iterator; typedef llvm::ImmutableList<SVal>::iterator iterator;
iterator begin() const { return L.begin(); } iterator begin() const { return L.begin(); }
@ -47,7 +49,9 @@ class LazyCompoundValData : public llvm::FoldingSetNode {
const TypedValueRegion *region; const TypedValueRegion *region;
public: public:
LazyCompoundValData(const StoreRef &st, const TypedValueRegion *r) 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 void *getStore() const { return store.getStore(); }
const TypedValueRegion *getRegion() const { return region; } const TypedValueRegion *getRegion() const { return region; }

View File

@ -182,6 +182,7 @@ protected:
MemSpaceRegion(MemRegionManager *mgr, Kind k) : MemRegion(k), Mgr(mgr) { MemSpaceRegion(MemRegionManager *mgr, Kind k) : MemRegion(k), Mgr(mgr) {
assert(classof(this)); assert(classof(this));
assert(mgr);
} }
MemRegionManager* getMemRegionManager() const override { return Mgr; } MemRegionManager* getMemRegionManager() const override { return Mgr; }
@ -215,9 +216,12 @@ public:
class GlobalsSpaceRegion : public MemSpaceRegion { class GlobalsSpaceRegion : public MemSpaceRegion {
virtual void anchor(); virtual void anchor();
protected: protected:
GlobalsSpaceRegion(MemRegionManager *mgr, Kind k) GlobalsSpaceRegion(MemRegionManager *mgr, Kind k) : MemSpaceRegion(mgr, k) {
: MemSpaceRegion(mgr, k) {} assert(classof(this));
}
public: public:
static bool classof(const MemRegion *R) { static bool classof(const MemRegion *R) {
Kind k = R->getKind(); Kind k = R->getKind();
@ -236,7 +240,9 @@ class StaticGlobalSpaceRegion : public GlobalsSpaceRegion {
const CodeTextRegion *CR; const CodeTextRegion *CR;
StaticGlobalSpaceRegion(MemRegionManager *mgr, const CodeTextRegion *cr) StaticGlobalSpaceRegion(MemRegionManager *mgr, const CodeTextRegion *cr)
: GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {} : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {
assert(cr);
}
public: public:
void Profile(llvm::FoldingSetNodeID &ID) const override; void Profile(llvm::FoldingSetNodeID &ID) const override;
@ -257,9 +263,13 @@ public:
/// RegionStoreManager::invalidateRegions (instead of finding all the dependent /// RegionStoreManager::invalidateRegions (instead of finding all the dependent
/// globals, we invalidate the whole parent region). /// globals, we invalidate the whole parent region).
class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion { class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion {
virtual void anchor() override;
protected: protected:
NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k) NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k)
: GlobalsSpaceRegion(mgr, k) {} : GlobalsSpaceRegion(mgr, k) {
assert(classof(this));
}
public: public:
@ -326,7 +336,6 @@ public:
}; };
class HeapSpaceRegion : public MemSpaceRegion { class HeapSpaceRegion : public MemSpaceRegion {
virtual void anchor();
friend class MemRegionManager; friend class MemRegionManager;
HeapSpaceRegion(MemRegionManager *mgr) HeapSpaceRegion(MemRegionManager *mgr)
@ -341,10 +350,10 @@ public:
}; };
class UnknownSpaceRegion : public MemSpaceRegion { class UnknownSpaceRegion : public MemSpaceRegion {
virtual void anchor();
friend class MemRegionManager; friend class MemRegionManager;
UnknownSpaceRegion(MemRegionManager *mgr) UnknownSpaceRegion(MemRegionManager *mgr)
: MemSpaceRegion(mgr, UnknownSpaceRegionKind) {} : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {}
public: public:
void dumpToStream(raw_ostream &os) const override; void dumpToStream(raw_ostream &os) const override;
@ -355,13 +364,15 @@ public:
}; };
class StackSpaceRegion : public MemSpaceRegion { class StackSpaceRegion : public MemSpaceRegion {
private: virtual void anchor();
const StackFrameContext *SFC; const StackFrameContext *SFC;
protected: protected:
StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc) StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc)
: MemSpaceRegion(mgr, k), SFC(sfc) { : MemSpaceRegion(mgr, k), SFC(sfc) {
assert(classof(this)); assert(classof(this));
assert(sfc);
} }
public: public:
@ -376,7 +387,6 @@ public:
}; };
class StackLocalsSpaceRegion : public StackSpaceRegion { class StackLocalsSpaceRegion : public StackSpaceRegion {
virtual void anchor();
friend class MemRegionManager; friend class MemRegionManager;
StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
: StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {} : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {}
@ -391,7 +401,6 @@ public:
class StackArgumentsSpaceRegion : public StackSpaceRegion { class StackArgumentsSpaceRegion : public StackSpaceRegion {
private: private:
virtual void anchor();
friend class MemRegionManager; friend class MemRegionManager;
StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
: StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {} : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {}
@ -408,11 +417,15 @@ public:
/// SubRegion - A region that subsets another larger region. Most regions /// SubRegion - A region that subsets another larger region. Most regions
/// are subclasses of SubRegion. /// are subclasses of SubRegion.
class SubRegion : public MemRegion { class SubRegion : public MemRegion {
private:
virtual void anchor(); virtual void anchor();
protected: protected:
const MemRegion* superRegion; 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: public:
const MemRegion* getSuperRegion() const { const MemRegion* getSuperRegion() const {
return superRegion; return superRegion;
@ -440,13 +453,18 @@ public:
/// by a call to 'alloca'. /// by a call to 'alloca'.
class AllocaRegion : public SubRegion { class AllocaRegion : public SubRegion {
friend class MemRegionManager; friend class MemRegionManager;
protected:
unsigned Cnt; // Block counter. Used to distinguish different pieces of unsigned Cnt; // Block counter. Used to distinguish different pieces of
// memory allocated by alloca at the same call site. // memory allocated by alloca at the same call site.
const Expr *Ex; const Expr *Ex;
AllocaRegion(const Expr *ex, unsigned cnt, const MemRegion *superRegion) AllocaRegion(const Expr *ex, unsigned cnt, const MemRegion *superRegion)
: SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) {} : SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) {
assert(Ex);
}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr *Ex,
unsigned Cnt, const MemRegion *superRegion);
public: public:
@ -458,9 +476,6 @@ public:
void Profile(llvm::FoldingSetNodeID& ID) const override; 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; void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion* R) { static bool classof(const MemRegion* R) {
@ -470,10 +485,12 @@ public:
/// TypedRegion - An abstract class representing regions that are typed. /// TypedRegion - An abstract class representing regions that are typed.
class TypedRegion : public SubRegion { class TypedRegion : public SubRegion {
public: virtual void anchor() override;
void anchor() override;
protected: protected:
TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {} TypedRegion(const MemRegion *sReg, Kind k) : SubRegion(sReg, k) {
assert(classof(this));
}
public: public:
virtual QualType getLocationType() const = 0; virtual QualType getLocationType() const = 0;
@ -492,10 +509,12 @@ public:
/// TypedValueRegion - An abstract class representing regions having a typed value. /// TypedValueRegion - An abstract class representing regions having a typed value.
class TypedValueRegion : public TypedRegion { class TypedValueRegion : public TypedRegion {
public: virtual void anchor() override;
void anchor() override;
protected: protected:
TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) {} TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) {
assert(classof(this));
}
public: public:
virtual QualType getValueType() const = 0; virtual QualType getValueType() const = 0;
@ -524,10 +543,13 @@ public:
class CodeTextRegion : public TypedRegion { class CodeTextRegion : public TypedRegion {
public: virtual void anchor() override;
void anchor() override;
protected: protected:
CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {} CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {
assert(classof(this));
}
public: public:
bool isBoundable() const override { return false; } bool isBoundable() const override { return false; }
@ -539,13 +561,19 @@ public:
/// FunctionCodeRegion - A region that represents code texts of function. /// FunctionCodeRegion - A region that represents code texts of function.
class FunctionCodeRegion : public CodeTextRegion { class FunctionCodeRegion : public CodeTextRegion {
friend class MemRegionManager;
const NamedDecl *FD; const NamedDecl *FD;
public:
FunctionCodeRegion(const NamedDecl *fd, const MemRegion* sreg) FunctionCodeRegion(const NamedDecl *fd, const MemRegion* sreg)
: CodeTextRegion(sreg, FunctionCodeRegionKind), FD(fd) { : CodeTextRegion(sreg, FunctionCodeRegionKind), FD(fd) {
assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd)); assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd));
} }
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const NamedDecl *FD,
const MemRegion*);
public:
QualType getLocationType() const override { QualType getLocationType() const override {
const ASTContext &Ctx = getContext(); const ASTContext &Ctx = getContext();
if (const FunctionDecl *D = dyn_cast<FunctionDecl>(FD)) { if (const FunctionDecl *D = dyn_cast<FunctionDecl>(FD)) {
@ -568,9 +596,6 @@ public:
void Profile(llvm::FoldingSetNodeID& ID) const override; void Profile(llvm::FoldingSetNodeID& ID) const override;
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const NamedDecl *FD,
const MemRegion*);
static bool classof(const MemRegion* R) { static bool classof(const MemRegion* R) {
return R->getKind() == FunctionCodeRegionKind; return R->getKind() == FunctionCodeRegionKind;
} }
@ -592,7 +617,15 @@ class BlockCodeRegion : public CodeTextRegion {
BlockCodeRegion(const BlockDecl *bd, CanQualType lTy, BlockCodeRegion(const BlockDecl *bd, CanQualType lTy,
AnalysisDeclContext *ac, const MemRegion* sreg) AnalysisDeclContext *ac, const MemRegion* sreg)
: CodeTextRegion(sreg, BlockCodeRegionKind), BD(bd), AC(ac), locTy(lTy) {} : 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: public:
QualType getLocationType() const override { QualType getLocationType() const override {
@ -609,10 +642,6 @@ public:
void Profile(llvm::FoldingSetNodeID& ID) const override; 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) { static bool classof(const MemRegion* R) {
return R->getKind() == BlockCodeRegionKind; return R->getKind() == BlockCodeRegionKind;
} }
@ -626,6 +655,7 @@ public:
/// variables. /// variables.
class BlockDataRegion : public TypedRegion { class BlockDataRegion : public TypedRegion {
friend class MemRegionManager; friend class MemRegionManager;
const BlockCodeRegion *BC; const BlockCodeRegion *BC;
const LocationContext *LC; // Can be null */ const LocationContext *LC; // Can be null */
unsigned BlockCount; unsigned BlockCount;
@ -634,9 +664,15 @@ class BlockDataRegion : public TypedRegion {
BlockDataRegion(const BlockCodeRegion *bc, const LocationContext *lc, BlockDataRegion(const BlockCodeRegion *bc, const LocationContext *lc,
unsigned count, const MemRegion *sreg) unsigned count, const MemRegion *sreg)
: TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc),
BlockCount(count), BlockCount(count), ReferencedVars(nullptr), OriginalVars(nullptr) {
ReferencedVars(nullptr), OriginalVars(nullptr) {} assert(bc);
assert(lc);
}
static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockCodeRegion *,
const LocationContext *, unsigned,
const MemRegion *);
public: public:
const BlockCodeRegion *getCodeRegion() const { return BC; } const BlockCodeRegion *getCodeRegion() const { return BC; }
@ -686,10 +722,6 @@ public:
void Profile(llvm::FoldingSetNodeID& ID) const override; 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) { static bool classof(const MemRegion* R) {
return R->getKind() == BlockDataRegionKind; return R->getKind() == BlockDataRegionKind;
} }
@ -705,13 +737,19 @@ private:
/// map the concept of symbolic values into the domain of regions. Symbolic /// map the concept of symbolic values into the domain of regions. Symbolic
/// regions do not need to be typed. /// regions do not need to be typed.
class SymbolicRegion : public SubRegion { class SymbolicRegion : public SubRegion {
protected: friend class MemRegionManager;
const SymbolRef sym; const SymbolRef sym;
public: SymbolicRegion(const SymbolRef s, const MemRegion *sreg)
SymbolicRegion(const SymbolRef s, const MemRegion* sreg) : SubRegion(sreg, SymbolicRegionKind), sym(s) {
: SubRegion(sreg, SymbolicRegionKind), sym(s) {} assert(s);
assert(s->getType()->isAnyPointerType() ||
s->getType()->isReferenceType() ||
s->getType()->isBlockPointerType());
}
public:
SymbolRef getSymbol() const { SymbolRef getSymbol() const {
return sym; return sym;
} }
@ -736,11 +774,13 @@ public:
/// StringRegion - Region associated with a StringLiteral. /// StringRegion - Region associated with a StringLiteral.
class StringRegion : public TypedValueRegion { class StringRegion : public TypedValueRegion {
friend class MemRegionManager; friend class MemRegionManager;
const StringLiteral* Str;
protected:
StringRegion(const StringLiteral* str, const MemRegion* sreg) const StringLiteral* Str;
: TypedValueRegion(sreg, StringRegionKind), Str(str) {}
StringRegion(const StringLiteral *str, const MemRegion *sreg)
: TypedValueRegion(sreg, StringRegionKind), Str(str) {
assert(str);
}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, static void ProfileRegion(llvm::FoldingSetNodeID& ID,
const StringLiteral* Str, const StringLiteral* Str,
@ -772,12 +812,14 @@ public:
/// The region associated with an ObjCStringLiteral. /// The region associated with an ObjCStringLiteral.
class ObjCStringRegion : public TypedValueRegion { class ObjCStringRegion : public TypedValueRegion {
friend class MemRegionManager; friend class MemRegionManager;
const ObjCStringLiteral* Str; const ObjCStringLiteral* Str;
protected:
ObjCStringRegion(const ObjCStringLiteral *str, const MemRegion *sreg)
ObjCStringRegion(const ObjCStringLiteral* str, const MemRegion* sreg) : TypedValueRegion(sreg, ObjCStringRegionKind), Str(str) {
: TypedValueRegion(sreg, ObjCStringRegionKind), Str(str) {} assert(str);
}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, static void ProfileRegion(llvm::FoldingSetNodeID& ID,
const ObjCStringLiteral* Str, const ObjCStringLiteral* Str,
const MemRegion* superRegion); const MemRegion* superRegion);
@ -807,12 +849,14 @@ public:
/// Compound literals are essentially temporaries that are stack allocated /// Compound literals are essentially temporaries that are stack allocated
/// or in the global constant pool. /// or in the global constant pool.
class CompoundLiteralRegion : public TypedValueRegion { class CompoundLiteralRegion : public TypedValueRegion {
private:
friend class MemRegionManager; friend class MemRegionManager;
const CompoundLiteralExpr *CL; const CompoundLiteralExpr *CL;
CompoundLiteralRegion(const CompoundLiteralExpr *cl, const MemRegion* sReg) CompoundLiteralRegion(const CompoundLiteralExpr *cl, const MemRegion *sReg)
: TypedValueRegion(sReg, CompoundLiteralRegionKind), CL(cl) {} : TypedValueRegion(sReg, CompoundLiteralRegionKind), CL(cl) {
assert(cl);
}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, static void ProfileRegion(llvm::FoldingSetNodeID& ID,
const CompoundLiteralExpr *CL, const CompoundLiteralExpr *CL,
@ -839,8 +883,11 @@ class DeclRegion : public TypedValueRegion {
protected: protected:
const Decl *D; const Decl *D;
DeclRegion(const Decl *d, const MemRegion* sReg, Kind k) DeclRegion(const Decl *d, const MemRegion *sReg, Kind k)
: TypedValueRegion(sReg, k), D(d) {} : TypedValueRegion(sReg, k), D(d) {
assert(classof(this));
assert(d);
}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl *D, static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl *D,
const MemRegion* superRegion, Kind k); const MemRegion* superRegion, Kind k);
@ -867,9 +914,9 @@ class VarRegion : public DeclRegion {
DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind); DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind);
} }
public:
void Profile(llvm::FoldingSetNodeID& ID) const override; void Profile(llvm::FoldingSetNodeID& ID) const override;
public:
const VarDecl *getDecl() const { return cast<VarDecl>(D); } const VarDecl *getDecl() const { return cast<VarDecl>(D); }
const StackFrameContext *getStackFrame() const; const StackFrameContext *getStackFrame() const;
@ -895,17 +942,18 @@ public:
/// referred to by 'this', but rather 'this' itself. /// referred to by 'this', but rather 'this' itself.
class CXXThisRegion : public TypedValueRegion { class CXXThisRegion : public TypedValueRegion {
friend class MemRegionManager; friend class MemRegionManager;
CXXThisRegion(const PointerType *thisPointerTy,
const MemRegion *sReg) CXXThisRegion(const PointerType *thisPointerTy, const MemRegion *sReg)
: TypedValueRegion(sReg, CXXThisRegionKind), ThisPointerTy(thisPointerTy) {} : TypedValueRegion(sReg, CXXThisRegionKind),
ThisPointerTy(thisPointerTy) {}
static void ProfileRegion(llvm::FoldingSetNodeID &ID, static void ProfileRegion(llvm::FoldingSetNodeID &ID,
const PointerType *PT, const PointerType *PT,
const MemRegion *sReg); const MemRegion *sReg);
public:
void Profile(llvm::FoldingSetNodeID &ID) const override; void Profile(llvm::FoldingSetNodeID &ID) const override;
public:
QualType getValueType() const override { QualType getValueType() const override {
return QualType(ThisPointerTy, 0); return QualType(ThisPointerTy, 0);
} }
@ -926,6 +974,11 @@ class FieldRegion : public DeclRegion {
FieldRegion(const FieldDecl *fd, const MemRegion* sReg) FieldRegion(const FieldDecl *fd, const MemRegion* sReg)
: DeclRegion(fd, sReg, FieldRegionKind) {} : DeclRegion(fd, sReg, FieldRegionKind) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl *FD,
const MemRegion* superRegion) {
DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind);
}
public: public:
const FieldDecl *getDecl() const { return cast<FieldDecl>(D); } const FieldDecl *getDecl() const { return cast<FieldDecl>(D); }
@ -936,11 +989,6 @@ public:
DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; 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) { static bool classof(const MemRegion* R) {
return R->getKind() == FieldRegionKind; return R->getKind() == FieldRegionKind;
} }
@ -954,7 +1002,6 @@ public:
}; };
class ObjCIvarRegion : public DeclRegion { class ObjCIvarRegion : public DeclRegion {
friend class MemRegionManager; friend class MemRegionManager;
ObjCIvarRegion(const ObjCIvarDecl *ivd, const MemRegion* sReg); ObjCIvarRegion(const ObjCIvarDecl *ivd, const MemRegion* sReg);
@ -982,7 +1029,6 @@ public:
class ElementRegion; class ElementRegion;
class RegionRawOffset { class RegionRawOffset {
private:
friend class ElementRegion; friend class ElementRegion;
const MemRegion *Region; const MemRegion *Region;
@ -1047,12 +1093,14 @@ class CXXTempObjectRegion : public TypedValueRegion {
Expr const *Ex; Expr const *Ex;
CXXTempObjectRegion(Expr const *E, MemRegion const *sReg) CXXTempObjectRegion(Expr const *E, MemRegion const *sReg)
: TypedValueRegion(sReg, CXXTempObjectRegionKind), Ex(E) {} : TypedValueRegion(sReg, CXXTempObjectRegionKind), Ex(E) {
assert(E);
}
static void ProfileRegion(llvm::FoldingSetNodeID &ID, static void ProfileRegion(llvm::FoldingSetNodeID &ID,
Expr const *E, const MemRegion *sReg); Expr const *E, const MemRegion *sReg);
public: public:
const Expr *getExpr() const { return Ex; } const Expr *getExpr() const { return Ex; }
@ -1078,7 +1126,9 @@ class CXXBaseObjectRegion : public TypedValueRegion {
CXXBaseObjectRegion(const CXXRecordDecl *RD, bool IsVirtual, CXXBaseObjectRegion(const CXXRecordDecl *RD, bool IsVirtual,
const MemRegion *SReg) const MemRegion *SReg)
: TypedValueRegion(SReg, CXXBaseObjectRegionKind), Data(RD, IsVirtual) {} : TypedValueRegion(SReg, CXXBaseObjectRegionKind), Data(RD, IsVirtual) {
assert(RD);
}
static void ProfileRegion(llvm::FoldingSetNodeID &ID, const CXXRecordDecl *RD, static void ProfileRegion(llvm::FoldingSetNodeID &ID, const CXXRecordDecl *RD,
bool IsVirtual, const MemRegion *SReg); bool IsVirtual, const MemRegion *SReg);

View File

@ -41,6 +41,22 @@ class MemRegionManager;
class ProgramStateManager; class ProgramStateManager;
class SValBuilder; 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 /// SVal - This represents a symbolic expression, which can be either
/// an L-value or an R-value. /// an L-value or an R-value.
/// ///
@ -75,10 +91,7 @@ public:
template<typename T> template<typename T>
T castAs() const { T castAs() const {
assert(T::isKind(*this)); assert(T::isKind(*this));
T t; return *static_cast<const T *>(this);
SVal& sv = t;
sv = *this;
return t;
} }
/// \brief Convert to the specified SVal type, returning None if this SVal is /// \brief Convert to the specified SVal type, returning None if this SVal is
@ -87,10 +100,7 @@ public:
Optional<T> getAs() const { Optional<T> getAs() const {
if (!T::isKind(*this)) if (!T::isKind(*this))
return None; return None;
T t; return *static_cast<const T *>(this);
SVal& sv = t;
sv = *this;
return t;
} }
/// BufferTy - A temporary buffer to hold a set of SVals. /// BufferTy - A temporary buffer to hold a set of SVals.
@ -273,6 +283,11 @@ protected:
public: public:
void dumpToStream(raw_ostream &Out) const; void dumpToStream(raw_ostream &Out) const;
static inline bool isCompoundType(QualType T) {
return T->isArrayType() || T->isRecordType() ||
T->isComplexType() || T->isVectorType();
}
private: private:
friend class SVal; friend class SVal;
static bool isKind(const SVal& V) { static bool isKind(const SVal& V) {
@ -307,15 +322,11 @@ private:
namespace nonloc { namespace nonloc {
enum Kind {
#define NONLOC_SVAL(Id, Parent) Id ## Kind,
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
};
/// \brief Represents symbolic expression. /// \brief Represents symbolic expression.
class SymbolVal : public NonLoc { class SymbolVal : public NonLoc {
public: public:
SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {} SymbolVal() = delete;
SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) { assert(sym); }
SymbolRef getSymbol() const { SymbolRef getSymbol() const {
return (const SymExpr*) Data; return (const SymExpr*) Data;
@ -327,7 +338,6 @@ public:
private: private:
friend class SVal; friend class SVal;
SymbolVal() {}
static bool isKind(const SVal& V) { static bool isKind(const SVal& V) {
return V.getBaseKind() == NonLocKind && return V.getBaseKind() == NonLocKind &&
V.getSubKind() == SymbolValKind; V.getSubKind() == SymbolValKind;
@ -373,7 +383,11 @@ class LocAsInteger : public NonLoc {
explicit LocAsInteger(const std::pair<SVal, uintptr_t> &data) explicit LocAsInteger(const std::pair<SVal, uintptr_t> &data)
: NonLoc(LocAsIntegerKind, &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: public:
@ -513,14 +527,11 @@ private:
namespace loc { namespace loc {
enum Kind {
#define LOC_SVAL(Id, Parent) Id ## Kind,
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
};
class GotoLabel : public Loc { class GotoLabel : public Loc {
public: public:
explicit GotoLabel(LabelDecl *Label) : Loc(GotoLabelKind, Label) {} explicit GotoLabel(const LabelDecl *Label) : Loc(GotoLabelKind, Label) {
assert(Label);
}
const LabelDecl *getLabel() const { const LabelDecl *getLabel() const {
return static_cast<const LabelDecl*>(Data); return static_cast<const LabelDecl*>(Data);
@ -541,7 +552,9 @@ private:
class MemRegionVal : public Loc { class MemRegionVal : public Loc {
public: public:
explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) {} explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) {
assert(r);
}
/// \brief Get the underlining region. /// \brief Get the underlining region.
const MemRegion* getRegion() const { const MemRegion* getRegion() const {

View File

@ -42,6 +42,12 @@ private:
protected: protected:
SymExpr(Kind k) : K(k) {} 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: public:
virtual ~SymExpr() {} virtual ~SymExpr() {}
@ -103,7 +109,9 @@ class SymbolData : public SymExpr {
const SymbolID Sym; const SymbolID Sym;
protected: protected:
SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) {} SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) {
assert(classof(this));
}
public: public:
~SymbolData() override {} ~SymbolData() override {}

View File

@ -44,7 +44,10 @@ class SymbolRegionValue : public SymbolData {
public: public:
SymbolRegionValue(SymbolID sym, const TypedValueRegion *r) 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; } const TypedValueRegion* getRegion() const { return R; }
@ -81,7 +84,15 @@ public:
SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx, SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx,
QualType t, unsigned count, const void *symbolTag) QualType t, unsigned count, const void *symbolTag)
: SymbolData(SymbolConjuredKind, sym), S(s), T(t), Count(count), : 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; } const Stmt *getStmt() const { return S; }
unsigned getCount() const { return Count; } unsigned getCount() const { return Count; }
@ -120,7 +131,11 @@ class SymbolDerived : public SymbolData {
public: public:
SymbolDerived(SymbolID sym, SymbolRef parent, const TypedValueRegion *r) 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; } SymbolRef getParentSymbol() const { return parentSymbol; }
const TypedValueRegion *getRegion() const { return R; } const TypedValueRegion *getRegion() const { return R; }
@ -155,7 +170,9 @@ class SymbolExtent : public SymbolData {
public: public:
SymbolExtent(SymbolID sym, const SubRegion *r) SymbolExtent(SymbolID sym, const SubRegion *r)
: SymbolData(SymbolExtentKind, sym), R(r) {} : SymbolData(SymbolExtentKind, sym), R(r) {
assert(r);
}
const SubRegion *getRegion() const { return R; } const SubRegion *getRegion() const { return R; }
@ -193,7 +210,13 @@ public:
SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t, SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t,
const LocationContext *LCtx, unsigned count, const void *tag) const LocationContext *LCtx, unsigned count, const void *tag)
: SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), LCtx(LCtx), : 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 MemRegion *getRegion() const { return R; }
const Stmt *getStmt() const { return S; } const Stmt *getStmt() const { return S; }
@ -236,8 +259,13 @@ class SymbolCast : public SymExpr {
QualType ToTy; QualType ToTy;
public: public:
SymbolCast(const SymExpr *In, QualType From, QualType To) : SymbolCast(const SymExpr *In, QualType From, QualType To)
SymExpr(SymbolCastKind), Operand(In), FromTy(From), ToTy(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; } QualType getType() const override { return ToTy; }
@ -270,7 +298,10 @@ class BinarySymExpr : public SymExpr {
protected: protected:
BinarySymExpr(Kind k, BinaryOperator::Opcode op, QualType t) 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: public:
// FIXME: We probably need to make this out-of-line to avoid redundant // FIXME: We probably need to make this out-of-line to avoid redundant
@ -293,8 +324,10 @@ class SymIntExpr : public BinarySymExpr {
public: public:
SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
const llvm::APSInt& rhs, QualType t) const llvm::APSInt &rhs, QualType t)
: BinarySymExpr(SymIntExprKind, op, t), LHS(lhs), RHS(rhs) {} : BinarySymExpr(SymIntExprKind, op, t), LHS(lhs), RHS(rhs) {
assert(lhs);
}
void dumpToStream(raw_ostream &os) const override; void dumpToStream(raw_ostream &os) const override;
@ -327,9 +360,11 @@ class IntSymExpr : public BinarySymExpr {
const SymExpr *RHS; const SymExpr *RHS;
public: public:
IntSymExpr(const llvm::APSInt& lhs, BinaryOperator::Opcode op, IntSymExpr(const llvm::APSInt &lhs, BinaryOperator::Opcode op,
const SymExpr *rhs, QualType t) 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; void dumpToStream(raw_ostream &os) const override;
@ -364,7 +399,10 @@ class SymSymExpr : public BinarySymExpr {
public: public:
SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs,
QualType t) 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 *getLHS() const { return LHS; }
const SymExpr *getRHS() const { return RHS; } const SymExpr *getRHS() const { return RHS; }

View File

@ -379,10 +379,8 @@ void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
void GlobalsSpaceRegion::anchor() { } void GlobalsSpaceRegion::anchor() { }
void HeapSpaceRegion::anchor() { } void NonStaticGlobalSpaceRegion::anchor() { }
void UnknownSpaceRegion::anchor() { } void StackSpaceRegion::anchor() { }
void StackLocalsSpaceRegion::anchor() { }
void StackArgumentsSpaceRegion::anchor() { }
void TypedRegion::anchor() { } void TypedRegion::anchor() { }
void TypedValueRegion::anchor() { } void TypedValueRegion::anchor() { }
void CodeTextRegion::anchor() { } void CodeTextRegion::anchor() { }