[comp.os.minix] C SYNTAX QUESTION

HBO043%DJUKFA11.BITNET@cunyvm.cuny.edu (Christoph van Wuellen) (04/10/90)

somenone pointed out that with my recetly posted C-compiler, the
funcion
test(a) char a;
{
write (1,&a,1);
}
passes a pointer to an integer to write (since a is really an integer)
write emits something else than you'd expected - it is easy to ,,fix''
in the compiler, BUT WHAT ABOUT
test(a) float a;
{
test1(&a);
}
This certainly passes a pointer to a double, and this can't be changed.
So I ask the C Syntax experts - what do you think a compiler should do
in both cases?
C.v.W.

tim@nucleus.amd.com (Tim Olson) (04/10/90)

In article <16304@nigel.udel.EDU> HBO043%DJUKFA11.BITNET@cunyvm.cuny.edu (Christoph van Wuellen) writes:
| somenone pointed out that with my recetly posted C-compiler, the
| funcion
| test(a) char a;
| {
| write (1,&a,1);
| }
| passes a pointer to an integer to write (since a is really an integer)
| write emits something else than you'd expected - it is easy to ,,fix''
| in the compiler, BUT WHAT ABOUT
| test(a) float a;
| {
| test1(&a);
| }
| This certainly passes a pointer to a double, and this can't be changed.
| So I ask the C Syntax experts - what do you think a compiler should do
| in both cases?
| C.v.W.


In non-ANSI C (and in ANSI C, in the absence of prototypes), function
parameters of type "char" and "short" are widened to int, and function
parameters of type "float" are widend to "double" by the caller:

	char c = 5;
	f(c);

will pass an int with value 5 to f.

If f is declared as:

	f(i)
	int i;

This is fine.  However, if f is declared as

	f(c)
	char c;

then the incoming integer must be converted to a character by the
compiler, then treated like a local variable declared as type "char".

Likewise, if a "float" is passed and converted to double by the
caller, then

	f(d)
	double d;

will work fine.  If f is declared

	f(d)
	float d;

then the incoming parameter must be converted from double-precision to
single-precision on entry by the compiler.

	-- Tim Olson
	Advanced Micro Devices
	(tim@amd.com)

MAB01057%UFRJ.BITNET@cornellc.cit.cornell.edu (Marcelo Amarante Ferreira Gomes) (04/11/90)

In a previous message, Chistoph van Wuellen <HBO043@DJUKFA11> writes
about problems with the function

test(a) float a;
{
test1(&a);
}

Since the message is addressed to 'C Sintax experts', I shouldn't be
answering to it, but I will anyway :-)

I believe that the compiler could (I don't know if it should) try the
following: on promoting the 'a' to double, copy it to another area of
memory (in the stack, maybe) and pass the pointer to that area. On return,
the code should copy the contents in there to the original float variable
'a', wich caused the whole mess.

I know this is not a very elegant solution, but I think it solves the
problem. I couldn't think of a code fragment in wich this approach would
cause any trouble. Can anyone out there think of it? :-)

                         Marcelo A. Ferreira Gomes (Wally Gator)

7103_2622@uwovax.uwo.ca (Eric Smith) (04/12/90)

In article <16304@nigel.udel.EDU>, HBO043%DJUKFA11.BITNET@cunyvm.cuny.edu (Christoph van Wuellen) writes:
> test(a) float a;
> {
> test1(&a);
> }
> This certainly passes a pointer to a double, and this can't be changed.
-- 
How about implementing this (and other promotions, like char->int) by
emitting the same code as for
test(_a) double _a;
{
  float a = (float)_a;
  test1(&a);
}?
This is the most user-friendly solution (although, it's
harder for the compiler writer).
--
Eric R. Smith                     email:
Dept. of Mathematics            ERSMITH@uwovax.uwo.ca
University of Western Ontario   ERSMITH@uwovax.bitnet
London, Ont. Canada N6A 5B7
ph: (519) 661-3638

HBO043%DJUKFA11.BITNET@cunyvm.cuny.edu (Christoph van Wuellen) (05/28/90)

In the ST-1.5 distribution, kernel/stvdu.c, there is a function
with body (flush) and the EXTERN (extern) attribute.
Is this legal?
My compiler compiled that function OK, but did not export the function
name since it was not global, so the linker gave an error.
The ,,fix'' to the compiler is trivial:
if (function with body AND storage class is extern) THEN set storage class
to global.

The question is: should I do this with the compiler, producing another
patch, or is it an error in stvdu.c?

C.v.W

archer%segin4.segin.fr@prime.com (Vincent Archer) (05/28/90)

Christoph van Wuellen <HBO043@DJUKFA11.BITNET> writes:
> In the ST-1.5 distribution, kernel/stvdu.c, there is a function
> with body (flush) and the EXTERN (extern) attribute.
> Is this legal?

It is. In K&R's C langage definition, they say that the functions have the
extern storage class by default, and the global storage class is implied. So
it seems perfectly legal to say "this function is external(ly accessible)!".
Anyway, stvdu should be fixed, it seems more logical to define flush() as
PUBLIC rather than EXTERN.

> The ,,fix'' to the compiler is trivial:
> if (function with body AND storage class is extern) THEN set storage class
> to global.
>
> The question is: should I do this with the compiler, producing another
> patch, or is it an error in stvdu.c?

I think you'll have to produce patch #3! :-)

(btw: If you gain 300 Dhrystones by compiling using C68K, I'll have a go at
      once! No more ACK - Sorry, ast - for me)


    Vincent


