Reading specs from /home/am/tools/gcc/usr/lib/gcc/i686-pc-linux-gnu/3.4/specs Konfiguriert mit: /home/am/tools/gcc/gcc/configure --prefix=/home/am/tools/gcc/usr --enable-languages=c,c++ --enable-threads=posix --disable-checking Thread model: posix gcc-Version 3.4 20030809 (experimental) (and all earlier versions) fails to detect this ambiguity: g++ ambig.c -----ambig.c----- void ambig() { struct A {}; struct B : A {}; struct C : A {}; struct D : B, C {}; D d; A* ap = static_cast<B*> (&d); D* db = static_cast<D*> (ap); //err expected D& dr1 = static_cast<D&> (*ap); //err expected A& ar = static_cast<C&> (d); D& dr = static_cast<D&> (ar); //err expected }
GCC 3.2.3 rejected this: pr11867.cc: In function `void ambig()': pr11867.cc:10: invalid static_cast from type `ambig()::A*' to type `ambig()::D* ' pr11867.cc:12: `ambig()::A' is an ambiguous base of `ambig()::D' pr11867.cc:15: `ambig()::A' is an ambiguous base of `ambig()::D' Where 3.3.1 (20030707) and the mainline (20030808) does not. From Phil's regression hunter: Search converges between 2003-06-25-trunk (#324) and 2003- 06-26-trunk (#325): Search converges between 2003-06-25-3.3 (#149) and 2003-06-26-3.3 (#150).
The regression in PR 11867 was introduced or exposed by this patch: --- gcc/gcc/cp/ChangeLog --- 2003-06-25 Mark Mitchell <mark@codesourcery.com> PR c++/10931 * call.c (convert_like): Pass issue_conversion_warnings. (convert_like_with_context): Likewise. (convert_like_real): Add issue_conversion_warnings parameter. (perform_direct_initialization_if_possible): New function. * cp-tree.h (perform_direct_initialization_if_possible): Declare it. * typeck.c (check_for_casting_away_constness): New function. (build_static_cast): Rewrite. The regression hunt took place on i686-pc-linux-gnu using the submitter's test case.
Fixed by (had the wrong PR number in it): 2003-09-06 Mark Mitchell PR c++/11687 * call.c (standard_conversion): Improve comments. (perform_direct_initialization): Make sure we return an expression of the correct type. * typeck.c (build_static_cast): Check for ambiguity and accessibility when performing conversions.
Thanks for fixing this. And also for adding the accessibility check. I did not report it, as I was not 100% sure about. e.g. Comeau online test pass this without error: (g++ now rejects it as I would have expected.) ------- struct A {}; struct B : private A {}; int main () { B b; A* ap = (A*) &b; B* bp = static_cast<B*> (ap); //Error } ---------
Subject: Re: [3.3/3.4 Regression] static_cast ignores ambiguity On Sun, 2003-09-07 at 03:28, alfred dot minarik dot 1 at aon dot at wrote: > PLEASE REPLY TO gcc-bugzilla@gcc.gnu.org ONLY, *NOT* gcc-bugs@gcc.gnu.org. > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11867 > > > > ------- Additional Comments From alfred dot minarik dot 1 at aon dot at 2003-09-07 10:28 ------- > Thanks for fixing this. > > And also for adding the accessibility check. > I did not report it, as I was not 100% sure about. Now that you mention that, I'd better go back and check the standard one more time on that to make sure one way or the other. Thanks,
Subject: Re: [3.3/3.4 Regression] static_cast ignores ambiguity > struct A {}; > > struct B : private A {}; > > int > main () > { > B b; > A* ap = (A*) &b; > B* bp = static_cast<B*> (ap); //Error > } This program is invalid. The reason is that the only static_cast alternative that would allow this conversion is the: An rvalue of type "pointer to cv1 B", where B is a class type, can be converted to an rvalue of type "pointer to cv2 D", where D is a class derived (clause _class.derived_) from B, if a valid standard conver- sion from "pointer to D" to "pointer to B" exists (_conv.ptr_), cv2 is the same cv-qualification as, or greater cv-qualification than, cv1, and B is not a virtual base class of D. The "valid standard conversion" clause must be read to imply that this restriction from [conv.ptr] applies to the conversion: If B is an inaccessible (clause _class.access_) or ambiguous (_class.member.lookup_) base class of D, a program that necessitates this conversion is ill-formed. Otherwise, there is nothing in the static_cast language to eliminate a conversion from an ambiguous base to a derived class. In fact, this was examined by the committee back in 1998, and is Core Issue 54: ===================== 54. Static_cast from private base to derived class Section: 5.2.9 expr.static.cast Status: NAD Submitter: Steve Adamczyk Date: 13 Oct 1998 Is it okay to use a static_cast to cast from a private base class to a derived class? That depends on what the words "valid standard conversion" in paragraph 8 mean — do they mean the conversion exists, or that it would not get an error if it were done? I think the former was intended — and therefore a static_cast from a private base to a derived class would be allowed. Rationale (04/99): A static_cast from a private base to a derived class is not allowed outside a member from the derived class, because 4.10 conv.ptr paragraph 3 implies that the conversion is not valid. (Classic style casts work.) =====================