ISO/ IEC JTC1/SC22/WG21 N0722

 
Accredited Standards Committee X3       Doc No: X3J16/95-0122   WG21/N0722
Information Processing Systems          Date:    Jun 30, 1995   Page 1 of 4
Operating under the procedures of       Project: Programming Language C++
American National Standards Institute   Ref Doc: X3J16/94-0034   WG21/N0421
                                        Reply to: Josee Lajoie
                                                  (josee@vnet.ibm.com)
 
 
extern "C" and the C++ type system (Revision 1)
==================================

This is the second version (almost identical to the first) of a paper  
presented to the committee in the Pre San Diego mailing (March 94). This
topic was never discussed by the committee and I believe should be before
we can mark the issue closed.
 
 
1.  Problem
    -------
 
  Is the linkage specified in a linkage-specification part of the
  function type?  
 
  Because the C portion of the C++ standard library contains functions that take
  pointers to functions, the answer to this question cannot be left as
  implementation-defined:
 
    17.4.7 Signal Handling
           (the same as 7.7 of the ISO C Standard)
    void  (*signal (int sig, void (*func) (int)) ) (int);
 
    17.4.10.5 Searching and sorting utilities
           (the same as 7.10.5 of the ISO C Standard)
    void  *bsearch (const void *key, const void *base,
                    size_t nmemb, size_t size,
                    int (*compar) (const void *, const void *) );
    void  *qsort (void *base, size_t nmemb, size_t size,
                  int (*compar) (const void *, const void *) );
 
  It is important to specify in the C++ standard if these functions take
  pointers to functions with C linkage or pointers to functions with C++
  linkage.  On some systems, C functions and C++ functions may have
  different calling conventions and calling a function using a pointer to
  function with the "wrong" linkage may result in a failure at runtime.
 
 
2.  linkage-specifications influence a function type
    ------------------------------------------------
 
  Proposal 1:
  ----------
  The linkage specified by an extern "C" linkage-specification is part of a 
  function type.
 
  I can see two ways to do this.
 
2.1  A linkage-specification affects all function types in a declaration
     -------------------------------------------------------------------
 
  The linkage-specification 'extern "C"' affects all the function
  types in a declaration. Therefore, the declaration:
 
    extern "C" void  (*signal (int sig, void (*func) (int)) ) (int);
 
  gives the function 'signal' the following type:
 
    function with "C" linkage taking
      1 parameter of type "int"  and
      1 parameter of type "pointer to function with "C" linkage"
    and returning a pointer to function with "C" linkage.
 
 
2.2  A linkage-specification only affects the type of the declarator
     ---------------------------------------------------------------
 
  The linkage-specification 'extern "C"' only affects the type of the
  declarator. Therefore, the declaration:
 
    extern "C" void  (*signal (int sig, void (*func) (int)) ) (int);
 
  gives the function 'signal' the following type:
 
    function with "C" linkage taking
      1 parameter of type "int"  and
      1 parameter of type "pointer to function with "C++" linkage"
    and returning a pointer to function with "C++" linkage.
 
  How would one declare 'signal''s second parameter type and return type
  to be pointer to functions with "C" linkage? Typedefsi must be used:
 
    extern "C" typedef void handler_type(int);
    extern "C" handler_type* signal (int sig, handler_type* func) ;
 
 
2.3 Discussion:
    ----------
 
  I have a slight preference for 2.2 because it is more explicit but
  I must say that neither of these solutions comes out as a clear
  winner.
 
 
  Solution 2.1:
  ------------
  This solution serves the C library (and therefore old code) well.  I
  assume that when users of a C library write:
 
    extern "C" void  (*signal (int sig, void (*func) (int)) ) (int);
 
  they want all function types to have C linkage.  After all, the
  library routine is most certainly written to accept and return a
  function with "C" linkage.
 
  This solution however renders it more difficult to declare functions
  that have parameters of function type with different linkage type.
  For example:
 
    extern "C++" typedef void func_type(int);
    extern "C"   int f(func_type* parm);
 
  What is the linkage of the function pointed at by 'parm'? "C" or "C++"?
  If it is "C++", then why is it that the 'extern "C"'
  linkage-specification didn't affect all the function types in the
  declaration?
 
 
  Solution 2.2
  ------------
  As described above, this solution is more flexible. It allows users  
  to separate the linkage of a function with that of its parameters or
  return type.  For example, in the declaration of 'f':
 
    extern "C" void f ( int (*pf) (int) );
 
  the linkage-specification applies only to 'f' and not to 'pf'.
 
  However this solution can appear to be more cumbersome since typedefs
  are required to declare functions (like 'signal') in the C library.
 
  Another question that has to be answered if solution 2.2 is adopted
  is: to what type of declarator can a linkage specification apply?
 
  2.2.1  a function type, obviously
 
  2.2.2  should a pointer to function type be influenced by a
         linkage-specification?
 
    For example:
 
      extern "C" int (*pf) (int);
 
    does this declaration declare a pointer to a "C" function, is the
    linkage-specification ignored or is the declaration in error?
 
  2.2.3  should other declarator types convey linkage as well?
 
    For example:
 
      extern "C" void (*a[3]) (int);
 
    does this declaration declare an array of pointers to "C" functions
    is the linkage-specification ignored or is the declaration in error?
 
  Of all these 3 points, I would definitely allow point 2.2.1, and
  definitely disallow point 2.2.3.  I am ambivalent regarding point
  2.2.2.  I would prefer to disallow it and say that a
  linkage-specification only applies to a declarator of function type,
  but this doesn't accurately reflect current practice.  On some
  implementations, linkage-specifications influence the type of a
  pointer.
 
 
  Proposal 2:
  ----------
  An extern "C" linkage-specification affects the type of a declarator 
  introduced by a function declaration or by a typedef declaration declaring 
  a function type. 
  [solutions 2.2 and 2.2.1 above]
 
 
3.  Type Conversions
    ----------------
 
  Proposal 3:
  ----------
  A C++ function and an extern "C" function have different types.
  No implicit conversion exits between pointers to functions with different 
  linkages.  Explicit type conversions (reinterpret_casts?) are allowed between 
  pointers to functions with different linkages.
 
  This implies that two pointers to functions with different linkages
  have different types and cannot be assigned to the one another, cannot
  be used to initialize one another, ... .
 

4.  Overloading
    -----------
 
  The working paper already says in 7.5 Linkage specifications
    "At most one of a set of functions of overloaded functions with a
     particular name can have C linkage."
 
  This is sufficient.