This is the mail archive of the gcc-patches@gcc.gnu.org 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]

Re: Patch for PR c/11234


On Thu, 8 Jan 2004, Zack Weinberg wrote:

> You could make it a struct if the host compiler doesn't support
> designated initializers, and a union if it does - just an #ifdef in
> recog.h and some tweaks to the generated code; users wouldn't even
> notice.  The table in insn-output.o would be bigger in stage1 but
> that's harmless.

How about this patch?  Bootstrapped with no regressions on 
i686-pc-linux-gnu.  Note: the !HAVE_DESIGNATED_INITIALIZERS case is 
untested although the generated insn-output.c looks OK to me.

2004-01-09  Joseph S. Myers  <jsm@polyomino.org.uk>

	PR c/11234
	* c-typeck.c (build_c_cast): If pedantic, warn for conversions
	between function and object pointers.
	(digest_init): When comparing a pointer to function type to the
	target type, only apply TREE_TYPE once to the pointer to function
	type.
	* except.c (for_each_eh_label_1): Treat data as a pointer to a
	function pointer rather than casting it to a function pointer.
	(for_each_eh_label): Update caller.
	* recog.h (struct insn_data): Use a struct or union for output.
	* genoutput.c (output_insn_data): Update.
	* final.c (get_insn_template): Update.

testsuite:
2004-01-09  Joseph S. Myers  <jsm@polyomino.org.uk>

	PR c/11234
	* gcc.dg/func-ptr-conv-1.c: New test.
	* gcc.dg/weak/weak-6.c, gcc.dg/weak/weak-7.c: Update.

--- GCC/gcc/c-typeck.c.orig	2004-01-07 22:20:16.000000000 +0000
+++ GCC/gcc/c-typeck.c	2004-01-07 23:16:00.000000000 +0000
@@ -3125,6 +3125,25 @@ build_c_cast (tree type, tree expr)
 	    warning ("dereferencing type-punned pointer will break strict-aliasing rules");
 	}
 
