What would be the right warning/error?

J

jacob navia

Consider this code

static typedef struct {
int boo;
} FOO;

This provokes with MSVC:
------------------------------
Microsoft (R) C/C++ Optimizing Compiler Version 14.00.50727.762 for x64
Copyright (C) Microsoft Corporation. All rights reserved.

tstruct.c
tstruct.c(1) : error C2159: more than one storage class specified
------------------------------

With gcc we have:
----------------------------
root@ubuntu-vm:/tmp# gcc t.c
t.c:1: error: multiple storage classes in declaration specifiers
----------------------------

With lcc-win I had
Warning tstruct.c: 1 multiple types in a declaration. Last will be
used: 'typedef'

with lcc-win64
------------------------------
Warning tstruct.c: 1 multiple use of 'typedef'
------------------------------

All those warnings are misleading in my opinion. I have changed the
wording to:
Warning tstruct.c: 1 typedefs can't be static. Static keyword ignored

I think that this is much more clear but I have now some doubts:

Is this true?

My reasoning is that the static keyword can only apply to an
object, and a typedef is not an object. (Obviously there is
another obscure meaning to "static". Let's leave that for now)

Another problem is that both msvc and gcc say something about
"multiple storage classes" that I can't understand. Why that?

Note too that lcc-win issues just a warning. The other two issue
an error and compilation fails. Is this such a bad error that
warrants a failure to compiler the code?
 
B

Bartc

jacob navia said:
Consider this code

static typedef struct {
int boo;
} FOO;

This provokes with MSVC:
------------------------------
Microsoft (R) C/C++ Optimizing Compiler Version 14.00.50727.762 for x64
Copyright (C) Microsoft Corporation. All rights reserved.

tstruct.c
tstruct.c(1) : error C2159: more than one storage class specified

Another problem is that both msvc and gcc say something about
"multiple storage classes" that I can't understand. Why that?

I think that typedef is itself considered a storage class specifier (like
static), for purposes of syntax. And presumably you're only allowed one at a
time:

static int *a[10]; /* declares a variable a with static storage */
typedef int *b[10]; /* declares a type alias b */
 
C

crisgoogle

Consider this code

static typedef struct {
int boo;

} FOO;

This provokes with MSVC:
------------------------------
Microsoft (R) C/C++ Optimizing Compiler Version 14.00.50727.762 for x64
Copyright (C) Microsoft Corporation. All rights reserved.

tstruct.c
tstruct.c(1) : error C2159: more than one storage class specified
------------------------------

With gcc we have:
----------------------------
root@ubuntu-vm:/tmp# gcc t.c
t.c:1: error: multiple storage classes in declaration specifiers
----------------------------

With lcc-win I had
Warning tstruct.c: 1 multiple types in a declaration. Last will be
used: 'typedef'

with lcc-win64
------------------------------
Warning tstruct.c: 1 multiple use of 'typedef'
------------------------------

All those warnings are misleading in my opinion. I have changed the
wording to:
Warning tstruct.c: 1 typedefs can't be static. Static keyword ignored

I think that this is much more clear but I have now some doubts:

Is this true?

Is what true? That the warnings are misleading? Well, "uninformative"
perhaps. That your warning is more explicit? Sure, okay. That typedefs
can't be static? Yes.
My reasoning is that the static keyword can only apply to an
object, and a typedef is not an object. (Obviously there is
another obscure meaning to "static". Let's leave that for now)

Another problem is that both msvc and gcc say something about
"multiple storage classes" that I can't understand. Why that?

I'm no compiler writer, but I'm guessing it's just the way the
compiler parses the code. "typedef" isn't a storage class (I don't
think <duck>), but it's certainly not a type either, which is what
would otherwise be required after that "static". I've seen many
compiler errors and warnings that are _far_ more obscure than this.
Note too that lcc-win issues just a warning. The other two issue
an error and compilation fails. Is this such a bad error that
warrants a failure to compiler the code?

Unless, as an extension, you document that construct to mean something
useful, I see no reason to allow the code to compile. It's almost
meaningless as it stands, won't compile on at least a couple of other
mainstream compilers, and is so simply fixed that a hard error seems
appropriate to me.
 
C

crisgoogle

I'm no compiler writer, but I'm guessing it's just the way the
compiler parses the code. "typedef" isn't a storage class (I don't
think <duck>),

<snip>

Oops, and thirty seconds after posting, I look it up, and lo and
behold, "typedef" _is_ a storage class specifier ...

Sigh.
 
