B.2. Changes in GCC

Red Hat Developer Toolset 2.0 is distributed with GCC 4.8, which provides a number of bug fixes and feature enhancements over the Red Hat Enterprise Linux system version and the version included in Red Hat Developer Toolset 1.1. Below is a comprehensive list of new features and compatibility changes in this release.

B.2.1. Changes Since Red Hat Developer Toolset 1.1

The following features have been added since the release of GCC included in Red Hat Developer Toolset 1.1.

B.2.1.1. Caveats

Aggressive Loop Optimizations
The loop optimizer of GCC has been improved to use language constraints in order to derive bounds for the number of iterations of a loop. The bounds are then used as a guide to loop unrolling, peeling, and loop exit test optimizations.
The optimizations assume that the loop code does not invoke undefined behavior by, for example, causing signed integer overflows or making out-of-bound array accesses. For example, consider the following code fragment:
unsigned int foo()
    unsigned int data_data[128];

    for (int fd = 0; fd < 128; ++fd)
        data_data[fd] = fd * (0x02000001); // error

    return data_data[0];
When the value of the fd variable is 64 or above, the fd * 0x02000001 operation overflows, which is invalid in both C and C++ for signed integers. In the example above, GCC may generate incorrect code or enter an infinite loop.
To fix this error, use the appropriate casts when converting between signed and unsigned types to avoid overflows, for instance:
data_data[fd] = (uint32_t) fd * (0x02000001U); // ok
If necessary, this optimization can be turned off by using the new command line option -fno-aggressive-loop-optimizations.

B.2.1.2. General Improvements and Changes

New Local Register Allocator
GCC 4.8 features a new Local Register Allocator (LRA), which replaces the 26-year old reload pass and improves the quality of generated code. The new local register allocator is meant to be simpler, easier to debug, and does a better job of register allocation.
A fast memory error detector called AddressSanitizer has been added and can be enabled by using the -fsanitize=address command line option. It augments memory access instructions in order to detect use-after-free and out-of-bound accesses to objects on the heap.
A fast data race detector called ThreadSanitizer has been added in GCC 4.8. The option to enable this feature is -fsanitize=thread.
Compiling Extremely Large Functions
Many scalability bottlenecks have been removed from GCC optimization passes. As a consequence, it is now possible to compile extremely large functions with smaller memory consumption in less time.
New -Og Optimization Level
A new general optimization level, -Og, has been introduced. This optimization level addresses the need for fast compilation and a superior debugging experience while providing a reasonable level of runtime performance. Overall, the development experience should be better than the default optimization level -O0.
Caret Diagnostic Messages
The diagnostic messages of GCC, which display a line of source code, now also show a caret that indicates the column where the problem was detected. For example:
fred.cc:4:15: fatal error: foo: No such file or directory
 #include <foo>
compilation terminated.
New -fira-hoist-pressure Option
A new command line option, -fira-hoist-pressure, has been added. This option uses the register allocator to help decide when it is worthwhile to move expressions out of loops. It can reduce the size of the compiler code, but it slows down the compiler. This option is enabled by default at -Os.
New -fopt-info Option
A new command line option, -fopt-info, has been added. This option controls printing information about the effects of particular optimization passes, and takes the following form:
The info part of the option controls what is printed. Replace it with optimized to print information when optimization takes place, missed to print information when optimization does not take place, note to print more verbose information, or optall to print everything.
Replace file_name with the name of the file in which you want the information to be written. If you omit this part of the option, GCC writes the information to the standard error output stream.
For example, to display a list of optimizations that were enabled by the -O2 option but had no effect when compiling a file named foo.c, type:
gcc -O2 -fopt-info-missed foo.c
New -floop-nest-optimize Option
A new command line option, -floop-nest-optimize, has been added. This option enables an experimental ISL-based loop nest optimizer, a generic loop nest optimizer that is based on the Pluto optimization algorithms and that calculates a loop structure optimized for data-locality and paralelism. For more information about this optimizer, see http://pluto-compiler.sourceforge.net.
Hot and Cold Attributes on Labels
The hot and cold function attributes can now also be applied to labels. Hot labels tell the compiler that the execution path following the label is more likely than any other execution path, and cold labels convey the opposite meaning. These attributes can be used in cases where __builtin_expect cannot be used, for instance with a computed goto or asm goto.

B.2.1.3. Debugging Enhancements

DWARF4 is now used as the default debugging data format when generating debugging information. To get the maximum benefit from this new debugging representation, use the latest version of Valgrind, elfutils, and GDB included in this release.
New -gsplit-dwarf Option
A new command line option, -gsplit-dwarf, has been added. This option tells the compiler driver to separate as much DWARF debugging information as possible into a separate output file with the .dwo file extension, and allows the build system to avoid linking files with debugging information.
In order to be useful, this option requires a debugger capable of reading .dwo files, such as the version of GDB included in Red Hat Developer Toolset 2.0.


elfutils, SystemTap, and Valgrind do not support the .dwo files.

B.2.1.4. C++ Changes

Experimental C++ Features from an Upcoming Standard
g++ now supports a new command line option, -std=c++1y. This option can be used for experimentation with features proposed for the next revision of the standard that is expected around 2014. Currently, the only difference from -std=c++11 is support for return type deduction in normal functions as proposed in N3386.
New thread_local Keyword
g++ now implements the C++11 thread_local keyword. In comparison with the GNU __thread keyword, thread_local allows dynamic initialization and destruction semantics.
The use of the thread_local keyword has currently one important limitation: when the dlclose() function is used to unload a dynamically loaded DSO that contains the definition of a thread_local object, the thread_local object is destroyed, its destructor is called and the DSO is unmapped from the address space of the process. If a thread in the process tries to access the thread_local object after this, the program may terminate unexpectedly. As a result, the programmer may have to take extra care to ensure that thread_local objects in a DSO are not referred after it has been unloaded.
See also the next item for dynamic initialization issues.
Dynamic Initialization of Thread-local Variables
The C++11 and OpenMP standards allow thread-local and thread-private variables to have dynamic (that is, runtime) initialization. To support this, any use of such a variable goes through a wrapper function that performs necessary initialization.
When the use and definition of the variable are in the same translation unit, this overhead can be optimized away, but when the use is in a different translation unit, there is significant overhead even if the variable does not actually need dynamic initialization. If the programmer can be sure that no use of the variable in a non-defining translation unit needs to trigger dynamic initialization (either because the variable is statically initialized, or a use of the variable in the defining translation unit will be executed before any uses in another translation unit), they can avoid this overhead by using the new -fno-extern-tls-init option.
By default, g++ uses the -fextern-tls-init option.
C++11 Attribute Syntax
g++ now implements the C++11 attribute syntax, for example:
[[noreturn]] void f();
C++11 Alignment Specifier
g++ now implements the C++11 alignment specifier, for example:
alignas(double) int i;

