xref: /llvm-project/clang/test/Modules/merge-extension-ivars.m (revision 7793e676514bc102e97a993e90257e8628069a8b)
1// UNSUPPORTED: target={{.*}}-zos{{.*}}, target={{.*}}-aix{{.*}}
2// RUN: rm -rf %t
3// RUN: split-file %s %t
4// RUN: %clang_cc1 -emit-llvm -o %t/test-compatible-extensions.ll -fobjc-runtime=macosx-10.9 -F%t/Frameworks %t/test-compatible-extensions.m \
5// RUN:            -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache -fmodule-name=InterfaceAndExtension
6// RUN: FileCheck --input-file=%t/test-compatible-extensions.ll %t/test-compatible-extensions.m
7
8// RUN: %clang_cc1 -emit-llvm -o %t/test-access-extension-ivar.ll -fobjc-runtime=macosx-10.9 -F%t/Frameworks %t/test-access-extension-ivar.m \
9// RUN:            -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache
10// RUN: FileCheck --input-file=%t/test-access-extension-ivar.ll %t/test-access-extension-ivar.m
11
12// RUN: %clang_cc1 -emit-llvm -o %t/test-synthesized-ivar.ll -fobjc-runtime=macosx-10.9 -F%t/Frameworks %t/test-synthesized-ivar.m \
13// RUN:            -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache
14// RUN: FileCheck --input-file=%t/test-synthesized-ivar.ll %t/test-synthesized-ivar.m
15// RUN: %clang_cc1 -emit-llvm -o %t/test-synthesized-ivar-extension.ll -fobjc-runtime=macosx-10.9 -F%t/Frameworks %t/test-synthesized-ivar.m \
16// RUN:            -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache \
17// RUN:            -DIMPORT_EXTENSION=1
18// RUN: FileCheck --input-file=%t/test-synthesized-ivar-extension.ll %t/test-synthesized-ivar.m
19
20// Test various scenarios where we can end up with the same-name ivars coming from multiple modules.
21// The goal is to avoid duplicate metadata for ivars because it can lead to miscompilations
22// with a wrong ivar offset.
23//
24// See specific .m tests for the details of various scenarios.
25
26//--- Frameworks/InterfaceAndExtension.framework/Headers/Interface.h
27@interface NSObject @end
28@interface ObjCInterface : NSObject
29@end
30
31//--- Frameworks/InterfaceAndExtension.framework/Headers/Extension.h
32#import <InterfaceAndExtension/Interface.h>
33@interface ObjCInterface() {
34  float ivarInExtension;
35  int bitfieldIvarInExtension: 3;
36}
37@end
38
39//--- Frameworks/InterfaceAndExtension.framework/Headers/InterfaceAndExtension.h
40#import <InterfaceAndExtension/Interface.h>
41#import <InterfaceAndExtension/Extension.h>
42
43//--- Frameworks/InterfaceAndExtension.framework/Modules/module.modulemap
44framework module InterfaceAndExtension {
45  umbrella header "InterfaceAndExtension.h"
46  export *
47  module * { export * }
48}
49
50//--- Frameworks/Redirecting.framework/Headers/Redirecting.h
51#import <InterfaceAndExtension/InterfaceAndExtension.h>
52
53//--- Frameworks/Redirecting.framework/Modules/module.modulemap
54framework module Redirecting {
55  header "Redirecting.h"
56  export *
57}
58
59//--- test-compatible-extensions.m
60// Test adding through deserialization an extension with already declared ivars.
61
62// First create `ObjCInterface()` extension by parsing corresponding code.
63#import <InterfaceAndExtension/InterfaceAndExtension.h>
64// Now add the same extension through deserialization from the imported module.
65#import <Redirecting/Redirecting.h>
66@implementation ObjCInterface {
67  int ivarInImplementation;
68}
69@end
70// CHECK: @"_OBJC_$_INSTANCE_VARIABLES_ObjCInterface"
71// CHECK-SAME: [3 x %struct._ivar_t] [%struct._ivar_t { ptr @"OBJC_IVAR_$_ObjCInterface.ivarInExtension", {{.*}} }, %struct._ivar_t { ptr @"OBJC_IVAR_$_ObjCInterface.bitfieldIvarInExtension", {{.*}} }, %struct._ivar_t { ptr @"OBJC_IVAR_$_ObjCInterface.ivarInImplementation", {{.*}} }]
72
73
74//--- Frameworks/WithInlineIvar.framework/Headers/WithInlineIvar.h
75#import <InterfaceAndExtension/InterfaceAndExtension.h>
76@interface ObjCInterface() {
77@public
78  int accessedIvar;
79}
80@end
81static inline void inlinedIvarAccessor(ObjCInterface *obj) {
82  obj->accessedIvar = 0;
83}
84
85//--- Frameworks/WithInlineIvar.framework/Modules/module.modulemap
86framework module WithInlineIvar {
87  header "WithInlineIvar.h"
88  export *
89}
90
91//--- test-access-extension-ivar.m
92// Test accessing ivars from extensions.
93#import <InterfaceAndExtension/InterfaceAndExtension.h>
94@interface ObjCInterface() {
95@public
96  int accessedIvar;
97}
98@end
99#import <WithInlineIvar/WithInlineIvar.h>
100@implementation ObjCInterface
101- (void)test {
102  inlinedIvarAccessor(self);
103  ivarInExtension = 0;
104}
105@end
106// CHECK: @"_OBJC_$_INSTANCE_VARIABLES_ObjCInterface"
107// CHECK-SAME: [3 x %struct._ivar_t] [%struct._ivar_t { ptr @"OBJC_IVAR_$_ObjCInterface.accessedIvar", {{.*}} }, %struct._ivar_t { ptr @"OBJC_IVAR_$_ObjCInterface.ivarInExtension", {{.*}} }, %struct._ivar_t { ptr @"OBJC_IVAR_$_ObjCInterface.bitfieldIvarInExtension", {{.*}} }]
108
109
110//--- Frameworks/WithProperty.framework/Headers/WithProperty.h
111@interface NSObject @end
112@interface WithProperty: NSObject
113@property (assign) int propertyName;
114@end
115
116//--- Frameworks/WithProperty.framework/Modules/module.modulemap
117framework module WithProperty {
118  header "WithProperty.h"
119  export *
120}
121
122//--- Frameworks/BackingIvarInExtension.framework/Headers/BackingIvarInExtension.h
123#import <WithProperty/WithProperty.h>
124@interface WithProperty() {
125  int propertyBackingIvar;
126}
127@end
128
129//--- Frameworks/BackingIvarInExtension.framework/Modules/module.modulemap
130framework module BackingIvarInExtension {
131  header "BackingIvarInExtension.h"
132  export *
133}
134
135//--- test-synthesized-ivar.m
136// Test when an ivar is both synthesized and when declared in an extension.
137// Behavior with and without extension should be the same.
138#import <WithProperty/WithProperty.h>
139#ifdef IMPORT_EXTENSION
140#import <BackingIvarInExtension/BackingIvarInExtension.h>
141#endif
142@implementation WithProperty
143@synthesize propertyName = propertyBackingIvar;
144@end
145// CHECK: @"_OBJC_$_INSTANCE_VARIABLES_WithProperty"
146// CHECK-SAME: [1 x %struct._ivar_t] [%struct._ivar_t { ptr @"OBJC_IVAR_$_WithProperty.propertyBackingIvar", {{.*}} }]
147