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 <est, 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 <est = 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 && .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 <est, 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.