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/ADT/STLExtras.h"

31#include "llvm/ADT/StringRef.h"

32#include "llvm/Support/Casting.h"

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

34#include

35#include

36#include

37#include

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55using namespace clang;

56using namespace consumed;

57

58

60

62

63

64 for (const auto &B : *Block)

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

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

67

68

69

72

73 return {};

74}

75

77

78

80 return StmtNode->getBeginLoc();

81 } else {

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

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

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

86 }

87 }

88

89

94 return Loc;

95

96

99

100 return Loc;

101}

102

104 switch (State) {

113 }

114 llvm_unreachable("invalid enum");

115}

116

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

121

122 switch (S) {

123 case CallableWhenAttr::Unknown:

125 break;

126

127 case CallableWhenAttr::Unconsumed:

129 break;

130

131 case CallableWhenAttr::Consumed:

133 break;

134 }

135

136 if (MappedAttrState == State)

137 return true;

138 }

139

140 return false;

141}

142

145 return false;

146

148 return RD->hasAttr();

149

150 return false;

151}

152

155 return false;

156

158 return RD->hasAttr();

159

160 return false;

161}

162

165 return RD->hasAttr();

166 return false;

167}

168

170 switch (State) {

173 return true;

176 return false;

177 }

178 llvm_unreachable("invalid enum");

179}

180

183}

184

186 return FunDecl->hasAttr();

187}

188

191

192 const ConsumableAttr *CAttr =

194

195 switch (CAttr->getDefaultState()) {

196 case ConsumableAttr::Unknown:

198 case ConsumableAttr::Unconsumed:

200 case ConsumableAttr::Consumed:

202 }

203 llvm_unreachable("invalid enum");

204}

205

208 switch (PTAttr->getParamState()) {

209 case ParamTypestateAttr::Unknown:

211 case ParamTypestateAttr::Unconsumed:

213 case ParamTypestateAttr::Consumed:

215 }

216 llvm_unreachable("invalid_enum");

217}

218

221 switch (RTSAttr->getState()) {

222 case ReturnTypestateAttr::Unknown:

224 case ReturnTypestateAttr::Unconsumed:

226 case ReturnTypestateAttr::Consumed:

228 }

229 llvm_unreachable("invalid enum");

230}

231

233 switch (STAttr->getNewState()) {

234 case SetTypestateAttr::Unknown:

236 case SetTypestateAttr::Unconsumed:

238 case SetTypestateAttr::Consumed:

240 }

241 llvm_unreachable("invalid_enum");

242}

243

245 switch (State) {

247 return "none";

248

250 return "unknown";

251

253 return "unconsumed";

254

256 return "consumed";

257 }

258 llvm_unreachable("invalid enum");

259}

260

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

264 case TestTypestateAttr::Unconsumed:

266 case TestTypestateAttr::Consumed:

268 }

269 llvm_unreachable("invalid enum");

270}

271

272namespace {

273

274struct VarTestResult {

277};

278

279}

280

282namespace consumed {

283

288

290 enum {

291 IT_None,

292 IT_State,

293 IT_VarTest,

294 IT_BinTest,

295 IT_Var,

296 IT_Tmp

297 } InfoType = IT_None;

298

299 struct BinTestTy {

302 VarTestResult LTest;

303 VarTestResult RTest;

304 };

305

306 union {

312 };

313

314public:

318

320 : InfoType(IT_VarTest) {

322 VarTest.TestsFor = TestsFor;

323 }

324

326 const VarTestResult &LTest, const VarTestResult &RTest)

327 : InfoType(IT_BinTest) {

332 }

333

337 : InfoType(IT_BinTest) {

340 BinTest.LTest.Var = LVar;

341 BinTest.LTest.TestsFor = LTestsFor;

342 BinTest.RTest.Var = RVar;

343 BinTest.RTest.TestsFor = RTestsFor;

344 }

345

347 : InfoType(IT_State), State(State) {}

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

351

353 assert(InfoType == IT_State);

355 }

356

358 assert(InfoType == IT_VarTest);

360 }

361

363 assert(InfoType == IT_BinTest);

365 }

366

368 assert(InfoType == IT_BinTest);

370 }

371

373 assert(InfoType == IT_Var);

374 return Var;

375 }

376

378 assert(InfoType == IT_Tmp);

379 return Tmp;

380 }

381

384

387 else if (isTmp())

391 else

393 }

394

396 assert(InfoType == IT_BinTest);

398 }

399

401 assert(InfoType == IT_BinTest);

403 }

404

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

411

413 return InfoType == IT_VarTest || InfoType == IT_BinTest;

414 }

415

417 return InfoType == IT_Var || InfoType == IT_Tmp;

418 }

419

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

422

423 if (InfoType == IT_VarTest) {

426

427 } else if (InfoType == IT_BinTest) {

432 } else {

433 return {};

434 }

435 }

436};

437

438}

439}

440

441static void

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

445

446 if (PInfo.isVar())

448 else

450}

451

