https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89586

            Bug ID: 89586
           Summary: warning: cast between incompatible function types when
                    building libobjc
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libobjc
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ubizjak at gmail dot com
  Target Milestone: ---

This warning is emitted during gcc bootstrap from the time warning for invalid
function casts was introduced:

/space/homedirs/uros/gcc-svn/trunk/libobjc/sendmsg.c: In function
‘__objc_get_forward_imp’:
/space/homedirs/uros/gcc-svn/trunk/libobjc/sendmsg.c:129:16: warning: cast
between incompatible function types from ‘__big (*)(struct objc_object *, const
struct objc_selector *, ...)’ {aka ‘struct <anonymous> (*)(struct objc_object
*, const struct objc_selector *, ...)’} to ‘struct objc_object * (*)(struct
objc_object *, const struct objc_selector *, ...)’ [-Wcast-function-type]
  129 |         return (IMP)__objc_block_forward;
      |                ^
/space/homedirs/uros/gcc-svn/trunk/libobjc/sendmsg.c:131:16: warning: cast
between incompatible function types from ‘double (*)(struct objc_object *,
const struct objc_selector *, ...)’ to ‘struct objc_object * (*)(struct
objc_object *, const struct objc_selector *, ...)’ [-Wcast-function-type]
  131 |         return (IMP)__objc_double_forward;
      |                ^


We have following snippets in libobjc/sendmsg.c:

--cut here--
/* Various forwarding functions that are used based upon the
   return type for the selector.
   __objc_block_forward for structures.
   __objc_double_forward for floats/doubles.
   __objc_word_forward for pointers or types that fit in registers.  */
static double __objc_double_forward (id, SEL, ...);
static id __objc_word_forward (id, SEL, ...);
typedef struct { id many[8]; } __big;
#if INVISIBLE_STRUCT_RETURN 
static __big 
#else
static id
#endif
__objc_block_forward (id, SEL, ...);

...

/* Given a selector, return the proper forwarding implementation.  */
inline
IMP
__objc_get_forward_imp (id rcv, SEL sel)
{
  ...
        return (IMP)__objc_block_forward;
      else if (t && (*t == 'f' || *t == 'd'))
        return (IMP)__objc_double_forward;
      else
        return (IMP)__objc_word_forward;
    }
}
--cut here--

with IMP defined in libobjc/objc/objc.h:

--cut here--
/* An 'id' is an object of an unknown class.  The way the object data
   is stored inside the object is private and what you see here is
   only the beginning of the actual struct.  The first field is always
   a pointer to the Class that the object belongs to.  */
typedef struct objc_object
{
  /* 'class_pointer' is the Class that the object belongs to.  In case
     of a Class object, this pointer points to the meta class.

     Compatibility Note: The Apple/NeXT runtime calls this field
     'isa'.  To access this field, use object_getClass() from
     runtime.h, which is an inline function so does not add any
     overhead and is also portable to other runtimes.  */
  Class class_pointer;
} *id;

/* 'IMP' is a C function that implements a method.  When retrieving
   the implementation of a method from the runtime, this is the type
   of the pointer returned.  The idea of the definition of IMP is to
   represent a 'pointer to a general function taking an id, a SEL,
   followed by other unspecified arguments'.  You must always cast an
   IMP to a pointer to a function taking the appropriate, specific
   types for that function, before calling it - to make sure the
   appropriate arguments are passed to it.  The code generated by the
   compiler to perform method calls automatically does this cast
   inside method calls.  */
typedef id (*IMP)(id, SEL, ...); 
--cut here--

Reply via email to