Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing multiple -std switches to g++

Tags:

gcc

g++

options

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.

like image 739
krlmlr Avatar asked Nov 12 '16 13:11

krlmlr


People also ask

Why do switch statements need break?

You can use the break statement to end processing of a particular labeled statement within the switch statement. It branches to the end of the switch statement. Without break , the program continues to the next labeled statement, executing the statements until a break or the end of the statement is reached.

Can a switch case have multiple values?

A switch statement using multiple value cases correspond to using more than one value in a single case. This is achieved by separating the multiple values in the case with a comma.

What is the switch formula in Excel?

The SWITCH function evaluates one value (called the expression) against a list of values, and returns the result corresponding to the first matching value.

Is switch faster than if else?

A switch statement is significantly faster than an if-else ladder if there are many nested if-else's involved. This is due to the creation of a jump table for switch during compilation. As a result, instead of checking which case is satisfied throughout execution, it just decides which case must be completed.


1 Answers

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.

like image 117
Mike Kinghan Avatar answered Sep 29 '22 10:09

Mike Kinghan