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/StmtCXX.h"
21651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/AST/StmtVisitor.h"
22df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/AST/Type.h"
23651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/Analysis/Analyses/Consumed.h"
24df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/Analysis/Analyses/PostOrderCFGView.h"
25df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/Analysis/AnalysisContext.h"
26df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/Analysis/CFG.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"
33651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include <memory>
34df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
354c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins// TODO: Adjust states of args to constructors in the same way that arguments to
364c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins//       function calls are handled.
374c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins// TODO: Use information from tests in for- and while-loop conditional.
380e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins// TODO: Add notes about the actual and expected state for
39b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins// TODO: Correctly identify unreachable blocks when chaining boolean operators.
4066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins// TODO: Adjust the parser and AttributesList class to support lists of
4166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins//       identifiers.
42b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins// TODO: Warn about unreachable code.
43b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins// TODO: Switch to using a bitmap to track unreachable blocks.
44b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins// TODO: Handle variable definitions, e.g. bool valid = x.isValid();
45b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins//       if (valid) ...; (Deferred)
46df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// TODO: Take notes on state transitions to provide better warning messages.
47df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//       (Deferred)
48df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// TODO: Test nested conditionals: A) Checking the same value multiple times,
49df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//       and 2) Checking different values. (Deferred)
50df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
51df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsusing namespace clang;
52df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsusing namespace consumed;
53df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
54df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// Key method definition
55df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley HutchinsConsumedWarningsHandlerBase::~ConsumedWarningsHandlerBase() {}
56df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
5752f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchinsstatic SourceLocation getFirstStmtLoc(const CFGBlock *Block) {
5852f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins  // Find the source location of the first statement in the block, if the block
5952f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins  // is not empty.
606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto &B : *Block)
616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (Optional<CFGStmt> CS = B.getAs<CFGStmt>())
6252f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins      return CS->getStmt()->getLocStart();
6352f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins
6452f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins  // Block is empty.
6552f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins  // If we have one successor, return the first statement in that block
6652f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins  if (Block->succ_size() == 1 && *Block->succ_begin())
6752f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins    return getFirstStmtLoc(*Block->succ_begin());
6852f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins
6952f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins  return SourceLocation();
7052f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins}
7152f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins
72627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchinsstatic SourceLocation getLastStmtLoc(const CFGBlock *Block) {
737385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  // Find the source location of the last statement in the block, if the block
747385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  // is not empty.
75627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins  if (const Stmt *StmtNode = Block->getTerminator()) {
767385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    return StmtNode->getLocStart();
777385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  } else {
78627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins    for (CFGBlock::const_reverse_iterator BI = Block->rbegin(),
79627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins         BE = Block->rend(); BI != BE; ++BI) {
807385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins      if (Optional<CFGStmt> CS = BI->getAs<CFGStmt>())
817385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins        return CS->getStmt()->getLocStart();
827385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    }
837385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  }
8452f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins
8552f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins  // If we have one successor, return the first statement in that block
8652f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins  SourceLocation Loc;
8752f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins  if (Block->succ_size() == 1 && *Block->succ_begin())
8852f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins    Loc = getFirstStmtLoc(*Block->succ_begin());
8952f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins  if (Loc.isValid())
9052f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins    return Loc;
91cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins
9252f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins  // If we have one predecessor, return the last statement in that block
9352f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins  if (Block->pred_size() == 1 && *Block->pred_begin())
9452f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins    return getLastStmtLoc(*Block->pred_begin());
9552f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins
9652f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins  return Loc;
977385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins}
987385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
99b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsstatic ConsumedState invertConsumedUnconsumed(ConsumedState State) {
100b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  switch (State) {
101b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_Unconsumed:
102b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return CS_Consumed;
103b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_Consumed:
104b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return CS_Unconsumed;
105b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_None:
106b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return CS_None;
107b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_Unknown:
108b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return CS_Unknown;
109b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
110b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  llvm_unreachable("invalid enum");
111b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins}
112b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
11366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchinsstatic bool isCallableInState(const CallableWhenAttr *CWAttr,
11466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins                              ConsumedState State) {
11566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
1166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto &S : CWAttr->callableStates()) {
11766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    ConsumedState MappedAttrState = CS_None;
1186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    switch (S) {
12066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    case CallableWhenAttr::Unknown:
12166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      MappedAttrState = CS_Unknown;
12266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      break;
12366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
12466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    case CallableWhenAttr::Unconsumed:
12566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      MappedAttrState = CS_Unconsumed;
12666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      break;
12766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
12866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    case CallableWhenAttr::Consumed:
12966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      MappedAttrState = CS_Consumed;
13066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      break;
13166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    }
13266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
13366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    if (MappedAttrState == State)
13466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      return true;
13566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins  }
13666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
13766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins  return false;
13866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins}
13966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
140651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
141c55bee6e278d888d7a5d29fc17df6a9ae1e8b7d3DeLesley Hutchinsstatic bool isConsumableType(const QualType &QT) {
1421aa89697dc73760dce700e99d78c5805aa8bd7bbChris Wailes  if (QT->isPointerType() || QT->isReferenceType())
1431aa89697dc73760dce700e99d78c5805aa8bd7bbChris Wailes    return false;
1441aa89697dc73760dce700e99d78c5805aa8bd7bbChris Wailes
145c55bee6e278d888d7a5d29fc17df6a9ae1e8b7d3DeLesley Hutchins  if (const CXXRecordDecl *RD = QT->getAsCXXRecordDecl())
146c55bee6e278d888d7a5d29fc17df6a9ae1e8b7d3DeLesley Hutchins    return RD->hasAttr<ConsumableAttr>();
1471aa89697dc73760dce700e99d78c5805aa8bd7bbChris Wailes
1481aa89697dc73760dce700e99d78c5805aa8bd7bbChris Wailes  return false;
149c55bee6e278d888d7a5d29fc17df6a9ae1e8b7d3DeLesley Hutchins}
150c55bee6e278d888d7a5d29fc17df6a9ae1e8b7d3DeLesley Hutchins
151651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool isAutoCastType(const QualType &QT) {
152651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (QT->isPointerType() || QT->isReferenceType())
153651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return false;
154651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
155651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (const CXXRecordDecl *RD = QT->getAsCXXRecordDecl())
156651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return RD->hasAttr<ConsumableAutoCastAttr>();
157651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
158651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return false;
159651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
160651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
161651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool isSetOnReadPtrType(const QualType &QT) {
162651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (const CXXRecordDecl *RD = QT->getPointeeCXXRecordDecl())
163651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return RD->hasAttr<ConsumableSetOnReadAttr>();
164651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return false;
165651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
166651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
167651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
168b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsstatic bool isKnownState(ConsumedState State) {
169b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  switch (State) {
170b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_Unconsumed:
171b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_Consumed:
172b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return true;
173b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_None:
174b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case CS_Unknown:
175b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return false;
176b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
1776b2ec037f16753547398efe1812160982f1d14e4Aaron Ballman  llvm_unreachable("invalid enum");
178b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins}
179b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
180651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool isRValueRef(QualType ParamType) {
181651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return ParamType->isRValueReferenceType();
182be63ab6612b250972ae528ae910e5fa64f9c5731DeLesley Hutchins}
183be63ab6612b250972ae528ae910e5fa64f9c5731DeLesley Hutchins
1845fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchinsstatic bool isTestingFunction(const FunctionDecl *FunDecl) {
1850e429f1f48298b749cd0b0d6e931ed15c2a7a2b1Chris Wailes  return FunDecl->hasAttr<TestTypestateAttr>();
1865fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins}
1875fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
188651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool isPointerOrRef(QualType ParamType) {
189651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return ParamType->isPointerType() || ParamType->isReferenceType();
190be63ab6612b250972ae528ae910e5fa64f9c5731DeLesley Hutchins}
191be63ab6612b250972ae528ae910e5fa64f9c5731DeLesley Hutchins
192a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikiestatic ConsumedState mapConsumableAttrState(const QualType QT) {
193a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  assert(isConsumableType(QT));
194a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie
195a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  const ConsumableAttr *CAttr =
196a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie      QT->getAsCXXRecordDecl()->getAttr<ConsumableAttr>();
197a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie
198a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  switch (CAttr->getDefaultState()) {
199a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  case ConsumableAttr::Unknown:
200a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    return CS_Unknown;
201a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  case ConsumableAttr::Unconsumed:
202a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    return CS_Unconsumed;
203a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  case ConsumableAttr::Consumed:
204a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    return CS_Consumed;
205a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  }
206a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  llvm_unreachable("invalid enum");
207a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie}
208a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie
209d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchinsstatic ConsumedState
210d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley HutchinsmapParamTypestateAttrState(const ParamTypestateAttr *PTAttr) {
211d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins  switch (PTAttr->getParamState()) {
212d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins  case ParamTypestateAttr::Unknown:
213f30e194f9d797ebeb2f6c3f96e88160ed1a6519aDeLesley Hutchins    return CS_Unknown;
214d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins  case ParamTypestateAttr::Unconsumed:
215f30e194f9d797ebeb2f6c3f96e88160ed1a6519aDeLesley Hutchins    return CS_Unconsumed;
216d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins  case ParamTypestateAttr::Consumed:
217f30e194f9d797ebeb2f6c3f96e88160ed1a6519aDeLesley Hutchins    return CS_Consumed;
218f30e194f9d797ebeb2f6c3f96e88160ed1a6519aDeLesley Hutchins  }
219f30e194f9d797ebeb2f6c3f96e88160ed1a6519aDeLesley Hutchins  llvm_unreachable("invalid_enum");
220f30e194f9d797ebeb2f6c3f96e88160ed1a6519aDeLesley Hutchins}
221f30e194f9d797ebeb2f6c3f96e88160ed1a6519aDeLesley Hutchins
222e988dc45254405aff0950337d82aa8623fb1b88eEric Christopherstatic ConsumedState
223e988dc45254405aff0950337d82aa8623fb1b88eEric ChristophermapReturnTypestateAttrState(const ReturnTypestateAttr *RTSAttr) {
2240e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins  switch (RTSAttr->getState()) {
2250e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins  case ReturnTypestateAttr::Unknown:
2260e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    return CS_Unknown;
2270e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins  case ReturnTypestateAttr::Unconsumed:
2280e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    return CS_Unconsumed;
2290e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins  case ReturnTypestateAttr::Consumed:
2300e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    return CS_Consumed;
2310e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins  }
232e988dc45254405aff0950337d82aa8623fb1b88eEric Christopher  llvm_unreachable("invalid enum");
2330e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins}
2340e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins
235d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchinsstatic ConsumedState mapSetTypestateAttrState(const SetTypestateAttr *STAttr) {
236d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins  switch (STAttr->getNewState()) {
237d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins  case SetTypestateAttr::Unknown:
238d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins    return CS_Unknown;
239d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins  case SetTypestateAttr::Unconsumed:
240d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins    return CS_Unconsumed;
241d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins  case SetTypestateAttr::Consumed:
242d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins    return CS_Consumed;
243d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins  }
244d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins  llvm_unreachable("invalid_enum");
245d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins}
246d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins
247df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsstatic StringRef stateToString(ConsumedState State) {
248df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  switch (State) {
249df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  case consumed::CS_None:
250df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    return "none";
251df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
252df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  case consumed::CS_Unknown:
253df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    return "unknown";
254df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
255df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  case consumed::CS_Unconsumed:
256df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    return "unconsumed";
257df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
258df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  case consumed::CS_Consumed:
259df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    return "consumed";
260df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
261a72f7206a71b3901d1b4b2b4718a5013f46010f2Reid Kleckner  llvm_unreachable("invalid enum");
262df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
263df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
2641bf6343612e394051fffc587e6899de6901065e0DeLesley Hutchinsstatic ConsumedState testsFor(const FunctionDecl *FunDecl) {
2651bf6343612e394051fffc587e6899de6901065e0DeLesley Hutchins  assert(isTestingFunction(FunDecl));
2660e429f1f48298b749cd0b0d6e931ed15c2a7a2b1Chris Wailes  switch (FunDecl->getAttr<TestTypestateAttr>()->getTestState()) {
2670e429f1f48298b749cd0b0d6e931ed15c2a7a2b1Chris Wailes  case TestTypestateAttr::Unconsumed:
2681bf6343612e394051fffc587e6899de6901065e0DeLesley Hutchins    return CS_Unconsumed;
2690e429f1f48298b749cd0b0d6e931ed15c2a7a2b1Chris Wailes  case TestTypestateAttr::Consumed:
2701bf6343612e394051fffc587e6899de6901065e0DeLesley Hutchins    return CS_Consumed;
2711bf6343612e394051fffc587e6899de6901065e0DeLesley Hutchins  }
2721bf6343612e394051fffc587e6899de6901065e0DeLesley Hutchins  llvm_unreachable("invalid enum");
2731bf6343612e394051fffc587e6899de6901065e0DeLesley Hutchins}
2741bf6343612e394051fffc587e6899de6901065e0DeLesley Hutchins
275df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsnamespace {
276b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsstruct VarTestResult {
277b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const VarDecl *Var;
278b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConsumedState TestsFor;
279b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins};
280b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins} // end anonymous::VarTestResult
281b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
282b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsnamespace clang {
283b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsnamespace consumed {
284b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
285b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsenum EffectiveOp {
286b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  EO_And,
287b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  EO_Or
288b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins};
289b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
290b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsclass PropagationInfo {
291b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  enum {
292b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    IT_None,
293b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    IT_State,
2944c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    IT_VarTest,
295b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    IT_BinTest,
2964c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    IT_Var,
2974c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    IT_Tmp
298b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  } InfoType;
299e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher
300e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher  struct BinTestTy {
301e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher    const BinaryOperator *Source;
302e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher    EffectiveOp EOp;
303e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher    VarTestResult LTest;
304e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher    VarTestResult RTest;
305e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher  };
306df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
307b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  union {
308df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    ConsumedState State;
3094c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    VarTestResult VarTest;
310df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    const VarDecl *Var;
3114c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    const CXXBindTemporaryExpr *Tmp;
312e444ea0f5c8c8cf677edd05d9fb1254422765bd5Eric Christopher    BinTestTy BinTest;
313df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  };
314df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
315b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinspublic:
316b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo() : InfoType(IT_None) {}
317df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
3184c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  PropagationInfo(const VarTestResult &VarTest)
3194c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    : InfoType(IT_VarTest), VarTest(VarTest) {}
3204c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins
321b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo(const VarDecl *Var, ConsumedState TestsFor)
3224c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    : InfoType(IT_VarTest) {
323df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
3244c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    VarTest.Var      = Var;
3254c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    VarTest.TestsFor = TestsFor;
326b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
327b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
328b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp,
329b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                  const VarTestResult &LTest, const VarTestResult &RTest)
330b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    : InfoType(IT_BinTest) {
331df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
332b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.Source  = Source;
333b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.EOp     = EOp;
334b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.LTest   = LTest;
335b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.RTest   = RTest;
336b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
337b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
338b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp,
339b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                  const VarDecl *LVar, ConsumedState LTestsFor,
340b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                  const VarDecl *RVar, ConsumedState RTestsFor)
341b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    : InfoType(IT_BinTest) {
342df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
343b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.Source         = Source;
344b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.EOp            = EOp;
345b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.LTest.Var      = LVar;
346b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.LTest.TestsFor = LTestsFor;
347b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.RTest.Var      = RVar;
348b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BinTest.RTest.TestsFor = RTestsFor;
349b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
350b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
3514c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  PropagationInfo(ConsumedState State)
3524c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    : InfoType(IT_State), State(State) {}
35366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins
354b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo(const VarDecl *Var) : InfoType(IT_Var), Var(Var) {}
3554c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  PropagationInfo(const CXXBindTemporaryExpr *Tmp)
3564c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    : InfoType(IT_Tmp), Tmp(Tmp) {}
357b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
358b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const ConsumedState & getState() const {
359b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_State);
360b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return State;
361b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
362b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
3634c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  const VarTestResult & getVarTest() const {
3644c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    assert(InfoType == IT_VarTest);
3654c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    return VarTest;
366b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
367b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
368b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const VarTestResult & getLTest() const {
369b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_BinTest);
370b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return BinTest.LTest;
371b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
372b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
373b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const VarTestResult & getRTest() const {
374b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_BinTest);
375b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return BinTest.RTest;
376b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
377b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
378b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const VarDecl * getVar() const {
379b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_Var);
380b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return Var;
381b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
382b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
3834c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  const CXXBindTemporaryExpr * getTmp() const {
3844c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    assert(InfoType == IT_Tmp);
3854c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    return Tmp;
3864c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  }
3874c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins
3884c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  ConsumedState getAsState(const ConsumedStateMap *StateMap) const {
3894c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    assert(isVar() || isTmp() || isState());
3904c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins
3914c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    if (isVar())
3924c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins      return StateMap->getState(Var);
3934c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    else if (isTmp())
3944c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins      return StateMap->getState(Tmp);
3954c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    else if (isState())
3964c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins      return State;
3974c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    else
3984c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins      return CS_None;
3994c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  }
4004c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins
401b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  EffectiveOp testEffectiveOp() const {
402b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_BinTest);
403b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return BinTest.EOp;
404b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
405b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
406b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const BinaryOperator * testSourceNode() const {
407b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    assert(InfoType == IT_BinTest);
408b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return BinTest.Source;
409b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
410b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
4114c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  inline bool isValid()   const { return InfoType != IT_None;    }
4124c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  inline bool isState()   const { return InfoType == IT_State;   }
4134c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  inline bool isVarTest() const { return InfoType == IT_VarTest; }
4144c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  inline bool isBinTest() const { return InfoType == IT_BinTest; }
4154c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  inline bool isVar()     const { return InfoType == IT_Var;     }
4164c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  inline bool isTmp()     const { return InfoType == IT_Tmp;     }
4174c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins
4184c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  bool isTest() const {
4194c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    return InfoType == IT_VarTest || InfoType == IT_BinTest;
4204c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  }
4214c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins
4224c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  bool isPointerToValue() const {
4234c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    return InfoType == IT_Var || InfoType == IT_Tmp;
4244c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  }
425b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
426b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo invertTest() const {
4274c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    assert(InfoType == IT_VarTest || InfoType == IT_BinTest);
428df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
4294c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    if (InfoType == IT_VarTest) {
4304c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins      return PropagationInfo(VarTest.Var,
4314c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins                             invertConsumedUnconsumed(VarTest.TestsFor));
432df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
433b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else if (InfoType == IT_BinTest) {
434b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      return PropagationInfo(BinTest.Source,
435b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        BinTest.EOp == EO_And ? EO_Or : EO_And,
436b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        BinTest.LTest.Var, invertConsumedUnconsumed(BinTest.LTest.TestsFor),
437b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        BinTest.RTest.Var, invertConsumedUnconsumed(BinTest.RTest.TestsFor));
438b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else {
439b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      return PropagationInfo();
440b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
441b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
442b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins};
443b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
4444c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchinsstatic inline void
4454c3e0bc7850df76824138ecfcc434388e7f69559DeLesley HutchinssetStateForVarOrTmp(ConsumedStateMap *StateMap, const PropagationInfo &PInfo,
4464c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins                    ConsumedState State) {
4474c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins
4484c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  assert(PInfo.isVar() || PInfo.isTmp());
4494c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins
4504c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  if (PInfo.isVar())
4514c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    StateMap->setState(PInfo.getVar(), State);
4524c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  else
4534c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    StateMap->setState(PInfo.getTmp(), State);
4544c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins}
4554c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins
456b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsclass ConsumedStmtVisitor : public ConstStmtVisitor<ConsumedStmtVisitor> {
457df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
458df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  typedef llvm::DenseMap<const Stmt *, PropagationInfo> MapType;
459df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  typedef std::pair<const Stmt *, PropagationInfo> PairType;
460df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  typedef MapType::iterator InfoEntry;
461b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  typedef MapType::const_iterator ConstInfoEntry;
462b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
4632d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner  AnalysisDeclContext &AC;
464df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  ConsumedAnalyzer &Analyzer;
465df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  ConsumedStateMap *StateMap;
466df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  MapType PropagationMap;
467651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
468651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  InfoEntry findInfo(const Expr *E) {
469651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return PropagationMap.find(E->IgnoreParens());
470651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
471651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  ConstInfoEntry findInfo(const Expr *E) const {
472651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return PropagationMap.find(E->IgnoreParens());
473651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
474651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void insertInfo(const Expr *E, const PropagationInfo &PI) {
475651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    PropagationMap.insert(PairType(E->IgnoreParens(), PI));
476651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
477651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
478651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void forwardInfo(const Expr *From, const Expr *To);
479651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void copyInfo(const Expr *From, const Expr *To, ConsumedState CS);
480651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  ConsumedState getInfo(const Expr *From);
481651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void setInfo(const Expr *To, ConsumedState NS);
482651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void propagateReturnType(const Expr *Call, const FunctionDecl *Fun);
48313be03222faa22b1a1088ea5c1a00014934b9ee4DeLesley Hutchins
484df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinspublic:
485627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins  void checkCallability(const PropagationInfo &PInfo,
486627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins                        const FunctionDecl *FunDecl,
487627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins                        SourceLocation BlameLoc);
488651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool handleCall(const CallExpr *Call, const Expr *ObjArg,
489651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                  const FunctionDecl *FunD);
490df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
491df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitBinaryOperator(const BinaryOperator *BinOp);
492df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitCallExpr(const CallExpr *Call);
493df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitCastExpr(const CastExpr *Cast);
494627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins  void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Temp);
495df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitCXXConstructExpr(const CXXConstructExpr *Call);
496df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitCXXMemberCallExpr(const CXXMemberCallExpr *Call);
497df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Call);
498df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitDeclRefExpr(const DeclRefExpr *DeclRef);
499df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitDeclStmt(const DeclStmt *DelcS);
500df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Temp);
501df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitMemberExpr(const MemberExpr *MExpr);
5024252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins  void VisitParmVarDecl(const ParmVarDecl *Param);
5030e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins  void VisitReturnStmt(const ReturnStmt *Ret);
504df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitUnaryOperator(const UnaryOperator *UOp);
505df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  void VisitVarDecl(const VarDecl *Var);
5062d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner
5074252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins  ConsumedStmtVisitor(AnalysisDeclContext &AC, ConsumedAnalyzer &Analyzer,
5084252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins                      ConsumedStateMap *StateMap)
5094252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins      : AC(AC), Analyzer(Analyzer), StateMap(StateMap) {}
510b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
511651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  PropagationInfo getInfo(const Expr *StmtNode) const {
512651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ConstInfoEntry Entry = findInfo(StmtNode);
513b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
514b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (Entry != PropagationMap.end())
515b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      return Entry->second;
516b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    else
517b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      return PropagationInfo();
518b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
519b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
520b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  void reset(ConsumedStateMap *NewStateMap) {
521b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    StateMap = NewStateMap;
522df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
523df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins};
524df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
525651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
526651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid ConsumedStmtVisitor::forwardInfo(const Expr *From, const Expr *To) {
527651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  InfoEntry Entry = findInfo(From);
528651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (Entry != PropagationMap.end())
529651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    insertInfo(To, Entry->second);
530651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
531651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
532651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
533651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// Create a new state for To, which is initialized to the state of From.
534651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// If NS is not CS_None, sets the state of From to NS.
535651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid ConsumedStmtVisitor::copyInfo(const Expr *From, const Expr *To,
536651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                   ConsumedState NS) {
537651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  InfoEntry Entry = findInfo(From);
538651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (Entry != PropagationMap.end()) {
539651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    PropagationInfo& PInfo = Entry->second;
540651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ConsumedState CS = PInfo.getAsState(StateMap);
541651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (CS != CS_None)
542651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      insertInfo(To, PropagationInfo(CS));
543651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (NS != CS_None && PInfo.isPointerToValue())
544651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      setStateForVarOrTmp(StateMap, PInfo, NS);
545651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
546651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
547651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
548651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
549651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// Get the ConsumedState for From
550651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesConsumedState ConsumedStmtVisitor::getInfo(const Expr *From) {
551651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  InfoEntry Entry = findInfo(From);
552651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (Entry != PropagationMap.end()) {
553651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    PropagationInfo& PInfo = Entry->second;
554651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return PInfo.getAsState(StateMap);
555651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
556651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return CS_None;
557651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
558651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
559651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
560651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// If we already have info for To then update it, otherwise create a new entry.
561651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid ConsumedStmtVisitor::setInfo(const Expr *To, ConsumedState NS) {
562651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  InfoEntry Entry = findInfo(To);
563651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (Entry != PropagationMap.end()) {
564651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    PropagationInfo& PInfo = Entry->second;
565651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (PInfo.isPointerToValue())
566651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      setStateForVarOrTmp(StateMap, PInfo, NS);
567651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  } else if (NS != CS_None) {
568651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines     insertInfo(To, PropagationInfo(NS));
569651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
570651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
571651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
572651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
573651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
574b01e2da54178f1b1b6ef43bf3fa91dcdd3ff3094DeLesley Hutchinsvoid ConsumedStmtVisitor::checkCallability(const PropagationInfo &PInfo,
5755fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins                                           const FunctionDecl *FunDecl,
576627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins                                           SourceLocation BlameLoc) {
5774c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  assert(!PInfo.isTest());
578651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
57966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins  const CallableWhenAttr *CWAttr = FunDecl->getAttr<CallableWhenAttr>();
580651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (!CWAttr)
581651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return;
582651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
583b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (PInfo.isVar()) {
5844c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    ConsumedState VarState = StateMap->getState(PInfo.getVar());
585651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
5864c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    if (VarState == CS_None || isCallableInState(CWAttr, VarState))
58766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      return;
588651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
58966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    Analyzer.WarningsHandler.warnUseInInvalidState(
5904c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins      FunDecl->getNameAsString(), PInfo.getVar()->getNameAsString(),
591627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins      stateToString(VarState), BlameLoc);
592651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
5934c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  } else {
5944c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    ConsumedState TmpState = PInfo.getAsState(StateMap);
595651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
5964c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    if (TmpState == CS_None || isCallableInState(CWAttr, TmpState))
59766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      return;
598651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
59966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    Analyzer.WarningsHandler.warnUseOfTempInInvalidState(
6004c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins      FunDecl->getNameAsString(), stateToString(TmpState), BlameLoc);
6015fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins  }
6025fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins}
6035fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins
604b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
605651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// Factors out common behavior for function, method, and operator calls.
606651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// Check parameters and set parameter state if necessary.
607651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// Returns true if the state of ObjArg is set, or false otherwise.
608651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesbool ConsumedStmtVisitor::handleCall(const CallExpr *Call, const Expr *ObjArg,
609651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                     const FunctionDecl *FunD) {
610651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  unsigned Offset = 0;
611651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (isa<CXXOperatorCallExpr>(Call) && isa<CXXMethodDecl>(FunD))
612651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Offset = 1;  // first argument is 'this'
613651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
614651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // check explicit parameters
615651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (unsigned Index = Offset; Index < Call->getNumArgs(); ++Index) {
616651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // Skip variable argument lists.
617651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (Index - Offset >= FunD->getNumParams())
618651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      break;
619651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
620651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const ParmVarDecl *Param = FunD->getParamDecl(Index - Offset);
621651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    QualType ParamType = Param->getType();
622651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
623651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    InfoEntry Entry = findInfo(Call->getArg(Index));
624651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
625651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (Entry == PropagationMap.end() || Entry->second.isTest())
626651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      continue;
627651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    PropagationInfo PInfo = Entry->second;
628651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
629651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // Check that the parameter is in the correct state.
630651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (ParamTypestateAttr *PTA = Param->getAttr<ParamTypestateAttr>()) {
631651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      ConsumedState ParamState = PInfo.getAsState(StateMap);
632651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      ConsumedState ExpectedState = mapParamTypestateAttrState(PTA);
633651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
634651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (ParamState != ExpectedState)
635651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        Analyzer.WarningsHandler.warnParamTypestateMismatch(
636651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          Call->getArg(Index)->getExprLoc(),
637651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          stateToString(ExpectedState), stateToString(ParamState));
638651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
639651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
640651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!(Entry->second.isVar() || Entry->second.isTmp()))
641651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      continue;
642651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
643651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // Adjust state on the caller side.
644651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (isRValueRef(ParamType))
645651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      setStateForVarOrTmp(StateMap, PInfo, consumed::CS_Consumed);
646651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    else if (ReturnTypestateAttr *RT = Param->getAttr<ReturnTypestateAttr>())
647651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      setStateForVarOrTmp(StateMap, PInfo, mapReturnTypestateAttrState(RT));
648651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    else if (isPointerOrRef(ParamType) &&
649651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines             (!ParamType->getPointeeType().isConstQualified() ||
650651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines              isSetOnReadPtrType(ParamType)))
651651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      setStateForVarOrTmp(StateMap, PInfo, consumed::CS_Unknown);
652651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
653651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
654651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (!ObjArg)
655651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return false;
656651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
657651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // check implicit 'self' parameter, if present
658651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  InfoEntry Entry = findInfo(ObjArg);
659651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (Entry != PropagationMap.end()) {
660651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    PropagationInfo PInfo = Entry->second;
661651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    checkCallability(PInfo, FunD, Call->getExprLoc());
662651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
663651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (SetTypestateAttr *STA = FunD->getAttr<SetTypestateAttr>()) {
664651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (PInfo.isVar()) {
665651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        StateMap->setState(PInfo.getVar(), mapSetTypestateAttrState(STA));
666651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        return true;
667651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      }
668651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      else if (PInfo.isTmp()) {
669651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        StateMap->setState(PInfo.getTmp(), mapSetTypestateAttrState(STA));
670651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        return true;
671651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      }
672651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
673651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    else if (isTestingFunction(FunD) && PInfo.isVar()) {
674651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      PropagationMap.insert(PairType(Call,
675651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        PropagationInfo(PInfo.getVar(), testsFor(FunD))));
676651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
677651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
678651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return false;
679df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
680df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
681651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
682651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid ConsumedStmtVisitor::propagateReturnType(const Expr *Call,
683651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                              const FunctionDecl *Fun) {
684651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  QualType RetType = Fun->getCallResultType();
685651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (RetType->isReferenceType())
686651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    RetType = RetType->getPointeeType();
687651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
688651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (isConsumableType(RetType)) {
6890e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    ConsumedState ReturnState;
690651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (ReturnTypestateAttr *RTA = Fun->getAttr<ReturnTypestateAttr>())
691651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      ReturnState = mapReturnTypestateAttrState(RTA);
6920e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    else
693651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      ReturnState = mapConsumableAttrState(RetType);
6940e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins
6954c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    PropagationMap.insert(PairType(Call, PropagationInfo(ReturnState)));
696b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
697b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins}
698b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
699651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
700df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitBinaryOperator(const BinaryOperator *BinOp) {
701df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  switch (BinOp->getOpcode()) {
702b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case BO_LAnd:
703b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case BO_LOr : {
704651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    InfoEntry LEntry = findInfo(BinOp->getLHS()),
705651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines              REntry = findInfo(BinOp->getRHS());
706b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
707b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    VarTestResult LTest, RTest;
708b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
7094c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    if (LEntry != PropagationMap.end() && LEntry->second.isVarTest()) {
7104c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins      LTest = LEntry->second.getVarTest();
711b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
712b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else {
7136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      LTest.Var      = nullptr;
714b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      LTest.TestsFor = CS_None;
715b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
716b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
7174c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    if (REntry != PropagationMap.end() && REntry->second.isVarTest()) {
7184c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins      RTest = REntry->second.getVarTest();
719b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
720b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else {
7216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      RTest.Var      = nullptr;
722b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      RTest.TestsFor = CS_None;
723b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
7246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
7256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (!(LTest.Var == nullptr && RTest.Var == nullptr))
726b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      PropagationMap.insert(PairType(BinOp, PropagationInfo(BinOp,
727b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        static_cast<EffectiveOp>(BinOp->getOpcode() == BO_LOr), LTest, RTest)));
728b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
729b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    break;
730b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
731b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
732df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  case BO_PtrMemD:
733df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  case BO_PtrMemI:
734df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    forwardInfo(BinOp->getLHS(), BinOp);
735df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    break;
736df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
737df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  default:
738df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    break;
739df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
740df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
741df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
742df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitCallExpr(const CallExpr *Call) {
743651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const FunctionDecl *FunDecl = Call->getDirectCallee();
744651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (!FunDecl)
745651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return;
746651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
747651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Special case for the std::move function.
748651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // TODO: Make this more specific. (Deferred)
7496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (Call->getNumArgs() == 1 && FunDecl->getNameAsString() == "move" &&
7506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      FunDecl->isInStdNamespace()) {
751651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    copyInfo(Call->getArg(0), Call, CS_Consumed);
752651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return;
753df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
754651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
7556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  handleCall(Call, nullptr, FunDecl);
756651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  propagateReturnType(Call, FunDecl);
757df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
758df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
759df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitCastExpr(const CastExpr *Cast) {
760b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  forwardInfo(Cast->getSubExpr(), Cast);
761df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
762df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
763627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitCXXBindTemporaryExpr(
764627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins  const CXXBindTemporaryExpr *Temp) {
765627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins
766651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  InfoEntry Entry = findInfo(Temp->getSubExpr());
7674c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins
7684c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  if (Entry != PropagationMap.end() && !Entry->second.isTest()) {
7694c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    StateMap->setState(Temp, Entry->second.getAsState(StateMap));
7704c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    PropagationMap.insert(PairType(Temp, PropagationInfo(Temp)));
7714c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  }
772627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins}
773627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins
774df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitCXXConstructExpr(const CXXConstructExpr *Call) {
775df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  CXXConstructorDecl *Constructor = Call->getConstructor();
7762d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner
7772d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner  ASTContext &CurrContext = AC.getASTContext();
778df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  QualType ThisType = Constructor->getThisType(CurrContext)->getPointeeType();
779df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
780c5cdafcdb8eea9625e86b015ba7a2504f18a99b7DeLesley Hutchins  if (!isConsumableType(ThisType))
781c5cdafcdb8eea9625e86b015ba7a2504f18a99b7DeLesley Hutchins    return;
782c5cdafcdb8eea9625e86b015ba7a2504f18a99b7DeLesley Hutchins
783c5cdafcdb8eea9625e86b015ba7a2504f18a99b7DeLesley Hutchins  // FIXME: What should happen if someone annotates the move constructor?
784651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (ReturnTypestateAttr *RTA = Constructor->getAttr<ReturnTypestateAttr>()) {
785651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // TODO: Adjust state of args appropriately.
786651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ConsumedState RetState = mapReturnTypestateAttrState(RTA);
7874c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    PropagationMap.insert(PairType(Call, PropagationInfo(RetState)));
788c5cdafcdb8eea9625e86b015ba7a2504f18a99b7DeLesley Hutchins  } else if (Constructor->isDefaultConstructor()) {
789c5cdafcdb8eea9625e86b015ba7a2504f18a99b7DeLesley Hutchins    PropagationMap.insert(PairType(Call,
7904c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins      PropagationInfo(consumed::CS_Consumed)));
791c5cdafcdb8eea9625e86b015ba7a2504f18a99b7DeLesley Hutchins  } else if (Constructor->isMoveConstructor()) {
792651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    copyInfo(Call->getArg(0), Call, CS_Consumed);
793c5cdafcdb8eea9625e86b015ba7a2504f18a99b7DeLesley Hutchins  } else if (Constructor->isCopyConstructor()) {
794651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // Copy state from arg.  If setStateOnRead then set arg to CS_Unknown.
795651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ConsumedState NS =
796651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      isSetOnReadPtrType(Constructor->getThisType(CurrContext)) ?
797651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      CS_Unknown : CS_None;
798651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    copyInfo(Call->getArg(0), Call, NS);
799c5cdafcdb8eea9625e86b015ba7a2504f18a99b7DeLesley Hutchins  } else {
8004c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    // TODO: Adjust state of args appropriately.
801c5cdafcdb8eea9625e86b015ba7a2504f18a99b7DeLesley Hutchins    ConsumedState RetState = mapConsumableAttrState(ThisType);
8024c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    PropagationMap.insert(PairType(Call, PropagationInfo(RetState)));
803df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
804df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
805df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
806651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
807df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitCXXMemberCallExpr(
808651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXMemberCallExpr *Call) {
809651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CXXMethodDecl* MD = Call->getMethodDecl();
810651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (!MD)
811651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return;
812651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
813651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  handleCall(Call, Call->getImplicitObjectArgument(), MD);
814651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  propagateReturnType(Call, MD);
815df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
816df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
817651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
818df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitCXXOperatorCallExpr(
819651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CXXOperatorCallExpr *Call) {
820651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
821df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  const FunctionDecl *FunDecl =
822df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    dyn_cast_or_null<FunctionDecl>(Call->getDirectCallee());
823df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (!FunDecl) return;
824651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
825651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (Call->getOperator() == OO_Equal) {
826651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ConsumedState CS = getInfo(Call->getArg(1));
827651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!handleCall(Call, Call->getArg(0), FunDecl))
828651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      setInfo(Call->getArg(0), CS);
829651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return;
830df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
831651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
832651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (const CXXMemberCallExpr *MCall = dyn_cast<CXXMemberCallExpr>(Call))
833651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    handleCall(MCall, MCall->getImplicitObjectArgument(), FunDecl);
834651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  else
835651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    handleCall(Call, Call->getArg(0), FunDecl);
836651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
837651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  propagateReturnType(Call, FunDecl);
838df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
839df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
840df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitDeclRefExpr(const DeclRefExpr *DeclRef) {
841df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(DeclRef->getDecl()))
842df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    if (StateMap->getState(Var) != consumed::CS_None)
843df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      PropagationMap.insert(PairType(DeclRef, PropagationInfo(Var)));
844df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
845df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
846df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitDeclStmt(const DeclStmt *DeclS) {
847651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto *DI : DeclS->decls())
848651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (isa<VarDecl>(DI))
849651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      VisitVarDecl(cast<VarDecl>(DI));
850df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
851df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (DeclS->isSingleDecl())
852df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(DeclS->getSingleDecl()))
853df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      PropagationMap.insert(PairType(DeclS, PropagationInfo(Var)));
854df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
855df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
856df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitMaterializeTemporaryExpr(
857df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  const MaterializeTemporaryExpr *Temp) {
858df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
859de2204b56096e2336d19b1feae8b1be99dfb49faChris Wailes  forwardInfo(Temp->GetTemporaryExpr(), Temp);
860df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
861df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
862df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitMemberExpr(const MemberExpr *MExpr) {
863df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  forwardInfo(MExpr->getBase(), MExpr);
864df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
865df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
8664252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins
8674252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitParmVarDecl(const ParmVarDecl *Param) {
868a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  QualType ParamType = Param->getType();
869a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  ConsumedState ParamState = consumed::CS_None;
870d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins
871651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (const ParamTypestateAttr *PTA = Param->getAttr<ParamTypestateAttr>())
872651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ParamState = mapParamTypestateAttrState(PTA);
873651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  else if (isConsumableType(ParamType))
874651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ParamState = mapConsumableAttrState(ParamType);
875651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  else if (isRValueRef(ParamType) &&
876651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines           isConsumableType(ParamType->getPointeeType()))
877651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ParamState = mapConsumableAttrState(ParamType->getPointeeType());
878651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  else if (ParamType->isReferenceType() &&
879651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines           isConsumableType(ParamType->getPointeeType()))
880a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    ParamState = consumed::CS_Unknown;
881d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins
882d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins  if (ParamState != CS_None)
883a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    StateMap->setState(Param, ParamState);
8844252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins}
8854252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins
8860e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitReturnStmt(const ReturnStmt *Ret) {
887cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins  ConsumedState ExpectedState = Analyzer.getExpectedReturnState();
888cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins
889cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins  if (ExpectedState != CS_None) {
890651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    InfoEntry Entry = findInfo(Ret->getRetValue());
8910e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins
8920e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    if (Entry != PropagationMap.end()) {
8934c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins      ConsumedState RetState = Entry->second.getAsState(StateMap);
8940e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins
8950e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins      if (RetState != ExpectedState)
8960e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins        Analyzer.WarningsHandler.warnReturnTypestateMismatch(
8970e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins          Ret->getReturnLoc(), stateToString(ExpectedState),
8980e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins          stateToString(RetState));
8990e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins    }
9000e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins  }
901cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins
902cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins  StateMap->checkParamsForReturnTypestate(Ret->getLocStart(),
903cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins                                          Analyzer.WarningsHandler);
9040e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins}
9050e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins
906df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitUnaryOperator(const UnaryOperator *UOp) {
907651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  InfoEntry Entry = findInfo(UOp->getSubExpr());
908b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (Entry == PropagationMap.end()) return;
909b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
910b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  switch (UOp->getOpcode()) {
911b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case UO_AddrOf:
912b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    PropagationMap.insert(PairType(UOp, Entry->second));
913b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    break;
914b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
915b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  case UO_LNot:
9164c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    if (Entry->second.isTest())
917b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      PropagationMap.insert(PairType(UOp, Entry->second.invertTest()));
918b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    break;
919b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
920b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  default:
921b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    break;
922df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
923df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
924df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
92566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins// TODO: See if I need to check for reference types here.
926df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStmtVisitor::VisitVarDecl(const VarDecl *Var) {
927c55bee6e278d888d7a5d29fc17df6a9ae1e8b7d3DeLesley Hutchins  if (isConsumableType(Var->getType())) {
9284252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins    if (Var->hasInit()) {
929651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      MapType::iterator VIT = findInfo(Var->getInit()->IgnoreImplicit());
93013be03222faa22b1a1088ea5c1a00014934b9ee4DeLesley Hutchins      if (VIT != PropagationMap.end()) {
93113be03222faa22b1a1088ea5c1a00014934b9ee4DeLesley Hutchins        PropagationInfo PInfo = VIT->second;
9324c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins        ConsumedState St = PInfo.getAsState(StateMap);
9334c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins
93413be03222faa22b1a1088ea5c1a00014934b9ee4DeLesley Hutchins        if (St != consumed::CS_None) {
93513be03222faa22b1a1088ea5c1a00014934b9ee4DeLesley Hutchins          StateMap->setState(Var, St);
93613be03222faa22b1a1088ea5c1a00014934b9ee4DeLesley Hutchins          return;
93713be03222faa22b1a1088ea5c1a00014934b9ee4DeLesley Hutchins        }
93813be03222faa22b1a1088ea5c1a00014934b9ee4DeLesley Hutchins      }
9394252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins    }
94013be03222faa22b1a1088ea5c1a00014934b9ee4DeLesley Hutchins    // Otherwise
94113be03222faa22b1a1088ea5c1a00014934b9ee4DeLesley Hutchins    StateMap->setState(Var, consumed::CS_Unknown);
942df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
943df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
944b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins}} // end clang::consumed::ConsumedStmtVisitor
945df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
946b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsnamespace clang {
947b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsnamespace consumed {
948df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
949b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsvoid splitVarStateForIf(const IfStmt * IfNode, const VarTestResult &Test,
950b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                        ConsumedStateMap *ThenStates,
951b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                        ConsumedStateMap *ElseStates) {
952b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
953b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConsumedState VarState = ThenStates->getState(Test.Var);
954df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
955b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (VarState == CS_Unknown) {
956b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    ThenStates->setState(Test.Var, Test.TestsFor);
95766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    ElseStates->setState(Test.Var, invertConsumedUnconsumed(Test.TestsFor));
958df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
959b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  } else if (VarState == invertConsumedUnconsumed(Test.TestsFor)) {
960b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    ThenStates->markUnreachable();
961df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
96266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins  } else if (VarState == Test.TestsFor) {
963b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    ElseStates->markUnreachable();
964df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
965df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
966df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
967b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsvoid splitVarStateForIfBinOp(const PropagationInfo &PInfo,
968b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConsumedStateMap *ThenStates, ConsumedStateMap *ElseStates) {
969df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
970b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  const VarTestResult &LTest = PInfo.getLTest(),
971b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                      &RTest = PInfo.getRTest();
972b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
973b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  ConsumedState LState = LTest.Var ? ThenStates->getState(LTest.Var) : CS_None,
974b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                RState = RTest.Var ? ThenStates->getState(RTest.Var) : CS_None;
975b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
976b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (LTest.Var) {
977b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (PInfo.testEffectiveOp() == EO_And) {
978b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (LState == CS_Unknown) {
979b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ThenStates->setState(LTest.Var, LTest.TestsFor);
980b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
981b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      } else if (LState == invertConsumedUnconsumed(LTest.TestsFor)) {
982b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ThenStates->markUnreachable();
983b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
984b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      } else if (LState == LTest.TestsFor && isKnownState(RState)) {
98566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins        if (RState == RTest.TestsFor)
98666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins          ElseStates->markUnreachable();
98766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins        else
988b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins          ThenStates->markUnreachable();
989b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      }
990b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
991b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else {
99266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      if (LState == CS_Unknown) {
993b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ElseStates->setState(LTest.Var,
994b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                             invertConsumedUnconsumed(LTest.TestsFor));
995b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
99666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins      } else if (LState == LTest.TestsFor) {
997b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ElseStates->markUnreachable();
998b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
999b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      } else if (LState == invertConsumedUnconsumed(LTest.TestsFor) &&
1000b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                 isKnownState(RState)) {
1001b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
100266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins        if (RState == RTest.TestsFor)
100366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins          ElseStates->markUnreachable();
100466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins        else
1005b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins          ThenStates->markUnreachable();
1006b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      }
1007b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
1008df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
1009df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1010b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (RTest.Var) {
1011b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (PInfo.testEffectiveOp() == EO_And) {
1012b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (RState == CS_Unknown)
1013b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ThenStates->setState(RTest.Var, RTest.TestsFor);
1014b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      else if (RState == invertConsumedUnconsumed(RTest.TestsFor))
1015b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ThenStates->markUnreachable();
1016b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
101766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins    } else {
1018b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (RState == CS_Unknown)
1019b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ElseStates->setState(RTest.Var,
1020b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                             invertConsumedUnconsumed(RTest.TestsFor));
1021b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      else if (RState == RTest.TestsFor)
1022b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        ElseStates->markUnreachable();
1023b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
1024b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
1025df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
1026df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
10277385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchinsbool ConsumedBlockInfo::allBackEdgesVisited(const CFGBlock *CurrBlock,
10287385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins                                            const CFGBlock *TargetBlock) {
10297385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
10307385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  assert(CurrBlock && "Block pointer must not be NULL");
10317385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  assert(TargetBlock && "TargetBlock pointer must not be NULL");
10327385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
10337385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  unsigned int CurrBlockOrder = VisitOrder[CurrBlock->getBlockID()];
10347385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  for (CFGBlock::const_pred_iterator PI = TargetBlock->pred_begin(),
10357385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins       PE = TargetBlock->pred_end(); PI != PE; ++PI) {
10367385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    if (*PI && CurrBlockOrder < VisitOrder[(*PI)->getBlockID()] )
10377385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins      return false;
10387385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  }
10397385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  return true;
10407385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins}
10417385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
1042df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedBlockInfo::addInfo(const CFGBlock *Block,
1043df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins                                ConsumedStateMap *StateMap,
1044df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins                                bool &AlreadyOwned) {
1045df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
10467385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  assert(Block && "Block pointer must not be NULL");
1047df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1048df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  ConsumedStateMap *Entry = StateMapsArray[Block->getBlockID()];
1049df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1050df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (Entry) {
1051df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    Entry->intersect(StateMap);
1052df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1053df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  } else if (AlreadyOwned) {
1054df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    StateMapsArray[Block->getBlockID()] = new ConsumedStateMap(*StateMap);
1055df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1056df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  } else {
1057df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    StateMapsArray[Block->getBlockID()] = StateMap;
1058df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    AlreadyOwned = true;
1059df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
1060df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
1061df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1062df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedBlockInfo::addInfo(const CFGBlock *Block,
1063df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins                                ConsumedStateMap *StateMap) {
10646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
10656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  assert(Block && "Block pointer must not be NULL");
10666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1067df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  ConsumedStateMap *Entry = StateMapsArray[Block->getBlockID()];
1068df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1069df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  if (Entry) {
1070df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    Entry->intersect(StateMap);
1071df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    delete StateMap;
1072df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1073df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  } else {
1074df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    StateMapsArray[Block->getBlockID()] = StateMap;
1075df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
1076df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
1077df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
10787385840b600d0e4a96d75042f612f6430e4a0390DeLesley HutchinsConsumedStateMap* ConsumedBlockInfo::borrowInfo(const CFGBlock *Block) {
10797385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  assert(Block && "Block pointer must not be NULL");
10807385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  assert(StateMapsArray[Block->getBlockID()] && "Block has no block info");
10817385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
1082df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  return StateMapsArray[Block->getBlockID()];
1083df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
1084df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
10857385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchinsvoid ConsumedBlockInfo::discardInfo(const CFGBlock *Block) {
10867385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  unsigned int BlockID = Block->getBlockID();
10877385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  delete StateMapsArray[BlockID];
10886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  StateMapsArray[BlockID] = nullptr;
10897385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins}
10907385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
10917385840b600d0e4a96d75042f612f6430e4a0390DeLesley HutchinsConsumedStateMap* ConsumedBlockInfo::getInfo(const CFGBlock *Block) {
10927385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  assert(Block && "Block pointer must not be NULL");
10937385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
10947385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  ConsumedStateMap *StateMap = StateMapsArray[Block->getBlockID()];
10957385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  if (isBackEdgeTarget(Block)) {
10967385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    return new ConsumedStateMap(*StateMap);
10977385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  } else {
10986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    StateMapsArray[Block->getBlockID()] = nullptr;
10997385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    return StateMap;
11007385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  }
11017385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins}
11027385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
11037385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchinsbool ConsumedBlockInfo::isBackEdge(const CFGBlock *From, const CFGBlock *To) {
11047385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  assert(From && "From block must not be NULL");
11057385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  assert(To   && "From block must not be NULL");
11067385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
11077385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  return VisitOrder[From->getBlockID()] > VisitOrder[To->getBlockID()];
11087385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins}
11097385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
11107385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchinsbool ConsumedBlockInfo::isBackEdgeTarget(const CFGBlock *Block) {
11116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  assert(Block && "Block pointer must not be NULL");
11126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
11137385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  // Anything with less than two predecessors can't be the target of a back
11147385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  // edge.
11157385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  if (Block->pred_size() < 2)
11167385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    return false;
11177385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
11187385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  unsigned int BlockVisitOrder = VisitOrder[Block->getBlockID()];
11197385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  for (CFGBlock::const_pred_iterator PI = Block->pred_begin(),
11207385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins       PE = Block->pred_end(); PI != PE; ++PI) {
11217385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    if (*PI && BlockVisitOrder < VisitOrder[(*PI)->getBlockID()])
11227385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins      return true;
11237385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  }
11247385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  return false;
1125df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
1126df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1127cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchinsvoid ConsumedStateMap::checkParamsForReturnTypestate(SourceLocation BlameLoc,
1128cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins  ConsumedWarningsHandlerBase &WarningsHandler) const {
1129cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins
11306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto &DM : VarMap) {
11316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (isa<ParmVarDecl>(DM.first)) {
11326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      const ParmVarDecl *Param = cast<ParmVarDecl>(DM.first);
1133651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      const ReturnTypestateAttr *RTA = Param->getAttr<ReturnTypestateAttr>();
1134cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins
1135651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (!RTA)
1136651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        continue;
1137cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins
1138651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      ConsumedState ExpectedState = mapReturnTypestateAttrState(RTA);
11396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      if (DM.second != ExpectedState)
1140cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins        WarningsHandler.warnParamReturnTypestateMismatch(BlameLoc,
1141cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins          Param->getNameAsString(), stateToString(ExpectedState),
11426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          stateToString(DM.second));
1143cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    }
1144cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins  }
1145cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins}
1146cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins
11474c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchinsvoid ConsumedStateMap::clearTemporaries() {
11484c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  TmpMap.clear();
11494c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins}
11504c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins
11517385840b600d0e4a96d75042f612f6430e4a0390DeLesley HutchinsConsumedState ConsumedStateMap::getState(const VarDecl *Var) const {
11524c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  VarMapType::const_iterator Entry = VarMap.find(Var);
1153df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
11544c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  if (Entry != VarMap.end())
1155df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    return Entry->second;
1156df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
11574c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  return CS_None;
11584c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins}
11594c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins
11604c3e0bc7850df76824138ecfcc434388e7f69559DeLesley HutchinsConsumedState
11614c3e0bc7850df76824138ecfcc434388e7f69559DeLesley HutchinsConsumedStateMap::getState(const CXXBindTemporaryExpr *Tmp) const {
11624c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  TmpMapType::const_iterator Entry = TmpMap.find(Tmp);
11634c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins
11644c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  if (Entry != TmpMap.end())
11654c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    return Entry->second;
11664c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins
11674c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  return CS_None;
1168df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
1169df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1170df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStateMap::intersect(const ConsumedStateMap *Other) {
1171df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  ConsumedState LocalState;
1172df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1173b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (this->From && this->From == Other->From && !Other->Reachable) {
1174b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    this->markUnreachable();
1175b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return;
1176b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
1177b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
11786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto &DM : Other->VarMap) {
11796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    LocalState = this->getState(DM.first);
1180df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1181b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (LocalState == CS_None)
1182b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      continue;
1183b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
11846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (LocalState != DM.second)
11856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines     VarMap[DM.first] = CS_Unknown;
1186df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  }
1187df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
1188df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
11897385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchinsvoid ConsumedStateMap::intersectAtLoopHead(const CFGBlock *LoopHead,
11907385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  const CFGBlock *LoopBack, const ConsumedStateMap *LoopBackStates,
11917385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  ConsumedWarningsHandlerBase &WarningsHandler) {
11927385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
11937385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  ConsumedState LocalState;
1194627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins  SourceLocation BlameLoc = getLastStmtLoc(LoopBack);
11957385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
11966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto &DM : LoopBackStates->VarMap) {
11976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    LocalState = this->getState(DM.first);
11987385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
11997385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    if (LocalState == CS_None)
12007385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins      continue;
12017385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
12026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (LocalState != DM.second) {
12036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      VarMap[DM.first] = CS_Unknown;
12046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      WarningsHandler.warnLoopStateMismatch(BlameLoc,
12056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                            DM.first->getNameAsString());
12067385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins    }
12077385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  }
12087385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins}
12097385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
1210b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsvoid ConsumedStateMap::markUnreachable() {
1211b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  this->Reachable = false;
12124c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  VarMap.clear();
12134c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  TmpMap.clear();
1214b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins}
1215b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1216df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedStateMap::setState(const VarDecl *Var, ConsumedState State) {
12174c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  VarMap[Var] = State;
12184c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins}
12194c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins
12204c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchinsvoid ConsumedStateMap::setState(const CXXBindTemporaryExpr *Tmp,
12214c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins                                ConsumedState State) {
12224c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins  TmpMap[Tmp] = State;
1223df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
1224df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
12256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesvoid ConsumedStateMap::remove(const CXXBindTemporaryExpr *Tmp) {
12266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  TmpMap.erase(Tmp);
12275fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins}
1228df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
12297385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchinsbool ConsumedStateMap::operator!=(const ConsumedStateMap *Other) const {
12306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto &DM : Other->VarMap)
12316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (this->getState(DM.first) != DM.second)
12326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      return true;
12337385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  return false;
12347385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins}
12357385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
1236a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikievoid ConsumedAnalyzer::determineExpectedReturnState(AnalysisDeclContext &AC,
1237a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie                                                    const FunctionDecl *D) {
1238a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  QualType ReturnType;
1239a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  if (const CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
1240a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    ASTContext &CurrContext = AC.getASTContext();
1241a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    ReturnType = Constructor->getThisType(CurrContext)->getPointeeType();
1242a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  } else
1243a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    ReturnType = D->getCallResultType();
1244a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie
1245651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (const ReturnTypestateAttr *RTSAttr = D->getAttr<ReturnTypestateAttr>()) {
1246a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
1247a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    if (!RD || !RD->hasAttr<ConsumableAttr>()) {
1248a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie      // FIXME: This should be removed when template instantiation propagates
1249a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie      //        attributes at template specialization definition, not
1250a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie      //        declaration. When it is removed the test needs to be enabled
1251a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie      //        in SemaDeclAttr.cpp.
1252a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie      WarningsHandler.warnReturnTypestateForUnconsumableType(
1253a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie          RTSAttr->getLocation(), ReturnType.getAsString());
1254a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie      ExpectedReturnState = CS_None;
1255a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    } else
1256a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie      ExpectedReturnState = mapReturnTypestateAttrState(RTSAttr);
1257651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  } else if (isConsumableType(ReturnType)) {
1258651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (isAutoCastType(ReturnType))   // We can auto-cast the state to the
1259651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      ExpectedReturnState = CS_None;  // expected state.
1260651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    else
1261651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      ExpectedReturnState = mapConsumableAttrState(ReturnType);
1262651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
1263a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  else
1264a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie    ExpectedReturnState = CS_None;
1265a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie}
1266a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie
1267b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchinsbool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,
1268b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                                  const ConsumedStmtVisitor &Visitor) {
1269651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1270651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::unique_ptr<ConsumedStateMap> FalseStates(
1271651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      new ConsumedStateMap(*CurrStates));
1272b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  PropagationInfo PInfo;
1273df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1274b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (const IfStmt *IfNode =
1275b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    dyn_cast_or_null<IfStmt>(CurrBlock->getTerminator().getStmt())) {
1276df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1277651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const Expr *Cond = IfNode->getCond();
1278b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1279b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    PInfo = Visitor.getInfo(Cond);
1280b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (!PInfo.isValid() && isa<BinaryOperator>(Cond))
1281b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      PInfo = Visitor.getInfo(cast<BinaryOperator>(Cond)->getRHS());
1282df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
12834c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    if (PInfo.isVarTest()) {
1284b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      CurrStates->setSource(Cond);
1285b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      FalseStates->setSource(Cond);
12864c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins      splitVarStateForIf(IfNode, PInfo.getVarTest(), CurrStates,
1287a0cbcabb1beaee6c0cd5d4aa30cd9450ff5331eaChris Wailes                         FalseStates.get());
1288b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1289b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else if (PInfo.isBinTest()) {
1290b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      CurrStates->setSource(PInfo.testSourceNode());
1291b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      FalseStates->setSource(PInfo.testSourceNode());
1292a0cbcabb1beaee6c0cd5d4aa30cd9450ff5331eaChris Wailes      splitVarStateForIfBinOp(PInfo, CurrStates, FalseStates.get());
1293df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1294df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    } else {
1295b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      return false;
1296df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
1297df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1298b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  } else if (const BinaryOperator *BinOp =
1299b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    dyn_cast_or_null<BinaryOperator>(CurrBlock->getTerminator().getStmt())) {
1300b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1301b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    PInfo = Visitor.getInfo(BinOp->getLHS());
13024c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    if (!PInfo.isVarTest()) {
1303b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if ((BinOp = dyn_cast_or_null<BinaryOperator>(BinOp->getLHS()))) {
1304b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        PInfo = Visitor.getInfo(BinOp->getRHS());
1305b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
13064c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins        if (!PInfo.isVarTest())
1307b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins          return false;
1308b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1309b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      } else {
1310b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        return false;
1311b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      }
1312b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
1313b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1314b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    CurrStates->setSource(BinOp);
1315b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    FalseStates->setSource(BinOp);
1316b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
13174c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins    const VarTestResult &Test = PInfo.getVarTest();
1318b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    ConsumedState VarState = CurrStates->getState(Test.Var);
1319b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1320b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (BinOp->getOpcode() == BO_LAnd) {
1321b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (VarState == CS_Unknown)
1322b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        CurrStates->setState(Test.Var, Test.TestsFor);
1323b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      else if (VarState == invertConsumedUnconsumed(Test.TestsFor))
1324b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        CurrStates->markUnreachable();
1325b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1326b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else if (BinOp->getOpcode() == BO_LOr) {
1327b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      if (VarState == CS_Unknown)
1328b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        FalseStates->setState(Test.Var,
1329b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins                              invertConsumedUnconsumed(Test.TestsFor));
1330b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      else if (VarState == Test.TestsFor)
1331b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        FalseStates->markUnreachable();
1332b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
1333b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1334b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  } else {
1335b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    return false;
1336b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  }
1337b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1338df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin();
1339df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1340b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (*SI)
1341b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    BlockInfo.addInfo(*SI, CurrStates);
1342b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  else
1343b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    delete CurrStates;
1344b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1345b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  if (*++SI)
1346651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    BlockInfo.addInfo(*SI, FalseStates.release());
1347651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
13486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  CurrStates = nullptr;
1349b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins  return true;
1350df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
1351df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1352df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsvoid ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
1353df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  const FunctionDecl *D = dyn_cast_or_null<FunctionDecl>(AC.getDecl());
135457b781dde2676cd1bd838a1cdd56d3aeea091d11DeLesley Hutchins  if (!D)
135557b781dde2676cd1bd838a1cdd56d3aeea091d11DeLesley Hutchins    return;
1356df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
135757b781dde2676cd1bd838a1cdd56d3aeea091d11DeLesley Hutchins  CFG *CFGraph = AC.getCFG();
135857b781dde2676cd1bd838a1cdd56d3aeea091d11DeLesley Hutchins  if (!CFGraph)
135957b781dde2676cd1bd838a1cdd56d3aeea091d11DeLesley Hutchins    return;
136052f717eba7eff69c97d64de5e3669f4a5ee57d5cDeLesley Hutchins
1361a33ab6074a2cc60fe895d6669f9ee776c5fea335David Blaikie  determineExpectedReturnState(AC, D);
13627385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
1363df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  PostOrderCFGView *SortedGraph = AC.getAnalysis<PostOrderCFGView>();
13647385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  // AC.getCFG()->viewCFG(LangOptions());
13657385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
13667385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins  BlockInfo = ConsumedBlockInfo(CFGraph->getNumBlockIDs(), SortedGraph);
1367df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1368df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  CurrStates = new ConsumedStateMap();
13694252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins  ConsumedStmtVisitor Visitor(AC, *this, CurrStates);
13704252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins
13714252598a2e58c3f74027511f535ed327f9b32b77DeLesley Hutchins  // Add all trackable parameters to the state map.
13726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto *PI : D->params())
1373651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Visitor.VisitParmVarDecl(PI);
1374df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1375df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  // Visit all of the function's basic blocks.
13766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto *CurrBlock : *SortedGraph) {
13776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (!CurrStates)
1378df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      CurrStates = BlockInfo.getInfo(CurrBlock);
1379b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1380b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (!CurrStates) {
1381b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      continue;
1382b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1383b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    } else if (!CurrStates->isReachable()) {
1384b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      delete CurrStates;
13856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      CurrStates = nullptr;
1386b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins      continue;
1387b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    }
1388b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1389b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    Visitor.reset(CurrStates);
1390b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1391df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    // Visit all of the basic block's statements.
13926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    for (const auto &B : *CurrBlock) {
13936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      switch (B.getKind()) {
13945fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      case CFGElement::Statement:
13956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        Visitor.Visit(B.castAs<CFGStmt>().getStmt());
13965fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins        break;
1397627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins
1398627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins      case CFGElement::TemporaryDtor: {
13996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        const CFGTemporaryDtor &DTor = B.castAs<CFGTemporaryDtor>();
1400627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins        const CXXBindTemporaryExpr *BTE = DTor.getBindTemporaryExpr();
1401627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins
14024c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins        Visitor.checkCallability(PropagationInfo(BTE),
14034c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins                                 DTor.getDestructorDecl(AC.getASTContext()),
14044c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins                                 BTE->getExprLoc());
14056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        CurrStates->remove(BTE);
1406627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins        break;
1407627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins      }
1408627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins
1409627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins      case CFGElement::AutomaticObjectDtor: {
14106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        const CFGAutomaticObjDtor &DTor = B.castAs<CFGAutomaticObjDtor>();
14114c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins        SourceLocation Loc = DTor.getTriggerStmt()->getLocEnd();
1412627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins        const VarDecl *Var = DTor.getVarDecl();
1413627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins
14144c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins        Visitor.checkCallability(PropagationInfo(Var),
14154c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins                                 DTor.getDestructorDecl(AC.getASTContext()),
14164c3e0bc7850df76824138ecfcc434388e7f69559DeLesley Hutchins                                 Loc);
1417627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins        break;
1418627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins      }
1419627c7f9740dfe9c208543798eccbe5ca23e1ef42DeLesley Hutchins
14205fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      default:
14215fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins        break;
14225fdd207ec8f4c1f58bd74f8a84ce1935487563ceDeLesley Hutchins      }
1423df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
1424df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1425b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    // TODO: Handle other forms of branching with precision, including while-
1426b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    //       and for-loops. (Deferred)
1427b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins    if (!splitState(CurrBlock, Visitor)) {
14286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      CurrStates->setSource(nullptr);
14296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
14307385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins      if (CurrBlock->succ_size() > 1 ||
14317385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins          (CurrBlock->succ_size() == 1 &&
14327385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins           (*CurrBlock->succ_begin())->pred_size() > 1)) {
1433df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1434b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        bool OwnershipTaken = false;
1435b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1436b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
1437b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins             SE = CurrBlock->succ_end(); SI != SE; ++SI) {
14386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
14396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          if (*SI == nullptr) continue;
14406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
14417385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins          if (BlockInfo.isBackEdge(CurrBlock, *SI)) {
14427385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins            BlockInfo.borrowInfo(*SI)->intersectAtLoopHead(*SI, CurrBlock,
14437385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins                                                           CurrStates,
14447385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins                                                           WarningsHandler);
14457385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins
14467385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins            if (BlockInfo.allBackEdgesVisited(*SI, CurrBlock))
14477385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins              BlockInfo.discardInfo(*SI);
14487385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins          } else {
14497385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins            BlockInfo.addInfo(*SI, CurrStates, OwnershipTaken);
14507385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins          }
1451b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        }
1452b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins
1453b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins        if (!OwnershipTaken)
1454b7dc1f5f30e1e46e44389b036d48f9614cfd5fe3DeLesley Hutchins          delete CurrStates;
14556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
14566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        CurrStates = nullptr;
1457df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins      }
1458df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins    }
1459cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins
1460cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins    if (CurrBlock == &AC.getCFG()->getExit() &&
1461cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins        D->getCallResultType()->isVoidType())
1462cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins      CurrStates->checkParamsForReturnTypestate(D->getLocation(),
1463cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins                                                WarningsHandler);
1464df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  } // End of block iterator.
1465df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1466df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  // Delete the last existing state map.
1467df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  delete CurrStates;
1468df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins
1469df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins  WarningsHandler.emitDiagnostics();
1470df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}
1471df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}} // end namespace clang::consumed
1472