Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp	(revision 179059)
+++ lib/Sema/SemaDeclAttr.cpp	(working copy)
@@ -59,13 +59,22 @@
 //  Helper functions
 //===----------------------------------------------------------------------===//
 
-static const FunctionType *getFunctionType(const Decl *D,
-                                           bool blocksToo = true) {
+/// Get function underlying function type for value or typedef name declaration
+/// and determine whether the function is static or is a C++ method.
+static const FunctionType *getFunctionTypeWithProps(const Decl *D,
+                                                    bool &IsStatic,
+                                                    bool &IsCXXMethod,
+                                                    bool blocksToo = true) {
+  if (!D)
+    return 0;
+
+  const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+  IsStatic = FD && FD->getStorageClass() == SC_Static;
+  IsCXXMethod = FD && isa<CXXMethodDecl>(FD);
+
   QualType Ty;
   if (const ValueDecl *decl = dyn_cast<ValueDecl>(D))
     Ty = decl->getType();
-  else if (const FieldDecl *decl = dyn_cast<FieldDecl>(D))
-    Ty = decl->getType();
   else if (const TypedefNameDecl* decl = dyn_cast<TypedefNameDecl>(D))
     Ty = decl->getUnderlyingType();
   else
@@ -75,10 +84,22 @@
     Ty = Ty->getAs<PointerType>()->getPointeeType();
   else if (blocksToo && Ty->isBlockPointerType())
     Ty = Ty->getAs<BlockPointerType>()->getPointeeType();
+  else if (Ty->isReferenceType())
+    Ty = Ty->getAs<ReferenceType>()->getPointeeType();
+  else if (Ty->isMemberFunctionPointerType()) {
+    Ty = Ty->getAs<MemberPointerType>()->getPointeeType();
+    IsCXXMethod = true;
+  }
 
   return Ty->getAs<FunctionType>();
 }
 
+static const FunctionType *getFunctionType(const Decl *D,
+                                           bool blocksToo = true) {
+  bool IsStatic, IsCXXMethod;
+  return getFunctionTypeWithProps(D, IsStatic, IsCXXMethod, blocksToo);
+}
+
 // FIXME: We should provide an abstraction around a method or function
 // to provide the following bits of information.
 
@@ -3919,16 +3940,45 @@
                            Attr.getAttributeSpellingListIndex()));
 }
 
+static bool CheckFunctionCallingConv(const Decl *D, SourceLocation Loc,
+                                     CallingConv CC, Sema &SemaRef) {
+  if (!D)
+    return false;
+
+  bool IsCXXMethod = false;
+  bool IsStatic = false;
+  const FunctionType *FTy =
+      getFunctionTypeWithProps(D, IsStatic, IsCXXMethod, /*blocksToo=*/false);
+  if (!FTy)
+    return false;
+
+  const FunctionProtoType *ProtoType = FTy->getAs<FunctionProtoType>();
+  bool IsVariadic = ProtoType && ProtoType->isVariadic();
+  bool CCAllowed = SemaRef.Context.isCallConvAllowed(IsVariadic,
+      IsCXXMethod && !IsStatic, CC);
+  if (!CCAllowed) {
+    SemaRef.Diag(Loc, diag::err_illegal_cconv)
+      << IsVariadic << IsStatic << IsCXXMethod
+      << FunctionType::getNameForCallConv(CC);
+    return true;
+  }
+  return false;
+}
+
 static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {
-  if (hasDeclarator(D)) return;
-
-  const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
   // Diagnostic is emitted elsewhere: here we store the (valid) Attr
   // in the Decl node for syntactic reasoning, e.g., pretty-printing.
   CallingConv CC;
-  if (S.CheckCallingConvAttr(Attr, CC, FD))
+  if (S.CheckCallingConvAttr(Attr, CC, D))
     return;
 
+  if (CheckFunctionCallingConv(D, Attr.getLoc(), CC, S)) {
+    Attr.setInvalid();
+  }
+
+  if (hasDeclarator(D))
+    return;
+
   if (!isa<ObjCMethodDecl>(D)) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
       << Attr.getName() << ExpectedFunctionOrMethod;
@@ -4017,12 +4067,15 @@
 }
 
 bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, 
