the big refactoring bits of PR3782.

This introduces FunctionType::ExtInfo to hold the calling convention and the
noreturn attribute. The next patch will extend it to include the regparm
attribute and fix the bug.

llvm-svn: 99920
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index f8f626a..00a7987 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1097,14 +1097,12 @@
   return getExtQualType(TypeNode, Quals);
 }
 
-static QualType getNoReturnCallConvType(ASTContext& Context, QualType T,
-                                        bool AddNoReturn,
-                                        CallingConv CallConv) {
+static QualType getExtFunctionType(ASTContext& Context, QualType T,
+                                        const FunctionType::ExtInfo &Info) {
   QualType ResultType;
   if (const PointerType *Pointer = T->getAs<PointerType>()) {
     QualType Pointee = Pointer->getPointeeType();
-    ResultType = getNoReturnCallConvType(Context, Pointee, AddNoReturn,
-                                         CallConv);
+    ResultType = getExtFunctionType(Context, Pointee, Info);
     if (ResultType == Pointee)
       return T;
 
@@ -1112,19 +1110,18 @@
   } else if (const BlockPointerType *BlockPointer
                                               = T->getAs<BlockPointerType>()) {
     QualType Pointee = BlockPointer->getPointeeType();
-    ResultType = getNoReturnCallConvType(Context, Pointee, AddNoReturn,
-                                         CallConv);
+    ResultType = getExtFunctionType(Context, Pointee, Info);
     if (ResultType == Pointee)
       return T;
 
     ResultType = Context.getBlockPointerType(ResultType);
    } else if (const FunctionType *F = T->getAs<FunctionType>()) {
-    if (F->getNoReturnAttr() == AddNoReturn && F->getCallConv() == CallConv)
+    if (F->getExtInfo() == Info)
       return T;
 
     if (const FunctionNoProtoType *FNPT = dyn_cast<FunctionNoProtoType>(F)) {
       ResultType = Context.getFunctionNoProtoType(FNPT->getResultType(),
-                                                  AddNoReturn, CallConv);
+                                                  Info);
     } else {
       const FunctionProtoType *FPT = cast<FunctionProtoType>(F);
       ResultType
@@ -1135,7 +1132,7 @@
                                   FPT->hasAnyExceptionSpec(),
                                   FPT->getNumExceptions(),
                                   FPT->exception_begin(),
-                                  AddNoReturn, CallConv);
+                                  Info);
     }
   } else
     return T;
@@ -1144,11 +1141,15 @@
 }
 
 QualType ASTContext::getNoReturnType(QualType T, bool AddNoReturn) {
-  return getNoReturnCallConvType(*this, T, AddNoReturn, T->getCallConv());
+  FunctionType::ExtInfo Info = getFunctionExtInfo(*T);
+  return getExtFunctionType(*this, T,
+                                 Info.withNoReturn(AddNoReturn));
 }
 
 QualType ASTContext::getCallConvType(QualType T, CallingConv CallConv) {
-  return getNoReturnCallConvType(*this, T, T->getNoReturnAttr(), CallConv);
+  FunctionType::ExtInfo Info = getFunctionExtInfo(*T);
+  return getExtFunctionType(*this, T,
+                            Info.withCallingConv(CallConv));
 }
 
 /// getComplexType - Return the uniqued reference to the type for a complex
@@ -1606,12 +1607,13 @@
 
 /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
 ///
-QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool NoReturn,
-                                            CallingConv CallConv) {
+QualType ASTContext::getFunctionNoProtoType(QualType ResultTy,
+                                            const FunctionType::ExtInfo &Info) {
+  const CallingConv CallConv = Info.getCC();
   // Unique functions, to guarantee there is only one function of a particular
   // structure.
   llvm::FoldingSetNodeID ID;
-  FunctionNoProtoType::Profile(ID, ResultTy, NoReturn, CallConv);
+  FunctionNoProtoType::Profile(ID, ResultTy, Info);
 
   void *InsertPos = 0;
   if (FunctionNoProtoType *FT =
@@ -1621,8 +1623,9 @@
   QualType Canonical;
   if (!ResultTy.isCanonical() ||
       getCanonicalCallConv(CallConv) != CallConv) {
-    Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy), NoReturn,
-                                       getCanonicalCallConv(CallConv));
+    Canonical =
+      getFunctionNoProtoType(getCanonicalType(ResultTy),
+                     Info.withCallingConv(getCanonicalCallConv(CallConv)));
 
     // Get the new insert position for the node we care about.
     FunctionNoProtoType *NewIP =
@@ -1631,7 +1634,7 @@
   }
 
   FunctionNoProtoType *New = new (*this, TypeAlignment)
-    FunctionNoProtoType(ResultTy, Canonical, NoReturn, CallConv);
+    FunctionNoProtoType(ResultTy, Canonical, Info);
   Types.push_back(New);
   FunctionNoProtoTypes.InsertNode(New, InsertPos);
   return QualType(New, 0);
@@ -1643,14 +1646,15 @@
                                      unsigned NumArgs, bool isVariadic,
                                      unsigned TypeQuals, bool hasExceptionSpec,
                                      bool hasAnyExceptionSpec, unsigned NumExs,
-                                     const QualType *ExArray, bool NoReturn,
-                                     CallingConv CallConv) {
+                                     const QualType *ExArray,
+                                     const FunctionType::ExtInfo &Info) {
+  const CallingConv CallConv= Info.getCC();
   // 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, NoReturn, CallConv);
+                             NumExs, ExArray, Info);
 
   void *InsertPos = 0;
   if (FunctionProtoType *FTP =
@@ -1675,8 +1679,8 @@
     Canonical = getFunctionType(getCanonicalType(ResultTy),
                                 CanonicalArgs.data(), NumArgs,
                                 isVariadic, TypeQuals, false,
-                                false, 0, 0, NoReturn,
-                                getCanonicalCallConv(CallConv));
+                                false, 0, 0,
+                     Info.withCallingConv(getCanonicalCallConv(CallConv)));
 
     // Get the new insert position for the node we care about.
     FunctionProtoType *NewIP =
@@ -1693,7 +1697,7 @@
                                  NumExs*sizeof(QualType), TypeAlignment);
   new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, isVariadic,
                               TypeQuals, hasExceptionSpec, hasAnyExceptionSpec,
-                              ExArray, NumExs, Canonical, NoReturn, CallConv);
+                              ExArray, NumExs, Canonical, Info);
   Types.push_back(FTP);
   FunctionProtoTypes.InsertNode(FTP, InsertPos);
   return QualType(FTP, 0);
@@ -4304,13 +4308,15 @@
   if (getCanonicalType(retType) != getCanonicalType(rbase->getResultType()))
     allRTypes = false;
   // FIXME: double check this
-  bool NoReturn = lbase->getNoReturnAttr() || rbase->getNoReturnAttr();
-  if (NoReturn != lbase->getNoReturnAttr())
+  FunctionType::ExtInfo lbaseInfo = lbase->getExtInfo();
+  FunctionType::ExtInfo rbaseInfo = rbase->getExtInfo();
+  bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn();
+  if (NoReturn != lbaseInfo.getNoReturn())
     allLTypes = false;
-  if (NoReturn != rbase->getNoReturnAttr())
+  if (NoReturn != rbaseInfo.getNoReturn())
     allRTypes = false;
-  CallingConv lcc = lbase->getCallConv();
-  CallingConv rcc = rbase->getCallConv();
+  CallingConv lcc = lbaseInfo.getCC();
+  CallingConv rcc = rbaseInfo.getCC();
   // Compatible functions must have compatible calling conventions
   if (!isSameCallConv(lcc, rcc))
     return QualType();
@@ -4349,7 +4355,8 @@
     if (allRTypes) return rhs;
     return getFunctionType(retType, types.begin(), types.size(),
                            lproto->isVariadic(), lproto->getTypeQuals(),
-                           false, false, 0, 0, NoReturn, lcc);
+                           false, false, 0, 0,
+                           FunctionType::ExtInfo(NoReturn, lcc));
   }
 
   if (lproto) allRTypes = false;
@@ -4382,13 +4389,15 @@
     if (allRTypes) return rhs;
     return getFunctionType(retType, proto->arg_type_begin(),
                            proto->getNumArgs(), proto->isVariadic(),
-                           proto->getTypeQuals(), 
-                           false, false, 0, 0, NoReturn, lcc);
+                           proto->getTypeQuals(),
+                           false, false, 0, 0,
+                           FunctionType::ExtInfo(NoReturn, lcc));
   }
 
   if (allLTypes) return lhs;
   if (allRTypes) return rhs;
-  return getFunctionNoProtoType(retType, NoReturn, lcc);
+  FunctionType::ExtInfo Info(NoReturn, lcc);
+  return getFunctionNoProtoType(retType, Info);
 }
 
 QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, 
@@ -4892,7 +4901,7 @@
   // FIXME: Should we create noreturn types?
   return getFunctionType(ResType, ArgTypes.data(), ArgTypes.size(),
                          TypeStr[0] == '.', 0, false, false, 0, 0,
-                         false, CC_Default);
+                         FunctionType::ExtInfo());
 }
 
 QualType