Allow calling convention attributes to apply to types.  Patch by Chip Davis!




git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95291 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 9065761..8833792 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1241,7 +1241,7 @@
 
     // See if there are any attributes on this declarator chunk.
     if (const AttributeList *AL = DeclType.getAttrs())
-      ProcessTypeAttributeList(T, AL);
+      ProcessTypeAttributeList(T, AL, true);
   }
 
   if (getLangOptions().CPlusPlus && T->isFunctionType()) {
@@ -1274,7 +1274,10 @@
   // If there were any type attributes applied to the decl itself (not the
   // type, apply the type attribute to the type!)
   if (const AttributeList *Attrs = D.getAttributes())
-    ProcessTypeAttributeList(T, Attrs);
+    ProcessTypeAttributeList(T, Attrs, true);
+  // Also look in the decl spec.
+  if (const AttributeList *Attrs = D.getDeclSpec().getAttributes())
+    ProcessTypeAttributeList(T, Attrs, true, true);
 
   if (TInfo) {
     if (D.isInvalidType())
@@ -1612,6 +1615,36 @@
   Type = S.Context.getAddrSpaceQualType(Type, ASIdx);
 }
 
+/// HandleCDeclTypeAttribute - Process the cdecl attribute on the
+/// specified type.  The attribute contains 0 arguments.
+static void HandleCDeclTypeAttribute(QualType &Type,
+                                     const AttributeList &Attr, Sema &S) {
+  if (Attr.getNumArgs() != 0)
+    return;
+
+  // We only apply this to a pointer to function.
+  if (!Type->isFunctionPointerType()
+      && !Type->isFunctionType())
+    return;
+
+  Type = S.Context.getCallConvType(Type, CC_C);
+}
+
+/// HandleFastCallTypeAttribute - Process the fastcall attribute on the
+/// specified type.  The attribute contains 0 arguments.
+static void HandleFastCallTypeAttribute(QualType &Type,
+                                        const AttributeList &Attr, Sema &S) {
+  if (Attr.getNumArgs() != 0)
+    return;
+
+  // We only apply this to a pointer to function.
+  if (!Type->isFunctionPointerType()
+      && !Type->isFunctionType())
+    return;
+
+  Type = S.Context.getCallConvType(Type, CC_X86FastCall);
+}
+
 /// HandleObjCGCTypeAttribute - Process an objc's gc attribute on the
 /// specified type.  The attribute contains 1 argument, weak or strong.
 static void HandleObjCGCTypeAttribute(QualType &Type,
@@ -1661,6 +1694,21 @@
   Type = S.Context.getNoReturnType(Type);
 }
 
+/// HandleStdCallTypeAttribute - Process the stdcall attribute on the
+/// specified type.  The attribute contains 0 arguments.
+static void HandleStdCallTypeAttribute(QualType &Type,
+                                       const AttributeList &Attr, Sema &S) {
+  if (Attr.getNumArgs() != 0)
+    return;
+
+  // We only apply this to a pointer to function.
+  if (!Type->isFunctionPointerType()
+      && !Type->isFunctionType())
+    return;
+
+  Type = S.Context.getCallConvType(Type, CC_X86StdCall);
+}
+
 /// HandleVectorSizeAttribute - this attribute is only applicable to integral
 /// and float scalars, although arrays, pointers, and function return values are
 /// allowed in conjunction with this construct. Aggregates with this attribute
@@ -1708,7 +1756,12 @@
   CurType = S.Context.getVectorType(CurType, vectorSize/typeSize);
 }
 
-void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL) {
+void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL,
+                                    bool HandleCallConvAttributes,
+                                    bool HandleOnlyCallConv) {
+  if(HandleOnlyCallConv)
+    assert(HandleCallConvAttributes && "Can't not handle call-conv attributes"
+           " while only handling them!");
   // Scan through and apply attributes to this type where it makes sense.  Some
   // attributes (such as __address_space__, __vector_size__, etc) apply to the
   // type, but others can be present in the type specifiers even though they
@@ -1719,16 +1772,32 @@
     switch (AL->getKind()) {
     default: break;
     case AttributeList::AT_address_space:
-      HandleAddressSpaceTypeAttribute(Result, *AL, *this);
+      if (!HandleOnlyCallConv)
+        HandleAddressSpaceTypeAttribute(Result, *AL, *this);
+      break;
+    case AttributeList::AT_cdecl:
+      if (HandleCallConvAttributes)
+        HandleCDeclTypeAttribute(Result, *AL, *this);
+      break;
+    case AttributeList::AT_fastcall:
+      if (HandleCallConvAttributes)
+        HandleFastCallTypeAttribute(Result, *AL, *this);
       break;
     case AttributeList::AT_objc_gc:
-      HandleObjCGCTypeAttribute(Result, *AL, *this);
+      if (!HandleOnlyCallConv)
+        HandleObjCGCTypeAttribute(Result, *AL, *this);
       break;
     case AttributeList::AT_noreturn:
-      HandleNoReturnTypeAttribute(Result, *AL, *this);
+      if (!HandleOnlyCallConv)
+        HandleNoReturnTypeAttribute(Result, *AL, *this);
+      break;
+    case AttributeList::AT_stdcall:
+      if (HandleCallConvAttributes)
+        HandleStdCallTypeAttribute(Result, *AL, *this);
       break;
     case AttributeList::AT_vector_size:
-      HandleVectorSizeAttr(Result, *AL, *this);
+      if (!HandleOnlyCallConv)
+        HandleVectorSizeAttr(Result, *AL, *this);
       break;
     }
   }