Add noreturn as a type attribute, handle printing for them and handle
calls to noreturn function pointers when CFG building.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77089 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 4684a80..27c8a81 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -965,7 +965,7 @@
   
   // Check if we've already instantiated this type.
   llvm::FoldingSetNodeID ID;
-  ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr);      
+  ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr);
   void *InsertPos = 0;
   if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos))
     return QualType(EXTQy, CVRQuals);
@@ -1007,17 +1007,17 @@
   unsigned AddressSpace = 0;
   
   if (ExtQualType *EQT = dyn_cast<ExtQualType>(TypeNode)) {
-    // If this type already has an address space specified, it cannot get
+    // If this type already has an ObjCGC specified, it cannot get
     // another one.
     assert(EQT->getObjCGCAttr() == QualType::GCNone &&
-           "Type cannot be in multiple addr spaces!");
+           "Type cannot have multiple ObjCGCs!");
     AddressSpace = EQT->getAddressSpace();
     TypeNode = EQT->getBaseType();
   }
   
   // Check if we've already instantiated an gc qual'd type of this type.
   llvm::FoldingSetNodeID ID;
-  ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr);      
+  ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr);
   void *InsertPos = 0;
   if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos))
     return QualType(EXTQy, CVRQuals);
@@ -1041,6 +1041,30 @@
   return QualType(New, CVRQuals);
 }
 
+QualType ASTContext::getNoReturnType(QualType T) {
+  if (T->isPointerType()) {
+    QualType Pointee = T->getAsPointerType()->getPointeeType();
+    QualType ResultType = getNoReturnType(Pointee);
+    return getPointerType(ResultType);
+  }
+  if (T->isBlockPointerType()) {
+    QualType Pointee = T->getAsBlockPointerType()->getPointeeType();
+    QualType ResultType = getNoReturnType(Pointee);
+    return getBlockPointerType(ResultType);
+  }    
+  if (!T->isFunctionType())
+    assert(0 && "can't noreturn qualify non-pointer to function or block type");
+  
+  if (const FunctionNoProtoType *F = dyn_cast<FunctionNoProtoType>(T)) {
+    return getFunctionNoProtoType(F->getResultType(), true);
+  }
+  const FunctionProtoType *F = cast<FunctionProtoType>(T);
+  return getFunctionType(F->getResultType(), F->arg_type_begin(),
+                         F->getNumArgs(), F->isVariadic(), F->getTypeQuals(),
+                         F->hasExceptionSpec(), F->hasAnyExceptionSpec(),
+                         F->getNumExceptions(), F->exception_begin(), true);
+}
+
 /// getComplexType - Return the uniqued reference to the type for a complex
 /// number with the specified element type.
 QualType ASTContext::getComplexType(QualType T) {
@@ -1474,11 +1498,11 @@
 
 /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
 ///
-QualType ASTContext::getFunctionNoProtoType(QualType ResultTy) {
+QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool NoReturn) {
   // Unique functions, to guarantee there is only one function of a particular
   // structure.
   llvm::FoldingSetNodeID ID;
-  FunctionNoProtoType::Profile(ID, ResultTy);
+  FunctionNoProtoType::Profile(ID, ResultTy, NoReturn);
   
   void *InsertPos = 0;
   if (FunctionNoProtoType *FT = 
@@ -1487,7 +1511,7 @@
   
   QualType Canonical;
   if (!ResultTy->isCanonical()) {
-    Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy));
+    Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy), NoReturn);
     
     // Get the new insert position for the node we care about.
     FunctionNoProtoType *NewIP =
@@ -1495,7 +1519,8 @@
     assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP;
   }
   
-  FunctionNoProtoType *New =new(*this,8)FunctionNoProtoType(ResultTy,Canonical);
+  FunctionNoProtoType *New
+    = new (*this,8) FunctionNoProtoType(ResultTy, Canonical, NoReturn);
   Types.push_back(New);
   FunctionNoProtoTypes.InsertNode(New, InsertPos);
   return QualType(New, 0);
@@ -1507,13 +1532,13 @@
                                      unsigned NumArgs, bool isVariadic,
                                      unsigned TypeQuals, bool hasExceptionSpec,
                                      bool hasAnyExceptionSpec, unsigned NumExs,
-                                     const QualType *ExArray) {
+                                     const QualType *ExArray, bool NoReturn) {
   // Unique functions, to guarantee there is only one function of a particular
   // structure.
   llvm::FoldingSetNodeID ID;
   FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, isVariadic,
                              TypeQuals, hasExceptionSpec, hasAnyExceptionSpec,
-                             NumExs, ExArray);
+                             NumExs, ExArray, NoReturn);
 
   void *InsertPos = 0;
   if (FunctionProtoType *FTP = 
@@ -1539,7 +1564,7 @@
 
     Canonical = getFunctionType(getCanonicalType(ResultTy),
                                 CanonicalArgs.data(), NumArgs,
-                                isVariadic, TypeQuals);
+                                isVariadic, TypeQuals, NoReturn);
 
     // Get the new insert position for the node we care about.
     FunctionProtoType *NewIP =
@@ -1556,7 +1581,7 @@
                                  NumExs*sizeof(QualType), 8);
   new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, isVariadic,
                               TypeQuals, hasExceptionSpec, hasAnyExceptionSpec,
-                              ExArray, NumExs, Canonical);
+                              ExArray, NumExs, Canonical, NoReturn);
   Types.push_back(FTP);
   FunctionProtoTypes.InsertNode(FTP, InsertPos);
   return QualType(FTP, 0);
@@ -3344,7 +3369,12 @@
     allLTypes = false;
   if (getCanonicalType(retType) != getCanonicalType(rbase->getResultType()))
     allRTypes = false;
-
+  bool NoReturn = lbase->getNoReturnAttr() || rbase->getNoReturnAttr();
+  if (NoReturn != lbase->getNoReturnAttr())
+    allLTypes = false;
+  if (NoReturn != rbase->getNoReturnAttr())
+    allRTypes = false;
+    
   if (lproto && rproto) { // two C99 style function prototypes
     assert(!lproto->hasExceptionSpec() && !rproto->hasExceptionSpec() &&
            "C++ shouldn't be here");
@@ -3378,7 +3408,8 @@
     if (allLTypes) return lhs;
     if (allRTypes) return rhs;
     return getFunctionType(retType, types.begin(), types.size(),
-                           lproto->isVariadic(), lproto->getTypeQuals());
+                           lproto->isVariadic(), lproto->getTypeQuals(),
+                           NoReturn);
   }
 
   if (lproto) allRTypes = false;
@@ -3405,12 +3436,12 @@
     if (allRTypes) return rhs;
     return getFunctionType(retType, proto->arg_type_begin(),
                            proto->getNumArgs(), lproto->isVariadic(),
-                           lproto->getTypeQuals());
+                           lproto->getTypeQuals(), NoReturn);
   }
 
   if (allLTypes) return lhs;
   if (allRTypes) return rhs;
-  return getFunctionNoProtoType(retType);
+  return getFunctionNoProtoType(retType, NoReturn);
 }
 
 QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {