Teach CFG building how to deal with CXXMemberCallExprs and BoundMemberTy,
then teach -Wreturn-type to handle the same.  Net effect:  we now correctly
handle noreturn attributes on member calls in the CFG.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131178 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index a247a9d..77c30dd 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -320,7 +320,6 @@
                                        AddStmtChoice asc);
   CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, 
                                         AddStmtChoice asc);
-  CFGBlock *VisitCXXMemberCallExpr(CXXMemberCallExpr *C, AddStmtChoice asc);
   CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc);
   CFGBlock *VisitCaseStmt(CaseStmt *C);
   CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc);
@@ -868,6 +867,7 @@
 
     case Stmt::CallExprClass:
     case Stmt::CXXOperatorCallExprClass:
+    case Stmt::CXXMemberCallExprClass:
       return VisitCallExpr(cast<CallExpr>(S), asc);
 
     case Stmt::CaseStmtClass:
@@ -903,9 +903,6 @@
     case Stmt::CXXTemporaryObjectExprClass:
       return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);
 
-    case Stmt::CXXMemberCallExprClass:
-      return VisitCXXMemberCallExpr(cast<CXXMemberCallExpr>(S), asc);
-
     case Stmt::CXXThrowExprClass:
       return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
 
@@ -1153,12 +1150,19 @@
 }
 
 CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
-  // If this is a call to a no-return function, this stops the block here.
-  bool NoReturn = false;
-  if (getFunctionExtInfo(*C->getCallee()->getType()).getNoReturn()) {
-    NoReturn = true;
+  // Compute the callee type.
+  QualType calleeType = C->getCallee()->getType();
+  if (calleeType == Context->BoundMemberTy) {
+    QualType boundType = Expr::findBoundMemberType(C->getCallee());
+
+    // We should only get a null bound type if processing a dependent
+    // CFG.  Recover by assuming nothing.
+    if (!boundType.isNull()) calleeType = boundType;
   }
 
+  // If this is a call to a no-return function, this stops the block here.
+  bool NoReturn = getFunctionExtInfo(*calleeType).getNoReturn();
+
   bool AddEHEdge = false;
 
   // Languages without exceptions are assumed to not throw.
@@ -2691,13 +2695,6 @@
   return VisitChildren(C);
 }
 
-CFGBlock *CFGBuilder::VisitCXXMemberCallExpr(CXXMemberCallExpr *C,
-                                             AddStmtChoice asc) {
-  autoCreateBlock();
-  appendStmt(Block, C);
-  return VisitChildren(C);
-}
-
 CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E,
                                             AddStmtChoice asc) {
   if (asc.alwaysAdd(*this, E)) {
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index e482172..9efae61 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -196,7 +196,12 @@
         continue;
       }
       Expr *CEE = C->getCallee()->IgnoreParenCasts();
-      if (getFunctionExtInfo(CEE->getType()).getNoReturn()) {
+      QualType calleeType = CEE->getType();
+      if (calleeType == AC.getASTContext().BoundMemberTy) {
+        calleeType = Expr::findBoundMemberType(CEE);
+        assert(!calleeType.isNull() && "analyzing unresolved call?");
+      }
+      if (getFunctionExtInfo(calleeType).getNoReturn()) {
         NoReturnEdge = true;
         HasFakeEdge = true;
       } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {