Hi,

This patch encodes calling conventions into FunctionType objects. Right
now, only cdecl, stdcall, and fastcall are supported. No real users yet,
but I went through and fixed all the users of
ASTContext::getFunctionType() and friends to respect the calling convention.

Next up: applying calling convention attributes to the function types.

Chip


Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h      (revision 91549)
+++ include/clang/AST/ASTContext.h      (working copy)
@@ -399,6 +399,11 @@
   /// BlockPointer.
   QualType getNoReturnType(QualType T, bool AddNoReturn = true);
 
+  /// getCallConvType - Adds the specified calling convention attribute to
+  /// the given type, which must be a FunctionType or a pointer to an
+  /// allowable type.
+  QualType getCallConvType(QualType T, unsigned CallConv);
+
   /// getComplexType - Return the uniqued reference to the type for a complex
   /// number with the specified element type.
   QualType getComplexType(QualType T);
@@ -515,7 +520,8 @@
 
   /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
   ///
-  QualType getFunctionNoProtoType(QualType ResultTy, bool NoReturn = false);
+  QualType getFunctionNoProtoType(QualType ResultTy, bool NoReturn = false,
+                                  unsigned CallConv = 0);
 
   /// getFunctionType - Return a normal function type with a typed argument
   /// list.  isVariadic indicates whether the argument list includes '...'.
@@ -524,7 +530,7 @@
                            unsigned TypeQuals, bool hasExceptionSpec = false,
                            bool hasAnyExceptionSpec = false,
                            unsigned NumExs = 0, const QualType *ExArray = 0,
-                           bool NoReturn = false);
+                           bool NoReturn = false, unsigned CallConv = 0);
 
   /// getTypeDeclType - Return the unique reference to the type for
   /// the specified type declaration.
Index: include/clang/AST/Type.h
===================================================================
--- include/clang/AST/Type.h    (revision 91549)
+++ include/clang/AST/Type.h    (working copy)
@@ -1708,21 +1708,26 @@
   /// NoReturn - Indicates if the function type is attribute noreturn.
   unsigned NoReturn : 1;
 
+  /// CallConv - The calling convention used by the function. Is 0
+  /// for default, 1 for C, 2 for stdcall, and 3 for fastcall.
+  unsigned CallConv : 2;
+
   // The type returned by the function.
   QualType ResultType;
 protected:
   FunctionType(TypeClass tc, QualType res, bool SubclassInfo,
                unsigned typeQuals, QualType Canonical, bool Dependent,
-               bool noReturn = false)
+               bool noReturn = false, unsigned callConv = 0)
     : Type(tc, Canonical, Dependent),
       SubClassData(SubclassInfo), TypeQuals(typeQuals), NoReturn(noReturn),
-      ResultType(res) {}
+      CallConv(callConv), ResultType(res) {}
   bool getSubClassData() const { return SubClassData; }
   unsigned getTypeQuals() const { return TypeQuals; }
 public:
 
   QualType getResultType() const { return ResultType; }
   bool getNoReturnAttr() const { return NoReturn; }
+  unsigned getCallConv() const { return CallConv; }
 
   static bool classof(const Type *T) {
     return T->getTypeClass() == FunctionNoProto ||
@@ -1735,9 +1740,9 @@
 /// no information available about its arguments.
 class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
   FunctionNoProtoType(QualType Result, QualType Canonical,
-                      bool NoReturn = false)
+                      bool NoReturn = false, unsigned CallConv = 0)
     : FunctionType(FunctionNoProto, Result, false, 0, Canonical,
-                   /*Dependent=*/false, NoReturn) {}
+                   /*Dependent=*/false, NoReturn, CallConv) {}
   friend class ASTContext;  // ASTContext creates these.
 public:
   // No additional state past what FunctionType provides.
@@ -1779,10 +1784,12 @@
   FunctionProtoType(QualType Result, const QualType *ArgArray, unsigned 
numArgs,
                     bool isVariadic, unsigned typeQuals, bool hasExs,
                     bool hasAnyExs, const QualType *ExArray,
-                    unsigned numExs, QualType Canonical, bool NoReturn)
+                    unsigned numExs, QualType Canonical, bool NoReturn,
+                    unsigned CallConv = 0)
     : FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical,
                    (Result->isDependentType() ||
-                    hasAnyDependentType(ArgArray, numArgs)), NoReturn),
+                    hasAnyDependentType(ArgArray, numArgs)), NoReturn,
+                   CallConv),
       NumArgs(numArgs), NumExceptions(numExs), HasExceptionSpec(hasExs),
       AnyExceptionSpec(hasAnyExs) {
     // Fill in the trailing argument array.
Index: lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiateDecl.cpp    (revision 91549)
+++ lib/Sema/SemaTemplateInstantiateDecl.cpp    (working copy)
@@ -1523,7 +1523,8 @@
                                                  Proto->hasAnyExceptionSpec(),
                                                  Exceptions.size(),
                                                  Exceptions.data(),
-                                                 Proto->getNoReturnAttr()));
+                                                 Proto->getNoReturnAttr(),
+                                                 Proto->getCallConv()));
   }
 
   return false;
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp      (revision 91549)
+++ lib/AST/ASTContext.cpp      (working copy)
@@ -1222,7 +1222,8 @@
       return T;
     
     if (const FunctionNoProtoType *FNPT = dyn_cast<FunctionNoProtoType>(F)) {
-      ResultType = getFunctionNoProtoType(FNPT->getResultType(), AddNoReturn);
+      ResultType = getFunctionNoProtoType(FNPT->getResultType(), AddNoReturn,
+                                          FNPT->getCallConv());
     } else {
       const FunctionProtoType *FPT = cast<FunctionProtoType>(F);
       ResultType
@@ -1231,7 +1232,7 @@
                           FPT->getTypeQuals(),
                           FPT->hasExceptionSpec(), FPT->hasAnyExceptionSpec(),
                           FPT->getNumExceptions(), FPT->exception_begin(), 
-                          AddNoReturn);
+                          AddNoReturn, FPT->getCallConv());
     }
   } else
     return T;
@@ -1239,6 +1240,38 @@
   return getQualifiedType(ResultType, T.getLocalQualifiers());
 }
 
+QualType ASTContext::getCallConvType(QualType T, unsigned CallConv) {
+  QualType ResultType;
+  if (const PointerType *Pointer = T->getAs<PointerType>()) {
+    QualType Pointee = Pointer->getPointeeType();
+    ResultType = getCallConvType(Pointee, CallConv);
+    if (ResultType == Pointee)
+      return T;
+
+    ResultType = getPointerType(ResultType);
+  } else if (const FunctionType *F = T->getAs<FunctionType>()) {
+    if (F->getCallConv() == CallConv)
+      return T;
+
+    if (const FunctionNoProtoType *FNPT = dyn_cast<FunctionNoProtoType>(F)) {
+      ResultType = getFunctionNoProtoType(FNPT->getResultType(),
+                                          FNPT->getNoReturn(), CallConv);
+    } else {
+      const FunctionProtoType *FPT = cast<FunctionProtoType>(F);
+      ResultType
+        = getFunctionType(FPT->getResultType(), FPT->arg_type_begin(),
+                          FPT->getNumArgs(), FPT->isVariadic(),
+                          FPT->getTypeQuals(),
+                          FPT->hasExceptionSpec(), FPT->hasAnyExceptionSpec(),
+                          FPT->getNumExceptions(), FPT->exception_begin(),
+                          FPT->getNoReturn(), CallConv);
+    }
+  } else
+    return T;
+
+  return getQualifiedType(ResultType, T.getLocalQualifiers());
+}
+
 /// getComplexType - Return the uniqued reference to the type for a complex
 /// number with the specified element type.
 QualType ASTContext::getComplexType(QualType T) {
@@ -1690,7 +1723,8 @@
 
 /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
 ///
-QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool NoReturn) {
+QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool NoReturn,
+                                            unsigned CallConv) {
   // Unique functions, to guarantee there is only one function of a particular
   // structure.
   llvm::FoldingSetNodeID ID;
@@ -1703,7 +1737,8 @@
 
   QualType Canonical;
   if (!ResultTy.isCanonical()) {
-    Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy), NoReturn);
+    Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy), NoReturn,
+                                       CallConv);
 
     // Get the new insert position for the node we care about.
     FunctionNoProtoType *NewIP =
@@ -1724,7 +1759,8 @@
                                      unsigned NumArgs, bool isVariadic,
                                      unsigned TypeQuals, bool hasExceptionSpec,
                                      bool hasAnyExceptionSpec, unsigned NumExs,
-                                     const QualType *ExArray, bool NoReturn) {
+                                     const QualType *ExArray, bool NoReturn,
+                                     unsigned CallConv) {
   // Unique functions, to guarantee there is only one function of a particular
   // structure.
   llvm::FoldingSetNodeID ID;
@@ -1755,7 +1791,7 @@
     Canonical = getFunctionType(getCanonicalType(ResultTy),
                                 CanonicalArgs.data(), NumArgs,
                                 isVariadic, TypeQuals, false,
-                                false, 0, 0, NoReturn);
+                                false, 0, 0, NoReturn, CallConv);
 
     // Get the new insert position for the node we care about.
     FunctionProtoType *NewIP =
@@ -1772,7 +1808,7 @@
                                  NumExs*sizeof(QualType), TypeAlignment);
   new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, isVariadic,
                               TypeQuals, hasExceptionSpec, hasAnyExceptionSpec,
-                              ExArray, NumExs, Canonical, NoReturn);
+                              ExArray, NumExs, Canonical, NoReturn, CallConv);
   Types.push_back(FTP);
   FunctionProtoTypes.InsertNode(FTP, InsertPos);
   return QualType(FTP, 0);
@@ -4213,6 +4249,11 @@
     allLTypes = false;
   if (NoReturn != rbase->getNoReturnAttr())
     allRTypes = false;
+  unsigned lcc = lbase->getCallConv();
+  unsigned rcc = rbase->getCallConv();
+  // Compatible functions must have the same calling convention
+  if((lcc == 0 || rcc != 0) && lcc != rcc)
+    return QualType();
 
   if (lproto && rproto) { // two C99 style function prototypes
     assert(!lproto->hasExceptionSpec() && !rproto->hasExceptionSpec() &&
@@ -4248,7 +4289,7 @@
     if (allRTypes) return rhs;
     return getFunctionType(retType, types.begin(), types.size(),
                            lproto->isVariadic(), lproto->getTypeQuals(),
-                           NoReturn);
+                           NoReturn, lcc);
   }
 
   if (lproto) allRTypes = false;
@@ -4275,12 +4316,12 @@
     if (allRTypes) return rhs;
     return getFunctionType(retType, proto->arg_type_begin(),
                            proto->getNumArgs(), proto->isVariadic(),
-                           proto->getTypeQuals(), NoReturn);
+                           proto->getTypeQuals(), NoReturn, lcc);
   }
 
   if (allLTypes) return lhs;
   if (allRTypes) return rhs;
-  return getFunctionNoProtoType(retType, NoReturn);
+  return getFunctionNoProtoType(retType, NoReturn, lcc);
 }
 
 QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to