GCC is re-implementing in C++ and C discarded

J

Jens Gustedt

Am 03.09.2012 17:38, schrieb Ike Naar:
(identifier-listopt) cannot expand to (void)
because void is not an identifier (it's a keyword).

Then it is even worse, and "void foo(void);" isn't captured by any of
the documented syntax at all. So it couldn't be parsed.

(But I don't think that there is a syntactical difference between
identifier and keyword.)

Jens
 
I

Ike Naar

Am 03.09.2012 17:38, schrieb Ike Naar:

Then it is even worse, and "void foo(void);" isn't captured by any of
the documented syntax at all. So it couldn't be parsed.

(parameter-type-list)
--6.7.6--> (parameter-list)
--6.7.6--> (parameter-declaration)
--6.7.6--> (declaration-specifiers abstract-declaratoropt)
--6.7.6--> (declaration-specifiers)
--6.7--> (type-specifier)
--6.7.2--> (void)
(But I don't think that there is a syntactical difference between
identifier and keyword.)

There is. 6.4.1 p2,

"The above tokens (case sensitive) are reserved (in translation phases
7 and 8) for use as keywords, and shall not be used otherwise."

where void is one of the "above tokens" (6.4.1).
 
H

Herbert Rosenau

Am 02.09.2012 00:59, schrieb Jens Gustedt:
Am 31.08.2012 23:40, schrieb (e-mail address removed):

Out of curiosity, why did the term prototype then never make it to a
syntactical definition? Do you agree with me that if we stick together
the current text as it stands we have that

- "void foo() { }" is a defintion of "foo"
- it is also a declaration
- it declares that "foo" has no parameters

No, it declares foo as a function with an unknown nuber of parameters
with onkown rypes each.
- so it also declares the types of these parameters (namely none)
- so it is a declaration of "foo" that declares the type of its parameters
- according to 6.2.1p2 it is a prototype

No, it is not a prototype because a prototype needs a complete list of
parameters and theyr types.

