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(); + + return RD->isStruct() && RD->getName() == "IUnknown" && RD->isEmpty() && + Uuid && Uuid->getGuid() =="00000000-0000-0000-C000-000000000046" && + dyn_cast(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 IndirectBaseSet; @@ -2450,10 +2477,10 @@ if (const RecordType *Record = NewBaseType->getAs()) { const CXXRecordDecl *RD = cast(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}}