Passing multiple -std switches to g++ - gcc

Is it safe to assume that running g++ with
g++ -std=c++98 -std=c++11 ...
will compile using C++11? I haven't found an explicit confirmation in the documentation, but I see the -O flags behave this way.

The GCC manual doesn't state that the
last of any mutually exclusive -std=... options specified takes effect. The first occurrence
or the last occurrence are the only alternatives. There are numerous
GCC flags that take mutually exclusive alternative values from a finite set - mutually
exclusive, at least modulo the language of a translation unit. Let's call them mutex options for short.
It is a seemingly random rarity for it to be documented that the last setting takes effect. It is
documented for the -O options as you've noted, and in general terms for mutually exclusive warning options, perhaps
others. It's never documented that the first of multiple setting takes effect, because
it's never true.
The documentation leans - with imperfect consistency - on the historical conventions
of command usage in unix-likes OSes. If a command accepts a mutex option
then the last occurrence of the option takes effect. If the command were - unusually -
to act only on the first occurrence of the option then it would be a bug for
the command to accept subsequent occurrences at all: it should give a usage error.
This is custom and practice. The custom facilitates scripting with tools that
respect it, e.g. a script can invoke a tool passing a default setting of some
mutex option but enable the user to override that setting via a parameter of the script,
whose value can simply be appended to the default invocation.
In the absence of official GCC documentation to the effect you want, you might get
reassurance by attempting to find any GCC mutex option for which it is not
the case that the last occurrence takes effect. Here's one stab:
I'll compile and link this program:
main.cpp
#include <cstdio>
#if __cplusplus >= 201103L
static const char * str = "C++11";
#else
static const char * str = "Not C++11";
#endif
int main()
{
printf("%s\n%d\n",str,str); // Format `%d` for `str` mismatch
return 0;
}
with the commandline:
g++ -std=c++98 -std=c++11 -m32 -m64 -O0 -O1 -g3 -g0 \
-Wformat -Wno-format -o wrong -o right main.cpp
which requests contradictory option pairs:
-std=c++98 -std=c++11: Conform to C++98. Conform to C++11.
-m32 -m64: Produce 32-bit code. Produce 64-bit code.
-O0 -O1: Do not optimise at all. Optimize to level 1.
-g3 -g0: Emit maximum debugging info. Emit no debugging info.
-Wformat -Wno-format. Sanity-check printf arguments. Don't sanity check them.
-o wrong -o right. Output program wrong. Output program right
It builds successfully with no diagnostics:
$ echo "[$(g++ -std=c++98 -std=c++11 -m32 -m64 -O0 -O1 -g3 -g0 \
-Wformat -Wno-format -o wrong -o right main.cpp 2>&1)]"
[]
It outputs no program wrong:
$ ./wrong
bash: ./wrong: No such file or directory
It does output a program right:
$ ./right
C++11
-1713064076
which tells us it was compiled to C++11, not C++98.
The bug exposed by the garbage -1713064076 was not diagnosed because
-Wno-format, not -Wformat, took effect.
It is a 64-bit, not 32-bit executable:
$ file right
right: ELF 64-bit LSB shared object, x86-64 ...
It was optimized -O1, not -O0, because:
$ "[$(nm -C right | grep str)]"
[]
shows that the local symbol str is not in the symbol table.
And it contains no debugging information:
echo "[$(readelf --debug-dump right)]"
[]
as per -g0, not -g3.
Since GCC is open-source software, another way of resolving doubts
about its behaviour that is available to C programmers, at least,
is to inspect the relevant source code, available via git source-control at
https://github.com/gcc-mirror/gcc.
The relevant source code for your question is in file gcc/gcc/c-family/c-opts.c,
function,
/* Handle switch SCODE with argument ARG. VALUE is true, unless no-
form of an -f or -W option was given. Returns false if the switch was
invalid, true if valid. Use HANDLERS in recursive handle_option calls. */
bool
c_common_handle_option (size_t scode, const char *arg, int value,
int kind, location_t loc,
const struct cl_option_handlers *handlers);
It is essentially a simple switch ladder over option settings enumerated by scode - which
is OPT_std_c__11 for option -std=c++11 - and leaves no doubt that it
puts an -std option setting into effect regardless of what setting was in effect previously. You can look at branches other than master
(gcc-{5|6|7}-branch) with the same conclusion.
It's not uncommon to find GCC build system scripts that rely on the validity of
overriding an option setting by appending a new setting. Legalistically, this
is usually counting on undocumented behaviour, but there's a better
chance of Russia joining NATO than of GCC ceasing to take the last setting that
it parses for a mutex option.

Related

Why does the comparison with integer works for nullptr?

