diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/c-family/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 73 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 3 | ||||
-rw-r--r-- | gcc/c/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/c/c-typeck.c | 3 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/call.c | 3 | ||||
-rw-r--r-- | gcc/input.c | 10 | ||||
-rw-r--r-- | gcc/input.h | 1 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr70859-2.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr70859.c | 69 |
13 files changed, 177 insertions, 36 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1a85213..69db5db 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2016-05-03 Marek Polacek <polacek@redhat.com> + + PR c/70859 + * input.c (expansion_point_location): New function. + * input.h (expansion_point_location): Declare. + 2016-05-03 Pierre-Marie de Rodat <derodat@adacore.com> * dwarf2out.c (resolve_args_picking_1): Replace the frame_offset diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index b34e8ed..09a72e39 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,12 @@ +2016-05-03 Marek Polacek <polacek@redhat.com> + + PR c/70859 + * c-common.c (builtin_function_validate_nargs): Add location + parameter. Use it. + (check_builtin_function_arguments): Add location and arguments + parameters. Use them. + * c-common.h (check_builtin_function_arguments): Update declaration. + 2016-05-03 Richard Biener <rguenther@suse.de> * cilk.c (cilk_gimplify_call_params_in_spawned_fn): Do not diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index d45bf1b..63a18c86 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -9797,31 +9797,39 @@ check_function_arguments_recurse (void (*callback) /* Checks for a builtin function FNDECL that the number of arguments NARGS against the required number REQUIRED and issues an error if there is a mismatch. Returns true if the number of arguments is - correct, otherwise false. */ + correct, otherwise false. LOC is the location of FNDECL. */ static bool -builtin_function_validate_nargs (tree fndecl, int nargs, int required) +builtin_function_validate_nargs (location_t loc, tree fndecl, int nargs, + int required) { if (nargs < required) { - error_at (input_location, - "not enough arguments to function %qE", fndecl); + error_at (loc, "not enough arguments to function %qE", fndecl); return false; } else if (nargs > required) { - error_at (input_location, - "too many arguments to function %qE", fndecl); + error_at (loc, "too many arguments to function %qE", fndecl); return false; } return true; } +/* Helper macro for check_builtin_function_arguments. */ +#define ARG_LOCATION(N) \ + (arg_loc.is_empty () \ + ? EXPR_LOC_OR_LOC (args[(N)], input_location) \ + : expansion_point_location (arg_loc[(N)])) + /* Verifies the NARGS arguments ARGS to the builtin function FNDECL. - Returns false if there was an error, otherwise true. */ + Returns false if there was an error, otherwise true. LOC is the + location of the function; ARG_LOC is a vector of locations of the + arguments. */ bool -check_builtin_function_arguments (tree fndecl, int nargs, tree *args) +check_builtin_function_arguments (location_t loc, vec<location_t> arg_loc, + tree fndecl, int nargs, tree *args) { if (!DECL_BUILT_IN (fndecl) || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL) @@ -9843,21 +9851,21 @@ check_builtin_function_arguments (tree fndecl, int nargs, tree *args) /* The maximum alignment in bits corresponding to the same maximum in bytes enforced in check_user_alignment(). */ unsigned maxalign = (UINT_MAX >> 1) + 1; - + /* Reject invalid alignments. */ if (align < BITS_PER_UNIT || maxalign < align) { - error_at (EXPR_LOC_OR_LOC (args[1], input_location), + error_at (ARG_LOCATION (1), "second argument to function %qE must be a constant " "integer power of 2 between %qi and %qu bits", fndecl, BITS_PER_UNIT, maxalign); return false; } - return true; + return true; } case BUILT_IN_CONSTANT_P: - return builtin_function_validate_nargs (fndecl, nargs, 1); + return builtin_function_validate_nargs (loc, fndecl, nargs, 1); case BUILT_IN_ISFINITE: case BUILT_IN_ISINF: @@ -9865,12 +9873,12 @@ check_builtin_function_arguments (tree fndecl, int nargs, tree *args) case BUILT_IN_ISNAN: case BUILT_IN_ISNORMAL: case BUILT_IN_SIGNBIT: - if (builtin_function_validate_nargs (fndecl, nargs, 1)) + if (builtin_function_validate_nargs (loc, fndecl, nargs, 1)) { if (TREE_CODE (TREE_TYPE (args[0])) != REAL_TYPE) { - error ("non-floating-point argument in call to " - "function %qE", fndecl); + error_at (ARG_LOCATION (0), "non-floating-point argument in " + "call to function %qE", fndecl); return false; } return true; @@ -9883,7 +9891,7 @@ check_builtin_function_arguments (tree fndecl, int nargs, tree *args) case BUILT_IN_ISLESSEQUAL: case BUILT_IN_ISLESSGREATER: case BUILT_IN_ISUNORDERED: - if (builtin_function_validate_nargs (fndecl, nargs, 2)) + if (builtin_function_validate_nargs (loc, fndecl, nargs, 2)) { enum tree_code code0, code1; code0 = TREE_CODE (TREE_TYPE (args[0])); @@ -9892,8 +9900,8 @@ check_builtin_function_arguments (tree fndecl, int nargs, tree *args) || (code0 == REAL_TYPE && code1 == INTEGER_TYPE) || (code0 == INTEGER_TYPE && code1 == REAL_TYPE))) { - error ("non-floating-point arguments in call to " - "function %qE", fndecl); + error_at (loc, "non-floating-point arguments in call to " + "function %qE", fndecl); return false; } return true; @@ -9901,22 +9909,20 @@ check_builtin_function_arguments (tree fndecl, int nargs, tree *args) return false; case BUILT_IN_FPCLASSIFY: - if (builtin_function_validate_nargs (fndecl, nargs, 6)) + if (builtin_function_validate_nargs (loc, fndecl, nargs, 6)) { - unsigned i; - - for (i=0; i<5; i++) + for (unsigned int i = 0; i < 5; i++) if (TREE_CODE (args[i]) != INTEGER_CST) { - error ("non-const integer argument %u in call to function %qE", - i+1, fndecl); + error_at (ARG_LOCATION (i), "non-const integer argument %u in " + "call to function %qE", i + 1, fndecl); return false; } if (TREE_CODE (TREE_TYPE (args[5])) != REAL_TYPE) { - error ("non-floating-point argument in call to function %qE", - fndecl); + error_at (ARG_LOCATION (5), "non-floating-point argument in " + "call to function %qE", fndecl); return false; } return true; @@ -9924,11 +9930,12 @@ check_builtin_function_arguments (tree fndecl, int nargs, tree *args) return false; case BUILT_IN_ASSUME_ALIGNED: - if (builtin_function_validate_nargs (fndecl, nargs, 2 + (nargs > 2))) + if (builtin_function_validate_nargs (loc, fndecl, nargs, 2 + (nargs > 2))) { if (nargs >= 3 && TREE_CODE (TREE_TYPE (args[2])) != INTEGER_TYPE) { - error ("non-integer argument 3 in call to function %qE", fndecl); + error_at (ARG_LOCATION (2), "non-integer argument 3 in call to " + "function %qE", fndecl); return false; } return true; @@ -9938,21 +9945,21 @@ check_builtin_function_arguments (tree fndecl, int nargs, tree *args) case BUILT_IN_ADD_OVERFLOW: case BUILT_IN_SUB_OVERFLOW: case BUILT_IN_MUL_OVERFLOW: - if (builtin_function_validate_nargs (fndecl, nargs, 3)) + if (builtin_function_validate_nargs (loc, fndecl, nargs, 3)) { unsigned i; for (i = 0; i < 2; i++) if (!INTEGRAL_TYPE_P (TREE_TYPE (args[i]))) { - error ("argument %u in call to function %qE does not have " - "integral type", i + 1, fndecl); + error_at (ARG_LOCATION (i), "argument %u in call to function " + "%qE does not have integral type", i + 1, fndecl); return false; } if (TREE_CODE (TREE_TYPE (args[2])) != POINTER_TYPE || TREE_CODE (TREE_TYPE (TREE_TYPE (args[2]))) != INTEGER_TYPE) { - error ("argument 3 in call to function %qE does not have " - "pointer to integer type", fndecl); + error_at (ARG_LOCATION (2), "argument 3 in call to function %qE " + "does not have pointer to integer type", fndecl); return false; } return true; diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index b121138..4454d08 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -788,7 +788,8 @@ extern void check_function_arguments_recurse (void (*) unsigned HOST_WIDE_INT), void *, tree, unsigned HOST_WIDE_INT); -extern bool check_builtin_function_arguments (tree, int, tree *); +extern bool check_builtin_function_arguments (location_t, vec<location_t>, + tree, int, tree *); extern void check_function_format (tree, int, tree *); extern tree handle_unused_attribute (tree *, tree, tree, int, bool *); extern tree handle_format_attribute (tree *, tree, tree, int, bool *); diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index ae62759..8ac13e3 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2016-05-03 Marek Polacek <polacek@redhat.com> + + PR c/70859 + * c-typeck.c (build_function_call_vec): Pass LOC and ARG_LOC down to + check_builtin_function_arguments. + 2016-05-03 Richard Biener <rguenther@suse.de> * Make-lang.in (cc1-checksum.c): For stage-final re-use diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 0fa9653..204702e 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -3046,7 +3046,8 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc, if (fundecl && DECL_BUILT_IN (fundecl) && DECL_BUILT_IN_CLASS (fundecl) == BUILT_IN_NORMAL - && !check_builtin_function_arguments (fundecl, nargs, argarray)) + && !check_builtin_function_arguments (loc, arg_loc, fundecl, nargs, + argarray)) return error_mark_node; /* Check that the arguments to the function are valid. */ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 497bc0e..3bc37e1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2016-05-03 Marek Polacek <polacek@redhat.com> + + PR c/70859 + * call.c (build_cxx_call): Pass location and vNULL down to + check_builtin_function_arguments. + 2016-05-03 Richard Biener <rguenther@suse.de> * Make-lang.in (cc1plus-checksum.c): For stage-final re-use diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 476e806..e9ebdbc 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -7790,7 +7790,8 @@ build_cxx_call (tree fn, int nargs, tree *argarray, for (i = 0; i < nargs; i++) argarray[i] = fold_non_dependent_expr (argarray[i]); - if (!check_builtin_function_arguments (fndecl, nargs, argarray)) + if (!check_builtin_function_arguments (EXPR_LOCATION (fn), vNULL, fndecl, + nargs, argarray)) return error_mark_node; } diff --git a/gcc/input.c b/gcc/input.c index 9779198..61b1e44 100644 --- a/gcc/input.c +++ b/gcc/input.c @@ -789,6 +789,16 @@ expansion_point_location_if_in_system_header (source_location location) return location; } +/* If LOCATION is a virtual location for a token coming from the expansion + of a macro, unwind to the location of the expansion point of the macro. */ + +source_location +expansion_point_location (source_location location) +{ + return linemap_resolve_location (line_table, location, + LRK_MACRO_EXPANSION_POINT, NULL); +} + #define ONE_K 1024 #define ONE_M (ONE_K * ONE_K) diff --git a/gcc/input.h b/gcc/input.h index 97c4333..ae4fecf 100644 --- a/gcc/input.h +++ b/gcc/input.h @@ -42,6 +42,7 @@ extern const char *location_get_source_line (const char *file_path, int line, int *line_size); extern expanded_location expand_location_to_spelling_point (source_location); extern source_location expansion_point_location_if_in_system_header (source_location); +extern source_location expansion_point_location (source_location); /* Historically GCC used location_t, while cpp used source_location. This could be removed but it hardly seems worth the effort. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 818a177..59e5be8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-05-03 Marek Polacek <polacek@redhat.com> + + PR c/70859 + * gcc.dg/pr70859.c: New test. + * gcc.dg/pr70859-2.c: New test. + 2016-05-03 Pierre-Marie de Rodat <derodat@adacore.com> * gnat.dg/debug5.adb: New testcase. diff --git a/gcc/testsuite/gcc.dg/pr70859-2.c b/gcc/testsuite/gcc.dg/pr70859-2.c new file mode 100644 index 0000000..4817852 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr70859-2.c @@ -0,0 +1,18 @@ +/* PR c/70859 */ +/* { dg-do compile } */ + +#include <stdint.h> +#define MAX __SIZE_MAX__ +#define MAX2 SIZE_MAX +#define FIVE 5 + +static void *p; + +void +fn0 (int n) +{ + p = __builtin_alloca_with_align (n, SIZE_MAX); /* { dg-error "39:must be a constant integer" } */ + p = __builtin_alloca_with_align (n, MAX); /* { dg-error "39:must be a constant integer" } */ + p = __builtin_alloca_with_align (n, MAX2); /* { dg-error "39:must be a constant integer" } */ + p = __builtin_alloca_with_align (n, FIVE); /* { dg-error "39:must be a constant integer" } */ +} diff --git a/gcc/testsuite/gcc.dg/pr70859.c b/gcc/testsuite/gcc.dg/pr70859.c new file mode 100644 index 0000000..0a3c843 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr70859.c @@ -0,0 +1,69 @@ +/* PR c/70859 */ +/* { dg-do compile } */ + +static void *p; +static double *d; +static int r; +__extension__ static _Bool b; + +void +fn0 (int n) +{ + p = __builtin_alloca_with_align (n, 6); /* { dg-error "39:must be a constant integer" } */ + + r += __builtin_isfinite (0); /* { dg-error "28:non-floating-point argument in call" } */ + r += __builtin_isinf (0); /* { dg-error "25:non-floating-point argument in call" } */ + r += __builtin_isinf_sign (0); /* { dg-error "30:non-floating-point argument in call" } */ + r += __builtin_isnan (0); /* { dg-error "25:non-floating-point argument in call" } */ + r += __builtin_isnormal (0); /* { dg-error "28:non-floating-point argument in call" } */ + r += __builtin_signbit (0); /* { dg-error "27:non-floating-point argument in call" } */ + + r += __builtin_isgreater (0, 0); /* { dg-error "8:non-floating-point arguments in call to function" } */ + r += __builtin_isgreaterequal (0, 0); /* { dg-error "8:non-floating-point arguments in call to function" } */ + r += __builtin_isless (0, 0); /* { dg-error "8:non-floating-point arguments in call to function" } */ + r += __builtin_islessequal (0, 0); /* { dg-error "8:non-floating-point arguments in call to function" } */ + r += __builtin_islessgreater (0, 0); /* { dg-error "8:non-floating-point arguments in call to function" } */ + r += __builtin_isunordered (0, 0); /* { dg-error "8:non-floating-point arguments in call to function" } */ + + r += __builtin_fpclassify (1, 2, n, 4, 5, n); /* { dg-error "36:non-const integer argument 3 in call" } */ + r += __builtin_fpclassify (1, 2, 3, 4, 5, 6); /* { dg-error "45:non-floating-point argument in call" } */ + + d = __builtin_assume_aligned (p, n, p); /* { dg-error "39:non-integer argument 3 in call" } */ + + b = __builtin_add_overflow (n, *d, &r); /* { dg-error "34:argument 2 in call to function" } */ + b = __builtin_add_overflow (n, 5, d); /* { dg-error "37:argument 3 in call" } */ + b = __builtin_sub_overflow (n, *d, &r); /* { dg-error "34:argument 2 in call to function" } */ + b = __builtin_sub_overflow (n, 5, d); /* { dg-error "37:argument 3 in call" } */ + b = __builtin_mul_overflow (n, *d, &r); /* { dg-error "34:argument 2 in call to function" } */ + b = __builtin_mul_overflow (n, 5, d); /* { dg-error "37:argument 3 in call" } */ +} + +int +fn1 (void) +{ + if (__builtin_constant_p ()) /* { dg-error "7:not enough" } */ + return 0; + if (__builtin_constant_p (1, 2)) /* { dg-error "7:too many" } */ + return 1; + if (__builtin_isfinite ()) /* { dg-error "7:not enough" } */ + return 3; + if (__builtin_isfinite (1, 2)) /* { dg-error "7:too many" } */ + return 4; + if (__builtin_isless (0)) /* { dg-error "7:not enough" } */ + return 5; + if (__builtin_isless (1, 2, 3)) /* { dg-error "7:too many" } */ + return 6; + if (__builtin_fpclassify (1, 2, 3, 4, 5)) /* { dg-error "7:not enough" } */ + return 7; + if (__builtin_fpclassify (1, 2, 3, 4, 5, r, 6)) /* { dg-error "7:too many" } */ + return 8; + if (__builtin_assume_aligned (p)) /* { dg-error "7:too few" } */ + return 9; + if (__builtin_assume_aligned (p, r, p, p)) /* { dg-error "7:too many" } */ + return 10; + if (__builtin_add_overflow ()) /* { dg-error "7:not enough" } */ + return 11; + if (__builtin_add_overflow (1, 2, 3, &r)) /* { dg-error "7:too many" } */ + return 12; + return -1; +} |