Mercurial > hg > CbC > CbC_gcc
diff gcc/c-family/c-common.c @ 132:d34655255c78
update gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 10:21:07 +0900 |
parents | bdf41c9fa0b7 84e7813d76e9 |
children | 351920fa3827 |
line wrap: on
line diff
--- a/gcc/c-family/c-common.c Thu Oct 25 08:08:40 2018 +0900 +++ b/gcc/c-family/c-common.c Thu Oct 25 10:21:07 2018 +0900 @@ -1,5 +1,5 @@ /* Subroutines shared by all languages that are variants of C. - Copyright (C) 1992-2017 Free Software Foundation, Inc. + Copyright (C) 1992-2018 Free Software Foundation, Inc. This file is part of GCC. @@ -48,6 +48,7 @@ #include "gimplify.h" #include "substring-locations.h" #include "spellcheck.h" +#include "selftest.h" cpp_reader *parse_in; /* Declared in c-pragma.h. */ @@ -213,6 +214,10 @@ int flag_isoc11; +/* Nonzero means use the ISO C2X dialect of C. */ + +int flag_isoc2x; + /* Nonzero means that we have builtin functions, and main is an int. */ int flag_hosted = 1; @@ -338,9 +343,6 @@ { "_Atomic", RID_ATOMIC, D_CONLY }, { "_Bool", RID_BOOL, D_CONLY }, { "_Complex", RID_COMPLEX, 0 }, - { "_Cilk_spawn", RID_CILK_SPAWN, 0 }, - { "_Cilk_sync", RID_CILK_SYNC, 0 }, - { "_Cilk_for", RID_CILK_FOR, 0 }, { "_Imaginary", RID_IMAGINARY, D_CONLY }, { "_Float16", RID_FLOAT16, D_CONLY }, { "_Float32", RID_FLOAT32, D_CONLY }, @@ -380,6 +382,7 @@ { "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY }, { "__builtin_launder", RID_BUILTIN_LAUNDER, D_CXXONLY }, { "__builtin_shuffle", RID_BUILTIN_SHUFFLE, 0 }, + { "__builtin_tgmath", RID_BUILTIN_TGMATH, D_CONLY }, { "__builtin_offsetof", RID_OFFSETOF, 0 }, { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, D_CONLY }, { "__builtin_va_arg", RID_VA_ARG, 0 }, @@ -878,19 +881,6 @@ } -/* Fold X for consideration by one of the warning functions when checking - whether an expression has a constant value. */ - -tree -fold_for_warn (tree x) -{ - if (c_dialect_cxx ()) - return c_fully_fold (x, /*for_init*/false, /*maybe_constp*/NULL); - else - /* The C front-end has already folded X appropriately. */ - return x; -} - /* Return true iff T is a boolean promoted to int. */ bool @@ -951,15 +941,16 @@ convertible_lax = (tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2)) - && (TREE_CODE (TREE_TYPE (t1)) != REAL_TYPE || - TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)) + && (TREE_CODE (TREE_TYPE (t1)) != REAL_TYPE + || known_eq (TYPE_VECTOR_SUBPARTS (t1), + TYPE_VECTOR_SUBPARTS (t2))) && (INTEGRAL_TYPE_P (TREE_TYPE (t1)) == INTEGRAL_TYPE_P (TREE_TYPE (t2)))); if (!convertible_lax || flag_lax_vector_conversions) return convertible_lax; - if (TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2) + if (known_eq (TYPE_VECTOR_SUBPARTS (t1), TYPE_VECTOR_SUBPARTS (t2)) && lang_hooks.types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))) return true; @@ -1027,10 +1018,10 @@ return error_mark_node; } - if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (v0)) - != TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask)) - && TYPE_VECTOR_SUBPARTS (TREE_TYPE (v1)) - != TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask))) + if (maybe_ne (TYPE_VECTOR_SUBPARTS (TREE_TYPE (v0)), + TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask))) + && maybe_ne (TYPE_VECTOR_SUBPARTS (TREE_TYPE (v1)), + TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask)))) { if (complain) error_at (loc, "__builtin_shuffle number of elements of the " @@ -2289,7 +2280,16 @@ if (inner_type != NULL_TREE) return build_complex_type (inner_type); } - else if (VECTOR_MODE_P (mode)) + else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL + && valid_vector_subparts_p (GET_MODE_NUNITS (mode))) + { + unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE (mode), + GET_MODE_NUNITS (mode)); + tree bool_type = build_nonstandard_boolean_type (elem_bits); + return build_vector_type_for_mode (bool_type, mode); + } + else if (VECTOR_MODE_P (mode) + && valid_vector_subparts_p (GET_MODE_NUNITS (mode))) { machine_mode inner_mode = GET_MODE_INNER (mode); tree inner_type = c_common_type_for_mode (inner_mode, unsignedp); @@ -2703,9 +2703,9 @@ default: gcc_unreachable (); } - error_at_rich_loc (richloc, - "invalid operands to binary %s (have %qT and %qT)", - opname, type0, type1); + error_at (richloc, + "invalid operands to binary %s (have %qT and %qT)", + opname, type0, type1); } /* Given an expression as a tree, return its original type. Do this @@ -3302,7 +3302,7 @@ tree inner = TREE_OPERAND (expr, 0); if (decl_with_nonnull_addr_p (inner)) { - /* Common Ada/Pascal programmer's mistake. */ + /* Common Ada programmer's mistake. */ warning_at (location, OPT_Waddress, "the address of %qD will always evaluate as %<true%>", @@ -3325,6 +3325,7 @@ case NEGATE_EXPR: case ABS_EXPR: + case ABSU_EXPR: case FLOAT_EXPR: case EXCESS_PRECISION_EXPR: /* These don't change whether an object is nonzero or zero. */ @@ -3943,9 +3944,6 @@ targetm.init_builtins (); build_common_builtin_nodes (); - - if (flag_cilkplus) - cilk_init_builtins (); } /* Like get_identifier, but avoid warnings about null arguments when @@ -4912,6 +4910,64 @@ return error_mark_node; } +/* Subroutine of c_switch_covers_all_cases_p, called via + splay_tree_foreach. Return 1 if it doesn't cover all the cases. + ARGS[0] is initially NULL and after the first iteration is the + so far highest case label. ARGS[1] is the minimum of SWITCH_COND's + type. */ + +static int +c_switch_covers_all_cases_p_1 (splay_tree_node node, void *data) +{ + tree label = (tree) node->value; + tree *args = (tree *) data; + + /* If there is a default case, we shouldn't have called this. */ + gcc_assert (CASE_LOW (label)); + + if (args[0] == NULL_TREE) + { + if (wi::to_widest (args[1]) < wi::to_widest (CASE_LOW (label))) + return 1; + } + else if (wi::add (wi::to_widest (args[0]), 1) + != wi::to_widest (CASE_LOW (label))) + return 1; + if (CASE_HIGH (label)) + args[0] = CASE_HIGH (label); + else + args[0] = CASE_LOW (label); + return 0; +} + +/* Return true if switch with CASES and switch condition with type + covers all possible values in the case labels. */ + +bool +c_switch_covers_all_cases_p (splay_tree cases, tree type) +{ + /* If there is default:, this is always the case. */ + splay_tree_node default_node + = splay_tree_lookup (cases, (splay_tree_key) NULL); + if (default_node) + return true; + + if (!INTEGRAL_TYPE_P (type)) + return false; + + tree args[2] = { NULL_TREE, TYPE_MIN_VALUE (type) }; + if (splay_tree_foreach (cases, c_switch_covers_all_cases_p_1, args)) + return false; + + /* If there are no cases at all, or if the highest case label + is smaller than TYPE_MAX_VALUE, return false. */ + if (args[0] == NULL_TREE + || wi::to_widest (args[0]) < wi::to_widest (TYPE_MAX_VALUE (type))) + return false; + + return true; +} + /* Finish an expression taking the address of LABEL (an IDENTIFIER_NODE). Returns an expression for the address. @@ -5267,26 +5323,37 @@ } } -/* Check that the same argument isn't passed to restrict arguments - and other arguments. */ - -static void +/* Check that the same argument isn't passed to two or more + restrict-qualified formal and issue a -Wrestrict warning + if it is. Return true if a warning has been issued. */ + +static bool check_function_restrict (const_tree fndecl, const_tree fntype, int nargs, tree *argarray) { int i; - tree parms; + tree parms = TYPE_ARG_TYPES (fntype); if (fndecl - && TREE_CODE (fndecl) == FUNCTION_DECL - && DECL_ARGUMENTS (fndecl)) - parms = DECL_ARGUMENTS (fndecl); - else - parms = TYPE_ARG_TYPES (fntype); + && TREE_CODE (fndecl) == FUNCTION_DECL) + { + /* Avoid diagnosing calls built-ins with a zero size/bound + here. They are checked in more detail elsewhere. */ + if (fndecl_built_in_p (fndecl, BUILT_IN_NORMAL) + && nargs == 3 + && TREE_CODE (argarray[2]) == INTEGER_CST + && integer_zerop (argarray[2])) + return false; + + if (DECL_ARGUMENTS (fndecl)) + parms = DECL_ARGUMENTS (fndecl); + } for (i = 0; i < nargs; i++) TREE_VISITED (argarray[i]) = 0; + bool warned = false; + for (i = 0; i < nargs && parms && parms != void_list_node; i++) { tree type; @@ -5303,11 +5370,13 @@ if (POINTER_TYPE_P (type) && TYPE_RESTRICT (type) && !TYPE_READONLY (TREE_TYPE (type))) - warn_for_restrict (i, argarray, nargs); + warned |= warn_for_restrict (i, argarray, nargs); } for (i = 0; i < nargs; i++) TREE_VISITED (argarray[i]) = 0; + + return warned; } /* Helper for check_function_nonnull; given a list of operands which @@ -5347,10 +5416,8 @@ if (TREE_CODE (TREE_TYPE (param)) != POINTER_TYPE) return; - /* When not optimizing diagnose the simple cases of null arguments. - When optimization is enabled defer the checking until expansion - when more cases can be detected. */ - if (integer_zerop (param)) + /* Diagnose the simple cases of null arguments. */ + if (integer_zerop (fold_for_warn (param))) { warning_at (pctx->loc, OPT_Wnonnull, "null argument where non-null " "required (argument %lu)", (unsigned long) param_num); @@ -5367,7 +5434,7 @@ /* Verify the arg number is a small constant. */ if (tree_fits_uhwi_p (arg_num_expr)) { - *valp = TREE_INT_CST_LOW (arg_num_expr); + *valp = tree_to_uhwi (arg_num_expr); return true; } else @@ -5548,8 +5615,10 @@ /* Check for valid arguments being passed to a function with FNTYPE. - There are NARGS arguments in the array ARGARRAY. LOC should be used for - diagnostics. Return true if -Wnonnull warning has been diagnosed. */ + There are NARGS arguments in the array ARGARRAY. LOC should be used + for diagnostics. Return true if either -Wnonnull or -Wrestrict has + been issued. */ + bool check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype, int nargs, tree *argarray, vec<location_t> *arglocs) @@ -5572,7 +5641,7 @@ check_function_sentinel (fntype, nargs, argarray); if (warn_restrict) - check_function_restrict (fndecl, fntype, nargs, argarray); + warned_p |= check_function_restrict (fndecl, fntype, nargs, argarray); return warned_p; } @@ -5698,8 +5767,7 @@ 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) + if (!fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)) return true; switch (DECL_FUNCTION_CODE (fndecl)) @@ -5899,10 +5967,10 @@ static char * catenate_strings (const char *lhs, const char *rhs_start, int rhs_size) { - const int lhs_size = strlen (lhs); + const size_t lhs_size = strlen (lhs); char *result = XNEWVEC (char, lhs_size + rhs_size); - strncpy (result, lhs, lhs_size); - strncpy (result + lhs_size, rhs_start, rhs_size); + memcpy (result, lhs, lhs_size); + memcpy (result + lhs_size, rhs_start, rhs_size); return result; } @@ -5953,7 +6021,7 @@ else message = catenate_messages (gmsgid, " before %s'\\x%x'"); - error_at_rich_loc (richloc, message, prefix, val); + error_at (richloc, message, prefix, val); free (message); message = NULL; } @@ -5981,7 +6049,7 @@ else if (token_type == CPP_NAME) { message = catenate_messages (gmsgid, " before %qE"); - error_at_rich_loc (richloc, message, value); + error_at (richloc, message, value); free (message); message = NULL; } @@ -5994,16 +6062,16 @@ else if (token_type < N_TTYPES) { message = catenate_messages (gmsgid, " before %qs token"); - error_at_rich_loc (richloc, message, cpp_type2name (token_type, token_flags)); + error_at (richloc, message, cpp_type2name (token_type, token_flags)); free (message); message = NULL; } else - error_at_rich_loc (richloc, gmsgid); + error_at (richloc, gmsgid); if (message) { - error_at_rich_loc (richloc, message); + error_at (richloc, message); free (message); } #undef catenate_messages @@ -6013,7 +6081,7 @@ message, or 0 if none. */ static int -c_option_controlling_cpp_error (int reason) +c_option_controlling_cpp_diagnostic (enum cpp_warning_reason reason) { const struct cpp_reason_option_codes_t *entry; @@ -6025,7 +6093,7 @@ return 0; } -/* Callback from cpp_error for PFILE to print diagnostics from the +/* Callback from cpp_diagnostic for PFILE to print diagnostics from the preprocessor. The diagnostic is of type LEVEL, with REASON set to the reason code if LEVEL is represents a warning, at location RICHLOC unless this is after lexing and the compiler's location @@ -6034,9 +6102,11 @@ otherwise. */ bool -c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason, - rich_location *richloc, - const char *msg, va_list *ap) +c_cpp_diagnostic (cpp_reader *pfile ATTRIBUTE_UNUSED, + enum cpp_diagnostic_level level, + enum cpp_warning_reason reason, + rich_location *richloc, + const char *msg, va_list *ap) { diagnostic_info diagnostic; diagnostic_t dlevel; @@ -6076,11 +6146,12 @@ gcc_unreachable (); } if (done_lexing) - richloc->set_range (line_table, 0, input_location, true); + richloc->set_range (0, input_location, SHOW_RANGE_WITH_CARET); diagnostic_set_info_translated (&diagnostic, msg, ap, richloc, dlevel); - diagnostic_override_option_index (&diagnostic, - c_option_controlling_cpp_error (reason)); + diagnostic_override_option_index + (&diagnostic, + c_option_controlling_cpp_diagnostic (reason)); ret = diagnostic_report_diagnostic (global_dc, &diagnostic); if (level == CPP_DL_WARNING_SYSHDR) global_dc->dc_warn_system_headers = save_warn_system_headers; @@ -6110,10 +6181,11 @@ /* Fold an offsetof-like expression. EXPR is a nested sequence of component references with an INDIRECT_REF of a constant at the bottom; much like the - traditional rendering of offsetof as a macro. Return the folded result. */ + traditional rendering of offsetof as a macro. TYPE is the desired type of + the whole expression. Return the folded result. */ tree -fold_offsetof_1 (tree expr, enum tree_code ctx) +fold_offsetof (tree expr, tree type, enum tree_code ctx) { tree base, off, t; tree_code code = TREE_CODE (expr); @@ -6138,10 +6210,10 @@ error ("cannot apply %<offsetof%> to a non constant address"); return error_mark_node; } - return TREE_OPERAND (expr, 0); + return convert (type, TREE_OPERAND (expr, 0)); case COMPONENT_REF: - base = fold_offsetof_1 (TREE_OPERAND (expr, 0), code); + base = fold_offsetof (TREE_OPERAND (expr, 0), type, code); if (base == error_mark_node) return base; @@ -6158,7 +6230,7 @@ break; case ARRAY_REF: - base = fold_offsetof_1 (TREE_OPERAND (expr, 0), code); + base = fold_offsetof (TREE_OPERAND (expr, 0), type, code); if (base == error_mark_node) return base; @@ -6214,24 +6286,17 @@ case COMPOUND_EXPR: /* Handle static members of volatile structs. */ t = TREE_OPERAND (expr, 1); - gcc_assert (VAR_P (t)); - return fold_offsetof_1 (t); + gcc_checking_assert (VAR_P (get_base_address (t))); + return fold_offsetof (t, type); default: gcc_unreachable (); } + if (!POINTER_TYPE_P (type)) + return size_binop (PLUS_EXPR, base, convert (type, off)); return fold_build_pointer_plus (base, off); } - -/* Likewise, but convert it to the return type of offsetof. */ - -tree -fold_offsetof (tree expr) -{ - return convert (size_type_node, fold_offsetof_1 (expr)); -} - /* *PTYPE is an incomplete array. Complete it with a domain based on INITIAL_VALUE. If INITIAL_VALUE is not present, use 1 if DO_DEFAULT @@ -6376,6 +6441,28 @@ return failure; } +/* INIT is an constructor of a structure with a flexible array member. + Complete the flexible array member with a domain based on it's value. */ +void +complete_flexible_array_elts (tree init) +{ + tree elt, type; + + if (init == NULL_TREE || TREE_CODE (init) != CONSTRUCTOR) + return; + + if (vec_safe_is_empty (CONSTRUCTOR_ELTS (init))) + return; + + elt = CONSTRUCTOR_ELTS (init)->last ().value; + type = TREE_TYPE (elt); + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_SIZE (type) == NULL_TREE) + complete_array_type (&TREE_TYPE (elt), elt, false); + else + complete_flexible_array_elts (elt); +} + /* Like c_mark_addressable but don't check register qualifier. */ void c_common_mark_addressable_vec (tree t) @@ -6406,6 +6493,122 @@ return type ? type : error_mark_node; } +/* Work out the size of the first argument of a call to + __builtin_speculation_safe_value. Only pointers and integral types + are permitted. Return -1 if the argument type is not supported or + the size is too large; 0 if the argument type is a pointer or the + size if it is integral. */ +static enum built_in_function +speculation_safe_value_resolve_call (tree function, vec<tree, va_gc> *params) +{ + /* Type of the argument. */ + tree type; + int size; + + if (vec_safe_is_empty (params)) + { + error ("too few arguments to function %qE", function); + return BUILT_IN_NONE; + } + + type = TREE_TYPE ((*params)[0]); + if (TREE_CODE (type) == ARRAY_TYPE && c_dialect_cxx ()) + { + /* Force array-to-pointer decay for C++. */ + (*params)[0] = default_conversion ((*params)[0]); + type = TREE_TYPE ((*params)[0]); + } + + if (POINTER_TYPE_P (type)) + return BUILT_IN_SPECULATION_SAFE_VALUE_PTR; + + if (!INTEGRAL_TYPE_P (type)) + goto incompatible; + + if (!COMPLETE_TYPE_P (type)) + goto incompatible; + + size = tree_to_uhwi (TYPE_SIZE_UNIT (type)); + if (size == 1 || size == 2 || size == 4 || size == 8 || size == 16) + return ((enum built_in_function) + ((int) BUILT_IN_SPECULATION_SAFE_VALUE_1 + exact_log2 (size))); + + incompatible: + /* Issue the diagnostic only if the argument is valid, otherwise + it would be redundant at best and could be misleading. */ + if (type != error_mark_node) + error ("operand type %qT is incompatible with argument %d of %qE", + type, 1, function); + + return BUILT_IN_NONE; +} + +/* Validate and coerce PARAMS, the arguments to ORIG_FUNCTION to fit + the prototype for FUNCTION. The first argument is mandatory, a second + argument, if present, must be type compatible with the first. */ +static bool +speculation_safe_value_resolve_params (location_t loc, tree orig_function, + vec<tree, va_gc> *params) +{ + tree val; + + if (params->length () == 0) + { + error_at (loc, "too few arguments to function %qE", orig_function); + return false; + } + + else if (params->length () > 2) + { + error_at (loc, "too many arguments to function %qE", orig_function); + return false; + } + + val = (*params)[0]; + if (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE) + val = default_conversion (val); + if (!(TREE_CODE (TREE_TYPE (val)) == POINTER_TYPE + || TREE_CODE (TREE_TYPE (val)) == INTEGER_TYPE)) + { + error_at (loc, + "expecting argument of type pointer or of type integer " + "for argument 1"); + return false; + } + (*params)[0] = val; + + if (params->length () == 2) + { + tree val2 = (*params)[1]; + if (TREE_CODE (TREE_TYPE (val2)) == ARRAY_TYPE) + val2 = default_conversion (val2); + if (!(TREE_TYPE (val) == TREE_TYPE (val2) + || useless_type_conversion_p (TREE_TYPE (val), TREE_TYPE (val2)))) + { + error_at (loc, "both arguments must be compatible"); + return false; + } + (*params)[1] = val2; + } + + return true; +} + +/* Cast the result of the builtin back to the type of the first argument, + preserving any qualifiers that it might have. */ +static tree +speculation_safe_value_resolve_return (tree first_param, tree result) +{ + tree ptype = TREE_TYPE (first_param); + tree rtype = TREE_TYPE (result); + ptype = TYPE_MAIN_VARIANT (ptype); + + if (tree_int_cst_equal (TYPE_SIZE (ptype), TYPE_SIZE (rtype))) + return convert (ptype, result); + + return result; +} + /* A helper function for resolve_overloaded_builtin in resolving the overloaded __sync_ builtins. Returns a positive power of 2 if the first operand of PARAMS is a pointer to a supported data type. @@ -6677,24 +6880,25 @@ for (x = n_param - n_model ; x < n_param; x++) { tree p = (*params)[x]; + if (!INTEGRAL_TYPE_P (TREE_TYPE (p))) + { + error_at (loc, "non-integer memory model argument %d of %qE", x + 1, + function); + return 0; + } + p = fold_for_warn (p); if (TREE_CODE (p) == INTEGER_CST) - { - int i = tree_to_uhwi (p); - if (i < 0 || (memmodel_base (i) >= MEMMODEL_LAST)) - { - warning_at (loc, OPT_Winvalid_memory_model, - "invalid memory model argument %d of %qE", x + 1, - function); - } + { + /* memmodel_base masks the low 16 bits, thus ignore any bits above + it by using TREE_INT_CST_LOW instead of tree_to_*hwi. Those high + bits will be checked later during expansion in target specific + way. */ + if (memmodel_base (TREE_INT_CST_LOW (p)) >= MEMMODEL_LAST) + warning_at (loc, OPT_Winvalid_memory_model, + "invalid memory model argument %d of %qE", x + 1, + function); } - else - if (!INTEGRAL_TYPE_P (TREE_TYPE (p))) - { - error_at (loc, "non-integer memory model argument %d of %qE", x + 1, - function); - return 0; - } - } + } return size_0; } @@ -7059,6 +7263,54 @@ /* Handle BUILT_IN_NORMAL here. */ switch (orig_code) { + case BUILT_IN_SPECULATION_SAFE_VALUE_N: + { + tree new_function, first_param, result; + enum built_in_function fncode + = speculation_safe_value_resolve_call (function, params);; + + first_param = (*params)[0]; + if (fncode == BUILT_IN_NONE + || !speculation_safe_value_resolve_params (loc, function, params)) + return error_mark_node; + + if (targetm.have_speculation_safe_value (true)) + { + new_function = builtin_decl_explicit (fncode); + result = build_function_call_vec (loc, vNULL, new_function, params, + NULL); + + if (result == error_mark_node) + return result; + + return speculation_safe_value_resolve_return (first_param, result); + } + else + { + /* This target doesn't have, or doesn't need, active mitigation + against incorrect speculative execution. Simply return the + first parameter to the builtin. */ + if (!targetm.have_speculation_safe_value (false)) + /* The user has invoked __builtin_speculation_safe_value + even though __HAVE_SPECULATION_SAFE_VALUE is not + defined: emit a warning. */ + warning_at (input_location, 0, + "this target does not define a speculation barrier; " + "your program will still execute correctly, " + "but incorrect speculation may not be be " + "restricted"); + + /* If the optional second argument is present, handle any side + effects now. */ + if (params->length () == 2 + && TREE_SIDE_EFFECTS ((*params)[1])) + return build2 (COMPOUND_EXPR, TREE_TYPE (first_param), + (*params)[1], first_param); + + return first_param; + } + } + case BUILT_IN_ATOMIC_EXCHANGE: case BUILT_IN_ATOMIC_COMPARE_EXCHANGE: case BUILT_IN_ATOMIC_LOAD: @@ -7229,8 +7481,11 @@ enum tree_code c1 = TREE_CODE (t1), c2 = TREE_CODE (t2); - gcc_assert ((c1 == INTEGER_TYPE || c1 == REAL_TYPE || c1 == FIXED_POINT_TYPE) - && (c2 == INTEGER_TYPE || c2 == REAL_TYPE + gcc_assert ((INTEGRAL_TYPE_P (t1) + || c1 == REAL_TYPE + || c1 == FIXED_POINT_TYPE) + && (INTEGRAL_TYPE_P (t2) + || c2 == REAL_TYPE || c2 == FIXED_POINT_TYPE)); t1 = c_common_signed_type (t1); @@ -7240,7 +7495,7 @@ if (t1 == t2) return true; if (opaque && c1 == c2 - && (c1 == INTEGER_TYPE || c1 == REAL_TYPE) + && (INTEGRAL_TYPE_P (t1) || c1 == REAL_TYPE) && TYPE_PRECISION (t1) == TYPE_PRECISION (t2)) return true; return false; @@ -7576,7 +7831,6 @@ { MARK_TS_TYPED (C_MAYBE_CONST_EXPR); MARK_TS_TYPED (EXCESS_PRECISION_EXPR); - MARK_TS_TYPED (ARRAY_NOTATION_REF); } /* Build a user-defined numeric literal out of an integer constant type VALUE @@ -7610,7 +7864,7 @@ if (TREE_CODE (index) == INTEGER_CST) if (!tree_fits_uhwi_p (index) - || tree_to_uhwi (index) >= TYPE_VECTOR_SUBPARTS (type)) + || maybe_ge (tree_to_uhwi (index), TYPE_VECTOR_SUBPARTS (type))) warning_at (loc, OPT_Warray_bounds, "index value is out of bound"); /* We are building an ARRAY_REF so mark the vector as addressable @@ -7786,6 +8040,8 @@ if (TREE_CODE (expr) == ADDR_EXPR) expr = TREE_OPERAND (expr, 0); + STRIP_ANY_LOCATION_WRAPPER (expr); + if (TREE_TYPE (expr) && TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE && TREE_CODE (expr) == FUNCTION_DECL @@ -7794,7 +8050,7 @@ strlen, and for C++ operators new and delete. The c_decl_implicit() test avoids false positives for implicitly declared built-ins with library fallbacks (such as abs). */ - && DECL_BUILT_IN (expr) + && fndecl_built_in_p (expr) && DECL_IS_BUILTIN (expr) && !c_decl_implicit (expr) && !DECL_ASSEMBLER_NAME_SET_P (expr)) @@ -7818,17 +8074,20 @@ the name of the array, or NULL_TREE for unnamed arrays. */ bool -valid_array_size_p (location_t loc, tree type, tree name) +valid_array_size_p (location_t loc, tree type, tree name, bool complain) { if (type != error_mark_node && COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST && !valid_constant_size_p (TYPE_SIZE_UNIT (type))) { - if (name) - error_at (loc, "size of array %qE is too large", name); - else - error_at (loc, "size of unnamed array is too large"); + if (complain) + { + if (name) + error_at (loc, "size of array %qE is too large", name); + else + error_at (loc, "size of unnamed array is too large"); + } return false; } return true; @@ -8118,8 +8377,8 @@ location_t hint_loc = hint->get_start_loc (); location_t old_loc = richloc->get_loc (); - richloc->set_range (line_table, 0, hint_loc, true); - richloc->add_range (old_loc, false); + richloc->set_range (0, hint_loc, SHOW_RANGE_WITH_CARET); + richloc->add_range (old_loc); } } @@ -8127,12 +8386,32 @@ namespace selftest { +/* Verify that fold_for_warn on error_mark_node is safe. */ + +static void +test_fold_for_warn () +{ + ASSERT_EQ (error_mark_node, fold_for_warn (error_mark_node)); +} + +/* Run all of the selftests within this file. */ + +static void +c_common_c_tests () +{ + test_fold_for_warn (); +} + /* Run all of the tests within c-family. */ void c_family_tests (void) { + c_common_c_tests (); c_format_c_tests (); + c_indentation_c_tests (); + c_pretty_print_c_tests (); + c_spellcheck_cc_tests (); } } // namespace selftest @@ -8174,8 +8453,8 @@ const line_map_ordinary *ord_map = LINEMAPS_ORDINARY_MAP_AT (line_table, i); - const line_map_ordinary *from = INCLUDED_FROM (line_table, ord_map); - if (from) + if (const line_map_ordinary *from + = linemap_included_from_linemap (line_table, ord_map)) if (from->to_file == file) { last_include_ord_map = from; @@ -8237,10 +8516,16 @@ location. This function is idempotent: a header will be added at most once to - any given file. */ + any given file. + + If OVERRIDE_LOCATION is true, then if a fix-it is added and will be + printed, then RICHLOC's primary location will be replaced by that of + the fix-it hint (for use by "inform" notes where the location of the + issue has already been reported). */ void -maybe_add_include_fixit (rich_location *richloc, const char *header) +maybe_add_include_fixit (rich_location *richloc, const char *header, + bool override_location) { location_t loc = richloc->get_loc (); const char *file = LOCATION_FILE (loc); @@ -8268,6 +8553,118 @@ char *text = xasprintf ("#include %s\n", header); richloc->add_fixit_insert_before (include_insert_loc, text); free (text); + + if (override_location && global_dc->show_caret) + { + /* Replace the primary location with that of the insertion point for the + fix-it hint. + + We use SHOW_LINES_WITHOUT_RANGE so that we don't meaningless print a + caret for the insertion point (or colorize it). + + Hence we print e.g.: + + ../x86_64-pc-linux-gnu/libstdc++-v3/include/vector:74:1: note: msg 2 + 73 | # include <debug/vector> + +++ |+#include <vector> + 74 | #endif + + rather than: + + ../x86_64-pc-linux-gnu/libstdc++-v3/include/vector:74:1: note: msg 2 + 73 | # include <debug/vector> + +++ |+#include <vector> + 74 | #endif + | ^ + + avoiding the caret on the first column of line 74. */ + richloc->set_range (0, include_insert_loc, SHOW_LINES_WITHOUT_RANGE); + } +} + +/* Attempt to convert a braced array initializer list CTOR for array + TYPE into a STRING_CST for convenience and efficiency. Return + the converted string on success or the original ctor on failure. */ + +tree +braced_list_to_string (tree type, tree ctor) +{ + if (!tree_fits_uhwi_p (TYPE_SIZE_UNIT (type))) + return ctor; + + /* If the array has an explicit bound, use it to constrain the size + of the string. If it doesn't, be sure to create a string that's + as long as implied by the index of the last zero specified via + a designator, as in: + const char a[] = { [7] = 0 }; */ + unsigned HOST_WIDE_INT maxelts = tree_to_uhwi (TYPE_SIZE_UNIT (type)); + maxelts /= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type))); + + /* Avoid converting initializers for zero-length arrays. */ + if (!maxelts) + return ctor; + + unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (ctor); + + auto_vec<char> str; + str.reserve (nelts + 1); + + unsigned HOST_WIDE_INT i; + tree index, value; + + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), i, index, value) + { + unsigned HOST_WIDE_INT idx = i; + if (index) + { + if (!tree_fits_uhwi_p (index)) + return ctor; + idx = tree_to_uhwi (index); + } + + /* auto_vec is limited to UINT_MAX elements. */ + if (idx > UINT_MAX) + return ctor; + + /* Avoid non-constant initializers. */ + if (!tree_fits_shwi_p (value)) + return ctor; + + /* Skip over embedded nuls except the last one (initializer + elements are in ascending order of indices). */ + HOST_WIDE_INT val = tree_to_shwi (value); + if (!val && i + 1 < nelts) + continue; + + if (idx < str.length()) + return ctor; + + /* Bail if the CTOR has a block of more than 256 embedded nuls + due to implicitly initialized elements. */ + unsigned nchars = (idx - str.length ()) + 1; + if (nchars > 256) + return ctor; + + if (nchars > 1) + { + str.reserve (idx); + str.quick_grow_cleared (idx); + } + + if (idx >= maxelts) + return ctor; + + str.safe_insert (idx, val); + } + + /* Append a nul string termination. */ + if (str.length () < maxelts) + str.safe_push (0); + + /* Build a STRING_CST with the same type as the array. */ + tree res = build_string (str.length (), str.begin ()); + TREE_TYPE (res) = type; + return res; } #include "gt-c-family-c-common.h"