aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2008-08-05 18:22:00 -0400
committerJason Merrill <jason@gcc.gnu.org>2008-08-05 18:22:00 -0400
commit8bd206211ddadcfb501aeed34d137ffd5baee59a (patch)
tree71ca7eb04a3cd8b370ea8d9edf3dc041fb540baf /gcc
parent8a24bf0486b5a23c2772b29ee38e6a8372eaeac1 (diff)
downloadgcc-8bd206211ddadcfb501aeed34d137ffd5baee59a.zip
gcc-8bd206211ddadcfb501aeed34d137ffd5baee59a.tar.gz
gcc-8bd206211ddadcfb501aeed34d137ffd5baee59a.tar.bz2
re PR c++/37016 (member function pointer failure with optimization)
PR c++/37016 * tree-ssa.c (useless_type_conversion_p_1): Call langhook if TYPE_STRUCTURAL_EQUALITY_P is true for both types. From-SVN: r138740
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/opt/pmf1.C76
-rw-r--r--gcc/tree-ssa.c10
3 files changed, 90 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8bce42a..eb2467b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2008-08-04 Jason Merrill <jason@redhat.com>
+
+ PR c++/37016
+ * tree-ssa.c (useless_type_conversion_p_1): Call langhook
+ if TYPE_STRUCTURAL_EQUALITY_P is true for both types.
+
2008-08-05 Richard Henderson <rth@redhat.com>
* configure.ac (HAVE_GAS_CFI_DIRECTIVE): Check .cfi_personality.
diff --git a/gcc/testsuite/g++.dg/opt/pmf1.C b/gcc/testsuite/g++.dg/opt/pmf1.C
new file mode 100644
index 0000000..428e753
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pmf1.C
@@ -0,0 +1,76 @@
+// PR c++/37016
+// { dg-do run }
+// { dg-options "-O2 -Wall" }
+
+/*
+ Basic design concept is that WorldObject implements remote method call
+ functionality using the "curiously recurring template pattern" to enable
+ forwarding calls from the generic base class that implements the transport
+ layer to the derived class.
+
+ The specific failure was in forwarding calls to items in a container.
+ This is emulated here by wrapping a single item.
+
+ In the main program there are two forms of the call. In the last
+ (uncommented) form the member function pointer is for clarity
+ assigned to a variable (itemfunptr) before making the call.
+ With 4.3.0 and 4.3.1 this code compiles incorrectly with -O1 or greater
+ to produce this warning
+
+ reproduce.cc: In function ‘int main()’:
+ reproduce.cc:26: warning: ‘itemfunptr.void (Container::*)(void
+(Item::*)(int), int)::__pfn’ is used uninitialized in this function
+ reproduce.cc:47: note: ‘itemfunptr.void (Container::*)(void (Item::*)(int),
+int)::__pfn’ was declared here
+
+ and the resulting executable segvs. It works correctly with -O0.
+
+ With 4.2.3 and earlier it works correctly with optimization.
+
+ In the first (commented out) form of the call in the main program
+ we directly refer to desired member function. This compiles
+ and executes correctly with all tested versions.
+*/
+
+extern "C" int printf (const char *, ...);
+
+template <class Derived>
+struct WorldObject {
+ template <typename memfunT, typename arg1T, typename arg2T>
+ void forward(memfunT memfun, arg1T arg1, arg2T arg2) {
+ Derived* obj = static_cast<Derived*>(this);
+ (obj->*memfun)(arg1, arg2);
+ }
+};
+
+struct Item {
+ void fred(int a) {
+ printf ("a=%d\n", a);
+ }
+};
+
+struct Container : public WorldObject<Container> {
+ Item item;
+ template <typename itemfunT, typename arg1T>
+ void itemfun(itemfunT itemfun, int a) {
+ (item.*itemfun)(a);
+ }
+};
+
+int main() {
+ typedef void (Item::*itemfun)(int);
+
+ Container t;
+
+ // This call compiles and executes correctly with all versions tested
+ //t.forward(&Container::itemfun<itemfun,int>, &Item::fred, 1);
+
+ // This call compiles with a warning and segvs on execution if using
+ // -O1 or greater with 4.3.*. 4.2.* is correct.
+ void (Container::*itemfunptr)(itemfun, int) =
+&Container::itemfun<itemfun,int>;
+ t.forward(itemfunptr, &Item::fred, 1);
+
+ return 0;
+}
+
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index fbfcbf2..c308a35 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1165,12 +1165,18 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type)
if (TREE_CODE (inner_type) != TREE_CODE (outer_type))
return false;
- /* ??? Add structural equivalence check. */
+ /* ??? This seems to be necessary even for aggregates that don't
+ have TYPE_STRUCTURAL_EQUALITY_P set. */
/* ??? This should eventually just return false. */
return lang_hooks.types_compatible_p (inner_type, outer_type);
}
-
+ /* Also for functions and possibly other types with
+ TYPE_STRUCTURAL_EQUALITY_P set. */
+ else if (TYPE_STRUCTURAL_EQUALITY_P (inner_type)
+ && TYPE_STRUCTURAL_EQUALITY_P (outer_type))
+ return lang_hooks.types_compatible_p (inner_type, outer_type);
+
return false;
}