-                                const FunctionDecl *FD) {
+                                const Decl *D) {
   if (attr.isInvalid())
     return true;
 
+  // Diagnostics are emitted only if declarator is present to avoid duplicates.
+  bool HasDeclarator = D && hasDeclarator(D);
+
   unsigned ReqArgs = attr.getKind() == AttributeList::AT_Pcs ? 1 : 0;
-  if (attr.getNumArgs() != ReqArgs || attr.getParameterName()) {
+  if (!HasDeclarator && (attr.getNumArgs() != ReqArgs || attr.getParameterName())) {
     Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << ReqArgs;
     attr.setInvalid();
     return true;
@@ -4039,7 +4092,7 @@
   case AttributeList::AT_Pcs: {
     Expr *Arg = attr.getArg(0);
     StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
-    if (!Str || !Str->isAscii()) {
+    if (!HasDeclarator && (!Str || !Str->isAscii())) {
       Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string)
         << "pcs" << 1;
       attr.setInvalid();
@@ -4055,6 +4108,9 @@
       break;
     }
 
+    if (HasDeclarator)
+      break;
+
     attr.setInvalid();
     Diag(attr.getLoc(), diag::err_invalid_pcs);
     return true;
@@ -4064,6 +4120,10 @@
   default: llvm_unreachable("unexpected attribute kind");
   }
 
+  if (HasDeclarator)
+    return false;
+
+  const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
   const TargetInfo &TI = Context.getTargetInfo();
   TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC);
   if (A == TargetInfo::CCCR_Warning) {
Index: lib/AST/CXXABI.h
===================================================================
--- lib/AST/CXXABI.h	(revision 179059)
+++ lib/AST/CXXABI.h	(working copy)
@@ -34,6 +34,11 @@
   /// Returns the default calling convention for C++ methods.
   virtual CallingConv getDefaultMethodCallConv(bool isVariadic) const = 0;
 
+  /// Returns \c true if the calling convention is allowed for the specified
+  /// combination of function properties.
+  virtual bool isCallingConvAllowed(bool isVariadic, bool isInstanceMethod,
+                                    CallingConv CC) const;
+
   // Returns whether the given class is nearly empty, with just virtual pointers
   // and no data except possibly virtual bases.
   virtual bool isNearlyEmpty(const CXXRecordDecl *RD) const = 0;
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp	(revision 179059)
+++ lib/AST/ASTContext.cpp	(working copy)
@@ -7759,6 +7759,14 @@
   return CC;
 }
 
+bool ASTContext::isCallConvAllowed(bool isVariadic, bool isInstanceMethod,
+                                   CallingConv CC) const {
+  // Pass through to the C++ ABI object.
+  if (!ABI)
+    return true;
+  return ABI->isCallingConvAllowed(isVariadic, isInstanceMethod, CC);
+}
+
 bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const {
   // Pass through to the C++ ABI object
   return ABI->isNearlyEmpty(RD);
@@ -7779,6 +7787,13 @@
 
 CXXABI::~CXXABI() {}
 
+bool CXXABI::isCallingConvAllowed(bool isVariadic, bool isInstanceMethod,
+                                  CallingConv CC) const {
+  // Assume any calling convention is allowed if the specific ABI doesn't
+  // override it.
+  return true;
+}
+
 size_t ASTContext::getSideTableAllocatedMemory() const {
   return ASTRecordLayouts.getMemorySize()
     + llvm::capacity_in_bytes(ObjCLayouts)
Index: lib/AST/MicrosoftCXXABI.cpp
===================================================================
--- lib/AST/MicrosoftCXXABI.cpp	(revision 179059)
+++ lib/AST/MicrosoftCXXABI.cpp	(working copy)
@@ -38,6 +38,18 @@
     return CC_C;
   }
 
+  bool isCallingConvAllowed(bool isVariadic, bool isInstanceMethod,
+                            CallingConv CC) const {
+    // Variadic functions can only have __cdecl which is the default CC.
+    if (isVariadic && CC != CC_C && CC != CC_Default)
+      return false;
+    // Free functions and static methods can not have __thiscall.
+    if (!isInstanceMethod && CC == CC_X86ThisCall)
+      return false;
+
+    return true;
+  }
+
   bool isNearlyEmpty(const CXXRecordDecl *RD) const {
     // FIXME: Audit the corners
     if (!RD->isDynamicClass())
Index: test/SemaCXX/decl-microsoft-call-conv.cpp
===================================================================
--- test/SemaCXX/decl-microsoft-call-conv.cpp	(revision 179059)
+++ test/SemaCXX/decl-microsoft-call-conv.cpp	(working copy)
@@ -26,7 +26,7 @@
 void __fastcall free_func_default(int);
 void __cdecl    free_func_default(int *);
 
-void __thiscall free_func_cdecl(char *);
+void __stdcall  free_func_cdecl(char *);
 void __cdecl    free_func_cdecl(double);
 
 
@@ -84,3 +84,109 @@
   (void)x;
 }
 
+// Illegal calling conventions in free functions.
+void            free_f_default();
+void __cdecl    free_f_cdecl();
+void __stdcall  free_f_stdcall();
+void __thiscall free_f_thiscall(); // expected-error {{non-member function cannot use thiscall calling convention}}
+void __fastcall free_f_fastcall();
+
+void            variadic_f_default(int, ...);
+void __cdecl    variadic_f_cdecl(int, ...);
+void __stdcall  variadic_f_stdcall(int, ...); // expected-error {{variadic non-member function cannot use stdcall calling convention}}
+void __thiscall variadic_f_thiscall(int, ...); // expected-error {{variadic non-member function cannot use thiscall calling convention}}
+void __fastcall variadic_f_fastcall(int, ...); // expected-error {{variadic function cannot use fastcall calling convention}}
+
+// Illegal calling conventions in member functions.
+class C {
+public:
+  void            member_default();
+  void __cdecl    member_cdecl();
+  void __stdcall  member_stdcall();
+  void __thiscall member_thiscall();
+  void __fastcall member_fastcall();
+
+  void            member_variadic_default(int, ...);
+  void __cdecl    member_variadic_cdecl(int, ...);
+  void __stdcall  member_variadic_stdcall(int, ...);// expected-error {{variadic member function cannot use stdcall calling convention}}
+  void __thiscall member_variadic_thiscall(int, ...); // expected-error {{variadic member function cannot use thiscall calling convention}}
+  void __fastcall member_variadic_fastcall(int, ...); // expected-error {{variadic function cannot use fastcall calling convention}}
+
+  static void            static_default();
+  static void __cdecl    static_cdecl();
+  static void __stdcall  static_stdcall();
+  static void __thiscall static_thiscall(); // expected-error {{static member function cannot use thiscall calling convention}}
+  static void __fastcall static_fastcall();
+
+  static void            static_variadic_default(int, ...);
+  static void __cdecl    static_variadic_cdecl(int, ...);
+  static void __stdcall  static_variadic_stdcall(int, ...);// expected-error {{variadic static member function cannot use stdcall calling convention}}
+  static void __thiscall static_variadic_thiscall(int, ...); // expected-error {{variadic static member function cannot use thiscall calling convention}}
+  static void __fastcall static_variadic_fastcall(int, ...); // expected-error {{variadic function cannot use fastcall calling convention}}
+};
+
+// Illegal calling conventions in pointer-to-function declarations.
+void (__cdecl    *cdecl_ptr)();
+void (__stdcall  *stdcall_ptr)();
+void (__thiscall *thiscall_ptr)(); // expected-error {{non-member function cannot use thiscall calling convention}}
+void (__fastcall *fastcall_ptr)();
+
+void (__cdecl    *cdecl_variadic_ptr)(int, ...);
+void (__stdcall  *stdcall_variadic_ptr)(int, ...); // expected-error {{variadic non-member function cannot use stdcall calling convention}}
+void (__thiscall *thiscall_variadic_ptr)(int, ...); // expected-error {{variadic non-member function cannot use thiscall calling convention}}
+void (__fastcall *fastcall_variadic_ptr)(int, ...); // expected-error {{variadic function cannot use fastcall calling convention}}
+
+// Illegal calling convention in reference-to-function declarations.
+void (__cdecl    &cdecl_ref)() = free_f_cdecl;
+void (__stdcall  &stdcall_ref)() = free_f_stdcall;
+void (__thiscall &thiscall_ref)() = free_f_thiscall; // expected-error {{non-member function cannot use thiscall calling convention}}
+void (__fastcall &fastcall_ref)() = free_f_fastcall;
+
+void (__cdecl    &cdecl_variadic_ref)(int, ...) = variadic_f_cdecl;
+void (__stdcall  &stdcall_variadic_ref)(int, ...) = variadic_f_stdcall; // expected-error {{variadic non-member function cannot use stdcall calling convention}}
+void (__thiscall &thiscall_variadic_ref)(int, ...) = variadic_f_thiscall; // expected-error {{variadic non-member function cannot use thiscall calling convention}}
+void (__fastcall &fastcall_variadic_ref)(int, ...) = variadic_f_fastcall; // expected-error {{variadic function cannot use fastcall calling convention}}
+
+// Illegal calling convention in pointer-to-member-function declarations.
+void (__cdecl    C::*cdecl_mem_ptr)();
+void (__stdcall  C::*stdcall_mem_ptr)();
+void (__thiscall C::*thiscall_mem_ptr)();
+void (__fastcall C::*fastcall_mem_ptr)();
+
+void (__cdecl    C::*cdecl_variadic_mem_ptr)(int, ...);
+void (__stdcall  C::*stdcall_variadic_mem_ptr)(int, ...); // expected-error {{variadic member function cannot use stdcall calling convention}}
+void (__thiscall C::*thiscall_variadic_mem_ptr)(int, ...); // expected-error {{variadic member function cannot use thiscall calling convention}}
+void (__fastcall C::*fastcall_variadic_mem_ptr)(int, ...); // expected-error {{variadic function cannot use fastcall calling convention}}
+
+// Illegal calling convention in function arguments.
+void cb1( void (__stdcall  *)() );
+void cb2( void (__thiscall *)() ); // expected-error {{non-member function cannot use thiscall calling convention}}
+void cb3( void (__stdcall  *)(int, ...) ); // expected-error {{variadic non-member function cannot use stdcall calling convention}}
+void cb4( void (__fastcall C::*)() );
+void cb5( void (__fastcall C::*)(int, ...) ); // expected-error {{variadic function cannot use fastcall calling convention}}
+void cb6( void (__cdecl    &)() );
+void cb7( void (__thiscall &)() ); // expected-error {{non-member function cannot use thiscall calling convention}}
+
+// Illegal calling convention in typedefs.
+typedef void (__stdcall  *stdcall_t)();
+typedef void (__thiscall *thiscall_t)(); // expected-error {{non-member function cannot use thiscall calling convention}}
+typedef void (__thiscall C::*thiscall_mem_t)();
+typedef void (__stdcall  *stdcall_variadic_t)(int, ...); // expected-error {{variadic non-member function cannot use stdcall calling convention}}
+typedef void (__thiscall C::*thiscall_variadic_mem_t)(int, ...); // expected-error {{variadic member function cannot use thiscall calling convention}}
+
+// Illegal calling convention in templates.
+template <typename T>
+void __thiscall temp_thiscall(T t) {} // expected-error {{non-member function cannot use thiscall calling convention}}
+
+template <typename T>
+void __stdcall temp_variadic_stdcall(T t, ...) {} // expected-error {{variadic non-member function cannot use stdcall calling convention}}
+
+template <typename T>
+struct CT {
+  void __stdcall temp_memb_variadic_stdcall(T t, ...); // expected-error {{variadic member function cannot use stdcall calling convention}}
+  static void __thiscall temp_static_memb_thiscall(T t); // expected-error {{static member function cannot use thiscall calling convention}}
+
+  template <typename U>
+  void __stdcall temp_temp_memb_variadic_stdcall(U u, T t, ...); // expected-error {{variadic member function cannot use stdcall calling convention}}
+};
+
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td	(revision 179059)
+++ include/clang/Basic/DiagnosticSemaKinds.td	(working copy)
@@ -1918,6 +1918,9 @@
   "function with no prototype cannot use %0 calling convention">;
 def err_cconv_varargs : Error<
   "variadic function cannot use %0 calling convention">;
+def err_illegal_cconv : Error<
+  "%select{|variadic }0%select{|static }1%select{non-member|member}2 function "
+  "cannot use %3 calling convention">;
 def err_regparm_mismatch : Error<"function declared with regparm(%0) "
   "attribute was previously declared "
   "%plural{0:without the regparm|:with the regparm(%1)}1 attribute">;
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h	(revision 179059)
+++ include/clang/Sema/Sema.h	(working copy)
@@ -2389,7 +2389,7 @@
 
   bool CheckRegparmAttr(const AttributeList &attr, unsigned &value);
   bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, 
-                            const FunctionDecl *FD = 0);
+                            const Decl *D = 0);
   bool CheckNoReturnAttr(const AttributeList &attr);
   void CheckAlignasUnderalignment(Decl *D);
 
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h	(revision 179059)
+++ include/clang/AST/ASTContext.h	(working copy)
@@ -1740,6 +1740,11 @@
     return (getCanonicalCallConv(lcc) == getCanonicalCallConv(rcc));
   }
 
+  /// \brief Checks if the specified calling convention is allowed in the ABI
+  /// for functions with the given combination of properties.
+  bool isCallConvAllowed(bool isVariadic, bool isInstanceMethod,
+                         CallingConv CC) const;
+
   /// \brief Retrieves the "canonical" template name that refers to a
   /// given template.
   ///
