r314557 - [Sema] Correct IUnknown to support Unknwnbase.h Header.

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 29 14:06:01 PDT 2017


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 at +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 at +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 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 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 at +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{};




More information about the cfe-commits mailing list