The following works for g++
assert(nullptr == 0);
I need to know if there is any implicit type conversion that is happening.
From what I know, nullptr can be compared with pointers only and not with integers, and also that it is more type-safe. Then why the comparison with integer works?
Then why the comparison with integer works?
Because, in most implementations, the nullptr is a 0 machine address. In other words (intptr_t)nullptr is 0. This is the case on Linux/x86-64 for example. Check by inspecting the generated assembler code obtained with g++ -S -O2 -fverbose-asm
I even believe that this is guaranteed by the C++ standard (read e.g. n3337)
However, if you compile your code with a recent GCC as gcc -Wall -Wextra you could get a warning.
Read also assert(3). In some cases (with NDEBUG) it is expanded to a no-op at compilation time.

GCC, compare the effect of using -O2 and using all the optimization flags it turns on

From gcc5.4 documentation, it says
-O2 turns on all optimization flags specified by -O. It also turns on the following optimization flags:
-fthread-jumps
-falign-functions -falign-jumps
-falign-loops -falign-labels
-fcaller-saves
-fcrossjumping
-fcse-follow-jumps, etc
It seems that using -O2 has the same effect of using all the 83 optimization flags turned on by -O2 in gcc 5.4.0 on the performance of the test programs.
However, I compare the running time of the executable files test1 and test2 obtained by
gcc-5.4 -O2 test.c -o test1
and
gcc-5.4 -fauto-inc-dec
-fbranch-count-reg
-fcombine-stack-adjustments
-fcompare-elim ... -fthread-jumps -falign-functions ...(all the 83 flags) test.c -o test2
I tested on 20 random generated c programs and running each test case 100000 times to make sure the measurement of running time is accurate enough. But the result is that using -O2 is averagely about 60% faster than using all the 83 flags.
I am really confused why the effect of using -O2 is not equivalent to using all the optimization flags it turns on.
I must misunderstood something, but I couldn't find any explanation yet. I'd appreciate any help. Thanks a lot.
It is a common gotcha. In order to enable (or disable) specific optimizations, you must first enable the optimizer in general, i.e. use one of -O... flags, except -O0 (or just -O, which is equivalent to -O1).
The optimisation level affects decisions in other parts of the compiler besides determining which passes get run. These can be during mandatory processes like transforming between internal representations of the code, register allocation etc, so the optimisation level is not exactly equivalent to a set of switches enabling every compiler pass.
Look at this thread for some discussion on this topic.

Disabling -Werror for -Wimplicit-interface

What is the right flag or order of flags to disable treating particular warning as error in GCC? I want to do that for -Wimplicit-interface.
>cat test.f90
call s
end
> gfortran -c -Werror -Wimplicit-interface -Wno-error=implicit-interface test.f90 -o test.o
test.f90:1.7:
call s
1
Warning: Procedure 's' called with an implicit interface at (1)
>ls test*
test.f90
No test.o was generated.
Without -Werror it works
> gfortran -c -Wimplicit-interface -Wno-error=implicit-interface test.f90 -o test.o
test.f90:1.7:
call s
1
Warning: Procedure 's' called with an implicit interface at (1)
> ls test*
test.f90 test.o
GCC version is gcc version 4.9.2 20141030 (Cray Inc.) (GCC).
This is not an explicit answer to the question. I found it educative enough and too long to be put as comment.
As you just found, you might not be able to achieve what you want if you combine -Werror and -Wno-error=implicit-interface. Let me explain: as opposed to what we have in the doc, especially the following sentence,
The combined effect of positive and negative forms is that more specific options have priority over less specific ones, independently of their position in the command-line.
It seems that it is not the case in the actual implementation. I had a similar problem recently, and by googling, I found this which contains this sentence:
'-w' permanently sets all warnings off no matter what specific warning is set on
It actually suggests that by using some non specific options, the actual implementation does not allow you to change specific option included in the non specific one.
As #innoSPG points out, the actual behaviour does not conform to what is claimed in the manual.
The comment by #MarkGlisse revealed that this have changed with GCC 5. Therefore it was probably a bug.
The solution is therefore to use the recent version, or to not use one of the -Werror and -Wimplicit-interface.
Or to really provide explicit interfaces everywhere, but that can be problematic, as MPI libraries differ in the amount of explicit interfaces provided in the mpi modules.

GCC 4.5: Why no compiler warning on no-effect statement?

I am using gcc 4.5 to compile a Linux kernel module. I just noticed that I have some code that looks like this:
#define NODE_ID "string_here"
int foot(int a) {
/* snip */
NODE_ID;
NODE_ID;
/* snip */
return 0;
}
I have these two no-effect statements, and the compiler never generates a warning telling me about them. Why is this? I wonder if there's other statements like this floating in my project that I haven't found.
It does warn you, you just weren't listening -- as #Mat said in the comments, you need to enable the -Wall option, and it will warn you:
$ gcc test.c -c -Wall
test.c: In function ‘foot’:
test.c:5:5: warning: statement with no effect
test.c:6:5: warning: statement with no effect
Or, you can just enable the -Wunused-value option for just this warning, but I highly recommend using -Wall, which includes this and many other useful warnings. You can also enable -Wextra and -pedantic for even more, but these sometimes give false positives for code which is perfectly fine, adding extra noise to your build process. So use them judiciously.

