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>
* 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;
/* 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
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 it is not, warn. */
if (CONVERT_EXPR_P (function)
&& TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR
&& TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL
&& !comptypes (fntype, TREE_TYPE (tem)))
{
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,
therefore, simply error unless we can prove that all possible
executions of the program must execute the code. */
if (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);
warning_at (loc, 0, "function called through a non-compatible type");
if (VOID_TYPE_P (return_type))
{
if (TYPE_QUALS (return_type) != TYPE_UNQUALIFIED)
pedwarn (loc, 0,
"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));
}
}
if (VOID_TYPE_P (return_type)
&& TYPE_QUALS (return_type) != TYPE_UNQUALIFIED)
pedwarn (loc, 0,
"function with qualified void return type called");
}
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>
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 g3 (void) { ((const void (*) (void)) f_v) (); } /* { dg-error "qualified void" } */
/* { 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" } */
/* { dg-warning "function called through a non-compatible type" "cast" { target *-*-* } 15 } */
/* { dg-message "will abort" "abort" { target *-*-* } 15 } */
/* { dg-warning "function called through a non-compatible type" "cast" { target *-*-* } 14 } */

View File

@ -16,12 +16,8 @@ typedef struct {
int a;
} 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" } */
i = ((int (*) (double)) foo1) (d); /* { dg-warning "33: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)
{
/* Prevent the function from becoming const and thus DCEd. */
__asm volatile ("" : "+r" (arg));
return arg;
}
int foo2(arg)
int arg;
{
/* Prevent the function from becoming const and thus DCEd. */
__asm volatile ("" : "+r" (arg));
return arg;
}

View File

@ -14,5 +14,4 @@ void foo()
{
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" } */
/* { dg-message "note: if this code is reached, the program will abort" "" { target *-*-* } 16 } */
}