UninitializedValues.cpp revision 2f868c013935791c421def45b422a6f6e79d2e4a
113ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek//==- UninitializedValues.cpp - Find Unintialized Values --------*- C++ --*-==// 213ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek// 313ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek// The LLVM Compiler Infrastructure 413ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek// 50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source 60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details. 713ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek// 813ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek//===----------------------------------------------------------------------===// 913ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek// 1013ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek// This file implements Uninitialized Values analysis for source-level CFGs. 1113ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek// 1213ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek//===----------------------------------------------------------------------===// 1313ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 14cf6e41baf2b23b6b56f0f79fff5554b7745737acTed Kremenek#include "clang/Analysis/Analyses/UninitializedValues.h" 1511de5cbe8162c368fea8384806d507649ac7c959Ted Kremenek#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h" 16cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek#include "clang/Analysis/LocalCheckers.h" 17cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek#include "clang/Basic/Diagnostic.h" 18cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek#include "clang/AST/ASTContext.h" 191de632bf4abb75fcd39f5d6fdf59337f0ff0edd4Ted Kremenek#include "clang/Analysis/FlowSensitive/DataflowSolver.h" 20c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenek#include "llvm/Support/Compiler.h" 2113ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 22cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek#include "llvm/ADT/SmallPtrSet.h" 23cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek 2413ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenekusing namespace clang; 2513ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 26cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 2713ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek// Dataflow initialization logic. 28cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 2913ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 3013ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremeneknamespace { 3113ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 32c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenekclass VISIBILITY_HIDDEN RegisterDecls 33c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenek : public CFGRecStmtDeclVisitor<RegisterDecls> { 34c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenek 3556d516d18a789a13696a310dbca67d4b5d9fc798Ted Kremenek UninitializedValues::AnalysisDataTy& AD; 3613ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenekpublic: 3711e7218db51efc825ec24e80d5b071892ca268bdTed Kremenek RegisterDecls(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {} 3813ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 39606ceeef820a3ecd46255d155e5d7f3aa888a04bTed Kremenek void VisitVarDecl(VarDecl* VD) { AD.Register(VD); } 409f9141cd46b87cefd74625d92634a5aa93d2c9c6Ted Kremenek CFG& getCFG() { return AD.getCFG(); } 4113ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek}; 4213ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 4313ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek} // end anonymous namespace 4413ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 4513ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenekvoid UninitializedValues::InitializeValues(const CFG& cfg) { 4611e7218db51efc825ec24e80d5b071892ca268bdTed Kremenek RegisterDecls R(getAnalysisData()); 47a90b0d1e585d993621a342d0b2874e61941372d5Ted Kremenek cfg.VisitBlockStmts(R); 4813ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek} 4913ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 50cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 5113ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek// Transfer functions. 52cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 5313ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 5413ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremeneknamespace { 55c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenekclass VISIBILITY_HIDDEN TransferFuncs 56c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenek : public CFGStmtVisitor<TransferFuncs,bool> { 57c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenek 5813ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek UninitializedValues::ValTy V; 5956d516d18a789a13696a310dbca67d4b5d9fc798Ted Kremenek UninitializedValues::AnalysisDataTy& AD; 6013ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenekpublic: 617deed0c65b315cac037539401c49586283158d9fTed Kremenek TransferFuncs(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {} 6213ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 6313ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek UninitializedValues::ValTy& getVal() { return V; } 649f9141cd46b87cefd74625d92634a5aa93d2c9c6Ted Kremenek CFG& getCFG() { return AD.getCFG(); } 6556d516d18a789a13696a310dbca67d4b5d9fc798Ted Kremenek 667deed0c65b315cac037539401c49586283158d9fTed Kremenek void SetTopValue(UninitializedValues::ValTy& X) { 677deed0c65b315cac037539401c49586283158d9fTed Kremenek X.resetValues(AD); 687deed0c65b315cac037539401c49586283158d9fTed Kremenek } 697deed0c65b315cac037539401c49586283158d9fTed Kremenek 7020ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek bool VisitDeclRefExpr(DeclRefExpr* DR); 7120ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek bool VisitBinaryOperator(BinaryOperator* B); 7220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek bool VisitUnaryOperator(UnaryOperator* U); 7320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek bool VisitStmt(Stmt* S); 7420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek bool VisitCallExpr(CallExpr* C); 75cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek bool VisitDeclStmt(DeclStmt* D); 76a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek bool VisitConditionalOperator(ConditionalOperator* C); 77a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek 78a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek bool Visit(Stmt *S); 79a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek bool BlockStmt_VisitExpr(Expr* E); 8037622081d8a139a3249613acaa80106ec97261fbTed Kremenek 817deed0c65b315cac037539401c49586283158d9fTed Kremenek void VisitTerminator(Stmt* T) { } 8213ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek}; 83aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek 84aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenekstatic const bool Initialized = true; 85aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenekstatic const bool Uninitialized = false; 8620ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 8720ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) { 882f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek 892f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) 902f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (VD->isBlockVarDecl()) { 912f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek 922f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (AD.Observer) 932f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek AD.Observer->ObserveDeclRefExpr(V, AD, DR, VD); 94a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek 952f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek // Pseudo-hack to prevent cascade of warnings. If an accessed variable 962f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek // is uninitialized, then we are already going to flag a warning for 972f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek // this variable, which a "source" of uninitialized values. 982f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek // We can otherwise do a full "taint" of uninitialized values. The 992f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek // client has both options by toggling AD.FullUninitTaint. 100a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek 1012f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (AD.FullUninitTaint) 1022f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek return V(VD,AD); 1032f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek } 1042f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek 1052f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek return Initialized; 10643a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek} 10743a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek 1082f868c013935791c421def45b422a6f6e79d2e4aTed Kremenekstatic VarDecl* FindBlockVarDecl(Expr* E) { 1092f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek 1102f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek // Blast through casts and parentheses to find any DeclRefExprs that 1112f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek // refer to a block VarDecl. 1122f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek 1132f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts())) 1142f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) 1152f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (VD->isBlockVarDecl()) return VD; 1162f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek 1172f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek return NULL; 11820ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 11920ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 12020ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitBinaryOperator(BinaryOperator* B) { 1212f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek 1222f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (VarDecl* VD = FindBlockVarDecl(B->getLHS())) 1236ce2b630652911c5b463ce0203855b1eaf4694bdTed Kremenek if (B->isAssignmentOp()) { 124ff7c538f7c37539bceb99113f7d507cd98daa578Ted Kremenek if (B->getOpcode() == BinaryOperator::Assign) 125ff7c538f7c37539bceb99113f7d507cd98daa578Ted Kremenek return V(VD,AD) = Visit(B->getRHS()); 126ff7c538f7c37539bceb99113f7d507cd98daa578Ted Kremenek else // Handle +=, -=, *=, etc. We do want '&', not '&&'. 127ff7c538f7c37539bceb99113f7d507cd98daa578Ted Kremenek return V(VD,AD) = Visit(B->getLHS()) & Visit(B->getRHS()); 1286ce2b630652911c5b463ce0203855b1eaf4694bdTed Kremenek } 1296ce2b630652911c5b463ce0203855b1eaf4694bdTed Kremenek 13020ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek return VisitStmt(B); 13120ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 13220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 133cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenekbool TransferFuncs::VisitDeclStmt(DeclStmt* S) { 134248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff for (ScopedDecl* D = S->getDecl(); D != NULL; D = D->getNextDeclarator()) { 135248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff VarDecl *VD = dyn_cast<VarDecl>(D); 136248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff if (VD && VD->isBlockVarDecl()) { 137a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek if (Stmt* I = VD->getInit()) 138a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek V(VD,AD) = AD.FullUninitTaint ? V(cast<Expr>(I),AD) : Initialized; 13981a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek else { 14081a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // Special case for declarations of array types. For things like: 14181a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // 14281a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // char x[10]; 14381a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // 14481a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // we should treat "x" as being initialized, because the variable 14581a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // "x" really refers to the memory block. Clearly x[1] is 14681a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // uninitialized, but expressions like "(char *) x" really do refer to 14781a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // an initialized value. This simple dataflow analysis does not reason 14881a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // about the contents of arrays, although it could be potentially 14981a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // extended to do so if the array were of constant size. 15081a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek if (VD->getType()->isArrayType()) 15181a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek V(VD,AD) = Initialized; 15281a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek else 15381a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek V(VD,AD) = Uninitialized; 15481a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek } 155aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek } 156248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff } 157a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek return Uninitialized; // Value is never consumed. 158cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek} 159248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff 16020ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitCallExpr(CallExpr* C) { 16159d1827c1a13bb2b112f2049a52aee0e81023d1bTed Kremenek VisitChildren(C); 162aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek return Initialized; 16320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 16420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 16520ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) { 1668d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek switch (U->getOpcode()) { 1678d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek case UnaryOperator::AddrOf: 168248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff VarDecl* VD = FindBlockVarDecl(U->getSubExpr()); 169248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff if (VD && VD->isBlockVarDecl()) 1708d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek return V(VD,AD) = Initialized; 1718d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek break; 1728d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek 1738d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek case UnaryOperator::SizeOf: 1748d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek return Initialized; 1758d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek 1768d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek default: 1778d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek break; 1788d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek } 179a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek 180a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek return Visit(U->getSubExpr()); 181a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek} 182a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek 183a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenekbool TransferFuncs::VisitConditionalOperator(ConditionalOperator* C) { 184a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek Visit(C->getCond()); 1853907323dd6665c0c4e383435cb145233f4533406Anders Carlsson 1863907323dd6665c0c4e383435cb145233f4533406Anders Carlsson bool rhsResult = Visit(C->getRHS()); 1873907323dd6665c0c4e383435cb145233f4533406Anders Carlsson // Handle the GNU extension for missing LHS. 1883907323dd6665c0c4e383435cb145233f4533406Anders Carlsson if (Expr *lhs = C->getLHS()) 1893907323dd6665c0c4e383435cb145233f4533406Anders Carlsson return Visit(lhs) & rhsResult; // Yes: we want &, not &&. 1903907323dd6665c0c4e383435cb145233f4533406Anders Carlsson else 1913907323dd6665c0c4e383435cb145233f4533406Anders Carlsson return rhsResult; 19220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 19320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 19420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitStmt(Stmt* S) { 195aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek bool x = Initialized; 19620ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 19720ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek // We don't stop at the first subexpression that is Uninitialized because 19820ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek // evaluating some subexpressions may result in propogating "Uninitialized" 19920ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek // or "Initialized" to variables referenced in the other subexpressions. 20020ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I) 201a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek if (*I && Visit(*I) == Uninitialized) x = Uninitialized; 20220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 20320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek return x; 20420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 205a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek 206a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenekbool TransferFuncs::Visit(Stmt *S) { 207a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek if (AD.isTracked(static_cast<Expr*>(S))) return V(static_cast<Expr*>(S),AD); 208a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek else return static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(S); 209a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek} 21020ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 21120ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::BlockStmt_VisitExpr(Expr* E) { 21233d4aab80f31bd06257526fe2883ea920529456bTed Kremenek bool x = static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(E); 21333d4aab80f31bd06257526fe2883ea920529456bTed Kremenek if (AD.isTracked(E)) V(E,AD) = x; 21433d4aab80f31bd06257526fe2883ea920529456bTed Kremenek return x; 21520ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 21620ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 21713ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek} // end anonymous namespace 21813ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 219cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 22013ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek// Merge operator. 22120ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek// 22220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek// In our transfer functions we take the approach that any 22320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek// combination of unintialized values, e.g. Unitialized + ___ = Unitialized. 22420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek// 2257deed0c65b315cac037539401c49586283158d9fTed Kremenek// Merges take the same approach, preferring soundness. At a confluence point, 2267deed0c65b315cac037539401c49586283158d9fTed Kremenek// if any predecessor has a variable marked uninitialized, the value is 2277deed0c65b315cac037539401c49586283158d9fTed Kremenek// uninitialized at the confluence point. 228cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 22913ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 23013ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremeneknamespace { 2315fb5c6afbb331b87c638fad42f5b37ed697e5580Ted Kremenek typedef ExprDeclBitVector_Types::Intersect Merge; 232aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek typedef DataflowSolver<UninitializedValues,TransferFuncs,Merge> Solver; 233aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek} 23413ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 235cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 236cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek// Unitialized values checker. Scan an AST and flag variable uses 237cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 23813ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 239cd5860ce7a793cdad1e55552bb23937263ea2921Ted KremenekUninitializedValues_ValueTypes::ObserverTy::~ObserverTy() {} 24013ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 241cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremeneknamespace { 242c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenekclass VISIBILITY_HIDDEN UninitializedValuesChecker 243c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenek : public UninitializedValues::ObserverTy { 244c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenek 245cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek ASTContext &Ctx; 246cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek Diagnostic &Diags; 247248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff llvm::SmallPtrSet<VarDecl*,10> AlreadyWarned; 24813ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 249cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenekpublic: 250cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek UninitializedValuesChecker(ASTContext &ctx, Diagnostic &diags) 251cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek : Ctx(ctx), Diags(diags) {} 252cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek 253cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek virtual void ObserveDeclRefExpr(UninitializedValues::ValTy& V, 254cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek UninitializedValues::AnalysisDataTy& AD, 255248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff DeclRefExpr* DR, VarDecl* VD) { 256cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek 25743a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek assert ( AD.isTracked(VD) && "Unknown VarDecl."); 25843a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek 259aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek if (V(VD,AD) == Uninitialized) 260cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek if (AlreadyWarned.insert(VD)) 2619c728dc4d8da89c73fcae74c9e72d7a83ffd7b6dTed Kremenek Diags.Report(Ctx.getFullLoc(DR->getSourceRange().getBegin()), 2629c728dc4d8da89c73fcae74c9e72d7a83ffd7b6dTed Kremenek diag::warn_uninit_val); 26313ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek } 264cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek}; 265cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek} // end anonymous namespace 26613ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 2672bf55140b893c874ef16929bfe953f7cc7823425Ted Kremeneknamespace clang { 268a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenekvoid CheckUninitializedValues(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags, 269a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek bool FullUninitTaint) { 270cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek 271cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek // Compute the unitialized values information. 27211e7218db51efc825ec24e80d5b071892ca268bdTed Kremenek UninitializedValues U(cfg); 273a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek U.getAnalysisData().FullUninitTaint = FullUninitTaint; 27413ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek Solver S(U); 275cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek S.runOnCFG(cfg); 276cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek 277cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek // Scan for DeclRefExprs that use uninitialized values. 278cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek UninitializedValuesChecker Observer(Ctx,Diags); 279cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek U.getAnalysisData().Observer = &Observer; 280294a7c9cf15c4aefd906ca0fde8ebf9ecf7aa1afTed Kremenek S.runOnAllBlocks(cfg); 2812bf55140b893c874ef16929bfe953f7cc7823425Ted Kremenek} 282294a7c9cf15c4aefd906ca0fde8ebf9ecf7aa1afTed Kremenek} // end namespace clang 283