Index: lib/AST/MicrosoftCXXABI.cpp
===================================================================
--- lib/AST/MicrosoftCXXABI.cpp	(revision 178252)
+++ lib/AST/MicrosoftCXXABI.cpp	(working copy)
@@ -36,6 +36,21 @@
       return CC_C;
   }
 
+  bool isCallingConvAllowed(bool isVariadic, bool isMethod, bool isStatic,
+                            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 can not have __thiscall.
+    if (!isMethod && CC == CC_X86ThisCall)
+      return false;
+    // Static member functions can not have __thiscall.
+    if (isMethod && isStatic && CC == CC_X86ThisCall)
+      return false;
+
+    return true;
+  }
+
   bool isNearlyEmpty(const CXXRecordDecl *RD) const {
     // FIXME: Audit the corners
     if (!RD->isDynamicClass())
Index: lib/AST/CXXABI.h
===================================================================
--- lib/AST/CXXABI.h	(revision 178252)
+++ 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 isMethod, 
+                                    bool isStatic, 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 178252)
+++ lib/AST/ASTContext.cpp	(working copy)
@@ -7754,6 +7754,14 @@
   return CC;
 }
 
+bool ASTContext::isCallConvAllowed(bool isVariadic, bool isMethod, 
+                                   bool isStatic, CallingConv CC) const {
+  // Pass through to the C++ ABI object.
+  if (!ABI)
+    return true;
+  return ABI->isCallingConvAllowed(isVariadic, isMethod, isStatic, CC);
+}
+
 bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const {
   // Pass through to the C++ ABI object
   return ABI->isNearlyEmpty(RD);
@@ -7774,6 +7782,13 @@
 
 CXXABI::~CXXABI() {}
 
+bool CXXABI::isCallingConvAllowed(bool isVariadic, bool isMethod, 
+                                  bool isStatic, 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/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp	(revision 178252)
+++ lib/Sema/SemaDecl.cpp	(working copy)
@@ -4403,6 +4403,56 @@
          diag::err_noreturn_non_function);
 }
 
+/// \brief Check that function prototype has proper calling convention in the
+/// current ABI.  Emit diagnostic at \c Loc if not.
+/// \returns \c true if type has illegal calling convention.
+static bool CheckFunctionCallConv(const FunctionProtoType *ProtoType,
+                         SourceLocation Loc, bool IsCXXMethodPointer, 
+                                        bool IsStatic, Sema &SemaRef) {
+  if (!ProtoType)
+    return false;
+
+  CallingConv CC = ProtoType->getExtInfo().getCC();
+  bool IsVariadic = ProtoType->isVariadic();
+  bool CCAllowed = SemaRef.Context.isCallConvAllowed(IsVariadic,
+      IsCXXMethodPointer, IsStatic, CC);
+  if (!CCAllowed) {
+    SemaRef.Diag(Loc, diag::err_illegal_cconv)
+      << IsVariadic << IsStatic << IsCXXMethodPointer
+      << FunctionType::getNameForCallConv(CC);
+    return true;
+  }                   
+  return false;
+}
+
+/// \brief Check that function prototype contained in type T has proper calling
+/// convention.  If the type T is not a function prototype, not a pointer to
+/// f unction or member function and not a reference to function, do nothing.
+/// \returns \c true if T contains a function type with illegal CC.
+static bool 
+CheckFunctionTypeCallConv(QualType T, SourceLocation Loc, Sema &SemaRef) {
+  const FunctionProtoType *ProtoType = NULL;
+  bool IsMethod = false;
+  if (T->isFunctionProtoType())
+    ProtoType = T->getAs<FunctionProtoType>();
+  else if (T->isFunctionPointerType())
+    ProtoType = T->getPointeeType()->getAs<FunctionProtoType>();
+  else if (T->isReferenceType()) {
+    QualType RefType = T->getAs<ReferenceType>()->getPointeeType();
+    ProtoType = RefType->getAs<FunctionProtoType>();
+  } else if (T->isMemberFunctionPointerType()) {
+    QualType PointerType = T->getAs<MemberPointerType>()->getPointeeType();
+    ProtoType = PointerType->getAs<FunctionProtoType>();
+    IsMethod = true;
+  } else
+    return false;
+
+  // One cannot declare a pointer to a static member function so IsStatic is
+  // irrelevant here.
+  return CheckFunctionCallConv(ProtoType, Loc, IsMethod, 
+                               /*IsStatic=*/false, SemaRef);
+}
+
 NamedDecl*
 Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                              TypeSourceInfo *TInfo, LookupResult &Previous) {
@@ -4438,6 +4488,10 @@
 
   CheckTypedefForVariablyModifiedType(S, NewTD);
 
+  QualType T = TInfo->getType();
+  if (CheckFunctionTypeCallConv(T, NewTD->getLocation(), *this))
+    NewTD->setInvalidDecl();
+
   bool Redeclaration = D.isRedeclaration();
   NamedDecl *ND = ActOnTypedefNameDecl(S, DC, NewTD, Previous, Redeclaration);
   D.setRedeclaration(Redeclaration);
@@ -5244,6 +5298,11 @@
     return false;
   }
 
+  // Declarations of pointer or reference to function or CXX member function
+  // should have proper calling conventions specifiers.
+  if (CheckFunctionTypeCallConv(T, NewVD->getLocation(), *this))
+    NewVD->setInvalidDecl();
+
   if (!Previous.empty()) {
     MergeVarDecl(NewVD, Previous);
     return true;
@@ -6748,6 +6807,15 @@
   }
 
   // Semantic checking for this function declaration (in isolation).
+  const bool IsCXXMethod = isa<CXXMethodDecl>(NewFD);
+  const bool IsStatic = NewFD->getStorageClass() == SC_Static;
+  const FunctionProtoType *ProtoType = 
+      NewFD->getType()->getAs<FunctionProtoType>();
+  // Do not allow function declaration with wrong calling convention.
+  if (CheckFunctionCallConv(ProtoType, NewFD->getLocation(), IsCXXMethod,
+                            IsStatic, *this))
+    NewFD->setInvalidDecl();
+
   if (getLangOpts().CPlusPlus) {
     // C++-specific checks.
     if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
@@ -8398,6 +8466,9 @@
     New->setInvalidDecl();
   }   
 
+  if (CheckFunctionTypeCallConv(T, StartLoc, *this))
+    New->setInvalidDecl();
+
   return New;
 }
 
Index: test/SemaCXX/decl-microsoft-call-conv.cpp
===================================================================
--- test/SemaCXX/decl-microsoft-call-conv.cpp	(revision 178252)
+++ 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/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h	(revision 178252)
+++ 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 isMethod, bool isStatic,
+                         CallingConv CC) const;
+
   /// \brief Retrieves the "canonical" template name that refers to a
   /// given template.
   ///
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td	(revision 178252)
+++ include/clang/Basic/DiagnosticSemaKinds.td	(working copy)
@@ -1916,6 +1916,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">;
