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