aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/ChangeLog397
-rw-r--r--gcc/c/c-decl.cc524
-rw-r--r--gcc/c/c-errors.cc63
-rw-r--r--gcc/c/c-lang.h12
-rw-r--r--gcc/c/c-objc-common.cc10
-rw-r--r--gcc/c/c-objc-common.h12
-rw-r--r--gcc/c/c-parser.cc698
-rw-r--r--gcc/c/c-tree.h25
-rw-r--r--gcc/c/c-typeck.cc727
-rw-r--r--gcc/c/gimple-parser.cc109
10 files changed, 1879 insertions, 698 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index f75a0f6..87a18c9 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,400 @@
+2025-08-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR preprocessor/120778
+ * c-decl.cc (c_init_decl_processing): Mark cpp nodes corresponding
+ to keywords as NODE_WARN if warn_keyword_macro.
+
+2025-08-06 Alexandre Oliva <oliva@adacore.com>
+
+ * c-tree.h (C_BOOLEAN_TYPE_P): Cover hardbools as well.
+ * c-typeck.cc (convert_lvalue_to_rvalue): New overload and
+ wrapper.
+ (build_atomic_assign, build_modify_expr): Use it.
+ (build_asm_expr, handle_omp-array_sections_1): Simplify with
+ it.
+ (build_unary_op): Handle hardbools.
+
+2025-08-06 Martin Uecker <uecker@tugraz.at>
+
+ PR c/108931
+ * c-typeck.cc (composite_type_cond): Renamed from
+ composite_type with argument for condition
+ (composite_type): New function.
+ (composite_type_internal): Implement new logic.
+ (build_conditional_expr): Pass condition.
+ (common_pointer_type): Adapt.
+ (pointer_diff): Adapt.
+ (build_binary_op): Adapt.
+
+2025-08-06 Martin Uecker <uecker@tugraz.at>
+
+ PR c/121217
+ * c-typeck.cc (tagged_types_tu_compatible_p): Add check.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+
+ * c-parser.cc (c_parser_omp_clause_from_to): Parse 'iterator' modifier.
+ * c-typeck.cc (c_finish_omp_clauses): Finish iterators for to/from
+ clauses.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+ Andrew Stubbs <ams@baylibre.com>
+
+ * c-parser.cc (c_parser_omp_variable_list): Use location of the
+ map expression as the clause location.
+ (c_parser_omp_clause_map): Parse 'iterator' modifier.
+ * c-typeck.cc (c_finish_omp_clauses): Finish iterators. Apply
+ iterators to generated clauses.
+
+2025-08-02 Martin Uecker <uecker@tugraz.at>
+
+ * c-decl.cc (get_parm_array_spec): Remove.
+ (push_parm_decl): Do not add `arg spec` attribute.
+ (build_arg_spec_attribute): New function.
+ (grokdeklarator): Add `arg spec` attribute.
+
+2025-07-25 David Malcolm <dmalcolm@redhat.com>
+
+ * c-errors.cc: Update usage of "diagnostic_info" to explicitly
+ refer to "diagnostics::diagnostic_info".
+
+2025-07-25 David Malcolm <dmalcolm@redhat.com>
+
+ * c-errors.cc: Update for diagnostic_t becoming
+ enum class diagnostics::kind.
+ * c-parser.cc: Likewise.
+ * c-typeck.cc: Likewise.
+
+2025-07-25 David Malcolm <dmalcolm@redhat.com>
+
+ * c-decl.cc: Update for renaming of diagnostic_option_id to
+ diagnostics::option_id.
+ * c-errors.cc: Likewise.
+ * c-tree.h: Likewise.
+
+2025-07-25 David Malcolm <dmalcolm@redhat.com>
+
+ * c-objc-common.cc: Update for diagnostic_context becoming
+ diagnostics::context.
+ * c-tree.h: Likewise.
+
+2025-07-25 David Malcolm <dmalcolm@redhat.com>
+
+ * c-errors.cc: Update to add "m_" prefix to fields of
+ diagnostic_info throughout.
+
+2025-07-21 Stefan Schulze Frielinghaus <stefansf@gcc.gnu.org>
+
+ * c-typeck.cc (build_asm_expr): Pass null pointer to
+ parse_{input,output}_constraint().
+
+2025-07-16 Kwok Cheung Yeung <kcyeung@baylibre.com>
+
+ * c-typeck.cc (handle_omp_array_sections): Use OMP_ITERATOR_DECL_P.
+ (c_finish_omp_clauses): Likewise.
+
+2025-07-15 Jakub Jelinek <jakub@redhat.com>
+ Jason Merrill <jason@redhat.com>
+
+ PR c/44677
+ * c-parser.cc (c_parser_unary_expression): Clear DECL_READ_P
+ after default_function_array_read_conversion for
+ -Wunused-but-set-{parameter,variable}={2,3} on
+ PRE{IN,DE}CREMENT_EXPR argument.
+ (c_parser_postfix_expression_after_primary): Similarly for
+ POST{IN,DE}CREMENT_EXPR.
+ * c-decl.cc (pop_scope): Use OPT_Wunused_but_set_variable_
+ instead of OPT_Wunused_but_set_variable.
+ (finish_function): Use OPT_Wunused_but_set_parameter_
+ instead of OPT_Wunused_but_set_parameter.
+ * c-typeck.cc (mark_exp_read): Handle {PRE,POST}{IN,DE}CREMENT_EXPR
+ and don't handle it when cast to void.
+ (build_modify_expr): Clear DECL_READ_P after build_binary_op
+ for -Wunused-but-set-{parameter,variable}=3.
+
+2025-07-10 Qing Zhao <qing.zhao@oracle.com>
+
+ * c-typeck.cc (build_access_with_size_for_counted_by): Update comments.
+ Adjust the arguments per the new design.
+
+2025-07-10 Qing Zhao <qing.zhao@oracle.com>
+
+ PR middle-end/121000
+ * c-typeck.cc (build_access_with_size_for_counted_by): Update comments.
+ Pass TYPE_SIZE_UNIT of the element as the 6th argument.
+
+2025-07-07 Qing Zhao <qing.zhao@oracle.com>
+
+ Revert:
+ 2025-07-07 Qing Zhao <qing.zhao@oracle.com>
+
+ * c-decl.cc (verify_counted_by_attribute): Change the 2nd argument
+ to a vector of fields with counted_by attribute. Verify all fields
+ in this vector.
+ (finish_struct): Collect all the fields with counted_by attribute
+ to a vector and pass this vector to verify_counted_by_attribute.
+ * c-typeck.cc (build_counted_by_ref): Handle pointers with counted_by.
+ Add one more argument, issue error when the pointee type is a structure
+ or union including a flexible array member.
+ (build_access_with_size_for_counted_by): Handle pointers with counted_by.
+ (handle_counted_by_for_component_ref): Call build_counted_by_ref
+ with the new prototype.
+
+2025-07-01 Qing Zhao <qing.zhao@oracle.com>
+
+ * c-decl.cc (verify_counted_by_attribute): Change the 2nd argument
+ to a vector of fields with counted_by attribute. Verify all fields
+ in this vector.
+ (finish_struct): Collect all the fields with counted_by attribute
+ to a vector and pass this vector to verify_counted_by_attribute.
+ * c-typeck.cc (build_counted_by_ref): Handle pointers with counted_by.
+ Add one more argument, issue error when the pointee type is a structure
+ or union including a flexible array member.
+ (build_access_with_size_for_counted_by): Handle pointers with counted_by.
+ (handle_counted_by_for_component_ref): Call build_counted_by_ref
+ with the new prototype.
+
+2025-06-23 Tobias Burnus <tburnus@baylibre.com>
+
+ * c-parser.cc (OACC_WAIT_CLAUSE_MASK): Add if clause.
+
+2025-06-12 Jakub Jelinek <jakub@redhat.com>
+
+ * c-lang.h (union lang_type::maybe_objc_info): New type.
+ (struct lang_type): Use union maybe_objc_info info member
+ instead of tree objc_info.
+ * c-decl.cc (finish_struct): Allocate struct lang_type using
+ ggc_internal_cleared_alloc instead of ggc_cleared_alloc,
+ and use sizeof (struct lang_type) for ObjC and otherwise
+ offsetof (struct lang_type, info) as size.
+ (finish_enum): Likewise.
+
+2025-06-11 Martin Uecker <uecker@tugraz.at>
+
+ PR c/120510
+ * c-typeck.cc (composite_type_internal): Activate checking
+ assertions for all types and also inputs.
+ (comptypes_for_composite_check): New helper function.
+ (function_types_compatible_p): Add exception.
+
+2025-06-11 Martin Uecker <uecker@tugraz.at>
+
+ * c-typeck.cc (function_types_compatible_p): Remove unused
+ variables and return true/false instead of 1/0.
+ (type_lists_compatible_p): Return false instead of 0.
+
+2025-06-11 Martin Uecker <uecker@tugraz.at>
+
+ PR c/120303
+ * c-parser.cc (c_parser_generic_selection): Handle error
+ condition.
+
+2025-06-09 Martin Uecker <uecker@tugraz.at>
+
+ PR c/120510
+ * c-typeck.cc (remove_qualifiers): New function.
+ (composite_type_internal): Use it.
+ (comp_target_types): Use it.
+ (type_lists_compatible_p): Use it.
+ (find_anonymous_field_with_type): Use it.
+ (convert_to_anonymous_field): Use it.
+ (convert_for_assignment): Use it.
+
+2025-06-09 Martin Uecker <uecker@tugraz.at>
+
+ PR c/120510
+ * c-typeck.cc (composite_type_internal): Activate checking
+ assertion for arrays.
+ (common_pointer_type): Remove qualifiers also from arrays.
+
+2025-06-09 Martin Uecker <uecker@tugraz.at>
+
+ PR c/120510
+ * c-typeck.cc (composite_types_internal): Handle arrays
+ declared with atomic for function arguments.
+
+2025-06-03 Martin Uecker <uecker@tugraz.at>
+
+ * c-typeck.cc (composite_type_internal,composite_type): Move
+ checking assertions.
+
+2025-06-03 Martin Uecker <uecker@tugraz.at>
+
+ PR c/116892
+ * c-decl.cc (finish_enum): Propagate TYPE_PACKED.
+
+2025-06-02 Sandra Loosemore <sloosemore@baylibre.com>
+
+ * c-parser.cc (c_parser_omp_context_selector): Call
+ convert_lvalue_to_rvalue and c_objc_common_truthvalue_conversion
+ on the expression for OMP_TRAIT_PROPERTY_BOOL_EXPR.
+
+2025-06-01 Martin Uecker <uecker@tugraz.at>
+
+ PR c/120380
+ * c-objc-common.cc (get_aka_type): Ignore attributes for tagged types.
+
+2025-05-30 Qing Zhao <qing.zhao@oracle.com>
+
+ PR c/120354
+ * c-decl.cc (finish_struct): Or the results for TYPE_INCLUDES_FLEXARRAY.
+
+2025-05-30 Qing Zhao <qing.zhao@oracle.com>
+
+ PR c/120353
+ * c-decl.cc (finish_struct): Copy TYPE_INCLUDES_FLEXARRAY marking
+ to all the variant types of the current structure type.
+
+2025-05-30 Julian Brown <julian@codesourcery.com>
+
+ * c-decl.cc (c_omp_mapper_id, c_omp_mapper_decl, c_omp_mapper_lookup,
+ c_omp_extract_mapper_directive, c_omp_map_array_section,
+ c_omp_scan_mapper_bindings_r, c_omp_scan_mapper_bindings): New
+ functions.
+ * c-objc-common.h (LANG_HOOKS_OMP_FINISH_MAPPER_CLAUSES,
+ LANG_HOOKS_OMP_MAPPER_LOOKUP, LANG_HOOKS_OMP_EXTRACT_MAPPER_DIRECTIVE,
+ LANG_HOOKS_OMP_MAP_ARRAY_SECTION): Define langhooks for C.
+ * c-parser.cc (c_parser_omp_clause_map): Add declare_mapper_p
+ parameter; handle mapper modifier.
+ (c_parser_omp_all_clauses): Update call to c_parser_omp_clause_map.
+ (c_parser_omp_target): Instantiate explicit mappers and record bindings
+ for implicit mappers.
+ (c_parser_omp_declare_mapper): Parse "declare mapper" directives.
+ (c_parser_omp_declare): Support "declare mapper".
+ (c_parser_omp_declare_reduction): Use inform not error_at.
+ * c-tree.h (c_omp_finish_mapper_clauses, c_omp_mapper_lookup,
+ c_omp_extract_mapper_directive, c_omp_map_array_section,
+ c_omp_mapper_id, c_omp_mapper_decl, c_omp_scan_mapper_bindings,
+ c_omp_instantiate_mappers): Add prototypes.
+ * c-typeck.cc (c_finish_omp_clauses): Handle GOMP_MAP_PUSH_MAPPER_NAME
+ and GOMP_MAP_POP_MAPPER_NAME.
+ (c_omp_finish_mapper_clauses): New function (langhook).
+
+2025-05-30 Martin Uecker <uecker@tugraz.at>
+
+ PR c/120381
+ * c-typeck.cc (composite_type_internal): Stop recursion for
+ swapped pairs.
+
+2025-05-29 Sandra Loosemore <sloosemore@baylibre.com>
+
+ * c-parser.cc (c_parser_skip_to_closing_brace): New, copied from
+ the equivalent function in the C++ front end.
+ (c_parser_skip_to_end_of_block_or_statement): Pass false to
+ the error flag.
+ (c_parser_omp_context_selector): Immediately return error_mark_node
+ after giving an error that the integer trait property is invalid,
+ similarly to C++ front end.
+ (c_parser_omp_context_selector_specification): Likewise handle
+ error return from c_parser_omp_context_selector similarly to C++.
+ (c_parser_omp_metadirective): Do not call
+ c_parser_skip_to_end_of_block_or_statement after an error.
+
+2025-05-29 Sandra Loosemore <sloosemore@baylibre.com>
+
+ PR c/120180
+ * c-parser.cc (c_parser_omp_metadirective): Only consume the
+ token if it is the expected close paren.
+
+2025-05-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/117025
+ * c-parser.cc (c_parser_sizeof_or_countof_expression): Use
+ C2Y rather than C23 in pedwarn_c23.
+
+2025-05-27 Alejandro Colomar <alx@kernel.org>
+
+ PR c/117025
+ * c-parser.cc (c_parser_sizeof_or_countof_expression):
+ Add -Wpedantic diagnostic for _Countof in <= C23 mode.
+
+2025-05-27 Alejandro Colomar <alx@kernel.org>
+ Martin Uecker <uecker@tugraz.at>
+
+ PR c/117025
+ * c-tree.h (in_countof): Add global variable declaration.
+ (c_expr_countof_expr): Add function prototype.
+ (c_expr_countof_type): Add function prototype.
+ * c-decl.cc (start_struct, finish_struct): Add support for
+ _Countof.
+ (start_enum, finish_enum): Add support for _Countof.
+ * c-parser.cc (c_parser_sizeof_expression): New macro.
+ (c_parser_countof_expression): New macro.
+ (c_parser_sizeof_or_countof_expression): Rename function and add
+ support for _Countof.
+ (c_parser_unary_expression): Add RID_COUNTOF entry.
+ * c-typeck.cc (in_countof): Add global variable.
+ (build_external_ref): Add support for _Countof.
+ (record_maybe_used_decl): Add support for _Countof.
+ (pop_maybe_used): Add support for _Countof.
+ (is_top_array_vla): New function.
+ (c_expr_countof_expr, c_expr_countof_type): New functions.
+
+2025-05-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/120057
+ * c-typeck.cc (check_constexpr_init): Handle RAW_DATA_CST.
+
+2025-05-02 Florian Weimer <fweimer@redhat.com>
+
+ PR c/120055
+ * c-typeck.cc (convert_arguments): Check if fundecl is null
+ before checking for builtin function declaration.
+
+2025-05-01 Christopher Bazley <chris.bazley@arm.com>
+
+ PR c/119317
+ * c-decl.cc (c_get_loop_names): Do not prematurely
+ end the search for a label that names a loop or
+ switch statement upon encountering a DEBUG_BEGIN_STMT.
+ Instead, ignore any instances of DEBUG_BEGIN_STMT.
+
+2025-05-01 Florian Weimer <fweimer@redhat.com>
+
+ PR c/119950
+ * c-typeck.cc (convert_arguments): Check for built-in
+ function declaration before warning.
+
+2025-04-28 David Malcolm <dmalcolm@redhat.com>
+
+ * c-decl.cc: Drop include of "make-unique.h".
+ Replace uses of ::make_unique with std::make_unique.
+ * c-objc-common.cc: Likewise.
+ * c-parser.cc: Likewise.
+
+2025-04-28 David Malcolm <dmalcolm@redhat.com>
+
+ * c-decl.cc: Include "make-unique.h".
+ (lookup_name_fuzzy): Use ::make_unique rather than "new" when
+ making suggest_missing_header and suggest_missing_option.
+ * c-parser.cc: Include "make-unique.h"
+ (c_parser_error_richloc): Use ::make_unique rather than "new" when
+ making suggest_missing_header.
+
+2025-04-28 Andrew Pinski <quic_apinski@quicinc.com>
+
+ PR c/119432
+ * gimple-parser.cc (gimple_binary_identifier_code): Add
+ __ROTATE_LEFT and __ROTATE_RIGHT.
+
+2025-04-28 Andrew Pinski <quic_apinski@quicinc.com>
+
+ * gimple-parser.cc (gimple_binary_identifier_code): New variable.
+ (c_parser_gimple_binary_expression): Use gimple_binary_identifier_code
+ instead of doing if statements on the strings.
+
+2025-04-27 H.J. Lu <hjl.tools@gmail.com>
+
+ PR c/48274
+ PR middle-end/112877
+ PR middle-end/118288
+ * c-decl.cc (start_decl): Remove the
+ targetm.calls.promote_prototypes call.
+ (store_parm_decls_oldstyle): Likewise.
+ (finish_function): Likewise.
+ * c-typeck.cc (convert_argument): Likewise.
+ (c_safe_arg_type_equiv_p): Likewise.
+
2025-04-15 Qing Zhao <qing.zhao@oracle.com>
PR c/119717
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 8c420f2..8e8bac6 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -1363,7 +1363,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)
@@ -1377,7 +1377,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);
}
@@ -4547,21 +4547,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. */
@@ -4823,6 +4825,29 @@ 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_lookup (parse_in,
+ (const unsigned char *) IDENTIFIER_POINTER (id),
+ IDENTIFIER_LENGTH (id))->flags |= NODE_WARN;
+ }
+ }
}
/* Create the VAR_DECL at LOC for __FUNCTION__ etc. ID is the name to
@@ -5721,26 +5746,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)))
@@ -6226,184 +6231,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
@@ -6419,7 +6247,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);
@@ -6793,6 +6620,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.
@@ -6852,6 +6698,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;
@@ -7344,6 +7191,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)))
@@ -7356,6 +7204,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);
@@ -7381,6 +7230,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. */
@@ -7996,6 +7846,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)
@@ -8961,12 +8815,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);
@@ -9665,15 +9521,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
@@ -9803,12 +9662,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;
@@ -9909,6 +9773,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.
@@ -9941,7 +9806,7 @@ 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);
}
@@ -10115,12 +9980,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",
@@ -10279,7 +10146,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;
@@ -10303,6 +10173,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. */
@@ -10314,7 +10185,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 */
@@ -11179,13 +11050,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
@@ -11413,19 +11277,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;
@@ -11486,9 +11337,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);
}
@@ -13857,6 +13708,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)
@@ -13899,7 +13918,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)
diff --git a/gcc/c/c-errors.cc b/gcc/c/c-errors.cc
index 4682dca..e2c74fe 100644
--- a/gcc/c/c-errors.cc
+++ b/gcc/c/c-errors.cc
@@ -33,10 +33,10 @@ along with GCC; see the file COPYING3. If not see
bool
pedwarn_c23 (location_t location,
- diagnostic_option_id option_id,
+ diagnostics::option_id option_id,
const char *gmsgid, ...)
{
- diagnostic_info diagnostic;
+ diagnostics::diagnostic_info diagnostic;
va_list ap;
bool warned = false;
rich_location richloc (line_table, location);
@@ -48,8 +48,9 @@ pedwarn_c23 (location_t location,
{
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
(pedantic && !flag_isoc2y)
- ? DK_PEDWARN : DK_WARNING);
- diagnostic.option_id = OPT_Wc23_c2y_compat;
+ ? diagnostics::kind::pedwarn
+ : diagnostics::kind::warning);
+ diagnostic.m_option_id = OPT_Wc23_c2y_compat;
warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
}
/* -Wno-c23-c2y-compat suppresses even the pedwarns. */
@@ -58,8 +59,9 @@ pedwarn_c23 (location_t location,
/* For -pedantic outside C2Y, issue a pedwarn. */
else if (pedantic && !flag_isoc2y)
{
- diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
- diagnostic.option_id = option_id;
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
+ diagnostics::kind::pedwarn);
+ diagnostic.m_option_id = option_id;
warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
}
va_end (ap);
@@ -77,10 +79,10 @@ pedwarn_c23 (location_t location,
bool
pedwarn_c11 (location_t location,
- diagnostic_option_id option_id,
+ diagnostics::option_id option_id,
const char *gmsgid, ...)
{
- diagnostic_info diagnostic;
+ diagnostics::diagnostic_info diagnostic;
va_list ap;
bool warned = false;
rich_location richloc (line_table, location);
@@ -93,11 +95,12 @@ pedwarn_c11 (location_t location,
{
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
(pedantic && !flag_isoc23)
- ? DK_PEDWARN : DK_WARNING);
+ ? diagnostics::kind::pedwarn
+ : diagnostics::kind::warning);
if (option_id == OPT_Wpedantic)
- diagnostic.option_id = OPT_Wc11_c23_compat;
+ diagnostic.m_option_id = OPT_Wc11_c23_compat;
else
- diagnostic.option_id = option_id;
+ diagnostic.m_option_id = option_id;
warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
}
/* -Wno-c11-c23-compat suppresses even the pedwarns. */
@@ -106,8 +109,9 @@ pedwarn_c11 (location_t location,
/* For -pedantic outside C23, issue a pedwarn. */
else if (pedantic && !flag_isoc23)
{
- diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
- diagnostic.option_id = option_id;
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
+ diagnostics::kind::pedwarn);
+ diagnostic.m_option_id = option_id;
warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
}
va_end (ap);
@@ -122,10 +126,10 @@ pedwarn_c11 (location_t location,
bool
pedwarn_c99 (location_t location,
- diagnostic_option_id option_id,
+ diagnostics::option_id option_id,
const char *gmsgid, ...)
{
- diagnostic_info diagnostic;
+ diagnostics::diagnostic_info diagnostic;
va_list ap;
bool warned = false;
rich_location richloc (line_table, location);
@@ -137,8 +141,9 @@ pedwarn_c99 (location_t location,
{
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
(pedantic && !flag_isoc11)
- ? DK_PEDWARN : DK_WARNING);
- diagnostic.option_id = OPT_Wc99_c11_compat;
+ ? diagnostics::kind::pedwarn
+ : diagnostics::kind::warning);
+ diagnostic.m_option_id = OPT_Wc99_c11_compat;
warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
}
/* -Wno-c99-c11-compat suppresses even the pedwarns. */
@@ -147,8 +152,9 @@ pedwarn_c99 (location_t location,
/* For -pedantic outside C11, issue a pedwarn. */
else if (pedantic && !flag_isoc11)
{
- diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
- diagnostic.option_id = option_id;
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
+ diagnostics::kind::pedwarn);
+ diagnostic.m_option_id = option_id;
warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
}
va_end (ap);
@@ -164,10 +170,10 @@ pedwarn_c99 (location_t location,
bool
pedwarn_c90 (location_t location,
- diagnostic_option_id option_id,
+ diagnostics::option_id option_id,
const char *gmsgid, ...)
{
- diagnostic_info diagnostic;
+ diagnostics::diagnostic_info diagnostic;
va_list ap;
bool warned = false;
rich_location richloc (line_table, location);
@@ -183,8 +189,9 @@ pedwarn_c90 (location_t location,
{
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
(pedantic && !flag_isoc99)
- ? DK_PEDWARN : DK_WARNING);
- diagnostic.option_id = option_id;
+ ? diagnostics::kind::pedwarn
+ : diagnostics::kind::warning);
+ diagnostic.m_option_id = option_id;
diagnostic_report_diagnostic (global_dc, &diagnostic);
warned = true;
goto out;
@@ -196,8 +203,9 @@ pedwarn_c90 (location_t location,
{
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
(pedantic && !flag_isoc99)
- ? DK_PEDWARN : DK_WARNING);
- diagnostic.option_id = OPT_Wc90_c99_compat;
+ ? diagnostics::kind::pedwarn
+ : diagnostics::kind::warning);
+ diagnostic.m_option_id = OPT_Wc90_c99_compat;
diagnostic_report_diagnostic (global_dc, &diagnostic);
}
/* -Wno-c90-c99-compat suppresses the pedwarns. */
@@ -206,8 +214,9 @@ pedwarn_c90 (location_t location,
/* For -pedantic outside C99, issue a pedwarn. */
else if (pedantic && !flag_isoc99)
{
- diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
- diagnostic.option_id = option_id;
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
+ diagnostics::kind::pedwarn);
+ diagnostic.m_option_id = option_id;
diagnostic_report_diagnostic (global_dc, &diagnostic);
warned = true;
}
diff --git a/gcc/c/c-lang.h b/gcc/c/c-lang.h
index 4b93d18..2e99b4d 100644
--- a/gcc/c/c-lang.h
+++ b/gcc/c/c-lang.h
@@ -35,10 +35,14 @@ struct GTY(()) lang_type {
/* In an ENUMERAL_TYPE, the min and max values. */
tree enum_min;
tree enum_max;
- /* In a RECORD_TYPE, information specific to Objective-C, such
- as a list of adopted protocols or a pointer to a corresponding
- @interface. See objc/objc-act.h for details. */
- tree objc_info;
+ union maybe_objc_info {
+ /* If not c_dialect_objc, this part is not even allocated. */
+ char GTY((tag ("0"))) non_objc;
+ /* In a RECORD_TYPE, information specific to Objective-C, such
+ as a list of adopted protocols or a pointer to a corresponding
+ @interface. See objc/objc-act.h for details. */
+ tree GTY((tag ("1"))) objc_info;
+ } GTY ((desc ("c_dialect_objc ()"))) info;
};
struct GTY(()) lang_decl {
diff --git a/gcc/c/c-objc-common.cc b/gcc/c/c-objc-common.cc
index 7e227d3..5c50983 100644
--- a/gcc/c/c-objc-common.cc
+++ b/gcc/c/c-objc-common.cc
@@ -32,7 +32,6 @@ along with GCC; see the file COPYING3. If not see
#include "stringpool.h"
#include "attribs.h"
#include "dwarf2.h"
-#include "make-unique.h"
static bool c_tree_printer (pretty_printer *, text_info *, const char *,
int, bool, bool, bool, bool *, pp_token_list &);
@@ -217,6 +216,11 @@ get_aka_type (tree type)
return canonical ? canonical : type;
}
}
+ /* For tagged types ignore attributes because they will otherwise
+ be ignored later causing a warning inside diagnostics which leads
+ to an ICE. */
+ if (RECORD_OR_UNION_TYPE_P (type) || TREE_CODE (type) == ENUMERAL_TYPE)
+ return build_qualified_type (result, TYPE_QUALS (type));
return build_type_attribute_qual_variant (result, TYPE_ATTRIBUTES (type),
TYPE_QUALS (type));
}
@@ -410,9 +414,9 @@ has_c_linkage (const_tree decl ATTRIBUTE_UNUSED)
}
void
-c_initialize_diagnostics (diagnostic_context *context)
+c_initialize_diagnostics (diagnostics::context *context)
{
- context->set_pretty_printer (::make_unique<c_pretty_printer> ());
+ context->set_pretty_printer (std::make_unique<c_pretty_printer> ());
c_common_diagnostics_set_defaults (context);
context->set_format_decoder (&c_tree_printer);
}
diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h
index 84bd357..84f6fd3 100644
--- a/gcc/c/c-objc-common.h
+++ b/gcc/c/c-objc-common.h
@@ -137,6 +137,18 @@ static const scoped_attribute_specs *const c_objc_attribute_table[] =
#undef LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP
#define LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP c_omp_clause_copy_ctor
+#undef LANG_HOOKS_OMP_FINISH_MAPPER_CLAUSES
+#define LANG_HOOKS_OMP_FINISH_MAPPER_CLAUSES c_omp_finish_mapper_clauses
+
+#undef LANG_HOOKS_OMP_MAPPER_LOOKUP
+#define LANG_HOOKS_OMP_MAPPER_LOOKUP c_omp_mapper_lookup
+
+#undef LANG_HOOKS_OMP_EXTRACT_MAPPER_DIRECTIVE
+#define LANG_HOOKS_OMP_EXTRACT_MAPPER_DIRECTIVE c_omp_extract_mapper_directive
+
+#undef LANG_HOOKS_OMP_MAP_ARRAY_SECTION
+#define LANG_HOOKS_OMP_MAP_ARRAY_SECTION c_omp_map_array_section
+
#undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P
#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P c_var_mod_p
#endif /* GCC_C_OBJC_COMMON */
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 22ec0f8..814accf 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -77,7 +77,7 @@ along with GCC; see the file COPYING3. If not see
#include "asan.h"
#include "c-family/c-ubsan.h"
#include "gcc-urlifier.h"
-
+
/* We need to walk over decls with incomplete struct/union/enum types
after parsing the whole translation unit.
In finish_decl(), if the decl is static, has incomplete
@@ -1072,9 +1072,11 @@ c_parser_error_richloc (c_parser *parser, const char *gmsgid,
const char *header_hint
= get_c_stdlib_header_for_string_macro_name (token_name);
if (header_hint != NULL)
- h = name_hint (NULL, new suggest_missing_header (token->location,
- token_name,
- header_hint));
+ h = name_hint (nullptr,
+ std::make_unique<suggest_missing_header>
+ (token->location,
+ token_name,
+ header_hint));
}
c_parse_error (gmsgid,
@@ -1418,6 +1420,51 @@ c_parser_skip_to_end_of_parameter (c_parser *parser)
parser->error = false;
}
+/* Skip tokens until a non-nested closing curly brace is the next
+ token, or there are no more tokens. Return true in the first case,
+ false otherwise. */
+
+static bool
+c_parser_skip_to_closing_brace (c_parser *parser)
+{
+ unsigned nesting_depth = 0;
+
+ while (true)
+ {
+ c_token *token = c_parser_peek_token (parser);
+
+ switch (token->type)
+ {
+ case CPP_PRAGMA_EOL:
+ if (!parser->in_pragma)
+ break;
+ /* FALLTHRU */
+ case CPP_EOF:
+ /* If we've run out of tokens, stop. */
+ return false;
+
+ case CPP_CLOSE_BRACE:
+ /* If the next token is a non-nested `}', then we have reached
+ the end of the current block. */
+ if (nesting_depth-- == 0)
+ return true;
+ break;
+
+ case CPP_OPEN_BRACE:
+ /* If it the next token is a `{', then we are entering a new
+ block. Consume the entire block. */
+ ++nesting_depth;
+ break;
+
+ default:
+ break;
+ }
+
+ /* Consume the token. */
+ c_parser_consume_token (parser);
+ }
+}
+
/* Expect to be at the end of the pragma directive and consume an
end of line marker. */
@@ -1533,7 +1580,7 @@ c_parser_skip_to_end_of_block_or_statement (c_parser *parser,
here for secondary error recovery, after parser->error has
been cleared. */
c_parser_consume_pragma (parser);
- c_parser_skip_to_pragma_eol (parser);
+ c_parser_skip_to_pragma_eol (parser, false);
parser->error = save_error;
continue;
@@ -1735,7 +1782,10 @@ static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *,
tree);
static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
static struct c_expr c_parser_unary_expression (c_parser *);
-static struct c_expr c_parser_sizeof_expression (c_parser *);
+static inline struct c_expr c_parser_sizeof_expression (c_parser *);
+static inline struct c_expr c_parser_countof_expression (c_parser *);
+static struct c_expr c_parser_sizeof_or_countof_expression (c_parser *,
+ enum rid);
static struct c_expr c_parser_alignof_expression (c_parser *);
static struct c_expr c_parser_postfix_expression (c_parser *);
static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
@@ -10450,9 +10500,13 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
++ unary-expression
-- unary-expression
unary-operator cast-expression
+ _Countof unary-expression
+ _Countof ( type-name )
sizeof unary-expression
sizeof ( type-name )
+ (_Countof is new in C2y.)
+
unary-operator: one of
& * + - ~ !
@@ -10493,15 +10547,31 @@ c_parser_unary_expression (c_parser *parser)
c_parser_consume_token (parser);
exp_loc = c_parser_peek_token (parser)->location;
op = c_parser_cast_expression (parser, NULL);
-
- op = default_function_array_read_conversion (exp_loc, op);
+ if ((VAR_P (op.value) || TREE_CODE (op.value) == PARM_DECL)
+ && !DECL_READ_P (op.value)
+ && (VAR_P (op.value) ? warn_unused_but_set_variable
+ : warn_unused_but_set_parameter) > 1)
+ {
+ op = default_function_array_read_conversion (exp_loc, op);
+ DECL_READ_P (op.value) = 0;
+ }
+ else
+ op = default_function_array_read_conversion (exp_loc, op);
return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
case CPP_MINUS_MINUS:
c_parser_consume_token (parser);
exp_loc = c_parser_peek_token (parser)->location;
op = c_parser_cast_expression (parser, NULL);
-
- op = default_function_array_read_conversion (exp_loc, op);
+ if ((VAR_P (op.value) || TREE_CODE (op.value) == PARM_DECL)
+ && !DECL_READ_P (op.value)
+ && (VAR_P (op.value) ? warn_unused_but_set_variable
+ : warn_unused_but_set_parameter) > 1)
+ {
+ op = default_function_array_read_conversion (exp_loc, op);
+ DECL_READ_P (op.value) = 0;
+ }
+ else
+ op = default_function_array_read_conversion (exp_loc, op);
return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
case CPP_AND:
c_parser_consume_token (parser);
@@ -10570,6 +10640,8 @@ c_parser_unary_expression (c_parser *parser)
case CPP_KEYWORD:
switch (c_parser_peek_token (parser)->keyword)
{
+ case RID_COUNTOF:
+ return c_parser_countof_expression (parser);
case RID_SIZEOF:
return c_parser_sizeof_expression (parser);
case RID_ALIGNOF:
@@ -10608,22 +10680,46 @@ c_parser_unary_expression (c_parser *parser)
/* Parse a sizeof expression. */
-static struct c_expr
+static inline struct c_expr
c_parser_sizeof_expression (c_parser *parser)
{
+ return c_parser_sizeof_or_countof_expression (parser, RID_SIZEOF);
+}
+
+/* Parse a _Countof expression. */
+
+static inline struct c_expr
+c_parser_countof_expression (c_parser *parser)
+{
+ return c_parser_sizeof_or_countof_expression (parser, RID_COUNTOF);
+}
+
+/* Parse a sizeof or _Countof expression. */
+
+static struct c_expr
+c_parser_sizeof_or_countof_expression (c_parser *parser, enum rid rid)
+{
+ const char *op_name = (rid == RID_COUNTOF) ? "_Countof" : "sizeof";
struct c_expr expr;
struct c_expr result;
location_t expr_loc;
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF));
+ gcc_assert (c_parser_next_token_is_keyword (parser, rid));
location_t start;
location_t finish = UNKNOWN_LOCATION;
start = c_parser_peek_token (parser)->location;
+ if (rid == RID_COUNTOF)
+ pedwarn_c23 (start, OPT_Wpedantic,
+ "ISO C does not support %qs before C2Y", op_name);
+
c_parser_consume_token (parser);
c_inhibit_evaluation_warnings++;
- in_sizeof++;
+ if (rid == RID_COUNTOF)
+ in_countof++;
+ else
+ in_sizeof++;
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
&& c_token_starts_compound_literal (c_parser_peek_2nd_token (parser)))
{
@@ -10644,7 +10740,7 @@ c_parser_sizeof_expression (c_parser *parser)
for parsing error; the parsing of the expression could have
called record_maybe_used_decl. */
expr.set_error ();
- goto sizeof_expr;
+ goto Xof_expr;
}
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
{
@@ -10652,31 +10748,45 @@ c_parser_sizeof_expression (c_parser *parser)
type_name,
expr_loc);
finish = expr.get_finish ();
- goto sizeof_expr;
+ goto Xof_expr;
}
/* sizeof ( type-name ). */
if (scspecs)
- error_at (expr_loc, "storage class specifier in %<sizeof%>");
+ error_at (expr_loc, "storage class specifier in %qs", op_name);
if (type_name->specs->alignas_p)
error_at (type_name->specs->locations[cdw_alignas],
- "alignment specified for type name in %<sizeof%>");
+ "alignment specified for type name in %qs", op_name);
c_inhibit_evaluation_warnings--;
- in_sizeof--;
- result = c_expr_sizeof_type (expr_loc, type_name);
+ if (rid == RID_COUNTOF)
+ {
+ in_countof--;
+ result = c_expr_countof_type (expr_loc, type_name);
+ }
+ else
+ {
+ in_sizeof--;
+ result = c_expr_sizeof_type (expr_loc, type_name);
+ }
}
else
{
expr_loc = c_parser_peek_token (parser)->location;
expr = c_parser_unary_expression (parser);
finish = expr.get_finish ();
- sizeof_expr:
+ Xof_expr:
c_inhibit_evaluation_warnings--;
- in_sizeof--;
+ if (rid == RID_COUNTOF)
+ in_countof--;
+ else
+ in_sizeof--;
mark_exp_read (expr.value);
if (TREE_CODE (expr.value) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
- error_at (expr_loc, "%<sizeof%> applied to a bit-field");
- result = c_expr_sizeof_expr (expr_loc, expr);
+ error_at (expr_loc, "%qs applied to a bit-field", op_name);
+ if (rid == RID_COUNTOF)
+ result = c_expr_countof_expr (expr_loc, expr);
+ else
+ result = c_expr_sizeof_expr (expr_loc, expr);
}
if (finish == UNKNOWN_LOCATION)
finish = start;
@@ -11052,8 +11162,14 @@ c_parser_generic_selection (c_parser *parser)
"ISO C does not support use of type name as %<_Generic%> "
"controlling operand before C2Y");
struct c_type_name *type = c_parser_type_name (parser);
- selector_type = groktypename (type, NULL, NULL);
+ if (type)
+ selector_type = groktypename (type, NULL, NULL);
c_inhibit_evaluation_warnings--;
+ if (!type)
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ return error_expr;
+ }
}
else
{
@@ -13833,7 +13949,17 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
start = expr.get_start ();
finish = c_parser_peek_token (parser)->get_finish ();
c_parser_consume_token (parser);
- expr = default_function_array_read_conversion (expr_loc, expr);
+ if ((VAR_P (expr.value) || TREE_CODE (expr.value) == PARM_DECL)
+ && !DECL_READ_P (expr.value)
+ && (VAR_P (expr.value) ? warn_unused_but_set_variable
+ : warn_unused_but_set_parameter) > 1
+ && TREE_CODE (TREE_TYPE (expr.value)) != ARRAY_TYPE)
+ {
+ expr = default_function_array_read_conversion (expr_loc, expr);
+ DECL_READ_P (expr.value) = 0;
+ }
+ else
+ expr = default_function_array_read_conversion (expr_loc, expr);
expr.value = build_unary_op (op_loc, POSTINCREMENT_EXPR,
expr.value, false);
set_c_expr_source_range (&expr, start, finish);
@@ -13845,7 +13971,17 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
start = expr.get_start ();
finish = c_parser_peek_token (parser)->get_finish ();
c_parser_consume_token (parser);
- expr = default_function_array_read_conversion (expr_loc, expr);
+ if ((VAR_P (expr.value) || TREE_CODE (expr.value) == PARM_DECL)
+ && !DECL_READ_P (expr.value)
+ && (VAR_P (expr.value) ? warn_unused_but_set_variable
+ : warn_unused_but_set_parameter) > 1
+ && TREE_CODE (TREE_TYPE (expr.value)) != ARRAY_TYPE)
+ {
+ expr = default_function_array_read_conversion (expr_loc, expr);
+ DECL_READ_P (expr.value) = 0;
+ }
+ else
+ expr = default_function_array_read_conversion (expr_loc, expr);
expr.value = build_unary_op (op_loc, POSTDECREMENT_EXPR,
expr.value, false);
set_c_expr_source_range (&expr, start, finish);
@@ -16523,7 +16659,7 @@ c_parser_omp_variable_list (c_parser *parser,
|| CONVERT_EXPR_P (decl))
decl = TREE_OPERAND (decl, 0);
- tree u = build_omp_clause (clause_loc, kind);
+ tree u = build_omp_clause (loc, kind);
OMP_CLAUSE_DECL (u) = decl;
OMP_CLAUSE_CHAIN (u) = list;
list = u;
@@ -19936,14 +20072,14 @@ c_parser_omp_clause_doacross (c_parser *parser, tree list)
map ( [map-type-modifier[,] ...] map-kind: variable-list )
map-type-modifier:
- always | close */
+ always | close | present | iterator (iterators-definition) */
static tree
-c_parser_omp_clause_map (c_parser *parser, tree list)
+c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
{
location_t clause_loc = c_parser_peek_token (parser)->location;
- enum gomp_map_kind kind = GOMP_MAP_TOFROM;
tree nl, c;
+ enum gomp_map_kind kind = declare_mapper_p ? GOMP_MAP_UNSET : GOMP_MAP_TOFROM;
matching_parens parens;
if (!parens.require_open (parser))
@@ -19951,22 +20087,57 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
int pos = 1;
int map_kind_pos = 0;
- while (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_NAME)
+ int iterator_length = 0;
+ for (;;)
{
- if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COLON)
+ c_token *tok = c_parser_peek_nth_token_raw (parser, pos);
+ if (tok->type != CPP_NAME)
+ break;
+
+ const char *p = IDENTIFIER_POINTER (tok->value);
+ c_token *next_tok = c_parser_peek_nth_token_raw (parser, pos + 1);
+ if (strcmp (p, "iterator") == 0 && next_tok->type == CPP_OPEN_PAREN)
+ {
+ unsigned n = pos + 2;
+ if (c_parser_check_balanced_raw_token_sequence (parser, &n)
+ && c_parser_peek_nth_token_raw (parser, n)->type
+ == CPP_CLOSE_PAREN)
+ {
+ iterator_length = n - pos + 1;
+ pos = n;
+ next_tok = c_parser_peek_nth_token_raw (parser, pos + 1);
+ }
+ }
+
+ if (next_tok->type == CPP_COLON)
{
map_kind_pos = pos;
break;
}
- if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA)
+ if (next_tok->type == CPP_COMMA)
pos++;
+ else if (c_parser_peek_nth_token_raw (parser, pos + 1)->type
+ == CPP_OPEN_PAREN)
+ {
+ unsigned int npos = pos + 2;
+ if (c_parser_check_balanced_raw_token_sequence (parser, &npos)
+ && (c_parser_peek_nth_token_raw (parser, npos)->type
+ == CPP_CLOSE_PAREN)
+ && (c_parser_peek_nth_token_raw (parser, npos + 1)->type
+ == CPP_COMMA))
+ pos = npos + 1;
+ }
+
pos++;
}
int always_modifier = 0;
int close_modifier = 0;
int present_modifier = 0;
+ int mapper_modifier = 0;
+ tree mapper_name = NULL_TREE;
+ tree iterators = NULL_TREE;
for (int pos = 1; pos < map_kind_pos; ++pos)
{
c_token *tok = c_parser_peek_token (parser);
@@ -19987,6 +20158,7 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
return list;
}
always_modifier++;
+ c_parser_consume_token (parser);
}
else if (strcmp ("close", p) == 0)
{
@@ -19997,6 +20169,77 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
return list;
}
close_modifier++;
+ c_parser_consume_token (parser);
+ }
+ else if (strcmp ("iterator", p) == 0)
+ {
+ if (iterators)
+ {
+ c_parser_error (parser, "too many %<iterator%> modifiers");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ iterators = c_parser_omp_iterators (parser);
+ pos += iterator_length - 1;
+ }
+ else if (strcmp ("mapper", p) == 0)
+ {
+ c_parser_consume_token (parser);
+
+ matching_parens mparens;
+ if (mparens.require_open (parser))
+ {
+ if (mapper_modifier)
+ {
+ c_parser_error (parser, "too many %<mapper%> modifiers");
+ /* Assume it's a well-formed mapper modifier, even if it
+ seems to be in the wrong place. */
+ c_parser_consume_token (parser);
+ mparens.require_close (parser);
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+
+ tok = c_parser_peek_token (parser);
+
+ switch (tok->type)
+ {
+ case CPP_NAME:
+ {
+ mapper_name = tok->value;
+ c_parser_consume_token (parser);
+ if (declare_mapper_p)
+ {
+ error_at (tok->location,
+ "in %<declare mapper%> directives, parameter "
+ "to %<mapper%> modifier must be %<default%>");
+ }
+ }
+ break;
+
+ case CPP_KEYWORD:
+ if (tok->keyword == RID_DEFAULT)
+ {
+ c_parser_consume_token (parser);
+ break;
+ }
+ /* Fallthrough. */
+
+ default:
+ error_at (tok->location,
+ "expected identifier or %<default%>");
+ return list;
+ }
+
+ if (!mparens.require_close (parser))
+ {
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+
+ mapper_modifier++;
+ pos += 3;
+ }
}
else if (strcmp ("present", p) == 0)
{
@@ -20007,16 +20250,16 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
return list;
}
present_modifier++;
+ c_parser_consume_token (parser);
}
else
{
c_parser_error (parser, "%<map%> clause with map-type modifier other "
- "than %<always%>, %<close%> or %<present%>");
+ "than %<always%>, %<close%>, %<iterator%>, "
+ "%<mapper%> or %<present%>");
parens.skip_until_found_close (parser);
return list;
}
-
- c_parser_consume_token (parser);
}
if (c_parser_next_token_is (parser, CPP_NAME)
@@ -20060,8 +20303,40 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_MAP, list,
true);
+ tree last_new = NULL_TREE;
+
+ if (iterators)
+ {
+ tree block = pop_scope ();
+ if (iterators == error_mark_node)
+ iterators = NULL_TREE;
+ else
+ TREE_VEC_ELT (iterators, 5) = block;
+ }
+
for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_SET_MAP_KIND (c, kind);
+ {
+ OMP_CLAUSE_SET_MAP_KIND (c, kind);
+ OMP_CLAUSE_ITERATORS (c) = iterators;
+ last_new = c;
+ }
+
+ if (mapper_name)
+ {
+ tree name = build_omp_clause (input_location, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (name, GOMP_MAP_PUSH_MAPPER_NAME);
+ OMP_CLAUSE_DECL (name) = mapper_name;
+ OMP_CLAUSE_CHAIN (name) = nl;
+ nl = name;
+
+ gcc_assert (last_new);
+
+ name = build_omp_clause (input_location, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (name, GOMP_MAP_POP_MAPPER_NAME);
+ OMP_CLAUSE_DECL (name) = null_pointer_node;
+ OMP_CLAUSE_CHAIN (name) = OMP_CLAUSE_CHAIN (last_new);
+ OMP_CLAUSE_CHAIN (last_new) = name;
+ }
parens.skip_until_found_close (parser);
return nl;
@@ -20301,8 +20576,11 @@ c_parser_omp_clause_device_type (c_parser *parser, tree list)
to ( variable-list )
OpenMP 5.1:
- from ( [present :] variable-list )
- to ( [present :] variable-list ) */
+ from ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
+ to ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
+
+ motion-modifier:
+ present | iterator (iterators-definition) */
static tree
c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
@@ -20313,18 +20591,85 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
if (!parens.require_open (parser))
return list;
+ int pos = 1, colon_pos = 0;
+ int iterator_length = 0;
+
+ while (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_NAME)
+ {
+ const char *identifier =
+ IDENTIFIER_POINTER (c_parser_peek_nth_token_raw (parser, pos)->value);
+ if (c_parser_peek_nth_token_raw (parser, pos + 1)->type
+ == CPP_OPEN_PAREN)
+ {
+ unsigned int npos = pos + 2;
+ if (c_parser_check_balanced_raw_token_sequence (parser, &npos)
+ && (c_parser_peek_nth_token_raw (parser, npos)->type
+ == CPP_CLOSE_PAREN))
+ {
+ if (strcmp (identifier, "iterator") == 0)
+ iterator_length = npos - pos + 1;
+ pos = npos;
+ }
+ }
+ if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA)
+ pos += 2;
+ else
+ pos++;
+ if (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_COLON)
+ {
+ colon_pos = pos;
+ break;
+ }
+ }
+
bool present = false;
- c_token *token = c_parser_peek_token (parser);
+ tree iterators = NULL_TREE;
- if (token->type == CPP_NAME
- && strcmp (IDENTIFIER_POINTER (token->value), "present") == 0
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ for (int pos = 1; pos < colon_pos; ++pos)
{
- present = true;
- c_parser_consume_token (parser);
- c_parser_consume_token (parser);
+ c_token *token = c_parser_peek_token (parser);
+ if (token->type == CPP_COMMA)
+ {
+ c_parser_consume_token (parser);
+ continue;
+ }
+ const char *p = IDENTIFIER_POINTER (token->value);
+ if (strcmp ("present", p) == 0)
+ {
+ if (present)
+ {
+ c_parser_error (parser, "too many %<present%> modifiers");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ present = true;
+ c_parser_consume_token (parser);
+ }
+ else if (strcmp ("iterator", p) == 0)
+ {
+ if (iterators)
+ {
+ c_parser_error (parser, "too many %<iterator%> modifiers");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ iterators = c_parser_omp_iterators (parser);
+ pos += iterator_length - 1;
+ }
+ else
+ {
+ error_at (token->location,
+ "%qs clause with modifier other than %<iterator%> or "
+ "%<present%>",
+ kind == OMP_CLAUSE_TO ? "to" : "from");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
}
+ if (colon_pos)
+ c_parser_require (parser, CPP_COLON, "expected %<:%>");
+
tree nl = c_parser_omp_variable_list (parser, loc, kind, list);
parens.skip_until_found_close (parser);
@@ -20332,6 +20677,19 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
OMP_CLAUSE_MOTION_PRESENT (c) = 1;
+ if (iterators)
+ {
+ tree block = pop_scope ();
+ if (iterators == error_mark_node)
+ iterators = NULL_TREE;
+ else
+ TREE_VEC_ELT (iterators, 5) = block;
+ }
+
+ if (iterators)
+ for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_ITERATORS (c) = iterators;
+
return nl;
}
@@ -21430,7 +21788,7 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
c_name = "interop";
break;
case PRAGMA_OMP_CLAUSE_MAP:
- clauses = c_parser_omp_clause_map (parser, clauses);
+ clauses = c_parser_omp_clause_map (parser, clauses, false);
c_name = "map";
break;
case PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR:
@@ -22304,7 +22662,8 @@ c_parser_oacc_update (c_parser *parser)
*/
#define OACC_WAIT_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) )
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) )
static tree
c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name)
@@ -26249,7 +26608,7 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
{
location_t loc = c_parser_peek_token (parser)->location;
c_parser_consume_pragma (parser);
- tree *pc = NULL, stmt, block;
+ tree *pc = NULL, stmt, block, body, clauses;
if (context != pragma_stmt && context != pragma_compound)
{
@@ -26404,10 +26763,9 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
stmt = make_node (OMP_TARGET);
TREE_TYPE (stmt) = void_type_node;
- OMP_TARGET_CLAUSES (stmt)
- = c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
- "#pragma omp target", false);
- for (tree c = OMP_TARGET_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
+ clauses = c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
+ "#pragma omp target", false);
+ for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
{
tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
@@ -26416,14 +26774,19 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
OMP_CLAUSE_CHAIN (c) = nc;
}
- OMP_TARGET_CLAUSES (stmt)
- = c_finish_omp_clauses (OMP_TARGET_CLAUSES (stmt), C_ORT_OMP_TARGET);
- c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
+ clauses = c_omp_instantiate_mappers (clauses);
+ clauses = c_finish_omp_clauses (clauses, C_ORT_OMP_TARGET);
+ c_omp_adjust_map_clauses (clauses, true);
- pc = &OMP_TARGET_CLAUSES (stmt);
keep_next_level ();
block = c_begin_compound_stmt (true);
- add_stmt (c_parser_omp_structured_block (parser, if_p));
+ body = c_parser_omp_structured_block (parser, if_p);
+
+ c_omp_scan_mapper_bindings (loc, &clauses, body);
+
+ add_stmt (body);
+ OMP_TARGET_CLAUSES (stmt) = clauses;
+ pc = &OMP_TARGET_CLAUSES (stmt);
OMP_TARGET_BODY (stmt) = c_end_compound_stmt (loc, block, true);
SET_EXPR_LOCATION (stmt, loc);
@@ -26771,20 +27134,31 @@ c_parser_omp_context_selector (c_parser *parser, enum omp_tss_code set,
break;
case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
case OMP_TRAIT_PROPERTY_BOOL_EXPR:
- t = c_parser_expr_no_commas (parser, NULL).value;
- if (t != error_mark_node)
+ {
+ c_expr texpr = c_parser_expr_no_commas (parser, NULL);
+ texpr = convert_lvalue_to_rvalue (token->location, texpr,
+ true, true);
+ t = texpr.value;
+ }
+ if (t == error_mark_node)
+ return error_mark_node;
+ mark_exp_read (t);
+ if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
{
- mark_exp_read (t);
- t = c_fully_fold (t, false, NULL);
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
- error_at (token->location,
- "property must be integer expression");
- else
- properties = make_trait_property (NULL_TREE, t,
- properties);
+ t = c_objc_common_truthvalue_conversion (token->location,
+ t,
+ boolean_type_node);
+ if (t == error_mark_node)
+ return error_mark_node;
}
- else
- return error_mark_node;
+ else if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error_at (token->location,
+ "property must be integer expression");
+ return error_mark_node;
+ }
+ t = c_fully_fold (t, false, NULL);
+ properties = make_trait_property (NULL_TREE, t, properties);
break;
case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
if (sel == OMP_TRAIT_CONSTRUCT_SIMD)
@@ -26886,11 +27260,14 @@ c_parser_omp_context_selector_specification (c_parser *parser, tree parms)
tree selectors = c_parser_omp_context_selector (parser, set, parms);
if (selectors == error_mark_node)
- ret = error_mark_node;
+ {
+ c_parser_skip_to_closing_brace (parser);
+ ret = error_mark_node;
+ }
else if (ret != error_mark_node)
ret = make_trait_set_selector (set, selectors, ret);
- braces.skip_until_found_close (parser);
+ braces.require_close (parser);
if (c_parser_next_token_is (parser, CPP_COMMA))
c_parser_consume_token (parser);
@@ -27795,6 +28172,151 @@ c_parser_omp_end (c_parser *parser)
}
}
+/* OpenMP 5.0
+ #pragma omp declare mapper ([mapper-identifier :] type var) \
+ [clause [ [,] clause ] ... ] new-line */
+
+static void
+c_parser_omp_declare_mapper (c_parser *parser, enum pragma_context context)
+{
+ tree type, mapper_name = NULL_TREE, var = NULL_TREE, stmt, stmtlist;
+ tree maplist = NULL_TREE, mapper_id, mapper_decl, t;
+ c_token *token;
+
+ if (context == pragma_struct || context == pragma_param)
+ {
+ error ("%<#pragma omp declare mapper%> not at file or block scope");
+ goto fail;
+ }
+
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ goto fail;
+
+ token = c_parser_peek_token (parser);
+
+ if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ {
+ switch (token->type)
+ {
+ case CPP_NAME:
+ mapper_name = token->value;
+ c_parser_consume_token (parser);
+ break;
+ case CPP_KEYWORD:
+ if (token->keyword == RID_DEFAULT)
+ {
+ mapper_name = NULL_TREE;
+ c_parser_consume_token (parser);
+ break;
+ }
+ /* Fallthrough. */
+ default:
+ error_at (token->location, "expected identifier or %<default%>");
+ c_parser_skip_to_pragma_eol (parser, false);
+ return;
+ }
+
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ goto fail;
+ }
+
+ mapper_id = c_omp_mapper_id (mapper_name);
+ mapper_decl = c_omp_mapper_decl (mapper_id);
+
+ {
+ location_t loc = c_parser_peek_token (parser)->location;
+ struct c_type_name *ctype = c_parser_type_name (parser);
+ type = groktypename (ctype, NULL, NULL);
+ if (type == error_mark_node)
+ goto fail;
+ if (!RECORD_OR_UNION_TYPE_P (type))
+ {
+ error_at (loc, "%qT is not a struct or union type in "
+ "%<#pragma omp declare mapper%>", type);
+ c_parser_skip_to_pragma_eol (parser, false);
+ return;
+ }
+ for (tree t = DECL_INITIAL (mapper_decl); t; t = TREE_CHAIN (t))
+ if (comptypes (TREE_PURPOSE (t), type))
+ {
+ error_at (loc, "redeclaration of %qs %<#pragma omp declare "
+ "mapper%> for type %qT", IDENTIFIER_POINTER (mapper_id)
+ + sizeof ("omp declare mapper ") - 1,
+ type);
+ tree prevmapper = TREE_VALUE (t);
+ /* Hmm, this location might not be very accurate. */
+ location_t ploc
+ = DECL_SOURCE_LOCATION (OMP_DECLARE_MAPPER_DECL (prevmapper));
+ inform (ploc, "%<#pragma omp declare mapper%> "
+ "previously declared here");
+ c_parser_skip_to_pragma_eol (parser, false);
+ return;
+ }
+ }
+
+ token = c_parser_peek_token (parser);
+ if (token->type == CPP_NAME)
+ {
+ var = build_decl (token->location, VAR_DECL, token->value, type);
+ c_parser_consume_token (parser);
+ DECL_ARTIFICIAL (var) = 1;
+ }
+ else
+ {
+ error_at (token->location, "expected identifier");
+ goto fail;
+ }
+
+ if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ goto fail;
+
+ push_scope ();
+ stmtlist = push_stmt_list ();
+ pushdecl (var);
+ DECL_CONTEXT (var) = current_function_decl;
+
+ while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+ {
+ location_t here;
+ pragma_omp_clause c_kind;
+ here = c_parser_peek_token (parser)->location;
+ c_kind = c_parser_omp_clause_name (parser);
+ if (c_kind != PRAGMA_OMP_CLAUSE_MAP)
+ {
+ error_at (here, "unexpected clause");
+ goto fail;
+ }
+ maplist = c_parser_omp_clause_map (parser, maplist, true);
+ }
+
+ if (maplist == NULL_TREE)
+ {
+ error_at (input_location, "missing %<map%> clause");
+ goto fail;
+ }
+
+ stmt = make_node (OMP_DECLARE_MAPPER);
+ TREE_TYPE (stmt) = type;
+ OMP_DECLARE_MAPPER_ID (stmt) = mapper_name;
+ OMP_DECLARE_MAPPER_DECL (stmt) = var;
+ OMP_DECLARE_MAPPER_CLAUSES (stmt) = maplist;
+
+ add_stmt (stmt);
+
+ pop_stmt_list (stmtlist);
+ pop_scope ();
+
+ c_parser_skip_to_pragma_eol (parser);
+
+ t = tree_cons (type, stmt, DECL_INITIAL (mapper_decl));
+ DECL_INITIAL (mapper_decl) = t;
+
+ return;
+
+ fail:
+ c_parser_skip_to_pragma_eol (parser);
+}
+
/* OpenMP 4.0
#pragma omp declare reduction (reduction-id : typename-list : expression) \
initializer-clause[opt] new-line
@@ -27921,8 +28443,8 @@ c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
location_t ploc
= DECL_SOURCE_LOCATION (TREE_VEC_ELT (TREE_VALUE (t),
0));
- error_at (ploc, "previous %<#pragma omp declare "
- "reduction%>");
+ inform (ploc, "%<#pragma omp declare reduction%> "
+ "previously declared here");
break;
}
if (t == NULL_TREE)
@@ -28186,6 +28708,12 @@ c_parser_omp_declare (c_parser *parser, enum pragma_context context)
c_parser_omp_declare_reduction (parser, context);
return false;
}
+ if (strcmp (p, "mapper") == 0)
+ {
+ c_parser_consume_token (parser);
+ c_parser_omp_declare_mapper (parser, context);
+ return false;
+ }
if (!flag_openmp) /* flag_openmp_simd */
{
c_parser_skip_to_pragma_eol (parser, false);
@@ -28759,11 +29287,14 @@ c_parser_omp_error (c_parser *parser, enum pragma_context context)
if (msg == NULL)
msg = _("<message unknown at compile time>");
}
+ const enum diagnostics::kind diag_kind = (severity_fatal
+ ? diagnostics::kind::error
+ : diagnostics::kind::warning);
if (msg)
- emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0,
+ emit_diagnostic (diag_kind, loc, 0,
"%<pragma omp error%> encountered: %s", msg);
else
- emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0,
+ emit_diagnostic (diag_kind, loc, 0,
"%<pragma omp error%> encountered");
return false;
}
@@ -29095,7 +29626,6 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p)
{
error_at (match_loc, "too many %<otherwise%> or %<default%> "
"clauses in %<metadirective%>");
- c_parser_skip_to_end_of_block_or_statement (parser, true);
goto error;
}
default_seen = true;
@@ -29104,14 +29634,12 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p)
{
error_at (match_loc, "%<otherwise%> or %<default%> clause "
"must appear last in %<metadirective%>");
- c_parser_skip_to_end_of_block_or_statement (parser, true);
goto error;
}
if (!default_p && strcmp (p, "when") != 0)
{
error_at (match_loc, "%qs is not valid for %qs",
p, "metadirective");
- c_parser_skip_to_end_of_block_or_statement (parser, true);
goto error;
}
@@ -29179,7 +29707,6 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p)
if (i == 0)
{
error_at (loc, "expected directive name");
- c_parser_skip_to_end_of_block_or_statement (parser, true);
goto error;
}
@@ -29247,7 +29774,10 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p)
goto add;
case CPP_CLOSE_PAREN:
if (nesting_depth-- == 0)
- break;
+ {
+ c_parser_consume_token (parser);
+ break;
+ }
goto add;
default:
add:
@@ -29259,8 +29789,6 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p)
break;
}
- c_parser_consume_token (parser);
-
if (!skip)
{
c_token eol_token;
@@ -29387,9 +29915,9 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p)
return;
error:
+ /* Skip the metadirective pragma. Do not skip the metadirective body. */
if (parser->in_pragma)
- c_parser_skip_to_pragma_eol (parser);
- c_parser_skip_to_end_of_block_or_statement (parser, true);
+ c_parser_skip_to_pragma_eol (parser, false);
}
/* Main entry point to parsing most OpenMP pragmas. */
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 2098120..dba94ab 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -163,7 +163,8 @@ along with GCC; see the file COPYING3. If not see
(TREE_CODE (TYPE) == BOOLEAN_TYPE \
|| (TREE_CODE (TYPE) == ENUMERAL_TYPE \
&& ENUM_UNDERLYING_TYPE (TYPE) != NULL_TREE \
- && TREE_CODE (ENUM_UNDERLYING_TYPE (TYPE)) == BOOLEAN_TYPE))
+ && (TREE_CODE (ENUM_UNDERLYING_TYPE (TYPE)) == BOOLEAN_TYPE \
+ || c_hardbool_type_attr (TYPE))))
/* Record parser information about an expression that is irrelevant
for code generation alongside a tree representing its value. */
@@ -757,7 +758,7 @@ extern tree c_finish_bc_name (location_t, tree, bool);
extern bool c_objc_common_init (void);
extern bool c_missing_noreturn_ok_p (tree);
extern bool c_warn_unused_global_decl (const_tree);
-extern void c_initialize_diagnostics (diagnostic_context *);
+extern void c_initialize_diagnostics (diagnostics::context *);
extern bool c_var_mod_p (tree x, tree fn);
extern alias_set_type c_get_alias_set (tree);
extern int c_type_dwarf_attribute (const_tree, int);
@@ -765,6 +766,7 @@ extern int c_type_dwarf_attribute (const_tree, int);
/* in c-typeck.cc */
extern int in_alignof;
extern int in_sizeof;
+extern int in_countof;
extern int in_typeof;
extern bool c_in_omp_for;
extern bool c_omp_array_section_p;
@@ -827,6 +829,9 @@ extern tree build_external_ref (location_t, tree, bool, tree *);
extern void pop_maybe_used (bool);
extern struct c_expr c_expr_sizeof_expr (location_t, struct c_expr);
extern struct c_expr c_expr_sizeof_type (location_t, struct c_type_name *);
+extern struct c_expr c_expr_countof_expr (location_t, struct c_expr);
+extern struct c_expr c_expr_countof_type (location_t loc,
+ struct c_type_name *);
extern struct c_expr parser_build_unary_op (location_t, enum tree_code,
struct c_expr);
extern struct c_expr parser_build_binary_op (location_t,
@@ -884,6 +889,10 @@ extern tree c_finish_omp_task (location_t, tree, tree);
extern void c_finish_omp_cancel (location_t, tree);
extern void c_finish_omp_cancellation_point (location_t, tree);
extern tree c_finish_omp_clauses (tree, enum c_omp_region_type);
+extern tree c_omp_finish_mapper_clauses (tree);
+extern tree c_omp_mapper_lookup (tree, tree);
+extern tree c_omp_extract_mapper_directive (tree);
+extern tree c_omp_map_array_section (location_t, tree);
extern tree c_build_va_arg (location_t, tree, location_t, tree);
extern tree c_finish_transaction (location_t, tree, int);
extern bool c_tree_equal (tree, tree);
@@ -942,19 +951,23 @@ extern tree c_omp_reduction_id (enum tree_code, tree);
extern tree c_omp_reduction_decl (tree);
extern tree c_omp_reduction_lookup (tree, tree);
extern tree c_check_omp_declare_reduction_r (tree *, int *, void *);
+extern tree c_omp_mapper_id (tree);
+extern tree c_omp_mapper_decl (tree);
+extern void c_omp_scan_mapper_bindings (location_t, tree *, tree);
+extern tree c_omp_instantiate_mappers (tree);
extern bool c_check_in_current_scope (tree);
extern void c_pushtag (location_t, tree, tree);
extern void c_bind (location_t, tree, bool);
extern bool tag_exists_p (enum tree_code, tree);
/* In c-errors.cc */
-extern bool pedwarn_c90 (location_t, diagnostic_option_id, const char *, ...)
+extern bool pedwarn_c90 (location_t, diagnostics::option_id, const char *, ...)
ATTRIBUTE_GCC_DIAG(3,4);
-extern bool pedwarn_c99 (location_t, diagnostic_option_id, const char *, ...)
+extern bool pedwarn_c99 (location_t, diagnostics::option_id, const char *, ...)
ATTRIBUTE_GCC_DIAG(3,4);
-extern bool pedwarn_c11 (location_t, diagnostic_option_id, const char *, ...)
+extern bool pedwarn_c11 (location_t, diagnostics::option_id, const char *, ...)
ATTRIBUTE_GCC_DIAG(3,4);
-extern bool pedwarn_c23 (location_t, diagnostic_option_id, const char *, ...)
+extern bool pedwarn_c23 (location_t, diagnostics::option_id, const char *, ...)
ATTRIBUTE_GCC_DIAG(3,4);
extern void add_note_about_new_keyword (location_t loc,
tree keyword_id);
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 55d896e..7a95f72 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -72,6 +72,9 @@ int in_alignof;
/* The level of nesting inside "sizeof". */
int in_sizeof;
+/* The level of nesting inside "countof". */
+int in_countof;
+
/* The level of nesting inside "typeof". */
int in_typeof;
@@ -133,6 +136,7 @@ static int lvalue_or_else (location_t, const_tree, enum lvalue_use);
static void record_maybe_used_decl (tree);
static bool comptypes_internal (const_tree, const_tree,
struct comptypes_data *data);
+static bool comptypes_check_for_composite (tree t1, tree t2);
/* Return true if EXP is a null pointer constant, false otherwise. */
@@ -610,6 +614,17 @@ c_type_tag (const_tree t)
return name;
}
+/* Remove qualifiers but not atomic. For arrays remove qualifiers
+ on the element type but also do not remove atomic. */
+static tree
+remove_qualifiers (tree t)
+{
+ if (!t || t == error_mark_node)
+ return t;
+ return TYPE_ATOMIC (strip_array_types (t))
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (t), TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (t);
+}
/* Return the composite type of two compatible types.
@@ -626,7 +641,8 @@ struct composite_cache {
};
tree
-composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
+composite_type_internal (tree t1, tree t2, tree cond,
+ struct composite_cache* cache)
{
enum tree_code code1;
enum tree_code code2;
@@ -671,8 +687,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
{
tree pointed_to_1 = TREE_TYPE (t1);
tree pointed_to_2 = TREE_TYPE (t2);
- tree target = composite_type_internal (pointed_to_1,
- pointed_to_2, cache);
+ tree target = composite_type_internal (pointed_to_1, pointed_to_2,
+ cond, cache);
t1 = c_build_pointer_type_for_mode (target, TYPE_MODE (t1), false);
t1 = c_build_type_attribute_variant (t1, attributes);
return qualify_type (t1, t2);
@@ -680,25 +696,20 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
case ARRAY_TYPE:
{
- tree elt = composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2),
- cache);
- int quals;
- tree unqual_elt;
tree d1 = TYPE_DOMAIN (t1);
tree d2 = TYPE_DOMAIN (t2);
- bool d1_variable, d2_variable;
- bool d1_zero, d2_zero;
- bool t1_complete, t2_complete;
/* We should not have any type quals on arrays at all. */
gcc_assert (!TYPE_QUALS_NO_ADDR_SPACE (t1)
&& !TYPE_QUALS_NO_ADDR_SPACE (t2));
- t1_complete = COMPLETE_TYPE_P (t1);
- t2_complete = COMPLETE_TYPE_P (t2);
+ bool t1_complete = COMPLETE_TYPE_P (t1);
+ bool t2_complete = COMPLETE_TYPE_P (t2);
+
+ bool d1_zero = d1 == NULL_TREE || !TYPE_MAX_VALUE (d1);
+ bool d2_zero = d2 == NULL_TREE || !TYPE_MAX_VALUE (d2);
- d1_zero = d1 == NULL_TREE || !TYPE_MAX_VALUE (d1);
- d2_zero = d2 == NULL_TREE || !TYPE_MAX_VALUE (d2);
+ bool d1_variable, d2_variable;
d1_variable = (!d1_zero
&& (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
@@ -707,10 +718,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
&& (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
|| TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
- bool use1 = TYPE_DOMAIN (t1)
- && (d2_variable || d2_zero || !d1_variable);
- bool use2 = TYPE_DOMAIN (t2)
- && (d1_variable || d1_zero || !d2_variable);
+ bool use1 = d1 && (d2_variable || d2_zero || !d1_variable);
+ bool use2 = d2 && (d1_variable || d1_zero || !d2_variable);
/* If the first is an unspecified size pick the other one. */
if (d2_variable && c_type_unspecified_p (t1))
@@ -719,25 +728,53 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
use1 = false;
}
- /* Save space: see if the result is identical to one of the args. */
- if (elt == TREE_TYPE (t1) && use1)
- return c_build_type_attribute_variant (t1, attributes);
- if (elt == TREE_TYPE (t2) && use2)
- return c_build_type_attribute_variant (t2, attributes);
+ /* If both are VLAs but not unspecified and we are in the
+ conditional operator, we create a conditional to select
+ the size of the active branch. */
+ bool use0 = cond && d1_variable && !c_type_unspecified_p (t1)
+ && d2_variable && !c_type_unspecified_p (t2);
- if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
- return c_build_type_attribute_variant (t1, attributes);
- if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
- return c_build_type_attribute_variant (t2, attributes);
+ tree td;
+ tree elt = composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2),
+ cond, cache);
+
+ if (!use0)
+ {
+ /* Save space: see if the result is identical to one of the args. */
+ if (elt == TREE_TYPE (t1) && use1)
+ return c_build_type_attribute_variant (t1, attributes);
+ if (elt == TREE_TYPE (t2) && use2)
+ return c_build_type_attribute_variant (t2, attributes);
+
+ if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
+ return c_build_type_attribute_variant (t1, attributes);
+ if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
+ return c_build_type_attribute_variant (t2, attributes);
+
+ td = TYPE_DOMAIN (use1 ? t1 : t2);
+ }
+ else
+ {
+ /* Not used in C. */
+ gcc_assert (size_zero_node == TYPE_MIN_VALUE (d1));
+ gcc_assert (size_zero_node == TYPE_MIN_VALUE (d2));
+
+ tree d = fold_build3_loc (UNKNOWN_LOCATION, COND_EXPR, sizetype,
+ cond, TYPE_MAX_VALUE (d1),
+ TYPE_MAX_VALUE (d2));
+
+ td = build_index_type (d);
+ }
/* Merge the element types, and have a size if either arg has
one. We may have qualifiers on the element types. To set
up TYPE_MAIN_VARIANT correctly, we need to form the
composite of the unqualified types and add the qualifiers
back at the end. */
- quals = TYPE_QUALS (strip_array_types (elt));
- unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
- t1 = c_build_array_type (unqual_elt, TYPE_DOMAIN (use1 ? t1 : t2));
+ int quals = TYPE_QUALS (strip_array_types (elt));
+ tree unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
+
+ t1 = c_build_array_type (unqual_elt, td);
/* Check that a type which has a varying outermost dimension
got marked has having a variable size. */
@@ -773,7 +810,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
construction, return it. */
for (struct composite_cache *c = cache; c != NULL; c = c->next)
- if (c->t1 == t1 && c->t2 == t2)
+ if ((c->t1 == t1 && c->t2 == t2) || (c->t1 == t2 && c->t2 == t1))
return c->composite;
/* Otherwise, create a new type node and link it into the cache. */
@@ -804,7 +841,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
gcc_assert (DECL_NAME (a) == DECL_NAME (b));
gcc_checking_assert (!DECL_NAME (a) || comptypes (ta, tb));
- tree t = composite_type_internal (ta, tb, cache);
+ tree t = composite_type_internal (ta, tb, cond, cache);
tree f = build_decl (input_location, FIELD_DECL, DECL_NAME (a), t);
DECL_PACKED (f) = DECL_PACKED (a);
@@ -843,12 +880,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
n = finish_struct (input_location, n, fields, attributes, NULL,
&expr);
- n = qualify_type (n, t1);
-
- gcc_checking_assert (!TYPE_NAME (n) || comptypes (n, t1));
- gcc_checking_assert (!TYPE_NAME (n) || comptypes (n, t2));
-
- return n;
+ return qualify_type (n, t1);
}
/* FALLTHRU */
case ENUMERAL_TYPE:
@@ -866,8 +898,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
/* Function types: prefer the one that specified arg types.
If both do, merge the arg types. Also merge the return types. */
{
- tree valtype = composite_type_internal (TREE_TYPE (t1),
- TREE_TYPE (t2), cache);
+ tree valtype = composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2),
+ cond, cache);
tree p1 = TYPE_ARG_TYPES (t1);
tree p2 = TYPE_ARG_TYPES (t2);
int len;
@@ -912,15 +944,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
for (; p1 && p1 != void_list_node;
p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2), n = TREE_CHAIN (n))
{
- tree mv1 = TREE_VALUE (p1);
- if (mv1 && mv1 != error_mark_node
- && TREE_CODE (mv1) != ARRAY_TYPE)
- mv1 = TYPE_MAIN_VARIANT (mv1);
-
- tree mv2 = TREE_VALUE (p2);
- if (mv2 && mv2 != error_mark_node
- && TREE_CODE (mv2) != ARRAY_TYPE)
- mv2 = TYPE_MAIN_VARIANT (mv2);
+ tree mv1 = remove_qualifiers (TREE_VALUE (p1));
+ tree mv2 = remove_qualifiers (TREE_VALUE (p2));
/* A null type means arg type is not specified.
Take whatever the other function type has. */
@@ -953,7 +978,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
{
TREE_VALUE (n) = composite_type_internal (TREE_TYPE (memb),
TREE_VALUE (p2),
- cache);
+ cond, cache);
pedwarn (input_location, OPT_Wpedantic,
"function types not truly compatible in ISO C");
goto parm_done;
@@ -976,14 +1001,14 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
TREE_VALUE (n)
= composite_type_internal (TREE_TYPE (memb),
TREE_VALUE (p1),
- cache);
+ cond, cache);
pedwarn (input_location, OPT_Wpedantic,
"function types not truly compatible in ISO C");
goto parm_done;
}
}
}
- TREE_VALUE (n) = composite_type_internal (mv1, mv2, cache);
+ TREE_VALUE (n) = composite_type_internal (mv1, mv2, cond, cache);
parm_done: ;
}
@@ -998,10 +1023,23 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
}
tree
-composite_type (tree t1, tree t2)
+composite_type_cond (tree t1, tree t2, tree cond)
{
+ gcc_checking_assert (comptypes_check_for_composite (t1, t2));
+
struct composite_cache cache = { };
- return composite_type_internal (t1, t2, &cache);
+ tree n = composite_type_internal (t1, t2, cond, &cache);
+
+ gcc_checking_assert (comptypes_check_for_composite (n, t1));
+ gcc_checking_assert (comptypes_check_for_composite (n, t2));
+ return n;
+}
+
+
+tree
+composite_type (tree t1, tree t2)
+{
+ return composite_type_cond (t1, t2, NULL_TREE);
}
/* Return the type of a conditional expression between pointers to
@@ -1011,12 +1049,9 @@ composite_type (tree t1, tree t2)
true; if that isn't so, this may crash. */
static tree
-common_pointer_type (tree t1, tree t2)
+common_pointer_type (tree t1, tree t2, tree cond)
{
tree attributes;
- tree pointed_to_1, mv1;
- tree pointed_to_2, mv2;
- tree target;
unsigned target_quals;
addr_space_t as1, as2, as_common;
int quals1, quals2;
@@ -1038,15 +1073,11 @@ common_pointer_type (tree t1, tree t2)
attributes = targetm.merge_type_attributes (t1, t2);
/* Find the composite type of the target types, and combine the
- qualifiers of the two types' targets. Do not lose qualifiers on
- array element types by taking the TYPE_MAIN_VARIANT. */
- mv1 = pointed_to_1 = TREE_TYPE (t1);
- mv2 = pointed_to_2 = TREE_TYPE (t2);
- if (TREE_CODE (mv1) != ARRAY_TYPE)
- mv1 = TYPE_MAIN_VARIANT (pointed_to_1);
- if (TREE_CODE (mv2) != ARRAY_TYPE)
- mv2 = TYPE_MAIN_VARIANT (pointed_to_2);
- target = composite_type (mv1, mv2);
+ qualifiers of the two types' targets. */
+ tree pointed_to_1 = TREE_TYPE (t1);
+ tree pointed_to_2 = TREE_TYPE (t2);
+ tree target = composite_type_cond (TYPE_MAIN_VARIANT (pointed_to_1),
+ TYPE_MAIN_VARIANT (pointed_to_2), cond);
/* Strip array types to get correct qualifier for pointers to arrays */
quals1 = TYPE_QUALS_NO_ADDR_SPACE (strip_array_types (pointed_to_1));
@@ -1451,16 +1482,39 @@ comptypes_verify (tree type1, tree type2)
}
struct comptypes_data {
+
+ /* output */
bool enum_and_int_p;
bool different_types_p;
bool warning_needed;
+
+ /* context */
bool anon_field;
bool pointedto;
+
+ /* configuration */
bool equiv;
+ bool ignore_promoting_args;
const struct tagged_tu_seen_cache* cache;
};
+
+/* Helper function for composite_type. This function ignores when the
+ function type of an old-style declaration is incompatible with a type
+ of a declaration with prototype because some are arguments are not
+ self-promoting. This is ignored only for function types but not
+ ignored in a nested context. */
+
+static bool
+comptypes_check_for_composite (tree t1, tree t2)
+{
+ struct comptypes_data data = { };
+ data.ignore_promoting_args = FUNCTION_TYPE == TREE_CODE (t1);
+ return comptypes_internal (t1, t2, &data);
+}
+
+
/* C implementation of compatible_types_for_indirection_note_p. */
bool
@@ -1590,6 +1644,10 @@ comptypes_equiv_p (tree type1, tree type2)
permitted in C11 typedef redeclarations, then this sets
'different_types_p' in DATA to true; it is never set to
false, but may or may not be set if the types are incompatible.
+ If two functions types are not compatible only because one is
+ an old-style definition that does not have self-promoting arguments,
+ then this can be ignored by setting 'ignore_promoting_args_p'.
+ For 'equiv' we can compute equivalency classes (see above).
This differs from comptypes, in that we don't free the seen
types. */
@@ -1788,15 +1846,9 @@ comp_target_types (location_t location, tree ttl, tree ttr)
val_ped = comptypes (mvl, mvr);
/* Qualifiers on element types of array types that are
- pointer targets are lost by taking their TYPE_MAIN_VARIANT. */
-
- mvl = (TYPE_ATOMIC (strip_array_types (mvl))
- ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvl), TYPE_QUAL_ATOMIC)
- : TYPE_MAIN_VARIANT (mvl));
-
- mvr = (TYPE_ATOMIC (strip_array_types (mvr))
- ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvr), TYPE_QUAL_ATOMIC)
- : TYPE_MAIN_VARIANT (mvr));
+ pointer targets are also removed. */
+ mvl = remove_qualifiers (mvl);
+ mvr = remove_qualifiers (mvr);
enum_and_int_p = false;
val = comptypes_check_enum_int (mvl, mvr, &enum_and_int_p);
@@ -1947,6 +1999,9 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
ft2 = DECL_BIT_FIELD_TYPE (s2);
}
+ if (!ft1 || !ft2)
+ return false;
+
if (TREE_CODE (ft1) == ERROR_MARK || TREE_CODE (ft2) == ERROR_MARK)
return false;
@@ -2019,14 +2074,8 @@ static bool
function_types_compatible_p (const_tree f1, const_tree f2,
struct comptypes_data *data)
{
- tree args1, args2;
- /* 1 if no need for warning yet, 2 if warning cause has been seen. */
- int val = 1;
- int val1;
- tree ret1, ret2;
-
- ret1 = TREE_TYPE (f1);
- ret2 = TREE_TYPE (f2);
+ tree ret1 = TREE_TYPE (f1);
+ tree ret2 = TREE_TYPE (f2);
/* 'volatile' qualifiers on a function's return type used to mean
the function is noreturn. */
@@ -2038,12 +2087,17 @@ function_types_compatible_p (const_tree f1, const_tree f2,
if (TYPE_VOLATILE (ret2))
ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
- val = comptypes_internal (ret1, ret2, data);
- if (val == 0)
- return 0;
- args1 = TYPE_ARG_TYPES (f1);
- args2 = TYPE_ARG_TYPES (f2);
+ bool ignore_pargs = data->ignore_promoting_args;
+ data->ignore_promoting_args = false;
+
+ if (!comptypes_internal (ret1, ret2, data))
+ return false;
+
+ data->ignore_promoting_args = ignore_pargs;
+
+ tree args1 = TYPE_ARG_TYPES (f1);
+ tree args2 = TYPE_ARG_TYPES (f2);
if ((args1 == NULL_TREE) != (args2 == NULL_TREE))
data->different_types_p = true;
@@ -2054,40 +2108,33 @@ function_types_compatible_p (const_tree f1, const_tree f2,
if (args1 == NULL_TREE)
{
if (TYPE_NO_NAMED_ARGS_STDARG_P (f1) != TYPE_NO_NAMED_ARGS_STDARG_P (f2))
- return 0;
- if (!self_promoting_args_p (args2))
- return 0;
+ return false;
+ if (!(data->ignore_promoting_args || self_promoting_args_p (args2)))
+ return false;
+ data->ignore_promoting_args = false;
/* If one of these types comes from a non-prototype fn definition,
compare that with the other type's arglist.
If they don't match, ask for a warning (but no error). */
if (TYPE_ACTUAL_ARG_TYPES (f1)
- && type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1),
- data) != 1)
- {
- val = 1;
- data->warning_needed = true;
- }
- return val;
+ && !type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1), data))
+ data->warning_needed = true;
+ return true;
}
if (args2 == NULL_TREE)
{
if (TYPE_NO_NAMED_ARGS_STDARG_P (f1) != TYPE_NO_NAMED_ARGS_STDARG_P (f2))
- return 0;
- if (!self_promoting_args_p (args1))
- return 0;
+ return false;
+ if (!(data->ignore_promoting_args || self_promoting_args_p (args1)))
+ return false;
+ data->ignore_promoting_args = false;
if (TYPE_ACTUAL_ARG_TYPES (f2)
- && type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2),
- data) != 1)
- {
- val = 1;
- data->warning_needed = true;
- }
- return val;
+ && !type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2), data))
+ data->warning_needed = true;
+ return true;
}
/* Both types have argument lists: compare them and propagate results. */
- val1 = type_lists_compatible_p (args1, args2, data);
- return val1;
+ return type_lists_compatible_p (args1, args2, data);
}
/* Check two lists of types for compatibility, returning false for
@@ -2099,25 +2146,16 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
{
while (1)
{
- tree a1, mv1, a2, mv2;
if (args1 == NULL_TREE && args2 == NULL_TREE)
return true;
/* If one list is shorter than the other,
they fail to match. */
if (args1 == NULL_TREE || args2 == NULL_TREE)
- return 0;
- mv1 = a1 = TREE_VALUE (args1);
- mv2 = a2 = TREE_VALUE (args2);
- if (mv1 && mv1 != error_mark_node && TREE_CODE (mv1) != ARRAY_TYPE)
- mv1 = (TYPE_ATOMIC (mv1)
- ? c_build_qualified_type (TYPE_MAIN_VARIANT (mv1),
- TYPE_QUAL_ATOMIC)
- : TYPE_MAIN_VARIANT (mv1));
- if (mv2 && mv2 != error_mark_node && TREE_CODE (mv2) != ARRAY_TYPE)
- mv2 = (TYPE_ATOMIC (mv2)
- ? c_build_qualified_type (TYPE_MAIN_VARIANT (mv2),
- TYPE_QUAL_ATOMIC)
- : TYPE_MAIN_VARIANT (mv2));
+ return false;
+ tree a1 = TREE_VALUE (args1);
+ tree a2 = TREE_VALUE (args2);
+ tree mv1 = remove_qualifiers (a1);
+ tree mv2 = remove_qualifiers (a2);
/* A null pointer instead of a type
means there is supposed to be an argument
but nothing is specified about what type it has.
@@ -2127,12 +2165,12 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
if (a1 == NULL_TREE)
{
if (c_type_promotes_to (a2) != a2)
- return 0;
+ return false;
}
else if (a2 == NULL_TREE)
{
if (c_type_promotes_to (a1) != a1)
- return 0;
+ return false;
}
/* If one of the lists has an error marker, ignore this arg. */
else if (TREE_CODE (a1) == ERROR_MARK
@@ -2154,18 +2192,12 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
for (memb = TYPE_FIELDS (a1);
memb; memb = DECL_CHAIN (memb))
{
- tree mv3 = TREE_TYPE (memb);
- if (mv3 && mv3 != error_mark_node
- && TREE_CODE (mv3) != ARRAY_TYPE)
- mv3 = (TYPE_ATOMIC (mv3)
- ? c_build_qualified_type (TYPE_MAIN_VARIANT (mv3),
- TYPE_QUAL_ATOMIC)
- : TYPE_MAIN_VARIANT (mv3));
+ tree mv3 = remove_qualifiers (TREE_TYPE (memb));
if (comptypes_internal (mv3, mv2, data))
break;
}
if (memb == NULL_TREE)
- return 0;
+ return false;
}
else if (TREE_CODE (a2) == UNION_TYPE
&& (TYPE_NAME (a2) == NULL_TREE
@@ -2178,21 +2210,15 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
for (memb = TYPE_FIELDS (a2);
memb; memb = DECL_CHAIN (memb))
{
- tree mv3 = TREE_TYPE (memb);
- if (mv3 && mv3 != error_mark_node
- && TREE_CODE (mv3) != ARRAY_TYPE)
- mv3 = (TYPE_ATOMIC (mv3)
- ? c_build_qualified_type (TYPE_MAIN_VARIANT (mv3),
- TYPE_QUAL_ATOMIC)
- : TYPE_MAIN_VARIANT (mv3));
+ tree mv3 = remove_qualifiers (TREE_TYPE (memb));
if (comptypes_internal (mv3, mv1, data))
break;
}
if (memb == NULL_TREE)
- return 0;
+ return false;
}
else
- return 0;
+ return false;
}
args1 = TREE_CHAIN (args1);
@@ -2316,14 +2342,30 @@ mark_exp_read (tree exp)
case PARM_DECL:
DECL_READ_P (exp) = 1;
break;
+ CASE_CONVERT:
+ if (VOID_TYPE_P (TREE_TYPE (exp)))
+ switch (TREE_CODE (TREE_OPERAND (exp, 0)))
+ {
+ case PREINCREMENT_EXPR:
+ case PREDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ return;
+ default:
+ break;
+ }
+ /* FALLTHRU */
case ARRAY_REF:
case COMPONENT_REF:
case MODIFY_EXPR:
case REALPART_EXPR:
case IMAGPART_EXPR:
- CASE_CONVERT:
case ADDR_EXPR:
case VIEW_CONVERT_EXPR:
+ case PREINCREMENT_EXPR:
+ case PREDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
mark_exp_read (TREE_OPERAND (exp, 0));
break;
case COMPOUND_EXPR:
@@ -2638,6 +2680,20 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp,
return exp;
}
+/* Wrapper for the overload above, same arguments but for tree rather than
+ c_expr. This is important for hardbools to decay to bools. */
+
+static inline tree
+convert_lvalue_to_rvalue (location_t loc, tree val,
+ bool convert_p, bool read_p, bool for_init = false)
+{
+ struct c_expr expr;
+ memset (&expr, 0, sizeof (expr));
+ expr.value = val;
+ expr = convert_lvalue_to_rvalue (loc, expr, convert_p, read_p, for_init);
+ return expr.value;
+}
+
/* EXP is an expression of integer type. Apply the integer promotions
to it and return the promoted value. */
@@ -2988,8 +3044,8 @@ build_counted_by_ref (tree datum, tree subdatum, tree *counted_by_type)
to:
- (*.ACCESS_WITH_SIZE (REF, COUNTED_BY_REF, 1, (TYPE_OF_SIZE)0, -1,
- (TYPE_OF_ARRAY *)0))
+ (*.ACCESS_WITH_SIZE (REF, COUNTED_BY_REF, (* TYPE_OF_SIZE)0,
+ TYPE_SIZE_UNIT for element)
NOTE: The return type of this function is the POINTER type pointing
to the original flexible array type.
@@ -2998,11 +3054,11 @@ build_counted_by_ref (tree datum, tree subdatum, tree *counted_by_type)
The type of the first argument of this function is a POINTER type
to the original flexible array type.
- The 4th argument of the call is a constant 0 with the TYPE of the
- object pointed by COUNTED_BY_REF.
+ The 3rd argument of the call is a constant 0 with the pointer TYPE whose
+ pointee type is the TYPE of the object pointed by COUNTED_BY_REF.
- The 6th argument of the call is a constant 0 with the pointer TYPE
- to the original flexible array type.
+ The 4th argument of the call is the TYPE_SIZE_UNIT of the element TYPE
+ of the array.
*/
static tree
@@ -3013,20 +3069,22 @@ build_access_with_size_for_counted_by (location_t loc, tree ref,
gcc_assert (c_flexible_array_member_type_p (TREE_TYPE (ref)));
/* The result type of the call is a pointer to the flexible array type. */
tree result_type = c_build_pointer_type (TREE_TYPE (ref));
+ tree element_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ref)));
+
tree first_param
= c_fully_fold (array_to_pointer_conversion (loc, ref), false, NULL);
tree second_param
= c_fully_fold (counted_by_ref, false, NULL);
+ tree third_param = build_int_cst (build_pointer_type (counted_by_type), 0);
tree call
= build_call_expr_internal_loc (loc, IFN_ACCESS_WITH_SIZE,
- result_type, 6,
+ result_type, 4,
first_param,
second_param,
- build_int_cst (integer_type_node, 1),
- build_int_cst (counted_by_type, 0),
- build_int_cst (integer_type_node, -1),
- build_int_cst (result_type, 0));
+ third_param,
+ element_size);
+
/* Wrap the call with an INDIRECT_REF with the flexible array type. */
call = build1 (INDIRECT_REF, TREE_TYPE (ref), call);
SET_EXPR_LOCATION (call, loc);
@@ -3540,7 +3598,7 @@ build_external_ref (location_t loc, tree id, bool fun, tree *type)
if (TREE_CODE (ref) == FUNCTION_DECL && !in_alignof)
{
- if (!in_sizeof && !in_typeof)
+ if (!in_sizeof && !in_typeof && !in_countof)
C_DECL_USED (ref) = 1;
else if (DECL_INITIAL (ref) == NULL_TREE
&& DECL_EXTERNAL (ref)
@@ -3596,7 +3654,7 @@ struct maybe_used_decl
{
/* The decl. */
tree decl;
- /* The level seen at (in_sizeof + in_typeof). */
+ /* The level seen at (in_sizeof + in_typeof + in_countof). */
int level;
/* The next one at this level or above, or NULL. */
struct maybe_used_decl *next;
@@ -3614,7 +3672,7 @@ record_maybe_used_decl (tree decl)
{
struct maybe_used_decl *t = XOBNEW (&parser_obstack, struct maybe_used_decl);
t->decl = decl;
- t->level = in_sizeof + in_typeof;
+ t->level = in_sizeof + in_typeof + in_countof;
t->next = maybe_used_decls;
maybe_used_decls = t;
}
@@ -3628,7 +3686,7 @@ void
pop_maybe_used (bool used)
{
struct maybe_used_decl *p = maybe_used_decls;
- int cur_level = in_sizeof + in_typeof;
+ int cur_level = in_sizeof + in_typeof + in_countof;
while (p && p->level > cur_level)
{
if (used)
@@ -3738,6 +3796,110 @@ c_expr_sizeof_type (location_t loc, struct c_type_name *t)
return ret;
}
+static bool
+is_top_array_vla (tree type)
+{
+ bool zero, var;
+ tree d;
+
+ if (TREE_CODE (type) != ARRAY_TYPE)
+ return false;
+ if (!COMPLETE_TYPE_P (type))
+ return false;
+
+ d = TYPE_DOMAIN (type);
+ zero = !TYPE_MAX_VALUE (d);
+ if (zero)
+ return false;
+
+ var = (TREE_CODE (TYPE_MIN_VALUE (d)) != INTEGER_CST
+ || TREE_CODE (TYPE_MAX_VALUE (d)) != INTEGER_CST);
+ return var;
+}
+
+/* Return the result of countof applied to EXPR. */
+
+struct c_expr
+c_expr_countof_expr (location_t loc, struct c_expr expr)
+{
+ struct c_expr ret;
+ if (expr.value == error_mark_node)
+ {
+ ret.value = error_mark_node;
+ ret.original_code = ERROR_MARK;
+ ret.original_type = NULL;
+ ret.m_decimal = 0;
+ pop_maybe_used (false);
+ }
+ else
+ {
+ bool expr_const_operands = true;
+
+ tree folded_expr = c_fully_fold (expr.value, require_constant_value,
+ &expr_const_operands);
+ ret.value = c_countof_type (loc, TREE_TYPE (folded_expr));
+ c_last_sizeof_arg = expr.value;
+ c_last_sizeof_loc = loc;
+ ret.original_code = COUNTOF_EXPR;
+ ret.original_type = NULL;
+ ret.m_decimal = 0;
+ if (is_top_array_vla (TREE_TYPE (folded_expr)))
+ {
+ /* countof is evaluated when given a vla. */
+ ret.value = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret.value),
+ folded_expr, ret.value);
+ C_MAYBE_CONST_EXPR_NON_CONST (ret.value) = !expr_const_operands;
+ SET_EXPR_LOCATION (ret.value, loc);
+ }
+ pop_maybe_used (is_top_array_vla (TREE_TYPE (folded_expr)));
+ }
+ return ret;
+}
+
+/* Return the result of countof applied to T, a structure for the type
+ name passed to countof (rather than the type itself). LOC is the
+ location of the original expression. */
+
+struct c_expr
+c_expr_countof_type (location_t loc, struct c_type_name *t)
+{
+ tree type;
+ struct c_expr ret;
+ tree type_expr = NULL_TREE;
+ bool type_expr_const = true;
+ type = groktypename (t, &type_expr, &type_expr_const);
+ ret.value = c_countof_type (loc, type);
+ c_last_sizeof_arg = type;
+ c_last_sizeof_loc = loc;
+ ret.original_code = COUNTOF_EXPR;
+ ret.original_type = NULL;
+ ret.m_decimal = 0;
+ if (type == error_mark_node)
+ {
+ ret.value = error_mark_node;
+ ret.original_code = ERROR_MARK;
+ }
+ else
+ if ((type_expr || TREE_CODE (ret.value) == INTEGER_CST)
+ && is_top_array_vla (type))
+ {
+ /* If the type is a [*] array, it is a VLA but is represented as
+ having a size of zero. In such a case we must ensure that
+ the result of countof does not get folded to a constant by
+ c_fully_fold, because if the number of elements is evaluated
+ the result is not constant and so
+ constraints on zero or negative size arrays must not be applied
+ when this countof call is inside another array declarator. */
+ if (!type_expr)
+ type_expr = integer_zero_node;
+ ret.value = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret.value),
+ type_expr, ret.value);
+ C_MAYBE_CONST_EXPR_NON_CONST (ret.value) = !type_expr_const;
+ }
+ pop_maybe_used (type != error_mark_node ? is_top_array_vla (type) : false);
+ return ret;
+}
+
/* Build a function call to function FUNCTION with parameters PARAMS.
The function call is at LOC.
PARAMS is a list--a chain of TREE_LIST nodes--in which the
@@ -4163,12 +4325,6 @@ convert_argument (location_t ploc, tree function, tree fundecl,
val, origtype, ic_argpass,
npc, fundecl, function,
parmnum + 1, warnopt);
-
- if (targetm.calls.promote_prototypes (fundecl ? TREE_TYPE (fundecl) : 0)
- && INTEGRAL_TYPE_P (type)
- && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- parmval = default_conversion (parmval);
-
return parmval;
}
@@ -4342,7 +4498,8 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree fntype,
builtin_typetail = NULL_TREE;
}
- if (!typetail && parmnum == 0 && !TYPE_NO_NAMED_ARGS_STDARG_P (fntype))
+ if (!typetail && parmnum == 0 && !TYPE_NO_NAMED_ARGS_STDARG_P (fntype)
+ && !(fundecl && fndecl_built_in_p (fundecl)))
{
auto_diagnostic_group d;
bool warned;
@@ -4815,7 +4972,7 @@ pointer_diff (location_t loc, tree op0, tree op1, tree *instrument_expr)
if (!addr_space_superset (as0, as1, &as_common))
gcc_unreachable ();
- common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1));
+ common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1), NULL_TREE);
op0 = convert (common_type, op0);
op1 = convert (common_type, op1);
}
@@ -5160,7 +5317,9 @@ cas_loop:
/* newval = old + val; */
if (rhs_type != rhs_semantic_type)
val = build1 (EXCESS_PRECISION_EXPR, nonatomic_rhs_semantic_type, val);
- rhs = build_binary_op (loc, modifycode, old, val, true);
+ rhs = build_binary_op (loc, modifycode,
+ convert_lvalue_to_rvalue (loc, old, true, true),
+ val, true);
if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
{
tree eptype = TREE_TYPE (rhs);
@@ -5616,7 +5775,48 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
goto return_build_unary_op;
}
- if (C_BOOLEAN_TYPE_P (TREE_TYPE (arg)))
+ tree true_res;
+ if (c_hardbool_type_attr (TREE_TYPE (arg), NULL, &true_res))
+ {
+ tree larg = stabilize_reference (arg);
+ tree sarg = save_expr (larg);
+ switch (code)
+ {
+ case PREINCREMENT_EXPR:
+ val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, true_res);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), sarg, val);
+ break;
+ case POSTINCREMENT_EXPR:
+ val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, true_res);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), val, sarg);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), sarg, val);
+ break;
+ case PREDECREMENT_EXPR:
+ {
+ tree rarg = convert_lvalue_to_rvalue (location, sarg,
+ true, true);
+ rarg = invert_truthvalue_loc (location, rarg);
+ rarg = convert (TREE_TYPE (sarg), rarg);
+ val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, rarg);
+ }
+ break;
+ case POSTDECREMENT_EXPR:
+ {
+ tree rarg = convert_lvalue_to_rvalue (location, sarg,
+ true, true);
+ rarg = invert_truthvalue_loc (location, rarg);
+ tree iarg = convert (TREE_TYPE (larg), rarg);
+ val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, iarg);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), val, sarg);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), sarg, val);
+ }
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ TREE_SIDE_EFFECTS (val) = 1;
+ }
+ else if (C_BOOLEAN_TYPE_P (TREE_TYPE (arg)))
val = boolean_increment (code, arg);
else
val = build2 (code, TREE_TYPE (arg), arg, inc);
@@ -6269,7 +6469,10 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
addr_space_t as_common;
if (comp_target_types (colon_loc, type1, type2))
- result_type = common_pointer_type (type1, type2);
+ {
+ ifexp = save_expr (ifexp);
+ result_type = common_pointer_type (type1, type2, ifexp);
+ }
else if (null_pointer_constant_p (orig_op1))
result_type = type2;
else if (null_pointer_constant_p (orig_op2))
@@ -6322,14 +6525,16 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
else
{
int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
- diagnostic_t kind = DK_PERMERROR;
+ enum diagnostics::kind kind = diagnostics::kind::permerror;
if (!flag_isoc99)
/* This downgrade to a warning ensures that -std=gnu89
-pedantic-errors does not flag these mismatches between
- builtins as errors (as DK_PERMERROR would). ISO C99
- and later do not have implicit function declarations,
+ builtins as errors (as diagnostics::kind::permerror would)
+ ISO C99 and later do not have implicit function declarations,
so the mismatch cannot occur naturally there. */
- kind = bltin1 && bltin2 ? DK_WARNING : DK_PEDWARN;
+ kind = (bltin1 && bltin2
+ ? diagnostics::kind::warning
+ : diagnostics::kind::pedwarn);
if (emit_diagnostic (kind, colon_loc, OPT_Wincompatible_pointer_types,
"pointer type mismatch "
"in conditional expression"))
@@ -6744,17 +6949,12 @@ c_safe_arg_type_equiv_p (tree t1, tree t2)
&& TREE_CODE (t2) == POINTER_TYPE)
return true;
- /* The signedness of the parameter matters only when an integral
- type smaller than int is promoted to int, otherwise only the
- precision of the parameter matters.
- This check should make sure that the callee does not see
- undefined values in argument registers. */
+ /* Only the precision of the parameter matters. This check should
+ make sure that the callee does not see undefined values in argument
+ registers. */
if (INTEGRAL_TYPE_P (t1)
&& INTEGRAL_TYPE_P (t2)
- && TYPE_PRECISION (t1) == TYPE_PRECISION (t2)
- && (TYPE_UNSIGNED (t1) == TYPE_UNSIGNED (t2)
- || !targetm.calls.promote_prototypes (NULL_TREE)
- || TYPE_PRECISION (t1) >= TYPE_PRECISION (integer_type_node)))
+ && TYPE_PRECISION (t1) == TYPE_PRECISION (t2))
return true;
return comptypes (t1, t2);
@@ -7218,8 +7418,23 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
newrhs = build1 (EXCESS_PRECISION_EXPR, TREE_TYPE (rhs),
newrhs);
}
- newrhs = build_binary_op (location,
- modifycode, lhs, newrhs, true);
+ bool clear_decl_read = false;
+ if ((VAR_P (lhs) || TREE_CODE (lhs) == PARM_DECL)
+ && !DECL_READ_P (lhs)
+ && (VAR_P (lhs) ? warn_unused_but_set_variable
+ : warn_unused_but_set_parameter) > 2)
+ {
+ mark_exp_read (newrhs);
+ if (!DECL_READ_P (lhs))
+ clear_decl_read = true;
+ }
+
+ newrhs = build_binary_op (location, modifycode,
+ convert_lvalue_to_rvalue (location, lhs,
+ true, true),
+ newrhs, true);
+ if (clear_decl_read)
+ DECL_READ_P (lhs) = 0;
/* The original type of the right hand side is no longer
meaningful. */
@@ -7382,10 +7597,7 @@ find_anonymous_field_with_type (tree struct_type, tree type)
field != NULL_TREE;
field = TREE_CHAIN (field))
{
- tree fieldtype = (TYPE_ATOMIC (TREE_TYPE (field))
- ? c_build_qualified_type (TREE_TYPE (field),
- TYPE_QUAL_ATOMIC)
- : TYPE_MAIN_VARIANT (TREE_TYPE (field)));
+ tree fieldtype = remove_qualifiers (TREE_TYPE (field));
if (DECL_NAME (field) == NULL
&& comptypes (type, fieldtype))
{
@@ -7423,10 +7635,7 @@ convert_to_anonymous_field (location_t location, tree type, tree rhs)
gcc_assert (RECORD_OR_UNION_TYPE_P (rhs_struct_type));
gcc_assert (POINTER_TYPE_P (type));
- lhs_main_type = (TYPE_ATOMIC (TREE_TYPE (type))
- ? c_build_qualified_type (TREE_TYPE (type),
- TYPE_QUAL_ATOMIC)
- : TYPE_MAIN_VARIANT (TREE_TYPE (type)));
+ lhs_main_type = remove_qualifiers (TREE_TYPE (type));
found_field = NULL_TREE;
found_sub_field = false;
@@ -7437,10 +7646,7 @@ convert_to_anonymous_field (location_t location, tree type, tree rhs)
if (DECL_NAME (field) != NULL_TREE
|| !RECORD_OR_UNION_TYPE_P (TREE_TYPE (field)))
continue;
- tree fieldtype = (TYPE_ATOMIC (TREE_TYPE (field))
- ? c_build_qualified_type (TREE_TYPE (field),
- TYPE_QUAL_ATOMIC)
- : TYPE_MAIN_VARIANT (TREE_TYPE (field)));
+ tree fieldtype = remove_qualifiers (TREE_TYPE (field));
if (comptypes (lhs_main_type, fieldtype))
{
if (found_field != NULL_TREE)
@@ -7488,7 +7694,8 @@ error_init (location_t loc, const char *gmsgid, ...)
/* The gmsgid may be a format string with %< and %>. */
va_list ap;
va_start (ap, gmsgid);
- bool warned = emit_diagnostic_valist (DK_ERROR, loc, -1, gmsgid, &ap);
+ bool warned = emit_diagnostic_valist (diagnostics::kind::error,
+ loc, -1, gmsgid, &ap);
va_end (ap);
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
@@ -7500,7 +7707,7 @@ error_init (location_t loc, const char *gmsgid, ...)
static bool ATTRIBUTE_GCC_DIAG (3,0)
pedwarn_permerror_init (location_t loc, int opt, const char *gmsgid,
- va_list *ap, diagnostic_t kind)
+ va_list *ap, enum diagnostics::kind kind)
{
/* Use the location where a macro was expanded rather than where
it was defined to make sure macros defined in system headers
@@ -7527,7 +7734,8 @@ pedwarn_init (location_t loc, int opt, const char *gmsgid, ...)
{
va_list ap;
va_start (ap, gmsgid);
- bool warned = pedwarn_permerror_init (loc, opt, gmsgid, &ap, DK_PEDWARN);
+ bool warned = pedwarn_permerror_init (loc, opt, gmsgid, &ap,
+ diagnostics::kind::pedwarn);
va_end (ap);
return warned;
}
@@ -7539,7 +7747,8 @@ permerror_init (location_t loc, int opt, const char *gmsgid, ...)
{
va_list ap;
va_start (ap, gmsgid);
- bool warned = pedwarn_permerror_init (loc, opt, gmsgid, &ap, DK_PERMERROR);
+ bool warned = pedwarn_permerror_init (loc, opt, gmsgid, &ap,
+ diagnostics::kind::permerror);
va_end (ap);
return warned;
}
@@ -8197,23 +8406,14 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
tree ttl = TREE_TYPE (type);
tree ttr = TREE_TYPE (rhstype);
- tree mvl = ttl;
- tree mvr = ttr;
bool is_opaque_pointer;
bool target_cmp = false; /* Cache comp_target_types () result. */
addr_space_t asl;
addr_space_t asr;
- if (TREE_CODE (mvl) != ARRAY_TYPE)
- mvl = (TYPE_ATOMIC (mvl)
- ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvl),
- TYPE_QUAL_ATOMIC)
- : TYPE_MAIN_VARIANT (mvl));
- if (TREE_CODE (mvr) != ARRAY_TYPE)
- mvr = (TYPE_ATOMIC (mvr)
- ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvr),
- TYPE_QUAL_ATOMIC)
- : TYPE_MAIN_VARIANT (mvr));
+ tree mvl = remove_qualifiers (ttl);
+ tree mvr = remove_qualifiers (ttr);
+
/* Opaque pointers are treated like void pointers. */
is_opaque_pointer = vector_targets_convertible_p (ttl, ttr);
@@ -9153,8 +9353,24 @@ check_constexpr_init (location_t loc, tree type, tree init,
/* The initializer must be an integer constant expression,
representable in the target type. */
if (!int_const_expr)
- error_at (loc, "%<constexpr%> integer initializer is not an "
- "integer constant expression");
+ {
+ if (TREE_CODE (init) == RAW_DATA_CST
+ && TYPE_PRECISION (type) == CHAR_BIT)
+ {
+ if (!TYPE_UNSIGNED (type))
+ for (unsigned int i = 0;
+ i < (unsigned) RAW_DATA_LENGTH (init); ++i)
+ if (RAW_DATA_SCHAR_ELT (init, i) < 0)
+ {
+ error_at (loc, "%<constexpr%> initializer not "
+ "representable in type of object");
+ break;
+ }
+ }
+ else
+ error_at (loc, "%<constexpr%> integer initializer is not an "
+ "integer constant expression");
+ }
else if (!int_fits_type_p (init, type))
error_at (loc, "%<constexpr%> initializer not representable in "
"type of object");
@@ -12529,7 +12745,8 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
oconstraints[i] = constraint;
if (parse_output_constraint (&constraint, i, ninputs, noutputs,
- &allows_mem, &allows_reg, &is_inout))
+ &allows_mem, &allows_reg, &is_inout,
+ nullptr))
{
/* If the operand is going to end up in memory,
mark it addressable. */
@@ -12590,7 +12807,8 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
input = TREE_VALUE (tail);
if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
- oconstraints, &allows_mem, &allows_reg))
+ oconstraints, &allows_mem, &allows_reg,
+ nullptr))
{
/* If the operand is going to end up in memory,
mark it addressable. */
@@ -12606,11 +12824,9 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
}
else
{
- struct c_expr expr;
- memset (&expr, 0, sizeof (expr));
- expr.value = input;
- expr = convert_lvalue_to_rvalue (loc, expr, true, false);
- input = c_fully_fold (expr.value, false, NULL);
+ input = c_fully_fold (convert_lvalue_to_rvalue (loc, input,
+ true, false),
+ false, NULL);
if (input != error_mark_node && VOID_TYPE_P (TREE_TYPE (input)))
{
@@ -12772,7 +12988,9 @@ c_finish_return (location_t loc, tree retval, tree origtype, bool musttail_p)
&& valtype != NULL_TREE && TREE_CODE (valtype) != VOID_TYPE)
{
no_warning = true;
- if (emit_diagnostic (flag_isoc99 ? DK_PERMERROR : DK_WARNING,
+ if (emit_diagnostic (flag_isoc99
+ ? diagnostics::kind::permerror
+ : diagnostics::kind::warning,
loc, OPT_Wreturn_mismatch,
"%<return%> with no value,"
" in function returning non-void"))
@@ -14264,7 +14482,7 @@ build_binary_op (location_t location, enum tree_code code,
Otherwise, the targets must be compatible
and both must be object or both incomplete. */
if (comp_target_types (location, type0, type1))
- result_type = common_pointer_type (type0, type1);
+ result_type = common_pointer_type (type0, type1, NULL_TREE);
else if (!addr_space_superset (as0, as1, &as_common))
{
error_at (location, "comparison of pointers to "
@@ -14403,7 +14621,7 @@ build_binary_op (location_t location, enum tree_code code,
if (comp_target_types (location, type0, type1))
{
- result_type = common_pointer_type (type0, type1);
+ result_type = common_pointer_type (type0, type1, NULL_TREE);
if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
!= !COMPLETE_TYPE_P (TREE_TYPE (type1)))
pedwarn_c99 (location, OPT_Wpedantic,
@@ -15230,12 +15448,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
/* If the array section is pointer based and the pointer
itself is _Atomic qualified, we need to atomically load
the pointer. */
- c_expr expr;
- memset (&expr, 0, sizeof (expr));
- expr.value = ret;
- expr = convert_lvalue_to_rvalue (OMP_CLAUSE_LOCATION (c),
- expr, false, false);
- ret = expr.value;
+ ret = convert_lvalue_to_rvalue (OMP_CLAUSE_LOCATION (c),
+ ret, false, false);
}
return ret;
}
@@ -15520,9 +15734,7 @@ handle_omp_array_sections (tree &c, enum c_omp_region_type ort)
tree *tp = &OMP_CLAUSE_DECL (c);
if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY)
- && TREE_CODE (*tp) == TREE_LIST
- && TREE_PURPOSE (*tp)
- && TREE_CODE (TREE_PURPOSE (*tp)) == TREE_VEC)
+ && OMP_ITERATOR_DECL_P (*tp))
tp = &TREE_VALUE (*tp);
tree first = handle_omp_array_sections_1 (c, *tp, types,
maybe_zero_len, first_non_one,
@@ -16080,7 +16292,14 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
/* We've reached the end of a list of expanded nodes. Reset the group
start pointer. */
if (c == grp_sentinel)
- grp_start_p = NULL;
+ {
+ if (grp_start_p
+ && OMP_CLAUSE_HAS_ITERATORS (*grp_start_p))
+ for (tree gc = *grp_start_p; gc != grp_sentinel;
+ gc = OMP_CLAUSE_CHAIN (gc))
+ OMP_CLAUSE_ITERATORS (gc) = OMP_CLAUSE_ITERATORS (*grp_start_p);
+ grp_start_p = NULL;
+ }
switch (OMP_CLAUSE_CODE (c))
{
@@ -16719,9 +16938,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
/* FALLTHRU */
case OMP_CLAUSE_AFFINITY:
t = OMP_CLAUSE_DECL (c);
- if (TREE_CODE (t) == TREE_LIST
- && TREE_PURPOSE (t)
- && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
+ if (OMP_ITERATOR_DECL_P (t))
{
if (TREE_PURPOSE (t) != last_iterators)
last_iterators_remove
@@ -16821,10 +17038,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
break;
}
}
- if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST
- && TREE_PURPOSE (OMP_CLAUSE_DECL (c))
- && (TREE_CODE (TREE_PURPOSE (OMP_CLAUSE_DECL (c)))
- == TREE_VEC))
+ if (OMP_ITERATOR_DECL_P (OMP_CLAUSE_DECL (c)))
TREE_VALUE (OMP_CLAUSE_DECL (c)) = t;
else
OMP_CLAUSE_DECL (c) = t;
@@ -16834,9 +17048,22 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
case OMP_CLAUSE_MAP:
if (OMP_CLAUSE_MAP_IMPLICIT (c) && !implicit_moved)
goto move_implicit;
+ if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POP_MAPPER_NAME)
+ {
+ remove = true;
+ break;
+ }
/* FALLTHRU */
case OMP_CLAUSE_TO:
case OMP_CLAUSE_FROM:
+ if (OMP_CLAUSE_ITERATORS (c)
+ && c_omp_finish_iterators (OMP_CLAUSE_ITERATORS (c)))
+ {
+ t = error_mark_node;
+ break;
+ }
+ /* FALLTHRU */
case OMP_CLAUSE__CACHE_:
{
using namespace omp_addr_tokenizer;
@@ -17565,6 +17792,11 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
pc = &OMP_CLAUSE_CHAIN (c);
}
+ if (grp_start_p
+ && OMP_CLAUSE_HAS_ITERATORS (*grp_start_p))
+ for (tree gc = *grp_start_p; gc; gc = OMP_CLAUSE_CHAIN (gc))
+ OMP_CLAUSE_ITERATORS (gc) = OMP_CLAUSE_ITERATORS (*grp_start_p);
+
if (simdlen
&& safelen
&& tree_int_cst_lt (OMP_CLAUSE_SAFELEN_EXPR (safelen),
@@ -17774,6 +18006,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
return clauses;
}
+/* Do processing necessary to make CLAUSES well-formed, where CLAUSES result
+ from implicit instantiation of user-defined mappers (in gimplify.cc). */
+
+tree
+c_omp_finish_mapper_clauses (tree clauses)
+{
+ return c_finish_omp_clauses (clauses, C_ORT_OMP);
+}
+
/* Return code to initialize DST with a copy constructor from SRC.
C doesn't have copy constructors nor assignment operators, only for
_Atomic vars we need to perform __atomic_load from src into a temporary
diff --git a/gcc/c/gimple-parser.cc b/gcc/c/gimple-parser.cc
index 90b9beb..5fd1db8 100644
--- a/gcc/c/gimple-parser.cc
+++ b/gcc/c/gimple-parser.cc
@@ -963,6 +963,29 @@ c_parser_gimple_statement (gimple_parser &parser, gimple_seq *seq)
return;
}
+/* A mapping between an identifier to a tree code for binary operations. */
+static const std::pair<const char *, tree_code> gimple_binary_identifier_code[] =
+ {
+ {"__MULT_HIGHPART", MULT_HIGHPART_EXPR},
+ {"__UNLT", UNLT_EXPR},
+ {"__UNLE", UNLE_EXPR},
+ {"__UNGT", UNGT_EXPR},
+ {"__UNGE", UNGE_EXPR},
+ {"__UNEQ", UNEQ_EXPR},
+ {"__UNORDERED", UNORDERED_EXPR},
+ {"__ORDERED", ORDERED_EXPR},
+ {"__LTGT", LTGT_EXPR},
+ {"__FLOOR_DIV", FLOOR_DIV_EXPR},
+ {"__ROUND_DIV", ROUND_DIV_EXPR},
+ {"__EXACT_DIV", EXACT_DIV_EXPR},
+ {"__CEIL_DIV", CEIL_DIV_EXPR},
+ {"__FLOOR_MOD", FLOOR_MOD_EXPR},
+ {"__ROUND_MOD", ROUND_MOD_EXPR},
+ {"__CEIL_MOD", CEIL_MOD_EXPR},
+ {"__ROTATE_LEFT", LROTATE_EXPR},
+ {"__ROTATE_RIGHT", RROTATE_EXPR},
+ };
+
/* Parse gimple binary expr.
gimple-binary-expression:
@@ -1061,86 +1084,16 @@ c_parser_gimple_binary_expression (gimple_parser &parser, tree ret_type)
case CPP_NAME:
{
tree id = c_parser_peek_token (parser)->value;
- if (strcmp (IDENTIFIER_POINTER (id), "__MULT_HIGHPART") == 0)
- {
- code = MULT_HIGHPART_EXPR;
- break;
- }
- else if (strcmp (IDENTIFIER_POINTER (id), "__UNLT") == 0)
- {
- code = UNLT_EXPR;
- break;
- }
- else if (strcmp (IDENTIFIER_POINTER (id), "__UNLE") == 0)
- {
- code = UNLE_EXPR;
- break;
- }
- else if (strcmp (IDENTIFIER_POINTER (id), "__UNGT") == 0)
- {
- code = UNGT_EXPR;
- break;
- }
- else if (strcmp (IDENTIFIER_POINTER (id), "__UNGE") == 0)
- {
- code = UNGE_EXPR;
- break;
- }
- else if (strcmp (IDENTIFIER_POINTER (id), "__UNEQ") == 0)
- {
- code = UNEQ_EXPR;
- break;
- }
- else if (strcmp (IDENTIFIER_POINTER (id), "__UNORDERED") == 0)
- {
- code = UNORDERED_EXPR;
- break;
- }
- else if (strcmp (IDENTIFIER_POINTER (id), "__ORDERED") == 0)
- {
- code = ORDERED_EXPR;
- break;
- }
- else if (strcmp (IDENTIFIER_POINTER (id), "__LTGT") == 0)
+ for (auto &p : gimple_binary_identifier_code)
{
- code = LTGT_EXPR;
- break;
- }
- else if (strcmp (IDENTIFIER_POINTER (id), "__FLOOR_DIV") == 0)
- {
- code = FLOOR_DIV_EXPR;
- break;
- }
- else if (strcmp (IDENTIFIER_POINTER (id), "__ROUND_DIV") == 0)
- {
- code = ROUND_DIV_EXPR;
- break;
- }
- else if (strcmp (IDENTIFIER_POINTER (id), "__EXACT_DIV") == 0)
- {
- code = EXACT_DIV_EXPR;
- break;
- }
- else if (strcmp (IDENTIFIER_POINTER (id), "__CEIL_DIV") == 0)
- {
- code = CEIL_DIV_EXPR;
- break;
- }
- else if (strcmp (IDENTIFIER_POINTER (id), "__FLOOR_MOD") == 0)
- {
- code = FLOOR_MOD_EXPR;
- break;
- }
- else if (strcmp (IDENTIFIER_POINTER (id), "__ROUND_MOD") == 0)
- {
- code = ROUND_MOD_EXPR;
- break;
- }
- else if (strcmp (IDENTIFIER_POINTER (id), "__CEIL_MOD") == 0)
- {
- code = CEIL_MOD_EXPR;
- break;
+ if (strcmp (IDENTIFIER_POINTER (id), p.first) == 0)
+ {
+ code = p.second;
+ break;
+ }
}
+ if (code != ERROR_MARK)
+ break;
}
/* Fallthru. */
default: