UninitializedValues.cpp revision f4e3cfbe8abd124be6341ef5d714819b4fbd9082
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" 16500d3297d2a21edeac4d46cbcbe21bc2352c2a28Chris Lattner#include "clang/Analysis/AnalysisDiagnostic.h" 17cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek#include "clang/AST/ASTContext.h" 181de632bf4abb75fcd39f5d6fdf59337f0ff0edd4Ted Kremenek#include "clang/Analysis/FlowSensitive/DataflowSolver.h" 1913ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 20cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek#include "llvm/ADT/SmallPtrSet.h" 21cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek 2213ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenekusing namespace clang; 2313ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 24cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 2513ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek// Dataflow initialization logic. 261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump//===----------------------------------------------------------------------===// 2713ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 2813ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremeneknamespace { 2913ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 30ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass RegisterDecls 311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump : public CFGRecStmtDeclVisitor<RegisterDecls> { 32c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenek 3356d516d18a789a13696a310dbca67d4b5d9fc798Ted Kremenek UninitializedValues::AnalysisDataTy& AD; 3413ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenekpublic: 3511e7218db51efc825ec24e80d5b071892ca268bdTed Kremenek RegisterDecls(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {} 361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 37606ceeef820a3ecd46255d155e5d7f3aa888a04bTed Kremenek void VisitVarDecl(VarDecl* VD) { AD.Register(VD); } 389f9141cd46b87cefd74625d92634a5aa93d2c9c6Ted Kremenek CFG& getCFG() { return AD.getCFG(); } 3913ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek}; 401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4113ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek} // end anonymous namespace 4213ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 4313ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenekvoid UninitializedValues::InitializeValues(const CFG& cfg) { 4411e7218db51efc825ec24e80d5b071892ca268bdTed Kremenek RegisterDecls R(getAnalysisData()); 45a90b0d1e585d993621a342d0b2874e61941372d5Ted Kremenek cfg.VisitBlockStmts(R); 4613ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek} 4713ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 48cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 4913ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek// Transfer functions. 501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump//===----------------------------------------------------------------------===// 5113ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 5213ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremeneknamespace { 53ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass TransferFuncs 54c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenek : public CFGStmtVisitor<TransferFuncs,bool> { 551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5613ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek UninitializedValues::ValTy V; 5756d516d18a789a13696a310dbca67d4b5d9fc798Ted Kremenek UninitializedValues::AnalysisDataTy& AD; 5813ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenekpublic: 597deed0c65b315cac037539401c49586283158d9fTed Kremenek TransferFuncs(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {} 601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6113ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek UninitializedValues::ValTy& getVal() { return V; } 629f9141cd46b87cefd74625d92634a5aa93d2c9c6Ted Kremenek CFG& getCFG() { return AD.getCFG(); } 631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 647deed0c65b315cac037539401c49586283158d9fTed Kremenek void SetTopValue(UninitializedValues::ValTy& X) { 65e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek X.setDeclValues(AD); 668d798c75b8aa8457ea06b22c6637d626ce1402deTed Kremenek X.resetBlkExprValues(AD); 677deed0c65b315cac037539401c49586283158d9fTed Kremenek } 681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6920ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek bool VisitDeclRefExpr(DeclRefExpr* DR); 7020ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek bool VisitBinaryOperator(BinaryOperator* B); 7120ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek bool VisitUnaryOperator(UnaryOperator* U); 7220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek bool VisitStmt(Stmt* S); 7320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek bool VisitCallExpr(CallExpr* C); 74cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek bool VisitDeclStmt(DeclStmt* D); 7556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall bool VisitAbstractConditionalOperator(AbstractConditionalOperator* C); 76bfcb712627b9346ab92880d9075896dcc7700ac2Ted Kremenek bool BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S); 771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 78a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek bool Visit(Stmt *S); 79a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek bool BlockStmt_VisitExpr(Expr* E); 801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 81411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek void VisitTerminator(CFGBlock* B) { } 82848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek 83848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek void setCurrentBlock(const CFGBlock *block) {} 8413ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek}; 851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 86e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenekstatic const bool Initialized = false; 871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpstatic const bool Uninitialized = true; 8820ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 8920ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) { 901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 912f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) 92b6bbcc9995186799a60ce17d0c1acff31601653aJohn McCall if (VD->isLocalVarDecl()) { 931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 942f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (AD.Observer) 952f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek AD.Observer->ObserveDeclRefExpr(V, AD, DR, VD); 961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 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 } 1061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1072f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek return Initialized; 10843a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek} 10943a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek 1102f868c013935791c421def45b422a6f6e79d2e4aTed Kremenekstatic VarDecl* FindBlockVarDecl(Expr* E) { 1111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1122f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek // Blast through casts and parentheses to find any DeclRefExprs that 1132f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek // refer to a block VarDecl. 1141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1152f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts())) 1161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) 117b6bbcc9995186799a60ce17d0c1acff31601653aJohn McCall if (VD->isLocalVarDecl()) 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()) { 1262de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() == BO_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); 138b6bbcc9995186799a60ce17d0c1acff31601653aJohn McCall if (VD && VD->isLocalVarDecl()) { 1395ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek if (Stmt* I = VD->getInit()) { 1405ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek // Visit the subexpression to check for uses of uninitialized values, 1415ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek // even if we don't propagate that value. 1425ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek bool isSubExprUninit = Visit(I); 1435ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek V(VD,AD) = AD.FullUninitTaint ? isSubExprUninit : Initialized; 1445ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek } 14581a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek else { 14681a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // Special case for declarations of array types. For things like: 14781a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // 14881a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // char x[10]; 14981a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // 15081a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // we should treat "x" as being initialized, because the variable 15181a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // "x" really refers to the memory block. Clearly x[1] is 1521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // uninitialized, but expressions like "(char *) x" really do refer to 1531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // an initialized value. This simple dataflow analysis does not reason 15481a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // about the contents of arrays, although it could be potentially 15581a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // extended to do so if the array were of constant size. 15681a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek if (VD->getType()->isArrayType()) 15781a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek V(VD,AD) = Initialized; 1581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else 15981a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek V(VD,AD) = Uninitialized; 16081a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek } 161aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek } 162248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff } 163a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek return Uninitialized; // Value is never consumed. 164cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek} 1651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16620ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitCallExpr(CallExpr* C) { 16759d1827c1a13bb2b112f2049a52aee0e81023d1bTed Kremenek VisitChildren(C); 168aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek return Initialized; 16920ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 17020ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 17120ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) { 1728d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek switch (U->getOpcode()) { 1732de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case UO_AddrOf: { 174248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff VarDecl* VD = FindBlockVarDecl(U->getSubExpr()); 175b6bbcc9995186799a60ce17d0c1acff31601653aJohn McCall if (VD && VD->isLocalVarDecl()) 1768d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek return V(VD,AD) = Initialized; 1778d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek break; 1785da6b2592fbf69708a7863b41d8bd76440d0f41bArgyrios Kyrtzidis } 1791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1808d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek default: 1818d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek break; 1828d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek } 183a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek 184a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek return Visit(U->getSubExpr()); 185a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek} 1861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 187bfcb712627b9346ab92880d9075896dcc7700ac2Ted Kremenekbool 188bfcb712627b9346ab92880d9075896dcc7700ac2Ted KremenekTransferFuncs::BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) { 189e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek // This represents a use of the 'collection' 190e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek bool x = Visit(S->getCollection()); 191e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek 192e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek if (x == Uninitialized) 193e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek return Uninitialized; 194e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek 195e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek // This represents an initialization of the 'element' value. 196e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek Stmt* Element = S->getElement(); 197e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek VarDecl* VD = 0; 198e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek 199e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek if (DeclStmt* DS = dyn_cast<DeclStmt>(Element)) 2007e24e82a70a2c681f4291a3397bcd1e1005f251aChris Lattner VD = cast<VarDecl>(DS->getSingleDecl()); 201c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek else { 202c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek Expr* ElemExpr = cast<Expr>(Element)->IgnoreParens(); 203c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek 204c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek // Initialize the value of the reference variable. 205c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(ElemExpr)) 206c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek VD = cast<VarDecl>(DR->getDecl()); 207c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek else 208c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek return Visit(ElemExpr); 209c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek } 2101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 211e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek V(VD,AD) = Initialized; 212e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek return Initialized; 213e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek} 2141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCallbool TransferFuncs:: 21756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCallVisitAbstractConditionalOperator(AbstractConditionalOperator* C) { 218a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek Visit(C->getCond()); 2193907323dd6665c0c4e383435cb145233f4533406Anders Carlsson 22056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall bool rhsResult = Visit(C->getFalseExpr()); 2213907323dd6665c0c4e383435cb145233f4533406Anders Carlsson // Handle the GNU extension for missing LHS. 22256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (isa<ConditionalOperator>(C)) 22356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall return Visit(C->getTrueExpr()) & rhsResult; // Yes: we want &, not &&. 2243907323dd6665c0c4e383435cb145233f4533406Anders Carlsson else 2253907323dd6665c0c4e383435cb145233f4533406Anders Carlsson return rhsResult; 22620ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 22720ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 22820ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitStmt(Stmt* S) { 229aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek bool x = Initialized; 23020ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 23120ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek // We don't stop at the first subexpression that is Uninitialized because 23220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek // evaluating some subexpressions may result in propogating "Uninitialized" 23320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek // or "Initialized" to variables referenced in the other subexpressions. 2347502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range I = S->children(); I; ++I) 235a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek if (*I && Visit(*I) == Uninitialized) x = Uninitialized; 2361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 23720ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek return x; 23820ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 2391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 240a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenekbool TransferFuncs::Visit(Stmt *S) { 241a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek if (AD.isTracked(static_cast<Expr*>(S))) return V(static_cast<Expr*>(S),AD); 242a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek else return static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(S); 243a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek} 24420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 24520ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::BlockStmt_VisitExpr(Expr* E) { 2461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump bool x = static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(E); 24733d4aab80f31bd06257526fe2883ea920529456bTed Kremenek if (AD.isTracked(E)) V(E,AD) = x; 24833d4aab80f31bd06257526fe2883ea920529456bTed Kremenek return x; 24920ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 2501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 25113ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek} // end anonymous namespace 25213ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 253cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 25413ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek// Merge operator. 25520ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek// 25620ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek// In our transfer functions we take the approach that any 2575d796aa7899d37d7f243fbc738d6bb8108791fbeNick Lewycky// combination of uninitialized values, e.g. 2585d796aa7899d37d7f243fbc738d6bb8108791fbeNick Lewycky// Uninitialized + ___ = Uninitialized. 25920ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek// 2607deed0c65b315cac037539401c49586283158d9fTed Kremenek// Merges take the same approach, preferring soundness. At a confluence point, 2617deed0c65b315cac037539401c49586283158d9fTed Kremenek// if any predecessor has a variable marked uninitialized, the value is 2627deed0c65b315cac037539401c49586283158d9fTed Kremenek// uninitialized at the confluence point. 2631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump//===----------------------------------------------------------------------===// 26413ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 26513ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremeneknamespace { 2668d798c75b8aa8457ea06b22c6637d626ce1402deTed Kremenek typedef StmtDeclBitVector_Types::Union Merge; 267aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek typedef DataflowSolver<UninitializedValues,TransferFuncs,Merge> Solver; 268aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek} 26913ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 270cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 2715d796aa7899d37d7f243fbc738d6bb8108791fbeNick Lewycky// Uninitialized values checker. Scan an AST and flag variable uses 2721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump//===----------------------------------------------------------------------===// 27313ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 274cd5860ce7a793cdad1e55552bb23937263ea2921Ted KremenekUninitializedValues_ValueTypes::ObserverTy::~ObserverTy() {} 27513ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 276cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremeneknamespace { 277ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass UninitializedValuesChecker 278c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenek : public UninitializedValues::ObserverTy { 2791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 280cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek ASTContext &Ctx; 281cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek Diagnostic &Diags; 282248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff llvm::SmallPtrSet<VarDecl*,10> AlreadyWarned; 2831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 284cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenekpublic: 285cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek UninitializedValuesChecker(ASTContext &ctx, Diagnostic &diags) 286cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek : Ctx(ctx), Diags(diags) {} 2871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 288cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek virtual void ObserveDeclRefExpr(UninitializedValues::ValTy& V, 289cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek UninitializedValues::AnalysisDataTy& AD, 290248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff DeclRefExpr* DR, VarDecl* VD) { 291cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek 29243a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek assert ( AD.isTracked(VD) && "Unknown VarDecl."); 2931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 294aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek if (V(VD,AD) == Uninitialized) 295cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek if (AlreadyWarned.insert(VD)) 2969c728dc4d8da89c73fcae74c9e72d7a83ffd7b6dTed Kremenek Diags.Report(Ctx.getFullLoc(DR->getSourceRange().getBegin()), 2979c728dc4d8da89c73fcae74c9e72d7a83ffd7b6dTed Kremenek diag::warn_uninit_val); 29813ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek } 299cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek}; 300cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek} // end anonymous namespace 30113ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 3022bf55140b893c874ef16929bfe953f7cc7823425Ted Kremeneknamespace clang { 303a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenekvoid CheckUninitializedValues(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags, 304a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek bool FullUninitTaint) { 3051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3065d796aa7899d37d7f243fbc738d6bb8108791fbeNick Lewycky // Compute the uninitialized values information. 30711e7218db51efc825ec24e80d5b071892ca268bdTed Kremenek UninitializedValues U(cfg); 308a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek U.getAnalysisData().FullUninitTaint = FullUninitTaint; 30913ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek Solver S(U); 310cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek S.runOnCFG(cfg); 3111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 312cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek // Scan for DeclRefExprs that use uninitialized values. 313cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek UninitializedValuesChecker Observer(Ctx,Diags); 314cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek U.getAnalysisData().Observer = &Observer; 315294a7c9cf15c4aefd906ca0fde8ebf9ecf7aa1afTed Kremenek S.runOnAllBlocks(cfg); 3162bf55140b893c874ef16929bfe953f7cc7823425Ted Kremenek} 317294a7c9cf15c4aefd906ca0fde8ebf9ecf7aa1afTed Kremenek} // end namespace clang 318