diff options
Diffstat (limited to 'gcc/c/c-decl.cc')
| -rw-r--r-- | gcc/c/c-decl.cc | 1563 |
1 files changed, 894 insertions, 669 deletions
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 1ae5208..e79f77e 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -71,7 +71,8 @@ enum decl_context FUNCDEF, /* Function definition */ PARM, /* Declaration of parm before function body */ FIELD, /* Declaration inside struct or union */ - TYPENAME}; /* Typename (inside cast or sizeof) */ + TYPENAME, /* Typename (inside cast or sizeof) */ + GENERIC_ASSOC }; /* Typename in generic association */ /* States indicating how grokdeclarator() should handle declspecs marked with __attribute__((deprecated)) or __attribute__((unavailable)). @@ -163,6 +164,9 @@ vec<c_omp_declare_target_attr, va_gc> *current_omp_declare_target_attribute; we are in. */ vec<c_omp_begin_assumes_data, va_gc> *current_omp_begin_assumes; +/* Vector of "omp begin/end declare variant" blocks we are in. */ +vec<c_omp_declare_variant_attr, va_gc> *current_omp_declare_variant_attribute; + /* Vector of loop names with C_DECL_LOOP_NAME or C_DECL_SWITCH_NAME marked LABEL_DECL as the last and canonical for each loop or switch. */ static vec<tree> loop_names; @@ -504,10 +508,8 @@ struct GTY((chain_next ("%h.outer"))) c_scope { if these appears in a function definition. */ BOOL_BITFIELD had_vla_unspec : 1; - /* True if we already complained about forward parameter decls - in this scope. This prevents double warnings on - foo (int a; int b; ...) */ - BOOL_BITFIELD warned_forward_parm_decls : 1; + /* True if we parsed a list of forward parameter decls in this scope. */ + BOOL_BITFIELD had_forward_parm_decls : 1; /* True if this is the outermost block scope of a function body. This scope contains the parameters, the local variables declared @@ -659,7 +661,8 @@ c_struct_hasher::hash (tree type) inchash::hash hstate; hstate.add_int (TREE_CODE (type)); - hstate.add_object (TYPE_NAME (type)); + tree tag = c_type_tag (type); + hstate.add_object (tag); return hstate.end (); } @@ -909,8 +912,12 @@ c_finish_incomplete_decl (tree decl) && !DECL_EXTERNAL (decl) && TYPE_DOMAIN (type) == NULL_TREE) { - warning_at (DECL_SOURCE_LOCATION (decl), - 0, "array %q+D assumed to have one element", decl); + if (flag_isoc2y && !TREE_PUBLIC (decl)) + error_at (DECL_SOURCE_LOCATION (decl), + "array size missing in %q+D", decl); + else + warning_at (DECL_SOURCE_LOCATION (decl), + 0, "array %q+D assumed to have one element", decl); complete_array_type (&TREE_TYPE (decl), NULL_TREE, true); @@ -1362,7 +1369,7 @@ pop_scope (void) case VAR_DECL: /* Warnings for unused variables. */ if ((!TREE_USED (p) || !DECL_READ_P (p)) - && !warning_suppressed_p (p, OPT_Wunused_but_set_variable) + && !warning_suppressed_p (p, OPT_Wunused_but_set_variable_) && !DECL_IN_SYSTEM_HEADER (p) && DECL_NAME (p) && !DECL_ARTIFICIAL (p) @@ -1376,7 +1383,7 @@ pop_scope (void) } else if (DECL_CONTEXT (p) == current_function_decl) warning_at (DECL_SOURCE_LOCATION (p), - OPT_Wunused_but_set_variable, + OPT_Wunused_but_set_variable_, "variable %qD set but not used", p); } @@ -1725,8 +1732,8 @@ pushtag (location_t loc, tree name, tree type) { auto_diagnostic_group d; if (warning_at (loc, OPT_Wc___compat, - ("using %qD as both a typedef and a tag is " - "invalid in C++"), b->decl) + "using %qD as both a typedef and a tag is " + "invalid in C++", b->decl) && b->locus != UNKNOWN_LOCATION) inform (b->locus, "originally defined here"); } @@ -2073,7 +2080,7 @@ static tree previous_tag (tree type) { struct c_binding *b = NULL; - tree name = TYPE_NAME (type); + tree name = c_type_tag (type); if (name) b = I_TAG_BINDING (name); @@ -2087,6 +2094,35 @@ previous_tag (tree type) return NULL_TREE; } +/* Subroutine to mark functions as versioned when using the attribute + 'target_version'. */ + +static void +maybe_mark_function_versioned (tree decl) +{ + if (!DECL_FUNCTION_VERSIONED (decl)) + { + /* Check if the name of the function has been overridden. */ + if (DECL_ASSEMBLER_NAME_SET_P (decl) + && IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))[0] == '*') + error_at (DECL_SOURCE_LOCATION (decl), + "cannot use function multiversioning on a renamed function"); + + /* We need to insert function version now to make sure the correct + pre-mangled assembler name is recorded. */ + cgraph_node *node = cgraph_node::get_create (decl); + + if (!node->function_version ()) + node->insert_new_function_version (); + + DECL_FUNCTION_VERSIONED (decl) = 1; + + tree mangled_name + = targetm.mangle_decl_assembler_name (decl, DECL_NAME (decl)); + SET_DECL_ASSEMBLER_NAME (decl, mangled_name); + } +} + /* Subroutine of duplicate_decls. Compare NEWDECL to OLDDECL. Returns true if the caller should proceed to merge the two, false if OLDDECL should simply be discarded. As a side effect, issues @@ -2304,10 +2340,40 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, error ("conflicting type qualifiers for %q+D", newdecl); } else - error ("conflicting types for %q+D; have %qT", newdecl, newtype); - diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype); - locate_old_decl (olddecl); - return false; + { + if (TREE_CODE (olddecl) == FUNCTION_DECL) + { + tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (olddecl)); + if (attrs && !TYPE_ATTRIBUTES (TREE_TYPE (newdecl))) + { + /* Similar to the C++ front-end, for FUNCTION_DECL, + if OLDDECL has attributes and NEWDECL doesn't, + try the type with OLDDECL attributes. */ + tree rettype = TREE_TYPE (newtype); + tree tryargs = TYPE_ARG_TYPES (newtype); + tree trytype = c_build_function_type (rettype, + tryargs); + trytype = c_build_type_attribute_variant (trytype, + attrs); + if (comptypes (oldtype, trytype)) + { + *newtypep = newtype = trytype; + comptypes_result = 1; + } + } + } + + if (!comptypes_result) + error ("conflicting types for %q+D; have %qT", newdecl, + newtype); + } + if (!comptypes_result) + { + diagnose_arglist_conflict (newdecl, olddecl, newtype, + oldtype); + locate_old_decl (olddecl); + return false; + } } } /* Warn about enum/integer type mismatches. They are compatible types @@ -2506,6 +2572,10 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, "but not here"); } } + /* Check if these are unmergable overlapping FMV declarations. */ + if (!TARGET_HAS_FMV_TARGET_ATTRIBUTE + && diagnose_versioned_decls (olddecl, newdecl)) + return false; } else if (VAR_P (newdecl)) { @@ -2629,9 +2699,8 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, && !DECL_EXTERNAL (olddecl)) warned |= warning_at (DECL_SOURCE_LOCATION (newdecl), OPT_Wc___compat, - ("duplicate declaration of %qD is " - "invalid in C++"), - newdecl); + "duplicate declaration of %qD is " + "invalid in C++", newdecl); } /* warnings */ @@ -2788,6 +2857,9 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) break; } } + + /* Make sure we refer to the same type as the olddecl. */ + DECL_ORIGINAL_TYPE (newdecl) = DECL_ORIGINAL_TYPE (olddecl); } /* Merge the data types specified in the two decls. */ @@ -2970,6 +3042,12 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) if (TREE_CODE (newdecl) == FUNCTION_DECL) { + if (DECL_FUNCTION_VERSIONED (olddecl) + || DECL_FUNCTION_VERSIONED (newdecl)) + { + maybe_mark_function_versioned (olddecl); + maybe_mark_function_versioned (newdecl); + } /* If we're redefining a function previously defined as extern inline, make sure we emit debug info for the inline before we throw it away, in case it was inlined into a function that @@ -3369,6 +3447,56 @@ pushdecl (tree x) TREE_TYPE (b_use->decl) = b_use->u.type; } } + + /* Check if x is part of a FMV set with b_use. + FMV is only supported in c for targets with target_version + attributes. */ + if (!TARGET_HAS_FMV_TARGET_ATTRIBUTE + && b_use && TREE_CODE (b_use->decl) == FUNCTION_DECL + && TREE_CODE (x) == FUNCTION_DECL && DECL_FILE_SCOPE_P (b_use->decl) + && DECL_FILE_SCOPE_P (x) + && disjoint_version_decls (x, b_use->decl) + && comptypes (vistype, type) != 0) + { + maybe_mark_function_versioned (b_use->decl); + maybe_mark_function_versioned (b->decl); + maybe_mark_function_versioned (x); + + cgraph_node *b_node = cgraph_node::get_create (b_use->decl); + cgraph_function_version_info *b_v = b_node->function_version (); + if (!b_v) + b_v = b_node->insert_new_function_version (); + + /* Check if this new node conflicts with any previous functions + in the set. */ + cgraph_function_version_info *version = b_v; + for (; version; version = version->next) + if (!disjoint_version_decls (version->this_node->decl, x)) + { + /* The decls define overlapping version, so attempt to merge + or diagnose the conflict. */ + if (duplicate_decls (x, version->this_node->decl)) + return version->this_node->decl; + else + return error_mark_node; + } + + /* This is a new version to be added to FMV structure. */ + cgraph_node::add_function_version (b_v, x); + + /* Get the first node from the structure. */ + cgraph_function_version_info *default_v = b_v; + while (default_v->prev) + default_v = default_v->prev; + /* Always use the default node for the bindings. */ + b_use->decl = default_v->this_node->decl; + b->decl = default_v->this_node->decl; + + /* Node is not a duplicate, so no need to do the rest of the + checks. */ + return x; + } + if (duplicate_decls (x, b_use->decl)) { if (b_use != b) @@ -4364,8 +4492,8 @@ c_check_switch_jump_warnings (struct c_spot_bindings *switch_bindings, { saw_error = true; error_at (case_loc, - ("switch jumps into scope of identifier with " - "variably modified type")); + "switch jumps into scope of identifier with " + "variably modified type"); emitted = true; } else if (flag_openmp @@ -4493,6 +4621,12 @@ tree lookup_name (tree name) { struct c_binding *b = I_SYMBOL_BINDING (name); + /* Do not resolve non-default function versions. */ + if (b + && TREE_CODE (b->decl) == FUNCTION_DECL + && DECL_FUNCTION_VERSIONED (b->decl) + && !is_function_default_version (b->decl)) + return NULL_TREE; if (b && !b->invisible) { maybe_record_typedef_use (b->decl); @@ -4543,21 +4677,23 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind, location_t loc) = get_c_stdlib_header_for_name (IDENTIFIER_POINTER (name)); if (header_hint) - return name_hint (NULL, - new suggest_missing_header (loc, - IDENTIFIER_POINTER (name), - header_hint)); + return name_hint + (nullptr, + std::make_unique<suggest_missing_header> (loc, + IDENTIFIER_POINTER (name), + header_hint)); /* Next, look for exact matches for builtin defines that would have been defined if the user had passed a command-line option (e.g. -fopenmp for "_OPENMP"). */ - diagnostic_option_id option_id + diagnostics::option_id option_id = get_option_for_builtin_define (IDENTIFIER_POINTER (name)); if (option_id.m_idx > 0) - return name_hint (nullptr, - new suggest_missing_option (loc, - IDENTIFIER_POINTER (name), - option_id)); + return name_hint + (nullptr, + std::make_unique<suggest_missing_option> (loc, + IDENTIFIER_POINTER (name), + option_id)); /* Only suggest names reserved for the implementation if NAME begins with an underscore. */ @@ -4819,6 +4955,28 @@ c_init_decl_processing (void) make_fname_decl = c_make_fname_decl; start_fname_decls (); + + if (warn_keyword_macro) + { + for (unsigned int i = 0; i < num_c_common_reswords; ++i) + /* For C register keywords which don't start with underscore + or start with just single underscore. Don't complain about + ObjC or Transactional Memory keywords. */ + if (c_common_reswords[i].word[0] == '_' + && c_common_reswords[i].word[1] == '_') + continue; + else if (c_common_reswords[i].disable + & (D_TRANSMEM | D_OBJC | D_CXX_OBJC)) + continue; + else + { + tree id = get_identifier (c_common_reswords[i].word); + if (C_IS_RESERVED_WORD (id) + && C_RID_CODE (id) != RID_CXX_COMPAT_WARN) + cpp_warn (parse_in, IDENTIFIER_POINTER (id), + IDENTIFIER_LENGTH (id)); + } + } } /* Create the VAR_DECL at LOC for __FUNCTION__ etc. ID is the name to @@ -5332,19 +5490,11 @@ build_array_declarator (location_t loc, "ISO C90 does not support %<static%> or type " "qualifiers in parameter array declarators"); if (vla_unspec_p) - pedwarn_c90 (loc, OPT_Wpedantic, - "ISO C90 does not support %<[*]%> array declarators"); - if (vla_unspec_p) { - if (!current_scope->parm_flag) - { - /* C99 6.7.5.2p4 */ - error_at (loc, "%<[*]%> not allowed in other than " - "function prototype scope"); - declarator->u.array.vla_unspec_p = false; - return NULL; - } - current_scope->had_vla_unspec = true; + pedwarn_c90 (loc, OPT_Wpedantic, + "ISO C90 does not support %<[*]%> array declarators"); + if (current_scope->parm_flag) + current_scope->had_vla_unspec = true; } return declarator; } @@ -5450,6 +5600,29 @@ groktypename (struct c_type_name *type_name, tree *expr, return type; } + +/* Decode a "typename", such as "int **", returning a ..._TYPE node, + as for groktypename but setting the context to GENERIC_ASSOC. */ + +tree +grokgenassoc (struct c_type_name *type_name) +{ + tree type; + tree attrs = type_name->specs->attrs; + + type_name->specs->attrs = NULL_TREE; + + type = grokdeclarator (type_name->declarator, type_name->specs, GENERIC_ASSOC, + false, NULL, &attrs, NULL, NULL, DEPRECATED_NORMAL); + + /* Apply attributes. */ + attrs = c_warn_type_attributes (type, attrs); + decl_attributes (&type, attrs, 0); + + return type; +} + + /* Looks up the most recent pushed declaration corresponding to DECL. */ static tree @@ -5555,7 +5728,16 @@ c_decl_attributes (tree *node, tree attributes, int flags) tree last_decl = lookup_last_decl (*node); if (last_decl == error_mark_node) last_decl = NULL_TREE; - return decl_attributes (node, attributes, flags, last_decl); + tree attr = decl_attributes (node, attributes, flags, last_decl); + if (VAR_P (*node) && DECL_THREAD_LOCAL_P (*node)) + { + // tls_model attribute can set a stronger TLS access model. + tls_model model = DECL_TLS_MODEL (*node); + tls_model default_model = decl_default_tls_model (*node); + if (default_model > model) + set_decl_tls_model (*node, default_model); + } + return attr; } @@ -5717,26 +5899,6 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, } if (TREE_CODE (decl) == FUNCTION_DECL - && targetm.calls.promote_prototypes (TREE_TYPE (decl))) - { - struct c_declarator *ce = declarator; - - if (ce->kind == cdk_pointer) - ce = declarator->declarator; - if (ce->kind == cdk_function) - { - tree args = ce->u.arg_info->parms; - for (; args; args = DECL_CHAIN (args)) - { - tree type = TREE_TYPE (args); - if (type && INTEGRAL_TYPE_P (type) - && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) - DECL_ARG_TYPE (args) = c_type_promotes_to (type); - } - } - } - - if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl) && DECL_UNINLINABLE (decl) && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl))) @@ -5762,6 +5924,17 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, && VAR_OR_FUNCTION_DECL_P (decl)) objc_check_global_decl (decl); + /* To enable versions to be created across TU's we mark and mangle all + non-default versioned functions. */ + if (TREE_CODE (decl) == FUNCTION_DECL + && !TARGET_HAS_FMV_TARGET_ATTRIBUTE + && get_target_version (decl).is_valid ()) + { + maybe_mark_function_versioned (decl); + if (current_scope != file_scope) + error ("versioned declarations are only allowed at file scope"); + } + /* Add this decl to the current scope. TEM may equal DECL or it may be a previous decl of the same name. */ if (do_push) @@ -5867,11 +6040,7 @@ finish_decl (tree decl, location_t init_loc, tree init, && !(TREE_PUBLIC (decl) && current_scope != file_scope)) { bool do_default - = (TREE_STATIC (decl) - /* Even if pedantic, an external linkage array - may have incomplete type at first. */ - ? pedantic && !TREE_PUBLIC (decl) - : !DECL_EXTERNAL (decl)); + = !TREE_STATIC (decl) && !DECL_EXTERNAL (decl); int failure = complete_array_type (&TREE_TYPE (decl), DECL_INITIAL (decl), do_default); @@ -5888,6 +6057,9 @@ finish_decl (tree decl, location_t init_loc, tree init, case 2: if (do_default) error ("array size missing in %q+D", decl); + else if (!TREE_PUBLIC (decl)) + pedwarn_c23 (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic, + "array size missing in %q+D", decl); break; case 3: @@ -6222,184 +6394,7 @@ grokparm (const struct c_parm *parm, tree *expr) return decl; } -/* Return attribute "arg spec" corresponding to an array/VLA parameter - described by PARM, concatenated onto attributes ATTRS. - The spec consists of one dollar symbol for each specified variable - bound, one asterisk for each unspecified variable bound, followed - by at most one specification of the most significant bound of - an ordinary array parameter. For ordinary arrays the specification - is either the constant bound itself, or the space character for - an array with an unspecified bound (the [] form). Finally, a chain - of specified variable bounds is appended to the spec, starting with - the most significant bound. For example, the PARM T a[2][m][3][n] - will produce __attribute__((arg spec ("[$$2]", m, n)). - For T a typedef for an array with variable bounds, the bounds are - included in the specification in the expected order. - No "arg spec" is created for parameters of pointer types, making - a distinction between T(*)[N] (or, equivalently, T[][N]) and - the T[M][N] form, all of which have the same type and are represented - the same, but only the last of which gets an "arg spec" describing - the most significant bound M. */ - -static tree -get_parm_array_spec (const struct c_parm *parm, tree attrs) -{ - /* The attribute specification string, minor bound first. */ - std::string spec; - - /* A list of VLA variable bounds, major first, or null if unspecified - or not a VLA. */ - tree vbchain = NULL_TREE; - /* True for a pointer parameter. */ - bool pointer = false; - /* True for an ordinary array with an unpecified bound. */ - bool nobound = false; - - /* Create a string representation for the bounds of the array/VLA. */ - for (c_declarator *pd = parm->declarator, *next; pd; pd = next) - { - next = pd->declarator; - while (next && next->kind == cdk_attrs) - next = next->declarator; - /* Remember if a pointer has been seen to avoid storing the constant - bound. */ - if (pd->kind == cdk_pointer) - pointer = true; - - if ((pd->kind == cdk_pointer || pd->kind == cdk_function) - && (!next || next->kind == cdk_id)) - { - /* Do nothing for the common case of a pointer. The fact that - the parameter is one can be deduced from the absence of - an arg spec for it. */ - return attrs; - } - - if (pd->kind == cdk_id) - { - if (pointer - || !parm->specs->type - || TREE_CODE (parm->specs->type) != ARRAY_TYPE - || !TYPE_DOMAIN (parm->specs->type) - || !TYPE_MAX_VALUE (TYPE_DOMAIN (parm->specs->type))) - continue; - - tree max = TYPE_MAX_VALUE (TYPE_DOMAIN (parm->specs->type)); - if (!vbchain - && TREE_CODE (max) == INTEGER_CST) - { - /* Extract the upper bound from a parameter of an array type - unless the parameter is an ordinary array of unspecified - bound in which case a next iteration of the loop will - exit. */ - if (spec.empty () || spec.end ()[-1] != ' ') - { - if (!tree_fits_shwi_p (max)) - continue; - - /* The upper bound is the value of the largest valid - index. */ - HOST_WIDE_INT n = tree_to_shwi (max) + 1; - char buf[40]; - sprintf (buf, HOST_WIDE_INT_PRINT_UNSIGNED, n); - spec += buf; - } - continue; - } - - /* For a VLA typedef, create a list of its variable bounds and - append it in the expected order to VBCHAIN. */ - tree tpbnds = NULL_TREE; - for (tree type = parm->specs->type; TREE_CODE (type) == ARRAY_TYPE; - type = TREE_TYPE (type)) - { - tree nelts_minus_one = array_type_nelts_minus_one (type); - if (error_operand_p (nelts_minus_one)) - return attrs; - if (TREE_CODE (nelts_minus_one) != INTEGER_CST) - { - /* Each variable VLA bound is represented by the dollar - sign. */ - spec += "$"; - tpbnds = tree_cons (NULL_TREE, nelts_minus_one, tpbnds); - } - } - tpbnds = nreverse (tpbnds); - vbchain = chainon (vbchain, tpbnds); - continue; - } - - if (pd->kind != cdk_array) - continue; - - if (pd->u.array.vla_unspec_p) - { - /* Each unspecified bound is represented by a star. There - can be any number of these in a declaration (but none in - a definition). */ - spec += '*'; - continue; - } - - tree nelts = pd->u.array.dimen; - if (!nelts) - { - /* Ordinary array of unspecified size. There can be at most - one for the most significant bound. Exit on the next - iteration which determines whether or not PARM is declared - as a pointer or an array. */ - nobound = true; - continue; - } - - if (pd->u.array.static_p) - spec += 's'; - - if (!INTEGRAL_TYPE_P (TREE_TYPE (nelts))) - /* Avoid invalid NELTS. */ - return attrs; - - STRIP_NOPS (nelts); - nelts = c_fully_fold (nelts, false, nullptr); - if (TREE_CODE (nelts) == INTEGER_CST) - { - /* Skip all constant bounds except the most significant one. - The interior ones are included in the array type. */ - if (next && (next->kind == cdk_array || next->kind == cdk_pointer)) - continue; - - if (!tree_fits_uhwi_p (nelts)) - /* Bail completely on invalid bounds. */ - return attrs; - - char buf[40]; - unsigned HOST_WIDE_INT n = tree_to_uhwi (nelts); - sprintf (buf, HOST_WIDE_INT_PRINT_UNSIGNED, n); - spec += buf; - break; - } - - /* Each variable VLA bound is represented by a dollar sign. */ - spec += "$"; - vbchain = tree_cons (NULL_TREE, nelts, vbchain); - } - - if (spec.empty () && !nobound) - return attrs; - - spec.insert (0, "["); - if (nobound) - /* Ordinary array of unspecified bound is represented by a space. - It must be last in the spec. */ - spec += ' '; - spec += ']'; - - tree acsstr = build_string (spec.length () + 1, spec.c_str ()); - tree args = tree_cons (NULL_TREE, acsstr, vbchain); - tree name = get_identifier ("arg spec"); - return tree_cons (name, args, attrs); -} /* Given a parsed parameter declaration, decode it into a PARM_DECL and push that on the current scope. EXPR is a pointer to an @@ -6415,7 +6410,6 @@ push_parm_decl (const struct c_parm *parm, tree *expr) if (decl && DECL_P (decl)) DECL_SOURCE_LOCATION (decl) = parm->loc; - attrs = get_parm_array_spec (parm, attrs); decl_attributes (&decl, attrs, 0); decl = pushdecl (decl); @@ -6431,12 +6425,14 @@ mark_forward_parm_decls (void) { struct c_binding *b; - if (pedantic && !current_scope->warned_forward_parm_decls) - { - pedwarn (input_location, OPT_Wpedantic, - "ISO C forbids forward parameter declarations"); - current_scope->warned_forward_parm_decls = true; - } + if (current_scope->had_forward_parm_decls) + warning_at (input_location, OPT_Wmultiple_parameter_fwd_decl_lists, + "more than one list of forward declarations of parameters"); + if (pedantic && !current_scope->had_forward_parm_decls) + pedwarn (input_location, OPT_Wpedantic, + "ISO C forbids forward parameter declarations"); + + current_scope->had_forward_parm_decls = true; for (b = current_scope->bindings; b; b = b->prev) if (TREE_CODE (b->decl) == PARM_DECL) @@ -6543,6 +6539,10 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const, return error_mark_node; } + if ((TREE_STATIC (decl) || C_DECL_DECLARED_CONSTEXPR (decl)) + && C_TYPE_VARIABLE_SIZE (type)) + error_at (loc, "storage size isn%'t constant"); + if (TREE_STATIC (decl) && !verify_type_context (loc, TCTX_STATIC_STORAGE, type)) return error_mark_node; @@ -6789,6 +6789,25 @@ add_decl_expr (location_t loc, tree type, tree *expr, bool set_name_p) } } + +/* Add attribute "arg spec" to ATTRS corresponding to an array/VLA parameter + declared with type TYPE. The attribute has two arguments. The first is + a string that encodes the presence of the static keyword. The second is + the declared type of the array before adjustment, i.e. as an array type + including the outermost bound. */ + +static tree +build_arg_spec_attribute (tree type, bool static_p, tree attrs) +{ + tree vbchain = tree_cons (NULL_TREE, type, NULL_TREE); + tree acsstr = static_p ? build_string (7, "static") : + build_string (1, ""); + tree args = tree_cons (NULL_TREE, acsstr, vbchain); + tree name = get_identifier ("arg spec"); + return tree_cons (name, args, attrs); +} + + /* Given declspecs and a declarator, determine the name and type of the object declared and construct a ..._DECL node for it. @@ -6806,6 +6825,7 @@ add_decl_expr (location_t loc, tree type, tree *expr, bool set_name_p) or before a function body). Make a PARM_DECL, or return void_type_node. TYPENAME if for a typename (in a cast or sizeof). Don't make a DECL node; just return the ..._TYPE node. + GENERIC_ASSOC for typenames in a generic association. FIELD for a struct or union field; make a FIELD_DECL. INITIALIZED is true if the decl has an initializer. WIDTH is non-NULL for bit-fields, and is a pointer to an INTEGER_CST node @@ -6848,6 +6868,7 @@ grokdeclarator (const struct c_declarator *declarator, bool funcdef_flag = false; bool funcdef_syntax = false; bool size_varies = false; + bool size_error = false; tree decl_attr = declspecs->decl_attr; int array_ptr_quals = TYPE_UNQUALIFIED; tree array_ptr_attrs = NULL_TREE; @@ -6941,6 +6962,7 @@ grokdeclarator (const struct c_declarator *declarator, { gcc_assert (decl_context == PARM || decl_context == TYPENAME + || decl_context == GENERIC_ASSOC || (decl_context == FIELD && declarator->kind == cdk_id)); gcc_assert (!initialized); @@ -7340,6 +7362,7 @@ grokdeclarator (const struct c_declarator *declarator, "size of unnamed array has non-integer type"); size = integer_one_node; size_int_const = true; + size_error = true; } /* This can happen with enum forward declaration. */ else if (!COMPLETE_TYPE_P (TREE_TYPE (size))) @@ -7352,6 +7375,7 @@ grokdeclarator (const struct c_declarator *declarator, "type"); size = integer_one_node; size_int_const = true; + size_error = true; } size = c_fully_fold (size, false, &size_maybe_const); @@ -7377,6 +7401,7 @@ grokdeclarator (const struct c_declarator *declarator, error_at (loc, "size of unnamed array is negative"); size = integer_one_node; size_int_const = true; + size_error = true; } /* Handle a size folded to an integer constant but not an integer constant expression. */ @@ -7511,14 +7536,6 @@ grokdeclarator (const struct c_declarator *declarator, itype = build_index_type (NULL_TREE); } - if (array_parm_vla_unspec_p) - { - /* C99 6.7.5.2p4 */ - if (decl_context == TYPENAME) - warning (0, "%<[*]%> not in a declaration"); - size_varies = true; - } - /* Complain about arrays of incomplete types. */ if (!COMPLETE_TYPE_P (type)) { @@ -7557,6 +7574,22 @@ grokdeclarator (const struct c_declarator *declarator, type = c_build_array_type (type, itype); } + if (array_parm_vla_unspec_p) + { + /* C99 6.7.5.2p4 */ + if (decl_context == TYPENAME) + warning (0, "%<[*]%> not in a declaration"); + else if (decl_context != GENERIC_ASSOC + && decl_context != PARM + && decl_context != FIELD) + { + error ("%<[*]%> not allowed in other than function prototype scope " + "or generic association"); + type = error_mark_node; + } + size_varies = true; + } + if (type != error_mark_node) { /* The GCC extension for zero-length arrays differs from @@ -7915,8 +7948,8 @@ grokdeclarator (const struct c_declarator *declarator, { auto_diagnostic_group d; if (warning_at (declarator->id_loc, OPT_Wc___compat, - ("using %qD as both a typedef and a tag is " - "invalid in C++"), decl) + "using %qD as both a typedef and a tag is " + "invalid in C++", decl) && b->locus != UNKNOWN_LOCATION) inform (b->locus, "originally defined here"); } @@ -7928,7 +7961,7 @@ grokdeclarator (const struct c_declarator *declarator, /* If this is a type name (such as, in a cast or sizeof), compute the type and return it now. */ - if (decl_context == TYPENAME) + if (decl_context == TYPENAME || decl_context == GENERIC_ASSOC) { /* Note that the grammar rejects storage classes in typenames and fields. */ @@ -7992,6 +8025,10 @@ grokdeclarator (const struct c_declarator *declarator, if (TREE_CODE (type) == ARRAY_TYPE) { + if (!size_error) + *decl_attrs = build_arg_spec_attribute (type, array_parm_static, + *decl_attrs); + /* Transfer const-ness of array into that of type pointed to. */ type = TREE_TYPE (type); if (orig_qual_type != NULL_TREE) @@ -8325,8 +8362,11 @@ grokdeclarator (const struct c_declarator *declarator, TREE_PUBLIC (decl) = extern_ref; } + // NB: Set a tentative TLS model to avoid tls_model attribute + // warnings due to lack of thread storage duration. It will + // be updated by c_decl_attributes later. if (threadp) - set_decl_tls_model (decl, decl_default_tls_model (decl)); + set_decl_tls_model (decl, TLS_MODEL_REAL); } if ((storage_class == csc_extern @@ -8363,7 +8403,8 @@ grokdeclarator (const struct c_declarator *declarator, /* Record `register' declaration for warnings on & and in case doing stupid register allocation. */ - if (storage_class == csc_register) + if (storage_class == csc_register + && TREE_CODE (type) != FUNCTION_TYPE) { C_DECL_REGISTER (decl) = 1; DECL_REGISTER (decl) = 1; @@ -8410,9 +8451,8 @@ grokdeclarator (const struct c_declarator *declarator, || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE) && TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE) warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat, - ("non-local variable %qD with anonymous type is " - "questionable in C++"), - decl); + "non-local variable %qD with anonymous type is " + "questionable in C++", decl); return decl; } @@ -8957,12 +8997,14 @@ start_struct (location_t loc, enum tree_code code, tree name, within a statement expr used within sizeof, et. al. This is not terribly serious as C++ doesn't permit statement exprs within sizeof anyhow. */ - if (warn_cxx_compat && (in_sizeof || in_typeof || in_alignof)) + if (warn_cxx_compat + && (in_sizeof || in_typeof || in_alignof || in_countof)) warning_at (loc, OPT_Wc___compat, "defining type in %qs expression is invalid in C++", - (in_sizeof - ? "sizeof" - : (in_typeof ? "typeof" : "alignof"))); + (in_sizeof ? "sizeof" + : in_typeof ? "typeof" + : in_alignof ? "alignof" + : "_Countof")); if (in_underspecified_init) error_at (loc, "%qT defined in underspecified object initializer", ref); @@ -9271,9 +9313,8 @@ warn_cxx_compat_finish_struct (tree fieldlist, enum tree_code code, && tset.contains (DECL_NAME (x))) { warning_at (DECL_SOURCE_LOCATION (x), OPT_Wc___compat, - ("using %qD as both field and typedef name is " - "invalid in C++"), - x); + "using %qD as both field and typedef name is " + "invalid in C++", x); /* FIXME: It would be nice to report the location where the typedef name is used. */ } @@ -9444,56 +9485,62 @@ c_update_type_canonical (tree t) } } -/* Verify the argument of the counted_by attribute of the flexible array - member FIELD_DECL is a valid field of the containing structure, - STRUCT_TYPE, Report error and remove this attribute when it's not. */ +/* Verify the argument of the counted_by attribute of each of the + FIELDS_WITH_COUNTED_BY is a valid field of the containing structure, + STRUCT_TYPE, Report error and remove the corresponding attribute + when it's not. */ static void -verify_counted_by_attribute (tree struct_type, tree field_decl) +verify_counted_by_attribute (tree struct_type, + auto_vec<tree> *fields_with_counted_by) { - tree attr_counted_by = lookup_attribute ("counted_by", - DECL_ATTRIBUTES (field_decl)); - - if (!attr_counted_by) - return; + for (tree field_decl : *fields_with_counted_by) + { + tree attr_counted_by = lookup_attribute ("counted_by", + DECL_ATTRIBUTES (field_decl)); - /* If there is an counted_by attribute attached to the field, - verify it. */ + if (!attr_counted_by) + continue; - tree fieldname = TREE_VALUE (TREE_VALUE (attr_counted_by)); + /* If there is an counted_by attribute attached to the field, + verify it. */ - /* Verify the argument of the attrbute is a valid field of the - containing structure. */ + tree fieldname = TREE_VALUE (TREE_VALUE (attr_counted_by)); - tree counted_by_field = lookup_field (struct_type, fieldname); + /* Verify the argument of the attrbute is a valid field of the + containing structure. */ - /* Error when the field is not found in the containing structure and - remove the corresponding counted_by attribute from the field_decl. */ - if (!counted_by_field) - { - error_at (DECL_SOURCE_LOCATION (field_decl), - "argument %qE to the %<counted_by%> attribute" - " is not a field declaration in the same structure" - " as %qD", fieldname, field_decl); - DECL_ATTRIBUTES (field_decl) - = remove_attribute ("counted_by", DECL_ATTRIBUTES (field_decl)); - } - else - /* Error when the field is not with an integer type. */ - { - while (TREE_CHAIN (counted_by_field)) - counted_by_field = TREE_CHAIN (counted_by_field); - tree real_field = TREE_VALUE (counted_by_field); + tree counted_by_field = lookup_field (struct_type, fieldname); - if (!INTEGRAL_TYPE_P (TREE_TYPE (real_field))) + /* Error when the field is not found in the containing structure and + remove the corresponding counted_by attribute from the field_decl. */ + if (!counted_by_field) { error_at (DECL_SOURCE_LOCATION (field_decl), "argument %qE to the %<counted_by%> attribute" - " is not a field declaration with an integer type", - fieldname); + " is not a field declaration in the same structure" + " as %qD", fieldname, field_decl); DECL_ATTRIBUTES (field_decl) = remove_attribute ("counted_by", DECL_ATTRIBUTES (field_decl)); } + else + /* Error when the field is not with an integer type. */ + { + while (TREE_CHAIN (counted_by_field)) + counted_by_field = TREE_CHAIN (counted_by_field); + tree real_field = TREE_VALUE (counted_by_field); + + if (!INTEGRAL_TYPE_P (TREE_TYPE (real_field))) + { + error_at (DECL_SOURCE_LOCATION (field_decl), + "argument %qE to the %<counted_by%> attribute" + " is not a field declaration with an integer type", + fieldname); + DECL_ATTRIBUTES (field_decl) + = remove_attribute ("counted_by", + DECL_ATTRIBUTES (field_decl)); + } + } } } @@ -9568,7 +9615,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, until now.) */ bool saw_named_field = false; - tree counted_by_fam_field = NULL_TREE; + auto_vec<tree> fields_with_counted_by; for (x = fieldlist; x; x = DECL_CHAIN (x)) { /* Whether this field is the last field of the structure or union. @@ -9649,9 +9696,16 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, record it here and do more verification later after the whole structure is complete. */ if (lookup_attribute ("counted_by", DECL_ATTRIBUTES (x))) - counted_by_fam_field = x; + fields_with_counted_by.safe_push (x); } + if (TREE_CODE (TREE_TYPE (x)) == POINTER_TYPE) + /* If there is a counted_by attribute attached to this field, + record it here and do more verification later after the + whole structure is complete. */ + if (lookup_attribute ("counted_by", DECL_ATTRIBUTES (x))) + fields_with_counted_by.safe_push (x); + if (pedantic && TREE_CODE (t) == RECORD_TYPE && flexible_array_type_p (TREE_TYPE (x))) pedwarn (DECL_SOURCE_LOCATION (x), OPT_Wpedantic, @@ -9661,15 +9715,18 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, DECL_NOT_FLEXARRAY (x) = !is_flexible_array_member_p (is_last_field, x); /* Set TYPE_INCLUDES_FLEXARRAY for the context of x, t. - when x is an array and is the last field. */ + when x is an array and is the last field. + There is only one last_field for a structure type, but there might + be multiple last_fields for a union type, therefore we should ORed + the result for multiple last_fields. */ if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE) TYPE_INCLUDES_FLEXARRAY (t) - = is_last_field && c_flexible_array_member_type_p (TREE_TYPE (x)); + |= is_last_field && c_flexible_array_member_type_p (TREE_TYPE (x)); /* Recursively set TYPE_INCLUDES_FLEXARRAY for the context of x, t when x is an union or record and is the last field. */ else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (x))) TYPE_INCLUDES_FLEXARRAY (t) - = is_last_field && TYPE_INCLUDES_FLEXARRAY (TREE_TYPE (x)); + |= is_last_field && TYPE_INCLUDES_FLEXARRAY (TREE_TYPE (x)); if (warn_flex_array_member_not_at_end && !is_last_field @@ -9717,6 +9774,13 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, unsigned HOST_WIDE_INT width = tree_to_uhwi (DECL_INITIAL (field)); tree type = TREE_TYPE (field); + if (VECTOR_TYPE_P (type)) + { + error_at (DECL_SOURCE_LOCATION (field), + "bit-field %qD has invalid type", field); + type = TREE_TYPE (type); + TREE_TYPE (field) = type; + } if (width != TYPE_PRECISION (type)) { if (TREE_CODE (type) == BITINT_TYPE @@ -9799,12 +9863,17 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, len += list_length (x); /* Use the same allocation policy here that make_node uses, to - ensure that this lives as long as the rest of the struct decl. - All decls in an inline function need to be saved. */ - - space = ggc_cleared_alloc<struct lang_type> (); - space2 = (sorted_fields_type *) ggc_internal_alloc - (sizeof (struct sorted_fields_type) + len * sizeof (tree)); + ensure that this lives as long as the rest of the struct decl. + All decls in an inline function need to be saved. */ + + space = ((struct lang_type *) + ggc_internal_cleared_alloc (c_dialect_objc () + ? sizeof (struct lang_type) + : offsetof (struct lang_type, + info))); + space2 = ((sorted_fields_type *) + ggc_internal_alloc (sizeof (struct sorted_fields_type) + + len * sizeof (tree))); len = 0; space->s = space2; @@ -9905,6 +9974,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, C_TYPE_VARIABLE_SIZE (x) = C_TYPE_VARIABLE_SIZE (t); C_TYPE_VARIABLY_MODIFIED (x) = C_TYPE_VARIABLY_MODIFIED (t); C_TYPE_INCOMPLETE_VARS (x) = NULL_TREE; + TYPE_INCLUDES_FLEXARRAY (x) = TYPE_INCLUDES_FLEXARRAY (t); } /* Update type location to the one of the definition, instead of e.g. @@ -9937,12 +10007,12 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, struct_types. */ if (warn_cxx_compat && struct_parse_info != NULL - && !in_sizeof && !in_typeof && !in_alignof) + && !in_sizeof && !in_typeof && !in_alignof && !in_countof) struct_parse_info->struct_types.safe_push (t); } - if (counted_by_fam_field) - verify_counted_by_attribute (t, counted_by_fam_field); + if (fields_with_counted_by.length () > 0) + verify_counted_by_attribute (t, &fields_with_counted_by); return t; } @@ -10111,12 +10181,14 @@ start_enum (location_t loc, struct c_enum_contents *the_enum, tree name, /* FIXME: This will issue a warning for a use of a type defined within sizeof in a statement expr. This is not terribly serious as C++ doesn't permit statement exprs within sizeof anyhow. */ - if (warn_cxx_compat && (in_sizeof || in_typeof || in_alignof)) + if (warn_cxx_compat + && (in_sizeof || in_typeof || in_alignof || in_countof)) warning_at (loc, OPT_Wc___compat, "defining type in %qs expression is invalid in C++", - (in_sizeof - ? "sizeof" - : (in_typeof ? "typeof" : "alignof"))); + (in_sizeof ? "sizeof" + : in_typeof ? "typeof" + : in_alignof ? "alignof" + : "_Countof")); if (in_underspecified_init) error_at (loc, "%qT defined in underspecified object initializer", @@ -10275,7 +10347,10 @@ finish_enum (tree enumtype, tree values, tree attributes) /* Record the min/max values so that we can warn about bit-field enumerations that are too small for the values. */ - lt = ggc_cleared_alloc<struct lang_type> (); + lt = ((struct lang_type *) + ggc_internal_cleared_alloc (c_dialect_objc () + ? sizeof (struct lang_type) + : offsetof (struct lang_type, info))); lt->enum_min = minnode; lt->enum_max = maxnode; TYPE_LANG_SPECIFIC (enumtype) = lt; @@ -10299,6 +10374,7 @@ finish_enum (tree enumtype, tree values, tree attributes) TYPE_UNSIGNED (tem) = TYPE_UNSIGNED (enumtype); TYPE_LANG_SPECIFIC (tem) = TYPE_LANG_SPECIFIC (enumtype); ENUM_UNDERLYING_TYPE (tem) = ENUM_UNDERLYING_TYPE (enumtype); + TYPE_PACKED (tem) = TYPE_PACKED (enumtype); } /* Finish debugging output for this type. */ @@ -10310,7 +10386,7 @@ finish_enum (tree enumtype, tree values, tree attributes) struct_types. */ if (warn_cxx_compat && struct_parse_info != NULL - && !in_sizeof && !in_typeof && !in_alignof) + && !in_sizeof && !in_typeof && !in_alignof && !in_countof) struct_parse_info->struct_types.safe_push (enumtype); /* Check for consistency with previous definition */ @@ -10444,9 +10520,9 @@ build_enumerator (location_t decl_loc, location_t loc, overflows.) */ warned_range = pedwarn (loc, OPT_Wpedantic, "enumerator value outside the range of %qs", - (TYPE_UNSIGNED (TREE_TYPE (value)) - ? "uintmax_t" - : "intmax_t")); + TYPE_UNSIGNED (TREE_TYPE (value)) + ? "uintmax_t" + : "intmax_t"); if (!warned_range && !int_fits_type_p (value, integer_type_node)) pedwarn_c11 (loc, OPT_Wpedantic, "ISO C restricts enumerator values to range of %<int%> " @@ -10854,7 +10930,18 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, if (old_decl) { location_t origloc = DECL_SOURCE_LOCATION (old_decl); - warn_parm_array_mismatch (origloc, old_decl, parms); + warn_parms_array_mismatch (origloc, old_decl, parms); + } + + /* To enable versions to be created across TU's we mark and mangle all + non-default versioned functions. */ + if (TREE_CODE (decl1) == FUNCTION_DECL + && !TARGET_HAS_FMV_TARGET_ATTRIBUTE + && get_target_version (decl1).is_valid ()) + { + maybe_mark_function_versioned (decl1); + if (current_scope != file_scope) + error ("versioned definitions are only allowed at file scope"); } /* Record the decl so that the function name is defined. @@ -11175,13 +11262,6 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info) useful for argument types like uid_t. */ DECL_ARG_TYPE (parm) = TREE_TYPE (parm); - if (targetm.calls.promote_prototypes (TREE_TYPE (current_function_decl)) - && INTEGRAL_TYPE_P (TREE_TYPE (parm)) - && (TYPE_PRECISION (TREE_TYPE (parm)) - < TYPE_PRECISION (integer_type_node))) - DECL_ARG_TYPE (parm) - = c_type_promotes_to (TREE_TYPE (parm)); - /* ??? Is it possible to get here with a built-in prototype or will it always have been diagnosed as conflicting with an @@ -11409,19 +11489,6 @@ finish_function (location_t end_loc) if (c_dialect_objc ()) objc_finish_function (); - if (TREE_CODE (fndecl) == FUNCTION_DECL - && targetm.calls.promote_prototypes (TREE_TYPE (fndecl))) - { - tree args = DECL_ARGUMENTS (fndecl); - for (; args; args = DECL_CHAIN (args)) - { - tree type = TREE_TYPE (args); - if (INTEGRAL_TYPE_P (type) - && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) - DECL_ARG_TYPE (args) = c_type_promotes_to (type); - } - } - if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node) BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; @@ -11482,9 +11549,9 @@ finish_function (location_t end_loc) && !DECL_READ_P (decl) && DECL_NAME (decl) && !DECL_ARTIFICIAL (decl) - && !warning_suppressed_p (decl, OPT_Wunused_but_set_parameter)) + && !warning_suppressed_p (decl, OPT_Wunused_but_set_parameter_)) warning_at (DECL_SOURCE_LOCATION (decl), - OPT_Wunused_but_set_parameter, + OPT_Wunused_but_set_parameter_, "parameter %qD set but not used", decl); } @@ -12088,8 +12155,8 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, if (specs->typespec_word == cts_double) { error_at (loc, - ("both %<long long%> and %<double%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long long", "double"); break; } pedwarn_c90 (loc, OPT_Wlong_long, @@ -12100,61 +12167,60 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, } if (specs->short_p) error_at (loc, - ("both %<long%> and %<short%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long", "short"); else if (specs->typespec_word == cts_auto_type) error_at (loc, - ("both %<long%> and %<__auto_type%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long", "__auto_type"); else if (specs->typespec_word == cts_void) error_at (loc, - ("both %<long%> and %<void%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long", "void"); else if (specs->typespec_word == cts_int_n) error_at (loc, - ("both %<long%> and %<__int%d%> in " - "declaration specifiers"), - int_n_data[specs->u.int_n_idx].bitsize); + "both %qs and %<__int%d%> in declaration specifiers", + "long", int_n_data[specs->u.int_n_idx].bitsize); else if (specs->typespec_word == cts_bool) error_at (loc, - ("both %<long%> and %<_Bool%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long", "_Bool"); else if (specs->typespec_word == cts_bitint) error_at (loc, - ("both %<long%> and %<_BitInt%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long", "_BitInt"); else if (specs->typespec_word == cts_char) error_at (loc, - ("both %<long%> and %<char%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long", "char"); else if (specs->typespec_word == cts_float) error_at (loc, - ("both %<long%> and %<float%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long", "float"); else if (specs->typespec_word == cts_floatn_nx) error_at (loc, - ("both %<long%> and %<_Float%d%s%> in " - "declaration specifiers"), + "both %qs and %<_Float%d%s%> in declaration " + "specifiers", "long", floatn_nx_types[specs->u.floatn_nx_idx].n, - (floatn_nx_types[specs->u.floatn_nx_idx].extended - ? "x" - : "")); + floatn_nx_types[specs->u.floatn_nx_idx].extended + ? "x" + : ""); else if (specs->typespec_word == cts_dfloat32) error_at (loc, - ("both %<long%> and %<_Decimal32%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long", "_Decimal32"); else if (specs->typespec_word == cts_dfloat64) error_at (loc, - ("both %<long%> and %<_Decimal64%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long", "_Decimal64"); else if (specs->typespec_word == cts_dfloat128) error_at (loc, - ("both %<long%> and %<_Decimal128%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long", "_Decimal128"); else if (specs->typespec_word == cts_dfloat64x) error_at (loc, - ("both %<long%> and %<_Decimal64x%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long", "_Decimal64x"); else { specs->long_p = true; @@ -12165,65 +12231,64 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, dupe = specs->short_p; if (specs->long_p) error_at (loc, - ("both %<long%> and %<short%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long", "short"); else if (specs->typespec_word == cts_auto_type) error_at (loc, - ("both %<short%> and %<__auto_type%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "short", "__auto_type"); else if (specs->typespec_word == cts_void) error_at (loc, - ("both %<short%> and %<void%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "short", "void"); else if (specs->typespec_word == cts_int_n) error_at (loc, - ("both %<short%> and %<__int%d%> in " - "declaration specifiers"), - int_n_data[specs->u.int_n_idx].bitsize); + "both %qs and %<__int%d%> in declaration specifiers", + "short", int_n_data[specs->u.int_n_idx].bitsize); else if (specs->typespec_word == cts_bool) error_at (loc, - ("both %<short%> and %<_Bool%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "short", "_Bool"); else if (specs->typespec_word == cts_bitint) error_at (loc, - ("both %<short%> and %<_BitInt%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "short", "_BitInt"); else if (specs->typespec_word == cts_char) error_at (loc, - ("both %<short%> and %<char%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "short", "char"); else if (specs->typespec_word == cts_float) error_at (loc, - ("both %<short%> and %<float%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "short", "float"); else if (specs->typespec_word == cts_double) error_at (loc, - ("both %<short%> and %<double%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "short", "double"); else if (specs->typespec_word == cts_floatn_nx) error_at (loc, - ("both %<short%> and %<_Float%d%s%> in " - "declaration specifiers"), + "both %qs and %<_Float%d%s%> in declaration " + "specifiers", "short", floatn_nx_types[specs->u.floatn_nx_idx].n, - (floatn_nx_types[specs->u.floatn_nx_idx].extended - ? "x" - : "")); + floatn_nx_types[specs->u.floatn_nx_idx].extended + ? "x" + : ""); else if (specs->typespec_word == cts_dfloat32) error_at (loc, - ("both %<short%> and %<_Decimal32%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "short", "_Decimal32"); else if (specs->typespec_word == cts_dfloat64) error_at (loc, - ("both %<short%> and %<_Decimal64%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "short", "_Decimal64"); else if (specs->typespec_word == cts_dfloat128) error_at (loc, - ("both %<short%> and %<_Decimal128%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "short", "_Decimal128"); else if (specs->typespec_word == cts_dfloat64x) error_at (loc, - ("both %<short%> and %<_Decimal64x%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "short", "_Decimal64x"); else { specs->short_p = true; @@ -12234,52 +12299,52 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, dupe = specs->signed_p; if (specs->unsigned_p) error_at (loc, - ("both %<signed%> and %<unsigned%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "signed", "unsigned"); else if (specs->typespec_word == cts_auto_type) error_at (loc, - ("both %<signed%> and %<__auto_type%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "signed", "__auto_type"); else if (specs->typespec_word == cts_void) error_at (loc, - ("both %<signed%> and %<void%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "signed", "void"); else if (specs->typespec_word == cts_bool) error_at (loc, - ("both %<signed%> and %<_Bool%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "signed", "_Bool"); else if (specs->typespec_word == cts_float) error_at (loc, - ("both %<signed%> and %<float%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "signed", "float"); else if (specs->typespec_word == cts_double) error_at (loc, - ("both %<signed%> and %<double%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "signed", "double"); else if (specs->typespec_word == cts_floatn_nx) error_at (loc, - ("both %<signed%> and %<_Float%d%s%> in " - "declaration specifiers"), + "both %qs and %<_Float%d%s%> in declaration " + "specifiers", "signed", floatn_nx_types[specs->u.floatn_nx_idx].n, - (floatn_nx_types[specs->u.floatn_nx_idx].extended - ? "x" - : "")); + floatn_nx_types[specs->u.floatn_nx_idx].extended + ? "x" + : ""); else if (specs->typespec_word == cts_dfloat32) error_at (loc, - ("both %<signed%> and %<_Decimal32%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "signed", "_Decimal32"); else if (specs->typespec_word == cts_dfloat64) error_at (loc, - ("both %<signed%> and %<_Decimal64%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "signed", "_Decimal64"); else if (specs->typespec_word == cts_dfloat128) error_at (loc, - ("both %<signed%> and %<_Decimal128%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "signed", "_Decimal128"); else if (specs->typespec_word == cts_dfloat64x) error_at (loc, - ("both %<signed%> and %<_Decimal64x%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "signed", "_Decimal64x"); else { specs->signed_p = true; @@ -12290,52 +12355,52 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, dupe = specs->unsigned_p; if (specs->signed_p) error_at (loc, - ("both %<signed%> and %<unsigned%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "signed", "unsigned"); else if (specs->typespec_word == cts_auto_type) error_at (loc, - ("both %<unsigned%> and %<__auto_type%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "unsigned", "__auto_type"); else if (specs->typespec_word == cts_void) error_at (loc, - ("both %<unsigned%> and %<void%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "unsigned", "void"); else if (specs->typespec_word == cts_bool) error_at (loc, - ("both %<unsigned%> and %<_Bool%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "unsigned", "_Bool"); else if (specs->typespec_word == cts_float) error_at (loc, - ("both %<unsigned%> and %<float%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "unsigned", "float"); else if (specs->typespec_word == cts_double) error_at (loc, - ("both %<unsigned%> and %<double%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "unsigned", "double"); else if (specs->typespec_word == cts_floatn_nx) error_at (loc, - ("both %<unsigned%> and %<_Float%d%s%> in " - "declaration specifiers"), + "both %qs and %<_Float%d%s%> in declaration " + "specifiers", "unsigned", floatn_nx_types[specs->u.floatn_nx_idx].n, - (floatn_nx_types[specs->u.floatn_nx_idx].extended - ? "x" - : "")); + floatn_nx_types[specs->u.floatn_nx_idx].extended + ? "x" + : ""); else if (specs->typespec_word == cts_dfloat32) error_at (loc, - ("both %<unsigned%> and %<_Decimal32%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "unsigned", "_Decimal32"); else if (specs->typespec_word == cts_dfloat64) error_at (loc, - ("both %<unsigned%> and %<_Decimal64%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "unsigned", "_Decimal64"); else if (specs->typespec_word == cts_dfloat128) error_at (loc, - ("both %<unsigned%> and %<_Decimal128%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "unsigned", "_Decimal128"); else if (specs->typespec_word == cts_dfloat64x) error_at (loc, - ("both %<unsigned%> and %<_Decimal64x%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "unsigned", "_Decimal64x"); else { specs->unsigned_p = true; @@ -12349,48 +12414,48 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, "ISO C90 does not support complex types"); if (specs->typespec_word == cts_auto_type) error_at (loc, - ("both %<complex%> and %<__auto_type%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "complex", "__auto_type"); else if (specs->typespec_word == cts_void) error_at (loc, - ("both %<complex%> and %<void%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "complex", "void"); else if (specs->typespec_word == cts_bool) error_at (loc, - ("both %<complex%> and %<_Bool%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "complex", "_Bool"); else if (specs->typespec_word == cts_bitint) error_at (loc, - ("both %<complex%> and %<_BitInt%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "complex", "_BitInt"); else if (specs->typespec_word == cts_dfloat32) error_at (loc, - ("both %<complex%> and %<_Decimal32%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "complex", "_Decimal32"); else if (specs->typespec_word == cts_dfloat64) error_at (loc, - ("both %<complex%> and %<_Decimal64%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "complex", "_Decimal64"); else if (specs->typespec_word == cts_dfloat128) error_at (loc, - ("both %<complex%> and %<_Decimal128%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "complex", "_Decimal128"); else if (specs->typespec_word == cts_dfloat64x) error_at (loc, - ("both %<complex%> and %<_Decimal64x%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "complex", "_Decimal64x"); else if (specs->typespec_word == cts_fract) error_at (loc, - ("both %<complex%> and %<_Fract%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "complex", "_Fract"); else if (specs->typespec_word == cts_accum) error_at (loc, - ("both %<complex%> and %<_Accum%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "complex", "_Accum"); else if (specs->saturating_p) error_at (loc, - ("both %<complex%> and %<_Sat%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "complex", "_Sat"); else { specs->complex_p = true; @@ -12402,72 +12467,69 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, pedwarn (loc, OPT_Wpedantic, "ISO C does not support saturating types"); if (specs->typespec_word == cts_int_n) - { - error_at (loc, - ("both %<_Sat%> and %<__int%d%> in " - "declaration specifiers"), - int_n_data[specs->u.int_n_idx].bitsize); - } + error_at (loc, + "both %qs and %<__int%d%> in declaration specifiers", + "_Sat", int_n_data[specs->u.int_n_idx].bitsize); else if (specs->typespec_word == cts_auto_type) error_at (loc, - ("both %<_Sat%> and %<__auto_type%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "__auto_type"); else if (specs->typespec_word == cts_void) error_at (loc, - ("both %<_Sat%> and %<void%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "void"); else if (specs->typespec_word == cts_bool) error_at (loc, - ("both %<_Sat%> and %<_Bool%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "_Bool"); else if (specs->typespec_word == cts_bitint) error_at (loc, - ("both %<_Sat%> and %<_BitInt%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "_BitInt"); else if (specs->typespec_word == cts_char) error_at (loc, - ("both %<_Sat%> and %<char%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "char"); else if (specs->typespec_word == cts_int) error_at (loc, - ("both %<_Sat%> and %<int%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "int"); else if (specs->typespec_word == cts_float) error_at (loc, - ("both %<_Sat%> and %<float%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "float"); else if (specs->typespec_word == cts_double) error_at (loc, - ("both %<_Sat%> and %<double%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "double"); else if (specs->typespec_word == cts_floatn_nx) error_at (loc, - ("both %<_Sat%> and %<_Float%d%s%> in " - "declaration specifiers"), + "both %qs and %<_Float%d%s%> in declaration " + "specifiers", "_Sat", floatn_nx_types[specs->u.floatn_nx_idx].n, - (floatn_nx_types[specs->u.floatn_nx_idx].extended - ? "x" - : "")); + floatn_nx_types[specs->u.floatn_nx_idx].extended + ? "x" + : ""); else if (specs->typespec_word == cts_dfloat32) error_at (loc, - ("both %<_Sat%> and %<_Decimal32%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "_Decimal32"); else if (specs->typespec_word == cts_dfloat64) error_at (loc, - ("both %<_Sat%> and %<_Decimal64%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "_Decimal64"); else if (specs->typespec_word == cts_dfloat128) error_at (loc, - ("both %<_Sat%> and %<_Decimal128%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "_Decimal128"); else if (specs->typespec_word == cts_dfloat64x) error_at (loc, - ("both %<_Sat%> and %<_Decimal64x%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "_Decimal64x"); else if (specs->complex_p) error_at (loc, - ("both %<_Sat%> and %<complex%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "complex"); else { specs->saturating_p = true; @@ -12514,28 +12576,28 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, case RID_AUTO_TYPE: if (specs->long_p) error_at (loc, - ("both %<long%> and %<__auto_type%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long", "__auto_type"); else if (specs->short_p) error_at (loc, - ("both %<short%> and %<__auto_type%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "short", "__auto_type"); else if (specs->signed_p) error_at (loc, - ("both %<signed%> and %<__auto_type%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "signed", "__auto_type"); else if (specs->unsigned_p) error_at (loc, - ("both %<unsigned%> and %<__auto_type%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "unsigned", "__auto_type"); else if (specs->complex_p) error_at (loc, - ("both %<complex%> and %<__auto_type%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "complex", "__auto_type"); else if (specs->saturating_p) error_at (loc, - ("both %<_Sat%> and %<__auto_type%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "__auto_type"); else { specs->typespec_word = cts_auto_type; @@ -12558,19 +12620,16 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, if (specs->long_p) error_at (loc, - ("both %<__int%d%> and %<long%> in " - "declaration specifiers"), - int_n_data[specs->u.int_n_idx].bitsize); + "both %<__int%d%> and %qs in declaration specifiers", + int_n_data[specs->u.int_n_idx].bitsize, "long"); else if (specs->saturating_p) error_at (loc, - ("both %<_Sat%> and %<__int%d%> in " - "declaration specifiers"), - int_n_data[specs->u.int_n_idx].bitsize); + "both %qs and %<__int%d%> in declaration specifiers", + "_Sat", int_n_data[specs->u.int_n_idx].bitsize); else if (specs->short_p) error_at (loc, - ("both %<__int%d%> and %<short%> in " - "declaration specifiers"), - int_n_data[specs->u.int_n_idx].bitsize); + "both %<__int%d%> and %qs in declaration specifiers", + int_n_data[specs->u.int_n_idx].bitsize, "short"); else if (! int_n_enabled_p[specs->u.int_n_idx]) { specs->typespec_word = cts_int_n; @@ -12587,28 +12646,28 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, case RID_VOID: if (specs->long_p) error_at (loc, - ("both %<long%> and %<void%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long", "void"); else if (specs->short_p) error_at (loc, - ("both %<short%> and %<void%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "short", "void"); else if (specs->signed_p) error_at (loc, - ("both %<signed%> and %<void%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "signed", "void"); else if (specs->unsigned_p) error_at (loc, - ("both %<unsigned%> and %<void%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "unsigned", "void"); else if (specs->complex_p) error_at (loc, - ("both %<complex%> and %<void%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "complex", "void"); else if (specs->saturating_p) error_at (loc, - ("both %<_Sat%> and %<void%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "void"); else { specs->typespec_word = cts_void; @@ -12621,28 +12680,28 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, "ISO C90 does not support boolean types"); if (specs->long_p) error_at (loc, - ("both %<long%> and %<_Bool%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long", "_Bool"); else if (specs->short_p) error_at (loc, - ("both %<short%> and %<_Bool%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "short", "_Bool"); else if (specs->signed_p) error_at (loc, - ("both %<signed%> and %<_Bool%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "signed", "_Bool"); else if (specs->unsigned_p) error_at (loc, - ("both %<unsigned%> and %<_Bool%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "unsigned", "_Bool"); else if (specs->complex_p) error_at (loc, - ("both %<complex%> and %<_Bool%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "complex", "_Bool"); else if (specs->saturating_p) error_at (loc, - ("both %<_Sat%> and %<_Bool%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "_Bool"); else { specs->typespec_word = cts_bool; @@ -12652,16 +12711,16 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, case RID_CHAR: if (specs->long_p) error_at (loc, - ("both %<long%> and %<char%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long", "char"); else if (specs->short_p) error_at (loc, - ("both %<short%> and %<char%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "short", "char"); else if (specs->saturating_p) error_at (loc, - ("both %<_Sat%> and %<char%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "char"); else { specs->typespec_word = cts_char; @@ -12671,8 +12730,8 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, case RID_INT: if (specs->saturating_p) error_at (loc, - ("both %<_Sat%> and %<int%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "int"); else { specs->typespec_word = cts_int; @@ -12682,24 +12741,24 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, case RID_FLOAT: if (specs->long_p) error_at (loc, - ("both %<long%> and %<float%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long", "float"); else if (specs->short_p) error_at (loc, - ("both %<short%> and %<float%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "short", "float"); else if (specs->signed_p) error_at (loc, - ("both %<signed%> and %<float%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "signed", "float"); else if (specs->unsigned_p) error_at (loc, - ("both %<unsigned%> and %<float%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "unsigned", "float"); else if (specs->saturating_p) error_at (loc, - ("both %<_Sat%> and %<float%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "float"); else { specs->typespec_word = cts_float; @@ -12709,24 +12768,24 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, case RID_DOUBLE: if (specs->long_long_p) error_at (loc, - ("both %<long long%> and %<double%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long long", "double"); else if (specs->short_p) error_at (loc, - ("both %<short%> and %<double%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "short", "double"); else if (specs->signed_p) error_at (loc, - ("both %<signed%> and %<double%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "signed", "double"); else if (specs->unsigned_p) error_at (loc, - ("both %<unsigned%> and %<double%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "unsigned", "double"); else if (specs->saturating_p) error_at (loc, - ("both %<_Sat%> and %<double%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "double"); else { specs->typespec_word = cts_double; @@ -12740,59 +12799,59 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, "ISO C does not support the %<_Float%d%s%> type" " before C23", floatn_nx_types[specs->u.floatn_nx_idx].n, - (floatn_nx_types[specs->u.floatn_nx_idx].extended - ? "x" - : "")); + floatn_nx_types[specs->u.floatn_nx_idx].extended + ? "x" + : ""); if (specs->long_p) error_at (loc, - ("both %<long%> and %<_Float%d%s%> in " - "declaration specifiers"), + "both %qs and %<_Float%d%s%> in declaration " + "specifiers", "long", floatn_nx_types[specs->u.floatn_nx_idx].n, - (floatn_nx_types[specs->u.floatn_nx_idx].extended - ? "x" - : "")); + floatn_nx_types[specs->u.floatn_nx_idx].extended + ? "x" + : ""); else if (specs->short_p) error_at (loc, - ("both %<short%> and %<_Float%d%s%> in " - "declaration specifiers"), + "both %qs and %<_Float%d%s%> in declaration " + "specifiers", "short", floatn_nx_types[specs->u.floatn_nx_idx].n, - (floatn_nx_types[specs->u.floatn_nx_idx].extended - ? "x" - : "")); + floatn_nx_types[specs->u.floatn_nx_idx].extended + ? "x" + : ""); else if (specs->signed_p) error_at (loc, - ("both %<signed%> and %<_Float%d%s%> in " - "declaration specifiers"), + "both %qs and %<_Float%d%s%> in declaration " + "specifiers", "signed", floatn_nx_types[specs->u.floatn_nx_idx].n, - (floatn_nx_types[specs->u.floatn_nx_idx].extended - ? "x" - : "")); + floatn_nx_types[specs->u.floatn_nx_idx].extended + ? "x" + : ""); else if (specs->unsigned_p) error_at (loc, - ("both %<unsigned%> and %<_Float%d%s%> in " - "declaration specifiers"), + "both %qs and %<_Float%d%s%> in declaration " + "specifiers", "unsigned", floatn_nx_types[specs->u.floatn_nx_idx].n, - (floatn_nx_types[specs->u.floatn_nx_idx].extended - ? "x" - : "")); + floatn_nx_types[specs->u.floatn_nx_idx].extended + ? "x" + : ""); else if (specs->saturating_p) error_at (loc, - ("both %<_Sat%> and %<_Float%d%s%> in " - "declaration specifiers"), + "both %qs and %<_Float%d%s%> in declaration " + "specifiers", "_Sat", floatn_nx_types[specs->u.floatn_nx_idx].n, - (floatn_nx_types[specs->u.floatn_nx_idx].extended - ? "x" - : "")); + floatn_nx_types[specs->u.floatn_nx_idx].extended + ? "x" + : ""); else if (FLOATN_NX_TYPE_NODE (specs->u.floatn_nx_idx) == NULL_TREE) { specs->typespec_word = cts_floatn_nx; error_at (loc, "%<_Float%d%s%> is not supported on this target", floatn_nx_types[specs->u.floatn_nx_idx].n, - (floatn_nx_types[specs->u.floatn_nx_idx].extended - ? "x" - : "")); + floatn_nx_types[specs->u.floatn_nx_idx].extended + ? "x" + : ""); } else { @@ -12816,39 +12875,32 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, str = "_Decimal64x"; if (specs->long_long_p) error_at (loc, - ("both %<long long%> and %qs in " - "declaration specifiers"), - str); + "both %qs and %qs in declaration specifiers", + "long long", str); if (specs->long_p) error_at (loc, - ("both %<long%> and %qs in " - "declaration specifiers"), - str); + "both %qs and %qs in declaration specifiers", + "long", str); else if (specs->short_p) error_at (loc, - ("both %<short%> and %qs in " - "declaration specifiers"), - str); + "both %qs and %qs in declaration specifiers", + "short", str); else if (specs->signed_p) error_at (loc, - ("both %<signed%> and %qs in " - "declaration specifiers"), - str); + "both %qs and %qs in declaration specifiers", + "signed", str); else if (specs->unsigned_p) error_at (loc, - ("both %<unsigned%> and %qs in " - "declaration specifiers"), - str); + "both %qs and %qs in declaration specifiers", + "unsigned", str); else if (specs->complex_p) error_at (loc, - ("both %<complex%> and %qs in " - "declaration specifiers"), - str); + "both %qs and %qs in declaration specifiers", + "complex", str); else if (specs->saturating_p) error_at (loc, - ("both %<_Sat%> and %qs in " - "declaration specifiers"), - str); + "both %qs and %qs in declaration specifiers", + "_Sat", str); else if (i == RID_DFLOAT32) specs->typespec_word = cts_dfloat32; else if (i == RID_DFLOAT64) @@ -12861,8 +12913,8 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, } if (!targetm.decimal_float_supported_p ()) error_at (loc, - ("decimal floating-point not supported " - "for this target")); + "decimal floating-point not supported " + "for this target"); pedwarn_c11 (loc, OPT_Wpedantic, "ISO C does not support decimal floating-point " "before C23"); @@ -12877,9 +12929,8 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, str = "_Accum"; if (specs->complex_p) error_at (loc, - ("both %<complex%> and %qs in " - "declaration specifiers"), - str); + "both %qs and %qs in declaration specifiers", + "complex", str); else if (i == RID_FRACT) specs->typespec_word = cts_fract; else @@ -12895,20 +12946,20 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, case RID_BITINT: if (specs->long_p) error_at (loc, - ("both %<long%> and %<_BitInt%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "long", "_BitInt"); else if (specs->short_p) error_at (loc, - ("both %<short%> and %<_BitInt%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "short", "_BitInt"); else if (specs->complex_p) error_at (loc, - ("both %<complex%> and %<_BitInt%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "complex", "_BitInt"); else if (specs->saturating_p) error_at (loc, - ("both %<_Sat%> and %<_BitInt%> in " - "declaration specifiers")); + "both %qs and %qs in declaration specifiers", + "_Sat", "_BitInt"); else { specs->typespec_word = cts_bitint; @@ -12967,6 +13018,7 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, error_at (loc, "two or more data types in declaration specifiers"); else if (TREE_CODE (type) == TYPE_DECL) { + mark_decl_used (type, false); specs->type = TREE_TYPE (type); if (TREE_TYPE (type) != error_mark_node) { @@ -13723,6 +13775,10 @@ c_parse_final_cleanups (void) c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t))); c_write_global_declarations_1 (BLOCK_VARS (ext_block)); + /* Call this to set cpp_implicit_aliases_done on all nodes. This is + important for function multiversioning aliases to get resolved. */ + symtab->process_same_body_aliases (); + if (!in_lto_p) free_attr_access_data (); @@ -13853,6 +13909,174 @@ c_check_omp_declare_reduction_r (tree *tp, int *, void *data) return NULL_TREE; } +/* Return identifier to look up for omp declare mapper. */ + +tree +c_omp_mapper_id (tree mapper_id) +{ + const char *p = NULL; + + const char prefix[] = "omp declare mapper "; + + if (mapper_id == NULL_TREE) + p = "<default>"; + else if (TREE_CODE (mapper_id) == IDENTIFIER_NODE) + p = IDENTIFIER_POINTER (mapper_id); + else + return error_mark_node; + + size_t lenp = sizeof (prefix); + size_t len = strlen (p); + char *name = XALLOCAVEC (char, lenp + len); + memcpy (name, prefix, lenp - 1); + memcpy (name + lenp - 1, p, len + 1); + return get_identifier (name); +} + +/* Lookup MAPPER_ID in the current scope, or create an artificial + VAR_DECL, bind it into the current scope and return it. */ + +tree +c_omp_mapper_decl (tree mapper_id) +{ + struct c_binding *b = I_SYMBOL_BINDING (mapper_id); + if (b != NULL && B_IN_CURRENT_SCOPE (b)) + return b->decl; + + tree decl = build_decl (BUILTINS_LOCATION, VAR_DECL, + mapper_id, integer_type_node); + DECL_ARTIFICIAL (decl) = 1; + DECL_EXTERNAL (decl) = 1; + TREE_STATIC (decl) = 1; + TREE_PUBLIC (decl) = 0; + bind (mapper_id, decl, current_scope, true, false, BUILTINS_LOCATION); + return decl; +} + +/* Lookup MAPPER_ID in the first scope where it has entry for TYPE. */ + +tree +c_omp_mapper_lookup (tree mapper_id, tree type) +{ + if (!RECORD_OR_UNION_TYPE_P (type)) + return NULL_TREE; + + mapper_id = c_omp_mapper_id (mapper_id); + + struct c_binding *b = I_SYMBOL_BINDING (mapper_id); + while (b) + { + tree t; + for (t = DECL_INITIAL (b->decl); t; t = TREE_CHAIN (t)) + if (comptypes (TREE_PURPOSE (t), type)) + return TREE_VALUE (t); + b = b->shadowed; + } + return NULL_TREE; +} + +/* For C, we record a pointer to the mapper itself without wrapping it in an + artificial function or similar. So, just return it. */ + +tree +c_omp_extract_mapper_directive (tree mapper) +{ + return mapper; +} + +/* For now we can handle singleton OMP_ARRAY_SECTIONs with custom mappers, but + nothing more complicated. */ + +tree +c_omp_map_array_section (location_t loc, tree t) +{ + tree low = TREE_OPERAND (t, 1); + tree len = TREE_OPERAND (t, 2); + + if (len && integer_onep (len)) + { + t = TREE_OPERAND (t, 0); + + if (!low) + low = integer_zero_node; + + t = build_array_ref (loc, t, low); + } + + return t; +} + +/* Helper function for below function. */ + +static tree +c_omp_scan_mapper_bindings_r (tree *tp, int *walk_subtrees, void *ptr) +{ + tree t = *tp; + omp_mapper_list<tree> *mlist = (omp_mapper_list<tree> *) ptr; + tree aggr_type = NULL_TREE; + + if (TREE_CODE (t) == SIZEOF_EXPR + || TREE_CODE (t) == ALIGNOF_EXPR) + { + *walk_subtrees = 0; + return NULL_TREE; + } + + if (TREE_CODE (t) == OMP_CLAUSE) + return NULL_TREE; + + if (TREE_CODE (t) == COMPONENT_REF + && RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0)))) + aggr_type = TREE_TYPE (TREE_OPERAND (t, 0)); + else if ((TREE_CODE (t) == VAR_DECL + || TREE_CODE (t) == PARM_DECL + || TREE_CODE (t) == RESULT_DECL) + && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t))) + aggr_type = TREE_TYPE (t); + + if (aggr_type) + { + tree mapper_fn = c_omp_mapper_lookup (NULL_TREE, aggr_type); + if (mapper_fn) + mlist->add_mapper (NULL_TREE, aggr_type, mapper_fn); + } + + return NULL_TREE; +} + +/* Scan an offload region's body, and record uses of struct- or union-typed + variables. Add _mapper_binding_ fake clauses to *CLAUSES_PTR. */ + +void +c_omp_scan_mapper_bindings (location_t loc, tree *clauses_ptr, tree body) +{ + hash_set<omp_name_type<tree>> seen_types; + auto_vec<tree> mappers; + omp_mapper_list<tree> mlist (&seen_types, &mappers); + + walk_tree_without_duplicates (&body, c_omp_scan_mapper_bindings_r, &mlist); + + unsigned int i; + tree mapper; + FOR_EACH_VEC_ELT (mappers, i, mapper) + c_omp_find_nested_mappers (&mlist, mapper); + + FOR_EACH_VEC_ELT (mappers, i, mapper) + { + if (mapper == error_mark_node) + continue; + tree mapper_name = OMP_DECLARE_MAPPER_ID (mapper); + tree decl = OMP_DECLARE_MAPPER_DECL (mapper); + + tree c = build_omp_clause (loc, OMP_CLAUSE__MAPPER_BINDING_); + OMP_CLAUSE__MAPPER_BINDING__ID (c) = mapper_name; + OMP_CLAUSE__MAPPER_BINDING__DECL (c) = decl; + OMP_CLAUSE__MAPPER_BINDING__MAPPER (c) = mapper; + + OMP_CLAUSE_CHAIN (c) = *clauses_ptr; + *clauses_ptr = c; + } +} bool c_check_in_current_scope (tree decl) @@ -13895,7 +14119,8 @@ c_get_loop_names (tree before_labels, bool switch_p, tree *last_p) ++ret; } } - else if (TREE_CODE (stmt) != CASE_LABEL_EXPR) + else if (TREE_CODE (stmt) != CASE_LABEL_EXPR + && TREE_CODE (stmt) != DEBUG_BEGIN_STMT) break; } if (last) |
