clang: lib/Analysis/Consumed.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

29#include "llvm/ADT/DenseMap.h"

30#include "llvm/Support/ErrorHandling.h"

31#include

32#include

33#include

34#include

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52using namespace clang;

54

55

57

59

60

61 for (const auto &B : *Block)

62 if (std::optional CS = B.getAs<CFGStmt>())

63 return CS->getStmt()->getBeginLoc();

64

65

66

67 if (Block->succ_size() == 1 && *Block->succ_begin())

69

70 return {};

71}

72

74

75

76 if (const Stmt *StmtNode = Block->getTerminatorStmt()) {

77 return StmtNode->getBeginLoc();

78 } else {

80 BE = Block->rend(); BI != BE; ++BI) {

81 if (std::optional CS = BI->getAs<CFGStmt>())

82 return CS->getStmt()->getBeginLoc();

83 }

84 }

85

86

88 if (Block->succ_size() == 1 && *Block->succ_begin())

91 return Loc;

92

93

94 if (Block->pred_size() == 1 && *Block->pred_begin())

96

97 return Loc;

98}

99

101 switch (State) {

110 }

111 llvm_unreachable("invalid enum");

112}

113

116 for (const auto &S : CWAttr->callableStates()) {

118

119 switch (S) {

120 case CallableWhenAttr::Unknown:

122 break;

123

124 case CallableWhenAttr::Unconsumed:

126 break;

127

128 case CallableWhenAttr::Consumed:

130 break;

131 }

132

133 if (MappedAttrState == State)

134 return true;

135 }

136

137 return false;

138}

139

142 return false;

143

145 return RD->hasAttr();

146

147 return false;

148}

149

152 return false;

153

155 return RD->hasAttr();

156

157 return false;

158}

159

162 return RD->hasAttr();

163 return false;

164}

165

167 switch (State) {

170 return true;

173 return false;

174 }

175 llvm_unreachable("invalid enum");

176}

177

181

183 return FunDecl->hasAttr();

184}

185

188

189 const ConsumableAttr *CAttr =

191

192 switch (CAttr->getDefaultState()) {

193 case ConsumableAttr::Unknown:

195 case ConsumableAttr::Unconsumed:

197 case ConsumableAttr::Consumed:

199 }

200 llvm_unreachable("invalid enum");

201}

202

205 switch (PTAttr->getParamState()) {

206 case ParamTypestateAttr::Unknown:

208 case ParamTypestateAttr::Unconsumed:

210 case ParamTypestateAttr::Consumed:

212 }

213 llvm_unreachable("invalid_enum");

214}

215

218 switch (RTSAttr->getState()) {

219 case ReturnTypestateAttr::Unknown:

221 case ReturnTypestateAttr::Unconsumed:

223 case ReturnTypestateAttr::Consumed:

225 }

226 llvm_unreachable("invalid enum");

227}

228

230 switch (STAttr->getNewState()) {

231 case SetTypestateAttr::Unknown:

233 case SetTypestateAttr::Unconsumed:

235 case SetTypestateAttr::Consumed:

237 }

238 llvm_unreachable("invalid_enum");

239}

240

242 switch (State) {

244 return "none";

245

247 return "unknown";

248

250 return "unconsumed";

251

253 return "consumed";

254 }

255 llvm_unreachable("invalid enum");

256}

257

260 switch (FunDecl->getAttr()->getTestState()) {

261 case TestTypestateAttr::Unconsumed:

263 case TestTypestateAttr::Consumed:

265 }

266 llvm_unreachable("invalid enum");

267}

268

269namespace {

270

271struct VarTestResult {

272 const VarDecl *Var;

274};

275

276}

277

280

285

287 enum {

288 IT_None,

289 IT_State,

290 IT_VarTest,

291 IT_BinTest,

292 IT_Var,

293 IT_Tmp

294 } InfoType = IT_None;

295

296 struct BinTestTy {

299 VarTestResult LTest;

300 VarTestResult RTest;

301 };

302

303 union {

309 };

310

311public:

315

317 : InfoType(IT_VarTest) {

319 VarTest.TestsFor = TestsFor;

320 }

321

323 const VarTestResult &LTest, const VarTestResult &RTest)

324 : InfoType(IT_BinTest) {

329 }

330

334 : InfoType(IT_BinTest) {

337 BinTest.LTest.Var = LVar;

338 BinTest.LTest.TestsFor = LTestsFor;

339 BinTest.RTest.Var = RVar;

340 BinTest.RTest.TestsFor = RTestsFor;

341 }

342

347 : InfoType(IT_Tmp), Tmp(Tmp) {}

348

350 assert(InfoType == IT_State);

352 }

353

355 assert(InfoType == IT_VarTest);

357 }

358

360 assert(InfoType == IT_BinTest);

362 }

363

365 assert(InfoType == IT_BinTest);

367 }

368

370 assert(InfoType == IT_Var);

371 return Var;

372 }

373

375 assert(InfoType == IT_Tmp);

376 return Tmp;

377 }

378

381

384 else if (isTmp())

388 else

390 }

391

393 assert(InfoType == IT_BinTest);

395 }

396

398 assert(InfoType == IT_BinTest);

400 }

401

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; }

408

410 return InfoType == IT_VarTest || InfoType == IT_BinTest;

411 }

412

414 return InfoType == IT_Var || InfoType == IT_Tmp;

415 }

416

418 assert(InfoType == IT_VarTest || InfoType == IT_BinTest);

419

420 if (InfoType == IT_VarTest) {

423

424 } else if (InfoType == IT_BinTest) {

429 } else {

430 return {};

431 }

432 }

433};

434

435}

436}

437

438static void

441 assert(PInfo.isVar() || PInfo.isTmp());

442

443 if (PInfo.isVar())

445 else

447}

448

451

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;

457

460 MapType PropagationMap;

461

462 InfoEntry findInfo(const Expr *E) {

463 if (const auto Cleanups = dyn_cast(E))

464 if (!Cleanups->cleanupsHaveSideEffects())

465 E = Cleanups->getSubExpr();

466 return PropagationMap.find(E->IgnoreParens());

467 }

468

469 ConstInfoEntry findInfo(const Expr *E) const {

470 if (const auto Cleanups = dyn_cast(E))

471 if (!Cleanups->cleanupsHaveSideEffects())

472 E = Cleanups->getSubExpr();

473 return PropagationMap.find(E->IgnoreParens());

474 }

475

477 PropagationMap.insert(PairType(E->IgnoreParens(), PI));

478 }

479

480 void forwardInfo(const Expr *From, const Expr *To);

485

486public:

492

508

510 : Analyzer(Analyzer), StateMap(StateMap) {}

511

513 ConstInfoEntry Entry = findInfo(StmtNode);

514

515 if (Entry != PropagationMap.end())

516 return Entry->second;

517 else

518 return {};

519 }

520

522 StateMap = NewStateMap;

523 }

524};

525

526}

527}

528

529void ConsumedStmtVisitor::forwardInfo(const Expr *From, const Expr *To) {

530 InfoEntry Entry = findInfo(From);

531 if (Entry != PropagationMap.end())

532 insertInfo(To, Entry->second);

533}

534

535

536

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));

547 }

548}

549

550

551ConsumedState ConsumedStmtVisitor::getInfo(const Expr *From) {

552 InfoEntry Entry = findInfo(From);

553 if (Entry != PropagationMap.end()) {

554 PropagationInfo& PInfo = Entry->second;

556 }

558}

559

560

561void ConsumedStmtVisitor::setInfo(const Expr *To, ConsumedState NS) {

562 InfoEntry Entry = findInfo(To);

563 if (Entry != PropagationMap.end()) {

564 PropagationInfo& PInfo = Entry->second;

567 } else if (NS != CS_None) {

568 insertInfo(To, PropagationInfo(NS));

569 }

570}

571

575 assert(!PInfo.isTest());

576

577 const CallableWhenAttr *CWAttr = FunDecl->getAttr();

578 if (!CWAttr)

579 return;

580

581 if (PInfo.isVar()) {

583

585 return;

586

587 Analyzer.WarningsHandler.warnUseInInvalidState(

590 } else {

592

594 return;

595

596 Analyzer.WarningsHandler.warnUseOfTempInInvalidState(

598 }

599}

600

601

602

603

606 unsigned Offset = 0;

608 Offset = 1;

609

610

611 for (unsigned Index = Offset; Index < Call->getNumArgs(); ++Index) {

612

614 break;

615

617 QualType ParamType = Param->getType();

618

619 InfoEntry Entry = findInfo(Call->getArg(Index));

620

621 if (Entry == PropagationMap.end() || Entry->second.isTest())

622 continue;

624

625

626 if (ParamTypestateAttr *PTA = Param->getAttr()) {

629

630 if (ParamState != ExpectedState)

631 Analyzer.WarningsHandler.warnParamTypestateMismatch(

632 Call->getArg(Index)->getExprLoc(),

634 }

635

636 if (!(Entry->second.isVar() || Entry->second.isTmp()))

637 continue;

638

639

640 if (ReturnTypestateAttr *RT = Param->getAttr())

648 }

649

650 if (!ObjArg)

651 return false;

652

653

654 InfoEntry Entry = findInfo(ObjArg);

655 if (Entry != PropagationMap.end()) {

658

659 if (SetTypestateAttr *STA = FunD->getAttr()) {

660 if (PInfo.isVar()) {

662 return true;

663 }

664 else if (PInfo.isTmp()) {

666 return true;

667 }

668 }

670 PropagationMap.insert(PairType(Call,

672 }

673 }

674 return false;

675}

676

677void ConsumedStmtVisitor::propagateReturnType(const Expr *Call,

682

685 if (ReturnTypestateAttr *RTA = Fun->getAttr())

687 else

689

691 }

692}

693

696 case BO_LAnd:

697 case BO_LOr : {

698 InfoEntry LEntry = findInfo(BinOp->getLHS()),

699 REntry = findInfo(BinOp->getRHS());

700

701 VarTestResult LTest, RTest;

702

703 if (LEntry != PropagationMap.end() && LEntry->second.isVarTest()) {

704 LTest = LEntry->second.getVarTest();

705 } else {

706 LTest.Var = nullptr;

707 LTest.TestsFor = CS_None;

708 }

709

710 if (REntry != PropagationMap.end() && REntry->second.isVarTest()) {

711 RTest = REntry->second.getVarTest();

712 } else {

713 RTest.Var = nullptr;

714 RTest.TestsFor = CS_None;

715 }

716

717 if (!(LTest.Var == nullptr && RTest.Var == nullptr))

718 PropagationMap.insert(PairType(BinOp, PropagationInfo(BinOp,

720 break;

721 }

722

723 case BO_PtrMemD:

724 case BO_PtrMemI:

725 forwardInfo(BinOp->getLHS(), BinOp);

726 break;

727

728 default:

729 break;

730 }

731}

732

735 if (!FunDecl)

736 return;

737

738

739

740 if (Call->isCallToStdMove()) {

742 return;

743 }

744

746 propagateReturnType(Call, FunDecl);

747}

748

750 forwardInfo(Cast->getSubExpr(), Cast);

751}

752

755

756 InfoEntry Entry = findInfo(Temp->getSubExpr());

757

758 if (Entry != PropagationMap.end() && !Entry->second.isTest()) {

759 StateMap->setState(Temp, Entry->second.getAsState(StateMap));

760 PropagationMap.insert(PairType(Temp, PropagationInfo(Temp)));

761 }

762}

763

766

768

770 return;

771

772

773 if (ReturnTypestateAttr *RTA = Constructor->getAttr()) {

774

777 } else if (Constructor->isDefaultConstructor()) {

778 PropagationMap.insert(PairType(Call,

780 } else if (Constructor->isMoveConstructor()) {

782 } else if (Constructor->isCopyConstructor()) {

783

787 copyInfo(Call->getArg(0), Call, NS);

788 } else {

789

792 }

793}

794

798 if (!MD)

799 return;

800

802 propagateReturnType(Call, MD);

803}

804

807 const auto *FunDecl = dyn_cast_or_null(Call->getDirectCallee());

808 if (!FunDecl) return;

809

810 if (Call->getOperator() == OO_Equal) {

813 setInfo(Call->getArg(0), CS);

814 return;

815 }

816

817 if (const auto *MCall = dyn_cast(Call))

818 handleCall(MCall, MCall->getImplicitObjectArgument(), FunDecl);

819 else

821

822 propagateReturnType(Call, FunDecl);

