http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49883

           Summary: clang + gcc 4.6 runtime = broken
           Product: gcc
           Version: 4.6.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libobjc
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: nic...@gcc.gnu.org


>From Jonathan Schleifer --

> the following code does not work when using Clang with the runtime of gcc 4.6:

#include <stdio.h>
#include <stdlib.h>

#import <objc/runtime.h>

@interface A
{
    Class isa;
}

+ alloc;
+ (Class)class;
@end

@interface B: A
@end

@implementation A
+ alloc
{
    A *instance = malloc(class_getInstanceSize(self));
    instance->isa = self;

    return instance;
}

+ (Class)class
{
    return self;
}

- (BOOL)isKindOfClass: (Class)class
{
    Class iter;

    for (iter = isa; iter != Nil; iter = class_getSuperclass(iter))
        if (iter == class)
            return YES;

    return NO;
}
@end

@implementation B
@end

int
main()
{
    B *b = [B alloc];

    printf("%d\n", [b isKindOfClass: [B class]]);
    printf("%d\n", [b isKindOfClass: [A class]]);

    return 0;
}

---

Upon further inspection, it seems likely that clang's Objective-C compiler, 
when compiling for the GNU runtime, is abusing some fields in the ABI.

In particular, it seems that clang is no longer setting the class->info field 
to 1 or 2, but to something like 17 or 18.  This is in my view a bug in clang, 
but I'm also aware that some users really do need this to be sorted out and 
backported to 4.6.x.

It should be possible to work around the problem by simply detecting the 17
or 18 when loading the class, and converting it to a 1 or 2.  I also produced a
preliminary (untested) patch to work around this problem --

Index: init.c
===================================================================
--- init.c    (revision 176090)
+++ init.c    (working copy)
@@ -643,6 +643,14 @@
      assert (CLS_ISMETA (class->class_pointer));
      DEBUG_PRINTF (" installing class '%s'\n", class->name);

+      /* Clang may set flags other than _CLS_CLASS and _CLS_META even
+     when compiling for the traditional ABI (version 8), confusing
+     our runtime.  Try to wipe these flags out.  */
+      if (CLS_ISCLASS (class))
+    __CLS_INFO (class) = _CLS_CLASS;
+      else
+    __CLS_INFO (class) = _CLS_META;
+
      /* Initialize the subclass list to be NULL.  In some cases it
     isn't and this crashes the program.  */
      class->subclass_list = NULL;

but was told that it doesn't work, so someone will now need to install clang
and figure out what is actually happening.

Thanks

Reply via email to