453namespace consumed {

454

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;

460

463 MapType PropagationMap;

464

465 InfoEntry findInfo(const Expr *E) {

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

467 if (!Cleanups->cleanupsHaveSideEffects())

468 E = Cleanups->getSubExpr();

470 }

471

472 ConstInfoEntry findInfo(const Expr *E) const {

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

474 if (!Cleanups->cleanupsHaveSideEffects())

475 E = Cleanups->getSubExpr();

477 }

478

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

481 }

482

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

488

489public:

495

511

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

514

516 ConstInfoEntry Entry = findInfo(StmtNode);

517

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

519 return Entry->second;

520 else

521 return {};

522 }

523

525 StateMap = NewStateMap;

526 }

527};

528

529}

530}

531

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

533 InfoEntry Entry = findInfo(From);

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

535 insertInfo(To, Entry->second);

536}

537

538

539

540void ConsumedStmtVisitor::copyInfo(const Expr *From, const Expr *To,

542 InfoEntry Entry = findInfo(From);

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

550 }

551}

552

553

555 InfoEntry Entry = findInfo(From);

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

559 }

561}

562

563

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

565 InfoEntry Entry = findInfo(To);

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

570 } else if (NS != CS_None) {

572 }

573}

574

578 assert(!PInfo.isTest());

579

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

581 if (!CWAttr)

582 return;

583

584 if (PInfo.isVar()) {

586

588 return;

589

593 } else {

595

597 return;

598

601 }

602}

603

604

605

606

609 unsigned Offset = 0;

610 if (isa(Call) && isa(FunD))

611 Offset = 1;

612

613

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

615

617 break;

618

621

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

623

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

625 continue;

627

628

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

632

633 if (ParamState != ExpectedState)

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

637 }

638

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

640 continue;

641

642

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

651 }

652

653 if (!ObjArg)

654 return false;

655

656

657 InfoEntry Entry = findInfo(ObjArg);

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

661

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

663 if (PInfo.isVar()) {

665 return true;

666 }

667 else if (PInfo.isTmp()) {

669 return true;

670 }

671 }

673 PropagationMap.insert(PairType(Call,

675 }

676 }

677 return false;

678}

679

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

685

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

690 else

692

694 }

695}

696

699 case BO_LAnd:

700 case BO_LOr : {

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

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

703

704 VarTestResult LTest, RTest;

705

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

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

708 } else {

709 LTest.Var = nullptr;

710 LTest.TestsFor = CS_None;

711 }

712

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

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

715 } else {

716 RTest.Var = nullptr;

717 RTest.TestsFor = CS_None;

718 }

719

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

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

723 break;

724 }

725

726 case BO_PtrMemD:

727 case BO_PtrMemI:

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

729 break;

730

731 default:

732 break;

733 }

734}

735

738 if (!FunDecl)

739 return;

740

741

742

743 if (Call->isCallToStdMove()) {

745 return;

746 }

747

749 propagateReturnType(Call, FunDecl);

750}

751

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

754}

755

758

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

760

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

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

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

764 }

765}

766

769

770 QualType ThisType = Constructor->getFunctionObjectParameterType();

771

773 return;

774

775

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

777

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

781 PropagationMap.insert(PairType(Call,

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

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

786

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

791 } else {

792

795 }

796}

797

801 if (!MD)

802 return;

803

805 propagateReturnType(Call, MD);

806}

807

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

811 if (!FunDecl) return;

812

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

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

817 return;

818 }

819

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

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

822 else

824

825 propagateReturnType(Call, FunDecl);

826}

827

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

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

832}

833

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

836 if (isa(DI))

838

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

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

842}

843

846 forwardInfo(Temp->getSubExpr(), Temp);

847}

848

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

851}

852

856

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

867

868 if (ParamState != CS_None)

869 StateMap->setState(Param, ParamState);

870}

871

874

875 if (ExpectedState != CS_None) {

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

877

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

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

880

881 if (RetState != ExpectedState)

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

885 }

886 }

887

890}

891

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

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

895

897 case UO_AddrOf:

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

899 break;

900

901 case UO_LNot:

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

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

904 break;

905

906 default:

907 break;

908 }

909}

910

911

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

919

922 return;

923 }

924 }

925 }

926

928 }

929}

930

935

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

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

943 }

944}

945

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

951

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

954

955 if (LTest.Var) {

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

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

962 if (RState == RTest.TestsFor)

964 else

966 }

967 } else {

969 ElseStates->setState(LTest.Var,

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

975 if (RState == RTest.TestsFor)

977 else

979 }

980 }

981 }

982

983 if (RTest.Var) {

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

989 } else {

991 ElseStates->setState(RTest.Var,

993 else if (RState == RTest.TestsFor)

995 }

996 }

997}

998

1000 const CFGBlock *TargetBlock) {

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

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

1003

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

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

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

1008 return false;

1009 }

1010 return true;

1011}

1012

1015 std::unique_ptr &OwnedStateMap) {

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

1017

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

1019

1020 if (Entry) {

1021 Entry->intersect(*StateMap);

1022 } else if (OwnedStateMap)

1023 Entry = std::move(OwnedStateMap);

1024 else

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

1026}

