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/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 2f21e4c..c68a16b 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -463,13 +463,14 @@
 }
 
 void CXXRecordDecl::addedMember(Decl *D) {
-  if (!D->isImplicit() &&
-      !isa<FieldDecl>(D) &&
-      !isa<IndirectFieldDecl>(D) &&
-      (!isa<TagDecl>(D) || cast<TagDecl>(D)->getTagKind() == TTK_Class))
-    data().HasOnlyCMembers = false;
-
-  // Ignore friends and invalid declarations.
+  if (!D->isImplicit() &&

+      !isa<FieldDecl>(D) &&

+      !isa<IndirectFieldDecl>(D) &&

+      (!isa<TagDecl>(D) || cast<TagDecl>(D)->getTagKind() == TTK_Class ||

+        cast<TagDecl>(D)->getTagKind() == TTK_Interface))

+    data().HasOnlyCMembers = false;

+

+  // Ignore friends and invalid declarations.

   if (D->getFriendObjectKind() || D->isInvalidDecl())
     return;
   
@@ -933,13 +934,14 @@
     if (Shadow->getDeclName().getNameKind()
           == DeclarationName::CXXConversionFunctionName)
       data().Conversions.addDecl(Shadow, Shadow->getAccess());
-}
-
-bool CXXRecordDecl::isCLike() const {
-  if (getTagKind() == TTK_Class || !TemplateOrInstantiation.isNull())
-    return false;
-  if (!hasDefinition())
-    return true;
+}

+

+bool CXXRecordDecl::isCLike() const {

+  if (getTagKind() == TTK_Class || getTagKind() == TTK_Interface ||

+      !TemplateOrInstantiation.isNull())

+    return false;

+  if (!hasDefinition())

+    return true;

 
   return isPOD() && data().HasOnlyCMembers;
 }
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 982e3ac..f0041b2 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -1270,12 +1270,13 @@
 void MicrosoftCXXNameMangler::mangleType(const TagType *T) {
   switch (T->getDecl()->getTagKind()) {
     case TTK_Union:
-      Out << 'T';
-      break;
-    case TTK_Struct:
-      Out << 'U';
-      break;
-    case TTK_Class:
+      Out << 'T';

+      break;

+    case TTK_Struct:

+    case TTK_Interface:

+      Out << 'U';

+      break;

+    case TTK_Class:

       Out << 'V';
       break;
     case TTK_Enum:
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index d5df63f..043e46e 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -2260,12 +2260,28 @@
   }
   
   // Use the externally-supplied field offset.
-  return ExternalFieldOffset;
-}
-
-void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset,
-                                            uint64_t UnpaddedOffset,
-                                            uint64_t UnpackedOffset,
+  return ExternalFieldOffset;

+}

+

+/// \brief Get diagnostic %select index for tag kind for

+/// field padding diagnostic message.

+/// WARNING: Indexes apply to particular diagnostics only!

+///

+/// \returns diagnostic %select index.

+static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag)

+{

+  switch (Tag) {

+    case TTK_Struct: return 0;

+    case TTK_Interface: return 1;

+    case TTK_Class:  return 2;

+    default: assert("Invalid tag kind for field padding diagnostic!");

+  }

+  return -1;

+}

+

+void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset,

+                                            uint64_t UnpaddedOffset,

+                                            uint64_t UnpackedOffset,

                                             unsigned UnpackedAlign,
                                             bool isPacked,
                                             const FieldDecl *D) {
@@ -2288,20 +2304,20 @@
     if (PadSize % CharBitNum == 0) {
       PadSize = PadSize / CharBitNum;
       InBits = false;
-    }
-    if (D->getIdentifier())
-      Diag(D->getLocation(), diag::warn_padded_struct_field)
-          << (D->getParent()->isStruct() ? 0 : 1) // struct|class
-          << Context.getTypeDeclType(D->getParent())
-          << PadSize
-          << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1) // plural or not
-          << D->getIdentifier();
-    else
-      Diag(D->getLocation(), diag::warn_padded_struct_anon_field)
-          << (D->getParent()->isStruct() ? 0 : 1) // struct|class
-          << Context.getTypeDeclType(D->getParent())
-          << PadSize
-          << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1); // plural or not
+    }

+    if (D->getIdentifier())

+      Diag(D->getLocation(), diag::warn_padded_struct_field)

+          << getPaddingDiagFromTagKind(D->getParent()->getTagKind())

+          << Context.getTypeDeclType(D->getParent())

+          << PadSize

+          << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1) // plural or not

+          << D->getIdentifier();

+    else

+      Diag(D->getLocation(), diag::warn_padded_struct_anon_field)

+          << getPaddingDiagFromTagKind(D->getParent()->getTagKind())

+          << Context.getTypeDeclType(D->getParent())

+          << PadSize

+          << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1); // plural or not

   }
 
   // Warn if we packed it unnecessarily. If the alignment is 1 byte don't
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 7445152..c54250a 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -357,9 +357,15 @@
     return RT->getDecl()->isStruct();
   return false;
 }
+bool Type::isInterfaceType() const {
+  if (const RecordType *RT = getAs<RecordType>())
+    return RT->getDecl()->isInterface();
+  return false;
+}
 bool Type::isStructureOrClassType() const {
   if (const RecordType *RT = getAs<RecordType>())
-    return RT->getDecl()->isStruct() || RT->getDecl()->isClass();
+    return RT->getDecl()->isStruct() || RT->getDecl()->isClass() ||
+      RT->getDecl()->isInterface();
   return false;
 }
 bool Type::isVoidPointerType() const {
@@ -1317,6 +1323,7 @@
   case TST_typename: return ETK_Typename;
   case TST_class: return ETK_Class;
   case TST_struct: return ETK_Struct;
+  case TST_interface: return ETK_Interface;
   case TST_union: return ETK_Union;
   case TST_enum: return ETK_Enum;
   }
@@ -1327,6 +1334,7 @@
   switch(TypeSpec) {
   case TST_class: return TTK_Class;
   case TST_struct: return TTK_Struct;
+  case TST_interface: return TTK_Interface;
   case TST_union: return TTK_Union;
   case TST_enum: return TTK_Enum;
   }
@@ -1339,6 +1347,7 @@
   switch (Kind) {
   case TTK_Class: return ETK_Class;
   case TTK_Struct: return ETK_Struct;
+  case TTK_Interface: return ETK_Interface;
   case TTK_Union: return ETK_Union;
   case TTK_Enum: return ETK_Enum;
   }
@@ -1350,6 +1359,7 @@
   switch (Keyword) {
   case ETK_Class: return TTK_Class;
   case ETK_Struct: return TTK_Struct;
+  case ETK_Interface: return TTK_Interface;
   case ETK_Union: return TTK_Union;
   case ETK_Enum: return TTK_Enum;
   case ETK_None: // Fall through.
@@ -1367,6 +1377,7 @@
     return false;
   case ETK_Class:
   case ETK_Struct:
+  case ETK_Interface:
   case ETK_Union:
   case ETK_Enum:
     return true;
@@ -1381,6 +1392,7 @@
   case ETK_Typename: return "typename";
   case ETK_Class:  return "class";
   case ETK_Struct: return "struct";
+  case ETK_Interface: return "__interface";
   case ETK_Union:  return "union";
   case ETK_Enum:   return "enum";
   }