xref: /llvm-project/clang/lib/Analysis/Consumed.cpp (revision 535bbcccb12b3a98bd53b68fef678e38814dbb0c)
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   void forwardInfo(const Stmt *From, const Stmt *To);
475   void copyInfo(const Stmt *From, const Stmt *To, ConsumedState CS);
476   ConsumedState getInfo(const Stmt *From);
477   void setInfo(const Stmt *To, ConsumedState NS);
478   void propagateReturnType(const Stmt *Call, const FunctionDecl *Fun);
479 
480 public:
481   void checkCallability(const PropagationInfo &PInfo,
482                         const FunctionDecl *FunDecl,
483                         SourceLocation BlameLoc);
484   bool handleCall(const CallExpr *Call, const Expr *ObjArg,
485                   const FunctionDecl *FunD);
486 
487   void VisitBinaryOperator(const BinaryOperator *BinOp);
488   void VisitCallExpr(const CallExpr *Call);
489   void VisitCastExpr(const CastExpr *Cast);
490   void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Temp);
491   void VisitCXXConstructExpr(const CXXConstructExpr *Call);
492   void VisitCXXMemberCallExpr(const CXXMemberCallExpr *Call);
493   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Call);
494   void VisitDeclRefExpr(const DeclRefExpr *DeclRef);
495   void VisitDeclStmt(const DeclStmt *DelcS);
496   void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Temp);
497   void VisitMemberExpr(const MemberExpr *MExpr);
498   void VisitParmVarDecl(const ParmVarDecl *Param);
499   void VisitReturnStmt(const ReturnStmt *Ret);
500   void VisitUnaryOperator(const UnaryOperator *UOp);
501   void VisitVarDecl(const VarDecl *Var);
502 
503   ConsumedStmtVisitor(AnalysisDeclContext &AC, ConsumedAnalyzer &Analyzer,
504                       ConsumedStateMap *StateMap)
505       : AC(AC), Analyzer(Analyzer), StateMap(StateMap) {}
506 
507   PropagationInfo getInfo(const Stmt *StmtNode) const {
508     ConstInfoEntry Entry = PropagationMap.find(StmtNode);
509 
510     if (Entry != PropagationMap.end())
511       return Entry->second;
512     else
513       return PropagationInfo();
514   }
515 
516   void reset(ConsumedStateMap *NewStateMap) {
517     StateMap = NewStateMap;
518   }
519 };
520 
521 
522 void ConsumedStmtVisitor::forwardInfo(const Stmt *From, const Stmt *To) {
523   InfoEntry Entry = PropagationMap.find(From);
524   if (Entry != PropagationMap.end())
525     PropagationMap.insert(PairType(To, Entry->second));
526 }
527 
528 
529 // Create a new state for To, which is initialized to the state of From.
530 // If NS is not CS_None, sets the state of From to NS.
531 void ConsumedStmtVisitor::copyInfo(const Stmt *From, const Stmt *To,
532                                    ConsumedState NS) {
533   InfoEntry Entry = PropagationMap.find(From);
534   if (Entry != PropagationMap.end()) {
535     PropagationInfo& PInfo = Entry->second;
536     ConsumedState CS = PInfo.getAsState(StateMap);
537     if (CS != CS_None)
538       PropagationMap.insert(PairType(To, CS));
539     if (NS != CS_None && PInfo.isPointerToValue())
540       setStateForVarOrTmp(StateMap, PInfo, NS);
541   }
542 }
543 
544 
545 // Get the ConsumedState for From
546 ConsumedState ConsumedStmtVisitor::getInfo(const Stmt *From) {
547   InfoEntry Entry = PropagationMap.find(From);
548   if (Entry != PropagationMap.end()) {
549     PropagationInfo& PInfo = Entry->second;
550     return PInfo.getAsState(StateMap);
551   }
552   return CS_None;
553 }
554 
555 
556 // If we already have info for To then update it, otherwise create a new entry.
557 void ConsumedStmtVisitor::setInfo(const Stmt *To, ConsumedState NS) {
558   InfoEntry Entry = PropagationMap.find(To);
559   if (Entry != PropagationMap.end()) {
560     PropagationInfo& PInfo = Entry->second;
561     if (PInfo.isPointerToValue())
562       setStateForVarOrTmp(StateMap, PInfo, NS);
563   } else if (NS != CS_None) {
564      PropagationMap.insert(PairType(To, PropagationInfo(NS)));
565   }
566 }
567 
568 
569 
570 void ConsumedStmtVisitor::checkCallability(const PropagationInfo &PInfo,
571                                            const FunctionDecl *FunDecl,
572                                            SourceLocation BlameLoc) {
573   assert(!PInfo.isTest());
574 
575   const CallableWhenAttr *CWAttr = FunDecl->getAttr<CallableWhenAttr>();
576   if (!CWAttr)
577     return;
578 
579   if (PInfo.isVar()) {
580     ConsumedState VarState = StateMap->getState(PInfo.getVar());
581 
582     if (VarState == CS_None || isCallableInState(CWAttr, VarState))
583       return;
584 
585     Analyzer.WarningsHandler.warnUseInInvalidState(
586       FunDecl->getNameAsString(), PInfo.getVar()->getNameAsString(),
587       stateToString(VarState), BlameLoc);
588 
589   } else {
590     ConsumedState TmpState = PInfo.getAsState(StateMap);
591 
592     if (TmpState == CS_None || isCallableInState(CWAttr, TmpState))
593       return;
594 
595     Analyzer.WarningsHandler.warnUseOfTempInInvalidState(
596       FunDecl->getNameAsString(), stateToString(TmpState), BlameLoc);
597   }
598 }
599 
600 
601 // Factors out common behavior for function, method, and operator calls.
602 // Check parameters and set parameter state if necessary.
603 // Returns true if the state of ObjArg is set, or false otherwise.
604 bool ConsumedStmtVisitor::handleCall(const CallExpr *Call, const Expr *ObjArg,
605                                      const FunctionDecl *FunD) {
606   unsigned Offset = 0;
607   if (isa<CXXOperatorCallExpr>(Call) && isa<CXXMethodDecl>(FunD))
608     Offset = 1;  // first argument is 'this'
609 
610   // check explicit parameters
611   for (unsigned Index = Offset; Index < Call->getNumArgs(); ++Index) {
612     // Skip variable argument lists.
613     if (Index - Offset >= FunD->getNumParams())
614       break;
615 
616     const ParmVarDecl *Param = FunD->getParamDecl(Index - Offset);
617     QualType ParamType = Param->getType();
618 
619     InfoEntry Entry = PropagationMap.find(Call->getArg(Index));
620 
621     if (Entry == PropagationMap.end() || Entry->second.isTest())
622       continue;
623     PropagationInfo PInfo = Entry->second;
624 
625     // Check that the parameter is in the correct state.
626     if (ParamTypestateAttr *PTA = Param->getAttr<ParamTypestateAttr>()) {
627       ConsumedState ParamState = PInfo.getAsState(StateMap);
628       ConsumedState ExpectedState = mapParamTypestateAttrState(PTA);
629 
630       if (ParamState != ExpectedState)
631         Analyzer.WarningsHandler.warnParamTypestateMismatch(
632           Call->getArg(Index)->getExprLoc(),
633           stateToString(ExpectedState), stateToString(ParamState));
634     }
635 
636     if (!(Entry->second.isVar() || Entry->second.isTmp()))
637       continue;
638 
639     // Adjust state on the caller side.
640     if (isRValueRef(ParamType))
641       setStateForVarOrTmp(StateMap, PInfo, consumed::CS_Consumed);
642     else if (ReturnTypestateAttr *RT = Param->getAttr<ReturnTypestateAttr>())
643       setStateForVarOrTmp(StateMap, PInfo, mapReturnTypestateAttrState(RT));
644     else if (isPointerOrRef(ParamType) &&
645              (!ParamType->getPointeeType().isConstQualified() ||
646               isSetOnReadPtrType(ParamType)))
647       setStateForVarOrTmp(StateMap, PInfo, consumed::CS_Unknown);
648   }
649 
650   if (!ObjArg)
651     return false;
652 
653   // check implicit 'self' parameter, if present
654   InfoEntry Entry = PropagationMap.find(ObjArg);
655   if (Entry != PropagationMap.end()) {
656     PropagationInfo PInfo = Entry->second;
657     checkCallability(PInfo, FunD, Call->getExprLoc());
658 
659     if (SetTypestateAttr *STA = FunD->getAttr<SetTypestateAttr>()) {
660       if (PInfo.isVar()) {
661         StateMap->setState(PInfo.getVar(), mapSetTypestateAttrState(STA));
662         return true;
663       }
664       else if (PInfo.isTmp()) {
665         StateMap->setState(PInfo.getTmp(), mapSetTypestateAttrState(STA));
666         return true;
667       }
668     }
669     else if (isTestingFunction(FunD) && PInfo.isVar()) {
670       PropagationMap.insert(PairType(Call,
671         PropagationInfo(PInfo.getVar(), testsFor(FunD))));
672     }
673   }
674   return false;
675 }
676 
677 
678 void ConsumedStmtVisitor::propagateReturnType(const Stmt *Call,
679                                               const FunctionDecl *Fun) {
680   QualType RetType = Fun->getCallResultType();
681   if (RetType->isReferenceType())
682     RetType = RetType->getPointeeType();
683 
684   if (isConsumableType(RetType)) {
685     ConsumedState ReturnState;
686     if (ReturnTypestateAttr *RTA = Fun->getAttr<ReturnTypestateAttr>())
687       ReturnState = mapReturnTypestateAttrState(RTA);
688     else
689       ReturnState = mapConsumableAttrState(RetType);
690 
691     PropagationMap.insert(PairType(Call, PropagationInfo(ReturnState)));
692   }
693 }
694 
695 
696 void ConsumedStmtVisitor::VisitBinaryOperator(const BinaryOperator *BinOp) {
697   switch (BinOp->getOpcode()) {
698   case BO_LAnd:
699   case BO_LOr : {
700     InfoEntry LEntry = PropagationMap.find(BinOp->getLHS()),
701               REntry = PropagationMap.find(BinOp->getRHS());
702 
703     VarTestResult LTest, RTest;
704 
705     if (LEntry != PropagationMap.end() && LEntry->second.isVarTest()) {
706       LTest = LEntry->second.getVarTest();
707 
708     } else {
709       LTest.Var      = NULL;
710       LTest.TestsFor = CS_None;
711     }
712 
713     if (REntry != PropagationMap.end() && REntry->second.isVarTest()) {
714       RTest = REntry->second.getVarTest();
715 
716     } else {
717       RTest.Var      = NULL;
718       RTest.TestsFor = CS_None;
719     }
720 
721     if (!(LTest.Var == NULL && RTest.Var == NULL))
722       PropagationMap.insert(PairType(BinOp, PropagationInfo(BinOp,
723         static_cast<EffectiveOp>(BinOp->getOpcode() == BO_LOr), LTest, RTest)));
724 
725     break;
726   }
727 
728   case BO_PtrMemD:
729   case BO_PtrMemI:
730     forwardInfo(BinOp->getLHS(), BinOp);
731     break;
732 
733   default:
734     break;
735   }
736 }
737 
738 static bool isStdNamespace(const DeclContext *DC) {
739   if (!DC->isNamespace()) return false;
740   while (DC->getParent()->isNamespace())
741     DC = DC->getParent();
742   const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC);
743 
744   return ND && ND->getName() == "std" &&
745          ND->getDeclContext()->isTranslationUnit();
746 }
747 
748 void ConsumedStmtVisitor::VisitCallExpr(const CallExpr *Call) {
749   const FunctionDecl *FunDecl = Call->getDirectCallee();
750   if (!FunDecl)
751     return;
752 
753   // Special case for the std::move function.
754   // TODO: Make this more specific. (Deferred)
755   if (Call->getNumArgs() == 1 &&
756       FunDecl->getNameAsString() == "move" &&
757       isStdNamespace(FunDecl->getDeclContext())) {
758     copyInfo(Call->getArg(0), Call, CS_Consumed);
759     return;
760   }
761 
762   handleCall(Call, 0, FunDecl);
763   propagateReturnType(Call, FunDecl);
764 }
765 
766 void ConsumedStmtVisitor::VisitCastExpr(const CastExpr *Cast) {
767   forwardInfo(Cast->getSubExpr(), Cast);
768 }
769 
770 void ConsumedStmtVisitor::VisitCXXBindTemporaryExpr(
771   const CXXBindTemporaryExpr *Temp) {
772 
773   InfoEntry Entry = PropagationMap.find(Temp->getSubExpr());
774 
775   if (Entry != PropagationMap.end() && !Entry->second.isTest()) {
776     StateMap->setState(Temp, Entry->second.getAsState(StateMap));
777     PropagationMap.insert(PairType(Temp, PropagationInfo(Temp)));
778   }
779 }
780 
781 void ConsumedStmtVisitor::VisitCXXConstructExpr(const CXXConstructExpr *Call) {
782   CXXConstructorDecl *Constructor = Call->getConstructor();
783 
784   ASTContext &CurrContext = AC.getASTContext();
785   QualType ThisType = Constructor->getThisType(CurrContext)->getPointeeType();
786 
787   if (!isConsumableType(ThisType))
788     return;
789 
790   // FIXME: What should happen if someone annotates the move constructor?
791   if (ReturnTypestateAttr *RTA = Constructor->getAttr<ReturnTypestateAttr>()) {
792     // TODO: Adjust state of args appropriately.
793     ConsumedState RetState = mapReturnTypestateAttrState(RTA);
794     PropagationMap.insert(PairType(Call, PropagationInfo(RetState)));
795   } else if (Constructor->isDefaultConstructor()) {
796     PropagationMap.insert(PairType(Call,
797       PropagationInfo(consumed::CS_Consumed)));
798   } else if (Constructor->isMoveConstructor()) {
799     copyInfo(Call->getArg(0), Call, CS_Consumed);
800   } else if (Constructor->isCopyConstructor()) {
801     // Copy state from arg.  If setStateOnRead then set arg to CS_Unknown.
802     ConsumedState NS =
803       isSetOnReadPtrType(Constructor->getThisType(CurrContext)) ?
804       CS_Unknown : CS_None;
805     copyInfo(Call->getArg(0), Call, NS);
806   } else {
807     // TODO: Adjust state of args appropriately.
808     ConsumedState RetState = mapConsumableAttrState(ThisType);
809     PropagationMap.insert(PairType(Call, PropagationInfo(RetState)));
810   }
811 }
812 
813 
814 void ConsumedStmtVisitor::VisitCXXMemberCallExpr(
815     const CXXMemberCallExpr *Call) {
816   CXXMethodDecl* MD = Call->getMethodDecl();
817   if (!MD)
818     return;
819 
820   handleCall(Call, Call->getImplicitObjectArgument(), MD);
821   propagateReturnType(Call, MD);
822 }
823 
824 
825 void ConsumedStmtVisitor::VisitCXXOperatorCallExpr(
826     const CXXOperatorCallExpr *Call) {
827 
828   const FunctionDecl *FunDecl =
829     dyn_cast_or_null<FunctionDecl>(Call->getDirectCallee());
830   if (!FunDecl) return;
831 
832   if (Call->getOperator() == OO_Equal) {
833     ConsumedState CS = getInfo(Call->getArg(1));
834     if (!handleCall(Call, Call->getArg(0), FunDecl))
835       setInfo(Call->getArg(0), CS);
836     return;
837   }
838 
839   if (const CXXMemberCallExpr *MCall = dyn_cast<CXXMemberCallExpr>(Call))
840     handleCall(MCall, MCall->getImplicitObjectArgument(), FunDecl);
841   else
842     handleCall(Call, Call->getArg(0), FunDecl);
843 
844   propagateReturnType(Call, FunDecl);
845 }
846 
847 void ConsumedStmtVisitor::VisitDeclRefExpr(const DeclRefExpr *DeclRef) {
848   if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(DeclRef->getDecl()))
849     if (StateMap->getState(Var) != consumed::CS_None)
850       PropagationMap.insert(PairType(DeclRef, PropagationInfo(Var)));
851 }
852 
853 void ConsumedStmtVisitor::VisitDeclStmt(const DeclStmt *DeclS) {
854   for (const auto *DI : DeclS->decls())
855     if (isa<VarDecl>(DI))
856       VisitVarDecl(cast<VarDecl>(DI));
857 
858   if (DeclS->isSingleDecl())
859     if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(DeclS->getSingleDecl()))
860       PropagationMap.insert(PairType(DeclS, PropagationInfo(Var)));
861 }
862 
863 void ConsumedStmtVisitor::VisitMaterializeTemporaryExpr(
864   const MaterializeTemporaryExpr *Temp) {
865 
866   forwardInfo(Temp->GetTemporaryExpr(), Temp);
867 }
868 
869 void ConsumedStmtVisitor::VisitMemberExpr(const MemberExpr *MExpr) {
870   forwardInfo(MExpr->getBase(), MExpr);
871 }
872 
873 
874 void ConsumedStmtVisitor::VisitParmVarDecl(const ParmVarDecl *Param) {
875   QualType ParamType = Param->getType();
876   ConsumedState ParamState = consumed::CS_None;
877 
878   if (const ParamTypestateAttr *PTA = Param->getAttr<ParamTypestateAttr>())
879     ParamState = mapParamTypestateAttrState(PTA);
880   else if (isConsumableType(ParamType))
881     ParamState = mapConsumableAttrState(ParamType);
882   else if (isRValueRef(ParamType) &&
883            isConsumableType(ParamType->getPointeeType()))
884     ParamState = mapConsumableAttrState(ParamType->getPointeeType());
885   else if (ParamType->isReferenceType() &&
886            isConsumableType(ParamType->getPointeeType()))
887     ParamState = consumed::CS_Unknown;
888 
889   if (ParamState != CS_None)
890     StateMap->setState(Param, ParamState);
891 }
892 
893 void ConsumedStmtVisitor::VisitReturnStmt(const ReturnStmt *Ret) {
894   ConsumedState ExpectedState = Analyzer.getExpectedReturnState();
895 
896   if (ExpectedState != CS_None) {
897     InfoEntry Entry = PropagationMap.find(Ret->getRetValue());
898 
899     if (Entry != PropagationMap.end()) {
900       ConsumedState RetState = Entry->second.getAsState(StateMap);
901 
902       if (RetState != ExpectedState)
903         Analyzer.WarningsHandler.warnReturnTypestateMismatch(
904           Ret->getReturnLoc(), stateToString(ExpectedState),
905           stateToString(RetState));
906     }
907   }
908 
909   StateMap->checkParamsForReturnTypestate(Ret->getLocStart(),
910                                           Analyzer.WarningsHandler);
911 }
912 
913 void ConsumedStmtVisitor::VisitUnaryOperator(const UnaryOperator *UOp) {
914   InfoEntry Entry = PropagationMap.find(UOp->getSubExpr()->IgnoreParens());
915   if (Entry == PropagationMap.end()) return;
916 
917   switch (UOp->getOpcode()) {
918   case UO_AddrOf:
919     PropagationMap.insert(PairType(UOp, Entry->second));
920     break;
921 
922   case UO_LNot:
923     if (Entry->second.isTest())
924       PropagationMap.insert(PairType(UOp, Entry->second.invertTest()));
925     break;
926 
927   default:
928     break;
929   }
930 }
931 
932 // TODO: See if I need to check for reference types here.
933 void ConsumedStmtVisitor::VisitVarDecl(const VarDecl *Var) {
934   if (isConsumableType(Var->getType())) {
935     if (Var->hasInit()) {
936       MapType::iterator VIT = PropagationMap.find(
937         Var->getInit()->IgnoreImplicit());
938       if (VIT != PropagationMap.end()) {
939         PropagationInfo PInfo = VIT->second;
940         ConsumedState St = PInfo.getAsState(StateMap);
941 
942         if (St != consumed::CS_None) {
943           StateMap->setState(Var, St);
944           return;
945         }
946       }
947     }
948     // Otherwise
949     StateMap->setState(Var, consumed::CS_Unknown);
950   }
951 }
952 }} // end clang::consumed::ConsumedStmtVisitor
953 
954 namespace clang {
955 namespace consumed {
956 
957 void splitVarStateForIf(const IfStmt * IfNode, const VarTestResult &Test,
958                         ConsumedStateMap *ThenStates,
959                         ConsumedStateMap *ElseStates) {
960 
961   ConsumedState VarState = ThenStates->getState(Test.Var);
962 
963   if (VarState == CS_Unknown) {
964     ThenStates->setState(Test.Var, Test.TestsFor);
965     ElseStates->setState(Test.Var, invertConsumedUnconsumed(Test.TestsFor));
966 
967   } else if (VarState == invertConsumedUnconsumed(Test.TestsFor)) {
968     ThenStates->markUnreachable();
969 
970   } else if (VarState == Test.TestsFor) {
971     ElseStates->markUnreachable();
972   }
973 }
974 
975 void splitVarStateForIfBinOp(const PropagationInfo &PInfo,
976   ConsumedStateMap *ThenStates, ConsumedStateMap *ElseStates) {
977 
978   const VarTestResult &LTest = PInfo.getLTest(),
979                       &RTest = PInfo.getRTest();
980 
981   ConsumedState LState = LTest.Var ? ThenStates->getState(LTest.Var) : CS_None,
982                 RState = RTest.Var ? ThenStates->getState(RTest.Var) : CS_None;
983 
984   if (LTest.Var) {
985     if (PInfo.testEffectiveOp() == EO_And) {
986       if (LState == CS_Unknown) {
987         ThenStates->setState(LTest.Var, LTest.TestsFor);
988 
989       } else if (LState == invertConsumedUnconsumed(LTest.TestsFor)) {
990         ThenStates->markUnreachable();
991 
992       } else if (LState == LTest.TestsFor && isKnownState(RState)) {
993         if (RState == RTest.TestsFor)
994           ElseStates->markUnreachable();
995         else
996           ThenStates->markUnreachable();
997       }
998 
999     } else {
1000       if (LState == CS_Unknown) {
1001         ElseStates->setState(LTest.Var,
1002                              invertConsumedUnconsumed(LTest.TestsFor));
1003 
1004       } else if (LState == LTest.TestsFor) {
1005         ElseStates->markUnreachable();
1006 
1007       } else if (LState == invertConsumedUnconsumed(LTest.TestsFor) &&
1008                  isKnownState(RState)) {
1009 
1010         if (RState == RTest.TestsFor)
1011           ElseStates->markUnreachable();
1012         else
1013           ThenStates->markUnreachable();
1014       }
1015     }
1016   }
1017 
1018   if (RTest.Var) {
1019     if (PInfo.testEffectiveOp() == EO_And) {
1020       if (RState == CS_Unknown)
1021         ThenStates->setState(RTest.Var, RTest.TestsFor);
1022       else if (RState == invertConsumedUnconsumed(RTest.TestsFor))
1023         ThenStates->markUnreachable();
1024 
1025     } else {
1026       if (RState == CS_Unknown)
1027         ElseStates->setState(RTest.Var,
1028                              invertConsumedUnconsumed(RTest.TestsFor));
1029       else if (RState == RTest.TestsFor)
1030         ElseStates->markUnreachable();
1031     }
1032   }
1033 }
1034 
1035 bool ConsumedBlockInfo::allBackEdgesVisited(const CFGBlock *CurrBlock,
1036                                             const CFGBlock *TargetBlock) {
1037 
1038   assert(CurrBlock && "Block pointer must not be NULL");
1039   assert(TargetBlock && "TargetBlock pointer must not be NULL");
1040 
1041   unsigned int CurrBlockOrder = VisitOrder[CurrBlock->getBlockID()];
1042   for (CFGBlock::const_pred_iterator PI = TargetBlock->pred_begin(),
1043        PE = TargetBlock->pred_end(); PI != PE; ++PI) {
1044     if (*PI && CurrBlockOrder < VisitOrder[(*PI)->getBlockID()] )
1045       return false;
1046   }
1047   return true;
1048 }
1049 
1050 void ConsumedBlockInfo::addInfo(const CFGBlock *Block,
1051                                 ConsumedStateMap *StateMap,
1052                                 bool &AlreadyOwned) {
1053 
1054   assert(Block && "Block pointer must not be NULL");
1055 
1056   ConsumedStateMap *Entry = StateMapsArray[Block->getBlockID()];
1057 
1058   if (Entry) {
1059     Entry->intersect(StateMap);
1060 
1061   } else if (AlreadyOwned) {
1062     StateMapsArray[Block->getBlockID()] = new ConsumedStateMap(*StateMap);
1063 
1064   } else {
1065     StateMapsArray[Block->getBlockID()] = StateMap;
1066     AlreadyOwned = true;
1067   }
1068 }
1069 
1070 void ConsumedBlockInfo::addInfo(const CFGBlock *Block,
1071                                 ConsumedStateMap *StateMap) {
1072 
1073   assert(Block != NULL && "Block pointer must not be NULL");
1074 
1075   ConsumedStateMap *Entry = StateMapsArray[Block->getBlockID()];
1076 
1077   if (Entry) {
1078     Entry->intersect(StateMap);
1079     delete StateMap;
1080 
1081   } else {
1082     StateMapsArray[Block->getBlockID()] = StateMap;
1083   }
1084 }
1085 
1086 ConsumedStateMap* ConsumedBlockInfo::borrowInfo(const CFGBlock *Block) {
1087   assert(Block && "Block pointer must not be NULL");
1088   assert(StateMapsArray[Block->getBlockID()] && "Block has no block info");
1089 
1090   return StateMapsArray[Block->getBlockID()];
1091 }
1092 
1093 void ConsumedBlockInfo::discardInfo(const CFGBlock *Block) {
1094   unsigned int BlockID = Block->getBlockID();
1095   delete StateMapsArray[BlockID];
1096   StateMapsArray[BlockID] = NULL;
1097 }
1098 
1099 ConsumedStateMap* ConsumedBlockInfo::getInfo(const CFGBlock *Block) {
1100   assert(Block && "Block pointer must not be NULL");
1101 
1102   ConsumedStateMap *StateMap = StateMapsArray[Block->getBlockID()];
1103   if (isBackEdgeTarget(Block)) {
1104     return new ConsumedStateMap(*StateMap);
1105   } else {
1106     StateMapsArray[Block->getBlockID()] = NULL;
1107     return StateMap;
1108   }
1109 }
1110 
1111 bool ConsumedBlockInfo::isBackEdge(const CFGBlock *From, const CFGBlock *To) {
1112   assert(From && "From block must not be NULL");
1113   assert(To   && "From block must not be NULL");
1114 
1115   return VisitOrder[From->getBlockID()] > VisitOrder[To->getBlockID()];
1116 }
1117 
1118 bool ConsumedBlockInfo::isBackEdgeTarget(const CFGBlock *Block) {
1119   assert(Block != NULL && "Block pointer must not be NULL");
1120 
1121   // Anything with less than two predecessors can't be the target of a back
1122   // edge.
1123   if (Block->pred_size() < 2)
1124     return false;
1125 
1126   unsigned int BlockVisitOrder = VisitOrder[Block->getBlockID()];
1127   for (CFGBlock::const_pred_iterator PI = Block->pred_begin(),
1128        PE = Block->pred_end(); PI != PE; ++PI) {
1129     if (*PI && BlockVisitOrder < VisitOrder[(*PI)->getBlockID()])
1130       return true;
1131   }
1132   return false;
1133 }
1134 
1135 void ConsumedStateMap::checkParamsForReturnTypestate(SourceLocation BlameLoc,
1136   ConsumedWarningsHandlerBase &WarningsHandler) const {
1137 
1138   for (VarMapType::const_iterator DMI = VarMap.begin(), DME = VarMap.end();
1139        DMI != DME; ++DMI) {
1140 
1141     if (isa<ParmVarDecl>(DMI->first)) {
1142       const ParmVarDecl *Param = cast<ParmVarDecl>(DMI->first);
1143       const ReturnTypestateAttr *RTA = Param->getAttr<ReturnTypestateAttr>();
1144 
1145       if (!RTA)
1146         continue;
1147 
1148       ConsumedState ExpectedState = mapReturnTypestateAttrState(RTA);
1149       if (DMI->second != ExpectedState)
1150         WarningsHandler.warnParamReturnTypestateMismatch(BlameLoc,
1151           Param->getNameAsString(), stateToString(ExpectedState),
1152           stateToString(DMI->second));
1153     }
1154   }
1155 }
1156 
1157 void ConsumedStateMap::clearTemporaries() {
1158   TmpMap.clear();
1159 }
1160 
1161 ConsumedState ConsumedStateMap::getState(const VarDecl *Var) const {
1162   VarMapType::const_iterator Entry = VarMap.find(Var);
1163 
1164   if (Entry != VarMap.end())
1165     return Entry->second;
1166 
1167   return CS_None;
1168 }
1169 
1170 ConsumedState
1171 ConsumedStateMap::getState(const CXXBindTemporaryExpr *Tmp) const {
1172   TmpMapType::const_iterator Entry = TmpMap.find(Tmp);
1173 
1174   if (Entry != TmpMap.end())
1175     return Entry->second;
1176 
1177   return CS_None;
1178 }
1179 
1180 void ConsumedStateMap::intersect(const ConsumedStateMap *Other) {
1181   ConsumedState LocalState;
1182 
1183   if (this->From && this->From == Other->From && !Other->Reachable) {
1184     this->markUnreachable();
1185     return;
1186   }
1187 
1188   for (VarMapType::const_iterator DMI = Other->VarMap.begin(),
1189        DME = Other->VarMap.end(); DMI != DME; ++DMI) {
1190 
1191     LocalState = this->getState(DMI->first);
1192 
1193     if (LocalState == CS_None)
1194       continue;
1195 
1196     if (LocalState != DMI->second)
1197        VarMap[DMI->first] = CS_Unknown;
1198   }
1199 }
1200 
1201 void ConsumedStateMap::intersectAtLoopHead(const CFGBlock *LoopHead,
1202   const CFGBlock *LoopBack, const ConsumedStateMap *LoopBackStates,
1203   ConsumedWarningsHandlerBase &WarningsHandler) {
1204 
1205   ConsumedState LocalState;
1206   SourceLocation BlameLoc = getLastStmtLoc(LoopBack);
1207 
1208   for (VarMapType::const_iterator DMI = LoopBackStates->VarMap.begin(),
1209        DME = LoopBackStates->VarMap.end(); DMI != DME; ++DMI) {
1210 
1211     LocalState = this->getState(DMI->first);
1212 
1213     if (LocalState == CS_None)
1214       continue;
1215 
1216     if (LocalState != DMI->second) {
1217       VarMap[DMI->first] = CS_Unknown;
1218       WarningsHandler.warnLoopStateMismatch(
1219         BlameLoc, DMI->first->getNameAsString());
1220     }
1221   }
1222 }
1223 
1224 void ConsumedStateMap::markUnreachable() {
1225   this->Reachable = false;
1226   VarMap.clear();
1227   TmpMap.clear();
1228 }
1229 
1230 void ConsumedStateMap::setState(const VarDecl *Var, ConsumedState State) {
1231   VarMap[Var] = State;
1232 }
1233 
1234 void ConsumedStateMap::setState(const CXXBindTemporaryExpr *Tmp,
1235                                 ConsumedState State) {
1236   TmpMap[Tmp] = State;
1237 }
1238 
1239 void ConsumedStateMap::remove(const VarDecl *Var) {
1240   VarMap.erase(Var);
1241 }
1242 
1243 bool ConsumedStateMap::operator!=(const ConsumedStateMap *Other) const {
1244   for (VarMapType::const_iterator DMI = Other->VarMap.begin(),
1245        DME = Other->VarMap.end(); DMI != DME; ++DMI) {
1246 
1247     if (this->getState(DMI->first) != DMI->second)
1248       return true;
1249   }
1250 
1251   return false;
1252 }
1253 
1254 void ConsumedAnalyzer::determineExpectedReturnState(AnalysisDeclContext &AC,
1255                                                     const FunctionDecl *D) {
1256   QualType ReturnType;
1257   if (const CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
1258     ASTContext &CurrContext = AC.getASTContext();
1259     ReturnType = Constructor->getThisType(CurrContext)->getPointeeType();
1260   } else
1261     ReturnType = D->getCallResultType();
1262 
1263   if (const ReturnTypestateAttr *RTSAttr = D->getAttr<ReturnTypestateAttr>()) {
1264     const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
1265     if (!RD || !RD->hasAttr<ConsumableAttr>()) {
1266       // FIXME: This should be removed when template instantiation propagates
1267       //        attributes at template specialization definition, not
1268       //        declaration. When it is removed the test needs to be enabled
1269       //        in SemaDeclAttr.cpp.
1270       WarningsHandler.warnReturnTypestateForUnconsumableType(
1271           RTSAttr->getLocation(), ReturnType.getAsString());
1272       ExpectedReturnState = CS_None;
1273     } else
1274       ExpectedReturnState = mapReturnTypestateAttrState(RTSAttr);
1275   } else if (isConsumableType(ReturnType)) {
1276     if (isAutoCastType(ReturnType))   // We can auto-cast the state to the
1277       ExpectedReturnState = CS_None;  // expected state.
1278     else
1279       ExpectedReturnState = mapConsumableAttrState(ReturnType);
1280   }
1281   else
1282     ExpectedReturnState = CS_None;
1283 }
1284 
1285 bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,
1286                                   const ConsumedStmtVisitor &Visitor) {
1287 
1288   std::unique_ptr<ConsumedStateMap> FalseStates(
1289       new ConsumedStateMap(*CurrStates));
1290   PropagationInfo PInfo;
1291 
1292   if (const IfStmt *IfNode =
1293     dyn_cast_or_null<IfStmt>(CurrBlock->getTerminator().getStmt())) {
1294 
1295     const Stmt *Cond = IfNode->getCond();
1296 
1297     PInfo = Visitor.getInfo(Cond);
1298     if (!PInfo.isValid() && isa<BinaryOperator>(Cond))
1299       PInfo = Visitor.getInfo(cast<BinaryOperator>(Cond)->getRHS());
1300 
1301     if (PInfo.isVarTest()) {
1302       CurrStates->setSource(Cond);
1303       FalseStates->setSource(Cond);
1304       splitVarStateForIf(IfNode, PInfo.getVarTest(), CurrStates,
1305                          FalseStates.get());
1306 
1307     } else if (PInfo.isBinTest()) {
1308       CurrStates->setSource(PInfo.testSourceNode());
1309       FalseStates->setSource(PInfo.testSourceNode());
1310       splitVarStateForIfBinOp(PInfo, CurrStates, FalseStates.get());
1311 
1312     } else {
1313       return false;
1314     }
1315 
1316   } else if (const BinaryOperator *BinOp =
1317     dyn_cast_or_null<BinaryOperator>(CurrBlock->getTerminator().getStmt())) {
1318 
1319     PInfo = Visitor.getInfo(BinOp->getLHS());
1320     if (!PInfo.isVarTest()) {
1321       if ((BinOp = dyn_cast_or_null<BinaryOperator>(BinOp->getLHS()))) {
1322         PInfo = Visitor.getInfo(BinOp->getRHS());
1323 
1324         if (!PInfo.isVarTest())
1325           return false;
1326 
1327       } else {
1328         return false;
1329       }
1330     }
1331 
1332     CurrStates->setSource(BinOp);
1333     FalseStates->setSource(BinOp);
1334 
1335     const VarTestResult &Test = PInfo.getVarTest();
1336     ConsumedState VarState = CurrStates->getState(Test.Var);
1337 
1338     if (BinOp->getOpcode() == BO_LAnd) {
1339       if (VarState == CS_Unknown)
1340         CurrStates->setState(Test.Var, Test.TestsFor);
1341       else if (VarState == invertConsumedUnconsumed(Test.TestsFor))
1342         CurrStates->markUnreachable();
1343 
1344     } else if (BinOp->getOpcode() == BO_LOr) {
1345       if (VarState == CS_Unknown)
1346         FalseStates->setState(Test.Var,
1347                               invertConsumedUnconsumed(Test.TestsFor));
1348       else if (VarState == Test.TestsFor)
1349         FalseStates->markUnreachable();
1350     }
1351 
1352   } else {
1353     return false;
1354   }
1355 
1356   CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin();
1357 
1358   if (*SI)
1359     BlockInfo.addInfo(*SI, CurrStates);
1360   else
1361     delete CurrStates;
1362 
1363   if (*++SI)
1364     BlockInfo.addInfo(*SI, FalseStates.release());
1365 
1366   CurrStates = NULL;
1367   return true;
1368 }
1369 
1370 void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
1371   const FunctionDecl *D = dyn_cast_or_null<FunctionDecl>(AC.getDecl());
1372   if (!D)
1373     return;
1374 
1375   CFG *CFGraph = AC.getCFG();
1376   if (!CFGraph)
1377     return;
1378 
1379   determineExpectedReturnState(AC, D);
1380 
1381   PostOrderCFGView *SortedGraph = AC.getAnalysis<PostOrderCFGView>();
1382   // AC.getCFG()->viewCFG(LangOptions());
1383 
1384   BlockInfo = ConsumedBlockInfo(CFGraph->getNumBlockIDs(), SortedGraph);
1385 
1386   CurrStates = new ConsumedStateMap();
1387   ConsumedStmtVisitor Visitor(AC, *this, CurrStates);
1388 
1389   // Add all trackable parameters to the state map.
1390   for (auto PI : D->params()) {
1391     Visitor.VisitParmVarDecl(PI);
1392   }
1393 
1394   // Visit all of the function's basic blocks.
1395   for (PostOrderCFGView::iterator I = SortedGraph->begin(),
1396        E = SortedGraph->end(); I != E; ++I) {
1397 
1398     const CFGBlock *CurrBlock = *I;
1399 
1400     if (CurrStates == NULL)
1401       CurrStates = BlockInfo.getInfo(CurrBlock);
1402 
1403     if (!CurrStates) {
1404       continue;
1405 
1406     } else if (!CurrStates->isReachable()) {
1407       delete CurrStates;
1408       CurrStates = NULL;
1409       continue;
1410     }
1411 
1412     Visitor.reset(CurrStates);
1413 
1414     // Visit all of the basic block's statements.
1415     for (CFGBlock::const_iterator BI = CurrBlock->begin(),
1416          BE = CurrBlock->end(); BI != BE; ++BI) {
1417 
1418       switch (BI->getKind()) {
1419       case CFGElement::Statement:
1420         Visitor.Visit(BI->castAs<CFGStmt>().getStmt());
1421         break;
1422 
1423       case CFGElement::TemporaryDtor: {
1424         const CFGTemporaryDtor DTor = BI->castAs<CFGTemporaryDtor>();
1425         const CXXBindTemporaryExpr *BTE = DTor.getBindTemporaryExpr();
1426 
1427         Visitor.checkCallability(PropagationInfo(BTE),
1428                                  DTor.getDestructorDecl(AC.getASTContext()),
1429                                  BTE->getExprLoc());
1430         break;
1431       }
1432 
1433       case CFGElement::AutomaticObjectDtor: {
1434         const CFGAutomaticObjDtor DTor = BI->castAs<CFGAutomaticObjDtor>();
1435         SourceLocation Loc = DTor.getTriggerStmt()->getLocEnd();
1436         const VarDecl *Var = DTor.getVarDecl();
1437 
1438         Visitor.checkCallability(PropagationInfo(Var),
1439                                  DTor.getDestructorDecl(AC.getASTContext()),
1440                                  Loc);
1441         break;
1442       }
1443 
1444       default:
1445         break;
1446       }
1447     }
1448 
1449     CurrStates->clearTemporaries();
1450 
1451     // TODO: Handle other forms of branching with precision, including while-
1452     //       and for-loops. (Deferred)
1453     if (!splitState(CurrBlock, Visitor)) {
1454       CurrStates->setSource(NULL);
1455 
1456       if (CurrBlock->succ_size() > 1 ||
1457           (CurrBlock->succ_size() == 1 &&
1458            (*CurrBlock->succ_begin())->pred_size() > 1)) {
1459 
1460         bool OwnershipTaken = false;
1461 
1462         for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
1463              SE = CurrBlock->succ_end(); SI != SE; ++SI) {
1464 
1465           if (*SI == NULL) continue;
1466 
1467           if (BlockInfo.isBackEdge(CurrBlock, *SI)) {
1468             BlockInfo.borrowInfo(*SI)->intersectAtLoopHead(*SI, CurrBlock,
1469                                                            CurrStates,
1470                                                            WarningsHandler);
1471 
1472             if (BlockInfo.allBackEdgesVisited(*SI, CurrBlock))
1473               BlockInfo.discardInfo(*SI);
1474           } else {
1475             BlockInfo.addInfo(*SI, CurrStates, OwnershipTaken);
1476           }
1477         }
1478 
1479         if (!OwnershipTaken)
1480           delete CurrStates;
1481 
1482         CurrStates = NULL;
1483       }
1484     }
1485 
1486     if (CurrBlock == &AC.getCFG()->getExit() &&
1487         D->getCallResultType()->isVoidType())
1488       CurrStates->checkParamsForReturnTypestate(D->getLocation(),
1489                                                 WarningsHandler);
1490   } // End of block iterator.
1491 
1492   // Delete the last existing state map.
1493   delete CurrStates;
1494 
1495   WarningsHandler.emitDiagnostics();
1496 }
1497 }} // end namespace clang::consumed
1498