zahiraam updated this revision to Diff 114497.
zahiraam added a comment.

Erich,

Addressed your comments.
Thanks.


https://reviews.llvm.org/D37308

Files:
  lib/Sema/SemaDeclCXX.cpp
  test/SemaCXX/ms-uuid.cpp


Index: test/SemaCXX/ms-uuid.cpp
===================================================================
--- test/SemaCXX/ms-uuid.cpp
+++ test/SemaCXX/ms-uuid.cpp
@@ -93,3 +93,32 @@
 [uuid("000000A0-0000-0000-C000-000000000049"),
  uuid("000000A0-0000-0000-C000-000000000049")] class C10;
 }
+
+struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown {};
+struct IPropertyPageBase : public IUnknown {};
+struct IPropertyPage : public IPropertyPageBase {};
+__interface ISfFileIOPropertyPage : public IPropertyPage {};
+
+
+__interface ISfFileIOPropertyPage1 : public IUnknown {};
+
+struct __declspec(uuid("00000000-0000-0000-C000-000000000045")) IUnknown1 {};
+__interface ISfFileIOPropertyPage2 : public IUnknown1 {};  // expected-error 
{{interface type cannot inherit from}}
+
+struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown2 {};
+struct IPropertyPage2 : public IUnknown2 {};
+__interface ISfFileIOPropertyPage3 : public IPropertyPage2 {}; // 
expected-error {{interface type cannot inherit from}}
+
+struct IPropertyPage3 : public IUnknown {};
+__interface ISfFileIOPropertyPage4 : public IPropertyPage3 {};
+
+__interface __declspec(dllimport) ISfFileIOPropertyPage33 : public IUnknown {};
+
+struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown4 {};
+__interface ISfFileIOPropertyPage5 : public IUnknown4 {}; // expected-error 
{{interface type cannot inherit from}}
+
+class __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown5 {};
+__interface ISfFileIOPropertyPage6 : public IUnknown5 {}; // expected-error 
{{interface type cannot inherit from}}
+
+struct __declspec(dllexport) IUnknown6{};
+__interface foo : public IUnknown6{}; // expected-error {{interface type 
cannot inherit from}}
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -2373,6 +2373,33 @@
   return true;
 }
 
+/// \brief Tests if the __interface base is public.
+static bool IsDeclPublicInterface(const CXXRecordDecl *RD,
+                                  AccessSpecifier spec) {
+  return RD->isInterface() && spec == AS_public;
+}
+
+/// \brief Test if record is an uuid Unknown.
+/// This is an MS SDK specific type that has a special
+/// behavior in the CL compiler.
+static bool IsIUnknownType(const CXXRecordDecl *RD) {
+  auto *Uuid = RD->getAttr<UuidAttr>();
+
+  return RD->isStruct() && RD->getName() == "IUnknown" && RD->isEmpty() &&
+         Uuid && Uuid->getGuid() =="00000000-0000-0000-C000-000000000046" &&
+         dyn_cast<TranslationUnitDecl>(RD->getDeclContext());
+}
+
+/// \brief Test if RD or its inhetited bases is an IUnknow type.
+static bool IsOrInheritsFromIUnknown(const CXXRecordDecl *RD) {
+  const CXXRecordDecl *Base =
+      RD->getNumBases() ? RD->bases_begin()->getType()->getAsCXXRecordDecl()
+                        : nullptr;
+
+  return IsIUnknownType(RD) ||
+         Base &&  (IsIUnknownType(Base) || IsOrInheritsFromIUnknown(Base));
+}
+
 /// Use small set to collect indirect bases.  As this is only used
 /// locally, there's no need to abstract the small size parameter.
 typedef llvm::SmallPtrSet<QualType, 4> IndirectBaseSet;
@@ -2450,10 +2477,10 @@
       if (const RecordType *Record = NewBaseType->getAs<RecordType>()) {
         const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
         if (Class->isInterface() &&
-              (!RD->isInterface() ||
-               KnownBase->getAccessSpecifier() != AS_public)) {
-          // The Microsoft extension __interface does not permit bases that
-          // are not themselves public interfaces.
+            // The Microsoft extension __interface does not permit bases that
+            // are not themselves public interfaces.
+            !IsDeclPublicInterface(RD, KnownBase->getAccessSpecifier()) &&
+            !IsOrInheritsFromIUnknown(RD)) {
           Diag(KnownBase->getLocStart(), diag::err_invalid_base_in_interface)
             << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getName()
             << RD->getSourceRange();


Index: test/SemaCXX/ms-uuid.cpp
===================================================================
--- test/SemaCXX/ms-uuid.cpp
+++ test/SemaCXX/ms-uuid.cpp
@@ -93,3 +93,32 @@
 [uuid("000000A0-0000-0000-C000-000000000049"),
  uuid("000000A0-0000-0000-C000-000000000049")] class C10;
 }
+
+struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown {};
+struct IPropertyPageBase : public IUnknown {};
+struct IPropertyPage : public IPropertyPageBase {};
+__interface ISfFileIOPropertyPage : public IPropertyPage {};
+
+
+__interface ISfFileIOPropertyPage1 : public IUnknown {};
+
+struct __declspec(uuid("00000000-0000-0000-C000-000000000045")) IUnknown1 {};
+__interface ISfFileIOPropertyPage2 : public IUnknown1 {};  // expected-error {{interface type cannot inherit from}}
+
+struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown2 {};
+struct IPropertyPage2 : public IUnknown2 {};
+__interface ISfFileIOPropertyPage3 : public IPropertyPage2 {}; // expected-error {{interface type cannot inherit from}}
+
+struct IPropertyPage3 : public IUnknown {};
+__interface ISfFileIOPropertyPage4 : public IPropertyPage3 {};
+
+__interface __declspec(dllimport) ISfFileIOPropertyPage33 : public IUnknown {};
+
+struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown4 {};
+__interface ISfFileIOPropertyPage5 : public IUnknown4 {}; // expected-error {{interface type cannot inherit from}}
+
+class __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown5 {};
+__interface ISfFileIOPropertyPage6 : public IUnknown5 {}; // expected-error {{interface type cannot inherit from}}
+
+struct __declspec(dllexport) IUnknown6{};
+__interface foo : public IUnknown6{}; // expected-error {{interface type cannot inherit from}}
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -2373,6 +2373,33 @@
   return true;
 }
 
+/// \brief Tests if the __interface base is public.
+static bool IsDeclPublicInterface(const CXXRecordDecl *RD,
+                                  AccessSpecifier spec) {
+  return RD->isInterface() && spec == AS_public;
+}
+
+/// \brief Test if record is an uuid Unknown.
+/// This is an MS SDK specific type that has a special
+/// behavior in the CL compiler.
+static bool IsIUnknownType(const CXXRecordDecl *RD) {
+  auto *Uuid = RD->getAttr<UuidAttr>();
+
+  return RD->isStruct() && RD->getName() == "IUnknown" && RD->isEmpty() &&
+         Uuid && Uuid->getGuid() =="00000000-0000-0000-C000-000000000046" &&
+         dyn_cast<TranslationUnitDecl>(RD->getDeclContext());
+}
+
+/// \brief Test if RD or its inhetited bases is an IUnknow type.
+static bool IsOrInheritsFromIUnknown(const CXXRecordDecl *RD) {
+  const CXXRecordDecl *Base =
+      RD->getNumBases() ? RD->bases_begin()->getType()->getAsCXXRecordDecl()
+                        : nullptr;
+
+  return IsIUnknownType(RD) ||
+         Base &&  (IsIUnknownType(Base) || IsOrInheritsFromIUnknown(Base));
+}
+
 /// Use small set to collect indirect bases.  As this is only used
 /// locally, there's no need to abstract the small size parameter.
 typedef llvm::SmallPtrSet<QualType, 4> IndirectBaseSet;
@@ -2450,10 +2477,10 @@
       if (const RecordType *Record = NewBaseType->getAs<RecordType>()) {
         const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
         if (Class->isInterface() &&
-              (!RD->isInterface() ||
-               KnownBase->getAccessSpecifier() != AS_public)) {
-          // The Microsoft extension __interface does not permit bases that
-          // are not themselves public interfaces.
+            // The Microsoft extension __interface does not permit bases that
+            // are not themselves public interfaces.
+            !IsDeclPublicInterface(RD, KnownBase->getAccessSpecifier()) &&
+            !IsOrInheritsFromIUnknown(RD)) {
           Diag(KnownBase->getLocStart(), diag::err_invalid_base_in_interface)
             << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getName()
             << RD->getSourceRange();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to