From: Mark Mitchell Date: Sun, 7 Sep 2003 04:10:10 +0000 (+0000) Subject: re PR c++/11867 (static_cast ignores ambiguity) X-Git-Tag: releases/gcc-3.4.0~3852 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=385bce060ac82554753630f1447a85c650300d9d;p=thirdparty%2Fgcc.git re PR c++/11867 (static_cast ignores ambiguity) 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. PR c++/11687 * g++.dg/expr/static_cast5.C: New test. From-SVN: r71157 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 755168e59b23..1c8fef025733 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +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. + 2003-09-06 Gabriel Dos Reis * cp-tree.h (add_binding): Remove declaration. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index cc03adc6f570..bc7e3b8ab5bd 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -701,16 +701,25 @@ standard_conversion (tree to, tree from, tree expr) } } else if (IS_AGGR_TYPE (TREE_TYPE (from)) - && IS_AGGR_TYPE (TREE_TYPE (to))) + && IS_AGGR_TYPE (TREE_TYPE (to)) + /* [conv.ptr] + + An rvalue of type "pointer to cv D," where D is a + class type, can be converted to an rvalue of type + "pointer to cv B," where B is a base class (clause + _class.derived_) of D. 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. */ + /* Therefore, we use DERIVED_FROM_P, and not + ACESSIBLY_UNIQUELY_DERIVED_FROM_P, in this test. */ + && DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from))) { - if (DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from))) - { - from = - cp_build_qualified_type (TREE_TYPE (to), - cp_type_quals (TREE_TYPE (from))); - from = build_pointer_type (from); - conv = build_conv (PTR_CONV, from, conv); - } + from = + cp_build_qualified_type (TREE_TYPE (to), + cp_type_quals (TREE_TYPE (from))); + from = build_pointer_type (from); + conv = build_conv (PTR_CONV, from, conv); } if (tcode == POINTER_TYPE) @@ -5970,10 +5979,13 @@ perform_direct_initialization_if_possible (tree type, tree expr) the overload resolution is ambiguous, the initialization is ill-formed. */ if (CLASS_TYPE_P (type)) - return build_special_member_call (NULL_TREE, complete_ctor_identifier, - build_tree_list (NULL_TREE, expr), - TYPE_BINFO (type), - LOOKUP_NORMAL); + { + expr = build_special_member_call (NULL_TREE, complete_ctor_identifier, + build_tree_list (NULL_TREE, expr), + TYPE_BINFO (type), + LOOKUP_NORMAL); + return build_cplus_new (type, expr); + } conv = implicit_conversion (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL); if (!conv || ICS_BAD_FLAG (conv)) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index da07fea0c5fe..8b391b8448d8 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -4427,12 +4427,13 @@ build_static_cast (tree type, tree expr) (TREE_TYPE (type)))) && at_least_as_qualified_p (TREE_TYPE (type), intype)) { - /* At this point we have checked all of the conditions except - that B is not a virtual base class of D. That will be - checked by build_base_path. */ - tree base = lookup_base (TREE_TYPE (type), intype, ba_any, NULL); + /* There is a standard conversion from "D*" to "B*" even if "B" + is ambiguous or inaccessible. Therefore, we ask lookup_base + to check these conditions. */ + tree base = lookup_base (TREE_TYPE (type), intype, ba_check, NULL); - /* Convert from B* to D*. */ + /* Convert from "B*" to "D*". This function will check that "B" + is not a virtual base of "D". */ expr = build_base_path (MINUS_EXPR, build_address (expr), base, /*nonnull=*/false); /* Convert the pointer to a reference -- but then remember that @@ -4491,8 +4492,8 @@ build_static_cast (tree type, tree expr) tree base; check_for_casting_away_constness (intype, type, "static_cast"); - base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), - ba_check | ba_quiet, NULL); + base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), ba_check, + NULL); return build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 331c00d8cbcb..d5b929a674db 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2003-09-06 Mark Mitchell + + PR c++/11687 + * g++.dg/expr/static_cast5.C: New test. + 2003-09-06 Nathan Sidwell PR c++/11794 diff --git a/gcc/testsuite/g++.dg/expr/static_cast5.C b/gcc/testsuite/g++.dg/expr/static_cast5.C new file mode 100644 index 000000000000..1a51f1516772 --- /dev/null +++ b/gcc/testsuite/g++.dg/expr/static_cast5.C @@ -0,0 +1,17 @@ +void ambig() +{ + struct A {}; + struct B : A {}; + struct C : A {}; + struct D : B, C {}; + + D d; + A* ap = static_cast (&d); + D* db = static_cast (ap); // { dg-error "" } + + D& dr1 = static_cast (*ap); // { dg-error "" } + + A& ar = static_cast (d); + D& dr = static_cast (ar); // { dg-error "" } +} +