zahiraam updated this revision to Diff 114935. zahiraam added a comment. Erich, Aaron, Please review at your convenience. 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 RD is a public interface. +static bool IsDeclPublicInterface(const CXXRecordDecl *RD, + AccessSpecifier spec) { + return RD->isInterface() && spec == AS_public; +} + +/// \brief Test if record is a uuid for IUnknown. +/// This is an MS SDK specific type that has a special +/// behavior in the CL compiler. +static bool IsIUnknownType(const CXXRecordDecl *RD) { + const auto *Uuid = RD->getAttr<UuidAttr>(); + + return Uuid && Uuid->getGuid() =="00000000-0000-0000-C000-000000000046" && + RD->isStruct() && RD->getName() == "IUnknown" && RD->isEmpty() && + RD->getDeclContext()->isTranslationUnit(); +} + +/// \brief Test if RD or its inherited bases is an IUnknow type. +static bool IsOrInheritsFromIUnknown(const CXXRecordDecl *RD) { + bool result = IsIUnknownType(RD); + for (const auto *I = RD->bases_begin(), *E = RD->bases_end(); I != E; ++I) { + const CXXRecordDecl *BB = I->getType()->getAsCXXRecordDecl(); + return result || IsOrInheritsFromIUnknown(BB); + } + return result; +} + /// 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 RD is a public interface. +static bool IsDeclPublicInterface(const CXXRecordDecl *RD, + AccessSpecifier spec) { + return RD->isInterface() && spec == AS_public; +} + +/// \brief Test if record is a uuid for IUnknown. +/// This is an MS SDK specific type that has a special +/// behavior in the CL compiler. +static bool IsIUnknownType(const CXXRecordDecl *RD) { + const auto *Uuid = RD->getAttr<UuidAttr>(); + + return Uuid && Uuid->getGuid() =="00000000-0000-0000-C000-000000000046" && + RD->isStruct() && RD->getName() == "IUnknown" && RD->isEmpty() && + RD->getDeclContext()->isTranslationUnit(); +} + +/// \brief Test if RD or its inherited bases is an IUnknow type. +static bool IsOrInheritsFromIUnknown(const CXXRecordDecl *RD) { + bool result = IsIUnknownType(RD); + for (const auto *I = RD->bases_begin(), *E = RD->bases_end(); I != E; ++I) { + const CXXRecordDecl *BB = I->getType()->getAsCXXRecordDecl(); + return result || IsOrInheritsFromIUnknown(BB); + } + return result; +} + /// 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