Bug 21917 - Missing warning when trying to explicitly construct a virtual base
Summary: Missing warning when trying to explicitly construct a virtual base
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.4.0
: P2 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2005-06-04 22:18 UTC by Ivan Godard
Modified: 2024-04-10 21:42 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2005-11-24 02:25:02


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ivan Godard 2005-06-04 22:18:04 UTC
struct  virt { virt() : i(2) {} virt(int i) : i(i){} int i;  };
struct der1 : public virtual virt { der1(int i) : virt(i) {} };
struct der2 : public virtual virt { der2(int i) : virt(i) {} };
struct top : public der1, public der2 {
    top () : der1(0), der2(1) {} };
int main() { top t; }


Compiles without comment. However, the null constructor for "virt" is called
rather than the explicit constructor that is indicated by the constructor chain
from top. In fact, the der* constructors say " : virt(i)" but that
sub-constructor will never be called because virt is a virtual base class.

I don't know if it is actually an error to try to explicitly construct a virtual
base, but is sure is misleading and I think deserves at least a warning.
Comment 1 Ivan Godard 2005-06-04 22:22:14 UTC
p.s. I suppose that if there is only a single path to the virtual base then
explicit construction is meaningful and the explicit construction in the der*
classes is not wrong. But in the constructor for "top" the compiler knows that
there are multiple derivations from virt (it has to or it couldn't know to call
the null constructor), so the warning could be issued in "top". Something like
"base constructor virt(int) in der1(int) bypassed, virt() used instead"?

Ivan
Comment 2 Andrew Pinski 2005-06-05 03:02:59 UTC
This is how C++ is done, maybe a warning can be emitted but it seems like it will emitt too much for 
valid C++ code.
Comment 3 Gabriel Dos Reis 2005-11-24 02:25:02 UTC
(In reply to comment #2)
> This is how C++ is done, maybe a warning can be emitted but it seems like it
> will emitt too much for 
> valid C++ code.
> 

I don't know; the code shown is very contrived to my taste.
Comment 4 Manuel López-Ibáñez 2007-01-09 15:02:17 UTC
Have you tried compiling with -pedantic -Wall -Wextra ?
Comment 5 Ivan Godard 2007-01-09 16:36:37 UTC
No message on 4.1.1 despite -pedantic -Wall -Wextra
Comment 6 Manuel López-Ibáñez 2007-01-20 16:52:27 UTC
Not sure if the summary is 100% correct but it is far better than the previous one.
Comment 7 Matt Carter 2008-06-05 23:07:11 UTC
I've run across this, too.
I agree with Ivan's 2005-06-04 suggestion.
It would be nice if the compiler would emit a warning that the derived class's constructor's call to the virtual base class's non-default constructor is being ignored and overridden by an implicit call to the virtual base class's default constructor.
Similarly, if the virtual base class fails to specify a default constructor (and specifies only a non-default one), the derived class's constructor's call to the virtual base class's non-default constructor produces only this error message:

In constructor 'top::top()':
 error: no matching function for call to 'virt::virt()'

which leaves the developer scratching his/her head if he doesn't know that the C++ spec. requires virtual base classes to have default constructors.  (True, s/he should know, but the compile error message could be more helpful.)
Something to the effect of:
"virtual base class lacks default constructor" would be much more helpful.

If this issue is different enough to warrant a separate "bug" report, let me know and I'll be happy to file it separately.
Thanks.
Comment 8 Jonathan Wakely 2010-10-28 09:17:23 UTC
I've relied on exactly this behaviour and wouldn't want a warning.

struct Base : virtual std::ios {
  Base() : std::ios(0) { }
  std::streambuf buf;
};

struct MyStream : Base, std::iostream {
  MyStream() : std::iostream(0) { }
};

If a concrete Base is constructed I want to call ios::ios(0) but if a MyStream is constructed then I want to call the ios::ios() default ctor and then have iostream::iostream(0) call ios::init(0)

If this warning is added (which I'm not convinced it should be) then it should not be given if the most-derived class *explicitly* uses a different ctor for the virtual base i.e. I could suppress the warning by changing the code above like so:

  MyStream() : std::ios(), std::iostream(0) { }
               ^^^^^^^^^^^

I also don't think the warning should be given if the unused mem-initializer in der1 and der2 calls the same constructor as is implicitly called by the most-derived class, i.e. if der1 and der2 called virt() then that has the same effect as the implicit initialization done by top.

I don't think this should be P2, and I think a better summary would be "Missing warning when virtual base is initialized with different constructor than requested by an ignored mem-initializer"