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();
80 return StmtNode->getBeginLoc();
84 if (std::optional<CFGStmt> CS = BI->getAs<
CFGStmt>())
85 return CS->getStmt()->getBeginLoc();
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>();
192 const ConsumableAttr *CAttr =
195 switch (CAttr->getDefaultState()) {
196 case ConsumableAttr::Unknown:
198 case ConsumableAttr::Unconsumed:
200 case ConsumableAttr::Consumed:
203 llvm_unreachable(
"invalid enum");
208 switch (PTAttr->getParamState()) {
209 case ParamTypestateAttr::Unknown:
211 case ParamTypestateAttr::Unconsumed:
213 case ParamTypestateAttr::Consumed:
216 llvm_unreachable(
"invalid_enum");
221 switch (RTSAttr->getState()) {
222 case ReturnTypestateAttr::Unknown:
224 case ReturnTypestateAttr::Unconsumed:
226 case ReturnTypestateAttr::Consumed:
229 llvm_unreachable(
"invalid enum");
233 switch (STAttr->getNewState()) {
234 case SetTypestateAttr::Unknown:
236 case SetTypestateAttr::Unconsumed:
238 case SetTypestateAttr::Consumed:
241 llvm_unreachable(
"invalid_enum");
258 llvm_unreachable(
"invalid enum");
263 switch (FunDecl->
getAttr<TestTypestateAttr>()->getTestState()) {
264 case TestTypestateAttr::Unconsumed:
266 case TestTypestateAttr::Consumed:
269 llvm_unreachable(
"invalid enum");
274struct VarTestResult {
297 } InfoType = IT_None;
320 : InfoType(IT_VarTest) {
326 const VarTestResult <est,
const VarTestResult &RTest)
327 : InfoType(IT_BinTest) {
337 : InfoType(IT_BinTest) {
341 BinTest.LTest.TestsFor = LTestsFor;
343 BinTest.RTest.TestsFor = RTestsFor;
350 : InfoType(IT_Tmp),
Tmp(
Tmp) {}
353 assert(InfoType == IT_State);
358 assert(InfoType == IT_VarTest);
363 assert(InfoType == IT_BinTest);
368 assert(InfoType == IT_BinTest);
373 assert(InfoType == IT_Var);
378 assert(InfoType == IT_Tmp);
396 assert(InfoType == IT_BinTest);
401 assert(InfoType == IT_BinTest);
405 bool isValid()
const {
return InfoType != IT_None; }
406 bool isState()
const {
return InfoType == IT_State; }
407 bool isVarTest()
const {
return InfoType == IT_VarTest; }
408 bool isBinTest()
const {
return InfoType == IT_BinTest; }
409 bool isVar()
const {
return InfoType == IT_Var; }
410 bool isTmp()
const {
return InfoType == IT_Tmp; }
413 return InfoType == IT_VarTest || InfoType == IT_BinTest;
417 return InfoType == IT_Var || InfoType == IT_Tmp;
421 assert(InfoType == IT_VarTest || InfoType == IT_BinTest);
423 if (InfoType == IT_VarTest) {
427 }
else if (InfoType == IT_BinTest) {
456 using MapType = llvm::DenseMap<const Stmt *, PropagationInfo>;
457 using PairType= std::pair<const Stmt *, PropagationInfo>;
458 using InfoEntry = MapType::iterator;
459 using ConstInfoEntry = MapType::const_iterator;
463 MapType PropagationMap;
465 InfoEntry findInfo(
const Expr *
E) {
466 if (
const auto Cleanups = dyn_cast<ExprWithCleanups>(
E))
467 if (!Cleanups->cleanupsHaveSideEffects())
468 E = Cleanups->getSubExpr();
472 ConstInfoEntry findInfo(
const Expr *
E)
const {
473 if (
const auto Cleanups = dyn_cast<ExprWithCleanups>(
E))
474 if (!Cleanups->cleanupsHaveSideEffects())
475 E = Cleanups->getSubExpr();
483 void forwardInfo(
const Expr *From,
const Expr *To);
513 : Analyzer(Analyzer), StateMap(StateMap) {}
516 ConstInfoEntry Entry = findInfo(StmtNode);
518 if (Entry != PropagationMap.end())
519 return Entry->second;
525 StateMap = NewStateMap;
532void ConsumedStmtVisitor::forwardInfo(
const Expr *From,
const Expr *To) {
533 InfoEntry Entry = findInfo(From);
534 if (Entry != PropagationMap.end())
535 insertInfo(To, Entry->second);
540void ConsumedStmtVisitor::copyInfo(
const Expr *From,
const Expr *To,
542 InfoEntry Entry = findInfo(From);
543 if (Entry != PropagationMap.end()) {
555 InfoEntry Entry = findInfo(From);
556 if (Entry != PropagationMap.end()) {
565 InfoEntry Entry = findInfo(To);
566 if (Entry != PropagationMap.end()) {
580 const CallableWhenAttr *CWAttr = FunDecl->
getAttr<CallableWhenAttr>();
610 if (isa<CXXOperatorCallExpr>(
Call) && isa<CXXMethodDecl>(FunD))
614 for (
unsigned Index = Offset; Index <
Call->getNumArgs(); ++Index) {
622 InfoEntry Entry = findInfo(
Call->getArg(Index));
624 if (Entry == PropagationMap.end() || Entry->second.isTest())
629 if (ParamTypestateAttr *PTA = Param->
getAttr<ParamTypestateAttr>()) {
633 if (ParamState != ExpectedState)
635 Call->getArg(Index)->getExprLoc(),
639 if (!(Entry->second.isVar() || Entry->second.isTmp()))
643 if (ReturnTypestateAttr *RT = Param->
getAttr<ReturnTypestateAttr>())
657 InfoEntry Entry = findInfo(ObjArg);
658 if (Entry != PropagationMap.end()) {
662 if (SetTypestateAttr *STA = FunD->
getAttr<SetTypestateAttr>()) {
667 else if (PInfo.
isTmp()) {
673 PropagationMap.insert(PairType(
Call,
680void ConsumedStmtVisitor::propagateReturnType(
const Expr *
Call,
688 if (ReturnTypestateAttr *RTA = Fun->
getAttr<ReturnTypestateAttr>())
701 InfoEntry LEntry = findInfo(BinOp->
getLHS()),
702 REntry = findInfo(BinOp->
getRHS());
704 VarTestResult LTest, RTest;
706 if (LEntry != PropagationMap.end() && LEntry->second.isVarTest()) {
707 LTest = LEntry->second.getVarTest();
713 if (REntry != PropagationMap.end() && REntry->second.isVarTest()) {
714 RTest = REntry->second.getVarTest();
720 if (!(LTest.Var ==
nullptr && RTest.Var ==
nullptr))
728 forwardInfo(BinOp->
getLHS(), BinOp);
743 if (
Call->isCallToStdMove()) {
749 propagateReturnType(
Call, FunDecl);
753 forwardInfo(Cast->getSubExpr(), Cast);
759 InfoEntry Entry = findInfo(Temp->
getSubExpr());
761 if (Entry != PropagationMap.end() && !Entry->second.isTest()) {
762 StateMap->
setState(Temp, Entry->second.getAsState(StateMap));
770 QualType ThisType = Constructor->getFunctionObjectParameterType();
776 if (ReturnTypestateAttr *RTA = Constructor->getAttr<ReturnTypestateAttr>()) {
780 }
else if (Constructor->isDefaultConstructor()) {
781 PropagationMap.insert(PairType(
Call,
783 }
else if (Constructor->isMoveConstructor()) {
785 }
else if (Constructor->isCopyConstructor()) {
790 copyInfo(
Call->getArg(0),
Call, NS);
805 propagateReturnType(
Call, MD);
810 const auto *FunDecl = dyn_cast_or_null<FunctionDecl>(
Call->getDirectCallee());
811 if (!FunDecl)
return;
813 if (
Call->getOperator() == OO_Equal) {
816 setInfo(
Call->getArg(0), CS);
820 if (
const auto *MCall = dyn_cast<CXXMemberCallExpr>(
Call))
821 handleCall(MCall, MCall->getImplicitObjectArgument(), FunDecl);
825 propagateReturnType(
Call, FunDecl);
829 if (
const auto *Var = dyn_cast_or_null<VarDecl>(DeclRef->
getDecl()))
835 for (
const auto *DI : DeclS->
decls())
836 if (isa<VarDecl>(DI))
840 if (
const auto *Var = dyn_cast_or_null<VarDecl>(DeclS->
getSingleDecl()))
850 forwardInfo(MExpr->
getBase(), MExpr);
857 if (
const ParamTypestateAttr *PTA = Param->
getAttr<ParamTypestateAttr>())
869 StateMap->
setState(Param, ParamState);
875 if (ExpectedState !=
CS_None) {
876 InfoEntry Entry = findInfo(Ret->getRetValue());
878 if (Entry != PropagationMap.end()) {
881 if (RetState != ExpectedState)
893 InfoEntry Entry = findInfo(UOp->
getSubExpr());
894 if (Entry == PropagationMap.end())
return;
898 PropagationMap.insert(PairType(UOp, Entry->second));
902 if (Entry->second.isTest())
903 PropagationMap.insert(PairType(UOp, Entry->second.invertTest()));
916 if (VIT != PropagationMap.end()) {
937 ThenStates->
setState(Test.Var, Test.TestsFor);
941 }
else if (VarState == Test.TestsFor) {
949 const VarTestResult <est = PInfo.
getLTest(),
958 ThenStates->
setState(LTest.Var, LTest.TestsFor);
961 }
else if (LState == LTest.TestsFor &&
isKnownState(RState)) {
962 if (RState == RTest.TestsFor)
971 }
else if (LState == LTest.TestsFor) {
975 if (RState == RTest.TestsFor)
986 ThenStates->
setState(RTest.Var, RTest.TestsFor);
993 else if (RState == RTest.TestsFor)
1001 assert(CurrBlock &&
"Block pointer must not be NULL");
1002 assert(TargetBlock &&
"TargetBlock pointer must not be NULL");
1004 unsigned int CurrBlockOrder = VisitOrder[CurrBlock->
getBlockID()];
1006 PE = TargetBlock->
pred_end(); PI != PE; ++PI) {
1007 if (*PI && CurrBlockOrder < VisitOrder[(*PI)->getBlockID()] )
1015 std::unique_ptr<ConsumedStateMap> &OwnedStateMap) {
1016 assert(
Block &&
"Block pointer must not be NULL");
1018 auto &Entry = StateMapsArray[
Block->getBlockID()];
1021 Entry->intersect(*StateMap);
1022 }
else if (OwnedStateMap)
1023 Entry = std::move(OwnedStateMap);
1025 Entry = std::make_unique<ConsumedStateMap>(*StateMap);
1029 std::unique_ptr<ConsumedStateMap> StateMap) {
1030 assert(
Block &&
"Block pointer must not be NULL");
1032 auto &Entry = StateMapsArray[
Block->getBlockID()];
1035 Entry->intersect(*StateMap);
1037 Entry = std::move(StateMap);
1042 assert(
Block &&
"Block pointer must not be NULL");
1043 assert(StateMapsArray[
Block->getBlockID()] &&
"Block has no block info");
1045 return StateMapsArray[
Block->getBlockID()].get();
1049 StateMapsArray[
Block->getBlockID()] =
nullptr;
1052std::unique_ptr<ConsumedStateMap>
1054 assert(
Block &&
"Block pointer must not be NULL");
1056 auto &Entry = StateMapsArray[
Block->getBlockID()];
1062 assert(From &&
"From block must not be NULL");
1063 assert(To &&
"From block must not be NULL");
1069 assert(
Block &&
"Block pointer must not be NULL");
1073 if (
Block->pred_size() < 2)
1076 unsigned int BlockVisitOrder = VisitOrder[
Block->getBlockID()];
1078 PE =
Block->pred_end(); PI != PE; ++PI) {
1079 if (*PI && BlockVisitOrder < VisitOrder[(*PI)->getBlockID()])
1088 for (
const auto &DM :
VarMap) {
1089 if (isa<ParmVarDecl>(DM.first)) {
1090 const auto *Param = cast<ParmVarDecl>(DM.first);
1091 const ReturnTypestateAttr *RTA = Param->getAttr<ReturnTypestateAttr>();
1097 if (DM.second != ExpectedState)
1110 VarMapType::const_iterator Entry =
VarMap.find(Var);
1112 if (Entry !=
VarMap.end())
1113 return Entry->second;
1120 TmpMapType::const_iterator Entry =
TmpMap.find(Tmp);
1122 if (Entry !=
TmpMap.end())
1123 return Entry->second;
1131 if (this->From && this->From ==
Other.From && !
Other.Reachable) {
1136 for (
const auto &DM :
Other.VarMap) {
1137 LocalState = this->
getState(DM.first);
1142 if (LocalState != DM.second)
1154 for (
const auto &DM : LoopBackStates->
VarMap) {
1155 LocalState = this->
getState(DM.first);
1160 if (LocalState != DM.second) {
1163 DM.first->getNameAsString());
1188 for (
const auto &DM :
Other->VarMap)
1189 if (this->
getState(DM.first) != DM.second)
1197 if (
const auto *Constructor = dyn_cast<CXXConstructorDecl>(
D)) {
1198 ReturnType = Constructor->getFunctionObjectParameterType();
1200 ReturnType =
D->getCallResultType();
1202 if (
const ReturnTypestateAttr *RTSAttr =
D->
getAttr<ReturnTypestateAttr>()) {
1204 if (!RD || !RD->
hasAttr<ConsumableAttr>()) {
1210 RTSAttr->getLocation(), ReturnType.
getAsString());
1211 ExpectedReturnState =
CS_None;
1216 ExpectedReturnState =
CS_None;
1221 ExpectedReturnState =
CS_None;
1224bool ConsumedAnalyzer::splitState(
const CFGBlock *CurrBlock,
1226 std::unique_ptr<ConsumedStateMap> FalseStates(
1230 if (
const auto *IfNode =
1232 const Expr *Cond = IfNode->getCond();
1234 PInfo = Visitor.getInfo(Cond);
1235 if (!PInfo.
isValid() && isa<BinaryOperator>(Cond))
1236 PInfo = Visitor.getInfo(cast<BinaryOperator>(Cond)->getRHS());
1239 CurrStates->setSource(Cond);
1240 FalseStates->setSource(Cond);
1250 }
else if (
const auto *BinOp =
1252 PInfo = Visitor.getInfo(BinOp->getLHS());
1254 if ((BinOp = dyn_cast_or_null<BinaryOperator>(BinOp->getLHS()))) {
1255 PInfo = Visitor.getInfo(BinOp->getRHS());
1264 CurrStates->setSource(BinOp);
1265 FalseStates->setSource(BinOp);
1267 const VarTestResult &Test = PInfo.
getVarTest();
1270 if (BinOp->getOpcode() == BO_LAnd) {
1272 CurrStates->setState(Test.Var, Test.TestsFor);
1274 CurrStates->markUnreachable();
1276 }
else if (BinOp->getOpcode() == BO_LOr) {
1278 FalseStates->setState(Test.Var,
1280 else if (VarState == Test.TestsFor)
1281 FalseStates->markUnreachable();
1290 BlockInfo.
addInfo(*SI, std::move(CurrStates));
1292 CurrStates =
nullptr;
1295 BlockInfo.
addInfo(*SI, std::move(FalseStates));
1301 const auto *
D = dyn_cast_or_null<FunctionDecl>(AC.getDecl());
1305 CFG *CFGraph = AC.getCFG();
1309 determineExpectedReturnState(AC,
D);
1316 CurrStates = std::make_unique<ConsumedStateMap>();
1320 for (
const auto *PI :
D->parameters())
1324 for (
const auto *CurrBlock : *SortedGraph) {
1326 CurrStates = BlockInfo.getInfo(CurrBlock);
1330 }
else if (!CurrStates->isReachable()) {
1331 CurrStates =
nullptr;
1335 Visitor.
reset(CurrStates.get());
1338 for (
const auto &B : *CurrBlock) {
1339 switch (B.getKind()) {
1351 CurrStates->remove(BTE);
1373 if (!splitState(CurrBlock, Visitor)) {
1374 CurrStates->setSource(
nullptr);
1376 if (CurrBlock->succ_size() > 1 ||
1377 (CurrBlock->succ_size() == 1 &&
1378 (*CurrBlock->succ_begin())->pred_size() > 1)) {
1380 auto *RawState = CurrStates.get();
1383 SE = CurrBlock->succ_end(); SI != SE; ++SI) {
1384 if (*SI ==
nullptr)
continue;
1386 if (BlockInfo.isBackEdge(CurrBlock, *SI)) {
1387 BlockInfo.borrowInfo(*SI)->intersectAtLoopHead(
1390 if (BlockInfo.allBackEdgesVisited(CurrBlock, *SI))
1391 BlockInfo.discardInfo(*SI);
1393 BlockInfo.addInfo(*SI, RawState, CurrStates);
1397 CurrStates =
nullptr;
1401 if (CurrBlock == &AC.getCFG()->getExit() &&
1402 D->getCallResultType()->isVoidType())
1403 CurrStates->checkParamsForReturnTypestate(
D->
getLocation(),
1408 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 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.
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.
reverse_iterator rbegin()
CFGTerminator getTerminator() const
succ_iterator succ_begin()
Stmt * getTerminatorStmt()
AdjacentBlocks::const_iterator const_pred_iterator
unsigned pred_size() const
pred_iterator pred_begin()
unsigned getBlockID() const
AdjacentBlocks::const_iterator const_succ_iterator
unsigned succ_size() const
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
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 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.
bool isPointerOrReferenceType() const
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
The JSON file list parser is used to communicate input to InstallAPI.
@ Other
Other implicit parameter.