UninitializedValues.cpp revision 7e24e82a70a2c681f4291a3397bcd1e1005f251a
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" 17500d3297d2a21edeac4d46cbcbe21bc2352c2a28Chris Lattner#include "clang/Analysis/AnalysisDiagnostic.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)) 1967e24e82a70a2c681f4291a3397bcd1e1005f251aChris Lattner VD = cast<VarDecl>(DS->getSingleDecl()); 197c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek else { 198c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek Expr* ElemExpr = cast<Expr>(Element)->IgnoreParens(); 199c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek 200c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek // Initialize the value of the reference variable. 201c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(ElemExpr)) 202c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek VD = cast<VarDecl>(DR->getDecl()); 203c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek else 204c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek return Visit(ElemExpr); 205c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek } 206c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek 207e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek V(VD,AD) = Initialized; 208e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek return Initialized; 209e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek} 210e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek 211e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek 212a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenekbool TransferFuncs::VisitConditionalOperator(ConditionalOperator* C) { 213a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek Visit(C->getCond()); 2143907323dd6665c0c4e383435cb145233f4533406Anders Carlsson 2153907323dd6665c0c4e383435cb145233f4533406Anders Carlsson bool rhsResult = Visit(C->getRHS()); 2163907323dd6665c0c4e383435cb145233f4533406Anders Carlsson // Handle the GNU extension for missing LHS. 2173907323dd6665c0c4e383435cb145233f4533406Anders Carlsson if (Expr *lhs = C->getLHS()) 2183907323dd6665c0c4e383435cb145233f4533406Anders Carlsson return Visit(lhs) & rhsResult; // Yes: we want &, not &&. 2193907323dd6665c0c4e383435cb145233f4533406Anders Carlsson else 2203907323dd6665c0c4e383435cb145233f4533406Anders Carlsson return rhsResult; 22120ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 22220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 22320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitStmt(Stmt* S) { 224aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek bool x = Initialized; 22520ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 22620ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek // We don't stop at the first subexpression that is Uninitialized because 22720ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek // evaluating some subexpressions may result in propogating "Uninitialized" 22820ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek // or "Initialized" to variables referenced in the other subexpressions. 22920ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I) 230a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek if (*I && Visit(*I) == Uninitialized) x = Uninitialized; 23120ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 23220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek return x; 23320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 234a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek 235a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenekbool TransferFuncs::Visit(Stmt *S) { 236a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek if (AD.isTracked(static_cast<Expr*>(S))) return V(static_cast<Expr*>(S),AD); 237a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek else return static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(S); 238a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek} 23920ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 24020ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::BlockStmt_VisitExpr(Expr* E) { 24133d4aab80f31bd06257526fe2883ea920529456bTed Kremenek bool x = static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(E); 24233d4aab80f31bd06257526fe2883ea920529456bTed Kremenek if (AD.isTracked(E)) V(E,AD) = x; 24333d4aab80f31bd06257526fe2883ea920529456bTed Kremenek return x; 24420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 24520ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 24613ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek} // end anonymous namespace 24713ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 248cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 24913ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek// Merge operator. 25020ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek// 25120ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek// In our transfer functions we take the approach that any 2525d796aa7899d37d7f243fbc738d6bb8108791fbeNick Lewycky// combination of uninitialized values, e.g. 2535d796aa7899d37d7f243fbc738d6bb8108791fbeNick Lewycky// Uninitialized + ___ = Uninitialized. 25420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek// 2557deed0c65b315cac037539401c49586283158d9fTed Kremenek// Merges take the same approach, preferring soundness. At a confluence point, 2567deed0c65b315cac037539401c49586283158d9fTed Kremenek// if any predecessor has a variable marked uninitialized, the value is 2577deed0c65b315cac037539401c49586283158d9fTed Kremenek// uninitialized at the confluence point. 258cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 25913ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 26013ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremeneknamespace { 2618d798c75b8aa8457ea06b22c6637d626ce1402deTed Kremenek typedef StmtDeclBitVector_Types::Union Merge; 262aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek typedef DataflowSolver<UninitializedValues,TransferFuncs,Merge> Solver; 263aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek} 26413ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 265cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 2665d796aa7899d37d7f243fbc738d6bb8108791fbeNick Lewycky// Uninitialized values checker. Scan an AST and flag variable uses 267cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 26813ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 269cd5860ce7a793cdad1e55552bb23937263ea2921Ted KremenekUninitializedValues_ValueTypes::ObserverTy::~ObserverTy() {} 27013ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 271cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremeneknamespace { 272c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenekclass VISIBILITY_HIDDEN UninitializedValuesChecker 273c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenek : public UninitializedValues::ObserverTy { 274c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenek 275cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek ASTContext &Ctx; 276cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek Diagnostic &Diags; 277248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff llvm::SmallPtrSet<VarDecl*,10> AlreadyWarned; 27813ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 279cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenekpublic: 280cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek UninitializedValuesChecker(ASTContext &ctx, Diagnostic &diags) 281cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek : Ctx(ctx), Diags(diags) {} 282cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek 283cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek virtual void ObserveDeclRefExpr(UninitializedValues::ValTy& V, 284cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek UninitializedValues::AnalysisDataTy& AD, 285248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff DeclRefExpr* DR, VarDecl* VD) { 286cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek 28743a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek assert ( AD.isTracked(VD) && "Unknown VarDecl."); 28843a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek 289aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek if (V(VD,AD) == Uninitialized) 290cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek if (AlreadyWarned.insert(VD)) 2919c728dc4d8da89c73fcae74c9e72d7a83ffd7b6dTed Kremenek Diags.Report(Ctx.getFullLoc(DR->getSourceRange().getBegin()), 2929c728dc4d8da89c73fcae74c9e72d7a83ffd7b6dTed Kremenek diag::warn_uninit_val); 29313ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek } 294cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek}; 295cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek} // end anonymous namespace 29613ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 2972bf55140b893c874ef16929bfe953f7cc7823425Ted Kremeneknamespace clang { 298a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenekvoid CheckUninitializedValues(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags, 299a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek bool FullUninitTaint) { 300cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek 3015d796aa7899d37d7f243fbc738d6bb8108791fbeNick Lewycky // Compute the uninitialized values information. 30211e7218db51efc825ec24e80d5b071892ca268bdTed Kremenek UninitializedValues U(cfg); 303a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek U.getAnalysisData().FullUninitTaint = FullUninitTaint; 30413ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek Solver S(U); 305cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek S.runOnCFG(cfg); 306cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek 307cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek // Scan for DeclRefExprs that use uninitialized values. 308cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek UninitializedValuesChecker Observer(Ctx,Diags); 309cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek U.getAnalysisData().Observer = &Observer; 310294a7c9cf15c4aefd906ca0fde8ebf9ecf7aa1afTed Kremenek S.runOnAllBlocks(cfg); 3112bf55140b893c874ef16929bfe953f7cc7823425Ted Kremenek} 312294a7c9cf15c4aefd906ca0fde8ebf9ecf7aa1afTed Kremenek} // end namespace clang 313