823}

824

826 if (const auto *Var = dyn_cast_or_null(DeclRef->getDecl()))

828 PropagationMap.insert(PairType(DeclRef, PropagationInfo(Var)));

829}

830

832 for (const auto *DI : DeclS->decls())

835

837 if (const auto *Var = dyn_cast_or_null(DeclS->getSingleDecl()))

838 PropagationMap.insert(PairType(DeclS, PropagationInfo(Var)));

839}

840

845

847 forwardInfo(MExpr->getBase(), MExpr);

848}

849

851 QualType ParamType = Param->getType();

853

854 if (const ParamTypestateAttr *PTA = Param->getAttr())

864

865 if (ParamState != CS_None)

866 StateMap->setState(Param, ParamState);

867}

868

870 ConsumedState ExpectedState = Analyzer.getExpectedReturnState();

871

872 if (ExpectedState != CS_None) {

873 InfoEntry Entry = findInfo(Ret->getRetValue());

874

875 if (Entry != PropagationMap.end()) {

876 ConsumedState RetState = Entry->second.getAsState(StateMap);

877

878 if (RetState != ExpectedState)

879 Analyzer.WarningsHandler.warnReturnTypestateMismatch(

880 Ret->getReturnLoc(), stateToString(ExpectedState),

882 }

883 }

884

885 StateMap->checkParamsForReturnTypestate(Ret->getBeginLoc(),

886 Analyzer.WarningsHandler);

887}

888

890 InfoEntry Entry = findInfo(UOp->getSubExpr());

891 if (Entry == PropagationMap.end()) return;

892

894 case UO_AddrOf:

895 PropagationMap.insert(PairType(UOp, Entry->second));

896 break;

897

898 case UO_LNot:

899 if (Entry->second.isTest())

900 PropagationMap.insert(PairType(UOp, Entry->second.invertTest()));

901 break;

902

903 default:

904 break;

905 }

906}

907

908

913 if (VIT != PropagationMap.end()) {

916

918 StateMap->setState(Var, St);

919 return;

920 }

921 }

922 }

923

925 }

926}

927

932

934 ThenStates->setState(Test.Var, Test.TestsFor);

938 } else if (VarState == Test.TestsFor) {

940 }

941}

942

946 const VarTestResult &LTest = PInfo.getLTest(),

948

950 RState = RTest.Var ? ThenStates->getState(RTest.Var) : CS_None;

951

952 if (LTest.Var) {

955 ThenStates->setState(LTest.Var, LTest.TestsFor);

958 } else if (LState == LTest.TestsFor && isKnownState(RState)) {

959 if (RState == RTest.TestsFor)

961 else

963 }

964 } else {

966 ElseStates->setState(LTest.Var,

968 } else if (LState == LTest.TestsFor) {

972 if (RState == RTest.TestsFor)

974 else

976 }

977 }

978 }

979

980 if (RTest.Var) {

983 ThenStates->setState(RTest.Var, RTest.TestsFor);

986 } else {

988 ElseStates->setState(RTest.Var,

990 else if (RState == RTest.TestsFor)

992 }

993 }

994}

995

997 const CFGBlock *TargetBlock) {

998 assert(CurrBlock && "Block pointer must not be NULL");

999 assert(TargetBlock && "TargetBlock pointer must not be NULL");

1000

1001 unsigned int CurrBlockOrder = VisitOrder[CurrBlock->getBlockID()];

1003 PE = TargetBlock->pred_end(); PI != PE; ++PI) {

1004 if (*PI && CurrBlockOrder < VisitOrder[(*PI)->getBlockID()] )

1005 return false;

1006 }

1007 return true;

1008}

1009

1012 std::unique_ptr &OwnedStateMap) {

1013 assert(Block && "Block pointer must not be NULL");

1014

1015 auto &Entry = StateMapsArray[Block->getBlockID()];

1016

1017 if (Entry) {

1018 Entry->intersect(*StateMap);

1019 } else if (OwnedStateMap)

1020 Entry = std::move(OwnedStateMap);

1021 else

1022 Entry = std::make_unique(*StateMap);

1023}

1024