B.2.1.5. Fortran Changes

B. Caveats
The version of module files (the .mod files) has been incremented. Fortran modules compiled by earlier GCC versions have to be recompiled when they are used by files compiled with GCC 4.8, as this version of GCC is not able to read .mod files created by earlier versions; attempting to do so fails with an error message.


The ABI of the produced assembler data itself has not changed; object files and libraries are fully compatible with older versions except as noted in Section B., “ABI Compatibility”.
B. ABI Compatibility
Some internal names used in the assembler or object file have changed for symbols declared in the specification part of a module. If an affected module — or a file using it via use association — is recompiled, the module and all files which directly use such symbols have to be recompiled as well. This change only affects the following kind of module symbols:
  • Procedure pointers. Note that C-interoperable function pointers (type(c_funptr)) are not affected, nor are procedure-pointer components.
  • Deferred-length character strings.
B. Other Changes
A new intrinsic subroutine, BACKTRACE, has been added. This subroutine shows a backtrace at an arbitrary place in user code, program execution continues normally afterwards.
Floating Point Numbers with q as Exponential
Reading floating point numbers that use q for the exponential (such as 4.0q0) is now supported as a vendor extension for better compatibility with old data files. It is strongly recommended to use the equivalent but standard conforming e (such as 4.0e0) for I/O.
For Fortran source code, consider replacing the q in floating-point literals by a kind parameter (such as 4.0e0_qp with a suitable qp). Note that — in Fortran source code — replacing q with a simple e is not equivalent.
GFORTRAN_TMPDIR Environment Variable
The GFORTRAN_TMPDIR environment variable for specifying a non-default directory for files opened with STATUS="SCRATCH", is not used anymore. Instead, gfortran checks the POSIX/GNU standard TMPDIR environment variable and if TMPDIR is not defined, gfortran falls back to other methods to determine the directory for temporary files as documented in the user manual.
Fortran 2003
Support for unlimited polymorphic variables (CLASS(*)) has been added. Non-constant character lengths are not yet supported.
TS 29113
Assumed types (TYPE(*)) are now supported.
Experimental support for assumed-rank arrays (dimension(..)) has been added. Note that at the moment, the gfortran array descriptor is used, which is different from the array descriptor defined in TS 29113. For more information, see the header file of gfortran or use the Chasm language interoperability tools.

B.2.1.6. x86-specific Improvements

New Instructions
GCC 4.8 has added support for the Intel FXSR, XSAVE, and XSAVEOPT instructions. Corresponding intrinsics and built-in functions can now be enabled by using the -mfxsr, -mxsave, and -mxsaveopt command line options respectively.
In addition, support for the RDSEED, ADCX, ADOX, and PREFETCHW instructions has been added and can be enabled by using the -mrdseed, -madx, and -mprfchw command line options.
New Built-in Functions to Detect Run-time CPU Type and ISA
A new built-in function, __builtin_cpu_is(), has been added to detect if the run-time CPU is of a particular type. This function accepts one string literal argument with the CPU name, and returns a positive integer on a match and zero otherwise. For example, __builtin_cpu_is("westmere") returns a positive integer if the run-time CPU is an Intel Core i7 Westmere processor. For a complete list of valid CPU names, see the user manual.
A new built-in function, __builtin_cpu_supports(), has been added to detect if the run-time CPU supports a particular ISA feature. This function accepts one string literal argument with the ISA feature, and returns a positive integer on a match and zero otherwise. For example, __builtin_cpu_supports("ssse3") returns a positive integer if the run-time CPU supports SSSE3 instructions. For a complete list of valid ISA names, see the user manual.


If these built-in functions are called before any static constructors are invoked, such as IFUNC initialization, then the CPU detection initialization must be explicitly run using this newly provided built-in function, __builtin_cpu_init(). The initialization needs to be done only once. For example, the following is sample invocation inside an IFUNC initializer:
static void (*some_ifunc_resolver(void))(void)
    if (__builtin_cpu_is("amdfam10h") ...
    if (__builtin_cpu_supports("popcnt") ...
Function Multiversioning
Function multiversioning allows the programmer to specify multiple versions of the same function, each of which is specialized for a particular variant of a given target. At runtime, the appropriate version is automatically executed depending upon the target where the execution takes place. For example, consider the following code fragment:
__attribute__ ((target ("default"))) int foo () { return 0; }
__attribute__ ((target ("sse4.2"))) int foo () { return 1; }
__attribute__ ((target ("arch=atom"))) int foo () { return 2; }
When the function foo() is executed, the result returned depends upon the architecture where the program runs, not the architecture where the program was compiled. See the GCC Wiki for more details.
New RTM and HLE Intrinsics
Support for the Intel RTM and HLE intrinsics, built-in functions, and code generation has been added and can be enabled by using the -mrtm and -mhle command line options. This is done via intrinsics for Restricted Transactional Memory (RTM) and extensions to the memory model for Hardware Lock Elision (HLE).
For HLE, two new flags can be used to mark a lock as using hardware elision:
Starts lock elision on a lock variable. The memory model in use must be __ATOMIC_ACQUIRE or stronger.
Ends lock elision on a lock variable. The memory model must be __ATOMIC_RELEASE or stronger.
For example, consider the following code fragment:
while (__atomic_exchange_n (& lockvar, 1, __ATOMIC_ACQUIRE
                                        | __ATOMIC_HLE_ACQUIRE))
    _mm_pause ();

// work with the acquired lock

__atomic_clear (& lockvar, __ATOMIC_RELEASE | __ATOMIC_HLE_RELEASE);
The new intrinsics that support Restricted Transactional Memory are:
unsigned _xbegin (void)
Attempts to start a transaction. If it succeeds, this function returns _XBEGIN_STARTED, otherwise it returns a status value indicating why the transaction could not be started.
void _xend (void)
Commits the current transaction. When no transaction is active, this function causes a fault. All memory side effects of the transactions become visible to other threads in an atomic manner.
int _xtest (void)
Returns a non-zero value if a transaction is currently active, or zero if it is not.
void _xabort (unsigned char status)
Aborts the current transaction. When no transaction is active, this is a no-op. The parameter status is included in the return value of any _xbegin() call that is aborted by this function.
The following example illustrates the use of these intrinsics:
if ((status = _xbegin ()) == _XBEGIN_STARTED)
    // some code
    _xend ();
    // examine the status to see why the transaction failed and possibly retry
Transactions Using Transactional Synchronization Extensions
Transactions in the transactional memory feature (the -fgnu-tm option) of GCC can now be run using Transactional Synchronization Extensions (TSX) if available on x86 hardware.
Support for AMD Family 15h Processors
The x86 backend of GCC now supports CPUs based on AMD Family 15h cores with the 64-bit x86 instruction set support. This can be enabled by using the -march=bdver3 option.
Support for AMD Family 16h Processors
The x86 backend of GCC now supports CPUs based on AMD Family 16h cores with the 64-bit x86 instruction set support. This can be enabled by using the -march=btver2 option.

B.2.2. Changes Since Red Hat Enterprise Linux 6.4 and 5.9

The following features have been added since the release of GCC included in Red Hat Enterprise Linux 6.4 and 5.9:

B.2.2.1. Status and Features

B. C++11
GCC 4.7 and later provides experimental support for building applications compliant with C++11 using the -std=c++11 or -std=gnu++11 command line options. However, there is no guarantee for compatibility between C++11 code compiled by different versions of the compiler. Refer to Section B., “C++ ABI” for details.
The C++ runtime library, libstdc++, supports a majority of the C++11 features. However, there is no or only partial support for some features such as certain properties on type traits or regular expressions. For details, refer to the libstdc++ documentation, which also lists implementation-defined behavior.
Support for C++11 exception_ptr and future requires changes to the exception handling runtime in the system libstdc++ package. These changes will be distributed through the normal Z-stream channel. Application of all Red Hat Enterprise Linux errata may be required to see correct runtime functionality when using these features.
B. C11
GCC 4.7 and later provides experimental support for some of the features from the C11 revision of the ISO C standard, and in addition to the previous (now deprecated) -std=c1x and -std=gnu1x command line options, gcc now accepts -std=c11 and -std=gnu11. Note that since this support is experimental, it may change incompatibly in future releases.
Examples for features that are supported are Unicode strings (including the predefined macros __STDC_UTF_16__ and __STDC_UTF_32__), nonreturning functions (_Noreturn and <stdnoreturn.h>), and alignment support (_Alignas, _Alignof, max_align_t, and <stdalign.h>).
B. Parallelism and Concurrency
GCC 4.7 and later provides improved support for programming parallel applications:
  1. The GCC compilers support the OpenMP API specification for parallel programming, version 3.1. Refer to the OpenMP website for more information about this specification.
  2. The C++11 and C11 standards provide programming abstractions for multi-threaded programs. The respective standard libraries include programming abstractions for threads and thread-related features such as locks, condition variables, or futures. These new versions of the standard also define a memory model that precisely specifies the runtime behavior of a multi-threaded program, such as the guarantees provided by compilers and the constraints programmers have to pay attention to when writing multi-threaded programs.
    Note that support for the memory model is still experimental (see below for details). For more information about the status of support for C++11 and C11, refer to Section B., “C++11” and Section B., “C11” respectively.
The rest of this section describes two new GCC features in more detail. Both these features make it easier for programmers to handle concurrency (such as when multiple threads do not run truly in parallel but instead have to synchronize concurrent access to shared state), and both provide atomicity for access to memory but differ in their scope, applicability, and complexity of runtime support.
C++11 Types and GCC Built-ins for Atomic Memory Access
C++11 has support for atomic types. Access to memory locations of this type is atomic, and appears as one indivisible access even when other threads access the same memory location concurrently. The atomicity is limited to a single read or write access or one of the other atomic operations supported by such types (for example, two subsequent operations executed on a variable of atomic type are each atomic separately, but do not form one joint atomic operation).
An atomic type is declared as atomic<T>, where T is the non-atomic base type and must be trivially copyable (for example, atomic<int> is an atomic integer). GCC does not yet support any base type T, but only those that can be accessed atomically with the atomic instructions offered by the target architecture. This is not a significant limitation in practice, given that atomics are primarily designed to expose hardware primitives in an architecture-independent fashion; pointers and integrals that are not larger than a machine word on the target are supported as base types. Using base types that are not yet supported results in link-time errors.
The code generated for operations on atomic types, including the memory orders, implements the semantics specified in the C++11 standard. However, support for the C++11 memory model is still experimental, and for example GCC might not always preserve data-race freedom when optimizing code.
GCC also supports new built-ins for atomic memory accesses, which follow the design of the memory model and new atomic operations. The former set of synchronization built-ins (that is, those prefixed with __sync) are still supported.
Transactional Memory
Transactional Memory (TM) allows programs to declare that a piece of code is supposed to execute as a transaction, that is, virtually atomically and in isolation from other transactions. GCC's transactional memory runtime library, libitm, then ensures this atomicity guarantee when executing the compiled program. Compared to atomic memory accesses, it is a higher-level programming abstraction, because it is not limited to single memory locations, does not require special data types for the data it modifies, and because transactions can contain arbitrary code and be nested within other transactions (with some restrictions explained subsequently).
GCC implements transactions as specified in the Draft Specification for Transactional Language Constructs for C++, version 1.1. This draft does not yet specify the language constructs for C, but GCC already supports a C-compatible subset of the constructs when compiling C source code.
The main language constructs are transaction statements and expressions, and are declared by the __transaction_atomic or __transaction_relaxed keywords followed by a compound statement or expression, respectively. The following example illustrates how to increment a global variable y if another variable x has a value less than 10:
__transaction_atomic { if (x < 10) y++; }
This happens atomically even in a multi-threaded execution of the program. In particular, even though the transaction can load x and y and store to y, all these memory accesses are virtually executed as one indivisible step.
Note that in line with the C++11 memory model, programs that use transactions must be free of data races. Transactions are guaranteed to be virtually executed serially in a global total order that is determined by the transactional memory implementation and that is consistent with and contributes to the happens-before order enforced by the rest of the program (that is, transaction semantics are specified based on the C++11 memory model, see the draft specification linked above). Nonetheless, if a program is not data-race-free, then it has undefined behavior. For example, a thread can first initialize some data and then make it publicly accessible by code like this:
__transaction_atomic { data_public = true;}  // data_public is initially false
Another thread can then safely use the data, for instance:
__transaction_atomic { if (data_public) use(data); }
However, the following code has a data race and thus results in undefined behavior:
__transaction_atomic { temp = copy(data); if (data_public) use(temp); }
Here, copy(data) races with init(data) in the initializing thread, because this can be executed even if data_public is not true. Another example for data races is one thread accessing a variable x transactionally and another thread accessing it nontransactionally at potentially the same time. Note that the data can be safely reclaimed using code like this (assuming only one thread ever does this):
__transaction_atomic { data_public = false; }
Here, destruct() does not race with potential concurrent uses of the data because after the transaction finishes, it is guaranteed that data_public is false and thus data is private. See the specification and the C++11 memory model for more background information about this.
Note that even if transactions are required to virtually execute in a total order, this does not mean that they execute mutually exclusive in time. Transactional memory implementations attempt to run transactions as much in parallel as possible to provide scalable performance.
There are two variants of transactions: atomic transactions (__transaction_atomic) and relaxed transactions (__transaction_relaxed). The former guarantee atomicity with regard to all other code, but allow only code that is known to not include nontransactional kinds of synchronization, such as atomic or volatile memory access. In contrast, relaxed transactions allow all code (for example calls to I/O functions), but only provide atomicity with regard to other transactions. Therefore, atomic transactions can be nested within other atomic and relaxed transactions, but relaxed transactions can only be nested within other relaxed transactions. Furthermore, relaxed transactions are likely to be executed with less performance, but this depends on the implementation and available hardware.
GCC verifies these restrictions statically at compile time (for example, the requirements on code allowed to be called from within atomic transactions). This has implications for when transactions call functions that are defined within other compilation unit (source file) or within libraries. To enable such cross-compilation-unit calls for transactional code, the respective functions must be marked to contain code that is safe to use from within atomic transactions. Programmers can do so by adding the transaction_safe function attribute to the declarations of these functions and by including this declaration when defining the function. In turn, GCC then verifies that the code in these functions is safe for atomic transactions and generates code accordingly. If the programmer does not follow these constraints and/or steps, compile-time or link-time errors occur. Note that within a compilation unit, GCC detects automatically whether a function is safe for use within transactions, and the attributes therefore typically do not need to be added. See the draft specification linked above for further details.
GCC's transactional memory support is designed in such a way that it does not decrease the performance of programs that do not use transactions, nor the performance of nontransactional code, except due to the normal kinds of interference by concurrent threads that use the same resources such as the CPU.
Transactional memory support in GCC and libitm is still experimental, and both the ABI and API could change in the future if this is required due to the evolution of the specification of the language constructs, or due to implementation requirements. Note that when executing applications built with the -fgnu-tm command line option, it is currently a prerequisite to also have the appropriate version of the libitm.so.1 shared library installed.
B. Architecture-specific Options
Red Hat Developer Toolset 2.0 is only available for Red Hat Enterprise Linux 5 and 6, both for the 32-bit and 64-bit Intel and AMD architectures. Consequently, the options described below are only relevant to these architectures.
Optimization for several processors is now available through the command line options described in Table B.1, “Processor Optimization Options”.

Table B.1. Processor Optimization Options

Option Description
-march=core2 and -mtune=core2 Optimization for Intel Core 2 processors.
-march=corei7 and -mtune=corei7 Optimization for Intel Core i3, i5, and i7 processors.
-march=corei7-avx and -mtune=corei7-avx Optimization for Intel Core i3, i5, and i7 processors with AVX.
-march=core-avx-i Optimization for the Intel processor code-named Ivy Bridge with RDRND, FSGSBASE, and F16C.
-march=core-avx2 Optimization for a next-generation processor from Intel with AVX2, FMA, BMI, BMI2, and LZCNT.
-march=bdver2 and -mtune=bdver2 Optimization for AMD Opteron processors code-named Piledriver.
-march=btver1 and -mtune=btver1 Optimization for AMD family 14 processors code-named Bobcat.
-march=bdver1 and -mtune=bdver1 Optimization for AMD family 15h processors code-named Bulldozer.

Support for various processor-specific intrinsics and instructions is now available through the command line options described in Table B.2, “Support for Processor-specific Intrinsics and Instructions”.

Table B.2. Support for Processor-specific Intrinsics and Instructions

Option Description
-mavx2 Support for Intel AVX2 intrinsics, built-in functions, and code generation.
-mbmi2 Support for Intel BMI2 intrinsics, built-in functions, and code generation.
-mlzcnt Implementation and automatic generation of __builtin_clz* using the lzcnt instruction.
-mfma Support for Intel FMA3 intrinsics and code generation.
-mfsgsbase Enables the generation of new segment register read/write instructions through dedicated built-ins.
-mrdrnd Support for the Intel rdrnd instruction.
-mf16c Support for two additional AVX vector conversion instructions.
-mtbm Support for TBM (Trailing Bit Manipulation) built-in functions and code generation.
-mbmi Support for AMD's BMI (Bit Manipulation) built-in functions and code generation.
-mcrc32 Support for crc32 intrinsics.
-mmovbe Enables the use of the movbe instruction to implement __builtin_bswap32 and __builtin_bswap64.
-mxop, -mfma4, and -mlwp Support for the XOP, FMA4, and LWP instruction sets for the AMD Orochi processors.
-mabm Enables the use of the popcnt and lzcnt instructions on AMD processors.
-mpopcnt Enables the use of the popcnt instruction on both AMD and Intel processors.

When using the x87 floating-point unit, GCC now generates code that conforms to ISO C99 in terms of handling of floating-point excess precision. This can be enabled by -fexcess-precision=standard and disabled by -fexcess-precision=fast. This feature is enabled by default when using standards conformance options such as -std=c99.
Vectors of type vector long long or vector long are passed and returned using the same method as other vectors with the VSX instruction set. Previously GCC did not adhere to the ABI for 128-bit vectors with 64-bit integer base types (see GCC PR 48857).
The -mrecip command line option has been added, which indicates whether the reciprocal and reciprocal square root instructions should be used.
The -mveclibabi=mass command line option has been added. This can be used to enable the compiler to auto-vectorize mathematical functions using the Mathematical Acceleration Subsystem library.
The -msingle-pic-base command line option has been added, which instructs the compiler to avoid loading the PIC base register in function prologues. The PIC base register must be initialized by the runtime system.
The -mblock-move-inline-limit command line option has been added, which enables the user to control the maximum size of inlined memcpy calls and similar.
B. Link-time Optimization
Link-time optimization (LTO) is a compilation technique in which GCC generates an internal representation of each compiled input file in addition to the native code, and writes both to the output object file. Subsequently, when several object files are linked together, GCC uses the internal representations of the compiled code to optimize inter-procedurally across all the compilation units. This can potentially improve the performance of the generated code (for example, functions defined in one file can potentially be inlined when called in another file).
To enable LTO, the -flto option needs to be specified at both compile time and link time. For further details, including interoperability with linkers and parallel execution of LTO, refer to the documentation for -flto in the GCC 4.7.0 Manual. Also note that the internal representation is not a stable interface, so LTO will only apply to code generated by the same version of GCC.


Use of Link-time Optimization with debug generation is not yet supported in gcc 4.7 and 4.8 and so use of the -flto and the -g options together is unsupported in Red Hat Developer Toolset.
B. Miscellaneous
-Ofast is now supported as a general optimization level. It operates similar to -O3, adds options that can yield better-optimized code, but in turn might invalidate standards compliance (for example, -ffast-math is enabled by -Ofast).
GCC can now inform users about cases in which code generation might be improved by adding attributes such as const, pure, and noreturn to functions declared in header files. Use the -Wsuggest-attribute=[const|pure|noreturn] command line option to enable this.
Assembler code can now make use of a goto feature that allows for jumps to labels in C code.

B.2.2.2. Language Compatibility

In this section, we describe the compatibility between the Red Hat Developer Toolset compilers and the Red Hat Enterprise Linux system compilers at the programming-language level (for example, differences in the implementation of language standards such as C99, or changes to the warnings generated by -Wall).
Some of the changes are a result of bug fixing, and some old behaviors have been intentionally changed in order to support new standards, or relaxed in standards-conforming ways to facilitate compilation or runtime performance. Some of these changes are not visible to the naked eye and will not cause problems when updating from older versions. However, some of these changes are visible, and can cause grief to users porting to Red Hat Developer Toolset's version of GCC. The following text attempts to identify major issues and suggests solutions.
B. C
Constant expressions are now handled by GCC in a way that conforms to C90 and C99. For code expressions that can be transformed into constants by the compiler but are in fact not constant expressions as defined by ISO C, this may cause warnings or errors.
Ill-formed redeclarations of library functions are no longer accepted by the compiler. In particular, a function with a signature similar to the built-in declaration of a library function (for example, abort() or memcpy()) must be declared with extern "C" to be considered as a redeclaration, otherwise it is ill-formed.
Duplicate Member
Consider the following struct declaration:
struct A { int *a; union { struct { int *a; }; }; };
Previously, this declaration used to be diagnosed just by the C++ compiler, now it is also diagnosed by the C compiler. Because of the anonymous unions and structs, there is ambiguity about what .a actually refers to and one of the fields therefore needs to be renamed.
B. C++
Header Dependency Changes
<iostream>, <string>, and other STL headers that previously included <unistd.h> as an implementation detail (to get some feature macros for gthr*.h purposes) no longer do so, because it was a C++ standard violation. This can result in diagnostic output similar to the following:
error: ‘truncate’ was not declared in this scope
error: ‘sleep’ was not declared in this scope
error: ‘pipe’ was not declared in this scope
error: there are no arguments to 'offsetof' that depend on a template
parameter, so a declaration of 'offsetof' must be available
To fix this, add the following line early in the source or header files that need it:
#include <unistd.h>
Many of the standard C++ library include files have been edited to no longer include <cstddef> to get namespace-std-scoped versions of size_t and ptrdiff_t. As such, C++ programs that used the macros NULL or offsetof without including <cstddef> will no longer compile. The diagnostic produced is similar to the following:
error: 'ptrdiff_t' does not name a type
error: 'size_t' has not been declared
error: 'NULL' was not declared in this scope
error: there are no arguments to 'offsetof' that depend on a template
parameter, so a declaration of 'offsetof' must be available
To fix this issue, add the following line:
#include <cstddef>
Name Lookup Changes
G++ no longer performs an extra unqualified lookup that it incorrectly performed in the past. Instead, it implements the two-phase lookup rules correctly, and an unqualified name used in a template must have an appropriate declaration that:
  1. is either in scope at the point of the template's definition, or
  2. can be found by argument-dependent lookup at the point of instantiation.
Code that incorrectly depends on a second unqualified lookup at the point of instantiation (such as finding functions declared after the template or in dependent bases) will result in compile-time errors.
In some cases, the diagnostics provided by G++ include hints how to fix the bugs. Consider the following code:
template<typename T>
int t(T i)
    return f(i);

int f(int i)
    return i;

int main()
    return t(1);
The following diagnostics output will be produced:
In instantiation of ‘int t(T) [with T = int]’
required from here
error: ‘f’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
note: ‘int f(int)’ declared here, later in the translation unit
To correct the error in this example, move the declaration of function f() before the definition of template function t(). The -fpermissive compiler flag turns compile-time errors into warnings and can be used as a temporary workaround.
Uninitialized const
Consider the following declaration:
struct A { int a; A (); };
struct B : public A { };
const B b;
An attempt to compile this code now fails with the following error:
error: uninitialized const ‘b’ [-fpermissive]
note: ‘const struct B’ has no user-provided default constructor
This happens, because B does not have a user-provided default constructor. Either an initializer needs to be provided, or the default constructor needs to be added.
Visibility of Template Instantiations
The ELF symbol visibility of a template instantiation is now properly constrained by the visibility of its template arguments. For instance, users that instantiate standard library components like std::vector with hidden user defined types such as struct my_hidden_struct can now expect hidden visibility for std::vector<my_hidden_struct> symbols. As a result, users that compile with the -fvisibility=hidden command line option should be aware of the visibility of types included from the library headers used. If the header does not explicitly control symbol visibility, types from those headers will be hidden, along with instantiations that use those types. For instance, consider the following code:
#include <vector>               // template std::vector has default visibility
#include <ctime>                // struct tm has hidden visibility
template class std::vector<tm>; // instantiation has hidden visibility
One approach to adjusting the visibility of a library header <foo.h> is to create a forwarding header on the -I include path consisting of the following:
#pragma GCC visibility push(default)
#include_next <foo.h>
#pragma GCC visibility push
User-defined Literal Support
When compiling C++ with the -std={c++11,c++0x,gnu++11,gnu++0x} command line option, GCC 4.7.0 and later, unlike older versions, supports user-defined literals, which are incompatible with some valid ISO C++03 code. In particular, white space is now needed after a string literal before something that could be a valid user defined literal. Consider the following code:
const char *p = "foobar"__TIME__;
In C++03, the __TIME__ macro expands to some string literal and is concatenated with the other one. In C++11, __TIME__ is not expanded and instead, operator "" __TIME__ is being looked up, which results in a warning like:
error: unable to find string literal operator ‘operator"" __TIME__’
This applies to any string literal followed without white space by some macro. To fix this, add some white space between the string literal and the macro name.
Taking the Address of Temporary
Consider the following code:
struct S { S (); int i; };
void bar (S *);
void foo () { bar (&S ()); }
Previously, an attempt to compile this code produced a warning message, now it fails with an error. This can be fixed by adding a variable and passing the address of this variable instead of the temporary. The -fpermissive compiler flag turns compile-time errors into warnings and can be used as a temporary workaround.
G++ now sets the predefined macro __cplusplus to the correct value: 199711L for C++98/03, and 201103L for C++11.
G++ now properly re-uses stack space allocated for temporary objects when their lifetime ends, which can significantly lower stack consumption for some C++ functions. As a result of this, some code with undefined behavior will now break.
When an extern declaration within a function does not match a declaration in the enclosing context, G++ now properly declares the name within the namespace of the function rather than the namespace which was open just before the function definition.
G++ now implements the proposed resolution of the C++ standard's core issue 253. Default initialization is allowed if it initializes all subobjects, and code that fails to compile can be fixed by providing an initializer such as:
struct A { A(); };
struct B : A { int i; };
const B b = B();
Access control is now applied to typedef names used in a template, which may cause G++ to reject some ill-formed code that was accepted by earlier releases. The -fno-access-control option can be used as a temporary workaround until the code is corrected.
G++ now implements the C++ standard's core issue 176. Previously, G++ did not support using the injected-class-name of a template base class as a type name, and lookup of the name found the declaration of the template in the enclosing scope. Now lookup of the name finds the injected-class-name, which can be used either as a type or as a template, depending on whether or not the name is followed by a template argument list. As a result of this change, some code that was previously accepted may be ill-formed, because:
  1. the injected-class-name is not accessible because it is from a private base, or
  2. the injected-class-name cannot be used as an argument for a template parameter.
In either of these cases, the code can be fixed by adding a nested-name-specifier to explicitly name the template. The first can be worked around with -fno-access-control, the second is only rejected with -pedantic.
B. C/C++ Warnings
GCC 4.7.0 and later adds a number of new warnings that are either enabled by default, or by using the -Wall option. Although these warnings do not result in a compilation failure on their own, often -Wall is used in conjunction with -Werror, causing these warnings to act like errors. This section provides a list of these new or newly enabled warnings. Unless noted otherwise, these warnings apply to both C and C++.
The behavior of the -Wall command line option has changed and now includes the new warning flags -Wunused-but-set-variable and, with -Wall -Wextra, -Wunused-but-set-parameter. This may result in new warnings in code that compiled cleanly with previous versions of GCC. For example, consider the following code:
void fn (void)
    int foo;
    foo = bar ();  /* foo is never used.  */
The following diagnostic output will be produced:
warning: variable "foo" set but not used [-Wunused-but-set-variable]
To fix this issue, first see if the unused variable or parameter can be removed without changing the result or logic of the surrounding code. If not, annotate it with __attribute__((__unused__)). As a workaround, you can use the -Wno-error=unused-but-set-variable or -Wno-error=unused-but-set-parameter command line option.
The -Wenum-compare option causes GCC to report a warning when values of different enum types are being compared. Previously, this option only worked for C++ programs, but now it works for C as well. This warning is enabled by -Wall and may be avoided by using a type cast.
Casting integers to larger pointer types now causes GCC to display a warning by default. To disable these warnings, use the -Wno-int-to-pointer-cast option, which is available for both C and C++.
Conversions between NULL and non-pointer types now cause GCC to report a warning by default. Previously, these warnings were only displayed when explicitly using -Wconversion. To disable these warnings, use the new -Wno-conversion-null command line option.
GCC can now warn when a class that has virtual functions and a non-virtual destructor is destroyed by using delete. This is unsafe to do because the pointer might refer to a base class that does not have a virtual destructor. The warning is enabled by -Wall and by a new command line option, -Wdelete-non-virtual-dtor.
New -Wc++11-compat and -Wc++0x-compat options are now available. These options cause GCC to display a warning about C++ constructs whose meaning differs between ISO C++ 1998 and ISO C++ 2011 (such as identifiers in ISO C++ 1998 that are keywords in ISO C++ 2011). This warning is enabled by -Wall and enables the -Wnarrowing option.
B. Fortran
B. New Features
  • A new compile flag -fstack-arrays has been added. This flag causes all local arrays to be put on stack memory, which can significantly improve the performance of some programs. Note that programs that use very large local arrays may require you to extend your runtime limits for stack memory.
  • Compile time has been significantly improved. For example, the improvement may be noticeable when working with programs that use large array constructors.
  • To improve code generation and diagnostics, the -fwhole-file compile flag is now enabled by default, and can be used with a newly supported -fwhole-program flag. To disable it, use the deprecated -fno-whole-file flag.
  • A new command line option -M is now supported. Similarly to gcc, this option allows you to generate Makefile dependencies. Note that the -cpp option may be required as well.
  • The -finit-real= command line option now supports snan as a valid value. This allows you to initialize REAL and COMPLEX variables with a signaling NaN (not a number), and requires you to enable trapping (for example, by using the -ffpe-trap= command line option). Note that compile-time optimizations may turn a signaling NaN into a quiet NaN.
  • A new command line option -fcheck= has been added. This option accepts the following arguments:
    • The -fcheck=bounds option is equivalent to the -fbounds-check command line option.
    • The -fcheck=array-temps option is equivalent to the -fcheck-array-temporaries command line option.
    • The -fcheck=do option checks for invalid modification of loop iteration variables.
    • The -fcheck=recursive option checks for recursive calls to subroutines or functions that are not marked as recursive.
    • The -fcheck=pointer option performs pointer association checks in calls, but does not handle undefined pointers nor pointers in expressions.
    • The -fcheck=all option enables all of the above options.
  • A new command line option -fno-protect-parens has been added. This option allows the compiler to reorder REAL and COMPLEX expressions with no regard to parentheses.
  • When OpenMP's WORKSHARE is used, array assignments and WHERE will now be run in parallel.
  • More Fortran 2003 and Fortran 2008 mathematical functions can now be used as initialization expressions.
  • The GCC$ compiler directive now enables support for some extended attributes such as STDCALL.
B. Compatibility Changes
  • The -Ofast command line option now automatically enables the -fno-protect-parens and -fstack-arrays flags.
  • Front-end optimizations can now be disabled by the -fno-frontend-optimize option, and selected by the -ffrontend-optimize option. The former is essentially only desirable if invalid Fortran source code needs to be compiled (for example, when functions—as compared to subroutines—have side-effects) or to work around compiler bugs.
  • The GFORTRAN_USE_STDERR environment variable has been removed, and GNU Fortran now always prints error messages to standard error.
  • The -fdump-core command line option and the GFORTRAN_ERROR_DUMPCORE environment variable have been removed. When encountering a serious error, GNU Fortran now always aborts the execution of the program.
  • The -fbacktrace command line option is now enabled by default. When a fatal error occurs, GNU Fortran now attempts to print a backtrace to standard error before aborting the execution of the program. To disable this behavior, use the -fno-backtrace option.
  • GNU Fortran no longer supports the use of the -M command line option to generate Makefile dependencies for the module path. To perform this operation, use the -J option instead.
  • To significantly reduce the number of warnings, the -Wconversion command line option now only displays warnings when a conversion leads to information loss, and a new command line option -Wconversion-extra has been added to display warnings about other conversions. The -Wconversion option is now enabled with -Wall.
  • A new command line option -Wunused-dummy-argument has been added. This option can be used to display warnings about unused dummy arguments, and is now enabled with -Wall. Note that the -Wunused-variable option previously also warned about unused dummy arguments.
  • The COMMON default padding has been changed. Previously, the padding was added before a variable. Now it is added after a variable to increase the compatibility with other vendors, as well as to help to obtain the correct output in some cases. Note that this behavior is in contrast with the behavior of the -falign-commons option.
  • GNU Fortran no longer links against the libgfortranbegin library. The MAIN__ assembler symbol is the actual Fortran main program and is invoked by the main function, which is now generated and put in the same object file as MAIN__. Note that the libgfortranbegin library is still present for backward compatibility.
B. Fortran 2003 Features
  • Improved but still experimental support for polymorphism between libraries and programs and for complicated inheritance patterns.
  • Generic interface names which have the same name as derived types are now supported, which allows the creation of constructor functions. Note that Fortran does not support static constructor functions; only default initialization or an explicit structure-constructor initialization are available.
  • Automatic (re)allocation: In intrinsic assignments to allocatable variables, the left-hand side will be automatically allocated (if unallocated) or reallocated (if the shape or type parameter is different). To avoid the small performance penalty, you can use a(:) = ... instead of a = ... for arrays and character strings — or disable the feature using -std=f95 or -fno-realloc-lhs.
  • Experimental support of the ASSOCIATE construct has been added.
  • In pointer assignments it is now possible to specify the lower bounds of the pointer and, for a rank-1 or a simply contiguous data-target, to remap the bounds.
  • Deferred type parameter: For scalar allocatable and pointer variables the character length can now be deferred.
  • Namelist variables with allocatable attribute, pointer attribute, and with a non-constant length type parameter are now supported.
  • Support has been added for procedure-pointer function results and procedure-pointer components (including PASS).
  • Support has been added for allocatable scalars (experimental), DEFERRED type-bound procedures, and the ERRMSG= argument of the ALLOCATE and DEALLOCATE statements.
  • The ALLOCATE statement now supports type-specs and the SOURCE= argument.
  • Rounding (ROUND=, RZ, ...) for output is now supported.
  • The INT_FAST{8,16,32,64,128}_T format for ISO_C_BINDING intrinsic module type parameters is now supported.
  • OPERATOR(*) and ASSIGNMENT(=) are now allowed as GENERIC type-bound procedures (i.e. as type-bound operators).
B. Fortran 2003 Compatibility
Extensible derived types with type-bound procedure or procedure pointer with PASS attribute now have to use CLASS in line with the Fortran 2003 standard; the workaround to use TYPE is no longer supported.
B. Fortran 2008 Features
  • A new command line option -std=f2008ts has been added. This option enables support for programs that conform to the Fortran 2008 standard and the draft Technical Specification (TS) 29113 on Further Interoperability of Fortran with C. For more information, refer to the Chart of Fortran TS 29113 Features supported by GNU Fortran.
  • The DO CONCURRENT construct is now supported. This construct can be used to specify that individual loop iterations do not have any interdependencies.
  • Full single-image support except for polymorphic coarrays has been added, and can be enabled by using the -fcoarray=single command line option. Additionally, GNU Fortran now provides preliminary support for multiple images via an MPI-based coarray communication library. Note that the library version is not yet usable as remote coarray access is not yet possible.
  • The STOP and ERROR STOP statements have been updated to support all constant expressions.
  • The CONTIGUOUS attribute is now supported.
  • Use of ALLOCATE with the MOLD argument is now supported.
  • The STORAGE_SIZE intrinsic inquiry function is now supported.
  • The NORM2 and PARITY intrinsic functions are now supported.
  • The following bit intrinsics have been added:
    • the POPCNT and POPPAR bit intrinsics for counting the number of 1 bits and returning the parity;
    • the BGE, BGT, BLE, and BLT bit intrinsics for bitwise comparisons;
    • the DSHIFTL and DSHIFTR bit intrinsics for combined left and right shifts;
    • the MASKL and MASKR bit intrinsics for simple left and right justified masks;
    • the MERGE_BITS bit intrinsic for a bitwise merge using a mask;
    • the SHIFTA, SHIFTL, and SHIFTR bit intrinsics for shift operations;
    • the transformational bit intrinsics IALL, IANY, and IPARITY.
  • The EXECUTE_COMMAND_LINE intrinsic subroutine is now supported.
  • The IMPURE attribute for procedures is now supported. This allows the use of ELEMENTAL procedures without the restrictions of PURE.
  • Null pointers (including NULL()) and unallocated variables can now be used as an actual argument to optional non-pointer, non-allocatable dummy arguments, denoting an absent argument.
  • Non-pointer variables with the TARGET attribute can now be used as an actual argument to POINTER dummies with INTENT(IN).
  • Pointers that include procedure pointers and those in a derived type (pointer components) can now also be initialized by a target instead of only by NULL.
  • The EXIT statement (with construct-name) can now be used to leave the ASSOCIATE, BLOCK, IF, SELECT CASE, and SELECT TYPE constructs in addition to DO.
  • Internal procedures can now be used as actual arguments.
  • The named constants INTEGER_KINDS, LOGICAL_KINDS, REAL_KINDS, and CHARACTER_KINDS of the intrinsic module ISO_FORTRAN_ENV have been added. These arrays contain the supported 'kind' values for the respective types.
  • The C_SIZEOF module procedures of the ISO_C_BINDINGS intrinsic module and the COMPILER_VERSION and COMPILER_OPTIONS module procedures of the ISO_FORTRAN_ENV intrinsic module have been implemented.
  • The OPEN statement now supports the NEWUNIT= option. This option returns a unique file unit and therefore prevents inadvertent use of the same unit in different parts of the program.
  • Unlimited format items are now supported.
  • The INT{8,16,32} and REAL{32,64,128} format for ISO_FORTRAN_ENV intrinsic module type parameters are now supported.
  • It is now possible to use complex arguments with the TAN, SINH, COSH, TANH, ASIN, ACOS, and ATAN functions. Additionally, the new functions ASINH, ACOSH, and ATANH have been added for real and complex arguments, and ATAN(Y,X) now serves as an alias for ATAN2(Y,X).
  • The BLOCK construct has been implemented.
B. Fortran 2008 Compatibility
The implementation of the ASYNCHRONOUS attribute in GCC is now compatible with the candidate draft of TS 29113: Technical Specification on Further Interoperability with C.
B. Fortran 77 Compatibility
When the GNU Fortran compiler is issued with the -fno-sign-zero option, the SIGN intrinsic now behaves as if zero were always positive.

B.2.2.3. ABI Compatibility

This section describes compatibility between the Red Hat Developer Toolset compilers and the system compilers at the application binary interface (ABI) level.
B. C++ ABI
Because the upstream GCC community development does not guarantee C++11 ABI compatibility across major versions of GCC, the same applies to use of C++11 with Red Hat Developer Toolset. Consequently, using the -std=c++11 option is supported in Red Hat Developer Toolset 2.0 only when all C++ objects compiled with that flag have been built using the same major version of Red Hat Developer Toolset. The mixing of objects, binaries and libraries, built by the Red Hat Enterprise Linux 5 or 6 system toolchain GCC using the -std=c++0x or -std=gnu++0x flags, with those built with the -std=c++11 or -std=gnu++11 flags using the GCC in Red Hat Developer Toolset is explicitly not supported.
As later major versions of Red Hat Developer Toolset may use a later major release of GCC, forward-compatibility of objects, binaries, and libraries built with the -std=c++11 or -std=gnu++11 options cannot be guaranteed, and so is not supported.
The default language standard setting for Red Hat Developer Toolset is C++98. Any C++98-compliant binaries or libraries built in this default mode (or explicitly with -std=c++98) can be freely mixed with binaries and shared libraries built by the Red Hat Enterprise Linux 5 or 6 system toolchain GCC. Red Hat recommends use of this default -std=c++98 mode for production software development.


Use of C++11 features in your application requires careful consideration of the above ABI compatibility information.
Aside from the C++11 ABI, discussed above, the Red Hat Enterprise Linux Application Compatibility Specification is unchanged for Red Hat Developer Toolset. When mixing objects built with Red Hat Developer Toolset with those built with the Red Hat Enterprise Linux v5.x/v6.x toolchain (particularly .o/.a files), the Red Hat Developer Toolset toolchain should be used for any linkage. This ensures any newer library features provided only by Red Hat Developer Toolset are resolved at link-time.
A new standard mangling for SIMD vector types has been added to avoid name clashes on systems with vectors of varying length. By default the compiler still uses the old mangling, but emits aliases with the new mangling on targets that support strong aliases. -Wabi will now display a warning about code that uses the old mangling.
B. Miscellaneous
GCC now optimizes calls to various standard C string functions such as strlen(), strchr(), strcpy(), strcat() and stpcpy() (as well as their respective _FORTIFY_SOURCE variants) by transforming them into custom, faster code. This means that there might be fewer or other calls to those functions than in the original source code. The optimization is enabled by default at -O2 or higher optimization levels. It is disabled when using -fno-optimize-strlen or when optimizing for size.
When compiling for 32-bit GNU/Linux and not optimizing for size, -fomit-frame-pointer is now enabled by default. The prior default setting can be chosen by using the -fno-omit-frame-pointer command line option.
Floating-point calculations on x86 targets and in strict C99 mode are now compiled by GCC with a stricter standard conformance. This might result in those calculations executing significantly slower. It can be disabled using -fexcess-precision=fast.

B.2.2.4. Debugging Compatibility

GCC now generates DWARF debugging information that uses more or newer DWARF features than previously. GDB contained in Red Hat Developer Toolset can handle these features, but versions of GDB older than 7.0 cannot. GCC can be restricted to only generate debugging information with older DWARF features by using the -gdwarf-2 -gstrict-dwarf or -gdwarf-3 -gstrict-dwarf options (the latter are handled partially by versions of GDB older than 7.0).
Many tools such as Valgrind, SystemTap, or third-party debuggers utilize debugging information. It is suggested to use the -gdwarf-2 -gstrict-dwarf options with those tools.


Use of Link-time Optimization with debug generation is not yet supported in gcc 4.7 and 4.8 and so use of the -flto and the -g options together is unsupported in Red Hat Developer Toolset.

B.2.2.5. Other Compatibility

GCC is now more strict when parsing command line options, and both gcc and g++ report an error when invalid command line options are used. In particular, when only linking and not compiling code, earlier versions of GCC ignored all options starting with --. For example, options accepted by the linker such as --as-needed and --export-dynamic are not accepted by gcc and g++ anymore, and should now be directed to the linker using -Wl,--as-needed or -Wl,--export-dynamic if that is intended.
Because of the new link-time optimization feature (see Section B., “Link-time Optimization”), support for the older intermodule optimization framework has been removed and the -combine command line option is not accepted anymore.