block-pointer-type.c   [plain text]


/* APPLE LOCAL file radar 5732232 - blocks */
/* Test that mixup of a pointer type and a block pointer type does not cause program to crash. */
/* { dg-do run { target *-*-darwin[1-2][0-9]* } } */
/* { dg-options "-fblocks" } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "-m64" } { "" } } */

void * _NSConcreteStackBlock;
#ifndef _BLOCK_PRIVATE_H_
#define _BLOCK_PRIVATE_H_

enum {
    BLOCK_NEEDS_FREE =        (1 << 24),
    BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
    BLOCK_NO_COPY =           (1 << 26), // interim byref: no copies allowed
    BLOCK_IS_GC =             (1 << 27),
};

struct Block_basic {
    long reserved;
    //char flags; char size; short refcount;
    int Block_flags;  // int32_t
    int Block_size; // XXX should be packed into Block_flags
    void (*Block_invoke)(void *);
    void (*Block_copy)(void *dst, void *src);
    void (*Block_dispose)(void *);
};

struct Block_byref {
    long reserved;
    struct Block_byref *forwarding;
    int refcount;
    int size;
    void (*byref_keep)(struct Block_byref *dst, struct Block_byref *src);
    void (*byref_destroy)(struct Block_byref *);
};

/* runtime entry for destroying shared data blocks */
void Block_destroy_byref(struct Block_byref *shared_struct);
/* runtime entry for sharing shared data blocks */
struct Block_byref *Block_share_byref(struct Block_byref *shared_struct);

/* runtime entry to get total size of a block */
int Block_size(struct Block_basic *aBlock);

// set the allocator/deallocator pair (used by ObjC to establish GC)
void _Block_set_allocator_pair(void *(*alloc)(const unsigned long), void (*dealloc)(const void *));

#endif

int GlobalInt;
void setGlobalInt(int value) { GlobalInt = value; }
int getGlobalInt() { int tmp = GlobalInt; GlobalInt = 0; return tmp; }


//
// Example block code generated for specific Blocks
//

//
// Partially bound block referencing const and byref args
//

/* Inclusion of this block block causes program to crash, even though it does not envoke it */
#if __BLOCKS__
int parameters_example_real(int verbose) {
    int desiredValue = 100;
    void (^myBlock)(int);
    myBlock = ^ (int param) {
        setGlobalInt(param);
    };
    myBlock(desiredValue);
    int globalValue = getGlobalInt();
   // if (error_found("parameters_real", globalValue, desiredValue, verbose)) return 1;
    return 0;
}

#endif __BLOCKS__

struct parameters_example_struct {
    struct Block_basic base;
};

// the "thunks" compiled for the invoke entry point of the parameters_example

void invoke_parameters_example(struct parameters_example_struct *aBlock, int param) {
  {
    setGlobalInt(param);
  }
}


// The rewritten version of the code above

int parameters_example(int verbose) {
    int desiredValue = 100;
    struct parameters_example_struct literal = {
        { 0, 0, sizeof(struct parameters_example_struct),
            (void (*)(void *))invoke_parameters_example,
        },
    };
    struct parameters_example_struct *myBlock = &literal;

    // get a type correct function pointer for the invocation function
    void (*correct)(struct parameters_example_struct *, int);
    correct = (void (*)(struct parameters_example_struct *, int))myBlock->base.Block_invoke;
    // call the block with itself as first arg and the parameter 100
    correct(myBlock, desiredValue);

    return 0;

}

int main(int argc, char *argv[]) { parameters_example(1); return 0; }