1027

1029 std::unique_ptr StateMap) {

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

1031

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

1033

1034 if (Entry) {

1035 Entry->intersect(*StateMap);

1036 } else {

1037 Entry = std::move(StateMap);

1038 }

1039}

1040

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

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

1044

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

1046}

1047

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

1050}

1051

1052std::unique_ptr

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

1055

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

1058 : std::move(Entry);

1059}

1060

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

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

1064

1066}

1067

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

1070

1071

1072

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

1074 return false;

1075

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

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

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

1080 return true;

1081 }

1082 return false;

1083}

1084

1087

1088 for (const auto &DM : VarMap) {

1089 if (isa(DM.first)) {

1090 const auto *Param = cast(DM.first);

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

1092

1093 if (!RTA)

1094 continue;

1095

1097 if (DM.second != ExpectedState)

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

1101 }

1102 }

1103}

1104

1107}

1108

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

1111

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

1113 return Entry->second;

1114

1116}

1117

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

1121

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

1123 return Entry->second;

1124

1126}

1127

1130

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

1133 return;

1134 }

1135

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

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

1138

1139 if (LocalState == CS_None)

1140 continue;

1141

1142 if (LocalState != DM.second)

1144 }

1145}

1146

1150

1153

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

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

1156

1157 if (LocalState == CS_None)

1158 continue;

1159

1160 if (LocalState != DM.second) {

1163 DM.first->getNameAsString());

1164 }

1165 }

1166}

1167

1172}

1173

1175 VarMap[Var] = State;

1176}

1177

1180 TmpMap[Tmp] = State;

1181}

1182

1185}

1186

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

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

1190 return true;

1191 return false;

1192}

1193

1194void ConsumedAnalyzer::determineExpectedReturnState(AnalysisDeclContext &AC,

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

1198 ReturnType = Constructor->getFunctionObjectParameterType();

1199 } else

1200 ReturnType = D->getCallResultType();

1201

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

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

1205

1206

1207

1208

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

1211 ExpectedReturnState = CS_None;

1212 } else

1215 if (isAutoCastType(ReturnType))

1216 ExpectedReturnState = CS_None;

1217 else

1219 }

1220 else

1221 ExpectedReturnState = CS_None;

1222}

1223

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

1226 std::unique_ptr FalseStates(

1229

1230 if (const auto *IfNode =

1232 if (IfNode->isConsteval())

1233 return false;

1234

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

1236

1237 PInfo = Visitor.getInfo(Cond);

1238 if (!PInfo.isValid() && isa(Cond))

1239 PInfo = Visitor.getInfo(cast(Cond)->getRHS());

1240

1242 CurrStates->setSource(Cond);

1243 FalseStates->setSource(Cond);

1245 FalseStates.get());

1250 } else {

1251 return false;

1252 }

1253 } else if (const auto *BinOp =

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

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

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

1259

1261 return false;

1262 } else {

1263 return false;

1264 }

1265 }

1266

1267 CurrStates->setSource(BinOp);

1268 FalseStates->setSource(BinOp);

1269

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

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

1272

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

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

1277 CurrStates->markUnreachable();

1278

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

1281 FalseStates->setState(Test.Var,

1283 else if (VarState == Test.TestsFor)

1284 FalseStates->markUnreachable();

1285 }

1286 } else {

1287 return false;

1288 }

1289

1291

1292 if (*SI)

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

1294 else

1295 CurrStates = nullptr;

1296

1297 if (*++SI)

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

1299

1300 return true;

1301}

1302

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

1305 if (D)

1306 return;

1307

1308 CFG *CFGraph = AC.getCFG();

1309 if (!CFGraph)

1310 return;

1311

1312 determineExpectedReturnState(AC, D);

1313

1315

1316

1318

1319 CurrStates = std::make_unique();

1321

1322

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

1325

1326

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

1328 if (!CurrStates)

1329 CurrStates = BlockInfo.getInfo(CurrBlock);

1330

1331 if (!CurrStates) {

1332 continue;

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

1334 CurrStates = nullptr;

1335 continue;

1336 }

1337

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

1339

1340

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

1342 switch (B.getKind()) {

1345 break;

1346

1350

1353 BTE->getExprLoc());

1354 CurrStates->remove(BTE);

1355 break;

1356 }

1357

1362

1366 break;

1367 }

1368

1369 default:

1370 break;

1371 }

1372 }

1373

1374

1375

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

1377 CurrStates->setSource(nullptr);

1378

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

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

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

1382

1383 auto *RawState = CurrStates.get();

1384

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

1387 if (*SI == nullptr) continue;

1388

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

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

1392

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

1394 BlockInfo.discardInfo(*SI);

1395 } else {

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

1397 }

1398 }

1399

1400 CurrStates = nullptr;

1401 }

1402 }

1403

1404 if (CurrBlock == &AC.getCFG()->getExit() &&

1405 D->getCallResultType()->isVoidType())

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

1408 }

1409

1410

1411 CurrStates = nullptr;

1412

1414}

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 &LTest, 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.