From: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Subject: Re: Standard library functions and macros
Organization: Computer Science, University of Melbourne, Australia
Date: Sat, 2 Jan 1993 15:22:04 GMT

jimad@microsoft.com (Jim Adcock) writes:

>jss@lucid.com (Jerry Schwarz) writes:
>|jimad@microsoft.com (Jim Adcock) writes:
>|
>||> Yes, assuming by "the meaning" of a C program you mean "the intent
>||> of the original C author."  For example, the original author can
>||> do a '#undef putchar' with "the meaning" that in this compilation his/her
>||> intent is that putchar be implemented out-of-line.  Under the proposed
>||> required changes to C++ implementations, "the meaning" of the original
>||> C author would be silently changed.  Thus someone porting this C program
>||> to C++ finds [or worse, DOESN'T FIND!] that C++ silently changes the 
>||> intent of the original author.
>|
>|There is no such guarantee in standard C.  If there is a #include <stdio.h>
>|present, a compiler is free to inline putchar whether or not the user
>|does #undef putchar.  The constraint is in the other direction.  A
>|programmer can't use "putchar" in specific ways unless an #undef appears.
>
>On the contrary, standard C DOES guarantee implementors the right
>to implement standard functions as macros,

Yes...

>DOES guarantee that 
>programmers can get to a guaranteed underlying actual function
>call implementation of the standard functions, and DOES guarantee that the 
>#undef will get the programmer to the function call implementation.

I don't think this is the case - as Steve Clamage pointed out, the "as if"
rule allows inline expansion despite the #undef.

>The fact that macro implementations are allowed under ANSI reserves the
>entirety of the name space of a standard function to the library if
>the header is included.  If the programmer doesn't like this, then
>the programmer is permitted to simply declare the function required
>out of the standard library, and just use that.  Which your changes
>will also break.

I would be surprised if the changes did not require "real" external functions
"shadowing" the inline definitions just as ANSI C required real functions
to shadow macro definitions. I think that perhaps you are overreacting a
little, Jim. Could someone who has actually read (or written ;-) the changes
confirm that they would not break
	extern char *puts(const char *);
	inti main() { puts("Hello world\n"); return 0; }
?

>|If Jim is saying that in a particular implementation the #undef has
>|this effect and believes that effect should be preserved, then nothing
>|stops an implementation from giving the #undef the same effect in C++,
>|although I suspect he will have to lobby his vendors very hard to
>|convince them to implement such a feature.
>
>If this is possible, then show me how to do it, because the solution
>is not obvious to me.

Step 1. Introduce a #pragma no-inline, eg.

	#pragma no-inline putchar	// don't inline any function
					// called putchar

This should not pose much implementation difficulty.
(Many compilers already allow a #pragma which has the same effect but
works on all inline functions, rather than a particular one at a time.)

Step 2. Ensure that if foo is not a macro, then
	#undef foo
has the same effect as
	#pragma no-inline foo
This should be even easier to implement.

>|I'm not sure I understand this.  Is the intented example that 
>|there might be something like
>|
>|	#define putchar __myputchar
>|
>|And __myputchar would then be callable in different ways?   
>
>No, the intended example would be if a macro-defined putchar were
>called with a parm not of char [actually int] type.  My claim is that
>a conforming implementation can have a macro-definition that accepts
>a superset of the parms that are strictly required to be accepted.
>
>This might argue that it would be good to allow implementors to 
>use multiple inlines for some standard C library calls, such that
>those inlines are optimal for a given parm type.  Or that templated
>versions of some of the C standard functions could be appropriate.
>But in these cases the entirety of the name space would remain to
>the implementor, not to the programmer.

This is not correct. In the first case, the name would only be reserved
for use as an external identifier. Programmers could still use that
name for member functions, for example.

I think you could make a strong argument for allowing multiple inline
implementations, in particular reserving the function name with any arguments
that could be converted to the appropriate type by a standard
conversion. I don't think you should allow templated versions.

>The problem lies with
>the fact that now, at this late date, you guys are trying to take
>part of the name space back from the implementor returning it to the
>programmer to do with as they will.  This is certain to break things.

I disagree. The pure namespace generally occurs only if you invoke the
compiler with the pure ANSI flag (well, this is true of both of the lines
of C++ compilers that I have any experience with). Conforming but not
strictly conforming programs might break if you compiled them with such
a flag enabled, but why would you do so? Such programs often rely
on additional functions which are declared in the standard headers
when the pure ANSI flag is not enabled.

>Again, I suggest that unless you have a very serious reason for requiring
>changes to existing standard C libraries, leave well enough alone.

They do.

-- 
Fergus Henderson             fjh@munta.cs.mu.OZ.AU      
This .signature virus is a self-referential statement that is true - but 
you will only be able to consistently believe it if you copy it to your own
.signature file!