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