29#include "llvm/ADT/DenseMap.h"
30#include "llvm/Support/ErrorHandling.h"
53using namespace consumed;
61 for (
const auto &B : *
Block)
62 if (std::optional<CFGStmt> CS = B.getAs<
CFGStmt>())
63 return CS->getStmt()->getBeginLoc();
77 return StmtNode->getBeginLoc();
81 if (std::optional<CFGStmt> CS = BI->getAs<
CFGStmt>())
82 return CS->getStmt()->getBeginLoc();
111 llvm_unreachable(
"invalid enum");
116 for (
const auto &S : CWAttr->callableStates()) {
120 case CallableWhenAttr::Unknown:
124 case CallableWhenAttr::Unconsumed:
128 case CallableWhenAttr::Consumed:
133 if (MappedAttrState == State)
145 return RD->hasAttr<ConsumableAttr>();
155 return RD->hasAttr<ConsumableAutoCastAttr>();
162 return RD->hasAttr<ConsumableSetOnReadAttr>();
175 llvm_unreachable(
"invalid enum");
183 return FunDecl->
hasAttr<TestTypestateAttr>();
189 const ConsumableAttr *CAttr =
192 switch (CAttr->getDefaultState()) {
193 case ConsumableAttr::Unknown:
195 case ConsumableAttr::Unconsumed:
197 case ConsumableAttr::Consumed:
200 llvm_unreachable(
"invalid enum");
205 switch (PTAttr->getParamState()) {
206 case ParamTypestateAttr::Unknown:
208 case ParamTypestateAttr::Unconsumed:
210 case ParamTypestateAttr::Consumed:
213 llvm_unreachable(
"invalid_enum");
218 switch (RTSAttr->getState()) {
219 case ReturnTypestateAttr::Unknown:
221 case ReturnTypestateAttr::Unconsumed:
223 case ReturnTypestateAttr::Consumed:
226 llvm_unreachable(
"invalid enum");
230 switch (STAttr->getNewState()) {
231 case SetTypestateAttr::Unknown:
233 case SetTypestateAttr::Unconsumed:
235 case SetTypestateAttr::Consumed:
238 llvm_unreachable(
"invalid_enum");
255 llvm_unreachable(
"invalid enum");
260 switch (FunDecl->
getAttr<TestTypestateAttr>()->getTestState()) {
261 case TestTypestateAttr::Unconsumed:
263 case TestTypestateAttr::Consumed:
266 llvm_unreachable(
"invalid enum");
271struct VarTestResult {
294 } InfoType = IT_None;
317 : InfoType(IT_VarTest) {
323 const VarTestResult <est,
const VarTestResult &RTest)
324 : InfoType(IT_BinTest) {
334 : InfoType(IT_BinTest) {
338 BinTest.LTest.TestsFor = LTestsFor;
340 BinTest.RTest.TestsFor = RTestsFor;
347 : InfoType(IT_Tmp),
Tmp(
Tmp) {}
350 assert(InfoType == IT_State);
355 assert(InfoType == IT_VarTest);
360 assert(InfoType == IT_BinTest);
365 assert(InfoType == IT_BinTest);
370 assert(InfoType == IT_Var);
375 assert(InfoType == IT_Tmp);
393 assert(InfoType == IT_BinTest);
398 assert(InfoType == IT_BinTest);
402 bool isValid()
const {
return InfoType != IT_None; }
403 bool isState()
const {
return InfoType == IT_State; }
404 bool isVarTest()
const {
return InfoType == IT_VarTest; }
405 bool isBinTest()
const {
return InfoType == IT_BinTest; }
406 bool isVar()
const {
return InfoType == IT_Var; }
407 bool isTmp()
const {
return InfoType == IT_Tmp; }
410 return InfoType == IT_VarTest || InfoType == IT_BinTest;
414 return InfoType == IT_Var || InfoType == IT_Tmp;
418 assert(InfoType == IT_VarTest || InfoType == IT_BinTest);
420 if (InfoType == IT_VarTest) {
424 }
else if (InfoType == IT_BinTest) {
453 using MapType = llvm::DenseMap<const Stmt *, PropagationInfo>;
454 using PairType= std::pair<const Stmt *, PropagationInfo>;
455 using InfoEntry = MapType::iterator;
456 using ConstInfoEntry = MapType::const_iterator;
460 MapType PropagationMap;
462 InfoEntry findInfo(
const Expr *
E) {
463 if (
const auto Cleanups = dyn_cast<ExprWithCleanups>(
E))
464 if (!Cleanups->cleanupsHaveSideEffects())
465 E = Cleanups->getSubExpr();
469 ConstInfoEntry findInfo(
const Expr *
E)
const {
470 if (
const auto Cleanups = dyn_cast<ExprWithCleanups>(
E))
471 if (!Cleanups->cleanupsHaveSideEffects())
472 E = Cleanups->getSubExpr();
480 void forwardInfo(
const Expr *From,
const Expr *To);
510 : Analyzer(Analyzer), StateMap(StateMap) {}
513 ConstInfoEntry Entry = findInfo(StmtNode);
515 if (Entry != PropagationMap.end())
516 return Entry->second;
522 StateMap = NewStateMap;
529void ConsumedStmtVisitor::forwardInfo(
const Expr *From,
const Expr *To) {
530 InfoEntry Entry = findInfo(From);
531 if (Entry != PropagationMap.end())
532 insertInfo(To, Entry->second);
537void ConsumedStmtVisitor::copyInfo(
const Expr *From,
const Expr *To,
539 InfoEntry Entry = findInfo(From);
540 if (Entry != PropagationMap.end()) {
552 InfoEntry Entry = findInfo(From);
553 if (Entry != PropagationMap.end()) {
562 InfoEntry Entry = findInfo(To);
563 if (Entry != PropagationMap.end()) {
577 const CallableWhenAttr *CWAttr = FunDecl->
getAttr<CallableWhenAttr>();
607 if (isa<CXXOperatorCallExpr>(
Call) && isa<CXXMethodDecl>(FunD))
611 for (
unsigned Index = Offset; Index <
Call->getNumArgs(); ++Index) {
619 InfoEntry Entry = findInfo(
Call->getArg(Index));
621 if (Entry == PropagationMap.end() || Entry->second.isTest())
626 if (ParamTypestateAttr *PTA = Param->
getAttr<ParamTypestateAttr>()) {
630 if (ParamState != ExpectedState)
632 Call->getArg(Index)->getExprLoc(),
636 if (!(Entry->second.isVar() || Entry->second.isTmp()))
640 if (ReturnTypestateAttr *RT = Param->
getAttr<ReturnTypestateAttr>())
654 InfoEntry Entry = findInfo(ObjArg);
655 if (Entry != PropagationMap.end()) {
659 if (SetTypestateAttr *STA = FunD->
getAttr<SetTypestateAttr>()) {
664 else if (PInfo.
isTmp()) {
670 PropagationMap.insert(PairType(
Call,
677void ConsumedStmtVisitor::propagateReturnType(
const Expr *
Call,
685 if (ReturnTypestateAttr *RTA = Fun->
getAttr<ReturnTypestateAttr>())
698 InfoEntry LEntry = findInfo(BinOp->
getLHS()),
699 REntry = findInfo(BinOp->
getRHS());
701 VarTestResult LTest, RTest;
703 if (LEntry != PropagationMap.end() && LEntry->second.isVarTest()) {
704 LTest = LEntry->second.getVarTest();
710 if (REntry != PropagationMap.end() && REntry->second.isVarTest()) {
711 RTest = REntry->second.getVarTest();
717 if (!(LTest.Var ==
nullptr && RTest.Var ==
nullptr))
725 forwardInfo(BinOp->
getLHS(), BinOp);
740 if (
Call->isCallToStdMove()) {
746 propagateReturnType(
Call, FunDecl);
750 forwardInfo(Cast->getSubExpr(), Cast);
756 InfoEntry Entry = findInfo(Temp->
getSubExpr());
758 if (Entry != PropagationMap.end() && !Entry->second.isTest()) {
759 StateMap->
setState(Temp, Entry->second.getAsState(StateMap));
773 if (ReturnTypestateAttr *RTA =
Constructor->getAttr<ReturnTypestateAttr>()) {
778 PropagationMap.insert(PairType(
Call,
787 copyInfo(
Call->getArg(0),
Call, NS);
802 propagateReturnType(
Call, MD);
807 const auto *FunDecl = dyn_cast_or_null<FunctionDecl>(
Call->getDirectCallee());
808 if (!FunDecl)
return;
810 if (
Call->getOperator() == OO_Equal) {
813 setInfo(
Call->getArg(0), CS);
817 if (
const auto *MCall = dyn_cast<CXXMemberCallExpr>(
Call))
818 handleCall(MCall, MCall->getImplicitObjectArgument(), FunDecl);
822 propagateReturnType(
Call, FunDecl);
826 if (
const auto *Var = dyn_cast_or_null<VarDecl>(DeclRef->
getDecl()))
832 for (
const auto *DI : DeclS->
decls())
833 if (isa<VarDecl>(DI))
837 if (
const auto *Var = dyn_cast_or_null<VarDecl>(DeclS->
getSingleDecl()))
847 forwardInfo(MExpr->
getBase(), MExpr);
854 if (
const ParamTypestateAttr *PTA = Param->
getAttr<ParamTypestateAttr>())
866 StateMap->
setState(Param, ParamState);
872 if (ExpectedState !=
CS_None) {
873 InfoEntry Entry = findInfo(Ret->getRetValue());
875 if (Entry != PropagationMap.end()) {
878 if (RetState != ExpectedState)
890 InfoEntry Entry = findInfo(UOp->
getSubExpr());
891 if (Entry == PropagationMap.end())
return;
895 PropagationMap.insert(PairType(UOp, Entry->second));
899 if (Entry->second.isTest())
900 PropagationMap.insert(PairType(UOp, Entry->second.invertTest()));
913 if (VIT != PropagationMap.end()) {
934 ThenStates->
setState(Test.Var, Test.TestsFor);
938 }
else if (VarState == Test.TestsFor) {
946 const VarTestResult <est = PInfo.
getLTest(),
955 ThenStates->
setState(LTest.Var, LTest.TestsFor);
958 }
else if (LState == LTest.TestsFor &&
isKnownState(RState)) {
959 if (RState == RTest.TestsFor)
968 }
else if (LState == LTest.TestsFor) {
972 if (RState == RTest.TestsFor)
983 ThenStates->
setState(RTest.Var, RTest.TestsFor);
990 else if (RState == RTest.TestsFor)
998 assert(CurrBlock &&
"Block pointer must not be NULL");
999 assert(TargetBlock &&
"TargetBlock pointer must not be NULL");
1001 unsigned int CurrBlockOrder = VisitOrder[CurrBlock->
getBlockID()];
1003 PE = TargetBlock->
pred_end(); PI != PE; ++PI) {
1004 if (*PI && CurrBlockOrder < VisitOrder[(*PI)->getBlockID()] )
1012 std::unique_ptr<ConsumedStateMap> &OwnedStateMap) {
1013 assert(
Block &&
"Block pointer must not be NULL");
1015 auto &Entry = StateMapsArray[
Block->getBlockID()];
1018 Entry->intersect(*StateMap);
1019 }
else if (OwnedStateMap)
1020 Entry = std::move(OwnedStateMap);
1022 Entry = std::make_unique<ConsumedStateMap>(*StateMap);
1026 std::unique_ptr<ConsumedStateMap> StateMap) {
1027 assert(
Block &&
"Block pointer must not be NULL");
1029 auto &Entry = StateMapsArray[
Block->getBlockID()];
1032 Entry->intersect(*StateMap);
1034 Entry = std::move(StateMap);
1039 assert(
Block &&
"Block pointer must not be NULL");
1040 assert(StateMapsArray[
Block->getBlockID()] &&
"Block has no block info");
1042 return StateMapsArray[
Block->getBlockID()].get();
1046 StateMapsArray[
Block->getBlockID()] =
nullptr;
1049std::unique_ptr<ConsumedStateMap>
1051 assert(
Block &&
"Block pointer must not be NULL");
1053 auto &Entry = StateMapsArray[
Block->getBlockID()];
1059 assert(From &&
"From block must not be NULL");
1060 assert(To &&
"From block must not be NULL");
1066 assert(
Block &&
"Block pointer must not be NULL");
1070 if (
Block->pred_size() < 2)
1073 unsigned int BlockVisitOrder = VisitOrder[
Block->getBlockID()];
1075 PE =
Block->pred_end(); PI != PE; ++PI) {
1076 if (*PI && BlockVisitOrder < VisitOrder[(*PI)->getBlockID()])
1085 for (
const auto &DM :
VarMap) {
1086 if (isa<ParmVarDecl>(DM.first)) {
1087 const auto *Param = cast<ParmVarDecl>(DM.first);
1088 const ReturnTypestateAttr *RTA = Param->getAttr<ReturnTypestateAttr>();
1094 if (DM.second != ExpectedState)
1107 VarMapType::const_iterator Entry =
VarMap.find(Var);
1109 if (Entry !=
VarMap.end())
1110 return Entry->second;
1117 TmpMapType::const_iterator Entry =
TmpMap.find(Tmp);
1119 if (Entry !=
TmpMap.end())
1120 return Entry->second;
1128 if (this->From && this->From ==
Other.From && !
Other.Reachable) {
1133 for (
const auto &DM :
Other.VarMap) {
1134 LocalState = this->
getState(DM.first);
1139 if (LocalState != DM.second)
1151 for (
const auto &DM : LoopBackStates->
VarMap) {
1152 LocalState = this->
getState(DM.first);
1157 if (LocalState != DM.second) {
1160 DM.first->getNameAsString());
1185 for (
const auto &DM :
Other->VarMap)
1186 if (this->
getState(DM.first) != DM.second)
1194 if (
const auto *
Constructor = dyn_cast<CXXConstructorDecl>(
D)) {
1195 ReturnType =
Constructor->getFunctionObjectParameterType();
1197 ReturnType =
D->getCallResultType();
1199 if (
const ReturnTypestateAttr *RTSAttr =
D->
getAttr<ReturnTypestateAttr>()) {
1201 if (!RD || !RD->
hasAttr<ConsumableAttr>()) {
1207 RTSAttr->getLocation(), ReturnType.
getAsString());
1208 ExpectedReturnState =
CS_None;
1213 ExpectedReturnState =
CS_None;
1218 ExpectedReturnState =
CS_None;
1221bool ConsumedAnalyzer::splitState(
const CFGBlock *CurrBlock,
1223 std::unique_ptr<ConsumedStateMap> FalseStates(
1227 if (
const auto *IfNode =
1229 if (IfNode->isConsteval())
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
bool isRValueReferenceType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
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.