From 13f9714bb6a00a628ed654f3863cb7ed7b7d9eee Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Fri, 1 Dec 2000 11:52:33 +0000 Subject: [PATCH] call.c (standard_conversion): Reject pointer to member conversions from ambiguous, inaccessible or virtual bases. cp: * call.c (standard_conversion): Reject pointer to member conversions from ambiguous, inaccessible or virtual bases. * typeck.c (build_static_cast): Don't check pointers to members specially. testsuite: * g++.old-deja/g++.other/cast6.C: New test. From-SVN: r37914 --- gcc/cp/ChangeLog | 7 +++ gcc/cp/call.c | 12 +++-- gcc/cp/typeck.c | 17 +++--- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/g++.old-deja/g++.other/cast6.C | 57 ++++++++++++++++++++ 5 files changed, 81 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.other/cast6.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8c3934fca20..8654377980d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2000-12-01 Nathan Sidwell + + * call.c (standard_conversion): Reject pointer to member + conversions from ambiguous, inaccessible or virtual bases. + * typeck.c (build_static_cast): Don't check pointers to members + specially. + 2000-11-30 Nathan Sidwell * method.c (do_build_copy_constructor): Preserve cv diff --git a/gcc/cp/call.c b/gcc/cp/call.c index ecd3d22347e..fd5f9046382 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -736,8 +736,9 @@ standard_conversion (to, from, expr) { tree fbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (from)); tree tbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (to)); + tree binfo = get_binfo (fbase, tbase, 1); - if (DERIVED_FROM_P (fbase, tbase) + if (binfo && !binfo_from_vbase (binfo) && (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (TREE_TYPE (from)), TREE_TYPE (TREE_TYPE (to))))) @@ -783,11 +784,12 @@ standard_conversion (to, from, expr) tree tofn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (to)); tree fbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fromfn))); tree tbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (tofn))); + tree binfo = get_binfo (fbase, tbase, 1); - if (! DERIVED_FROM_P (fbase, tbase) - || ! same_type_p (TREE_TYPE (fromfn), TREE_TYPE (tofn)) - || ! compparms (TREE_CHAIN (TYPE_ARG_TYPES (fromfn)), - TREE_CHAIN (TYPE_ARG_TYPES (tofn))) + if (!binfo || binfo_from_vbase (binfo) + || !same_type_p (TREE_TYPE (fromfn), TREE_TYPE (tofn)) + || !compparms (TREE_CHAIN (TYPE_ARG_TYPES (fromfn)), + TREE_CHAIN (TYPE_ARG_TYPES (tofn))) || CP_TYPE_QUALS (fbase) != CP_TYPE_QUALS (tbase)) return 0; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 39f8b54515e..6f99a5fb677 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5095,23 +5095,18 @@ build_static_cast (type, expr) ? 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. */ + tree binfo; + if (IS_AGGR_TYPE (TREE_TYPE (type)) && IS_AGGR_TYPE (TREE_TYPE (intype)) && (binfo = get_binfo (TREE_TYPE (intype), TREE_TYPE (type), 0)) - && ! TREE_VIA_VIRTUAL (binfo)) - ok = 1; - } - else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype)) - { - if (same_type_ignoring_top_level_qualifiers_p - (TREE_TYPE (TREE_TYPE (type)), - TREE_TYPE (TREE_TYPE (intype))) - && (binfo = get_binfo (TYPE_OFFSET_BASETYPE (TREE_TYPE (type)), - TYPE_OFFSET_BASETYPE (TREE_TYPE (intype)), 0)) - && ! TREE_VIA_VIRTUAL (binfo)) + && !binfo_from_vbase (binfo)) ok = 1; } else if (TREE_CODE (intype) != BOOLEAN_TYPE diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3363678eb10..aae082d791f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2000-12-01 Nathan Sidwell + + * g++.old-deja/g++.other/cast6.C: New test. + 2000-11-30 Geoffrey Keating * gcc.c-torture/execute/20001130-2.c: New testcase. diff --git a/gcc/testsuite/g++.old-deja/g++.other/cast6.C b/gcc/testsuite/g++.old-deja/g++.other/cast6.C new file mode 100644 index 00000000000..23f63e7797b --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/cast6.C @@ -0,0 +1,57 @@ +// Build don't link: + +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 28 Nov 2000 + +// We failed to reject static_cast and implicit conversions of pointers to +// member that traversed a virtual base. + +struct bar +{ + int barm; + static void a(); +}; +struct filler1 {int fm;}; +struct filler2 {int fm;}; +struct filler3 {int fm;}; +struct filler4 {int fm;}; + +struct baz : filler1, bar, filler2 +{ + int bazm; +}; + +struct foo : filler3, virtual baz, filler4 +{ + static void a(); + void b() {}; + int m; +}; + +typedef void (bar::*barfPtr)(); +typedef void (foo::*foofPtr)(); +typedef int bar::*barmPtr; +typedef int foo::*foomPtr; + +struct X; +typedef void (X::*xfPtr) (); +typedef int X::*xmPtr; + +int main () +{ + { + foofPtr fp = &foo::b; + barfPtr bp = static_cast (fp); // ERROR - invalid static_cast + foofPtr fp2 = static_cast (bp); // ERROR - invalid static_cast + foofPtr fp3 = bp; // ERROR - cannot convert + fp3 = (foofPtr)bp; // WARNING - via virtual base + + foomPtr fmp = &foo::m; + barmPtr bmp = static_cast (fmp); // ERROR - invalid static_cast + foomPtr fmp2 = static_cast (bmp); // ERROR - invalid static_cast + foomPtr fmp3 = bmp; // ERROR - cannot convert + fmp3 = (foomPtr)bmp; // WARNING - via virtual base + } + + return 0; +} -- 2.30.2