Diagnose the use of 'fastcall' on functions without prototypes or with
varargs prototypes.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86001 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index a3f8eb5..18f57da 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1032,6 +1032,22 @@
   d->addAttr(::new (S.Context) StdCallAttr());
 }
 
+/// Diagnose the use of a non-standard calling convention on the given
+/// function.
+static void DiagnoseCConv(FunctionDecl *D, const char *CConv,
+                          SourceLocation Loc, Sema &S) {
+  if (!D->hasPrototype()) {
+    S.Diag(Loc, diag::err_cconv_knr) << CConv;
+    return;
+  }
+
+  const FunctionProtoType *T = D->getType()->getAs<FunctionProtoType>();
+  if (T->isVariadic()) {
+    S.Diag(Loc, diag::err_cconv_varargs) << CConv;
+    return;
+  }
+}
+
 static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
   // Attribute has no arguments.
   if (Attr.getNumArgs() != 0) {
@@ -1045,6 +1061,8 @@
     return;
   }
 
+  DiagnoseCConv(cast<FunctionDecl>(d), "fastcall", Attr.getLoc(), S);
+
   // stdcall and fastcall attributes are mutually incompatible.
   if (d->getAttr<StdCallAttr>()) {
     S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)