29#include "llvm/ADT/DenseMap.h"
30#include "llvm/ADT/STLExtras.h"
31#include "llvm/ADT/StringRef.h"
32#include "llvm/Support/Casting.h"
33#include "llvm/Support/ErrorHandling.h"
56using namespace consumed;
64 for (
const auto &B : *
Block)
65 if (std::optional<CFGStmt> CS = B.getAs<
CFGStmt>())
66 return CS->getStmt()->getBeginLoc();
70 if (
Block->succ_size() == 1 && *
Block->succ_begin())
79 if (
const Stmt *StmtNode =
Block->getTerminatorStmt()) {
80 return StmtNode->getBeginLoc();
83 BE =
Block->rend(); BI != BE; ++BI) {
84 if (std::optional<CFGStmt> CS = BI->getAs<
CFGStmt>())
85 return CS->getStmt()->getBeginLoc();
91 if (
Block->succ_size() == 1 && *
Block->succ_begin())
97 if (
Block->pred_size() == 1 && *
Block->pred_begin())
114 llvm_unreachable(
"invalid enum");
119 for (
const auto &S : CWAttr->callableStates()) {
123 case CallableWhenAttr::Unknown:
127 case CallableWhenAttr::Unconsumed:
131 case CallableWhenAttr::Consumed:
136 if (MappedAttrState == State)
148 return RD->hasAttr<ConsumableAttr>();
158 return RD->hasAttr<ConsumableAutoCastAttr>();
165 return RD->hasAttr<ConsumableSetOnReadAttr>();
178 llvm_unreachable(
"invalid enum");
186 return FunDecl->
hasAttr<TestTypestateAttr>();
196 const ConsumableAttr *CAttr =
199 switch (CAttr->getDefaultState()) {
200 case ConsumableAttr::Unknown:
202 case ConsumableAttr::Unconsumed:
204 case ConsumableAttr::Consumed:
207 llvm_unreachable(
"invalid enum");
212 switch (PTAttr->getParamState()) {
213 case ParamTypestateAttr::Unknown:
215 case ParamTypestateAttr::Unconsumed:
217 case ParamTypestateAttr::Consumed:
220 llvm_unreachable(
"invalid_enum");
225 switch (RTSAttr->getState()) {
226 case ReturnTypestateAttr::Unknown:
228 case ReturnTypestateAttr::Unconsumed:
230 case ReturnTypestateAttr::Consumed:
233 llvm_unreachable(
"invalid enum");
237 switch (STAttr->getNewState()) {
238 case SetTypestateAttr::Unknown:
240 case SetTypestateAttr::Unconsumed:
242 case SetTypestateAttr::Consumed:
245 llvm_unreachable(
"invalid_enum");
262 llvm_unreachable(
"invalid enum");
267 switch (FunDecl->
getAttr<TestTypestateAttr>()->getTestState()) {
268 case TestTypestateAttr::Unconsumed:
270 case TestTypestateAttr::Consumed:
273 llvm_unreachable(
"invalid enum");
278struct VarTestResult {
301 } InfoType = IT_None;
324 : InfoType(IT_VarTest) {
330 const VarTestResult <est,
const VarTestResult &RTest)
331 : InfoType(IT_BinTest) {
341 : InfoType(IT_BinTest) {
345 BinTest.LTest.TestsFor = LTestsFor;
347 BinTest.RTest.TestsFor = RTestsFor;
354 : InfoType(IT_Tmp),
Tmp(
Tmp) {}
357 assert(InfoType == IT_State);
362 assert(InfoType == IT_VarTest);
367 assert(InfoType == IT_BinTest);
372 assert(InfoType == IT_BinTest);
377 assert(InfoType == IT_Var);
382 assert(InfoType == IT_Tmp);
400 assert(InfoType == IT_BinTest);
405 assert(InfoType == IT_BinTest);
409 bool isValid()
const {
return InfoType != IT_None; }
410 bool isState()
const {
return InfoType == IT_State; }
411 bool isVarTest()
const {
return InfoType == IT_VarTest; }
412 bool isBinTest()
const {
return InfoType == IT_BinTest; }
413 bool isVar()
const {
return InfoType == IT_Var; }
414 bool isTmp()
const {
return InfoType == IT_Tmp; }
417 return InfoType == IT_VarTest || InfoType == IT_BinTest;
421 return InfoType == IT_Var || InfoType == IT_Tmp;
425 assert(InfoType == IT_VarTest || InfoType == IT_BinTest);
427 if (InfoType == IT_VarTest) {
431 }
else if (InfoType == IT_BinTest) {
460 using MapType = llvm::DenseMap<const Stmt *, PropagationInfo>;
461 using PairType= std::pair<const Stmt *, PropagationInfo>;
462 using InfoEntry = MapType::iterator;
463 using ConstInfoEntry = MapType::const_iterator;
467 MapType PropagationMap;
469 InfoEntry findInfo(
const Expr *E) {
470 if (
const auto Cleanups = dyn_cast<ExprWithCleanups>(E))
471 if (!Cleanups->cleanupsHaveSideEffects())
472 E = Cleanups->getSubExpr();
476 ConstInfoEntry findInfo(
const Expr *E)
const {
477 if (
const auto Cleanups = dyn_cast<ExprWithCleanups>(E))
478 if (!Cleanups->cleanupsHaveSideEffects())
479 E = Cleanups->getSubExpr();
487 void forwardInfo(
const Expr *From,
const Expr *To);
517 : Analyzer(Analyzer), StateMap(StateMap) {}
520 ConstInfoEntry Entry = findInfo(StmtNode);
522 if (Entry != PropagationMap.end())
523 return Entry->second;
529 StateMap = NewStateMap;
536void ConsumedStmtVisitor::forwardInfo(
const Expr *From,
const Expr *To) {
537 InfoEntry Entry = findInfo(From);
538 if (Entry != PropagationMap.end())
539 insertInfo(To, Entry->second);
544void ConsumedStmtVisitor::copyInfo(
const Expr *From,
const Expr *To,
546 InfoEntry Entry = findInfo(From);
547 if (Entry != PropagationMap.end()) {
559 InfoEntry Entry = findInfo(From);
560 if (Entry != PropagationMap.end()) {
569 InfoEntry Entry = findInfo(To);
570 if (Entry != PropagationMap.end()) {
584 const CallableWhenAttr *CWAttr = FunDecl->
getAttr<CallableWhenAttr>();
614 if (isa<CXXOperatorCallExpr>(Call) && isa<CXXMethodDecl>(FunD))
618 for (
unsigned Index =
Offset; Index < Call->getNumArgs(); ++Index) {
626 InfoEntry Entry = findInfo(Call->getArg(Index));
628 if (Entry == PropagationMap.end() || Entry->second.isTest())
633 if (ParamTypestateAttr *PTA = Param->
getAttr<ParamTypestateAttr>()) {
637 if (ParamState != ExpectedState)
639 Call->getArg(Index)->getExprLoc(),
643 if (!(Entry->second.isVar() || Entry->second.isTmp()))
647 if (ReturnTypestateAttr *RT = Param->
getAttr<ReturnTypestateAttr>())
661 InfoEntry Entry = findInfo(ObjArg);
662 if (Entry != PropagationMap.end()) {
666 if (SetTypestateAttr *STA = FunD->
getAttr<SetTypestateAttr>()) {
671 else if (PInfo.
isTmp()) {
677 PropagationMap.insert(PairType(Call,
684void ConsumedStmtVisitor::propagateReturnType(
const Expr *Call,
692 if (ReturnTypestateAttr *RTA = Fun->
getAttr<ReturnTypestateAttr>())
705 InfoEntry LEntry = findInfo(BinOp->
getLHS()),
706 REntry = findInfo(BinOp->
getRHS());
708 VarTestResult LTest, RTest;
710 if (LEntry != PropagationMap.end() && LEntry->second.isVarTest()) {
711 LTest = LEntry->second.getVarTest();
717 if (REntry != PropagationMap.end() && REntry->second.isVarTest()) {
718 RTest = REntry->second.getVarTest();
724 if (!(LTest.Var ==
nullptr && RTest.Var ==
nullptr))
732 forwardInfo(BinOp->
getLHS(), BinOp);
747 if (Call->isCallToStdMove()) {
753 propagateReturnType(Call, FunDecl);
757 forwardInfo(Cast->getSubExpr(), Cast);
763 InfoEntry Entry = findInfo(Temp->
getSubExpr());
765 if (Entry != PropagationMap.end() && !Entry->second.isTest()) {
766 StateMap->
setState(Temp, Entry->second.getAsState(StateMap));
774 QualType ThisType = Constructor->getThisType()->getPointeeType();
780 if (ReturnTypestateAttr *RTA = Constructor->getAttr<ReturnTypestateAttr>()) {
784 }
else if (Constructor->isDefaultConstructor()) {
785 PropagationMap.insert(PairType(Call,
787 }
else if (Constructor->isMoveConstructor()) {
789 }
else if (Constructor->isCopyConstructor()) {
794 copyInfo(Call->getArg(0), Call, NS);
808 handleCall(Call, Call->getImplicitObjectArgument(), MD);
809 propagateReturnType(Call, MD);
814 const auto *FunDecl = dyn_cast_or_null<FunctionDecl>(Call->getDirectCallee());
815 if (!FunDecl)
return;
817 if (Call->getOperator() == OO_Equal) {
819 if (!
handleCall(Call, Call->getArg(0), FunDecl))
820 setInfo(Call->getArg(0), CS);
824 if (
const auto *MCall = dyn_cast<CXXMemberCallExpr>(Call))
825 handleCall(MCall, MCall->getImplicitObjectArgument(), FunDecl);
829 propagateReturnType(Call, FunDecl);
833 if (
const auto *Var = dyn_cast_or_null<VarDecl>(DeclRef->
getDecl()))
839 for (
const auto *DI : DeclS->
decls())
840 if (isa<VarDecl>(DI))
844 if (
const auto *Var = dyn_cast_or_null<VarDecl>(DeclS->
getSingleDecl()))
854 forwardInfo(MExpr->
getBase(), MExpr);
861 if (
const ParamTypestateAttr *PTA = Param->
getAttr<ParamTypestateAttr>())
873 StateMap->
setState(Param, ParamState);
879 if (ExpectedState !=
CS_None) {
880 InfoEntry Entry = findInfo(Ret->getRetValue());
882 if (Entry != PropagationMap.end()) {
885 if (RetState != ExpectedState)
897 InfoEntry Entry = findInfo(UOp->
getSubExpr());
898 if (Entry == PropagationMap.end())
return;
902 PropagationMap.insert(PairType(UOp, Entry->second));
906 if (Entry->second.isTest())
907 PropagationMap.insert(PairType(UOp, Entry->second.invertTest()));
920 if (VIT != PropagationMap.end()) {
941 ThenStates->
setState(Test.Var, Test.TestsFor);
945 }
else if (VarState == Test.TestsFor) {
953 const VarTestResult <est = PInfo.
getLTest(),
962 ThenStates->
setState(LTest.Var, LTest.TestsFor);
965 }
else if (LState == LTest.TestsFor &&
isKnownState(RState)) {
966 if (RState == RTest.TestsFor)
975 }
else if (LState == LTest.TestsFor) {
979 if (RState == RTest.TestsFor)
990 ThenStates->
setState(RTest.Var, RTest.TestsFor);
997 else if (RState == RTest.TestsFor)
1005 assert(CurrBlock &&
"Block pointer must not be NULL");
1006 assert(TargetBlock &&
"TargetBlock pointer must not be NULL");
1008 unsigned int CurrBlockOrder = VisitOrder[CurrBlock->
getBlockID()];
1010 PE = TargetBlock->
pred_end(); PI != PE; ++PI) {
1011 if (*PI && CurrBlockOrder < VisitOrder[(*PI)->getBlockID()] )
1019 std::unique_ptr<ConsumedStateMap> &OwnedStateMap) {
1020 assert(
Block &&
"Block pointer must not be NULL");
1022 auto &Entry = StateMapsArray[
Block->getBlockID()];
1025 Entry->intersect(*StateMap);
1026 }
else if (OwnedStateMap)
1027 Entry = std::move(OwnedStateMap);
1029 Entry = std::make_unique<ConsumedStateMap>(*StateMap);
1033 std::unique_ptr<ConsumedStateMap> StateMap) {
1034 assert(
Block &&
"Block pointer must not be NULL");
1036 auto &Entry = StateMapsArray[
Block->getBlockID()];
1039 Entry->intersect(*StateMap);
1041 Entry = std::move(StateMap);
1046 assert(
Block &&
"Block pointer must not be NULL");
1047 assert(StateMapsArray[
Block->getBlockID()] &&
"Block has no block info");
1049 return StateMapsArray[
Block->getBlockID()].get();
1053 StateMapsArray[
Block->getBlockID()] =
nullptr;
1056std::unique_ptr<ConsumedStateMap>
1058 assert(
Block &&
"Block pointer must not be NULL");
1060 auto &Entry = StateMapsArray[
Block->getBlockID()];
1066 assert(From &&
"From block must not be NULL");
1067 assert(To &&
"From block must not be NULL");
1073 assert(
Block &&
"Block pointer must not be NULL");
1077 if (
Block->pred_size() < 2)
1080 unsigned int BlockVisitOrder = VisitOrder[
Block->getBlockID()];
1082 PE =
Block->pred_end(); PI != PE; ++PI) {
1083 if (*PI && BlockVisitOrder < VisitOrder[(*PI)->getBlockID()])
1092 for (
const auto &DM :
VarMap) {
1093 if (isa<ParmVarDecl>(DM.first)) {
1094 const auto *Param = cast<ParmVarDecl>(DM.first);
1095 const ReturnTypestateAttr *RTA = Param->getAttr<ReturnTypestateAttr>();
1101 if (DM.second != ExpectedState)
1114 VarMapType::const_iterator Entry =
VarMap.find(Var);
1116 if (Entry !=
VarMap.end())
1117 return Entry->second;
1124 TmpMapType::const_iterator Entry =
TmpMap.find(Tmp);
1126 if (Entry !=
TmpMap.end())
1127 return Entry->second;
1135 if (this->From && this->From == Other.From && !Other.Reachable) {
1140 for (
const auto &DM : Other.VarMap) {
1141 LocalState = this->
getState(DM.first);
1146 if (LocalState != DM.second)
1158 for (
const auto &DM : LoopBackStates->
VarMap) {
1159 LocalState = this->
getState(DM.first);
1164 if (LocalState != DM.second) {
1167 DM.first->getNameAsString());
1192 for (
const auto &DM : Other->VarMap)
1193 if (this->
getState(DM.first) != DM.second)
1201 if (
const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
1202 ReturnType = Constructor->getThisType()->getPointeeType();
1206 if (
const ReturnTypestateAttr *RTSAttr = D->
getAttr<ReturnTypestateAttr>()) {
1208 if (!RD || !RD->
hasAttr<ConsumableAttr>()) {
1214 RTSAttr->getLocation(), ReturnType.
getAsString());
1215 ExpectedReturnState =
CS_None;
1220 ExpectedReturnState =
CS_None;
1225 ExpectedReturnState =
CS_None;
1228bool ConsumedAnalyzer::splitState(
const CFGBlock *CurrBlock,
1230 std::unique_ptr<ConsumedStateMap> FalseStates(
1234 if (
const auto *IfNode =
1236 const Expr *Cond = IfNode->getCond();
1238 PInfo = Visitor.getInfo(Cond);
1239 if (!PInfo.
isValid() && isa<BinaryOperator>(Cond))
1240 PInfo = Visitor.getInfo(cast<BinaryOperator>(Cond)->getRHS());
1243 CurrStates->setSource(Cond);
1244 FalseStates->setSource(Cond);
1254 }
else if (
const auto *BinOp =
1256 PInfo = Visitor.getInfo(BinOp->getLHS());
1258 if ((BinOp = dyn_cast_or_null<BinaryOperator>(BinOp->getLHS()))) {
1259 PInfo = Visitor.getInfo(BinOp->getRHS());
1268 CurrStates->setSource(BinOp);
1269 FalseStates->setSource(BinOp);
1271 const VarTestResult &Test = PInfo.
getVarTest();
1274 if (BinOp->getOpcode() == BO_LAnd) {
1276 CurrStates->setState(Test.Var, Test.TestsFor);
1278 CurrStates->markUnreachable();
1280 }
else if (BinOp->getOpcode() == BO_LOr) {
1282 FalseStates->setState(Test.Var,
1284 else if (VarState == Test.TestsFor)
1285 FalseStates->markUnreachable();
1294 BlockInfo.
addInfo(*SI, std::move(CurrStates));
1296 CurrStates =
nullptr;
1299 BlockInfo.
addInfo(*SI, std::move(FalseStates));
1305 const auto *D = dyn_cast_or_null<FunctionDecl>(AC.
getDecl());
1313 determineExpectedReturnState(AC, D);
1320 CurrStates = std::make_unique<ConsumedStateMap>();
1328 for (
const auto *CurrBlock : *SortedGraph) {
1330 CurrStates = BlockInfo.getInfo(CurrBlock);
1334 }
else if (!CurrStates->isReachable()) {
1335 CurrStates =
nullptr;
1339 Visitor.
reset(CurrStates.get());
1342 for (
const auto &B : *CurrBlock) {
1343 switch (B.getKind()) {
1355 CurrStates->remove(BTE);
1377 if (!splitState(CurrBlock, Visitor)) {
1378 CurrStates->setSource(
nullptr);
1380 if (CurrBlock->succ_size() > 1 ||
1381 (CurrBlock->succ_size() == 1 &&
1382 (*CurrBlock->succ_begin())->pred_size() > 1)) {
1384 auto *RawState = CurrStates.get();
1387 SE = CurrBlock->succ_end(); SI != SE; ++SI) {
1388 if (*SI ==
nullptr)
continue;
1390 if (BlockInfo.isBackEdge(CurrBlock, *SI)) {
1391 BlockInfo.borrowInfo(*SI)->intersectAtLoopHead(
1394 if (BlockInfo.allBackEdgesVisited(CurrBlock, *SI))
1395 BlockInfo.discardInfo(*SI);
1397 BlockInfo.addInfo(*SI, RawState, CurrStates);
1401 CurrStates =
nullptr;
1407 CurrStates->checkParamsForReturnTypestate(D->
getLocation(),
1412 CurrStates =
nullptr;
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
static void splitVarStateForIfBinOp(const PropagationInfo &PInfo, ConsumedStateMap *ThenStates, ConsumedStateMap *ElseStates)
static ConsumedState invertConsumedUnconsumed(ConsumedState State)
static bool isCallableInState(const CallableWhenAttr *CWAttr, ConsumedState State)
static ConsumedState mapParamTypestateAttrState(const ParamTypestateAttr *PTAttr)
static bool isRValueRef(QualType ParamType)
static ConsumedState mapReturnTypestateAttrState(const ReturnTypestateAttr *RTSAttr)
static ConsumedState testsFor(const FunctionDecl *FunDecl)
static bool isConsumableType(const QualType &QT)
static StringRef stateToString(ConsumedState State)
static void splitVarStateForIf(const IfStmt *IfNode, const VarTestResult &Test, ConsumedStateMap *ThenStates, ConsumedStateMap *ElseStates)
static bool isTestingFunction(const FunctionDecl *FunDecl)
static bool isAutoCastType(const QualType &QT)
static bool isPointerOrRef(QualType ParamType)
static SourceLocation getFirstStmtLoc(const CFGBlock *Block)
static void setStateForVarOrTmp(ConsumedStateMap *StateMap, const PropagationInfo &PInfo, ConsumedState State)
static ConsumedState mapConsumableAttrState(const QualType QT)
static ConsumedState mapSetTypestateAttrState(const SetTypestateAttr *STAttr)
static SourceLocation getLastStmtLoc(const CFGBlock *Block)
static bool isSetOnReadPtrType(const QualType &QT)
static bool isKnownState(ConsumedState State)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines an enumeration for C++ overloaded operators.
Defines the clang::SourceLocation class and associated facilities.
C Language Family Type Representation.
AnalysisDeclContext contains the context data for the function, method or block under analysis.
const Decl * getDecl() const
ASTContext & getASTContext() const
A builtin binary operation expression such as "x + y" or "x <= y".
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
const VarDecl * getVarDecl() const
const Stmt * getTriggerStmt() const
Represents a single basic block in a source-level CFG.
CFGTerminator getTerminator() const
succ_iterator succ_begin()
AdjacentBlocks::const_iterator const_pred_iterator
pred_iterator pred_begin()
unsigned getBlockID() const
AdjacentBlocks::const_iterator const_succ_iterator
Represents a top-level expression in a basic block.
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type.
const CXXDestructorDecl * getDestructorDecl(ASTContext &astContext) const
const Stmt * getStmt() const
Represents C++ object destructor implicitly generated at the end of full expression for temporary obj...
const CXXBindTemporaryExpr * getBindTemporaryExpr() const
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
Represents binding an expression to a temporary.
const Expr * getSubExpr() const
Represents a call to a C++ constructor.
Represents a C++ constructor within a class.
Represents a call to a member function that may be written either with member call syntax (e....
Represents a static or instance method of a struct/union/class.
A call to an overloaded operator written using operator syntax.
Represents a C++ struct/union/class.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
A reference to a declared variable, function, enum, etc.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl.
const Decl * getSingleDecl() const
SourceLocation getLocation() const
This represents one expression.
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
ArrayRef< ParmVarDecl * > parameters() const
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
QualType getCallResultType() const
Determine the type of an expression that calls this function.
IfStmt - This represents an if/then/else.
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Represents a parameter to a function.
A (possibly-)qualified type.
bool isConstQualified() const
Determine whether this type is const-qualified.
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
RetTy Visit(PTR(Stmt) S, ParamTys... P)
Stmt - This represents one statement.
SourceLocation getEndLoc() const LLVM_READONLY
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isRValueReferenceType() const
bool isPointerType() const
bool isReferenceType() const
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Expr * getSubExpr() const
Represents a variable declaration or definition.
const Expr * getInit() const
A class that handles the analysis of uniqueness violations.
ConsumedWarningsHandlerBase & WarningsHandler
ConsumedState getExpectedReturnState() const
void run(AnalysisDeclContext &AC)
Check a function's CFG for consumed violations.
ConsumedStateMap * borrowInfo(const CFGBlock *Block)
bool isBackEdgeTarget(const CFGBlock *Block)
std::unique_ptr< ConsumedStateMap > getInfo(const CFGBlock *Block)
void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap, std::unique_ptr< ConsumedStateMap > &OwnedStateMap)
void discardInfo(const CFGBlock *Block)
bool allBackEdgesVisited(const CFGBlock *CurrBlock, const CFGBlock *TargetBlock)
bool isBackEdge(const CFGBlock *From, const CFGBlock *To)
void clearTemporaries()
Clear the TmpMap.
void checkParamsForReturnTypestate(SourceLocation BlameLoc, ConsumedWarningsHandlerBase &WarningsHandler) const
Warn if any of the parameters being tracked are not in the state they were declared to be in upon ret...
void intersect(const ConsumedStateMap &Other)
Merge this state map with another map.
ConsumedState getState(const VarDecl *Var) const
Get the consumed state of a given variable.
void intersectAtLoopHead(const CFGBlock *LoopHead, const CFGBlock *LoopBack, const ConsumedStateMap *LoopBackStates, ConsumedWarningsHandlerBase &WarningsHandler)
void remove(const CXXBindTemporaryExpr *Tmp)
Remove the temporary value from our state map.
void markUnreachable()
Mark the block as unreachable.
bool operator!=(const ConsumedStateMap *Other) const
Tests to see if there is a mismatch in the states stored in two maps.
void setState(const VarDecl *Var, ConsumedState State)
Set the consumed state of a given variable.
void VisitUnaryOperator(const UnaryOperator *UOp)
PropagationInfo getInfo(const Expr *StmtNode) const
void VisitVarDecl(const VarDecl *Var)
void VisitCXXMemberCallExpr(const CXXMemberCallExpr *Call)
void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Temp)
void VisitMemberExpr(const MemberExpr *MExpr)
void reset(ConsumedStateMap *NewStateMap)
void VisitReturnStmt(const ReturnStmt *Ret)
void VisitDeclStmt(const DeclStmt *DelcS)
void checkCallability(const PropagationInfo &PInfo, const FunctionDecl *FunDecl, SourceLocation BlameLoc)
void VisitCallExpr(const CallExpr *Call)
void VisitDeclRefExpr(const DeclRefExpr *DeclRef)
void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Temp)
bool handleCall(const CallExpr *Call, const Expr *ObjArg, const FunctionDecl *FunD)
ConsumedStmtVisitor(ConsumedAnalyzer &Analyzer, ConsumedStateMap *StateMap)
void VisitCXXConstructExpr(const CXXConstructExpr *Call)
void VisitBinaryOperator(const BinaryOperator *BinOp)
void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Call)
void VisitCastExpr(const CastExpr *Cast)
void VisitParmVarDecl(const ParmVarDecl *Param)
virtual void warnUseOfTempInInvalidState(StringRef MethodName, StringRef State, SourceLocation Loc)
Warn about use-while-consumed errors.
virtual void warnParamTypestateMismatch(SourceLocation LOC, StringRef ExpectedState, StringRef ObservedState)
virtual void warnLoopStateMismatch(SourceLocation Loc, StringRef VariableName)
Warn that a variable's state doesn't match at the entry and exit of a loop.
virtual void warnUseInInvalidState(StringRef MethodName, StringRef VariableName, StringRef State, SourceLocation Loc)
Warn about use-while-consumed errors.
virtual void emitDiagnostics()
Emit the warnings and notes left by the analysis.
virtual void warnReturnTypestateMismatch(SourceLocation Loc, StringRef ExpectedState, StringRef ObservedState)
Warn about return typestate mismatches.
virtual void warnReturnTypestateForUnconsumableType(SourceLocation Loc, StringRef TypeName)
Warn about return typestates set for unconsumable types.
virtual ~ConsumedWarningsHandlerBase()
virtual void warnParamReturnTypestateMismatch(SourceLocation Loc, StringRef VariableName, StringRef ExpectedState, StringRef ObservedState)
Warn about parameter typestate mismatches upon return.
const VarTestResult & getRTest() const
PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp, const VarTestResult <est, const VarTestResult &RTest)
const CXXBindTemporaryExpr * Tmp
PropagationInfo(const VarTestResult &VarTest)
EffectiveOp testEffectiveOp() const
PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp, const VarDecl *LVar, ConsumedState LTestsFor, const VarDecl *RVar, ConsumedState RTestsFor)
const ConsumedState & getState() const
const VarTestResult & getVarTest() const
const VarDecl * getVar() const
PropagationInfo(ConsumedState State)
PropagationInfo(const VarDecl *Var)
PropagationInfo(const VarDecl *Var, ConsumedState TestsFor)
PropagationInfo(const CXXBindTemporaryExpr *Tmp)
const VarTestResult & getLTest() const
bool isPointerToValue() const
PropagationInfo()=default
const CXXBindTemporaryExpr * getTmp() const
PropagationInfo invertTest() const
ConsumedState getAsState(const ConsumedStateMap *StateMap) const
const BinaryOperator * testSourceNode() const