UninitializedValues.cpp revision 8d798c75b8aa8457ea06b22c6637d626ce1402de
15d796aa7899d37d7f243fbc738d6bb8108791fbeNick Lewycky//==- UninitializedValues.cpp - Find Uninitialized 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) { 67e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek X.setDeclValues(AD); 688d798c75b8aa8457ea06b22c6637d626ce1402deTed Kremenek X.resetBlkExprValues(AD); 697deed0c65b315cac037539401c49586283158d9fTed Kremenek } 707deed0c65b315cac037539401c49586283158d9fTed Kremenek 7120ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek bool VisitDeclRefExpr(DeclRefExpr* DR); 7220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek bool VisitBinaryOperator(BinaryOperator* B); 7320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek bool VisitUnaryOperator(UnaryOperator* U); 7420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek bool VisitStmt(Stmt* S); 7520ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek bool VisitCallExpr(CallExpr* C); 76cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek bool VisitDeclStmt(DeclStmt* D); 77a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek bool VisitConditionalOperator(ConditionalOperator* C); 78bfcb712627b9346ab92880d9075896dcc7700ac2Ted Kremenek bool BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S); 79a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek 80a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek bool Visit(Stmt *S); 81a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek bool BlockStmt_VisitExpr(Expr* E); 8237622081d8a139a3249613acaa80106ec97261fbTed Kremenek 83411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek void VisitTerminator(CFGBlock* B) { } 8413ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek}; 85aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek 86e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenekstatic const bool Initialized = false; 87e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenekstatic const bool Uninitialized = true; 8820ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 8920ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) { 902f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek 912f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) 922f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (VD->isBlockVarDecl()) { 932f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek 942f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (AD.Observer) 952f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek AD.Observer->ObserveDeclRefExpr(V, AD, DR, VD); 96a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek 972f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek // Pseudo-hack to prevent cascade of warnings. If an accessed variable 982f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek // is uninitialized, then we are already going to flag a warning for 992f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek // this variable, which a "source" of uninitialized values. 1002f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek // We can otherwise do a full "taint" of uninitialized values. The 1012f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek // client has both options by toggling AD.FullUninitTaint. 102a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek 1032f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (AD.FullUninitTaint) 1042f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek return V(VD,AD); 1052f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek } 1062f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek 1072f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek return Initialized; 10843a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek} 10943a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek 1102f868c013935791c421def45b422a6f6e79d2e4aTed Kremenekstatic VarDecl* FindBlockVarDecl(Expr* E) { 1112f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek 1122f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek // Blast through casts and parentheses to find any DeclRefExprs that 1132f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek // refer to a block VarDecl. 1142f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek 1152f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts())) 1162f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) 1172f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (VD->isBlockVarDecl()) return VD; 1182f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek 1192f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek return NULL; 12020ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 12120ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 12220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitBinaryOperator(BinaryOperator* B) { 1232f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek 1242f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (VarDecl* VD = FindBlockVarDecl(B->getLHS())) 1256ce2b630652911c5b463ce0203855b1eaf4694bdTed Kremenek if (B->isAssignmentOp()) { 126ff7c538f7c37539bceb99113f7d507cd98daa578Ted Kremenek if (B->getOpcode() == BinaryOperator::Assign) 127ff7c538f7c37539bceb99113f7d507cd98daa578Ted Kremenek return V(VD,AD) = Visit(B->getRHS()); 128ff7c538f7c37539bceb99113f7d507cd98daa578Ted Kremenek else // Handle +=, -=, *=, etc. We do want '&', not '&&'. 129ff7c538f7c37539bceb99113f7d507cd98daa578Ted Kremenek return V(VD,AD) = Visit(B->getLHS()) & Visit(B->getRHS()); 1306ce2b630652911c5b463ce0203855b1eaf4694bdTed Kremenek } 1316ce2b630652911c5b463ce0203855b1eaf4694bdTed Kremenek 13220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek return VisitStmt(B); 13320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 13420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 135cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenekbool TransferFuncs::VisitDeclStmt(DeclStmt* S) { 13614f8b4ff660bcaa763974b8d0fae81857c594495Ted Kremenek for (DeclStmt::decl_iterator I=S->decl_begin(), E=S->decl_end(); I!=E; ++I) { 13714f8b4ff660bcaa763974b8d0fae81857c594495Ted Kremenek VarDecl *VD = dyn_cast<VarDecl>(*I); 138248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff if (VD && VD->isBlockVarDecl()) { 139a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek if (Stmt* I = VD->getInit()) 140a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek V(VD,AD) = AD.FullUninitTaint ? V(cast<Expr>(I),AD) : Initialized; 14181a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek else { 14281a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // Special case for declarations of array types. For things like: 14381a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // 14481a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // char x[10]; 14581a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // 14681a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // we should treat "x" as being initialized, because the variable 14781a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // "x" really refers to the memory block. Clearly x[1] is 14881a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // uninitialized, but expressions like "(char *) x" really do refer to 14981a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // an initialized value. This simple dataflow analysis does not reason 15081a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // about the contents of arrays, although it could be potentially 15181a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // extended to do so if the array were of constant size. 15281a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek if (VD->getType()->isArrayType()) 15381a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek V(VD,AD) = Initialized; 15481a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek else 15581a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek V(VD,AD) = Uninitialized; 15681a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek } 157aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek } 158248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff } 159a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek return Uninitialized; // Value is never consumed. 160cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek} 161248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff 16220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitCallExpr(CallExpr* C) { 16359d1827c1a13bb2b112f2049a52aee0e81023d1bTed Kremenek VisitChildren(C); 164aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek return Initialized; 16520ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 16620ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 16720ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) { 1688d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek switch (U->getOpcode()) { 1695da6b2592fbf69708a7863b41d8bd76440d0f41bArgyrios Kyrtzidis case UnaryOperator::AddrOf: { 170248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff VarDecl* VD = FindBlockVarDecl(U->getSubExpr()); 171248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff if (VD && VD->isBlockVarDecl()) 1728d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek return V(VD,AD) = Initialized; 1738d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek break; 1745da6b2592fbf69708a7863b41d8bd76440d0f41bArgyrios Kyrtzidis } 1758d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek 1768d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek default: 1778d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek break; 1788d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek } 179a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek 180a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek return Visit(U->getSubExpr()); 181a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek} 182a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek 183bfcb712627b9346ab92880d9075896dcc7700ac2Ted Kremenekbool 184bfcb712627b9346ab92880d9075896dcc7700ac2Ted KremenekTransferFuncs::BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) { 185e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek // This represents a use of the 'collection' 186e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek bool x = Visit(S->getCollection()); 187e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek 188e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek if (x == Uninitialized) 189e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek return Uninitialized; 190e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek 191e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek // This represents an initialization of the 'element' value. 192e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek Stmt* Element = S->getElement(); 193e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek VarDecl* VD = 0; 194e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek 195e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek if (DeclStmt* DS = dyn_cast<DeclStmt>(Element)) 196e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek VD = cast<VarDecl>(DS->getSolitaryDecl()); 197e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek else 198e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek VD = cast<VarDecl>(cast<DeclRefExpr>(Element)->getDecl()); 199e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek 200e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek V(VD,AD) = Initialized; 201e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek return Initialized; 202e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek} 203e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek 204e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek 205a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenekbool TransferFuncs::VisitConditionalOperator(ConditionalOperator* C) { 206a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek Visit(C->getCond()); 2073907323dd6665c0c4e383435cb145233f4533406Anders Carlsson 2083907323dd6665c0c4e383435cb145233f4533406Anders Carlsson bool rhsResult = Visit(C->getRHS()); 2093907323dd6665c0c4e383435cb145233f4533406Anders Carlsson // Handle the GNU extension for missing LHS. 2103907323dd6665c0c4e383435cb145233f4533406Anders Carlsson if (Expr *lhs = C->getLHS()) 2113907323dd6665c0c4e383435cb145233f4533406Anders Carlsson return Visit(lhs) & rhsResult; // Yes: we want &, not &&. 2123907323dd6665c0c4e383435cb145233f4533406Anders Carlsson else 2133907323dd6665c0c4e383435cb145233f4533406Anders Carlsson return rhsResult; 21420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 21520ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 21620ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitStmt(Stmt* S) { 217aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek bool x = Initialized; 21820ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 21920ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek // We don't stop at the first subexpression that is Uninitialized because 22020ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek // evaluating some subexpressions may result in propogating "Uninitialized" 22120ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek // or "Initialized" to variables referenced in the other subexpressions. 22220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I) 223a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek if (*I && Visit(*I) == Uninitialized) x = Uninitialized; 22420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 22520ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek return x; 22620ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 227a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek 228a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenekbool TransferFuncs::Visit(Stmt *S) { 229a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek if (AD.isTracked(static_cast<Expr*>(S))) return V(static_cast<Expr*>(S),AD); 230a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek else return static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(S); 231a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek} 23220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 23320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::BlockStmt_VisitExpr(Expr* E) { 23433d4aab80f31bd06257526fe2883ea920529456bTed Kremenek bool x = static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(E); 23533d4aab80f31bd06257526fe2883ea920529456bTed Kremenek if (AD.isTracked(E)) V(E,AD) = x; 23633d4aab80f31bd06257526fe2883ea920529456bTed Kremenek return x; 23720ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 23820ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 23913ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek} // end anonymous namespace 24013ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 241cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 24213ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek// Merge operator. 24320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek// 24420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek// In our transfer functions we take the approach that any 2455d796aa7899d37d7f243fbc738d6bb8108791fbeNick Lewycky// combination of uninitialized values, e.g. 2465d796aa7899d37d7f243fbc738d6bb8108791fbeNick Lewycky// Uninitialized + ___ = Uninitialized. 24720ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek// 2487deed0c65b315cac037539401c49586283158d9fTed Kremenek// Merges take the same approach, preferring soundness. At a confluence point, 2497deed0c65b315cac037539401c49586283158d9fTed Kremenek// if any predecessor has a variable marked uninitialized, the value is 2507deed0c65b315cac037539401c49586283158d9fTed Kremenek// uninitialized at the confluence point. 251cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 25213ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 25313ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremeneknamespace { 2548d798c75b8aa8457ea06b22c6637d626ce1402deTed Kremenek typedef StmtDeclBitVector_Types::Union Merge; 255aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek typedef DataflowSolver<UninitializedValues,TransferFuncs,Merge> Solver; 256aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek} 25713ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 258cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 2595d796aa7899d37d7f243fbc738d6bb8108791fbeNick Lewycky// Uninitialized values checker. Scan an AST and flag variable uses 260cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 26113ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 262cd5860ce7a793cdad1e55552bb23937263ea2921Ted KremenekUninitializedValues_ValueTypes::ObserverTy::~ObserverTy() {} 26313ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 264cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremeneknamespace { 265c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenekclass VISIBILITY_HIDDEN UninitializedValuesChecker 266c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenek : public UninitializedValues::ObserverTy { 267c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenek 268cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek ASTContext &Ctx; 269cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek Diagnostic &Diags; 270248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff llvm::SmallPtrSet<VarDecl*,10> AlreadyWarned; 27113ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 272cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenekpublic: 273cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek UninitializedValuesChecker(ASTContext &ctx, Diagnostic &diags) 274cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek : Ctx(ctx), Diags(diags) {} 275cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek 276cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek virtual void ObserveDeclRefExpr(UninitializedValues::ValTy& V, 277cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek UninitializedValues::AnalysisDataTy& AD, 278248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff DeclRefExpr* DR, VarDecl* VD) { 279cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek 28043a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek assert ( AD.isTracked(VD) && "Unknown VarDecl."); 28143a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek 282aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek if (V(VD,AD) == Uninitialized) 283cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek if (AlreadyWarned.insert(VD)) 2849c728dc4d8da89c73fcae74c9e72d7a83ffd7b6dTed Kremenek Diags.Report(Ctx.getFullLoc(DR->getSourceRange().getBegin()), 2859c728dc4d8da89c73fcae74c9e72d7a83ffd7b6dTed Kremenek diag::warn_uninit_val); 28613ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek } 287cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek}; 288cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek} // end anonymous namespace 28913ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 2902bf55140b893c874ef16929bfe953f7cc7823425Ted Kremeneknamespace clang { 291a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenekvoid CheckUninitializedValues(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags, 292a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek bool FullUninitTaint) { 293cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek 2945d796aa7899d37d7f243fbc738d6bb8108791fbeNick Lewycky // Compute the uninitialized values information. 29511e7218db51efc825ec24e80d5b071892ca268bdTed Kremenek UninitializedValues U(cfg); 296a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek U.getAnalysisData().FullUninitTaint = FullUninitTaint; 29713ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek Solver S(U); 298cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek S.runOnCFG(cfg); 299cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek 300cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek // Scan for DeclRefExprs that use uninitialized values. 301cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek UninitializedValuesChecker Observer(Ctx,Diags); 302cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek U.getAnalysisData().Observer = &Observer; 303294a7c9cf15c4aefd906ca0fde8ebf9ecf7aa1afTed Kremenek S.runOnAllBlocks(cfg); 3042bf55140b893c874ef16929bfe953f7cc7823425Ted Kremenek} 305294a7c9cf15c4aefd906ca0fde8ebf9ecf7aa1afTed Kremenek} // end namespace clang 306