diff options
author | Ted Kremenek <kremenek@apple.com> | 2008-04-22 22:25:27 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2008-04-22 22:25:27 +0000 |
commit | 5b7dcce86c79370f16fd89ecebd454a3b4eec73c (patch) | |
tree | c4e4a69f7d636fa84da06fc6d91b631e519aa8d8 /lib/Analysis/GRExprEngine.cpp | |
parent | a548846b471f7ca05ec6038c7d9d3b4d0de777cc (diff) |
Rewrote VisitDeclStmt to properly handle initializers that can do anything.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50112 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/GRExprEngine.cpp')
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 138 |
1 files changed, 84 insertions, 54 deletions
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 128ef82c63..3da8a72c57 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -1164,76 +1164,106 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){ } } -void GRExprEngine::VisitDeclStmt(DeclStmt* DS, GRExprEngine::NodeTy* Pred, - GRExprEngine::NodeSet& Dst) { +void GRExprEngine::VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst) { + VisitDeclStmtAux(DS, DS->getDecl(), Pred, Dst); +} + +void GRExprEngine::VisitDeclStmtAux(DeclStmt* DS, ScopedDecl* D, + NodeTy* Pred, NodeSet& Dst) { + + if (!D) + return; - ValueState* St = GetState(Pred); + if (!isa<VarDecl>(D)) { + VisitDeclStmtAux(DS, D->getNextDeclarator(), Pred, Dst); + return; + } + + const VarDecl* VD = dyn_cast<VarDecl>(D); + + // FIXME: Add support for local arrays. + if (VD->getType()->isArrayType()) { + VisitDeclStmtAux(DS, D->getNextDeclarator(), Pred, Dst); + return; + } - for (const ScopedDecl* D = DS->getDecl(); D; D = D->getNextDeclarator()) - if (const VarDecl* VD = dyn_cast<VarDecl>(D)) { + Expr* Ex = const_cast<Expr*>(VD->getInit()); + + // FIXME: static variables may have an initializer, but the second + // time a function is called those values may not be current. + NodeSet Tmp; + + if (Ex) Visit(Ex, Pred, Tmp); + if (Tmp.empty()) Tmp.Add(Pred); + + for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { - // FIXME: Add support for local arrays. - if (VD->getType()->isArrayType()) - continue; + ValueState* St = GetState(*I); + + if (!Ex && VD->hasGlobalStorage()) { - const Expr* Ex = VD->getInit(); + // Handle variables with global storage and no initializers. - if (!VD->hasGlobalStorage() || VD->getStorageClass() == VarDecl::Static) { - - // In this context, Static => Local variable. - - assert (!VD->getStorageClass() == VarDecl::Static || - !VD->isFileVarDecl()); + // FIXME: static variables may have an initializer, but the second + // time a function is called those values may not be current. + + + // In this context, Static => Local variable. + + assert (!VD->getStorageClass() == VarDecl::Static || + !VD->isFileVarDecl()); + + // If there is no initializer, set the value of the + // variable to "Undefined". + + if (VD->getStorageClass() == VarDecl::Static) { + + // C99: 6.7.8 Initialization + // If an object that has static storage duration is not initialized + // explicitly, then: + // —if it has pointer type, it is initialized to a null pointer; + // —if it has arithmetic type, it is initialized to (positive or + // unsigned) zero; - // If there is no initializer, set the value of the - // variable to "Undefined". - // - // FIXME: static variables may have an initializer, but the second - // time a function is called those values may not be current. + // FIXME: Handle structs. Now we treat their values as unknown. QualType T = VD->getType(); - if ( VD->getStorageClass() == VarDecl::Static) { - - // C99: 6.7.8 Initialization - // If an object that has static storage duration is not initialized - // explicitly, then: - // —if it has pointer type, it is initialized to a null pointer; - // —if it has arithmetic type, it is initialized to (positive or - // unsigned) zero; - - // FIXME: Handle structs. Now we treat their values as unknown. - - if (T->isPointerType()) { - - St = SetRVal(St, lval::DeclVal(VD), - lval::ConcreteInt(BasicVals.getValue(0, T))); - } - else if (T->isIntegerType()) { - - St = SetRVal(St, lval::DeclVal(VD), - nonlval::ConcreteInt(BasicVals.getValue(0, T))); - } - - - } - else { - - // FIXME: Handle structs. Now we treat them as unknown. What - // we need to do is treat their members as unknown. + if (T->isPointerType()) + St = SetRVal(St, lval::DeclVal(VD), + lval::ConcreteInt(BasicVals.getValue(0, T))); + else if (T->isIntegerType()) + St = SetRVal(St, lval::DeclVal(VD), + nonlval::ConcreteInt(BasicVals.getValue(0, T))); - if (T->isPointerType() || T->isIntegerType()) - St = SetRVal(St, lval::DeclVal(VD), - Ex ? GetRVal(St, Ex) : UndefinedVal()); - } + // FIXME: Handle structs. Now we treat them as unknown. What + // we need to do is treat their members as unknown. } } + else { + + // FIXME: Handle structs. Now we treat them as unknown. What + // we need to do is treat their members as unknown. + + QualType T = VD->getType(); + + if (T->isPointerType() || T->isIntegerType()) + St = SetRVal(St, lval::DeclVal(VD), + Ex ? GetRVal(St, Ex) : UndefinedVal()); + } - MakeNode(Dst, DS, Pred, St); + // Create a new node. We don't really need to create a new NodeSet + // here, but it simplifies things and doesn't cost much. + NodeSet Tmp2; + MakeNode(Tmp2, DS, *I, St); + if (Tmp2.empty()) Tmp2.Add(*I); + + for (NodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end(); I2!=E2; ++I2) + VisitDeclStmtAux(DS, D->getNextDeclarator(), *I2, Dst); + } } - /// VisitSizeOfAlignOfTypeExpr - Transfer function for sizeof(type). void GRExprEngine::VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr* Ex, NodeTy* Pred, |