Bug 33101 - [DR 577] allow typedefs for void in empty parameter list
Summary: [DR 577] allow typedefs for void in empty parameter list
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.2.0
: P3 normal
Target Milestone: 5.0
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2007-08-17 23:32 UTC by Ian Lance Taylor
Modified: 2014-06-23 17:07 UTC (History)
12 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2007-09-08 23:24:59


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ian Lance Taylor 2007-08-17 23:32:18 UTC
This C++ test case works with gcc 4.1.1.  With gcc 4.2 and with mainline it gets an inexplicable error.

typedef void v;
typedef v (*pf)(v);

foo.cc:2: error: ‘<anonymous>’ has incomplete type
foo.cc:2: error: invalid use of ‘v’
Comment 1 Andrew Pinski 2007-08-17 23:33:38 UTC
This is not valid code.

*** This bug has been marked as a duplicate of 9278 ***
Comment 2 Ian Lance Taylor 2007-08-18 04:19:33 UTC
Thanks for the explanation.  That is new to me.

I am now going to reopen this bug because the error message is terrible.  There is no anonymous or incomplete type here.  gcc should perhaps print something like

error: invalid use of typedef 'v' in function parameter declaration
Comment 3 Andreas Schwab 2007-08-18 09:00:25 UTC
The error message makes perfect sense: void is an incomplete type and the formal parameter has no name.
Comment 4 Ian Lance Taylor 2007-08-18 17:12:24 UTC
The error message makes some sense if you already understand the issue.  If you do not know what the problem is, then I believe it is completely obscure.  This is particularly so since the same code is valid C code.
Comment 5 Andrew Pinski 2007-08-18 17:15:14 UTC
Here is my quote for today:
Stop programming in C using a C++ compiler.  Learn C+.
Comment 6 David Fang 2007-08-18 17:29:04 UTC
Subject: Re:  Bad C++ error on invalid code: <anonymous> has
 incomplete type

> ------- Comment #5 from pinskia at gcc dot gnu dot org  2007-08-18 17:15 -------
> Here is my quote for today:
> Stop programming in C using a C++ compiler.  Learn C+.

Haha.  And I keep telling people to
"Stop programming in C.  [Period.]  Learn C++."

(ok, that's perhaps too extreme)

Comment 7 gdr@cs.tamu.edu 2007-08-18 19:52:16 UTC
Subject: Re:  C++ error on valid code: <anonymous> has incomplete type

"ian at airs dot com" <gcc-bugzilla@gcc.gnu.org> writes:

| Thanks for the explanation.  That is new to me.

Check for "abomination" in D&E :-)

| I am now going to reopen this bug because the error message is terrible.  There
| is no anonymous or incomplete type here.

Well, I believe the parameter is unnamed, and its type is incomplete.

|  gcc should perhaps print something
| like
| 
| error: invalid use of typedef 'v' in function parameter declaration

That is also obscure :-)

Maybe you want

  error: invalid use of typedef-name for type 'void' in a function
         parameter declaration
  note: 'void' can be used as a function parameter only if it appears
        lexically as a keyword

?

-- Gaby
Comment 8 Ian Lance Taylor 2007-08-18 22:10:03 UTC
Works for me.
Comment 9 Wolfgang Bangerth 2007-09-08 23:24:59 UTC
This sounds good to me to. I guess we can now confirm the PR.
Comment 10 Keith Thompson 2012-03-16 19:26:45 UTC
This came up in a question on stackoverflow.com:

    http://stackoverflow.com/q/9742135/827263

I believe the code is valid. Here's a simpler test case:

    typedef void VOID;
    int main(VOID) { }

which g++ 4.5.2 rejects with the following:

    void_test.cpp:2:10: error: ‘<anonymous>’ has incomplete type
    void_test.cpp:2:14: error: invalid use of ‘VOID’

Quoting N3290, a draft of the 2011 ISO C++ standard, section 8.3.5 [dcl.fct]:

    The parameter-declaration-clause determines the arguments that can
    be specified, and their processing, when the function is called.
    [ ... ] If the parameter-declaration-clause is empty, the function
    takes no arguments. The parameter list (void) is equivalent to
    the empty parameter list. Except for this special case, void
    shall not be a parameter type (though types derived from void,
    such as void*, can).

Earlier versions of the standard have similar or identical wording.

The last sentence implies that "void" here is being used as a type
name, not as some special-case syntactic use of the keyword.  I believe
the phrase "special case" is meant to exclude declarations like

    void foo(void, int);

or 

    void bar(void param);

not to prohibit the use of a typedef.  Since a typedef creates an
*alias* for an existing type, the name "VOID" should be usable as a
replacement for "void" whenever it's used as a type name.

Note that the syntax for a parameter-declaration does not refer
specifically to the "void" keyword; rather, "void" is valid in that
context because it's a type name.

Practically speaking, the purpose of allowing "void" as a parameter
declaration is for compatibility with C.  Quoting the latest draft
of the C standard, N1570 6.7.6.3p10:

    The special case of an unnamed parameter of type void as the only
    item in the list specifies that the function has no parameters.

It refers to the *type* void, not the keyword, implying that a
typedef is acceptable in this context -- and gcc 4.5.2 accepts the
above program without complaint when compiling it as C.

I agree that the C++ standard's wording is ambiguous, and *could*
be read as requiring the keyword "void", but I believe the intent
is to permit a typedef.  (And if you want to argue that the use of
a typedef is silly, I agree completely.)

I believe that the resolution of DR 577:
    http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#577
