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