blob: c9c02d0afd549850f7e88ab5cdb8696624a2706b [file] [log] [blame]
Ted Kremenek7f49f502007-09-14 22:49:21 +00001//==- UninitializedValues.cpp - Find Unintialized Values --------*- C++ --*-==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Ted Kremenek and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements Uninitialized Values analysis for source-level CFGs.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Analysis/UninitializedValues.h"
15#include "clang/Analysis/CFGVarDeclVisitor.h"
16#include "clang/Analysis/CFGStmtVisitor.h"
17#include "DataflowSolver.h"
18
19using namespace clang;
20
21//===--------------------------------------------------------------------===//
22// Dataflow initialization logic.
23//===--------------------------------------------------------------------===//
24
25namespace {
26
Ted Kremenek3e039752007-09-17 17:14:52 +000027class RegisterDeclsAndExprs : public CFGVarDeclVisitor<RegisterDeclsAndExprs> {
28 UninitializedValues::AnalysisDataTy& AD;
Ted Kremenek7f49f502007-09-14 22:49:21 +000029public:
Ted Kremenek3e039752007-09-17 17:14:52 +000030 RegisterDeclsAndExprs(const CFG& cfg, UninitializedValues::AnalysisDataTy& ad)
31 : CFGVarDeclVisitor<RegisterDeclsAndExprs>(cfg), AD(ad)
32 {}
Ted Kremenek7f49f502007-09-14 22:49:21 +000033
34 void VisitVarDecl(VarDecl* D) {
Ted Kremenek3e039752007-09-17 17:14:52 +000035 if (AD.VMap.find(D) == AD.VMap.end())
Ted Kremenek334b30a2007-09-17 18:31:23 +000036 AD.VMap[D] = AD.NumDecls++;
Ted Kremenek3e039752007-09-17 17:14:52 +000037 }
38
39 void BlockStmt_VisitExpr(Expr* E) {
40 if (AD.EMap.find(E) == AD.EMap.end())
Ted Kremenek334b30a2007-09-17 18:31:23 +000041 AD.EMap[E] = AD.NumBlockExprs++;
Ted Kremenek3e039752007-09-17 17:14:52 +000042 }
Ted Kremenek7f49f502007-09-14 22:49:21 +000043};
44
45} // end anonymous namespace
46
47void UninitializedValues::InitializeValues(const CFG& cfg) {
Ted Kremenek3e039752007-09-17 17:14:52 +000048 RegisterDeclsAndExprs R(cfg,this->getAnalysisData());
49 R.VisitAllDecls();
Ted Kremenek334b30a2007-09-17 18:31:23 +000050 UninitializedValues::ValTy& V = getBlockDataMap()[&cfg.getEntry()];
51 V.DeclBV.resize(getAnalysisData().NumDecls);
52 V.ExprBV.resize(getAnalysisData().NumBlockExprs);
Ted Kremenek7f49f502007-09-14 22:49:21 +000053}
54
55//===--------------------------------------------------------------------===//
56// Transfer functions.
57//===--------------------------------------------------------------------===//
58
59namespace {
Ted Kremenek334b30a2007-09-17 18:31:23 +000060
Ted Kremenek7f49f502007-09-14 22:49:21 +000061class TransferFuncs : public CFGStmtVisitor<TransferFuncs,bool> {
62 UninitializedValues::ValTy V;
Ted Kremenek3e039752007-09-17 17:14:52 +000063 UninitializedValues::AnalysisDataTy& AD;
Ted Kremenek7f49f502007-09-14 22:49:21 +000064public:
Ted Kremenek3e039752007-09-17 17:14:52 +000065 TransferFuncs(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {
Ted Kremenek334b30a2007-09-17 18:31:23 +000066 V.DeclBV.resize(AD.NumDecls);
67 V.ExprBV.resize(AD.NumBlockExprs);
Ted Kremenek7f49f502007-09-14 22:49:21 +000068 }
69
70 UninitializedValues::ValTy& getVal() { return V; }
Ted Kremenek3e039752007-09-17 17:14:52 +000071
Ted Kremenek334b30a2007-09-17 18:31:23 +000072 bool VisitDeclRefExpr(DeclRefExpr* DR);
73 bool VisitBinaryOperator(BinaryOperator* B);
74 bool VisitUnaryOperator(UnaryOperator* U);
75 bool VisitStmt(Stmt* S);
76 bool VisitCallExpr(CallExpr* C);
77 bool BlockStmt_VisitExpr(Expr* E);
78
79 static inline bool Initialized() { return true; }
80 static inline bool Unintialized() { return false; }
Ted Kremenek7f49f502007-09-14 22:49:21 +000081};
Ted Kremenek334b30a2007-09-17 18:31:23 +000082
83
84bool TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
85 if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) {
86 assert ( AD.VMap.find(VD) != AD.VMap.end() && "Unknown VarDecl.");
87 return V.DeclBV[ AD.VMap[VD] ];
88 }
89 else
90 return Initialized();
91}
92
93bool TransferFuncs::VisitBinaryOperator(BinaryOperator* B) {
94 if (CFG::hasImplicitControlFlow(B)) {
95 assert ( AD.EMap.find(B) != AD.EMap.end() && "Unknown block-level expr.");
96 return V.ExprBV[ AD.EMap[B] ];
97 }
98
99 return VisitStmt(B);
100}
101
102bool TransferFuncs::VisitCallExpr(CallExpr* C) {
103 VisitStmt(C);
104 return Initialized();
105}
106
107bool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
108 switch (U->getOpcode()) {
109 case UnaryOperator::AddrOf: {
110 // Blast through parentheses and find the decl (if any). Treat it
111 // as initialized from this point forward.
112 for (Stmt* S = U->getSubExpr() ;; )
113 if (ParenExpr* P = dyn_cast<ParenExpr>(S))
114 S = P->getSubExpr();
115 else if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S)) {
116 if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) {
117 assert ( AD.VMap.find(VD) != AD.VMap.end() && "Unknown VarDecl.");
118 V.DeclBV[ AD.VMap[VD] ] = Initialized();
119 }
120 break;
121 }
122 else {
123 // Evaluate the transfer function for subexpressions, even
124 // if we cannot reason more deeply about the &-expression.
125 return Visit(U->getSubExpr());
126 }
127
128 return Initialized();
129 }
130
131 default:
132 return Visit(U->getSubExpr());
133 }
134}
135
136bool TransferFuncs::VisitStmt(Stmt* S) {
137 bool x = Initialized();
138
139 // We don't stop at the first subexpression that is Uninitialized because
140 // evaluating some subexpressions may result in propogating "Uninitialized"
141 // or "Initialized" to variables referenced in the other subexpressions.
142 for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I)
143 if (Visit(*I) == Unintialized())
144 x = Unintialized();
145
146 return x;
147}
148
149bool TransferFuncs::BlockStmt_VisitExpr(Expr* E) {
150 assert ( AD.EMap.find(E) != AD.EMap.end() );
151 return V.ExprBV[ AD.EMap[E] ] = Visit(E);
152}
153
Ted Kremenek7f49f502007-09-14 22:49:21 +0000154} // end anonymous namespace
155
156//===--------------------------------------------------------------------===//
157// Merge operator.
Ted Kremenek334b30a2007-09-17 18:31:23 +0000158//
159// In our transfer functions we take the approach that any
160// combination of unintialized values, e.g. Unitialized + ___ = Unitialized.
161//
162// Merges take the opposite approach.
163//
164// In the merge of dataflow values (for Decls) we prefer unsoundness, and
165// prefer false negatives to false positives. At merges, if a value for a
166// tracked Decl is EVER initialized in any of the predecessors we treat it as
167// initialized at the confluence point.
168//
169// For tracked CFGBlock-level expressions (such as the result of
170// short-circuit), we do the opposite merge: if a value is EVER uninitialized
171// in a predecessor we treat it as uninitalized at the confluence point.
172// The reason we do this is because dataflow values for tracked Exprs are
173// not as control-dependent as dataflow values for tracked Decls.
Ted Kremenek7f49f502007-09-14 22:49:21 +0000174//===--------------------------------------------------------------------===//
175
176namespace {
177struct Merge {
178 void operator()(UninitializedValues::ValTy& Dst,
179 UninitializedValues::ValTy& Src) {
Ted Kremenek334b30a2007-09-17 18:31:23 +0000180 assert (Dst.DeclBV.size() == Src.DeclBV.size()
181 && "Bitvector sizes do not match.");
182
183 Dst.DeclBV |= Src.DeclBV;
184
185 assert (Dst.ExprBV.size() == Src.ExprBV.size()
186 && "Bitvector sizes do not match.");
187
188 Dst.ExprBV &= Src.ExprBV;
Ted Kremenek7f49f502007-09-14 22:49:21 +0000189 }
190};
191} // end anonymous namespace
192
193//===--------------------------------------------------------------------===//
Ted Kremenek7f49f502007-09-14 22:49:21 +0000194// External interface (driver logic).
195//===--------------------------------------------------------------------===//
196
197void UninitializedValues::CheckUninitializedValues(const CFG& cfg) {
198
199 typedef DataflowSolver<UninitializedValues,TransferFuncs,Merge> Solver;
200
201 UninitializedValues U;
202
203 { // Compute the unitialized values information.
204 Solver S(U);
205 S.runOnCFG(cfg);
206 }
207
208// WarnObserver O;
209 Solver S(U);
210
211 for (CFG::const_iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
212 S.runOnBlock(&*I);
213}