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