1026 std::unique_ptr StateMap) {

1027 assert(Block && "Block pointer must not be NULL");

1028

1029 auto &Entry = StateMapsArray[Block->getBlockID()];

1030

1031 if (Entry) {

1032 Entry->intersect(*StateMap);

1033 } else {

1034 Entry = std::move(StateMap);

1035 }

1036}

1037

1039 assert(Block && "Block pointer must not be NULL");

1040 assert(StateMapsArray[Block->getBlockID()] && "Block has no block info");

1041

1042 return StateMapsArray[Block->getBlockID()].get();

1043}

1044

1046 StateMapsArray[Block->getBlockID()] = nullptr;

1047}

1048

1049std::unique_ptr

1051 assert(Block && "Block pointer must not be NULL");

1052

1053 auto &Entry = StateMapsArray[Block->getBlockID()];

1055 : std::move(Entry);

1056}

1057

1059 assert(From && "From block must not be NULL");

1060 assert(To && "From block must not be NULL");

1061

1063}

1064

1066 assert(Block && "Block pointer must not be NULL");

1067

1068

1069

1070 if (Block->pred_size() < 2)

1071 return false;

1072

1073 unsigned int BlockVisitOrder = VisitOrder[Block->getBlockID()];

1075 PE = Block->pred_end(); PI != PE; ++PI) {

1076 if (*PI && BlockVisitOrder < VisitOrder[(*PI)->getBlockID()])

1077 return true;

1078 }

1079 return false;

1080}

1081

1084

1085 for (const auto &DM : VarMap) {

1088 const ReturnTypestateAttr *RTA = Param->getAttr();

1089

1090 if (!RTA)

1091 continue;

1092

1094 if (DM.second != ExpectedState)

1096 Param->getNameAsString(), stateToString(ExpectedState),

1098 }

1099 }

1100}

1101

1105

1107 VarMapType::const_iterator Entry = VarMap.find(Var);

1108

1109 if (Entry != VarMap.end())

1110 return Entry->second;

1111

1113}

1114

1117 TmpMapType::const_iterator Entry = TmpMap.find(Tmp);

1118

1119 if (Entry != TmpMap.end())

1120 return Entry->second;

1121

1123}

1124

1127

1128 if (this->From && this->From == Other.From && Other.Reachable) {

1130 return;

1131 }

1132

1133 for (const auto &DM : Other.VarMap) {

1134 LocalState = this->getState(DM.first);

1135

1136 if (LocalState == CS_None)

1137 continue;

1138

1139 if (LocalState != DM.second)

1141 }

1142}

1143

1147

1150

1151 for (const auto &DM : LoopBackStates->VarMap) {

1152 LocalState = this->getState(DM.first);

1153

1154 if (LocalState == CS_None)

1155 continue;

1156

1157 if (LocalState != DM.second) {

1160 DM.first->getNameAsString());

1161 }

1162 }

1163}

1164

1170

1172 VarMap[Var] = State;

1173}

1174

1177 TmpMap[Tmp] = State;

1178}

1179

1183

1185 for (const auto &DM : Other->VarMap)

1186 if (this->getState(DM.first) != DM.second)

1187 return true;

1188 return false;

1189}

1190

1191void ConsumedAnalyzer::determineExpectedReturnState(AnalysisDeclContext &AC,

1194 if (const auto *Constructor = dyn_cast(D)) {

1195 ReturnType = Constructor->getFunctionObjectParameterType();

1196 } else

1198

1199 if (const ReturnTypestateAttr *RTSAttr = D->getAttr()) {

1201 if (!RD || !RD->hasAttr()) {

1202

1203

1204

1205

1207 RTSAttr->getLocation(), ReturnType.getAsString());

1208 ExpectedReturnState = CS_None;

1209 } else

1212 if (isAutoCastType(ReturnType))

1213 ExpectedReturnState = CS_None;

1214 else

1216 }

1217 else

1218 ExpectedReturnState = CS_None;

1219}

1220

1221bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,

1223 std::unique_ptr FalseStates(

1224 new ConsumedStateMap(*CurrStates));

1225 PropagationInfo PInfo;

1226

1227 if (const auto *IfNode =

1229 if (IfNode->isConsteval())

1230 return false;

1231

1232 const Expr *Cond = IfNode->getCond();

1233

1234 PInfo = Visitor.getInfo(Cond);

1237

1239 CurrStates->setSource(Cond);

1240 FalseStates->setSource(Cond);

1242 FalseStates.get());

1247 } else {

1248 return false;

1249 }

1250 } else if (const auto *BinOp =

1252 PInfo = Visitor.getInfo(BinOp->getLHS());

1254 if ((BinOp = dyn_cast_or_null(BinOp->getLHS()))) {

1255 PInfo = Visitor.getInfo(BinOp->getRHS());

1256

1258 return false;

1259 } else {

1260 return false;

1261 }

1262 }

1263

1264 CurrStates->setSource(BinOp);

1265 FalseStates->setSource(BinOp);

1266

1267 const VarTestResult &Test = PInfo.getVarTest();

1268 ConsumedState VarState = CurrStates->getState(Test.Var);

1269

1270 if (BinOp->getOpcode() == BO_LAnd) {

1272 CurrStates->setState(Test.Var, Test.TestsFor);

1274 CurrStates->markUnreachable();

1275

1276 } else if (BinOp->getOpcode() == BO_LOr) {

1278 FalseStates->setState(Test.Var,

1280 else if (VarState == Test.TestsFor)

1281 FalseStates->markUnreachable();

1282 }

1283 } else {

1284 return false;

1285 }

1286

1288

1289 if (*SI)

1290 BlockInfo.addInfo(*SI, std::move(CurrStates));

1291 else

1292 CurrStates = nullptr;

1293

1294 if (*++SI)

1295 BlockInfo.addInfo(*SI, std::move(FalseStates));

1296

1297 return true;

1298}

1299

1301 const auto *D = dyn_cast_or_null(AC.getDecl());

1302 if (!D)

1303 return;

1304

1306 if (!CFGraph)

1307 return;

1308

1309 determineExpectedReturnState(AC, D);

1310

1312

1313

1315

1316 CurrStates = std::make_unique();

1318

1319

1320 for (const auto *PI : D->parameters())

1322

1323

1324 for (const auto *CurrBlock : *SortedGraph) {

1325 if (!CurrStates)

1326 CurrStates = BlockInfo.getInfo(CurrBlock);

1327

1328 if (!CurrStates) {

1329 continue;

1330 } else if (!CurrStates->isReachable()) {

1331 CurrStates = nullptr;

1332 continue;

1333 }

1334

1335 Visitor.reset(CurrStates.get());

1336

1337

1338 for (const auto &B : *CurrBlock) {

1339 switch (B.getKind()) {

1342 break;

1343

1347

1350 BTE->getExprLoc());

1351 CurrStates->remove(BTE);

1352 break;

1353 }

1354

1358 if (!DD)

1359 break;

1360

1364 break;

1365 }

1366

1367 default:

1368 break;

1369 }

1370 }

1371

1372

1373

1374 if (!splitState(CurrBlock, Visitor)) {

1375 CurrStates->setSource(nullptr);

1376

1377 if (CurrBlock->succ_size() > 1 ||

1378 (CurrBlock->succ_size() == 1 &&

1379 (*CurrBlock->succ_begin())->pred_size() > 1)) {

1380

1381 auto *RawState = CurrStates.get();

1382

1384 SE = CurrBlock->succ_end(); SI != SE; ++SI) {

1385 if (*SI == nullptr) continue;

1386

1387 if (BlockInfo.isBackEdge(CurrBlock, *SI)) {

1388 BlockInfo.borrowInfo(*SI)->intersectAtLoopHead(

1390

1391 if (BlockInfo.allBackEdgesVisited(CurrBlock, *SI))

1392 BlockInfo.discardInfo(*SI);

1393 } else {

1394 BlockInfo.addInfo(*SI, RawState, CurrStates);

1395 }

1396 }

1397

1398 CurrStates = nullptr;

1399 }

1400 }

1401

1404 CurrStates->checkParamsForReturnTypestate(D->getLocation(),

1406 }

1407

1408

1409 CurrStates = nullptr;

1410

1412}

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)

Definition Consumed.cpp:943

static ConsumedState invertConsumedUnconsumed(ConsumedState State)

Definition Consumed.cpp:100

static bool isCallableInState(const CallableWhenAttr *CWAttr, ConsumedState State)

Definition Consumed.cpp:114