Vincent Archer                   | Email:archer%segin4.segin.fr@prime.com
"People that are good at finding excuses are never good at anything else"

HBO043%DJUKFA11.BITNET@cunyvm.cuny.edu (Christoph van Wuellen) (02/01/91)

Is this correct, and if so, why?

test()
{
int i;
void void_function();

...

i ?  void_function() : 0;
}

In GNU GAS, file obstack.h, many macros of such type are declared, and
my c68/c386 compiler complains about that..

Of course,

i ? void_function() : (void) 0;

works. c68 knows that 0 is a legal pointer of any type in the Syntax, but
what about void?
Since c68 claims to be K&R, and my copy of K&R does not mention void,
I would appreciate a syntax rule. The implementation into the compiler
is not that problem, but what is the exact rule?
C.v.W.

tim@proton.amd.com (Tim Olson) (02/01/91)

In article <43415@nigel.ee.udel.edu> HBO043%DJUKFA11.BITNET@cunyvm.cuny.edu (Christoph van Wuellen) writes:
| Is this correct, and if so, why?
| 
| test()
| {
| int i;
| void void_function();
| 
| ...
| 
| i ?  void_function() : 0;
| }
| 
| In GNU GAS, file obstack.h, many macros of such type are declared, and
| my c68/c386 compiler complains about that..

Yes, it should.  void and int are incompatible types.

| Of course,
| 
| i ? void_function() : (void) 0;
| 
| works. c68 knows that 0 is a legal pointer of any type in the Syntax, but
| what about void?

Yes, 0 is a legal pointer of any type, including void, but
void_function() is of type "void", not "void *".


--
	-- Tim Olson
	Advanced Micro Devices
	(tim@amd.com)

kls@ditka.Chicago.COM (Karl Swartz) (02/04/91)

In article <43415@nigel.ee.udel.edu> HBO043%DJUKFA11.BITNET@cunyvm.cuny.edu (Christoph van Wuellen) writes:
>Is this correct, and if so, why?

(all but critical fragments deleted)

>void void_function();

>i ?  void_function() : 0;

>In GNU GAS, file obstack.h, many macros of such type are declared, and
>my c68/c386 compiler [K&R] complains about that..

>i ? void_function() : (void) 0;

>works.

For a strictly K&R compiler the question is irrelevant since there is
no void type in K&R.  If c68/c386 is a "K&R+" compiler, with a few
additions such as void, the rules are whatever the compiler writers
decided made sense to them.

For ANSI C, going by the old draft that I have at hand, the first
version of the code (without the cast to void on the third operand)
is not legal C.  The conditional operator is described in section
3.3.15, with the following constraints:

    The first operand shall have scalar type.

    One of the following shall hold for the second and third operands:

  * both operands have arithmetic type;

  * both operands have the same structure or union type;

  * both operands are pointers to the same type;

  * both operands are pointers to objects that have qualified or
    unqualified versions of the same type;

  * both operands have void type;

  * one operand is a pointer and the other is a null pointer constant;
    or

  * one operand is a pointer to an object or incomplete type and the
    other is a pointer to void.

One operand of type void and the other of type int don't meet these
constraints.

One compiler that I encountered (an older version of VAX-11 C for VMS)
didn't even allow a void *result* from a conditional expression, which
required a bit of hackery along the lines of:

    void void_function();

    (void) i ? (void_function(), 0) : 0;

Blech!

-- 
Karl Swartz		|INet	kls@ditka.chicago.com
1-408/223-1308		|UUCP	{uunet,decwrl}!daver!ditka!kls
			|Snail	1738 Deer Creek Ct., San Jose CA 95148
"It's psychosomatic.  You need a lobotomy.  I'll get a saw." (Calvin)

webber@csd.uwo.ca (Robert E. Webber) (02/04/91)

In article <1991Feb1.155656.27244@mozart.amd.com> tim@amd.com (Tim Olson) writes:
.In article <43415@nigel.ee.udel.edu> HBO043%DJUKFA11.BITNET@cunyvm.cuny.edu (Christoph van Wuellen) writes:
.| Is this correct, and if so, why?
.| test()
.| {
.| int i;
.| void void_function();
.| ...
.| i ?  void_function() : 0;
.| }
.| 
.| In GNU GAS, file obstack.h, many macros of such type are declared, and
.| my c68/c386 compiler complains about that..
.
.Yes, it should.  void and int are incompatible types.

The gcc compiler has no problem with this mixture of void with
non-void (sort of metaphysical, ain't it).  Of course, gcc is
pre-ANSI.  It seems that an ANSI compiler should complain, for
example, if you compiled the above with gcc with both the options
-ansi and the options -pedantic, then it would issue a warning.  Gcc
appears to be using a rule that is a bit more general than the ANSI
table of chaos for the conditional expressions.  In general, gcc tends
to be a bit more orthogonal in its interpretation of the semantics of
various constructs than other C compilers.  Unfortunately, the ANSI
people don't seem to have picked up on this even though the GNU
compiler was out long before the ANSI specs.  For that matter,
Harbison & Steele seems to ignore the GNU compiler as it surveys C
compiler variations.  With the GNU compiler et al being ported to those
Minix systems that have the memory to support it, we will doubtless
being seeing more of these variances over time.

If the GNU project has ANSI compliance as part of their coding goals, then
it would be worthwhile mentioning this problem with GAS source to them.  

--- BOB (webber@csd.uwo.ca)