Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -2373,6 +2373,32 @@ return true; } +/// \brief Tests if the __interface base is public. +static bool IsBasePublicInterface(const CXXRecordDecl *RD, + AccessSpecifier spec) { + return RD->isInterface() && spec == AS_public; +} + +/// \brief Test is base RD is an uuid Unknown type. +static bool IsUnknownType(const CXXRecordDecl *RD) { + return RD->isStruct() && RD->hasAttr() && + RD->getName() == "IUnknown" && + (RD->getAttr())->getGuid() == + "00000000-0000-0000-C000-000000000046" && + RD->isEmpty(); +} + +static bool IsInheritatedBaseUuid(const CXXRecordDecl *RD) { + for (unsigned int n = 0; n < RD->getNumBases(); n++) { + const CXXRecordDecl *Base = + RD->bases_begin()->getType()->getAsCXXRecordDecl(); + + return (Base && Base->getName() == "IUnknown" && + !strcmp(Base->getAttr()->getSpelling(),"uuid")); + } + return false; +} + /// 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 +2476,8 @@ if (const RecordType *Record = NewBaseType->getAs()) { const CXXRecordDecl *RD = cast(Record->getDecl()); if (Class->isInterface() && - (!RD->isInterface() || - KnownBase->getAccessSpecifier() != AS_public)) { + !IsBasePublicInterface(RD, KnownBase->getAccessSpecifier()) && + !IsUnknownType(RD) && !IsInheritatedBaseUuid(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,28 @@ [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}}