]> granicus.if.org Git - clang/commitdiff
[Modules][ObjC] ASTReader should add protocols for class extensions
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Fri, 27 Apr 2018 18:01:23 +0000 (18:01 +0000)
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Fri, 27 Apr 2018 18:01:23 +0000 (18:01 +0000)
During deserialization clang is currently missing the merging of
protocols into the canonical interface for the class extension.

This merging only currently happens during parsing and should also
be considered during deserialization.

rdar://problem/38724303

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@331063 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Serialization/ASTReaderDecl.cpp
test/Modules/Inputs/class-extension/a-private.h [new file with mode: 0644]
test/Modules/Inputs/class-extension/a-proto.h [new file with mode: 0644]
test/Modules/Inputs/class-extension/a.h [new file with mode: 0644]
test/Modules/Inputs/class-extension/module.modulemap [new file with mode: 0644]
test/Modules/class-extension-protocol.m [new file with mode: 0644]

index 7a5d22c00f8f7502ec2c1b0c227f2ef991834298..046c699a224f6b39786e925752835887d0c36f7c 100644 (file)
@@ -1205,6 +1205,12 @@ void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
     ProtoLocs.push_back(ReadSourceLocation());
   CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
                       Reader.getContext());
+
+  // Protocols in the class extension belong to the class.
+  if (NumProtoRefs > 0 && CD->ClassInterface && CD->IsClassExtension())
+    CD->ClassInterface->mergeClassExtensionProtocolList(
+        (ObjCProtocolDecl *const *)ProtoRefs.data(), NumProtoRefs,
+        Reader.getContext());
 }
 
 void ASTDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
diff --git a/test/Modules/Inputs/class-extension/a-private.h b/test/Modules/Inputs/class-extension/a-private.h
new file mode 100644 (file)
index 0000000..e35402a
--- /dev/null
@@ -0,0 +1,5 @@
+#import "a.h"
+#import "a-proto.h"
+
+@interface A () <AProto>
+@end
diff --git a/test/Modules/Inputs/class-extension/a-proto.h b/test/Modules/Inputs/class-extension/a-proto.h
new file mode 100644 (file)
index 0000000..32043ec
--- /dev/null
@@ -0,0 +1,7 @@
+@protocol NSObject
+@end
+
+@protocol AProto <NSObject>
+@property (nonatomic, readwrite, assign) int p0;
+@property (nonatomic, readwrite, assign) int p1;
+@end
diff --git a/test/Modules/Inputs/class-extension/a.h b/test/Modules/Inputs/class-extension/a.h
new file mode 100644 (file)
index 0000000..28c409c
--- /dev/null
@@ -0,0 +1,5 @@
+@interface NSObject
+@end
+
+@interface A : NSObject
+@end
diff --git a/test/Modules/Inputs/class-extension/module.modulemap b/test/Modules/Inputs/class-extension/module.modulemap
new file mode 100644 (file)
index 0000000..5c30bc5
--- /dev/null
@@ -0,0 +1,11 @@
+
+module A {
+  header "a.h"
+  header "a-proto.h"
+  export *
+}
+
+module AP {
+  header "a-private.h"
+  export *
+}
diff --git a/test/Modules/class-extension-protocol.m b/test/Modules/class-extension-protocol.m
new file mode 100644 (file)
index 0000000..752e4e1
--- /dev/null
@@ -0,0 +1,9 @@
+// RUN: rm -rf %t.cache
+// RUN: %clang_cc1 %s -fsyntax-only -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.cache -I%S/Inputs/class-extension -verify
+// expected-no-diagnostics
+
+#import "a-private.h"
+
+int foo(A *X) {
+  return X.p0 + X.p1;
+}