From 61e71a9e5e6c268d7c9ad25c6bec24829045de63 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Mon, 17 Oct 2005 17:25:17 +0000 Subject: [PATCH] re PR c++/24386 (wrong virtual function called in template member) cp: PR c++/24386 * cp-tree.h (BASELINK_QUALIFIED_P): New. * pt.c (tsubst_copy_and_build): : Use it. * typeck.c (finish_class_member_access_expr): Set it. testsuite: PR c++/24386 * g++.dg/template/overload7.C: New. From-SVN: r105507 --- gcc/cp/ChangeLog | 5 ++++ gcc/cp/cp-tree.h | 4 +++ gcc/cp/pt.c | 14 +++++++--- gcc/cp/typeck.c | 16 +++++++++--- gcc/testsuite/ChangeLog | 3 +++ gcc/testsuite/g++.dg/template/overload7.C | 31 +++++++++++++++++++++++ 6 files changed, 66 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/overload7.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a7259695193a..08344ee960ae 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,10 @@ 2005-10-17 Nathan Sidwell + PR c++/24386 + * cp-tree.h (BASELINK_QUALIFIED_P): New. + * pt.c (tsubst_copy_and_build): : Use it. + * typeck.c (finish_class_member_access_expr): Set it. + PR c++/21353 * decl.c (check_default_argument): Don't check processing_template_decl or uses_template_parms here. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 9a2becc3c941..b63d08e5fcce 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -52,6 +52,7 @@ struct diagnostic_context; TYPENAME_IS_ENUM_P (in TYPENAME_TYPE) REFERENCE_REF_P (in INDIRECT_EXPR) QUALIFIED_NAME_IS_TEMPLATE (in SCOPE_REF) + BASELINK_QUALIFIED_P (in BASELINK) 1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE) TI_PENDING_TEMPLATE_FLAG. TEMPLATE_PARMS_FOR_INLINE. @@ -341,6 +342,9 @@ struct tree_overload GTY(()) requested. */ #define BASELINK_OPTYPE(NODE) \ (TREE_CHAIN (BASELINK_CHECK (NODE))) +/* Non-zero if this baselink was from a qualified lookup. */ +#define BASELINK_QUALIFIED_P(NODE) \ + TREE_LANG_FLAG_0 (BASELINK_CHECK (NODE)) struct tree_baselink GTY(()) { diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3de54a4e3778..d25130a078d5 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -8720,9 +8720,17 @@ tsubst_copy_and_build (tree t, } else { - qualified_p = (TREE_CODE (function) == COMPONENT_REF - && (TREE_CODE (TREE_OPERAND (function, 1)) - == SCOPE_REF)); + if (TREE_CODE (function) == COMPONENT_REF) + { + tree op = TREE_OPERAND (function, 1); + + qualified_p = (TREE_CODE (op) == SCOPE_REF + || (BASELINK_P (op) + && BASELINK_QUALIFIED_P (op))); + } + else + qualified_p = false; + function = tsubst_copy_and_build (function, args, complain, in_decl, !qualified_p); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index e3c431d96d02..a7edfc12e7f5 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2055,10 +2055,18 @@ finish_class_member_access_expr (tree object, tree name, bool template_p) expr = build_class_member_access_expr (object, member, access_path, /*preserve_reference=*/false); if (processing_template_decl && expr != error_mark_node) - return build_min_non_dep (COMPONENT_REF, expr, - orig_object, - BASELINK_P (member) ? member : orig_name, - NULL_TREE); + { + if (BASELINK_P (member)) + { + if (TREE_CODE (orig_name) == SCOPE_REF) + BASELINK_QUALIFIED_P (member) = 1; + orig_name = member; + } + return build_min_non_dep (COMPONENT_REF, expr, + orig_object, orig_name, + NULL_TREE); + } + return expr; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e17dc16bf02f..319812ac4297 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2005-10-17 Nathan Sidwell + PR c++/24386 + * g++.dg/template/overload7.C: New. + PR c++/22551 * g++.dg/other/switch2.C: Remove expected warnings. diff --git a/gcc/testsuite/g++.dg/template/overload7.C b/gcc/testsuite/g++.dg/template/overload7.C new file mode 100644 index 000000000000..28bd16c4e540 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/overload7.C @@ -0,0 +1,31 @@ +// { dg-do run } + +// Copyright (C) 2005 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 17 Oct 2005 + +// PR 24386:Wrong virtual function called +// Origin: Scott Snyder snyder@fnal.gov + +struct A +{ + virtual int Foo () { return 1; } +}; +struct B : public A +{ + virtual int Foo () { return 2; } +}; + +template +int Bar (T *a) +{ + if (static_cast(a)->A::Foo () != 1) + return 1; + if (static_cast(a)->Foo () != 2) + return 2; + return 0; +} + +int main () +{ + return Bar (new B); +}