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