void, VOID, C and C++ - c++

I have the following code:
typedef void VOID;
int f(void);
int g(VOID);
which compiles just fine in C (using gcc 4.3.2 on Fedora 10). The same code compiled as C++ gives me the following error:
void.c:3: error: ‘<anonymous>’ has incomplete type
void.c:3: error: invalid use of ‘VOID’
Now, this is something in external library and I would like the owner to fix that problem. So I have a question - does C++ standard forbids this construct? Could you give me a pointer/citation? The only thing I can recall is that function declaration with (void) to signal empty parameter list is deprecated in C++, but I don't understand why typedefed VOID does not work.

Yes, as far as i know the second declaration is invalid in C++ and C89, but it is valid in C99.
From The C99 draft, TC2 (6.7.5.3/10):
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's explicitly talking about the type "void", not the keyword.
From The C++ Standard, 8.3.5/2:
If the parameter-declaration-clause is empty, the function takes no arguments. The parameter list (void) is equivalent to the empty parameter list.
That it means the actual keyword with "void", and not the general type "void" can also be seen from one of the cases where template argument deduction fails (14.8.2/2):
Attempting to create a function type in which a parameter has a type of void.
It's put clear by others, notable in one core language issue report here and some GCC bugreports linked to by other answers.
To recap, your GCC is right but earlier GCC versions were wrong. Thus that code might have been successfully compiled with it earlier. You should fix your code, so that it uses "void" for both functions, then it will compile also with other compilers (comeau also rejects the second declaration with that "VOID").

gcc bugs. Edit: since it wasn't clear enough, what I meant was gcc 4.3.2 was compiling it due to bugs. See #32364 and #9278.

I just put your code in a .cpp file, and it compiled with no problems in VS2005, SUSE, Redhat, and Solaris, so I guess your specific gcc version does not approve of this.
Gal

Related

Why did newer compilers start accepting this template function call?

