re PR c/59905 (Unfriendly abort when calling a fucntion via a function pointer cast)

2014-01-30  Richard Biener  <rguenther@suse.de>

	PR c/59905
	* c-typeck.c (build_function_call_vec): Do not replace calls
	to a function via an incompatible type with a runtime abort.

	* gcc.dg/cast-function-1.c: Adjust to survive DCE.
	* gcc.dg/call-diag-2.c: Remove expected warnings about calling
	abort.
	* gcc.dg/invalid-call-1.c: Likewise.

From-SVN: r207300
This commit is contained in:
Richard Biener 2014-01-30 14:17:02 +00:00 committed by Richard Biener
parent f30a0ba57a
commit fa337f3ae5
6 changed files with 27 additions and 48 deletions

View File

@ -1,3 +1,9 @@
2014-01-30 Richard Biener <rguenther@suse.de>
PR c/59905
* c-typeck.c (build_function_call_vec): Do not replace calls
to a function via an incompatible type with a runtime abort.
2014-01-24 Balaji V. Iyer <balaji.v.iyer@intel.com> 2014-01-24 Balaji V. Iyer <balaji.v.iyer@intel.com>
* c-parser.c (c_parser_declaration_or_fndef): Replaced * c-parser.c (c_parser_declaration_or_fndef): Replaced

View File

@ -2907,56 +2907,24 @@ build_function_call_vec (location_t loc, tree function,
return error_mark_node; return error_mark_node;
/* Check that the function is called through a compatible prototype. /* Check that the function is called through a compatible prototype.
If it is not, replace the call by a trap, wrapped up in a compound If it is not, warn. */
expression if necessary. This has the nice side-effect to prevent
the tree-inliner from generating invalid assignment trees which may
blow up in the RTL expander later. */
if (CONVERT_EXPR_P (function) if (CONVERT_EXPR_P (function)
&& TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR
&& TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL
&& !comptypes (fntype, TREE_TYPE (tem))) && !comptypes (fntype, TREE_TYPE (tem)))
{ {
tree return_type = TREE_TYPE (fntype); tree return_type = TREE_TYPE (fntype);
tree trap = build_function_call (loc,
builtin_decl_explicit (BUILT_IN_TRAP),
NULL_TREE);
int i;
/* This situation leads to run-time undefined behavior. We can't, /* This situation leads to run-time undefined behavior. We can't,
therefore, simply error unless we can prove that all possible therefore, simply error unless we can prove that all possible
executions of the program must execute the code. */ executions of the program must execute the code. */
if (warning_at (loc, 0, "function called through a non-compatible type")) warning_at (loc, 0, "function called through a non-compatible type");
/* We can, however, treat "undefined" any way we please.
Call abort to encourage the user to fix the program. */
inform (loc, "if this code is reached, the program will abort");
/* Before the abort, allow the function arguments to exit or
call longjmp. */
for (i = 0; i < nargs; i++)
trap = build2 (COMPOUND_EXPR, void_type_node, (*params)[i], trap);
if (VOID_TYPE_P (return_type)) if (VOID_TYPE_P (return_type)
{ && TYPE_QUALS (return_type) != TYPE_UNQUALIFIED)
if (TYPE_QUALS (return_type) != TYPE_UNQUALIFIED) pedwarn (loc, 0,
pedwarn (loc, 0, "function with qualified void return type called");
"function with qualified void return type called"); }
return trap;
}
else
{
tree rhs;
if (AGGREGATE_TYPE_P (return_type))
rhs = build_compound_literal (loc, return_type,
build_constructor (return_type,
NULL),
false);
else
rhs = build_zero_cst (return_type);
return require_complete_type (build2 (COMPOUND_EXPR, return_type,
trap, rhs));
}
}
argarray = vec_safe_address (params); argarray = vec_safe_address (params);

View File

@ -1,3 +1,11 @@
2014-01-30 Richard Biener <rguenther@suse.de>
PR c/59905
* gcc.dg/cast-function-1.c: Adjust to survive DCE.
* gcc.dg/call-diag-2.c: Remove expected warnings about calling
abort.
* gcc.dg/invalid-call-1.c: Likewise.
2014-01-29 Paolo Carlini <paolo.carlini@oracle.com> 2014-01-29 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/58561 PR c++/58561

View File

@ -11,7 +11,5 @@ void g1 (void) { f_cv (); } /* { dg-error "qualified void" } */
void g2 (void) { f_s (); } /* { dg-error "invalid use of undefined type" } */ void g2 (void) { f_s (); } /* { dg-error "invalid use of undefined type" } */
void g3 (void) { ((const void (*) (void)) f_v) (); } /* { dg-error "qualified void" } */ void g3 (void) { ((const void (*) (void)) f_v) (); } /* { dg-error "qualified void" } */
/* { dg-warning "function called through a non-compatible type" "cast" { target *-*-* } 12 } */ /* { dg-warning "function called through a non-compatible type" "cast" { target *-*-* } 12 } */
/* { dg-message "will abort" "abort" { target *-*-* } 12 } */
void g4 (void) { ((struct s (*) (void)) f_v) (), (void) 0; } /* { dg-error "invalid use of undefined type" } */ void g4 (void) { ((struct s (*) (void)) f_v) (), (void) 0; } /* { dg-error "invalid use of undefined type" } */
/* { dg-warning "function called through a non-compatible type" "cast" { target *-*-* } 15 } */ /* { dg-warning "function called through a non-compatible type" "cast" { target *-*-* } 14 } */
/* { dg-message "will abort" "abort" { target *-*-* } 15 } */

View File

@ -16,12 +16,8 @@ typedef struct {
int a; int a;
} str_t; } str_t;
void bar(void) void bar(double d, int i, str_t s)
{ {
double d;
int i;
str_t s;
d = ((double (*) (int)) foo1) (i); /* { dg-warning "33:non-compatible|abort" } */ d = ((double (*) (int)) foo1) (i); /* { dg-warning "33:non-compatible|abort" } */
i = ((int (*) (double)) foo1) (d); /* { dg-warning "33:non-compatible|abort" } */ i = ((int (*) (double)) foo1) (d); /* { dg-warning "33:non-compatible|abort" } */
s = ((str_t (*) (int)) foo1) (i); /* { dg-warning "32:non-compatible|abort" } */ s = ((str_t (*) (int)) foo1) (i); /* { dg-warning "32:non-compatible|abort" } */
@ -39,11 +35,15 @@ void bar(void)
int foo1(int arg) int foo1(int arg)
{ {
/* Prevent the function from becoming const and thus DCEd. */
__asm volatile ("" : "+r" (arg));
return arg; return arg;
} }
int foo2(arg) int foo2(arg)
int arg; int arg;
{ {
/* Prevent the function from becoming const and thus DCEd. */
__asm volatile ("" : "+r" (arg));
return arg; return arg;
} }

View File

@ -14,5 +14,4 @@ void foo()
{ {
cptr = mar(6); cptr = mar(6);
((char *(*)(void *,int (*)(void *,unsigned char **),char**))((fp)bar))(0,0,(void*)(0)); /* { dg-warning "function called through a non-compatible type" "non-compatible type" } */ ((char *(*)(void *,int (*)(void *,unsigned char **),char**))((fp)bar))(0,0,(void*)(0)); /* { dg-warning "function called through a non-compatible type" "non-compatible type" } */
/* { dg-message "note: if this code is reached, the program will abort" "" { target *-*-* } 16 } */
} }