X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-common.c;h=4c0ce271077cc5323907c8c7fb21a4c7ac9e2e9f;hb=a11012593e4f48eab77adfd4cbd3761edd630755;hp=b4151faf7657c5dcf842a1bfcb499042a7ca333a;hpb=5bfb07427003f7499c419f401416232ade150501;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-common.c b/gcc/c-common.c index b4151faf765..4c0ce271077 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -1,6 +1,6 @@ /* Subroutines shared by all languages that are variants of C. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003 Free Software Foundation, Inc. + 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GCC. @@ -346,7 +346,25 @@ int warn_format_nonliteral; int warn_format_security; - +/* Zero means that faster, ...NonNil variants of objc_msgSend... + calls will be used in ObjC; passing nil receivers to such calls + will most likely result in crashes. */ +int flag_nil_receivers = 1; + +/* Nonzero means that we will allow new ObjC exception syntax (@throw, + @try, etc.) in source code. */ +int flag_objc_exceptions = 0; + +/* Nonzero means that code generation will be altered to support + "zero-link" execution. This currently affects ObjC only, but may + affect other languages in the future. */ +int flag_zero_link = 0; + +/* Nonzero means emit an '__OBJC, __image_info' for the current translation + unit. It will inform the ObjC runtime that class definition(s) herein + contained are to replace one(s) previously loaded. */ +int flag_replace_objc_classes = 0; + /* C/ObjC language option variables. */ @@ -368,7 +386,7 @@ int flag_isoc94; int flag_isoc99; -/* Nonzero means that we have builtin functions, and main is an int */ +/* Nonzero means that we have builtin functions, and main is an int. */ int flag_hosted = 1; @@ -429,6 +447,10 @@ int warn_implicit_int; int warn_nonnull; +/* Warn about old-style parameter declaration. */ + +int warn_old_style_definition; + /* ObjC language option variables. */ @@ -488,17 +510,6 @@ int flag_no_gnu_keywords; int flag_implement_inlines = 1; -/* Nonzero means do emit exported implementations of templates, instead of - multiple static copies in each file that needs a definition. */ - -int flag_external_templates; - -/* Nonzero means that the decision to emit or not emit the implementation of a - template depends on where the template is instantiated, rather than where - it is defined. */ - -int flag_alt_external_templates; - /* Nonzero means that implicit instantiations will be emitted if needed. */ int flag_implicit_templates = 1; @@ -588,21 +599,6 @@ int flag_permissive; int flag_enforce_eh_specs = 1; -/* The version of the C++ ABI in use. The following values are - allowed: - - 0: The version of the ABI believed most conformant with the - C++ ABI specification. This ABI may change as bugs are - discovered and fixed. Therefore, 0 will not necessarily - indicate the same ABI in different versions of G++. - - 1: The version of the ABI first used in G++ 3.2. - - Additional positive integers will be assigned as new versions of - the ABI become the default version of the ABI. */ - -int flag_abi_version = 1; - /* Nonzero means warn about things that will change when compiling with an ABI-compliant compiler. */ @@ -769,7 +765,8 @@ static tree handle_vector_size_attribute (tree *, tree, tree, int, static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *); static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *); static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *); -static tree vector_size_helper (tree, tree); +static tree handle_warn_unused_result_attribute (tree *, tree, tree, int, + bool *); static void check_function_nonnull (tree, tree); static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT); @@ -846,6 +843,8 @@ const struct attribute_spec c_common_attribute_table[] = { "may_alias", 0, 0, false, true, false, NULL }, { "cleanup", 1, 1, true, false, false, handle_cleanup_attribute }, + { "warn_unused_result", 0, 0, false, true, true, + handle_warn_unused_result_attribute }, { NULL, 0, 0, false, false, false, NULL } }; @@ -1036,7 +1035,13 @@ finish_fname_decls (void) tree *p = &DECL_SAVED_TREE (current_function_decl); /* Skip the dummy EXPR_STMT and any EH_SPEC_BLOCK. */ while (TREE_CODE (*p) != COMPOUND_STMT) - p = &TREE_CHAIN (*p); + { + if (TREE_CODE (*p) == EXPR_STMT) + p = &TREE_CHAIN (*p); + else + p = &TREE_OPERAND(*p, 0); + } + p = &COMPOUND_BODY (*p); if (TREE_CODE (*p) == SCOPE_STMT) p = &TREE_CHAIN (*p); @@ -1071,16 +1076,18 @@ finish_fname_decls (void) const char * fname_as_string (int pretty_p) { - const char *name = NULL; - - if (pretty_p) - name = (current_function_decl - ? (*lang_hooks.decl_printable_name) (current_function_decl, 2) - : "top level"); - else if (current_function_decl && DECL_NAME (current_function_decl)) - name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl)); - else - name = ""; + const char *name = "top level"; + int vrb = 2; + + if (! pretty_p) + { + name = ""; + vrb = 0; + } + + if (current_function_decl) + name = (*lang_hooks.decl_printable_name) (current_function_decl, vrb); + return name; } @@ -1130,8 +1137,7 @@ fname_decl (unsigned int rid, tree id) input_line = saved_lineno; } if (!ix && !current_function_decl) - pedwarn ("%H'%D' is not defined outside of function scope", - &DECL_SOURCE_LOCATION (decl), decl); + pedwarn ("%J'%D' is not defined outside of function scope", decl, decl); return decl; } @@ -1158,7 +1164,7 @@ fix_string_type (tree value) -Wwrite-strings says make the string constant an array of const char so that copying it to a non-const pointer will get a warning. For C++, this is the standard behavior. */ - if (flag_const_strings && ! flag_writable_strings) + if (flag_const_strings) { tree elements = build_type_variant (wide_flag ? wchar_type_node : char_type_node, @@ -1173,7 +1179,7 @@ fix_string_type (tree value) build_index_type (build_int_2 (nchars - 1, 0))); TREE_CONSTANT (value) = 1; - TREE_READONLY (value) = ! flag_writable_strings; + TREE_READONLY (value) = 1; TREE_STATIC (value) = 1; return value; } @@ -1801,6 +1807,10 @@ c_common_type_for_size (unsigned int bits, int unsignedp) return 0; } +/* Used for communication between c_common_type_for_mode and + c_register_builtin_type. */ +static GTY(()) tree registered_builtin_types; + /* Return a data type that has machine mode MODE. If the mode is an integer, then UNSIGNEDP selects between signed and unsigned types. */ @@ -1808,6 +1818,8 @@ c_common_type_for_size (unsigned int bits, int unsignedp) tree c_common_type_for_mode (enum machine_mode mode, int unsignedp) { + tree t; + if (mode == TYPE_MODE (integer_type_node)) return unsignedp ? unsigned_type_node : integer_type_node; @@ -1853,6 +1865,9 @@ c_common_type_for_mode (enum machine_mode mode, int unsignedp) if (mode == TYPE_MODE (long_double_type_node)) return long_double_type_node; + if (mode == TYPE_MODE (void_type_node)) + return void_type_node; + if (mode == TYPE_MODE (build_pointer_type (char_type_node))) return unsignedp ? make_unsigned_type (mode) : make_signed_type (mode); @@ -1893,6 +1908,10 @@ c_common_type_for_mode (enum machine_mode mode, int unsignedp) break; } + for (t = registered_builtin_types; t; t = TREE_CHAIN (t)) + if (TYPE_MODE (TREE_VALUE (t)) == mode) + return TREE_VALUE (t); + return 0; } @@ -1973,36 +1992,58 @@ c_common_signed_or_unsigned_type (int unsignedp, tree type) || TREE_UNSIGNED (type) == unsignedp) return type; - if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node)) + /* Must check the mode of the types, not the precision. Enumeral types + in C++ have precision set to match their range, but may use a wider + mode to match an ABI. If we change modes, we may wind up with bad + conversions. */ + + if (TYPE_MODE (type) == TYPE_MODE (signed_char_type_node)) return unsignedp ? unsigned_char_type_node : signed_char_type_node; - if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)) + if (TYPE_MODE (type) == TYPE_MODE (integer_type_node)) return unsignedp ? unsigned_type_node : integer_type_node; - if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node)) + if (TYPE_MODE (type) == TYPE_MODE (short_integer_type_node)) return unsignedp ? short_unsigned_type_node : short_integer_type_node; - if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node)) + if (TYPE_MODE (type) == TYPE_MODE (long_integer_type_node)) return unsignedp ? long_unsigned_type_node : long_integer_type_node; - if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node)) + if (TYPE_MODE (type) == TYPE_MODE (long_long_integer_type_node)) return (unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node); - if (TYPE_PRECISION (type) == TYPE_PRECISION (widest_integer_literal_type_node)) + if (TYPE_MODE (type) == TYPE_MODE (widest_integer_literal_type_node)) return (unsignedp ? widest_unsigned_literal_type_node : widest_integer_literal_type_node); #if HOST_BITS_PER_WIDE_INT >= 64 - if (TYPE_PRECISION (type) == TYPE_PRECISION (intTI_type_node)) + if (TYPE_MODE (type) == TYPE_MODE (intTI_type_node)) return unsignedp ? unsigned_intTI_type_node : intTI_type_node; #endif - if (TYPE_PRECISION (type) == TYPE_PRECISION (intDI_type_node)) + if (TYPE_MODE (type) == TYPE_MODE (intDI_type_node)) return unsignedp ? unsigned_intDI_type_node : intDI_type_node; - if (TYPE_PRECISION (type) == TYPE_PRECISION (intSI_type_node)) + if (TYPE_MODE (type) == TYPE_MODE (intSI_type_node)) return unsignedp ? unsigned_intSI_type_node : intSI_type_node; - if (TYPE_PRECISION (type) == TYPE_PRECISION (intHI_type_node)) + if (TYPE_MODE (type) == TYPE_MODE (intHI_type_node)) return unsignedp ? unsigned_intHI_type_node : intHI_type_node; - if (TYPE_PRECISION (type) == TYPE_PRECISION (intQI_type_node)) + if (TYPE_MODE (type) == TYPE_MODE (intQI_type_node)) return unsignedp ? unsigned_intQI_type_node : intQI_type_node; return type; } + +/* The C version of the register_builtin_type langhook. */ + +void +c_register_builtin_type (tree type, const char* name) +{ + tree decl; + + decl = build_decl (TYPE_DECL, get_identifier (name), type); + DECL_ARTIFICIAL (decl) = 1; + if (!TYPE_NAME (type)) + TYPE_NAME (type) = decl; + pushdecl (decl); + + registered_builtin_types = tree_cons (0, type, registered_builtin_types); +} + /* Return the minimum number of bits needed to represent VALUE in a signed or unsigned type, UNSIGNEDP says which. */ @@ -2552,27 +2593,8 @@ c_common_truthvalue_conversion (tree expr) if (TREE_CODE (expr) == ERROR_MARK) return expr; -#if 0 /* This appears to be wrong for C++. */ - /* These really should return error_mark_node after 2.4 is stable. - But not all callers handle ERROR_MARK properly. */ - switch (TREE_CODE (TREE_TYPE (expr))) - { - case RECORD_TYPE: - error ("struct type value used where scalar is required"); - return truthvalue_false_node; - - case UNION_TYPE: - error ("union type value used where scalar is required"); - return truthvalue_false_node; - - case ARRAY_TYPE: - error ("array type value used where scalar is required"); - return truthvalue_false_node; - - default: - break; - } -#endif /* 0 */ + if (TREE_CODE (expr) == FUNCTION_DECL) + expr = build_unary_op (ADDR_EXPR, expr, 0); switch (TREE_CODE (expr)) { @@ -2597,32 +2619,42 @@ c_common_truthvalue_conversion (tree expr) return real_zerop (expr) ? truthvalue_false_node : truthvalue_true_node; case ADDR_EXPR: - /* If we are taking the address of an external decl, it might be zero - if it is weak, so we cannot optimize. */ - if (DECL_P (TREE_OPERAND (expr, 0)) - && DECL_EXTERNAL (TREE_OPERAND (expr, 0))) - break; + { + if (TREE_CODE (TREE_OPERAND (expr, 0)) == FUNCTION_DECL + && ! DECL_WEAK (TREE_OPERAND (expr, 0))) + { + /* Common Ada/Pascal programmer's mistake. We always warn + about this since it is so bad. */ + warning ("the address of `%D', will always evaluate as `true'", + TREE_OPERAND (expr, 0)); + return truthvalue_true_node; + } - if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0))) - return build (COMPOUND_EXPR, truthvalue_type_node, - TREE_OPERAND (expr, 0), truthvalue_true_node); - else - return truthvalue_true_node; + /* If we are taking the address of an external decl, it might be + zero if it is weak, so we cannot optimize. */ + if (DECL_P (TREE_OPERAND (expr, 0)) + && DECL_EXTERNAL (TREE_OPERAND (expr, 0))) + break; + + if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0))) + return build (COMPOUND_EXPR, truthvalue_type_node, + TREE_OPERAND (expr, 0), truthvalue_true_node); + else + return truthvalue_true_node; + } case COMPLEX_EXPR: return build_binary_op ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)) ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR), - c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)), - c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)), + (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0)), + (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 1)), 0); case NEGATE_EXPR: case ABS_EXPR: case FLOAT_EXPR: - case FFS_EXPR: - case POPCOUNT_EXPR: /* These don't change whether an object is nonzero or zero. */ - return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)); + return (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0)); case LROTATE_EXPR: case RROTATE_EXPR: @@ -2630,15 +2662,15 @@ c_common_truthvalue_conversion (tree expr) we can't ignore them if their second arg has side-effects. */ if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))) return build (COMPOUND_EXPR, truthvalue_type_node, TREE_OPERAND (expr, 1), - c_common_truthvalue_conversion (TREE_OPERAND (expr, 0))); + (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0))); else - return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)); + return (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0)); case COND_EXPR: /* Distribute the conversion into the arms of a COND_EXPR. */ return fold (build (COND_EXPR, truthvalue_type_node, TREE_OPERAND (expr, 0), - c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)), - c_common_truthvalue_conversion (TREE_OPERAND (expr, 2)))); + (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 1)), + (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 2)))); case CONVERT_EXPR: /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE, @@ -2651,7 +2683,7 @@ c_common_truthvalue_conversion (tree 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)))) - return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)); + return (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0)); break; case MINUS_EXPR: @@ -2700,8 +2732,8 @@ c_common_truthvalue_conversion (tree expr) return (build_binary_op ((TREE_SIDE_EFFECTS (expr) ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR), - c_common_truthvalue_conversion (build_unary_op (REALPART_EXPR, t, 0)), - c_common_truthvalue_conversion (build_unary_op (IMAGPART_EXPR, t, 0)), + (*lang_hooks.truthvalue_conversion) (build_unary_op (REALPART_EXPR, t, 0)), + (*lang_hooks.truthvalue_conversion) (build_unary_op (IMAGPART_EXPR, t, 0)), 0)); } @@ -2718,13 +2750,17 @@ static tree builtin_function_2 (const char *, const char *, tree, tree, tree c_build_qualified_type (tree type, int type_quals) { + if (type == error_mark_node) + return type; + + if (TREE_CODE (type) == ARRAY_TYPE) + return build_array_type (c_build_qualified_type (TREE_TYPE (type), + type_quals), + TYPE_DOMAIN (type)); + /* A restrict-qualified pointer type must be a pointer to object or incomplete type. Note that the use of POINTER_TYPE_P also allows - REFERENCE_TYPEs, which is appropriate for C++. Unfortunately, - the C++ front-end also use POINTER_TYPE for pointer-to-member - values, so even though it should be illegal to use `restrict' - with such an entity we don't flag that here. Thus, special case - code for that case is required in the C++ front-end. */ + REFERENCE_TYPEs, which is appropriate for C++. */ if ((type_quals & TYPE_QUAL_RESTRICT) && (!POINTER_TYPE_P (type) || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type)))) @@ -2733,10 +2769,6 @@ c_build_qualified_type (tree type, int type_quals) type_quals &= ~TYPE_QUAL_RESTRICT; } - if (TREE_CODE (type) == ARRAY_TYPE) - return build_array_type (c_build_qualified_type (TREE_TYPE (type), - type_quals), - TYPE_DOMAIN (type)); return build_qualified_type (type, type_quals); } @@ -2745,9 +2777,19 @@ c_build_qualified_type (tree type, int type_quals) void c_apply_type_quals_to_decl (int type_quals, tree decl) { - if ((type_quals & TYPE_QUAL_CONST) - || (TREE_TYPE (decl) - && TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)) + tree type = TREE_TYPE (decl); + + if (type == error_mark_node) + return; + + if (((type_quals & TYPE_QUAL_CONST) + || (type && TREE_CODE (type) == REFERENCE_TYPE)) + /* An object declared 'const' is only readonly after it is + initialized. We don't have any way of expressing this currently, + so we need to be conservative and unset TREE_READONLY for types + with constructors. Otherwise aliasing code will ignore stores in + an inline constructor. */ + && !(type && TYPE_NEEDS_CONSTRUCTING (type))) TREE_READONLY (decl) = 1; if (type_quals & TYPE_QUAL_VOLATILE) { @@ -2756,11 +2798,15 @@ c_apply_type_quals_to_decl (int type_quals, tree decl) } if (type_quals & TYPE_QUAL_RESTRICT) { - if (!TREE_TYPE (decl) - || !POINTER_TYPE_P (TREE_TYPE (decl)) - || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (TREE_TYPE (decl)))) + while (type && TREE_CODE (type) == ARRAY_TYPE) + /* Allow 'restrict' on arrays of pointers. + FIXME currently we just ignore it. */ + type = TREE_TYPE (type); + if (!type + || !POINTER_TYPE_P (type) + || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))) error ("invalid use of `restrict'"); - else if (flag_strict_aliasing) + else if (flag_strict_aliasing && type == TREE_TYPE (decl)) /* Indicate we need to make a unique alias set for this pointer. We can't do it here because it might be pointing to an incomplete type. */ @@ -2836,7 +2882,7 @@ c_common_get_alias_set (tree t) int *ip; int **ipp = &ip; - const int* const* cipp = &ipp; + const int* const* cipp = ipp; And, it doesn't make sense for that to be legal unless you can dereference IPP and CIPP. So, we ignore cv-qualifiers on @@ -3547,6 +3593,15 @@ strip_array_types (tree type) return type; } +/* Recursively remove any '*' or '&' operator from TYPE. */ +tree +strip_pointer_operator (tree t) +{ + while (POINTER_TYPE_P (t)) + t = TREE_TYPE (t); + return t; +} + static tree expand_unordered_cmp (tree, tree, enum tree_code, enum tree_code); /* Expand a call to an unordered comparison function such as @@ -3660,14 +3715,16 @@ expand_tree_builtin (tree function, tree params, tree coerced_params) case BUILT_IN_CREALL: if (coerced_params == 0) return integer_zero_node; - return build_unary_op (REALPART_EXPR, TREE_VALUE (coerced_params), 0); + return non_lvalue (build_unary_op (REALPART_EXPR, + TREE_VALUE (coerced_params), 0)); case BUILT_IN_CIMAG: case BUILT_IN_CIMAGF: case BUILT_IN_CIMAGL: if (coerced_params == 0) return integer_zero_node; - return build_unary_op (IMAGPART_EXPR, TREE_VALUE (coerced_params), 0); + return non_lvalue (build_unary_op (IMAGPART_EXPR, + TREE_VALUE (coerced_params), 0)); case BUILT_IN_ISGREATER: return expand_unordered_cmp (function, params, UNLE_EXPR, LE_EXPR); @@ -3904,19 +3961,17 @@ c_add_case_label (splay_tree cases, tree cond, tree low_value, if (high_value) { error ("duplicate (or overlapping) case value"); - error ("%Hthis is the first entry overlapping that value", - &DECL_SOURCE_LOCATION (duplicate)); + error ("%Jthis is the first entry overlapping that value", duplicate); } else if (low_value) { error ("duplicate case value") ; - error ("%Hpreviously used here", &DECL_SOURCE_LOCATION (duplicate)); + error ("%Jpreviously used here", duplicate); } else { error ("multiple default labels in one switch"); - error ("%Hthis is the first default label", - &DECL_SOURCE_LOCATION (duplicate)); + error ("%Jthis is the first default label", duplicate); } if (!cases->root) add_stmt (build_case_label (NULL_TREE, NULL_TREE, label)); @@ -3965,8 +4020,9 @@ finish_label_address_expr (tree label) /* Hook used by expand_expr to expand language-specific tree codes. */ rtx -c_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier) - /* Actually enum_modifier. */ +c_expand_expr (tree exp, rtx target, enum machine_mode tmode, + int modifier /* Actually enum_modifier. */, + rtx *alt_rtl) { switch (TREE_CODE (exp)) { @@ -3975,7 +4031,26 @@ c_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier) tree rtl_expr; rtx result; bool preserve_result = false; - bool return_target = false; + + if (STMT_EXPR_WARN_UNUSED_RESULT (exp) && target == const0_rtx) + { + tree stmt = STMT_EXPR_STMT (exp); + tree scope; + + for (scope = COMPOUND_BODY (stmt); + scope && TREE_CODE (scope) != SCOPE_STMT; + scope = TREE_CHAIN (scope)); + + if (scope && SCOPE_STMT_BLOCK (scope)) + warning ("%Hignoring return value of `%D', " + "declared with attribute warn_unused_result", + &expr_wfl_stack->location, + BLOCK_ABSTRACT_ORIGIN (SCOPE_STMT_BLOCK (scope))); + else + warning ("%Hignoring return value of function " + "declared with attribute warn_unused_result", + &expr_wfl_stack->location); + } /* Since expand_expr_stmt calls free_temp_slots after every expression statement, we must call push_temp_slots here. @@ -4003,30 +4078,18 @@ c_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier) if (TREE_CODE (last) == SCOPE_STMT && TREE_CODE (expr) == EXPR_STMT) { - if (target && TREE_CODE (EXPR_STMT_EXPR (expr)) == VAR_DECL - && DECL_RTL_IF_SET (EXPR_STMT_EXPR (expr)) == target) - /* If the last expression is a variable whose RTL is the - same as our target, just return the target; if it - isn't valid expanding the decl would produce different - RTL, and store_expr would try to do a copy. */ - return_target = true; - else - { - /* Otherwise, note that we want the value from the last - expression. */ - TREE_ADDRESSABLE (expr) = 1; - preserve_result = true; - } + /* Otherwise, note that we want the value from the last + expression. */ + TREE_ADDRESSABLE (expr) = 1; + preserve_result = true; } } expand_stmt (STMT_EXPR_STMT (exp)); expand_end_stmt_expr (rtl_expr); - result = expand_expr (rtl_expr, target, tmode, modifier); - if (return_target) - result = target; - else if (preserve_result && GET_CODE (result) == MEM) + result = expand_expr_real (rtl_expr, target, tmode, modifier, alt_rtl); + if (preserve_result && GET_CODE (result) == MEM) { if (GET_MODE (result) != BLKmode) result = copy_to_reg (result); @@ -4051,7 +4114,7 @@ c_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier) literal, then return the variable. */ tree decl = COMPOUND_LITERAL_EXPR_DECL (exp); emit_local_var (decl); - return expand_expr (decl, target, tmode, modifier); + return expand_expr_real (decl, target, tmode, modifier, alt_rtl); } default: @@ -4185,21 +4248,6 @@ c_init_attributes (void) #undef DEF_ATTR_TREE_LIST } -/* Output a -Wshadow warning MSGCODE about NAME, and give the location - of the previous declaration DECL. */ -void -shadow_warning (enum sw_kind msgcode, const char *name, tree decl) -{ - static const char *const msgs[] = { - /* SW_PARAM */ N_("declaration of \"%s\" shadows a parameter"), - /* SW_LOCAL */ N_("declaration of \"%s\" shadows a previous local"), - /* SW_GLOBAL */ N_("declaration of \"%s\" shadows a global declaration") - }; - - warning (msgs[msgcode], name); - warning ("%Hshadowed declaration is here", &DECL_SOURCE_LOCATION (decl)); -} - /* Attribute handlers common to C front ends. */ /* Handle a "packed" attribute; arguments as in @@ -4638,8 +4686,8 @@ handle_section_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args, && current_function_decl != NULL_TREE && ! TREE_STATIC (decl)) { - error ("%Hsection attribute cannot be specified for " - "local variables", &DECL_SOURCE_LOCATION (decl)); + error ("%Jsection attribute cannot be specified for " + "local variables", decl); *no_add_attrs = true; } @@ -4649,8 +4697,8 @@ handle_section_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args, && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)), TREE_STRING_POINTER (TREE_VALUE (args))) != 0) { - error ("%Hsection of '%D' conflicts with previous declaration", - &DECL_SOURCE_LOCATION (*node), *node); + error ("%Jsection of '%D' conflicts with previous declaration", + *node, *node); *no_add_attrs = true; } else @@ -4658,15 +4706,13 @@ handle_section_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args, } else { - error ("%Hsection attribute not allowed for '%D'", - &DECL_SOURCE_LOCATION (*node), *node); + error ("%Jsection attribute not allowed for '%D'", *node, *node); *no_add_attrs = true; } } else { - error ("%Hsection attributes are not supported for this target", - &DECL_SOURCE_LOCATION (*node)); + error ("%Jsection attributes are not supported for this target", *node); *no_add_attrs = true; } @@ -4740,8 +4786,7 @@ handle_aligned_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args, else if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FIELD_DECL) { - error ("%Halignment may not be specified for '%D'", - &DECL_SOURCE_LOCATION (decl), decl); + error ("%Jalignment may not be specified for '%D'", decl, decl); *no_add_attrs = true; } else @@ -4779,11 +4824,16 @@ handle_alias_attribute (tree *node, tree name, tree args, if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl)) || (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl))) { - error ("%H'%D' defined both normally and as an alias", - &DECL_SOURCE_LOCATION (decl), decl); + error ("%J'%D' defined both normally and as an alias", decl, decl); *no_add_attrs = true; } - else if (decl_function_context (decl) == 0) + + /* Note that the very first time we process a nested declaration, + decl_function_context will not be set. Indeed, *would* never + be set except for the DECL_INITIAL/DECL_EXTERNAL frobbery that + we do below. After such frobbery, pushdecl would set the context. + In any case, this is never what we want. */ + else if (decl_function_context (decl) == 0 && current_function_decl == NULL) { tree id; @@ -4821,34 +4871,33 @@ handle_visibility_attribute (tree *node, tree name, tree args, bool *no_add_attrs) { tree decl = *node; + tree id = TREE_VALUE (args); + + *no_add_attrs = true; if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl)) { warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); - *no_add_attrs = true; + return NULL_TREE; } - else - { - tree id; - id = TREE_VALUE (args); - if (TREE_CODE (id) != STRING_CST) - { - error ("visibility arg not a string"); - *no_add_attrs = true; - return NULL_TREE; - } - if (strcmp (TREE_STRING_POINTER (id), "hidden") - && strcmp (TREE_STRING_POINTER (id), "protected") - && strcmp (TREE_STRING_POINTER (id), "internal") - && strcmp (TREE_STRING_POINTER (id), "default")) - { - error ("visibility arg must be one of \"default\", \"hidden\", \"protected\" or \"internal\""); - *no_add_attrs = true; - return NULL_TREE; - } + if (TREE_CODE (id) != STRING_CST) + { + error ("visibility arg not a string"); + return NULL_TREE; } + if (strcmp (TREE_STRING_POINTER (id), "default") == 0) + DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; + else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0) + DECL_VISIBILITY (decl) = VISIBILITY_INTERNAL; + else if (strcmp (TREE_STRING_POINTER (id), "hidden") == 0) + DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; + else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0) + DECL_VISIBILITY (decl) = VISIBILITY_PROTECTED; + else + error ("visibility arg must be one of \"default\", \"hidden\", \"protected\" or \"internal\""); + return NULL_TREE; } @@ -4904,14 +4953,12 @@ handle_no_instrument_function_attribute (tree *node, tree name, if (TREE_CODE (decl) != FUNCTION_DECL) { - error ("%H'%E' attribute applies only to functions", - &DECL_SOURCE_LOCATION (decl), name); + error ("%J'%E' attribute applies only to functions", decl, name); *no_add_attrs = true; } else if (DECL_INITIAL (decl)) { - error ("%Hcan't set '%E' attribute after definition", - &DECL_SOURCE_LOCATION (decl), name); + error ("%Jcan't set '%E' attribute after definition", decl, name); *no_add_attrs = true; } else @@ -4952,14 +4999,12 @@ handle_no_limit_stack_attribute (tree *node, tree name, if (TREE_CODE (decl) != FUNCTION_DECL) { - error ("%H'%E' attribute applies only to functions", - &DECL_SOURCE_LOCATION (decl), name); + error ("%J'%E' attribute applies only to functions", decl, name); *no_add_attrs = true; } else if (DECL_INITIAL (decl)) { - error ("%Hcan't set '%E' attribute after definition", - &DECL_SOURCE_LOCATION (decl), name); + error ("%Jcan't set '%E' attribute after definition", decl, name); *no_add_attrs = true; } else @@ -5189,57 +5234,11 @@ handle_vector_size_attribute (tree *node, tree name, tree args, } /* Build back pointers if needed. */ - *node = vector_size_helper (*node, new_type); + *node = reconstruct_complex_type (*node, new_type); return NULL_TREE; } -/* HACK. GROSS. This is absolutely disgusting. I wish there was a - better way. - - If we requested a pointer to a vector, build up the pointers that - we stripped off while looking for the inner type. Similarly for - return values from functions. - - The argument "type" is the top of the chain, and "bottom" is the - new type which we will point to. */ - -static tree -vector_size_helper (tree type, tree bottom) -{ - tree inner, outer; - - if (POINTER_TYPE_P (type)) - { - inner = vector_size_helper (TREE_TYPE (type), bottom); - outer = build_pointer_type (inner); - } - else if (TREE_CODE (type) == ARRAY_TYPE) - { - inner = vector_size_helper (TREE_TYPE (type), bottom); - outer = build_array_type (inner, TYPE_DOMAIN (type)); - } - else if (TREE_CODE (type) == FUNCTION_TYPE) - { - inner = vector_size_helper (TREE_TYPE (type), bottom); - outer = build_function_type (inner, TYPE_ARG_TYPES (type)); - } - else if (TREE_CODE (type) == METHOD_TYPE) - { - inner = vector_size_helper (TREE_TYPE (type), bottom); - outer = build_method_type_directly (TYPE_METHOD_BASETYPE (type), - inner, - TYPE_ARG_TYPES (type)); - } - else - return bottom; - - TREE_READONLY (outer) = TREE_READONLY (type); - TREE_THIS_VOLATILE (outer) = TREE_THIS_VOLATILE (type); - - return outer; -} - /* Handle the "nonnull" attribute. */ static tree handle_nonnull_attribute (tree *node, tree name ATTRIBUTE_UNUSED, @@ -5466,6 +5465,23 @@ handle_cleanup_attribute (tree *node, tree name, tree args, return NULL_TREE; } + +/* Handle a "warn_unused_result" attribute. No special handling. */ + +static tree +handle_warn_unused_result_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + /* Ignore the attribute for functions not returning any value. */ + if (VOID_TYPE_P (TREE_TYPE (*node))) + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} /* Check for valid arguments being passed to a function. */ void @@ -5654,21 +5670,40 @@ c_estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data) return NULL; switch (TREE_CODE (x)) { - /* Reconginze assignments of large structures and constructors of + /* Recognize assignments of large structures and constructors of big arrays. */ case MODIFY_EXPR: case CONSTRUCTOR: { - int size = int_size_in_bytes (TREE_TYPE (x)); + HOST_WIDE_INT size; - if (!size || size > MOVE_MAX_PIECES) + size = int_size_in_bytes (TREE_TYPE (x)); + + if (size < 0 || size > MOVE_MAX_PIECES * MOVE_RATIO) *count += 10; else - *count += 2 * (size + MOVE_MAX - 1) / MOVE_MAX; - return NULL; + *count += ((size + MOVE_MAX_PIECES - 1) / MOVE_MAX_PIECES); } break; - /* Few special cases of expensive operations. This is usefull + case CALL_EXPR: + { + tree decl = get_callee_fndecl (x); + + if (decl && DECL_BUILT_IN (decl)) + switch (DECL_FUNCTION_CODE (decl)) + { + case BUILT_IN_CONSTANT_P: + *walk_subtrees = 0; + return NULL_TREE; + case BUILT_IN_EXPECT: + return NULL_TREE; + default: + break; + } + *count += 10; + break; + } + /* Few special cases of expensive operations. This is useful to avoid inlining on functions having too many of these. */ case TRUNC_DIV_EXPR: case CEIL_DIV_EXPR: @@ -5679,7 +5714,6 @@ c_estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data) case FLOOR_MOD_EXPR: case ROUND_MOD_EXPR: case RDIV_EXPR: - case CALL_EXPR: *count += 10; break; /* Various containers that will produce no code themselves. */ @@ -5773,4 +5807,36 @@ c_decl_uninit (tree t) return false; } +/* Issue the error given by MSGID, indicating that it occurred before + TOKEN, which had the associated VALUE. */ + +void +c_parse_error (const char *msgid, enum cpp_ttype token, tree value) +{ + const char *string = _(msgid); + + if (token == CPP_EOF) + error ("%s at end of input", string); + else if (token == CPP_CHAR || token == CPP_WCHAR) + { + unsigned int val = TREE_INT_CST_LOW (value); + const char *const ell = (token == CPP_CHAR) ? "" : "L"; + if (val <= UCHAR_MAX && ISGRAPH (val)) + error ("%s before %s'%c'", string, ell, val); + else + error ("%s before %s'\\x%x'", string, ell, val); + } + else if (token == CPP_STRING + || token == CPP_WSTRING) + error ("%s before string constant", string); + else if (token == CPP_NUMBER) + error ("%s before numeric constant", string); + else if (token == CPP_NAME) + error ("%s before \"%s\"", string, IDENTIFIER_POINTER (value)); + else if (token < N_TTYPES) + error ("%s before '%s' token", string, cpp_type2name (token)); + else + error ("%s", string); +} + #include "gt-c-common.h"