Consumed.cpp revision 627c7f9740dfe9c208543798eccbe5ca23e1ef42
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
347385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins// TODO: Use information from tests in while-loop conditional.
350e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins// TODO: Add notes about the actual and expected state for
36b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins// TODO: Correctly identify unreachable blocks when chaining boolean operators.
3766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins// TODO: Adjust the parser and AttributesList class to support lists of
3866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins//       identifiers.
39b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins// TODO: Warn about unreachable code.
40b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins// TODO: Switch to using a bitmap to track unreachable blocks.
41b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins// TODO: Handle variable definitions, e.g. bool valid = x.isValid();
42b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins//       if (valid) ...; (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
48df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsusing namespace clang;
49df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsusing namespace consumed;
50df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
51df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// Key method definition
52df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley HutchinsConsumedWarningsHandlerBase::~ConsumedWarningsHandlerBase() {}
53df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
54627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchinsstatic SourceLocation getLastStmtLoc(const CFGBlock *Block) {
557385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  // Find the source location of the last statement in the block, if the block
567385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  // is not empty.
57627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins  if (const Stmt *StmtNode = Block->getTerminator()) {
587385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    return StmtNode->getLocStart();
597385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  } else {
60627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins    for (CFGBlock::const_reverse_iterator BI = Block->rbegin(),
61627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins         BE = Block->rend(); BI != BE; ++BI) {
627385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins      // FIXME: Handle other CFGElement kinds.
637385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins      if (Optional<CFGStmt> CS = BI->getAs<CFGStmt>())
647385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins        return CS->getStmt()->getLocStart();
657385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    }
667385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  }
677385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
687385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  // The block is empty, and has a single predecessor. Use its exit location.
69627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins  assert(Block->pred_size() == 1 && *Block->pred_begin() &&
70627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins         Block->succ_size() != 0);
717385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
72627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins  return getLastStmtLoc(*Block->pred_begin());
737385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins}
747385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
75b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsstatic ConsumedState invertConsumedUnconsumed(ConsumedState State) {
76b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  switch (State) {
77b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_Unconsumed:
78b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return CS_Consumed;
79b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_Consumed:
80b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return CS_Unconsumed;
81b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_None:
82b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return CS_None;
83b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_Unknown:
84b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return CS_Unknown;
85b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
86b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  llvm_unreachable("invalid enum");
87b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins}
88b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
8966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchinsstatic bool isCallableInState(const CallableWhenAttr *CWAttr,
9066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins                              ConsumedState State) {
9166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
9266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins  CallableWhenAttr::callableState_iterator I = CWAttr->callableState_begin(),
9366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins                                           E = CWAttr->callableState_end();
9466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
9566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins  for (; I != E; ++I) {
9666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
9766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    ConsumedState MappedAttrState = CS_None;
9866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
9966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    switch (*I) {
10066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    case CallableWhenAttr::Unknown:
10166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      MappedAttrState = CS_Unknown;
10266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      break;
10366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
10466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    case CallableWhenAttr::Unconsumed:
10566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      MappedAttrState = CS_Unconsumed;
10666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      break;
10766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
10866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    case CallableWhenAttr::Consumed:
10966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      MappedAttrState = CS_Consumed;
11066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      break;
11166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    }
11266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
11366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    if (MappedAttrState == State)
11466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      return true;
11566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins  }
11666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
11766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins  return false;
11866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins}
11966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
120c55bee6e278d888d7a5d29fc17df6a9ae1e8b7d3DeLesley Hutchinsstatic bool isConsumableType(const QualType &QT) {
121c55bee6e278d888d7a5d29fc17df6a9ae1e8b7d3DeLesley Hutchins  if (const CXXRecordDecl *RD = QT->getAsCXXRecordDecl())
122c55bee6e278d888d7a5d29fc17df6a9ae1e8b7d3DeLesley Hutchins    return RD->hasAttr<ConsumableAttr>();
123c55bee6e278d888d7a5d29fc17df6a9ae1e8b7d3DeLesley Hutchins  else
124c55bee6e278d888d7a5d29fc17df6a9ae1e8b7d3DeLesley Hutchins    return false;
125c55bee6e278d888d7a5d29fc17df6a9ae1e8b7d3DeLesley Hutchins}
126c55bee6e278d888d7a5d29fc17df6a9ae1e8b7d3DeLesley Hutchins
127b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsstatic bool isKnownState(ConsumedState State) {
128b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  switch (State) {
129b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_Unconsumed:
130b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_Consumed:
131b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return true;
132b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_None:
133b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_Unknown:
134b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return false;
135b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
1366b2ec037f16753547398efe1812160982f1d14e4Aaron Ballman  llvm_unreachable("invalid enum");
137b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins}
138b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1395fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchinsstatic bool isTestingFunction(const FunctionDecl *FunDecl) {
1405fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins  return FunDecl->hasAttr<TestsUnconsumedAttr>();
1415fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins}
1425fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
143a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikiestatic ConsumedState mapConsumableAttrState(const QualType QT) {
144a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  assert(isConsumableType(QT));
145a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie
146a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  const ConsumableAttr *CAttr =
147a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie      QT->getAsCXXRecordDecl()->getAttr<ConsumableAttr>();
148a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie
149a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  switch (CAttr->getDefaultState()) {
150a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  case ConsumableAttr::Unknown:
151a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    return CS_Unknown;
152a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  case ConsumableAttr::Unconsumed:
153a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    return CS_Unconsumed;
154a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  case ConsumableAttr::Consumed:
155a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    return CS_Consumed;
156a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  }
157a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  llvm_unreachable("invalid enum");
158a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie}
159a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie
160e988dc45254405aff0950337d82aa8623fb1b88eEric Christopherstatic ConsumedState
161e988dc45254405aff0950337d82aa8623fb1b88eEric ChristophermapReturnTypestateAttrState(const ReturnTypestateAttr *RTSAttr) {
1620e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins  switch (RTSAttr->getState()) {
1630e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins  case ReturnTypestateAttr::Unknown:
1640e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    return CS_Unknown;
1650e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins  case ReturnTypestateAttr::Unconsumed:
1660e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    return CS_Unconsumed;
1670e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins  case ReturnTypestateAttr::Consumed:
1680e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    return CS_Consumed;
1690e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins  }
170e988dc45254405aff0950337d82aa8623fb1b88eEric Christopher  llvm_unreachable("invalid enum");
1710e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins}
1720e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins
173df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsstatic StringRef stateToString(ConsumedState State) {
174df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  switch (State) {
175df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  case consumed::CS_None:
176df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    return "none";
177df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
178df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  case consumed::CS_Unknown:
179df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    return "unknown";
180df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
181df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  case consumed::CS_Unconsumed:
182df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    return "unconsumed";
183df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
184df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  case consumed::CS_Consumed:
185df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    return "consumed";
186df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
187a72f7206a71b3901d1b4b2b4718a5013f46010f2Reid Kleckner  llvm_unreachable("invalid enum");
188df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
189df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
190df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsnamespace {
191b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsstruct VarTestResult {
192b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const VarDecl *Var;
193b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConsumedState TestsFor;
194b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins};
195b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins} // end anonymous::VarTestResult
196b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
197b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsnamespace clang {
198b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsnamespace consumed {
199b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
200b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsenum EffectiveOp {
201b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  EO_And,
202b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  EO_Or
203b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins};
204b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
205b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsclass PropagationInfo {
206b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  enum {
207b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    IT_None,
208b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    IT_State,
209b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    IT_Test,
210b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    IT_BinTest,
211b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    IT_Var
212b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  } InfoType;
213e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher
214e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher  struct BinTestTy {
215e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher    const BinaryOperator *Source;
216e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher    EffectiveOp EOp;
217e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher    VarTestResult LTest;
218e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher    VarTestResult RTest;
219e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher  };
220df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
221b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  union {
222df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    ConsumedState State;
223b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    VarTestResult Test;
224df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    const VarDecl *Var;
225e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher    BinTestTy BinTest;
226df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  };
227df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
22866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins  QualType TempType;
22966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
230b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinspublic:
231b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo() : InfoType(IT_None) {}
232df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
233b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo(const VarTestResult &Test) : InfoType(IT_Test), Test(Test) {}
234b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo(const VarDecl *Var, ConsumedState TestsFor)
235b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    : InfoType(IT_Test) {
236df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
237b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    Test.Var      = Var;
238b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    Test.TestsFor = TestsFor;
239b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
240b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
241b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp,
242b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                  const VarTestResult &LTest, const VarTestResult &RTest)
243b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    : InfoType(IT_BinTest) {
244df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
245b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.Source  = Source;
246b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.EOp     = EOp;
247b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.LTest   = LTest;
248b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.RTest   = RTest;
249b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
250b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
251b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp,
252b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                  const VarDecl *LVar, ConsumedState LTestsFor,
253b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                  const VarDecl *RVar, ConsumedState RTestsFor)
254b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    : InfoType(IT_BinTest) {
255df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
256b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.Source         = Source;
257b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.EOp            = EOp;
258b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.LTest.Var      = LVar;
259b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.LTest.TestsFor = LTestsFor;
260b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.RTest.Var      = RVar;
261b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.RTest.TestsFor = RTestsFor;
262b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
263b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
26466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins  PropagationInfo(ConsumedState State, QualType TempType)
26566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    : InfoType(IT_State), State(State), TempType(TempType) {}
26666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
267b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo(const VarDecl *Var) : InfoType(IT_Var), Var(Var) {}
268b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
269b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const ConsumedState & getState() const {
270b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_State);
271b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return State;
272b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
273b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
27466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins  const QualType & getTempType() const {
27566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    assert(InfoType == IT_State);
27666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    return TempType;
27766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins  }
27866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
279b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const VarTestResult & getTest() const {
280b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_Test);
281b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return Test;
282b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
283b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
284b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const VarTestResult & getLTest() const {
285b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_BinTest);
286b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return BinTest.LTest;
287b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
288b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
289b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const VarTestResult & getRTest() const {
290b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_BinTest);
291b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return BinTest.RTest;
292b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
293b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
294b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const VarDecl * getVar() const {
295b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_Var);
296b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return Var;
297b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
298b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
299b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  EffectiveOp testEffectiveOp() const {
300b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_BinTest);
301b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return BinTest.EOp;
302b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
303b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
304b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const BinaryOperator * testSourceNode() const {
305b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_BinTest);
306b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return BinTest.Source;
307b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
308b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
309b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  bool isValid()   const { return InfoType != IT_None;     }
310b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  bool isState()   const { return InfoType == IT_State;    }
311b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  bool isTest()    const { return InfoType == IT_Test;     }
312b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  bool isBinTest() const { return InfoType == IT_BinTest;  }
313b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  bool isVar()     const { return InfoType == IT_Var;      }
314b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
315b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo invertTest() const {
316b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_Test || InfoType == IT_BinTest);
317df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
318b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (InfoType == IT_Test) {
319b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      return PropagationInfo(Test.Var, invertConsumedUnconsumed(Test.TestsFor));
320df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
321b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else if (InfoType == IT_BinTest) {
322b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      return PropagationInfo(BinTest.Source,
323b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        BinTest.EOp == EO_And ? EO_Or : EO_And,
324b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        BinTest.LTest.Var, invertConsumedUnconsumed(BinTest.LTest.TestsFor),
325b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        BinTest.RTest.Var, invertConsumedUnconsumed(BinTest.RTest.TestsFor));
326b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else {
327b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      return PropagationInfo();
328b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
329b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
330b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins};
331b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
332b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsclass ConsumedStmtVisitor : public ConstStmtVisitor<ConsumedStmtVisitor> {
333df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
334df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  typedef llvm::DenseMap<const Stmt *, PropagationInfo> MapType;
335df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  typedef std::pair<const Stmt *, PropagationInfo> PairType;
336df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  typedef MapType::iterator InfoEntry;
337b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  typedef MapType::const_iterator ConstInfoEntry;
338b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
3392d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner  AnalysisDeclContext &AC;
340df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  ConsumedAnalyzer &Analyzer;
341df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  ConsumedStateMap *StateMap;
342df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  MapType PropagationMap;
343df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void forwardInfo(const Stmt *From, const Stmt *To);
344b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  void handleTestingFunctionCall(const CallExpr *Call, const VarDecl *Var);
345df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  bool isLikeMoveAssignment(const CXXMethodDecl *MethodDecl);
3460e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins  void propagateReturnType(const Stmt *Call, const FunctionDecl *Fun,
3470e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins                           QualType ReturnType);
348df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
349df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinspublic:
350627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins  void checkCallability(const PropagationInfo &PInfo,
351627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins                        const FunctionDecl *FunDecl,
352627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins                        SourceLocation BlameLoc);
353b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
354df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void Visit(const Stmt *StmtNode);
355df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
356df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitBinaryOperator(const BinaryOperator *BinOp);
357df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitCallExpr(const CallExpr *Call);
358df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitCastExpr(const CastExpr *Cast);
359627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins  void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Temp);
360df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitCXXConstructExpr(const CXXConstructExpr *Call);
361df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitCXXMemberCallExpr(const CXXMemberCallExpr *Call);
362df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Call);
363df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitDeclRefExpr(const DeclRefExpr *DeclRef);
364df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitDeclStmt(const DeclStmt *DelcS);
365df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Temp);
366df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitMemberExpr(const MemberExpr *MExpr);
3674252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins  void VisitParmVarDecl(const ParmVarDecl *Param);
3680e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins  void VisitReturnStmt(const ReturnStmt *Ret);
369df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitUnaryOperator(const UnaryOperator *UOp);
370df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitVarDecl(const VarDecl *Var);
3712d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner
3724252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins  ConsumedStmtVisitor(AnalysisDeclContext &AC, ConsumedAnalyzer &Analyzer,
3734252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins                      ConsumedStateMap *StateMap)
3744252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins      : AC(AC), Analyzer(Analyzer), StateMap(StateMap) {}
375b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
376b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo getInfo(const Stmt *StmtNode) const {
377b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    ConstInfoEntry Entry = PropagationMap.find(StmtNode);
378b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
379b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (Entry != PropagationMap.end())
380b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      return Entry->second;
381b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    else
382b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      return PropagationInfo();
383b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
384b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
385b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  void reset(ConsumedStateMap *NewStateMap) {
386b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    StateMap = NewStateMap;
387df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
388df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins};
389df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
390b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchinsvoid ConsumedStmtVisitor::checkCallability(const PropagationInfo &PInfo,
3915fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins                                           const FunctionDecl *FunDecl,
392627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins                                           SourceLocation BlameLoc) {
3935fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
39466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins  if (!FunDecl->hasAttr<CallableWhenAttr>())
39566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    return;
39666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
39766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins  const CallableWhenAttr *CWAttr = FunDecl->getAttr<CallableWhenAttr>();
3985fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
399b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (PInfo.isVar()) {
400b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins    const VarDecl *Var = PInfo.getVar();
40166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    ConsumedState VarState = StateMap->getState(Var);
4025fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
40366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    assert(VarState != CS_None && "Invalid state");
4045fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
40566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    if (isCallableInState(CWAttr, VarState))
40666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      return;
4075fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
40866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    Analyzer.WarningsHandler.warnUseInInvalidState(
40966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      FunDecl->getNameAsString(), Var->getNameAsString(),
410627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins      stateToString(VarState), BlameLoc);
4115fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
41266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins  } else if (PInfo.isState()) {
41366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
41466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    assert(PInfo.getState() != CS_None && "Invalid state");
41566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
41666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    if (isCallableInState(CWAttr, PInfo.getState()))
41766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      return;
41866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
41966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    Analyzer.WarningsHandler.warnUseOfTempInInvalidState(
420627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins      FunDecl->getNameAsString(), stateToString(PInfo.getState()), BlameLoc);
4215fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins  }
4225fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins}
4235fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
424df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::forwardInfo(const Stmt *From, const Stmt *To) {
425df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  InfoEntry Entry = PropagationMap.find(From);
426df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
427b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (Entry != PropagationMap.end())
428b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    PropagationMap.insert(PairType(To, Entry->second));
429b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins}
430b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
431b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsvoid ConsumedStmtVisitor::handleTestingFunctionCall(const CallExpr *Call,
432b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                                                    const VarDecl  *Var) {
433b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
434b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConsumedState VarState = StateMap->getState(Var);
435b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
436b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (VarState != CS_Unknown) {
437b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    SourceLocation CallLoc = Call->getExprLoc();
438b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
439b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (!CallLoc.isMacroID())
440b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      Analyzer.WarningsHandler.warnUnnecessaryTest(Var->getNameAsString(),
441b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        stateToString(VarState), CallLoc);
442df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
443b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
444b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationMap.insert(PairType(Call, PropagationInfo(Var, CS_Unconsumed)));
445df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
446df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
447df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsbool ConsumedStmtVisitor::isLikeMoveAssignment(
448df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  const CXXMethodDecl *MethodDecl) {
449df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
450df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  return MethodDecl->isMoveAssignmentOperator() ||
451df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins         (MethodDecl->getOverloadedOperator() == OO_Equal &&
452df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins          MethodDecl->getNumParams() == 1 &&
453df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins          MethodDecl->getParamDecl(0)->getType()->isRValueReferenceType());
454df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
455df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
4560e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchinsvoid ConsumedStmtVisitor::propagateReturnType(const Stmt *Call,
4570e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins                                              const FunctionDecl *Fun,
4580e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins                                              QualType ReturnType) {
4590e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins  if (isConsumableType(ReturnType)) {
4600e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins
4610e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    ConsumedState ReturnState;
4620e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins
4630e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    if (Fun->hasAttr<ReturnTypestateAttr>())
4640e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins      ReturnState = mapReturnTypestateAttrState(
4650e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins        Fun->getAttr<ReturnTypestateAttr>());
4660e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    else
467a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie      ReturnState = mapConsumableAttrState(ReturnType);
4680e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins
4690e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    PropagationMap.insert(PairType(Call,
47066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      PropagationInfo(ReturnState, ReturnType)));
4710e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins  }
4720e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins}
4730e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins
474b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsvoid ConsumedStmtVisitor::Visit(const Stmt *StmtNode) {
475b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
476b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConstStmtVisitor<ConsumedStmtVisitor>::Visit(StmtNode);
477b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
478b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  for (Stmt::const_child_iterator CI = StmtNode->child_begin(),
479b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins       CE = StmtNode->child_end(); CI != CE; ++CI) {
480b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
481b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    PropagationMap.erase(*CI);
482b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
483b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins}
484b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
485df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitBinaryOperator(const BinaryOperator *BinOp) {
486df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  switch (BinOp->getOpcode()) {
487b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case BO_LAnd:
488b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case BO_LOr : {
489b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    InfoEntry LEntry = PropagationMap.find(BinOp->getLHS()),
490b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins              REntry = PropagationMap.find(BinOp->getRHS());
491b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
492b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    VarTestResult LTest, RTest;
493b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
494b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (LEntry != PropagationMap.end() && LEntry->second.isTest()) {
495b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      LTest = LEntry->second.getTest();
496b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
497b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else {
498b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      LTest.Var      = NULL;
499b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      LTest.TestsFor = CS_None;
500b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
501b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
502b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (REntry != PropagationMap.end() && REntry->second.isTest()) {
503b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      RTest = REntry->second.getTest();
504b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
505b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else {
506b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      RTest.Var      = NULL;
507b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      RTest.TestsFor = CS_None;
508b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
509b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
510b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (!(LTest.Var == NULL && RTest.Var == NULL))
511b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      PropagationMap.insert(PairType(BinOp, PropagationInfo(BinOp,
512b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        static_cast<EffectiveOp>(BinOp->getOpcode() == BO_LOr), LTest, RTest)));
513b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
514b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    break;
515b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
516b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
517df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  case BO_PtrMemD:
518df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  case BO_PtrMemI:
519df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    forwardInfo(BinOp->getLHS(), BinOp);
520df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    break;
521df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
522df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  default:
523df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    break;
524df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
525df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
526df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
527df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitCallExpr(const CallExpr *Call) {
528df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (const FunctionDecl *FunDecl =
529df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    dyn_cast_or_null<FunctionDecl>(Call->getDirectCallee())) {
530df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
531df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    // Special case for the std::move function.
532df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    // TODO: Make this more specific. (Deferred)
533df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    if (FunDecl->getNameAsString() == "move") {
534df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      InfoEntry Entry = PropagationMap.find(Call->getArg(0));
535df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
536df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      if (Entry != PropagationMap.end()) {
537df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        PropagationMap.insert(PairType(Call, Entry->second));
538df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      }
539df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
540df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      return;
541df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
542df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
543df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    unsigned Offset = Call->getNumArgs() - FunDecl->getNumParams();
544df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
545df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    for (unsigned Index = Offset; Index < Call->getNumArgs(); ++Index) {
546df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      QualType ParamType = FunDecl->getParamDecl(Index - Offset)->getType();
547df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
548df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      InfoEntry Entry = PropagationMap.find(Call->getArg(Index));
549df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
550b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (Entry == PropagationMap.end() || !Entry->second.isVar()) {
551df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        continue;
552df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      }
553df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
554b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins      PropagationInfo PInfo = Entry->second;
555df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
556df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      if (ParamType->isRValueReferenceType() ||
557df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins          (ParamType->isLValueReferenceType() &&
558df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins           !cast<LValueReferenceType>(*ParamType).isSpelledAsLValue())) {
559df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
560b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        StateMap->setState(PInfo.getVar(), consumed::CS_Consumed);
561df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
562df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      } else if (!(ParamType.isConstQualified() ||
563df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins                   ((ParamType->isReferenceType() ||
564df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins                     ParamType->isPointerType()) &&
565df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins                    ParamType->getPointeeType().isConstQualified()))) {
566df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
567b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        StateMap->setState(PInfo.getVar(), consumed::CS_Unknown);
568df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      }
569df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
5700e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins
57166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    QualType RetType = FunDecl->getCallResultType();
57266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    if (RetType->isReferenceType())
57366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      RetType = RetType->getPointeeType();
57466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
57566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    propagateReturnType(Call, FunDecl, RetType);
576df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
577df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
578df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
579df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitCastExpr(const CastExpr *Cast) {
580b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  forwardInfo(Cast->getSubExpr(), Cast);
581df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
582df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
583627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitCXXBindTemporaryExpr(
584627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins  const CXXBindTemporaryExpr *Temp) {
585627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins
586627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins  forwardInfo(Temp->getSubExpr(), Temp);
587627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins}
588627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins
589df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitCXXConstructExpr(const CXXConstructExpr *Call) {
590df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  CXXConstructorDecl *Constructor = Call->getConstructor();
5912d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner
5922d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner  ASTContext &CurrContext = AC.getASTContext();
593df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  QualType ThisType = Constructor->getThisType(CurrContext)->getPointeeType();
594df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
595c55bee6e278d888d7a5d29fc17df6a9ae1e8b7d3DeLesley Hutchins  if (isConsumableType(ThisType)) {
5960e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    if (Constructor->isDefaultConstructor()) {
597df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
598df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      PropagationMap.insert(PairType(Call,
59966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins        PropagationInfo(consumed::CS_Consumed, ThisType)));
600df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
601df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    } else if (Constructor->isMoveConstructor()) {
602df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
603b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins      PropagationInfo PInfo =
604df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        PropagationMap.find(Call->getArg(0))->second;
605df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
606b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (PInfo.isVar()) {
607b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        const VarDecl* Var = PInfo.getVar();
608df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
609df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        PropagationMap.insert(PairType(Call,
61066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins          PropagationInfo(StateMap->getState(Var), ThisType)));
611df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
612df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        StateMap->setState(Var, consumed::CS_Consumed);
613df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
614df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      } else {
615b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        PropagationMap.insert(PairType(Call, PInfo));
616df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      }
617df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
618df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    } else if (Constructor->isCopyConstructor()) {
619df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      MapType::iterator Entry = PropagationMap.find(Call->getArg(0));
620df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
621df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      if (Entry != PropagationMap.end())
622df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        PropagationMap.insert(PairType(Call, Entry->second));
623df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
624df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    } else {
6250e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins      propagateReturnType(Call, Constructor, ThisType);
626df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
627df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
628df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
629df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
630627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins
631df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitCXXMemberCallExpr(
632df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  const CXXMemberCallExpr *Call) {
633df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
634df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  VisitCallExpr(Call);
635df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
636df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  InfoEntry Entry = PropagationMap.find(Call->getCallee()->IgnoreParens());
637df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
638df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (Entry != PropagationMap.end()) {
639b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins    PropagationInfo PInfo = Entry->second;
6405fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins    const CXXMethodDecl *MethodDecl = Call->getMethodDecl();
641df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
642627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins    checkCallability(PInfo, MethodDecl, Call->getExprLoc());
643df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
644b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (PInfo.isVar()) {
645b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (isTestingFunction(MethodDecl))
646b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        handleTestingFunctionCall(Call, PInfo.getVar());
647b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      else if (MethodDecl->hasAttr<ConsumesAttr>())
648b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        StateMap->setState(PInfo.getVar(), consumed::CS_Consumed);
6495fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins    }
650df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
651df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
652df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
653df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitCXXOperatorCallExpr(
654df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  const CXXOperatorCallExpr *Call) {
655df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
656df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  const FunctionDecl *FunDecl =
657df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    dyn_cast_or_null<FunctionDecl>(Call->getDirectCallee());
658df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
659df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (!FunDecl) return;
660df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
661df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (isa<CXXMethodDecl>(FunDecl) &&
662df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      isLikeMoveAssignment(cast<CXXMethodDecl>(FunDecl))) {
663df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
664df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    InfoEntry LEntry = PropagationMap.find(Call->getArg(0));
665df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    InfoEntry REntry = PropagationMap.find(Call->getArg(1));
666df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
667b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins    PropagationInfo LPInfo, RPInfo;
668df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
669df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    if (LEntry != PropagationMap.end() &&
670df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        REntry != PropagationMap.end()) {
671df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
672b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins      LPInfo = LEntry->second;
673b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins      RPInfo = REntry->second;
674df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
675b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (LPInfo.isVar() && RPInfo.isVar()) {
676b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        StateMap->setState(LPInfo.getVar(),
677b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins          StateMap->getState(RPInfo.getVar()));
678df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
679b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        StateMap->setState(RPInfo.getVar(), consumed::CS_Consumed);
680df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
681b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        PropagationMap.insert(PairType(Call, LPInfo));
682df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
683b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      } else if (LPInfo.isVar() && !RPInfo.isVar()) {
684b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        StateMap->setState(LPInfo.getVar(), RPInfo.getState());
685df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
686b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        PropagationMap.insert(PairType(Call, LPInfo));
687df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
688b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      } else if (!LPInfo.isVar() && RPInfo.isVar()) {
689df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        PropagationMap.insert(PairType(Call,
69066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins          PropagationInfo(StateMap->getState(RPInfo.getVar()),
69166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins                          LPInfo.getTempType())));
692df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
693b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        StateMap->setState(RPInfo.getVar(), consumed::CS_Consumed);
694df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
695df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      } else {
696b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        PropagationMap.insert(PairType(Call, RPInfo));
697df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      }
698df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
699df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    } else if (LEntry != PropagationMap.end() &&
700df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins               REntry == PropagationMap.end()) {
701df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
702b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins      LPInfo = LEntry->second;
703df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
704b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (LPInfo.isVar()) {
705b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        StateMap->setState(LPInfo.getVar(), consumed::CS_Unknown);
706df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
707b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins        PropagationMap.insert(PairType(Call, LPInfo));
708df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
70966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      } else if (LPInfo.isState()) {
710df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        PropagationMap.insert(PairType(Call,
71166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins          PropagationInfo(consumed::CS_Unknown, LPInfo.getTempType())));
712df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      }
713df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
714df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    } else if (LEntry == PropagationMap.end() &&
715df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins               REntry != PropagationMap.end()) {
716df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
71766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      if (REntry->second.isVar())
71866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins        StateMap->setState(REntry->second.getVar(), consumed::CS_Consumed);
719df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
720df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
721df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  } else {
722df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
723df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    VisitCallExpr(Call);
724df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
725df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    InfoEntry Entry = PropagationMap.find(Call->getArg(0));
726df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
727df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    if (Entry != PropagationMap.end()) {
728b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins      PropagationInfo PInfo = Entry->second;
729df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
730627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins      checkCallability(PInfo, FunDecl, Call->getExprLoc());
7315fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
732b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (PInfo.isVar()) {
733d324a0bcda2754c6fe0b5e27ad50e42850d498c4DeLesley Hutchins        if (isTestingFunction(FunDecl))
734b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins          handleTestingFunctionCall(Call, PInfo.getVar());
735d324a0bcda2754c6fe0b5e27ad50e42850d498c4DeLesley Hutchins        else if (FunDecl->hasAttr<ConsumesAttr>())
736b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchins          StateMap->setState(PInfo.getVar(), consumed::CS_Consumed);
737df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      }
738df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
739df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
740df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
741df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
742df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitDeclRefExpr(const DeclRefExpr *DeclRef) {
743df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(DeclRef->getDecl()))
744df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    if (StateMap->getState(Var) != consumed::CS_None)
745df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      PropagationMap.insert(PairType(DeclRef, PropagationInfo(Var)));
746df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
747df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
748df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitDeclStmt(const DeclStmt *DeclS) {
749df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  for (DeclStmt::const_decl_iterator DI = DeclS->decl_begin(),
750df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins       DE = DeclS->decl_end(); DI != DE; ++DI) {
751df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
752df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    if (isa<VarDecl>(*DI)) VisitVarDecl(cast<VarDecl>(*DI));
753df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
754df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
755df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (DeclS->isSingleDecl())
756df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(DeclS->getSingleDecl()))
757df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      PropagationMap.insert(PairType(DeclS, PropagationInfo(Var)));
758df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
759df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
760df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitMaterializeTemporaryExpr(
761df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  const MaterializeTemporaryExpr *Temp) {
762df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
763df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  InfoEntry Entry = PropagationMap.find(Temp->GetTemporaryExpr());
764df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
765df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (Entry != PropagationMap.end())
766df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    PropagationMap.insert(PairType(Temp, Entry->second));
767df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
768df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
769df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitMemberExpr(const MemberExpr *MExpr) {
770df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  forwardInfo(MExpr->getBase(), MExpr);
771df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
772df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
7734252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins
7744252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitParmVarDecl(const ParmVarDecl *Param) {
775a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  QualType ParamType = Param->getType();
776a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  ConsumedState ParamState = consumed::CS_None;
777a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie
778a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  if (!(ParamType->isPointerType() || ParamType->isReferenceType()) &&
779a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie      isConsumableType(ParamType))
780a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    ParamState = mapConsumableAttrState(ParamType);
781a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  else if (ParamType->isReferenceType() &&
782a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie           isConsumableType(ParamType->getPointeeType()))
783a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    ParamState = consumed::CS_Unknown;
784a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie
785a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  if (ParamState)
786a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    StateMap->setState(Param, ParamState);
7874252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins}
7884252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins
7890e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitReturnStmt(const ReturnStmt *Ret) {
7900e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins  if (ConsumedState ExpectedState = Analyzer.getExpectedReturnState()) {
7910e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    InfoEntry Entry = PropagationMap.find(Ret->getRetValue());
7920e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins
7930e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    if (Entry != PropagationMap.end()) {
7940e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins      assert(Entry->second.isState() || Entry->second.isVar());
7950e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins
7960e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins      ConsumedState RetState = Entry->second.isState() ?
7970e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins        Entry->second.getState() : StateMap->getState(Entry->second.getVar());
7980e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins
7990e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins      if (RetState != ExpectedState)
8000e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins        Analyzer.WarningsHandler.warnReturnTypestateMismatch(
8010e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins          Ret->getReturnLoc(), stateToString(ExpectedState),
8020e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins          stateToString(RetState));
8030e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    }
8040e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins  }
8050e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins}
8060e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins
807df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitUnaryOperator(const UnaryOperator *UOp) {
808b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  InfoEntry Entry = PropagationMap.find(UOp->getSubExpr()->IgnoreParens());
809b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (Entry == PropagationMap.end()) return;
810b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
811b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  switch (UOp->getOpcode()) {
812b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case UO_AddrOf:
813b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    PropagationMap.insert(PairType(UOp, Entry->second));
814b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    break;
815b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
816b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case UO_LNot:
817b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (Entry->second.isTest() || Entry->second.isBinTest())
818b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      PropagationMap.insert(PairType(UOp, Entry->second.invertTest()));
819b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    break;
820b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
821b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  default:
822b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    break;
823df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
824df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
825df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
82666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins// TODO: See if I need to check for reference types here.
827df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitVarDecl(const VarDecl *Var) {
828c55bee6e278d888d7a5d29fc17df6a9ae1e8b7d3DeLesley Hutchins  if (isConsumableType(Var->getType())) {
8294252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins    if (Var->hasInit()) {
8304252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins      PropagationInfo PInfo =
8314252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins        PropagationMap.find(Var->getInit())->second;
8324252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins
8334252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins      StateMap->setState(Var, PInfo.isVar() ?
8344252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins        StateMap->getState(PInfo.getVar()) : PInfo.getState());
8354252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins
8364252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins    } else {
8374252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins      StateMap->setState(Var, consumed::CS_Unknown);
8384252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins    }
839df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
840df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
841b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins}} // end clang::consumed::ConsumedStmtVisitor
842df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
843b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsnamespace clang {
844b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsnamespace consumed {
845df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
846b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsvoid splitVarStateForIf(const IfStmt * IfNode, const VarTestResult &Test,
847b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                        ConsumedStateMap *ThenStates,
848b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                        ConsumedStateMap *ElseStates) {
849b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
850b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConsumedState VarState = ThenStates->getState(Test.Var);
851df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
852b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (VarState == CS_Unknown) {
853b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    ThenStates->setState(Test.Var, Test.TestsFor);
85466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    ElseStates->setState(Test.Var, invertConsumedUnconsumed(Test.TestsFor));
855df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
856b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  } else if (VarState == invertConsumedUnconsumed(Test.TestsFor)) {
857b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    ThenStates->markUnreachable();
858df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
85966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins  } else if (VarState == Test.TestsFor) {
860b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    ElseStates->markUnreachable();
861df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
862df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
863df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
864b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsvoid splitVarStateForIfBinOp(const PropagationInfo &PInfo,
865b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConsumedStateMap *ThenStates, ConsumedStateMap *ElseStates) {
866df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
867b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const VarTestResult &LTest = PInfo.getLTest(),
868b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                      &RTest = PInfo.getRTest();
869b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
870b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConsumedState LState = LTest.Var ? ThenStates->getState(LTest.Var) : CS_None,
871b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                RState = RTest.Var ? ThenStates->getState(RTest.Var) : CS_None;
872b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
873b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (LTest.Var) {
874b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (PInfo.testEffectiveOp() == EO_And) {
875b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (LState == CS_Unknown) {
876b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ThenStates->setState(LTest.Var, LTest.TestsFor);
877b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
878b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      } else if (LState == invertConsumedUnconsumed(LTest.TestsFor)) {
879b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ThenStates->markUnreachable();
880b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
881b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      } else if (LState == LTest.TestsFor && isKnownState(RState)) {
88266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins        if (RState == RTest.TestsFor)
88366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins          ElseStates->markUnreachable();
88466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins        else
885b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins          ThenStates->markUnreachable();
886b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      }
887b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
888b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else {
88966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      if (LState == CS_Unknown) {
890b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ElseStates->setState(LTest.Var,
891b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                             invertConsumedUnconsumed(LTest.TestsFor));
892b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
89366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      } else if (LState == LTest.TestsFor) {
894b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ElseStates->markUnreachable();
895b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
896b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      } else if (LState == invertConsumedUnconsumed(LTest.TestsFor) &&
897b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                 isKnownState(RState)) {
898b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
89966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins        if (RState == RTest.TestsFor)
90066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins          ElseStates->markUnreachable();
90166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins        else
902b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins          ThenStates->markUnreachable();
903b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      }
904b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
905df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
906df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
907b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (RTest.Var) {
908b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (PInfo.testEffectiveOp() == EO_And) {
909b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (RState == CS_Unknown)
910b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ThenStates->setState(RTest.Var, RTest.TestsFor);
911b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      else if (RState == invertConsumedUnconsumed(RTest.TestsFor))
912b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ThenStates->markUnreachable();
913b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
91466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    } else {
915b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (RState == CS_Unknown)
916b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ElseStates->setState(RTest.Var,
917b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                             invertConsumedUnconsumed(RTest.TestsFor));
918b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      else if (RState == RTest.TestsFor)
919b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ElseStates->markUnreachable();
920b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
921b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
922df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
923df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
9247385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchinsbool ConsumedBlockInfo::allBackEdgesVisited(const CFGBlock *CurrBlock,
9257385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins                                            const CFGBlock *TargetBlock) {
9267385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
9277385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  assert(CurrBlock && "Block pointer must not be NULL");
9287385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  assert(TargetBlock && "TargetBlock pointer must not be NULL");
9297385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
9307385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  unsigned int CurrBlockOrder = VisitOrder[CurrBlock->getBlockID()];
9317385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  for (CFGBlock::const_pred_iterator PI = TargetBlock->pred_begin(),
9327385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins       PE = TargetBlock->pred_end(); PI != PE; ++PI) {
9337385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    if (*PI && CurrBlockOrder < VisitOrder[(*PI)->getBlockID()] )
9347385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins      return false;
9357385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  }
9367385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  return true;
9377385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins}
9387385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
939df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedBlockInfo::addInfo(const CFGBlock *Block,
940df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins                                ConsumedStateMap *StateMap,
941df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins                                bool &AlreadyOwned) {
942df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
9437385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  assert(Block && "Block pointer must not be NULL");
944df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
945df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  ConsumedStateMap *Entry = StateMapsArray[Block->getBlockID()];
946df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
947df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (Entry) {
948df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    Entry->intersect(StateMap);
949df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
950df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  } else if (AlreadyOwned) {
951df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    StateMapsArray[Block->getBlockID()] = new ConsumedStateMap(*StateMap);
952df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
953df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  } else {
954df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    StateMapsArray[Block->getBlockID()] = StateMap;
955df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    AlreadyOwned = true;
956df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
957df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
958df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
959df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedBlockInfo::addInfo(const CFGBlock *Block,
960df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins                                ConsumedStateMap *StateMap) {
961df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
9627385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  assert(Block != NULL && "Block pointer must not be NULL");
963df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
964df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  ConsumedStateMap *Entry = StateMapsArray[Block->getBlockID()];
965df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
966df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (Entry) {
967df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    Entry->intersect(StateMap);
968df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    delete StateMap;
969df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
970df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  } else {
971df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    StateMapsArray[Block->getBlockID()] = StateMap;
972df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
973df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
974df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
9757385840b600d0e4a96d75042f612f6430e4a0390DeLesley HutchinsConsumedStateMap* ConsumedBlockInfo::borrowInfo(const CFGBlock *Block) {
9767385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  assert(Block && "Block pointer must not be NULL");
9777385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  assert(StateMapsArray[Block->getBlockID()] && "Block has no block info");
9787385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
979df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  return StateMapsArray[Block->getBlockID()];
980df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
981df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
9827385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchinsvoid ConsumedBlockInfo::discardInfo(const CFGBlock *Block) {
9837385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  unsigned int BlockID = Block->getBlockID();
9847385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  delete StateMapsArray[BlockID];
9857385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  StateMapsArray[BlockID] = NULL;
9867385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins}
9877385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
9887385840b600d0e4a96d75042f612f6430e4a0390DeLesley HutchinsConsumedStateMap* ConsumedBlockInfo::getInfo(const CFGBlock *Block) {
9897385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  assert(Block && "Block pointer must not be NULL");
9907385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
9917385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  ConsumedStateMap *StateMap = StateMapsArray[Block->getBlockID()];
9927385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  if (isBackEdgeTarget(Block)) {
9937385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    return new ConsumedStateMap(*StateMap);
9947385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  } else {
9957385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    StateMapsArray[Block->getBlockID()] = NULL;
9967385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    return StateMap;
9977385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  }
9987385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins}
9997385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
10007385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchinsbool ConsumedBlockInfo::isBackEdge(const CFGBlock *From, const CFGBlock *To) {
10017385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  assert(From && "From block must not be NULL");
10027385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  assert(To   && "From block must not be NULL");
10037385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
10047385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  return VisitOrder[From->getBlockID()] > VisitOrder[To->getBlockID()];
10057385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins}
10067385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
10077385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchinsbool ConsumedBlockInfo::isBackEdgeTarget(const CFGBlock *Block) {
10087385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  assert(Block != NULL && "Block pointer must not be NULL");
10097385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
10107385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  // Anything with less than two predecessors can't be the target of a back
10117385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  // edge.
10127385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  if (Block->pred_size() < 2)
10137385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    return false;
10147385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
10157385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  unsigned int BlockVisitOrder = VisitOrder[Block->getBlockID()];
10167385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  for (CFGBlock::const_pred_iterator PI = Block->pred_begin(),
10177385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins       PE = Block->pred_end(); PI != PE; ++PI) {
10187385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    if (*PI && BlockVisitOrder < VisitOrder[(*PI)->getBlockID()])
10197385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins      return true;
10207385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  }
10217385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  return false;
1022df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
1023df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
10247385840b600d0e4a96d75042f612f6430e4a0390DeLesley HutchinsConsumedState ConsumedStateMap::getState(const VarDecl *Var) const {
1025df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  MapType::const_iterator Entry = Map.find(Var);
1026df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1027df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (Entry != Map.end()) {
1028df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    return Entry->second;
1029df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1030df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  } else {
1031df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    return CS_None;
1032df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
1033df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
1034df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1035df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStateMap::intersect(const ConsumedStateMap *Other) {
1036df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  ConsumedState LocalState;
1037df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1038b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (this->From && this->From == Other->From && !Other->Reachable) {
1039b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    this->markUnreachable();
1040b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return;
1041b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
1042b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
10437385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  for (MapType::const_iterator DMI = Other->Map.begin(), DME = Other->Map.end();
10447385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins       DMI != DME; ++DMI) {
1045df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1046df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    LocalState = this->getState(DMI->first);
1047df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1048b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (LocalState == CS_None)
1049b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      continue;
1050b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1051b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (LocalState != DMI->second)
1052b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins       Map[DMI->first] = CS_Unknown;
1053df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
1054df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
1055df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
10567385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchinsvoid ConsumedStateMap::intersectAtLoopHead(const CFGBlock *LoopHead,
10577385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  const CFGBlock *LoopBack, const ConsumedStateMap *LoopBackStates,
10587385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  ConsumedWarningsHandlerBase &WarningsHandler) {
10597385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
10607385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  ConsumedState LocalState;
1061627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins  SourceLocation BlameLoc = getLastStmtLoc(LoopBack);
10627385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
10637385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  for (MapType::const_iterator DMI = LoopBackStates->Map.begin(),
10647385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins       DME = LoopBackStates->Map.end(); DMI != DME; ++DMI) {
10657385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
10667385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    LocalState = this->getState(DMI->first);
10677385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
10687385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    if (LocalState == CS_None)
10697385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins      continue;
10707385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
10717385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    if (LocalState != DMI->second) {
10727385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins      Map[DMI->first] = CS_Unknown;
10737385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins      WarningsHandler.warnLoopStateMismatch(
10747385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins        BlameLoc, DMI->first->getNameAsString());
10757385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    }
10767385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  }
10777385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins}
10787385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
1079b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsvoid ConsumedStateMap::markUnreachable() {
1080b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  this->Reachable = false;
1081b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  Map.clear();
1082b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins}
1083b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1084df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStateMap::setState(const VarDecl *Var, ConsumedState State) {
1085df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  Map[Var] = State;
1086df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
1087df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
10885fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchinsvoid ConsumedStateMap::remove(const VarDecl *Var) {
10895fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins  Map.erase(Var);
10905fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins}
1091df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
10927385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchinsbool ConsumedStateMap::operator!=(const ConsumedStateMap *Other) const {
10937385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  for (MapType::const_iterator DMI = Other->Map.begin(), DME = Other->Map.end();
10947385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins       DMI != DME; ++DMI) {
10957385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
10967385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    if (this->getState(DMI->first) != DMI->second)
10977385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins      return true;
10987385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  }
10997385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
11007385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  return false;
11017385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins}
11027385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
1103a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikievoid ConsumedAnalyzer::determineExpectedReturnState(AnalysisDeclContext &AC,
1104a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie                                                    const FunctionDecl *D) {
1105a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  QualType ReturnType;
1106a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  if (const CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
1107a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    ASTContext &CurrContext = AC.getASTContext();
1108a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    ReturnType = Constructor->getThisType(CurrContext)->getPointeeType();
1109a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  } else
1110a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    ReturnType = D->getCallResultType();
1111a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie
1112a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  if (D->hasAttr<ReturnTypestateAttr>()) {
1113a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    const ReturnTypestateAttr *RTSAttr = D->getAttr<ReturnTypestateAttr>();
1114a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie
1115a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
1116a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    if (!RD || !RD->hasAttr<ConsumableAttr>()) {
1117a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie      // FIXME: This should be removed when template instantiation propagates
1118a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie      //        attributes at template specialization definition, not
1119a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie      //        declaration. When it is removed the test needs to be enabled
1120a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie      //        in SemaDeclAttr.cpp.
1121a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie      WarningsHandler.warnReturnTypestateForUnconsumableType(
1122a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie          RTSAttr->getLocation(), ReturnType.getAsString());
1123a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie      ExpectedReturnState = CS_None;
1124a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    } else
1125a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie      ExpectedReturnState = mapReturnTypestateAttrState(RTSAttr);
1126a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  } else if (isConsumableType(ReturnType))
1127a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    ExpectedReturnState = mapConsumableAttrState(ReturnType);
1128a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  else
1129a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    ExpectedReturnState = CS_None;
1130a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie}
1131a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie
1132b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsbool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,
1133b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                                  const ConsumedStmtVisitor &Visitor) {
1134df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1135b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConsumedStateMap *FalseStates = new ConsumedStateMap(*CurrStates);
1136b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo PInfo;
1137df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1138b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (const IfStmt *IfNode =
1139b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    dyn_cast_or_null<IfStmt>(CurrBlock->getTerminator().getStmt())) {
1140df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1141b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    const Stmt *Cond = IfNode->getCond();
1142b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1143b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    PInfo = Visitor.getInfo(Cond);
1144b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (!PInfo.isValid() && isa<BinaryOperator>(Cond))
1145b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      PInfo = Visitor.getInfo(cast<BinaryOperator>(Cond)->getRHS());
1146df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1147b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (PInfo.isTest()) {
1148b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      CurrStates->setSource(Cond);
1149b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      FalseStates->setSource(Cond);
115066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      splitVarStateForIf(IfNode, PInfo.getTest(), CurrStates, FalseStates);
1151b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1152b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else if (PInfo.isBinTest()) {
1153b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      CurrStates->setSource(PInfo.testSourceNode());
1154b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      FalseStates->setSource(PInfo.testSourceNode());
115566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      splitVarStateForIfBinOp(PInfo, CurrStates, FalseStates);
1156df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1157df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    } else {
1158b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      delete FalseStates;
1159b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      return false;
1160df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
1161df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1162b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  } else if (const BinaryOperator *BinOp =
1163b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    dyn_cast_or_null<BinaryOperator>(CurrBlock->getTerminator().getStmt())) {
1164b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1165b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    PInfo = Visitor.getInfo(BinOp->getLHS());
1166b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (!PInfo.isTest()) {
1167b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if ((BinOp = dyn_cast_or_null<BinaryOperator>(BinOp->getLHS()))) {
1168b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        PInfo = Visitor.getInfo(BinOp->getRHS());
1169b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1170b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        if (!PInfo.isTest()) {
1171b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins          delete FalseStates;
1172b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins          return false;
1173b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        }
1174b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1175b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      } else {
1176b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        delete FalseStates;
1177b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        return false;
1178b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      }
1179b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
1180b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1181b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    CurrStates->setSource(BinOp);
1182b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    FalseStates->setSource(BinOp);
1183b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1184b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    const VarTestResult &Test = PInfo.getTest();
1185b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    ConsumedState VarState = CurrStates->getState(Test.Var);
1186b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1187b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (BinOp->getOpcode() == BO_LAnd) {
1188b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (VarState == CS_Unknown)
1189b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        CurrStates->setState(Test.Var, Test.TestsFor);
1190b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      else if (VarState == invertConsumedUnconsumed(Test.TestsFor))
1191b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        CurrStates->markUnreachable();
1192b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1193b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else if (BinOp->getOpcode() == BO_LOr) {
1194b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (VarState == CS_Unknown)
1195b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        FalseStates->setState(Test.Var,
1196b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                              invertConsumedUnconsumed(Test.TestsFor));
1197b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      else if (VarState == Test.TestsFor)
1198b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        FalseStates->markUnreachable();
1199b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
1200b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1201b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  } else {
1202b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    delete FalseStates;
1203b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return false;
1204b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
1205b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1206df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin();
1207df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1208b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (*SI)
1209b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BlockInfo.addInfo(*SI, CurrStates);
1210b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  else
1211b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    delete CurrStates;
1212b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1213b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (*++SI)
1214b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BlockInfo.addInfo(*SI, FalseStates);
1215b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  else
1216b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    delete FalseStates;
1217b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1218b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  CurrStates = NULL;
1219b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  return true;
1220df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
1221df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1222df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
1223df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  const FunctionDecl *D = dyn_cast_or_null<FunctionDecl>(AC.getDecl());
122457b781dde2676cd1bd838a1cdd56d3aeea091d11DeLesley Hutchins  if (!D)
122557b781dde2676cd1bd838a1cdd56d3aeea091d11DeLesley Hutchins    return;
1226df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
122757b781dde2676cd1bd838a1cdd56d3aeea091d11DeLesley Hutchins  CFG *CFGraph = AC.getCFG();
122857b781dde2676cd1bd838a1cdd56d3aeea091d11DeLesley Hutchins  if (!CFGraph)
122957b781dde2676cd1bd838a1cdd56d3aeea091d11DeLesley Hutchins    return;
1230df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1231a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  determineExpectedReturnState(AC, D);
12327385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
1233df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  PostOrderCFGView *SortedGraph = AC.getAnalysis<PostOrderCFGView>();
12347385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  // AC.getCFG()->viewCFG(LangOptions());
12357385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
12367385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  BlockInfo = ConsumedBlockInfo(CFGraph->getNumBlockIDs(), SortedGraph);
1237df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1238df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  CurrStates = new ConsumedStateMap();
12394252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins  ConsumedStmtVisitor Visitor(AC, *this, CurrStates);
12404252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins
12414252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins  // Add all trackable parameters to the state map.
12424252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins  for (FunctionDecl::param_const_iterator PI = D->param_begin(),
12434252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins       PE = D->param_end(); PI != PE; ++PI) {
12444252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins    Visitor.VisitParmVarDecl(*PI);
12454252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins  }
1246df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1247df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  // Visit all of the function's basic blocks.
1248df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  for (PostOrderCFGView::iterator I = SortedGraph->begin(),
1249df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins       E = SortedGraph->end(); I != E; ++I) {
1250df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1251df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    const CFGBlock *CurrBlock = *I;
1252df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1253df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    if (CurrStates == NULL)
1254df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      CurrStates = BlockInfo.getInfo(CurrBlock);
1255b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1256b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (!CurrStates) {
1257b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      continue;
1258b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1259b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else if (!CurrStates->isReachable()) {
1260b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      delete CurrStates;
1261b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      CurrStates = NULL;
1262b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      continue;
1263b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
1264b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1265b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    Visitor.reset(CurrStates);
1266b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1267df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    // Visit all of the basic block's statements.
1268df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    for (CFGBlock::const_iterator BI = CurrBlock->begin(),
1269df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins         BE = CurrBlock->end(); BI != BE; ++BI) {
1270df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
12715fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      switch (BI->getKind()) {
12725fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      case CFGElement::Statement:
1273df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins        Visitor.Visit(BI->castAs<CFGStmt>().getStmt());
12745fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins        break;
1275627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins
1276627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins      case CFGElement::TemporaryDtor: {
1277627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins        const CFGTemporaryDtor DTor = BI->castAs<CFGTemporaryDtor>();
1278627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins        const CXXBindTemporaryExpr *BTE = DTor.getBindTemporaryExpr();
1279627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins        PropagationInfo PInfo = Visitor.getInfo(BTE);
1280627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins
1281627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins        if (PInfo.isValid())
1282627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins          Visitor.checkCallability(PInfo,
1283627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins                                   DTor.getDestructorDecl(AC.getASTContext()),
1284627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins                                   BTE->getExprLoc());
1285627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins        break;
1286627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins      }
1287627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins
1288627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins      case CFGElement::AutomaticObjectDtor: {
1289627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins        const CFGAutomaticObjDtor DTor = BI->castAs<CFGAutomaticObjDtor>();
1290627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins
1291627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins        const VarDecl *Var = DTor.getVarDecl();
1292627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins        ConsumedState VarState = CurrStates->getState(Var);
1293627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins
1294627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins        if (VarState != CS_None) {
1295627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins          PropagationInfo PInfo(Var);
1296627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins
1297627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins          Visitor.checkCallability(PInfo,
1298627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins                                   DTor.getDestructorDecl(AC.getASTContext()),
1299627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins                                   getLastStmtLoc(CurrBlock));
1300627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins
1301627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins          CurrStates->remove(Var);
1302627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins        }
1303627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins        break;
1304627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins      }
1305627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins
13065fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      default:
13075fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins        break;
13085fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      }
1309df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
1310df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1311b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    // TODO: Handle other forms of branching with precision, including while-
1312b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    //       and for-loops. (Deferred)
1313b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (!splitState(CurrBlock, Visitor)) {
1314b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      CurrStates->setSource(NULL);
1315df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
13167385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins      if (CurrBlock->succ_size() > 1 ||
13177385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins          (CurrBlock->succ_size() == 1 &&
13187385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins           (*CurrBlock->succ_begin())->pred_size() > 1)) {
1319df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1320b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        bool OwnershipTaken = false;
1321b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1322b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
1323b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins             SE = CurrBlock->succ_end(); SI != SE; ++SI) {
1324b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
13257385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins          if (*SI == NULL) continue;
13267385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
13277385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins          if (BlockInfo.isBackEdge(CurrBlock, *SI)) {
13287385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins            BlockInfo.borrowInfo(*SI)->intersectAtLoopHead(*SI, CurrBlock,
13297385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins                                                           CurrStates,
13307385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins                                                           WarningsHandler);
13317385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
13327385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins            if (BlockInfo.allBackEdgesVisited(*SI, CurrBlock))
13337385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins              BlockInfo.discardInfo(*SI);
13347385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins          } else {
13357385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins            BlockInfo.addInfo(*SI, CurrStates, OwnershipTaken);
13367385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins          }
1337b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        }
1338b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1339b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        if (!OwnershipTaken)
1340b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins          delete CurrStates;
1341b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1342b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        CurrStates = NULL;
1343df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      }
1344df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
1345df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  } // End of block iterator.
1346df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1347df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  // Delete the last existing state map.
1348df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  delete CurrStates;
1349df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1350df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  WarningsHandler.emitDiagnostics();
1351df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
1352df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}} // end namespace clang::consumed
1353