GCC 4.4 Release Series
Porting to the New Tools

The GCC 4.4 release series differs from previous GCC releases in more than the usual list of new features. Some of these 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 GCC versions.

However, some of these changes are visible, and can cause grief to users porting to GCC 4.4. This document is an effort to identify major issues and provide clear solutions in a quick and easily-searched manner. Additions and suggestions for improvement are welcome.

C language issues

Preprocessor conditionals always evaluated

When using the preprocessor statement #elif, the argument is now evaluated even if earlier #if or #elif conditionals evaluated non-zero. This is done to make sure they are valid constant expressions. (For details, see bug 36320).

For example, the code

#if 1
#elif
#endif

Now produces the following diagnostic:

error: #elif with no expression

To fix this, either use #else without an argument or provide a constant expression when using #elif.

Stricter aliasing requirements

GCC warns about more cases of type-punning while optimizing, like the following.

struct A 
{ 
  char data[14];
  int i; 
};

void foo()
{
  char buf[sizeof(struct A)];
  ((struct A*)buf)->i = 4;
}

Now produces the following diagnostic:

warning: dereferencing type-punned pointer will break strict-aliasing rules

This can be temporarily worked around by using -fno-strict-aliasing or by ignoring this class of warning via -Wno-strict-aliasing. To fix, access the structure from pointers of an equivalent type, use a union, use memcpy, or (if using C++) use placement new. See the section Casting does not work as expected when optimization is turned on in our bug reporting documentation for more information.

C++ language issues

Header dependency changes

Some of the standard C++ library include files have been edited to include only the smallest possible number of additional files. As such, C++ programs that used std::printf without including <cstdio>, or used uint32_t without including <stdint.h> will no longer compile.

In detail:

The file <cstdio> is no longer included as part of <string>, <ios>, <iomanip>, <streambuf>, or <locale>.

The file <stdint.h> is no longer included as part of <string> or<ios>.

Strict null-terminated sequence utilities

Some of the standard C++ library include files have been edited to use replacement overloads for some common C library functions (if available), with the goal of improving const-correctness: functions passed a const char* return const char*.

The table below shows the functions and files that have been changed.

Header Functions
<cstring> strchr, strpbrk, strrchr, strstr, memchr
<cwchar> wcschr wcspbrk, wcsrchr, wcsstr, wmemchr

An example.

#include <cstring>

const char* str1;
char* str2 = strchr(str1, 'a');

Gives the following compiler error:

error: invalid conversion from ‘const char*’ to ‘char*’

Fixing this is easy, as demonstrated below.

#include <cstring>

const char* str1;
const char* str2 = strchr(str1, 'a');

More information about the C++ standard requirements can be found in chapter 21, section "Null-terminated sequence utilities."

Initialization changes

GCC by default no longer accepts code such as

struct A { virtual ~A (); };

struct B : public A { int i; };

struct C
{ 
  const B a; 
  C() { bar(&a); } 
  void bar(const B*); 
};

but will issue the diagnostic

In constructor 'C::C()':
error: uninitialized member 'C::a' with 'const' type 'const B'

To fix, use a member initialization list to initialize the member, like so:

C(): a(B()) { bar(&a); } 

Links

Jakub Jelinek, Results of a test mass rebuild of rawhide-20090126 with gcc-4.4.0-0.9