aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2003-09-07 04:10:10 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2003-09-07 04:10:10 +0000
commit385bce060ac82554753630f1447a85c650300d9d (patch)
tree36da4e4899471215b1c1ed86f5a20bf2d7365607 /gcc
parentef8f74d66da4c6034217dfe1147bb24e0193ef80 (diff)
downloadgcc-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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/call.c38
-rw-r--r--gcc/cp/typeck.c15
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/expr/static_cast5.C17
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 "" }
+}
+