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