void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, ExplodedNodeSet &Dst) { // FIXME: static variables may have an initializer, but the second // time a function is called those values may not be current. // This may need to be reflected in the CFG. // Assumption: The CFG has one DeclStmt per Decl. const Decl *D = *DS->decl_begin(); if (!D || !isa<VarDecl>(D)) { //TODO:AZ: remove explicit insertion after refactoring is done. Dst.insert(Pred); return; } // FIXME: all pre/post visits should eventually be handled by ::Visit(). ExplodedNodeSet dstPreVisit; getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, DS, *this); StmtNodeBuilder B(dstPreVisit, Dst, *currentBuilderContext); const VarDecl *VD = dyn_cast<VarDecl>(D); for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end(); I!=E; ++I) { ExplodedNode *N = *I; ProgramStateRef state = N->getState(); // Decls without InitExpr are not initialized explicitly. const LocationContext *LC = N->getLocationContext(); if (const Expr *InitEx = VD->getInit()) { SVal InitVal = state->getSVal(InitEx, LC); if (InitVal == state->getLValue(VD, LC) || (VD->getType()->isArrayType() && isa<CXXConstructExpr>(InitEx->IgnoreImplicit()))) { // We constructed the object directly in the variable. // No need to bind anything. B.generateNode(DS, N, state); } else { // We bound the temp obj region to the CXXConstructExpr. Now recover // the lazy compound value when the variable is not a reference. if (AMgr.getLangOpts().CPlusPlus && VD->getType()->isRecordType() && !VD->getType()->isReferenceType() && isa<loc::MemRegionVal>(InitVal)){ InitVal = state->getSVal(cast<loc::MemRegionVal>(InitVal).getRegion()); assert(isa<nonloc::LazyCompoundVal>(InitVal)); } // Recover some path-sensitivity if a scalar value evaluated to // UnknownVal. if (InitVal.isUnknown()) { QualType Ty = InitEx->getType(); if (InitEx->isGLValue()) { Ty = getContext().getPointerType(Ty); } InitVal = svalBuilder.getConjuredSymbolVal(NULL, InitEx, LC, Ty, currentBuilderContext->getCurrentBlockCount()); } B.takeNodes(N); ExplodedNodeSet Dst2; evalBind(Dst2, DS, N, state->getLValue(VD, LC), InitVal, true); B.addNodes(Dst2); } } else { B.generateNode(DS, N,state->bindDeclWithNoInit(state->getRegion(VD, LC))); } } }