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
This commit is contained in:
Joseph Myers 2004-01-09 20:03:58 +00:00 committed by Joseph Myers
parent 0fab64a344
commit 3897f229d5
10 changed files with 152 additions and 17 deletions

View file

@ -1,3 +1,18 @@
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>
* expr.h (expand_expr): Make it a macro, not a function.

View file

@ -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 require_constant)
|| (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)

View file

@ -1,6 +1,6 @@
/* Implements exception handling.
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>.
This file is part of GCC.
@ -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;

View file

@ -1,6 +1,6 @@
/* Convert RTL to assembler code and output it, for GNU compiler.
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.
@ -1591,17 +1591,16 @@ final (rtx first, FILE *file, int optimize, int prescan)
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 ();

View file

@ -1,6 +1,6 @@
/* Generate code from to output assembler insns as recognized from rtl.
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.
@ -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 ();

View file

@ -1,5 +1,5 @@
/* 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.
This file is part of GCC.
@ -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;

View file

@ -1,3 +1,9 @@
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>
PR target/13380.

View file

@ -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;

View file

@ -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

View file

@ -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));