UninitializedValues.cpp revision 2f868c013935791c421def45b422a6f6e79d2e4a
113ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek//==- UninitializedValues.cpp - Find Unintialized 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) {
677deed0c65b315cac037539401c49586283158d9fTed Kremenek    X.resetValues(AD);
687deed0c65b315cac037539401c49586283158d9fTed Kremenek  }
697deed0c65b315cac037539401c49586283158d9fTed Kremenek
7020ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek  bool VisitDeclRefExpr(DeclRefExpr* DR);
7120ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek  bool VisitBinaryOperator(BinaryOperator* B);
7220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek  bool VisitUnaryOperator(UnaryOperator* U);
7320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek  bool VisitStmt(Stmt* S);
7420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek  bool VisitCallExpr(CallExpr* C);
75cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek  bool VisitDeclStmt(DeclStmt* D);
76a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek  bool VisitConditionalOperator(ConditionalOperator* C);
77a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek
78a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek  bool Visit(Stmt *S);
79a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek  bool BlockStmt_VisitExpr(Expr* E);
8037622081d8a139a3249613acaa80106ec97261fbTed Kremenek
817deed0c65b315cac037539401c49586283158d9fTed Kremenek  void VisitTerminator(Stmt* T) { }
8213ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek};
83aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek
84aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenekstatic const bool Initialized = true;
85aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenekstatic const bool Uninitialized = false;
8620ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek
8720ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
882f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek
892f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek  if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl()))
902f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek    if (VD->isBlockVarDecl()) {
912f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek
922f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek      if (AD.Observer)
932f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek        AD.Observer->ObserveDeclRefExpr(V, AD, DR, VD);
94a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek
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    }
1042f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek
1052f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek  return Initialized;
10643a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek}
10743a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek
1082f868c013935791c421def45b422a6f6e79d2e4aTed Kremenekstatic VarDecl* FindBlockVarDecl(Expr* E) {
1092f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek
1102f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek  // Blast through casts and parentheses to find any DeclRefExprs that
1112f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek  // refer to a block VarDecl.
1122f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek
1132f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek  if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
1142f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek    if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl()))
1152f868c013935791c421def45b422a6f6e79d2e4aTed Kremenek      if (VD->isBlockVarDecl()) 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()) {
124ff7c538f7c37539bceb99113f7d507cd98daa578Ted Kremenek      if (B->getOpcode() == BinaryOperator::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) {
134248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff  for (ScopedDecl* D = S->getDecl(); D != NULL; D = D->getNextDeclarator()) {
135248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff    VarDecl *VD = dyn_cast<VarDecl>(D);
136248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff    if (VD && VD->isBlockVarDecl()) {
137a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek      if (Stmt* I = VD->getInit())
138a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek        V(VD,AD) = AD.FullUninitTaint ? V(cast<Expr>(I),AD) : Initialized;
13981a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek      else {
14081a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek        // Special case for declarations of array types.  For things like:
14181a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek        //
14281a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek        //  char x[10];
14381a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek        //
14481a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek        // we should treat "x" as being initialized, because the variable
14581a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek        // "x" really refers to the memory block.  Clearly x[1] is
14681a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek        // uninitialized, but expressions like "(char *) x" really do refer to
14781a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek        // an initialized value.  This simple dataflow analysis does not reason
14881a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek        // about the contents of arrays, although it could be potentially
14981a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek        // extended to do so if the array were of constant size.
15081a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek        if (VD->getType()->isArrayType())
15181a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek          V(VD,AD) = Initialized;
15281a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek        else
15381a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek          V(VD,AD) = Uninitialized;
15481a56ec2620e40694e63bbac2ee11a21bd6b9240Ted Kremenek      }
155aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek    }
156248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff  }
157a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek  return Uninitialized; // Value is never consumed.
158cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek}
159248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff
16020ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitCallExpr(CallExpr* C) {
16159d1827c1a13bb2b112f2049a52aee0e81023d1bTed Kremenek  VisitChildren(C);
162aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek  return Initialized;
16320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek}
16420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek
16520ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
1668d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek  switch (U->getOpcode()) {
1678d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek    case UnaryOperator::AddrOf:
168248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff      VarDecl* VD = FindBlockVarDecl(U->getSubExpr());
169248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff      if (VD && VD->isBlockVarDecl())
1708d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek        return V(VD,AD) = Initialized;
1718d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek      break;
1728d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek
1738d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek    case UnaryOperator::SizeOf:
1748d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek      return Initialized;
1758d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek
1768d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek    default:
1778d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek      break;
1788d9ebae7ba382d3151e4a7d336578d9b92f73c3cTed Kremenek  }
179a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek
180a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek  return Visit(U->getSubExpr());
181a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek}
182a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek
183a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenekbool TransferFuncs::VisitConditionalOperator(ConditionalOperator* C) {
184a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek  Visit(C->getCond());
1853907323dd6665c0c4e383435cb145233f4533406Anders Carlsson
1863907323dd6665c0c4e383435cb145233f4533406Anders Carlsson  bool rhsResult = Visit(C->getRHS());
1873907323dd6665c0c4e383435cb145233f4533406Anders Carlsson  // Handle the GNU extension for missing LHS.
1883907323dd6665c0c4e383435cb145233f4533406Anders Carlsson  if (Expr *lhs = C->getLHS())
1893907323dd6665c0c4e383435cb145233f4533406Anders Carlsson    return Visit(lhs) & rhsResult; // Yes: we want &, not &&.
1903907323dd6665c0c4e383435cb145233f4533406Anders Carlsson  else
1913907323dd6665c0c4e383435cb145233f4533406Anders Carlsson    return rhsResult;
19220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek}
19320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek
19420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::VisitStmt(Stmt* S) {
195aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek  bool x = Initialized;
19620ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek
19720ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek  // We don't stop at the first subexpression that is Uninitialized because
19820ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek  // evaluating some subexpressions may result in propogating "Uninitialized"
19920ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek  // or "Initialized" to variables referenced in the other subexpressions.
20020ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek  for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I)
201a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek    if (*I && Visit(*I) == Uninitialized) x = Uninitialized;
20220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek
20320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek  return x;
20420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek}
205a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek
206a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenekbool TransferFuncs::Visit(Stmt *S) {
207a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek  if (AD.isTracked(static_cast<Expr*>(S))) return V(static_cast<Expr*>(S),AD);
208a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek  else return static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(S);
209a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek}
21020ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek
21120ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenekbool TransferFuncs::BlockStmt_VisitExpr(Expr* E) {
21233d4aab80f31bd06257526fe2883ea920529456bTed Kremenek  bool x = static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(E);
21333d4aab80f31bd06257526fe2883ea920529456bTed Kremenek  if (AD.isTracked(E)) V(E,AD) = x;
21433d4aab80f31bd06257526fe2883ea920529456bTed Kremenek  return x;
21520ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek}
21620ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek
21713ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek} // end anonymous namespace
21813ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek
219cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===//
22013ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek// Merge operator.
22120ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek//
22220ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek//  In our transfer functions we take the approach that any
22320ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek//  combination of unintialized values, e.g. Unitialized + ___ = Unitialized.
22420ee4fbee7db6b551de7d509801bbe25367aacf2Ted Kremenek//
2257deed0c65b315cac037539401c49586283158d9fTed Kremenek//  Merges take the same approach, preferring soundness.  At a confluence point,
2267deed0c65b315cac037539401c49586283158d9fTed Kremenek//  if any predecessor has a variable marked uninitialized, the value is
2277deed0c65b315cac037539401c49586283158d9fTed Kremenek//  uninitialized at the confluence point.
228cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===//
22913ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek
23013ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremeneknamespace {
2315fb5c6afbb331b87c638fad42f5b37ed697e5580Ted Kremenek  typedef ExprDeclBitVector_Types::Intersect Merge;
232aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek  typedef DataflowSolver<UninitializedValues,TransferFuncs,Merge> Solver;
233aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek}
23413ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek
235cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===//
236cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek// Unitialized values checker.   Scan an AST and flag variable uses
237cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek//===----------------------------------------------------------------------===//
23813ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek
239cd5860ce7a793cdad1e55552bb23937263ea2921Ted KremenekUninitializedValues_ValueTypes::ObserverTy::~ObserverTy() {}
24013ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek
241cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremeneknamespace {
242c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenekclass VISIBILITY_HIDDEN UninitializedValuesChecker
243c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenek  : public UninitializedValues::ObserverTy {
244c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenek
245cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek  ASTContext &Ctx;
246cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek  Diagnostic &Diags;
247248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff  llvm::SmallPtrSet<VarDecl*,10> AlreadyWarned;
24813ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek
249cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenekpublic:
250cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek  UninitializedValuesChecker(ASTContext &ctx, Diagnostic &diags)
251cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek    : Ctx(ctx), Diags(diags) {}
252cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek
253cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek  virtual void ObserveDeclRefExpr(UninitializedValues::ValTy& V,
254cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek                                  UninitializedValues::AnalysisDataTy& AD,
255248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff                                  DeclRefExpr* DR, VarDecl* VD) {
256cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek
25743a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek    assert ( AD.isTracked(VD) && "Unknown VarDecl.");
25843a1698cfbdd6623737d72bdf6ab9a13cdeadd14Ted Kremenek
259aead1539e7481fde73725d8eadeea82087982bf3Ted Kremenek    if (V(VD,AD) == Uninitialized)
260cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek      if (AlreadyWarned.insert(VD))
2619c728dc4d8da89c73fcae74c9e72d7a83ffd7b6dTed Kremenek        Diags.Report(Ctx.getFullLoc(DR->getSourceRange().getBegin()),
2629c728dc4d8da89c73fcae74c9e72d7a83ffd7b6dTed Kremenek                     diag::warn_uninit_val);
26313ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek  }
264cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek};
265cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek} // end anonymous namespace
26613ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek
2672bf55140b893c874ef16929bfe953f7cc7823425Ted Kremeneknamespace clang {
268a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenekvoid CheckUninitializedValues(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags,
269a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek                              bool FullUninitTaint) {
270cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek
271cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek  // Compute the unitialized values information.
27211e7218db51efc825ec24e80d5b071892ca268bdTed Kremenek  UninitializedValues U(cfg);
273a1de8c784a574a89a8a828331a8ce6b1aa57bed1Ted Kremenek  U.getAnalysisData().FullUninitTaint = FullUninitTaint;
27413ed7fea9728a89abc8fe1530d148a3589867b4cTed Kremenek  Solver S(U);
275cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek  S.runOnCFG(cfg);
276cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek
277cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek  // Scan for DeclRefExprs that use uninitialized values.
278cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek  UninitializedValuesChecker Observer(Ctx,Diags);
279cd5860ce7a793cdad1e55552bb23937263ea2921Ted Kremenek  U.getAnalysisData().Observer = &Observer;
280294a7c9cf15c4aefd906ca0fde8ebf9ecf7aa1afTed Kremenek  S.runOnAllBlocks(cfg);
2812bf55140b893c874ef16929bfe953f7cc7823425Ted Kremenek}
282294a7c9cf15c4aefd906ca0fde8ebf9ecf7aa1afTed Kremenek} // end namespace clang
283