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