Index: test/Sema/callingconv.c
===================================================================
--- test/Sema/callingconv.c	(revision 95094)
+++ test/Sema/callingconv.c	(working copy)
@@ -21,3 +21,15 @@
 void __attribute__((cdecl)) ctest0() {}
 
 void __attribute__((cdecl(1))) ctest1(float x) {} // expected-error {{attribute requires 0 argument(s)}}
+
+void (__attribute__((fastcall)) *pfoo)(float*) = foo;
+
+void (__attribute__((stdcall)) *pbar)(float*) = bar;
+
+void (__attribute__((cdecl)) *ptest1)(void) = test1; // expected-warning {{incompatible pointer types}}
+
+void (*pctest0)() = ctest0;
+
+void ctest2() {}
+void (__attribute__((cdecl)) *pctest2)() = ctest2;
+
Index: include/clang/AST/Type.h
===================================================================
--- include/clang/AST/Type.h	(revision 95094)
+++ include/clang/AST/Type.h	(working copy)
@@ -1745,10 +1745,11 @@
   QualType desugar() const { return QualType(this, 0); }
 
   void Profile(llvm::FoldingSetNodeID &ID) {
-    Profile(ID, getResultType(), getNoReturnAttr());
+    Profile(ID, getResultType(), getNoReturnAttr(), getCallConv());
   }
   static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType,
-                      bool NoReturn) {
+                      bool NoReturn, CallingConv CallConv) {
+    ID.AddInteger(CallConv);
     ID.AddInteger(NoReturn);
     ID.AddPointer(ResultType.getAsOpaquePtr());
   }
@@ -1867,7 +1868,7 @@
                       bool isVariadic, unsigned TypeQuals,
                       bool hasExceptionSpec, bool anyExceptionSpec,
                       unsigned NumExceptions, exception_iterator Exs,
-                      bool NoReturn);
+                      bool NoReturn, CallingConv CallConv);
 };
 
 
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp	(revision 95094)
+++ lib/Sema/SemaType.cpp	(working copy)
@@ -1275,6 +1275,9 @@
   // type, apply the type attribute to the type!)
   if (const AttributeList *Attrs = D.getAttributes())
     ProcessTypeAttributeList(T, Attrs);
+  // Also look in the decl spec.
+  if (const AttributeList *Attrs = D.getDeclSpec().getAttributes())
+    ProcessTypeAttributeList(T, Attrs);
 
   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
@@ -1721,12 +1769,21 @@
     case AttributeList::AT_address_space:
       HandleAddressSpaceTypeAttribute(Result, *AL, *this);
       break;
+    case AttributeList::AT_cdecl:
+      HandleCDeclTypeAttribute(Result, *AL, *this);
+      break;
+    case AttributeList::AT_fastcall:
+      HandleFastCallTypeAttribute(Result, *AL, *this);
+      break;
     case AttributeList::AT_objc_gc:
       HandleObjCGCTypeAttribute(Result, *AL, *this);
       break;
     case AttributeList::AT_noreturn:
       HandleNoReturnTypeAttribute(Result, *AL, *this);
       break;
+    case AttributeList::AT_stdcall:
+      HandleStdCallTypeAttribute(Result, *AL, *this);
+      break;
     case AttributeList::AT_vector_size:
       HandleVectorSizeAttr(Result, *AL, *this);
       break;
Index: lib/AST/Type.cpp
===================================================================
--- lib/AST/Type.cpp	(revision 95094)
+++ lib/AST/Type.cpp	(working copy)
@@ -802,7 +802,8 @@
                                 unsigned NumArgs, bool isVariadic,
                                 unsigned TypeQuals, bool hasExceptionSpec,
                                 bool anyExceptionSpec, unsigned NumExceptions,
-                                exception_iterator Exs, bool NoReturn) {
+                                exception_iterator Exs, bool NoReturn,
+                                CallingConv CallConv) {
   ID.AddPointer(Result.getAsOpaquePtr());
   for (unsigned i = 0; i != NumArgs; ++i)
     ID.AddPointer(ArgTys[i].getAsOpaquePtr());
@@ -815,12 +816,14 @@
       ID.AddPointer(Exs[i].getAsOpaquePtr());
   }
   ID.AddInteger(NoReturn);
+  ID.AddInteger(CallConv);
 }
 
 void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID) {
   Profile(ID, getResultType(), arg_type_begin(), NumArgs, isVariadic(),
           getTypeQuals(), hasExceptionSpec(), hasAnyExceptionSpec(),
-          getNumExceptions(), exception_begin(), getNoReturnAttr());
+          getNumExceptions(), exception_begin(), getNoReturnAttr(),
+          getCallConv());
 }
 
 void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID,
Index: lib/AST/TypePrinter.cpp
===================================================================
--- lib/AST/TypePrinter.cpp	(revision 95094)
+++ lib/AST/TypePrinter.cpp	(working copy)
@@ -271,6 +271,19 @@
   
   S += ")";
 
+  switch(T->getCallConv()) {
+  case CC_Default:
+  default: break;
+  case CC_C:
+    S += " __attribute__((cdecl))";
+    break;
+  case CC_X86StdCall:
+    S += " __attribute__((stdcall))";
+    break;
+  case CC_X86FastCall:
+    S += " __attribute__((fastcall))";
+    break;
+  }
   if (T->getNoReturnAttr())
     S += " __attribute__((noreturn))";
 
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp	(revision 95094)
+++ lib/AST/ASTContext.cpp	(working copy)
@@ -1716,7 +1716,7 @@
   // Unique functions, to guarantee there is only one function of a particular
   // structure.
   llvm::FoldingSetNodeID ID;
-  FunctionNoProtoType::Profile(ID, ResultTy, NoReturn);
+  FunctionNoProtoType::Profile(ID, ResultTy, NoReturn, CallConv);
 
   void *InsertPos = 0;
   if (FunctionNoProtoType *FT =
@@ -1755,7 +1755,7 @@
   llvm::FoldingSetNodeID ID;
   FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, isVariadic,
                              TypeQuals, hasExceptionSpec, hasAnyExceptionSpec,
-                             NumExs, ExArray, NoReturn);
+                             NumExs, ExArray, NoReturn, CallConv);
 
   void *InsertPos = 0;
   if (FunctionProtoType *FTP =