int foo/(; ist only a declaration
int foo(void); is a prototype and also a declaration because it defines
a complete list of all the parameters (none(.
int foo(<type> (optional parameter name), ...); with at least one but
optionally more parameters. This is both a prototype and a declaration
too but with the special meaning that there after the full declaration
of the mandatory parameter(s) before the ,... is required and ,... can
be replaced at current call with a list of 0 to n parameters (see
fprintf() for example.
 
J

Jens Gustedt

Am 03.09.2012 19:04, schrieb Ike Naar:
(parameter-type-list)
--6.7.6--> (parameter-list)
--6.7.6--> (parameter-declaration)
--6.7.6--> (declaration-specifiers abstract-declaratoropt)
--6.7.6--> (declaration-specifiers)
--6.7--> (type-specifier)
--6.7.2--> (void)

ah my bad, I had overlooked/forgotten that in 6.9.1p5
If the declarator includes a parameter type list, the declaration of
each parameter shall include an identifier,

there is this special exception
except for the special case of a parameter list consisting of a
single parameter of type void, in which case there shall not be an
identifier.

Jens
 
J

Jens Gustedt

Am 03.09.2012 21:48, schrieb Herbert Rosenau:
Am 02.09.2012 00:59, schrieb Jens Gustedt:

No, it declares foo as a function with an unknown nuber of parameters
with onkown rypes each.

How do you come to that "no". In 6.7.6.3p14 it says
An empty list in a function declarator that is part of a definition of
that function specifies that the function has no parameters.

so you are making the difference that a function "declarator" here
only "specifies" that the function has no parameters but the
declarator doesn't "declare" that it has no parameters?

Honestly, I am lost, linguistically.

I think term prototype should have been also defined by syntax,
perhaps in 6.2.5p20 where function types are introduced or even better
6.7.6.3p5 where a simple phrase could be added at the end:
Only if it is of the form D( parameter-type-list ) the declaration
provides a prototype for the function.

Jens
 
R

Richard Damon

Am 03.09.2012 21:48, schrieb Herbert Rosenau:

How do you come to that "no". In 6.7.6.3p14 it says


so you are making the difference that a function "declarator" here
only "specifies" that the function has no parameters but the
declarator doesn't "declare" that it has no parameters?

Honestly, I am lost, linguistically.

I think term prototype should have been also defined by syntax,
perhaps in 6.2.5p20 where function types are introduced or even better
6.7.6.3p5 where a simple phrase could be added at the end:


Jens

The key is that there are several levels of "declaring" a function. All
of the following provide a declaration.

int f1();
int f2(void);
int f3(i);
int f4(int i);
int f5() { return 0; }
int f6(void) { return 0;)
int f7(i) int i; { return i;}
int f8(int i) { return i; }

The even ones of these provide a prototype for fn, and will require a
diagnostic if called with an incorrect parameter. The odd fn do not
provide a prototype, and incorrect calls do not need a diagnostic.

f5-f8 provide definitions for fn, f1-f4 just are declarations,
presumable with a definition elsewhere if the function is called.

f5 has a definition that says that f5 is a function with 0 parameters,
but no prototype, so a later call of f5(1) does not require a
diagnostic, but does invoke undefined behavior if executed.

Note that the definitions that don't provide a prototype (sometimes
called K&R style) are still "valid" syntax, but I believe have been
depreciated. In C++, f1, and f5 are prototypes, and f3 and f7 are
constraint violations (all declarations/definitions provide a prototype
in C++, but not in C).
 
J

Jens Gustedt

Am 04.09.2012 01:37, schrieb Richard Damon:
The key is that there are several levels of "declaring" a function. All
of the following provide a declaration.

int f1();
int f2(void);
int f3(i);
int f4(int i);
int f5() { return 0; }
int f6(void) { return 0;)
int f7(i) int i; { return i;}
int f8(int i) { return i; }

The even ones of these provide a prototype for fn, and will require a
diagnostic if called with an incorrect parameter. The odd fn do not
provide a prototype, and incorrect calls do not need a diagnostic.

f5-f8 provide definitions for fn, f1-f4 just are declarations,
presumable with a definition elsewhere if the function is called.

f5 has a definition that says that f5 is a function with 0 parameters,
but no prototype, so a later call of f5(1) does not require a
diagnostic, but does invoke undefined behavior if executed.

Note that the definitions that don't provide a prototype (sometimes
called K&R style) are still "valid" syntax, but I believe have been
depreciated. In C++, f1, and f5 are prototypes, and f3 and f7 are
constraint violations (all declarations/definitions provide a prototype
in C++, but not in C).

Hm, I don't see what you are adding to the discussion so far. My point
was just that what constitutes the declaration of a prototype is not
sufficiently clear in the standard. You are just repeating the "common
belief" and not pointing out why f5 wouldn't be declaring one. (Please
look through the previous messages to see why I found that there is an
ambiguity, I noted it several times already.)

My point in the message that you are refering to was that the standard
would need such a clarification, and I was proposing a snippet that
would be sufficient to clarify this.

Jens
 
P

Phil Carmody

Johannes Bauer said:
Alright, then, since you do understand what I'm getting at but are
unwilling to recoginze the point, here's a more complete example.
Imagine there are 3 hardware platforms (these are about 10-20 in
reality) each which have 10 IRQ vectors (these at least 100 in reality):

hw1.h:
struct ivtlayout {
int vec1;
int vec2;
int vec3;
int vec6;
int vec4;
int vec7;
int vec9;
int vec5;
int vec8;
int vec0;
};

#define INIT_IVT(v0,v1,v2,v3,v4,v5,v6,v7,v8,v9) v1,v2,v3,v6,v4,v7,v9,v5,v8,v0
hw2.h:
struct ivtlayout {
int vec4;
int vec2;
int vec5;
int vec8;
int vec1;
int vec3;
int vec9;
int vec0;
int vec6;
int vec7;
};

+ similar define
hw3.h:
struct ivtlayout {
int vec7;
int vec6;
int vec9;
int vec8;
int vec4;
int vec1;
int vec3;
int vec0;
int vec5;
int vec2;
};

+ similar define

And note that to prevent redundant definition of the order, the structure
definition and the initialiser could be created from a generalisation of
the above.
Now you want to include for each version a IVT which specifies a value
for vector 8. C solution:

struct ivtlayout ivt = {
.vec8 = 1234,
};

struct ivtlayout ivt = {
INIT_IVT(0,0,0,0,0,0,0,0,1234,0)
};
I'll leave the C++ solution as an excersise to you. Hopefully you'll see
the point now.

That took me 20 seconds. How many hours should I bill you for if you think
it was hard work?

And if you think that using the preprocessor isn't C++, then what about the
following?

class ivtlayout {
int vec7;
int vec6;
//...

public:
ivt(int v0, int v1, int v2, /*...*/, int v8, int v9)
: vec7(v7), vec6(v6), /*...*/, vec8(v8), vec9(v9) {;}
};

ivtlayout ivt(0,0,0,0,0,0,0,0,1234,0);

E&OE, I've not programmed C++ to any significant extent for about a decade.

OK, the above took about 30s of thought, but over a minute of typing -
how many more hours can I bill you for?

Phil
 
T

Tim Rentsch

[...talking about different ways of defining 'main()'...]
The examples you cite do strongly imply that `int main(){}` was
*intended* to be a valid definition, as does the observation that
making it invalid would have broken pre-ANSI code, something the
C89 committee was generally careful to avoid. My argument is that
the wording of the standard does not accurately reflect this intent.

I'ts plausible that the committee meant for us to assume that `int
main(void){}` and `int main(){}` are "equivalent". They certainly are
equivalent *in some ways*. My reading is that they are *not* entirely
equivalent, and their partial equivalence is not enough to say that
they're "equivalent". This at least needs to be made clearer.

Obviously "equivalent" was meant to read in the sense of what the
calling sequence would be. I wouldn't mind a clarifying footnote,
but I don't think even that small a change is absolutely necessary.
 
T

Tim Rentsch

Jens Gustedt said:
Am 03.09.2012 21:48, schrieb Herbert Rosenau:

How do you come to that "no". In 6.7.6.3p14 it says


so you are making the difference that a function "declarator" here
only "specifies" that the function has no parameters but the
declarator doesn't "declare" that it has no parameters?

This is a settled question: asked in a Defect Report, and the
response is that this case does not provide a prototype. That
might not be the answer you want, but that's the answer.

Honestly, I am lost, linguistically.

I think term prototype should have been also defined by syntax,
perhaps in 6.2.5p20 where function types are introduced or even better
6.7.6.3p5 where a simple phrase could be added at the end:

I can't say I agree, but in any case if you want to do something
about it then further comments should be addressed to people
in WG14 (aka "the committee"). Since the question has been
asked and answered through a DR, and no changes have been
made to the text of the Standard, there isn't really anything
people in the newsgroup can do for you.
 
J

Johannes Bauer

#define INIT_IVT(v0,v1,v2,v3,v4,v5,v6,v7,v8,v9) v1,v2,v3,v6,v4,v7,v9,v5,v8,v0

Boy we're in for a treat. You're a C++ wizard.
struct ivtlayout ivt = {
INIT_IVT(0,0,0,0,0,0,0,0,1234,0)
};


That took me 20 seconds. How many hours should I bill you for if you think
it was hard work?

You should apply for a software patent for your ingenious solution. It's
probably worth millions. Marvellous!
And if you think that using the preprocessor isn't C++, then what about the
following?

class ivtlayout {
int vec7;
int vec6;
//...

public:
ivt(int v0, int v1, int v2, /*...*/, int v8, int v9)
: vec7(v7), vec6(v6), /*...*/, vec8(v8), vec9(v9) {;}
};

ivtlayout ivt(0,0,0,0,0,0,0,0,1234,0);

That doesn't fulfill the requirements. Please look at the generated code.
E&OE, I've not programmed C++ to any significant extent for about a decade.

And it shows.

Regards,
Johannes

--
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen
Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <[email protected]>
 
P

Phil Carmody

Johannes Bauer said:
Boy we're in for a treat. You're a C++ wizard.


You should apply for a software patent for your ingenious solution. It's
probably worth millions. Marvellous!

If you're attempting to be patronising, I feel obliged to point out
that it was you who was unable to come up with something and getting
in a flap about how it was impossible in C++. I'm sorry if proving
you wrong hurts your pride.

Phil
 
P

Phil Carmody

Johannes Bauer said:
Boy we're in for a treat. You're a C++ wizard.

Only relatively. You've not set the standard particularly high.


#if defined(REVERSE)

/* this goes in one header file */
template <int v0, int v1, int v2, int v3> struct IVT
{
IVT() { ; }
static const int ivt[4];
};
template <int v0, int v1, int v2, int v3> const int IVT<v0,v1,v2,v3>::ivt[4] = { v3, v2, v1, v0, };

#else

/* this goes in a different header file */
template <int v0, int v1, int v2, int v3> struct IVT
{
IVT() { ; }
static const int ivt[4];
};
template <int v0, int v1, int v2, int v3> const int IVT<v0,v1,v2,v3>::ivt[4] = { v0, v1, v2, v3, };

#endif

/* back in your C file */
static const IVT<0,0,1234,0> ivt=0; /* IRQ2 initialised, no matter where it is in the array */

#include <iostream>
int main()
{
std::cout << ivt.ivt[0] << ' ' << ivt.ivt[1] << ' ' << ivt.ivt[2] << ' ' << ivt.ivt[3] << std::endl;
return 0;
}



phil@geespaz:tmp$ g++ crap.c -o crap
phil@geespaz:tmp$ ./crap
0 0 1234 0
phil@geespaz:tmp$ g++ -DREVERSE crap.c -o crap
phil@geespaz:tmp$ ./crap
0 1234 0 0


Objdump confirms there's some .rodata with the appropriate values in the appropriate order.

Phil
 
J

Johannes Bauer

If you're attempting to be patronising, I feel obliged to point out
that it was you who was unable to come up with something and getting
in a flap about how it was impossible in C++. I'm sorry if proving
you wrong hurts your pride.

It is not possible in C++ to initialize structure members by their
names, which is the only nice solution that I know of. This doesn't hurt
my pride, it's a basic fact that you can read up in the C++ standard if
you find the time.

Your "solution" is having the exact same problem that a manually
initialized structure has: In a list of ~100 numbers, you need to set
exactly the correct one (i.e. count by hand).

Also, every definition file must include the union of all possible
vectors. You're making the problem much worse, not better. So if you're
really proposing this as a viable alternative you really have no idea at
all about how to write code that can be maintained well.

Regards,
Johannes

--
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen
Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <[email protected]>
 
J

Johannes Bauer

Only relatively. You've not set the standard particularly high.

You might want to look up the Dunning-Kruger effect.
/* back in your C file */
static const IVT<0,0,1234,0> ivt=0; /* IRQ2 initialised, no matter where it is in the array */

What if the selected architecture doesn't include the filled out vector
entry? Designated initializers: Compiler error. Your solution: Silent
discard.

What if a new architecture has a new vector entry that the others didn't
have? Designated initializers: Add it to the new definition structure.
You solution: Change all definition files to accomodate for it.
phil@geespaz:tmp$ ./crap

At least you named it correctly.

Regards,
Johannes

--
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen
Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <[email protected]>
 
P

Phil Carmody

Johannes Bauer said:
It is not possible in C++ to initialize structure members by their
names, which is the only nice solution that I know of. This doesn't hurt
my pride, it's a basic fact that you can read up in the C++ standard if
you find the time.

Your "solution" is having the exact same problem that a manually
initialized structure has: In a list of ~100 numbers, you need to set
exactly the correct one (i.e. count by hand).

Ah, sorry, yes, I was presuming the ability to count. If that doesn't apply,
you'll have a spot of bother in C++.

Phil
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,078
Messages
2,570,570
Members
47,204
Latest member
MalorieSte

Latest Threads

Top