X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-common.c;h=30a61c2d5a59a1051f4a16e93f02979a4ad7e122;hb=b3ded9f87912f68f2ecb1d8cc15aa58111ca08d0;hp=90a373cfa661e1f318de35b6737a5ee4a69a1c2d;hpb=95c90e04ee6d5268b0897fbbbf56d5757c035838;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-common.c b/gcc/c-common.c index 90a373cfa66..30a61c2d5a5 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -131,6 +131,10 @@ cpp_reader *parse_in; /* Declared in c-pragma.h. */ tree complex_double_type_node; tree complex_long_double_type_node; + tree dfloat32_type_node; + tree dfloat64_type_node; + tree_dfloat128_type_node; + tree intQI_type_node; tree intHI_type_node; tree intSI_type_node; @@ -340,7 +344,7 @@ int flag_gen_declaration; int print_struct_values; -/* ???. Undocumented. */ +/* Tells the compiler what is the constant string class for Objc. */ const char *constant_string_class_name; @@ -520,6 +524,7 @@ static tree handle_section_attribute (tree *, tree, tree, int, bool *); static tree handle_aligned_attribute (tree *, tree, tree, int, bool *); static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ; static tree handle_alias_attribute (tree *, tree, tree, int, bool *); +static tree handle_weakref_attribute (tree *, tree, tree, int, bool *) ; static tree handle_visibility_attribute (tree *, tree, tree, int, bool *); static tree handle_tls_model_attribute (tree *, tree, tree, int, @@ -599,6 +604,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_weak_attribute }, { "alias", 1, 1, true, false, false, handle_alias_attribute }, + { "weakref", 0, 1, true, false, false, + handle_weakref_attribute }, { "no_instrument_function", 0, 0, true, false, false, handle_no_instrument_function_attribute }, { "malloc", 0, 0, true, false, false, @@ -695,7 +702,7 @@ finish_fname_decls (void) if (TREE_CODE (*bodyp) == BIND_EXPR) bodyp = &BIND_EXPR_BODY (*bodyp); - append_to_statement_list (*bodyp, &stmts); + append_to_statement_list_force (*bodyp, &stmts); *bodyp = stmts; } @@ -951,6 +958,42 @@ unsigned_conversion_warning (tree result, tree operand) } } +/* Print a warning about casts that might indicate violation + of strict aliasing rules if -Wstrict-aliasing is used and + strict aliasing mode is in effect. otype is the original + TREE_TYPE of expr, and type the type we're casting to. */ + +void +strict_aliasing_warning(tree otype, tree type, tree expr) +{ + if (flag_strict_aliasing && warn_strict_aliasing + && POINTER_TYPE_P (type) && POINTER_TYPE_P (otype) + && TREE_CODE (expr) == ADDR_EXPR + && (DECL_P (TREE_OPERAND (expr, 0)) + || handled_component_p (TREE_OPERAND (expr, 0))) + && !VOID_TYPE_P (TREE_TYPE (type))) + { + /* Casting the address of an object to non void pointer. Warn + if the cast breaks type based aliasing. */ + if (!COMPLETE_TYPE_P (TREE_TYPE (type))) + warning (OPT_Wstrict_aliasing, "type-punning to incomplete type " + "might break strict-aliasing rules"); + else + { + HOST_WIDE_INT set1 = get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0))); + HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type)); + + if (!alias_sets_conflict_p (set1, set2)) + warning (OPT_Wstrict_aliasing, "dereferencing type-punned " + "pointer will break strict-aliasing rules"); + else if (warn_strict_aliasing > 1 + && !alias_sets_might_conflict_p (set1, set2)) + warning (OPT_Wstrict_aliasing, "dereferencing type-punned " + "pointer might break strict-aliasing rules"); + } + } +} + /* Nonzero if constant C has a value that is permissible for type TYPE (an INTEGER_TYPE). */ @@ -972,6 +1015,8 @@ vector_types_convertible_p (tree t1, tree t2) return targetm.vector_opaque_p (t1) || targetm.vector_opaque_p (t2) || (tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2)) + && (TREE_CODE (TREE_TYPE (t1)) != REAL_TYPE || + TYPE_PRECISION (t1) == TYPE_PRECISION (t2)) && INTEGRAL_TYPE_P (TREE_TYPE (t1)) == INTEGRAL_TYPE_P (TREE_TYPE (t2))); } @@ -1645,6 +1690,13 @@ c_common_type_for_mode (enum machine_mode mode, int unsignedp) return build_vector_type_for_mode (inner_type, mode); } + if (mode == TYPE_MODE (dfloat32_type_node)) + return dfloat32_type_node; + if (mode == TYPE_MODE (dfloat64_type_node)) + return dfloat64_type_node; + if (mode == TYPE_MODE (dfloat128_type_node)) + return dfloat128_type_node; + for (t = registered_builtin_types; t; t = TREE_CHAIN (t)) if (TYPE_MODE (TREE_VALUE (t)) == mode) return TREE_VALUE (t); @@ -1821,8 +1873,7 @@ min_precision (tree value, int unsignedp) } /* Print an error message for invalid operands to arith operation - CODE. NOP_EXPR is used as a special case (see - c_common_truthvalue_conversion). */ + CODE. */ void binary_op_error (enum tree_code code) @@ -1831,10 +1882,6 @@ binary_op_error (enum tree_code code) switch (code) { - case NOP_EXPR: - error ("invalid truth-value expression"); - return; - case PLUS_EXPR: opname = "+"; break; case MINUS_EXPR: @@ -2132,6 +2179,14 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr, in the type of the operand that is not constant. TYPE is already properly set. */ } + + /* If either arg is decimal float and the other is float, find the + proper common type to use for comparison. */ + else if (real1 && real2 + && (DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop0))) + || DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop1))))) + type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1)); + else if (real1 && real2 && (TYPE_PRECISION (TREE_TYPE (primop0)) == TYPE_PRECISION (TREE_TYPE (primop1)))) @@ -2371,12 +2426,12 @@ c_common_truthvalue_conversion (tree expr) case ADDR_EXPR: { - if (TREE_CODE (TREE_OPERAND (expr, 0)) == FUNCTION_DECL + if (DECL_P (TREE_OPERAND (expr, 0)) && !DECL_WEAK (TREE_OPERAND (expr, 0))) { /* Common Ada/Pascal programmer's mistake. We always warn about this since it is so bad. */ - warning (0, "the address of %qD, will always evaluate as %", + warning (OPT_Walways_true, "the address of %qD, will always evaluate as %", TREE_OPERAND (expr, 0)); return truthvalue_true_node; } @@ -2426,13 +2481,12 @@ c_common_truthvalue_conversion (tree expr) c_common_truthvalue_conversion (TREE_OPERAND (expr, 2))); case CONVERT_EXPR: + case NOP_EXPR: /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE, since that affects how `default_conversion' will behave. */ if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE) break; - /* Fall through.... */ - case NOP_EXPR: /* If this is widening the argument, we can ignore it. */ if (TYPE_PRECISION (TREE_TYPE (expr)) >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0)))) @@ -2494,12 +2548,12 @@ c_common_truthvalue_conversion (tree expr) return build_binary_op (NE_EXPR, expr, integer_zero_node, 1); } -static tree builtin_function_2 (const char *builtin_name, const char *name, - tree builtin_type, tree type, - enum built_in_function function_code, - enum built_in_class cl, int library_name_p, - bool nonansi_p, - tree attrs); +static void def_builtin_1 (enum built_in_function fncode, + const char *name, + enum built_in_class fnclass, + tree fntype, tree libtype, + bool both_p, bool fallback_p, bool nonansi_p, + tree fnattrs, bool implicit_p); /* Make a variant type in the proper way for C/C++, propagating qualifiers down to the element type of an array. */ @@ -2832,7 +2886,7 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain) TYPE_IS_SIZETYPE means that certain things (like overflow) will never happen. However, this node should really have type `size_t', which is just a typedef for an ordinary integer type. */ - value = fold_build1 (NOP_EXPR, size_type_node, value); + value = fold_convert (size_type_node, value); gcc_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value))); return value; @@ -2867,7 +2921,7 @@ c_alignof_expr (tree expr) tree best = t; int bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t))); - while (TREE_CODE (t) == NOP_EXPR + while ((TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR) && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE) { int thisalign; @@ -2882,7 +2936,7 @@ c_alignof_expr (tree expr) else return c_alignof (TREE_TYPE (expr)); - return fold_build1 (NOP_EXPR, size_type_node, t); + return fold_convert (size_type_node, t); } /* Handle C and C++ default attributes. */ @@ -2951,7 +3005,7 @@ c_common_nodes_and_builtins (void) typedef enum builtin_type builtin_type; - tree builtin_types[(int) BT_LAST]; + tree builtin_types[(int) BT_LAST + 1]; int wchar_type_size; tree array_domain_type; tree va_list_ref_type_node; @@ -3049,6 +3103,17 @@ c_common_nodes_and_builtins (void) record_builtin_type (RID_DOUBLE, NULL, double_type_node); record_builtin_type (RID_MAX, "long double", long_double_type_node); + /* Only supported decimal floating point extension if the target + actually supports underlying modes. */ + if (targetm.scalar_mode_supported_p (SDmode) + && targetm.scalar_mode_supported_p (DDmode) + && targetm.scalar_mode_supported_p (TDmode)) + { + record_builtin_type (RID_DFLOAT32, NULL, dfloat32_type_node); + record_builtin_type (RID_DFLOAT64, NULL, dfloat64_type_node); + record_builtin_type (RID_DFLOAT128, NULL, dfloat128_type_node); + } + lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"), complex_integer_type_node)); @@ -3311,42 +3376,18 @@ c_common_nodes_and_builtins (void) #undef DEF_FUNCTION_TYPE_VAR_4 #undef DEF_FUNCTION_TYPE_VAR_5 #undef DEF_POINTER_TYPE + builtin_types[(int) BT_LAST] = NULL_TREE; c_init_attributes (); #define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P, \ NONANSI_P, ATTRS, IMPLICIT, COND) \ if (NAME && COND) \ - { \ - tree decl; \ - \ - gcc_assert ((!BOTH_P && !FALLBACK_P) \ - || !strncmp (NAME, "__builtin_", \ - strlen ("__builtin_"))); \ - \ - if (!BOTH_P) \ - decl = lang_hooks.builtin_function (NAME, builtin_types[TYPE], \ - ENUM, \ - CLASS, \ - (FALLBACK_P \ - ? (NAME + strlen ("__builtin_")) \ - : NULL), \ - built_in_attributes[(int) ATTRS]); \ - else \ - decl = builtin_function_2 (NAME, \ - NAME + strlen ("__builtin_"), \ - builtin_types[TYPE], \ - builtin_types[LIBTYPE], \ - ENUM, \ - CLASS, \ - FALLBACK_P, \ - NONANSI_P, \ - built_in_attributes[(int) ATTRS]); \ - \ - built_in_decls[(int) ENUM] = decl; \ - if (IMPLICIT) \ - implicit_built_in_decls[(int) ENUM] = decl; \ - } + def_builtin_1 (ENUM, NAME, CLASS, \ + builtin_types[(int) TYPE], \ + builtin_types[(int) LIBTYPE], \ + BOTH_P, FALLBACK_P, NONANSI_P, \ + built_in_attributes[(int) ATTRS], IMPLICIT); #include "builtins.def" #undef DEF_BUILTIN @@ -3436,42 +3477,39 @@ builtin_function_disabled_p (const char *name) } -/* Possibly define a builtin function with one or two names. BUILTIN_NAME - is an __builtin_-prefixed name; NAME is the ordinary name; one or both - of these may be NULL (though both being NULL is useless). - BUILTIN_TYPE is the type of the __builtin_-prefixed function; - TYPE is the type of the function with the ordinary name. These - may differ if the ordinary name is declared with a looser type to avoid - conflicts with headers. FUNCTION_CODE and CL are as for - builtin_function. If LIBRARY_NAME_P is nonzero, NAME is passed as - the LIBRARY_NAME parameter to builtin_function when declaring BUILTIN_NAME. - If NONANSI_P is true, the name NAME is treated as a non-ANSI name; - ATTRS is the tree list representing the builtin's function attributes. - Returns the declaration of BUILTIN_NAME, if any, otherwise - the declaration of NAME. Does not declare NAME if flag_no_builtin, - or if NONANSI_P and flag_no_nonansi_builtin. */ +/* Worker for DEF_BUILTIN. + Possibly define a builtin function with one or two names. + Does not declare a non-__builtin_ function if flag_no_builtin, or if + nonansi_p and flag_no_nonansi_builtin. */ -static tree -builtin_function_2 (const char *builtin_name, const char *name, - tree builtin_type, tree type, - enum built_in_function function_code, - enum built_in_class cl, int library_name_p, - bool nonansi_p, tree attrs) +static void +def_builtin_1 (enum built_in_function fncode, + const char *name, + enum built_in_class fnclass, + tree fntype, tree libtype, + bool both_p, bool fallback_p, bool nonansi_p, + tree fnattrs, bool implicit_p) { - tree bdecl = NULL_TREE; - tree decl = NULL_TREE; - - if (builtin_name != 0) - bdecl = lang_hooks.builtin_function (builtin_name, builtin_type, - function_code, cl, - library_name_p ? name : NULL, attrs); - - if (name != 0 && !flag_no_builtin && !builtin_function_disabled_p (name) + tree decl; + const char *libname; + + gcc_assert ((!both_p && !fallback_p) + || !strncmp (name, "__builtin_", + strlen ("__builtin_"))); + + libname = name + strlen ("__builtin_"); + decl = lang_hooks.builtin_function (name, fntype, fncode, fnclass, + (fallback_p ? libname : NULL), + fnattrs); + if (both_p + && !flag_no_builtin && !builtin_function_disabled_p (libname) && !(nonansi_p && flag_no_nonansi_builtin)) - decl = lang_hooks.builtin_function (name, type, function_code, cl, - NULL, attrs); + lang_hooks.builtin_function (libname, libtype, fncode, fnclass, + NULL, fnattrs); - return (bdecl != 0 ? bdecl : decl); + built_in_decls[(int) fncode] = decl; + if (implicit_p) + implicit_built_in_decls[(int) fncode] = decl; } /* Nonzero if the type T promotes to int. This is (nearly) the @@ -3613,25 +3651,27 @@ c_add_case_label (splay_tree cases, tree cond, tree orig_type, { low_value = check_case_value (low_value); low_value = convert_and_check (type, low_value); + if (low_value == error_mark_node) + goto error_out; } if (high_value) { high_value = check_case_value (high_value); high_value = convert_and_check (type, high_value); + if (high_value == error_mark_node) + goto error_out; } - /* If an error has occurred, bail out now. */ - if (low_value == error_mark_node || high_value == error_mark_node) - goto error_out; - - /* If the LOW_VALUE and HIGH_VALUE are the same, then this isn't - really a case range, even though it was written that way. Remove - the HIGH_VALUE to simplify later processing. */ - if (tree_int_cst_equal (low_value, high_value)) - high_value = NULL_TREE; - if (low_value && high_value - && !tree_int_cst_lt (low_value, high_value)) - warning (0, "empty range specified"); + if (low_value && high_value) + { + /* If the LOW_VALUE and HIGH_VALUE are the same, then this isn't + really a case range, even though it was written that way. + Remove the HIGH_VALUE to simplify later processing. */ + if (tree_int_cst_equal (low_value, high_value)) + high_value = NULL_TREE; + else if (!tree_int_cst_lt (low_value, high_value)) + warning (0, "empty range specified"); + } /* See if the case is in range of the type of the original testing expression. If both low_value and high_value are out of range, @@ -3832,7 +3872,32 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location, { splay_tree_node node = splay_tree_lookup (cases, (splay_tree_key) TREE_VALUE (chain)); - + if (!node) + { + tree low_value = TREE_VALUE (chain); + splay_tree_node low_bound; + splay_tree_node high_bound; + /* Even though there wasn't an exact match, there might be a + case range which includes the enumator's value. */ + low_bound = splay_tree_predecessor (cases, + (splay_tree_key) low_value); + high_bound = splay_tree_successor (cases, + (splay_tree_key) low_value); + + /* It is smaller than the LOW_VALUE, so there is no need to check + unless the LOW_BOUND is in fact itself a case range. */ + if (low_bound + && CASE_HIGH ((tree) low_bound->value) + && tree_int_cst_compare (CASE_HIGH ((tree) low_bound->value), + low_value) >= 0) + node = low_bound; + /* The low end of that range is bigger than the current value. */ + else if (high_bound + && (tree_int_cst_compare ((tree) high_bound->key, + low_value) + <= 0)) + node = high_bound; + } if (node) { /* Mark the CASE_LOW part of the case entry as seen, so @@ -4024,17 +4089,23 @@ handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args), struct Foo { struct Foo const *ptr; // creates a variant w/o packed flag - } __ attribute__((packed)); // packs it now. - */ + } __ attribute__((packed)); // packs it now. + */ tree probe; for (probe = *node; probe; probe = TYPE_NEXT_VARIANT (probe)) TYPE_PACKED (probe) = 1; } - } else if (TREE_CODE (*node) == FIELD_DECL) - DECL_PACKED (*node) = 1; + { + if (TYPE_ALIGN (TREE_TYPE (*node)) <= BITS_PER_UNIT) + warning (OPT_Wattributes, + "%qE attribute ignored for field of type %qT", + name, TREE_TYPE (*node)); + else + DECL_PACKED (*node) = 1; + } /* We can't set DECL_PACKED for a VAR_DECL, because the bit is used for DECL_REGISTER. It wouldn't mean anything anyway. We can't set DECL_PACKED on the type of a TYPE_DECL, because @@ -4309,39 +4380,43 @@ handle_transparent_union_attribute (tree *node, tree name, tree ARG_UNUSED (args), int flags, bool *no_add_attrs) { - tree decl = NULL_TREE; - tree *type = NULL; - int is_type = 0; + tree type = NULL; + + *no_add_attrs = true; if (DECL_P (*node)) { - decl = *node; - type = &TREE_TYPE (decl); - is_type = TREE_CODE (*node) == TYPE_DECL; + if (TREE_CODE (*node) != TYPE_DECL) + goto ignored; + node = &TREE_TYPE (*node); + type = *node; } else if (TYPE_P (*node)) - type = node, is_type = 1; + type = *node; + else + goto ignored; - if (is_type - && TREE_CODE (*type) == UNION_TYPE - && (decl == 0 - || (TYPE_FIELDS (*type) != 0 - && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type))))) + if (TREE_CODE (type) == UNION_TYPE) { + /* When IN_PLACE is set, leave the check for FIELDS and MODE to + the code in finish_struct. */ if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) - *type = build_variant_type_copy (*type); - TYPE_TRANSPARENT_UNION (*type) = 1; - } - else if (decl != 0 && TREE_CODE (decl) == PARM_DECL - && TREE_CODE (*type) == UNION_TYPE - && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type))) - DECL_TRANSPARENT_UNION (decl) = 1; - else - { - warning (OPT_Wattributes, "%qE attribute ignored", name); - *no_add_attrs = true; + { + if (TYPE_FIELDS (type) == NULL_TREE + || TYPE_MODE (type) != DECL_MODE (TYPE_FIELDS (type))) + goto ignored; + + /* A type variant isn't good enough, since we don't a cast + to such a type removed as a no-op. */ + *node = type = build_duplicate_type (type); + } + + TYPE_TRANSPARENT_UNION (type) = 1; + return NULL_TREE; } + ignored: + warning (OPT_Wattributes, "%qE attribute ignored", name); return NULL_TREE; } @@ -4461,6 +4536,7 @@ handle_mode_attribute (tree *node, tree name, tree args, case MODE_INT: case MODE_PARTIAL_INT: case MODE_FLOAT: + case MODE_DECIMAL_FLOAT: valid_mode = targetm.scalar_mode_supported_p (mode); break; @@ -4522,21 +4598,24 @@ handle_mode_attribute (tree *node, tree name, tree args, return NULL_TREE; } - if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) - type = build_variant_type_copy (type); - - /* We cannot use layout_type here, because that will attempt - to re-layout all variants, corrupting our original. */ - TYPE_PRECISION (type) = TYPE_PRECISION (typefm); - TYPE_MIN_VALUE (type) = TYPE_MIN_VALUE (typefm); - TYPE_MAX_VALUE (type) = TYPE_MAX_VALUE (typefm); - TYPE_SIZE (type) = TYPE_SIZE (typefm); - TYPE_SIZE_UNIT (type) = TYPE_SIZE_UNIT (typefm); - TYPE_MODE (type) = TYPE_MODE (typefm); - if (!TYPE_USER_ALIGN (type)) - TYPE_ALIGN (type) = TYPE_ALIGN (typefm); - - typefm = type; + if (flags & ATTR_FLAG_TYPE_IN_PLACE) + { + TYPE_PRECISION (type) = TYPE_PRECISION (typefm); + typefm = type; + } + else + { + /* We cannot build a type variant, as there's code that assumes + that TYPE_MAIN_VARIANT has the same mode. This includes the + debug generators. Instead, create a subrange type. This + results in all of the enumeral values being emitted only once + in the original, and the subtype gets them by reference. */ + if (TYPE_UNSIGNED (type)) + typefm = make_unsigned_type (TYPE_PRECISION (typefm)); + else + typefm = make_signed_type (TYPE_PRECISION (typefm)); + TREE_TYPE (typefm) = type; + } } else if (VECTOR_MODE_P (mode) ? TREE_CODE (type) != TREE_CODE (TREE_TYPE (typefm)) @@ -4703,7 +4782,12 @@ handle_alias_attribute (tree *node, tree name, tree args, tree decl = *node; if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl)) - || (TREE_CODE (decl) != FUNCTION_DECL && !DECL_EXTERNAL (decl))) + || (TREE_CODE (decl) != FUNCTION_DECL + && TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl)) + /* A static variable declaration is always a tentative definition, + but the alias is a non-tentative definition which overrides. */ + || (TREE_CODE (decl) != FUNCTION_DECL + && ! TREE_PUBLIC (decl) && DECL_INITIAL (decl))) { error ("%q+D defined both normally and as an alias", decl); *no_add_attrs = true; @@ -4733,7 +4817,10 @@ handle_alias_attribute (tree *node, tree name, tree args, DECL_INITIAL (decl) = error_mark_node; else { - DECL_EXTERNAL (decl) = 0; + if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))) + DECL_EXTERNAL (decl) = 1; + else + DECL_EXTERNAL (decl) = 0; TREE_STATIC (decl) = 1; } } @@ -4746,6 +4833,43 @@ handle_alias_attribute (tree *node, tree name, tree args, return NULL_TREE; } +/* Handle a "weakref" attribute; arguments as in struct + attribute_spec.handler. */ + +static tree +handle_weakref_attribute (tree *node, tree ARG_UNUSED (name), tree args, + int flags, bool *no_add_attrs) +{ + tree attr = NULL_TREE; + + /* The idea here is that `weakref("name")' mutates into `weakref, + alias("name")', and weakref without arguments, in turn, + implicitly adds weak. */ + + if (args) + { + attr = tree_cons (get_identifier ("alias"), args, attr); + attr = tree_cons (get_identifier ("weakref"), NULL_TREE, attr); + + *no_add_attrs = true; + + decl_attributes (node, attr, flags); + } + else + { + if (lookup_attribute ("alias", DECL_ATTRIBUTES (*node))) + error ("%Jweakref attribute must appear before alias attribute", + *node); + + /* Can't call declare_weak because it wants this to be TREE_PUBLIC, + and that isn't supported; and because it wants to add it to + the list of weak decls, which isn't helpful. */ + DECL_WEAK (*node) = 1; + } + + return NULL_TREE; +} + /* Handle an "visibility" attribute; arguments as in struct attribute_spec.handler. */ @@ -5115,7 +5239,7 @@ handle_vector_size_attribute (tree *node, tree name, tree args, orig_mode = TYPE_MODE (type); if (TREE_CODE (type) == RECORD_TYPE - || (GET_MODE_CLASS (orig_mode) != MODE_FLOAT + || (!SCALAR_FLOAT_MODE_P (orig_mode) && GET_MODE_CLASS (orig_mode) != MODE_INT) || !host_integerp (TYPE_SIZE_UNIT (type), 1)) { @@ -5259,7 +5383,8 @@ check_function_sentinel (tree attrs, tree params, tree typelist) } if (typelist || !params) - warning (0, "not enough variable arguments to fit a sentinel"); + warning (OPT_Wformat, + "not enough variable arguments to fit a sentinel"); else { tree sentinel, end; @@ -5281,7 +5406,8 @@ check_function_sentinel (tree attrs, tree params, tree typelist) } if (pos > 0) { - warning (0, "not enough variable arguments to fit a sentinel"); + warning (OPT_Wformat, + "not enough variable arguments to fit a sentinel"); return; } @@ -5302,7 +5428,7 @@ check_function_sentinel (tree attrs, tree params, tree typelist) We warn with -Wstrict-null-sentinel, though. */ && (warn_strict_null_sentinel || null_node != TREE_VALUE (sentinel))) - warning (0, "missing sentinel in function call"); + warning (OPT_Wformat, "missing sentinel in function call"); } } } @@ -5344,8 +5470,8 @@ check_nonnull_arg (void * ARG_UNUSED (ctx), tree param, return; if (integer_zerop (param)) - warning (0, "null argument where non-null required (argument %lu)", - (unsigned long) param_num); + warning (OPT_Wnonnull, "null argument where non-null required " + "(argument %lu)", (unsigned long) param_num); } /* Helper for nonnull attribute handling; fetch the operand number @@ -5521,7 +5647,9 @@ check_function_arguments_recurse (void (*callback) void *ctx, tree param, unsigned HOST_WIDE_INT param_num) { - if (TREE_CODE (param) == NOP_EXPR) + if ((TREE_CODE (param) == NOP_EXPR || TREE_CODE (param) == CONVERT_EXPR) + && (TYPE_PRECISION (TREE_TYPE (param)) + == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (param, 0))))) { /* Strip coercion. */ check_function_arguments_recurse (callback, ctx, @@ -5897,19 +6025,19 @@ lvalue_error (enum lvalue_use use) switch (use) { case lv_assign: - error ("invalid lvalue in assignment"); + error ("lvalue required as left operand of assignment"); break; case lv_increment: - error ("invalid lvalue in increment"); + error ("lvalue required as increment operand"); break; case lv_decrement: - error ("invalid lvalue in decrement"); + error ("lvalue required as decrement operand"); break; case lv_addressof: - error ("invalid lvalue in unary %<&%>"); + error ("lvalue required as unary %<&%> operand"); break; case lv_asm: - error ("invalid lvalue in asm statement"); + error ("lvalue required in asm statement"); break; default: gcc_unreachable (); @@ -5938,9 +6066,9 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default) } else if (TREE_CODE (initial_value) == CONSTRUCTOR) { - tree elts = CONSTRUCTOR_ELTS (initial_value); + VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initial_value); - if (elts == NULL) + if (VEC_empty (constructor_elt, v)) { if (pedantic) failure = 3; @@ -5949,15 +6077,21 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default) else { tree curindex; + unsigned HOST_WIDE_INT cnt; + constructor_elt *ce; - if (TREE_PURPOSE (elts)) - maxindex = fold_convert (sizetype, TREE_PURPOSE (elts)); + if (VEC_index (constructor_elt, v, 0)->index) + maxindex = fold_convert (sizetype, + VEC_index (constructor_elt, + v, 0)->index); curindex = maxindex; - for (elts = TREE_CHAIN (elts); elts; elts = TREE_CHAIN (elts)) + for (cnt = 1; + VEC_iterate (constructor_elt, v, cnt, ce); + cnt++) { - if (TREE_PURPOSE (elts)) - curindex = fold_convert (sizetype, TREE_PURPOSE (elts)); + if (ce->index) + curindex = fold_convert (sizetype, ce->index); else curindex = size_binop (PLUS_EXPR, curindex, size_one_node); @@ -6113,6 +6247,7 @@ static tree sync_resolve_return (tree params, tree result) { tree ptype = TREE_TYPE (TREE_TYPE (TREE_VALUE (params))); + ptype = TYPE_MAIN_VARIANT (ptype); return convert (ptype, result); } @@ -6200,4 +6335,46 @@ same_scalar_type_ignoring_signedness (tree t1, tree t2) == lang_hooks.types.signed_type (t2); } +/* Check for missing format attributes on function pointers. LTYPE is + the new type or left-hand side type. RTYPE is the old type or + right-hand side type. Returns TRUE if LTYPE is missing the desired + attribute. */ + +bool +check_missing_format_attribute (tree ltype, tree rtype) +{ + tree const ttr = TREE_TYPE (rtype), ttl = TREE_TYPE (ltype); + tree ra; + + for (ra = TYPE_ATTRIBUTES (ttr); ra; ra = TREE_CHAIN (ra)) + if (is_attribute_p ("format", TREE_PURPOSE (ra))) + break; + if (ra) + { + tree la; + for (la = TYPE_ATTRIBUTES (ttl); la; la = TREE_CHAIN (la)) + if (is_attribute_p ("format", TREE_PURPOSE (la))) + break; + return !la; + } + else + return false; +} + +/* Subscripting with type char is likely to lose on a machine where + chars are signed. So warn on any machine, but optionally. Don't + warn for unsigned char since that type is safe. Don't warn for + signed char because anyone who uses that must have done so + deliberately. Furthermore, we reduce the false positive load by + warning only for non-constant value of type char. */ + +void +warn_array_subscript_with_type_char (tree index) +{ + if (TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node + && TREE_CODE (index) != INTEGER_CST) + warning (OPT_Wchar_subscripts, "array subscript has type %"); +} + + #include "gt-c-common.h"