Commit 3897f229 by Joseph Myers Committed by Joseph Myers

re PR c/11234 (-pedantic accepts function pointer <-> void*)

	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:
	* gcc.dg/func-ptr-conv-1.c: New test.
	* gcc.dg/weak/weak-6.c, gcc.dg/weak/weak-7.c: Update.

From-SVN: r75595
parent 0fab64a3
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.
2004-01-09 Mark Mitchell <mark@codesourcery.com> 2004-01-09 Mark Mitchell <mark@codesourcery.com>
* expr.h (expand_expr): Make it a macro, not a function. * expr.h (expand_expr): Make it a macro, not a function.
......
...@@ -3125,6 +3125,25 @@ build_c_cast (tree type, tree expr) ...@@ -3125,6 +3125,25 @@ build_c_cast (tree type, tree expr)
warning ("dereferencing type-punned pointer will break strict-aliasing rules"); 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; ovalue = value;
/* Replace a nonvolatile const static variable with its value. */ /* Replace a nonvolatile const static variable with its value. */
if (optimize && TREE_CODE (value) == VAR_DECL) if (optimize && TREE_CODE (value) == VAR_DECL)
...@@ -4088,9 +4107,12 @@ digest_init (tree type, tree init, int require_constant) ...@@ -4088,9 +4107,12 @@ digest_init (tree type, tree init, int require_constant)
|| (code == VECTOR_TYPE || (code == VECTOR_TYPE
&& comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT)) && comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT))
|| (code == POINTER_TYPE || (code == POINTER_TYPE
&& (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE && TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE)
&& comptypes (TREE_TYPE (TREE_TYPE (inside_init)), && 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)))) TREE_TYPE (type), COMPARE_STRICT))))
{ {
if (code == POINTER_TYPE) if (code == POINTER_TYPE)
......
/* Implements exception handling. /* Implements exception handling.
Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
Contributed by Mike Stump <mrs@cygnus.com>. Contributed by Mike Stump <mrs@cygnus.com>.
This file is part of GCC. This file is part of GCC.
...@@ -2430,14 +2430,14 @@ void ...@@ -2430,14 +2430,14 @@ void
for_each_eh_label (void (*callback) (rtx)) for_each_eh_label (void (*callback) (rtx))
{ {
htab_traverse (cfun->eh->exception_handler_label_map, for_each_eh_label_1, htab_traverse (cfun->eh->exception_handler_label_map, for_each_eh_label_1,
(void *)callback); (void *) &callback);
} }
static int static int
for_each_eh_label_1 (void **pentry, void *data) for_each_eh_label_1 (void **pentry, void *data)
{ {
struct ehl_map_entry *entry = *(struct ehl_map_entry **)pentry; 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); (*callback) (entry->label);
return 1; return 1;
......
/* Convert RTL to assembler code and output it, for GNU compiler. /* Convert RTL to assembler code and output it, for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -1591,17 +1591,16 @@ final (rtx first, FILE *file, int optimize, int prescan) ...@@ -1591,17 +1591,16 @@ final (rtx first, FILE *file, int optimize, int prescan)
const char * const char *
get_insn_template (int code, rtx insn) get_insn_template (int code, rtx insn)
{ {
const void *output = insn_data[code].output;
switch (insn_data[code].output_format) switch (insn_data[code].output_format)
{ {
case INSN_OUTPUT_FORMAT_SINGLE: case INSN_OUTPUT_FORMAT_SINGLE:
return (const char *) output; return insn_data[code].output.single;
case INSN_OUTPUT_FORMAT_MULTI: 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: case INSN_OUTPUT_FORMAT_FUNCTION:
if (insn == NULL) if (insn == NULL)
abort (); abort ();
return (*(insn_output_fn) output) (recog_data.operand, insn); return (*insn_data[code].output.function) (recog_data.operand, insn);
default: default:
abort (); abort ();
......
/* Generate code from to output assembler insns as recognized from rtl. /* Generate code from to output assembler insns as recognized from rtl.
Copyright (C) 1987, 1988, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2002, Copyright (C) 1987, 1988, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2002,
2003 Free Software Foundation, Inc. 2003, 2004 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -286,6 +286,7 @@ output_insn_data (void) ...@@ -286,6 +286,7 @@ output_insn_data (void)
break; break;
} }
printf ("#if GCC_VERSION >= 2007\n__extension__\n#endif\n");
printf ("\nconst struct insn_data insn_data[] = \n{\n"); printf ("\nconst struct insn_data insn_data[] = \n{\n");
for (d = idata; d; d = d->next) for (d = idata; d; d = d->next)
...@@ -322,13 +323,22 @@ output_insn_data (void) ...@@ -322,13 +323,22 @@ output_insn_data (void)
switch (d->output_format) switch (d->output_format)
{ {
case INSN_OUTPUT_FORMAT_NONE: 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; break;
case INSN_OUTPUT_FORMAT_SINGLE: case INSN_OUTPUT_FORMAT_SINGLE:
{ {
const char *p = d->template; const char *p = d->template;
char prev = 0; char prev = 0;
printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
printf (" { .single =\n");
printf ("#else\n");
printf (" {\n");
printf ("#endif\n");
printf (" \""); printf (" \"");
while (*p) while (*p)
{ {
...@@ -345,11 +355,26 @@ output_insn_data (void) ...@@ -345,11 +355,26 @@ output_insn_data (void)
++p; ++p;
} }
printf ("\",\n"); printf ("\",\n");
printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
printf (" },\n");
printf ("#else\n");
printf (" 0, 0 },\n");
printf ("#endif\n");
} }
break; break;
case INSN_OUTPUT_FORMAT_MULTI: 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: 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; break;
default: default:
abort (); abort ();
......
/* Declarations for interface to insn recognizer and insn-output.c. /* Declarations for interface to insn recognizer and insn-output.c.
Copyright (C) 1987, 1996, 1997, 1998, 1999, 2000, 2001, 2003 Copyright (C) 1987, 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -238,7 +238,19 @@ struct insn_operand_data ...@@ -238,7 +238,19 @@ struct insn_operand_data
struct insn_data struct insn_data
{ {
const char *const name; 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 insn_gen_fn genfun;
const struct insn_operand_data *const operand; const struct insn_operand_data *const operand;
......
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.
2004-01-09 Kazu Hirata <kazu@cs.umass.edu> 2004-01-09 Kazu Hirata <kazu@cs.umass.edu>
PR target/13380. PR target/13380.
......
/* 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;
...@@ -3,5 +3,5 @@ ...@@ -3,5 +3,5 @@
extern void * foo (void); extern void * foo (void);
void * foo (void) { return (void *)foo; } /* { dg-error "precede" } */ void * foo (void) { return (void *)foo; } /* { dg-error "precede" } */
/* { dg-error "function pointer" "pointer conversion" { target *-*-* } 5 } */
#pragma weak foo #pragma weak foo
...@@ -3,5 +3,5 @@ ...@@ -3,5 +3,5 @@
extern void * foo (void); extern void * foo (void);
void * foo (void) { return (void *)foo; } /* { dg-error "precede" } */ void * foo (void) { return (void *)foo; } /* { dg-error "precede" } */
/* { dg-error "function pointer" "pointer conversion" { target *-*-* } 5 } */
extern void * foo (void) __attribute__((weak)); extern void * foo (void) __attribute__((weak));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment