Consumed.cpp 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415
  1. //===- Consumed.cpp -------------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // A intra-procedural analysis for checking consumed properties. This is based,
  10. // in part, on research on linear types.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/Analysis/Analyses/Consumed.h"
  14. #include "clang/AST/Attr.h"
  15. #include "clang/AST/Decl.h"
  16. #include "clang/AST/DeclCXX.h"
  17. #include "clang/AST/Expr.h"
  18. #include "clang/AST/ExprCXX.h"
  19. #include "clang/AST/Stmt.h"
  20. #include "clang/AST/StmtVisitor.h"
  21. #include "clang/AST/Type.h"
  22. #include "clang/Analysis/Analyses/PostOrderCFGView.h"
  23. #include "clang/Analysis/AnalysisDeclContext.h"
  24. #include "clang/Analysis/CFG.h"
  25. #include "clang/Basic/LLVM.h"
  26. #include "clang/Basic/OperatorKinds.h"
  27. #include "clang/Basic/SourceLocation.h"
  28. #include "llvm/ADT/DenseMap.h"
  29. #include "llvm/ADT/Optional.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 <cassert>
  35. #include <memory>
  36. #include <utility>
  37. // TODO: Adjust states of args to constructors in the same way that arguments to
  38. // function calls are handled.
  39. // TODO: Use information from tests in for- and while-loop conditional.
  40. // TODO: Add notes about the actual and expected state for
  41. // TODO: Correctly identify unreachable blocks when chaining boolean operators.
  42. // TODO: Adjust the parser and AttributesList class to support lists of
  43. // identifiers.
  44. // TODO: Warn about unreachable code.
  45. // TODO: Switch to using a bitmap to track unreachable blocks.
  46. // TODO: Handle variable definitions, e.g. bool valid = x.isValid();
  47. // if (valid) ...; (Deferred)
  48. // TODO: Take notes on state transitions to provide better warning messages.
  49. // (Deferred)
  50. // TODO: Test nested conditionals: A) Checking the same value multiple times,
  51. // and 2) Checking different values. (Deferred)
  52. using namespace clang;
  53. using namespace consumed;
  54. // Key method definition
  55. ConsumedWarningsHandlerBase::~ConsumedWarningsHandlerBase() = default;
  56. static SourceLocation getFirstStmtLoc(const CFGBlock *Block) {
  57. // Find the source location of the first statement in the block, if the block
  58. // is not empty.
  59. for (const auto &B : *Block)
  60. if (Optional<CFGStmt> CS = B.getAs<CFGStmt>())
  61. return CS->getStmt()->getBeginLoc();
  62. // Block is empty.
  63. // If we have one successor, return the first statement in that block
  64. if (Block->succ_size() == 1 && *Block->succ_begin())
  65. return getFirstStmtLoc(*Block->succ_begin());
  66. return {};
  67. }
  68. static SourceLocation getLastStmtLoc(const CFGBlock *Block) {
  69. // Find the source location of the last statement in the block, if the block
  70. // is not empty.
  71. if (const Stmt *StmtNode = Block->getTerminatorStmt()) {
  72. return StmtNode->getBeginLoc();
  73. } else {
  74. for (CFGBlock::const_reverse_iterator BI = Block->rbegin(),
  75. BE = Block->rend(); BI != BE; ++BI) {
  76. if (Optional<CFGStmt> CS = BI->getAs<CFGStmt>())
  77. return CS->getStmt()->getBeginLoc();
  78. }
  79. }
  80. // If we have one successor, return the first statement in that block
  81. SourceLocation Loc;
  82. if (Block->succ_size() == 1 && *Block->succ_begin())
  83. Loc = getFirstStmtLoc(*Block->succ_begin());
  84. if (Loc.isValid())
  85. return Loc;
  86. // If we have one predecessor, return the last statement in that block
  87. if (Block->pred_size() == 1 && *Block->pred_begin())
  88. return getLastStmtLoc(*Block->pred_begin());
  89. return Loc;
  90. }
  91. static ConsumedState invertConsumedUnconsumed(ConsumedState State) {
  92. switch (State) {
  93. case CS_Unconsumed:
  94. return CS_Consumed;
  95. case CS_Consumed:
  96. return CS_Unconsumed;
  97. case CS_None:
  98. return CS_None;
  99. case CS_Unknown:
  100. return CS_Unknown;
  101. }
  102. llvm_unreachable("invalid enum");
  103. }
  104. static bool isCallableInState(const CallableWhenAttr *CWAttr,
  105. ConsumedState State) {
  106. for (const auto &S : CWAttr->callableStates()) {
  107. ConsumedState MappedAttrState = CS_None;
  108. switch (S) {
  109. case CallableWhenAttr::Unknown:
  110. MappedAttrState = CS_Unknown;
  111. break;
  112. case CallableWhenAttr::Unconsumed:
  113. MappedAttrState = CS_Unconsumed;
  114. break;
  115. case CallableWhenAttr::Consumed:
  116. MappedAttrState = CS_Consumed;
  117. break;
  118. }
  119. if (MappedAttrState == State)
  120. return true;
  121. }
  122. return false;
  123. }
  124. static bool isConsumableType(const QualType &QT) {
  125. if (QT->isPointerType() || QT->isReferenceType())
  126. return false;
  127. if (const CXXRecordDecl *RD = QT->getAsCXXRecordDecl())
  128. return RD->hasAttr<ConsumableAttr>();
  129. return false;
  130. }
  131. static bool isAutoCastType(const QualType &QT) {
  132. if (QT->isPointerType() || QT->isReferenceType())
  133. return false;
  134. if (const CXXRecordDecl *RD = QT->getAsCXXRecordDecl())
  135. return RD->hasAttr<ConsumableAutoCastAttr>();
  136. return false;
  137. }
  138. static bool isSetOnReadPtrType(const QualType &QT) {
  139. if (const CXXRecordDecl *RD = QT->getPointeeCXXRecordDecl())
  140. return RD->hasAttr<ConsumableSetOnReadAttr>();
  141. return false;
  142. }
  143. static bool isKnownState(ConsumedState State) {
  144. switch (State) {
  145. case CS_Unconsumed:
  146. case CS_Consumed:
  147. return true;
  148. case CS_None:
  149. case CS_Unknown:
  150. return false;
  151. }
  152. llvm_unreachable("invalid enum");
  153. }
  154. static bool isRValueRef(QualType ParamType) {
  155. return ParamType->isRValueReferenceType();
  156. }
  157. static bool isTestingFunction(const FunctionDecl *FunDecl) {
  158. return FunDecl->hasAttr<TestTypestateAttr>();
  159. }
  160. static bool isPointerOrRef(QualType ParamType) {
  161. return ParamType->isPointerType() || ParamType->isReferenceType();
  162. }
  163. static ConsumedState mapConsumableAttrState(const QualType QT) {
  164. assert(isConsumableType(QT));
  165. const ConsumableAttr *CAttr =
  166. QT->getAsCXXRecordDecl()->getAttr<ConsumableAttr>();
  167. switch (CAttr->getDefaultState()) {
  168. case ConsumableAttr::Unknown:
  169. return CS_Unknown;
  170. case ConsumableAttr::Unconsumed:
  171. return CS_Unconsumed;
  172. case ConsumableAttr::Consumed:
  173. return CS_Consumed;
  174. }
  175. llvm_unreachable("invalid enum");
  176. }
  177. static ConsumedState
  178. mapParamTypestateAttrState(const ParamTypestateAttr *PTAttr) {
  179. switch (PTAttr->getParamState()) {
  180. case ParamTypestateAttr::Unknown:
  181. return CS_Unknown;
  182. case ParamTypestateAttr::Unconsumed:
  183. return CS_Unconsumed;
  184. case ParamTypestateAttr::Consumed:
  185. return CS_Consumed;
  186. }
  187. llvm_unreachable("invalid_enum");
  188. }
  189. static ConsumedState
  190. mapReturnTypestateAttrState(const ReturnTypestateAttr *RTSAttr) {
  191. switch (RTSAttr->getState()) {
  192. case ReturnTypestateAttr::Unknown:
  193. return CS_Unknown;
  194. case ReturnTypestateAttr::Unconsumed:
  195. return CS_Unconsumed;
  196. case ReturnTypestateAttr::Consumed:
  197. return CS_Consumed;
  198. }
  199. llvm_unreachable("invalid enum");
  200. }
  201. static ConsumedState mapSetTypestateAttrState(const SetTypestateAttr *STAttr) {
  202. switch (STAttr->getNewState()) {
  203. case SetTypestateAttr::Unknown:
  204. return CS_Unknown;
  205. case SetTypestateAttr::Unconsumed:
  206. return CS_Unconsumed;
  207. case SetTypestateAttr::Consumed:
  208. return CS_Consumed;
  209. }
  210. llvm_unreachable("invalid_enum");
  211. }
  212. static StringRef stateToString(ConsumedState State) {
  213. switch (State) {
  214. case consumed::CS_None:
  215. return "none";
  216. case consumed::CS_Unknown:
  217. return "unknown";
  218. case consumed::CS_Unconsumed:
  219. return "unconsumed";
  220. case consumed::CS_Consumed:
  221. return "consumed";
  222. }
  223. llvm_unreachable("invalid enum");
  224. }
  225. static ConsumedState testsFor(const FunctionDecl *FunDecl) {
  226. assert(isTestingFunction(FunDecl));
  227. switch (FunDecl->getAttr<TestTypestateAttr>()->getTestState()) {
  228. case TestTypestateAttr::Unconsumed:
  229. return CS_Unconsumed;
  230. case TestTypestateAttr::Consumed:
  231. return CS_Consumed;
  232. }
  233. llvm_unreachable("invalid enum");
  234. }
  235. namespace {
  236. struct VarTestResult {
  237. const VarDecl *Var;
  238. ConsumedState TestsFor;
  239. };
  240. } // namespace
  241. namespace clang {
  242. namespace consumed {
  243. enum EffectiveOp {
  244. EO_And,
  245. EO_Or
  246. };
  247. class PropagationInfo {
  248. enum {
  249. IT_None,
  250. IT_State,
  251. IT_VarTest,
  252. IT_BinTest,
  253. IT_Var,
  254. IT_Tmp
  255. } InfoType = IT_None;
  256. struct BinTestTy {
  257. const BinaryOperator *Source;
  258. EffectiveOp EOp;
  259. VarTestResult LTest;
  260. VarTestResult RTest;
  261. };
  262. union {
  263. ConsumedState State;
  264. VarTestResult VarTest;
  265. const VarDecl *Var;
  266. const CXXBindTemporaryExpr *Tmp;
  267. BinTestTy BinTest;
  268. };
  269. public:
  270. PropagationInfo() = default;
  271. PropagationInfo(const VarTestResult &VarTest)
  272. : InfoType(IT_VarTest), VarTest(VarTest) {}
  273. PropagationInfo(const VarDecl *Var, ConsumedState TestsFor)
  274. : InfoType(IT_VarTest) {
  275. VarTest.Var = Var;
  276. VarTest.TestsFor = TestsFor;
  277. }
  278. PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp,
  279. const VarTestResult &LTest, const VarTestResult &RTest)
  280. : InfoType(IT_BinTest) {
  281. BinTest.Source = Source;
  282. BinTest.EOp = EOp;
  283. BinTest.LTest = LTest;
  284. BinTest.RTest = RTest;
  285. }
  286. PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp,
  287. const VarDecl *LVar, ConsumedState LTestsFor,
  288. const VarDecl *RVar, ConsumedState RTestsFor)
  289. : InfoType(IT_BinTest) {
  290. BinTest.Source = Source;
  291. BinTest.EOp = EOp;
  292. BinTest.LTest.Var = LVar;
  293. BinTest.LTest.TestsFor = LTestsFor;
  294. BinTest.RTest.Var = RVar;
  295. BinTest.RTest.TestsFor = RTestsFor;
  296. }
  297. PropagationInfo(ConsumedState State)
  298. : InfoType(IT_State), State(State) {}
  299. PropagationInfo(const VarDecl *Var) : InfoType(IT_Var), Var(Var) {}
  300. PropagationInfo(const CXXBindTemporaryExpr *Tmp)
  301. : InfoType(IT_Tmp), Tmp(Tmp) {}
  302. const ConsumedState &getState() const {
  303. assert(InfoType == IT_State);
  304. return State;
  305. }
  306. const VarTestResult &getVarTest() const {
  307. assert(InfoType == IT_VarTest);
  308. return VarTest;
  309. }
  310. const VarTestResult &getLTest() const {
  311. assert(InfoType == IT_BinTest);
  312. return BinTest.LTest;
  313. }
  314. const VarTestResult &getRTest() const {
  315. assert(InfoType == IT_BinTest);
  316. return BinTest.RTest;
  317. }
  318. const VarDecl *getVar() const {
  319. assert(InfoType == IT_Var);
  320. return Var;
  321. }
  322. const CXXBindTemporaryExpr *getTmp() const {
  323. assert(InfoType == IT_Tmp);
  324. return Tmp;
  325. }
  326. ConsumedState getAsState(const ConsumedStateMap *StateMap) const {
  327. assert(isVar() || isTmp() || isState());
  328. if (isVar())
  329. return StateMap->getState(Var);
  330. else if (isTmp())
  331. return StateMap->getState(Tmp);
  332. else if (isState())
  333. return State;
  334. else
  335. return CS_None;
  336. }
  337. EffectiveOp testEffectiveOp() const {
  338. assert(InfoType == IT_BinTest);
  339. return BinTest.EOp;
  340. }
  341. const BinaryOperator * testSourceNode() const {
  342. assert(InfoType == IT_BinTest);
  343. return BinTest.Source;
  344. }
  345. bool isValid() const { return InfoType != IT_None; }
  346. bool isState() const { return InfoType == IT_State; }
  347. bool isVarTest() const { return InfoType == IT_VarTest; }
  348. bool isBinTest() const { return InfoType == IT_BinTest; }
  349. bool isVar() const { return InfoType == IT_Var; }
  350. bool isTmp() const { return InfoType == IT_Tmp; }
  351. bool isTest() const {
  352. return InfoType == IT_VarTest || InfoType == IT_BinTest;
  353. }
  354. bool isPointerToValue() const {
  355. return InfoType == IT_Var || InfoType == IT_Tmp;
  356. }
  357. PropagationInfo invertTest() const {
  358. assert(InfoType == IT_VarTest || InfoType == IT_BinTest);
  359. if (InfoType == IT_VarTest) {
  360. return PropagationInfo(VarTest.Var,
  361. invertConsumedUnconsumed(VarTest.TestsFor));
  362. } else if (InfoType == IT_BinTest) {
  363. return PropagationInfo(BinTest.Source,
  364. BinTest.EOp == EO_And ? EO_Or : EO_And,
  365. BinTest.LTest.Var, invertConsumedUnconsumed(BinTest.LTest.TestsFor),
  366. BinTest.RTest.Var, invertConsumedUnconsumed(BinTest.RTest.TestsFor));
  367. } else {
  368. return {};
  369. }
  370. }
  371. };
  372. } // namespace consumed
  373. } // namespace clang
  374. static void
  375. setStateForVarOrTmp(ConsumedStateMap *StateMap, const PropagationInfo &PInfo,
  376. ConsumedState State) {
  377. assert(PInfo.isVar() || PInfo.isTmp());
  378. if (PInfo.isVar())
  379. StateMap->setState(PInfo.getVar(), State);
  380. else
  381. StateMap->setState(PInfo.getTmp(), State);
  382. }
  383. namespace clang {
  384. namespace consumed {
  385. class ConsumedStmtVisitor : public ConstStmtVisitor<ConsumedStmtVisitor> {
  386. using MapType = llvm::DenseMap<const Stmt *, PropagationInfo>;
  387. using PairType= std::pair<const Stmt *, PropagationInfo>;
  388. using InfoEntry = MapType::iterator;
  389. using ConstInfoEntry = MapType::const_iterator;
  390. ConsumedAnalyzer &Analyzer;
  391. ConsumedStateMap *StateMap;
  392. MapType PropagationMap;
  393. InfoEntry findInfo(const Expr *E) {
  394. if (const auto Cleanups = dyn_cast<ExprWithCleanups>(E))
  395. if (!Cleanups->cleanupsHaveSideEffects())
  396. E = Cleanups->getSubExpr();
  397. return PropagationMap.find(E->IgnoreParens());
  398. }
  399. ConstInfoEntry findInfo(const Expr *E) const {
  400. if (const auto Cleanups = dyn_cast<ExprWithCleanups>(E))
  401. if (!Cleanups->cleanupsHaveSideEffects())
  402. E = Cleanups->getSubExpr();
  403. return PropagationMap.find(E->IgnoreParens());
  404. }
  405. void insertInfo(const Expr *E, const PropagationInfo &PI) {
  406. PropagationMap.insert(PairType(E->IgnoreParens(), PI));
  407. }
  408. void forwardInfo(const Expr *From, const Expr *To);
  409. void copyInfo(const Expr *From, const Expr *To, ConsumedState CS);
  410. ConsumedState getInfo(const Expr *From);
  411. void setInfo(const Expr *To, ConsumedState NS);
  412. void propagateReturnType(const Expr *Call, const FunctionDecl *Fun);
  413. public:
  414. void checkCallability(const PropagationInfo &PInfo,
  415. const FunctionDecl *FunDecl,
  416. SourceLocation BlameLoc);
  417. bool handleCall(const CallExpr *Call, const Expr *ObjArg,
  418. const FunctionDecl *FunD);
  419. void VisitBinaryOperator(const BinaryOperator *BinOp);
  420. void VisitCallExpr(const CallExpr *Call);
  421. void VisitCastExpr(const CastExpr *Cast);
  422. void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Temp);
  423. void VisitCXXConstructExpr(const CXXConstructExpr *Call);
  424. void VisitCXXMemberCallExpr(const CXXMemberCallExpr *Call);
  425. void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Call);
  426. void VisitDeclRefExpr(const DeclRefExpr *DeclRef);
  427. void VisitDeclStmt(const DeclStmt *DelcS);
  428. void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Temp);
  429. void VisitMemberExpr(const MemberExpr *MExpr);
  430. void VisitParmVarDecl(const ParmVarDecl *Param);
  431. void VisitReturnStmt(const ReturnStmt *Ret);
  432. void VisitUnaryOperator(const UnaryOperator *UOp);
  433. void VisitVarDecl(const VarDecl *Var);
  434. ConsumedStmtVisitor(ConsumedAnalyzer &Analyzer, ConsumedStateMap *StateMap)
  435. : Analyzer(Analyzer), StateMap(StateMap) {}
  436. PropagationInfo getInfo(const Expr *StmtNode) const {
  437. ConstInfoEntry Entry = findInfo(StmtNode);
  438. if (Entry != PropagationMap.end())
  439. return Entry->second;
  440. else
  441. return {};
  442. }
  443. void reset(ConsumedStateMap *NewStateMap) {
  444. StateMap = NewStateMap;
  445. }
  446. };
  447. } // namespace consumed
  448. } // namespace clang
  449. void ConsumedStmtVisitor::forwardInfo(const Expr *From, const Expr *To) {
  450. InfoEntry Entry = findInfo(From);
  451. if (Entry != PropagationMap.end())
  452. insertInfo(To, Entry->second);
  453. }
  454. // Create a new state for To, which is initialized to the state of From.
  455. // If NS is not CS_None, sets the state of From to NS.
  456. void ConsumedStmtVisitor::copyInfo(const Expr *From, const Expr *To,
  457. ConsumedState NS) {
  458. InfoEntry Entry = findInfo(From);
  459. if (Entry != PropagationMap.end()) {
  460. PropagationInfo& PInfo = Entry->second;
  461. ConsumedState CS = PInfo.getAsState(StateMap);
  462. if (CS != CS_None)
  463. insertInfo(To, PropagationInfo(CS));
  464. if (NS != CS_None && PInfo.isPointerToValue())
  465. setStateForVarOrTmp(StateMap, PInfo, NS);
  466. }
  467. }
  468. // Get the ConsumedState for From
  469. ConsumedState ConsumedStmtVisitor::getInfo(const Expr *From) {
  470. InfoEntry Entry = findInfo(From);
  471. if (Entry != PropagationMap.end()) {
  472. PropagationInfo& PInfo = Entry->second;
  473. return PInfo.getAsState(StateMap);
  474. }
  475. return CS_None;
  476. }
  477. // If we already have info for To then update it, otherwise create a new entry.
  478. void ConsumedStmtVisitor::setInfo(const Expr *To, ConsumedState NS) {
  479. InfoEntry Entry = findInfo(To);
  480. if (Entry != PropagationMap.end()) {
  481. PropagationInfo& PInfo = Entry->second;
  482. if (PInfo.isPointerToValue())
  483. setStateForVarOrTmp(StateMap, PInfo, NS);
  484. } else if (NS != CS_None) {
  485. insertInfo(To, PropagationInfo(NS));
  486. }
  487. }
  488. void ConsumedStmtVisitor::checkCallability(const PropagationInfo &PInfo,
  489. const FunctionDecl *FunDecl,
  490. SourceLocation BlameLoc) {
  491. assert(!PInfo.isTest());
  492. const CallableWhenAttr *CWAttr = FunDecl->getAttr<CallableWhenAttr>();
  493. if (!CWAttr)
  494. return;
  495. if (PInfo.isVar()) {
  496. ConsumedState VarState = StateMap->getState(PInfo.getVar());
  497. if (VarState == CS_None || isCallableInState(CWAttr, VarState))
  498. return;
  499. Analyzer.WarningsHandler.warnUseInInvalidState(
  500. FunDecl->getNameAsString(), PInfo.getVar()->getNameAsString(),
  501. stateToString(VarState), BlameLoc);
  502. } else {
  503. ConsumedState TmpState = PInfo.getAsState(StateMap);
  504. if (TmpState == CS_None || isCallableInState(CWAttr, TmpState))
  505. return;
  506. Analyzer.WarningsHandler.warnUseOfTempInInvalidState(
  507. FunDecl->getNameAsString(), stateToString(TmpState), BlameLoc);
  508. }
  509. }
  510. // Factors out common behavior for function, method, and operator calls.
  511. // Check parameters and set parameter state if necessary.
  512. // Returns true if the state of ObjArg is set, or false otherwise.
  513. bool ConsumedStmtVisitor::handleCall(const CallExpr *Call, const Expr *ObjArg,
  514. const FunctionDecl *FunD) {
  515. unsigned Offset = 0;
  516. if (isa<CXXOperatorCallExpr>(Call) && isa<CXXMethodDecl>(FunD))
  517. Offset = 1; // first argument is 'this'
  518. // check explicit parameters
  519. for (unsigned Index = Offset; Index < Call->getNumArgs(); ++Index) {
  520. // Skip variable argument lists.
  521. if (Index - Offset >= FunD->getNumParams())
  522. break;
  523. const ParmVarDecl *Param = FunD->getParamDecl(Index - Offset);
  524. QualType ParamType = Param->getType();
  525. InfoEntry Entry = findInfo(Call->getArg(Index));
  526. if (Entry == PropagationMap.end() || Entry->second.isTest())
  527. continue;
  528. PropagationInfo PInfo = Entry->second;
  529. // Check that the parameter is in the correct state.
  530. if (ParamTypestateAttr *PTA = Param->getAttr<ParamTypestateAttr>()) {
  531. ConsumedState ParamState = PInfo.getAsState(StateMap);
  532. ConsumedState ExpectedState = mapParamTypestateAttrState(PTA);
  533. if (ParamState != ExpectedState)
  534. Analyzer.WarningsHandler.warnParamTypestateMismatch(
  535. Call->getArg(Index)->getExprLoc(),
  536. stateToString(ExpectedState), stateToString(ParamState));
  537. }
  538. if (!(Entry->second.isVar() || Entry->second.isTmp()))
  539. continue;
  540. // Adjust state on the caller side.
  541. if (ReturnTypestateAttr *RT = Param->getAttr<ReturnTypestateAttr>())
  542. setStateForVarOrTmp(StateMap, PInfo, mapReturnTypestateAttrState(RT));
  543. else if (isRValueRef(ParamType) || isConsumableType(ParamType))
  544. setStateForVarOrTmp(StateMap, PInfo, consumed::CS_Consumed);
  545. else if (isPointerOrRef(ParamType) &&
  546. (!ParamType->getPointeeType().isConstQualified() ||
  547. isSetOnReadPtrType(ParamType)))
  548. setStateForVarOrTmp(StateMap, PInfo, consumed::CS_Unknown);
  549. }
  550. if (!ObjArg)
  551. return false;
  552. // check implicit 'self' parameter, if present
  553. InfoEntry Entry = findInfo(ObjArg);
  554. if (Entry != PropagationMap.end()) {
  555. PropagationInfo PInfo = Entry->second;
  556. checkCallability(PInfo, FunD, Call->getExprLoc());
  557. if (SetTypestateAttr *STA = FunD->getAttr<SetTypestateAttr>()) {
  558. if (PInfo.isVar()) {
  559. StateMap->setState(PInfo.getVar(), mapSetTypestateAttrState(STA));
  560. return true;
  561. }
  562. else if (PInfo.isTmp()) {
  563. StateMap->setState(PInfo.getTmp(), mapSetTypestateAttrState(STA));
  564. return true;
  565. }
  566. }
  567. else if (isTestingFunction(FunD) && PInfo.isVar()) {
  568. PropagationMap.insert(PairType(Call,
  569. PropagationInfo(PInfo.getVar(), testsFor(FunD))));
  570. }
  571. }
  572. return false;
  573. }
  574. void ConsumedStmtVisitor::propagateReturnType(const Expr *Call,
  575. const FunctionDecl *Fun) {
  576. QualType RetType = Fun->getCallResultType();
  577. if (RetType->isReferenceType())
  578. RetType = RetType->getPointeeType();
  579. if (isConsumableType(RetType)) {
  580. ConsumedState ReturnState;
  581. if (ReturnTypestateAttr *RTA = Fun->getAttr<ReturnTypestateAttr>())
  582. ReturnState = mapReturnTypestateAttrState(RTA);
  583. else
  584. ReturnState = mapConsumableAttrState(RetType);
  585. PropagationMap.insert(PairType(Call, PropagationInfo(ReturnState)));
  586. }
  587. }
  588. void ConsumedStmtVisitor::VisitBinaryOperator(const BinaryOperator *BinOp) {
  589. switch (BinOp->getOpcode()) {
  590. case BO_LAnd:
  591. case BO_LOr : {
  592. InfoEntry LEntry = findInfo(BinOp->getLHS()),
  593. REntry = findInfo(BinOp->getRHS());
  594. VarTestResult LTest, RTest;
  595. if (LEntry != PropagationMap.end() && LEntry->second.isVarTest()) {
  596. LTest = LEntry->second.getVarTest();
  597. } else {
  598. LTest.Var = nullptr;
  599. LTest.TestsFor = CS_None;
  600. }
  601. if (REntry != PropagationMap.end() && REntry->second.isVarTest()) {
  602. RTest = REntry->second.getVarTest();
  603. } else {
  604. RTest.Var = nullptr;
  605. RTest.TestsFor = CS_None;
  606. }
  607. if (!(LTest.Var == nullptr && RTest.Var == nullptr))
  608. PropagationMap.insert(PairType(BinOp, PropagationInfo(BinOp,
  609. static_cast<EffectiveOp>(BinOp->getOpcode() == BO_LOr), LTest, RTest)));
  610. break;
  611. }
  612. case BO_PtrMemD:
  613. case BO_PtrMemI:
  614. forwardInfo(BinOp->getLHS(), BinOp);
  615. break;
  616. default:
  617. break;
  618. }
  619. }
  620. void ConsumedStmtVisitor::VisitCallExpr(const CallExpr *Call) {
  621. const FunctionDecl *FunDecl = Call->getDirectCallee();
  622. if (!FunDecl)
  623. return;
  624. // Special case for the std::move function.
  625. // TODO: Make this more specific. (Deferred)
  626. if (Call->isCallToStdMove()) {
  627. copyInfo(Call->getArg(0), Call, CS_Consumed);
  628. return;
  629. }
  630. handleCall(Call, nullptr, FunDecl);
  631. propagateReturnType(Call, FunDecl);
  632. }
  633. void ConsumedStmtVisitor::VisitCastExpr(const CastExpr *Cast) {
  634. forwardInfo(Cast->getSubExpr(), Cast);
  635. }
  636. void ConsumedStmtVisitor::VisitCXXBindTemporaryExpr(
  637. const CXXBindTemporaryExpr *Temp) {
  638. InfoEntry Entry = findInfo(Temp->getSubExpr());
  639. if (Entry != PropagationMap.end() && !Entry->second.isTest()) {
  640. StateMap->setState(Temp, Entry->second.getAsState(StateMap));
  641. PropagationMap.insert(PairType(Temp, PropagationInfo(Temp)));
  642. }
  643. }
  644. void ConsumedStmtVisitor::VisitCXXConstructExpr(const CXXConstructExpr *Call) {
  645. CXXConstructorDecl *Constructor = Call->getConstructor();
  646. QualType ThisType = Constructor->getThisType()->getPointeeType();
  647. if (!isConsumableType(ThisType))
  648. return;
  649. // FIXME: What should happen if someone annotates the move constructor?
  650. if (ReturnTypestateAttr *RTA = Constructor->getAttr<ReturnTypestateAttr>()) {
  651. // TODO: Adjust state of args appropriately.
  652. ConsumedState RetState = mapReturnTypestateAttrState(RTA);
  653. PropagationMap.insert(PairType(Call, PropagationInfo(RetState)));
  654. } else if (Constructor->isDefaultConstructor()) {
  655. PropagationMap.insert(PairType(Call,
  656. PropagationInfo(consumed::CS_Consumed)));
  657. } else if (Constructor->isMoveConstructor()) {
  658. copyInfo(Call->getArg(0), Call, CS_Consumed);
  659. } else if (Constructor->isCopyConstructor()) {
  660. // Copy state from arg. If setStateOnRead then set arg to CS_Unknown.
  661. ConsumedState NS =
  662. isSetOnReadPtrType(Constructor->getThisType()) ?
  663. CS_Unknown : CS_None;
  664. copyInfo(Call->getArg(0), Call, NS);
  665. } else {
  666. // TODO: Adjust state of args appropriately.
  667. ConsumedState RetState = mapConsumableAttrState(ThisType);
  668. PropagationMap.insert(PairType(Call, PropagationInfo(RetState)));
  669. }
  670. }
  671. void ConsumedStmtVisitor::VisitCXXMemberCallExpr(
  672. const CXXMemberCallExpr *Call) {
  673. CXXMethodDecl* MD = Call->getMethodDecl();
  674. if (!MD)
  675. return;
  676. handleCall(Call, Call->getImplicitObjectArgument(), MD);
  677. propagateReturnType(Call, MD);
  678. }
  679. void ConsumedStmtVisitor::VisitCXXOperatorCallExpr(
  680. const CXXOperatorCallExpr *Call) {
  681. const auto *FunDecl = dyn_cast_or_null<FunctionDecl>(Call->getDirectCallee());
  682. if (!FunDecl) return;
  683. if (Call->getOperator() == OO_Equal) {
  684. ConsumedState CS = getInfo(Call->getArg(1));
  685. if (!handleCall(Call, Call->getArg(0), FunDecl))
  686. setInfo(Call->getArg(0), CS);
  687. return;
  688. }
  689. if (const auto *MCall = dyn_cast<CXXMemberCallExpr>(Call))
  690. handleCall(MCall, MCall->getImplicitObjectArgument(), FunDecl);
  691. else
  692. handleCall(Call, Call->getArg(0), FunDecl);
  693. propagateReturnType(Call, FunDecl);
  694. }
  695. void ConsumedStmtVisitor::VisitDeclRefExpr(const DeclRefExpr *DeclRef) {
  696. if (const auto *Var = dyn_cast_or_null<VarDecl>(DeclRef->getDecl()))
  697. if (StateMap->getState(Var) != consumed::CS_None)
  698. PropagationMap.insert(PairType(DeclRef, PropagationInfo(Var)));
  699. }
  700. void ConsumedStmtVisitor::VisitDeclStmt(const DeclStmt *DeclS) {
  701. for (const auto *DI : DeclS->decls())
  702. if (isa<VarDecl>(DI))
  703. VisitVarDecl(cast<VarDecl>(DI));
  704. if (DeclS->isSingleDecl())
  705. if (const auto *Var = dyn_cast_or_null<VarDecl>(DeclS->getSingleDecl()))
  706. PropagationMap.insert(PairType(DeclS, PropagationInfo(Var)));
  707. }
  708. void ConsumedStmtVisitor::VisitMaterializeTemporaryExpr(
  709. const MaterializeTemporaryExpr *Temp) {
  710. forwardInfo(Temp->getSubExpr(), Temp);
  711. }
  712. void ConsumedStmtVisitor::VisitMemberExpr(const MemberExpr *MExpr) {
  713. forwardInfo(MExpr->getBase(), MExpr);
  714. }
  715. void ConsumedStmtVisitor::VisitParmVarDecl(const ParmVarDecl *Param) {
  716. QualType ParamType = Param->getType();
  717. ConsumedState ParamState = consumed::CS_None;
  718. if (const ParamTypestateAttr *PTA = Param->getAttr<ParamTypestateAttr>())
  719. ParamState = mapParamTypestateAttrState(PTA);
  720. else if (isConsumableType(ParamType))
  721. ParamState = mapConsumableAttrState(ParamType);
  722. else if (isRValueRef(ParamType) &&
  723. isConsumableType(ParamType->getPointeeType()))
  724. ParamState = mapConsumableAttrState(ParamType->getPointeeType());
  725. else if (ParamType->isReferenceType() &&
  726. isConsumableType(ParamType->getPointeeType()))
  727. ParamState = consumed::CS_Unknown;
  728. if (ParamState != CS_None)
  729. StateMap->setState(Param, ParamState);
  730. }
  731. void ConsumedStmtVisitor::VisitReturnStmt(const ReturnStmt *Ret) {
  732. ConsumedState ExpectedState = Analyzer.getExpectedReturnState();
  733. if (ExpectedState != CS_None) {
  734. InfoEntry Entry = findInfo(Ret->getRetValue());
  735. if (Entry != PropagationMap.end()) {
  736. ConsumedState RetState = Entry->second.getAsState(StateMap);
  737. if (RetState != ExpectedState)
  738. Analyzer.WarningsHandler.warnReturnTypestateMismatch(
  739. Ret->getReturnLoc(), stateToString(ExpectedState),
  740. stateToString(RetState));
  741. }
  742. }
  743. StateMap->checkParamsForReturnTypestate(Ret->getBeginLoc(),
  744. Analyzer.WarningsHandler);
  745. }
  746. void ConsumedStmtVisitor::VisitUnaryOperator(const UnaryOperator *UOp) {
  747. InfoEntry Entry = findInfo(UOp->getSubExpr());
  748. if (Entry == PropagationMap.end()) return;
  749. switch (UOp->getOpcode()) {
  750. case UO_AddrOf:
  751. PropagationMap.insert(PairType(UOp, Entry->second));
  752. break;
  753. case UO_LNot:
  754. if (Entry->second.isTest())
  755. PropagationMap.insert(PairType(UOp, Entry->second.invertTest()));
  756. break;
  757. default:
  758. break;
  759. }
  760. }
  761. // TODO: See if I need to check for reference types here.
  762. void ConsumedStmtVisitor::VisitVarDecl(const VarDecl *Var) {
  763. if (isConsumableType(Var->getType())) {
  764. if (Var->hasInit()) {
  765. MapType::iterator VIT = findInfo(Var->getInit()->IgnoreImplicit());
  766. if (VIT != PropagationMap.end()) {
  767. PropagationInfo PInfo = VIT->second;
  768. ConsumedState St = PInfo.getAsState(StateMap);
  769. if (St != consumed::CS_None) {
  770. StateMap->setState(Var, St);
  771. return;
  772. }
  773. }
  774. }
  775. // Otherwise
  776. StateMap->setState(Var, consumed::CS_Unknown);
  777. }
  778. }
  779. static void splitVarStateForIf(const IfStmt *IfNode, const VarTestResult &Test,
  780. ConsumedStateMap *ThenStates,
  781. ConsumedStateMap *ElseStates) {
  782. ConsumedState VarState = ThenStates->getState(Test.Var);
  783. if (VarState == CS_Unknown) {
  784. ThenStates->setState(Test.Var, Test.TestsFor);
  785. ElseStates->setState(Test.Var, invertConsumedUnconsumed(Test.TestsFor));
  786. } else if (VarState == invertConsumedUnconsumed(Test.TestsFor)) {
  787. ThenStates->markUnreachable();
  788. } else if (VarState == Test.TestsFor) {
  789. ElseStates->markUnreachable();
  790. }
  791. }
  792. static void splitVarStateForIfBinOp(const PropagationInfo &PInfo,
  793. ConsumedStateMap *ThenStates,
  794. ConsumedStateMap *ElseStates) {
  795. const VarTestResult &LTest = PInfo.getLTest(),
  796. &RTest = PInfo.getRTest();
  797. ConsumedState LState = LTest.Var ? ThenStates->getState(LTest.Var) : CS_None,
  798. RState = RTest.Var ? ThenStates->getState(RTest.Var) : CS_None;
  799. if (LTest.Var) {
  800. if (PInfo.testEffectiveOp() == EO_And) {
  801. if (LState == CS_Unknown) {
  802. ThenStates->setState(LTest.Var, LTest.TestsFor);
  803. } else if (LState == invertConsumedUnconsumed(LTest.TestsFor)) {
  804. ThenStates->markUnreachable();
  805. } else if (LState == LTest.TestsFor && isKnownState(RState)) {
  806. if (RState == RTest.TestsFor)
  807. ElseStates->markUnreachable();
  808. else
  809. ThenStates->markUnreachable();
  810. }
  811. } else {
  812. if (LState == CS_Unknown) {
  813. ElseStates->setState(LTest.Var,
  814. invertConsumedUnconsumed(LTest.TestsFor));
  815. } else if (LState == LTest.TestsFor) {
  816. ElseStates->markUnreachable();
  817. } else if (LState == invertConsumedUnconsumed(LTest.TestsFor) &&
  818. isKnownState(RState)) {
  819. if (RState == RTest.TestsFor)
  820. ElseStates->markUnreachable();
  821. else
  822. ThenStates->markUnreachable();
  823. }
  824. }
  825. }
  826. if (RTest.Var) {
  827. if (PInfo.testEffectiveOp() == EO_And) {
  828. if (RState == CS_Unknown)
  829. ThenStates->setState(RTest.Var, RTest.TestsFor);
  830. else if (RState == invertConsumedUnconsumed(RTest.TestsFor))
  831. ThenStates->markUnreachable();
  832. } else {
  833. if (RState == CS_Unknown)
  834. ElseStates->setState(RTest.Var,
  835. invertConsumedUnconsumed(RTest.TestsFor));
  836. else if (RState == RTest.TestsFor)
  837. ElseStates->markUnreachable();
  838. }
  839. }
  840. }
  841. bool ConsumedBlockInfo::allBackEdgesVisited(const CFGBlock *CurrBlock,
  842. const CFGBlock *TargetBlock) {
  843. assert(CurrBlock && "Block pointer must not be NULL");
  844. assert(TargetBlock && "TargetBlock pointer must not be NULL");
  845. unsigned int CurrBlockOrder = VisitOrder[CurrBlock->getBlockID()];
  846. for (CFGBlock::const_pred_iterator PI = TargetBlock->pred_begin(),
  847. PE = TargetBlock->pred_end(); PI != PE; ++PI) {
  848. if (*PI && CurrBlockOrder < VisitOrder[(*PI)->getBlockID()] )
  849. return false;
  850. }
  851. return true;
  852. }
  853. void ConsumedBlockInfo::addInfo(
  854. const CFGBlock *Block, ConsumedStateMap *StateMap,
  855. std::unique_ptr<ConsumedStateMap> &OwnedStateMap) {
  856. assert(Block && "Block pointer must not be NULL");
  857. auto &Entry = StateMapsArray[Block->getBlockID()];
  858. if (Entry) {
  859. Entry->intersect(*StateMap);
  860. } else if (OwnedStateMap)
  861. Entry = std::move(OwnedStateMap);
  862. else
  863. Entry = std::make_unique<ConsumedStateMap>(*StateMap);
  864. }
  865. void ConsumedBlockInfo::addInfo(const CFGBlock *Block,
  866. std::unique_ptr<ConsumedStateMap> StateMap) {
  867. assert(Block && "Block pointer must not be NULL");
  868. auto &Entry = StateMapsArray[Block->getBlockID()];
  869. if (Entry) {
  870. Entry->intersect(*StateMap);
  871. } else {
  872. Entry = std::move(StateMap);
  873. }
  874. }
  875. ConsumedStateMap* ConsumedBlockInfo::borrowInfo(const CFGBlock *Block) {
  876. assert(Block && "Block pointer must not be NULL");
  877. assert(StateMapsArray[Block->getBlockID()] && "Block has no block info");
  878. return StateMapsArray[Block->getBlockID()].get();
  879. }
  880. void ConsumedBlockInfo::discardInfo(const CFGBlock *Block) {
  881. StateMapsArray[Block->getBlockID()] = nullptr;
  882. }
  883. std::unique_ptr<ConsumedStateMap>
  884. ConsumedBlockInfo::getInfo(const CFGBlock *Block) {
  885. assert(Block && "Block pointer must not be NULL");
  886. auto &Entry = StateMapsArray[Block->getBlockID()];
  887. return isBackEdgeTarget(Block) ? std::make_unique<ConsumedStateMap>(*Entry)
  888. : std::move(Entry);
  889. }
  890. bool ConsumedBlockInfo::isBackEdge(const CFGBlock *From, const CFGBlock *To) {
  891. assert(From && "From block must not be NULL");
  892. assert(To && "From block must not be NULL");
  893. return VisitOrder[From->getBlockID()] > VisitOrder[To->getBlockID()];
  894. }
  895. bool ConsumedBlockInfo::isBackEdgeTarget(const CFGBlock *Block) {
  896. assert(Block && "Block pointer must not be NULL");
  897. // Anything with less than two predecessors can't be the target of a back
  898. // edge.
  899. if (Block->pred_size() < 2)
  900. return false;
  901. unsigned int BlockVisitOrder = VisitOrder[Block->getBlockID()];
  902. for (CFGBlock::const_pred_iterator PI = Block->pred_begin(),
  903. PE = Block->pred_end(); PI != PE; ++PI) {
  904. if (*PI && BlockVisitOrder < VisitOrder[(*PI)->getBlockID()])
  905. return true;
  906. }
  907. return false;
  908. }
  909. void ConsumedStateMap::checkParamsForReturnTypestate(SourceLocation BlameLoc,
  910. ConsumedWarningsHandlerBase &WarningsHandler) const {
  911. for (const auto &DM : VarMap) {
  912. if (isa<ParmVarDecl>(DM.first)) {
  913. const auto *Param = cast<ParmVarDecl>(DM.first);
  914. const ReturnTypestateAttr *RTA = Param->getAttr<ReturnTypestateAttr>();
  915. if (!RTA)
  916. continue;
  917. ConsumedState ExpectedState = mapReturnTypestateAttrState(RTA);
  918. if (DM.second != ExpectedState)
  919. WarningsHandler.warnParamReturnTypestateMismatch(BlameLoc,
  920. Param->getNameAsString(), stateToString(ExpectedState),
  921. stateToString(DM.second));
  922. }
  923. }
  924. }
  925. void ConsumedStateMap::clearTemporaries() {
  926. TmpMap.clear();
  927. }
  928. ConsumedState ConsumedStateMap::getState(const VarDecl *Var) const {
  929. VarMapType::const_iterator Entry = VarMap.find(Var);
  930. if (Entry != VarMap.end())
  931. return Entry->second;
  932. return CS_None;
  933. }
  934. ConsumedState
  935. ConsumedStateMap::getState(const CXXBindTemporaryExpr *Tmp) const {
  936. TmpMapType::const_iterator Entry = TmpMap.find(Tmp);
  937. if (Entry != TmpMap.end())
  938. return Entry->second;
  939. return CS_None;
  940. }
  941. void ConsumedStateMap::intersect(const ConsumedStateMap &Other) {
  942. ConsumedState LocalState;
  943. if (this->From && this->From == Other.From && !Other.Reachable) {
  944. this->markUnreachable();
  945. return;
  946. }
  947. for (const auto &DM : Other.VarMap) {
  948. LocalState = this->getState(DM.first);
  949. if (LocalState == CS_None)
  950. continue;
  951. if (LocalState != DM.second)
  952. VarMap[DM.first] = CS_Unknown;
  953. }
  954. }
  955. void ConsumedStateMap::intersectAtLoopHead(const CFGBlock *LoopHead,
  956. const CFGBlock *LoopBack, const ConsumedStateMap *LoopBackStates,
  957. ConsumedWarningsHandlerBase &WarningsHandler) {
  958. ConsumedState LocalState;
  959. SourceLocation BlameLoc = getLastStmtLoc(LoopBack);
  960. for (const auto &DM : LoopBackStates->VarMap) {
  961. LocalState = this->getState(DM.first);
  962. if (LocalState == CS_None)
  963. continue;
  964. if (LocalState != DM.second) {
  965. VarMap[DM.first] = CS_Unknown;
  966. WarningsHandler.warnLoopStateMismatch(BlameLoc,
  967. DM.first->getNameAsString());
  968. }
  969. }
  970. }
  971. void ConsumedStateMap::markUnreachable() {
  972. this->Reachable = false;
  973. VarMap.clear();
  974. TmpMap.clear();
  975. }
  976. void ConsumedStateMap::setState(const VarDecl *Var, ConsumedState State) {
  977. VarMap[Var] = State;
  978. }
  979. void ConsumedStateMap::setState(const CXXBindTemporaryExpr *Tmp,
  980. ConsumedState State) {
  981. TmpMap[Tmp] = State;
  982. }
  983. void ConsumedStateMap::remove(const CXXBindTemporaryExpr *Tmp) {
  984. TmpMap.erase(Tmp);
  985. }
  986. bool ConsumedStateMap::operator!=(const ConsumedStateMap *Other) const {
  987. for (const auto &DM : Other->VarMap)
  988. if (this->getState(DM.first) != DM.second)
  989. return true;
  990. return false;
  991. }
  992. void ConsumedAnalyzer::determineExpectedReturnState(AnalysisDeclContext &AC,
  993. const FunctionDecl *D) {
  994. QualType ReturnType;
  995. if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
  996. ReturnType = Constructor->getThisType()->getPointeeType();
  997. } else
  998. ReturnType = D->getCallResultType();
  999. if (const ReturnTypestateAttr *RTSAttr = D->getAttr<ReturnTypestateAttr>()) {
  1000. const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
  1001. if (!RD || !RD->hasAttr<ConsumableAttr>()) {
  1002. // FIXME: This should be removed when template instantiation propagates
  1003. // attributes at template specialization definition, not
  1004. // declaration. When it is removed the test needs to be enabled
  1005. // in SemaDeclAttr.cpp.
  1006. WarningsHandler.warnReturnTypestateForUnconsumableType(
  1007. RTSAttr->getLocation(), ReturnType.getAsString());
  1008. ExpectedReturnState = CS_None;
  1009. } else
  1010. ExpectedReturnState = mapReturnTypestateAttrState(RTSAttr);
  1011. } else if (isConsumableType(ReturnType)) {
  1012. if (isAutoCastType(ReturnType)) // We can auto-cast the state to the
  1013. ExpectedReturnState = CS_None; // expected state.
  1014. else
  1015. ExpectedReturnState = mapConsumableAttrState(ReturnType);
  1016. }
  1017. else
  1018. ExpectedReturnState = CS_None;
  1019. }
  1020. bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,
  1021. const ConsumedStmtVisitor &Visitor) {
  1022. std::unique_ptr<ConsumedStateMap> FalseStates(
  1023. new ConsumedStateMap(*CurrStates));
  1024. PropagationInfo PInfo;
  1025. if (const auto *IfNode =
  1026. dyn_cast_or_null<IfStmt>(CurrBlock->getTerminator().getStmt())) {
  1027. const Expr *Cond = IfNode->getCond();
  1028. PInfo = Visitor.getInfo(Cond);
  1029. if (!PInfo.isValid() && isa<BinaryOperator>(Cond))
  1030. PInfo = Visitor.getInfo(cast<BinaryOperator>(Cond)->getRHS());
  1031. if (PInfo.isVarTest()) {
  1032. CurrStates->setSource(Cond);
  1033. FalseStates->setSource(Cond);
  1034. splitVarStateForIf(IfNode, PInfo.getVarTest(), CurrStates.get(),
  1035. FalseStates.get());
  1036. } else if (PInfo.isBinTest()) {
  1037. CurrStates->setSource(PInfo.testSourceNode());
  1038. FalseStates->setSource(PInfo.testSourceNode());
  1039. splitVarStateForIfBinOp(PInfo, CurrStates.get(), FalseStates.get());
  1040. } else {
  1041. return false;
  1042. }
  1043. } else if (const auto *BinOp =
  1044. dyn_cast_or_null<BinaryOperator>(CurrBlock->getTerminator().getStmt())) {
  1045. PInfo = Visitor.getInfo(BinOp->getLHS());
  1046. if (!PInfo.isVarTest()) {
  1047. if ((BinOp = dyn_cast_or_null<BinaryOperator>(BinOp->getLHS()))) {
  1048. PInfo = Visitor.getInfo(BinOp->getRHS());
  1049. if (!PInfo.isVarTest())
  1050. return false;
  1051. } else {
  1052. return false;
  1053. }
  1054. }
  1055. CurrStates->setSource(BinOp);
  1056. FalseStates->setSource(BinOp);
  1057. const VarTestResult &Test = PInfo.getVarTest();
  1058. ConsumedState VarState = CurrStates->getState(Test.Var);
  1059. if (BinOp->getOpcode() == BO_LAnd) {
  1060. if (VarState == CS_Unknown)
  1061. CurrStates->setState(Test.Var, Test.TestsFor);
  1062. else if (VarState == invertConsumedUnconsumed(Test.TestsFor))
  1063. CurrStates->markUnreachable();
  1064. } else if (BinOp->getOpcode() == BO_LOr) {
  1065. if (VarState == CS_Unknown)
  1066. FalseStates->setState(Test.Var,
  1067. invertConsumedUnconsumed(Test.TestsFor));
  1068. else if (VarState == Test.TestsFor)
  1069. FalseStates->markUnreachable();
  1070. }
  1071. } else {
  1072. return false;
  1073. }
  1074. CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin();
  1075. if (*SI)
  1076. BlockInfo.addInfo(*SI, std::move(CurrStates));
  1077. else
  1078. CurrStates = nullptr;
  1079. if (*++SI)
  1080. BlockInfo.addInfo(*SI, std::move(FalseStates));
  1081. return true;
  1082. }
  1083. void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
  1084. const auto *D = dyn_cast_or_null<FunctionDecl>(AC.getDecl());
  1085. if (!D)
  1086. return;
  1087. CFG *CFGraph = AC.getCFG();
  1088. if (!CFGraph)
  1089. return;
  1090. determineExpectedReturnState(AC, D);
  1091. PostOrderCFGView *SortedGraph = AC.getAnalysis<PostOrderCFGView>();
  1092. // AC.getCFG()->viewCFG(LangOptions());
  1093. BlockInfo = ConsumedBlockInfo(CFGraph->getNumBlockIDs(), SortedGraph);
  1094. CurrStates = std::make_unique<ConsumedStateMap>();
  1095. ConsumedStmtVisitor Visitor(*this, CurrStates.get());
  1096. // Add all trackable parameters to the state map.
  1097. for (const auto *PI : D->parameters())
  1098. Visitor.VisitParmVarDecl(PI);
  1099. // Visit all of the function's basic blocks.
  1100. for (const auto *CurrBlock : *SortedGraph) {
  1101. if (!CurrStates)
  1102. CurrStates = BlockInfo.getInfo(CurrBlock);
  1103. if (!CurrStates) {
  1104. continue;
  1105. } else if (!CurrStates->isReachable()) {
  1106. CurrStates = nullptr;
  1107. continue;
  1108. }
  1109. Visitor.reset(CurrStates.get());
  1110. // Visit all of the basic block's statements.
  1111. for (const auto &B : *CurrBlock) {
  1112. switch (B.getKind()) {
  1113. case CFGElement::Statement:
  1114. Visitor.Visit(B.castAs<CFGStmt>().getStmt());
  1115. break;
  1116. case CFGElement::TemporaryDtor: {
  1117. const CFGTemporaryDtor &DTor = B.castAs<CFGTemporaryDtor>();
  1118. const CXXBindTemporaryExpr *BTE = DTor.getBindTemporaryExpr();
  1119. Visitor.checkCallability(PropagationInfo(BTE),
  1120. DTor.getDestructorDecl(AC.getASTContext()),
  1121. BTE->getExprLoc());
  1122. CurrStates->remove(BTE);
  1123. break;
  1124. }
  1125. case CFGElement::AutomaticObjectDtor: {
  1126. const CFGAutomaticObjDtor &DTor = B.castAs<CFGAutomaticObjDtor>();
  1127. SourceLocation Loc = DTor.getTriggerStmt()->getEndLoc();
  1128. const VarDecl *Var = DTor.getVarDecl();
  1129. Visitor.checkCallability(PropagationInfo(Var),
  1130. DTor.getDestructorDecl(AC.getASTContext()),
  1131. Loc);
  1132. break;
  1133. }
  1134. default:
  1135. break;
  1136. }
  1137. }
  1138. // TODO: Handle other forms of branching with precision, including while-
  1139. // and for-loops. (Deferred)
  1140. if (!splitState(CurrBlock, Visitor)) {
  1141. CurrStates->setSource(nullptr);
  1142. if (CurrBlock->succ_size() > 1 ||
  1143. (CurrBlock->succ_size() == 1 &&
  1144. (*CurrBlock->succ_begin())->pred_size() > 1)) {
  1145. auto *RawState = CurrStates.get();
  1146. for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
  1147. SE = CurrBlock->succ_end(); SI != SE; ++SI) {
  1148. if (*SI == nullptr) continue;
  1149. if (BlockInfo.isBackEdge(CurrBlock, *SI)) {
  1150. BlockInfo.borrowInfo(*SI)->intersectAtLoopHead(
  1151. *SI, CurrBlock, RawState, WarningsHandler);
  1152. if (BlockInfo.allBackEdgesVisited(CurrBlock, *SI))
  1153. BlockInfo.discardInfo(*SI);
  1154. } else {
  1155. BlockInfo.addInfo(*SI, RawState, CurrStates);
  1156. }
  1157. }
  1158. CurrStates = nullptr;
  1159. }
  1160. }
  1161. if (CurrBlock == &AC.getCFG()->getExit() &&
  1162. D->getCallResultType()->isVoidType())
  1163. CurrStates->checkParamsForReturnTypestate(D->getLocation(),
  1164. WarningsHandler);
  1165. } // End of block iterator.
  1166. // Delete the last existing state map.
  1167. CurrStates = nullptr;
  1168. WarningsHandler.emitDiagnostics();
  1169. }