ahatanak created this revision.
ahatanak added reviewers: rjmccall, theraven.
ahatanak added a project: clang.
Herald added subscribers: dexonsmith, jkorous.

clang currently emits different strings for `s0` and `s1` in the following code 
because pointers to typedefs are encoded as "^{PointeeClassName=#}" while ObjC 
pointer types that aren't pointers to typedefs are encoded as "@".

  @class Class1;
  
  typedef NSArray<Class1 *> MyArray;
  
  void foo1(void) {
    const char *s0 = @encode(MyArray *); // "^{NSArray=#}"
    const char *s1 = @encode(NSArray<Class1 *> *); // "@" 
  }

It seems that this was a deliberate choice made in r61387 to make clang 
compatible with gcc (see 
http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20081222/010465.html), 
but it causes apple's runtime to crash. This patch fixes the bug by checking 
whether the runtime is one of the GNU runtimes before using the special 
encoding for typedefs.

rdar://problem/50563529


Repository:
  rC Clang

https://reviews.llvm.org/D61974

Files:
  lib/AST/ASTContext.cpp
  test/CodeGenObjC/encode-test-6.m
  test/CodeGenObjC/encode-test.m
  test/CodeGenObjCXX/encode.mm

Index: test/CodeGenObjCXX/encode.mm
===================================================================
--- test/CodeGenObjCXX/encode.mm
+++ test/CodeGenObjCXX/encode.mm
@@ -242,6 +242,6 @@
 @end
 
 const char *expand_struct() {
-  // CHECK: @{{.*}} = private unnamed_addr constant [16 x i8] c"{N={S<N>=^{N}}}\00"
+  // CHECK: @{{.*}} = private unnamed_addr constant [13 x i8] c"{N={S<N>=@}}\00"
   return @encode(N);
 }
Index: test/CodeGenObjC/encode-test.m
===================================================================
--- test/CodeGenObjC/encode-test.m
+++ test/CodeGenObjC/encode-test.m
@@ -1,7 +1,8 @@
-// RUN: %clang_cc1 -triple i686-apple-darwin9 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -o %t %s
-// RUN: FileCheck < %t %s
+// RUN: %clang_cc1 -triple i686-apple-darwin9 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -o - %s |  FileCheck -check-prefix=MACOSX -check-prefix=CHECK %s
+// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -fobjc-runtime=gnustep-1.7 -emit-llvm -o - %s |  FileCheck -check-prefix=GNUSTEP -check-prefix=CHECK %s
+
 //
-// CHECK: @OBJC_METH_VAR_TYPE_{{.*}} = private unnamed_addr constant [16 x i8] c"v12@0:4[3[4@]]8\00"
+// MACOSX: @OBJC_METH_VAR_TYPE_{{.*}} = private unnamed_addr constant [16 x i8] c"v12@0:4[3[4@]]8\00"
 
 @class Int1;
 
@@ -95,7 +96,8 @@
 // CHECK: @g0 = constant [15 x i8] c"{Innermost=CC}\00"
 const char g0[] = @encode(struct Innermost);
 
-// CHECK: @g1 = constant [38 x i8] c"{Derived=#ib32b8b3b8sb16b8b8b2b8ccb6}\00"
+// MACOSX: @g1 = constant [38 x i8] c"{Derived=#ib32b8b3b8sb16b8b8b2b8ccb6}\00"
+// GNUSTEP: @g1 = constant [83 x i8] c"{Derived=#ib96i32b128i8b136i3b139I8sb176I16b192i8b200i8b208i2b210i8ccb240i6b248c0}\00"
 const char g1[] = @encode(Derived);
 
 // CHECK: @g2 = constant [9 x i8] c"{B1=#@c}\00"
@@ -107,7 +109,8 @@
 // CHECK: @g4 = constant [6 x i8] c"{S=i}\00"
 const char g4[] = @encode(const struct S);
 
-// CHECK: @g5 = constant [12 x i8] c"^{Object=#}\00"
+// MACOSX: @g5 = constant [2 x i8] c"@\00"
+// GNUSTEP: @g5 = constant [12 x i8] c"^{Object=#}\00"
 const char g5[] = @encode(MyObj * const);
 
 ////
@@ -133,10 +136,12 @@
 
 @implementation Derived1X @end
 
-// CHECK: @g6 = constant [18 x i8] c"{Base1X=b2b3b4b5}\00"
+// MACOSX: @g6 = constant [18 x i8] c"{Base1X=b2b3b4b5}\00"
+// GNUSTEP: @g6 = constant [31 x i8] c"{Base1X=b0I2b2i3b5i4b9I5b16c0}\00"
 const char g6[] = @encode(Base1X);
 
-// CHECK: @g7 = constant [27 x i8] c"{Derived1X=b2b3b4b5b5b4b3}\00"
+// MACOSX: @g7 = constant [27 x i8] c"{Derived1X=b2b3b4b5b5b4b3}\00"
+// GNUSTEP: @g7 = constant [54 x i8] c"{Derived1X=b0I2b2i3b5i4b9I5b16c0b16i5b21i4b25i3b32c0}\00"
 const char g7[] = @encode(Derived1X);
 
 // CHECK: @g8 = constant [7 x i8] c"{s8=D}\00"
@@ -184,10 +189,10 @@
 typedef typeof(sizeof(int)) size_t;
 size_t strlen(const char *s);
 
-// CHECK-LABEL: @test_strlen(
-// CHECK: %[[i:.*]] = alloca i32
-// CHECK: %[[call:.*]] = call i32 @strlen
-// CHECK: store i32 %[[call]], i32* %[[i]]
+// MACOSX-LABEL: @test_strlen(
+// MACOSX: %[[i:.*]] = alloca i32
+// MACOSX: %[[call:.*]] = call i32 @strlen
+// MACOSX: store i32 %[[call]], i32* %[[i]]
 void test_strlen() {
   const char array[] = @encode(int);
   int i = strlen(array);
Index: test/CodeGenObjC/encode-test-6.m
===================================================================
--- test/CodeGenObjC/encode-test-6.m
+++ test/CodeGenObjC/encode-test-6.m
@@ -34,7 +34,7 @@
 @synthesize property = _property;
 @end
 
-// CHECK: private unnamed_addr constant [24 x i8] c"^{BABugExample=@}16
+// CHECK: private unnamed_addr constant [8 x i8] c"@16
 
 // rdar://14408244
 @class SCNCamera;
@@ -52,7 +52,7 @@
     C3DCameraStorage _storage;
 }
 @end
-// CHECK: private unnamed_addr constant [39 x i8] c"{?=\22presentationInstance\22^{SCNCamera}}\00"
+// CHECK: private unnamed_addr constant [39 x i8] c"{?=\22presentationInstance\22@\22SCNCamera\22}\00"
 
 // rdar://16655340
 int i;
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -6970,11 +6970,12 @@
     }
 
     QualType PointeeTy = OPT->getPointeeType();
-    if (!Options.EncodingProperty() &&
+    if (getLangOpts().ObjCRuntime.isGNUFamily() &&
+        !Options.EncodingProperty() &&
         isa<TypedefType>(PointeeTy.getTypePtr()) &&
         !Options.EncodePointerToObjCTypedef()) {
-      // Another historical/compatibility reason.
-      // We encode the underlying type which comes out as
+      // If the runtime is one of the GNU family runtimes, encode the underlying
+      // type which comes out as
       // {...};
       S += '^';
       if (FD && OPT->getInterfaceDecl()) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to