29#include "llvm/ADT/DenseMap.h" 
   30#include "llvm/Support/ErrorHandling.h" 
   61  for (
const auto &B : *
Block)
 
   62    if (std::optional<CFGStmt> CS = B.getAs<
CFGStmt>())
 
   63      return CS->getStmt()->getBeginLoc();
 
   67  if (
Block->succ_size() == 1 && *
Block->succ_begin())
 
 
   76  if (
const Stmt *StmtNode = 
Block->getTerminatorStmt()) {
 
   77    return StmtNode->getBeginLoc();
 
   80         BE = 
Block->rend(); BI != BE; ++BI) {
 
   81      if (std::optional<CFGStmt> CS = BI->getAs<
CFGStmt>())
 
   82        return CS->getStmt()->getBeginLoc();
 
   88  if (
Block->succ_size() == 1 && *
Block->succ_begin())
 
   94  if (
Block->pred_size() == 1 && *
Block->pred_begin())
 
 
  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()) {
 
  541    PropagationInfo& PInfo = Entry->second;
 
  544      insertInfo(To, PropagationInfo(CS));
 
  551ConsumedState ConsumedStmtVisitor::getInfo(
const Expr *From) {
 
  552  InfoEntry Entry = findInfo(From);
 
  553  if (Entry != PropagationMap.end()) {
 
  554    PropagationInfo& PInfo = Entry->second;
 
  561void ConsumedStmtVisitor::setInfo(
const Expr *To, 
ConsumedState NS) {
 
  562  InfoEntry Entry = findInfo(To);
 
  563  if (Entry != PropagationMap.end()) {
 
  564    PropagationInfo& PInfo = Entry->second;
 
  568     insertInfo(To, PropagationInfo(NS));
 
  577  const CallableWhenAttr *CWAttr = FunDecl->
getAttr<CallableWhenAttr>();
 
  587    Analyzer.WarningsHandler.warnUseInInvalidState(
 
  596    Analyzer.WarningsHandler.warnUseOfTempInInvalidState(
 
 
  611  for (
unsigned Index = Offset; Index < 
Call->getNumArgs(); ++Index) {
 
  617    QualType ParamType = Param->getType();
 
  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)
 
  631        Analyzer.WarningsHandler.warnParamTypestateMismatch(
 
  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())
 
  837    if (
const auto *Var = dyn_cast_or_null<VarDecl>(DeclS->
getSingleDecl()))
 
 
  847  forwardInfo(MExpr->
getBase(), MExpr);
 
 
  851  QualType ParamType = Param->getType();
 
  854  if (
const ParamTypestateAttr *PTA = Param->getAttr<ParamTypestateAttr>())
 
  866    StateMap->setState(Param, ParamState);
 
 
  870  ConsumedState ExpectedState = Analyzer.getExpectedReturnState();
 
  872  if (ExpectedState != 
CS_None) {
 
  873    InfoEntry Entry = findInfo(Ret->getRetValue());
 
  875    if (Entry != PropagationMap.end()) {
 
  878      if (RetState != ExpectedState)
 
  879        Analyzer.WarningsHandler.warnReturnTypestateMismatch(
 
  885  StateMap->checkParamsForReturnTypestate(Ret->getBeginLoc(),
 
  886                                          Analyzer.WarningsHandler);
 
 
  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()) {
 
  918          StateMap->setState(Var, St);
 
 
  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) {
 
 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();
 
 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(
 
 1224      new ConsumedStateMap(*CurrStates));
 
 1225  PropagationInfo PInfo;
 
 1227  if (
const auto *IfNode =
 
 1229    if (IfNode->isConsteval())
 
 1232    const Expr *
Cond = IfNode->getCond();
 
 1234    PInfo = Visitor.getInfo(
Cond);
 
 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());
 
 1309  determineExpectedReturnState(AC, D);
 
 1316  CurrStates = std::make_unique<ConsumedStateMap>();
 
 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;
 
 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.
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.
ElementList::const_reverse_iterator const_reverse_iterator
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
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
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
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.
ConsumedStateMap()=default
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 warnLoopStateMismatch(SourceLocation Loc, StringRef VariableName)
Warn that a variable's state doesn't match at the entry and exit of a loop.
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.
bool isa(CodeGen::Address addr)
U cast(CodeGen::Address addr)
@ Other
Other implicit parameter.