+      /* If pedantic, warn for conversions between function and object
+	 pointer types, except for converting a null pointer constant
+	 to function pointer type.  */
+      if (pedantic
+	  && TREE_CODE (type) == POINTER_TYPE
+	  && TREE_CODE (otype) == POINTER_TYPE
+	  && TREE_CODE (TREE_TYPE (otype)) == FUNCTION_TYPE
+	  && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
+	pedwarn ("ISO C forbids conversion of function pointer to object pointer type");
+
+      if (pedantic
+	  && TREE_CODE (type) == POINTER_TYPE
+	  && TREE_CODE (otype) == POINTER_TYPE
+	  && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
+	  && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
+	  && !(integer_zerop (value) && TREE_TYPE (otype) == void_type_node
+	       && TREE_CODE (expr) != NOP_EXPR))
+	pedwarn ("ISO C forbids conversion of object pointer to function pointer type");
+
       ovalue = value;
       /* Replace a nonvolatile const static variable with its value.  */
       if (optimize && TREE_CODE (value) == VAR_DECL)
@@ -4088,9 +4107,12 @@ digest_init (tree type, tree init, int r
 	  || (code == VECTOR_TYPE
 	      && comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT))
 	  || (code == POINTER_TYPE
-	      && (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
-		  || TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE)
+	      && TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
 	      && comptypes (TREE_TYPE (TREE_TYPE (inside_init)),
+			    TREE_TYPE (type), COMPARE_STRICT))
+	  || (code == POINTER_TYPE
+	      && TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE
+	      && comptypes (TREE_TYPE (inside_init),
 			    TREE_TYPE (type), COMPARE_STRICT))))
     {
       if (code == POINTER_TYPE)
--- GCC/gcc/except.c.orig	2003-11-15 10:50:35.000000000 +0000
+++ GCC/gcc/except.c	2004-01-08 16:16:56.000000000 +0000
@@ -2430,14 +2430,14 @@ void
 for_each_eh_label (void (*callback) (rtx))
 {
   htab_traverse (cfun->eh->exception_handler_label_map, for_each_eh_label_1,
-		 (void *)callback);
+		 (void *) &callback);
 }
 
 static int
 for_each_eh_label_1 (void **pentry, void *data)
 {
   struct ehl_map_entry *entry = *(struct ehl_map_entry **)pentry;
-  void (*callback) (rtx) = (void (*) (rtx)) data;
+  void (*callback) (rtx) = *(void (**) (rtx)) data;
 
   (*callback) (entry->label);
   return 1;
--- GCC/gcc/recog.h.orig	2003-12-02 10:26:31.000000000 +0000
+++ GCC/gcc/recog.h	2004-01-08 22:21:05.000000000 +0000
@@ -238,7 +238,19 @@ struct insn_operand_data
 struct insn_data
 {
   const char *const name;
-  const void *output;
+#if HAVE_DESIGNATED_INITIALIZERS
+  union {
+    const char *single;
+    const char *const *multi;
+    insn_output_fn function;
+  } output;
+#else
+  struct {
+    const char *single;
+    const char *const *multi;
+    insn_output_fn function;
+  } output;
+#endif
   const insn_gen_fn genfun;
   const struct insn_operand_data *const operand;
 
--- GCC/gcc/final.c.orig	2004-01-07 10:59:53.000000000 +0000
+++ GCC/gcc/final.c	2004-01-08 22:22:14.000000000 +0000
@@ -1597,17 +1597,16 @@ final (rtx first, FILE *file, int optimi
 const char *
 get_insn_template (int code, rtx insn)
 {
-  const void *output = insn_data[code].output;
   switch (insn_data[code].output_format)
     {
     case INSN_OUTPUT_FORMAT_SINGLE:
-      return (const char *) output;
+      return insn_data[code].output.single;
     case INSN_OUTPUT_FORMAT_MULTI:
-      return ((const char *const *) output)[which_alternative];
+      return insn_data[code].output.multi[which_alternative];
     case INSN_OUTPUT_FORMAT_FUNCTION:
       if (insn == NULL)
 	abort ();
-      return (*(insn_output_fn) output) (recog_data.operand, insn);
+      return (*insn_data[code].output.function) (recog_data.operand, insn);
 
     default:
       abort ();
--- GCC/gcc/genoutput.c.orig	2003-10-06 12:25:12.000000000 +0000
+++ GCC/gcc/genoutput.c	2004-01-08 22:32:33.000000000 +0000
@@ -286,6 +286,7 @@ output_insn_data (void)
 	break;
       }
 
+  printf ("#if GCC_VERSION >= 2007\n__extension__\n#endif\n");
   printf ("\nconst struct insn_data insn_data[] = \n{\n");
 
   for (d = idata; d; d = d->next)
@@ -322,13 +323,22 @@ output_insn_data (void)
       switch (d->output_format)
 	{
 	case INSN_OUTPUT_FORMAT_NONE:
-	  printf ("    0,\n");
+	  printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
+	  printf ("    { 0 },\n");
+	  printf ("#else\n");
+	  printf ("    { 0, 0, 0 },\n");
+	  printf ("#endif\n");
 	  break;
 	case INSN_OUTPUT_FORMAT_SINGLE:
 	  {
 	    const char *p = d->template;
 	    char prev = 0;
 
+	    printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
+	    printf ("    { .single =\n");
+	    printf ("#else\n");
+	    printf ("    {\n");
+	    printf ("#endif\n");
 	    printf ("    \"");
 	    while (*p)
 	      {
@@ -345,11 +355,26 @@ output_insn_data (void)
 		++p;
 	      }
 	    printf ("\",\n");
+	    printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
+	    printf ("    },\n");
+	    printf ("#else\n");
+	    printf ("    0, 0 },\n");
+	    printf ("#endif\n");
 	  }
 	  break;
 	case INSN_OUTPUT_FORMAT_MULTI:
+	  printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
+	  printf ("    { .multi = output_%d },\n", d->code_number);
+	  printf ("#else\n");
+	  printf ("    { 0, output_%d, 0 },\n", d->code_number);
+	  printf ("#endif\n");
+	  break;
 	case INSN_OUTPUT_FORMAT_FUNCTION:
-	  printf ("    (const void *) output_%d,\n", d->code_number);
+	  printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
+	  printf ("    { .function = output_%d },\n", d->code_number);
+	  printf ("#else\n");
+	  printf ("    { 0, 0, output_%d },\n", d->code_number);
+	  printf ("#endif\n");
 	  break;
 	default:
 	  abort ();
--- GCC/gcc/testsuite/gcc.dg/func-ptr-conv-1.c	2002-08-26 16:21:36.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/func-ptr-conv-1.c	2004-01-07 23:21:42.000000000 +0000
@@ -0,0 +1,56 @@
+/* Conversions between function and object pointers are not permitted
+   in any version of ISO C, even with casts, except for the special
+   case of converting a null pointer constant to function pointer
+   type.  Likewise, comparisons between function and object pointers
+   are not permitted.  PR c/11234.  */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "-pedantic" } */
+
+void f(void);
+
+void *v1 = f; /* { dg-warning "pointer" "bad conversion" } */
+void *v2 = &f; /* { dg-warning "pointer" "bad conversion" } */
+void *v3 = (void *)f; /* { dg-warning "pointer" "bad conversion" } */
+void *v4 = (void *)&f; /* { dg-warning "pointer" "bad conversion" } */
+void *v5;
+char *c1 = f; /* { dg-warning "pointer" "bad conversion" } */
+char *c2 = &f; /* { dg-warning "pointer" "bad conversion" } */
+char *c3 = (char *)f; /* { dg-warning "pointer" "bad conversion" } */
+char *c4 = (char *)&f; /* { dg-warning "pointer" "bad conversion" } */
+char *c5;
+void (*fp)(void);
+int a;
+
+void
+g(void)
+{
+  v5 = f; /* { dg-warning "pointer" "bad conversion" } */
+  v5 = &f; /* { dg-warning "pointer" "bad conversion" } */
+  v5 = (void *)f; /* { dg-warning "pointer" "bad conversion" } */
+  v5 = (void *)&f; /* { dg-warning "pointer" "bad conversion" } */
+  c5 = f; /* { dg-warning "pointer" "bad conversion" } */
+  c5 = &f; /* { dg-warning "pointer" "bad conversion" } */
+  c5 = (char *)f; /* { dg-warning "pointer" "bad conversion" } */
+  c5 = (char *)&f; /* { dg-warning "pointer" "bad conversion" } */
+  fp = v5; /* { dg-warning "pointer" "bad conversion" } */
+  fp = c5; /* { dg-warning "pointer" "bad conversion" } */
+  fp = (void (*)(void))v5; /* { dg-warning "pointer" "bad conversion" } */
+  fp = (void (*)(void))c5; /* { dg-warning "pointer" "bad conversion" } */
+  (a ? f : v3); /* { dg-warning "pointer" "bad conversion" } */
+  (a ? v2 : fp); /* { dg-warning "pointer" "bad conversion" } */
+  /* The following are OK.  */
+  fp = 0;
+  fp = (void *)0;
+  fp = 0L;
+  fp = (void (*)(void))0;
+  fp = (void (*)(void))(void *)0;
+  (a ? f : 0);
+  (a ? f : (void *)0);
+  (a ? (void *)0 : fp);
+  (a ? 0 : fp);
+}
+
+/* The following are OK.  */
+void (*fp2)(void) = 0;
+void (*fp3)(void) = (void *)0;
--- GCC/gcc/testsuite/gcc.dg/weak/weak-6.c.orig	2003-10-04 07:36:45.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/weak/weak-6.c	2004-01-08 19:26:37.000000000 +0000
@@ -3,5 +3,5 @@
 
 extern void * foo (void);
 void * foo (void) { return (void *)foo; } /* { dg-error "precede" } */
-
+/* { dg-error "function pointer" "pointer conversion" { target *-*-* } 5 } */
 #pragma weak foo
--- GCC/gcc/testsuite/gcc.dg/weak/weak-7.c.orig	2003-10-04 07:36:45.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/weak/weak-7.c	2004-01-08 19:26:49.000000000 +0000
@@ -3,5 +3,5 @@
 
 extern void * foo (void);
 void * foo (void) { return (void *)foo; } /* { dg-error "precede" } */
-
+/* { dg-error "function pointer" "pointer conversion" { target *-*-* } 5 } */
 extern void * foo (void) __attribute__((weak));

-- 
Joseph S. Myers
jsm@polyomino.org.uk


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