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