The following small C++ program involving a call to the template function std::atomic_fetch_add() fails to compile in godbolt for x86-64 clang versions less than 9.0 and gcc versions less than 9.1,
in both cases using the --std=c++11 option.
#include <iostream>
#include <atomic>
std::atomic<char> ch ('#');
int main ()
{
std::atomic_fetch_add (&ch, 5);
std::cout << ch << std::endl;
}
In those early compiler versions (it might be more related to the C++ libraries provided by the compilers, I'm not sure), the std::atomic_fetch_add (&ch, 5); call fails to match any template specialization for the atomic fetch function, since the type of ch is char, and the type of 5 is int:
: In function 'int main()':
:8:34: error: no matching function for call to 'atomic_fetch_add(std::atomic*, int)'
std::atomic_fetch_add (&ch, 5);
...
However, later versions of the compiler (& libraries?) successfully compile this usage.
What changed to make this start compiling?
If it is a standard library change, what technique is used to allow this?
Does the C++ standard (& what version?) require that this usage should work.
I'm pretty much a C++ beginner, but I gather that this is related to implicit conversions not being performed as part of figuring out the appropriate template specialization to use. (I may not be using precise language.)
I know that I can modify the call to work by rewriting it as either
std::atomic_fetch_add<char> (&ch, 5);
or
std::atomic_fetch_add (&ch, (char)5);
However, I'm interested in getting a version of the <atomic> library to support the usage without the explicit instantiation and without the cast. (The compiler is clang 15.0.0, --std=c++11. The library is a proprietary version of the Dinkum libraries.)
I need to understand how to support the calling of template functions like
std::atomic_fetch_char (&ch, 5) where the argument types do not exactly match those in the template declaration. I would, for example, like to understand how this is supported in the linux /usr/include/c++/11/ standard library.
The nearest I've come up with myself is to add non-template overloads of various instantiations of std::atomic_fetch_add() & similar functions, but I don't see that being done in the Linux/GNU C++ libraries and I suspect there is a cleaner way. I want to understand it.
Originally std::atomic_fetch_add required the second parameter to have the same type as the value_type of the atomic object as both parameters participated in type deduction.
This was removed with defect report P0558R1 so that deduction only happens on the atomic object and the second parameter is just converted to the differece_type of the atomic object.
You get the error because older versions didn't get patched with this defect report but newer versions did.

Why GCC can compile std::exception("some error msg") without error?

I found the following code that is throwing an exception with a message for the parameter, but GCC can successfully compile it without any error.
When I use clang to compile, the result is failure. I want to debug the GCC compile process to find the difference with the GCC option -Q, but it seems not to work. I hope someone can give me some advice, or tell me why GCC can compile it successfully.
T* lpItem = new T;
if (NULL == lpItem)
{
throw std::exception("New CachePool Item Fail");
}
GCC is taking advantage of [member.functions] to add something like
std::exception::exception(const char *);
Clang is not
For a non-virtual member function described in the C++ standard library, an implementation may declare a different set of member function signatures, provided that any call to the member function that would select an overload from the set of declarations described in this document behaves as if that overload were selected. [ Note: For instance, an implementation may add parameters with default values, or replace a member function with default arguments with two or more member functions with equivalent behavior, or add additional signatures for a member function name. — end note ]
Emphasis added

Why does gcc warn about decltype(main()) but not clang?

Take the following code:
int main()
{
decltype(main()) x = 0;
return x;
}
gcc complains:
main.cpp: In function 'int main()':
main.cpp:8:19: warning: ISO C++ forbids taking address of function '::main' [-Wpedantic]
decltype(main()) x = 0;
^
main.cpp:8:19: warning: ISO C++ forbids taking address of function '::main' [-Wpedantic]
but not clang. So what about decltype(main()) raises this error? How does decltype take the address of main?
GCC's diagnostic might not be correctly phrased in this case, because decltype doesn't need to know the address of main; it only needs to know its type. However, the warning is based on the following from the standard (§3.6.1/3):
The function main shall not be used within a program.
I suppose GCC interprets this to mean that you can't even use it in an unevaluated expression.
Clang (version 3.4 anyway) appears to not implement this rule at all, even if I turn on all the flags I can think of and even if main calls itself recursively. That's why it doesn't give you a warning.
This topic actually came up recently in the undefined behaviour study group discussion list in the thread What does "The function main shall not be used within a program" mean?. It does not come up right away but here is where it starts in the thread with the following statement:
I don't think decltype(main()) is an odr-use, or
sizeof(decltype(main)).
a very abbreviated set of responses looks like this:
True, I just don’t see what utility those would be. You might mean
sizeof(decltype(&main)) in the latter case.
I think the most common non-ODR use of main would be defining it after
a forward declaration, and now Steven Clamage has clarified that
should be ill-formed. The broader definition of “use” as being a
result of name lookup without reference to ODR looks correct now.
and:
C++98's mention of 'use' had a cross-reference to 3.2 [basic.def.odr].
C++11 no longer has the cross-reference, and was not changed to say
'odr-use', so I expect it means any use.
and so it would seem that the interpretation of section 3.6.1 Main function which says:
The function main shall not be used within a program. [...]
means any use even in unevaluated contexts and so gcc is correct here to produce an error although the message itself does not seem to make sense.
Update
It is interesting and instructive to note that the original proposal: N3154 to fix Defect report 1109 would have changed 3.6.1 to:
The function main shall not be odr-used (3.2) within a program. ...
which would have allowed the decltype example but was amended when accepted and we can see that the new proposal: N3214 changed to what we have today:
The function main shall not be used within a program
which would strongly indicate the opinion in the UB mailing list that any use of main is ill-formed is indeed correct.

"extra qualification" errors. How warranted by the Standard?

This similar ill-fated question
got comments and short answers, before it was closed, to the effect: Because that's
how the language is defined. Here I am asking for the evidence within the
C++ Standard that it is so defined.
gcc 4.8.1 and clang 3.3 alike, with default diagnostic options or stricter,
give errors for extra qualification or explicit qualification on
code such as:
struct x
{
int x::i; // Error: gcc/clang: "extra"
};
int ::y; // Error: gcc: "explicit", clang: "extra"
gcc has diagnosed such errors since v4.1. But popular compilers are not
unanimous about these errors. MSVC++ 2012 (Nov CTP)
gives an error at int ::y; but even with /Wall, gives no diagnostic at all
int x::i; - the kind of case that the ill-fated questioner was raising -
and that difference suggests deliberation by the MS compiler writers.
How are these errors warranted by the Standard, if they are? References to the C++11
Standard will suffice.
An answer might be "They follow from grammar". In that case,
please try to show how they follow from the grammar and feel free to use
the Standard's grammatical classifications. I have a copy and will re-read it
to understand the explanation.
A qualified name in C++ always must refer to a previously declared name. This is specified in clause 8.3 and 3.4.3.2.
You cannot firstly declare a variable or member by using a qualified name - it will end up in a "cannot resolve identifier"-liky compiler error. Such qualifiers are designed to be used for redeclaration. Hence the requirement that these names must find previously declared entities.
It is a bug in the Microsoft compiler to allow x::i within the definition of struct x. There are several of these errors in the MSVC front end, and have been reported to Microsoft but they get closed without being fixed (see similar but different error reported here: https://connect.microsoft.com/VisualStudio/feedback/details/783433/c-compiler-accepts-explicit-constructor-call#details and https://connect.microsoft.com/VisualStudio/feedback/details/794504/keyword-struct-before-constructor-name).
The reason it is invalid is because you are both trying to declare a variable int i and provide a scope using x::i. The scope of the variable is dictated by where it is declared, so trying to declare something with a scope specification is trying to declare it somewhere else, which is invalid.

Why is gcc's option "-Wstrict-prototypes" not valid for C++?

Here is a warning I, and lots of people out there on the web, see when running gcc on C++ code:
cc1plus: warning: command line option "-Wstrict-prototypes" is valid for Ada/C/ObjC but not for C++
The warning text is very clear: 'C++' is not in the set [Ada/C/ObjC ], so I have no question at all about why gcc gives this warning when compiling C++ code. (FYI the reason we have this flag turned on in spite of having C++ code is because it's mostly C code, we have chosen a strict (high level of) warning options list, but we've added a bit of C++ code.
My question is: Why isn't this warning valid for C++?
The gcc documentation for the warning option, from http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Warning-Options.html, is:
-Wstrict-prototypes (C and Objective-C only) Warn if a function is declared or defined without specifying the argument types. (An
old-style function definition is permitted without a warning if
preceded by a declaration which specifies the argument types.)
Now I just know I'm forgetting something obvious about C++, but doesn't C++ also require specifying argument types for functions in a prototype? True that those function prototypes are often in class declarations because the functions are often member functions, but aren't prototypes nevertheless required? Or even if they're just good practice, then why wouldn't gcc offer support by this option? Or if not, by a parallel option for C++?
I suppose it's becuase C++ requires strict prototypes as part of the language, so the option is superfluous. Why that makes it so GCC needs to complain about it is beyond me.
I have that option set in my build script for small sample/test C or C++ programs, and the warning kind of irritates me - it seems like there's no reason to warn just because the default behavior for a language is what I'm asking for. But it's there, so one day when it irritates me enough I'll fix my script to not bother with that option for C++ builds.
It's required by the C++ standard so there's no meaning of turning it on or off: It's always on in the language.
It is implicit in C++ because declaring/defining a function without specifying the argument types is illegal C++ by the standard (yes, this is one of the differences between C and C++ which makes C++ not a true superset).
This is legal C99, but not legal C++03:
void foo(x, y)
int x;
char *y;
{
// ...
}
GCC gives a warning for this in C if compiled with -Wstrict-prototypes.
Another interesting special case:
extern int foo();
By C semantics this declaration specifies an incomplete type for foo, as a function where the number and type of arguments remains unspecified. This is nevertheless a fully valid declaration in C99/C11; however -Wstrict-prototypes forces a warning for this valid declaration in C.
By C++ semantics, this declaration specifies a complete type for foo, as a function that takes no arguments (i.e., it is equivalent to extern int foo(void)). Hence -Wstrict-prototypes is not relevant for this case in C++.