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’
This is not valid code. *** This bug has been marked as a duplicate of 9278 ***
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
The error message makes perfect sense: void is an incomplete type and the formal parameter has no name.
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.
Here is my quote for today: Stop programming in C using a C++ compiler. Learn C+.
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)
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
Works for me.
This sounds good to me to. I guess we can now confirm the PR.
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.
And since the C++ code is valid, the title of this bug should be changed.
(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.
(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.
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 "()".)
(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!
Let's resolve this.
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
Done.
Oops, I think the DR577 proper bit isn't done yet ;)
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