Building the Bullet Physics SDK with Clang: Success!

Mostly just for fun, I decided to try compiling the Bullet Physics SDK
(www.bulletphysics.org) with clang. I am happy to report that aside
from a very small modification to the Bullet code, clang built the entire
SDK (libraries and demos) with no problem!

The small refactor was necessary because the soft body library
tries to use static const variables to zero-initialize certain objects.
The objects happen to be structs, without a user-defined constructor,
derived from another struct with a user-defined default constructor.
The reduced test case is

struct Base {
   Base() {}
};

struct Derived: Base {
};

static const Derived d;

Clang says, "error: default initialization of an object of const
type 'const Derived' requires a user-provided default constructor."
G++ accepts this code.

Looking at the C++03 standard, I'm a bit confused. Section 8.5 paragraph 6
says that "Every object of static storage duration shall be zero-initialized at
program startup before any other initialization takes place." But it also says
in paragraph 9 of the same section that "If no initializer is specified for an
object, ... if the object is of const-qualified type, the underlying class type
shall have a user-declared default constructor."

My intuition tells me that static objects get zero-initialized first,
then default-constructed a bit later, all during program startup. Is this the
correct interpretation of the standard? If so, it sounds like it goes against
the C++ principle of not paying for things you don't use. Why zero-init an
object if it's just going to be default-initialized immediately after?

Of course, if this is the case, then clang is correct, and g++ & Bullet are
not standard-conforming.

-Ryan

Mostly just for fun, I decided to try compiling the Bullet Physics SDK
(www.bulletphysics.org) with clang. I am happy to report that aside
from a very small modification to the Bullet code, clang built the entire
SDK (libraries and demos) with no problem!

The small refactor was necessary because the soft body library
tries to use static const variables to zero-initialize certain objects.
The objects happen to be structs, without a user-defined constructor,
derived from another struct with a user-defined default constructor.
The reduced test case is

struct Base {
  Base() {}
};

struct Derived: Base {
};

static const Derived d;

Clang says, "error: default initialization of an object of const
type 'const Derived' requires a user-provided default constructor."
G++ accepts this code.

Looking at the C++03 standard, I'm a bit confused. Section 8.5 paragraph 6
says that "Every object of static storage duration shall be zero-initialized at
program startup before any other initialization takes place." But it also says
in paragraph 9 of the same section that "If no initializer is specified for an
object, ... if the object is of const-qualified type, the underlying class type
shall have a user-declared default constructor."

My intuition tells me that static objects get zero-initialized first,
then default-constructed a bit later, all during program startup. Is this the
correct interpretation of the standard?

Yes.

If so, it sounds like it goes against
the C++ principle of not paying for things you don't use. Why zero-init an
object if it's just going to be default-initialized immediately after?

Default-initialization doesn't necessarily set anything to zero. Besides, the zero-initialization for static objects tends to be free.

Of course, if this is the case, then clang is correct, and g++ & Bullet are
not standard-conforming.

Yes, Clang is correct to diagnose the requirement in p9 that a const-qualified object of class type have a user-declared default constructor.

  - Doug

Yes, Clang is correct to diagnose the requirement in p9 that a const-qualified object of class type have a user-declared default constructor.

Thank you for clearing this up! I have proposed a patch to Bullet to
fix this issue.

-Ryan

FYI, Bullet is actually part of the LLVM test-suite repository, which
we regular build / test / time as part of our nightly tests.

- Daniel

FYI, Bullet is actually part of the LLVM test-suite repository, which
we regular build / test / time as part of our nightly tests.

Not the latest version though. Probably we'll need to update it...

FYI, Bullet is actually part of the LLVM test-suite repository, which
we regular build / test / time as part of our nightly tests.

Not the latest version though. Probably we'll need to update it...

Ah, that's good to know, I didn't see it because I've only been
working with the main LLVM repository, and of course, clang.
Is this nightly test run with llvm-gcc, clang, or both?

-Ryan

FYI, Bullet is actually part of the LLVM test-suite repository, which
we regular build / test / time as part of our nightly tests.

Not the latest version though. Probably we'll need to update it...

Ah, that's good to know, I didn't see it because I've only been
working with the main LLVM repository, and of course, clang.
Is this nightly test run with llvm-gcc, clang, or both?

Both, in a lot of different configurations, but we don't have any
public access to the results anymore. I'm hoping to fix that
relatively soon though.

- Daniel