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