Commit 385bce06 by Mark Mitchell Committed by Mark Mitchell

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
parent ef8f74d6
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> 2003-09-06 Gabriel Dos Reis <gdr@integrable-solutions.net>
* cp-tree.h (add_binding): Remove declaration. * cp-tree.h (add_binding): Remove declaration.
......
...@@ -701,16 +701,25 @@ standard_conversion (tree to, tree from, tree expr) ...@@ -701,16 +701,25 @@ standard_conversion (tree to, tree from, tree expr)
} }
} }
else if (IS_AGGR_TYPE (TREE_TYPE (from)) 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),
from = cp_type_quals (TREE_TYPE (from)));
cp_build_qualified_type (TREE_TYPE (to), from = build_pointer_type (from);
cp_type_quals (TREE_TYPE (from))); conv = build_conv (PTR_CONV, from, conv);
from = build_pointer_type (from);
conv = build_conv (PTR_CONV, from, conv);
}
} }
if (tcode == POINTER_TYPE) if (tcode == POINTER_TYPE)
...@@ -5970,10 +5979,13 @@ perform_direct_initialization_if_possible (tree type, tree expr) ...@@ -5970,10 +5979,13 @@ perform_direct_initialization_if_possible (tree type, tree expr)
the overload resolution is ambiguous, the initialization is the overload resolution is ambiguous, the initialization is
ill-formed. */ ill-formed. */
if (CLASS_TYPE_P (type)) if (CLASS_TYPE_P (type))
return build_special_member_call (NULL_TREE, complete_ctor_identifier, {
build_tree_list (NULL_TREE, expr), expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
TYPE_BINFO (type), build_tree_list (NULL_TREE, expr),
LOOKUP_NORMAL); TYPE_BINFO (type),
LOOKUP_NORMAL);
return build_cplus_new (type, expr);
}
conv = implicit_conversion (type, TREE_TYPE (expr), expr, conv = implicit_conversion (type, TREE_TYPE (expr), expr,
LOOKUP_NORMAL); LOOKUP_NORMAL);
if (!conv || ICS_BAD_FLAG (conv)) if (!conv || ICS_BAD_FLAG (conv))
......
...@@ -4427,12 +4427,13 @@ build_static_cast (tree type, tree expr) ...@@ -4427,12 +4427,13 @@ build_static_cast (tree type, tree expr)
(TREE_TYPE (type)))) (TREE_TYPE (type))))
&& at_least_as_qualified_p (TREE_TYPE (type), intype)) && at_least_as_qualified_p (TREE_TYPE (type), intype))
{ {
/* At this point we have checked all of the conditions except /* There is a standard conversion from "D*" to "B*" even if "B"
that B is not a virtual base class of D. That will be is ambiguous or inaccessible. Therefore, we ask lookup_base
checked by build_base_path. */ to check these conditions. */
tree base = lookup_base (TREE_TYPE (type), intype, ba_any, NULL); 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), expr = build_base_path (MINUS_EXPR, build_address (expr),
base, /*nonnull=*/false); base, /*nonnull=*/false);
/* Convert the pointer to a reference -- but then remember that /* Convert the pointer to a reference -- but then remember that
...@@ -4491,8 +4492,8 @@ build_static_cast (tree type, tree expr) ...@@ -4491,8 +4492,8 @@ build_static_cast (tree type, tree expr)
tree base; tree base;
check_for_casting_away_constness (intype, type, "static_cast"); check_for_casting_away_constness (intype, type, "static_cast");
base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), ba_check,
ba_check | ba_quiet, NULL); NULL);
return build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false); return build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false);
} }
......
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> 2003-09-06 Nathan Sidwell <nathan@codesourcery.com>
PR c++/11794 PR c++/11794
......
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 "" }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment