llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.09k stars 11.6k forks source link

Miscompiled direct base initialization in inherited constructor from virtual base of same type #33774

Open hubert-reinterpretcast opened 7 years ago

hubert-reinterpretcast commented 7 years ago
Bugzilla Link 34426
Version trunk
OS All
CC @DougGregor,@zygoloid

Extended Description

When a constructor is inherited from a virtual base and the class from which said constructor is inherited is also a direct base of the complete object being constructed, the initialization of the direct base is supposed to be a default initialization, but Clang seems to treat it like the virtual base.

SOURCE (<stdin>):

extern "C" int printf(const char *, ...);

struct A { A(int); A() = default; };
A::A(int x) { printf("%s: %d\n", __PRETTY_FUNCTION__, x); }

struct B : virtual A { using A::A; };
struct C : B, A { using B::B; };

int main(void) { C c(42); }

COMPILER INVOCATION:

clang++ -Wall -Wextra -Wno-inaccessible-base -xc++ -std=c++1z -o a.out -

COMPILER OUTPUT:

(Clean compile)

ACTUAL RUN OUTPUT (./a.out):

A::A(int): 42
A::A(int): 42

EXPECTED RUN OUTPUT:

A::A(int): 42

COMPILER VERSION INFO (clang++ -v):

clang version 6.0.0 (https://github.com/llvm-mirror/clang.git 9b13d907c509a53fd938dcc777bb7dd097cea4c0) (https://github.com/llvm-mirror/llvm.git 707fb1cf0ca99d98c59f1ae87b7e0ff9b2dd0c8b)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /opt/wandbox/clang-head/bin
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/5
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/5.4.0
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/6
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/6.0.0
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/5.4.0
Candidate multilib: .;@m64
Selected multilib: .;@m64
hubert-reinterpretcast commented 7 years ago

Similarly, the virtual base initialization is miscompiled when the constructor is inherited from the direct base (or at least this is about the only interpretation more natural than deeming the program ill-formed).

extern "C" int printf(const char *, ...);

struct A { A(int); A() = default; };
A::A(int x) { printf("%s: %d\n", __PRETTY_FUNCTION__, x); }

struct B : virtual A { };
struct C : B, A { using A::A; };

int main(void) { C c(42); }