Properly diagnose Microsoft __declspec attributes which have optional argument lists when the arguments are elided. eg)

__declspec(deprecated()) // error
__declspec(deprecated) // OK
__declspec(deprecated("")) // OK

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@206191 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 720a68c..3fa3031 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -394,6 +394,8 @@
     return false;
   }
 
+  SourceLocation OpenParenLoc = Tok.getLocation();
+
   if (AttrName->getName() == "property") {
     // The property declspec is more complex in that it can take one or two
     // assignment expressions as a parameter, but the lhs of the assignment
@@ -507,8 +509,17 @@
     return !HasInvalidAccessor;
   }
 
-  ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr,
-                           SourceLocation(), AttributeList::AS_Declspec);
+  unsigned NumArgs =
+      ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr,
+                               SourceLocation(), AttributeList::AS_Declspec);
+
+  // If this attribute's args were parsed, and it was expected to have
+  // arguments but none were provided, emit a diagnostic.
+  const AttributeList *Attr = Attrs.getList();
+  if (Attr && Attr->getMaxArgs() && !NumArgs) {
+    Diag(OpenParenLoc, diag::err_attribute_requires_arguements) << AttrName;
+    return false;
+  }
   return true;
 }
 
diff --git a/test/Parser/MicrosoftExtensions.c b/test/Parser/MicrosoftExtensions.c
index b9f531f..1998703 100644
--- a/test/Parser/MicrosoftExtensions.c
+++ b/test/Parser/MicrosoftExtensions.c
@@ -102,6 +102,12 @@
 struct __declspec(12) S2 {};	/* expected-error {{__declspec attributes must be an identifier or string literal}} */
 struct __declspec("testing") S3 {}; /* expected-warning {{__declspec attribute '"testing"' is not supported}} */
 
+/* declspecs with arguments cannot have an empty argument list, even if the
+   arguments are optional. */
+__declspec(deprecated()) void dep_func_test(void); /* expected-error {{attribute 'deprecated' requires a nonempty argument list}} */
+__declspec(deprecated) void dep_func_test2(void);
+__declspec(deprecated("")) void dep_func_test3(void);
+
 /* Ensure multiple declspec attributes are supported */
 struct __declspec(align(8) deprecated) S4 {};