Clang's C++ Compatibility

Introduction

Clang strives to strictly conform to the C++ standard. That means it will reject invalid C++ code that another compiler may accept. This page helps you decide whether a Clang error message means a C++-conformance bug in your code and how you can fix it.

Variable-length arrays

GCC and C99 allow an array's size to be determined at run time. This extension is not permitted in standard C++. However, Clang supports such variable length arrays in very limited circumstances for compatibility with GNU C and C99 programs:

If your code uses variable length arrays in a manner that Clang doesn't support, there are several ways to fix your code:

  1. replace the variable length array with a fixed-size array if you can determine a reasonable upper bound at compile time; sometimes this is as simple as changing int size = ...; to const int size = ...; (if the definition of size is a compile-time integral constant);
  2. use an std::string instead of a char [];
  3. use std::vector or some other suitable container type; or
  4. allocate the array on the heap instead using new Type[] - just remember to delete[] it.

Initialization of non-integral static const data members within a class definition

The following code is ill-formed in C++'03:
class SomeClass {
 public:
  static const double SomeConstant = 0.5;
};

const double SomeClass::SomeConstant;
Clang errors with something similar to:
.../your_file.h:42:42: error: 'SomeConstant' can only be initialized if it is a static const integral data member
  static const double SomeConstant = 0.5;
                      ^              ~~~
Only integral constant expressions are allowed as initializers within the class definition. See C++'03 [class.static.data] p4 for the details of this restriction. The fix here is straightforward: move the initializer to the definition of the static data member, which must exist outside of the class definition:
class SomeClass {
 public:
  static const double SomeConstant;
};

const double SomeClass::SomeConstant = 0.5;
Note that the forthcoming C++0x standard will allow this.

Unqualified lookup in templates

Some versions of GCC accept the following invalid code:
template <typename T> struct Foo {
  void Work(T x) {
    func(x);
  }
};
...
void func(int x);
...
template struct Foo<int>; // or anything else that instantiates Foo<int>::Work
The standard says that unqualified names like func are looked up when the template is defined, not when it's instantiated. Since void func(int) was not declared yet when Foo was defined, it's not considered. The fix is usually to declare func before Foo.

This is complicated by argument-dependent lookup (ADL), which is done when unqualified names are called as functions, like func(x) above. The standard says that ADL is performed in both places if any of the arguments are type-dependent, like x is in this example. However, ADL does nothing for builtin types like int, so the example is still invalid. See [basic.lookup.argdep] for more information.

Unqualified lookup into dependent bases of class templates

Some versions of GCC accept the following invalid code:
template <typename T> struct Base {
  void DoThis(T x) {}
  static void DoThat(T x) {}
};

template <typename T> struct Derived : public Base<T> {
  void Work(T x) {
    DoThis(x);  // Invalid!
    DoThat(x);  // Invalid!
  }
};
Clang correctly rejects it with the following errors (when Derived is eventually instantiated):
my_file.cpp:8:5: error: use of undeclared identifier 'DoThis'
    DoThis(x);
    ^
    this->
my_file.cpp:2:8: note: must qualify identifier to find this declaration in dependent base class
  void DoThis(T x) {}
       ^
my_file.cpp:9:5: error: use of undeclared identifier 'DoThat'
    DoThat(x);
    ^
    this->
my_file.cpp:3:15: note: must qualify identifier to find this declaration in dependent base class
  static void DoThat(T x) {}
Like we said above, unqualified names like DoThis and DoThat are looked up when the template Derived is defined, not when it's instantiated. When we look up a name used in a class, we usually look into the base classes. However, we can't look into the base class Base<T> because its type depends on the template argument T, so the standard says we should just ignore it. See [temp.dep]p3 for details.

The fix, as Clang tells you, is to tell the compiler that we want a class member by prefixing the calls with this->:

  void Work(T x) {
    this->DoThis(x);
    this->DoThat(x);
  }
Alternatively, you can tell the compiler exactly where to look:
  void Work(T x) {
    Base<T>::DoThis(x);
    Base<T>::DoThat(x);
  }
This works whether the methods are static or not, but be careful: if DoThis is virtual, calling it this way will bypass virtual dispatch!

Templates with no valid instantiations

The following code contains a typo: the programmer meant init() but wrote innit() instead.
  template <class T> class Processor {
    ...
    void init();
    ...
  };
  ...
  template <class T> void process() {
    Processor<T> processor;
    processor.innit();       // <-- should be 'init()'
    ...
  }
Unfortunately, we can't flag this mistake as soon as we see it: inside a template, we're not allowed to make assumptions about "dependent types" like Processor<T>. Suppose that later on in this file the programmer adds an explicit specialization of Processor, like so:
  template <> class Processor<char*> {
    void innit();
  };
Now the program will work — as long as the programmer only ever instantiates process() with T = char*! This is why it's hard, and sometimes impossible, to diagnose mistakes in a template definition before it's instantiated.

The standard says that a template with no valid instantiations is ill-formed. Clang tries to do as much checking as possible at definition-time instead of instantiation-time: not only does this produce clearer diagnostics, but it also substantially improves compile times when using pre-compiled headers. The downside to this philosophy is that Clang sometimes fails to process files because they contain broken templates that are no longer used. The solution is simple: since the code is unused, just remove it.

Default initialization of const variable of a class type requires user-defined default constructor

If a class or struct has no user-defined default constructor, C++ doesn't allow you to default construct a const instance of it like this ([dcl.init], p9):
class Foo {
 public:
  // The compiler-supplied default constructor works fine, so we
  // don't bother with defining one.
  ...
};

void Bar() {
  const Foo foo;  // Error!
  ...
}
To fix this, you can define a default constructor for the class:
class Foo {
 public:
  Foo() {}
  ...
};

void Bar() {
  const Foo foo;  // Now the compiler is happy.
  ...
}