www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 19017] New: Calling objc method returning struct segfaults


          Issue ID: 19017
           Summary: Calling objc method returning struct segfaults
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Mac OS X
            Status: NEW
          Severity: critical
          Priority: P1
         Component: dmd
          Assignee: nobody puremagic.com
          Reporter: doob me.com

Calling an Objective-C method that returns a struct that is too big to fit in
registers will result in a segmentation fault when accessing fields of the
returned struct. Example:

// foo.m

#import <Foundation/Foundation.h>

typedef struct
    int a, b, c, d, e;
} Bar;

 interface Foo : NSObject
-(Bar) getValue;

 implementation Foo
-(Bar) getValue
    Bar s = { 3, 3, 3, 3, 3 };
    return s;

// main.d

extern (C) int printf(in char*, ...);

struct Bar
    int a, b, c, d, e;

extern (Objective-C)
interface Foo
    static Foo alloc()  selector("alloc");
    Foo init()  selector("init");
    Bar getValue()  selector("getValue");

void main()
    auto f = Foo.alloc.init;
    auto b = f.getValue;
    printf("%d\n", b.a);

Compile with:
clang foo.m -o foo.o
dmd main.d foo.o -L-framework -LFoundation

Running this in a debugger results in:

lldb main
(lldb) target create "main"
Current executable set to 'main' (x86_64).
(lldb) r
Process 84149 launched: 'main' (x86_64)
Process 84149 stopped


->  0x7fff6ac2030a <+0>: movdqa %xmm0, (%rsp)
    0x7fff6ac2030f <+5>: int3

    0x7fff6ac20310 <+0>: pushq  %rbp
    0x7fff6ac20311 <+1>: movq   %rsp, %rbp
Target 0: (main) stopped.
(lldb) bt


main`_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv + 40

main`_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ7tryExecMFMDFZvZv + 32

main`_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZv + 139

main`_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ7tryExecMFMDFZvZv + 32

An Objective-C call like "f.getValue" is supposed to be lowered to this C call

Bar tmp;
objc_msgSend_stret(&tmp, f, "getValue");

As far as I know this is the same ABI as a regular C function returning a

[1] For more details see the Objective-C ABI documentation:

Jun 23 2018