Understanding what flags to pass to the compiler

I have a program, that in XCode, compiles and runs perfectly. It's actually one of apple's example programs for CoreAudio;
http://developer.apple.com/library/mac/#samplecode/PlayFile/Listings/PlayFile_cpp.html
The question I have is not directed specifically at this code, but is more general; I'd like to understand the compiling and linking process a bit better; XCode is making this a little abstract for me. I can't seem to understand what flags should be passed to make this compile, let alone why.
I understand that the headers aren't on the default build path, so clang needs to be told where they are; I used -I./PublicUtility and clang can now find the header files.
This application also links to the CoreAudio framework, so when an application uses code from a framework, is there anything different I need to do with the compiler compared to linking to a library?
( I know the distinction between library and framework Isn't clear : What is the major difference between a framework and a toolkit? )
Right now, In terms of trying to compile PlayFile, I have the command
clang++ PlayFile.cpp -I./PublicUtility -o playfile
I tried to signal the compiler to look for frameworks with -F and for libraries with -L (though if I'm reading this application's code right, it only links to frameworks, not to any libraries.
I have read the man pages and the documentation for the gnu compiler ( clang is gcc compatible, so flags passed to gcc should be compatible with clang? )
but again it all seems a little abstract from my perspective currently.
Can anyone provide insight into what flags need to be passed under what circumstances?
On the comment of another user, I've discovered what commands xcode uses to compile the program, however I'm still a little bit lost.
All of the commands the xcode issues are relative to a directory called ~/Library/Developer/Xcode/DerivedData I'm a little closer to understanding how xcode builds programs, but none of my source files are in this directory. How would I alter the arguments XCode supplies to the compiler to compile outside of XCode? Is this directory simply a holding place that XCode uses to contain object files before they are built into a program?
Some of the the arguments still I don't understand; whether or not they're neccesary to compile the application or even what they mean.
These ones which are listed before includes or frameworks are specified.
fmessage-length=0 -Wno-trigraphs -fpascal-strings -O0 -Wno-missing-field-initializers -Wno-missing-prototypes -Wreturn-type -Wno-implicit-atomic-properties -Wno-receiver-is-weak -Wno-non-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wformat -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-empty-body -Wno-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wno-constant-conversion -Wno-int-conversion -Wno-enum-conversion -Wno-shorten-64-to-32 -Wno-newline-eof -Wno-selector -Wno-strict-selector-match -Wno-undeclared-selector -Wno-deprecated-implementations -Wno-c++11-extensions -fasm-blocks -fstrict-aliasing -Wprotocol -Wdeprecated-declarations -Winvalid-offsetof -g -fvisibility=hidden -fvisibility-inlines-hidden -Wno-sign-conversion
Wno-trigraphs and -Wno-c++11-extensions seem pretty self explanatory:
Dont interpret trigraphs in the code and dont use c++11 extensions if I'm guessing correctly?
It would be silly to ask for a definition of all of these, but some, like -fpascal-strings, give no results on a quick google search. And none of this is even written in pascal!
Looking at the commands further;
-I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
is included 3 times in one command.
Are some of these basically extraneous, or am I missing some basic concept here?
Wno-trigraphs and -Wno-c++11-extensions seem pretty self explanatory: Dont interpret trigraphs in the code and dont use c++11 extensions if I'm guessing correctly?
Not quite. First, -W is a flag to enable (and disable) warnings, so you know these flags are just about warnings, not changing any compiler features. Secondly, no- is a prefix that causes the -W flag to disable the named warning whereas without this prefix it enables warnings. So these flags are disabling warnings that occur when you use trigraphs and C++11 extensions.
It would be silly to ask for a definition of all of these, but some, like -fpascal-strings, give no results on a quick google search. And none of this is even written in pascal!
There are two basic data structures for string data. They are named 'C strings' and 'Pascal strings' respectively after languages that used them, however the general strategy can be used outside those languages. A 'C string' is a string whose length is determined by a terminating null character. A 'Pascal string' is a string where the length is stored before the string data.
The -f flag controls compiler features and so -fpascal-strings enables an extension where you can specify that a string literal will be a pascal string instead of a c string. This extension to C and C++ typically looks like this:
char const *c = "\phello, world!";
The \p escape character designates the string literal as a pascal string, and the initial byte of the string will be the length of the string. In this case c[0] will be 13. One can manually create pascal strings as well, "\xDhello, world!", but this requires manual counting and the number must be updated when you change the string.

Resources