class AddStmtChoice {
public:
- enum Kind { NotAlwaysAdd = 0, AlwaysAdd, AlwaysAddAsLValue };
+ enum Kind { NotAlwaysAdd = 0,
+ AlwaysAdd = 1,
+ AsLValueNotAlwaysAdd = 2,
+ AlwaysAddAsLValue = 3 };
+
public:
- AddStmtChoice(Kind kind) : k(kind) {}
- bool alwaysAdd() const { return k != NotAlwaysAdd; }
- bool asLValue() const { return k == AlwaysAddAsLValue; }
+ AddStmtChoice(Kind k)
+ : AsLValue(k >= AlwaysAddAsLValue), AlwaysAddStmt((unsigned)k & 0x1) {}
+
+ bool alwaysAdd() const { return (bool) AlwaysAddStmt; };
+ bool asLValue() const { return (bool) AsLValue; };
+
private:
- Kind k;
+ unsigned AsLValue : 1;
+ unsigned AlwaysAddStmt : 1;
};
/// CFGBuilder - This class implements CFG construction from an AST.
Expr *Init = VD->getInit();
if (Init) {
- // Optimization: Don't create separate block-level statements for literals.
- switch (Init->getStmtClass()) {
- case Stmt::IntegerLiteralClass:
- case Stmt::CharacterLiteralClass:
- case Stmt::StringLiteralClass:
- break;
- default:
- Block = addStmt(Init,
- VD->getType()->isReferenceType()
- ? AddStmtChoice::AlwaysAddAsLValue
- : AddStmtChoice::AlwaysAdd);
- }
+ AddStmtChoice::Kind k =
+ VD->getType()->isReferenceType() ? AddStmtChoice::AsLValueNotAlwaysAdd
+ : AddStmtChoice::NotAlwaysAdd;
+ Visit(Init, AddStmtChoice(k));
}
// If the type of VD is a VLA, then we must process its size expressions.
for (DeclStmt::decl_iterator I=S->decl_begin(), E=S->decl_end(); I!=E; ++I) {
VarDecl *VD = dyn_cast<VarDecl>(*I);
if (VD && VD->isBlockVarDecl()) {
- if (Stmt* I = VD->getInit())
- V(VD,AD) = AD.FullUninitTaint ? V(cast<Expr>(I),AD) : Initialized;
+ if (Stmt* I = VD->getInit()) {
+ // Visit the subexpression to check for uses of uninitialized values,
+ // even if we don't propagate that value.
+ bool isSubExprUninit = Visit(I);
+ V(VD,AD) = AD.FullUninitTaint ? isSubExprUninit : Initialized;
+ }
else {
// Special case for declarations of array types. For things like:
//
const char *sep);
private:
+ SVal LazyRetrieve(Store store, const TypedRegion *R);
+
ASTContext& getContext() { return StateMgr.getContext(); }
};
}
}
+SVal BasicStoreManager::LazyRetrieve(Store store, const TypedRegion *R) {
+ const VarRegion *VR = dyn_cast<VarRegion>(R);
+ if (!VR)
+ return UnknownVal();
+
+ const VarDecl *VD = VR->getDecl();
+ QualType T = VD->getType();
+
+ // Only handle simple types that we can symbolicate.
+ if (!SymbolManager::canSymbolicate(T) || !T->isScalarType())
+ return UnknownVal();
+
+ // Globals and parameters start with symbolic values.
+ // Local variables initially are undefined.
+ if (VR->hasGlobalsOrParametersStorage())
+ return ValMgr.getRegionValueSymbolVal(R);
+ return UndefinedVal();
+}
+
SVal BasicStoreManager::Retrieve(Store store, Loc loc, QualType T) {
if (isa<UnknownVal>(loc))
return UnknownVal();
BindingsTy B = GetBindings(store);
BindingsTy::data_type *Val = B.lookup(R);
+ const TypedRegion *TR = cast<TypedRegion>(R);
- if (!Val)
- break;
+ if (Val)
+ return CastRetrievedVal(*Val, TR, T);
- return CastRetrievedVal(*Val, cast<TypedRegion>(R), T);
+ SVal V = LazyRetrieve(store, TR);
+ return V.isUnknownOrUndef() ? V : CastRetrievedVal(V, TR, T);
}
case loc::ConcreteIntKind:
// SelfRegion? (i.e., it implements MD->getClassInterface()).
const VarRegion *VR = MRMgr.getVarRegion(PD, InitLoc);
const MemRegion *SelfRegion =
- ValMgr.getRegionValueSymbolVal(VR).getAsRegion();
- assert(SelfRegion);
+ ValMgr.getRegionValueSymbolVal(VR).getAsRegion();
+ assert(SelfRegion);
St = Bind(St, ValMgr.makeLoc(VR), loc::MemRegionVal(SelfRegion));
// Scan the method for ivar references. While this requires an
// entire AST scan, the cost should not be high in practice.
}
}
}
- else if (VarDecl* VD = dyn_cast<VarDecl>(ND)) {
- // Only handle simple types that we can symbolicate.
- if (!SymbolManager::canSymbolicate(VD->getType()))
- continue;
-
- // Initialize globals and parameters to symbolic values.
- // Initialize local variables to undefined.
- const VarRegion *R = ValMgr.getRegionManager().getVarRegion(VD, InitLoc);
- SVal X = UndefinedVal();
- if (R->hasGlobalsOrParametersStorage())
- X = ValMgr.getRegionValueSymbolVal(R);
-
- St = Bind(St, ValMgr.makeLoc(R), X);
- }
}
+
return St;
}