What does the ms-extensions flag do exactly with gcc? - c++

GCC has a flag -fms-extensions.
What does this flag do exactly? Why is it sometimes on by default, and why does it exist?

According to the gcc 9.1.0 source code (grepped for flag_ms_extensions) the effects are:
(C) Allow Microsoft's version of anonymous unions and struct. This includes support for C11 anonymous unions and structs as well as Microsoft-specific flavours, including omitting the braced member list entirely, and placing members in the parent namespace even if the struct/union had an identifier.
(C++) Allow a class member to have the same name as its type (e.g. using foo = int; struct A { foo foo; }). With ms-extensions disabled, the behaviour is to accept this code in C (where it is legal); or an extern "C" block unless -pedantic flag was given. The error message for this is declaration of NAME changes meaning of NAME.
(C++) Allow implicit int; any situation that would have produced the diagnostic ISO C++ forbids declaration of NAME with no type is now allowed, with int assumed as the type. Examples: const *p; or const f();.
(C++) Allow implicit conversion from a qualified-id naming a non-static member function, to a pointer-to-member. In ISO C++ the & operator is required to perform that conversion.
(C++) Allow &f to form a pointer-to-member, if f (an unqualified-id) names a non-overloaded member function in that context. ISO C++ requires explicit qualification with the class name.
The flag is turned on by default if the Target ABI is a Microsoft ABI. It can be disabled by manually specifying -fno-ms-extensions.
The rationale behind this is a tougher question. The documentation has to say:
Accept some non-standard constructs used in Microsoft header files.
Disable Wpedantic warnings about constructs used in MFC.
So I assume the rationale is to allow g++ to build MFC applications which depend on non-standard code in MSVC vendor-supplied headers.
I am not sure how relevant that still is in 2019 and I think a good case could be made for gcc to default to having this flag turned off. (Users can always specify it if they want to build an old MFC app).
For example MSVC 19.xx (the latest version to date) no longer allows the last three bullet points in its default mode. (It does still allow foo foo; even with /Za flag).

Related

(v) is actually (*&v) since when?

Could C++ standards gurus please enlighten me:
Since which C++ standard version has this statement failed because (v) seems to be equivalent to (*&v)?
I.e. for example the code:
#define DEC(V) ( ((V)>0)? ((V)-=1) : 0 )
...{...
register int v=1;
int r = DEC(v) ;
...}...
This now produces warnings under -std=c++17 like:
cannot take address of register variable
left hand side of operand must be lvalue
Many C macros enclose ALL macro parameters in parentheses, of which the above is meant only to be a representative example.
The actual macros that produce warnings are for instance
the RTA_* macros in /usr/include/linux/rtnetlink.h.
Short of not using/redefining these macros in C++, is there any workaround?
If you look at the revision summary of the latest C++1z draft, you'd see this in [diff.cpp14.dcl.dcl]
[dcl.stc]
Change: Removal of register storage-class-specifier.
Rationale: Enable repurposing of deprecated keyword in future
revisions of this International Standard.
Effect on original feature: A valid C++ 2014 declaration utilizing the register
storage-class-specifier is ill-formed in this International Standard.
The specifier can simply be removed to retain the original meaning.
The warning may be due to that.
register is no longer a storage class specifier, you should remove it. Compilers may not be issuing the right error or warnings but your code should not have register to begin with
The following is a quote from the standard informing people about what they should do with regards to register in their code (relevant part emphasized), you probably have an old version of that file
C.1.6 Clause 10: declarations [diff.dcl]
Change: In C++, register is not a storage class specifier.
Rationale: The storage class specifier had no effect in C++.
Effect on original feature: Deletion of semantically well-defined feature.
Difficulty of converting: Syntactic transformation.
How widely used: Common.
Your worry is unwarranted since the file in question does not actually contain the register keyword:
grep "register" /usr/include/linux/rtnetlink.h
outputs nothing. Either way, you shouldn't be receiving the warning since:
System headers don't emit warnings by default, at least in GCC
It isn't wise to try to compile a file that belongs to a systems project like the linux kernel in C++ mode, as there may be subtle and nasty breaking changes
Just include the file normally or link the C code to your C++ binary. Report a bug if you really are getting a warning that should normally be suppressed to your compiler vendor.

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++.

What is wrong with this use of offsetof?

