Consumed.cpp revision e444ea0f5c8c8cf677edd05d9fb1254422765bd5
1df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//===- Consumed.cpp --------------------------------------------*- C++ --*-===//
2df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//
3df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//                     The LLVM Compiler Infrastructure
4df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//
5df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// This file is distributed under the University of Illinois Open Source
6df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// License. See LICENSE.TXT for details.
7df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//
8df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//===----------------------------------------------------------------------===//
9df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//
10df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// A intra-procedural analysis for checking consumed properties.  This is based,
11df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// in part, on research on linear types.
12df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//
13df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//===----------------------------------------------------------------------===//
14df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
15df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/AST/ASTContext.h"
16df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/AST/Attr.h"
17df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/AST/DeclCXX.h"
18df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/AST/ExprCXX.h"
19df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/AST/RecursiveASTVisitor.h"
20df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/AST/StmtVisitor.h"
21df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/AST/StmtCXX.h"
22df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/AST/Type.h"
23df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/Analysis/Analyses/PostOrderCFGView.h"
24df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/Analysis/AnalysisContext.h"
25df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/Analysis/CFG.h"
26df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/Analysis/Analyses/Consumed.h"
27df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/Basic/OperatorKinds.h"
28df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/Basic/SourceLocation.h"
29df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "llvm/ADT/DenseMap.h"
30df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "llvm/ADT/SmallVector.h"
31b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins#include "llvm/Support/Compiler.h"
32df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "llvm/Support/raw_ostream.h"
33df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
34b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins// TODO: Correctly identify unreachable blocks when chaining boolean operators.
35b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins// TODO: Warn about unreachable code.
36b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins// TODO: Switch to using a bitmap to track unreachable blocks.
37df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// TODO: Mark variables as Unknown going into while- or for-loops only if they
38df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//       are referenced inside that block. (Deferred)
39b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins// TODO: Handle variable definitions, e.g. bool valid = x.isValid();
40b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins//       if (valid) ...; (Deferred)
41df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// TODO: Add a method(s) to identify which method calls perform what state
42df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//       transitions. (Deferred)
43df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// TODO: Take notes on state transitions to provide better warning messages.
44df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//       (Deferred)
45df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// TODO: Test nested conditionals: A) Checking the same value multiple times,
46df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//       and 2) Checking different values. (Deferred)
47df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// TODO: Test IsFalseVisitor with values in the unknown state. (Deferred)
48df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// TODO: Look into combining IsFalseVisitor and TestedVarsVisitor. (Deferred)
49df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
50df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsusing namespace clang;
51df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsusing namespace consumed;
52df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
53df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// Key method definition
54df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley HutchinsConsumedWarningsHandlerBase::~ConsumedWarningsHandlerBase() {}
55df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
56b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsstatic ConsumedState invertConsumedUnconsumed(ConsumedState State) {
57b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  switch (State) {
58b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_Unconsumed:
59b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return CS_Consumed;
60b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_Consumed:
61b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return CS_Unconsumed;
62b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_None:
63b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return CS_None;
64b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_Unknown:
65b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return CS_Unknown;
66b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
67b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  llvm_unreachable("invalid enum");
68b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins}
69b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
70b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsstatic bool isKnownState(ConsumedState State) {
71b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  switch (State) {
72b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_Unconsumed:
73b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_Consumed:
74b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return true;
75b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_None:
76b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_Unknown:
77b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return false;
78b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
79b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins}
80b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
815fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchinsstatic bool isTestingFunction(const FunctionDecl *FunDecl) {
825fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins  return FunDecl->hasAttr<TestsUnconsumedAttr>();
835fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins}
845fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
85df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsstatic StringRef stateToString(ConsumedState State) {
86df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  switch (State) {
87df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  case consumed::CS_None:
88df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    return "none";
89df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
90df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  case consumed::CS_Unknown:
91df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    return "unknown";
92df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
93df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  case consumed::CS_Unconsumed:
94df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    return "unconsumed";
95df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
96df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  case consumed::CS_Consumed:
97df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    return "consumed";
98df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
99a72f7206a71b3901d1b4b2b4718a5013f46010f2Reid Kleckner  llvm_unreachable("invalid enum");
100df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
101df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
102df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsnamespace {
103b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsstruct VarTestResult {
104b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const VarDecl *Var;
105b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConsumedState TestsFor;
106b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins};
107b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins} // end anonymous::VarTestResult
108b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
109b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsnamespace clang {
110b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsnamespace consumed {
111b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
112b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsenum EffectiveOp {
113b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  EO_And,
114b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  EO_Or
115b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins};
116b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
117b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsclass PropagationInfo {
118b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  enum {
119b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    IT_None,
120b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    IT_State,
121b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    IT_Test,
122b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    IT_BinTest,
123b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    IT_Var
124b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  } InfoType;
125e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher
126e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher  struct BinTestTy {
127e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher    const BinaryOperator *Source;
128e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher    EffectiveOp EOp;
129e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher    VarTestResult LTest;
130e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher    VarTestResult RTest;
131e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher  };
132df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
133b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  union {
134df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    ConsumedState State;
135b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    VarTestResult Test;
136df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    const VarDecl *Var;
137e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher    BinTestTy BinTest;
138df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  };
139df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
140b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinspublic:
141b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo() : InfoType(IT_None) {}
142df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
143b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo(const VarTestResult &Test) : InfoType(IT_Test), Test(Test) {}
144b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo(const VarDecl *Var, ConsumedState TestsFor)
145b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    : InfoType(IT_Test) {
146df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
147b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    Test.Var      = Var;
148b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    Test.TestsFor = TestsFor;
149b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
150b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
151b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp,
152b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                  const VarTestResult &LTest, const VarTestResult &RTest)
153b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    : InfoType(IT_BinTest) {
154df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
155b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.Source  = Source;
156b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.EOp     = EOp;
157b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.LTest   = LTest;
158b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.RTest   = RTest;
159b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
160b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
161b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp,
162b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                  const VarDecl *LVar, ConsumedState LTestsFor,
163b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                  const VarDecl *RVar, ConsumedState RTestsFor)
164b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    : InfoType(IT_BinTest) {
165df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
166b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.Source         = Source;
167b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.EOp            = EOp;
168b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.LTest.Var      = LVar;
169b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.LTest.TestsFor = LTestsFor;
170b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.RTest.Var      = RVar;
171b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.RTest.TestsFor = RTestsFor;
172b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
173b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
174b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo(ConsumedState State) : InfoType(IT_State), State(State) {}
175b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo(const VarDecl *Var) : InfoType(IT_Var), Var(Var) {}
176b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
177b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const ConsumedState & getState() const {
178b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_State);
179b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return State;
180b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
181b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
182b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const VarTestResult & getTest() const {
183b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_Test);
184b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return Test;
185b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
186b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
187b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const VarTestResult & getLTest() const {
188b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_BinTest);
189b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return BinTest.LTest;
190b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
191b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
192b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const VarTestResult & getRTest() const {
193b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_BinTest);
194b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return BinTest.RTest;
195b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
196b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
197b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const VarDecl * getVar() const {
198b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_Var);
199b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return Var;
200b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
201b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
202b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  EffectiveOp testEffectiveOp() const {
203b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_BinTest);
204b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return BinTest.EOp;
205b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
206b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
207b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const BinaryOperator * testSourceNode() const {
208b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_BinTest);
209b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return BinTest.Source;
210b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
211b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
212b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  bool isValid()   const { return InfoType != IT_None;     }
213b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  bool isState()   const { return InfoType == IT_State;    }
214b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  bool isTest()    const { return InfoType == IT_Test;     }
215b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  bool isBinTest() const { return InfoType == IT_BinTest;  }
216b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  bool isVar()     const { return InfoType == IT_Var;      }
217b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
218b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo invertTest() const {
219b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_Test || InfoType == IT_BinTest);
220df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
221b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (InfoType == IT_Test) {
222b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      return PropagationInfo(Test.Var, invertConsumedUnconsumed(Test.TestsFor));
223df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
224b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else if (InfoType == IT_BinTest) {
225b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      return PropagationInfo(BinTest.Source,
226b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        BinTest.EOp == EO_And ? EO_Or : EO_And,
227b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        BinTest.LTest.Var, invertConsumedUnconsumed(BinTest.LTest.TestsFor),
228b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        BinTest.RTest.Var, invertConsumedUnconsumed(BinTest.RTest.TestsFor));
229b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else {
230b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      return PropagationInfo();
231b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
232b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
233b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins};
234b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
235b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsclass ConsumedStmtVisitor : public ConstStmtVisitor<ConsumedStmtVisitor> {
236df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
237df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  typedef llvm::DenseMap<const Stmt *, PropagationInfo> MapType;
238df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  typedef std::pair<const Stmt *, PropagationInfo> PairType;
239df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  typedef MapType::iterator InfoEntry;
240b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  typedef MapType::const_iterator ConstInfoEntry;
241b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
2422d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner  AnalysisDeclContext &AC;
243df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  ConsumedAnalyzer &Analyzer;
244df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  ConsumedStateMap *StateMap;
245df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  MapType PropagationMap;
246df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
247b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins  void checkCallability(const PropagationInfo &PInfo,
2485fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins                        const FunctionDecl *FunDecl,
2495fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins                        const CallExpr *Call);
250df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void forwardInfo(const Stmt *From, const Stmt *To);
251b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  void handleTestingFunctionCall(const CallExpr *Call, const VarDecl *Var);
252df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  bool isLikeMoveAssignment(const CXXMethodDecl *MethodDecl);
253df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
254df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinspublic:
255b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
256df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void Visit(const Stmt *StmtNode);
257df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
258df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitBinaryOperator(const BinaryOperator *BinOp);
259df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitCallExpr(const CallExpr *Call);
260df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitCastExpr(const CastExpr *Cast);
261df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitCXXConstructExpr(const CXXConstructExpr *Call);
262df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitCXXMemberCallExpr(const CXXMemberCallExpr *Call);
263df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Call);
264df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitDeclRefExpr(const DeclRefExpr *DeclRef);
265df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitDeclStmt(const DeclStmt *DelcS);
266df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Temp);
267df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitMemberExpr(const MemberExpr *MExpr);
268df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitUnaryOperator(const UnaryOperator *UOp);
269df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitVarDecl(const VarDecl *Var);
2702d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner
271b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConsumedStmtVisitor(AnalysisDeclContext &AC, ConsumedAnalyzer &Analyzer)
272b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      : AC(AC), Analyzer(Analyzer), StateMap(NULL) {}
273b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
274b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo getInfo(const Stmt *StmtNode) const {
275b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    ConstInfoEntry Entry = PropagationMap.find(StmtNode);
276b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
277b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (Entry != PropagationMap.end())
278b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      return Entry->second;
279b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    else
280b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      return PropagationInfo();
281b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
282b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
283b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  void reset(ConsumedStateMap *NewStateMap) {
284b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    StateMap = NewStateMap;
285df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
286df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins};
287df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
2885fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins// TODO: When we support CallableWhenConsumed this will have to check for
2895fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins//       the different attributes and change the behavior bellow. (Deferred)
290b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchinsvoid ConsumedStmtVisitor::checkCallability(const PropagationInfo &PInfo,
2915fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins                                           const FunctionDecl *FunDecl,
2925fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins                                           const CallExpr *Call) {
2935fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
2945fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins  if (!FunDecl->hasAttr<CallableWhenUnconsumedAttr>()) return;
2955fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
296b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (PInfo.isVar()) {
297b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins    const VarDecl *Var = PInfo.getVar();
2985fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
2995fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins    switch (StateMap->getState(Var)) {
3005fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins    case CS_Consumed:
3015fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      Analyzer.WarningsHandler.warnUseWhileConsumed(
3025fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins        FunDecl->getNameAsString(), Var->getNameAsString(),
3035fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins        Call->getExprLoc());
3045fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      break;
3055fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
3065fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins    case CS_Unknown:
3075fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      Analyzer.WarningsHandler.warnUseInUnknownState(
3085fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins        FunDecl->getNameAsString(), Var->getNameAsString(),
3095fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins        Call->getExprLoc());
3105fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      break;
3115fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
3125fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins    case CS_None:
3135fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins    case CS_Unconsumed:
3145fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      break;
3155fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins    }
3165fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
3175fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins  } else {
318b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins    switch (PInfo.getState()) {
3195fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins    case CS_Consumed:
3205fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      Analyzer.WarningsHandler.warnUseOfTempWhileConsumed(
3215fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins        FunDecl->getNameAsString(), Call->getExprLoc());
3225fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      break;
3235fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
3245fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins    case CS_Unknown:
3255fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      Analyzer.WarningsHandler.warnUseOfTempInUnknownState(
3265fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins        FunDecl->getNameAsString(), Call->getExprLoc());
3275fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      break;
3285fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
3295fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins    case CS_None:
3305fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins    case CS_Unconsumed:
3315fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      break;
3325fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins    }
3335fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins  }
3345fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins}
3355fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
336df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::forwardInfo(const Stmt *From, const Stmt *To) {
337df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  InfoEntry Entry = PropagationMap.find(From);
338df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
339b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (Entry != PropagationMap.end())
340b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    PropagationMap.insert(PairType(To, Entry->second));
341b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins}
342b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
343b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsvoid ConsumedStmtVisitor::handleTestingFunctionCall(const CallExpr *Call,
344b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                                                    const VarDecl  *Var) {
345b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
346b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConsumedState VarState = StateMap->getState(Var);
347b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
348b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (VarState != CS_Unknown) {
349b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    SourceLocation CallLoc = Call->getExprLoc();
350b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
351b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (!CallLoc.isMacroID())
352b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      Analyzer.WarningsHandler.warnUnnecessaryTest(Var->getNameAsString(),
353b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        stateToString(VarState), CallLoc);
354df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
355b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
356b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationMap.insert(PairType(Call, PropagationInfo(Var, CS_Unconsumed)));
357df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
358df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
359df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsbool ConsumedStmtVisitor::isLikeMoveAssignment(
360df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  const CXXMethodDecl *MethodDecl) {
361df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
362df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  return MethodDecl->isMoveAssignmentOperator() ||
363df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins         (MethodDecl->getOverloadedOperator() == OO_Equal &&
364df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins          MethodDecl->getNumParams() == 1 &&
365df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins          MethodDecl->getParamDecl(0)->getType()->isRValueReferenceType());
366df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
367df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
368b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsvoid ConsumedStmtVisitor::Visit(const Stmt *StmtNode) {
369b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
370b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConstStmtVisitor<ConsumedStmtVisitor>::Visit(StmtNode);
371b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
372b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  for (Stmt::const_child_iterator CI = StmtNode->child_begin(),
373b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins       CE = StmtNode->child_end(); CI != CE; ++CI) {
374b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
375b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    PropagationMap.erase(*CI);
376b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
377b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins}
378b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
379df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitBinaryOperator(const BinaryOperator *BinOp) {
380df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  switch (BinOp->getOpcode()) {
381b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case BO_LAnd:
382b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case BO_LOr : {
383b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    InfoEntry LEntry = PropagationMap.find(BinOp->getLHS()),
384b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins              REntry = PropagationMap.find(BinOp->getRHS());
385b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
386b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    VarTestResult LTest, RTest;
387b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
388b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (LEntry != PropagationMap.end() && LEntry->second.isTest()) {
389b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      LTest = LEntry->second.getTest();
390b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
391b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else {
392b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      LTest.Var      = NULL;
393b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      LTest.TestsFor = CS_None;
394b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
395b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
396b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (REntry != PropagationMap.end() && REntry->second.isTest()) {
397b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      RTest = REntry->second.getTest();
398b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
399b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else {
400b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      RTest.Var      = NULL;
401b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      RTest.TestsFor = CS_None;
402b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
403b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
404b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (!(LTest.Var == NULL && RTest.Var == NULL))
405b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      PropagationMap.insert(PairType(BinOp, PropagationInfo(BinOp,
406b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        static_cast<EffectiveOp>(BinOp->getOpcode() == BO_LOr), LTest, RTest)));
407b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
408b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    break;
409b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
410b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
411df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  case BO_PtrMemD:
412df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  case BO_PtrMemI:
413df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    forwardInfo(BinOp->getLHS(), BinOp);
414df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    break;
415df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
416df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  default:
417df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    break;
418df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
419df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
420df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
421df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitCallExpr(const CallExpr *Call) {
422df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (const FunctionDecl *FunDecl =
423df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    dyn_cast_or_null<FunctionDecl>(Call->getDirectCallee())) {
424df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
425df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    // Special case for the std::move function.
426df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    // TODO: Make this more specific. (Deferred)
427df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    if (FunDecl->getNameAsString() == "move") {
428df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      InfoEntry Entry = PropagationMap.find(Call->getArg(0));
429df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
430df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      if (Entry != PropagationMap.end()) {
431df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        PropagationMap.insert(PairType(Call, Entry->second));
432df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      }
433df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
434df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      return;
435df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
436df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
437df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    unsigned Offset = Call->getNumArgs() - FunDecl->getNumParams();
438df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
439df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    for (unsigned Index = Offset; Index < Call->getNumArgs(); ++Index) {
440df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      QualType ParamType = FunDecl->getParamDecl(Index - Offset)->getType();
441df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
442df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      InfoEntry Entry = PropagationMap.find(Call->getArg(Index));
443df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
444b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (Entry == PropagationMap.end() || !Entry->second.isVar()) {
445df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        continue;
446df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      }
447df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
448b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins      PropagationInfo PInfo = Entry->second;
449df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
450df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      if (ParamType->isRValueReferenceType() ||
451df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins          (ParamType->isLValueReferenceType() &&
452df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins           !cast<LValueReferenceType>(*ParamType).isSpelledAsLValue())) {
453df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
454b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        StateMap->setState(PInfo.getVar(), consumed::CS_Consumed);
455df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
456df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      } else if (!(ParamType.isConstQualified() ||
457df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins                   ((ParamType->isReferenceType() ||
458df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins                     ParamType->isPointerType()) &&
459df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins                    ParamType->getPointeeType().isConstQualified()))) {
460df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
461b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        StateMap->setState(PInfo.getVar(), consumed::CS_Unknown);
462df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      }
463df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
464df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
465df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
466df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
467df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitCastExpr(const CastExpr *Cast) {
468b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  forwardInfo(Cast->getSubExpr(), Cast);
469df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
470df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
471df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitCXXConstructExpr(const CXXConstructExpr *Call) {
472df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  CXXConstructorDecl *Constructor = Call->getConstructor();
4732d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner
4742d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner  ASTContext &CurrContext = AC.getASTContext();
475df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  QualType ThisType = Constructor->getThisType(CurrContext)->getPointeeType();
476df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
477df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (Analyzer.isConsumableType(ThisType)) {
478df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    if (Constructor->hasAttr<ConsumesAttr>() ||
479df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        Constructor->isDefaultConstructor()) {
480df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
481df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      PropagationMap.insert(PairType(Call,
482df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        PropagationInfo(consumed::CS_Consumed)));
483df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
484df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    } else if (Constructor->isMoveConstructor()) {
485df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
486b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins      PropagationInfo PInfo =
487df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        PropagationMap.find(Call->getArg(0))->second;
488df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
489b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (PInfo.isVar()) {
490b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        const VarDecl* Var = PInfo.getVar();
491df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
492df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        PropagationMap.insert(PairType(Call,
493df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins          PropagationInfo(StateMap->getState(Var))));
494df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
495df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        StateMap->setState(Var, consumed::CS_Consumed);
496df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
497df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      } else {
498b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        PropagationMap.insert(PairType(Call, PInfo));
499df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      }
500df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
501df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    } else if (Constructor->isCopyConstructor()) {
502df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      MapType::iterator Entry = PropagationMap.find(Call->getArg(0));
503df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
504df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      if (Entry != PropagationMap.end())
505df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        PropagationMap.insert(PairType(Call, Entry->second));
506df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
507df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    } else {
508df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      PropagationMap.insert(PairType(Call,
509df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        PropagationInfo(consumed::CS_Unconsumed)));
510df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
511df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
512df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
513df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
514df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitCXXMemberCallExpr(
515df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  const CXXMemberCallExpr *Call) {
516df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
517df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  VisitCallExpr(Call);
518df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
519df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  InfoEntry Entry = PropagationMap.find(Call->getCallee()->IgnoreParens());
520df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
521df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (Entry != PropagationMap.end()) {
522b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins    PropagationInfo PInfo = Entry->second;
5235fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins    const CXXMethodDecl *MethodDecl = Call->getMethodDecl();
524df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
525b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins    checkCallability(PInfo, MethodDecl, Call);
526df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
527b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (PInfo.isVar()) {
528b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (isTestingFunction(MethodDecl))
529b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        handleTestingFunctionCall(Call, PInfo.getVar());
530b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      else if (MethodDecl->hasAttr<ConsumesAttr>())
531b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        StateMap->setState(PInfo.getVar(), consumed::CS_Consumed);
5325fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      else if (!MethodDecl->isConst())
533b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        StateMap->setState(PInfo.getVar(), consumed::CS_Unknown);
5345fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins    }
535df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
536df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
537df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
538df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitCXXOperatorCallExpr(
539df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  const CXXOperatorCallExpr *Call) {
540df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
541df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  const FunctionDecl *FunDecl =
542df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    dyn_cast_or_null<FunctionDecl>(Call->getDirectCallee());
543df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
544df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (!FunDecl) return;
545df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
546df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (isa<CXXMethodDecl>(FunDecl) &&
547df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      isLikeMoveAssignment(cast<CXXMethodDecl>(FunDecl))) {
548df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
549df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    InfoEntry LEntry = PropagationMap.find(Call->getArg(0));
550df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    InfoEntry REntry = PropagationMap.find(Call->getArg(1));
551df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
552b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins    PropagationInfo LPInfo, RPInfo;
553df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
554df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    if (LEntry != PropagationMap.end() &&
555df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        REntry != PropagationMap.end()) {
556df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
557b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins      LPInfo = LEntry->second;
558b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins      RPInfo = REntry->second;
559df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
560b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (LPInfo.isVar() && RPInfo.isVar()) {
561b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        StateMap->setState(LPInfo.getVar(),
562b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins          StateMap->getState(RPInfo.getVar()));
563df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
564b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        StateMap->setState(RPInfo.getVar(), consumed::CS_Consumed);
565df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
566b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        PropagationMap.insert(PairType(Call, LPInfo));
567df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
568b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      } else if (LPInfo.isVar() && !RPInfo.isVar()) {
569b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        StateMap->setState(LPInfo.getVar(), RPInfo.getState());
570df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
571b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        PropagationMap.insert(PairType(Call, LPInfo));
572df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
573b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      } else if (!LPInfo.isVar() && RPInfo.isVar()) {
574df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        PropagationMap.insert(PairType(Call,
575b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins          PropagationInfo(StateMap->getState(RPInfo.getVar()))));
576df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
577b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        StateMap->setState(RPInfo.getVar(), consumed::CS_Consumed);
578df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
579df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      } else {
580b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        PropagationMap.insert(PairType(Call, RPInfo));
581df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      }
582df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
583df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    } else if (LEntry != PropagationMap.end() &&
584df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins               REntry == PropagationMap.end()) {
585df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
586b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins      LPInfo = LEntry->second;
587df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
588b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (LPInfo.isVar()) {
589b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        StateMap->setState(LPInfo.getVar(), consumed::CS_Unknown);
590df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
591b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        PropagationMap.insert(PairType(Call, LPInfo));
592df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
593df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      } else {
594df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        PropagationMap.insert(PairType(Call,
595df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins          PropagationInfo(consumed::CS_Unknown)));
596df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      }
597df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
598df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    } else if (LEntry == PropagationMap.end() &&
599df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins               REntry != PropagationMap.end()) {
600df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
601b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins      RPInfo = REntry->second;
602df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
603b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (RPInfo.isVar()) {
604b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        const VarDecl *Var = RPInfo.getVar();
605df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
606df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        PropagationMap.insert(PairType(Call,
607df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins          PropagationInfo(StateMap->getState(Var))));
608df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
609df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        StateMap->setState(Var, consumed::CS_Consumed);
610df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
611df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      } else {
612b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        PropagationMap.insert(PairType(Call, RPInfo));
613df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      }
614df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
615df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
616df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  } else {
617df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
618df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    VisitCallExpr(Call);
619df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
620df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    InfoEntry Entry = PropagationMap.find(Call->getArg(0));
621df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
622df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    if (Entry != PropagationMap.end()) {
623b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins      PropagationInfo PInfo = Entry->second;
624df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
625b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins      checkCallability(PInfo, FunDecl, Call);
6265fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
627b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (PInfo.isVar()) {
628b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        if (isTestingFunction(FunDecl)) {
629b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins          handleTestingFunctionCall(Call, PInfo.getVar());
630b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
631b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        } else if (FunDecl->hasAttr<ConsumesAttr>()) {
632b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins          StateMap->setState(PInfo.getVar(), consumed::CS_Consumed);
633b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
6345fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins        } else if (const CXXMethodDecl *MethodDecl =
635b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                     dyn_cast_or_null<CXXMethodDecl>(FunDecl)) {
636df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
6375fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins          if (!MethodDecl->isConst())
638b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins            StateMap->setState(PInfo.getVar(), consumed::CS_Unknown);
639df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        }
640df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      }
641df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
642df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
643df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
644df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
645df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitDeclRefExpr(const DeclRefExpr *DeclRef) {
646df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(DeclRef->getDecl()))
647df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    if (StateMap->getState(Var) != consumed::CS_None)
648df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      PropagationMap.insert(PairType(DeclRef, PropagationInfo(Var)));
649df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
650df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
651df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitDeclStmt(const DeclStmt *DeclS) {
652df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  for (DeclStmt::const_decl_iterator DI = DeclS->decl_begin(),
653df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins       DE = DeclS->decl_end(); DI != DE; ++DI) {
654df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
655df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    if (isa<VarDecl>(*DI)) VisitVarDecl(cast<VarDecl>(*DI));
656df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
657df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
658df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (DeclS->isSingleDecl())
659df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(DeclS->getSingleDecl()))
660df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      PropagationMap.insert(PairType(DeclS, PropagationInfo(Var)));
661df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
662df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
663df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitMaterializeTemporaryExpr(
664df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  const MaterializeTemporaryExpr *Temp) {
665df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
666df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  InfoEntry Entry = PropagationMap.find(Temp->GetTemporaryExpr());
667df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
668df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (Entry != PropagationMap.end())
669df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    PropagationMap.insert(PairType(Temp, Entry->second));
670df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
671df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
672df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitMemberExpr(const MemberExpr *MExpr) {
673df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  forwardInfo(MExpr->getBase(), MExpr);
674df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
675df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
676df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitUnaryOperator(const UnaryOperator *UOp) {
677b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  InfoEntry Entry = PropagationMap.find(UOp->getSubExpr()->IgnoreParens());
678b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (Entry == PropagationMap.end()) return;
679b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
680b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  switch (UOp->getOpcode()) {
681b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case UO_AddrOf:
682b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    PropagationMap.insert(PairType(UOp, Entry->second));
683b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    break;
684b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
685b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case UO_LNot:
686b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (Entry->second.isTest() || Entry->second.isBinTest())
687b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      PropagationMap.insert(PairType(UOp, Entry->second.invertTest()));
688b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    break;
689b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
690b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  default:
691b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    break;
692df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
693df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
694df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
695df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitVarDecl(const VarDecl *Var) {
696df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (Analyzer.isConsumableType(Var->getType())) {
697b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins    PropagationInfo PInfo =
698df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      PropagationMap.find(Var->getInit())->second;
699df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
700b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    StateMap->setState(Var, PInfo.isVar() ?
701b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins      StateMap->getState(PInfo.getVar()) : PInfo.getState());
702df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
703df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
704b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins}} // end clang::consumed::ConsumedStmtVisitor
705df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
706b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsnamespace clang {
707b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsnamespace consumed {
708df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
709b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsvoid splitVarStateForIf(const IfStmt * IfNode, const VarTestResult &Test,
710b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                        ConsumedStateMap *ThenStates,
711b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                        ConsumedStateMap *ElseStates) {
712b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
713b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConsumedState VarState = ThenStates->getState(Test.Var);
714df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
715b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (VarState == CS_Unknown) {
716b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    ThenStates->setState(Test.Var, Test.TestsFor);
717b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (ElseStates)
718b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      ElseStates->setState(Test.Var, invertConsumedUnconsumed(Test.TestsFor));
719df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
720b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  } else if (VarState == invertConsumedUnconsumed(Test.TestsFor)) {
721b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    ThenStates->markUnreachable();
722df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
723b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  } else if (VarState == Test.TestsFor && ElseStates) {
724b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    ElseStates->markUnreachable();
725df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
726df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
727df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
728b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsvoid splitVarStateForIfBinOp(const PropagationInfo &PInfo,
729b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConsumedStateMap *ThenStates, ConsumedStateMap *ElseStates) {
730df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
731b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const VarTestResult &LTest = PInfo.getLTest(),
732b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                      &RTest = PInfo.getRTest();
733b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
734b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConsumedState LState = LTest.Var ? ThenStates->getState(LTest.Var) : CS_None,
735b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                RState = RTest.Var ? ThenStates->getState(RTest.Var) : CS_None;
736b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
737b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (LTest.Var) {
738b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (PInfo.testEffectiveOp() == EO_And) {
739b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (LState == CS_Unknown) {
740b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ThenStates->setState(LTest.Var, LTest.TestsFor);
741b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
742b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      } else if (LState == invertConsumedUnconsumed(LTest.TestsFor)) {
743b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ThenStates->markUnreachable();
744b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
745b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      } else if (LState == LTest.TestsFor && isKnownState(RState)) {
746b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        if (RState == RTest.TestsFor) {
747b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins          if (ElseStates)
748b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins            ElseStates->markUnreachable();
749b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        } else {
750b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins          ThenStates->markUnreachable();
751b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        }
752b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      }
753b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
754b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else {
755b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (LState == CS_Unknown && ElseStates) {
756b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ElseStates->setState(LTest.Var,
757b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                             invertConsumedUnconsumed(LTest.TestsFor));
758b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
759b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      } else if (LState == LTest.TestsFor && ElseStates) {
760b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ElseStates->markUnreachable();
761b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
762b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      } else if (LState == invertConsumedUnconsumed(LTest.TestsFor) &&
763b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                 isKnownState(RState)) {
764b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
765b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        if (RState == RTest.TestsFor) {
766b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins          if (ElseStates)
767b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins            ElseStates->markUnreachable();
768b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        } else {
769b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins          ThenStates->markUnreachable();
770b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        }
771b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      }
772b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
773df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
774df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
775b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (RTest.Var) {
776b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (PInfo.testEffectiveOp() == EO_And) {
777b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (RState == CS_Unknown)
778b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ThenStates->setState(RTest.Var, RTest.TestsFor);
779b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      else if (RState == invertConsumedUnconsumed(RTest.TestsFor))
780b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ThenStates->markUnreachable();
781b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
782b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else if (ElseStates) {
783b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (RState == CS_Unknown)
784b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ElseStates->setState(RTest.Var,
785b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                             invertConsumedUnconsumed(RTest.TestsFor));
786b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      else if (RState == RTest.TestsFor)
787b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ElseStates->markUnreachable();
788b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
789b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
790df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
791df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
792df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedBlockInfo::addInfo(const CFGBlock *Block,
793df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins                                ConsumedStateMap *StateMap,
794df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins                                bool &AlreadyOwned) {
795df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
796df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (VisitedBlocks.alreadySet(Block)) return;
797df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
798df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  ConsumedStateMap *Entry = StateMapsArray[Block->getBlockID()];
799df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
800df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (Entry) {
801df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    Entry->intersect(StateMap);
802df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
803df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  } else if (AlreadyOwned) {
804df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    StateMapsArray[Block->getBlockID()] = new ConsumedStateMap(*StateMap);
805df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
806df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  } else {
807df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    StateMapsArray[Block->getBlockID()] = StateMap;
808df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    AlreadyOwned = true;
809df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
810df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
811df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
812df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedBlockInfo::addInfo(const CFGBlock *Block,
813df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins                                ConsumedStateMap *StateMap) {
814df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
815df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (VisitedBlocks.alreadySet(Block)) {
816df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    delete StateMap;
817df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    return;
818df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
819df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
820df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  ConsumedStateMap *Entry = StateMapsArray[Block->getBlockID()];
821df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
822df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (Entry) {
823df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    Entry->intersect(StateMap);
824df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    delete StateMap;
825df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
826df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  } else {
827df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    StateMapsArray[Block->getBlockID()] = StateMap;
828df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
829df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
830df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
831df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley HutchinsConsumedStateMap* ConsumedBlockInfo::getInfo(const CFGBlock *Block) {
832df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  return StateMapsArray[Block->getBlockID()];
833df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
834df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
835df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedBlockInfo::markVisited(const CFGBlock *Block) {
836df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  VisitedBlocks.insert(Block);
837df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
838df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
839df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley HutchinsConsumedState ConsumedStateMap::getState(const VarDecl *Var) {
840df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  MapType::const_iterator Entry = Map.find(Var);
841df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
842df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (Entry != Map.end()) {
843df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    return Entry->second;
844df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
845df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  } else {
846df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    return CS_None;
847df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
848df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
849df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
850df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStateMap::intersect(const ConsumedStateMap *Other) {
851df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  ConsumedState LocalState;
852df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
853b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (this->From && this->From == Other->From && !Other->Reachable) {
854b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    this->markUnreachable();
855b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return;
856b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
857b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
858df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  for (MapType::const_iterator DMI = Other->Map.begin(),
859df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins       DME = Other->Map.end(); DMI != DME; ++DMI) {
860df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
861df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    LocalState = this->getState(DMI->first);
862df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
863b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (LocalState == CS_None)
864b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      continue;
865b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
866b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (LocalState != DMI->second)
867b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins       Map[DMI->first] = CS_Unknown;
868df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
869df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
870df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
871b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsvoid ConsumedStateMap::markUnreachable() {
872b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  this->Reachable = false;
873b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  Map.clear();
874b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins}
875b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
876df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStateMap::makeUnknown() {
877df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  for (MapType::const_iterator DMI = Map.begin(), DME = Map.end(); DMI != DME;
878df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins       ++DMI) {
879df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
880b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    Map[DMI->first] = CS_Unknown;
881df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
882df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
883df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
884df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStateMap::setState(const VarDecl *Var, ConsumedState State) {
885df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  Map[Var] = State;
886df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
887df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
8885fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchinsvoid ConsumedStateMap::remove(const VarDecl *Var) {
8895fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins  Map.erase(Var);
8905fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins}
891df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
892df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsbool ConsumedAnalyzer::isConsumableType(QualType Type) {
893df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  const CXXRecordDecl *RD =
894df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    dyn_cast_or_null<CXXRecordDecl>(Type->getAsCXXRecordDecl());
895df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
896df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (!RD) return false;
897df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
898df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  std::pair<CacheMapType::iterator, bool> Entry =
899df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    ConsumableTypeCache.insert(std::make_pair(RD, false));
900df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
901df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (Entry.second)
902df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    Entry.first->second = hasConsumableAttributes(RD);
903df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
904df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  return Entry.first->second;
905df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
906df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
907df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// TODO: Walk the base classes to see if any of them are unique types.
908df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//       (Deferred)
909df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsbool ConsumedAnalyzer::hasConsumableAttributes(const CXXRecordDecl *RD) {
910df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  for (CXXRecordDecl::method_iterator MI = RD->method_begin(),
911df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins       ME = RD->method_end(); MI != ME; ++MI) {
912df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
913df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    for (Decl::attr_iterator AI = (*MI)->attr_begin(), AE = (*MI)->attr_end();
914df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins         AI != AE; ++AI) {
915df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
916df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      switch ((*AI)->getKind()) {
917df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      case attr::CallableWhenUnconsumed:
918df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      case attr::TestsUnconsumed:
919df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        return true;
920df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
921df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      default:
922df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        break;
923df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      }
924df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
925df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
926df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
927df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  return false;
928df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
929df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
930b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsbool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,
931b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                                  const ConsumedStmtVisitor &Visitor) {
932df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
933b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConsumedStateMap *FalseStates = new ConsumedStateMap(*CurrStates);
934b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo PInfo;
935df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
936b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (const IfStmt *IfNode =
937b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    dyn_cast_or_null<IfStmt>(CurrBlock->getTerminator().getStmt())) {
938df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
939b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    bool HasElse = IfNode->getElse() != NULL;
940b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    const Stmt *Cond = IfNode->getCond();
941b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
942b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    PInfo = Visitor.getInfo(Cond);
943b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (!PInfo.isValid() && isa<BinaryOperator>(Cond))
944b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      PInfo = Visitor.getInfo(cast<BinaryOperator>(Cond)->getRHS());
945df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
946b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (PInfo.isTest()) {
947b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      CurrStates->setSource(Cond);
948b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      FalseStates->setSource(Cond);
949b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
950b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      splitVarStateForIf(IfNode, PInfo.getTest(), CurrStates,
951b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                         HasElse ? FalseStates : NULL);
952b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
953b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else if (PInfo.isBinTest()) {
954b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      CurrStates->setSource(PInfo.testSourceNode());
955b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      FalseStates->setSource(PInfo.testSourceNode());
956b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
957b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      splitVarStateForIfBinOp(PInfo, CurrStates, HasElse ? FalseStates : NULL);
958df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
959df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    } else {
960b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      delete FalseStates;
961b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      return false;
962df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
963df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
964b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  } else if (const BinaryOperator *BinOp =
965b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    dyn_cast_or_null<BinaryOperator>(CurrBlock->getTerminator().getStmt())) {
966b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
967b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    PInfo = Visitor.getInfo(BinOp->getLHS());
968b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (!PInfo.isTest()) {
969b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if ((BinOp = dyn_cast_or_null<BinaryOperator>(BinOp->getLHS()))) {
970b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        PInfo = Visitor.getInfo(BinOp->getRHS());
971b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
972b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        if (!PInfo.isTest()) {
973b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins          delete FalseStates;
974b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins          return false;
975b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        }
976b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
977b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      } else {
978b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        delete FalseStates;
979b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        return false;
980b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      }
981b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
982b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
983b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    CurrStates->setSource(BinOp);
984b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    FalseStates->setSource(BinOp);
985b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
986b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    const VarTestResult &Test = PInfo.getTest();
987b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    ConsumedState VarState = CurrStates->getState(Test.Var);
988b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
989b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (BinOp->getOpcode() == BO_LAnd) {
990b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (VarState == CS_Unknown)
991b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        CurrStates->setState(Test.Var, Test.TestsFor);
992b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      else if (VarState == invertConsumedUnconsumed(Test.TestsFor))
993b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        CurrStates->markUnreachable();
994b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
995b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else if (BinOp->getOpcode() == BO_LOr) {
996b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (VarState == CS_Unknown)
997b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        FalseStates->setState(Test.Var,
998b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                              invertConsumedUnconsumed(Test.TestsFor));
999b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      else if (VarState == Test.TestsFor)
1000b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        FalseStates->markUnreachable();
1001b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
1002b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1003b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  } else {
1004b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    delete FalseStates;
1005b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return false;
1006b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
1007b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1008df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin();
1009df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1010b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (*SI)
1011b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BlockInfo.addInfo(*SI, CurrStates);
1012b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  else
1013b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    delete CurrStates;
1014b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1015b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (*++SI)
1016b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BlockInfo.addInfo(*SI, FalseStates);
1017b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  else
1018b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    delete FalseStates;
1019b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1020b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  CurrStates = NULL;
1021b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  return true;
1022df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
1023df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1024df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
1025df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  const FunctionDecl *D = dyn_cast_or_null<FunctionDecl>(AC.getDecl());
1026df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1027df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (!D) return;
1028df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1029df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  BlockInfo = ConsumedBlockInfo(AC.getCFG());
1030df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1031df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  PostOrderCFGView *SortedGraph = AC.getAnalysis<PostOrderCFGView>();
1032df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1033df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  CurrStates = new ConsumedStateMap();
1034b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConsumedStmtVisitor Visitor(AC, *this);
1035df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1036df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  // Visit all of the function's basic blocks.
1037df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  for (PostOrderCFGView::iterator I = SortedGraph->begin(),
1038df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins       E = SortedGraph->end(); I != E; ++I) {
1039df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1040df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    const CFGBlock *CurrBlock = *I;
1041df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    BlockInfo.markVisited(CurrBlock);
1042df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1043df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    if (CurrStates == NULL)
1044df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      CurrStates = BlockInfo.getInfo(CurrBlock);
1045b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1046b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (!CurrStates) {
1047b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      continue;
1048b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1049b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else if (!CurrStates->isReachable()) {
1050b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      delete CurrStates;
1051b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      CurrStates = NULL;
1052b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      continue;
1053b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
1054b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1055b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    Visitor.reset(CurrStates);
1056b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1057df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    // Visit all of the basic block's statements.
1058df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    for (CFGBlock::const_iterator BI = CurrBlock->begin(),
1059df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins         BE = CurrBlock->end(); BI != BE; ++BI) {
1060df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
10615fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      switch (BI->getKind()) {
10625fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      case CFGElement::Statement:
1063df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        Visitor.Visit(BI->castAs<CFGStmt>().getStmt());
10645fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins        break;
10655fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      case CFGElement::AutomaticObjectDtor:
10665fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins        CurrStates->remove(BI->castAs<CFGAutomaticObjDtor>().getVarDecl());
10675fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      default:
10685fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins        break;
10695fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      }
1070df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
1071df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1072b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    // TODO: Handle other forms of branching with precision, including while-
1073b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    //       and for-loops. (Deferred)
1074b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (!splitState(CurrBlock, Visitor)) {
1075b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      CurrStates->setSource(NULL);
1076df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1077b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (CurrBlock->succ_size() > 1) {
1078b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        CurrStates->makeUnknown();
1079df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1080b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        bool OwnershipTaken = false;
1081b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1082b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
1083b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins             SE = CurrBlock->succ_end(); SI != SE; ++SI) {
1084b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1085b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins          if (*SI) BlockInfo.addInfo(*SI, CurrStates, OwnershipTaken);
1086b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        }
1087b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1088b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        if (!OwnershipTaken)
1089b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins          delete CurrStates;
1090b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1091b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        CurrStates = NULL;
1092b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1093b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      } else if (CurrBlock->succ_size() == 1 &&
1094b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                 (*CurrBlock->succ_begin())->pred_size() > 1) {
1095b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1096b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        BlockInfo.addInfo(*CurrBlock->succ_begin(), CurrStates);
1097b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        CurrStates = NULL;
1098df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      }
1099df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
1100df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  } // End of block iterator.
1101df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1102df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  // Delete the last existing state map.
1103df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  delete CurrStates;
1104df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1105df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  WarningsHandler.emitDiagnostics();
1106df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
1107df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}} // end namespace clang::consumed
1108