static ConsumedState mapParamTypestateAttrState(const ParamTypestateAttr *PTAttr)

Definition Consumed.cpp:204

static bool isRValueRef(QualType ParamType)

Definition Consumed.cpp:178

static ConsumedState mapReturnTypestateAttrState(const ReturnTypestateAttr *RTSAttr)

Definition Consumed.cpp:217

static ConsumedState testsFor(const FunctionDecl *FunDecl)

Definition Consumed.cpp:258

static bool isConsumableType(const QualType &QT)

Definition Consumed.cpp:140

static StringRef stateToString(ConsumedState State)

Definition Consumed.cpp:241

static void splitVarStateForIf(const IfStmt *IfNode, const VarTestResult &Test, ConsumedStateMap *ThenStates, ConsumedStateMap *ElseStates)

Definition Consumed.cpp:928

static bool isTestingFunction(const FunctionDecl *FunDecl)

Definition Consumed.cpp:182

static bool isAutoCastType(const QualType &QT)

Definition Consumed.cpp:150

static SourceLocation getFirstStmtLoc(const CFGBlock *Block)

Definition Consumed.cpp:58

static void setStateForVarOrTmp(ConsumedStateMap *StateMap, const PropagationInfo &PInfo, ConsumedState State)

Definition Consumed.cpp:439

static ConsumedState mapConsumableAttrState(const QualType QT)

Definition Consumed.cpp:186

static ConsumedState mapSetTypestateAttrState(const SetTypestateAttr *STAttr)

Definition Consumed.cpp:229

static SourceLocation getLastStmtLoc(const CFGBlock *Block)

Definition Consumed.cpp:73

static bool isSetOnReadPtrType(const QualType &QT)

Definition Consumed.cpp:160

static bool isKnownState(ConsumedState State)

Definition Consumed.cpp:166

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.

Definition Consumed.cpp:1300

ConsumedStateMap * borrowInfo(const CFGBlock *Block)

Definition Consumed.cpp:1038

bool isBackEdgeTarget(const CFGBlock *Block)

Definition Consumed.cpp:1065

std::unique_ptr< ConsumedStateMap > getInfo(const CFGBlock *Block)

Definition Consumed.cpp:1050

void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap, std::unique_ptr< ConsumedStateMap > &OwnedStateMap)

Definition Consumed.cpp:1010

void discardInfo(const CFGBlock *Block)

Definition Consumed.cpp:1045

bool allBackEdgesVisited(const CFGBlock *CurrBlock, const CFGBlock *TargetBlock)

Definition Consumed.cpp:996

bool isBackEdge(const CFGBlock *From, const CFGBlock *To)

Definition Consumed.cpp:1058

void clearTemporaries()

Clear the TmpMap.

Definition Consumed.cpp:1102

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...

Definition Consumed.cpp:1082

void intersect(const ConsumedStateMap &Other)

Merge this state map with another map.

Definition Consumed.cpp:1125

ConsumedState getState(const VarDecl *Var) const

Get the consumed state of a given variable.

Definition Consumed.cpp:1106

void intersectAtLoopHead(const CFGBlock *LoopHead, const CFGBlock *LoopBack, const ConsumedStateMap *LoopBackStates, ConsumedWarningsHandlerBase &WarningsHandler)

Definition Consumed.cpp:1144

void remove(const CXXBindTemporaryExpr *Tmp)

Remove the temporary value from our state map.

Definition Consumed.cpp:1180

void markUnreachable()

Mark the block as unreachable.

Definition Consumed.cpp:1165

bool operator!=(const ConsumedStateMap *Other) const

Tests to see if there is a mismatch in the states stored in two maps.

Definition Consumed.cpp:1184

ConsumedStateMap()=default

void setState(const VarDecl *Var, ConsumedState State)

Set the consumed state of a given variable.

Definition Consumed.cpp:1171

Definition Consumed.cpp:452

void VisitUnaryOperator(const UnaryOperator *UOp)

Definition Consumed.cpp:889

PropagationInfo getInfo(const Expr *StmtNode) const

Definition Consumed.cpp:512

void VisitVarDecl(const VarDecl *Var)

Definition Consumed.cpp:909

void VisitCXXMemberCallExpr(const CXXMemberCallExpr *Call)

