xref: /llvm-project/clang/lib/Analysis/Consumed.cpp (revision 5553d0d4cadc35733a910e7af5f8911105ff529d)
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/OwningPtr.h"
31 #include "llvm/ADT/SmallVector.h"
32 #include "llvm/Support/Compiler.h"
33 #include "llvm/Support/raw_ostream.h"
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 static bool isConsumableType(const QualType &QT) {
147   if (QT->isPointerType() || QT->isReferenceType())
148     return false;
149 
150   if (const CXXRecordDecl *RD = QT->getAsCXXRecordDecl())
151     return RD->hasAttr<ConsumableAttr>();
152 
153   return false;
154 }
155 
156 static bool isKnownState(ConsumedState State) {
157   switch (State) {
158   case CS_Unconsumed:
159   case CS_Consumed:
160     return true;
161   case CS_None:
162   case CS_Unknown:
163     return false;
164   }
165   llvm_unreachable("invalid enum");
166 }
167 
168 static bool isRValueRefish(QualType ParamType) {
169   return ParamType->isRValueReferenceType() ||
170         (ParamType->isLValueReferenceType() &&
171          !cast<LValueReferenceType>(
172            ParamType.getCanonicalType())->isSpelledAsLValue());
173 }
174 
175 static bool isTestingFunction(const FunctionDecl *FunDecl) {
176   return FunDecl->hasAttr<TestTypestateAttr>();
177 }
178 
179 static bool isValueType(QualType ParamType) {
180   return !(ParamType->isPointerType() || ParamType->isReferenceType());
181 }
182 
183 static ConsumedState mapConsumableAttrState(const QualType QT) {
184   assert(isConsumableType(QT));
185 
186   const ConsumableAttr *CAttr =
187       QT->getAsCXXRecordDecl()->getAttr<ConsumableAttr>();
188 
189   switch (CAttr->getDefaultState()) {
190   case ConsumableAttr::Unknown:
191     return CS_Unknown;
192   case ConsumableAttr::Unconsumed:
193     return CS_Unconsumed;
194   case ConsumableAttr::Consumed:
195     return CS_Consumed;
196   }
197   llvm_unreachable("invalid enum");
198 }
199 
200 static ConsumedState
201 mapParamTypestateAttrState(const ParamTypestateAttr *PTAttr) {
202   switch (PTAttr->getParamState()) {
203   case ParamTypestateAttr::Unknown:
204     return CS_Unknown;
205   case ParamTypestateAttr::Unconsumed:
206     return CS_Unconsumed;
207   case ParamTypestateAttr::Consumed:
208     return CS_Consumed;
209   }
210   llvm_unreachable("invalid_enum");
211 }
212 
213 static ConsumedState
214 mapReturnTypestateAttrState(const ReturnTypestateAttr *RTSAttr) {
215   switch (RTSAttr->getState()) {
216   case ReturnTypestateAttr::Unknown:
217     return CS_Unknown;
218   case ReturnTypestateAttr::Unconsumed:
219     return CS_Unconsumed;
220   case ReturnTypestateAttr::Consumed:
221     return CS_Consumed;
222   }
223   llvm_unreachable("invalid enum");
224 }
225 
226 static ConsumedState mapSetTypestateAttrState(const SetTypestateAttr *STAttr) {
227   switch (STAttr->getNewState()) {
228   case SetTypestateAttr::Unknown:
229     return CS_Unknown;
230   case SetTypestateAttr::Unconsumed:
231     return CS_Unconsumed;
232   case SetTypestateAttr::Consumed:
233     return CS_Consumed;
234   }
235   llvm_unreachable("invalid_enum");
236 }
237 
238 static StringRef stateToString(ConsumedState State) {
239   switch (State) {
240   case consumed::CS_None:
241     return "none";
242 
243   case consumed::CS_Unknown:
244     return "unknown";
245 
246   case consumed::CS_Unconsumed:
247     return "unconsumed";
248 
249   case consumed::CS_Consumed:
250     return "consumed";
251   }
252   llvm_unreachable("invalid enum");
253 }
254 
255 static ConsumedState testsFor(const FunctionDecl *FunDecl) {
256   assert(isTestingFunction(FunDecl));
257   switch (FunDecl->getAttr<TestTypestateAttr>()->getTestState()) {
258   case TestTypestateAttr::Unconsumed:
259     return CS_Unconsumed;
260   case TestTypestateAttr::Consumed:
261     return CS_Consumed;
262   }
263   llvm_unreachable("invalid enum");
264 }
265 
266 namespace {
267 struct VarTestResult {
268   const VarDecl *Var;
269   ConsumedState TestsFor;
270 };
271 } // end anonymous::VarTestResult
272 
273 namespace clang {
274 namespace consumed {
275 
276 enum EffectiveOp {
277   EO_And,
278   EO_Or
279 };
280 
281 class PropagationInfo {
282   enum {
283     IT_None,
284     IT_State,
285     IT_VarTest,
286     IT_BinTest,
287     IT_Var,
288     IT_Tmp
289   } InfoType;
290 
291   struct BinTestTy {
292     const BinaryOperator *Source;
293     EffectiveOp EOp;
294     VarTestResult LTest;
295     VarTestResult RTest;
296   };
297 
298   union {
299     ConsumedState State;
300     VarTestResult VarTest;
301     const VarDecl *Var;
302     const CXXBindTemporaryExpr *Tmp;
303     BinTestTy BinTest;
304   };
305 
306 public:
307   PropagationInfo() : InfoType(IT_None) {}
308 
309   PropagationInfo(const VarTestResult &VarTest)
310     : InfoType(IT_VarTest), VarTest(VarTest) {}
311 
312   PropagationInfo(const VarDecl *Var, ConsumedState TestsFor)
313     : InfoType(IT_VarTest) {
314 
315     VarTest.Var      = Var;
316     VarTest.TestsFor = TestsFor;
317   }
318 
319   PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp,
320                   const VarTestResult &LTest, const VarTestResult &RTest)
321     : InfoType(IT_BinTest) {
322 
323     BinTest.Source  = Source;
324     BinTest.EOp     = EOp;
325     BinTest.LTest   = LTest;
326     BinTest.RTest   = RTest;
327   }
328 
329   PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp,
330                   const VarDecl *LVar, ConsumedState LTestsFor,
331                   const VarDecl *RVar, ConsumedState RTestsFor)
332     : InfoType(IT_BinTest) {
333 
334     BinTest.Source         = Source;
335     BinTest.EOp            = EOp;
336     BinTest.LTest.Var      = LVar;
337     BinTest.LTest.TestsFor = LTestsFor;
338     BinTest.RTest.Var      = RVar;
339     BinTest.RTest.TestsFor = RTestsFor;
340   }
341 
342   PropagationInfo(ConsumedState State)
343     : InfoType(IT_State), State(State) {}
344 
345   PropagationInfo(const VarDecl *Var) : InfoType(IT_Var), Var(Var) {}
346   PropagationInfo(const CXXBindTemporaryExpr *Tmp)
347     : InfoType(IT_Tmp), Tmp(Tmp) {}
348 
349   const ConsumedState & getState() const {
350     assert(InfoType == IT_State);
351     return State;
352   }
353 
354   const VarTestResult & getVarTest() const {
355     assert(InfoType == IT_VarTest);
356     return VarTest;
357   }
358 
359   const VarTestResult & getLTest() const {
360     assert(InfoType == IT_BinTest);
361     return BinTest.LTest;
362   }
363 
364   const VarTestResult & getRTest() const {
365     assert(InfoType == IT_BinTest);
366     return BinTest.RTest;
367   }
368 
369   const VarDecl * getVar() const {
370     assert(InfoType == IT_Var);
371     return Var;
372   }
373 
374   const CXXBindTemporaryExpr * getTmp() const {
375     assert(InfoType == IT_Tmp);
376     return Tmp;
377   }
378 
379   ConsumedState getAsState(const ConsumedStateMap *StateMap) const {
380     assert(isVar() || isTmp() || isState());
381 
382     if (isVar())
383       return StateMap->getState(Var);
384     else if (isTmp())
385       return StateMap->getState(Tmp);
386     else if (isState())
387       return State;
388     else
389       return CS_None;
390   }
391 
392   EffectiveOp testEffectiveOp() const {
393     assert(InfoType == IT_BinTest);
394     return BinTest.EOp;
395   }
396 
397   const BinaryOperator * testSourceNode() const {
398     assert(InfoType == IT_BinTest);
399     return BinTest.Source;
400   }
401 
402   inline bool isValid()   const { return InfoType != IT_None;    }
403   inline bool isState()   const { return InfoType == IT_State;   }
404   inline bool isVarTest() const { return InfoType == IT_VarTest; }
405   inline bool isBinTest() const { return InfoType == IT_BinTest; }
406   inline bool isVar()     const { return InfoType == IT_Var;     }
407   inline bool isTmp()     const { return InfoType == IT_Tmp;     }
408 
409   bool isTest() const {
410     return InfoType == IT_VarTest || InfoType == IT_BinTest;
411   }
412 
413   bool isPointerToValue() const {
414     return InfoType == IT_Var || InfoType == IT_Tmp;
415   }
416 
417   PropagationInfo invertTest() const {
418     assert(InfoType == IT_VarTest || InfoType == IT_BinTest);
419 
420     if (InfoType == IT_VarTest) {
421       return PropagationInfo(VarTest.Var,
422                              invertConsumedUnconsumed(VarTest.TestsFor));
423 
424     } else if (InfoType == IT_BinTest) {
425       return PropagationInfo(BinTest.Source,
426         BinTest.EOp == EO_And ? EO_Or : EO_And,
427         BinTest.LTest.Var, invertConsumedUnconsumed(BinTest.LTest.TestsFor),
428         BinTest.RTest.Var, invertConsumedUnconsumed(BinTest.RTest.TestsFor));
429     } else {
430       return PropagationInfo();
431     }
432   }
433 };
434 
435 static inline void
436 setStateForVarOrTmp(ConsumedStateMap *StateMap, const PropagationInfo &PInfo,
437                     ConsumedState State) {
438 
439   assert(PInfo.isVar() || PInfo.isTmp());
440 
441   if (PInfo.isVar())
442     StateMap->setState(PInfo.getVar(), State);
443   else
444     StateMap->setState(PInfo.getTmp(), State);
445 }
446 
447 class ConsumedStmtVisitor : public ConstStmtVisitor<ConsumedStmtVisitor> {
448 
449   typedef llvm::DenseMap<const Stmt *, PropagationInfo> MapType;
450   typedef std::pair<const Stmt *, PropagationInfo> PairType;
451   typedef MapType::iterator InfoEntry;
452   typedef MapType::const_iterator ConstInfoEntry;
453 
454   AnalysisDeclContext &AC;
455   ConsumedAnalyzer &Analyzer;
456   ConsumedStateMap *StateMap;
457   MapType PropagationMap;
458   void forwardInfo(const Stmt *From, const Stmt *To);
459   bool isLikeMoveAssignment(const CXXMethodDecl *MethodDecl);
460   void propagateReturnType(const Stmt *Call, const FunctionDecl *Fun,
461                            QualType ReturnType);
462 
463 public:
464   void checkCallability(const PropagationInfo &PInfo,
465                         const FunctionDecl *FunDecl,
466                         SourceLocation BlameLoc);
467 
468   void VisitBinaryOperator(const BinaryOperator *BinOp);
469   void VisitCallExpr(const CallExpr *Call);
470   void VisitCastExpr(const CastExpr *Cast);
471   void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Temp);
472   void VisitCXXConstructExpr(const CXXConstructExpr *Call);
473   void VisitCXXMemberCallExpr(const CXXMemberCallExpr *Call);
474   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Call);
475   void VisitDeclRefExpr(const DeclRefExpr *DeclRef);
476   void VisitDeclStmt(const DeclStmt *DelcS);
477   void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Temp);
478   void VisitMemberExpr(const MemberExpr *MExpr);
479   void VisitParmVarDecl(const ParmVarDecl *Param);
480   void VisitReturnStmt(const ReturnStmt *Ret);
481   void VisitUnaryOperator(const UnaryOperator *UOp);
482   void VisitVarDecl(const VarDecl *Var);
483 
484   ConsumedStmtVisitor(AnalysisDeclContext &AC, ConsumedAnalyzer &Analyzer,
485                       ConsumedStateMap *StateMap)
486       : AC(AC), Analyzer(Analyzer), StateMap(StateMap) {}
487 
488   PropagationInfo getInfo(const Stmt *StmtNode) const {
489     ConstInfoEntry Entry = PropagationMap.find(StmtNode);
490 
491     if (Entry != PropagationMap.end())
492       return Entry->second;
493     else
494       return PropagationInfo();
495   }
496 
497   void reset(ConsumedStateMap *NewStateMap) {
498     StateMap = NewStateMap;
499   }
500 };
501 
502 void ConsumedStmtVisitor::checkCallability(const PropagationInfo &PInfo,
503                                            const FunctionDecl *FunDecl,
504                                            SourceLocation BlameLoc) {
505   assert(!PInfo.isTest());
506 
507   const CallableWhenAttr *CWAttr = FunDecl->getAttr<CallableWhenAttr>();
508   if (!CWAttr)
509     return;
510 
511   if (PInfo.isVar()) {
512     ConsumedState VarState = StateMap->getState(PInfo.getVar());
513 
514     if (VarState == CS_None || isCallableInState(CWAttr, VarState))
515       return;
516 
517     Analyzer.WarningsHandler.warnUseInInvalidState(
518       FunDecl->getNameAsString(), PInfo.getVar()->getNameAsString(),
519       stateToString(VarState), BlameLoc);
520 
521   } else {
522     ConsumedState TmpState = PInfo.getAsState(StateMap);
523 
524     if (TmpState == CS_None || isCallableInState(CWAttr, TmpState))
525       return;
526 
527     Analyzer.WarningsHandler.warnUseOfTempInInvalidState(
528       FunDecl->getNameAsString(), stateToString(TmpState), BlameLoc);
529   }
530 }
531 
532 void ConsumedStmtVisitor::forwardInfo(const Stmt *From, const Stmt *To) {
533   InfoEntry Entry = PropagationMap.find(From);
534 
535   if (Entry != PropagationMap.end())
536     PropagationMap.insert(PairType(To, Entry->second));
537 }
538 
539 bool ConsumedStmtVisitor::isLikeMoveAssignment(
540   const CXXMethodDecl *MethodDecl) {
541 
542   return MethodDecl->isMoveAssignmentOperator() ||
543          (MethodDecl->getOverloadedOperator() == OO_Equal &&
544           MethodDecl->getNumParams() == 1 &&
545           MethodDecl->getParamDecl(0)->getType()->isRValueReferenceType());
546 }
547 
548 void ConsumedStmtVisitor::propagateReturnType(const Stmt *Call,
549                                               const FunctionDecl *Fun,
550                                               QualType ReturnType) {
551   if (isConsumableType(ReturnType)) {
552 
553     ConsumedState ReturnState;
554 
555     if (ReturnTypestateAttr *RTA = Fun->getAttr<ReturnTypestateAttr>())
556       ReturnState = mapReturnTypestateAttrState(RTA);
557     else
558       ReturnState = mapConsumableAttrState(ReturnType);
559 
560     PropagationMap.insert(PairType(Call, PropagationInfo(ReturnState)));
561   }
562 }
563 
564 void ConsumedStmtVisitor::VisitBinaryOperator(const BinaryOperator *BinOp) {
565   switch (BinOp->getOpcode()) {
566   case BO_LAnd:
567   case BO_LOr : {
568     InfoEntry LEntry = PropagationMap.find(BinOp->getLHS()),
569               REntry = PropagationMap.find(BinOp->getRHS());
570 
571     VarTestResult LTest, RTest;
572 
573     if (LEntry != PropagationMap.end() && LEntry->second.isVarTest()) {
574       LTest = LEntry->second.getVarTest();
575 
576     } else {
577       LTest.Var      = NULL;
578       LTest.TestsFor = CS_None;
579     }
580 
581     if (REntry != PropagationMap.end() && REntry->second.isVarTest()) {
582       RTest = REntry->second.getVarTest();
583 
584     } else {
585       RTest.Var      = NULL;
586       RTest.TestsFor = CS_None;
587     }
588 
589     if (!(LTest.Var == NULL && RTest.Var == NULL))
590       PropagationMap.insert(PairType(BinOp, PropagationInfo(BinOp,
591         static_cast<EffectiveOp>(BinOp->getOpcode() == BO_LOr), LTest, RTest)));
592 
593     break;
594   }
595 
596   case BO_PtrMemD:
597   case BO_PtrMemI:
598     forwardInfo(BinOp->getLHS(), BinOp);
599     break;
600 
601   default:
602     break;
603   }
604 }
605 
606 static bool isStdNamespace(const DeclContext *DC) {
607   if (!DC->isNamespace()) return false;
608   while (DC->getParent()->isNamespace())
609     DC = DC->getParent();
610   const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC);
611 
612   return ND && ND->getName() == "std" &&
613          ND->getDeclContext()->isTranslationUnit();
614 }
615 
616 void ConsumedStmtVisitor::VisitCallExpr(const CallExpr *Call) {
617   if (const FunctionDecl *FunDecl =
618     dyn_cast_or_null<FunctionDecl>(Call->getDirectCallee())) {
619 
620     // Special case for the std::move function.
621     // TODO: Make this more specific. (Deferred)
622     if (Call->getNumArgs() == 1 &&
623         FunDecl->getNameAsString() == "move" &&
624         isStdNamespace(FunDecl->getDeclContext())) {
625       forwardInfo(Call->getArg(0), Call);
626       return;
627     }
628 
629     unsigned Offset = Call->getNumArgs() - FunDecl->getNumParams();
630 
631     for (unsigned Index = Offset; Index < Call->getNumArgs(); ++Index) {
632       const ParmVarDecl *Param = FunDecl->getParamDecl(Index - Offset);
633       QualType ParamType = Param->getType();
634 
635       InfoEntry Entry = PropagationMap.find(Call->getArg(Index));
636 
637       if (Entry == PropagationMap.end() || Entry->second.isTest())
638         continue;
639 
640       PropagationInfo PInfo = Entry->second;
641 
642       // Check that the parameter is in the correct state.
643 
644       if (ParamTypestateAttr *PTA = Param->getAttr<ParamTypestateAttr>()) {
645         ConsumedState ParamState = PInfo.getAsState(StateMap);
646         ConsumedState ExpectedState = mapParamTypestateAttrState(PTA);
647 
648         if (ParamState != ExpectedState)
649           Analyzer.WarningsHandler.warnParamTypestateMismatch(
650             Call->getArg(Index - Offset)->getExprLoc(),
651             stateToString(ExpectedState), stateToString(ParamState));
652       }
653 
654       if (!(Entry->second.isVar() || Entry->second.isTmp()))
655         continue;
656 
657       // Adjust state on the caller side.
658 
659       if (isRValueRefish(ParamType))
660         setStateForVarOrTmp(StateMap, PInfo, consumed::CS_Consumed);
661       else if (ReturnTypestateAttr *RT = Param->getAttr<ReturnTypestateAttr>())
662         setStateForVarOrTmp(StateMap, PInfo, mapReturnTypestateAttrState(RT));
663       else if (!isValueType(ParamType) &&
664                !ParamType->getPointeeType().isConstQualified())
665         setStateForVarOrTmp(StateMap, PInfo, consumed::CS_Unknown);
666     }
667 
668     QualType RetType = FunDecl->getCallResultType();
669     if (RetType->isReferenceType())
670       RetType = RetType->getPointeeType();
671 
672     propagateReturnType(Call, FunDecl, RetType);
673   }
674 }
675 
676 void ConsumedStmtVisitor::VisitCastExpr(const CastExpr *Cast) {
677   forwardInfo(Cast->getSubExpr(), Cast);
678 }
679 
680 void ConsumedStmtVisitor::VisitCXXBindTemporaryExpr(
681   const CXXBindTemporaryExpr *Temp) {
682 
683   InfoEntry Entry = PropagationMap.find(Temp->getSubExpr());
684 
685   if (Entry != PropagationMap.end() && !Entry->second.isTest()) {
686     StateMap->setState(Temp, Entry->second.getAsState(StateMap));
687     PropagationMap.insert(PairType(Temp, PropagationInfo(Temp)));
688   }
689 }
690 
691 void ConsumedStmtVisitor::VisitCXXConstructExpr(const CXXConstructExpr *Call) {
692   CXXConstructorDecl *Constructor = Call->getConstructor();
693 
694   ASTContext &CurrContext = AC.getASTContext();
695   QualType ThisType = Constructor->getThisType(CurrContext)->getPointeeType();
696 
697   if (!isConsumableType(ThisType))
698     return;
699 
700   // FIXME: What should happen if someone annotates the move constructor?
701   if (ReturnTypestateAttr *RTA = Constructor->getAttr<ReturnTypestateAttr>()) {
702     // TODO: Adjust state of args appropriately.
703     ConsumedState RetState = mapReturnTypestateAttrState(RTA);
704     PropagationMap.insert(PairType(Call, PropagationInfo(RetState)));
705   } else if (Constructor->isDefaultConstructor()) {
706     PropagationMap.insert(PairType(Call,
707       PropagationInfo(consumed::CS_Consumed)));
708   } else if (Constructor->isMoveConstructor()) {
709     InfoEntry Entry = PropagationMap.find(Call->getArg(0));
710 
711     if (Entry != PropagationMap.end()) {
712       PropagationInfo PInfo = Entry->second;
713 
714       if (PInfo.isVar()) {
715         const VarDecl* Var = PInfo.getVar();
716 
717         PropagationMap.insert(PairType(Call,
718           PropagationInfo(StateMap->getState(Var))));
719 
720         StateMap->setState(Var, consumed::CS_Consumed);
721 
722       } else if (PInfo.isTmp()) {
723         const CXXBindTemporaryExpr *Tmp = PInfo.getTmp();
724 
725         PropagationMap.insert(PairType(Call,
726           PropagationInfo(StateMap->getState(Tmp))));
727 
728         StateMap->setState(Tmp, consumed::CS_Consumed);
729 
730       } else {
731         PropagationMap.insert(PairType(Call, PInfo));
732       }
733     }
734   } else if (Constructor->isCopyConstructor()) {
735     forwardInfo(Call->getArg(0), Call);
736 
737   } else {
738     // TODO: Adjust state of args appropriately.
739 
740     ConsumedState RetState = mapConsumableAttrState(ThisType);
741     PropagationMap.insert(PairType(Call, PropagationInfo(RetState)));
742   }
743 }
744 
745 void ConsumedStmtVisitor::VisitCXXMemberCallExpr(
746   const CXXMemberCallExpr *Call) {
747 
748   VisitCallExpr(Call);
749 
750   InfoEntry Entry = PropagationMap.find(Call->getCallee()->IgnoreParens());
751 
752   if (Entry != PropagationMap.end()) {
753     PropagationInfo PInfo = Entry->second;
754     const CXXMethodDecl *MethodDecl = Call->getMethodDecl();
755 
756     checkCallability(PInfo, MethodDecl, Call->getExprLoc());
757 
758     SetTypestateAttr *STA = MethodDecl->getAttr<SetTypestateAttr>();
759     if (PInfo.isVar()) {
760       if (isTestingFunction(MethodDecl))
761         PropagationMap.insert(PairType(Call,
762           PropagationInfo(PInfo.getVar(), testsFor(MethodDecl))));
763       else if (STA)
764         StateMap->setState(PInfo.getVar(), mapSetTypestateAttrState(STA));
765     } else if (STA && PInfo.isTmp())
766       StateMap->setState(PInfo.getTmp(), mapSetTypestateAttrState(STA));
767   }
768 }
769 
770 void ConsumedStmtVisitor::VisitCXXOperatorCallExpr(
771   const CXXOperatorCallExpr *Call) {
772 
773   const FunctionDecl *FunDecl =
774     dyn_cast_or_null<FunctionDecl>(Call->getDirectCallee());
775 
776   if (!FunDecl) return;
777 
778   if (isa<CXXMethodDecl>(FunDecl) &&
779       isLikeMoveAssignment(cast<CXXMethodDecl>(FunDecl))) {
780 
781     InfoEntry LEntry = PropagationMap.find(Call->getArg(0));
782     InfoEntry REntry = PropagationMap.find(Call->getArg(1));
783 
784     PropagationInfo LPInfo, RPInfo;
785 
786     if (LEntry != PropagationMap.end() &&
787         REntry != PropagationMap.end()) {
788 
789       LPInfo = LEntry->second;
790       RPInfo = REntry->second;
791 
792       if (LPInfo.isPointerToValue() && RPInfo.isPointerToValue()) {
793         setStateForVarOrTmp(StateMap, LPInfo, RPInfo.getAsState(StateMap));
794         PropagationMap.insert(PairType(Call, LPInfo));
795         setStateForVarOrTmp(StateMap, RPInfo, consumed::CS_Consumed);
796 
797       } else if (RPInfo.isState()) {
798         setStateForVarOrTmp(StateMap, LPInfo, RPInfo.getState());
799         PropagationMap.insert(PairType(Call, LPInfo));
800 
801       } else {
802         setStateForVarOrTmp(StateMap, RPInfo, consumed::CS_Consumed);
803       }
804 
805     } else if (LEntry != PropagationMap.end() &&
806                REntry == PropagationMap.end()) {
807 
808       LPInfo = LEntry->second;
809 
810       assert(!LPInfo.isTest());
811 
812       if (LPInfo.isPointerToValue()) {
813         setStateForVarOrTmp(StateMap, LPInfo, consumed::CS_Unknown);
814         PropagationMap.insert(PairType(Call, LPInfo));
815 
816       } else {
817         PropagationMap.insert(PairType(Call,
818           PropagationInfo(consumed::CS_Unknown)));
819       }
820 
821     } else if (LEntry == PropagationMap.end() &&
822                REntry != PropagationMap.end()) {
823 
824       RPInfo = REntry->second;
825 
826       if (RPInfo.isPointerToValue())
827         setStateForVarOrTmp(StateMap, RPInfo, consumed::CS_Consumed);
828     }
829 
830   } else {
831 
832     VisitCallExpr(Call);
833 
834     InfoEntry Entry = PropagationMap.find(Call->getArg(0));
835 
836     if (Entry != PropagationMap.end()) {
837       PropagationInfo PInfo = Entry->second;
838 
839       checkCallability(PInfo, FunDecl, Call->getExprLoc());
840 
841       SetTypestateAttr *STA = FunDecl->getAttr<SetTypestateAttr>();
842       if (PInfo.isVar()) {
843         if (isTestingFunction(FunDecl))
844           PropagationMap.insert(PairType(Call,
845             PropagationInfo(PInfo.getVar(), testsFor(FunDecl))));
846         else if (STA)
847           StateMap->setState(PInfo.getVar(), mapSetTypestateAttrState(STA));
848       } else if (STA && PInfo.isTmp())
849         StateMap->setState(PInfo.getTmp(), mapSetTypestateAttrState(STA));
850     }
851   }
852 }
853 
854 void ConsumedStmtVisitor::VisitDeclRefExpr(const DeclRefExpr *DeclRef) {
855   if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(DeclRef->getDecl()))
856     if (StateMap->getState(Var) != consumed::CS_None)
857       PropagationMap.insert(PairType(DeclRef, PropagationInfo(Var)));
858 }
859 
860 void ConsumedStmtVisitor::VisitDeclStmt(const DeclStmt *DeclS) {
861   for (DeclStmt::const_decl_iterator DI = DeclS->decl_begin(),
862        DE = DeclS->decl_end(); DI != DE; ++DI) {
863 
864     if (isa<VarDecl>(*DI)) VisitVarDecl(cast<VarDecl>(*DI));
865   }
866 
867   if (DeclS->isSingleDecl())
868     if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(DeclS->getSingleDecl()))
869       PropagationMap.insert(PairType(DeclS, PropagationInfo(Var)));
870 }
871 
872 void ConsumedStmtVisitor::VisitMaterializeTemporaryExpr(
873   const MaterializeTemporaryExpr *Temp) {
874 
875   forwardInfo(Temp->GetTemporaryExpr(), Temp);
876 }
877 
878 void ConsumedStmtVisitor::VisitMemberExpr(const MemberExpr *MExpr) {
879   forwardInfo(MExpr->getBase(), MExpr);
880 }
881 
882 
883 void ConsumedStmtVisitor::VisitParmVarDecl(const ParmVarDecl *Param) {
884   QualType ParamType = Param->getType();
885   ConsumedState ParamState = consumed::CS_None;
886 
887   if (const ParamTypestateAttr *PTA = Param->getAttr<ParamTypestateAttr>())
888     ParamState = mapParamTypestateAttrState(PTA);
889   else if (isConsumableType(ParamType))
890     ParamState = mapConsumableAttrState(ParamType);
891   else if (isRValueRefish(ParamType) &&
892              isConsumableType(ParamType->getPointeeType()))
893     ParamState = mapConsumableAttrState(ParamType->getPointeeType());
894   else if (ParamType->isReferenceType() &&
895              isConsumableType(ParamType->getPointeeType()))
896     ParamState = consumed::CS_Unknown;
897 
898   if (ParamState != CS_None)
899     StateMap->setState(Param, ParamState);
900 }
901 
902 void ConsumedStmtVisitor::VisitReturnStmt(const ReturnStmt *Ret) {
903   ConsumedState ExpectedState = Analyzer.getExpectedReturnState();
904 
905   if (ExpectedState != CS_None) {
906     InfoEntry Entry = PropagationMap.find(Ret->getRetValue());
907 
908     if (Entry != PropagationMap.end()) {
909       ConsumedState RetState = Entry->second.getAsState(StateMap);
910 
911       if (RetState != ExpectedState)
912         Analyzer.WarningsHandler.warnReturnTypestateMismatch(
913           Ret->getReturnLoc(), stateToString(ExpectedState),
914           stateToString(RetState));
915     }
916   }
917 
918   StateMap->checkParamsForReturnTypestate(Ret->getLocStart(),
919                                           Analyzer.WarningsHandler);
920 }
921 
922 void ConsumedStmtVisitor::VisitUnaryOperator(const UnaryOperator *UOp) {
923   InfoEntry Entry = PropagationMap.find(UOp->getSubExpr()->IgnoreParens());
924   if (Entry == PropagationMap.end()) return;
925 
926   switch (UOp->getOpcode()) {
927   case UO_AddrOf:
928     PropagationMap.insert(PairType(UOp, Entry->second));
929     break;
930 
931   case UO_LNot:
932     if (Entry->second.isTest())
933       PropagationMap.insert(PairType(UOp, Entry->second.invertTest()));
934     break;
935 
936   default:
937     break;
938   }
939 }
940 
941 // TODO: See if I need to check for reference types here.
942 void ConsumedStmtVisitor::VisitVarDecl(const VarDecl *Var) {
943   if (isConsumableType(Var->getType())) {
944     if (Var->hasInit()) {
945       MapType::iterator VIT = PropagationMap.find(
946         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     ExpectedReturnState = mapConsumableAttrState(ReturnType);
1286   else
1287     ExpectedReturnState = CS_None;
1288 }
1289 
1290 bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,
1291                                   const ConsumedStmtVisitor &Visitor) {
1292 
1293   OwningPtr<ConsumedStateMap> FalseStates(new ConsumedStateMap(*CurrStates));
1294   PropagationInfo PInfo;
1295 
1296   if (const IfStmt *IfNode =
1297     dyn_cast_or_null<IfStmt>(CurrBlock->getTerminator().getStmt())) {
1298 
1299     const Stmt *Cond = IfNode->getCond();
1300 
1301     PInfo = Visitor.getInfo(Cond);
1302     if (!PInfo.isValid() && isa<BinaryOperator>(Cond))
1303       PInfo = Visitor.getInfo(cast<BinaryOperator>(Cond)->getRHS());
1304 
1305     if (PInfo.isVarTest()) {
1306       CurrStates->setSource(Cond);
1307       FalseStates->setSource(Cond);
1308       splitVarStateForIf(IfNode, PInfo.getVarTest(), CurrStates,
1309                          FalseStates.get());
1310 
1311     } else if (PInfo.isBinTest()) {
1312       CurrStates->setSource(PInfo.testSourceNode());
1313       FalseStates->setSource(PInfo.testSourceNode());
1314       splitVarStateForIfBinOp(PInfo, CurrStates, FalseStates.get());
1315 
1316     } else {
1317       return false;
1318     }
1319 
1320   } else if (const BinaryOperator *BinOp =
1321     dyn_cast_or_null<BinaryOperator>(CurrBlock->getTerminator().getStmt())) {
1322 
1323     PInfo = Visitor.getInfo(BinOp->getLHS());
1324     if (!PInfo.isVarTest()) {
1325       if ((BinOp = dyn_cast_or_null<BinaryOperator>(BinOp->getLHS()))) {
1326         PInfo = Visitor.getInfo(BinOp->getRHS());
1327 
1328         if (!PInfo.isVarTest())
1329           return false;
1330 
1331       } else {
1332         return false;
1333       }
1334     }
1335 
1336     CurrStates->setSource(BinOp);
1337     FalseStates->setSource(BinOp);
1338 
1339     const VarTestResult &Test = PInfo.getVarTest();
1340     ConsumedState VarState = CurrStates->getState(Test.Var);
1341 
1342     if (BinOp->getOpcode() == BO_LAnd) {
1343       if (VarState == CS_Unknown)
1344         CurrStates->setState(Test.Var, Test.TestsFor);
1345       else if (VarState == invertConsumedUnconsumed(Test.TestsFor))
1346         CurrStates->markUnreachable();
1347 
1348     } else if (BinOp->getOpcode() == BO_LOr) {
1349       if (VarState == CS_Unknown)
1350         FalseStates->setState(Test.Var,
1351                               invertConsumedUnconsumed(Test.TestsFor));
1352       else if (VarState == Test.TestsFor)
1353         FalseStates->markUnreachable();
1354     }
1355 
1356   } else {
1357     return false;
1358   }
1359 
1360   CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin();
1361 
1362   if (*SI)
1363     BlockInfo.addInfo(*SI, CurrStates);
1364   else
1365     delete CurrStates;
1366 
1367   if (*++SI)
1368     BlockInfo.addInfo(*SI, FalseStates.take());
1369 
1370   CurrStates = NULL;
1371   return true;
1372 }
1373 
1374 void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
1375   const FunctionDecl *D = dyn_cast_or_null<FunctionDecl>(AC.getDecl());
1376   if (!D)
1377     return;
1378 
1379   CFG *CFGraph = AC.getCFG();
1380   if (!CFGraph)
1381     return;
1382 
1383   determineExpectedReturnState(AC, D);
1384 
1385   PostOrderCFGView *SortedGraph = AC.getAnalysis<PostOrderCFGView>();
1386   // AC.getCFG()->viewCFG(LangOptions());
1387 
1388   BlockInfo = ConsumedBlockInfo(CFGraph->getNumBlockIDs(), SortedGraph);
1389 
1390   CurrStates = new ConsumedStateMap();
1391   ConsumedStmtVisitor Visitor(AC, *this, CurrStates);
1392 
1393   // Add all trackable parameters to the state map.
1394   for (FunctionDecl::param_const_iterator PI = D->param_begin(),
1395        PE = D->param_end(); PI != PE; ++PI) {
1396     Visitor.VisitParmVarDecl(*PI);
1397   }
1398 
1399   // Visit all of the function's basic blocks.
1400   for (PostOrderCFGView::iterator I = SortedGraph->begin(),
1401        E = SortedGraph->end(); I != E; ++I) {
1402 
1403     const CFGBlock *CurrBlock = *I;
1404 
1405     if (CurrStates == NULL)
1406       CurrStates = BlockInfo.getInfo(CurrBlock);
1407 
1408     if (!CurrStates) {
1409       continue;
1410 
1411     } else if (!CurrStates->isReachable()) {
1412       delete CurrStates;
1413       CurrStates = NULL;
1414       continue;
1415     }
1416 
1417     Visitor.reset(CurrStates);
1418 
1419     // Visit all of the basic block's statements.
1420     for (CFGBlock::const_iterator BI = CurrBlock->begin(),
1421          BE = CurrBlock->end(); BI != BE; ++BI) {
1422 
1423       switch (BI->getKind()) {
1424       case CFGElement::Statement:
1425         Visitor.Visit(BI->castAs<CFGStmt>().getStmt());
1426         break;
1427 
1428       case CFGElement::TemporaryDtor: {
1429         const CFGTemporaryDtor DTor = BI->castAs<CFGTemporaryDtor>();
1430         const CXXBindTemporaryExpr *BTE = DTor.getBindTemporaryExpr();
1431 
1432         Visitor.checkCallability(PropagationInfo(BTE),
1433                                  DTor.getDestructorDecl(AC.getASTContext()),
1434                                  BTE->getExprLoc());
1435         break;
1436       }
1437 
1438       case CFGElement::AutomaticObjectDtor: {
1439         const CFGAutomaticObjDtor DTor = BI->castAs<CFGAutomaticObjDtor>();
1440         SourceLocation Loc = DTor.getTriggerStmt()->getLocEnd();
1441         const VarDecl *Var = DTor.getVarDecl();
1442 
1443         Visitor.checkCallability(PropagationInfo(Var),
1444                                  DTor.getDestructorDecl(AC.getASTContext()),
1445                                  Loc);
1446         break;
1447       }
1448 
1449       default:
1450         break;
1451       }
1452     }
1453 
1454     CurrStates->clearTemporaries();
1455 
1456     // TODO: Handle other forms of branching with precision, including while-
1457     //       and for-loops. (Deferred)
1458     if (!splitState(CurrBlock, Visitor)) {
1459       CurrStates->setSource(NULL);
1460 
1461       if (CurrBlock->succ_size() > 1 ||
1462           (CurrBlock->succ_size() == 1 &&
1463            (*CurrBlock->succ_begin())->pred_size() > 1)) {
1464 
1465         bool OwnershipTaken = false;
1466 
1467         for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
1468              SE = CurrBlock->succ_end(); SI != SE; ++SI) {
1469 
1470           if (*SI == NULL) continue;
1471 
1472           if (BlockInfo.isBackEdge(CurrBlock, *SI)) {
1473             BlockInfo.borrowInfo(*SI)->intersectAtLoopHead(*SI, CurrBlock,
1474                                                            CurrStates,
1475                                                            WarningsHandler);
1476 
1477             if (BlockInfo.allBackEdgesVisited(*SI, CurrBlock))
1478               BlockInfo.discardInfo(*SI);
1479           } else {
1480             BlockInfo.addInfo(*SI, CurrStates, OwnershipTaken);
1481           }
1482         }
1483 
1484         if (!OwnershipTaken)
1485           delete CurrStates;
1486 
1487         CurrStates = NULL;
1488       }
1489     }
1490 
1491     if (CurrBlock == &AC.getCFG()->getExit() &&
1492         D->getCallResultType()->isVoidType())
1493       CurrStates->checkParamsForReturnTypestate(D->getLocation(),
1494                                                 WarningsHandler);
1495   } // End of block iterator.
1496 
1497   // Delete the last existing state map.
1498   delete CurrStates;
1499 
1500   WarningsHandler.emitDiagnostics();
1501 }
1502 }} // end namespace clang::consumed
1503