Author: erichkeane Date: Fri Sep 29 14:06:00 2017 New Revision: 314557 URL: http://llvm.org/viewvc/llvm-project?rev=314557&view=rev Log: [Sema] Correct IUnknown to support Unknwnbase.h Header.
Apparently, the MSVC SDK has a strange implementation that causes a number of implicit functions as well as a template member function of the IUnknown type. This patch allows these as InterfaceLike types as well. Additionally, it corrects the behavior where extern-C++ wrapped around an Interface-Like type would permit an interface-like type to exist in a namespace. Differential Revision: https://reviews.llvm.org/D38303 Added: cfe/trunk/test/SemaCXX/ms-iunknown-template-function.cpp (with props) Modified: cfe/trunk/lib/AST/DeclCXX.cpp cfe/trunk/test/SemaCXX/ms-iunknown.cpp Modified: cfe/trunk/lib/AST/DeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=314557&r1=314556&r2=314557&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclCXX.cpp (original) +++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Sep 29 14:06:00 2017 @@ -1470,6 +1470,15 @@ bool CXXRecordDecl::isAnyDestructorNoRet return false; } +static bool isDeclContextInNamespace(const DeclContext *DC) { + while (!DC->isTranslationUnit()) { + if (DC->isNamespace()) + return true; + DC = DC->getParent(); + } + return false; +} + bool CXXRecordDecl::isInterfaceLike() const { assert(hasDefinition() && "checking for interface-like without a definition"); // All __interfaces are inheritently interface-like. @@ -1486,13 +1495,16 @@ bool CXXRecordDecl::isInterfaceLike() co // No interface-like type can have a method with a definition. for (const auto *const Method : methods()) - if (Method->isDefined()) + if (Method->isDefined() && !Method->isImplicit()) return false; // Check "Special" types. const auto *Uuid = getAttr<UuidAttr>(); - if (Uuid && isStruct() && (getDeclContext()->isTranslationUnit() || - getDeclContext()->isExternCXXContext()) && + // MS SDK declares IUnknown/IDispatch both in the root of a TU, or in an + // extern C++ block directly in the TU. These are only valid if in one + // of these two situations. + if (Uuid && isStruct() && !getDeclContext()->isExternCContext() && + !isDeclContextInNamespace(getDeclContext()) && ((getName() == "IUnknown" && Uuid->getGuid() == "00000000-0000-0000-C000-000000000046") || (getName() == "IDispatch" && Added: cfe/trunk/test/SemaCXX/ms-iunknown-template-function.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ms-iunknown-template-function.cpp?rev=314557&view=auto ============================================================================== --- cfe/trunk/test/SemaCXX/ms-iunknown-template-function.cpp (added) +++ cfe/trunk/test/SemaCXX/ms-iunknown-template-function.cpp Fri Sep 29 14:06:00 2017 @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s +typedef long HRESULT; +typedef unsigned long ULONG; +typedef struct _GUID { + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +} GUID; +typedef GUID IID; + +// remove stdcall, since the warnings have nothing to do with +// what is being tested. +#define __stdcall + +extern "C" { +extern "C++" { +// expected-warning@+1 {{__declspec attribute 'novtable'}} +struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) __declspec(novtable) + IUnknown { +public: + virtual HRESULT __stdcall QueryInterface( + const IID &riid, + void **ppvObject) = 0; + + virtual ULONG __stdcall AddRef(void) = 0; + + virtual ULONG __stdcall Release(void) = 0; + + template <class Q> + HRESULT __stdcall QueryInterface(Q **pp) { + return QueryInterface(__uuidof(Q), (void **)pp); + } +}; +} +} + +__interface ISfFileIOPropertyPage : public IUnknown{}; + Propchange: cfe/trunk/test/SemaCXX/ms-iunknown-template-function.cpp ------------------------------------------------------------------------------ svn:eol-style = native Propchange: cfe/trunk/test/SemaCXX/ms-iunknown-template-function.cpp ------------------------------------------------------------------------------ svn:keywords = Author Date Id Rev URL Propchange: cfe/trunk/test/SemaCXX/ms-iunknown-template-function.cpp ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: cfe/trunk/test/SemaCXX/ms-iunknown.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ms-iunknown.cpp?rev=314557&r1=314556&r2=314557&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/ms-iunknown.cpp (original) +++ cfe/trunk/test/SemaCXX/ms-iunknown.cpp Fri Sep 29 14:06:00 2017 @@ -2,7 +2,11 @@ extern "C++" struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown { void foo(); + // Definitions aren't allowed, unless they are a template. + template<typename T> + void bar(T t){} }; + struct IPropertyPageBase : public IUnknown {}; struct IPropertyPage : public IPropertyPageBase {}; __interface ISfFileIOPropertyPage : public IPropertyPage {}; @@ -11,10 +15,17 @@ __interface ISfFileIOPropertyPage : publ namespace NS { struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown {}; // expected-error@+1 {{interface type cannot inherit from}} - __interface IPropertyPageBase : public IUnknown {}; + __interface IPropertyPageBase : public IUnknown {}; } + +namespace NS2 { +extern "C++" 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 IPropertyPageBase2 : public NS::IUnknown {}; __interface temp_iface {}; struct bad_base : temp_iface {}; @@ -32,8 +43,8 @@ __interface PropertyPage : public Page4 struct Page5 : public Page3, Page4{}; // expected-error@+1 {{interface type cannot inherit from}} -__interface PropertyPage2 : public Page5 {}; +__interface PropertyPage2 : public Page5 {}; __interface IF1 {}; -__interface PP : IUnknown, IF1{}; +__interface PP : IUnknown, IF1{}; __interface PP2 : PP, Page3, Page4{}; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits