Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -2373,6 +2373,35 @@ return true; } +/// \brief Tests if the __interface base is public. +static bool IsRecordPublicInterface(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 IsUnknownType(const CXXRecordDecl *RD) { + auto *Uuid = RD->getAttr(); + + return RD->isStruct() && RD->getName() == "IUnknown" && RD->isEmpty() && + Uuid && Uuid->getGuid() =="00000000-0000-0000-C000-000000000046"; +} + +/// \brief Test if record and records in inheritance tree is a an Unknown. +static bool IsOrInheritsFromUnknown(const CXXRecordDecl *RD) { + if (RD->getNumBases()) { + const CXXRecordDecl *Base = + RD->bases_begin()->getType()->getAsCXXRecordDecl(); + + return Base && IsUnknownType(Base) && !IsUnknownType(RD) && + IsOrInheritsFromUnknown(Base); + } else { + return IsUnknownType(RD); + } +} + /// 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,8 +2479,8 @@ if (const RecordType *Record = NewBaseType->getAs()) { const CXXRecordDecl *RD = cast(Record->getDecl()); if (Class->isInterface() && - (!RD->isInterface() || - KnownBase->getAccessSpecifier() != AS_public)) { + !IsRecordPublicInterface(RD, KnownBase->getAccessSpecifier()) && + !IsOrInheritsFromUnknown(RD)) { // The Microsoft extension __interface does not permit bases that // are not themselves public interfaces. Diag(KnownBase->getLocStart(), diag::err_invalid_base_in_interface) Index: test/SemaCXX/ms-uuid.cpp =================================================================== --- test/SemaCXX/ms-uuid.cpp +++ test/SemaCXX/ms-uuid.cpp @@ -93,3 +93,27 @@ [uuid("000000A0-0000-0000-C000-000000000049"), uuid("000000A0-0000-0000-C000-000000000049")] class C10; } + +struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown {}; +__interface ISfFileIOPropertyPage : public IUnknown {}; + +struct __declspec(uuid("00000000-0000-0000-C000-000000000045")) IUnknown1 {}; +__interface ISfFileIOPropertyPage1 : public IUnknown1 {}; // expected-error {{interface type cannot inherit from}} + +struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown2 {}; +struct IPropertyPage2 : public IUnknown2 {}; +__interface ISfFileIOPropertyPage2 : public IPropertyPage2 {}; // expected-error {{interface type cannot inherit from}} + +struct IPropertyPage3 : public IUnknown {}; +__interface ISfFileIOPropertyPage3 : public IPropertyPage3 {}; + +__interface __declspec(dllimport) ISfFileIOPropertyPage33 : public IUnknown {}; + +struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown4 {}; +__interface ISfFileIOPropertyPage4 : public IUnknown4 {}; // expected-error {{interface type cannot inherit from}} + +class __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown5 {}; +__interface ISfFileIOPropertyPage5 : public IUnknown5 {}; // expected-error {{interface type cannot inherit from}} + +struct __declspec(dllexport) IUnknown6{}; +__interface foo : public IUnknown6{}; // expected-error {{interface type cannot inherit from}}