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@+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@+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@+1 {{interface type cannot inherit from}} + __interface IPropertyPageBase : public IUnknown {}; +} +// expected-error@+1 {{interface type cannot inherit from}} +__interface IPropertyPageBase2 : public NS::IUnknown {}; + +__interface temp_iface {}; +struct bad_base : temp_iface {}; +// expected-error@+1 {{interface type cannot inherit from}} +__interface bad_inherit : public bad_base{}; + +struct mult_inher_base : temp_iface, IUnknown {}; +// expected-error@+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@+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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits