This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Fix PR 17564: function pointer canonicalization in comparisons

GCC as an extension allows the comparison of a void pointer and a function
pointer.  However, the semantics of this are not well defined, particularly
for systems that have function pointers that need canonicalization.

I believe that the following should hold.  Conversion of a function pointer
to a void pointer and back should yield a usable function pointer.  Thus,
canonicalization can't occur when a function pointer is cast to a void

In the case of equality comparisons, if one pointer is a pointer to an
object or incomplete type, and the other a pointer to void, the former
is converted to the latter.  If we follow the same rule for the comparison
of a function pointer with a void pointer, the function pointer will
not be canonicalized for the comparison as it will be cast to a void

The behavior may not be what is expected but it's consistent with the
treatment in previous GCC versions.  On the PA, comparison of a function
pointer with a void pointer resulted in a direct comparison of the
function pointers which aren't unique.  It appears previous GCC versions
performed the cast of a function pointer to void pointer during parsing.
This no longer happens in 4.0.

The enclosed patch changes dojump.c to only perform function pointer
canonicalization when both sides of a comparison are function pointers.

The patch has been tested on hppa2.0w-hp-hpux11.11 and hppa-unknown-linux-gnu
with no regressions.  These two ports use function pointer canonicalization.

Okay for main?

Nathanael developped the change.  I did analysis and testing.

J. David Anglin                        
National Research Council of Canada              (613) 990-0752 (FAX: 952-6602)

2004-12-12  Nathanael Nerode  <>
	    John David Anglin  <>

	PR middle-end/17564
	* dojump.c (do_compare_and_jump): Only canonicalize function pointers
	in a comparison if both sides are function pointers.

Index: dojump.c
RCS file: /cvs/gcc/gcc/gcc/dojump.c,v
retrieving revision 1.33
diff -u -3 -p -r1.33 dojump.c
--- dojump.c	11 Dec 2004 01:49:05 -0000	1.33
+++ dojump.c	12 Dec 2004 18:02:43 -0000
@@ -904,24 +904,23 @@ do_compare_and_jump (tree exp, enum rtx_
 #ifdef HAVE_canonicalize_funcptr_for_compare
   /* If function pointers need to be "canonicalized" before they can
-     be reliably compared, then canonicalize them.  */
+     be reliably compared, then canonicalize them.
+     Only do this if *both* sides of the comparison are function pointers.
+     If one side isn't, we want a noncanonicalized comparison.  See PR
+     middle-end/17564. */
   if (HAVE_canonicalize_funcptr_for_compare
-          == FUNCTION_TYPE))
+          == FUNCTION_TYPE
+          == FUNCTION_TYPE)
       rtx new_op0 = gen_reg_rtx (mode);
+      rtx new_op1 = gen_reg_rtx (mode);
       emit_insn (gen_canonicalize_funcptr_for_compare (new_op0, op0));
       op0 = new_op0;
-    }
-  if (HAVE_canonicalize_funcptr_for_compare
-          == FUNCTION_TYPE))
-    {
-      rtx new_op1 = gen_reg_rtx (mode);
       emit_insn (gen_canonicalize_funcptr_for_compare (new_op1, op1));
       op1 = new_op1;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]