aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorFabien Chêne <fabien@gcc.gnu.org>2012-11-14 21:12:47 +0100
committerFabien Chêne <fabien@gcc.gnu.org>2012-11-14 21:12:47 +0100
commit7628dc541e7092f0d58de9a3622ce242807cb47d (patch)
treea138a764fd88db8b06626eb9bfea1e90755b2ede /gcc
parentccd025e14c48690c37d0321be833a426df31dc16 (diff)
downloadgcc-7628dc541e7092f0d58de9a3622ce242807cb47d.zip
gcc-7628dc541e7092f0d58de9a3622ce242807cb47d.tar.gz
gcc-7628dc541e7092f0d58de9a3622ce242807cb47d.tar.bz2
re PR c++/11750 (class scope using-declaration lookup not implemented)
gcc/testsuite/ChangeLog 2012-11-14 Fabien Chêne <fabien@gcc.gnu.org> PR c++/11750 * g++.dg/inherit/vitual9.C: New. gcc/cp/ChangeLog 2012-11-14 Fabien Chêne <fabien@gcc.gnu.org> PR c++/11750 * call.c (build_new_method_call_1): Check that the instance type and the function context are the same before setting the flag LOOKUP_NONVIRTUAL. From-SVN: r193504
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/call.c10
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/inherit/virtual9.C44
4 files changed, 66 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8d12568..fc5351815 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2012-11-14 Fabien Chêne <fabien@gcc.gnu.org>
+
+ PR c++/11750
+ * call.c (build_new_method_call_1): Check that the instance type
+ and the function context are the same before setting the flag
+ LOOKUP_NONVIRTUAL.
+
2012-11-13 Sriraman Tallam <tmsriram@google.com>
* class.c (mark_versions_used): Remove.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index bbeea85..77bd288 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7652,9 +7652,15 @@ build_new_method_call_1 (tree instance, tree fns, VEC(tree,gc) **args,
}
else
{
- /* Optimize away vtable lookup if we know that this function
- can't be overridden. */
+ /* Optimize away vtable lookup if we know that this
+ function can't be overridden. We need to check if
+ the context and the instance type are the same,
+ actually FN might be defined in a different class
+ type because of a using-declaration. In this case, we
+ do not want to perform a non-virtual call. */
if (DECL_VINDEX (fn) && ! (flags & LOOKUP_NONVIRTUAL)
+ && same_type_ignoring_top_level_qualifiers_p
+ (DECL_CONTEXT (fn), TREE_TYPE (instance))
&& resolves_to_fixed_type_p (instance, 0))
flags |= LOOKUP_NONVIRTUAL;
if (explicit_targs)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index fec239c..23424c5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2012-11-14 Fabien Chêne <fabien@gcc.gnu.org>
+
+ PR c++/11750
+ * call.c (build_new_method_call_1): Check that the instance type
+ and the function context are the same before setting the flag
+ LOOKUP_NONVIRTUAL.
+
2012-11-13 Sriraman Tallam <tmsriram@google.com>
* testsuite/g++.dg/mv4.C: Add require ifunc. Change error message.
diff --git a/gcc/testsuite/g++.dg/inherit/virtual9.C b/gcc/testsuite/g++.dg/inherit/virtual9.C
new file mode 100644
index 0000000..0334264
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/virtual9.C
@@ -0,0 +1,44 @@
+// { dg-do run }
+// PR c++/11750
+
+struct A
+{
+ virtual void f() const { __builtin_abort(); }
+ virtual void g() {}
+};
+
+struct B : virtual A
+{
+ virtual void f() const {}
+ virtual void g() { __builtin_abort(); }
+};
+
+struct C : B, virtual A
+{
+ using A::f;
+ using A::g;
+};
+
+int main()
+{
+ C c;
+ c.f(); // call B::f
+
+ C c2;
+ c2.C::g(); // call A::g
+
+ C* c3 = &c;
+ c3->f(); // call B::f
+
+ C& c4 = c;
+ c4.f(); // call B::f
+
+ C const* c5 = &c;
+ c5->f(); // call B::f
+
+ C** c6 = &c3;
+ (*c6)->f(); // call B::f
+
+ C const& c7 = c;
+ c7.f(); // call B::f
+}