Consumed.cpp 44 KB

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