K

Keith Thompson

[My posts via rr.com still aren't showing up on aioe.org, so I'm
posting this through aioe.org so jacob can see it. I'm continuing
to post most of my articles through rr.com]

jacob navia said:
Consider this code

static typedef struct {
int boo;
} FOO;

This provokes with MSVC:
------------------------------
Microsoft (R) C/C++ Optimizing Compiler Version 14.00.50727.762 for x64
Copyright (C) Microsoft Corporation. All rights reserved.

tstruct.c
tstruct.c(1) : error C2159: more than one storage class specified

Both of those seem reasonable.
With lcc-win I had
Warning tstruct.c: 1 multiple types in a declaration. Last will be
used: 'typedef'

with lcc-win64
------------------------------
Warning tstruct.c: 1 multiple use of 'typedef'
------------------------------

All those warnings are misleading in my opinion. I have changed the
wording to:
Warning tstruct.c: 1 typedefs can't be static. Static keyword ignored

I think that this is much more clear but I have now some doubts:

Is this true?

The warning is correct, as far as it goes, but the fact that your
diagnostic *doesn't* refer to multiple storage classes makes me
concerned that you might be missing some other cases.
My reasoning is that the static keyword can only apply to an
object, and a typedef is not an object. (Obviously there is
another obscure meaning to "static". Let's leave that for now)

Another problem is that both msvc and gcc say something about
"multiple storage classes" that I can't understand. Why that?

C99 6.7.1p3:

The typedef specifier is called a storage-class specifier for
syntactic convenience only; it is discussed in 6.7.7.
Note too that lcc-win issues just a warning. The other two issue
an error and compilation fails. Is this such a bad error that
warrants a failure to compiler the code?

Absolutely. Issuing a warning for code with a constraint violation
is, of course, permitted by the standard, but I can't imagine why
you'd want to do so in this case. I see no benefit from allowing the
user to leave this error uncorrected, or in blindly *guessing* that
the last storage class is what was intended.

You apparently treat this:
static typedef int foo;
as a typedef (ignoring "static"), and this:
typedef static int foo;
as a static object declaration. Both are simply errors.

(In another thread, you do something equally arbitrary for type
specifiers.)
 
J

jacob navia

Eric said:
The first two seem to me more precise than the latter two,
but I'll grant that they might mislead someone who didn't know
that `typedef' was a storage class. The number of such someones
may be non-negligible, hence the potential to mislead may be
non-negligible.

I didn't know that a typedef is a storage class. And now that
the appropiate parts of the standard have been cited I still
do not understand it.

#define FOO 8

the #define is not a storage class.

A typedef is a compile time alias for another type. Why should it
be a storage class?

Mystery.
 
J

jacob navia

Keith said:
C99 6.7.1p3:

The typedef specifier is called a storage-class specifier for
syntactic convenience only; it is discussed in 6.7.7.

Note:

"FOR SYNTACTIC CONVENIENCE ONLY"

typedefs are surely not a storage class!
 
K

Keith Thompson

jacob navia said:
I didn't know that a typedef is a storage class. And now that
the appropiate parts of the standard have been cited I still
do not understand it.

As the standard clearly says, it's "for syntactic convenience only".

I'm guessing that the inventor of "typedef" (presumably Dennis
Ritchie) decided what he wanted a declaration to look like, then
noticed that it fits exactly the same pattern as "static", "extern",
et al. These two declarations:

typedef int foo;
static int foo;

of course mean two very different things, but they follow exactly the
same pattern, the only *syntactic* difference being the different
keywords.

The point is to make the language a bit easier to describe, and to
make the job of compiler writers like you just a little bit simpler.
#define FOO 8

the #define is not a storage class.

Of course not. A macro definition is processed in a different
translation phase, and it has very different syntax *and* semantics
than either typedefs or (other) storage classes. There would be no
benefit in treating it as a storage class.

For a typedef, on the other hand, it's just *convenient* to use the
same syntax as for other storage classes.

Perhaps the standard would have been clearer if, rather than this:

storage-class-specifier:
typedef
extern
static
auto
register

it had defined this:

storage-class-specifier:
extern
static
auto
register

storage-class-specifier-or-typedef:
storage-class-specifier
typedef

and used "storage-class-specifier-or-typedef" wherever
"storage-class-specifier" is used now. I'd probably advocate doing it
that way if the existing definition weren't already well established,
but once you understand what's going on, I don't find the existing
definition to be all that troubling. But you could always use my
proposed modification within your own compiler. Unless I've made a
mistake, it will accept exactly the same set of syntactically valid
translation units, and might make it a bit easier to generate clear
diagnostics. But you can already do that by treating "typedef" as a
special case of the set of storage classes.
A typedef is a compile time alias for another type. Why should it
be a storage class?

See above.

Not really.
 
K

Keith Thompson

jacob navia said:
Note:

"FOR SYNTACTIC CONVENIENCE ONLY"

YES, IT'S FOR SYNTACTIC CONVENIENCE ONLY. WHY ARE WE SHOUTING?
typedefs are surely not a storage class!

The standard says they are. If you don't want to follow the
standard's terminology, nobody is forcing you to do so. But I note
that your failure to do so in this case has caused you to introduce a
bug into your compiler. (By "bug" I don't necessarily mean a failure
to conform to the standard's requirements.)
 
S

Serve Lau

jacob navia said:
Consider this code

static typedef struct {
int boo;
} FOO;

This provokes with MSVC:
------------------------------
Microsoft (R) C/C++ Optimizing Compiler Version 14.00.50727.762 for x64
Copyright (C) Microsoft Corporation. All rights reserved.

tstruct.c
tstruct.c(1) : error C2159: more than one storage class specified
------------------------------

With gcc we have:
----------------------------
root@ubuntu-vm:/tmp# gcc t.c
t.c:1: error: multiple storage classes in declaration specifiers
----------------------------

With lcc-win I had
Warning tstruct.c: 1 multiple types in a declaration. Last will be
used: 'typedef'

with lcc-win64
------------------------------
Warning tstruct.c: 1 multiple use of 'typedef'
------------------------------

All those warnings are misleading in my opinion. I have changed the
wording to:
Warning tstruct.c: 1 typedefs can't be static. Static keyword ignored

what if you say
register typedef struct...
or
extern typedef struct...

etc.

I noticed that MSVC compiles the following with no complaints.

const typedef struct {
int boo;
} FOO;

Is that correct?
 
R

Richard Tobin

Eric Sosman said:
It is true that there can be at most one storage class
specifier in a declaration, so you can't have `static typedef'.

I think Jacob is right to try to give a more specific error message in
this case. "typedef" may be a storage class as far as the standard is
concerned, but that's just the standard-writer's trick for terseness,
and an error message has other goals.

-- Richard
 
H

Harald van Dijk

I noticed that MSVC compiles the following with no complaints.

const typedef struct {
int boo;
} FOO;

Is that correct?

Yes. Declaration specifiers may be placed in any order. It means the exact
same thing as

typedef const struct {
int boo;
} FOO;

However, "the placement of a storage-class specifier other than at the
beginning of the declaration specifiers in a declaration is an obsolescent
feature." And even if it weren't, you probably shouldn't do that, as
there's no good reason (other than as part of a conformance test) for
doing it.
 
R

Richard

CBFalconer said:
#define p1 int*
typedef p2 int*;

p1 a1, b1;
p2 a2, b2;

note that a1, a2, and b2 are pointers. b1 is an int object.

No they are not. p2 is nothing since it can not compile.

I assume you mean something more like:

typedef int * p2;
 
K

Keith Thompson

I think Jacob is right to try to give a more specific error message in
this case. "typedef" may be a storage class as far as the standard is
concerned, but that's just the standard-writer's trick for terseness,
and an error message has other goals.

Agreed.

One cannot reasonably dispute that "typedef" is a
"storage-class-specifier" *according to the standard* (since it's the
standard that defines the term "storage-class-specifier"). But
there's no requirement, and in this particular case perhaps no good
reason, to use the standard's terminology in a diagnostic. The
purpose of a diagnostic is to explain something to the user, with the
goal of letting the user figure out how to correct the error.
(Personally, I like seeing error messages that cite chapter and verse
in the standard, but I'm not a typical user.)

I don't know what kind of parser lcc-win (or it's predecessor lcc)
uses internally. Presumably there's a description of the C grammar,
either explicitly or implicitly. It's likely that this grammar
follows the standard's grammar in treating "typedef" as a
storage-class-specifier. But a little extra work to treat it as a
special case when printing an error message would be worthwhile.

Or, for that matter, the message could be something like "foo and bar
may not be used in the same declaration", where foo and bar are
replaced with whatever storage-class-specifiers appear in the
incorrect code. In this case, there isn't even a need to mention
storage-class specifiers. (Generating a reasonable diagnostic for
three or more is left as an exercise.)
 

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
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top