Improved MSVC __interface support by adding first class support for it, instead of aliasing to "struct" which had some incorrect behaviour. Patch by David Robins.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@163013 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 42ec6b0..e574011 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1031,12 +1031,14 @@
                                  const ParsedTemplateInfo &TemplateInfo,
                                  AccessSpecifier AS, 
                                  bool EnteringContext, DeclSpecContext DSC) {
-  DeclSpec::TST TagType;
-  if (TagTokKind == tok::kw_struct)
-    TagType = DeclSpec::TST_struct;
-  else if (TagTokKind == tok::kw_class)
-    TagType = DeclSpec::TST_class;
-  else {
+  DeclSpec::TST TagType;

+  if (TagTokKind == tok::kw_struct)

+    TagType = DeclSpec::TST_struct;

+  else if (TagTokKind == tok::kw___interface)

+    TagType = DeclSpec::TST_interface;

+  else if (TagTokKind == tok::kw_class)

+    TagType = DeclSpec::TST_class;

+  else {

     assert(TagTokKind == tok::kw_union && "Not a class specifier");
     TagType = DeclSpec::TST_union;
   }
@@ -1148,13 +1150,14 @@
       }
 
       Diag(NameLoc, diag::err_explicit_spec_non_template)
-        << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
-        << (TagType == DeclSpec::TST_class? 0
-            : TagType == DeclSpec::TST_struct? 1
-            : 2)
-        << Name
-        << SourceRange(LAngleLoc, RAngleLoc);
-
+        << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)

+        << (TagType == DeclSpec::TST_class? 0

+            : TagType == DeclSpec::TST_struct? 1

+            : TagType == DeclSpec::TST_interface? 2

+            : 3)

+        << Name

+        << SourceRange(LAngleLoc, RAngleLoc);

+

       // Strip off the last template parameter list if it was empty, since
       // we've removed its template argument list.
       if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) {
@@ -1240,14 +1243,13 @@
              (Tok.is(tok::semi) ||
               (Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(false)))) {
     TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration;
-    if (Tok.isNot(tok::semi)) {
-      // A semicolon was missing after this declaration. Diagnose and recover.
-      ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
-                       TagType == DeclSpec::TST_class ? "class" :
-                       TagType == DeclSpec::TST_struct ? "struct" : "union");
-      PP.EnterToken(Tok);
-      Tok.setKind(tok::semi);
-    }
+    if (Tok.isNot(tok::semi)) {

+      // A semicolon was missing after this declaration. Diagnose and recover.

+      ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,

+        DeclSpec::getSpecifierName(TagType));

+      PP.EnterToken(Tok);

+      Tok.setKind(tok::semi);

+    }

   } else
     TUK = Sema::TUK_Reference;
 
@@ -1466,14 +1468,13 @@
   // Also enforce C++ [temp]p3:
   //   In a template-declaration which defines a class, no declarator
   //   is permitted.
-  if (TUK == Sema::TUK_Definition &&
-      (TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) {
-    ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
-                     TagType == DeclSpec::TST_class ? "class" :
-                     TagType == DeclSpec::TST_struct ? "struct" : "union");
-    // Push this token back into the preprocessor and change our current token
-    // to ';' so that the rest of the code recovers as though there were an
-    // ';' after the definition.
+  if (TUK == Sema::TUK_Definition &&

+      (TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) {

+    ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,

+      DeclSpec::getSpecifierName(TagType));

+    // Push this token back into the preprocessor and change our current token

+    // to ';' so that the rest of the code recovers as though there were an

+    // ';' after the definition.

     PP.EnterToken(Tok);
     Tok.setKind(tok::semi);
   }
@@ -2236,12 +2237,13 @@
 ///         member-declaration member-specification[opt]
 ///         access-specifier ':' member-specification[opt]
 ///
-void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
-                                         unsigned TagType, Decl *TagDecl) {
-  assert((TagType == DeclSpec::TST_struct ||
-         TagType == DeclSpec::TST_union  ||
-         TagType == DeclSpec::TST_class) && "Invalid TagType!");
-
+void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,

+                                         unsigned TagType, Decl *TagDecl) {

+  assert((TagType == DeclSpec::TST_struct ||

+         TagType == DeclSpec::TST_interface ||

+         TagType == DeclSpec::TST_union  ||

+         TagType == DeclSpec::TST_class) && "Invalid TagType!");

+

   PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, RecordLoc,
                                       "parsing struct/union/class body");