Definition Consumed.cpp:795

void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Temp)

Definition Consumed.cpp:753

void VisitMemberExpr(const MemberExpr *MExpr)

Definition Consumed.cpp:846

void reset(ConsumedStateMap *NewStateMap)

Definition Consumed.cpp:521

void VisitReturnStmt(const ReturnStmt *Ret)

Definition Consumed.cpp:869

void VisitDeclStmt(const DeclStmt *DelcS)

Definition Consumed.cpp:831

void checkCallability(const PropagationInfo &PInfo, const FunctionDecl *FunDecl, SourceLocation BlameLoc)

Definition Consumed.cpp:572

void VisitCallExpr(const CallExpr *Call)

Definition Consumed.cpp:733

void VisitDeclRefExpr(const DeclRefExpr *DeclRef)

Definition Consumed.cpp:825

void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Temp)

Definition Consumed.cpp:841

bool handleCall(const CallExpr *Call, const Expr *ObjArg, const FunctionDecl *FunD)

Definition Consumed.cpp:604

ConsumedStmtVisitor(ConsumedAnalyzer &Analyzer, ConsumedStateMap *StateMap)

Definition Consumed.cpp:509

void VisitCXXConstructExpr(const CXXConstructExpr *Call)

Definition Consumed.cpp:764

void VisitBinaryOperator(const BinaryOperator *BinOp)

Definition Consumed.cpp:694

void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Call)

Definition Consumed.cpp:805

void VisitCastExpr(const CastExpr *Cast)

Definition Consumed.cpp:749

void VisitParmVarDecl(const ParmVarDecl *Param)

Definition Consumed.cpp:850

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.

Definition Consumed.cpp:286

const VarTestResult & getRTest() const

Definition Consumed.cpp:364

PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp, const VarTestResult &LTest, const VarTestResult &RTest)

Definition Consumed.cpp:322

const CXXBindTemporaryExpr * Tmp

Definition Consumed.cpp:307

PropagationInfo(const VarTestResult &VarTest)

Definition Consumed.cpp:313

EffectiveOp testEffectiveOp() const

Definition Consumed.cpp:392

PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp, const VarDecl *LVar, ConsumedState LTestsFor, const VarDecl *RVar, ConsumedState RTestsFor)

Definition Consumed.cpp:331

const ConsumedState & getState() const

Definition Consumed.cpp:349

bool isVarTest() const

Definition Consumed.cpp:404

bool isState() const

Definition Consumed.cpp:403

const VarTestResult & getVarTest() const

Definition Consumed.cpp:354

bool isBinTest() const

Definition Consumed.cpp:405

const VarDecl * getVar() const

Definition Consumed.cpp:369

bool isTest() const

Definition Consumed.cpp:409

PropagationInfo(ConsumedState State)

Definition Consumed.cpp:343

PropagationInfo(const VarDecl *Var)

Definition Consumed.cpp:345

ConsumedState State

Definition Consumed.cpp:304

bool isValid() const

Definition Consumed.cpp:402

PropagationInfo(const VarDecl *Var, ConsumedState TestsFor)

Definition Consumed.cpp:316

PropagationInfo(const CXXBindTemporaryExpr *Tmp)

Definition Consumed.cpp:346

const VarTestResult & getLTest() const

Definition Consumed.cpp:359

bool isPointerToValue() const

Definition Consumed.cpp:413

bool isTmp() const

Definition Consumed.cpp:407

PropagationInfo()=default

const CXXBindTemporaryExpr * getTmp() const

Definition Consumed.cpp:374

PropagationInfo invertTest() const

Definition Consumed.cpp:417

bool isVar() const

Definition Consumed.cpp:406

ConsumedState getAsState(const ConsumedStateMap *StateMap) const

Definition Consumed.cpp:379

VarTestResult VarTest

Definition Consumed.cpp:305

BinTestTy BinTest

Definition Consumed.cpp:308

const VarDecl * Var

Definition Consumed.cpp:306

const BinaryOperator * testSourceNode() const

Definition Consumed.cpp:397

EffectiveOp

Definition Consumed.cpp:281

@ EO_Or

Definition Consumed.cpp:283

@ EO_And

Definition Consumed.cpp:282

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.