https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84451

            Bug ID: 84451
           Summary: Multiple invocation of virtual base class constructor
                    in diamond inheritance
           Product: gcc
           Version: 5.5.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: tolez_xuninada at hotmail dot com
  Target Milestone: ---

I have a virtual and multiple inheritance situation: classes E<int> and 
F<int> inherits virtually from Root<int> and G<int> 
inherits from a wrapper class MultipleInherit<Root&lt;int>,E<int>,F<int>>, 
which in turns inherit from E<int> and F<int>. Here's a minimal working 
example: 

In testbases1.cpp: 
#include<iostream> 
#include<utility> 
#include<type_traits> 

using namespace std; 

namespace details { 
template 
< 
  template <class,class> class BinaryPred, 
  class FirstOp, 
  class SecondOp, 
  class ... RestOp 
> struct OneToAll { 
  static constexpr bool value = 
    BinaryPred<FirstOp,SecondOp>::value && 
    OneToAll<BinaryPred,FirstOp,RestOp...>::value; 
}; 

template 
< 
  template <class,class> class BinaryPred, 
  class FirstOp, 
  class SecondOp, 
  class ... RestOp 
> 
constexpr bool OneToAll_v = 
OneToAll<BinaryPred,FirstOp,SecondOp,RestOp...>::value; 

template 
< 
  template <class,class> class BinaryPred, 
  class FirstOp, 
  class SecondOp 
> 
struct OneToAll<BinaryPred,FirstOp,SecondOp> { 
  static constexpr bool value = BinaryPred<FirstOp,SecondOp>::value; 
}; 

struct EmptyBase {}; 

template < class VirtualBase, class ... Bases > 
struct MultipleInherit : 
  public 
std::conditional_t<OneToAll_v&lt;std::is_base_of,VirtualBase,Bases...>, 
         EmptyBase, 
         VirtualBase>, 
  public Bases... 
{ 

  static constexpr std::size_t NBases = sizeof...(Bases)+1; 

  template < class ... Args > 
  MultipleInherit(Args&&... args) 
    :VirtualBase(std::forward<Args>(args)...) 
    ,Bases{std::forward<Args>(args)...}... 
  { 
    cout << "MI()\n"; 
  } 

}; 

} 

using namespace details; 

template <class T> 
struct Root { 
  Root(T& i, const double& d) : ri_(i), d_(d) { cout << "Root()\n"; }; 
protected: 
  T& ri_; 
  double d_; 
}; 

template < class T > 
struct E : public virtual Root<T> { 
  E(T& i, const double& d) : Root<T>(i,d) { 
    cout << "E()\n"; 
  } 
}; 

template < class T > 
struct F : public virtual Root<T> { 
  F(T& i, const double& d) : Root<T>(i,d) { 
    cout << "F()\n"; 
  } 
}; 

template < class T > 
struct G : public MultipleInherit<Root&lt;T>,E<T>,F<T>> { 
  using BaseType = MultipleInherit<Root&lt;T>,E<T>,F<T>>; 
  G(T& i, const double& d) : Root<T>(i,d),BaseType(i,d) { 
    cout << "G()\n"; 
  } 
}; 

int main(int argc, char* argv[]) { 
  int i = 3; 
  double d = 4; 
  G<int> g(i,d); 
} 

If I compile with gcc 7.3.0: g++ testbases1.cpp -o testbases1 -g -std=c++14, 
I get the expected output: 
Root() 
E() 
F() 
MI() 
G() 
I also tried clang++ which gives the correct answer too. But if I compile with
gcc 5.5.0, I get: 
Root() 
Root() 
E() 
Root() 
F() 
MI() 
G() 

The gcc 5.5.0 is obviously giving the wrong answer because one would expect 
the virtual base is only constructed once in this situation.

Reply via email to