Commit fa337f3a by Richard Biener Committed by Richard Biener

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
parent f30a0ba5
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
......
...@@ -2907,56 +2907,24 @@ build_function_call_vec (location_t loc, tree function, ...@@ -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 (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, if (VOID_TYPE_P (return_type)
trap, rhs)); && TYPE_QUALS (return_type) != TYPE_UNQUALIFIED)
} pedwarn (loc, 0,
} "function with qualified void return type called");
}
argarray = vec_safe_address (params); argarray = vec_safe_address (params);
......
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
......
...@@ -11,7 +11,5 @@ void g1 (void) { f_cv (); } /* { dg-error "qualified void" } */ ...@@ -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 } */
...@@ -16,12 +16,8 @@ typedef struct { ...@@ -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) ...@@ -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;
} }
...@@ -14,5 +14,4 @@ void foo() ...@@ -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 } */
} }
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