Implement -fms-extensions. This allows us to fuzzy parse non-standard MS constructs used in "windows.h".


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46838 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Parse/ParseDecl.cpp b/Parse/ParseDecl.cpp
index 91e77b9..902c523 100644
--- a/Parse/ParseDecl.cpp
+++ b/Parse/ParseDecl.cpp
@@ -36,6 +36,48 @@
   return Actions.ActOnTypeName(CurScope, DeclaratorInfo).Val;
 }
 
+/// FuzzyParseMicrosoftDeclspec. The following construct is Microsoft's
+/// equivalent of GCC's __attribute__. The grammar below is taken from 
+/// Microsoft's website. Unfortunately, it is incomplete. FIXME: If/when we 
+/// parse this for real, we will need to get a real/current grammar.
+///
+///  decl-specifier:
+///    '__declspec' '(' extended-decl-modifier-seq ')'
+///  
+///  extended-decl-modifier-seq:
+///    extended-decl-modifier opt
+///    extended-decl-modifier extended-decl-modifier-seq
+///
+///  extended-decl-modifier:
+///    align( # )
+///    allocate(" segname ")
+///    appdomain
+///    deprecated
+///    dllimport
+///    dllexport
+///    jitintrinsic
+///    naked
+///    noalias
+///    noinline
+///    noreturn
+///    nothrow
+///    novtable
+///    process
+///    property({get=get_func_name|,put=put_func_name})
+///    restrict
+///    selectany
+///    thread
+///    uuid(" ComObjectGUID ")
+///
+void Parser::FuzzyParseMicrosoftDeclspec() {
+  assert(Tok.is(tok::kw___declspec) && "Not an declspec!");
+  ConsumeToken();
+  do {
+    ConsumeAnyToken();
+  } while (ParenCount > 0 && Tok.isNot(tok::eof));
+  return;
+}
+
 /// ParseAttributes - Parse a non-empty attributes list.
 ///
 /// [GNU] attributes:
@@ -441,6 +483,15 @@
     case tok::kw_typedef:
       isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec);
       break;
+    case tok::kw___w64: // ignore Microsoft specifier
+      break;
+    case tok::kw___declspec:
+      FuzzyParseMicrosoftDeclspec();
+      // Don't consume the next token, __declspec's can appear one after
+      // another. For example:
+      //   __declspec(deprecated("comment1")) 
+      //   __declspec(deprecated("comment2")) extern unsigned int _winmajor;
+      continue;
     case tok::kw_extern:
       if (DS.isThreadSpecified())
         Diag(Tok, diag::ext_thread_before, "extern");
@@ -465,9 +516,11 @@
       break;
       
     // type-specifiers
+    case tok::kw___int16:
     case tok::kw_short:
       isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec);
       break;
+    case tok::kw___int64:
     case tok::kw_long:
       if (DS.getTypeSpecWidth() != DeclSpec::TSW_long)
         isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec);
@@ -489,9 +542,11 @@
     case tok::kw_void:
       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec);
       break;
+    case tok::kw___int8:
     case tok::kw_char:
       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec);
       break;
+    case tok::kw___int32:
     case tok::kw_int:
       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec);
       break;
@@ -625,6 +680,9 @@
     Tok.is(tok::kw_union) ? DeclSpec::TST_union : DeclSpec::TST_struct;
   SourceLocation StartLoc = ConsumeToken();
 
+  if (getLang().Microsoft && Tok.is(tok::kw___declspec))
+    FuzzyParseMicrosoftDeclspec();
+  
   // Parse the tag portion of this.
   DeclTy *TagDecl;
   if (ParseTag(TagDecl, TagType, StartLoc))
@@ -671,7 +729,8 @@
   
   // If there are no declarators, issue a warning.
   if (Tok.is(tok::semi)) {
-    Diag(SpecQualLoc, diag::w_no_declarators);
+    if (!getLang().Microsoft) // MS allows unnamed struct/union fields.
+      Diag(SpecQualLoc, diag::w_no_declarators);
     return;
   }