r313364 - Fix the __interface inheritence rules to work better with IUnknown and IDispatch

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 15 09:03:35 PDT 2017


Author: erichkeane
Date: Fri Sep 15 09:03:35 2017
New Revision: 313364

URL: http://llvm.org/viewvc/llvm-project?rev=313364&view=rev
Log:
Fix the __interface inheritence rules to work better with IUnknown and IDispatch

__interface objects in MSVC are permitted to inherit from __interface types, 
and interface-like types.

Additionally, there are two default interface-like types 
(IUnknown and IDispatch) that all interface-like
types must inherit from.

Differential Revision: https://reviews.llvm.org/D37308

Added:
    cfe/trunk/test/SemaCXX/ms-iunknown-inline-def.cpp   (with props)
    cfe/trunk/test/SemaCXX/ms-iunknown-outofline-def.cpp   (with props)
    cfe/trunk/test/SemaCXX/ms-iunknown.cpp   (with props)
Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=313364&r1=313363&r2=313364&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Sep 15 09:03:35 2017
@@ -1831,6 +1831,10 @@ public:
     return getLambdaData().MethodTyInfo;
   }
 
+  // \brief Determine whether this type is an Interface Like type for
+  // __interface inheritence purposes.
+  bool isInterfaceLike() const;
+
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classofKind(Kind K) {
     return K >= firstCXXRecord && K <= lastCXXRecord;

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=313364&r1=313363&r2=313364&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Sep 15 09:03:35 2017
@@ -1470,6 +1470,53 @@ bool CXXRecordDecl::isAnyDestructorNoRet
   return false;
 }
 
+bool CXXRecordDecl::isInterfaceLike() const {
+  assert(hasDefinition() && "checking for interface-like without a definition");
+  // All __interfaces are inheritently interface-like.
+  if (isInterface())
+    return true;
+
+  // Interface-like types cannot have a user declared constructor, destructor,
+  // friends, VBases, conversion functions, or fields.  Additionally, lambdas
+  // cannot be interface types.
+  if (isLambda() || hasUserDeclaredConstructor() ||
+      hasUserDeclaredDestructor() || !field_empty() || hasFriends() ||
+      getNumVBases() > 0 || conversion_end() - conversion_begin() > 0)
+    return false;
+
+  // No interface-like type can have a method with a definition.
+  for (const auto *const Method : methods())
+    if (Method->isDefined())
+      return false;
+
+  // Check "Special" types.
+  const auto *Uuid = getAttr<UuidAttr>();
+  if (Uuid && isStruct() && getDeclContext()->isTranslationUnit() &&
+      ((getName() == "IUnknown" &&
+        Uuid->getGuid() == "00000000-0000-0000-C000-000000000046") ||
+       (getName() == "IDispatch" &&
+        Uuid->getGuid() == "00020400-0000-0000-C000-000000000046"))) {
+    if (getNumBases() > 0)
+      return false;
+    return true;
+  }
+
+  // FIXME: Any access specifiers is supposed to make this no longer interface
+  // like.
+
+  // If this isn't a 'special' type, it must have a single interface-like base.
+  if (getNumBases() != 1)
+    return false;
+
+  const auto BaseSpec = *bases_begin();
+  if (BaseSpec.isVirtual() || BaseSpec.getAccessSpecifier() != AS_public)
+    return false;
+  const auto *Base = BaseSpec.getType()->getAsCXXRecordDecl();
+  if (Base->isInterface() || !Base->isInterfaceLike())
+    return false;
+  return true;
+}
+
 void CXXRecordDecl::completeDefinition() {
   completeDefinition(nullptr);
 }

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=313364&r1=313363&r2=313364&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Sep 15 09:03:35 2017
@@ -2388,7 +2388,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecor
       if (const RecordType *Record = NewBaseType->getAs<RecordType>()) {
         const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
         if (Class->isInterface() &&
-              (!RD->isInterface() ||
+              (!RD->isInterfaceLike() ||
                KnownBase->getAccessSpecifier() != AS_public)) {
           // The Microsoft extension __interface does not permit bases that
           // are not themselves public interfaces.

Added: cfe/trunk/test/SemaCXX/ms-iunknown-inline-def.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ms-iunknown-inline-def.cpp?rev=313364&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/ms-iunknown-inline-def.cpp (added)
+++ cfe/trunk/test/SemaCXX/ms-iunknown-inline-def.cpp Fri Sep 15 09:03:35 2017
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s 
+
+struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown {
+  void foo() {}
+};
+
+// expected-error at +1{{interface type cannot inherit from}}
+__interface HasError : public IUnknown {}; 

Propchange: cfe/trunk/test/SemaCXX/ms-iunknown-inline-def.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/SemaCXX/ms-iunknown-inline-def.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/SemaCXX/ms-iunknown-inline-def.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/SemaCXX/ms-iunknown-outofline-def.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ms-iunknown-outofline-def.cpp?rev=313364&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/ms-iunknown-outofline-def.cpp (added)
+++ cfe/trunk/test/SemaCXX/ms-iunknown-outofline-def.cpp Fri Sep 15 09:03:35 2017
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s 
+
+struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown {
+  void foo();
+};
+
+__interface NoError : public IUnknown {};
+void IUnknown::foo() {}
+// expected-error at +1{{interface type cannot inherit from}}
+__interface HasError : public IUnknown {}; 

Propchange: cfe/trunk/test/SemaCXX/ms-iunknown-outofline-def.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/SemaCXX/ms-iunknown-outofline-def.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/SemaCXX/ms-iunknown-outofline-def.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/SemaCXX/ms-iunknown.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ms-iunknown.cpp?rev=313364&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/ms-iunknown.cpp (added)
+++ cfe/trunk/test/SemaCXX/ms-iunknown.cpp Fri Sep 15 09:03:35 2017
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s 
+
+struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown {
+  void foo();
+};
+struct IPropertyPageBase : public IUnknown {};
+struct IPropertyPage : public IPropertyPageBase {};
+__interface ISfFileIOPropertyPage : public IPropertyPage {};
+
+
+namespace NS {
+  struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown {};
+  // expected-error at +1 {{interface type cannot inherit from}}
+  __interface IPropertyPageBase : public IUnknown {}; 
+}
+// expected-error at +1 {{interface type cannot inherit from}}
+__interface IPropertyPageBase2 : public NS::IUnknown {}; 
+
+__interface temp_iface {};
+struct bad_base : temp_iface {};
+// expected-error at +1 {{interface type cannot inherit from}}
+__interface bad_inherit : public bad_base{};
+
+struct mult_inher_base : temp_iface, IUnknown {};
+// expected-error at +1 {{interface type cannot inherit from}}
+__interface bad_inherit2 : public mult_inher_base{};
+
+struct PageBase : public IUnknown {};
+struct Page3 : public PageBase {};
+struct Page4 : public PageBase {};
+__interface PropertyPage : public Page4 {};
+
+struct Page5 : public Page3, Page4{};
+// expected-error at +1 {{interface type cannot inherit from}}
+__interface PropertyPage2 : public Page5 {}; 
+
+__interface IF1 {};
+__interface PP : IUnknown, IF1{}; 
+__interface PP2 : PP, Page3, Page4{};

Propchange: cfe/trunk/test/SemaCXX/ms-iunknown.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/SemaCXX/ms-iunknown.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/SemaCXX/ms-iunknown.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain




More information about the cfe-commits mailing list