Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

G++ error: ‘<anonymous>’ has incomplete type

I am forced to use a third party dongle access library that provides an include file 'sense4.h' with code as follows:

#if !defined _WINDOWS_

#define WINAPI
#define CONST const

typedef unsigned char   UCHAR;
typedef unsigned short  USHORT;
typedef unsigned int    UINT;
typedef unsigned long   ULONG;

typedef char            CHAR;
typedef char            TCHAR;

typedef void            VOID;

...

#endif /* !defined _WINDOWS */

...

unsigned long WINAPI S4Startup(
        VOID
);


unsigned long WINAPI S4Cleanup(
        VOID
);

...

The problem is that g++ 4.6.1 complains about lines of code where typedefed VOID is used:

sense4.h:375:9: error: ‘<anonymous>’ has incomplete type
sense4.h:376:1: error: invalid use of ‘VOID {aka void}’
sense4.h:383:9: error: ‘<anonymous>’ has incomplete type
sense4.h:384:1: error: invalid use of ‘VOID {aka void}’

Is there anything I can do without changing the 'sense.h' include file to make my project compile with g++?

Update 1

I found out that the section 18 of C++ Standard Core Language Closed Issues, Revision 30 states:

If the parameter-declaration-clause is empty, the function takes no arguments. The parameter list (void) is equivalent to the empty parameter list.

Can a typedef to void be used instead of the type void in the parameter list?

Rationale: The IS is already clear that this is not allowed.

like image 592
ezpresso Avatar asked Mar 16 '12 17:03

ezpresso


1 Answers

Quick summary: The code is not valid C++, though there's some lack of clarity about whether it should be. Using void rather than VOID, or just using empty parentheses, will avoid the error.

I think this is a bug in g++.

I thought this was a bug in g++. I'm now convinced that it isn't, though I argue that it would be better to make this a warning rather than a fatal error.

Normally in C++, a function with no parameters is declared with empty parentheses:

int foo();

As a concession to C compatibility, C++ also allows a C-style prototype, using void to indicate that the function has no parameters (since empty parentheses mean something else in C):

int bar(void);

g++'s interpretation seems to be that the void in this syntax here doesn't refer to the incomplete type void; rather, it treats it as a special syntax with a distinct use of the keyword.

I think you'll need to modify the header file to get g++ to accept it.

gcc accepts it as valid C, but that's not helpful if you need to #include it from a C++ source file -- unless you write a C wrapper and invoke it from your C++ code, which might be an acceptable workaround.

(Incidentally, I hate typedefs like that. What's the purpose of typedef void VOID;? Did the author think void was too confusing? I suspect it's for compatibility with very old C compilers that didn't support the void keyword, but the need for that is long past.)

Here's the relevant description from the latest draft of the ISO C++ 2011 standard (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).

This implies that the void keyword in int bar(void); does refer to the type void. Since a typedef name is a synonym for the named type, int bar(VOID); should be equally legal. It would make the most sense for a typedef name like VOID to be accepted in place of void, but the wording of the standard actually refers to the keyword void, not to the type.

The whole purpose of permitting (void) is C compatibility. Just to add to the confusion, the 1990 ISO C standard requires the void keyword; the 1999 and 2011 C standards changed the wording, allowing a typedef instead. The response to C++ Defect Report #577 confirms that the current wording requires the void keyword, and proposes a change that will permit a typedef -- but that change is not yet in any ISO C++ standard. It will probably appear in the first Technical Corrigendum for C++ 2011, whenever it's published.

Thanks to another.anon.coward for finding the existing gcc bug report. I've added an overly verbose comment suggesting that the code is valid and the error message should not be produced -- and a later comment conceding that the code is invalid, but that a warning would be more appropriate than a fatal error.

In the meantime, I suggest contacting the provider of this sense4.h header file. If they intended it to #included only from C code, there's no real problem with it (other than the IMHO poor style); otherwise, they might consider using #ifdef __cplusplus, declaring the functions with (void) in C and with () in C++. And you could go ahead and make that change yourself. Whether g++ should accept the code or not, with a few changes it would be valid C, valid C++, acceptable to both gcc and g++, and better style.

If you've read this far and you're still awake, I'm impressed.

like image 142
Keith Thompson Avatar answered Sep 25 '22 02:09

Keith Thompson