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