Re: C++ ansi/pedantic problem



> On Mon, 27 Dec 1999, Karl Nelson wrote:
> > 
> > The gtk-- project is having a problem with one of the declarations
> > in the gtk+ headers.  Apparently, a compiler switch for checking
           ^^^^^^^^^^^^
> > for ansi violations in C++ code is also changing the nature of some 
> > of the declarations.  
> > 
> >   typedef void (*GtkSignalFunc) ();
> > 
> >      ==  void (*)(void)   default
> >      ==  void (*)(...)    -ansi -pedantic
> 
> In C++, the type GtkSignalFunc is declared as a pointer to a function that
> takes no parameters and returns void. If the -ansi -pedantic options bring
> about any other meaning, then the compiler is broken.

You misunderstand.  The typedef is in a C header file (gtk+) and thus
gets interpeted with the proper extern "C" as the C (1978) meaning with
the ansi switch.  Our code (C++) uses those typedefs and therefore
I want to fix its definition to the C++ one instead of having it mangled
by the extern statement.


> The only way to get the (...) meaning is to write a declarator with (...).

Not with the GNU C compiler.  () means (...) when in an extern "C" 
statement when ansi compience is on.  To my knowledge and the 
documentation of the compiler this is completely correct behavior.


> However, in the C language, the type is declared as a pointer to a
> (non-variadic) function  having an uknown number and types of arguments---thi
> s
> information will be deduced from the call.

And that is exactly what the compiler is doing.  It sees a declaration 
in an C linkage and uses the ansi C meaning.  This translates to 
void (*)(...).


> > This means that if unless the gtk+ library and the applications
> > are compiled with the same switchs there is linker errors for
> > C++ programs.  (A demo of how this is a problem is attached.)
> 
> Without looking at the attached code, I suspect that the problem might be
> related due to lack of proper extern "C" linkage specification.

If you bothered to look at the attached code you would have found
that the extern was documented as the problem!


> > The solution is to fix the declaration of GtkSignalFunc to 
> > the desired meaning when working with C++ compilers.
> > 
> > Replacing the declaration with 
> > 
> >   #ifdef __cplusplus
> >   typedef void (*GtkSignalFunc) (void);
> >   #else
> >   typedef void (*GtkSignalFunc) ();
> >   #endif
> 
> This is backwards. In C, the parameter list (void) fully specifies that the
> function doesn't take any parameters. In C++, the (void) parameter list is
> unnecessary, but supported for backward compatibility with C. You
> should never use (void) in C++ programs. It's a syntactic hack specifically
> introduced in ANSI C to solve problems unique to that language.

It is not in C++ code.  It is gtk+ C headers where (void) is required
to ensure correct meaning.

It is not backwards.  It is the meaning that we wish the achieve
that GtkSignalFunc takes no arguments.  But either would solve the
problem...  If you perfer I would guess this is the most correct
solution.

   #ifdef __cplusplus
   }
   typedef void (*GtkSignalFunc) (); // C++ interpretes this funny in extern
   extern "C" {
   #else
   typedef void (*GtkSignalFunc) ();
   #endif

or even 

   typedef void (*GtkSignalFunc) (void);

This is exactly the same meaning as I proposed.  The gtk+ code just must
be careful to use (void) and avoid () or place extern statements like
you see above.


> If you want to interface new C++ code with a C library which depends on
> the use of less-than-fully specified function types, you might have to
> resort to the (...) declaration, e.g.
> 
>     /* header file for brain-damaged C library */
>     #ifdef __cplusplus
>     typedef void (*callback_function_with_uknown_parameters)(...);
>     #else /* ANSI C */
>     typedef void (*callback_function_with_unknown_parameters)();
>     #endif

Actually, we don't really care what the specification is.  
int (*)(int) would work just fine.  I just need to fixed at one
type that is the same for all compiler settings and thus prevent
me for answering the same questions about "why doesn't this link"
every week for the next 2 years!


> The real solution in this case is to use a type that has a well defined
> parameter list, and stop writing in 1978 C once and for all.

Exactly what I am requesting.  In C, this means that you need to add
(void) and not use ().  C++ can interpet this correctly all the time
as what is meant.  (a function with no parameters).  I am
certainly not the one coding in 1978 C, I am just trying to
use the 1978 C that the gtk+ folks spit out.


Sorry for the tone, but you are making way too many assumptions
about who did the coding and what knowledge I have about the
problem.  I certainly don't need the full history leason of how
this constructs should be interpeted or whether the compiler is
broken.  I have had them many times before and they are irrelevent
because the compiler writers have chosen this meaning and are unlikely
to change.  We in the gtk-- project have been having this problem
pop up in our code for 2 years now and every time we kludge arround
it.  It only seems reasonable to solve in in gtk+ where the source
occurs so that gtk+ users that compile with the C++ compiler don't
face the same problem.  

--Karl



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]