In preparation for fixing PR 6884, rework CFGElement to have getAs<> return pointers instead of fresh CFGElements.

- Also, consoldiate getDtorKind() and getKind() into one "kind".
- Add empty getDestructorDecl() method to CFGImplicitDtor.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126738 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index d2cccc8..7ee2a9c 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -2704,6 +2704,10 @@
   return Builder.buildCFG(D, Statement, C, BO);
 }
 
+const CXXDestructorDecl *CFGImplicitDtor::getDestructorDecl() const {
+  return 0;
+}
+
 //===----------------------------------------------------------------------===//
 // CFG: Queries for BlkExprs.
 //===----------------------------------------------------------------------===//
@@ -2740,8 +2744,8 @@
 
   for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I)
     for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI)
-      if (CFGStmt S = BI->getAs<CFGStmt>())
-        FindSubExprAssignments(S, SubExprAssignments);
+      if (const CFGStmt *S = BI->getAs<CFGStmt>())
+        FindSubExprAssignments(S->getStmt(), SubExprAssignments);
 
   for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) {
 
@@ -2749,10 +2753,10 @@
     // block-level that are block-level expressions.
 
     for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) {
-      CFGStmt CS = BI->getAs<CFGStmt>();
-      if (!CS.isValid())
+      const CFGStmt *CS = BI->getAs<CFGStmt>();
+      if (!CS)
         continue;
-      if (Expr* Exp = dyn_cast<Expr>(CS.getStmt())) {
+      if (Expr* Exp = dyn_cast<Expr>(CS->getStmt())) {
 
         if (BinaryOperator* B = dyn_cast<BinaryOperator>(Exp)) {
           // Assignment expressions that are not nested within another
@@ -2845,8 +2849,8 @@
 namespace {
 
 class StmtPrinterHelper : public PrinterHelper  {
-  typedef llvm::DenseMap<Stmt*,std::pair<unsigned,unsigned> > StmtMapTy;
-  typedef llvm::DenseMap<Decl*,std::pair<unsigned,unsigned> > DeclMapTy;
+  typedef llvm::DenseMap<const Stmt*,std::pair<unsigned,unsigned> > StmtMapTy;
+  typedef llvm::DenseMap<const Decl*,std::pair<unsigned,unsigned> > DeclMapTy;
   StmtMapTy StmtMap;
   DeclMapTy DeclMap;
   signed currentBlock;
@@ -2855,42 +2859,62 @@
 public:
 
   StmtPrinterHelper(const CFG* cfg, const LangOptions &LO)
-    : currentBlock(0), currentStmt(0), LangOpts(LO) {
+    : currentBlock(0), currentStmt(0), LangOpts(LO)
+  {
     for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) {
       unsigned j = 1;
       for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ;
            BI != BEnd; ++BI, ++j ) {        
-        if (CFGStmt SE = BI->getAs<CFGStmt>()) {
+        if (const CFGStmt *SE = BI->getAs<CFGStmt>()) {
+          const Stmt *stmt= SE->getStmt();
           std::pair<unsigned, unsigned> P((*I)->getBlockID(), j);
-          StmtMap[SE] = P;
+          StmtMap[stmt] = P;
 
-          if (DeclStmt* DS = dyn_cast<DeclStmt>(SE.getStmt())) {
-              DeclMap[DS->getSingleDecl()] = P;
-
-          } else if (IfStmt* IS = dyn_cast<IfStmt>(SE.getStmt())) {
-            if (VarDecl* VD = IS->getConditionVariable())
-              DeclMap[VD] = P;
-
-          } else if (ForStmt* FS = dyn_cast<ForStmt>(SE.getStmt())) {
-            if (VarDecl* VD = FS->getConditionVariable())
-              DeclMap[VD] = P;
-
-          } else if (WhileStmt* WS = dyn_cast<WhileStmt>(SE.getStmt())) {
-            if (VarDecl* VD = WS->getConditionVariable())
-              DeclMap[VD] = P;
-
-          } else if (SwitchStmt* SS = dyn_cast<SwitchStmt>(SE.getStmt())) {
-            if (VarDecl* VD = SS->getConditionVariable())
-              DeclMap[VD] = P;
-
-          } else if (CXXCatchStmt* CS = dyn_cast<CXXCatchStmt>(SE.getStmt())) {
-            if (VarDecl* VD = CS->getExceptionDecl())
-              DeclMap[VD] = P;
+          switch (stmt->getStmtClass()) {
+            case Stmt::DeclStmtClass:
+                DeclMap[cast<DeclStmt>(stmt)->getSingleDecl()] = P;
+                break;
+            case Stmt::IfStmtClass: {
+              const VarDecl *var = cast<IfStmt>(stmt)->getConditionVariable();
+              if (var)
+                DeclMap[var] = P;
+              break;
+            }
+            case Stmt::ForStmtClass: {
+              const VarDecl *var = cast<ForStmt>(stmt)->getConditionVariable();
+              if (var)
+                DeclMap[var] = P;
+              break;
+            }
+            case Stmt::WhileStmtClass: {
+              const VarDecl *var =
+                cast<WhileStmt>(stmt)->getConditionVariable();
+              if (var)
+                DeclMap[var] = P;
+              break;
+            }
+            case Stmt::SwitchStmtClass: {
+              const VarDecl *var =
+                cast<SwitchStmt>(stmt)->getConditionVariable();
+              if (var)
+                DeclMap[var] = P;
+              break;
+            }
+            case Stmt::CXXCatchStmtClass: {
+              const VarDecl *var =
+                cast<CXXCatchStmt>(stmt)->getExceptionDecl();
+              if (var)
+                DeclMap[var] = P;
+              break;
+            }
+            default:
+              break;
           }
         }
       }
     }
   }
+  
 
   virtual ~StmtPrinterHelper() {}
 
@@ -2913,7 +2937,7 @@
     return true;
   }
 
-  bool handleDecl(Decl* D, llvm::raw_ostream& OS) {
+  bool handleDecl(const Decl* D, llvm::raw_ostream& OS) {
     DeclMapTy::iterator I = DeclMap.find(D);
 
     if (I == DeclMap.end())
@@ -3031,8 +3055,8 @@
 
 static void print_elem(llvm::raw_ostream &OS, StmtPrinterHelper* Helper,
                        const CFGElement &E) {
-  if (CFGStmt CS = E.getAs<CFGStmt>()) {
-    Stmt *S = CS;
+  if (const CFGStmt *CS = E.getAs<CFGStmt>()) {
+    Stmt *S = CS->getStmt();
     
     if (Helper) {
 
@@ -3069,8 +3093,8 @@
     if (isa<Expr>(S))
       OS << '\n';
 
-  } else if (CFGInitializer IE = E.getAs<CFGInitializer>()) {
-    CXXCtorInitializer* I = IE;
+  } else if (const CFGInitializer *IE = E.getAs<CFGInitializer>()) {
+    const CXXCtorInitializer *I = IE->getInitializer();
     if (I->isBaseInitializer())
       OS << I->getBaseClass()->getAsCXXRecordDecl()->getName();
     else OS << I->getAnyMember()->getName();
@@ -3084,8 +3108,8 @@
       OS << " (Base initializer)\n";
     else OS << " (Member initializer)\n";
 
-  } else if (CFGAutomaticObjDtor DE = E.getAs<CFGAutomaticObjDtor>()){
-    VarDecl* VD = DE.getVarDecl();
+  } else if (const CFGAutomaticObjDtor *DE = E.getAs<CFGAutomaticObjDtor>()){
+    const VarDecl* VD = DE->getVarDecl();
     Helper->handleDecl(VD, OS);
 
     const Type* T = VD->getType().getTypePtr();
@@ -3097,13 +3121,13 @@
     OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()";
     OS << " (Implicit destructor)\n";
 
-  } else if (CFGBaseDtor BE = E.getAs<CFGBaseDtor>()) {
-    const CXXBaseSpecifier *BS = BE.getBaseSpecifier();
+  } else if (const CFGBaseDtor *BE = E.getAs<CFGBaseDtor>()) {
+    const CXXBaseSpecifier *BS = BE->getBaseSpecifier();
     OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()";
     OS << " (Base object destructor)\n";
 
-  } else if (CFGMemberDtor ME = E.getAs<CFGMemberDtor>()) {
-    FieldDecl *FD = ME.getFieldDecl();
+  } else if (const CFGMemberDtor *ME = E.getAs<CFGMemberDtor>()) {
+    const FieldDecl *FD = ME->getFieldDecl();
 
     const Type *T = FD->getType().getTypePtr();
     if (const Type *ET = T->getArrayElementTypeNoTypeQual())
@@ -3113,8 +3137,8 @@
     OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()";
     OS << " (Member object destructor)\n";
 
-  } else if (CFGTemporaryDtor TE = E.getAs<CFGTemporaryDtor>()) {
-    CXXBindTemporaryExpr *BT = TE.getBindTemporaryExpr();
+  } else if (const CFGTemporaryDtor *TE = E.getAs<CFGTemporaryDtor>()) {
+    const CXXBindTemporaryExpr *BT = TE->getBindTemporaryExpr();
     OS << "~" << BT->getType()->getAsCXXRecordDecl()->getName() << "()";
     OS << " (Temporary object destructor)\n";
   }
diff --git a/lib/Analysis/CFGStmtMap.cpp b/lib/Analysis/CFGStmtMap.cpp
index 3a030f9..1fd5eed 100644
--- a/lib/Analysis/CFGStmtMap.cpp
+++ b/lib/Analysis/CFGStmtMap.cpp
@@ -50,11 +50,11 @@
   // First walk the block-level expressions.
   for (CFGBlock::iterator I = B->begin(), E = B->end(); I != E; ++I) {
     const CFGElement &CE = *I;
-    CFGStmt CS = CE.getAs<CFGStmt>();
-    if (!CS.isValid())
+    const CFGStmt *CS = CE.getAs<CFGStmt>();
+    if (!CS)
       continue;
     
-    CFGBlock *&Entry = SM[CS];
+    CFGBlock *&Entry = SM[CS->getStmt()];
     // If 'Entry' is already initialized (e.g., a terminator was already),
     // skip.
     if (Entry)
diff --git a/lib/Analysis/ReachableCode.cpp b/lib/Analysis/ReachableCode.cpp
index 7afa586..9659e9e 100644
--- a/lib/Analysis/ReachableCode.cpp
+++ b/lib/Analysis/ReachableCode.cpp
@@ -31,11 +31,11 @@
   R1 = R2 = SourceRange();
 
   if (sn < b.size()) {
-    CFGStmt CS = b[sn].getAs<CFGStmt>();
+    const CFGStmt *CS = b[sn].getAs<CFGStmt>();
     if (!CS)
       return SourceLocation();
 
-    S = CS.getStmt(); 
+    S = CS->getStmt(); 
   } else if (b.getTerminator())
     S = b.getTerminator();
   else
@@ -49,7 +49,7 @@
       const BinaryOperator *BO = cast<BinaryOperator>(S);
       if (BO->getOpcode() == BO_Comma) {
         if (sn+1 < b.size())
-          return b[sn+1].getAs<CFGStmt>().getStmt()->getLocStart();
+          return b[sn+1].getAs<CFGStmt>()->getStmt()->getLocStart();
         const CFGBlock *n = &b;
         while (1) {
           if (n->getTerminator())
@@ -60,7 +60,7 @@
           if (n->pred_size() != 1)
             return SourceLocation();
           if (!n->empty())
-            return n[0][0].getAs<CFGStmt>().getStmt()->getLocStart();
+            return n[0][0].getAs<CFGStmt>()->getStmt()->getLocStart();
         }
       }
       R1 = BO->getLHS()->getSourceRange();
diff --git a/lib/Analysis/UninitializedValuesV2.cpp b/lib/Analysis/UninitializedValuesV2.cpp
index 75eccbf..0d0bc36 100644
--- a/lib/Analysis/UninitializedValuesV2.cpp
+++ b/lib/Analysis/UninitializedValuesV2.cpp
@@ -146,8 +146,8 @@
   if (block->empty())
     return 0;
 
-  CFGStmt cstmt = block->front().getAs<CFGStmt>();
-  BinaryOperator *b = llvm::dyn_cast_or_null<BinaryOperator>(cstmt.getStmt());
+  const CFGStmt *cstmt = block->front().getAs<CFGStmt>();
+  BinaryOperator *b = llvm::dyn_cast_or_null<BinaryOperator>(cstmt->getStmt());
   
   if (!b || !b->isLogicalOp())
     return 0;
diff --git a/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp b/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
index 3d8327f..905a99e 100644
--- a/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
@@ -112,8 +112,8 @@
     // such as llvm_unreachable.
     if (!CB->empty()) {
       CFGElement First = CB->front();
-      if (CFGStmt S = First.getAs<CFGStmt>()) {
-        if (const CallExpr *CE = dyn_cast<CallExpr>(S.getStmt())) {
+      if (const CFGStmt *S = First.getAs<CFGStmt>()) {
+        if (const CallExpr *CE = dyn_cast<CallExpr>(S->getStmt())) {
           if (CE->isBuiltinCall(Ctx) == Builtin::BI__builtin_unreachable)
             continue;
         }
@@ -164,8 +164,8 @@
 // Find the Stmt* in a CFGBlock for reporting a warning
 const Stmt *UnreachableCodeChecker::getUnreachableStmt(const CFGBlock *CB) {
   for (CFGBlock::const_iterator I = CB->begin(), E = CB->end(); I != E; ++I) {
-    if (CFGStmt S = I->getAs<CFGStmt>())
-      return S;
+    if (const CFGStmt *S = I->getAs<CFGStmt>())
+      return S->getStmt();
   }
   if (const Stmt *S = CB->getTerminator())
     return S;
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index 672982a..74cd359 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -1170,13 +1170,14 @@
       }
 
       if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
-        if (CFGStmt S = BE->getFirstElement().getAs<CFGStmt>()) {
-          if (IsControlFlowExpr(S)) {
+        if (const CFGStmt *S = BE->getFirstElement().getAs<CFGStmt>()) {
+          const Stmt *stmt = S->getStmt();
+          if (IsControlFlowExpr(stmt)) {
             // Add the proper context for '&&', '||', and '?'.
-            EB.addContext(S);
+            EB.addContext(stmt);
           }
           else
-            EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
+            EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt());
         }
         
         break;
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index cb777ae..615c216 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -191,18 +191,20 @@
 void ExprEngine::processCFGElement(const CFGElement E, 
                                   StmtNodeBuilder& builder) {
   switch (E.getKind()) {
-  case CFGElement::Statement:
-    ProcessStmt(E.getAs<CFGStmt>(), builder);
-    break;
-  case CFGElement::Initializer:
-    ProcessInitializer(E.getAs<CFGInitializer>(), builder);
-    break;
-  case CFGElement::ImplicitDtor:
-    ProcessImplicitDtor(E.getAs<CFGImplicitDtor>(), builder);
-    break;
-  default:
-    // Suppress compiler warning.
-    llvm_unreachable("Unexpected CFGElement kind.");
+    case CFGElement::Invalid:
+      llvm_unreachable("Unexpected CFGElement kind.");
+    case CFGElement::Statement:
+      ProcessStmt(E.getAs<CFGStmt>()->getStmt(), builder);
+      return;
+    case CFGElement::Initializer:
+      ProcessInitializer(E.getAs<CFGInitializer>()->getInitializer(), builder);
+      return;
+    case CFGElement::AutomaticObjectDtor:
+    case CFGElement::BaseDtor:
+    case CFGElement::MemberDtor:
+    case CFGElement::TemporaryDtor:
+      ProcessImplicitDtor(*E.getAs<CFGImplicitDtor>(), builder);
+      return;
   }
 }
 
@@ -345,7 +347,7 @@
                                        StmtNodeBuilder &builder) {
   Builder = &builder;
 
-  switch (D.getDtorKind()) {
+  switch (D.getKind()) {
   case CFGElement::AutomaticObjectDtor:
     ProcessAutomaticObjDtor(cast<CFGAutomaticObjDtor>(D), builder);
     break;