UninitializedValues.cpp revision 13bd4236ab8297350be388ab442b4c42eb8fe437
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); 75a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek bool VisitConditionalOperator(ConditionalOperator* 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) { } 8213ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek}; 831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 84e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenekstatic const bool Initialized = false; 851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpstatic const bool Uninitialized = true; 8620ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 8720ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) { 881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 892f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) 90b6bbcc9995186799a60ce17d0c1acff31601653aJohn McCall if (VD->isLocalVarDecl()) { 911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 922f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (AD.Observer) 932f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek AD.Observer->ObserveDeclRefExpr(V, AD, DR, VD); 941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 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 } 1041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1052f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek return Initialized; 10643a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek} 10743a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek 1082f868c013935791c421def45b422a6f6e79d2e4aTed Kremenekstatic VarDecl* FindBlockVarDecl(Expr* E) { 1091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1102f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek // Blast through casts and parentheses to find any DeclRefExprs that 1112f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek // refer to a block VarDecl. 1121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1132f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts())) 1141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) 115b6bbcc9995186799a60ce17d0c1acff31601653aJohn McCall if (VD->isLocalVarDecl()) 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()) { 1242de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() == BO_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) { 13414f8b4ff660bcaa763974b8d0fae81857c594495Ted Kremenek for (DeclStmt::decl_iterator I=S->decl_begin(), E=S->decl_end(); I!=E; ++I) { 13514f8b4ff660bcaa763974b8d0fae81857c594495Ted Kremenek VarDecl *VD = dyn_cast<VarDecl>(*I); 136b6bbcc9995186799a60ce17d0c1acff31601653aJohn McCall if (VD && VD->isLocalVarDecl()) { 1375ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek if (Stmt* I = VD->getInit()) { 1385ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek // Visit the subexpression to check for uses of uninitialized values, 1395ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek // even if we don't propagate that value. 1405ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek bool isSubExprUninit = Visit(I); 1415ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek V(VD,AD) = AD.FullUninitTaint ? isSubExprUninit : Initialized; 1425ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek } 14381a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek else { 14481a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // Special case for declarations of array types. For things like: 14581a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // 14681a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // char x[10]; 14781a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // 14881a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // we should treat "x" as being initialized, because the variable 14981a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // "x" really refers to the memory block. Clearly x[1] is 1501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // uninitialized, but expressions like "(char *) x" really do refer to 1511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // an initialized value. This simple dataflow analysis does not reason 15281a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // about the contents of arrays, although it could be potentially 15381a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek // extended to do so if the array were of constant size. 15481a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek if (VD->getType()->isArrayType()) 15581a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek V(VD,AD) = Initialized; 1561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else 15781a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek V(VD,AD) = Uninitialized; 15881a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek } 159aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek } 160248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff } 161a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek return Uninitialized; // Value is never consumed. 162cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek} 1631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitCallExpr(CallExpr* C) { 16559d1827c1a13bb2b112f2049a52aee0e81023d1bTed Kremenek VisitChildren(C); 166aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek return Initialized; 16720ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 16820ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 16920ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) { 1708d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek switch (U->getOpcode()) { 1712de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case UO_AddrOf: { 172248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff VarDecl* VD = FindBlockVarDecl(U->getSubExpr()); 173b6bbcc9995186799a60ce17d0c1acff31601653aJohn McCall if (VD && VD->isLocalVarDecl()) 1748d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek return V(VD,AD) = Initialized; 1758d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek break; 1765da6b2592fbf69708a7863b41d8bd76440d0f41bArgyrios Kyrtzidis } 1771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1788d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek default: 1798d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek break; 1808d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek } 181a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek 182a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek return Visit(U->getSubExpr()); 183a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek} 1841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 185bfcb712627b9346ab92880d9075896dcc7700ac2Ted Kremenekbool 186bfcb712627b9346ab92880d9075896dcc7700ac2Ted KremenekTransferFuncs::BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) { 187e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek // This represents a use of the 'collection' 188e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek bool x = Visit(S->getCollection()); 189e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek 190e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek if (x == Uninitialized) 191e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek return Uninitialized; 192e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek 193e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek // This represents an initialization of the 'element' value. 194e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek Stmt* Element = S->getElement(); 195e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek VarDecl* VD = 0; 196e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek 197e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek if (DeclStmt* DS = dyn_cast<DeclStmt>(Element)) 1987e24e82a70a2c681f4291a3397bcd1e1005f251aChris Lattner VD = cast<VarDecl>(DS->getSingleDecl()); 199c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek else { 200c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek Expr* ElemExpr = cast<Expr>(Element)->IgnoreParens(); 201c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek 202c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek // Initialize the value of the reference variable. 203c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(ElemExpr)) 204c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek VD = cast<VarDecl>(DR->getDecl()); 205c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek else 206c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek return Visit(ElemExpr); 207c2813f77bad184470f81f85f7df88b87eb1bb915Ted Kremenek } 2081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 209e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek V(VD,AD) = Initialized; 210e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek return Initialized; 211e219b8a9c02198b1938dfa9ed91ef9cf0e6ce4f3Ted Kremenek} 2121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 214a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenekbool TransferFuncs::VisitConditionalOperator(ConditionalOperator* C) { 215a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek Visit(C->getCond()); 2163907323dd6665c0c4e383435cb145233f4533406Anders Carlsson 2173907323dd6665c0c4e383435cb145233f4533406Anders Carlsson bool rhsResult = Visit(C->getRHS()); 2183907323dd6665c0c4e383435cb145233f4533406Anders Carlsson // Handle the GNU extension for missing LHS. 2193907323dd6665c0c4e383435cb145233f4533406Anders Carlsson if (Expr *lhs = C->getLHS()) 2203907323dd6665c0c4e383435cb145233f4533406Anders Carlsson return Visit(lhs) & rhsResult; // Yes: we want &, not &&. 2213907323dd6665c0c4e383435cb145233f4533406Anders Carlsson else 2223907323dd6665c0c4e383435cb145233f4533406Anders Carlsson return rhsResult; 22320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 22420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 22520ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitStmt(Stmt* S) { 226aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek bool x = Initialized; 22720ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 22820ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek // We don't stop at the first subexpression that is Uninitialized because 22920ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek // evaluating some subexpressions may result in propogating "Uninitialized" 23020ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek // or "Initialized" to variables referenced in the other subexpressions. 23120ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I) 232a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek if (*I && Visit(*I) == Uninitialized) x = Uninitialized; 2331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 23420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek return x; 23520ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 2361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 237a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenekbool TransferFuncs::Visit(Stmt *S) { 238a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek if (AD.isTracked(static_cast<Expr*>(S))) return V(static_cast<Expr*>(S),AD); 239a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek else return static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(S); 240a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek} 24120ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek 24220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::BlockStmt_VisitExpr(Expr* E) { 2431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump bool x = static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(E); 24433d4aab80f31bd06257526fe2883ea920529456bTed Kremenek if (AD.isTracked(E)) V(E,AD) = x; 24533d4aab80f31bd06257526fe2883ea920529456bTed Kremenek return x; 24620ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek} 2471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 24813ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek} // end anonymous namespace 24913ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 250cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 25113ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek// Merge operator. 25220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek// 25320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek// In our transfer functions we take the approach that any 2545d796aa7899d37d7f243fbc738d6bb8108791fbeNick Lewycky// combination of uninitialized values, e.g. 2555d796aa7899d37d7f243fbc738d6bb8108791fbeNick Lewycky// Uninitialized + ___ = Uninitialized. 25620ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek// 2577deed0c65b315cac037539401c49586283158d9fTed Kremenek// Merges take the same approach, preferring soundness. At a confluence point, 2587deed0c65b315cac037539401c49586283158d9fTed Kremenek// if any predecessor has a variable marked uninitialized, the value is 2597deed0c65b315cac037539401c49586283158d9fTed Kremenek// uninitialized at the confluence point. 2601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump//===----------------------------------------------------------------------===// 26113ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 26213ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremeneknamespace { 2638d798c75b8aa8457ea06b22c6637d626ce1402deTed Kremenek typedef StmtDeclBitVector_Types::Union Merge; 264aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek typedef DataflowSolver<UninitializedValues,TransferFuncs,Merge> Solver; 265aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek} 26613ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 267cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===// 2685d796aa7899d37d7f243fbc738d6bb8108791fbeNick Lewycky// Uninitialized values checker. Scan an AST and flag variable uses 2691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump//===----------------------------------------------------------------------===// 27013ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 271cd5860ce7a793cdad1e55552bb23937263ea2921Ted KremenekUninitializedValues_ValueTypes::ObserverTy::~ObserverTy() {} 27213ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 273cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremeneknamespace { 274ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass UninitializedValuesChecker 275c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenek : public UninitializedValues::ObserverTy { 2761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 277cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek ASTContext &Ctx; 278cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek Diagnostic &Diags; 279248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff llvm::SmallPtrSet<VarDecl*,10> AlreadyWarned; 2801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 281cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenekpublic: 282cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek UninitializedValuesChecker(ASTContext &ctx, Diagnostic &diags) 283cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek : Ctx(ctx), Diags(diags) {} 2841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 285cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek virtual void ObserveDeclRefExpr(UninitializedValues::ValTy& V, 286cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek UninitializedValues::AnalysisDataTy& AD, 287248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff DeclRefExpr* DR, VarDecl* VD) { 288cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek 28943a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek assert ( AD.isTracked(VD) && "Unknown VarDecl."); 2901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 291aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek if (V(VD,AD) == Uninitialized) 292cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek if (AlreadyWarned.insert(VD)) 2939c728dc4d8da89c73fcae74c9e72d7a83ffd7b6dTed Kremenek Diags.Report(Ctx.getFullLoc(DR->getSourceRange().getBegin()), 2949c728dc4d8da89c73fcae74c9e72d7a83ffd7b6dTed Kremenek diag::warn_uninit_val); 29513ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek } 296cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek}; 297cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek} // end anonymous namespace 29813ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek 2992bf55140b893c874ef16929bfe953f7cc7823425Ted Kremeneknamespace clang { 300a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenekvoid CheckUninitializedValues(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags, 301a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek bool FullUninitTaint) { 3021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3035d796aa7899d37d7f243fbc738d6bb8108791fbeNick Lewycky // Compute the uninitialized values information. 30411e7218db51efc825ec24e80d5b071892ca268bdTed Kremenek UninitializedValues U(cfg); 305a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek U.getAnalysisData().FullUninitTaint = FullUninitTaint; 30613ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek Solver S(U); 307cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek S.runOnCFG(cfg); 3081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 309cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek // Scan for DeclRefExprs that use uninitialized values. 310cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek UninitializedValuesChecker Observer(Ctx,Diags); 311cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek U.getAnalysisData().Observer = &Observer; 312294a7c9cf15c4aefd906ca0fde8ebf9ecf7aa1afTed Kremenek S.runOnAllBlocks(cfg); 3132bf55140b893c874ef16929bfe953f7cc7823425Ted Kremenek} 314294a7c9cf15c4aefd906ca0fde8ebf9ecf7aa1afTed Kremenek} // end namespace clang 315