r281119 - Modules: for ObjectiveC try to keep the definition invariant.

Manman Ren via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 9 16:48:28 PDT 2016


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 @@
+ at interface BaseInterface
+- (void) test;
+ at 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"
+ at interface DerivedInterface : BaseInterface
+ at 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 @@
+ at interface DVTSourceModel // expected-error {{duplicate interface definition for class}} \
+                          // expected-note {{previous definition is here}}
+ at 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"
+ at interface DVTSourceModel(Additions)
+- (int)test:(int)item;
+ at 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 @@
+ at interface DVTSourceModel
+ at 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"
+ at interface DVTSourceModel(Additions)
+- (int)test:(int)item;
+ at 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"
+ at interface DVTSourceModel(AdditionsB)
+- (int)testB:(int)item matchingMask:(int)mask;
+ at 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 @@
+ at interface DVTSourceModel
+ at 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"
+ at interface DVTSourceModel(Additions)
+- (int)test:(int)item;
+ at 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>
+ at implementation DerivedInterface
+- (void)test {
+}
+ at 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];
+}




More information about the cfe-commits mailing list