I'm compiling some c++ code in MinGW GCC 4.4.0, and getting warnings with the following form...
warning: invalid access to non-static data member '<membername>' of NULL object
warning: (perhaps the 'offsetof' macro was used incorrectly)
This problem seems familiar - something I've tried to resolve before and failed, I think, but a while ago. The code builds fine in Visual C++, but I haven't built this particular code recently in any other compiler.
The problem code is the following template...
template<typename T>
class c_Align_Of
{
private:
struct c_Test
{
char m_Char;
T m_Test;
};
public:
enum { e_Align = offsetof (c_Test, m_Test) };
};
Obviously I can probably use some conditional compilation to use compiler-specific functions for this, and I believe C++0x will (at long last) make it redundant. But in any case, I cannot see anything wrong with this use of offsetof.
Very pedantically, it's possible that because the T parameter types are sometimes non-POD, so GCC classes c_Test as non-POD and complains (and complains and complains - I'm getting nearly 800 lines of these warnings).
This is naughty by the strict wording of the standard, since non-POD types can break offsetof. However, this kind of non-POD shouldn't be a problem in practice - c_Test will not have a virtual table, and no run-time trickery is needed to find the offset of m_Test.
Besides, even if c_Test had a virtual table, GCC implements the offsetof macro using an intrinsic that is always evaluated at compile-time based on the static layout of that particular type. Providing a tool then whining (sorry, warning) every time it's used just seems silly.
Also, I'm not the only person around here who does this kind of thing...
Answer to legit-uses-of-offsetof question
I do remember having an issue with offsetof for this kind of reason, but I don't think the problem was this template.
Any ideas?
Oops...
The issue is with the c_Test struct being non-POD due to the T type being non-POD. Here's a quote from the GCC manual...
-Wno-invalid-offsetof (C++ and Objective-C++ only)
Suppress warnings from applying the
‘offsetof’ macro to a non-POD type.
According to the 1998 ISO C++
standard, applying ‘offsetof’ to a
non-POD type is undefined. In existing
C++ implementations, however,
‘offsetof’ typically gives meaningful
results even when applied to certain
kinds of non-POD types. (Such as a
simple ‘struct’ that fails to be a POD
type only by virtue of having a
constructor.) This flag is for users
who are aware that they are writing
nonportable code and who have
deliberately chosen to ignore the
warning about it.
The restrictions on ‘offsetof’ may be
relaxed in a future version of the C++
standard.
My problem is that almost all my T types have constructors, and are therefore classed as non-POD. I ignored this point as irrelevant earlier - and of course it should be irrelevant for offsetof in principle. The trouble is that the C++ standard uses the one POD vs. non-POD classification even though there are a number of distinct ways to be non-POD, and the compiler is correct to warn about non-standards-compliant use by default.
My solution for the moment will be the option above to suppress the warning - now I just need to figure out how to tell cmake to use it.

Porting c++ code from unix to windows

Hi i have to port some stuff written on c++ from unix bases os to windows visual studio 2008.
The following code implements array data type with void ** - pointer to the data.
struct array
{
int id;
void **array; // store the actual data of the array
// more members
}
When i compile with g++ on Unix it's ok but when i try with MSVS 2008 I get the error - error C2461: 'array' : constructor syntax missing formal parameters. When i change the member from 'array' to something else it works, so it seems that the compiler thinks that the member name 'array' is actually the constructor of the struct array. It's obviously not a good practice to name the member like the struct but it's already written that way. Can i tell the MSVS compiler to ignore this problem or i should rename all members that are the same as the struct name.
You are dealing with a bug in GCC compiler. C++ language explicitly prohibits having data members whose name is the same as the name of the class (see 9.2/13). MS compiler is right to complain about it. Moreover, any C++ compiler is required to issue a diagnostic message in this case. Since GCC is silent even in '-ansi -pedantic -Wall' mode, it is a clear bug in GCC.
Revison: What I said above is only correct within the "classic" C++98 specification of C++ language. In the most recent specification this requirement only applies to static data members of the class. Non-static data members can now share the name with the class. I don't know whether this change is already in the official version of the revised standard though.
That means that both compilers are correct in their own way. MS compiler sticks to the "classic" C++98 specification of the language, while GCC seems to implement a more recent one.
I'd say that if you're doing something that you yourself describe as "not a good practice", then you should change it.
I would rename your attribute to not have the same name as the class. This will make your code more portable. If you have to move to yet another compiler in the future, you won't run in to this problem again then.

void, VOID, C and 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