Author: mren Date: Fri Sep 9 18:48:27 2016 New Revision: 281119 URL: http://llvm.org/viewvc/llvm-project?rev=281119&view=rev Log: Modules: for ObjectiveC try to keep the definition invariant.
When deserializing ObjCInterfaceDecl with definition data, if we already have a definition, try to keep the definition invariant; also pull in the categories even if it is not what getDefinition returns (this effectively combines categories). rdar://27926200 rdar://26708823 Added: cfe/trunk/test/Modules/Inputs/lookup-assert/ cfe/trunk/test/Modules/Inputs/lookup-assert/Base.h cfe/trunk/test/Modules/Inputs/lookup-assert/Derive.h cfe/trunk/test/Modules/Inputs/lookup-assert/H3.h cfe/trunk/test/Modules/Inputs/lookup-assert/module.map cfe/trunk/test/Modules/Inputs/objc-category/ cfe/trunk/test/Modules/Inputs/objc-category-2/ cfe/trunk/test/Modules/Inputs/objc-category-2/Base.h cfe/trunk/test/Modules/Inputs/objc-category-2/Category.h cfe/trunk/test/Modules/Inputs/objc-category-2/H3.h cfe/trunk/test/Modules/Inputs/objc-category-2/module.map cfe/trunk/test/Modules/Inputs/objc-category-3/ cfe/trunk/test/Modules/Inputs/objc-category-3/Base.h cfe/trunk/test/Modules/Inputs/objc-category-3/Category.h cfe/trunk/test/Modules/Inputs/objc-category-3/Category_B.h cfe/trunk/test/Modules/Inputs/objc-category-3/H3.h cfe/trunk/test/Modules/Inputs/objc-category-3/module.map cfe/trunk/test/Modules/Inputs/objc-category/Base.h cfe/trunk/test/Modules/Inputs/objc-category/Category.h cfe/trunk/test/Modules/Inputs/objc-category/H3.h cfe/trunk/test/Modules/Inputs/objc-category/module.map cfe/trunk/test/Modules/lookup-assert.m cfe/trunk/test/Modules/objc-category-2.m cfe/trunk/test/Modules/objc-category-3.m cfe/trunk/test/Modules/objc-category.m Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=281119&r1=281118&r2=281119&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Sep 9 18:48:27 2016 @@ -133,6 +133,10 @@ namespace clang { const RecordData &R, unsigned &I); void MergeDefinitionData(CXXRecordDecl *D, struct CXXRecordDecl::DefinitionData &&NewDD); + void ReadObjCDefinitionData(struct ObjCInterfaceDecl::DefinitionData &Data, + const RecordData &R, unsigned &I); + void MergeDefinitionData(ObjCInterfaceDecl *D, + struct ObjCInterfaceDecl::DefinitionData &&NewDD); static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, @@ -981,6 +985,43 @@ ObjCTypeParamList *ASTDeclReader::ReadOb typeParams, rAngleLoc); } +void ASTDeclReader::ReadObjCDefinitionData( + struct ObjCInterfaceDecl::DefinitionData &Data, + const RecordData &R, unsigned &I) { + // Read the superclass. + Data.SuperClassTInfo = GetTypeSourceInfo(Record, Idx); + + Data.EndLoc = ReadSourceLocation(Record, Idx); + Data.HasDesignatedInitializers = Record[Idx++]; + + // Read the directly referenced protocols and their SourceLocations. + unsigned NumProtocols = Record[Idx++]; + SmallVector<ObjCProtocolDecl *, 16> Protocols; + Protocols.reserve(NumProtocols); + for (unsigned I = 0; I != NumProtocols; ++I) + Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); + SmallVector<SourceLocation, 16> ProtoLocs; + ProtoLocs.reserve(NumProtocols); + for (unsigned I = 0; I != NumProtocols; ++I) + ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); + Data.ReferencedProtocols.set(Protocols.data(), NumProtocols, ProtoLocs.data(), + Reader.getContext()); + + // Read the transitive closure of protocols referenced by this class. + NumProtocols = Record[Idx++]; + Protocols.clear(); + Protocols.reserve(NumProtocols); + for (unsigned I = 0; I != NumProtocols; ++I) + Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); + Data.AllReferencedProtocols.set(Protocols.data(), NumProtocols, + Reader.getContext()); +} + +void ASTDeclReader::MergeDefinitionData(ObjCInterfaceDecl *D, + struct ObjCInterfaceDecl::DefinitionData &&NewDD) { + // FIXME: odr checking? +} + void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { RedeclarableResult Redecl = VisitRedeclarable(ID); VisitObjCContainerDecl(ID); @@ -991,43 +1032,22 @@ void ASTDeclReader::VisitObjCInterfaceDe if (Record[Idx++]) { // Read the definition. ID->allocateDefinitionData(); - - // Set the definition data of the canonical declaration, so other - // redeclarations will see it. - ID->getCanonicalDecl()->Data = ID->Data; - - ObjCInterfaceDecl::DefinitionData &Data = ID->data(); - - // Read the superclass. - Data.SuperClassTInfo = GetTypeSourceInfo(Record, Idx); - Data.EndLoc = ReadSourceLocation(Record, Idx); - Data.HasDesignatedInitializers = Record[Idx++]; + ReadObjCDefinitionData(ID->data(), Record, Idx); + ObjCInterfaceDecl *Canon = ID->getCanonicalDecl(); + if (Canon->Data.getPointer()) { + // If we already have a definition, keep the definition invariant and + // merge the data. + MergeDefinitionData(Canon, std::move(ID->data())); + ID->Data = Canon->Data; + } else { + // Set the definition data of the canonical declaration, so other + // redeclarations will see it. + ID->getCanonicalDecl()->Data = ID->Data; - // Read the directly referenced protocols and their SourceLocations. - unsigned NumProtocols = Record[Idx++]; - SmallVector<ObjCProtocolDecl *, 16> Protocols; - Protocols.reserve(NumProtocols); - for (unsigned I = 0; I != NumProtocols; ++I) - Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); - SmallVector<SourceLocation, 16> ProtoLocs; - ProtoLocs.reserve(NumProtocols); - for (unsigned I = 0; I != NumProtocols; ++I) - ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); - ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(), - Reader.getContext()); - - // Read the transitive closure of protocols referenced by this class. - NumProtocols = Record[Idx++]; - Protocols.clear(); - Protocols.reserve(NumProtocols); - for (unsigned I = 0; I != NumProtocols; ++I) - Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); - ID->data().AllReferencedProtocols.set(Protocols.data(), NumProtocols, - Reader.getContext()); - - // We will rebuild this list lazily. - ID->setIvarList(nullptr); + // We will rebuild this list lazily. + ID->setIvarList(nullptr); + } // Note that we have deserialized a definition. Reader.PendingDefinitions.insert(ID); @@ -3502,7 +3522,10 @@ Decl *ASTReader::ReadDeclRecord(DeclID I // Load the categories after recursive loading is finished. if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D)) - if (Class->isThisDeclarationADefinition()) + // If we already have a definition when deserializing the ObjCInterfaceDecl, + // we put the Decl in PendingDefinitions so we can pull the categories here. + if (Class->isThisDeclarationADefinition() || + PendingDefinitions.count(Class)) loadObjCCategories(ID, Class); // If we have deserialized a declaration that has a definition the Added: cfe/trunk/test/Modules/Inputs/lookup-assert/Base.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/lookup-assert/Base.h?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/Inputs/lookup-assert/Base.h (added) +++ cfe/trunk/test/Modules/Inputs/lookup-assert/Base.h Fri Sep 9 18:48:27 2016 @@ -0,0 +1,3 @@ +@interface BaseInterface +- (void) test; +@end Added: cfe/trunk/test/Modules/Inputs/lookup-assert/Derive.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/lookup-assert/Derive.h?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/Inputs/lookup-assert/Derive.h (added) +++ cfe/trunk/test/Modules/Inputs/lookup-assert/Derive.h Fri Sep 9 18:48:27 2016 @@ -0,0 +1,3 @@ +#include "Base.h" +@interface DerivedInterface : BaseInterface +@end Added: cfe/trunk/test/Modules/Inputs/lookup-assert/H3.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/lookup-assert/H3.h?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/Inputs/lookup-assert/H3.h (added) +++ cfe/trunk/test/Modules/Inputs/lookup-assert/H3.h Fri Sep 9 18:48:27 2016 @@ -0,0 +1 @@ +#include "Base.h" Added: cfe/trunk/test/Modules/Inputs/lookup-assert/module.map URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/lookup-assert/module.map?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/Inputs/lookup-assert/module.map (added) +++ cfe/trunk/test/Modules/Inputs/lookup-assert/module.map Fri Sep 9 18:48:27 2016 @@ -0,0 +1,4 @@ +module X { + header "H3.h" + export * +} Added: cfe/trunk/test/Modules/Inputs/objc-category-2/Base.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/objc-category-2/Base.h?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/Inputs/objc-category-2/Base.h (added) +++ cfe/trunk/test/Modules/Inputs/objc-category-2/Base.h Fri Sep 9 18:48:27 2016 @@ -0,0 +1,3 @@ +@interface DVTSourceModel // expected-error {{duplicate interface definition for class}} \ + // expected-note {{previous definition is here}} +@end Added: cfe/trunk/test/Modules/Inputs/objc-category-2/Category.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/objc-category-2/Category.h?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/Inputs/objc-category-2/Category.h (added) +++ cfe/trunk/test/Modules/Inputs/objc-category-2/Category.h Fri Sep 9 18:48:27 2016 @@ -0,0 +1,4 @@ +#include "Base.h" +@interface DVTSourceModel(Additions) +- (int)test:(int)item; +@end Added: cfe/trunk/test/Modules/Inputs/objc-category-2/H3.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/objc-category-2/H3.h?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/Inputs/objc-category-2/H3.h (added) +++ cfe/trunk/test/Modules/Inputs/objc-category-2/H3.h Fri Sep 9 18:48:27 2016 @@ -0,0 +1 @@ +#include "Base.h" Added: cfe/trunk/test/Modules/Inputs/objc-category-2/module.map URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/objc-category-2/module.map?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/Inputs/objc-category-2/module.map (added) +++ cfe/trunk/test/Modules/Inputs/objc-category-2/module.map Fri Sep 9 18:48:27 2016 @@ -0,0 +1,4 @@ +module X { + header "Category.h" + export * +} Added: cfe/trunk/test/Modules/Inputs/objc-category-3/Base.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/objc-category-3/Base.h?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/Inputs/objc-category-3/Base.h (added) +++ cfe/trunk/test/Modules/Inputs/objc-category-3/Base.h Fri Sep 9 18:48:27 2016 @@ -0,0 +1,2 @@ +@interface DVTSourceModel +@end Added: cfe/trunk/test/Modules/Inputs/objc-category-3/Category.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/objc-category-3/Category.h?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/Inputs/objc-category-3/Category.h (added) +++ cfe/trunk/test/Modules/Inputs/objc-category-3/Category.h Fri Sep 9 18:48:27 2016 @@ -0,0 +1,4 @@ +#include "Base.h" +@interface DVTSourceModel(Additions) +- (int)test:(int)item; +@end Added: cfe/trunk/test/Modules/Inputs/objc-category-3/Category_B.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/objc-category-3/Category_B.h?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/Inputs/objc-category-3/Category_B.h (added) +++ cfe/trunk/test/Modules/Inputs/objc-category-3/Category_B.h Fri Sep 9 18:48:27 2016 @@ -0,0 +1,4 @@ +#include "Base.h" +@interface DVTSourceModel(AdditionsB) +- (int)testB:(int)item matchingMask:(int)mask; +@end Added: cfe/trunk/test/Modules/Inputs/objc-category-3/H3.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/objc-category-3/H3.h?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/Inputs/objc-category-3/H3.h (added) +++ cfe/trunk/test/Modules/Inputs/objc-category-3/H3.h Fri Sep 9 18:48:27 2016 @@ -0,0 +1 @@ +#include "Base.h" Added: cfe/trunk/test/Modules/Inputs/objc-category-3/module.map URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/objc-category-3/module.map?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/Inputs/objc-category-3/module.map (added) +++ cfe/trunk/test/Modules/Inputs/objc-category-3/module.map Fri Sep 9 18:48:27 2016 @@ -0,0 +1,4 @@ +module X { + header "Category_B.h" + export * +} Added: cfe/trunk/test/Modules/Inputs/objc-category/Base.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/objc-category/Base.h?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/Inputs/objc-category/Base.h (added) +++ cfe/trunk/test/Modules/Inputs/objc-category/Base.h Fri Sep 9 18:48:27 2016 @@ -0,0 +1,2 @@ +@interface DVTSourceModel +@end Added: cfe/trunk/test/Modules/Inputs/objc-category/Category.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/objc-category/Category.h?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/Inputs/objc-category/Category.h (added) +++ cfe/trunk/test/Modules/Inputs/objc-category/Category.h Fri Sep 9 18:48:27 2016 @@ -0,0 +1,4 @@ +#include "Base.h" +@interface DVTSourceModel(Additions) +- (int)test:(int)item; +@end Added: cfe/trunk/test/Modules/Inputs/objc-category/H3.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/objc-category/H3.h?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/Inputs/objc-category/H3.h (added) +++ cfe/trunk/test/Modules/Inputs/objc-category/H3.h Fri Sep 9 18:48:27 2016 @@ -0,0 +1 @@ +#include "Base.h" Added: cfe/trunk/test/Modules/Inputs/objc-category/module.map URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/objc-category/module.map?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/Inputs/objc-category/module.map (added) +++ cfe/trunk/test/Modules/Inputs/objc-category/module.map Fri Sep 9 18:48:27 2016 @@ -0,0 +1,4 @@ +module X { + header "H3.h" + export * +} Added: cfe/trunk/test/Modules/lookup-assert.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/lookup-assert.m?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/lookup-assert.m (added) +++ cfe/trunk/test/Modules/lookup-assert.m Fri Sep 9 18:48:27 2016 @@ -0,0 +1,10 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/lookup-assert %s -verify +// expected-no-diagnostics + +#include "Derive.h" +#import <H3.h> +@implementation DerivedInterface +- (void)test { +} +@end Added: cfe/trunk/test/Modules/objc-category-2.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/objc-category-2.m?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/objc-category-2.m (added) +++ cfe/trunk/test/Modules/objc-category-2.m Fri Sep 9 18:48:27 2016 @@ -0,0 +1,12 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/objc-category-2 %s -verify -fobjc-arc + +// We have a definition of category and the base interface imported from a +// module, definition for the base interface is also textually included. +// Currently we emit an error "duplicate interface definition". +#import <Category.h> +#include "H3.h" + +void test(DVTSourceModel *m) { + [m test:1]; +} Added: cfe/trunk/test/Modules/objc-category-3.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/objc-category-3.m?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/objc-category-3.m (added) +++ cfe/trunk/test/Modules/objc-category-3.m Fri Sep 9 18:48:27 2016 @@ -0,0 +1,14 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/objc-category-3 %s -verify -fobjc-arc +// expected-no-diagnostics + +// We have a definition of the base interface textually included from +// Category.h, the definition is also in the module that includes the base +// interface. We should be able to see both categories in the TU. +#include "Category.h" +#import <Category_B.h> + +void test(DVTSourceModel *m) { + [m test:1]; + [m testB:1 matchingMask:2]; +} Added: cfe/trunk/test/Modules/objc-category.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/objc-category.m?rev=281119&view=auto ============================================================================== --- cfe/trunk/test/Modules/objc-category.m (added) +++ cfe/trunk/test/Modules/objc-category.m Fri Sep 9 18:48:27 2016 @@ -0,0 +1,13 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/objc-category %s -verify -fobjc-arc +// expected-no-diagnostics + +// We have a definition of the base interface textually included from +// Category.h, the definition is also in the module that includes the base +// interface. We should be able to see the category in the TU. +#include "Category.h" +#import <H3.h> + +void test(DVTSourceModel *m) { + [m test:1]; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits