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:
parent
f30a0ba57a
commit
fa337f3ae5
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 } */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 } */
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user