This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 10990 and 10931
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 25 Jun 2003 17:11:41 -0700
- Subject: C++ PATCH: PR 10990 and 10931
- Reply-to: mark at codesourcery dot com
This patch fixes two regressions: one in static_cast and one with
dynamic_cast. Both are solved by implementing functions that
dogmatically adhere to the standard -- and in the process several
other bugs are fixed. For example, static_cast no longer permits
casts to inaccessible base classes.
Tested on i686-pc-linux-gnu, applied on the mainline. I'll apply the
same patch to the branch as soon as I can test it there.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2003-06-25 Mark Mitchell <mark@codesourcery.com>
PR c++/10990
* search.c (lookup_base_r): Rely on accessible_p, rather than
trying to emulate that logic here.
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.
2003-06-25 Mark Mitchell <mark@codesourcery.com>
PR c++/10990
* g++.dg/rtti/dyncast1.C: New test.
* g++.dg/abi/mangle4.C: Correct base-specifier access.
* g++.dg/lookup/scoped1.C: Remove XFAIL.
* g++.old-deja/g++.martin/pmf1.C: Correct base-specifier access.
PR c++/10931
* g++.dg/expr/static_cast1.C: New test.
Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.388
diff -c -5 -p -r1.388 call.c
*** cp/call.c 20 Jun 2003 00:48:36 -0000 1.388
--- cp/call.c 26 Jun 2003 00:03:19 -0000
*************** static struct z_candidate * tourney (str
*** 43,57 ****
static int equal_functions (tree, tree);
static int joust (struct z_candidate *, struct z_candidate *, bool);
static int compare_ics (tree, tree);
static tree build_over_call (struct z_candidate *, int);
static tree build_java_interface_fn_ref (tree, tree);
! #define convert_like(CONV, EXPR) \
! convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0)
! #define convert_like_with_context(CONV, EXPR, FN, ARGNO) \
! convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0)
! static tree convert_like_real (tree, tree, tree, int, int);
static void op_error (enum tree_code, enum tree_code, tree, tree,
tree, const char *);
static tree build_object_call (tree, tree);
static tree resolve_args (tree);
static struct z_candidate *build_user_type_conversion_1 (tree, tree, int);
--- 43,59 ----
static int equal_functions (tree, tree);
static int joust (struct z_candidate *, struct z_candidate *, bool);
static int compare_ics (tree, tree);
static tree build_over_call (struct z_candidate *, int);
static tree build_java_interface_fn_ref (tree, tree);
! #define convert_like(CONV, EXPR) \
! convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0, \
! /*issue_conversion_warnings=*/true)
! #define convert_like_with_context(CONV, EXPR, FN, ARGNO) \
! convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0, \
! /*issue_conversion_warnings=*/true)
! static tree convert_like_real (tree, tree, tree, int, int, bool);
static void op_error (enum tree_code, enum tree_code, tree, tree,
tree, const char *);
static tree build_object_call (tree, tree);
static tree resolve_args (tree);
static struct z_candidate *build_user_type_conversion_1 (tree, tree, int);
*************** enforce_access (tree basetype_path, tree
*** 4107,4124 ****
}
return true;
}
! /* Perform the conversions in CONVS on the expression EXPR.
! FN and ARGNUM are used for diagnostics. ARGNUM is zero based, -1
indicates the `this' argument of a method. INNER is nonzero when
being called to continue a conversion chain. It is negative when a
! reference binding will be applied, positive otherwise. */
static tree
! convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner)
{
int savew, savee;
tree totype = TREE_TYPE (convs);
--- 4109,4129 ----
}
return true;
}
! /* Perform the conversions in CONVS on the expression EXPR. FN and
! ARGNUM are used for diagnostics. ARGNUM is zero based, -1
indicates the `this' argument of a method. INNER is nonzero when
being called to continue a conversion chain. It is negative when a
! reference binding will be applied, positive otherwise. If
! ISSUE_CONVERSION_WARNINGS is true, warnings about suspicious
! conversions will be emitted if appropriate. */
static tree
! convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner,
! bool issue_conversion_warnings)
{
int savew, savee;
tree totype = TREE_TYPE (convs);
*************** convert_like_real (tree convs, tree expr
*** 4130,4154 ****
tree t = convs;
for (; t; t = TREE_OPERAND (t, 0))
{
if (TREE_CODE (t) == USER_CONV || !ICS_BAD_FLAG (t))
{
! expr = convert_like_real (t, expr, fn, argnum, 1);
break;
}
else if (TREE_CODE (t) == AMBIG_CONV)
! return convert_like_real (t, expr, fn, argnum, 1);
else if (TREE_CODE (t) == IDENTITY_CONV)
break;
}
pedwarn ("invalid conversion from `%T' to `%T'", TREE_TYPE (expr), totype);
if (fn)
pedwarn (" initializing argument %P of `%D'", argnum, fn);
return cp_convert (totype, expr);
}
! if (!inner)
expr = dubious_conversion_warnings
(totype, expr, "argument", fn, argnum);
switch (TREE_CODE (convs))
{
case USER_CONV:
--- 4135,4161 ----
tree t = convs;
for (; t; t = TREE_OPERAND (t, 0))
{
if (TREE_CODE (t) == USER_CONV || !ICS_BAD_FLAG (t))
{
! expr = convert_like_real (t, expr, fn, argnum, 1,
! /*issue_conversion_warnings=*/false);
break;
}
else if (TREE_CODE (t) == AMBIG_CONV)
! return convert_like_real (t, expr, fn, argnum, 1,
! /*issue_conversion_warnings=*/false);
else if (TREE_CODE (t) == IDENTITY_CONV)
break;
}
pedwarn ("invalid conversion from `%T' to `%T'", TREE_TYPE (expr), totype);
if (fn)
pedwarn (" initializing argument %P of `%D'", argnum, fn);
return cp_convert (totype, expr);
}
! if (issue_conversion_warnings)
expr = dubious_conversion_warnings
(totype, expr, "argument", fn, argnum);
switch (TREE_CODE (convs))
{
case USER_CONV:
*************** convert_like_real (tree convs, tree expr
*** 4242,4252 ****
default:
break;
};
expr = convert_like_real (TREE_OPERAND (convs, 0), expr, fn, argnum,
! TREE_CODE (convs) == REF_BIND ? -1 : 1);
if (expr == error_mark_node)
return error_mark_node;
switch (TREE_CODE (convs))
{
--- 4249,4260 ----
default:
break;
};
expr = convert_like_real (TREE_OPERAND (convs, 0), expr, fn, argnum,
! TREE_CODE (convs) == REF_BIND ? -1 : 1,
! /*issue_conversion_warnings=*/false);
if (expr == error_mark_node)
return error_mark_node;
switch (TREE_CODE (convs))
{
*************** perform_implicit_conversion (tree type,
*** 6048,6057 ****
--- 6056,6084 ----
error ("could not convert `%E' to `%T'", expr, type);
return error_mark_node;
}
return convert_like (conv, expr);
+ }
+
+ /* Convert EXPR to TYPE (as a direct-initialization) if that is
+ permitted. If the conversion is valid, the converted expression is
+ returned. Otherwise, NULL_TREE is returned. */
+
+ tree
+ perform_direct_initialization_if_possible (tree type, tree expr)
+ {
+ tree conv;
+
+ if (type == error_mark_node || error_operand_p (expr))
+ return error_mark_node;
+ conv = implicit_conversion (type, TREE_TYPE (expr), expr,
+ LOOKUP_NORMAL);
+ if (!conv || ICS_BAD_FLAG (conv))
+ return NULL_TREE;
+ return convert_like_real (conv, expr, NULL_TREE, 0, 0,
+ /*issue_conversion_warnings=*/false);
}
/* DECL is a VAR_DECL whose type is a REFERENCE_TYPE. The reference
is being bound to a temporary. Create and return a new VAR_DECL
with the indicated TYPE; this variable will store the value to
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.858
diff -c -5 -p -r1.858 cp-tree.h
*** cp/cp-tree.h 20 Jun 2003 02:40:33 -0000 1.858
--- cp/cp-tree.h 26 Jun 2003 00:03:19 -0000
*************** extern tree cp_convert_parm_for_inlining
*** 3519,3528 ****
--- 3519,3529 ----
extern bool is_properly_derived_from (tree, tree);
extern tree initialize_reference (tree, tree, tree);
extern tree make_temporary_var_for_ref_to_temp (tree, tree);
extern tree strip_top_quals (tree);
extern tree perform_implicit_conversion (tree, tree);
+ extern tree perform_direct_initialization_if_possible (tree, tree);
extern tree in_charge_arg_for_name (tree);
extern tree build_cxx_call (tree, tree, tree);
/* in class.c */
extern tree build_base_path (enum tree_code, tree, tree, int);
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v
retrieving revision 1.265
diff -c -5 -p -r1.265 search.c
*** cp/search.c 17 Jun 2003 16:58:17 -0000 1.265
--- cp/search.c 26 Jun 2003 00:03:19 -0000
*************** lookup_base_r (tree binfo, tree base, ba
*** 186,197 ****
/* We have found a base. Check against what we have found
already. */
found = bk_same_type;
if (is_virtual)
found = bk_via_virtual;
- if (is_non_public)
- found = bk_inaccessible;
if (!*binfo_ptr)
*binfo_ptr = binfo;
else if (binfo != *binfo_ptr)
{
--- 186,195 ----
*************** lookup_base (tree t, tree base, base_acc
*** 315,348 ****
base = complete_type (TYPE_MAIN_VARIANT (base));
bk = lookup_base_r (t_binfo, base, access & ~ba_quiet,
0, 0, 0, &binfo);
! switch (bk)
! {
! case bk_inaccessible:
! binfo = NULL_TREE;
! if (!(access & ba_quiet))
! {
! error ("`%T' is an inaccessible base of `%T'", base, t);
! binfo = error_mark_node;
! }
! break;
! case bk_ambig:
! if (access != ba_any)
! {
! binfo = NULL_TREE;
! if (!(access & ba_quiet))
! {
! error ("`%T' is an ambiguous base of `%T'", base, t);
! binfo = error_mark_node;
! }
! }
! break;
! default:;
! }
!
if (kind_ptr)
*kind_ptr = bk;
return binfo;
}
--- 313,378 ----
base = complete_type (TYPE_MAIN_VARIANT (base));
bk = lookup_base_r (t_binfo, base, access & ~ba_quiet,
0, 0, 0, &binfo);
! /* Check that the base is unambiguous and accessible. */
! if (access != ba_any)
! switch (bk)
! {
! case bk_not_base:
! break;
!
! case bk_ambig:
! binfo = NULL_TREE;
! if (!(access & ba_quiet))
! {
! error ("`%T' is an ambiguous base of `%T'", base, t);
! binfo = error_mark_node;
! }
! break;
!
! default:
! if (access != ba_ignore
! /* If BASE is incomplete, then BASE and TYPE are probably
! the same, in which case BASE is accessible. If they
! are not the same, then TYPE is invalid. In that case,
! there's no need to issue another error here, and
! there's no implicit typedef to use in the code that
! follows, so we skip the check. */
! && COMPLETE_TYPE_P (base))
! {
! tree decl;
!
! /* [class.access.base]
!
! A base class is said to be accessible if an invented public
! member of the base class is accessible. */
! /* Rather than inventing a public member, we use the implicit
! public typedef created in the scope of every class. */
! decl = TYPE_FIELDS (base);
! while (TREE_CODE (decl) != TYPE_DECL
! || !DECL_ARTIFICIAL (decl)
! || DECL_NAME (decl) != constructor_name (base))
! decl = TREE_CHAIN (decl);
! while (ANON_AGGR_TYPE_P (t))
! t = TYPE_CONTEXT (t);
! if (!accessible_p (t, decl))
! {
! if (!(access & ba_quiet))
! {
! error ("`%T' is an inaccessible base of `%T'", base, t);
! binfo = error_mark_node;
! }
! else
! binfo = NULL_TREE;
! bk = bk_inaccessible;
! }
! }
! break;
! }
!
if (kind_ptr)
*kind_ptr = bk;
return binfo;
}
*************** dfs_accessible_p (tree binfo, void *data
*** 786,796 ****
return NULL_TREE;
}
/* Returns nonzero if it is OK to access DECL through an object
! indiated by BINFO in the context of DERIVED. */
static int
protected_accessible_p (tree decl, tree derived, tree binfo)
{
access_kind access;
--- 816,826 ----
return NULL_TREE;
}
/* Returns nonzero if it is OK to access DECL through an object
! indicated by BINFO in the context of DERIVED. */
static int
protected_accessible_p (tree decl, tree derived, tree binfo)
{
access_kind access;
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.466
diff -c -5 -p -r1.466 typeck.c
*** cp/typeck.c 18 Jun 2003 19:17:04 -0000 1.466
--- cp/typeck.c 26 Jun 2003 00:03:19 -0000
*************** build_compound_expr (tree list)
*** 4762,4776 ****
return rest;
return build (COMPOUND_EXPR, TREE_TYPE (rest), first, rest);
}
tree
build_static_cast (tree type, tree expr)
{
tree intype;
! int ok;
if (type == error_mark_node || expr == error_mark_node)
return error_mark_node;
if (TREE_CODE (expr) == OFFSET_REF)
--- 4762,4789 ----
return rest;
return build (COMPOUND_EXPR, TREE_TYPE (rest), first, rest);
}
+ /* Issue an error message if casting from SRC_TYPE to DEST_TYPE casts
+ away constness. */
+
+ static void
+ check_for_casting_away_constness (tree src_type, tree dest_type)
+ {
+ if (casts_away_constness (src_type, dest_type))
+ error ("static_cast from type `%T' to type `%T' casts away constness",
+ src_type, dest_type);
+ }
+
+ /* Return an expression representing static_cast<TYPE>(EXPR). */
+
tree
build_static_cast (tree type, tree expr)
{
tree intype;
! tree result;
if (type == error_mark_node || expr == error_mark_node)
return error_mark_node;
if (TREE_CODE (expr) == OFFSET_REF)
*************** build_static_cast (tree type, tree expr)
*** 4787,4878 ****
if (TREE_CODE (type) != REFERENCE_TYPE
&& TREE_CODE (expr) == NOP_EXPR
&& TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0)))
expr = TREE_OPERAND (expr, 0);
if (TREE_CODE (type) == VOID_TYPE)
{
! expr = convert_to_void (expr, /*implicit=*/NULL);
! return expr;
}
! if (TREE_CODE (type) == REFERENCE_TYPE)
! return (convert_from_reference
! (convert_to_reference (type, expr, CONV_STATIC|CONV_IMPLICIT,
! LOOKUP_COMPLAIN, NULL_TREE)));
!
! if (IS_AGGR_TYPE (type))
! return build_cplus_new (type, (build_special_member_call
! (NULL_TREE, complete_ctor_identifier,
! build_tree_list (NULL_TREE, expr),
! TYPE_BINFO (type), LOOKUP_NORMAL)));
!
! intype = TREE_TYPE (expr);
!
! /* FIXME handle casting to array type. */
! ok = 0;
! if (IS_AGGR_TYPE (intype)
! ? can_convert_arg (type, intype, expr)
! : can_convert_arg (strip_all_pointer_quals (type),
! strip_all_pointer_quals (intype), expr))
! /* This is a standard conversion. */
! ok = 1;
! else if (TYPE_PTROB_P (type) && TYPE_PTROB_P (intype))
{
! /* They're pointers to objects. They must be aggregates that
! are related non-virtually. */
! base_kind kind;
!
! if (IS_AGGR_TYPE (TREE_TYPE (type)) && IS_AGGR_TYPE (TREE_TYPE (intype))
! && lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
! ba_ignore | ba_quiet, &kind)
! && kind != bk_via_virtual)
! ok = 1;
}
! else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
{
! /* They're pointers to members. The pointed to objects must be
! the same (ignoring CV qualifiers), and the containing classes
! must be related non-virtually. */
! base_kind kind;
!
! if (same_type_p
! (strip_all_pointer_quals (TREE_TYPE (TREE_TYPE (type))),
! strip_all_pointer_quals (TREE_TYPE (TREE_TYPE (intype))))
! && (lookup_base (TYPE_OFFSET_BASETYPE (TREE_TYPE (intype)),
! TYPE_OFFSET_BASETYPE (TREE_TYPE (type)),
! ba_ignore | ba_quiet, &kind))
! && kind != bk_via_virtual)
! ok = 1;
}
! else if (TREE_CODE (intype) != BOOLEAN_TYPE
! && TREE_CODE (type) != ARRAY_TYPE
! && TREE_CODE (type) != FUNCTION_TYPE
! && can_convert (intype, strip_all_pointer_quals (type)))
! ok = 1;
! else if (TREE_CODE (intype) == ENUMERAL_TYPE
! && TREE_CODE (type) == ENUMERAL_TYPE)
! /* DR 128: "A value of integral _or enumeration_ type can be explicitly
! converted to an enumeration type."
! The integral to enumeration will be accepted by the previous clause.
! We need to explicitly check for enumeration to enumeration. */
! ok = 1;
!
/* [expr.static.cast]
! The static_cast operator shall not be used to cast away
! constness. */
! if (ok && casts_away_constness (intype, type))
{
! error ("static_cast from type `%T' to type `%T' casts away constness",
! intype, type);
! return error_mark_node;
}
-
- if (ok)
- return build_c_cast (type, expr);
error ("invalid static_cast from type `%T' to type `%T'", intype, type);
return error_mark_node;
}
--- 4800,4952 ----
if (TREE_CODE (type) != REFERENCE_TYPE
&& TREE_CODE (expr) == NOP_EXPR
&& TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0)))
expr = TREE_OPERAND (expr, 0);
+ intype = TREE_TYPE (expr);
+
+ /* [expr.static.cast]
+
+ An expression e can be explicitly converted to a type T using a
+ static_cast of the form static_cast<T>(e) if the declaration T
+ t(e);" is well-formed, for some invented temporary variable
+ t. */
+ result = perform_direct_initialization_if_possible (type, expr);
+ if (result)
+ return result;
+
+ /* [expr.static.cast]
+
+ Any expression can be explicitly converted to type cv void. */
if (TREE_CODE (type) == VOID_TYPE)
+ return convert_to_void (expr, /*implicit=*/NULL);
+
+ /* [expr.static.cast]
+
+ An lvalue of type "cv1 B", where B is a class type, can be cast
+ to type "reference to cv2 D", where D is a class derived (clause
+ _class.derived_) from B, if a valid standard conversion 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. */
+ if (TREE_CODE (type) == REFERENCE_TYPE
+ && CLASS_TYPE_P (TREE_TYPE (type))
+ && CLASS_TYPE_P (intype)
+ && real_non_cast_lvalue_p (expr)
+ && DERIVED_FROM_P (intype, TREE_TYPE (type))
+ && can_convert (build_pointer_type (TYPE_MAIN_VARIANT (intype)),
+ build_pointer_type (TYPE_MAIN_VARIANT
+ (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);
!
! /* Convert from B* to D*. */
! expr = build_base_path (MINUS_EXPR, build_address (expr),
! base, /*nonnull=*/false);
! /* Convert the pointer to a reference. */
! return build_nop (type, expr);
}
! /* [expr.static.cast]
! The inverse of any standard conversion sequence (clause _conv_),
! other than the lvalue-to-rvalue (_conv.lval_), array-to-pointer
! (_conv.array_), function-to-pointer (_conv.func_), and boolean
! (_conv.bool_) conversions, can be performed explicitly using
! static_cast subject to the restriction that the explicit
! conversion does not cast away constness (_expr.const.cast_), and
! the following additional rules for specific cases: */
! /* For reference, the conversions not excluded are: integral
! promotions, floating point promotion, integral conversions,
! floating point conversions, floating-integral conversions,
! pointer conversions, and pointer to member conversions. */
! if ((ARITHMETIC_TYPE_P (type) && ARITHMETIC_TYPE_P (intype))
! /* DR 128
!
! A value of integral _or enumeration_ type can be explicitly
! converted to an enumeration type. */
! || (INTEGRAL_OR_ENUMERATION_TYPE_P (type)
! && INTEGRAL_OR_ENUMERATION_TYPE_P (intype)))
! /* Really, build_c_cast should defer to this function rather
! than the other way around. */
! return build_c_cast (type, expr);
! if (TYPE_PTR_P (type) && TYPE_PTR_P (intype)
! && CLASS_TYPE_P (TREE_TYPE (type))
! && CLASS_TYPE_P (TREE_TYPE (intype))
! && can_convert (build_pointer_type (TYPE_MAIN_VARIANT
! (TREE_TYPE (intype))),
! build_pointer_type (TYPE_MAIN_VARIANT
! (TREE_TYPE (type)))))
{
! tree base;
!
! check_for_casting_away_constness (intype, type);
! base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
! ba_check | ba_quiet, NULL);
! return build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false);
}
! if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
! || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
{
! tree c1;
! tree c2;
! tree t1;
! tree t2;
!
! c1 = TYPE_PTRMEM_CLASS_TYPE (intype);
! c2 = TYPE_PTRMEM_CLASS_TYPE (type);
!
! if (TYPE_PTRMEM_P (type))
! {
! t1 = (build_ptrmem_type
! (c1,
! TYPE_MAIN_VARIANT (TYPE_PTRMEM_POINTED_TO_TYPE (intype))));
! t2 = (build_ptrmem_type
! (c2,
! TYPE_MAIN_VARIANT (TYPE_PTRMEM_POINTED_TO_TYPE (type))));
! }
! else
! {
! t1 = intype;
! t2 = type;
! }
! if (can_convert (t1, t2))
! {
! check_for_casting_away_constness (intype, type);
! if (TYPE_PTRMEM_P (type))
! {
! if (TREE_CODE (expr) == PTRMEM_CST)
! expr = cplus_expand_constant (expr);
! expr = cp_build_binary_op (PLUS_EXPR,
! cp_convert (ptrdiff_type_node, expr),
! get_delta_difference (c1, c2,
! /*force=*/1));
! return build_nop (type, expr);
! }
! else
! return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr,
! /*force=*/1);
! }
}
!
/* [expr.static.cast]
! An rvalue of type "pointer to cv void" can be explicitly
! converted to a pointer to object type. A value of type pointer
! to object converted to "pointer to cv void" and back to the
! original pointer type will have its original value. */
! if (TREE_CODE (intype) == POINTER_TYPE
! && VOID_TYPE_P (TREE_TYPE (intype))
! && TYPE_PTROB_P (type))
{
! check_for_casting_away_constness (intype, type);
! return build_nop (type, expr);
}
error ("invalid static_cast from type `%T' to type `%T'", intype, type);
return error_mark_node;
}
Index: testsuite/g++.dg/abi/mangle4.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/abi/mangle4.C,v
retrieving revision 1.1
diff -c -5 -p -r1.1 mangle4.C
*** testsuite/g++.dg/abi/mangle4.C 18 Nov 2001 06:24:45 -0000 1.1
--- testsuite/g++.dg/abi/mangle4.C 26 Jun 2003 00:03:19 -0000
***************
*** 1,10 ****
// Test mangling of type casts
// { dg-do compile }
class A {};
! class B : A {};
template<const A* a> class C {};
template<const B* b> class D {};
template<B* b> class E {};
--- 1,10 ----
// Test mangling of type casts
// { dg-do compile }
class A {};
! class B : public A {};
template<const A* a> class C {};
template<const B* b> class D {};
template<B* b> class E {};
Index: testsuite/g++.dg/expr/static_cast1.C
===================================================================
RCS file: testsuite/g++.dg/expr/static_cast1.C
diff -N testsuite/g++.dg/expr/static_cast1.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/expr/static_cast1.C 26 Jun 2003 00:03:19 -0000
***************
*** 0 ****
--- 1,5 ----
+ void foo(int x)
+ {
+ static_cast<const unsigned int&>(x);
+ }
+
Index: testsuite/g++.dg/lookup/scoped1.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/lookup/scoped1.C,v
retrieving revision 1.2
diff -c -5 -p -r1.2 scoped1.C
*** testsuite/g++.dg/lookup/scoped1.C 28 Dec 2002 07:48:06 -0000 1.2
--- testsuite/g++.dg/lookup/scoped1.C 26 Jun 2003 00:03:19 -0000
*************** struct C: public B
*** 15,22 ****
void g ()
{
::A::i1 = 1;
::A::i2 = 1; // { dg-error "(access)|(context)" "" }
::A::f1 ();
! ::A::f2 (); // { dg-error "access" "" { xfail *-*-* } }
}
};
--- 15,22 ----
void g ()
{
::A::i1 = 1;
::A::i2 = 1; // { dg-error "(access)|(context)" "" }
::A::f1 ();
! ::A::f2 (); // { dg-error "" }
}
};
Index: testsuite/g++.dg/rtti/dyncast1.C
===================================================================
RCS file: testsuite/g++.dg/rtti/dyncast1.C
diff -N testsuite/g++.dg/rtti/dyncast1.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/rtti/dyncast1.C 26 Jun 2003 00:03:19 -0000
***************
*** 0 ****
--- 1,23 ----
+ class JunkBase
+ {
+ public:
+ virtual void DoSomething( void ) = 0;
+ protected:
+ virtual ~JunkBase( void ) {};
+ JunkBase( void ) {}
+ };
+
+ class Junk : protected JunkBase
+ {
+ public:
+ Junk( void ) : JunkBase() {}
+ virtual ~Junk( void ) {}
+ protected:
+ inline JunkBase * AsBase( void )
+ { return dynamic_cast< JunkBase * >( this ); }
+ virtual void DoSomething( void ) { }
+ };
+
+
+
+
Index: testsuite/g++.old-deja/g++.martin/pmf1.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.martin/pmf1.C,v
retrieving revision 1.2
diff -c -5 -p -r1.2 pmf1.C
*** testsuite/g++.old-deja/g++.martin/pmf1.C 1 May 2003 02:02:44 -0000 1.2
--- testsuite/g++.old-deja/g++.martin/pmf1.C 26 Jun 2003 00:03:19 -0000
***************
*** 3,13 ****
// Check for pointer-to-virtual-function calls on
// bases without virtual functions.
struct B{};
! struct D:B{
virtual void foo();
};
void D::foo(){}
--- 3,13 ----
// Check for pointer-to-virtual-function calls on
// bases without virtual functions.
struct B{};
! struct D: public B{
virtual void foo();
};
void D::foo(){}