confirms this.  The resolution, as of August, 2011, suggests changing
the wording to refer to the *type* void rather than the keyword.  
(That change doesn't appear in the N3270 draft; I don't know whether
it appears in the final ISO C++ 2011 standard.)

At the very least, since there is (unfortunately) real-world code that 
depends on this, I suggest changing it from a fatal error to a warning,
though I think removing the diagnostic altogether would be better.
Comment 11 Keith Thompson 2012-03-16 19:30:17 UTC
And since the C++ code is valid, the title of this bug should be changed.
Comment 12 Jonathan Wakely 2012-03-16 20:17:02 UTC
(In reply to comment #10)
> I believe that the resolution of DR 577:
>     http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#577
> confirms this.  The resolution, as of August, 2011, suggests changing
> the wording to refer to the *type* void rather than the keyword.  
> (That change doesn't appear in the N3270 draft; I don't know whether
> it appears in the final ISO C++ 2011 standard.)

It doesn't, the DR says [Voted into the WP at the February, 2012 meeting.]
i.e. after the 2011 standard.

> At the very least, since there is (unfortunately) real-world code that 
> depends on this, I suggest changing it from a fatal error to a warning,
> though I think removing the diagnostic altogether would be better.

Since GCC, Clang and EDG all reject it today I'm surprised such real-world code hasn't been changed already.
Comment 13 Jonathan Wakely 2012-03-16 20:37:33 UTC
(In reply to comment #10)
> I agree that the C++ standard's wording is ambiguous, and *could*
> be read as requiring the keyword "void", but I believe the intent
> is to permit a typedef.  (And if you want to argue that the use of
> a typedef is silly, I agree completely.)
> 
> I believe that the resolution of DR 577:
>     http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#577
> confirms this. 

No, that issue confirms quite clearly that before that change (which only happened last month and is not part of C++98, C++03 or C++11) the code was definitely invalid:

"The C99 formulation allows typedefs for void, while C++ (and C90) accept only the keyword itself in this role."

The language was not ambiguous and the intent wasn't clarified by DR 577, the rule was changed so previously invalid code is now valid.

Subject and keywords changed to match the new status.
Comment 14 Keith Thompson 2012-03-16 21:41:18 UTC
On re-reading DR 577, I agree that it implies the current standard
says that only "(void)" is allowed, and in particular that a typedef
is not.  I might have interpreted it differently myself, but I defer to
the committee.  (I thought perhaps that the change had been made between
N3290 and the released standard, but apparently that's not the case.)

The fact that C90 required the keyword further weakens my previous
argument.

So the diagnostic is necessary, but I'd still suggest that a warning
would be more appropriate, and would still meet the current standard's
requirements.

(I should mention that I have no need for this myself; I don't even take
advantage of the permission to use "(void)" rather than "()".)
Comment 15 Jonathan Wakely 2012-03-16 21:46:05 UTC
(In reply to comment #14)
> (I thought perhaps that the change had been made between
> N3290 and the released standard, but apparently that's not the case.)

See the text in bold at the top of the issues list:
"Issues with DR and WP status are NOT part of the International Standard for C++."

> The fact that C90 required the keyword further weakens my previous
> argument.
> 
> So the diagnostic is necessary, but I'd still suggest that a warning
> would be more appropriate, and would still meet the current standard's
> requirements.

The current standard is C++11, that change is only in the current *draft* and that's not a standard.

> (I should mention that I have no need for this myself; I don't even take
> advantage of the permission to use "(void)" rather than "()".)

Good, it's an abomination!
Comment 16 Paolo Carlini 2014-06-12 14:08:57 UTC
Let's resolve this.
Comment 17 paolo@gcc.gnu.org 2014-06-14 22:56:12 UTC
Author: paolo
Date: Sat Jun 14 22:55:40 2014
New Revision: 211673

URL: https://gcc.gnu.org/viewcvs?rev=211673&root=gcc&view=rev
Log:
/cp
2014-06-14  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/33101
	* decl.c (grokparms): Improve error message about void parameters.
	* error.c (type_to_string): Fix aka cut off code.

/testsuite
2014-06-14  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/33101
	* g++.dg/other/void3.C: New.
	* g++.dg/conversion/err-recover1.C: Update.

Added:
    trunk/gcc/testsuite/g++.dg/other/void3.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/decl.c
    trunk/gcc/cp/error.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/g++.dg/conversion/err-recover1.C
Comment 18 Paolo Carlini 2014-06-14 23:00:39 UTC
Done.
Comment 19 Paolo Carlini 2014-06-14 23:06:01 UTC
Oops, I think the DR577 proper bit isn't done yet ;)
Comment 20 paolo@gcc.gnu.org 2014-06-23 17:06:04 UTC
Author: paolo
Date: Mon Jun 23 17:05:33 2014
New Revision: 211906

URL: https://gcc.gnu.org/viewcvs?rev=211906&root=gcc&view=rev
Log:
/cp
2014-06-23  Paolo Carlini  <paolo.carlini@oracle.com>

	DR 577
	PR c++/33101
	* decl.c (grokparms): Accept a single parameter of type 'void'.

/testsuite
2014-06-23  Paolo Carlini  <paolo.carlini@oracle.com>

	DR 577
	PR c++/33101
	* g++.dg/other/void1.C: Adjust.
	* g++.dg/other/void3.C: Likewise.

Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/decl.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/g++.dg/other/void1.C
    trunk/gcc/testsuite/g++.dg/other/void3.C
Comment 21 Paolo Carlini 2014-06-23 17:07:38 UTC
Done.