X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fc-common.c;h=1bd59ff5e227ae7056be37fe61a43b6086074480;hp=997fc717749709defa85031eb97322f0e2a2cc60;hb=92fccaaa535d5555bda8058c165fe3b2e0528c88;hpb=1b53eb2049bbdd60579efc45d4116c06b73e05c9 diff --git a/gcc/c-common.c b/gcc/c-common.c index 997fc717749..1bd59ff5e22 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, 2004, 2005 Free Software Foundation, Inc. + 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of GCC. @@ -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; @@ -250,6 +254,10 @@ int flag_short_double; int flag_short_wchar; +/* Nonzero means allow implicit conversions between vectors with + differing numbers of subparts and/or differing element types. */ +int flag_lax_vector_conversions; + /* Nonzero means allow Microsoft extensions without warnings or errors. */ int flag_ms_extensions; @@ -257,20 +265,10 @@ int flag_ms_extensions; int flag_no_asm; -/* Nonzero means give string constants the type `const char *', as mandated - by the standard. */ - -int flag_const_strings; - /* Nonzero means to treat bitfields as signed unless they say `unsigned'. */ int flag_signed_bitfields = 1; -/* Nonzero means warn about deprecated conversion from string constant to - `char *'. */ - -int warn_write_strings; - /* Warn about #pragma directives that are not recognized. */ int warn_unknown_pragmas; /* Tri state variable. */ @@ -340,7 +338,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; @@ -407,6 +405,11 @@ int flag_access_control = 1; int flag_check_new; +/* Nonzero if we want to allow the use of experimental features that + are likely to become part of C++0x. */ + +int flag_cpp0x = 0; + /* Nonzero if we want the new ISO rules for pushing a new scope for `for' initialization variables. 0: Old rules, set by -fno-for-scope. @@ -430,10 +433,16 @@ int flag_weak = 1; int flag_working_directory = -1; /* Nonzero to use __cxa_atexit, rather than atexit, to register - destructors for local statics and global objects. */ + destructors for local statics and global objects. '2' means it has been + set nonzero as a default, not by a command-line flag. */ int flag_use_cxa_atexit = DEFAULT_USE_CXA_ATEXIT; +/* Nonzero to use __cxa_get_exception_ptr in C++ exception-handling + code. '2' means it has not been set explicitly on the command line. */ + +int flag_use_cxa_get_exception_ptr = 2; + /* Nonzero means make the default pedwarns warnings instead of errors. The value of this flag is ignored if -pedantic is specified. */ @@ -494,7 +503,6 @@ const struct fname_var_t fname_vars[] = {NULL, 0, 0}, }; -static int constant_fits_type_p (tree, tree); static tree check_case_value (tree); static bool check_case_bounds (tree, tree, tree *, tree *); @@ -505,6 +513,9 @@ static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *); static tree handle_noinline_attribute (tree *, tree, tree, int, bool *); static tree handle_always_inline_attribute (tree *, tree, tree, int, bool *); +static tree handle_gnu_inline_attribute (tree *, tree, tree, int, + bool *); +static tree handle_flatten_attribute (tree *, tree, tree, int, bool *); static tree handle_used_attribute (tree *, tree, tree, int, bool *); static tree handle_unused_attribute (tree *, tree, tree, int, bool *); static tree handle_externally_visible_attribute (tree *, tree, tree, int, @@ -519,6 +530,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, @@ -571,6 +583,10 @@ const struct attribute_spec c_common_attribute_table[] = handle_noinline_attribute }, { "always_inline", 0, 0, true, false, false, handle_always_inline_attribute }, + { "gnu_inline", 0, 0, true, false, false, + handle_gnu_inline_attribute }, + { "flatten", 0, 0, true, false, false, + handle_flatten_attribute }, { "used", 0, 0, true, false, false, handle_used_attribute }, { "unused", 0, 0, false, false, false, @@ -596,6 +612,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, @@ -692,7 +710,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; } @@ -767,10 +785,10 @@ c_expand_decl (tree decl) { /* Let the back-end know about this variable. */ if (!anon_aggr_type_p (TREE_TYPE (decl))) - emit_local_var (decl); + emit_local_var (decl); else - expand_anon_union_decl (decl, NULL_TREE, - DECL_ANON_UNION_ELEMS (decl)); + expand_anon_union_decl (decl, NULL_TREE, + DECL_ANON_UNION_ELEMS (decl)); } else return 0; @@ -834,7 +852,6 @@ fix_string_type (tree value) { const int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT; const int wide_flag = TREE_TYPE (value) == wchar_array_type_node; - const int nchars_max = flag_isoc99 ? 4095 : 509; int length = TREE_STRING_LENGTH (value); int nchars; tree e_type, i_type, a_type; @@ -842,15 +859,32 @@ fix_string_type (tree value) /* Compute the number of elements, for the array type. */ nchars = wide_flag ? length / wchar_bytes : length; - if (pedantic && nchars - 1 > nchars_max && !c_dialect_cxx ()) - pedwarn ("string length %qd is greater than the length %qd ISO C%d compilers are required to support", - nchars - 1, nchars_max, flag_isoc99 ? 99 : 89); - - e_type = wide_flag ? wchar_type_node : char_type_node; - /* Create the array type for the string constant. flag_const_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. + /* C89 2.2.4.1, C99 5.2.4.1 (Translation limits). The analogous + limit in C++98 Annex B is very large (65536) and is not normative, + so we do not diagnose it (warn_overlength_strings is forced off + in c_common_post_options). */ + if (warn_overlength_strings) + { + const int nchars_max = flag_isoc99 ? 4095 : 509; + const int relevant_std = flag_isoc99 ? 99 : 90; + if (nchars - 1 > nchars_max) + /* Translators: The %d after 'ISO C' will be 90 or 99. Do not + separate the %d from the 'C'. 'ISO' should not be + translated, but it may be moved after 'C%d' in languages + where modifiers follow nouns. */ + pedwarn ("string length %qd is greater than the length %qd " + "ISO C%d compilers are required to support", + nchars - 1, nchars_max, relevant_std); + } + + /* Create the array type for the string constant. The ISO C++ + standard says that a string literal has type `const char[N]' or + `const wchar_t[N]'. We use the same logic when invoked as a C + front-end with -Wwrite-strings. + ??? We should change the type of an expression depending on the + state of a warning flag. We should just be warning -- see how + this is handled in the C++ front-end for the deprecated implicit + conversion from string literals to `char*' or `wchar_t*'. The C++ front end relies on TYPE_MAIN_VARIANT of a cv-qualified array type being the unqualified version of that type. @@ -858,9 +892,10 @@ fix_string_type (tree value) construct the matching unqualified array type first. The C front end does not require this, but it does no harm, so we do it unconditionally. */ + e_type = wide_flag ? wchar_type_node : char_type_node; i_type = build_index_type (build_int_cst (NULL_TREE, nchars - 1)); a_type = build_array_type (e_type, i_type); - if (flag_const_strings) + if (c_dialect_cxx() || warn_write_strings) a_type = c_build_qualified_type (a_type, TYPE_QUAL_CONST); TREE_TYPE (value) = a_type; @@ -883,94 +918,317 @@ constant_expression_warning (tree value) if ((TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST || TREE_CODE (value) == VECTOR_CST || TREE_CODE (value) == COMPLEX_CST) - && TREE_CONSTANT_OVERFLOW (value) && pedantic) + && TREE_OVERFLOW (value) + && warn_overflow + && pedantic) pedwarn ("overflow in constant expression"); } -/* Print a warning if an expression had overflow in folding. +/* Print a warning if an expression had overflow in folding and its + operands hadn't. + Invoke this function on every expression that (1) appears in the source code, and - (2) might be a constant expression that overflowed, and + (2) is a constant expression that overflowed, and (3) is not already checked by convert_and_check; - however, do not invoke this function on operands of explicit casts. */ + however, do not invoke this function on operands of explicit casts + or when the expression is the result of an operator and any operand + already overflowed. */ void overflow_warning (tree value) { - if ((TREE_CODE (value) == INTEGER_CST - || (TREE_CODE (value) == COMPLEX_CST - && TREE_CODE (TREE_REALPART (value)) == INTEGER_CST)) - && TREE_OVERFLOW (value)) + if (skip_evaluation) return; + + switch (TREE_CODE (value)) { - TREE_OVERFLOW (value) = 0; - if (skip_evaluation == 0) - warning (0, "integer overflow in expression"); + case INTEGER_CST: + warning (OPT_Woverflow, "integer overflow in expression"); + break; + + case REAL_CST: + warning (OPT_Woverflow, "floating point overflow in expression"); + break; + + case VECTOR_CST: + warning (OPT_Woverflow, "vector overflow in expression"); + break; + + case COMPLEX_CST: + if (TREE_CODE (TREE_REALPART (value)) == INTEGER_CST) + warning (OPT_Woverflow, "complex integer overflow in expression"); + else if (TREE_CODE (TREE_REALPART (value)) == REAL_CST) + warning (OPT_Woverflow, "complex floating point overflow in expression"); + break; + + default: + break; } - else if ((TREE_CODE (value) == REAL_CST - || (TREE_CODE (value) == COMPLEX_CST - && TREE_CODE (TREE_REALPART (value)) == REAL_CST)) - && TREE_OVERFLOW (value)) - { - TREE_OVERFLOW (value) = 0; - if (skip_evaluation == 0) - warning (0, "floating point overflow in expression"); +} + +/* 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"); + } } - else if (TREE_CODE (value) == VECTOR_CST && TREE_OVERFLOW (value)) +} + +/* Print a warning about if (); or if () .. else; constructs + via the special empty statement node that we create. INNER_THEN + and INNER_ELSE are the statement lists of the if and the else + block. */ + +void +empty_body_warning (tree inner_then, tree inner_else) +{ + if (warn_empty_body) { - TREE_OVERFLOW (value) = 0; - if (skip_evaluation == 0) - warning (0, "vector overflow in expression"); - } + if (TREE_CODE (inner_then) == STATEMENT_LIST + && STATEMENT_LIST_TAIL (inner_then)) + inner_then = STATEMENT_LIST_TAIL (inner_then)->stmt; + + if (inner_else && TREE_CODE (inner_else) == STATEMENT_LIST + && STATEMENT_LIST_TAIL (inner_else)) + inner_else = STATEMENT_LIST_TAIL (inner_else)->stmt; + + if (IS_EMPTY_STMT (inner_then) && !inner_else) + warning (OPT_Wempty_body, "%Hempty body in an if-statement", + EXPR_LOCUS (inner_then)); + + if (inner_else && IS_EMPTY_STMT (inner_else)) + warning (OPT_Wempty_body, "%Hempty body in an else-statement", + EXPR_LOCUS (inner_else)); + } } -/* Print a warning if a large constant is truncated to unsigned, - or if -Wconversion is used and a constant < 0 is converted to unsigned. - Invoke this function on every expression that might be implicitly - converted to an unsigned type. */ +/* Warn for unlikely, improbable, or stupid DECL declarations + of `main'. */ void -unsigned_conversion_warning (tree result, tree operand) +check_main_parameter_types (tree decl) +{ + tree args; + int argct = 0; + + for (args = TYPE_ARG_TYPES (TREE_TYPE (decl)); args; + args = TREE_CHAIN (args)) + { + tree type = args ? TREE_VALUE (args) : 0; + + if (type == void_type_node || type == error_mark_node ) + break; + + ++argct; + switch (argct) + { + case 1: + if (TYPE_MAIN_VARIANT (type) != integer_type_node) + pedwarn ("first argument of %q+D should be %", decl); + break; + + case 2: + if (TREE_CODE (type) != POINTER_TYPE + || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE + || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))) + != char_type_node)) + pedwarn ("second argument of %q+D should be %", + decl); + break; + + case 3: + if (TREE_CODE (type) != POINTER_TYPE + || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE + || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))) + != char_type_node)) + pedwarn ("third argument of %q+D should probably be " + "%", decl); + break; + } + } + + /* It is intentional that this message does not mention the third + argument because it's only mentioned in an appendix of the + standard. */ + if (argct > 0 && (argct < 2 || argct > 3)) + pedwarn ("%q+D takes only zero or two arguments", decl); +} + +/* True if vector types T1 and T2 can be converted to each other + without an explicit cast. If EMIT_LAX_NOTE is true, and T1 and T2 + can only be converted with -flax-vector-conversions yet that is not + in effect, emit a note telling the user about that option if such + a note has not previously been emitted. */ +bool +vector_types_convertible_p (tree t1, tree t2, bool emit_lax_note) { - tree type = TREE_TYPE (result); + static bool emitted_lax_note = false; + bool convertible_lax; - if (TREE_CODE (operand) == INTEGER_CST - && TREE_CODE (type) == INTEGER_TYPE - && TYPE_UNSIGNED (type) - && skip_evaluation == 0 - && !int_fits_type_p (operand, type)) + if ((targetm.vector_opaque_p (t1) || targetm.vector_opaque_p (t2)) + && tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2))) + return true; + + convertible_lax = + (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)))); + + if (!convertible_lax || flag_lax_vector_conversions) + return convertible_lax; + + if (TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2) + && comptypes (TREE_TYPE (t1), TREE_TYPE (t2))) + return true; + + if (emit_lax_note && !emitted_lax_note) { - if (!int_fits_type_p (operand, c_common_signed_type (type))) - /* This detects cases like converting -129 or 256 to unsigned char. */ - warning (0, "large integer implicitly truncated to unsigned type"); - else - warning (OPT_Wconversion, - "negative integer implicitly converted to unsigned type"); + emitted_lax_note = true; + inform ("use -flax-vector-conversions to permit " + "conversions between vectors with differing " + "element types or numbers of subparts"); } + + return false; } -/* Nonzero if constant C has a value that is permissible - for type TYPE (an INTEGER_TYPE). */ +/* Warns if the conversion of EXPR to TYPE may alter a value. + This function is called from convert_and_check. */ -static int -constant_fits_type_p (tree c, tree type) +static void +conversion_warning (tree type, tree expr) { - if (TREE_CODE (c) == INTEGER_CST) - return int_fits_type_p (c, type); + bool give_warning = false; - c = convert (type, c); - return !TREE_OVERFLOW (c); -} + unsigned int formal_prec = TYPE_PRECISION (type); -/* Nonzero if vector types T1 and T2 can be converted to each other - without an explicit cast. */ -int -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)) - && INTEGRAL_TYPE_P (TREE_TYPE (t1)) - == INTEGRAL_TYPE_P (TREE_TYPE (t2))); + if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST) + { + /* Warn for real constant that is not an exact integer converted + to integer type. */ + if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE + && TREE_CODE (type) == INTEGER_TYPE) + { + if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (TREE_TYPE (expr)))) + give_warning = true; + } + /* Warn for an integer constant that does not fit into integer type. */ + else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE + && TREE_CODE (type) == INTEGER_TYPE + && !int_fits_type_p (expr, type)) + { + if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (TREE_TYPE (expr))) + warning (OPT_Wconversion, + "negative integer implicitly converted to unsigned type"); + else + give_warning = true; + } + else if (TREE_CODE (type) == REAL_TYPE) + { + /* Warn for an integer constant that does not fit into real type. */ + if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE) + { + REAL_VALUE_TYPE a = real_value_from_int_cst (0, expr); + if (!exact_real_truncate (TYPE_MODE (type), &a)) + give_warning = true; + } + /* Warn for a real constant that does not fit into a smaller + real type. */ + else if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE + && formal_prec < TYPE_PRECISION (TREE_TYPE (expr))) + { + REAL_VALUE_TYPE a = TREE_REAL_CST (expr); + if (!exact_real_truncate (TYPE_MODE (type), &a)) + give_warning = true; + } + } + + if (give_warning) + warning (OPT_Wconversion, + "conversion to %qT alters %qT constant value", + type, TREE_TYPE (expr)); + } + else /* 'expr' is not a constant. */ + { + /* Warn for real types converted to integer types. */ + if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE + && TREE_CODE (type) == INTEGER_TYPE) + give_warning = true; + + else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE + && TREE_CODE (type) == INTEGER_TYPE) + { + /* Warn for integer types converted to smaller integer types. */ + if (formal_prec < TYPE_PRECISION (TREE_TYPE (expr)) + /* When they are the same width but different signedness, + then the value may change. */ + || (formal_prec == TYPE_PRECISION (TREE_TYPE (expr)) + && TYPE_UNSIGNED (TREE_TYPE (expr)) != TYPE_UNSIGNED (type)) + /* Even when converted to a bigger type, if the type is + unsigned but expr is signed, then negative values + will be changed. */ + || (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (TREE_TYPE (expr)))) + give_warning = true; + } + + /* Warn for integer types converted to real types if and only if + all the range of values of the integer type cannot be + represented by the real type. */ + else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE + && TREE_CODE (type) == REAL_TYPE) + { + tree type_low_bound = TYPE_MIN_VALUE (TREE_TYPE (expr)); + tree type_high_bound = TYPE_MAX_VALUE (TREE_TYPE (expr)); + REAL_VALUE_TYPE real_low_bound = real_value_from_int_cst (0, type_low_bound); + REAL_VALUE_TYPE real_high_bound = real_value_from_int_cst (0, type_high_bound); + + if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound) + || !exact_real_truncate (TYPE_MODE (type), &real_high_bound)) + give_warning = true; + } + + /* Warn for real types converted to smaller real types. */ + else if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE + && TREE_CODE (type) == REAL_TYPE + && formal_prec < TYPE_PRECISION (TREE_TYPE (expr))) + give_warning = true; + + + if (give_warning) + warning (OPT_Wconversion, + "conversion to %qT from %qT may alter its value", + type, TREE_TYPE (expr)); + } } /* Convert EXPR to TYPE, warning about conversion problems with constants. @@ -980,34 +1238,60 @@ vector_types_convertible_p (tree t1, tree t2) tree convert_and_check (tree type, tree expr) { - tree t = convert (type, expr); - if (TREE_CODE (t) == INTEGER_CST) + tree result; + + if (TREE_TYPE (expr) == type) + return expr; + + result = convert (type, expr); + + if (skip_evaluation) + return result; + + + if (TREE_CODE (expr) == INTEGER_CST + && (TREE_CODE (type) == INTEGER_TYPE + || TREE_CODE (type) == ENUMERAL_TYPE) + && !int_fits_type_p (expr, type)) { - if (TREE_OVERFLOW (t)) - { - TREE_OVERFLOW (t) = 0; - - /* Do not diagnose overflow in a constant expression merely - because a conversion overflowed. */ - TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (expr); - - /* No warning for converting 0x80000000 to int. */ - if (!(TYPE_UNSIGNED (type) < TYPE_UNSIGNED (TREE_TYPE (expr)) - && TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE - && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (expr)))) - /* If EXPR fits in the unsigned version of TYPE, - don't warn unless pedantic. */ - if ((pedantic - || TYPE_UNSIGNED (type) - || !constant_fits_type_p (expr, - c_common_unsigned_type (type))) - && skip_evaluation == 0) - warning (0, "overflow in implicit constant conversion"); - } + /* Do not diagnose overflow in a constant expression merely + because a conversion overflowed. */ + if (TREE_OVERFLOW (result)) + TREE_OVERFLOW (result) = TREE_OVERFLOW (expr); + + if (TYPE_UNSIGNED (type)) + { + /* This detects cases like converting -129 or 256 to + unsigned char. */ + if (!int_fits_type_p (expr, c_common_signed_type (type))) + warning (OPT_Woverflow, + "large integer implicitly truncated to unsigned type"); + else if (warn_conversion) + conversion_warning (type, expr); + } else - unsigned_conversion_warning (t, expr); - } - return t; + { + if (!int_fits_type_p (expr, c_common_unsigned_type (type))) + warning (OPT_Woverflow, + "overflow in implicit constant conversion"); + /* No warning for converting 0x80000000 to int. */ + else if (pedantic + && (TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE + || TYPE_PRECISION (TREE_TYPE (expr)) + != TYPE_PRECISION (type))) + warning (OPT_Woverflow, + "overflow in implicit constant conversion"); + else if (warn_conversion) + conversion_warning (type, expr); + } + } + else if (TREE_CODE (result) == INTEGER_CST && TREE_OVERFLOW (result)) + warning (OPT_Woverflow, + "overflow in implicit constant conversion"); + else if (warn_conversion) + conversion_warning (type, expr); + + return result; } /* A node in a list that describes references to variables (EXPR), which are @@ -1350,7 +1634,7 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp, default: /* For other expressions, simply recurse on their operands. - Manual tail recursion for unary expressions. + Manual tail recursion for unary expressions. Other non-expressions need not be processed. */ if (cl == tcc_unary) { @@ -1642,6 +1926,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); @@ -1773,6 +2064,31 @@ c_common_signed_or_unsigned_type (int unsignedp, tree type) return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp); } +/* Build a bit-field integer type for the given WIDTH and UNSIGNEDP. */ + +tree +c_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp) +{ + /* Extended integer types of the same width as a standard type have + lesser rank, so those of the same width as int promote to int or + unsigned int and are valid for printf formats expecting int or + unsigned int. To avoid such special cases, avoid creating + extended integer types for bit-fields if a standard integer type + is available. */ + if (width == TYPE_PRECISION (integer_type_node)) + return unsignedp ? unsigned_type_node : integer_type_node; + if (width == TYPE_PRECISION (signed_char_type_node)) + return unsignedp ? unsigned_char_type_node : signed_char_type_node; + if (width == TYPE_PRECISION (short_integer_type_node)) + return unsignedp ? short_unsigned_type_node : short_integer_type_node; + if (width == TYPE_PRECISION (long_integer_type_node)) + return unsignedp ? long_unsigned_type_node : long_integer_type_node; + if (width == TYPE_PRECISION (long_long_integer_type_node)) + return (unsignedp ? long_long_unsigned_type_node + : long_long_integer_type_node); + return build_nonstandard_integer_type (width, unsignedp); +} + /* The C version of the register_builtin_type langhook. */ void @@ -1818,8 +2134,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) @@ -1828,10 +2143,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: @@ -2006,12 +2317,10 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr, { /* Convert primop1 to target type, but do not introduce additional overflow. We know primop1 is an int_cst. */ - tree tmp = build_int_cst_wide (*restype_ptr, - TREE_INT_CST_LOW (primop1), - TREE_INT_CST_HIGH (primop1)); - - primop1 = force_fit_type (tmp, 0, TREE_OVERFLOW (primop1), - TREE_CONSTANT_OVERFLOW (primop1)); + primop1 = force_fit_type_double (*restype_ptr, + TREE_INT_CST_LOW (primop1), + TREE_INT_CST_HIGH (primop1), 0, + TREE_OVERFLOW (primop1)); } if (type != *restype_ptr) { @@ -2129,6 +2438,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)))) @@ -2304,6 +2621,18 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop) return fold_build2 (resultcode, result_type, ptrop, intop); } +/* Return whether EXPR is a declaration whose address can never be + NULL. */ + +bool +decl_with_nonnull_addr_p (tree expr) +{ + return (DECL_P (expr) + && (TREE_CODE (expr) == PARM_DECL + || TREE_CODE (expr) == LABEL_DECL + || !DECL_WEAK (expr))); +} + /* Prepare expr to be an argument of a TRUTH_NOT_EXPR, or for an `if' or `while' statement or ?..: exp. It should already have been validated to be of suitable type; otherwise, a bad @@ -2352,10 +2681,8 @@ c_common_truthvalue_conversion (tree expr) return expr; case INTEGER_CST: - /* Avoid integer_zerop to ignore TREE_CONSTANT_OVERFLOW. */ - return (TREE_INT_CST_LOW (expr) != 0 || TREE_INT_CST_HIGH (expr) != 0) - ? truthvalue_true_node - : truthvalue_false_node; + return integer_zerop (expr) ? truthvalue_false_node + : truthvalue_true_node; case REAL_CST: return real_compare (NE_EXPR, &TREE_REAL_CST (expr), &dconst0) @@ -2368,25 +2695,27 @@ c_common_truthvalue_conversion (tree expr) case ADDR_EXPR: { - if (TREE_CODE (TREE_OPERAND (expr, 0)) == FUNCTION_DECL - && !DECL_WEAK (TREE_OPERAND (expr, 0))) + tree inner = TREE_OPERAND (expr, 0); + if (decl_with_nonnull_addr_p (inner)) { - /* 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 %", - TREE_OPERAND (expr, 0)); + /* Common Ada/Pascal programmer's mistake. */ + warning (OPT_Walways_true, + "the address of %qD will always evaluate as %", + inner); 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 we still have a decl, it is possible for its address to + be NULL, so we cannot optimize. */ + if (DECL_P (inner)) + { + gcc_assert (DECL_WEAK (inner)); + break; + } - if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0))) + if (TREE_SIDE_EFFECTS (inner)) return build2 (COMPOUND_EXPR, truthvalue_type_node, - TREE_OPERAND (expr, 0), truthvalue_true_node); + inner, truthvalue_true_node); else return truthvalue_true_node; } @@ -2423,54 +2752,26 @@ 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)))) return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)); break; - case MINUS_EXPR: - /* Perhaps reduce (x - y) != 0 to (x != y). The expressions - aren't guaranteed to the be same for modes that can represent - infinity, since if x and y are both +infinity, or both - -infinity, then x - y is not a number. - - Note that this transformation is safe when x or y is NaN. - (x - y) is then NaN, and both (x - y) != 0 and x != y will - be false. */ - if (HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (TREE_OPERAND (expr, 0))))) - break; - /* Fall through.... */ - case BIT_XOR_EXPR: - /* This and MINUS_EXPR can be changed into a comparison of the - two objects. */ - if (TREE_TYPE (TREE_OPERAND (expr, 0)) - == TREE_TYPE (TREE_OPERAND (expr, 1))) - return fold_build2 (NE_EXPR, truthvalue_type_node, - TREE_OPERAND (expr, 0), TREE_OPERAND (expr, 1)); - return fold_build2 (NE_EXPR, truthvalue_type_node, - TREE_OPERAND (expr, 0), - fold_convert (TREE_TYPE (TREE_OPERAND (expr, 0)), - TREE_OPERAND (expr, 1))); - - case BIT_AND_EXPR: - if (integer_onep (TREE_OPERAND (expr, 1)) - && TREE_TYPE (expr) != truthvalue_type_node) - /* Using convert here would cause infinite recursion. */ - return build1 (NOP_EXPR, truthvalue_type_node, expr); - break; - case MODIFY_EXPR: - if (!TREE_NO_WARNING (expr)) - warning (OPT_Wparentheses, - "suggest parentheses around assignment used as truth value"); + if (!TREE_NO_WARNING (expr) + && warn_parentheses) + { + warning (OPT_Wparentheses, + "suggest parentheses around assignment used as truth value"); + TREE_NO_WARNING (expr) = 1; + } break; default: @@ -2491,12 +2792,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. */ @@ -2699,9 +3000,9 @@ c_common_get_alias_set (tree t) But, the standard is wrong. In particular, this code is legal C++: - int *ip; - int **ipp = &ip; - const int* const* cipp = ipp; + int *ip; + int **ipp = &ip; + 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 @@ -2829,7 +3130,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; @@ -2864,7 +3165,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; @@ -2879,7 +3180,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. */ @@ -2902,14 +3203,8 @@ static GTY(()) tree built_in_attributes[(int) ATTR_LAST]; static void c_init_attributes (void); -/* Build tree nodes and builtin functions common to both C and C++ language - frontends. */ - -void -c_common_nodes_and_builtins (void) +enum c_builtin_type { - enum builtin_type - { #define DEF_PRIMITIVE_TYPE(NAME, VALUE) NAME, #define DEF_FUNCTION_TYPE_0(NAME, RETURN) NAME, #define DEF_FUNCTION_TYPE_1(NAME, RETURN, ARG1) NAME, @@ -2917,8 +3212,8 @@ c_common_nodes_and_builtins (void) #define DEF_FUNCTION_TYPE_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME, #define DEF_FUNCTION_TYPE_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME, #define DEF_FUNCTION_TYPE_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) NAME, -#define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \ - NAME, +#define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) NAME, +#define DEF_FUNCTION_TYPE_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) NAME, #define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME, #define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME, #define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME, @@ -2936,6 +3231,113 @@ c_common_nodes_and_builtins (void) #undef DEF_FUNCTION_TYPE_4 #undef DEF_FUNCTION_TYPE_5 #undef DEF_FUNCTION_TYPE_6 +#undef DEF_FUNCTION_TYPE_7 +#undef DEF_FUNCTION_TYPE_VAR_0 +#undef DEF_FUNCTION_TYPE_VAR_1 +#undef DEF_FUNCTION_TYPE_VAR_2 +#undef DEF_FUNCTION_TYPE_VAR_3 +#undef DEF_FUNCTION_TYPE_VAR_4 +#undef DEF_FUNCTION_TYPE_VAR_5 +#undef DEF_POINTER_TYPE + BT_LAST +}; + +typedef enum c_builtin_type builtin_type; + +/* A temporary array for c_common_nodes_and_builtins. Used in + communication with def_fn_type. */ +static tree builtin_types[(int) BT_LAST + 1]; + +/* A helper function for c_common_nodes_and_builtins. Build function type + for DEF with return type RET and N arguments. If VAR is true, then the + function should be variadic after those N arguments. + + Takes special care not to ICE if any of the types involved are + error_mark_node, which indicates that said type is not in fact available + (see builtin_type_for_size). In which case the function type as a whole + should be error_mark_node. */ + +static void +def_fn_type (builtin_type def, builtin_type ret, bool var, int n, ...) +{ + tree args = NULL, t; + va_list list; + int i; + + va_start (list, n); + for (i = 0; i < n; ++i) + { + builtin_type a = va_arg (list, builtin_type); + t = builtin_types[a]; + if (t == error_mark_node) + goto egress; + args = tree_cons (NULL_TREE, t, args); + } + va_end (list); + + args = nreverse (args); + if (!var) + args = chainon (args, void_list_node); + + t = builtin_types[ret]; + if (t == error_mark_node) + goto egress; + t = build_function_type (t, args); + + egress: + builtin_types[def] = t; +} + +/* Build builtin functions common to both C and C++ language + frontends. */ + +static void +c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node) +{ +#define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \ + builtin_types[ENUM] = VALUE; +#define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \ + def_fn_type (ENUM, RETURN, 0, 0); +#define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \ + def_fn_type (ENUM, RETURN, 0, 1, ARG1); +#define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \ + def_fn_type (ENUM, RETURN, 0, 2, ARG1, ARG2); +#define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \ + def_fn_type (ENUM, RETURN, 0, 3, ARG1, ARG2, ARG3); +#define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \ + def_fn_type (ENUM, RETURN, 0, 4, ARG1, ARG2, ARG3, ARG4); +#define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \ + def_fn_type (ENUM, RETURN, 0, 5, ARG1, ARG2, ARG3, ARG4, ARG5); +#define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ + ARG6) \ + def_fn_type (ENUM, RETURN, 0, 6, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6); +#define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ + ARG6, ARG7) \ + def_fn_type (ENUM, RETURN, 0, 7, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7); +#define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \ + def_fn_type (ENUM, RETURN, 1, 0); +#define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \ + def_fn_type (ENUM, RETURN, 1, 1, ARG1); +#define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \ + def_fn_type (ENUM, RETURN, 1, 2, ARG1, ARG2); +#define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \ + def_fn_type (ENUM, RETURN, 1, 3, ARG1, ARG2, ARG3); +#define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \ + def_fn_type (ENUM, RETURN, 1, 4, ARG1, ARG2, ARG3, ARG4); +#define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \ + def_fn_type (ENUM, RETURN, 1, 5, ARG1, ARG2, ARG3, ARG4, ARG5); +#define DEF_POINTER_TYPE(ENUM, TYPE) \ + builtin_types[(int) ENUM] = build_pointer_type (builtin_types[(int) TYPE]); + +#include "builtin-types.def" + +#undef DEF_PRIMITIVE_TYPE +#undef DEF_FUNCTION_TYPE_1 +#undef DEF_FUNCTION_TYPE_2 +#undef DEF_FUNCTION_TYPE_3 +#undef DEF_FUNCTION_TYPE_4 +#undef DEF_FUNCTION_TYPE_5 +#undef DEF_FUNCTION_TYPE_6 #undef DEF_FUNCTION_TYPE_VAR_0 #undef DEF_FUNCTION_TYPE_VAR_1 #undef DEF_FUNCTION_TYPE_VAR_2 @@ -2943,12 +3345,34 @@ c_common_nodes_and_builtins (void) #undef DEF_FUNCTION_TYPE_VAR_4 #undef DEF_FUNCTION_TYPE_VAR_5 #undef DEF_POINTER_TYPE - BT_LAST - }; + builtin_types[(int) BT_LAST] = NULL_TREE; - typedef enum builtin_type builtin_type; + c_init_attributes (); - tree builtin_types[(int) BT_LAST]; +#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P, \ + NONANSI_P, ATTRS, IMPLICIT, COND) \ + if (NAME && COND) \ + 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 + + build_common_builtin_nodes (); + + targetm.init_builtins (); + if (flag_mudflap) + mudflap_init (); +} + +/* Build tree nodes and builtin functions common to both C and C++ language + frontends. */ + +void +c_common_nodes_and_builtins (void) +{ int wchar_type_size; tree array_domain_type; tree va_list_ref_type_node; @@ -3046,6 +3470,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)); @@ -3066,6 +3501,16 @@ c_common_nodes_and_builtins (void) record_builtin_type (RID_VOID, NULL, void_type_node); + /* Set the TYPE_NAME for any variants that were built before + record_builtin_type gave names to the built-in types. */ + { + tree void_name = TYPE_NAME (void_type_node); + TYPE_NAME (void_type_node) = NULL_TREE; + TYPE_NAME (build_qualified_type (void_type_node, TYPE_QUAL_CONST)) + = void_name; + TYPE_NAME (void_type_node) = void_name; + } + /* This node must not be shared. */ void_zero_node = make_node (INTEGER_CST); TREE_TYPE (void_zero_node) = void_type_node; @@ -3144,214 +3589,8 @@ c_common_nodes_and_builtins (void) va_list_ref_type_node = build_reference_type (va_list_type_node); } -#define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \ - builtin_types[(int) ENUM] = VALUE; -#define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \ - builtin_types[(int) ENUM] \ - = build_function_type (builtin_types[(int) RETURN], \ - void_list_node); -#define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \ - builtin_types[(int) ENUM] \ - = build_function_type (builtin_types[(int) RETURN], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG1], \ - void_list_node)); -#define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \ - builtin_types[(int) ENUM] \ - = build_function_type \ - (builtin_types[(int) RETURN], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG1], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG2], \ - void_list_node))); -#define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \ - builtin_types[(int) ENUM] \ - = build_function_type \ - (builtin_types[(int) RETURN], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG1], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG2], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG3], \ - void_list_node)))); -#define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \ - builtin_types[(int) ENUM] \ - = build_function_type \ - (builtin_types[(int) RETURN], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG1], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG2], \ - tree_cons \ - (NULL_TREE, \ - builtin_types[(int) ARG3], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG4], \ - void_list_node))))); -#define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \ - builtin_types[(int) ENUM] \ - = build_function_type \ - (builtin_types[(int) RETURN], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG1], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG2], \ - tree_cons \ - (NULL_TREE, \ - builtin_types[(int) ARG3], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG4], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG5],\ - void_list_node)))))); -#define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ - ARG6) \ - builtin_types[(int) ENUM] \ - = build_function_type \ - (builtin_types[(int) RETURN], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG1], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG2], \ - tree_cons \ - (NULL_TREE, \ - builtin_types[(int) ARG3], \ - tree_cons \ - (NULL_TREE, \ - builtin_types[(int) ARG4], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG5], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG6],\ - void_list_node))))))); -#define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \ - builtin_types[(int) ENUM] \ - = build_function_type (builtin_types[(int) RETURN], NULL_TREE); -#define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \ - builtin_types[(int) ENUM] \ - = build_function_type (builtin_types[(int) RETURN], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG1], \ - NULL_TREE)); - -#define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \ - builtin_types[(int) ENUM] \ - = build_function_type \ - (builtin_types[(int) RETURN], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG1], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG2], \ - NULL_TREE))); - -#define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \ - builtin_types[(int) ENUM] \ - = build_function_type \ - (builtin_types[(int) RETURN], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG1], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG2], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG3], \ - NULL_TREE)))); - -#define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \ - builtin_types[(int) ENUM] \ - = build_function_type \ - (builtin_types[(int) RETURN], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG1], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG2], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG3], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG4],\ - NULL_TREE))))); - -#define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, \ - ARG5) \ - builtin_types[(int) ENUM] \ - = build_function_type \ - (builtin_types[(int) RETURN], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG1], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG2], \ - tree_cons \ - (NULL_TREE, \ - builtin_types[(int) ARG3], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG4], \ - tree_cons (NULL_TREE, \ - builtin_types[(int) ARG5],\ - NULL_TREE)))))); - -#define DEF_POINTER_TYPE(ENUM, TYPE) \ - builtin_types[(int) ENUM] \ - = build_pointer_type (builtin_types[(int) TYPE]); -#include "builtin-types.def" -#undef DEF_PRIMITIVE_TYPE -#undef DEF_FUNCTION_TYPE_1 -#undef DEF_FUNCTION_TYPE_2 -#undef DEF_FUNCTION_TYPE_3 -#undef DEF_FUNCTION_TYPE_4 -#undef DEF_FUNCTION_TYPE_5 -#undef DEF_FUNCTION_TYPE_6 -#undef DEF_FUNCTION_TYPE_VAR_0 -#undef DEF_FUNCTION_TYPE_VAR_1 -#undef DEF_FUNCTION_TYPE_VAR_2 -#undef DEF_FUNCTION_TYPE_VAR_3 -#undef DEF_FUNCTION_TYPE_VAR_4 -#undef DEF_FUNCTION_TYPE_VAR_5 -#undef DEF_POINTER_TYPE - - 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; \ - } -#include "builtins.def" -#undef DEF_BUILTIN - - build_common_builtin_nodes (); - - targetm.init_builtins (); - if (flag_mudflap) - mudflap_init (); + if (!flag_preprocess_only) + c_define_builtins (va_list_ref_type_node, va_list_arg_type_node); main_identifier_node = get_identifier ("main"); @@ -3359,6 +3598,9 @@ c_common_nodes_and_builtins (void) not shared. */ null_node = make_node (INTEGER_CST); TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0); + + /* Since builtin_types isn't gc'ed, don't export these nodes. */ + memset (builtin_types, 0, sizeof (builtin_types)); } /* Look up the function in built_in_decls that corresponds to DECL @@ -3381,6 +3623,21 @@ set_builtin_user_assembler_name (tree decl, const char *asmspec) init_block_clear_fn (asmspec); } +/* The number of named compound-literals generated thus far. */ +static GTY(()) int compound_literal_number; + +/* Set DECL_NAME for DECL, a VAR_DECL for a compound-literal. */ + +void +set_compound_literal_name (tree decl) +{ + char *name; + ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal", + compound_literal_number); + compound_literal_number++; + DECL_NAME (decl) = get_identifier (name); +} + tree build_va_arg (tree expr, tree type) { @@ -3433,42 +3690,42 @@ 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; + tree decl; + const char *libname; + + if (fntype == error_mark_node) + return; - if (builtin_name != 0) - bdecl = lang_hooks.builtin_function (builtin_name, builtin_type, - function_code, cl, - library_name_p ? name : NULL, attrs); + gcc_assert ((!both_p && !fallback_p) + || !strncmp (name, "__builtin_", + strlen ("__builtin_"))); - if (name != 0 && !flag_no_builtin && !builtin_function_disabled_p (name) + libname = name + strlen ("__builtin_"); + decl = add_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); + add_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 @@ -3512,6 +3769,9 @@ self_promoting_args_p (tree parms) { tree type = TREE_VALUE (t); + if (type == error_mark_node) + continue; + if (TREE_CHAIN (t) == 0 && type != void_type_node) return 0; @@ -3610,25 +3870,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, @@ -3754,6 +4016,9 @@ match_case_to_enum_1 (tree key, tree type, tree label) CASE_LABEL (label), buf, type); } +/* Subroutine of c_do_switch_warnings, called via splay_tree_foreach. + Used to verify that case values match up with enumerator values. */ + static int match_case_to_enum (splay_tree_node node, void *data) { @@ -3764,26 +4029,22 @@ match_case_to_enum (splay_tree_node node, void *data) if (!CASE_LOW (label)) return 0; - /* If TREE_ADDRESSABLE is not set, that means CASE_LOW did not appear + /* If CASE_LOW_SEEN is not set, that means CASE_LOW did not appear when we did our enum->case scan. Reset our scratch bit after. */ - if (!TREE_ADDRESSABLE (label)) + if (!CASE_LOW_SEEN (label)) match_case_to_enum_1 (CASE_LOW (label), type, label); else - TREE_ADDRESSABLE (label) = 0; + CASE_LOW_SEEN (label) = 0; - /* If CASE_HIGH is non-null, we have a range. Here we must search. - Note that the old code in stmt.c did not check for the values in - the range either, just the endpoints. */ + /* If CASE_HIGH is non-null, we have a range. If CASE_HIGH_SEEN is + not set, that means that CASE_HIGH did not appear when we did our + enum->case scan. Reset our scratch bit after. */ if (CASE_HIGH (label)) { - tree chain, key = CASE_HIGH (label); - - for (chain = TYPE_VALUES (type); - chain && !tree_int_cst_equal (key, TREE_VALUE (chain)); - chain = TREE_CHAIN (chain)) - continue; - if (!chain) - match_case_to_enum_1 (key, type, label); + if (!CASE_HIGH_SEEN (label)) + match_case_to_enum_1 (CASE_HIGH (label), type, label); + else + CASE_HIGH_SEEN (label) = 0; } return 0; @@ -3801,6 +4062,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location, tree type, tree cond) { splay_tree_node default_node; + splay_tree_node node; + tree chain; if (!warn_switch && !warn_switch_enum && !warn_switch_default) return; @@ -3810,54 +4073,79 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location, warning (OPT_Wswitch_default, "%Hswitch missing default case", &switch_location); + /* From here on, we only care about about enumerated types. */ + if (!type || TREE_CODE (type) != ENUMERAL_TYPE) + return; + /* If the switch expression was an enumerated type, check that exactly all enumeration literals are covered by the cases. The check is made when -Wswitch was specified and there is no default case, or when -Wswitch-enum was specified. */ - if (((warn_switch && !default_node) || warn_switch_enum) - && type && TREE_CODE (type) == ENUMERAL_TYPE - && TREE_CODE (cond) != INTEGER_CST) - { - tree chain; - /* The time complexity here is O(N*lg(N)) worst case, but for the - common case of monotonically increasing enumerators, it is - O(N), since the nature of the splay tree will keep the next - element adjacent to the root at all times. */ + if (!warn_switch_enum + && !(warn_switch && !default_node)) + return; + + /* Clearing COND if it is not an integer constant simplifies + the tests inside the loop below. */ + if (TREE_CODE (cond) != INTEGER_CST) + cond = NULL_TREE; - for (chain = TYPE_VALUES (type); chain; chain = TREE_CHAIN (chain)) + /* The time complexity here is O(N*lg(N)) worst case, but for the + common case of monotonically increasing enumerators, it is + O(N), since the nature of the splay tree will keep the next + element adjacent to the root at all times. */ + + for (chain = TYPE_VALUES (type); chain; chain = TREE_CHAIN (chain)) + { + tree value = TREE_VALUE (chain); + node = splay_tree_lookup (cases, (splay_tree_key) value); + if (node) { - splay_tree_node node - = splay_tree_lookup (cases, (splay_tree_key) TREE_VALUE (chain)); + /* Mark the CASE_LOW part of the case entry as seen. */ + tree label = (tree) node->value; + CASE_LOW_SEEN (label) = 1; + continue; + } - if (node) - { - /* Mark the CASE_LOW part of the case entry as seen, so - that we save time later. Choose TREE_ADDRESSABLE - randomly as a bit that won't have been set to-date. */ - tree label = (tree) node->value; - TREE_ADDRESSABLE (label) = 1; - } - else + /* Even though there wasn't an exact match, there might be a + case range which includes the enumator's value. */ + node = splay_tree_predecessor (cases, (splay_tree_key) value); + if (node && CASE_HIGH ((tree) node->value)) + { + tree label = (tree) node->value; + int cmp = tree_int_cst_compare (CASE_HIGH (label), value); + if (cmp >= 0) { - /* Warn if there are enumerators that don't correspond to - case expressions. */ - warning (0, "%Henumeration value %qE not handled in switch", - &switch_location, TREE_PURPOSE (chain)); + /* If we match the upper bound exactly, mark the CASE_HIGH + part of the case entry as seen. */ + if (cmp == 0) + CASE_HIGH_SEEN (label) = 1; + continue; } } - /* Warn if there are case expressions that don't correspond to - enumerators. This can occur since C and C++ don't enforce - type-checking of assignments to enumeration variables. + /* We've now determined that this enumerated literal isn't + handled by the case labels of the switch statement. */ - The time complexity here is O(N**2) worst case, since we've - not sorted the enumeration values. However, in the absence - of case ranges this is O(N), since all single cases that - corresponded to enumerations have been marked above. */ + /* If the switch expression is a constant, we only really care + about whether that constant is handled by the switch. */ + if (cond && tree_int_cst_compare (cond, value)) + continue; - splay_tree_foreach (cases, match_case_to_enum, type); + warning (0, "%Henumeration value %qE not handled in switch", + &switch_location, TREE_PURPOSE (chain)); } + + /* Warn if there are case expressions that don't correspond to + enumerators. This can occur since C and C++ don't enforce + type-checking of assignments to enumeration variables. + + The time complexity here is now always O(N) worst case, since + we should have marked both the lower bound and upper bound of + every disjoint case label, with CASE_LOW_SEEN and CASE_HIGH_SEEN + above. This scan also resets those fields. */ + splay_tree_foreach (cases, match_case_to_enum, type); } /* Finish an expression taking the address of LABEL (an @@ -4014,24 +4302,16 @@ handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args), if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) *node = build_variant_type_copy (*node); TYPE_PACKED (*node) = 1; - if (TYPE_MAIN_VARIANT (*node) == *node) - { - /* If it is the main variant, then pack the other variants - too. This happens in, - - struct Foo { - struct Foo const *ptr; // creates a variant w/o packed flag - } __ 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 @@ -4151,6 +4431,51 @@ handle_always_inline_attribute (tree *node, tree name, return NULL_TREE; } +/* Handle a "gnu_inline" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_gnu_inline_attribute (tree *node, tree name, + tree ARG_UNUSED (args), + int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (*node)) + { + /* Do nothing else, just set the attribute. We'll get at + it later with lookup_attribute. */ + } + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "flatten" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_flatten_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_DECL) + /* Do nothing else, just set the attribute. We'll get at + it later with lookup_attribute. */ + ; + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + + /* Handle a "used" attribute; arguments as in struct attribute_spec.handler. */ @@ -4219,26 +4544,15 @@ handle_externally_visible_attribute (tree *pnode, tree name, { tree node = *pnode; - if ((!TREE_STATIC (node) && TREE_CODE (node) != FUNCTION_DECL) - || !TREE_PUBLIC (node)) - { - warning (OPT_Wattributes, - "%qE attribute have effect only on public objects", name); - *no_add_attrs = true; - } - else if (TREE_CODE (node) == FUNCTION_DECL) - { - struct cgraph_node *n = cgraph_node (node); - n->local.externally_visible = true; - if (n->local.finalized) - cgraph_mark_needed_node (n); - } - else if (TREE_CODE (node) == VAR_DECL) + if (TREE_CODE (node) == FUNCTION_DECL || TREE_CODE (node) == VAR_DECL) { - struct cgraph_varpool_node *n = cgraph_varpool_node (node); - n->externally_visible = true; - if (n->finalized) - cgraph_varpool_mark_needed_node (n); + if ((!TREE_STATIC (node) && TREE_CODE (node) != FUNCTION_DECL + && !DECL_EXTERNAL (node)) || !TREE_PUBLIC (node)) + { + warning (OPT_Wattributes, + "%qE attribute have effect only on public objects", name); + *no_add_attrs = true; + } } else { @@ -4284,39 +4598,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; } @@ -4436,6 +4754,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; @@ -4472,14 +4791,14 @@ handle_mode_attribute (tree *node, tree name, tree args, return NULL_TREE; } - if (TREE_CODE (type) == POINTER_TYPE) + if (TREE_CODE (type) == POINTER_TYPE) fn = build_pointer_type_for_mode; else fn = build_reference_type_for_mode; typefm = fn (TREE_TYPE (type), mode, false); } else - typefm = lang_hooks.types.type_for_mode (mode, TYPE_UNSIGNED (type)); + typefm = lang_hooks.types.type_for_mode (mode, TYPE_UNSIGNED (type)); if (typefm == NULL_TREE) { @@ -4497,21 +4816,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)) @@ -4559,8 +4881,8 @@ handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args, && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)), TREE_STRING_POINTER (TREE_VALUE (args))) != 0) { - error ("%Jsection of %qD conflicts with previous declaration", - *node, *node); + error ("section of %q+D conflicts with previous declaration", + *node); *no_add_attrs = true; } else @@ -4568,7 +4890,7 @@ handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args, } else { - error ("%Jsection attribute not allowed for %qD", *node, *node); + error ("section attribute not allowed for %q+D", *node); *no_add_attrs = true; } } @@ -4642,7 +4964,7 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args, else if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FIELD_DECL) { - error ("%Jalignment may not be specified for %qD", decl, decl); + error ("alignment may not be specified for %q+D", decl); *no_add_attrs = true; } else @@ -4658,12 +4980,17 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args, struct attribute_spec.handler. */ static tree -handle_weak_attribute (tree *node, tree ARG_UNUSED (name), +handle_weak_attribute (tree *node, tree name, tree ARG_UNUSED (args), int ARG_UNUSED (flags), bool * ARG_UNUSED (no_add_attrs)) { - declare_weak (*node); + if (TREE_CODE (*node) == FUNCTION_DECL + || TREE_CODE (*node) == VAR_DECL) + declare_weak (*node); + else + warning (OPT_Wattributes, "%qE attribute ignored", name); + return NULL_TREE; } @@ -4678,9 +5005,14 @@ 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))) - { - error ("%J%qD defined both normally and as an alias", decl, 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; } @@ -4708,7 +5040,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; } } @@ -4721,27 +5056,81 @@ 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; + + /* We must ignore the attribute when it is associated with + local-scoped decls, since attribute alias is ignored and many + such symbols do not even have a DECL_WEAK field. */ + if (decl_function_context (*node) || current_function_decl) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + return 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. */ static tree handle_visibility_attribute (tree *node, tree name, tree args, int ARG_UNUSED (flags), - bool *no_add_attrs) + bool *ARG_UNUSED (no_add_attrs)) { tree decl = *node; tree id = TREE_VALUE (args); - - *no_add_attrs = true; + enum symbol_visibility vis; if (TYPE_P (*node)) { - if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE) - { - warning (OPT_Wattributes, "%qE attribute ignored on non-class types", - name); - return NULL_TREE; - } + if (TREE_CODE (*node) == ENUMERAL_TYPE) + /* OK */; + else if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE) + { + warning (OPT_Wattributes, "%qE attribute ignored on non-class types", + name); + return NULL_TREE; + } + else if (TYPE_FIELDS (*node)) + { + error ("%qE attribute ignored because %qT is already defined", + name, *node); + return NULL_TREE; + } } else if (decl_function_context (decl) != 0 || !TREE_PUBLIC (decl)) { @@ -4760,7 +5149,7 @@ handle_visibility_attribute (tree *node, tree name, tree args, { decl = TYPE_NAME (decl); if (!decl) - return NULL_TREE; + return NULL_TREE; if (TREE_CODE (decl) == IDENTIFIER_NODE) { warning (OPT_Wattributes, "%qE attribute ignored on types", @@ -4770,23 +5159,33 @@ handle_visibility_attribute (tree *node, tree name, tree args, } if (strcmp (TREE_STRING_POINTER (id), "default") == 0) - DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; + vis = VISIBILITY_DEFAULT; else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0) - DECL_VISIBILITY (decl) = VISIBILITY_INTERNAL; + vis = VISIBILITY_INTERNAL; else if (strcmp (TREE_STRING_POINTER (id), "hidden") == 0) - DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; + vis = VISIBILITY_HIDDEN; else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0) - DECL_VISIBILITY (decl) = VISIBILITY_PROTECTED; + vis = VISIBILITY_PROTECTED; else - error ("visibility argument must be one of \"default\", \"hidden\", \"protected\" or \"internal\""); + { + error ("visibility argument must be one of \"default\", \"hidden\", \"protected\" or \"internal\""); + vis = VISIBILITY_DEFAULT; + } + + if (DECL_VISIBILITY_SPECIFIED (decl) + && vis != DECL_VISIBILITY (decl) + && lookup_attribute ("visibility", (TYPE_P (*node) + ? TYPE_ATTRIBUTES (*node) + : DECL_ATTRIBUTES (decl)))) + error ("%qD redeclared with different visibility", decl); + + DECL_VISIBILITY (decl) = vis; DECL_VISIBILITY_SPECIFIED (decl) = 1; - /* For decls only, go ahead and attach the attribute to the node as well. - This is needed so we can determine whether we have VISIBILITY_DEFAULT - because the visibility was not specified, or because it was explicitly - overridden from the class visibility. */ - if (DECL_P (*node)) - *no_add_attrs = false; + /* Go ahead and attach the attribute to the node as well. This is needed + so we can determine whether we have VISIBILITY_DEFAULT because the + visibility was not specified, or because it was explicitly overridden + from the containing scope. */ return NULL_TREE; } @@ -4823,6 +5222,13 @@ c_determine_visibility (tree decl) return true; } + /* Set default visibility to whatever the user supplied with + visibility_specified depending on #pragma GCC visibility. */ + if (!DECL_VISIBILITY_SPECIFIED (decl)) + { + DECL_VISIBILITY (decl) = default_visibility; + DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma; + } return false; } @@ -5090,7 +5496,9 @@ 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 + || TREE_CODE (type) == UNION_TYPE + || TREE_CODE (type) == VECTOR_TYPE + || (!SCALAR_FLOAT_MODE_P (orig_mode) && GET_MODE_CLASS (orig_mode) != MODE_INT) || !host_integerp (TYPE_SIZE_UNIT (type), 1)) { @@ -5098,6 +5506,18 @@ handle_vector_size_attribute (tree *node, tree name, tree args, return NULL_TREE; } + if (vecsize % tree_low_cst (TYPE_SIZE_UNIT (type), 1)) + { + error ("vector size not an integral multiple of component size"); + return NULL; + } + + if (vecsize == 0) + { + error ("zero vector size"); + return NULL; + } + /* Calculate how many units fit in the vector. */ nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1); if (nunits & (nunits - 1)) @@ -5206,11 +5626,11 @@ check_function_nonnull (tree attrs, tree params) param_num++, param = TREE_CHAIN (param)) { if (!param) - break; + break; if (!args || nonnull_check_p (args, param_num)) - check_function_arguments_recurse (check_nonnull_arg, NULL, - TREE_VALUE (param), - param_num); + check_function_arguments_recurse (check_nonnull_arg, NULL, + TREE_VALUE (param), + param_num); } } } @@ -5232,14 +5652,15 @@ check_function_sentinel (tree attrs, tree params, tree typelist) typelist = TREE_CHAIN (typelist); params = TREE_CHAIN (params); } - + 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; unsigned pos = 0; - + if (TREE_VALUE (attr)) { tree p = TREE_VALUE (TREE_VALUE (attr)); @@ -5256,7 +5677,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; } @@ -5275,9 +5697,9 @@ check_function_sentinel (tree attrs, tree params, tree typelist) as wide as a pointer, and we don't want to force users to cast the NULL they have written there. We warn with -Wstrict-null-sentinel, though. */ - && (warn_strict_null_sentinel + && (warn_strict_null_sentinel || null_node != TREE_VALUE (sentinel))) - warning (0, "missing sentinel in function call"); + warning (OPT_Wformat, "missing sentinel in function call"); } } } @@ -5319,8 +5741,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 @@ -5439,24 +5861,24 @@ handle_sentinel_attribute (tree *node, tree name, tree args, params = TREE_CHAIN (params); if (VOID_TYPE_P (TREE_VALUE (params))) - { + { warning (OPT_Wattributes, "%qE attribute only applies to variadic functions", name); *no_add_attrs = true; } } - + if (args) { tree position = TREE_VALUE (args); if (TREE_CODE (position) != INTEGER_CST) - { + { warning (0, "requested position is not an integer constant"); *no_add_attrs = true; } else - { + { if (tree_int_cst_lt (position, integer_zero_node)) { warning (0, "requested position is less than zero"); @@ -5464,7 +5886,7 @@ handle_sentinel_attribute (tree *node, tree name, tree args, } } } - + return NULL_TREE; } @@ -5480,11 +5902,11 @@ check_function_arguments (tree attrs, tree params, tree typelist) /* Check for errors in format strings. */ - if (warn_format) - { + if (warn_format || warn_missing_format_attribute) check_function_format (attrs, params); - check_function_sentinel (attrs, params, typelist); - } + + if (warn_format) + check_function_sentinel (attrs, params, typelist); } /* Generic argument checking recursion routine. PARAM is the argument to @@ -5496,7 +5918,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, @@ -5667,9 +6091,9 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token, tree value) unsigned int val = TREE_INT_CST_LOW (value); const char *const ell = (token == CPP_CHAR) ? "" : "L"; if (val <= UCHAR_MAX && ISGRAPH (val)) - message = catenate_messages (gmsgid, " before %s'%c'"); + message = catenate_messages (gmsgid, " before %s'%c'"); else - message = catenate_messages (gmsgid, " before %s'\\x%x'"); + message = catenate_messages (gmsgid, " before %s'\\x%x'"); error (message, ell, val); free (message); @@ -5686,6 +6110,10 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token, tree value) free (message); message = NULL; } + else if (token == CPP_PRAGMA) + message = catenate_messages (gmsgid, " before %<#pragma%>"); + else if (token == CPP_PRAGMA_EOL) + message = catenate_messages (gmsgid, " before end of line"); else if (token < N_TTYPES) { message = catenate_messages (gmsgid, " before %qs token"); @@ -5701,7 +6129,7 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token, tree value) error (message); free (message); } -#undef catenate_messages +#undef catenate_messages } /* Walk a gimplified function and warn for functions whose return value is @@ -5799,26 +6227,44 @@ c_common_to_target_charset (HOST_WIDE_INT c) } /* Build the result of __builtin_offsetof. EXPR is a nested sequence of - component references, with an INDIRECT_REF at the bottom; much like - the traditional rendering of offsetof as a macro. Returns the folded - and properly cast result. */ + component references, with STOP_REF, or alternatively an INDIRECT_REF of + NULL, at the bottom; much like the traditional rendering of offsetof as a + macro. Returns the folded and properly cast result. */ static tree -fold_offsetof_1 (tree expr) +fold_offsetof_1 (tree expr, tree stop_ref) { enum tree_code code = PLUS_EXPR; tree base, off, t; + if (expr == stop_ref && TREE_CODE (expr) != ERROR_MARK) + return size_zero_node; + switch (TREE_CODE (expr)) { case ERROR_MARK: return expr; - case INDIRECT_REF: + case VAR_DECL: + error ("cannot apply % to static data member %qD", expr); + return error_mark_node; + + case CALL_EXPR: + error ("cannot apply % when % is overloaded"); + return error_mark_node; + + case INTEGER_CST: + gcc_assert (integer_zerop (expr)); return size_zero_node; + case NOP_EXPR: + case INDIRECT_REF: + base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref); + gcc_assert (base == error_mark_node || base == size_zero_node); + return base; + case COMPONENT_REF: - base = fold_offsetof_1 (TREE_OPERAND (expr, 0)); + base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref); if (base == error_mark_node) return base; @@ -5835,7 +6281,7 @@ fold_offsetof_1 (tree expr) break; case ARRAY_REF: - base = fold_offsetof_1 (TREE_OPERAND (expr, 0)); + base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref); if (base == error_mark_node) return base; @@ -5857,10 +6303,10 @@ fold_offsetof_1 (tree expr) } tree -fold_offsetof (tree expr) +fold_offsetof (tree expr, tree stop_ref) { /* Convert back from the internal sizetype to size_t. */ - return convert (size_type_node, fold_offsetof_1 (expr)); + return convert (size_type_node, fold_offsetof_1 (expr, stop_ref)); } /* Print an error message for an invalid lvalue. USE says @@ -5872,19 +6318,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 (); @@ -5901,6 +6347,7 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default) { tree maxindex, type, main_type, elt, unqual_elt; int failure = 0, quals; + hashval_t hashcode = 0; maxindex = size_zero_node; if (initial_value) @@ -5913,9 +6360,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; @@ -5924,15 +6371,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); @@ -5971,6 +6424,12 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default) TYPE_DOMAIN (main_type) = build_index_type (maxindex); layout_type (main_type); + /* Make sure we have the canonical MAIN_TYPE. */ + hashcode = iterative_hash_object (TYPE_HASH (unqual_elt), hashcode); + hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (main_type)), + hashcode); + main_type = type_hash_canon (hashcode, main_type); + if (quals == 0) type = main_type; else @@ -6019,7 +6478,7 @@ sync_resolve_size (tree function, tree params) goto incompatible; size = tree_low_cst (TYPE_SIZE_UNIT (type), 1); - if (size == 1 || size == 2 || size == 4 || size == 8) + if (size == 1 || size == 2 || size == 4 || size == 8 || size == 16) return size; incompatible: @@ -6027,7 +6486,7 @@ sync_resolve_size (tree function, tree params) return 0; } -/* A helper function for resolve_overloaded_builtin. Adds casts to +/* A helper function for resolve_overloaded_builtin. Adds casts to PARAMS to make arguments match up with those of FUNCTION. Drops the variadic arguments at the end. Returns false if some error was encountered; true on success. */ @@ -6080,7 +6539,7 @@ sync_resolve_params (tree orig_function, tree function, tree params) return true; } -/* A helper function for resolve_overloaded_builtin. Adds a cast to +/* A helper function for resolve_overloaded_builtin. Adds a cast to RESULT to make it match the type of the first pointer argument in PARAMS. */ @@ -6088,6 +6547,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); } @@ -6110,13 +6570,13 @@ resolve_overloaded_builtin (tree function, tree params) break; case BUILT_IN_MD: if (targetm.resolve_overloaded_builtin) - return targetm.resolve_overloaded_builtin (function, params); + return targetm.resolve_overloaded_builtin (function, params); else - return NULL_TREE; + return NULL_TREE; default: return NULL_TREE; } - + /* Handle BUILT_IN_NORMAL here. */ switch (orig_code) { @@ -6175,4 +6635,141 @@ 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 %"); +} + +/* Implement -Wparentheses for the unexpected C precedence rules, to + cover cases like x + y << z which readers are likely to + misinterpret. We have seen an expression in which CODE is a binary + operator used to combine expressions headed by CODE_LEFT and + CODE_RIGHT. CODE_LEFT and CODE_RIGHT may be ERROR_MARK, which + means that that side of the expression was not formed using a + binary operator, or it was enclosed in parentheses. */ + +void +warn_about_parentheses (enum tree_code code, enum tree_code code_left, + enum tree_code code_right) +{ + if (!warn_parentheses) + return; + + if (code == LSHIFT_EXPR || code == RSHIFT_EXPR) + { + if (code_left == PLUS_EXPR || code_left == MINUS_EXPR + || code_right == PLUS_EXPR || code_right == MINUS_EXPR) + warning (OPT_Wparentheses, + "suggest parentheses around + or - inside shift"); + } + + if (code == TRUTH_ORIF_EXPR) + { + if (code_left == TRUTH_ANDIF_EXPR + || code_right == TRUTH_ANDIF_EXPR) + warning (OPT_Wparentheses, + "suggest parentheses around && within ||"); + } + + if (code == BIT_IOR_EXPR) + { + if (code_left == BIT_AND_EXPR || code_left == BIT_XOR_EXPR + || code_left == PLUS_EXPR || code_left == MINUS_EXPR + || code_right == BIT_AND_EXPR || code_right == BIT_XOR_EXPR + || code_right == PLUS_EXPR || code_right == MINUS_EXPR) + warning (OPT_Wparentheses, + "suggest parentheses around arithmetic in operand of |"); + /* Check cases like x|y==z */ + if (TREE_CODE_CLASS (code_left) == tcc_comparison + || TREE_CODE_CLASS (code_right) == tcc_comparison) + warning (OPT_Wparentheses, + "suggest parentheses around comparison in operand of |"); + } + + if (code == BIT_XOR_EXPR) + { + if (code_left == BIT_AND_EXPR + || code_left == PLUS_EXPR || code_left == MINUS_EXPR + || code_right == BIT_AND_EXPR + || code_right == PLUS_EXPR || code_right == MINUS_EXPR) + warning (OPT_Wparentheses, + "suggest parentheses around arithmetic in operand of ^"); + /* Check cases like x^y==z */ + if (TREE_CODE_CLASS (code_left) == tcc_comparison + || TREE_CODE_CLASS (code_right) == tcc_comparison) + warning (OPT_Wparentheses, + "suggest parentheses around comparison in operand of ^"); + } + + if (code == BIT_AND_EXPR) + { + if (code_left == PLUS_EXPR || code_left == MINUS_EXPR + || code_right == PLUS_EXPR || code_right == MINUS_EXPR) + warning (OPT_Wparentheses, + "suggest parentheses around + or - in operand of &"); + /* Check cases like x&y==z */ + if (TREE_CODE_CLASS (code_left) == tcc_comparison + || TREE_CODE_CLASS (code_right) == tcc_comparison) + warning (OPT_Wparentheses, + "suggest parentheses around comparison in operand of &"); + } + + /* Similarly, check for cases like 1<=i<=10 that are probably errors. */ + if (TREE_CODE_CLASS (code) == tcc_comparison + && (TREE_CODE_CLASS (code_left) == tcc_comparison + || TREE_CODE_CLASS (code_right) == tcc_comparison)) + warning (OPT_Wparentheses, "comparisons like X<=Y<=Z do not " + "have their mathematical meaning"); +} + +/* If LABEL (a LABEL_DECL) has not been used, issue a warning. */ + +void +warn_for_unused_label (tree label) +{ + if (!TREE_USED (label)) + { + if (DECL_INITIAL (label)) + warning (OPT_Wunused_label, "label %q+D defined but not used", label); + else + warning (OPT_Wunused_label, "label %q+D declared but not defined", label); + } +} + #include "gt-c-common.h"