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>
|
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,
|
|||||||
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);
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -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 } */
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user