diff options
author | Mark Mitchell <mark@codesourcery.com> | 2003-09-07 04:10:10 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2003-09-07 04:10:10 +0000 |
commit | 385bce060ac82554753630f1447a85c650300d9d (patch) | |
tree | 36da4e4899471215b1c1ed86f5a20bf2d7365607 | |
parent | ef8f74d66da4c6034217dfe1147bb24e0193ef80 (diff) | |
download | gcc-385bce060ac82554753630f1447a85c650300d9d.zip gcc-385bce060ac82554753630f1447a85c650300d9d.tar.gz gcc-385bce060ac82554753630f1447a85c650300d9d.tar.bz2 |
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
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/call.c | 38 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/expr/static_cast5.C | 17 |
5 files changed, 64 insertions, 20 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 755168e..1c8fef0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2003-09-06 Mark Mitchell <mark@codesourcery.com> + + 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 <gdr@integrable-solutions.net> * cp-tree.h (add_binding): Remove declaration. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index cc03adc..bc7e3b8 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 da07fea..8b391b8 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 331c00d..d5b929a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2003-09-06 Mark Mitchell <mark@codesourcery.com> + + PR c++/11687 + * g++.dg/expr/static_cast5.C: New test. + 2003-09-06 Nathan Sidwell <nathan@codesourcery.com> 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 0000000..1a51f15 --- /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<B*> (&d); + D* db = static_cast<D*> (ap); // { dg-error "" } + + D& dr1 = static_cast<D&> (*ap); // { dg-error "" } + + A& ar = static_cast<C&> (d); + D& dr = static_cast<D&> (ar); // { dg-error "" } +} + |