summaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-05-02 14:43:35 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-05-02 14:43:35 +0000
commit34efdaf078b01a7387007c4e6bde6db86384c4b7 (patch)
treed503eaf41d085669d1481bb46ec038bc866fece6 /gcc/c
parentf733cf303bcdc952c92b81dd62199a40a1f555ec (diff)
downloadgcc-tarball-master.tar.gz
gcc-7.1.0gcc-7.1.0
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/ChangeLog1047
-rw-r--r--gcc/c/Make-lang.in31
-rw-r--r--gcc/c/c-array-notation.c12
-rw-r--r--gcc/c/c-aux-info.c2
-rw-r--r--gcc/c/c-convert.c2
-rw-r--r--gcc/c/c-decl.c646
-rw-r--r--gcc/c/c-errors.c8
-rw-r--r--gcc/c/c-fold.c20
-rw-r--r--gcc/c/c-lang.c27
-rw-r--r--gcc/c/c-lang.h2
-rw-r--r--gcc/c/c-objc-common.c2
-rw-r--r--gcc/c/c-objc-common.h10
-rw-r--r--gcc/c/c-parser.c1504
-rw-r--r--gcc/c/c-parser.h189
-rw-r--r--gcc/c/c-tree.h39
-rw-r--r--gcc/c/c-typeck.c821
-rw-r--r--gcc/c/config-lang.in4
-rw-r--r--gcc/c/gccspec.c2
-rw-r--r--gcc/c/gimple-parser.c1567
-rw-r--r--gcc/c/gimple-parser.h27
20 files changed, 4989 insertions, 973 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index ed09d22be1..2324203a9b 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,6 +1,580 @@
-2016-08-22 Release Manager
+2017-05-02 Release Manager
- * GCC 6.2.0 released.
+ * GCC 7.1.0 released.
+
+2017-04-03 Jonathan Wakely <jwakely@redhat.com>
+
+ * c-array-notation.c: Fix typo in comment.
+
+2017-03-29 Marek Polacek <polacek@redhat.com>
+
+ PR c/79730
+ * c-decl.c (finish_decl): Check VAR_P.
+
+2017-03-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/80162
+ * c-tree.h (c_mark_addressable): Add array_ref_p argument.
+ * c-typeck.c (c_mark_addressable): Likewise. Look through
+ VIEW_CONVERT_EXPR unless array_ref_p and VCE is from VECTOR_TYPE
+ to ARRAY_TYPE.
+ (build_array_ref): Pass true as array_ref_p to c_mark_addressable.
+
+2017-03-23 Marek Polacek <polacek@redhat.com>
+
+ * c-tree.h: Remove a C_RID_YYCODE reference.
+
+2017-03-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/80097
+ * c-typeck.c (build_binary_op): Add EXCESS_PRECISION_EXPR only around
+ optional COMPOUND_EXPR with ubsan instrumentation.
+
+2017-03-17 Marek Polacek <polacek@redhat.com>
+
+ * c-parser.c: Add C11 references.
+
+2017-03-15 Marek Polacek <polacek@redhat.com>
+
+ * c-parser.c (c_parser_enum_specifier): Remove redundant line.
+
+2017-03-11 Marek Polacek <polacek@redhat.com>
+
+ * c-decl.c (implicit_decl_warning): Add a comment. Fix formatting.
+
+2017-03-10 David Malcolm <dmalcolm@redhat.com>
+
+ PR translation/79848
+ * c-decl.c (declspecs_add_type): Simplify uses of "%<%s%>" to
+ "%qs".
+ * c-parser.c (c_parser_oacc_shape_clause): Likewise.
+
+2017-03-09 Marek Polacek <polacek@redhat.com>
+
+ PR sanitizer/79757
+ * c-parser.c (c_parser_declaration_or_fndef): Don't sanitize old-style
+ parameter declarations with initializers.
+
+2017-03-09 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/79969
+ * c-decl.c (start_enum): Adjust DECL_SOURCE_LOCATION of
+ TYPE_STUB_DECL.
+
+2017-03-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/79834
+ * c-parser.c (c_parser_pragma): Use error_at instead of c_parser_error
+ for "may only be used in compound statements" diagnostics, change it
+ such that the same translatable string is used for all pragmas. For
+ PRAGMA_OACC_WAIT use "acc wait" rather than "acc enter data" in the
+ diagnostics.
+ (c_parser_omp_cancellation_point, c_parser_omp_target_update,
+ c_parser_omp_target_enter_data, c_parser_omp_target_exit_data): Change
+ "may only be used in compound statements" diagnostics, such that the
+ same translatable string is used for all pragmas.
+
+2017-03-04 Marek Polacek <polacek@redhat.com>
+
+ PR c/79847
+ * c-decl.c (implicit_decl_warning): Add missing space.
+
+2017-03-03 Marek Polacek <polacek@redhat.com>
+
+ PR c/79758
+ * c-decl.c (store_parm_decls_oldstyle): Check if the element of
+ current_function_prototype_arg_types is error_mark_node. Fix
+ formatting. Use TREE_VALUE instead of TREE_TYPE.
+
+2017-03-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/79837
+ * c-parser.c (c_parser_omp_clause_reduction): Don't mention
+ %<min%> or %<max%> in the diagnostics, instead mention identifier.
+ (c_parser_omp_declare_reduction): Don't mention %<min%> in the
+ diagnostics.
+
+ PR c/79836
+ * c-parser.c (c_parser_generic_selection): Use %<_Generic%>
+ instead of %<_Generic>.
+ (c_parser_omp_ordered): Use %<depend%> instead of %<depend>.
+ (c_parser_omp_target_exit_data): Use %<release%> instead of
+ %<release>.
+
+2017-02-28 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_asm_statement): Use cond ? G_("...") : G_("...")
+ instead of just cond ? "..." : "...".
+ (c_parser_oacc_enter_exit_data): Use %s and ternary operator only
+ for "enter"/"exit" keyword.
+ (c_finish_oacc_routine): Don't use %s to supply portions of the
+ message.
+
+2017-02-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/79588
+ * c-parser.c (c_parser_postfix_expression_after_primary): Don't
+ handle -Wrestrict here.
+ * c-typeck.c (build_function_call_vec): Adjust
+ check_function_arguments caller.
+
+2017-02-23 Richard Biener <rguenther@suse.de>
+
+ PR c/79684
+ * gimple-parser.c (c_parser_gimple_statement): Use set_error
+ to initialize c_exprs to return.
+ (c_parser_gimple_binary_expression): Likewise.
+ (c_parser_gimple_unary_expression): Likewise.
+ (c_parser_gimple_postfix_expression): Likewise.
+
+2017-02-22 Marek Polacek <polacek@redhat.com>
+
+ PR c/79662
+ * c-typeck.c (convert_arguments): Handle error_mark_node.
+
+2017-02-19 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ * gimple-parser.c (c_parser_gimple_postfix_expression): Check return
+ value of c_parser_parse_ssa_name against error_mark_node and emit
+ error if ssa name is anonymous and written as default definition.
+
+2017-02-19 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ * gimple-parser.c (c_parser_gimple_postfix_expression): Handle
+ FMA_EXPR.
+
+2017-02-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/79512
+ * c-parser.c (c_parser_omp_target): For -fopenmp-simd
+ ignore #pragma omp target even when not followed by identifier.
+
+2017-02-14 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ * gimpler-parser.c (c_parser_gimple_statement): Handle ABS_EXPR.
+ (c_parser_gimple_unary_expression): Likewise.
+
+2017-02-13 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_oacc_declare): Add missing space in
+ diagnostics.
+
+2017-02-13 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ PR c/79478
+ * gimple-parser.c (c_parser_gimple_postfix_expression): Call
+ set_c_expr_source_range when parsing ssa-name.
+
+2017-02-10 Prasad Ghangal <prasad.ghangal@gmail.com>
+ Richard Biener <rguenther@suse.de>
+
+ * gimple-parser.c (c_parser_gimple_binary_expression): Avoid
+ building IL when arguments are error_mark_node.
+ (c_parser_gimple_unary_expression): Likewise.
+ (c_parser_gimple_if_stmt): Likewise.
+ (c_parser_gimple_switch_stmt): Likewise.
+ (c_parser_gimple_return_stmt): Likewise.
+ (c_parser_parse_ssa_name): When name lookup fails do not build
+ an SSA name. Use undeclared rather than not declared in error
+ reporting.
+
+2017-02-09 Marek Polacek <polacek@redhat.com>
+
+ PR c/79428
+ * c-parser.c (c_parser_omp_ordered): Call c_parser_skip_to_pragma_eol
+ instead of c_parser_skip_until_found.
+
+2017-02-09 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/79431
+ * c-parser.c (c_parser_omp_declare_target): Don't invoke
+ symtab_node::get on automatic variables.
+
+2016-02-09 Nathan Sidwell <nathan@codesourcery.com>
+ Chung-Lin Tang <cltang@codesourcery.com>
+
+ * c-parser.c (c_parser_omp_clause_collapse): Disallow tile.
+ (c_parser_oacc_clause_tile): Disallow collapse. Fix parsing and
+ semantic checking.
+ * c-parser.c (c_parser_omp_for_loop): Accept tiling constructs.
+
+2017-02-07 Richard Biener <rguenther@suse.de>
+
+ * gimple-parser.c (c_parser_gimple_expr_list): Simplify.
+ (c_parser_gimple_postfix_expression_after_primary):
+ Do not use c_build_function_call_vec to avoid folding and promotion.
+ Simplify.
+
+2017-01-25 Maxim Ostapenko <m.ostapenko@samsung.com>
+
+ PR lto/79061
+ * c-decl.c (pop_scope): Pass main_input_filename to
+ build_translation_unit_decl.
+
+2017-01-24 David Malcolm <dmalcolm@redhat.com>
+
+ * c-parser.c: Include "read-rtl-function.h" and
+ "run-rtl-passes.h".
+ (c_parser_declaration_or_fndef): Rename "gimple-pass-list" in
+ grammar to gimple-or-rtl-pass-list. Add rtl-function-definition
+ production. Update for renaming of field "gimple_pass" to
+ "gimple_or_rtl_pass". If __RTL was seen, call
+ c_parser_parse_rtl_body. Convert a timevar_push/pop pair
+ to an auto_timevar, to cope with early exit.
+ (c_parser_declspecs): Update RID_GIMPLE handling for renaming of
+ field "gimple_pass" to "gimple_or_rtl_pass", and for renaming of
+ c_parser_gimple_pass_list to c_parser_gimple_or_rtl_pass_list.
+ Handle RID_RTL.
+ (c_parser_parse_rtl_body): New function.
+ * c-tree.h (enum c_declspec_word): Add cdw_rtl.
+ (struct c_declspecs): Rename field "gimple_pass" to
+ "gimple_or_rtl_pass". Add field "rtl_p".
+ * gimple-parser.c (c_parser_gimple_pass_list): Rename to...
+ (c_parser_gimple_or_rtl_pass_list): ...this, updating accordingly.
+ * gimple-parser.h (c_parser_gimple_pass_list): Rename to...
+ (c_parser_gimple_or_rtl_pass_list): ...this.
+
+2017-01-20 Marek Polacek <polacek@redhat.com>
+
+ PR c/64279
+ * c-typeck.c (build_conditional_expr): Warn about duplicated branches.
+
+2017-01-13 Richard Biener <rguenther@suse.de>
+
+ * gimple-parser.c (c_parser_gimple_compound_statement): Handle
+ nops.
+
+2017-01-13 Richard Biener <rguenther@suse.de>
+
+ * gimple-parser.c (c_parser_gimple_postfix_expression): Parse
+ _Literal ( type-name ) number.
+
+2017-01-12 Richard Biener <rguenther@suse.de>
+
+ * gimple-parser.c (c_parser_gimple_postfix_expression): Parse
+ __MEM.
+
+2017-01-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/72813
+ * c-decl.c (pop_file_scope): Set flag_syntax_only to 1 after writing
+ PCH file.
+
+2017-01-11 Richard Biener <rguenther@suse.de>
+
+ PR bootstrap/79052
+ * gimple-parser.c (c_parser_gimple_switch_stmt): Add missing
+ returns on parse errors.
+
+2017-01-04 Marek Polacek <polacek@redhat.com>
+
+ PR c++/64767
+ * c-parser.c (c_parser_postfix_expression): Mark zero character
+ constants by setting original_type in c_expr.
+ * c-typeck.c (parser_build_binary_op): Warn when a pointer is compared
+ with a zero character constant.
+ (char_type_p): New function.
+
+2017-01-04 David Malcolm <dmalcolm@redhat.com>
+
+ * c-parser.c (c_parser_declaration_or_fndef): Create a
+ rich_location at init_loc and parse it to start_init.
+ (last_init_list_comma): New global.
+ (c_parser_braced_init): Update last_init_list_comma when parsing
+ commas. Pass it to pop_init_level. Pass location of closing
+ brace to pop_init_level.
+ (c_parser_postfix_expression_after_paren_type): Create a
+ rich_location at type_loc and parse it to start_init.
+ (c_parser_omp_declare_reduction): Likewise for loc.
+ * c-tree.h (start_init): Add rich_location * param.
+ (pop_init_level): Add location_t param.
+ * c-typeck.c (struct initializer_stack): Add field
+ "missing_brace_richloc".
+ (start_init): Add richloc param, use it to initialize
+ the stack node's missing_brace_richloc.
+ (last_init_list_comma): New decl.
+ (finish_implicit_inits): Pass last_init_list_comma to
+ pop_init_level.
+ (push_init_level): When finding missing open braces, add fix-it
+ hints to the richloc.
+ (pop_init_level): Add "insert_before" param and pass it
+ when calling pop_init_level. Add fixits about missing
+ close braces to any richloc. Use the richloc for the
+ -Wmissing-braces warning.
+ (set_designator): Pass last_init_list_comma to pop_init_level.
+ (process_init_element): Likewise.
+
+2017-01-01 Jakub Jelinek <jakub@redhat.com>
+
+ Update copyright years.
+
+2016-12-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR bootstrap/78817
+ * c-typeck.c (build_function_call_vec): If check_function_arguments
+ returns true, set TREE_NO_WARNING on CALL_EXPR.
+
+ PR c/77767
+ * c-decl.c (grokdeclarator): If *expr is non-NULL, append expression
+ to *expr instead of overwriting it.
+
+2016-12-20 Richard Biener <rguenther@suse.de>
+
+ * gimple-parser.c (c_parser_gimple_compound_statement): Improve
+ error recovery.
+ (c_parser_gimple_statement): Only build assigns for non-error
+ stmts.
+ (c_parser_gimple_postfix_expression_after): Improve error recovery.
+
+2016-12-14 Martin Jambor <mjambor@suse.cz>
+
+ * c-parser.c: Include omp-general.h and omp-offload.h instead of
+ omp-low.h.
+ (c_finish_oacc_routine): Adjusted call to
+ get_oacc_fn_attrib, build_oacc_routine_dims and replace_oacc_fn_attrib
+ to use their new names.
+ (c_parser_oacc_enter_exit_data): Adjusted call to find_omp_clause to
+ use its new name.
+ (c_parser_oacc_update): Likewise.
+ (c_parser_omp_simd): Likewise.
+ (c_parser_omp_target_update): Likewise.
+ * c-typeck.c: Include omp-general.h instead of omp-low.h.
+ (c_finish_omp_cancel): Adjusted call to find_omp_clause to use its new
+ name.
+ (c_finish_omp_cancellation_point): Likewise.
+ * gimple-parser.c: Do not include omp-low.h
+
+2016-12-02 Cesar Philippidis <cesar@codesourcery.com>
+ James Norris <jnorris@codesourcery.com>
+
+ * c-parser.c (c_parser_pragma): Error when PRAGMA_OACC_{ENTER_DATA,
+ EXIT_DATA,WAIT} are not used in compound statements.
+ (c_parser_oacc_enter_exit_data): Update diagnostics.
+
+2016-11-21 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR c++/71973
+ * c-decl.c (diagnose_mismatched_decls): Use
+ OPT_Wbuiltin_declaration_mismatch here too.
+
+2016-11-18 Richard Sandiford <richard.sandiford@arm.com>
+ Alan Hayward <alan.hayward@arm.com>
+ David Sherwood <david.sherwood@arm.com>
+
+ * c-decl.c (merge_decls): Use SET_DECL_MODE.
+ (make_label, finish_struct): Likewise.
+
+2016-11-14 Prasad Ghangal <prasad.ghangal@gmail.com>
+ Richard Biener <rguenther@suse.de>
+
+ * Make-lang.in (C_AND_OBJC_OBJS): Add gimple-parser.o.
+ * config-lang.in (gtfiles): Add c/c-parser.h.
+ * c-tree.h (enum c_declspec_word): Add cdw_gimple.
+ (struct c_declspecs): Add gimple_pass member and gimple_p flag.
+ * c-parser.c (enum c_id_kind, struct c_token,
+ c_parser_next_token_is, c_parser_next_token_is_not,
+ c_parser_next_token_is_keyword,
+ enum c_lookahead_kind, enum c_dtr_syn, enum c_parser_prec):
+ Split out to ...
+ * c-parser.h: ... new header.
+ * c-parser.c: Include c-parser.h and gimple-parser.h.
+ (c_parser_peek_token, c_parser_peek_2nd_token,
+ c_token_starts_typename, c_parser_next_token_starts_declspecs,
+ c_parser_next_tokens_start_declaration, c_parser_consume_token,
+ c_parser_error, c_parser_require, c_parser_skip_until_found,
+ c_parser_declspecs, c_parser_declarator, c_parser_peek_nth_token,
+ c_parser_type_name): Export.
+ (c_parser_tokens_buf): New function.
+ (c_parser_error): Likewise.
+ (c_parser_set_error): Likewise.
+ (c_parser_declspecs): Handle RID_GIMPLE.
+ (c_parser_declaration_or_fndef): Parse __GIMPLE marked body
+ via c_parser_parse_gimple_body.
+ * c-parser.h (c_parser_peek_token, c_parser_peek_2nd_token,
+ c_token_starts_typename, c_parser_next_token_starts_declspecs,
+ c_parser_next_tokens_start_declaration, c_parser_consume_token,
+ c_parser_error, c_parser_require, c_parser_skip_until_found,
+ c_parser_declspecs, c_parser_declarator, c_parser_peek_nth_token,
+ c_parser_type_name): Declare.
+ (struct c_parser): Declare forward.
+ (c_parser_tokens_buf): Declare.
+ (c_parser_error): Likewise.
+ (c_parser_set_error): Likewise.
+ * gimple-parser.c: New file.
+ * gimple-parser.h: Likewise.
+
+2016-11-13 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ PR c/35503
+ * c-parser.c (c_parser_postfix_expression_after_primary): Call
+ warn_for_restrict.
+
+2016-09-11 Le-Chun Wu <lcwu@google.com>
+ Mark Wielaard <mjw@redhat.com>
+
+ * c-decl.c (warn_if_shadowing): Use the warning code corresponding
+ to the given -Wshadow= variant.
+
+2016-10-13 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ * c-typeck.c: Include memmodel.h.
+
+2016-10-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/77957
+ * c-objc-common.h (LANG_HOOKS_GETDECLS): Use hook_tree_void_null
+ instead of lhd_return_null_tree_v.
+
+2016-10-07 Bernd Schmidt <bschmidt@redhat.com>
+
+ PR c++/69733
+ * c-decl.c (smallest_type_quals_location): New static function.
+ (grokdeclarator): Try to find the correct location for an ignored
+ qualifier.
+
+2016-09-26 Marek Polacek <polacek@redhat.com>
+
+ PR c/7652
+ * c-decl.c (pop_scope): Add gcc_fallthrough.
+
+2016-09-26 Marek Polacek <polacek@redhat.com>
+
+ PR c/7652
+ * c-parser.c (struct c_token): Add flags field.
+ (c_lex_one_token): Pass it to c_lex_with_flags.
+ (c_parser_declaration_or_fndef): Turn __attribute__((fallthrough));
+ into IFN_FALLTHROUGH.
+ (c_parser_label): Set FALLTHROUGH_LABEL_P on labels. Handle
+ attribute fallthrough after a case label or default label.
+ (c_parser_statement_after_labels): Handle RID_ATTRIBUTE.
+
+2016-09-24 Marek Polacek <polacek@redhat.com>
+
+ PR c/77490
+ * c-typeck.c (build_unary_op): Warn about bit not on expressions that
+ have boolean value. Warn about ++/-- on booleans.
+
+2016-09-23 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (incomplete_record_decls): Remove unnecessary
+ = vNULL initialization of file scope vec.
+
+2016-09-16 Marek Polacek <polacek@redhat.com>
+
+ * c-typeck.c (lvalue_p): Use true and false instead of 1 and 0.
+
+2016-09-14 Marek Polacek <polacek@redhat.com>
+
+ * c-array-notation.c (create_cmp_incr): Use false instead of 0.
+ (fix_array_notation_expr): Likewise.
+ * c-decl.c (finish_decl): Likewise.
+ * c-parser.c (c_parser_postfix_expression_after_primary): Likewise.
+ * c-typeck.c (array_to_pointer_conversion): Use true instead of 1.
+ (function_to_pointer_conversion): Use false instead of 0.
+ (convert_lvalue_to_rvalue): Likewise.
+ (parser_build_unary_op): Likewise.
+ (build_atomic_assign): Likewise.
+ (build_unary_op): Change nonconvert parameter type to bool, use
+ true/false instead of 1/0.
+ (build_binary_op): Use true instead of 1.
+
+2016-09-13 David Malcolm <dmalcolm@redhat.com>
+
+ * c-parser.c (c_parser_declaration_or_fndef): Update for renaming
+ of add_fixit_insert to add_fixit_insert_before.
+
+2016-09-13 Marek Polacek <polacek@redhat.com>
+
+ * c-typeck.c (build_unary_op): Rename FLAG parameter to NOCONVERT. Use
+ it.
+
+2016-09-12 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR c++/77496
+ * c-parser.c (c_parser_conditional_expression): Pass the rightmost
+ COMPOUND_EXPR to warn_for_omitted_condop.
+
+2016-09-07 David Malcolm <dmalcolm@redhat.com>
+
+ * c-lang.c (LANG_HOOKS_GET_SUBSTRING_LOCATION): Use
+ c_get_substring_location for this new langhook.
+
+2016-09-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/65467
+ * c-parser.c (c_parser_declspecs): Don't sorry about _Atomic if
+ flag_openmp.
+ (c_parser_omp_variable_list): Use convert_lvalue_to_rvalue
+ instead of mark_exp_read on low_bound/length expression.
+ (c_parser_omp_clause_num_gangs, c_parser_omp_clause_num_threads,
+ c_parser_omp_clause_num_tasks, c_parser_omp_clause_grainsize,
+ c_parser_omp_clause_priority, c_parser_omp_clause_hint,
+ c_parser_omp_clause_num_workers, c_parser_oacc_shape_clause,
+ c_parser_oacc_clause_tile, c_parser_omp_clause_schedule,
+ c_parser_omp_clause_vector_length, c_parser_omp_clause_num_teams,
+ c_parser_omp_clause_thread_limit, c_parser_omp_clause_aligned,
+ c_parser_omp_clause_linear, c_parser_omp_clause_safelen,
+ c_parser_omp_clause_simdlen, c_parser_omp_clause_device,
+ c_parser_omp_clause_dist_schedule): Use convert_lvalue_to_rvalue
+ instead of mark_expr_read.
+ (c_parser_omp_declare_reduction): Reject _Atomic qualified types.
+ * c-objc-common.h (LANG_HOOKS_OMP_CLAUSE_COPY_CTOR,
+ LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP): Redefine.
+ * c-tree.h (c_omp_clause_copy_ctor): New prototype.
+ * c-typeck.c (handle_omp_array_sections_1): Diagnose _Atomic qualified
+ array section bases outside of depend clause, for depend clause
+ use convert_lvalue_to_rvalue on the base.
+ (c_finish_omp_clauses): Reject _Atomic qualified vars in reduction,
+ linear, aligned, map, to and from clauses.
+ (c_omp_clause_copy_ctor): New function.
+
+2016-09-01 Marek Polacek <polacek@redhat.com>
+
+ PR c/7652
+ * c-typeck.c (composite_type): Add FALLTHRU comment.
+
+2016-08-31 David Malcolm <dmalcolm@redhat.com>
+
+ * c-parser.c (c_parser_declaration_or_fndef): Add trailing space
+ to the insertion fixits for "struct", "union", and "enum".
+
+2016-08-30 David Malcolm <dmalcolm@redhat.com>
+
+ * c-decl.c (implicit_decl_warning): Use add_fixit_replace
+ rather than add_fixit_misspelled_id.
+ (undeclared_variable): Likewise.
+ * c-parser.c (c_parser_declaration_or_fndef): Likewise. Remove
+ now-redundant "here" params from add_fixit_insert method calls.
+ (c_parser_parameter_declaration): Likewise.
+ * c-typeck.c (build_component_ref): Remove now-redundant range
+ param from add_fixit_replace method calls.
+
+2016-08-25 Marek Polacek <polacek@redhat.com>
+
+ * c-typeck.c (parser_build_binary_op): Pass LHS to
+ warn_logical_not_parentheses.
+
+2016-08-25 Marek Polacek <polacek@redhat.com>
+
+ PR c/77323
+ * c-decl.c (declspecs_add_type): Set typespec_word even when __intN
+ or _FloatN or _FloatNx is not supported.
+ (finish_declspecs): Set type to integer_type_node when _FloatN or
+ _FloatNx is not supported.
+
+2016-08-19 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/32187
+ * c-tree.h (cts_floatn_nx): New enum c_typespec_keyword value.
+ (struct c_declspecs): Add field floatn_nx_idx.
+ * c-decl.c (declspecs_add_type, finish_declspecs): Handle _FloatN
+ and _FloatNx type specifiers.
+ * c-parser.c (c_keyword_starts_typename, c_token_starts_declspecs)
+ (c_parser_declspecs, c_parser_attribute_any_word)
+ (c_parser_objc_selector): Use CASE_RID_FLOATN_NX.
+ * c-typeck.c (c_common_type): Handle _FloatN and _FloatNx types.
+ (convert_arguments): Avoid promoting _FloatN and _FloatNx types
+ narrower than double.
2016-08-12 Jakub Jelinek <jakub@redhat.com>
Martin Liska <mliska@suse.cz>
@@ -10,41 +584,331 @@
% to determine val element to change. Assert that
wchar_bytes * charwidth fits into val array.
-2016-08-11 Jakub Jelinek <jakub@redhat.com>
+2016-08-12 Marek Polacek <polacek@redhat.com>
+
+ PR c/7652
+ * c-parser.c (c_parser_external_declaration): Add FALLTHRU.
+ (c_parser_postfix_expression): Likewise.
+ * c-typeck.c (build_unary_op): Adjust fall through comment.
+ (c_mark_addressable): Likewise.
- Backported from mainline
- 2016-08-11 Jakub Jelinek <jakub@redhat.com>
+2016-08-11 Jakub Jelinek <jakub@redhat.com>
PR c/72816
* c-decl.c (grokdeclarator): When adding TYPE_DOMAIN for flexible
array member through typedef, for orig_qual_indirect == 0 clear
orig_qual_type.
+2016-08-08 David Malcolm <dmalcolm@redhat.com>
+
+ PR c/64955
+ * c-lang.c (LANG_HOOKS_RUN_LANG_SELFTESTS): If CHECKING_P, wire
+ this up to selftest::run_c_tests.
+ (selftest::run_c_tests): New function.
+
+2016-08-04 Thomas Schwinge <thomas@codesourcery.com>
+
+ * c-parser.c (struct oacc_routine_data): Add error_seen and
+ fndecl_seen members.
+ (c_finish_oacc_routine): Use these.
+ (c_parser_declaration_or_fndef): Adjust.
+ (c_parser_oacc_routine): Likewise. Support more C language
+ constructs, and improve diagnostics. Move pragma context
+ checking...
+ (c_parser_pragma): ... here.
+
+ * c-parser.c (struct oacc_routine_data): New.
+ (c_parser_declaration_or_fndef, c_parser_oacc_routine): Use it.
+ Simplify code.
+ (c_finish_oacc_routine): Likewise. Don't attach clauses to "omp
+ declare target" attribute.
+
+2016-08-01 Jan Beulich <jbeulich@suse.com>
+
+ * c-fold.c (c_fully_fold_internal): Also emit shift count
+ warnings for vector types.
+ * c-typeck.c (build_binary_op): Likewise.
+
+2016-07-29 Marek Polacek <polacek@redhat.com>
+
+ PR c/71742
+ * c-decl.c (finish_struct): Rephrase an error message.
+
+ PR c/71853
+ * c-parser.c (c_parser_switch_statement): Initialize ce.original_type
+ to error node for invalid code.
+
+ PR c/71573
+ * c-decl.c (implicitly_declare): Return decl early not only for
+ error_mark_nodes, but for anything that is not a FUNCTION_DECL.
+
+2016-07-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/71969
+ * c-decl.c (finish_function): Only set DECL_DISREGARD_INLINE_LIMITS
+ on GNU extern inline functions.
+
+2016-07-29 Marek Polacek <polacek@redhat.com>
+
+ PR c/71583
+ * c-parser.c (c_parser_postfix_expression_after_paren_type): Also
+ check expr.value.
+
+2016-07-22 Uros Bizjak <ubizjak@gmail.com>
+
+ * c-typeck.c: Use HOST_WIDE_INT_1 instead of (HOST_WIDE_INT) 1,
+
+2016-07-20 David Malcolm <dmalcolm@redhat.com>
+
+ * c-decl.c (struct edit_distance_traits<cpp_hashnode *>): Move to
+ spellcheck-tree.h
+ (best_macro_match): Likewise, converting from a typedef to a
+ subclass.
+ (find_closest_macro_cpp_cb): Move to spellcheck-tree.c.
+ (lookup_name_fuzzy): Update for change of best_macro_match to a
+ subclass with a ctor that calls cpp_forall_identifiers.
+
+2016-07-20 David Malcolm <dmalcolm@redhat.com>
+
+ * c-decl.c (implicit_decl_warning): Update for conversion of
+ return type of lookup_name_fuzzy to const char *.
+ (undeclared_variable): Likewise.
+ (lookup_name_fuzzy): Convert return type from tree to
+ const char *.
+ * c-parser.c (c_parser_declaration_or_fndef): Update for
+ conversion of return type of lookup_name_fuzzy to const char *.
+ (c_parser_parameter_declaration): Likewise.
+
+2016-07-15 Cesar Philippidis <cesar@codesourcery.com>
+
+ * c-parser.c (c_parser_oacc_declare): Don't scan for
+ GOMP_MAP_POINTER.
+ * c-typeck.c (handle_omp_array_sections): Mark data clauses with
+ GOMP_MAP_FORCE_{PRESENT,TO,FROM,TOFROM} as potentially having
+ zero-length subarrays.
+
+2016-07-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/71858
+ * c-decl.c (implicit_decl_warning): Use FUZZY_LOOKUP_FUNCTION_NAME
+ instead of FUZZY_LOOKUP_NAME.
+ (lookup_name_fuzzy): For FUZZY_LOOKUP_FUNCTION_NAME consider
+ FUNCTION_DECLs, {VAR,PARM}_DECLs function pointers and macros.
+
+2016-07-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/71858
+ * c-decl.c (lookup_name_fuzzy): Ignore binding->invisible.
+
+2016-07-12 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * c-parser.c (c_parser_generic_selection): Make type of variable
+ auto_vec.
+ (c_parser_omp_declare_simd): Likewise.
+
+2016-07-12 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * c-decl.c (struct c_struct_parse_info): Change member types
+ from vec to auto_vec.
+ (start_struct): Adjust.
+ (finish_struct): Likewise.
+
2016-07-02 Jakub Jelinek <jakub@redhat.com>
- Backported from mainline
- 2016-06-29 Jakub Jelinek <jakub@redhat.com>
+ PR c/71719
+ * c-typeck.c (mark_exp_read): Handle VIEW_CONVERT_EXPR.
+
+2016-06-29 Thomas Schwinge <thomas@codesourcery.com>
+
+ * c-parser.c (c_parser_pragma) <PRAGMA_OMP_CANCELLATION_POINT>:
+ Move pragma context checking into...
+ (c_parser_omp_cancellation_point): ... here, and improve
+ diagnostic messages.
+ * c-typeck.c (c_finish_omp_cancel)
+ (c_finish_omp_cancellation_point): Improve diagnostic messages.
+
+2016-06-29 Jakub Jelinek <jakub@redhat.com>
PR c/71685
* c-typeck.c (c_build_qualified_type): Don't clear
C_TYPE_INCOMPLETE_VARS for the main variant.
+2016-06-28 Martin Sebor <msebor@redhat.com>
+
+ PR c/71552
+ * c-typeck.c (output_init_element): Diagnose incompatible types
+ before non-constant initializers.
+
+2016-06-28 Jakub Jelinek <jakub@redhat.com>
+
+ * Make-lang.in: Don't cat ../stage_current if it does not exist.
+
+2016-06-23 Andi Kleen <ak@linux.intel.com>
+
+ * Make-lang.in: Add support for autofdo.
+
+2016-06-22 David Malcolm <dmalcolm@redhat.com>
+
+ PR c/70339
+ * c-decl.c: Include spellcheck-tree.h and gcc-rich-location.h.
+ (implicit_decl_warning): When issuing warnings for implicit
+ declarations, attempt to provide a suggestion via
+ lookup_name_fuzzy.
+ (undeclared_variable): Likewise when issuing errors.
+ (lookup_name_in_scope): Likewise.
+ (struct edit_distance_traits<cpp_hashnode *>): New struct.
+ (best_macro_match): New typedef.
+ (find_closest_macro_cpp_cb): New function.
+ (lookup_name_fuzzy): New function.
+ * c-parser.c: Include gcc-rich-location.h.
+ (c_token_starts_typename): Split out case CPP_KEYWORD into...
+ (c_keyword_starts_typename): ...this new function.
+ (c_parser_declaration_or_fndef): When issuing errors about
+ missing "struct" etc, add a fixit. For other kinds of errors,
+ attempt to provide a suggestion via lookup_name_fuzzy.
+ (c_parser_parms_declarator): When looking ahead to detect typos in
+ type names, also reject CPP_KEYWORD.
+ (c_parser_parameter_declaration): When issuing errors about
+ unknown type names, attempt to provide a suggestion via
+ lookup_name_fuzzy.
+ * c-tree.h (c_keyword_starts_typename): New prototype.
+
+2016-06-20 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/71601
+ * c-typeck.c (build_conditional_expr): Return error_mark_node if
+ c_common_type returns error_mark_node.
+
+2016-06-19 Martin Sebor <msebor@redhat.com>
+
+ PR c/69507
+ * c-parser.c (c_parser_alignof_expression): Avoid diagnosing
+ __alignof__ (expression).
+
+2016-06-14 David Malcolm <dmalcolm@redhat.com>
+
+ * c-typeck.c: Include spellcheck-tree.h rather than spellcheck.h.
+
+2016-06-14 David Malcolm <dmalcolm@redhat.com>
+
+ * c-typeck.c (build_component_ref): Simplify fixit code by
+ using gcc_rich_location::add_fixit_misspelled_id.
+ (set_init_label): Likewise.
+
+2016-06-13 David Malcolm <dmalcolm@redhat.com>
+
+ * c-parser.c (c_parser_initelt): Provide location of name for new
+ location_t param of set_init_label.
+ * c-tree.h (set_init_label): Add location_t param.
+ * c-typeck.c (set_init_index): Add "fieldname_loc" location_t
+ param and use it when issuing error messages about unrecognized
+ field names. Attempt to provide a fixit hint if appropriate,
+ otherwise update the error message to provide the type name.
+
2016-06-10 Thomas Schwinge <thomas@codesourcery.com>
PR c/71381
- Backport from trunk r237290:
* c-parser.c (c_parser_omp_variable_list) <OMP_CLAUSE__CACHE_>:
Loosen checking.
+2016-06-08 Martin Sebor <msebor@redhat.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/70507
+ PR c/68120
+ * c-typeck.c (convert_arguments): Don't promote last argument
+ of BUILT_IN_{ADD,SUB,MUL}_OVERFLOW_P.
+
+2016-06-08 Marek Polacek <polacek@redhat.com>
+
+ PR c/71418
+ * c-decl.c (grokdeclarator): Check TYPE_P.
+
+ PR c/71426
+ * c-decl.c (get_parm_info): Don't crash on an assert on invalid
+ code.
+
+2016-06-07 David Malcolm <dmalcolm@redhat.com>
+
+ * c-parser.c (c_parser_postfix_expression): In __builtin_offsetof
+ and structure element reference, capture the location of the
+ element name token and pass it to build_component_ref.
+ (c_parser_postfix_expression_after_primary): Likewise for
+ structure element dereference.
+ (c_parser_omp_variable_list): Likewise for
+ OMP_CLAUSE_{_CACHE, MAP, FROM, TO},
+ * c-tree.h (build_component_ref): Add location_t param.
+ * c-typeck.c (build_component_ref): Add location_t param
+ COMPONENT_LOC. Use it, if available, when issuing hints about
+ mispelled member names to provide a fixit replacement hint.
+
+2016-06-06 Marek Polacek <polacek@redhat.com>
+
+ PR c/71362
+ * c-parser.c (c_parser_direct_declarator): Set location.
+
+2016-06-06 Marek Polacek <polacek@redhat.com>
+
+ * c-typeck.c (comptypes_internal): Handle comparisons of
+ INTEGER_TYPE, FIXED_POINT_TYPE, and REAL_TYPE nodes. Don't check
+ TYPE_REF_CAN_ALIAS_ALL.
+
+2016-06-03 Chung-Lin Tang <cltang@codesourcery.com>
+
+ * c-typeck.c (c_finish_omp_clauses): Mark OpenACC reduction
+ arguments as addressable when async clause exists.
+
2016-05-30 Jakub Jelinek <jakub@redhat.com>
PR c++/71349
* c-parser.c (c_parser_omp_for): Don't disallow nowait clause
when combined with target construct.
+2016-05-26 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_clause_schedule): Warn if
+ OMP_CLAUSE_SCHEDULE_CHUNK_EXPR is known not to be positive.
+
+2016-05-25 Marek Polacek <polacek@redhat.com>
+
+ PR c/71265
+ * c-decl.c (c_make_fname_decl): Don't check seen_error.
+
+ PR c/71266
+ * c-decl.c (store_parm_decls_oldstyle): Skip non-PARM_DECLs.
+
+2016-05-24 Cesar Philippidis <cesar@codesourcery.com>
+
+ * c-parser.c (c_parser_oacc_declare): Add support for
+ GOMP_MAP_FIRSTPRIVATE_POINTER.
+ * c-typeck.c (handle_omp_array_sections_1): Replace bool is_omp
+ argument with enum c_omp_region_type ort.
+ (handle_omp_array_sections): Likewise. Update call to
+ handle_omp_array_sections_1.
+ (c_finish_omp_clauses): Add specific errors and warning messages for
+ OpenACC. Use firsrtprivate pointers for OpenACC subarrays. Update
+ call to handle_omp_array_sections.
+
+2016-05-24 Thomas Schwinge <thomas@codesourcery.com>
+
+ * c-parser.c (c_parser_oacc_routine): Tighten syntax checks.
+
+2016-05-24 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/70434
+ PR c/69504
+ * c-typeck.c (build_array_ref): Do not complain about indexing
+ non-lvalue vectors. Adjust for function name change.
+
+2016-05-20 Martin Sebor <msebor@redhat.com>
+
+ PR c/71115
+ * c-typeck.c (error_init): Use
+ expansion_point_location_if_in_system_header.
+ (warning_init): Same.
+
2016-05-19 David Malcolm <dmalcolm@redhat.com>
- Backport from trunk r236488.
PR c/71171
* c-parser.c (c_parser_generic_selection): Use c_expr::set_error
in error-handling.
@@ -53,6 +917,114 @@
* c-typeck.c (parser_build_binary_op): In error-handling, ensure
that result's range is initialized.
+2016-05-17 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * c-typeck.c (parser_build_unary_op): Fix formatting.
+
+2016-05-16 Matthew Wahab <matthew.wahab@arm.com>
+
+ * c-decl.c (grokdeclarator): Remove errmsg and use of
+ targetm.invalid_return_type.
+ (grokparms): Remove errmsg and use of
+ targetm.invalid_parameter_type.
+
+2016-05-13 Joseph Myers <joseph@codesourcery.com>
+
+ * c-decl.c (grokdeclarator): For C11, discard qualifiers on
+ function return type.
+
+2016-05-12 Marek Polacek <polacek@redhat.com>
+
+ PR c/70756
+ * c-decl.c (build_compound_literal): Pass LOC down to
+ c_incomplete_type_error.
+ * c-tree.h (require_complete_type): Adjust declaration.
+ (c_incomplete_type_error): Likewise.
+ * c-typeck.c (require_complete_type): Add location parameter, pass it
+ down to c_incomplete_type_error.
+ (c_incomplete_type_error): Add location parameter, pass it down to
+ error_at.
+ (build_component_ref): Pass location down to c_incomplete_type_error.
+ (default_conversion): Pass location down to require_complete_type.
+ (build_array_ref): Likewise.
+ (build_function_call_vec): Likewise.
+ (convert_arguments): Likewise.
+ (build_unary_op): Likewise.
+ (build_c_cast): Likewise.
+ (build_modify_expr): Likewise.
+ (convert_for_assignment): Likewise.
+ (c_finish_omp_clauses): Likewise.
+
+2016-05-11 Mikhail Maltsev <maltsevm@gmail.com>
+
+ PR c/43651
+ * c-decl.c (declspecs_add_qual): Warn when -Wduplicate-decl-specifier
+ is enabled.
+ * c-errors.c (pedwarn_c90): Return true if warned.
+ * c-tree.h (pedwarn_c90): Change return type to bool.
+ (enum c_declspec_word): Add new enumerator cdw_atomic.
+
+2016-05-11 Marek Polacek <polacek@redhat.com>
+
+ PR c++/71024
+ * c-decl.c (diagnose_mismatched_decls): Factor out code to
+ diagnose_mismatched_attributes and call it.
+
+2016-05-10 Marek Polacek <polacek@redhat.com>
+
+ PR c/70255
+ * c-decl.c (diagnose_mismatched_decls): Warn for optimize attribute
+ on a declaration following the definition.
+
+2016-05-05 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_switch_statement): Add IF_P argument,
+ parse it through to c_parser_c99_block_statement.
+ (c_parser_statement_after_labels): Adjust c_parser_switch_statement
+ caller.
+
+2016-05-04 Marek Polacek <polacek@redhat.com>
+
+ * c-parser.c (c_parser_if_statement): Replace OPT_Wparentheses with
+ OPT_Wdangling_else.
+
+2016-05-04 Marek Polacek <polacek@redhat.com>
+
+ PR c/48778
+ * c-typeck.c (build_binary_op): Don't issue -Waddress warnings
+ for macro expansions.
+
+2016-05-03 Marek Polacek <polacek@redhat.com>
+
+ PR c/70859
+ * c-typeck.c (build_function_call_vec): Pass LOC and ARG_LOC down to
+ check_builtin_function_arguments.
+
+2016-05-03 Richard Biener <rguenther@suse.de>
+
+ * Make-lang.in (cc1-checksum.c): For stage-final re-use
+ the checksum from the previous stage.
+
+2016-05-02 Cesar Philippidis <cesar@codesourcery.com>
+
+ * c-parser.c (c_parser_oacc_all_clauses): Update call to
+ c_finish_omp_clauses.
+ (c_parser_omp_all_clauses): Likewise.
+ (c_parser_oacc_cache): Likewise.
+ (c_parser_oacc_loop): Likewise.
+ (omp_split_clauses): Likewise.
+ (c_parser_omp_declare_target): Likewise.
+ (c_parser_cilk_all_clauses): Likewise.
+ (c_parser_cilk_for): Likewise.
+ * c-typeck.c (c_finish_omp_clauses): Replace bool arguments
+ is_omp, declare_simd, and is_cilk with enum c_omp_region_type ort.
+
+2016-05-02 Marek Polacek <polacek@redhat.com>
+
+ PR c/70851
+ * c-decl.c (grokdeclarator): Diagnose when array's size has an
+ incomplete type.
+
2016-04-29 Cesar Philippidis <cesar@codesourcery.com>
PR middle-end/70626
@@ -61,9 +1033,42 @@
(c_parser_oacc_kernels_parallel): Update call to
c_oacc_split_loop_clauses.
-2016-04-27 Release Manager
+2016-04-28 Andrew MacLeod <amacleod@redhat.com>
+
+ * c-array-notation.c (fix_builtin_array_notation_fn): Fix final
+ argument to build_modify_expr in two cases.
+
+2016-04-27 Bernd Schmidt <bschmidt@redhat.com>
+
+ * c-parser.c (c_parser_postfix_expression_after_primary): Call
+ warn_for_memset instead of warning directly here.
+
+2016-04-26 Marek Polacek <polacek@redhat.com>
+
+ PR c/67784
+ * c-parser.c (c_parser_maybe_reclassify_token): New function factored
+ out of ...
+ (c_parser_for_statement): ... here.
+ (c_parser_if_statement): Use it.
+ (c_parser_switch_statement): Use it.
+ (c_parser_while_statement): Use it.
+
+ PR c/70791
+ * c-decl.c (pushdecl): Pass LOCUS down to warning.
+
+2016-04-20 Ilya Verbin <ilya.verbin@intel.com>
+
+ PR c++/69363
+ * c-parser.c (c_parser_cilk_all_clauses): Use c_finish_omp_clauses
+ instead of c_finish_cilk_clauses.
+ * c-tree.h (c_finish_omp_clauses): Add new default argument.
+ * c-typeck.c (c_finish_omp_clauses): Add new argument. Allow
+ floating-point variables in the linear clause for Cilk Plus.
+
+2016-04-18 Michael Matz <matz@suse.de>
- * GCC 6.1.0 released.
+ * c-decl.c (merge_decls): Use SET_DECL_ALIGN and SET_TYPE_ALIGN.
+ (grokdeclarator, parser_xref_tag, finish_enum): Use SET_TYPE_ALIGN.
2016-04-15 Marek Polacek <polacek@redhat.com>
@@ -1523,16 +2528,16 @@
* c-typeck.c (build_array_ref): Pass loc down to
warn_array_subscript_with_type_char.
-2014-12-20 Martin Uecker <uecker@eecs.berkeley.edu>
+2014-12-20 Martin Uecker <uecker@eecs.berkeley.edu>
* c-typeck.c: New behavious for pointers to arrays with qualifiers
- (common-pointer-type): For pointers to arrays take qualifiers from
+ (common-pointer-type): For pointers to arrays take qualifiers from
element type.
- (build_conditional_expr): Add warnings for lost qualifiers.
+ (build_conditional_expr): Add warnings for lost qualifiers.
(comp-target-types): Allow pointers to arrays with different qualifiers.
- (convert-for-assignment): Adapt warnings for discarded qualifiers. Add
+ (convert-for-assignment): Adapt warnings for discarded qualifiers. Add
WARNING_FOR_QUALIFIERS macro and rename WARN_FOR_QUALIFIERS
- to PEDWARN_FOR_QUALIFIERS.
+ to PEDWARN_FOR_QUALIFIERS.
2014-12-17 Jakub Jelinek <jakub@redhat.com>
@@ -1705,9 +2710,9 @@
2014-10-13 Anthony Brandon <anthony.brandon@gmail.com>
- * c-parser.c (c_parser_all_labels): New function to replace
+ * c-parser.c (c_parser_all_labels): New function to replace
the duplicate code.
- (c_parser_statement): Call the new function.
+ (c_parser_statement): Call the new function.
2014-10-09 Marek Polacek <polacek@redhat.com>
@@ -1845,7 +2850,7 @@
Likewise.
(c_parser_postfix_expression) <case RID_C99_FUNCTION_NAME>: Likewise.
-2014-08-10 Marek Polacek <polacek@redhat.com>
+2014-08-10 Marek Polacek <polacek@redhat.com>
PR c/51849
* c-decl.c (build_array_declarator): Remove check for !flag_isoc99.
@@ -1932,7 +2937,7 @@
function parameter.
2014-07-02 Jan Hubicka <hubicka@ucw.cz>
- Chen Gang <gang.chen.5i5j@gmail.com>
+ Chen Gang <gang.chen.5i5j@gmail.com>
* c-decl.c (duplicate_decls): CLear DECL_STRUCT_FUNCTION before
releasing symbol.
@@ -3441,7 +4446,7 @@
* c-decl.c: Likewise. Include gt-c-c-decl.h, not gt-c-decl.h.
* c-parser.c: Likewise. Include gt-c-c-parser.h, not gt-c-parser.h.
-Copyright (C) 2012-2016 Free Software Foundation, Inc.
+Copyright (C) 2012-2017 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
diff --git a/gcc/c/Make-lang.in b/gcc/c/Make-lang.in
index 8525707f99..cfd8cd2b16 100644
--- a/gcc/c/Make-lang.in
+++ b/gcc/c/Make-lang.in
@@ -1,5 +1,5 @@
# Top level -*- makefile -*- fragment for GNU C - C language.
-# Copyright (C) 1994-2016 Free Software Foundation, Inc.
+# Copyright (C) 1994-2017 Free Software Foundation, Inc.
#This file is part of GCC.
@@ -51,7 +51,8 @@ CFLAGS-c/gccspec.o += $(DRIVER_DEFINES)
# Language-specific object files for C and Objective C.
C_AND_OBJC_OBJS = attribs.o c/c-errors.o c/c-decl.o c/c-typeck.o \
c/c-convert.o c/c-aux-info.o c/c-objc-common.o c/c-parser.o \
- c/c-array-notation.o c/c-fold.o $(C_COMMON_OBJS) $(C_TARGET_OBJS)
+ c/c-array-notation.o c/c-fold.o c/gimple-parser.o \
+ $(C_COMMON_OBJS) $(C_TARGET_OBJS)
# Language-specific object files for C.
C_OBJS = c/c-lang.o c-family/stub-objc.o $(C_AND_OBJC_OBJS)
@@ -60,16 +61,33 @@ c_OBJS = $(C_OBJS) cc1-checksum.o c/gccspec.o
# Use strict warnings for this front end.
c-warn = $(STRICT_WARN)
+ifeq ($(if $(wildcard ../stage_current),$(shell cat \
+ ../stage_current)),stageautofeedback)
+$(C_OBJS): ALL_COMPILERFLAGS += -fauto-profile=cc1.fda
+$(C_OBJS): cc1.fda
+endif
+
# compute checksum over all object files and the options
+# re-use the checksum from the prev-final stage so it passes
+# the bootstrap comparison and allows comparing of the cc1 binary
cc1-checksum.c : build/genchecksum$(build_exeext) checksum-options \
$(C_OBJS) $(BACKEND) $(LIBDEPS)
- build/genchecksum$(build_exeext) $(C_OBJS) $(BACKEND) $(LIBDEPS) \
+ if [ -f ../stage_final ] \
+ && cmp -s ../stage_current ../stage_final; then \
+ cp ../prev-gcc/cc1-checksum.c cc1-checksum.c; \
+ else \
+ build/genchecksum$(build_exeext) $(C_OBJS) $(BACKEND) $(LIBDEPS) \
checksum-options > cc1-checksum.c.tmp && \
- $(srcdir)/../move-if-change cc1-checksum.c.tmp cc1-checksum.c
+ $(srcdir)/../move-if-change cc1-checksum.c.tmp cc1-checksum.c; \
+ fi
cc1$(exeext): $(C_OBJS) cc1-checksum.o $(BACKEND) $(LIBDEPS)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) \
cc1-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
+
+cc1.fda: ../stage1-gcc/cc1$(exeext) ../prev-gcc/$(PERF_DATA)
+ $(CREATE_GCOV) -binary ../stage1-gcc/cc1$(exeext) -gcov cc1.fda -profile ../prev-gcc/$(PERF_DATA) -gcov_version 1
+
#
# Build hooks:
@@ -119,6 +137,7 @@ c.mostlyclean:
-rm -f cc1$(exeext)
-rm -f c/*$(objext)
-rm -f c/*$(coverageexts)
+ -rm -f cc1.fda
c.clean:
c.distclean:
-rm -f c/config.status c/Makefile
@@ -139,3 +158,7 @@ c.stageprofile: stageprofile-start
-mv c/*$(objext) stageprofile/c
c.stagefeedback: stagefeedback-start
-mv c/*$(objext) stagefeedback/c
+c.autostageprofile: autostageprofile-start
+ -mv c/*$(objext) autostageprofile/c
+c.autostagefeedback: autostagefeedback-start
+ -mv c/*$(objext) autostagefeedback/c
diff --git a/gcc/c/c-array-notation.c b/gcc/c/c-array-notation.c
index 716bd119ff..e430f5c681 100644
--- a/gcc/c/c-array-notation.c
+++ b/gcc/c/c-array-notation.c
@@ -1,7 +1,7 @@
/* This file is part of the Intel(R) Cilk(TM) Plus support
This file contains routines to handle Array Notation expression
handling routines in the C Compiler.
- Copyright (C) 2013-2016 Free Software Foundation, Inc.
+ Copyright (C) 2013-2017 Free Software Foundation, Inc.
Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
Intel Corporation.
@@ -26,7 +26,7 @@
An array notation expression has 4 major components:
1. The array name
2. Start Index
- 3. Number of elements we need to acess (we call it length)
+ 3. Number of elements we need to access (we call it length)
4. Stride
For example, A[0:5:2], implies that we are accessing A[0], A[2], A[4],
@@ -104,7 +104,7 @@ create_cmp_incr (location_t loc, vec<an_loop_parts> *node, size_t rank,
{
tree var = (*node)[ii].var;
tree length = an_info[0][ii].length;
- (*node)[ii].incr = build_unary_op (loc, POSTINCREMENT_EXPR, var, 0);
+ (*node)[ii].incr = build_unary_op (loc, POSTINCREMENT_EXPR, var, false);
(*node)[ii].cmp = build2 (LT_EXPR, boolean_type_node, var, length);
}
}
@@ -489,7 +489,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
new_yes_expr = build_modify_expr
(location, array_ind_value, TREE_TYPE (array_ind_value),
NOP_EXPR,
- location, func_parm, TREE_OPERAND (array_op0, 1));
+ location, func_parm, TREE_TYPE (TREE_OPERAND (array_op0, 1)));
}
new_yes_list = alloc_stmt_list ();
append_to_statement_list (new_yes_ind, &new_yes_list);
@@ -539,7 +539,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
new_yes_expr = build_modify_expr
(location, array_ind_value, TREE_TYPE (array_ind_value),
NOP_EXPR,
- location, func_parm, TREE_OPERAND (array_op0, 1));
+ location, func_parm, TREE_TYPE (TREE_OPERAND (array_op0, 1)));
}
new_yes_list = alloc_stmt_list ();
append_to_statement_list (new_yes_ind, &new_yes_list);
@@ -1088,7 +1088,7 @@ fix_array_notation_expr (location_t location, enum tree_code code,
arg = default_function_array_read_conversion (location, arg);
if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
- arg.value = build_unary_op (location, code, arg.value, 0);
+ arg.value = build_unary_op (location, code, arg.value, false);
else if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
arg = parser_build_unary_op (location, code, arg);
diff --git a/gcc/c/c-aux-info.c b/gcc/c/c-aux-info.c
index f69c04369c..a7928f4375 100644
--- a/gcc/c/c-aux-info.c
+++ b/gcc/c/c-aux-info.c
@@ -1,7 +1,7 @@
/* Generate information regarding function declarations and definitions based
on information stored in GCC's tree structure. This code implements the
-aux-info option.
- Copyright (C) 1989-2016 Free Software Foundation, Inc.
+ Copyright (C) 1989-2017 Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@segfault.us.com).
This file is part of GCC.
diff --git a/gcc/c/c-convert.c b/gcc/c/c-convert.c
index 4167c3461f..163feff837 100644
--- a/gcc/c/c-convert.c
+++ b/gcc/c/c-convert.c
@@ -1,5 +1,5 @@
/* Language-level data type conversion for GNU C.
- Copyright (C) 1987-2016 Free Software Foundation, Inc.
+ Copyright (C) 1987-2017 Free Software Foundation, Inc.
This file is part of GCC.
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index b237e93b92..53c390c9e4 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -1,5 +1,5 @@
/* Process declarations and variables for C compiler.
- Copyright (C) 1988-2016 Free Software Foundation, Inc.
+ Copyright (C) 1988-2017 Free Software Foundation, Inc.
This file is part of GCC.
@@ -51,6 +51,8 @@ along with GCC; see the file COPYING3. If not see
#include "c-family/c-ada-spec.h"
#include "cilk.h"
#include "builtins.h"
+#include "spellcheck-tree.h"
+#include "gcc-rich-location.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
@@ -572,15 +574,15 @@ struct c_struct_parse_info
{
/* If warn_cxx_compat, a list of types defined within this
struct. */
- vec<tree> struct_types;
+ auto_vec<tree> struct_types;
/* If warn_cxx_compat, a list of field names which have bindings,
and which are defined in this struct, but which are not defined
in any enclosing struct. This is used to clear the in_struct
field of the c_bindings structure. */
- vec<c_binding_ptr> fields;
+ auto_vec<c_binding_ptr> fields;
/* If warn_cxx_compat, a list of typedef names used when defining
fields in this struct. */
- vec<tree> typedefs_seen;
+ auto_vec<tree> typedefs_seen;
};
/* Information for the struct or union currently being parsed, or
@@ -1175,7 +1177,8 @@ pop_scope (void)
context = current_function_decl;
else if (scope == file_scope)
{
- tree file_decl = build_translation_unit_decl (NULL_TREE);
+ tree file_decl
+ = build_translation_unit_decl (get_identifier (main_input_filename));
context = file_decl;
debug_hooks->register_main_translation_unit (file_decl);
}
@@ -1326,7 +1329,7 @@ pop_scope (void)
set_type_context (TREE_TYPE (p), context);
}
- /* Fall through. */
+ gcc_fallthrough ();
/* Parameters go in DECL_ARGUMENTS, not BLOCK_VARS, and have
already been put there by store_parm_decls. Unused-
parameter warnings are handled by function.c.
@@ -1418,6 +1421,8 @@ pop_file_scope (void)
if (pch_file)
{
c_common_write_pch ();
+ /* Ensure even the callers don't try to finalize the CU. */
+ flag_syntax_only = 1;
return;
}
@@ -1865,7 +1870,8 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
/* If types don't match for a built-in, throw away the
built-in. No point in calling locate_old_decl here, it
won't print anything. */
- warning (0, "conflicting types for built-in function %q+D",
+ warning (OPT_Wbuiltin_declaration_mismatch,
+ "conflicting types for built-in function %q+D",
newdecl);
return false;
}
@@ -2227,43 +2233,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
- {
- /* Diagnose inline __attribute__ ((noinline)) which is silly. */
- if (DECL_DECLARED_INLINE_P (newdecl)
- && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
- warned |= warning (OPT_Wattributes,
- "inline declaration of %qD follows "
- "declaration with attribute noinline", newdecl);
- else if (DECL_DECLARED_INLINE_P (olddecl)
- && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
- warned |= warning (OPT_Wattributes,
- "declaration of %q+D with attribute "
- "noinline follows inline declaration ", newdecl);
- else if (lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl))
- && lookup_attribute ("always_inline", DECL_ATTRIBUTES (olddecl)))
- warned |= warning (OPT_Wattributes,
- "declaration of %q+D with attribute "
- "%qs follows declaration with attribute %qs",
- newdecl, "noinline", "always_inline");
- else if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (newdecl))
- && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
- warned |= warning (OPT_Wattributes,
- "declaration of %q+D with attribute "
- "%qs follows declaration with attribute %qs",
- newdecl, "always_inline", "noinline");
- else if (lookup_attribute ("cold", DECL_ATTRIBUTES (newdecl))
- && lookup_attribute ("hot", DECL_ATTRIBUTES (olddecl)))
- warned |= warning (OPT_Wattributes,
- "declaration of %q+D with attribute %qs follows "
- "declaration with attribute %qs", newdecl, "cold",
- "hot");
- else if (lookup_attribute ("hot", DECL_ATTRIBUTES (newdecl))
- && lookup_attribute ("cold", DECL_ATTRIBUTES (olddecl)))
- warned |= warning (OPT_Wattributes,
- "declaration of %q+D with attribute %qs follows "
- "declaration with attribute %qs", newdecl, "hot",
- "cold");
- }
+ warned |= diagnose_mismatched_attributes (olddecl, newdecl);
else /* PARM_DECL, VAR_DECL */
{
/* Redeclaration of a parameter is a constraint violation (this is
@@ -2369,7 +2339,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
if (TYPE_USER_ALIGN (tem))
{
if (TYPE_ALIGN (tem) > TYPE_ALIGN (newtype))
- TYPE_ALIGN (newtype) = TYPE_ALIGN (tem);
+ SET_TYPE_ALIGN (newtype, TYPE_ALIGN (tem));
TYPE_USER_ALIGN (newtype) = true;
}
@@ -2407,10 +2377,10 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
/* Since the type is OLDDECL's, make OLDDECL's size go with. */
DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
- DECL_MODE (newdecl) = DECL_MODE (olddecl);
+ SET_DECL_MODE (newdecl, DECL_MODE (olddecl));
if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
{
- DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
+ SET_DECL_ALIGN (newdecl, DECL_ALIGN (olddecl));
DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl);
}
}
@@ -2769,7 +2739,9 @@ warn_if_shadowing (tree new_decl)
struct c_binding *b;
/* Shadow warnings wanted? */
- if (!warn_shadow
+ if (!(warn_shadow
+ || warn_shadow_local
+ || warn_shadow_compatible_local)
/* No shadow warnings for internally generated vars. */
|| DECL_IS_BUILTIN (new_decl)
/* No shadow warnings for vars made for inlining. */
@@ -2793,9 +2765,23 @@ warn_if_shadowing (tree new_decl)
break;
}
else if (TREE_CODE (old_decl) == PARM_DECL)
- warned = warning (OPT_Wshadow,
- "declaration of %q+D shadows a parameter",
- new_decl);
+ {
+ enum opt_code warning_code;
+
+ /* If '-Wshadow=compatible-local' is specified without other
+ -Wshadow= flags, we will warn only when the types of the
+ shadowing variable (i.e. new_decl) and the shadowed variable
+ (old_decl) are compatible. */
+ if (warn_shadow)
+ warning_code = OPT_Wshadow;
+ else if (comptypes (TREE_TYPE (old_decl), TREE_TYPE (new_decl)))
+ warning_code = OPT_Wshadow_compatible_local;
+ else
+ warning_code = OPT_Wshadow_local;
+ warned = warning_at (DECL_SOURCE_LOCATION (new_decl), warning_code,
+ "declaration of %qD shadows a parameter",
+ new_decl);
+ }
else if (DECL_FILE_SCOPE_P (old_decl))
{
/* Do not warn if a variable shadows a function, unless
@@ -2818,8 +2804,23 @@ warn_if_shadowing (tree new_decl)
break;
}
else
- warned = warning (OPT_Wshadow, "declaration of %q+D shadows a "
- "previous local", new_decl);
+ {
+ enum opt_code warning_code;
+
+ /* If '-Wshadow=compatible-local' is specified without other
+ -Wshadow= flags, we will warn only when the types of the
+ shadowing variable (i.e. new_decl) and the shadowed variable
+ (old_decl) are compatible. */
+ if (warn_shadow)
+ warning_code = OPT_Wshadow;
+ else if (comptypes (TREE_TYPE (old_decl), TREE_TYPE (new_decl)))
+ warning_code = OPT_Wshadow_compatible_local;
+ else
+ warning_code = OPT_Wshadow_local;
+ warned = warning_at (DECL_SOURCE_LOCATION (new_decl), warning_code,
+ "declaration of %qD shadows a previous local",
+ new_decl);
+ }
if (warned)
inform (DECL_SOURCE_LOCATION (old_decl),
@@ -2949,7 +2950,8 @@ pushdecl (tree x)
}
if (scope != file_scope
&& !DECL_IN_SYSTEM_HEADER (x))
- warning (OPT_Wnested_externs, "nested extern declaration of %qD", x);
+ warning_at (locus, OPT_Wnested_externs,
+ "nested extern declaration of %qD", x);
while (b && !B_IN_EXTERNAL_SCOPE (b))
{
@@ -3115,22 +3117,52 @@ pushdecl_top_level (tree x)
return x;
}
+
+/* Issue a warning about implicit function declaration. ID is the function
+ identifier, OLDDECL is a declaration of the function in a different scope,
+ or NULL_TREE. */
+
static void
implicit_decl_warning (location_t loc, tree id, tree olddecl)
{
- if (warn_implicit_function_declaration)
- {
- bool warned;
+ if (!warn_implicit_function_declaration)
+ return;
- if (flag_isoc99)
+ bool warned;
+ const char *hint = NULL;
+ if (!olddecl)
+ hint = lookup_name_fuzzy (id, FUZZY_LOOKUP_FUNCTION_NAME);
+
+ if (flag_isoc99)
+ {
+ if (hint)
+ {
+ gcc_rich_location richloc (loc);
+ richloc.add_fixit_replace (hint);
+ warned = pedwarn_at_rich_loc
+ (&richloc, OPT_Wimplicit_function_declaration,
+ "implicit declaration of function %qE; did you mean %qs?",
+ id, hint);
+ }
+ else
warned = pedwarn (loc, OPT_Wimplicit_function_declaration,
"implicit declaration of function %qE", id);
- else
- warned = warning_at (loc, OPT_Wimplicit_function_declaration,
- G_("implicit declaration of function %qE"), id);
- if (olddecl && warned)
- locate_old_decl (olddecl);
}
+ else if (hint)
+ {
+ gcc_rich_location richloc (loc);
+ richloc.add_fixit_replace (hint);
+ warned = warning_at_rich_loc
+ (&richloc, OPT_Wimplicit_function_declaration,
+ G_("implicit declaration of function %qE; did you mean %qs?"),
+ id, hint);
+ }
+ else
+ warned = warning_at (loc, OPT_Wimplicit_function_declaration,
+ G_("implicit declaration of function %qE"), id);
+
+ if (olddecl && warned)
+ locate_old_decl (olddecl);
}
/* This function represents mapping of a function code FCODE
@@ -3337,7 +3369,7 @@ implicitly_declare (location_t loc, tree functionid)
if (decl)
{
- if (decl == error_mark_node)
+ if (TREE_CODE (decl) != FUNCTION_DECL)
return decl;
/* FIXME: Objective-C has weird not-really-builtin functions
@@ -3443,13 +3475,38 @@ undeclared_variable (location_t loc, tree id)
if (current_function_decl == 0)
{
- error_at (loc, "%qE undeclared here (not in a function)", id);
+ const char *guessed_id = lookup_name_fuzzy (id, FUZZY_LOOKUP_NAME);
+ if (guessed_id)
+ {
+ gcc_rich_location richloc (loc);
+ richloc.add_fixit_replace (guessed_id);
+ error_at_rich_loc (&richloc,
+ "%qE undeclared here (not in a function);"
+ " did you mean %qs?",
+ id, guessed_id);
+ }
+ else
+ error_at (loc, "%qE undeclared here (not in a function)", id);
scope = current_scope;
}
else
{
if (!objc_diagnose_private_ivar (id))
- error_at (loc, "%qE undeclared (first use in this function)", id);
+ {
+ const char *guessed_id = lookup_name_fuzzy (id, FUZZY_LOOKUP_NAME);
+ if (guessed_id)
+ {
+ gcc_rich_location richloc (loc);
+ richloc.add_fixit_replace (guessed_id);
+ error_at_rich_loc
+ (&richloc,
+ "%qE undeclared (first use in this function);"
+ " did you mean %qs?",
+ id, guessed_id);
+ }
+ else
+ error_at (loc, "%qE undeclared (first use in this function)", id);
+ }
if (!already)
{
inform (loc, "each undeclared identifier is reported only"
@@ -3475,7 +3532,7 @@ make_label (location_t location, tree name, bool defining,
{
tree label = build_decl (location, LABEL_DECL, name, void_type_node);
DECL_CONTEXT (label) = current_function_decl;
- DECL_MODE (label) = VOIDmode;
+ SET_DECL_MODE (label, VOIDmode);
c_label_vars *label_vars = ggc_alloc<c_label_vars> ();
label_vars->shadowed = NULL;
@@ -3939,6 +3996,119 @@ lookup_name_in_scope (tree name, struct c_scope *scope)
return b->decl;
return NULL_TREE;
}
+
+/* Look for the closest match for NAME within the currently valid
+ scopes.
+
+ This finds the identifier with the lowest Levenshtein distance to
+ NAME. If there are multiple candidates with equal minimal distance,
+ the first one found is returned. Scopes are searched from innermost
+ outwards, and within a scope in reverse order of declaration, thus
+ benefiting candidates "near" to the current scope.
+
+ The function also looks for similar macro names to NAME, since a
+ misspelled macro name will not be expanded, and hence looks like an
+ identifier to the C frontend.
+
+ It also looks for start_typename keywords, to detect "singed" vs "signed"
+ typos. */
+
+const char *
+lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind)
+{
+ gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
+
+ best_match<tree, tree> bm (name);
+
+ /* Look within currently valid scopes. */
+ for (c_scope *scope = current_scope; scope; scope = scope->outer)
+ for (c_binding *binding = scope->bindings; binding; binding = binding->prev)
+ {
+ if (!binding->id || binding->invisible)
+ continue;
+ /* Don't use bindings from implicitly declared functions,
+ as they were likely misspellings themselves. */
+ if (TREE_CODE (binding->decl) == FUNCTION_DECL)
+ if (C_DECL_IMPLICIT (binding->decl))
+ continue;
+ switch (kind)
+ {
+ case FUZZY_LOOKUP_TYPENAME:
+ if (TREE_CODE (binding->decl) != TYPE_DECL)
+ continue;
+ break;
+
+ case FUZZY_LOOKUP_FUNCTION_NAME:
+ if (TREE_CODE (binding->decl) != FUNCTION_DECL)
+ {
+ /* Allow function pointers. */
+ if ((VAR_P (binding->decl)
+ || TREE_CODE (binding->decl) == PARM_DECL)
+ && TREE_CODE (TREE_TYPE (binding->decl)) == POINTER_TYPE
+ && (TREE_CODE (TREE_TYPE (TREE_TYPE (binding->decl)))
+ == FUNCTION_TYPE))
+ break;
+ continue;
+ }
+ break;
+
+ default:
+ break;
+ }
+ bm.consider (binding->id);
+ }
+
+ /* Consider macros: if the user misspelled a macro name e.g. "SOME_MACRO"
+ as:
+ x = SOME_OTHER_MACRO (y);
+ then "SOME_OTHER_MACRO" will survive to the frontend and show up
+ as a misspelled identifier.
+
+ Use the best distance so far so that a candidate is only set if
+ a macro is better than anything so far. This allows early rejection
+ (without calculating the edit distance) of macro names that must have
+ distance >= bm.get_best_distance (), and means that we only get a
+ non-NULL result for best_macro_match if it's better than any of
+ the identifiers already checked, which avoids needless creation
+ of identifiers for macro hashnodes. */
+ best_macro_match bmm (name, bm.get_best_distance (), parse_in);
+ cpp_hashnode *best_macro = bmm.get_best_meaningful_candidate ();
+ /* If a macro is the closest so far to NAME, use it, creating an
+ identifier tree node for it. */
+ if (best_macro)
+ {
+ const char *id = (const char *)best_macro->ident.str;
+ tree macro_as_identifier
+ = get_identifier_with_length (id, best_macro->ident.len);
+ bm.set_best_so_far (macro_as_identifier,
+ bmm.get_best_distance (),
+ bmm.get_best_candidate_length ());
+ }
+
+ /* Try the "start_typename" keywords to detect
+ "singed" vs "signed" typos. */
+ if (kind == FUZZY_LOOKUP_TYPENAME)
+ {
+ for (unsigned i = 0; i < num_c_common_reswords; i++)
+ {
+ const c_common_resword *resword = &c_common_reswords[i];
+ if (!c_keyword_starts_typename (resword->rid))
+ continue;
+ tree resword_identifier = ridpointers [resword->rid];
+ if (!resword_identifier)
+ continue;
+ gcc_assert (TREE_CODE (resword_identifier) == IDENTIFIER_NODE);
+ bm.consider (resword_identifier);
+ }
+ }
+
+ tree best = bm.get_best_meaningful_candidate ();
+ if (best)
+ return IDENTIFIER_POINTER (best);
+ else
+ return NULL;
+}
+
/* Create the predefined scalar types of C,
and some nodes representing standard constants (0, 1, (void *) 0).
@@ -4024,7 +4194,7 @@ c_make_fname_decl (location_t loc, tree id, int type_dep)
the __FUNCTION__ is believed to appear in K&R style function
parameter declarator. In that case we still don't have
function_scope. */
- && (!seen_error () || current_function_scope))
+ && current_function_scope)
{
DECL_CONTEXT (decl) = current_function_decl;
bind (id, decl, current_function_scope,
@@ -4896,7 +5066,7 @@ finish_decl (tree decl, location_t init_loc, tree init,
when a tentative file-scope definition is seen.
But at end of compilation, do output code for them. */
DECL_DEFER_OUTPUT (decl) = 1;
- if (asmspec && C_DECL_REGISTER (decl))
+ if (asmspec && VAR_P (decl) && C_DECL_REGISTER (decl))
DECL_HARD_REGISTER (decl) = 1;
rest_of_decl_compilation (decl, true, 0);
}
@@ -4974,7 +5144,7 @@ finish_decl (tree decl, location_t init_loc, tree init,
vec<tree, va_gc> *v;
/* Build "cleanup(&decl)" for the destructor. */
- cleanup = build_unary_op (input_location, ADDR_EXPR, decl, 0);
+ cleanup = build_unary_op (input_location, ADDR_EXPR, decl, false);
vec_alloc (v, 1);
v->quick_push (cleanup);
cleanup = c_build_function_call_vec (DECL_SOURCE_LOCATION (decl),
@@ -5111,7 +5281,7 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const)
if (type == error_mark_node || !COMPLETE_TYPE_P (type))
{
- c_incomplete_type_error (NULL_TREE, type);
+ c_incomplete_type_error (loc, NULL_TREE, type);
return error_mark_node;
}
@@ -5320,6 +5490,27 @@ warn_defaults_to (location_t location, int opt, const char *gmsgid, ...)
va_end (ap);
}
+/* Returns the smallest location != UNKNOWN_LOCATION in LOCATIONS,
+ considering only those c_declspec_words found in LIST, which
+ must be terminated by cdw_number_of_elements. */
+
+static location_t
+smallest_type_quals_location (const location_t *locations,
+ const c_declspec_word *list)
+{
+ location_t loc = UNKNOWN_LOCATION;
+ while (*list != cdw_number_of_elements)
+ {
+ location_t newloc = locations[*list];
+ if (loc == UNKNOWN_LOCATION
+ || (newloc != UNKNOWN_LOCATION && newloc < loc))
+ loc = newloc;
+ list++;
+ }
+
+ return loc;
+}
+
/* Given declspecs and a declarator,
determine the name and type of the object declared
and construct a ..._DECL node for it.
@@ -5391,7 +5582,6 @@ grokdeclarator (const struct c_declarator *declarator,
struct c_arg_info *arg_info = 0;
addr_space_t as1, as2, address_space;
location_t loc = UNKNOWN_LOCATION;
- const char *errmsg;
tree expr_dummy;
bool expr_const_operands_dummy;
enum c_declarator_kind first_non_attr_kind;
@@ -5400,11 +5590,21 @@ grokdeclarator (const struct c_declarator *declarator,
if (TREE_CODE (type) == ERROR_MARK)
return error_mark_node;
if (expr == NULL)
- expr = &expr_dummy;
+ {
+ expr = &expr_dummy;
+ expr_dummy = NULL_TREE;
+ }
if (expr_const_operands == NULL)
expr_const_operands = &expr_const_operands_dummy;
- *expr = declspecs->expr;
+ if (declspecs->expr)
+ {
+ if (*expr)
+ *expr = build2 (COMPOUND_EXPR, TREE_TYPE (declspecs->expr), *expr,
+ declspecs->expr);
+ else
+ *expr = declspecs->expr;
+ }
*expr_const_operands = declspecs->expr_const_operands;
if (decl_context == FUNCDEF)
@@ -5798,10 +5998,21 @@ grokdeclarator (const struct c_declarator *declarator,
{
if (name)
error_at (loc, "size of array %qE has non-integer type",
- name);
+ name);
else
error_at (loc,
- "size of unnamed array has non-integer type");
+ "size of unnamed array has non-integer type");
+ size = integer_one_node;
+ }
+ /* This can happen with enum forward declaration. */
+ else if (!COMPLETE_TYPE_P (TREE_TYPE (size)))
+ {
+ if (name)
+ error_at (loc, "size of array %qE has incomplete type",
+ name);
+ else
+ error_at (loc, "size of unnamed array has incomplete "
+ "type");
size = integer_one_node;
}
@@ -6114,12 +6325,6 @@ grokdeclarator (const struct c_declarator *declarator,
"an array");
type = integer_type_node;
}
- errmsg = targetm.invalid_return_type (type);
- if (errmsg)
- {
- error (errmsg);
- type = integer_type_node;
- }
/* Construct the function type and go to the next
inner layer of declarator. */
@@ -6130,20 +6335,48 @@ grokdeclarator (const struct c_declarator *declarator,
qualify the return type, not the function type. */
if (type_quals)
{
+ const enum c_declspec_word ignored_quals_list[] =
+ {
+ cdw_const, cdw_volatile, cdw_restrict, cdw_address_space,
+ cdw_atomic, cdw_number_of_elements
+ };
+ location_t specs_loc
+ = smallest_type_quals_location (declspecs->locations,
+ ignored_quals_list);
+ if (specs_loc == UNKNOWN_LOCATION)
+ specs_loc = declspecs->locations[cdw_typedef];
+ if (specs_loc == UNKNOWN_LOCATION)
+ specs_loc = loc;
+
/* Type qualifiers on a function return type are
normally permitted by the standard but have no
effect, so give a warning at -Wreturn-type.
Qualifiers on a void return type are banned on
function definitions in ISO C; GCC used to used
- them for noreturn functions. */
- if (VOID_TYPE_P (type) && really_funcdef)
- pedwarn (loc, 0,
+ them for noreturn functions. The resolution of C11
+ DR#423 means qualifiers (other than _Atomic) are
+ actually removed from the return type when
+ determining the function type. */
+ int quals_used = type_quals;
+ if (flag_isoc11)
+ quals_used &= TYPE_QUAL_ATOMIC;
+ if (quals_used && VOID_TYPE_P (type) && really_funcdef)
+ pedwarn (specs_loc, 0,
"function definition has qualified void return type");
else
- warning_at (loc, OPT_Wignored_qualifiers,
+ warning_at (specs_loc, OPT_Wignored_qualifiers,
"type qualifiers ignored on function return type");
- type = c_build_qualified_type (type, type_quals);
+ /* Ensure an error for restrict on invalid types; the
+ DR#423 resolution is not entirely clear about
+ this. */
+ if (flag_isoc11
+ && (type_quals & TYPE_QUAL_RESTRICT)
+ && (!POINTER_TYPE_P (type)
+ || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
+ error_at (loc, "invalid use of %<restrict%>");
+ if (quals_used)
+ type = c_build_qualified_type (type, quals_used);
}
type_quals = TYPE_UNQUALIFIED;
@@ -6329,7 +6562,7 @@ grokdeclarator (const struct c_declarator *declarator,
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
error_at (loc, "alignment specified for function %qE", name);
- else if (declspecs->align_log != -1)
+ else if (declspecs->align_log != -1 && TYPE_P (type))
{
alignas_align = 1U << declspecs->align_log;
if (alignas_align < min_align_of_type (type))
@@ -6765,7 +6998,7 @@ grokdeclarator (const struct c_declarator *declarator,
/* Apply _Alignas specifiers. */
if (alignas_align)
{
- DECL_ALIGN (decl) = alignas_align * BITS_PER_UNIT;
+ SET_DECL_ALIGN (decl, alignas_align * BITS_PER_UNIT);
DECL_USER_ALIGN (decl) = 1;
}
@@ -6858,7 +7091,6 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
{
tree parm, type, typelt;
unsigned int parmno;
- const char *errmsg;
/* If there is a parameter of incomplete type in a definition,
this is an error. In a declaration this is valid, and a
@@ -6907,15 +7139,6 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
}
}
- errmsg = targetm.invalid_parameter_type (type);
- if (errmsg)
- {
- error (errmsg);
- TREE_VALUE (typelt) = error_mark_node;
- TREE_TYPE (parm) = error_mark_node;
- arg_types = NULL_TREE;
- }
-
if (DECL_NAME (parm) && TREE_USED (parm))
warn_if_shadowing (parm);
}
@@ -7082,9 +7305,9 @@ get_parm_info (bool ellipsis, tree expr)
break;
case FUNCTION_DECL:
- /* FUNCTION_DECLs appear when there is an implicit function
- declaration in the parameter list. */
- gcc_assert (b->nested);
+ /* FUNCTION_DECLs appear when there is an implicit function
+ declaration in the parameter list. */
+ gcc_assert (b->nested || seen_error ());
goto set_shadowed;
case CONST_DECL:
@@ -7207,7 +7430,7 @@ parser_xref_tag (location_t loc, enum tree_code code, tree name)
/* Give the type a default layout like unsigned int
to avoid crashing if it does not get defined. */
SET_TYPE_MODE (ref, TYPE_MODE (unsigned_type_node));
- TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
+ SET_TYPE_ALIGN (ref, TYPE_ALIGN (unsigned_type_node));
TYPE_USER_ALIGN (ref) = 0;
TYPE_UNSIGNED (ref) = 1;
TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node);
@@ -7293,10 +7516,7 @@ start_struct (location_t loc, enum tree_code code, tree name,
TYPE_PACKED (v) = flag_pack_struct;
*enclosing_struct_parse_info = struct_parse_info;
- struct_parse_info = XNEW (struct c_struct_parse_info);
- struct_parse_info->struct_types.create (0);
- struct_parse_info->fields.create (0);
- struct_parse_info->typedefs_seen.create (0);
+ struct_parse_info = new c_struct_parse_info ();
/* FIXME: This will issue a warning for a use of a type defined
within a statement expr used within sizeof, et. al. This is not
@@ -7748,7 +7968,8 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
else if (!saw_named_field)
{
error_at (DECL_SOURCE_LOCATION (x),
- "flexible array member in otherwise empty struct");
+ "flexible array member in a struct with no named "
+ "members");
TREE_TYPE (x) = error_mark_node;
}
}
@@ -7795,7 +8016,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
{
TREE_TYPE (field)
= c_build_bitfield_integer_type (width, TYPE_UNSIGNED (type));
- DECL_MODE (field) = TYPE_MODE (TREE_TYPE (field));
+ SET_DECL_MODE (field, TYPE_MODE (TREE_TYPE (field)));
}
DECL_INITIAL (field) = 0;
}
@@ -7938,10 +8159,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
if (warn_cxx_compat)
warn_cxx_compat_finish_struct (fieldlist, TREE_CODE (t), loc);
- struct_parse_info->struct_types.release ();
- struct_parse_info->fields.release ();
- struct_parse_info->typedefs_seen.release ();
- XDELETE (struct_parse_info);
+ delete struct_parse_info;
struct_parse_info = enclosing_struct_parse_info;
@@ -7990,6 +8208,10 @@ start_enum (location_t loc, struct c_enum_contents *the_enum, tree name)
enumtype = make_node (ENUMERAL_TYPE);
pushtag (loc, name, enumtype);
}
+ /* Update type location to the one of the definition, instead of e.g.
+ a forward declaration. */
+ else if (TYPE_STUB_DECL (enumtype))
+ DECL_SOURCE_LOCATION (TYPE_STUB_DECL (enumtype)) = loc;
if (C_TYPE_BEING_DEFINED (enumtype))
error_at (loc, "nested redefinition of %<enum %E%>", name);
@@ -8103,7 +8325,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
TYPE_MIN_VALUE (enumtype) = TYPE_MIN_VALUE (tem);
TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (tem);
TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (tem);
- TYPE_ALIGN (enumtype) = TYPE_ALIGN (tem);
+ SET_TYPE_ALIGN (enumtype, TYPE_ALIGN (tem));
TYPE_SIZE (enumtype) = 0;
TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem);
@@ -8165,7 +8387,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (enumtype);
SET_TYPE_MODE (tem, TYPE_MODE (enumtype));
TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
- TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
+ SET_TYPE_ALIGN (tem, TYPE_ALIGN (enumtype));
TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype);
TYPE_UNSIGNED (tem) = TYPE_UNSIGNED (enumtype);
TYPE_LANG_SPECIFIC (tem) = TYPE_LANG_SPECIFIC (enumtype);
@@ -8633,8 +8855,11 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
continue;
/* If we got something other than a PARM_DECL it is an error. */
if (TREE_CODE (decl) != PARM_DECL)
- error_at (DECL_SOURCE_LOCATION (decl),
- "%qD declared as a non-parameter", decl);
+ {
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%qD declared as a non-parameter", decl);
+ continue;
+ }
/* If the declaration is already marked, we have a duplicate
name. Complain and ignore the duplicate. */
else if (seen_args.contains (decl))
@@ -8751,12 +8976,15 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
tree type;
for (parm = DECL_ARGUMENTS (fndecl),
type = current_function_prototype_arg_types;
- parm || (type && TREE_VALUE (type) != error_mark_node
- && (TYPE_MAIN_VARIANT (TREE_VALUE (type)) != void_type_node));
+ parm || (type != NULL_TREE
+ && TREE_VALUE (type) != error_mark_node
+ && TYPE_MAIN_VARIANT (TREE_VALUE (type)) != void_type_node);
parm = DECL_CHAIN (parm), type = TREE_CHAIN (type))
{
- if (parm == 0 || type == 0
- || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
+ if (parm == NULL_TREE
+ || type == NULL_TREE
+ || (TREE_VALUE (type) != error_mark_node
+ && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node))
{
if (current_function_prototype_built_in)
warning_at (DECL_SOURCE_LOCATION (fndecl),
@@ -8782,7 +9010,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
declared for the arg. ISO C says we take the unqualified
type for parameters declared with qualified type. */
if (TREE_TYPE (parm) != error_mark_node
- && TREE_TYPE (type) != error_mark_node
+ && TREE_VALUE (type) != error_mark_node
&& ((TYPE_ATOMIC (DECL_ARG_TYPE (parm))
!= TYPE_ATOMIC (TREE_VALUE (type)))
|| !comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
@@ -8802,8 +9030,8 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
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))
+ && (TYPE_PRECISION (TREE_TYPE (parm))
+ < TYPE_PRECISION (integer_type_node)))
DECL_ARG_TYPE (parm)
= c_type_promotes_to (TREE_TYPE (parm));
@@ -9130,7 +9358,9 @@ finish_function (void)
/* For GNU C extern inline functions disregard inline limits. */
if (DECL_EXTERNAL (fndecl)
- && DECL_DECLARED_INLINE_P (fndecl))
+ && DECL_DECLARED_INLINE_P (fndecl)
+ && (flag_gnu89_inline
+ || lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (fndecl))))
DECL_DISREGARD_INLINE_LIMITS (fndecl) = 1;
/* Genericize before inlining. Delay genericizing nested functions
@@ -9541,32 +9771,48 @@ declspecs_add_qual (source_location loc,
gcc_assert (TREE_CODE (qual) == IDENTIFIER_NODE
&& C_IS_RESERVED_WORD (qual));
i = C_RID_CODE (qual);
+ location_t prev_loc = 0;
switch (i)
{
case RID_CONST:
dupe = specs->const_p;
specs->const_p = true;
+ prev_loc = specs->locations[cdw_const];
specs->locations[cdw_const] = loc;
break;
case RID_VOLATILE:
dupe = specs->volatile_p;
specs->volatile_p = true;
+ prev_loc = specs->locations[cdw_volatile];
specs->locations[cdw_volatile] = loc;
break;
case RID_RESTRICT:
dupe = specs->restrict_p;
specs->restrict_p = true;
+ prev_loc = specs->locations[cdw_restrict];
specs->locations[cdw_restrict] = loc;
break;
case RID_ATOMIC:
dupe = specs->atomic_p;
specs->atomic_p = true;
+ prev_loc = specs->locations[cdw_atomic];
+ specs->locations[cdw_atomic] = loc;
break;
default:
gcc_unreachable ();
}
if (dupe)
- pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %qE", qual);
+ {
+ bool warned = pedwarn_c90 (loc, OPT_Wpedantic,
+ "duplicate %qE declaration specifier", qual);
+ if (!warned
+ && warn_duplicate_decl_specifier
+ && prev_loc >= RESERVED_LOCATION_COUNT
+ && !from_macro_expansion_at (prev_loc)
+ && !from_macro_expansion_at (loc))
+ warning_at (loc, OPT_Wduplicate_decl_specifier,
+ "duplicate %qE declaration specifier", qual);
+ }
return specs;
}
@@ -9651,6 +9897,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
error_at (loc,
("both %<long%> and %<float%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_floatn_nx)
+ error_at (loc,
+ ("both %<long%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
else if (specs->typespec_word == cts_dfloat32)
error_at (loc,
("both %<long%> and %<_Decimal32%> in "
@@ -9704,6 +9958,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
error_at (loc,
("both %<short%> and %<double%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_floatn_nx)
+ error_at (loc,
+ ("both %<short%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
else if (specs->typespec_word == cts_dfloat32)
error_at (loc,
("both %<short%> and %<_Decimal32%> in "
@@ -9748,6 +10010,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
error_at (loc,
("both %<signed%> and %<double%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_floatn_nx)
+ error_at (loc,
+ ("both %<signed%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
else if (specs->typespec_word == cts_dfloat32)
error_at (loc,
("both %<signed%> and %<_Decimal32%> in "
@@ -9792,6 +10062,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
error_at (loc,
("both %<unsigned%> and %<double%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_floatn_nx)
+ error_at (loc,
+ ("both %<unsigned%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
else if (specs->typespec_word == cts_dfloat32)
error_at (loc,
("both %<unsigned%> and %<_Decimal32%> in "
@@ -9896,6 +10174,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
error_at (loc,
("both %<_Sat%> and %<double%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_floatn_nx)
+ error_at (loc,
+ ("both %<_Sat%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
else if (specs->typespec_word == cts_dfloat32)
error_at (loc,
("both %<_Sat%> and %<_Decimal32%> in "
@@ -9929,8 +10215,9 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
}
else
{
- /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
- "__intN", "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
+ /* "void", "_Bool", "char", "int", "float", "double",
+ "_FloatN", "_FloatNx", "_Decimal32", "__intN",
+ "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
"__auto_type". */
if (specs->typespec_word != cts_none)
{
@@ -9996,10 +10283,13 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
("both %<__int%d%> and %<short%> in "
"declaration specifiers"),
int_n_data[specs->int_n_idx].bitsize);
- else if (! int_n_enabled_p [specs->int_n_idx])
- error_at (loc,
- "%<__int%d%> is not supported on this target",
- int_n_data[specs->int_n_idx].bitsize);
+ else if (! int_n_enabled_p[specs->int_n_idx])
+ {
+ specs->typespec_word = cts_int_n;
+ error_at (loc,
+ "%<__int%d%> is not supported on this target",
+ int_n_data[specs->int_n_idx].bitsize);
+ }
else
{
specs->typespec_word = cts_int_n;
@@ -10155,6 +10445,72 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
specs->locations[cdw_typespec] = loc;
}
return specs;
+ CASE_RID_FLOATN_NX:
+ specs->floatn_nx_idx = i - RID_FLOATN_NX_FIRST;
+ if (!in_system_header_at (input_location))
+ pedwarn (loc, OPT_Wpedantic,
+ "ISO C does not support the %<_Float%d%s%> type",
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+
+ if (specs->long_p)
+ error_at (loc,
+ ("both %<long%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+ else if (specs->short_p)
+ error_at (loc,
+ ("both %<short%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+ else if (specs->signed_p)
+ error_at (loc,
+ ("both %<signed%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+ else if (specs->unsigned_p)
+ error_at (loc,
+ ("both %<unsigned%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+ else if (specs->saturating_p)
+ error_at (loc,
+ ("both %<_Sat%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+ else if (FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx) == NULL_TREE)
+ {
+ specs->typespec_word = cts_floatn_nx;
+ error_at (loc,
+ "%<_Float%d%s%> is not supported on this target",
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+ }
+ else
+ {
+ specs->typespec_word = cts_floatn_nx;
+ specs->locations[cdw_typespec] = loc;
+ }
+ return specs;
case RID_DFLOAT32:
case RID_DFLOAT64:
case RID_DFLOAT128:
@@ -10168,37 +10524,37 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
str = "_Decimal128";
if (specs->long_long_p)
error_at (loc,
- ("both %<long long%> and %<%s%> in "
+ ("both %<long long%> and %qs in "
"declaration specifiers"),
str);
if (specs->long_p)
error_at (loc,
- ("both %<long%> and %<%s%> in "
+ ("both %<long%> and %qs in "
"declaration specifiers"),
str);
else if (specs->short_p)
error_at (loc,
- ("both %<short%> and %<%s%> in "
+ ("both %<short%> and %qs in "
"declaration specifiers"),
str);
else if (specs->signed_p)
error_at (loc,
- ("both %<signed%> and %<%s%> in "
+ ("both %<signed%> and %qs in "
"declaration specifiers"),
str);
else if (specs->unsigned_p)
error_at (loc,
- ("both %<unsigned%> and %<%s%> in "
+ ("both %<unsigned%> and %qs in "
"declaration specifiers"),
str);
else if (specs->complex_p)
error_at (loc,
- ("both %<complex%> and %<%s%> in "
+ ("both %<complex%> and %qs in "
"declaration specifiers"),
str);
else if (specs->saturating_p)
error_at (loc,
- ("both %<_Sat%> and %<%s%> in "
+ ("both %<_Sat%> and %qs in "
"declaration specifiers"),
str);
else if (i == RID_DFLOAT32)
@@ -10226,7 +10582,7 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
str = "_Accum";
if (specs->complex_p)
error_at (loc,
- ("both %<complex%> and %<%s%> in "
+ ("both %<complex%> and %qs in "
"declaration specifiers"),
str);
else if (i == RID_FRACT)
@@ -10632,6 +10988,16 @@ finish_declspecs (struct c_declspecs *specs)
: double_type_node);
}
break;
+ case cts_floatn_nx:
+ gcc_assert (!specs->long_p && !specs->short_p
+ && !specs->signed_p && !specs->unsigned_p);
+ if (FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx) == NULL_TREE)
+ specs->type = integer_type_node;
+ else if (specs->complex_p)
+ specs->type = COMPLEX_FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx);
+ else
+ specs->type = FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx);
+ break;
case cts_dfloat32:
case cts_dfloat64:
case cts_dfloat128:
diff --git a/gcc/c/c-errors.c b/gcc/c/c-errors.c
index d5e78b875e..2c9267c186 100644
--- a/gcc/c/c-errors.c
+++ b/gcc/c/c-errors.c
@@ -1,5 +1,5 @@
/* Various diagnostic subroutines for the GNU C language.
- Copyright (C) 2000-2016 Free Software Foundation, Inc.
+ Copyright (C) 2000-2017 Free Software Foundation, Inc.
Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
This file is part of GCC.
@@ -71,11 +71,12 @@ pedwarn_c99 (location_t location, int opt, const char *gmsgid, ...)
ISO C99 but not supported in ISO C90, thus we explicitly don't pedwarn
when C99 is specified. (There is no flag_c90.) */
-void
+bool
pedwarn_c90 (location_t location, int opt, const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
+ bool warned = false;
rich_location richloc (line_table, location);
va_start (ap, gmsgid);
@@ -92,6 +93,7 @@ pedwarn_c90 (location_t location, int opt, const char *gmsgid, ...)
? DK_PEDWARN : DK_WARNING);
diagnostic.option_index = opt;
report_diagnostic (&diagnostic);
+ warned = true;
goto out;
}
}
@@ -114,7 +116,9 @@ pedwarn_c90 (location_t location, int opt, const char *gmsgid, ...)
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
diagnostic.option_index = opt;
report_diagnostic (&diagnostic);
+ warned = true;
}
out:
va_end (ap);
+ return warned;
}
diff --git a/gcc/c/c-fold.c b/gcc/c/c-fold.c
index 6c82f242bf..b060d76da4 100644
--- a/gcc/c/c-fold.c
+++ b/gcc/c/c-fold.c
@@ -1,5 +1,5 @@
/* Support for fully folding sub-trees of an expression for C compiler.
- Copyright (C) 1992-2016 Free Software Foundation, Inc.
+ Copyright (C) 1992-2017 Free Software Foundation, Inc.
This file is part of GCC.
@@ -320,8 +320,6 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
if ((code == LSHIFT_EXPR || code == RSHIFT_EXPR)
&& TREE_CODE (orig_op1) != INTEGER_CST
&& TREE_CODE (op1) == INTEGER_CST
- && (TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE
- || TREE_CODE (TREE_TYPE (orig_op0)) == FIXED_POINT_TYPE)
&& TREE_CODE (TREE_TYPE (orig_op1)) == INTEGER_TYPE
&& c_inhibit_evaluation_warnings == 0)
{
@@ -330,13 +328,23 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
(code == LSHIFT_EXPR
? G_("left shift count is negative")
: G_("right shift count is negative")));
- else if (compare_tree_int (op1,
- TYPE_PRECISION (TREE_TYPE (orig_op0)))
- >= 0)
+ else if ((TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE
+ || TREE_CODE (TREE_TYPE (orig_op0)) == FIXED_POINT_TYPE)
+ && compare_tree_int (op1,
+ TYPE_PRECISION (TREE_TYPE (orig_op0)))
+ >= 0)
warning_at (loc, OPT_Wshift_count_overflow,
(code == LSHIFT_EXPR
? G_("left shift count >= width of type")
: G_("right shift count >= width of type")));
+ else if (TREE_CODE (TREE_TYPE (orig_op0)) == VECTOR_TYPE
+ && compare_tree_int (op1,
+ TYPE_PRECISION (TREE_TYPE (TREE_TYPE (orig_op0))))
+ >= 0)
+ warning_at (loc, OPT_Wshift_count_overflow,
+ code == LSHIFT_EXPR
+ ? G_("left shift count >= width of vector element")
+ : G_("right shift count >= width of vector element"));
}
if (code == LSHIFT_EXPR
/* If either OP0 has been folded to INTEGER_CST... */
diff --git a/gcc/c/c-lang.c b/gcc/c/c-lang.c
index 89954b749c..510b7e7de4 100644
--- a/gcc/c/c-lang.c
+++ b/gcc/c/c-lang.c
@@ -1,5 +1,5 @@
/* Language-specific hook definitions for C front end.
- Copyright (C) 1991-2016 Free Software Foundation, Inc.
+ Copyright (C) 1991-2017 Free Software Foundation, Inc.
This file is part of GCC.
@@ -38,7 +38,32 @@ enum c_language_kind c_language = clk_c;
#undef LANG_HOOKS_INIT_TS
#define LANG_HOOKS_INIT_TS c_common_init_ts
+#if CHECKING_P
+#undef LANG_HOOKS_RUN_LANG_SELFTESTS
+#define LANG_HOOKS_RUN_LANG_SELFTESTS selftest::run_c_tests
+#endif /* #if CHECKING_P */
+
+#undef LANG_HOOKS_GET_SUBSTRING_LOCATION
+#define LANG_HOOKS_GET_SUBSTRING_LOCATION c_get_substring_location
+
/* Each front end provides its own lang hook initializer. */
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+#if CHECKING_P
+
+namespace selftest {
+
+/* Implementation of LANG_HOOKS_RUN_LANG_SELFTESTS for the C frontend. */
+
+void
+run_c_tests (void)
+{
+ c_format_c_tests ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
+
#include "gtype-c.h"
diff --git a/gcc/c/c-lang.h b/gcc/c/c-lang.h
index ac7c1bb054..872bd5823c 100644
--- a/gcc/c/c-lang.h
+++ b/gcc/c/c-lang.h
@@ -1,5 +1,5 @@
/* Definitions for C language specific types.
- Copyright (C) 2009-2016 Free Software Foundation, Inc.
+ Copyright (C) 2009-2017 Free Software Foundation, Inc.
This file is part of GCC.
diff --git a/gcc/c/c-objc-common.c b/gcc/c/c-objc-common.c
index 20dc024b85..5e69488730 100644
--- a/gcc/c/c-objc-common.c
+++ b/gcc/c/c-objc-common.c
@@ -1,5 +1,5 @@
/* Some code common to C and ObjC front ends.
- Copyright (C) 2001-2016 Free Software Foundation, Inc.
+ Copyright (C) 2001-2017 Free Software Foundation, Inc.
This file is part of GCC.
diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h
index ccb4903ee4..bee06e9a37 100644
--- a/gcc/c/c-objc-common.h
+++ b/gcc/c/c-objc-common.h
@@ -1,5 +1,5 @@
/* Language hooks common to C and ObjC front ends.
- Copyright (C) 2004-2016 Free Software Foundation, Inc.
+ Copyright (C) 2004-2017 Free Software Foundation, Inc.
Contributed by Ziemowit Laski <zlaski@apple.com>
This file is part of GCC.
@@ -91,7 +91,7 @@ along with GCC; see the file COPYING3. If not see
This means it must also provide its own write_globals. */
#undef LANG_HOOKS_GETDECLS
-#define LANG_HOOKS_GETDECLS lhd_return_null_tree_v
+#define LANG_HOOKS_GETDECLS hook_tree_void_null
/* Hooks for tree gimplification. */
#undef LANG_HOOKS_GIMPLIFY_EXPR
@@ -100,6 +100,12 @@ along with GCC; see the file COPYING3. If not see
#undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
#define LANG_HOOKS_OMP_PREDETERMINED_SHARING c_omp_predetermined_sharing
+#undef LANG_HOOKS_OMP_CLAUSE_COPY_CTOR
+#define LANG_HOOKS_OMP_CLAUSE_COPY_CTOR c_omp_clause_copy_ctor
+
+#undef LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP
+#define LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP c_omp_clause_copy_ctor
+
#undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P
#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P c_vla_unspec_p
#endif /* GCC_C_OBJC_COMMON */
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index c9eb8ddbae..988369e419 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1,5 +1,5 @@
/* Parser for C and Objective-C.
- Copyright (C) 1987-2016 Free Software Foundation, Inc.
+ Copyright (C) 1987-2017 Free Software Foundation, Inc.
Parser actions based on the old Bison parser; structure somewhat
influenced by and fragments based on the C++ parser.
@@ -52,12 +52,19 @@ along with GCC; see the file COPYING3. If not see
#include "c-lang.h"
#include "c-family/c-objc.h"
#include "plugin.h"
-#include "omp-low.h"
+#include "omp-general.h"
+#include "omp-offload.h"
#include "builtins.h"
#include "gomp-constants.h"
#include "c-family/c-indentation.h"
#include "gimple-expr.h"
#include "context.h"
+#include "gcc-rich-location.h"
+#include "c-parser.h"
+#include "gimple-parser.h"
+#include "read-rtl-function.h"
+#include "run-rtl-passes.h"
+#include "intl.h"
/* We need to walk over decls with incomplete struct/union/enum types
after parsing the whole translation unit.
@@ -66,7 +73,7 @@ along with GCC; see the file COPYING3. If not see
In c_parser_translation_unit(), we iterate over incomplete_record_decls
and report error if any of the decls are still incomplete. */
-vec<tree> incomplete_record_decls = vNULL;
+vec<tree> incomplete_record_decls;
void
set_c_expr_source_range (c_expr *expr,
@@ -149,61 +156,6 @@ c_parse_init (void)
}
}
-/* The C lexer intermediates between the lexer in cpplib and c-lex.c
- and the C parser. Unlike the C++ lexer, the parser structure
- stores the lexer information instead of using a separate structure.
- Identifiers are separated into ordinary identifiers, type names,
- keywords and some other Objective-C types of identifiers, and some
- look-ahead is maintained.
-
- ??? It might be a good idea to lex the whole file up front (as for
- C++). It would then be possible to share more of the C and C++
- lexer code, if desired. */
-
-/* More information about the type of a CPP_NAME token. */
-enum c_id_kind {
- /* An ordinary identifier. */
- C_ID_ID,
- /* An identifier declared as a typedef name. */
- C_ID_TYPENAME,
- /* An identifier declared as an Objective-C class name. */
- C_ID_CLASSNAME,
- /* An address space identifier. */
- C_ID_ADDRSPACE,
- /* Not an identifier. */
- C_ID_NONE
-};
-
-/* A single C token after string literal concatenation and conversion
- of preprocessing tokens to tokens. */
-struct GTY (()) c_token {
- /* The kind of token. */
- ENUM_BITFIELD (cpp_ttype) type : 8;
- /* If this token is a CPP_NAME, this value indicates whether also
- declared as some kind of type. Otherwise, it is C_ID_NONE. */
- ENUM_BITFIELD (c_id_kind) id_kind : 8;
- /* If this token is a keyword, this value indicates which keyword.
- Otherwise, this value is RID_MAX. */
- ENUM_BITFIELD (rid) keyword : 8;
- /* If this token is a CPP_PRAGMA, this indicates the pragma that
- was seen. Otherwise it is PRAGMA_NONE. */
- ENUM_BITFIELD (pragma_kind) pragma_kind : 8;
- /* The location at which this token was found. */
- location_t location;
- /* The value associated with this token, if any. */
- tree value;
-
- source_range get_range () const
- {
- return get_range_from_loc (line_table, location);
- }
-
- location_t get_finish () const
- {
- return get_range ().m_finish;
- }
-};
-
/* A parser structure recording information about the state and
context of parsing. Includes lexer information with up to two
tokens of look-ahead; more are not needed for C. */
@@ -256,6 +208,30 @@ struct GTY(()) c_parser {
vec <c_token, va_gc> *cilk_simd_fn_tokens;
};
+/* Return a pointer to the Nth token in PARSERs tokens_buf. */
+
+c_token *
+c_parser_tokens_buf (c_parser *parser, unsigned n)
+{
+ return &parser->tokens_buf[n];
+}
+
+/* Return the error state of PARSER. */
+
+bool
+c_parser_error (c_parser *parser)
+{
+ return parser->error;
+}
+
+/* Set the error state of PARSER to ERR. */
+
+void
+c_parser_set_error (c_parser *parser, bool err)
+{
+ parser->error = err;
+}
+
/* The actual parser and external interface. ??? Does this need to be
garbage-collected? */
@@ -269,7 +245,8 @@ c_lex_one_token (c_parser *parser, c_token *token)
{
timevar_push (TV_LEX);
- token->type = c_lex_with_flags (&token->value, &token->location, NULL,
+ token->type = c_lex_with_flags (&token->value, &token->location,
+ &token->flags,
(parser->lex_untranslated_string
? C_LEX_STRING_NO_TRANSLATE : 0));
token->id_kind = C_ID_NONE;
@@ -300,6 +277,9 @@ c_lex_one_token (c_parser *parser, c_token *token)
else if (rid_code >= RID_FIRST_ADDR_SPACE
&& rid_code <= RID_LAST_ADDR_SPACE)
{
+ addr_space_t as;
+ as = (addr_space_t) (rid_code - RID_FIRST_ADDR_SPACE);
+ targetm.addr_space.diagnose_usage (as, token->location);
token->id_kind = C_ID_ADDRSPACE;
token->keyword = rid_code;
break;
@@ -447,7 +427,7 @@ c_lex_one_token (c_parser *parser, c_token *token)
/* Return a pointer to the next token from PARSER, reading it in if
necessary. */
-static inline c_token *
+c_token *
c_parser_peek_token (c_parser *parser)
{
if (parser->tokens_avail == 0)
@@ -458,37 +438,10 @@ c_parser_peek_token (c_parser *parser)
return &parser->tokens[0];
}
-/* Return true if the next token from PARSER has the indicated
- TYPE. */
-
-static inline bool
-c_parser_next_token_is (c_parser *parser, enum cpp_ttype type)
-{
- return c_parser_peek_token (parser)->type == type;
-}
-
-/* Return true if the next token from PARSER does not have the
- indicated TYPE. */
-
-static inline bool
-c_parser_next_token_is_not (c_parser *parser, enum cpp_ttype type)
-{
- return !c_parser_next_token_is (parser, type);
-}
-
-/* Return true if the next token from PARSER is the indicated
- KEYWORD. */
-
-static inline bool
-c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword)
-{
- return c_parser_peek_token (parser)->keyword == keyword;
-}
-
/* Return a pointer to the next-but-one token from PARSER, reading it
in if necessary. The next token is already read in. */
-static c_token *
+c_token *
c_parser_peek_2nd_token (c_parser *parser)
{
if (parser->tokens_avail >= 2)
@@ -504,7 +457,7 @@ c_parser_peek_2nd_token (c_parser *parser)
/* Return a pointer to the Nth token from PARSER, reading it
in if necessary. The N-1th token is already read in. */
-static c_token *
+c_token *
c_parser_peek_nth_token (c_parser *parser, unsigned int n)
{
/* N is 1-based, not zero-based. */
@@ -518,9 +471,52 @@ c_parser_peek_nth_token (c_parser *parser, unsigned int n)
return &parser->tokens[n - 1];
}
+bool
+c_keyword_starts_typename (enum rid keyword)
+{
+ switch (keyword)
+ {
+ case RID_UNSIGNED:
+ case RID_LONG:
+ case RID_SHORT:
+ case RID_SIGNED:
+ case RID_COMPLEX:
+ case RID_INT:
+ case RID_CHAR:
+ case RID_FLOAT:
+ case RID_DOUBLE:
+ case RID_VOID:
+ case RID_DFLOAT32:
+ case RID_DFLOAT64:
+ case RID_DFLOAT128:
+ CASE_RID_FLOATN_NX:
+ case RID_BOOL:
+ case RID_ENUM:
+ case RID_STRUCT:
+ case RID_UNION:
+ case RID_TYPEOF:
+ case RID_CONST:
+ case RID_ATOMIC:
+ case RID_VOLATILE:
+ case RID_RESTRICT:
+ case RID_ATTRIBUTE:
+ case RID_FRACT:
+ case RID_ACCUM:
+ case RID_SAT:
+ case RID_AUTO_TYPE:
+ return true;
+ default:
+ if (keyword >= RID_FIRST_INT_N
+ && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+ && int_n_enabled_p[keyword - RID_FIRST_INT_N])
+ return true;
+ return false;
+ }
+}
+
/* Return true if TOKEN can start a type name,
false otherwise. */
-static bool
+bool
c_token_starts_typename (c_token *token)
{
switch (token->type)
@@ -541,43 +537,7 @@ c_token_starts_typename (c_token *token)
gcc_unreachable ();
}
case CPP_KEYWORD:
- switch (token->keyword)
- {
- case RID_UNSIGNED:
- case RID_LONG:
- case RID_SHORT:
- case RID_SIGNED:
- case RID_COMPLEX:
- case RID_INT:
- case RID_CHAR:
- case RID_FLOAT:
- case RID_DOUBLE:
- case RID_VOID:
- case RID_DFLOAT32:
- case RID_DFLOAT64:
- case RID_DFLOAT128:
- case RID_BOOL:
- case RID_ENUM:
- case RID_STRUCT:
- case RID_UNION:
- case RID_TYPEOF:
- case RID_CONST:
- case RID_ATOMIC:
- case RID_VOLATILE:
- case RID_RESTRICT:
- case RID_ATTRIBUTE:
- case RID_FRACT:
- case RID_ACCUM:
- case RID_SAT:
- case RID_AUTO_TYPE:
- return true;
- default:
- if (token->keyword >= RID_FIRST_INT_N
- && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
- && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
- return true;
- return false;
- }
+ return c_keyword_starts_typename (token->keyword);
case CPP_LESS:
if (c_dialect_objc ())
return true;
@@ -587,18 +547,6 @@ c_token_starts_typename (c_token *token)
}
}
-enum c_lookahead_kind {
- /* Always treat unknown identifiers as typenames. */
- cla_prefer_type,
-
- /* Could be parsing a nonabstract declarator. Only treat an identifier
- as a typename if followed by another identifier or a star. */
- cla_nonabstract_decl,
-
- /* Never treat identifiers as typenames. */
- cla_prefer_id
-};
-
/* Return true if the next token from PARSER can start a type name,
false otherwise. LA specifies how to do lookahead in order to
detect unknown type names. If unsure, pick CLA_PREFER_ID. */
@@ -717,6 +665,7 @@ c_token_starts_declspecs (c_token *token)
case RID_DFLOAT32:
case RID_DFLOAT64:
case RID_DFLOAT128:
+ CASE_RID_FLOATN_NX:
case RID_BOOL:
case RID_ENUM:
case RID_STRUCT:
@@ -764,7 +713,7 @@ c_token_starts_declaration (c_token *token)
/* Return true if the next token from PARSER can start declaration
specifiers, false otherwise. */
-static inline bool
+bool
c_parser_next_token_starts_declspecs (c_parser *parser)
{
c_token *token = c_parser_peek_token (parser);
@@ -786,7 +735,7 @@ c_parser_next_token_starts_declspecs (c_parser *parser)
/* Return true if the next tokens from PARSER can start declaration
specifiers or a static assertion, false otherwise. */
-static inline bool
+bool
c_parser_next_tokens_start_declaration (c_parser *parser)
{
c_token *token = c_parser_peek_token (parser);
@@ -814,7 +763,7 @@ c_parser_next_tokens_start_declaration (c_parser *parser)
/* Consume the next token from PARSER. */
-static void
+void
c_parser_consume_token (c_parser *parser)
{
gcc_assert (parser->tokens_avail >= 1);
@@ -907,7 +856,7 @@ c_parser_peek_conflict_marker (c_parser *parser, enum cpp_ttype tok1_kind,
this way is not i18n-friendly and some other approach should be
used. */
-static void
+void
c_parser_error (c_parser *parser, const char *gmsgid)
{
c_token *token = c_parser_peek_token (parser);
@@ -950,7 +899,7 @@ c_parser_error (c_parser *parser, const char *gmsgid)
been produced and no message will be produced this time. Returns
true if found, false otherwise. */
-static bool
+bool
c_parser_require (c_parser *parser,
enum cpp_ttype type,
const char *msgid)
@@ -993,7 +942,7 @@ c_parser_require_keyword (c_parser *parser,
already been produced and no message will be produced this
time. */
-static void
+void
c_parser_skip_until_found (c_parser *parser,
enum cpp_ttype type,
const char *msgid)
@@ -1228,58 +1177,27 @@ restore_extension_diagnostics (int flags)
warn_c99_c11_compat = (flags >> 9) & 1 ? 1 : ((flags >> 10) & 1 ? -1 : 0);
}
-/* Possibly kinds of declarator to parse. */
-enum c_dtr_syn {
- /* A normal declarator with an identifier. */
- C_DTR_NORMAL,
- /* An abstract declarator (maybe empty). */
- C_DTR_ABSTRACT,
- /* A parameter declarator: may be either, but after a type name does
- not redeclare a typedef name as an identifier if it can
- alternatively be interpreted as a typedef name; see DR#009,
- applied in C90 TC1, omitted from C99 and reapplied in C99 TC2
- following DR#249. For example, given a typedef T, "int T" and
- "int *T" are valid parameter declarations redeclaring T, while
- "int (T)" and "int * (T)" and "int (T[])" and "int (T (int))" are
- abstract declarators rather than involving redundant parentheses;
- the same applies with attributes inside the parentheses before
- "T". */
- C_DTR_PARM
-};
-
-/* The binary operation precedence levels, where 0 is a dummy lowest level
- used for the bottom of the stack. */
-enum c_parser_prec {
- PREC_NONE,
- PREC_LOGOR,
- PREC_LOGAND,
- PREC_BITOR,
- PREC_BITXOR,
- PREC_BITAND,
- PREC_EQ,
- PREC_REL,
- PREC_SHIFT,
- PREC_ADD,
- PREC_MULT,
- NUM_PRECS
+/* Helper data structure for parsing #pragma acc routine. */
+struct oacc_routine_data {
+ bool error_seen; /* Set if error has been reported. */
+ bool fndecl_seen; /* Set if one fn decl/definition has been seen already. */
+ tree clauses;
+ location_t loc;
};
static void c_parser_external_declaration (c_parser *);
static void c_parser_asm_definition (c_parser *);
static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
bool, bool, tree *, vec<c_token>,
- tree = NULL_TREE);
+ struct oacc_routine_data * = NULL,
+ bool * = NULL);
static void c_parser_static_assert_declaration_no_semi (c_parser *);
static void c_parser_static_assert_declaration (c_parser *);
-static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
- bool, bool, bool, enum c_lookahead_kind);
static struct c_typespec c_parser_enum_specifier (c_parser *);
static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
static tree c_parser_struct_declaration (c_parser *);
static struct c_typespec c_parser_typeof_specifier (c_parser *);
static tree c_parser_alignas_specifier (c_parser *);
-static struct c_declarator *c_parser_declarator (c_parser *, bool, c_dtr_syn,
- bool *);
static struct c_declarator *c_parser_direct_declarator (c_parser *, bool,
c_dtr_syn, bool *);
static struct c_declarator *c_parser_direct_declarator_inner (c_parser *,
@@ -1291,7 +1209,6 @@ static struct c_arg_info *c_parser_parms_list_declarator (c_parser *, tree,
static struct c_parm *c_parser_parameter_declaration (c_parser *, tree);
static tree c_parser_simple_asm_expr (c_parser *);
static tree c_parser_attributes (c_parser *);
-static struct c_type_name *c_parser_type_name (c_parser *);
static struct c_expr c_parser_initializer (c_parser *);
static struct c_expr c_parser_braced_init (c_parser *, tree, bool,
struct obstack *);
@@ -1305,7 +1222,7 @@ static void c_parser_statement (c_parser *, bool *);
static void c_parser_statement_after_labels (c_parser *, bool *,
vec<tree> * = NULL);
static void c_parser_if_statement (c_parser *, bool *, vec<tree> *);
-static void c_parser_switch_statement (c_parser *);
+static void c_parser_switch_statement (c_parser *, bool *);
static void c_parser_while_statement (c_parser *, bool, bool *);
static void c_parser_do_statement (c_parser *, bool);
static void c_parser_for_statement (c_parser *, bool, bool *);
@@ -1351,16 +1268,16 @@ static tree c_parser_omp_for_loop (location_t, c_parser *, enum tree_code,
static void c_parser_omp_taskwait (c_parser *);
static void c_parser_omp_taskyield (c_parser *);
static void c_parser_omp_cancel (c_parser *);
-static void c_parser_omp_cancellation_point (c_parser *);
enum pragma_context { pragma_external, pragma_struct, pragma_param,
pragma_stmt, pragma_compound };
static bool c_parser_pragma (c_parser *, enum pragma_context, bool *);
+static void c_parser_omp_cancellation_point (c_parser *, enum pragma_context);
static bool c_parser_omp_target (c_parser *, enum pragma_context, bool *);
static void c_parser_omp_end_declare_target (c_parser *);
static void c_parser_omp_declare (c_parser *, enum pragma_context);
static bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *);
-static void c_parser_oacc_routine (c_parser *parser, enum pragma_context);
+static void c_parser_oacc_routine (c_parser *, enum pragma_context);
/* These Objective-C parser functions are only ever called when
compiling Objective-C. */
@@ -1397,7 +1314,9 @@ static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool);
static void c_parser_cilk_grainsize (c_parser *, bool *);
-/* Parse a translation unit (C90 6.7, C99 6.9).
+static void c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass);
+
+/* Parse a translation unit (C90 6.7, C99 6.9, C11 6.9).
translation-unit:
external-declarations
@@ -1440,7 +1359,7 @@ c_parser_translation_unit (c_parser *parser)
error ("storage size of %q+D isn%'t known", decl);
}
-/* Parse an external declaration (C90 6.7, C99 6.9).
+/* Parse an external declaration (C90 6.7, C99 6.9, C11 6.9).
external-declaration:
function-definition
@@ -1539,6 +1458,7 @@ c_parser_external_declaration (c_parser *parser)
}
/* Else fall through, and yield a syntax error trying to parse
as a declaration or function definition. */
+ /* FALLTHRU */
default:
decl_or_fndef:
/* A declaration or a function definition (or, in Objective-C,
@@ -1552,11 +1472,11 @@ c_parser_external_declaration (c_parser *parser)
}
static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token>);
-static void c_finish_oacc_routine (c_parser *, tree, tree, bool, bool, bool);
+static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool);
/* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
- 6.7, 6.9.1). If FNDEF_OK is true, a function definition is
- accepted; otherwise (old-style parameter declarations) only other
+ 6.7, 6.9.1, C11 6.7, 6.9.1). If FNDEF_OK is true, a function definition
+ is accepted; otherwise (old-style parameter declarations) only other
declarations are accepted. If STATIC_ASSERT_OK is true, a static
assertion is accepted; otherwise (old-style parameter declarations)
it is not. If NESTED is true, we are inside a function or parsing
@@ -1570,6 +1490,8 @@ static void c_finish_oacc_routine (c_parser *, tree, tree, bool, bool, bool);
attributes; otherwise they may not.
OBJC_FOREACH_OBJECT_DECLARATION can be used to get back the parsed
declaration when parsing an Objective-C foreach statement.
+ FALLTHRU_ATTR_P is used to signal whether this function parsed
+ "__attribute__((fallthrough));".
declaration:
declaration-specifiers init-declarator-list[opt] ;
@@ -1597,6 +1519,8 @@ static void c_finish_oacc_routine (c_parser *, tree, tree, bool, bool, bool);
declaration-specifiers declarator declaration-list[opt]
compound-statement
+ attribute ;
+
Objective-C:
attributes objc-class-definition
attributes objc-category-definition
@@ -1623,7 +1547,17 @@ static void c_finish_oacc_routine (c_parser *, tree, tree, bool, bool, bool);
OpenMP:
declaration:
- threadprivate-directive */
+ threadprivate-directive
+
+ GIMPLE:
+
+ gimple-function-definition:
+ declaration-specifiers[opt] __GIMPLE (gimple-or-rtl-pass-list) declarator
+ declaration-list[opt] compound-statement
+
+ rtl-function-definition:
+ declaration-specifiers[opt] __RTL (gimple-or-rtl-pass-list) declarator
+ declaration-list[opt] compound-statement */
static void
c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
@@ -1631,7 +1565,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
bool nested, bool start_attr_ok,
tree *objc_foreach_object_declaration,
vec<c_token> omp_declare_simd_clauses,
- tree oacc_routine_clauses)
+ struct oacc_routine_data *oacc_routine_data,
+ bool *fallthru_attr_p)
{
struct c_declspecs *specs;
tree prefix_attrs;
@@ -1655,15 +1590,50 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
&& (!nested || !lookup_name (c_parser_peek_token (parser)->value)))
{
tree name = c_parser_peek_token (parser)->value;
- error_at (here, "unknown type name %qE", name);
- /* Give a hint to the user. This is not C++ with its implicit
- typedef. */
+
+ /* Issue a warning about NAME being an unknown type name, perhaps
+ with some kind of hint.
+ If the user forgot a "struct" etc, suggest inserting
+ it. Otherwise, attempt to look for misspellings. */
+ gcc_rich_location richloc (here);
if (tag_exists_p (RECORD_TYPE, name))
- inform (here, "use %<struct%> keyword to refer to the type");
+ {
+ /* This is not C++ with its implicit typedef. */
+ richloc.add_fixit_insert_before ("struct ");
+ error_at_rich_loc (&richloc,
+ "unknown type name %qE;"
+ " use %<struct%> keyword to refer to the type",
+ name);
+ }
else if (tag_exists_p (UNION_TYPE, name))
- inform (here, "use %<union%> keyword to refer to the type");
+ {
+ richloc.add_fixit_insert_before ("union ");
+ error_at_rich_loc (&richloc,
+ "unknown type name %qE;"
+ " use %<union%> keyword to refer to the type",
+ name);
+ }
else if (tag_exists_p (ENUMERAL_TYPE, name))
- inform (here, "use %<enum%> keyword to refer to the type");
+ {
+ richloc.add_fixit_insert_before ("enum ");
+ error_at_rich_loc (&richloc,
+ "unknown type name %qE;"
+ " use %<enum%> keyword to refer to the type",
+ name);
+ }
+ else
+ {
+ const char *hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_TYPENAME);
+ if (hint)
+ {
+ richloc.add_fixit_replace (hint);
+ error_at_rich_loc (&richloc,
+ "unknown type name %qE; did you mean %qs?",
+ name, hint);
+ }
+ else
+ error_at (here, "unknown type name %qE", name);
+ }
/* Parse declspecs normally to get a correct pointer type, but avoid
a further "fails to be a type name" error. Refuse nested functions
@@ -1687,12 +1657,22 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
c_parser_skip_to_end_of_block_or_statement (parser);
return;
}
+
finish_declspecs (specs);
bool auto_type_p = specs->typespec_word == cts_auto_type;
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
if (auto_type_p)
error_at (here, "%<__auto_type%> in empty declaration");
+ else if (specs->typespec_kind == ctsk_none
+ && attribute_fallthrough_p (specs->attrs))
+ {
+ if (fallthru_attr_p != NULL)
+ *fallthru_attr_p = true;
+ tree fn = build_call_expr_internal_loc (here, IFN_FALLTHROUGH,
+ void_type_node, 0);
+ add_stmt (fn);
+ }
else if (empty_ok)
shadow_tag (specs);
else
@@ -1701,9 +1681,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
pedwarn (here, 0, "empty declaration");
}
c_parser_consume_token (parser);
- if (oacc_routine_clauses)
- c_finish_oacc_routine (parser, NULL_TREE,
- oacc_routine_clauses, false, true, false);
+ if (oacc_routine_data)
+ c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
return;
}
@@ -1796,17 +1775,20 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
break;
}
}
-
+ else if (attribute_fallthrough_p (specs->attrs))
+ warning_at (here, OPT_Wattributes,
+ "%<fallthrough%> attribute not followed by %<;%>");
+
pending_xref_error ();
prefix_attrs = specs->attrs;
all_prefix_attrs = prefix_attrs;
specs->attrs = NULL_TREE;
- for (bool first = true;; first = false)
+ while (true)
{
struct c_declarator *declarator;
bool dummy = false;
timevar_id_t tv;
- tree fnbody;
+ tree fnbody = NULL_TREE;
/* Declaring either one or more declarators (in which case we
should diagnose if there were no declaration specifiers) or a
function definition (in which case the diagnostic for
@@ -1820,10 +1802,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
|| !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
omp_declare_simd_clauses);
- if (oacc_routine_clauses)
- c_finish_oacc_routine (parser, NULL_TREE,
- oacc_routine_clauses,
- false, first, false);
+ if (oacc_routine_data)
+ c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
c_parser_skip_to_end_of_block_or_statement (parser);
return;
}
@@ -1876,9 +1856,16 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
c_parser_consume_token (parser);
if (auto_type_p)
{
- start_init (NULL_TREE, asm_name, global_bindings_p ());
init_loc = c_parser_peek_token (parser)->location;
+ rich_location richloc (line_table, init_loc);
+ start_init (NULL_TREE, asm_name, global_bindings_p (), &richloc);
+ /* A parameter is initialized, which is invalid. Don't
+ attempt to instrument the initializer. */
+ int flag_sanitize_save = flag_sanitize;
+ if (nested && !empty_ok)
+ flag_sanitize = 0;
init = c_parser_expr_no_commas (parser, NULL);
+ flag_sanitize = flag_sanitize_save;
if (TREE_CODE (init.value) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND (init.value, 1)))
error_at (here,
@@ -1933,14 +1920,20 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
|| !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
c_finish_omp_declare_simd (parser, d, NULL_TREE,
omp_declare_simd_clauses);
- start_init (d, asm_name, global_bindings_p ());
init_loc = c_parser_peek_token (parser)->location;
+ rich_location richloc (line_table, init_loc);
+ start_init (d, asm_name, global_bindings_p (), &richloc);
+ /* A parameter is initialized, which is invalid. Don't
+ attempt to instrument the initializer. */
+ int flag_sanitize_save = flag_sanitize;
+ if (TREE_CODE (d) == PARM_DECL)
+ flag_sanitize = 0;
init = c_parser_initializer (parser);
+ flag_sanitize = flag_sanitize_save;
finish_init ();
}
- if (oacc_routine_clauses)
- c_finish_oacc_routine (parser, d, oacc_routine_clauses,
- false, first, false);
+ if (oacc_routine_data)
+ c_finish_oacc_routine (oacc_routine_data, d, false);
if (d != error_mark_node)
{
maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
@@ -1984,9 +1977,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
if (parms)
temp_pop_parm_decls ();
}
- if (oacc_routine_clauses)
- c_finish_oacc_routine (parser, d, oacc_routine_clauses,
- false, first, false);
+ if (oacc_routine_data)
+ c_finish_oacc_routine (oacc_routine_data, d, false);
if (d)
finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
NULL_TREE, asm_name);
@@ -2074,7 +2066,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
tv = TV_PARSE_INLINE;
else
tv = TV_PARSE_FUNC;
- timevar_push (tv);
+ auto_timevar at (g_timer, tv);
/* Parse old-style parameter declarations. ??? Attributes are
not allowed to start declaration specifiers here because of a
@@ -2097,14 +2089,44 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
|| !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
omp_declare_simd_clauses);
- if (oacc_routine_clauses)
- c_finish_oacc_routine (parser, current_function_decl,
- oacc_routine_clauses, false, first, true);
+ if (oacc_routine_data)
+ c_finish_oacc_routine (oacc_routine_data, current_function_decl, true);
DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
= c_parser_peek_token (parser)->location;
- fnbody = c_parser_compound_statement (parser);
- if (flag_cilkplus && contains_array_notation_expr (fnbody))
- fnbody = expand_array_notation_exprs (fnbody);
+
+ /* If the definition was marked with __GIMPLE then parse the
+ function body as GIMPLE. */
+ if (specs->gimple_p)
+ {
+ cfun->pass_startwith = specs->gimple_or_rtl_pass;
+ bool saved = in_late_binary_op;
+ in_late_binary_op = true;
+ c_parser_parse_gimple_body (parser);
+ in_late_binary_op = saved;
+ }
+ /* Similarly, if it was marked with __RTL, use the RTL parser now,
+ consuming the function body. */
+ else if (specs->rtl_p)
+ {
+ c_parser_parse_rtl_body (parser, specs->gimple_or_rtl_pass);
+
+ /* Normally, store_parm_decls sets next_is_function_body,
+ anticipating a function body. We need a push_scope/pop_scope
+ pair to flush out this state, or subsequent function parsing
+ will go wrong. */
+ push_scope ();
+ pop_scope ();
+
+ finish_function ();
+ return;
+ }
+ else
+ {
+ fnbody = c_parser_compound_statement (parser);
+ if (flag_cilkplus && contains_array_notation_expr (fnbody))
+ fnbody = expand_array_notation_exprs (fnbody);
+ }
+ tree fndecl = current_function_decl;
if (nested)
{
tree decl = current_function_decl;
@@ -2120,11 +2142,14 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
}
else
{
- add_stmt (fnbody);
+ if (fnbody)
+ add_stmt (fnbody);
finish_function ();
}
+ /* Get rid of the empty stmt list for GIMPLE. */
+ if (specs->gimple_p)
+ DECL_SAVED_TREE (fndecl) = NULL_TREE;
- timevar_pop (tv);
break;
}
}
@@ -2237,7 +2262,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
}
/* Parse some declaration specifiers (possibly none) (C90 6.5, C99
- 6.7), adding them to SPECS (which may already include some).
+ 6.7, C11 6.7), adding them to SPECS (which may already include some).
Storage class specifiers are accepted iff SCSPEC_OK; type
specifiers are accepted iff TYPESPEC_OK; alignment specifiers are
accepted iff ALIGNSPEC_OK; attributes are accepted at the start
@@ -2254,7 +2279,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
handled as storage class specifiers, as is __thread. Alignment
specifiers are from C11.
- C90 6.5.1, C99 6.7.1:
+ C90 6.5.1, C99 6.7.1, C11 6.7.1:
storage-class-specifier:
typedef
extern
@@ -2265,14 +2290,14 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
(_Thread_local is new in C11.)
- C99 6.7.4:
+ C99 6.7.4, C11 6.7.4:
function-specifier:
inline
_Noreturn
(_Noreturn is new in C11.)
- C90 6.5.2, C99 6.7.2:
+ C90 6.5.2, C99 6.7.2, C11 6.7.2:
type-specifier:
void
char
@@ -2294,7 +2319,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
(_Bool and _Complex are new in C99.)
(atomic-type-specifier is new in C11.)
- C90 6.5.3, C99 6.7.3:
+ C90 6.5.3, C99 6.7.3, C11 6.7.3:
type-qualifier:
const
@@ -2345,7 +2370,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
objc-protocol-refs
*/
-static void
+void
c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
bool scspec_ok, bool typespec_ok, bool start_attr_ok,
bool alignspec_ok, bool auto_type_ok,
@@ -2488,6 +2513,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
case RID_DFLOAT32:
case RID_DFLOAT64:
case RID_DFLOAT128:
+ CASE_RID_FLOATN_NX:
case RID_BOOL:
case RID_FRACT:
case RID_ACCUM:
@@ -2549,10 +2575,6 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
and objc_types_are_equivalent may also need updates. */
if (c_dialect_objc ())
sorry ("%<_Atomic%> in Objective-C");
- /* C parser handling of OpenMP constructs needs checking for
- correct lvalue-to-rvalue conversions. */
- if (flag_openmp)
- sorry ("%<_Atomic%> with OpenMP");
if (flag_isoc99)
pedwarn_c99 (loc, OPT_Wpedantic,
"ISO C99 does not support the %<_Atomic%> qualifier");
@@ -2613,6 +2635,20 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
align = c_parser_alignas_specifier (parser);
declspecs_add_alignas (loc, specs, align);
break;
+ case RID_GIMPLE:
+ if (! flag_gimple)
+ error_at (loc, "%<__GIMPLE%> only valid with -fgimple");
+ c_parser_consume_token (parser);
+ specs->gimple_p = true;
+ specs->locations[cdw_gimple] = loc;
+ specs->gimple_or_rtl_pass = c_parser_gimple_or_rtl_pass_list (parser);
+ break;
+ case RID_RTL:
+ c_parser_consume_token (parser);
+ specs->rtl_p = true;
+ specs->locations[cdw_rtl] = loc;
+ specs->gimple_or_rtl_pass = c_parser_gimple_or_rtl_pass_list (parser);
+ break;
default:
goto out;
}
@@ -2620,7 +2656,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
out: ;
}
-/* Parse an enum specifier (C90 6.5.2.2, C99 6.7.2.2).
+/* Parse an enum specifier (C90 6.5.2.2, C99 6.7.2.2, C11 6.7.2.2).
enum-specifier:
enum attributes[opt] identifier[opt] { enumerator-list } attributes[opt]
@@ -2658,7 +2694,6 @@ c_parser_enum_specifier (c_parser *parser)
location_t enum_loc;
location_t ident_loc = UNKNOWN_LOCATION; /* Quiet warning. */
gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
- enum_loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
attrs = c_parser_attributes (parser);
enum_loc = c_parser_peek_token (parser)->location;
@@ -2784,7 +2819,7 @@ c_parser_enum_specifier (c_parser *parser)
return ret;
}
-/* Parse a struct or union specifier (C90 6.5.2.1, C99 6.7.2.1).
+/* Parse a struct or union specifier (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1).
struct-or-union-specifier:
struct-or-union attributes[opt] identifier[opt]
@@ -2979,8 +3014,8 @@ c_parser_struct_or_union_specifier (c_parser *parser)
return ret;
}
-/* Parse a struct-declaration (C90 6.5.2.1, C99 6.7.2.1), *without*
- the trailing semicolon.
+/* Parse a struct-declaration (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1),
+ *without* the trailing semicolon.
struct-declaration:
specifier-qualifier-list struct-declarator-list
@@ -3265,13 +3300,13 @@ c_parser_alignas_specifier (c_parser * parser)
}
/* Parse a declarator, possibly an abstract declarator (C90 6.5.4,
- 6.5.5, C99 6.7.5, 6.7.6). If TYPE_SEEN_P then a typedef name may
- be redeclared; otherwise it may not. KIND indicates which kind of
- declarator is wanted. Returns a valid declarator except in the
- case of a syntax error in which case NULL is returned. *SEEN_ID is
- set to true if an identifier being declared is seen; this is used
- to diagnose bad forms of abstract array declarators and to
- determine whether an identifier list is syntactically permitted.
+ 6.5.5, C99 6.7.5, 6.7.6, C11 6.7.6, 6.7.7). If TYPE_SEEN_P then
+ a typedef name may be redeclared; otherwise it may not. KIND
+ indicates which kind of declarator is wanted. Returns a valid
+ declarator except in the case of a syntax error in which case NULL is
+ returned. *SEEN_ID is set to true if an identifier being declared is
+ seen; this is used to diagnose bad forms of abstract array declarators
+ and to determine whether an identifier list is syntactically permitted.
declarator:
pointer[opt] direct-declarator
@@ -3347,7 +3382,7 @@ c_parser_alignas_specifier (c_parser * parser)
This function also accepts an omitted abstract declarator as being
an abstract declarator, although not part of the formal syntax. */
-static struct c_declarator *
+struct c_declarator *
c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
bool *seen_id)
{
@@ -3430,6 +3465,7 @@ c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
&& c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
{
struct c_declarator *inner = build_id_declarator (NULL_TREE);
+ inner->id_loc = c_parser_peek_token (parser)->location;
return c_parser_direct_declarator_inner (parser, *seen_id, inner);
}
@@ -3631,7 +3667,8 @@ c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs)
&& c_parser_peek_2nd_token (parser)->type != CPP_NAME
&& c_parser_peek_2nd_token (parser)->type != CPP_MULT
&& c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
- && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_SQUARE)
+ && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_SQUARE
+ && c_parser_peek_2nd_token (parser)->type != CPP_KEYWORD)
{
tree list = NULL_TREE, *nextp = &list;
while (c_parser_next_token_is (parser, CPP_NAME)
@@ -3806,7 +3843,18 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
c_parser_set_source_position_from_token (token);
if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
{
- error_at (token->location, "unknown type name %qE", token->value);
+ const char *hint = lookup_name_fuzzy (token->value,
+ FUZZY_LOOKUP_TYPENAME);
+ if (hint)
+ {
+ gcc_rich_location richloc (token->location);
+ richloc.add_fixit_replace (hint);
+ error_at_rich_loc (&richloc,
+ "unknown type name %qE; did you mean %qs?",
+ token->value, hint);
+ }
+ else
+ error_at (token->location, "unknown type name %qE", token->value);
parser->error = true;
}
/* ??? In some Objective-C cases '...' isn't applicable so there
@@ -3948,6 +3996,7 @@ c_parser_attribute_any_word (c_parser *parser)
case RID_DFLOAT32:
case RID_DFLOAT64:
case RID_DFLOAT128:
+ CASE_RID_FLOATN_NX:
case RID_BOOL:
case RID_FRACT:
case RID_ACCUM:
@@ -4223,13 +4272,13 @@ c_parser_attributes (c_parser *parser)
return attrs;
}
-/* Parse a type name (C90 6.5.5, C99 6.7.6).
+/* Parse a type name (C90 6.5.5, C99 6.7.6, C11 6.7.7).
type-name:
specifier-qualifier-list abstract-declarator[opt]
*/
-static struct c_type_name *
+struct c_type_name *
c_parser_type_name (c_parser *parser)
{
struct c_declspecs *specs = build_null_declspecs ();
@@ -4259,7 +4308,7 @@ c_parser_type_name (c_parser *parser)
return ret;
}
-/* Parse an initializer (C90 6.5.7, C99 6.7.8).
+/* Parse an initializer (C90 6.5.7, C99 6.7.8, C11 6.7.9).
initializer:
assignment-expression
@@ -4319,6 +4368,11 @@ c_parser_initializer (c_parser *parser)
}
}
+/* The location of the last comma within the current initializer list,
+ or UNKNOWN_LOCATION if not within one. */
+
+location_t last_init_list_comma;
+
/* Parse a braced initializer list. TYPE is the type specified for a
compound literal, and NULL_TREE for other initializers and for
nested braced lists. NESTED_P is true for nested braced lists,
@@ -4356,7 +4410,10 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
if (parser->error)
break;
if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
+ {
+ last_init_list_comma = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ }
else
break;
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
@@ -4370,13 +4427,13 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
ret.original_code = ERROR_MARK;
ret.original_type = NULL;
c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>");
- pop_init_level (brace_loc, 0, &braced_init_obstack);
+ pop_init_level (brace_loc, 0, &braced_init_obstack, last_init_list_comma);
obstack_free (&braced_init_obstack, NULL);
return ret;
}
location_t close_loc = next_tok->location;
c_parser_consume_token (parser);
- ret = pop_init_level (brace_loc, 0, &braced_init_obstack);
+ ret = pop_init_level (brace_loc, 0, &braced_init_obstack, close_loc);
obstack_free (&braced_init_obstack, NULL);
set_c_expr_source_range (&ret, brace_loc, close_loc);
return ret;
@@ -4396,6 +4453,7 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
/* Old-style structure member designator. */
set_init_label (c_parser_peek_token (parser)->location,
c_parser_peek_token (parser)->value,
+ c_parser_peek_token (parser)->location,
braced_init_obstack);
/* Use the colon as the error location. */
pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_Wpedantic,
@@ -4425,6 +4483,7 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
if (c_parser_next_token_is (parser, CPP_NAME))
{
set_init_label (des_loc, c_parser_peek_token (parser)->value,
+ c_parser_peek_token (parser)->location,
braced_init_obstack);
c_parser_consume_token (parser);
}
@@ -4611,7 +4670,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after,
}
/* Parse a compound statement (possibly a function body) (C90 6.6.2,
- C99 6.8.2).
+ C99 6.8.2, C11 6.8.2).
compound-statement:
{ block-item-list[opt] }
@@ -4778,12 +4837,14 @@ c_parser_compound_statement_nostart (c_parser *parser)
{
last_label = false;
mark_valid_location_for_stdc_pragma (false);
+ bool fallthru_attr_p = false;
c_parser_declaration_or_fndef (parser, true, true, true, true,
- true, NULL, vNULL);
- if (last_stmt)
+ true, NULL, vNULL, NULL,
+ &fallthru_attr_p);
+ if (last_stmt && !fallthru_attr_p)
pedwarn_c90 (loc, OPT_Wdeclaration_after_statement,
"ISO C90 forbids mixed declarations and code");
- last_stmt = false;
+ last_stmt = fallthru_attr_p;
}
else if (!last_label
&& c_parser_next_token_is_keyword (parser, RID_EXTENSION))
@@ -4879,7 +4940,7 @@ c_parser_all_labels (c_parser *parser)
c_parser_label (parser);
}
-/* Parse a label (C90 6.6.1, C99 6.8.1).
+/* Parse a label (C90 6.6.1, C99 6.8.1, C11 6.8.1).
label:
identifier : attributes[opt]
@@ -4900,6 +4961,11 @@ c_parser_label (c_parser *parser)
{
location_t loc1 = c_parser_peek_token (parser)->location;
tree label = NULL_TREE;
+
+ /* Remember whether this case or a user-defined label is allowed to fall
+ through to. */
+ bool fallthrough_p = c_parser_peek_token (parser)->flags & PREV_FALLTHROUGH;
+
if (c_parser_next_token_is_keyword (parser, RID_CASE))
{
tree exp1, exp2;
@@ -4946,6 +5012,33 @@ c_parser_label (c_parser *parser)
}
if (label)
{
+ if (TREE_CODE (label) == LABEL_EXPR)
+ FALLTHROUGH_LABEL_P (LABEL_EXPR_LABEL (label)) = fallthrough_p;
+ else
+ FALLTHROUGH_LABEL_P (CASE_LABEL (label)) = fallthrough_p;
+
+ /* Allow '__attribute__((fallthrough));'. */
+ if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+ {
+ location_t loc = c_parser_peek_token (parser)->location;
+ tree attrs = c_parser_attributes (parser);
+ if (attribute_fallthrough_p (attrs))
+ {
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ tree fn = build_call_expr_internal_loc (loc,
+ IFN_FALLTHROUGH,
+ void_type_node, 0);
+ add_stmt (fn);
+ }
+ else
+ warning_at (loc, OPT_Wattributes, "%<fallthrough%> attribute "
+ "not followed by %<;%>");
+ }
+ else if (attrs != NULL_TREE)
+ warning_at (loc, OPT_Wattributes, "only attribute %<fallthrough%>"
+ " can be applied to a null statement");
+ }
if (c_parser_next_tokens_start_declaration (parser))
{
error_at (c_parser_peek_token (parser)->location,
@@ -4960,7 +5053,7 @@ c_parser_label (c_parser *parser)
}
}
-/* Parse a statement (C90 6.6, C99 6.8).
+/* Parse a statement (C90 6.6, C99 6.8, C11 6.8).
statement:
labeled-statement
@@ -4999,6 +5092,9 @@ c_parser_label (c_parser *parser)
jump-statement:
goto * expression ;
+ expression-statement:
+ attributes ;
+
Objective-C:
statement:
@@ -5138,7 +5234,7 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
c_parser_if_statement (parser, if_p, chain);
break;
case RID_SWITCH:
- c_parser_switch_statement (parser);
+ c_parser_switch_statement (parser, if_p);
break;
case RID_WHILE:
c_parser_while_statement (parser, false, if_p);
@@ -5260,6 +5356,31 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
gcc_assert (c_dialect_objc ());
c_parser_objc_synchronized_statement (parser);
break;
+ case RID_ATTRIBUTE:
+ {
+ /* Allow '__attribute__((fallthrough));'. */
+ tree attrs = c_parser_attributes (parser);
+ if (attribute_fallthrough_p (attrs))
+ {
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ tree fn = build_call_expr_internal_loc (loc,
+ IFN_FALLTHROUGH,
+ void_type_node, 0);
+ add_stmt (fn);
+ /* Eat the ';'. */
+ c_parser_consume_token (parser);
+ }
+ else
+ warning_at (loc, OPT_Wattributes,
+ "%<fallthrough%> attribute not followed "
+ "by %<;%>");
+ }
+ else if (attrs != NULL_TREE)
+ warning_at (loc, OPT_Wattributes, "only attribute %<fallthrough%>"
+ " can be applied to a null statement");
+ break;
+ }
default:
goto expr_stmt;
}
@@ -5425,7 +5546,44 @@ c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo,
return c_end_compound_stmt (body_loc, block, flag_isoc99);
}
-/* Parse an if statement (C90 6.6.4, C99 6.8.4).
+/* We might need to reclassify any previously-lexed identifier, e.g.
+ when we've left a for loop with an if-statement without else in the
+ body - we might have used a wrong scope for the token. See PR67784. */
+
+static void
+c_parser_maybe_reclassify_token (c_parser *parser)
+{
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ c_token *token = c_parser_peek_token (parser);
+
+ if (token->id_kind != C_ID_CLASSNAME)
+ {
+ tree decl = lookup_name (token->value);
+
+ token->id_kind = C_ID_ID;
+ if (decl)
+ {
+ if (TREE_CODE (decl) == TYPE_DECL)
+ token->id_kind = C_ID_TYPENAME;
+ }
+ else if (c_dialect_objc ())
+ {
+ tree objc_interface_decl = objc_is_class_name (token->value);
+ /* Objective-C class names are in the same namespace as
+ variables and typedefs, and hence are shadowed by local
+ declarations. */
+ if (objc_interface_decl)
+ {
+ token->value = objc_interface_decl;
+ token->id_kind = C_ID_CLASSNAME;
+ }
+ }
+ }
+ }
+}
+
+/* Parse an if statement (C90 6.6.4, C99 6.8.4, C11 6.8.4).
if-statement:
if ( expression ) statement
@@ -5505,7 +5663,7 @@ c_parser_if_statement (c_parser *parser, bool *if_p, vec<tree> *chain)
/* Diagnose an ambiguous else if if-then-else is nested inside
if-then. */
if (nested_if)
- warning_at (loc, OPT_Wparentheses,
+ warning_at (loc, OPT_Wdangling_else,
"suggest explicit braces to avoid ambiguous %<else%>");
if (warn_duplicated_cond)
@@ -5523,16 +5681,17 @@ c_parser_if_statement (c_parser *parser, bool *if_p, vec<tree> *chain)
if (flag_cilkplus && contains_array_notation_expr (if_stmt))
if_stmt = fix_conditional_array_notations (if_stmt);
add_stmt (if_stmt);
+ c_parser_maybe_reclassify_token (parser);
}
-/* Parse a switch statement (C90 6.6.4, C99 6.8.4).
+/* Parse a switch statement (C90 6.6.4, C99 6.8.4, C11 6.8.4).
switch-statement:
switch (expression) statement
*/
static void
-c_parser_switch_statement (c_parser *parser)
+c_parser_switch_statement (c_parser *parser, bool *if_p)
{
struct c_expr ce;
tree block, expr, body, save_break;
@@ -5563,11 +5722,12 @@ c_parser_switch_statement (c_parser *parser)
{
switch_cond_loc = UNKNOWN_LOCATION;
expr = error_mark_node;
+ ce.original_type = error_mark_node;
}
c_start_case (switch_loc, switch_cond_loc, expr, explicit_cast_p);
save_break = c_break_label;
c_break_label = NULL_TREE;
- body = c_parser_c99_block_statement (parser, NULL/*if??*/);
+ body = c_parser_c99_block_statement (parser, if_p);
c_finish_case (body, ce.original_type);
if (c_break_label)
{
@@ -5578,9 +5738,10 @@ c_parser_switch_statement (c_parser *parser)
}
c_break_label = save_break;
add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99));
+ c_parser_maybe_reclassify_token (parser);
}
-/* Parse a while statement (C90 6.6.5, C99 6.8.5).
+/* Parse a while statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
while-statement:
while (expression) statement
@@ -5620,6 +5781,7 @@ c_parser_while_statement (c_parser *parser, bool ivdep, bool *if_p)
body = c_parser_c99_block_statement (parser, if_p);
c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true);
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
+ c_parser_maybe_reclassify_token (parser);
token_indent_info next_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
@@ -5629,7 +5791,7 @@ c_parser_while_statement (c_parser *parser, bool ivdep, bool *if_p)
c_cont_label = save_cont;
}
-/* Parse a do statement (C90 6.6.5, C99 6.8.5).
+/* Parse a do statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
do-statement:
do statement while ( expression ) ;
@@ -5673,7 +5835,7 @@ c_parser_do_statement (c_parser *parser, bool ivdep)
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
}
-/* Parse a for statement (C90 6.6.5, C99 6.8.5).
+/* Parse a for statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
for-statement:
for ( expression[opt] ; expression[opt] ; expression[opt] ) statement
@@ -5916,38 +6078,7 @@ c_parser_for_statement (c_parser *parser, bool ivdep, bool *if_p)
else
c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99 || c_dialect_objc ()));
-
- /* We might need to reclassify any previously-lexed identifier, e.g.
- when we've left a for loop with an if-statement without else in the
- body - we might have used a wrong scope for the token. See PR67784. */
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- c_token *token = c_parser_peek_token (parser);
-
- if (token->id_kind != C_ID_CLASSNAME)
- {
- tree decl = lookup_name (token->value);
-
- token->id_kind = C_ID_ID;
- if (decl)
- {
- if (TREE_CODE (decl) == TYPE_DECL)
- token->id_kind = C_ID_TYPENAME;
- }
- else if (c_dialect_objc ())
- {
- tree objc_interface_decl = objc_is_class_name (token->value);
- /* Objective-C class names are in the same namespace as
- variables and typedefs, and hence are shadowed by local
- declarations. */
- if (objc_interface_decl)
- {
- token->value = objc_interface_decl;
- token->id_kind = C_ID_CLASSNAME;
- }
- }
- }
- }
+ c_parser_maybe_reclassify_token (parser);
token_indent_info next_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
@@ -6040,8 +6171,8 @@ c_parser_asm_statement (c_parser *parser)
{
if (!c_parser_require (parser, CPP_COLON,
is_goto
- ? "expected %<:%>"
- : "expected %<:%> or %<)%>"))
+ ? G_("expected %<:%>")
+ : G_("expected %<:%> or %<)%>")))
goto error_close_paren;
/* Once past any colon, we're no longer a simple asm. */
@@ -6230,9 +6361,9 @@ c_parser_asm_goto_operands (c_parser *parser)
}
/* Parse an expression other than a compound expression; that is, an
- assignment expression (C90 6.3.16, C99 6.5.16). If AFTER is not
- NULL then it is an Objective-C message expression which is the
- primary-expression starting the expression as an initializer.
+ assignment expression (C90 6.3.16, C99 6.5.16, C11 6.5.16). If
+ AFTER is not NULL then it is an Objective-C message expression which
+ is the primary-expression starting the expression as an initializer.
assignment-expression:
conditional-expression
@@ -6313,8 +6444,8 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
return ret;
}
-/* Parse a conditional expression (C90 6.3.15, C99 6.5.15). If AFTER
- is not NULL then it is an Objective-C message expression which is
+/* Parse a conditional expression (C90 6.3.15, C99 6.5.15, C11 6.5.15). If
+ AFTER is not NULL then it is an Objective-C message expression which is
the primary-expression starting the expression as an initializer.
conditional-expression:
@@ -6352,14 +6483,17 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
tree eptype = NULL_TREE;
middle_loc = c_parser_peek_token (parser)->location;
- pedwarn (middle_loc, OPT_Wpedantic,
+ pedwarn (middle_loc, OPT_Wpedantic,
"ISO C forbids omitting the middle term of a ?: expression");
- warn_for_omitted_condop (middle_loc, cond.value);
if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
{
eptype = TREE_TYPE (cond.value);
cond.value = TREE_OPERAND (cond.value, 0);
}
+ tree e = cond.value;
+ while (TREE_CODE (e) == COMPOUND_EXPR)
+ e = TREE_OPERAND (e, 1);
+ warn_for_omitted_condop (middle_loc, e);
/* Make sure first operand is calculated only once. */
exp1.value = c_save_expr (default_conversion (cond.value));
if (eptype)
@@ -6424,9 +6558,9 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
}
/* Parse a binary expression; that is, a logical-OR-expression (C90
- 6.3.5-6.3.14, C99 6.5.5-6.5.14). If AFTER is not NULL then it is
- an Objective-C message expression which is the primary-expression
- starting the expression as an initializer.
+ 6.3.5-6.3.14, C99 6.5.5-6.5.14, C11 6.5.5-6.5.14). If AFTER is not
+ NULL then it is an Objective-C message expression which is the
+ primary-expression starting the expression as an initializer.
OMP_ATOMIC_LHS is NULL, unless parsing OpenMP #pragma omp atomic,
when it should be the unfolded lhs. In a valid OpenMP source,
@@ -6698,8 +6832,8 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
#undef POP
}
-/* Parse a cast expression (C90 6.3.4, C99 6.5.4). If AFTER is not
- NULL then it is an Objective-C message expression which is the
+/* Parse a cast expression (C90 6.3.4, C99 6.5.4, C11 6.5.4). If AFTER
+ is not NULL then it is an Objective-C message expression which is the
primary-expression starting the expression as an initializer.
cast-expression:
@@ -6759,7 +6893,7 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
return c_parser_unary_expression (parser);
}
-/* Parse an unary expression (C90 6.3.3, C99 6.5.3).
+/* Parse an unary expression (C90 6.3.3, C99 6.5.3, C11 6.5.3).
unary-expression:
postfix-expression
@@ -7079,9 +7213,10 @@ c_parser_alignof_expression (c_parser *parser)
mark_exp_read (expr.value);
c_inhibit_evaluation_warnings--;
in_alignof--;
- pedwarn (start_loc,
- OPT_Wpedantic, "ISO C does not allow %<%E (expression)%>",
- alignof_spelling);
+ if (is_c11_alignof)
+ pedwarn (start_loc,
+ OPT_Wpedantic, "ISO C does not allow %<%E (expression)%>",
+ alignof_spelling);
ret.value = c_alignof_expr (start_loc, expr.value);
ret.original_code = ERROR_MARK;
ret.original_type = NULL;
@@ -7176,7 +7311,6 @@ struct c_generic_association
static struct c_expr
c_parser_generic_selection (c_parser *parser)
{
- vec<c_generic_association> associations = vNULL;
struct c_expr selector, error_expr;
tree selector_type;
struct c_generic_association matched_assoc;
@@ -7233,6 +7367,7 @@ c_parser_generic_selection (c_parser *parser)
return error_expr;
}
+ auto_vec<c_generic_association> associations;
while (1)
{
struct c_generic_association assoc, *iter;
@@ -7253,13 +7388,13 @@ c_parser_generic_selection (c_parser *parser)
if (type_name == NULL)
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- goto error_exit;
+ return error_expr;
}
assoc.type = groktypename (type_name, NULL, NULL);
if (assoc.type == error_mark_node)
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- goto error_exit;
+ return error_expr;
}
if (TREE_CODE (assoc.type) == FUNCTION_TYPE)
@@ -7278,14 +7413,14 @@ c_parser_generic_selection (c_parser *parser)
if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- goto error_exit;
+ return error_expr;
}
assoc.expression = c_parser_expr_no_commas (parser, NULL);
if (assoc.expression.value == error_mark_node)
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- goto error_exit;
+ return error_expr;
}
for (ix = 0; associations.iterate (ix, &iter); ++ix)
@@ -7328,7 +7463,7 @@ c_parser_generic_selection (c_parser *parser)
else
{
error_at (assoc.type_location,
- "%<_Generic> selector matches multiple associations");
+ "%<_Generic%> selector matches multiple associations");
inform (matched_assoc.type_location,
"other match is here");
}
@@ -7341,8 +7476,6 @@ c_parser_generic_selection (c_parser *parser)
c_parser_consume_token (parser);
}
- associations.release ();
-
if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
@@ -7358,13 +7491,10 @@ c_parser_generic_selection (c_parser *parser)
}
return matched_assoc.expression;
-
- error_exit:
- associations.release ();
- return error_expr;
}
-/* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2).
+/* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2,
+ C11 6.5.1-6.5.2).
postfix-expression:
primary-expression
@@ -7452,6 +7582,9 @@ c_parser_postfix_expression (c_parser *parser)
case CPP_CHAR32:
case CPP_WCHAR:
expr.value = c_parser_peek_token (parser)->value;
+ /* For the purpose of warning when a pointer is compared with
+ a zero character constant. */
+ expr.original_type = char_type_node;
set_c_expr_source_range (&expr, tok_range);
c_parser_consume_token (parser);
break;
@@ -7698,8 +7831,9 @@ c_parser_postfix_expression (c_parser *parser)
accept sub structure and sub array references. */
if (c_parser_next_token_is (parser, CPP_NAME))
{
+ c_token *comp_tok = c_parser_peek_token (parser);
offsetof_ref = build_component_ref
- (loc, offsetof_ref, c_parser_peek_token (parser)->value);
+ (loc, offsetof_ref, comp_tok->value, comp_tok->location);
c_parser_consume_token (parser);
while (c_parser_next_token_is (parser, CPP_DOT)
|| c_parser_next_token_is (parser,
@@ -7725,9 +7859,10 @@ c_parser_postfix_expression (c_parser *parser)
c_parser_error (parser, "expected identifier");
break;
}
+ c_token *comp_tok = c_parser_peek_token (parser);
offsetof_ref = build_component_ref
- (loc, offsetof_ref,
- c_parser_peek_token (parser)->value);
+ (loc, offsetof_ref, comp_tok->value,
+ comp_tok->location);
c_parser_consume_token (parser);
}
else
@@ -8105,6 +8240,7 @@ c_parser_postfix_expression (c_parser *parser)
break;
}
/* Else fall through to report error. */
+ /* FALLTHRU */
default:
c_parser_error (parser, "expected expression");
expr.set_error ();
@@ -8137,7 +8273,8 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
tree type_expr = NULL_TREE;
bool type_expr_const = true;
check_compound_literal_type (type_loc, type_name);
- start_init (NULL_TREE, NULL, 0);
+ rich_location richloc (line_table, type_loc);
+ start_init (NULL_TREE, NULL, 0, &richloc);
type = groktypename (type_name, &type_expr, &type_expr_const);
start_loc = c_parser_peek_token (parser)->location;
if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
@@ -8166,7 +8303,9 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
set_c_expr_source_range (&expr, init.src_range);
expr.original_code = ERROR_MARK;
expr.original_type = NULL;
- if (type != error_mark_node && type_expr)
+ if (type != error_mark_node
+ && expr.value != error_mark_node
+ && type_expr)
{
if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
{
@@ -8204,7 +8343,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
{
struct c_expr orig_expr;
tree ident, idx;
- location_t sizeof_arg_loc[3];
+ location_t sizeof_arg_loc[3], comp_loc;
tree sizeof_arg[3];
unsigned int literal_zero_mask;
unsigned int i;
@@ -8282,18 +8421,15 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
expr.value, exprlist,
sizeof_arg,
sizeof_ptr_memacc_comptypes);
- if (warn_memset_transposed_args
- && TREE_CODE (expr.value) == FUNCTION_DECL
+ if (TREE_CODE (expr.value) == FUNCTION_DECL
&& DECL_BUILT_IN_CLASS (expr.value) == BUILT_IN_NORMAL
&& DECL_FUNCTION_CODE (expr.value) == BUILT_IN_MEMSET
- && vec_safe_length (exprlist) == 3
- && integer_zerop ((*exprlist)[2])
- && (literal_zero_mask & (1 << 2)) != 0
- && (!integer_zerop ((*exprlist)[1])
- || (literal_zero_mask & (1 << 1)) == 0))
- warning_at (expr_loc, OPT_Wmemset_transposed_args,
- "%<memset%> used with constant zero length parameter; "
- "this could be due to transposed parameters");
+ && vec_safe_length (exprlist) == 3)
+ {
+ tree arg0 = (*exprlist)[0];
+ tree arg2 = (*exprlist)[2];
+ warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask);
+ }
start = expr.get_start ();
finish = parser->tokens_buf[0].get_finish ();
@@ -8321,7 +8457,11 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
c_parser_consume_token (parser);
expr = default_function_array_conversion (expr_loc, expr);
if (c_parser_next_token_is (parser, CPP_NAME))
- ident = c_parser_peek_token (parser)->value;
+ {
+ c_token *comp_tok = c_parser_peek_token (parser);
+ ident = comp_tok->value;
+ comp_loc = comp_tok->location;
+ }
else
{
c_parser_error (parser, "expected identifier");
@@ -8333,7 +8473,8 @@ 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.value = build_component_ref (op_loc, expr.value, ident);
+ expr.value = build_component_ref (op_loc, expr.value, ident,
+ comp_loc);
set_c_expr_source_range (&expr, start, finish);
expr.original_code = ERROR_MARK;
if (TREE_CODE (expr.value) != COMPONENT_REF)
@@ -8353,7 +8494,11 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
c_parser_consume_token (parser);
expr = convert_lvalue_to_rvalue (expr_loc, expr, true, false);
if (c_parser_next_token_is (parser, CPP_NAME))
- ident = c_parser_peek_token (parser)->value;
+ {
+ c_token *comp_tok = c_parser_peek_token (parser);
+ ident = comp_tok->value;
+ comp_loc = comp_tok->location;
+ }
else
{
c_parser_error (parser, "expected identifier");
@@ -8369,7 +8514,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
build_indirect_ref (op_loc,
expr.value,
RO_ARROW),
- ident);
+ ident, comp_loc);
set_c_expr_source_range (&expr, start, finish);
expr.original_code = ERROR_MARK;
if (TREE_CODE (expr.value) != COMPONENT_REF)
@@ -8396,8 +8541,8 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
else
{
expr = default_function_array_read_conversion (expr_loc, expr);
- expr.value = build_unary_op (op_loc,
- POSTINCREMENT_EXPR, expr.value, 0);
+ expr.value = build_unary_op (op_loc, POSTINCREMENT_EXPR,
+ expr.value, false);
}
set_c_expr_source_range (&expr, start, finish);
expr.original_code = ERROR_MARK;
@@ -8415,8 +8560,8 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
else
{
expr = default_function_array_read_conversion (expr_loc, expr);
- expr.value = build_unary_op (op_loc,
- POSTDECREMENT_EXPR, expr.value, 0);
+ expr.value = build_unary_op (op_loc, POSTDECREMENT_EXPR,
+ expr.value, false);
}
set_c_expr_source_range (&expr, start, finish);
expr.original_code = ERROR_MARK;
@@ -8428,7 +8573,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
}
}
-/* Parse an expression (C90 6.3.17, C99 6.5.17).
+/* Parse an expression (C90 6.3.17, C99 6.5.17, C11 6.5.17).
expression:
assignment-expression
@@ -9559,6 +9704,7 @@ c_parser_objc_selector (c_parser *parser)
case RID_CHAR:
case RID_FLOAT:
case RID_DOUBLE:
+ CASE_RID_FLOATN_NX:
case RID_VOID:
case RID_BOOL:
case RID_ATOMIC:
@@ -10023,6 +10169,7 @@ static bool
c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
{
unsigned int id;
+ const char *construct = NULL;
id = c_parser_peek_token (parser)->pragma_kind;
gcc_assert (id != PRAGMA_NONE);
@@ -10034,24 +10181,48 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
return false;
case PRAGMA_OACC_ENTER_DATA:
+ if (context != pragma_compound)
+ {
+ construct = "acc enter data";
+ in_compound:
+ if (context == pragma_stmt)
+ {
+ error_at (c_parser_peek_token (parser)->location,
+ "%<#pragma %s%> may only be used in compound "
+ "statements", construct);
+ c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+ return false;
+ }
+ goto bad_stmt;
+ }
c_parser_oacc_enter_exit_data (parser, true);
return false;
case PRAGMA_OACC_EXIT_DATA:
+ if (context != pragma_compound)
+ {
+ construct = "acc exit data";
+ goto in_compound;
+ }
c_parser_oacc_enter_exit_data (parser, false);
return false;
case PRAGMA_OACC_ROUTINE:
+ if (context != pragma_external)
+ {
+ error_at (c_parser_peek_token (parser)->location,
+ "%<#pragma acc routine%> must be at file scope");
+ c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+ return false;
+ }
c_parser_oacc_routine (parser, context);
return false;
case PRAGMA_OACC_UPDATE:
if (context != pragma_compound)
{
- if (context == pragma_stmt)
- c_parser_error (parser, "%<#pragma acc update%> may only be "
- "used in compound statements");
- goto bad_stmt;
+ construct = "acc update";
+ goto in_compound;
}
c_parser_oacc_update (parser);
return false;
@@ -10059,10 +10230,8 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
case PRAGMA_OMP_BARRIER:
if (context != pragma_compound)
{
- if (context == pragma_stmt)
- c_parser_error (parser, "%<#pragma omp barrier%> may only be "
- "used in compound statements");
- goto bad_stmt;
+ construct = "omp barrier";
+ goto in_compound;
}
c_parser_omp_barrier (parser);
return false;
@@ -10070,10 +10239,8 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
case PRAGMA_OMP_FLUSH:
if (context != pragma_compound)
{
- if (context == pragma_stmt)
- c_parser_error (parser, "%<#pragma omp flush%> may only be "
- "used in compound statements");
- goto bad_stmt;
+ construct = "omp flush";
+ goto in_compound;
}
c_parser_omp_flush (parser);
return false;
@@ -10081,10 +10248,8 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
case PRAGMA_OMP_TASKWAIT:
if (context != pragma_compound)
{
- if (context == pragma_stmt)
- c_parser_error (parser, "%<#pragma omp taskwait%> may only be "
- "used in compound statements");
- goto bad_stmt;
+ construct = "omp taskwait";
+ goto in_compound;
}
c_parser_omp_taskwait (parser);
return false;
@@ -10092,10 +10257,8 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
case PRAGMA_OMP_TASKYIELD:
if (context != pragma_compound)
{
- if (context == pragma_stmt)
- c_parser_error (parser, "%<#pragma omp taskyield%> may only be "
- "used in compound statements");
- goto bad_stmt;
+ construct = "omp taskyield";
+ goto in_compound;
}
c_parser_omp_taskyield (parser);
return false;
@@ -10103,23 +10266,14 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
case PRAGMA_OMP_CANCEL:
if (context != pragma_compound)
{
- if (context == pragma_stmt)
- c_parser_error (parser, "%<#pragma omp cancel%> may only be "
- "used in compound statements");
- goto bad_stmt;
+ construct = "omp cancel";
+ goto in_compound;
}
c_parser_omp_cancel (parser);
return false;
case PRAGMA_OMP_CANCELLATION_POINT:
- if (context != pragma_compound)
- {
- if (context == pragma_stmt)
- c_parser_error (parser, "%<#pragma omp cancellation point%> may "
- "only be used in compound statements");
- goto bad_stmt;
- }
- c_parser_omp_cancellation_point (parser);
+ c_parser_omp_cancellation_point (parser, context);
return false;
case PRAGMA_OMP_THREADPRIVATE:
@@ -10140,7 +10294,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
return false;
- case PRAGMA_OMP_DECLARE_REDUCTION:
+ case PRAGMA_OMP_DECLARE:
c_parser_omp_declare (parser, context);
return false;
@@ -10194,6 +10348,14 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
c_parser_cilk_grainsize (parser, if_p);
return false;
+ case PRAGMA_OACC_WAIT:
+ if (context != pragma_compound)
+ {
+ construct = "acc wait";
+ goto in_compound;
+ }
+ /* FALL THROUGH. */
+
default:
if (id < PRAGMA_FIRST_EXTERNAL)
{
@@ -10617,9 +10779,12 @@ c_parser_omp_variable_list (c_parser *parser,
t = error_mark_node;
break;
}
- tree ident = c_parser_peek_token (parser)->value;
+
+ c_token *comp_tok = c_parser_peek_token (parser);
+ tree ident = comp_tok->value;
+ location_t comp_loc = comp_tok->location;
c_parser_consume_token (parser);
- t = build_component_ref (op_loc, t, ident);
+ t = build_component_ref (op_loc, t, ident, comp_loc);
}
/* FALLTHROUGH */
case OMP_CLAUSE_DEPEND:
@@ -10631,8 +10796,12 @@ c_parser_omp_variable_list (c_parser *parser,
c_parser_consume_token (parser);
if (!c_parser_next_token_is (parser, CPP_COLON))
{
- low_bound = c_parser_expression (parser).value;
- mark_exp_read (low_bound);
+ location_t expr_loc
+ = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr,
+ false, true);
+ low_bound = expr.value;
}
if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
length = integer_one_node;
@@ -10647,8 +10816,12 @@ c_parser_omp_variable_list (c_parser *parser,
}
if (!c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
{
- length = c_parser_expression (parser).value;
- mark_exp_read (length);
+ location_t expr_loc
+ = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr,
+ false, true);
+ length = expr.value;
}
}
/* Look for the closing `]'. */
@@ -10833,6 +11006,7 @@ c_parser_omp_clause_collapse (c_parser *parser, tree list)
location_t loc;
check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
+ check_no_duplicate_clause (list, OMP_CLAUSE_TILE, "tile");
loc = c_parser_peek_token (parser)->location;
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
@@ -11170,8 +11344,9 @@ c_parser_omp_clause_num_gangs (c_parser *parser, tree list)
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
location_t expr_loc = c_parser_peek_token (parser)->location;
- tree c, t = c_parser_expression (parser).value;
- mark_exp_read (t);
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -11214,8 +11389,9 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list)
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
location_t expr_loc = c_parser_peek_token (parser)->location;
- tree c, t = c_parser_expression (parser).value;
- mark_exp_read (t);
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -11258,8 +11434,9 @@ c_parser_omp_clause_num_tasks (c_parser *parser, tree list)
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
location_t expr_loc = c_parser_peek_token (parser)->location;
- tree c, t = c_parser_expression (parser).value;
- mark_exp_read (t);
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -11302,8 +11479,9 @@ c_parser_omp_clause_grainsize (c_parser *parser, tree list)
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
location_t expr_loc = c_parser_peek_token (parser)->location;
- tree c, t = c_parser_expression (parser).value;
- mark_exp_read (t);
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -11346,8 +11524,9 @@ c_parser_omp_clause_priority (c_parser *parser, tree list)
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
location_t expr_loc = c_parser_peek_token (parser)->location;
- tree c, t = c_parser_expression (parser).value;
- mark_exp_read (t);
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -11390,8 +11569,10 @@ c_parser_omp_clause_hint (c_parser *parser, tree list)
location_t hint_loc = c_parser_peek_token (parser)->location;
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
- tree c, t = c_parser_expression (parser).value;
- mark_exp_read (t);
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -11494,8 +11675,9 @@ c_parser_omp_clause_num_workers (c_parser *parser, tree list)
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
location_t expr_loc = c_parser_peek_token (parser)->location;
- tree c, t = c_parser_expression (parser).value;
- mark_exp_read (t);
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -11616,11 +11798,12 @@ c_parser_oacc_shape_clause (c_parser *parser, omp_clause_code kind,
}
location_t expr_loc = c_parser_peek_token (parser)->location;
- tree expr = c_parser_expr_no_commas (parser, NULL).value;
+ c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
+ cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
+ tree expr = cexpr.value;
if (expr == error_mark_node)
goto cleanup_error;
- mark_exp_read (expr);
expr = c_fully_fold (expr, false, NULL);
/* Attempt to statically determine when the number isn't a
@@ -11637,7 +11820,7 @@ c_parser_oacc_shape_clause (c_parser *parser, omp_clause_code kind,
if (c == boolean_true_node)
{
warning_at (loc, 0,
- "%<%s%> value must be positive", str);
+ "%qs value must be positive", str);
expr = integer_one_node;
}
@@ -11734,10 +11917,11 @@ static tree
c_parser_oacc_clause_tile (c_parser *parser, tree list)
{
tree c, expr = error_mark_node;
- location_t loc, expr_loc;
+ location_t loc;
tree tile = NULL_TREE;
check_no_duplicate_clause (list, OMP_CLAUSE_TILE, "tile");
+ check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
loc = c_parser_peek_token (parser)->location;
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
@@ -11745,17 +11929,22 @@ c_parser_oacc_clause_tile (c_parser *parser, tree list)
do
{
+ if (tile && !c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+ return list;
+
if (c_parser_next_token_is (parser, CPP_MULT)
&& (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
|| c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN))
{
c_parser_consume_token (parser);
- expr = integer_minus_one_node;
+ expr = integer_zero_node;
}
else
{
- expr_loc = c_parser_peek_token (parser)->location;
- expr = c_parser_expr_no_commas (parser, NULL).value;
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
+ cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
+ expr = cexpr.value;
if (expr == error_mark_node)
{
@@ -11764,29 +11953,19 @@ c_parser_oacc_clause_tile (c_parser *parser, tree list)
return list;
}
- if (!INTEGRAL_TYPE_P (TREE_TYPE (expr)))
- {
- c_parser_error (parser, "%<tile%> value must be integral");
- return list;
- }
-
- mark_exp_read (expr);
expr = c_fully_fold (expr, false, NULL);
- /* Attempt to statically determine when expr isn't positive. */
- c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, expr,
- build_int_cst (TREE_TYPE (expr), 0));
- protected_set_expr_location (c, expr_loc);
- if (c == boolean_true_node)
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
+ || !tree_fits_shwi_p (expr)
+ || tree_to_shwi (expr) <= 0)
{
- warning_at (expr_loc, 0,"%<tile%> value must be positive");
- expr = integer_one_node;
+ error_at (expr_loc, "%<tile%> argument needs positive"
+ " integral constant");
+ expr = integer_zero_node;
}
}
tile = tree_cons (NULL_TREE, expr, tile);
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
}
while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN));
@@ -11937,7 +12116,7 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list)
default:
c_parser_error (parser,
"expected %<+%>, %<*%>, %<-%>, %<&%>, "
- "%<^%>, %<|%>, %<&&%>, %<||%>, %<min%> or %<max%>");
+ "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
return list;
}
@@ -12093,8 +12272,9 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list)
c_parser_consume_token (parser);
here = c_parser_peek_token (parser)->location;
- t = c_parser_expr_no_commas (parser, NULL).value;
- mark_exp_read (t);
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (here, expr, false, true);
+ t = expr.value;
t = c_fully_fold (t, false, NULL);
if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
@@ -12105,7 +12285,20 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list)
"schedule %<auto%> does not take "
"a %<chunk_size%> parameter");
else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE)
- OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
+ {
+ /* Attempt to statically determine when the number isn't
+ positive. */
+ tree s = fold_build2_loc (loc, LE_EXPR, boolean_type_node, t,
+ build_int_cst (TREE_TYPE (t), 0));
+ protected_set_expr_location (s, loc);
+ if (s == boolean_true_node)
+ {
+ warning_at (loc, 0,
+ "chunk size value must be positive");
+ t = integer_one_node;
+ }
+ OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
+ }
else
c_parser_error (parser, "expected integer expression");
@@ -12166,8 +12359,9 @@ c_parser_omp_clause_vector_length (c_parser *parser, tree list)
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
location_t expr_loc = c_parser_peek_token (parser)->location;
- tree c, t = c_parser_expression (parser).value;
- mark_exp_read (t);
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -12269,8 +12463,9 @@ c_parser_omp_clause_num_teams (c_parser *parser, tree list)
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
location_t expr_loc = c_parser_peek_token (parser)->location;
- tree c, t = c_parser_expression (parser).value;
- mark_exp_read (t);
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -12312,8 +12507,9 @@ c_parser_omp_clause_thread_limit (c_parser *parser, tree list)
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
location_t expr_loc = c_parser_peek_token (parser)->location;
- tree c, t = c_parser_expression (parser).value;
- mark_exp_read (t);
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -12365,8 +12561,10 @@ c_parser_omp_clause_aligned (c_parser *parser, tree list)
if (c_parser_next_token_is (parser, CPP_COLON))
{
c_parser_consume_token (parser);
- tree alignment = c_parser_expr_no_commas (parser, NULL).value;
- mark_exp_read (alignment);
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree alignment = expr.value;
alignment = c_fully_fold (alignment, false, NULL);
if (TREE_CODE (alignment) != INTEGER_CST
|| !INTEGRAL_TYPE_P (TREE_TYPE (alignment))
@@ -12428,8 +12626,10 @@ c_parser_omp_clause_linear (c_parser *parser, tree list, bool is_cilk_simd_fn)
if (c_parser_next_token_is (parser, CPP_COLON))
{
c_parser_consume_token (parser);
- step = c_parser_expression (parser).value;
- mark_exp_read (step);
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ step = expr.value;
step = c_fully_fold (step, false, NULL);
if (is_cilk_simd_fn && TREE_CODE (step) == PARM_DECL)
{
@@ -12469,8 +12669,10 @@ c_parser_omp_clause_safelen (c_parser *parser, tree list)
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
return list;
- t = c_parser_expr_no_commas (parser, NULL).value;
- mark_exp_read (t);
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ t = expr.value;
t = c_fully_fold (t, false, NULL);
if (TREE_CODE (t) != INTEGER_CST
|| !INTEGRAL_TYPE_P (TREE_TYPE (t))
@@ -12505,8 +12707,10 @@ c_parser_omp_clause_simdlen (c_parser *parser, tree list)
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
return list;
- t = c_parser_expr_no_commas (parser, NULL).value;
- mark_exp_read (t);
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ t = expr.value;
t = c_fully_fold (t, false, NULL);
if (TREE_CODE (t) != INTEGER_CST
|| !INTEGRAL_TYPE_P (TREE_TYPE (t))
@@ -12821,8 +13025,10 @@ c_parser_omp_clause_device (c_parser *parser, tree list)
location_t clause_loc = c_parser_peek_token (parser)->location;
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
- tree c, t = c_parser_expr_no_commas (parser, NULL).value;
- mark_exp_read (t);
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -12870,8 +13076,10 @@ c_parser_omp_clause_dist_schedule (c_parser *parser, tree list)
{
c_parser_consume_token (parser);
- t = c_parser_expr_no_commas (parser, NULL).value;
- mark_exp_read (t);
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
}
@@ -13160,7 +13368,7 @@ c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask,
c_parser_skip_to_pragma_eol (parser);
if (finish_p)
- return c_finish_omp_clauses (clauses, false);
+ return c_finish_omp_clauses (clauses, C_ORT_ACC);
return clauses;
}
@@ -13445,8 +13653,8 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
if (finish_p)
{
if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM)) != 0)
- return c_finish_omp_clauses (clauses, true, true);
- return c_finish_omp_clauses (clauses, true);
+ return c_finish_omp_clauses (clauses, C_ORT_OMP_DECLARE_SIMD);
+ return c_finish_omp_clauses (clauses, C_ORT_OMP);
}
return clauses;
@@ -13480,7 +13688,7 @@ c_parser_oacc_cache (location_t loc, c_parser *parser)
tree stmt, clauses;
clauses = c_parser_omp_var_list_parens (parser, OMP_CLAUSE__CACHE_, NULL);
- clauses = c_finish_omp_clauses (clauses, false);
+ clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
c_parser_skip_to_pragma_eol (parser);
@@ -13579,24 +13787,20 @@ c_parser_oacc_declare (c_parser *parser)
switch (OMP_CLAUSE_MAP_KIND (t))
{
+ case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_FORCE_ALLOC:
case GOMP_MAP_FORCE_TO:
case GOMP_MAP_FORCE_DEVICEPTR:
case GOMP_MAP_DEVICE_RESIDENT:
break;
- case GOMP_MAP_POINTER:
- /* Generated by c_finish_omp_clauses from array sections;
- avoid spurious diagnostics. */
- break;
-
case GOMP_MAP_LINK:
if (!global_bindings_p ()
&& (TREE_STATIC (decl)
|| !DECL_EXTERNAL (decl)))
{
error_at (loc,
- "%qD must be a global variable in"
+ "%qD must be a global variable in "
"%<#pragma acc declare link%>",
decl);
error = true;
@@ -13714,28 +13918,25 @@ c_parser_oacc_enter_exit_data (c_parser *parser, bool enter)
{
location_t loc = c_parser_peek_token (parser)->location;
tree clauses, stmt;
+ const char *p = "";
c_parser_consume_pragma (parser);
- if (!c_parser_next_token_is (parser, CPP_NAME))
+ if (c_parser_next_token_is (parser, CPP_NAME))
{
- c_parser_error (parser, enter
- ? "expected %<data%> in %<#pragma acc enter data%>"
- : "expected %<data%> in %<#pragma acc exit data%>");
- c_parser_skip_to_pragma_eol (parser);
- return;
+ p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ c_parser_consume_token (parser);
}
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
if (strcmp (p, "data") != 0)
{
- c_parser_error (parser, "invalid pragma");
+ error_at (loc, "expected %<data%> after %<#pragma acc %s%>",
+ enter ? "enter" : "exit");
+ parser->error = true;
c_parser_skip_to_pragma_eol (parser);
return;
}
- c_parser_consume_token (parser);
-
if (enter)
clauses = c_parser_oacc_all_clauses (parser, OACC_ENTER_DATA_CLAUSE_MASK,
"#pragma acc enter data");
@@ -13743,11 +13944,10 @@ c_parser_oacc_enter_exit_data (c_parser *parser, bool enter)
clauses = c_parser_oacc_all_clauses (parser, OACC_EXIT_DATA_CLAUSE_MASK,
"#pragma acc exit data");
- if (find_omp_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE)
+ if (omp_find_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE)
{
- error_at (loc, enter
- ? "%<#pragma acc enter data%> has no data movement clause"
- : "%<#pragma acc exit data%> has no data movement clause");
+ error_at (loc, "%<#pragma acc %s data%> has no data movement clause",
+ enter ? "enter" : "exit");
return;
}
@@ -13816,9 +14016,9 @@ c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
{
clauses = c_oacc_split_loop_clauses (clauses, cclauses, is_parallel);
if (*cclauses)
- *cclauses = c_finish_omp_clauses (*cclauses, false);
+ *cclauses = c_finish_omp_clauses (*cclauses, C_ORT_ACC);
if (clauses)
- clauses = c_finish_omp_clauses (clauses, false);
+ clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
}
tree block = c_begin_compound_stmt (true);
@@ -13944,95 +14144,154 @@ c_parser_oacc_kernels_parallel (location_t loc, c_parser *parser,
static void
c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
{
- tree decl = NULL_TREE;
- /* Create a dummy claue, to record location. */
- tree c_head = build_omp_clause (c_parser_peek_token (parser)->location,
- OMP_CLAUSE_SEQ);
-
- if (context != pragma_external)
- c_parser_error (parser, "%<#pragma acc routine%> not at file scope");
+ gcc_checking_assert (context == pragma_external);
+
+ oacc_routine_data data;
+ data.error_seen = false;
+ data.fndecl_seen = false;
+ data.clauses = NULL_TREE;
+ data.loc = c_parser_peek_token (parser)->location;
c_parser_consume_pragma (parser);
- /* Scan for optional '( name )'. */
- if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
+ /* Look for optional '( name )'. */
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
{
- c_parser_consume_token (parser);
+ c_parser_consume_token (parser); /* '(' */
- c_token *token = c_parser_peek_token (parser);
-
- if (token->type == CPP_NAME && (token->id_kind == C_ID_ID
- || token->id_kind == C_ID_TYPENAME))
+ tree decl = NULL_TREE;
+ c_token *name_token = c_parser_peek_token (parser);
+ location_t name_loc = name_token->location;
+ if (name_token->type == CPP_NAME
+ && (name_token->id_kind == C_ID_ID
+ || name_token->id_kind == C_ID_TYPENAME))
{
- decl = lookup_name (token->value);
+ decl = lookup_name (name_token->value);
if (!decl)
- {
- error_at (token->location, "%qE has not been declared",
- token->value);
- decl = error_mark_node;
- }
+ error_at (name_loc,
+ "%qE has not been declared", name_token->value);
+ c_parser_consume_token (parser);
}
else
c_parser_error (parser, "expected function name");
- if (token->type != CPP_CLOSE_PAREN)
- c_parser_consume_token (parser);
+ if (!decl
+ || !c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ {
+ c_parser_skip_to_pragma_eol (parser, false);
+ return;
+ }
+
+ data.clauses
+ = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
+ "#pragma acc routine");
+
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ {
+ error_at (name_loc, "%qD does not refer to a function", decl);
+ return;
+ }
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
+ c_finish_oacc_routine (&data, decl, false);
}
+ else /* No optional '( name )'. */
+ {
+ data.clauses
+ = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
+ "#pragma acc routine");
- /* Build a chain of clauses. */
- parser->in_pragma = true;
- tree clauses = c_parser_oacc_all_clauses
- (parser, OACC_ROUTINE_CLAUSE_MASK, "#pragma acc routine");
+ /* Emit a helpful diagnostic if there's another pragma following this
+ one. Also don't allow a static assertion declaration, as in the
+ following we'll just parse a *single* "declaration or function
+ definition", and the static assertion counts an one. */
+ if (c_parser_next_token_is (parser, CPP_PRAGMA)
+ || c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
+ {
+ error_at (data.loc,
+ "%<#pragma acc routine%> not immediately followed by"
+ " function declaration or definition");
+ /* ..., and then just keep going. */
+ return;
+ }
- /* Force clauses to be non-null, by attaching context to it. */
- clauses = tree_cons (c_head, clauses, NULL_TREE);
-
- if (decl)
- c_finish_oacc_routine (parser, decl, clauses, true, true, false);
- else if (c_parser_peek_token (parser)->type == CPP_PRAGMA)
- /* This will emit an error. */
- c_finish_oacc_routine (parser, NULL_TREE, clauses, false, true, false);
- else
- c_parser_declaration_or_fndef (parser, true, false, false, false,
- true, NULL, vNULL, clauses);
+ /* We only have to consider the pragma_external case here. */
+ if (c_parser_next_token_is (parser, CPP_KEYWORD)
+ && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
+ {
+ int ext = disable_extension_diagnostics ();
+ do
+ c_parser_consume_token (parser);
+ while (c_parser_next_token_is (parser, CPP_KEYWORD)
+ && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
+ c_parser_declaration_or_fndef (parser, true, true, true, false, true,
+ NULL, vNULL, &data);
+ restore_extension_diagnostics (ext);
+ }
+ else
+ c_parser_declaration_or_fndef (parser, true, true, true, false, true,
+ NULL, vNULL, &data);
+ }
}
-/* Finalize an OpenACC routine pragma, applying it to FNDECL. CLAUSES
- are the parsed clauses. IS_DEFN is true if we're applying it to
- the definition (so expect FNDEF to look somewhat defined. */
+/* Finalize an OpenACC routine pragma, applying it to FNDECL.
+ IS_DEFN is true if we're applying it to the definition. */
static void
-c_finish_oacc_routine (c_parser *ARG_UNUSED (parser), tree fndecl,
- tree clauses, bool named, bool first, bool is_defn)
+c_finish_oacc_routine (struct oacc_routine_data *data, tree fndecl,
+ bool is_defn)
{
- location_t loc = OMP_CLAUSE_LOCATION (TREE_PURPOSE (clauses));
+ /* Keep going if we're in error reporting mode. */
+ if (data->error_seen
+ || fndecl == error_mark_node)
+ return;
- if (!fndecl || TREE_CODE (fndecl) != FUNCTION_DECL || !first)
+ if (data->fndecl_seen)
{
- if (fndecl != error_mark_node)
- error_at (loc, "%<#pragma acc routine%> %s",
- named ? "does not refer to a function"
- : "not followed by single function");
+ error_at (data->loc,
+ "%<#pragma acc routine%> not immediately followed by"
+ " a single function declaration or definition");
+ data->error_seen = true;
+ return;
+ }
+ if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
+ {
+ error_at (data->loc,
+ "%<#pragma acc routine%> not immediately followed by"
+ " function declaration or definition");
+ data->error_seen = true;
return;
}
- if (get_oacc_fn_attrib (fndecl))
- error_at (loc, "%<#pragma acc routine%> already applied to %D", fndecl);
+ if (oacc_get_fn_attrib (fndecl))
+ {
+ error_at (data->loc,
+ "%<#pragma acc routine%> already applied to %qD", fndecl);
+ data->error_seen = true;
+ return;
+ }
if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
- error_at (loc, "%<#pragma acc routine%> must be applied before %s",
- TREE_USED (fndecl) ? "use" : "definition");
+ {
+ error_at (data->loc,
+ TREE_USED (fndecl)
+ ? G_("%<#pragma acc routine%> must be applied before use")
+ : G_("%<#pragma acc routine%> must be applied before "
+ "definition"));
+ data->error_seen = true;
+ return;
+ }
- /* Process for function attrib */
- tree dims = build_oacc_routine_dims (TREE_VALUE (clauses));
- replace_oacc_fn_attrib (fndecl, dims);
+ /* Process the routine's dimension clauses. */
+ tree dims = oacc_build_routine_dims (data->clauses);
+ oacc_replace_fn_attrib (fndecl, dims);
- /* Also attach as a declare. */
+ /* Add an "omp declare target" attribute. */
DECL_ATTRIBUTES (fndecl)
= tree_cons (get_identifier ("omp declare target"),
- clauses, DECL_ATTRIBUTES (fndecl));
+ NULL_TREE, DECL_ATTRIBUTES (fndecl));
+
+ /* Remember that we've used this "#pragma acc routine". */
+ data->fndecl_seen = true;
}
/* OpenACC 2.0:
@@ -14056,7 +14315,7 @@ c_parser_oacc_update (c_parser *parser)
tree clauses = c_parser_oacc_all_clauses (parser, OACC_UPDATE_CLAUSE_MASK,
"#pragma acc update");
- if (find_omp_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE)
+ if (omp_find_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE)
{
error_at (loc,
"%<#pragma acc update%> must contain at least one "
@@ -14630,11 +14889,17 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
bool fail = false, open_brace_parsed = false;
int i, collapse = 1, ordered = 0, count, nbraces = 0;
location_t for_loc;
+ bool tiling = false;
vec<tree, va_gc> *for_block = make_tree_vector ();
for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl));
+ else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_TILE)
+ {
+ tiling = true;
+ collapse = list_length (OMP_CLAUSE_TILE_LIST (cl));
+ }
else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_ORDERED
&& OMP_CLAUSE_ORDERED_EXPR (cl))
{
@@ -14664,7 +14929,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
pc = &OMP_CLAUSE_CHAIN (*pc);
}
- gcc_assert (collapse >= 1 && ordered >= 0);
+ gcc_assert (tiling || (collapse >= 1 && ordered >= 0));
count = ordered ? ordered : collapse;
declv = make_tree_vec (count);
@@ -14992,7 +15257,7 @@ omp_split_clauses (location_t loc, enum tree_code code,
c_omp_split_clauses (loc, code, mask, clauses, cclauses);
for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
if (cclauses[i])
- cclauses[i] = c_finish_omp_clauses (cclauses[i], true);
+ cclauses[i] = c_finish_omp_clauses (cclauses[i], C_ORT_OMP);
}
/* OpenMP 4.0:
@@ -15027,7 +15292,7 @@ c_parser_omp_simd (location_t loc, c_parser *parser,
{
omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses);
clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
- tree c = find_omp_clause (cclauses[C_OMP_CLAUSE_SPLIT_FOR],
+ tree c = omp_find_clause (cclauses[C_OMP_CLAUSE_SPLIT_FOR],
OMP_CLAUSE_ORDERED);
if (c && OMP_CLAUSE_ORDERED_EXPR (c))
{
@@ -15180,7 +15445,7 @@ c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
if (context != pragma_stmt && context != pragma_compound)
{
c_parser_error (parser, "expected declaration specifiers");
- c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+ c_parser_skip_to_pragma_eol (parser, false);
return false;
}
@@ -15193,7 +15458,7 @@ c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
if (context == pragma_stmt)
{
error_at (loc,
- "%<#pragma omp ordered%> with %<depend> clause may "
+ "%<#pragma omp ordered%> with %<depend%> clause may "
"only be used in compound statements");
c_parser_skip_to_pragma_eol (parser, false);
return false;
@@ -15577,7 +15842,7 @@ c_parser_omp_cancel (c_parser *parser)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP))
static void
-c_parser_omp_cancellation_point (c_parser *parser)
+c_parser_omp_cancellation_point (c_parser *parser, enum pragma_context context)
{
location_t loc = c_parser_peek_token (parser)->location;
tree clauses;
@@ -15600,6 +15865,18 @@ c_parser_omp_cancellation_point (c_parser *parser)
return;
}
+ if (context != pragma_compound)
+ {
+ if (context == pragma_stmt)
+ error_at (loc,
+ "%<#pragma %s%> may only be used in compound statements",
+ "omp cancellation point");
+ else
+ c_parser_error (parser, "expected declaration specifiers");
+ c_parser_skip_to_pragma_eol (parser, false);
+ return;
+ }
+
clauses
= c_parser_omp_all_clauses (parser, OMP_CANCELLATION_POINT_CLAUSE_MASK,
"#pragma omp cancellation point");
@@ -15850,9 +16127,8 @@ c_parser_omp_target_update (location_t loc, c_parser *parser,
{
if (context == pragma_stmt)
{
- error_at (loc,
- "%<#pragma omp target update%> may only be "
- "used in compound statements");
+ error_at (loc, "%<#pragma %s%> may only be used in compound statements",
+ "omp target update");
c_parser_skip_to_pragma_eol (parser, false);
return false;
}
@@ -15860,8 +16136,8 @@ c_parser_omp_target_update (location_t loc, c_parser *parser,
tree clauses
= c_parser_omp_all_clauses (parser, OMP_TARGET_UPDATE_CLAUSE_MASK,
"#pragma omp target update");
- if (find_omp_clause (clauses, OMP_CLAUSE_TO) == NULL_TREE
- && find_omp_clause (clauses, OMP_CLAUSE_FROM) == NULL_TREE)
+ if (omp_find_clause (clauses, OMP_CLAUSE_TO) == NULL_TREE
+ && omp_find_clause (clauses, OMP_CLAUSE_FROM) == NULL_TREE)
{
error_at (loc,
"%<#pragma omp target update%> must contain at least one "
@@ -15910,9 +16186,8 @@ c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
if (context == pragma_stmt)
{
- error_at (loc,
- "%<#pragma omp target enter data%> may only be "
- "used in compound statements");
+ error_at (loc, "%<#pragma %s%> may only be used in compound statements",
+ "omp target enter data");
c_parser_skip_to_pragma_eol (parser, false);
return NULL_TREE;
}
@@ -15995,9 +16270,8 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
if (context == pragma_stmt)
{
- error_at (loc,
- "%<#pragma omp target exit data%> may only be "
- "used in compound statements");
+ error_at (loc, "%<#pragma %s%> may only be used in compound statements",
+ "omp target exit data");
c_parser_skip_to_pragma_eol (parser, false);
return NULL_TREE;
}
@@ -16025,7 +16299,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
map_seen |= 1;
error_at (OMP_CLAUSE_LOCATION (*pc),
"%<#pragma omp target exit data%> with map-type other "
- "than %<from%>, %<release> or %<delete%> on %<map%>"
+ "than %<from%>, %<release%> or %<delete%> on %<map%>"
" clause");
*pc = OMP_CLAUSE_CHAIN (*pc);
continue;
@@ -16212,6 +16486,11 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
return c_parser_omp_target_update (loc, parser, context);
}
}
+ if (!flag_openmp) /* flag_openmp_simd */
+ {
+ c_parser_skip_to_pragma_eol (parser, false);
+ return false;
+ }
stmt = make_node (OMP_TARGET);
TREE_TYPE (stmt) = void_type_node;
@@ -16271,14 +16550,13 @@ check_clauses:
static void
c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
{
- vec<c_token> clauses = vNULL;
+ auto_vec<c_token> clauses;
while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
{
c_token *token = c_parser_peek_token (parser);
if (token->type == CPP_EOF)
{
c_parser_skip_to_pragma_eol (parser);
- clauses.release ();
return;
}
clauses.safe_push (*token);
@@ -16290,7 +16568,7 @@ c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
while (c_parser_next_token_is (parser, CPP_PRAGMA))
{
if (c_parser_peek_token (parser)->pragma_kind
- != PRAGMA_OMP_DECLARE_REDUCTION
+ != PRAGMA_OMP_DECLARE
|| c_parser_peek_2nd_token (parser)->type != CPP_NAME
|| strcmp (IDENTIFIER_POINTER
(c_parser_peek_2nd_token (parser)->value),
@@ -16300,7 +16578,6 @@ c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
"%<#pragma omp declare simd%> must be followed by "
"function declaration or definition or another "
"%<#pragma omp declare simd%>");
- clauses.release ();
return;
}
c_parser_consume_pragma (parser);
@@ -16310,7 +16587,6 @@ c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
if (token->type == CPP_EOF)
{
c_parser_skip_to_pragma_eol (parser);
- clauses.release ();
return;
}
clauses.safe_push (*token);
@@ -16382,7 +16658,6 @@ c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
default:
gcc_unreachable ();
}
- clauses.release ();
}
/* Finalize #pragma omp declare simd clauses after FNDECL has been parsed,
@@ -16525,7 +16800,7 @@ c_parser_omp_declare_target (c_parser *parser)
{
clauses = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_TO_DECLARE,
clauses);
- clauses = c_finish_omp_clauses (clauses, true);
+ clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
c_parser_skip_to_pragma_eol (parser);
}
else
@@ -16560,8 +16835,11 @@ c_parser_omp_declare_target (c_parser *parser)
}
if (!at1)
{
- symtab_node *node = symtab_node::get (t);
DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
+ if (TREE_CODE (t) != FUNCTION_DECL && !is_global_var (t))
+ continue;
+
+ symtab_node *node = symtab_node::get (t);
if (node != NULL)
{
node->offloadable = 1;
@@ -16684,7 +16962,7 @@ c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
default:
c_parser_error (parser,
"expected %<+%>, %<*%>, %<-%>, %<&%>, "
- "%<^%>, %<|%>, %<&&%>, %<||%>, %<min%> or identifier");
+ "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
goto fail;
}
@@ -16716,6 +16994,9 @@ c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
|| TREE_CODE (type) == ARRAY_TYPE)
error_at (loc, "function or array type in "
"%<#pragma omp declare reduction%>");
+ else if (TYPE_ATOMIC (type))
+ error_at (loc, "%<_Atomic%> qualified type in "
+ "%<#pragma omp declare reduction%>");
else if (TYPE_QUALS_NO_ADDR_SPACE (type))
error_at (loc, "const, volatile or restrict qualified type in "
"%<#pragma omp declare reduction%>");
@@ -16893,8 +17174,9 @@ c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
else
{
tree st = push_stmt_list ();
- start_init (omp_priv, NULL_TREE, 0);
location_t loc = c_parser_peek_token (parser)->location;
+ rich_location richloc (line_table, loc);
+ start_init (omp_priv, NULL_TREE, 0, &richloc);
struct c_expr init = c_parser_initializer (parser);
finish_init ();
finish_decl (omp_priv, loc, init.value,
@@ -17494,7 +17776,7 @@ c_parser_cilk_all_clauses (c_parser *parser)
saw_error:
c_parser_skip_to_pragma_eol (parser);
- return c_finish_cilk_clauses (clauses);
+ return c_finish_omp_clauses (clauses, C_ORT_CILK);
}
/* This function helps parse the grainsize pragma for a _Cilk_for statement.
@@ -17576,7 +17858,7 @@ c_parser_cilk_for (c_parser *parser, tree grain, bool *if_p)
tree clauses = build_omp_clause (EXPR_LOCATION (grain), OMP_CLAUSE_SCHEDULE);
OMP_CLAUSE_SCHEDULE_KIND (clauses) = OMP_CLAUSE_SCHEDULE_CILKFOR;
OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clauses) = grain;
- clauses = c_finish_omp_clauses (clauses, false);
+ clauses = c_finish_omp_clauses (clauses, C_ORT_CILK);
tree block = c_begin_compound_stmt (true);
tree sb = push_stmt_list ();
@@ -17642,7 +17924,7 @@ c_parser_cilk_for (c_parser *parser, tree grain, bool *if_p)
OMP_CLAUSE_OPERAND (c, 0)
= cilk_for_number_of_iterations (omp_for);
OMP_CLAUSE_CHAIN (c) = clauses;
- OMP_PARALLEL_CLAUSES (omp_par) = c_finish_omp_clauses (c, true);
+ OMP_PARALLEL_CLAUSES (omp_par) = c_finish_omp_clauses (c, C_ORT_CILK);
add_stmt (omp_par);
}
@@ -18034,4 +18316,74 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
return value_tree;
}
+/* Parse the body of a function declaration marked with "__RTL".
+
+ The RTL parser works on the level of characters read from a
+ FILE *, whereas c_parser works at the level of tokens.
+ Square this circle by consuming all of the tokens up to and
+ including the closing brace, recording the start/end of the RTL
+ fragment, and reopening the file and re-reading the relevant
+ lines within the RTL parser.
+
+ This requires the opening and closing braces of the C function
+ to be on separate lines from the RTL they wrap.
+
+ Take ownership of START_WITH_PASS, if non-NULL. */
+
+void
+c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass)
+{
+ if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+ {
+ free (start_with_pass);
+ return;
+ }
+
+ location_t start_loc = c_parser_peek_token (parser)->location;
+
+ /* Consume all tokens, up to the closing brace, handling
+ matching pairs of braces in the rtl dump. */
+ int num_open_braces = 1;
+ while (1)
+ {
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_OPEN_BRACE:
+ num_open_braces++;
+ break;
+ case CPP_CLOSE_BRACE:
+ if (--num_open_braces == 0)
+ goto found_closing_brace;
+ break;
+ case CPP_EOF:
+ error_at (start_loc, "no closing brace");
+ free (start_with_pass);
+ return;
+ default:
+ break;
+ }
+ c_parser_consume_token (parser);
+ }
+
+ found_closing_brace:
+ /* At the closing brace; record its location. */
+ location_t end_loc = c_parser_peek_token (parser)->location;
+
+ /* Consume the closing brace. */
+ c_parser_consume_token (parser);
+
+ /* Invoke the RTL parser. */
+ if (!read_rtl_function_body_from_file_range (start_loc, end_loc))
+ {
+ free (start_with_pass);
+ return;
+ }
+
+ /* If a pass name was provided for START_WITH_PASS, run the backend
+ accordingly now, on the cfun created above, transferring
+ ownership of START_WITH_PASS. */
+ if (start_with_pass)
+ run_rtl_passes (start_with_pass);
+}
+
#include "gt-c-c-parser.h"
diff --git a/gcc/c/c-parser.h b/gcc/c/c-parser.h
new file mode 100644
index 0000000000..1e344c40e2
--- /dev/null
+++ b/gcc/c/c-parser.h
@@ -0,0 +1,189 @@
+/* Declarations for the parser for C and Objective-C.
+ Copyright (C) 1987-2017 Free Software Foundation, Inc.
+
+ Parser actions based on the old Bison parser; structure somewhat
+ influenced by and fragments based on the C++ parser.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_C_PARSER_H
+#define GCC_C_PARSER_H
+
+/* The C lexer intermediates between the lexer in cpplib and c-lex.c
+ and the C parser. Unlike the C++ lexer, the parser structure
+ stores the lexer information instead of using a separate structure.
+ Identifiers are separated into ordinary identifiers, type names,
+ keywords and some other Objective-C types of identifiers, and some
+ look-ahead is maintained.
+
+ ??? It might be a good idea to lex the whole file up front (as for
+ C++). It would then be possible to share more of the C and C++
+ lexer code, if desired. */
+
+/* More information about the type of a CPP_NAME token. */
+enum c_id_kind {
+ /* An ordinary identifier. */
+ C_ID_ID,
+ /* An identifier declared as a typedef name. */
+ C_ID_TYPENAME,
+ /* An identifier declared as an Objective-C class name. */
+ C_ID_CLASSNAME,
+ /* An address space identifier. */
+ C_ID_ADDRSPACE,
+ /* Not an identifier. */
+ C_ID_NONE
+};
+
+/* A single C token after string literal concatenation and conversion
+ of preprocessing tokens to tokens. */
+struct GTY (()) c_token {
+ /* The kind of token. */
+ ENUM_BITFIELD (cpp_ttype) type : 8;
+ /* If this token is a CPP_NAME, this value indicates whether also
+ declared as some kind of type. Otherwise, it is C_ID_NONE. */
+ ENUM_BITFIELD (c_id_kind) id_kind : 8;
+ /* If this token is a keyword, this value indicates which keyword.
+ Otherwise, this value is RID_MAX. */
+ ENUM_BITFIELD (rid) keyword : 8;
+ /* If this token is a CPP_PRAGMA, this indicates the pragma that
+ was seen. Otherwise it is PRAGMA_NONE. */
+ ENUM_BITFIELD (pragma_kind) pragma_kind : 8;
+ /* The location at which this token was found. */
+ location_t location;
+ /* The value associated with this token, if any. */
+ tree value;
+ /* Token flags. */
+ unsigned char flags;
+
+ source_range get_range () const
+ {
+ return get_range_from_loc (line_table, location);
+ }
+
+ location_t get_finish () const
+ {
+ return get_range ().m_finish;
+ }
+};
+
+/* The parser. */
+struct c_parser;
+
+/* Possibly kinds of declarator to parse. */
+enum c_dtr_syn {
+ /* A normal declarator with an identifier. */
+ C_DTR_NORMAL,
+ /* An abstract declarator (maybe empty). */
+ C_DTR_ABSTRACT,
+ /* A parameter declarator: may be either, but after a type name does
+ not redeclare a typedef name as an identifier if it can
+ alternatively be interpreted as a typedef name; see DR#009,
+ applied in C90 TC1, omitted from C99 and reapplied in C99 TC2
+ following DR#249. For example, given a typedef T, "int T" and
+ "int *T" are valid parameter declarations redeclaring T, while
+ "int (T)" and "int * (T)" and "int (T[])" and "int (T (int))" are
+ abstract declarators rather than involving redundant parentheses;
+ the same applies with attributes inside the parentheses before
+ "T". */
+ C_DTR_PARM
+};
+
+/* The binary operation precedence levels, where 0 is a dummy lowest level
+ used for the bottom of the stack. */
+enum c_parser_prec {
+ PREC_NONE,
+ PREC_LOGOR,
+ PREC_LOGAND,
+ PREC_BITOR,
+ PREC_BITXOR,
+ PREC_BITAND,
+ PREC_EQ,
+ PREC_REL,
+ PREC_SHIFT,
+ PREC_ADD,
+ PREC_MULT,
+ NUM_PRECS
+};
+
+enum c_lookahead_kind {
+ /* Always treat unknown identifiers as typenames. */
+ cla_prefer_type,
+
+ /* Could be parsing a nonabstract declarator. Only treat an identifier
+ as a typename if followed by another identifier or a star. */
+ cla_nonabstract_decl,
+
+ /* Never treat identifiers as typenames. */
+ cla_prefer_id
+};
+
+
+extern c_token * c_parser_peek_token (c_parser *parser);
+extern c_token * c_parser_peek_2nd_token (c_parser *parser);
+extern c_token * c_parser_peek_nth_token (c_parser *parser, unsigned int n);
+extern bool c_parser_require (c_parser *parser, enum cpp_ttype type,
+ const char *msgid);
+extern void c_parser_error (c_parser *parser, const char *gmsgid);
+extern void c_parser_consume_token (c_parser *parser);
+extern void c_parser_skip_until_found (c_parser *parser, enum cpp_ttype type,
+ const char *msgid);
+extern bool c_parser_next_token_starts_declspecs (c_parser *parser);
+bool c_parser_next_tokens_start_declaration (c_parser *parser);
+bool c_token_starts_typename (c_token *token);
+
+/* Abstraction to avoid defining c_parser here which messes up gengtype
+ output wrt ObjC due to vec<c_token> routines being put in gtype-c.h
+ but not gtype-objc.h. */
+extern c_token * c_parser_tokens_buf (c_parser *parser, unsigned n);
+extern bool c_parser_error (c_parser *parser);
+extern void c_parser_set_error (c_parser *parser, bool);
+
+/* Return true if the next token from PARSER has the indicated
+ TYPE. */
+
+static inline bool
+c_parser_next_token_is (c_parser *parser, enum cpp_ttype type)
+{
+ return c_parser_peek_token (parser)->type == type;
+}
+
+/* Return true if the next token from PARSER does not have the
+ indicated TYPE. */
+
+static inline bool
+c_parser_next_token_is_not (c_parser *parser, enum cpp_ttype type)
+{
+ return !c_parser_next_token_is (parser, type);
+}
+
+/* Return true if the next token from PARSER is the indicated
+ KEYWORD. */
+
+static inline bool
+c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword)
+{
+ return c_parser_peek_token (parser)->keyword == keyword;
+}
+
+extern struct c_declarator *
+c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
+ bool *seen_id);
+extern void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
+ bool, bool, bool, enum c_lookahead_kind);
+extern struct c_type_name *c_parser_type_name (c_parser *);
+
+#endif
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index bb12a200f7..5fa32a48f2 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -1,5 +1,5 @@
/* Definitions for C parsing and type checking.
- Copyright (C) 1987-2016 Free Software Foundation, Inc.
+ Copyright (C) 1987-2017 Free Software Foundation, Inc.
This file is part of GCC.
@@ -43,8 +43,7 @@ along with GCC; see the file COPYING3. If not see
#define C_TYPE_INCOMPLETE_VARS(TYPE) TYPE_VFIELD (TYPE)
/* In an IDENTIFIER_NODE, nonzero if this identifier is actually a
- keyword. C_RID_CODE (node) is then the RID_* value of the keyword,
- and C_RID_YYCODE is the token number wanted by Yacc. */
+ keyword. C_RID_CODE (node) is then the RID_* value of the keyword. */
#define C_IS_RESERVED_WORD(ID) TREE_LANG_FLAG_0 (ID)
/* Record whether a type or decl was written with nonconstant size.
@@ -230,6 +229,7 @@ enum c_typespec_keyword {
cts_dfloat32,
cts_dfloat64,
cts_dfloat128,
+ cts_floatn_nx,
cts_fract,
cts_accum,
cts_auto_type
@@ -262,9 +262,12 @@ enum c_declspec_word {
cdw_const,
cdw_volatile,
cdw_restrict,
+ cdw_atomic,
cdw_saturating,
cdw_alignas,
cdw_address_space,
+ cdw_gimple,
+ cdw_rtl,
cdw_number_of_elements /* This one must always be the last
enumerator. */
};
@@ -288,12 +291,17 @@ struct c_declspecs {
NULL; attributes (possibly from multiple lists) will be passed
separately. */
tree attrs;
+ /* The pass to start compiling a __GIMPLE or __RTL function with. */
+ char *gimple_or_rtl_pass;
/* The base-2 log of the greatest alignment required by an _Alignas
specifier, in bytes, or -1 if no such specifiers with nonzero
alignment. */
int align_log;
/* For the __intN declspec, this stores the index into the int_n_* arrays. */
int int_n_idx;
+ /* For the _FloatN and _FloatNx declspec, this stores the index into
+ the floatn_nx_types array. */
+ int floatn_nx_idx;
/* The storage class specifier, or csc_none if none. */
enum c_storage_class storage_class;
/* Any type specifier keyword used such as "int", not reflecting
@@ -357,6 +365,10 @@ struct c_declspecs {
/* Whether any alignment specifier (even with zero alignment) was
specified. */
BOOL_BITFIELD alignas_p : 1;
+ /* Whether any __GIMPLE specifier was specified. */
+ BOOL_BITFIELD gimple_p : 1;
+ /* Whether any __RTL specifier was specified. */
+ BOOL_BITFIELD rtl_p : 1;
/* The address space that the declaration belongs to. */
addr_space_t address_space;
};
@@ -481,6 +493,7 @@ enum c_inline_static_type {
/* in c-parser.c */
extern void c_parse_init (void);
+extern bool c_keyword_starts_typename (enum rid keyword);
/* in c-aux-info.c */
extern void gen_aux_info_record (tree, int, int, int);
@@ -597,13 +610,13 @@ extern tree c_last_sizeof_arg;
extern struct c_switch *c_switch_stack;
extern tree c_objc_common_truthvalue_conversion (location_t, tree);
-extern tree require_complete_type (tree);
+extern tree require_complete_type (location_t, tree);
extern int same_translation_unit_p (const_tree, const_tree);
extern int comptypes (tree, tree);
extern int comptypes_check_different_types (tree, tree, bool *);
extern bool c_vla_type_p (const_tree);
-extern bool c_mark_addressable (tree);
-extern void c_incomplete_type_error (const_tree, const_tree);
+extern bool c_mark_addressable (tree, bool = false);
+extern void c_incomplete_type_error (location_t, const_tree, const_tree);
extern tree c_type_promotes_to (tree);
extern struct c_expr default_function_array_conversion (location_t,
struct c_expr);
@@ -613,7 +626,7 @@ extern struct c_expr convert_lvalue_to_rvalue (location_t, struct c_expr,
bool, bool);
extern void mark_exp_read (tree);
extern tree composite_type (tree, tree);
-extern tree build_component_ref (location_t, tree, tree);
+extern tree build_component_ref (location_t, tree, tree, location_t);
extern tree build_array_ref (location_t, tree, tree);
extern tree build_external_ref (location_t, tree, int, tree *);
extern void pop_maybe_used (bool);
@@ -631,14 +644,15 @@ extern tree c_cast_expr (location_t, struct c_type_name *, tree);
extern tree build_c_cast (location_t, tree, tree);
extern void store_init_value (location_t, tree, tree, tree);
extern void maybe_warn_string_init (location_t, tree, struct c_expr);
-extern void start_init (tree, tree, int);
+extern void start_init (tree, tree, int, rich_location *);
extern void finish_init (void);
extern void really_start_incremental_init (tree);
extern void finish_implicit_inits (location_t, struct obstack *);
extern void push_init_level (location_t, int, struct obstack *);
-extern struct c_expr pop_init_level (location_t, int, struct obstack *);
+extern struct c_expr pop_init_level (location_t, int, struct obstack *,
+ location_t);
extern void set_init_index (location_t, tree, tree, struct obstack *);
-extern void set_init_label (location_t, tree, struct obstack *);
+extern void set_init_label (location_t, tree, location_t, struct obstack *);
extern void process_init_element (location_t, struct c_expr, bool,
struct obstack *);
extern tree build_compound_literal (location_t, tree, tree, bool);
@@ -670,12 +684,13 @@ extern tree c_begin_omp_task (void);
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, bool, bool = false);
+extern tree c_finish_omp_clauses (tree, enum c_omp_region_type);
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);
extern tree c_build_function_call_vec (location_t, vec<location_t>, tree,
vec<tree, va_gc> *, vec<tree, va_gc> *);
+extern tree c_omp_clause_copy_ctor (tree, tree, tree);
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */
@@ -725,7 +740,7 @@ extern void c_bind (location_t, tree, bool);
extern bool tag_exists_p (enum tree_code, tree);
/* In c-errors.c */
-extern void pedwarn_c90 (location_t, int opt, const char *, ...)
+extern bool pedwarn_c90 (location_t, int opt, const char *, ...)
ATTRIBUTE_GCC_DIAG(3,4);
extern bool pedwarn_c99 (location_t, int opt, const char *, ...)
ATTRIBUTE_GCC_DIAG(3,4);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 09cca41ade..ff239e2d62 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -1,5 +1,5 @@
/* Build expressions with type checking for C compiler.
- Copyright (C) 1987-2016 Free Software Foundation, Inc.
+ Copyright (C) 1987-2017 Free Software Foundation, Inc.
This file is part of GCC.
@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "memmodel.h"
#include "target.h"
#include "function.h"
#include "bitmap.h"
@@ -42,12 +43,12 @@ along with GCC; see the file COPYING3. If not see
#include "tree-iterator.h"
#include "gimplify.h"
#include "tree-inline.h"
-#include "omp-low.h"
+#include "omp-general.h"
#include "c-family/c-objc.h"
#include "c-family/c-ubsan.h"
#include "cilk.h"
#include "gomp-constants.h"
-#include "spellcheck.h"
+#include "spellcheck-tree.h"
#include "gcc-rich-location.h"
/* Possible cases of implicit bad conversions. Used to select
@@ -183,11 +184,12 @@ struct tagged_tu_seen_cache {
static const struct tagged_tu_seen_cache * tagged_tu_seen_base;
static void free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *);
-/* Do `exp = require_complete_type (exp);' to make sure exp
- does not have an incomplete type. (That includes void types.) */
+/* Do `exp = require_complete_type (loc, exp);' to make sure exp
+ does not have an incomplete type. (That includes void types.)
+ LOC is the location of the use. */
tree
-require_complete_type (tree value)
+require_complete_type (location_t loc, tree value)
{
tree type = TREE_TYPE (value);
@@ -198,23 +200,24 @@ require_complete_type (tree value)
if (COMPLETE_TYPE_P (type))
return value;
- c_incomplete_type_error (value, type);
+ c_incomplete_type_error (loc, value, type);
return error_mark_node;
}
/* Print an error message for invalid use of an incomplete type.
VALUE is the expression that was used (or 0 if that isn't known)
- and TYPE is the type that was invalid. */
+ and TYPE is the type that was invalid. LOC is the location for
+ the error. */
void
-c_incomplete_type_error (const_tree value, const_tree type)
+c_incomplete_type_error (location_t loc, const_tree value, const_tree type)
{
/* Avoid duplicate error message. */
if (TREE_CODE (type) == ERROR_MARK)
return;
if (value != 0 && (VAR_P (value) || TREE_CODE (value) == PARM_DECL))
- error ("%qD has an incomplete type %qT", value, type);
+ error_at (loc, "%qD has an incomplete type %qT", value, type);
else
{
retry:
@@ -228,7 +231,7 @@ c_incomplete_type_error (const_tree value, const_tree type)
break;
case VOID_TYPE:
- error ("invalid use of void expression");
+ error_at (loc, "invalid use of void expression");
return;
case ARRAY_TYPE:
@@ -236,13 +239,13 @@ c_incomplete_type_error (const_tree value, const_tree type)
{
if (TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL)
{
- error ("invalid use of flexible array member");
+ error_at (loc, "invalid use of flexible array member");
return;
}
type = TREE_TYPE (type);
goto retry;
}
- error ("invalid use of array with unspecified bounds");
+ error_at (loc, "invalid use of array with unspecified bounds");
return;
default:
@@ -250,10 +253,10 @@ c_incomplete_type_error (const_tree value, const_tree type)
}
if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
- error ("invalid use of undefined type %qT", type);
+ error_at (loc, "invalid use of undefined type %qT", type);
else
/* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL. */
- error ("invalid use of incomplete typedef %qT", type);
+ error_at (loc, "invalid use of incomplete typedef %qT", type);
}
}
@@ -603,8 +606,8 @@ composite_type (tree t1, tree t2)
t1 = build_function_type (valtype, newargs);
t1 = qualify_type (t1, t2);
- /* ... falls through ... */
}
+ /* FALLTHRU */
default:
return build_type_attribute_variant (t1, attributes);
@@ -925,18 +928,41 @@ c_common_type (tree t1, tree t2)
return long_integer_type_node;
}
+ /* For floating types of the same TYPE_PRECISION (which we here
+ assume means either the same set of values, or sets of values
+ neither a subset of the other, with behavior being undefined in
+ the latter case), follow the rules from TS 18661-3: prefer
+ interchange types _FloatN, then standard types long double,
+ double, float, then extended types _FloatNx. For extended types,
+ check them starting with _Float128x as that seems most consistent
+ in spirit with preferring long double to double; for interchange
+ types, also check in that order for consistency although it's not
+ possible for more than one of them to have the same
+ precision. */
+ tree mv1 = TYPE_MAIN_VARIANT (t1);
+ tree mv2 = TYPE_MAIN_VARIANT (t2);
+
+ for (int i = NUM_FLOATN_TYPES - 1; i >= 0; i--)
+ if (mv1 == FLOATN_TYPE_NODE (i) || mv2 == FLOATN_TYPE_NODE (i))
+ return FLOATN_TYPE_NODE (i);
+
/* Likewise, prefer long double to double even if same size. */
- if (TYPE_MAIN_VARIANT (t1) == long_double_type_node
- || TYPE_MAIN_VARIANT (t2) == long_double_type_node)
+ if (mv1 == long_double_type_node || mv2 == long_double_type_node)
return long_double_type_node;
/* Likewise, prefer double to float even if same size.
We got a couple of embedded targets with 32 bit doubles, and the
pdp11 might have 64 bit floats. */
- if (TYPE_MAIN_VARIANT (t1) == double_type_node
- || TYPE_MAIN_VARIANT (t2) == double_type_node)
+ if (mv1 == double_type_node || mv2 == double_type_node)
return double_type_node;
+ if (mv1 == float_type_node || mv2 == float_type_node)
+ return float_type_node;
+
+ for (int i = NUM_FLOATNX_TYPES - 1; i >= 0; i--)
+ if (mv1 == FLOATNX_TYPE_NODE (i) || mv2 == FLOATNX_TYPE_NODE (i))
+ return FLOATNX_TYPE_NODE (i);
+
/* Otherwise prefer the unsigned one. */
if (TYPE_UNSIGNED (t1))
@@ -1103,10 +1129,28 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p,
switch (TREE_CODE (t1))
{
+ case INTEGER_TYPE:
+ case FIXED_POINT_TYPE:
+ case REAL_TYPE:
+ /* With these nodes, we can't determine type equivalence by
+ looking at what is stored in the nodes themselves, because
+ two nodes might have different TYPE_MAIN_VARIANTs but still
+ represent the same type. For example, wchar_t and int could
+ have the same properties (TYPE_PRECISION, TYPE_MIN_VALUE,
+ TYPE_MAX_VALUE, etc.), but have different TYPE_MAIN_VARIANTs
+ and are distinct types. On the other hand, int and the
+ following typedef
+
+ typedef int INT __attribute((may_alias));
+
+ have identical properties, different TYPE_MAIN_VARIANTs, but
+ represent the same type. The canonical type system keeps
+ track of equivalence in this case, so we fall back on it. */
+ return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2);
+
case POINTER_TYPE:
- /* Do not remove mode or aliasing information. */
- if (TYPE_MODE (t1) != TYPE_MODE (t2)
- || TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
+ /* Do not remove mode information. */
+ if (TYPE_MODE (t1) != TYPE_MODE (t2))
break;
val = (TREE_TYPE (t1) == TREE_TYPE (t2)
? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
@@ -1837,7 +1881,7 @@ array_to_pointer_conversion (location_t loc, tree exp)
"is ill-formed in C++");
}
- adr = build_unary_op (loc, ADDR_EXPR, exp, 1);
+ adr = build_unary_op (loc, ADDR_EXPR, exp, true);
return convert (ptrtype, adr);
}
@@ -1854,7 +1898,7 @@ function_to_pointer_conversion (location_t loc, tree exp)
if (TREE_NO_WARNING (orig_exp))
TREE_NO_WARNING (exp) = 1;
- return build_unary_op (loc, ADDR_EXPR, exp, 0);
+ return build_unary_op (loc, ADDR_EXPR, exp, false);
}
/* Mark EXP as read, not just set, for set but not used -Wunused
@@ -1876,6 +1920,7 @@ mark_exp_read (tree exp)
case IMAGPART_EXPR:
CASE_CONVERT:
case ADDR_EXPR:
+ case VIEW_CONVERT_EXPR:
mark_exp_read (TREE_OPERAND (exp, 0));
break;
case COMPOUND_EXPR:
@@ -1998,7 +2043,7 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp,
vec<tree, va_gc> *params;
tree nonatomic_type, tmp, tmp_addr, fndecl, func_call;
tree expr_type = TREE_TYPE (exp.value);
- tree expr_addr = build_unary_op (loc, ADDR_EXPR, exp.value, 0);
+ tree expr_addr = build_unary_op (loc, ADDR_EXPR, exp.value, false);
tree seq_cst = build_int_cst (integer_type_node, MEMMODEL_SEQ_CST);
gcc_assert (TYPE_ATOMIC (expr_type));
@@ -2011,7 +2056,7 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp,
create the VAL temp variable to hold the RHS. */
nonatomic_type = build_qualified_type (expr_type, TYPE_UNQUALIFIED);
tmp = create_tmp_var_raw (nonatomic_type);
- tmp_addr = build_unary_op (loc, ADDR_EXPR, tmp, 0);
+ tmp_addr = build_unary_op (loc, ADDR_EXPR, tmp, false);
TREE_ADDRESSABLE (tmp) = 1;
TREE_NO_WARNING (tmp) = 1;
@@ -2117,7 +2162,7 @@ default_conversion (tree exp)
return error_mark_node;
}
- exp = require_complete_type (exp);
+ exp = require_complete_type (EXPR_LOC_OR_LOC (exp, input_location), exp);
if (exp == error_mark_node)
return error_mark_node;
@@ -2309,10 +2354,12 @@ should_suggest_deref_p (tree datum_type)
/* Make an expression to refer to the COMPONENT field of structure or
union value DATUM. COMPONENT is an IDENTIFIER_NODE. LOC is the
- location of the COMPONENT_REF. */
+ location of the COMPONENT_REF. COMPONENT_LOC is the location
+ of COMPONENT. */
tree
-build_component_ref (location_t loc, tree datum, tree component)
+build_component_ref (location_t loc, tree datum, tree component,
+ location_t component_loc)
{
tree type = TREE_TYPE (datum);
enum tree_code code = TREE_CODE (type);
@@ -2334,7 +2381,7 @@ build_component_ref (location_t loc, tree datum, tree component)
{
if (!COMPLETE_TYPE_P (type))
{
- c_incomplete_type_error (NULL_TREE, type);
+ c_incomplete_type_error (loc, NULL_TREE, type);
return error_mark_node;
}
@@ -2344,8 +2391,19 @@ build_component_ref (location_t loc, tree datum, tree component)
{
tree guessed_id = lookup_field_fuzzy (type, component);
if (guessed_id)
- error_at (loc, "%qT has no member named %qE; did you mean %qE?",
- type, component, guessed_id);
+ {
+ /* Attempt to provide a fixit replacement hint, if
+ we have a valid range for the component. */
+ location_t reported_loc
+ = (component_loc != UNKNOWN_LOCATION) ? component_loc : loc;
+ gcc_rich_location rich_loc (reported_loc);
+ if (component_loc != UNKNOWN_LOCATION)
+ rich_loc.add_fixit_misspelled_id (component_loc, guessed_id);
+ error_at_rich_loc
+ (&rich_loc,
+ "%qT has no member named %qE; did you mean %qE?",
+ type, component, guessed_id);
+ }
else
error_at (loc, "%qT has no member named %qE", type, component);
return error_mark_node;
@@ -2417,7 +2475,7 @@ build_component_ref (location_t loc, tree datum, tree component)
where the user has confused "." vs "->". */
rich_location richloc (line_table, loc);
/* "loc" should be the "." token. */
- richloc.add_fixit_replace (source_range::from_location (loc), "->");
+ richloc.add_fixit_replace ("->");
error_at_rich_loc (&richloc,
"%qE is a pointer; did you mean to use %<->%>?",
datum);
@@ -2581,8 +2639,8 @@ build_array_ref (location_t loc, tree array, tree index)
gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE);
- bool non_lvalue
- = convert_vector_to_pointer_for_subscript (loc, &array, index);
+ bool was_vector = VECTOR_TYPE_P (TREE_TYPE (array));
+ bool non_lvalue = convert_vector_to_array_for_subscript (loc, &array, index);
if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
{
@@ -2596,7 +2654,7 @@ build_array_ref (location_t loc, tree array, tree index)
|| (COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (array)))
&& TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))) != INTEGER_CST))
{
- if (!c_mark_addressable (array))
+ if (!c_mark_addressable (array, true))
return error_mark_node;
}
/* An array that is indexed by a constant value which is not within
@@ -2611,7 +2669,8 @@ build_array_ref (location_t loc, tree array, tree index)
return error_mark_node;
}
- if (pedantic || warn_c90_c99_compat)
+ if ((pedantic || warn_c90_c99_compat)
+ && ! was_vector)
{
tree foo = array;
while (TREE_CODE (foo) == COMPONENT_REF)
@@ -2642,7 +2701,7 @@ build_array_ref (location_t loc, tree array, tree index)
in an inline function.
Hope it doesn't break something else. */
| TREE_THIS_VOLATILE (array));
- ret = require_complete_type (rval);
+ ret = require_complete_type (loc, rval);
protected_set_expr_location (ret, loc);
if (non_lvalue)
ret = non_lvalue_loc (loc, ret);
@@ -3046,19 +3105,21 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
if (fundecl
&& DECL_BUILT_IN (fundecl)
&& DECL_BUILT_IN_CLASS (fundecl) == BUILT_IN_NORMAL
- && !check_builtin_function_arguments (fundecl, nargs, argarray))
+ && !check_builtin_function_arguments (loc, arg_loc, fundecl, nargs,
+ argarray))
return error_mark_node;
/* Check that the arguments to the function are valid. */
- check_function_arguments (loc, fntype, nargs, argarray);
+ bool warned_p = check_function_arguments (loc, fundecl, fntype,
+ nargs, argarray);
if (name != NULL_TREE
&& !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10))
{
if (require_constant_value)
- result =
- fold_build_call_array_initializer_loc (loc, TREE_TYPE (fntype),
- function, nargs, argarray);
+ result
+ = fold_build_call_array_initializer_loc (loc, TREE_TYPE (fntype),
+ function, nargs, argarray);
else
result = fold_build_call_array_loc (loc, TREE_TYPE (fntype),
function, nargs, argarray);
@@ -3069,6 +3130,10 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
else
result = build_call_array_loc (loc, TREE_TYPE (fntype),
function, nargs, argarray);
+ /* If -Wnonnull warning has been diagnosed, avoid diagnosing it again
+ later. */
+ if (warned_p && TREE_CODE (result) == CALL_EXPR)
+ TREE_NO_WARNING (result) = 1;
/* In this improbable scenario, a nested function returns a VM type.
Create a TARGET_EXPR so that the call always has a LHS, much as
@@ -3087,7 +3152,7 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
"function with qualified void return type called");
return result;
}
- return require_complete_type (result);
+ return require_complete_type (loc, result);
}
/* Like build_function_call_vec, but call also resolve_overloaded_builtin. */
@@ -3146,6 +3211,7 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
const bool type_generic = fundecl
&& lookup_attribute ("type generic", TYPE_ATTRIBUTES (TREE_TYPE (fundecl)));
bool type_generic_remove_excess_precision = false;
+ bool type_generic_overflow_p = false;
tree selector;
/* Change pointer to function to the function itself for
@@ -3175,8 +3241,15 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
type_generic_remove_excess_precision = true;
break;
+ case BUILT_IN_ADD_OVERFLOW_P:
+ case BUILT_IN_SUB_OVERFLOW_P:
+ case BUILT_IN_MUL_OVERFLOW_P:
+ /* The last argument of these type-generic builtins
+ should not be promoted. */
+ type_generic_overflow_p = true;
+ break;
+
default:
- type_generic_remove_excess_precision = false;
break;
}
}
@@ -3238,7 +3311,31 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
val = c_fully_fold (val, false, NULL);
STRIP_TYPE_NOPS (val);
- val = require_complete_type (val);
+ val = require_complete_type (ploc, val);
+
+ /* Some floating-point arguments must be promoted to double when
+ no type is specified by a prototype. This applies to
+ arguments of type float, and to architecture-specific types
+ (ARM __fp16), but not to _FloatN or _FloatNx types. */
+ bool promote_float_arg = false;
+ if (type == NULL_TREE
+ && TREE_CODE (valtype) == REAL_TYPE
+ && (TYPE_PRECISION (valtype)
+ <= TYPE_PRECISION (double_type_node))
+ && TYPE_MAIN_VARIANT (valtype) != double_type_node
+ && TYPE_MAIN_VARIANT (valtype) != long_double_type_node
+ && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (valtype)))
+ {
+ /* Promote this argument, unless it has a _FloatN or
+ _FloatNx type. */
+ promote_float_arg = true;
+ for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ if (TYPE_MAIN_VARIANT (valtype) == FLOATN_NX_TYPE_NODE (i))
+ {
+ promote_float_arg = false;
+ break;
+ }
+ }
if (type != 0)
{
@@ -3341,15 +3438,18 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
/* Detect integer changing in width or signedness.
These warnings are only activated with
-Wtraditional-conversion, not with -Wtraditional. */
- else if (warn_traditional_conversion && INTEGRAL_TYPE_P (type)
+ else if (warn_traditional_conversion
+ && INTEGRAL_TYPE_P (type)
&& INTEGRAL_TYPE_P (valtype))
{
tree would_have_been = default_conversion (val);
tree type1 = TREE_TYPE (would_have_been);
- if (TREE_CODE (type) == ENUMERAL_TYPE
- && (TYPE_MAIN_VARIANT (type)
- == TYPE_MAIN_VARIANT (valtype)))
+ if (val == error_mark_node)
+ /* VAL could have been of incomplete type. */;
+ else if (TREE_CODE (type) == ENUMERAL_TYPE
+ && (TYPE_MAIN_VARIANT (type)
+ == TYPE_MAIN_VARIANT (valtype)))
/* No warning if function asks for enum
and the actual arg is that enum type. */
;
@@ -3406,12 +3506,7 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
parmval = default_conversion (parmval);
}
}
- else if (TREE_CODE (valtype) == REAL_TYPE
- && (TYPE_PRECISION (valtype)
- <= TYPE_PRECISION (double_type_node))
- && TYPE_MAIN_VARIANT (valtype) != double_type_node
- && TYPE_MAIN_VARIANT (valtype) != long_double_type_node
- && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (valtype)))
+ else if (promote_float_arg)
{
if (type_generic)
parmval = val;
@@ -3426,9 +3521,12 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
parmval = convert (double_type_node, val);
}
}
- else if (excess_precision && !type_generic)
+ else if ((excess_precision && !type_generic)
+ || (type_generic_overflow_p && parmnum == 2))
/* A "double" argument with excess precision being passed
- without a prototype or in variable arguments. */
+ without a prototype or in variable arguments.
+ The last argument of __builtin_*_overflow_p should not be
+ promoted. */
parmval = convert (valtype, val);
else if ((invalid_func_diag =
targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val)))
@@ -3486,10 +3584,10 @@ parser_build_unary_op (location_t loc, enum tree_code code, struct c_expr arg)
}
else
{
- result.value = build_unary_op (loc, code, arg.value, 0);
+ result.value = build_unary_op (loc, code, arg.value, false);
- if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value))
- overflow_warning (loc, result.value);
+ if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value))
+ overflow_warning (loc, result.value);
}
/* We are typically called when parsing a prefix token at LOC acting on
@@ -3501,6 +3599,18 @@ parser_build_unary_op (location_t loc, enum tree_code code, struct c_expr arg)
return result;
}
+/* Returns true if TYPE is a character type, *not* including wchar_t. */
+
+static bool
+char_type_p (tree type)
+{
+ return (type == char_type_node
+ || type == unsigned_char_type_node
+ || type == signed_char_type_node
+ || type == char16_type_node
+ || type == char32_type_node);
+}
+
/* This is the entry point used by the parser to build binary operators
in the input. CODE, a tree_code, specifies the binary operator, and
ARG1 and ARG2 are the operands. In addition to constructing the
@@ -3607,7 +3717,7 @@ parser_build_binary_op (location_t location, enum tree_code code,
while (1);
}
if (TREE_CODE (TREE_TYPE (t)) != BOOLEAN_TYPE)
- warn_logical_not_parentheses (location, code, arg2.value);
+ warn_logical_not_parentheses (location, code, arg1.value, arg2.value);
}
/* Warn about comparisons against string literals, with the exception
@@ -3620,6 +3730,21 @@ parser_build_binary_op (location_t location, enum tree_code code,
&& !integer_zerop (tree_strip_nop_conversions (arg1.value))))
warning_at (location, OPT_Waddress,
"comparison with string literal results in unspecified behavior");
+ /* Warn for ptr == '\0', it's likely that it should've been ptr[0]. */
+ if (POINTER_TYPE_P (type1)
+ && null_pointer_constant_p (arg2.value)
+ && char_type_p (type2)
+ && warning_at (location, OPT_Wpointer_compare,
+ "comparison between pointer and zero character "
+ "constant"))
+ inform (arg1.get_start (), "did you mean to dereference the pointer?");
+ else if (POINTER_TYPE_P (type2)
+ && null_pointer_constant_p (arg1.value)
+ && char_type_p (type1)
+ && warning_at (location, OPT_Wpointer_compare,
+ "comparison between pointer and zero character "
+ "constant"))
+ inform (arg2.get_start (), "did you mean to dereference the pointer?");
}
else if (TREE_CODE_CLASS (code) == tcc_comparison
&& (code1 == STRING_CST || code2 == STRING_CST))
@@ -3783,7 +3908,7 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
tree loop_label, loop_decl, done_label, done_decl;
tree lhs_type = TREE_TYPE (lhs);
- tree lhs_addr = build_unary_op (loc, ADDR_EXPR, lhs, 0);
+ tree lhs_addr = build_unary_op (loc, ADDR_EXPR, lhs, false);
tree seq_cst = build_int_cst (integer_type_node, MEMMODEL_SEQ_CST);
tree rhs_type = TREE_TYPE (rhs);
@@ -3820,7 +3945,7 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
if (modifycode == NOP_EXPR)
{
/* Build __atomic_store (&lhs, &val, SEQ_CST) */
- rhs = build_unary_op (loc, ADDR_EXPR, val, 0);
+ rhs = build_unary_op (loc, ADDR_EXPR, val, false);
fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_STORE);
params->quick_push (lhs_addr);
params->quick_push (rhs);
@@ -3925,12 +4050,12 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
cas_loop:
/* Create the variables and labels required for the op= form. */
old = create_tmp_var_raw (nonatomic_lhs_type);
- old_addr = build_unary_op (loc, ADDR_EXPR, old, 0);
+ old_addr = build_unary_op (loc, ADDR_EXPR, old, false);
TREE_ADDRESSABLE (old) = 1;
TREE_NO_WARNING (old) = 1;
newval = create_tmp_var_raw (nonatomic_lhs_type);
- newval_addr = build_unary_op (loc, ADDR_EXPR, newval, 0);
+ newval_addr = build_unary_op (loc, ADDR_EXPR, newval, false);
TREE_ADDRESSABLE (newval) = 1;
TREE_NO_WARNING (newval) = 1;
@@ -4023,17 +4148,17 @@ cas_loop:
/* Construct and perhaps optimize a tree representation
for a unary operation. CODE, a tree_code, specifies the operation
and XARG is the operand.
- For any CODE other than ADDR_EXPR, FLAG nonzero suppresses
- the default promotions (such as from short to int).
- For ADDR_EXPR, the default promotions are not applied; FLAG nonzero
- allows non-lvalues; this is only used to handle conversion of non-lvalue
- arrays to pointers in C99.
+ For any CODE other than ADDR_EXPR, NOCONVERT suppresses the default
+ promotions (such as from short to int).
+ For ADDR_EXPR, the default promotions are not applied; NOCONVERT allows
+ non-lvalues; this is only used to handle conversion of non-lvalue arrays
+ to pointers in C99.
LOCATION is the location of the operator. */
tree
-build_unary_op (location_t location,
- enum tree_code code, tree xarg, int flag)
+build_unary_op (location_t location, enum tree_code code, tree xarg,
+ bool noconvert)
{
/* No default_conversion here. It causes trouble for ADDR_EXPR. */
tree arg = xarg;
@@ -4042,7 +4167,6 @@ build_unary_op (location_t location,
tree val;
tree ret = error_mark_node;
tree eptype = NULL_TREE;
- int noconvert = flag;
const char *invalid_op_diag;
bool int_operands;
@@ -4051,7 +4175,7 @@ build_unary_op (location_t location,
arg = remove_c_maybe_const_expr (arg);
if (code != ADDR_EXPR)
- arg = require_complete_type (arg);
+ arg = require_complete_type (location, arg);
typecode = TREE_CODE (TREE_TYPE (arg));
if (typecode == ERROR_MARK)
@@ -4108,6 +4232,22 @@ build_unary_op (location_t location,
|| (typecode == VECTOR_TYPE
&& !VECTOR_FLOAT_TYPE_P (TREE_TYPE (arg))))
{
+ tree e = arg;
+
+ /* Warn if the expression has boolean value. */
+ while (TREE_CODE (e) == COMPOUND_EXPR)
+ e = TREE_OPERAND (e, 1);
+
+ if ((TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE
+ || truth_value_p (TREE_CODE (e)))
+ && warning_at (location, OPT_Wbool_operation,
+ "%<~%> on a boolean expression"))
+ {
+ gcc_rich_location richloc (location);
+ richloc.add_fixit_insert_before (location, "!");
+ inform_at_rich_loc (&richloc, "did you mean to use logical "
+ "not?");
+ }
if (!noconvert)
arg = default_conversion (arg);
}
@@ -4187,7 +4327,8 @@ build_unary_op (location_t location,
if (TREE_CODE (arg) == C_MAYBE_CONST_EXPR)
{
tree inner = build_unary_op (location, code,
- C_MAYBE_CONST_EXPR_EXPR (arg), flag);
+ C_MAYBE_CONST_EXPR_EXPR (arg),
+ noconvert);
if (inner == error_mark_node)
return error_mark_node;
ret = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (inner),
@@ -4217,6 +4358,16 @@ build_unary_op (location_t location,
"decrement of enumeration value is invalid in C++");
}
+ if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
+ {
+ if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
+ warning_at (location, OPT_Wbool_operation,
+ "increment of a boolean expression");
+ else
+ warning_at (location, OPT_Wbool_operation,
+ "decrement of a boolean expression");
+ }
+
/* Ensure the argument is fully folded inside any SAVE_EXPR. */
arg = c_fully_fold (arg, false, NULL);
@@ -4235,9 +4386,11 @@ build_unary_op (location_t location,
if (!atomic_op)
{
arg = stabilize_reference (arg);
- real = build_unary_op (EXPR_LOCATION (arg), REALPART_EXPR, arg, 1);
- imag = build_unary_op (EXPR_LOCATION (arg), IMAGPART_EXPR, arg, 1);
- real = build_unary_op (EXPR_LOCATION (arg), code, real, 1);
+ real = build_unary_op (EXPR_LOCATION (arg), REALPART_EXPR, arg,
+ true);
+ imag = build_unary_op (EXPR_LOCATION (arg), IMAGPART_EXPR, arg,
+ true);
+ real = build_unary_op (EXPR_LOCATION (arg), code, real, true);
if (real == error_mark_node || imag == error_mark_node)
return error_mark_node;
ret = build2 (COMPLEX_EXPR, TREE_TYPE (arg),
@@ -4397,7 +4550,7 @@ build_unary_op (location_t location,
/* Anything not already handled and not a true memory reference
or a non-lvalue array is an error. */
- if (typecode != FUNCTION_TYPE && !flag
+ if (typecode != FUNCTION_TYPE && !noconvert
&& !lvalue_or_else (location, arg, lv_addressof))
return error_mark_node;
@@ -4406,7 +4559,8 @@ build_unary_op (location_t location,
if (TREE_CODE (arg) == C_MAYBE_CONST_EXPR)
{
tree inner = build_unary_op (location, code,
- C_MAYBE_CONST_EXPR_EXPR (arg), flag);
+ C_MAYBE_CONST_EXPR_EXPR (arg),
+ noconvert);
ret = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (inner),
C_MAYBE_CONST_EXPR_PRE (arg), inner);
gcc_assert (!C_MAYBE_CONST_EXPR_INT_OPERANDS (arg));
@@ -4446,7 +4600,7 @@ build_unary_op (location_t location,
return error_mark_node;
}
- /* ... fall through ... */
+ /* fall through */
case ARRAY_REF:
if (TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_OPERAND (arg, 0))))
@@ -4539,7 +4693,7 @@ lvalue_p (const_tree ref)
case COMPOUND_LITERAL_EXPR:
case STRING_CST:
- return 1;
+ return true;
case INDIRECT_REF:
case ARRAY_REF:
@@ -4555,7 +4709,7 @@ lvalue_p (const_tree ref)
return TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE;
default:
- return 0;
+ return false;
}
}
@@ -4601,16 +4755,26 @@ lvalue_or_else (location_t loc, const_tree ref, enum lvalue_use use)
/* Mark EXP saying that we need to be able to take the
address of it; it should not be allocated in a register.
- Returns true if successful. */
+ Returns true if successful. ARRAY_REF_P is true if this
+ is for ARRAY_REF construction - in that case we don't want
+ to look through VIEW_CONVERT_EXPR from VECTOR_TYPE to ARRAY_TYPE,
+ it is fine to use ARRAY_REFs for vector subscripts on vector
+ register variables. */
bool
-c_mark_addressable (tree exp)
+c_mark_addressable (tree exp, bool array_ref_p)
{
tree x = exp;
while (1)
switch (TREE_CODE (x))
{
+ case VIEW_CONVERT_EXPR:
+ if (array_ref_p
+ && TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
+ && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0))))
+ return true;
+ /* FALLTHRU */
case COMPONENT_REF:
case ADDR_EXPR:
case ARRAY_REF:
@@ -4648,10 +4812,10 @@ c_mark_addressable (tree exp)
return false;
}
- /* drops in */
+ /* FALLTHRU */
case FUNCTION_DECL:
TREE_ADDRESSABLE (x) = 1;
- /* drops out */
+ /* FALLTHRU */
default:
return true;
}
@@ -4800,6 +4964,8 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
|| code2 == COMPLEX_TYPE))
{
result_type = c_common_type (type1, type2);
+ if (result_type == error_mark_node)
+ return error_mark_node;
do_warn_double_promotion (result_type, type1, type2,
"implicit conversion from %qT to %qT to "
"match other result of conditional",
@@ -5041,6 +5207,15 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
ret = build1 (EXCESS_PRECISION_EXPR, semantic_result_type, ret);
protected_set_expr_location (ret, colon_loc);
+
+ /* If the OP1 and OP2 are the same and don't have side-effects,
+ warn here, because the COND_EXPR will be turned into OP1. */
+ if (warn_duplicated_branches
+ && TREE_CODE (ret) == COND_EXPR
+ && (op1 == op2 || operand_equal_p (op1, op2, 0)))
+ warning_at (EXPR_LOCATION (ret), OPT_Wduplicated_branches,
+ "this condition has identical branches");
+
return ret;
}
@@ -5272,7 +5447,7 @@ build_c_cast (location_t loc, tree type, tree expr)
if (!VOID_TYPE_P (type))
{
- value = require_complete_type (value);
+ value = require_complete_type (loc, value);
if (value == error_mark_node)
return error_mark_node;
}
@@ -5542,7 +5717,7 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
bool is_atomic_op;
/* Types that aren't fully specified cannot be used in assignments. */
- lhs = require_complete_type (lhs);
+ lhs = require_complete_type (location, lhs);
/* Avoid duplicate error messages from operands that had errors. */
if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
@@ -5876,16 +6051,21 @@ error_init (location_t loc, const char *gmsgid)
component name is taken from the spelling stack. */
static void
-pedwarn_init (location_t location, int opt, const char *gmsgid)
+pedwarn_init (location_t loc, int opt, const char *gmsgid)
{
char *ofwhat;
bool warned;
+ /* Use the location where a macro was expanded rather than where
+ it was defined to make sure macros defined in system headers
+ but used incorrectly elsewhere are diagnosed. */
+ source_location exploc = expansion_point_location_if_in_system_header (loc);
+
/* The gmsgid may be a format string with %< and %>. */
- warned = pedwarn (location, opt, gmsgid);
+ warned = pedwarn (exploc, opt, gmsgid);
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat && warned)
- inform (location, "(near initialization for %qs)", ofwhat);
+ inform (exploc, "(near initialization for %qs)", ofwhat);
}
/* Issue a warning for a bad initializer component.
@@ -5900,11 +6080,16 @@ warning_init (location_t loc, int opt, const char *gmsgid)
char *ofwhat;
bool warned;
+ /* Use the location where a macro was expanded rather than where
+ it was defined to make sure macros defined in system headers
+ but used incorrectly elsewhere are diagnosed. */
+ source_location exploc = expansion_point_location_if_in_system_header (loc);
+
/* The gmsgid may be a format string with %< and %>. */
- warned = warning_at (loc, opt, gmsgid);
+ warned = warning_at (exploc, opt, gmsgid);
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat && warned)
- inform (loc, "(near initialization for %qs)", ofwhat);
+ inform (exploc, "(near initialization for %qs)", ofwhat);
}
/* If TYPE is an array type and EXPR is a parenthesized string
@@ -6137,7 +6322,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
error_at (location, "void value not ignored as it ought to be");
return error_mark_node;
}
- rhs = require_complete_type (rhs);
+ rhs = require_complete_type (location, rhs);
if (rhs == error_mark_node)
return error_mark_node;
@@ -7359,6 +7544,7 @@ struct initializer_stack
char top_level;
char require_constant_value;
char require_constant_elements;
+ rich_location *missing_brace_richloc;
};
static struct initializer_stack *initializer_stack;
@@ -7366,7 +7552,8 @@ static struct initializer_stack *initializer_stack;
/* Prepare to parse and output the initializer for variable DECL. */
void
-start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level)
+start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level,
+ rich_location *richloc)
{
const char *locus;
struct initializer_stack *p = XNEW (struct initializer_stack);
@@ -7382,6 +7569,7 @@ start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level)
p->spelling_size = spelling_size;
p->top_level = constructor_top_level;
p->next = initializer_stack;
+ p->missing_brace_richloc = richloc;
initializer_stack = p;
constructor_decl = decl;
@@ -7566,6 +7754,8 @@ really_start_incremental_init (tree type)
}
}
+extern location_t last_init_list_comma;
+
/* Called when we see an open brace for a nested initializer. Finish
off any pending levels with implicit braces. */
void
@@ -7576,14 +7766,16 @@ finish_implicit_inits (location_t loc, struct obstack *braced_init_obstack)
if (RECORD_OR_UNION_TYPE_P (constructor_type)
&& constructor_fields == 0)
process_init_element (input_location,
- pop_init_level (loc, 1, braced_init_obstack),
+ pop_init_level (loc, 1, braced_init_obstack,
+ last_init_list_comma),
true, braced_init_obstack);
else if (TREE_CODE (constructor_type) == ARRAY_TYPE
&& constructor_max_index
&& tree_int_cst_lt (constructor_max_index,
constructor_index))
process_init_element (input_location,
- pop_init_level (loc, 1, braced_init_obstack),
+ pop_init_level (loc, 1, braced_init_obstack,
+ last_init_list_comma),
true, braced_init_obstack);
else
break;
@@ -7702,7 +7894,12 @@ push_init_level (location_t loc, int implicit,
}
if (implicit == 1)
- found_missing_braces = 1;
+ {
+ found_missing_braces = 1;
+ if (initializer_stack->missing_brace_richloc)
+ initializer_stack->missing_brace_richloc->add_fixit_insert_before
+ (loc, "{");
+ }
if (RECORD_OR_UNION_TYPE_P (constructor_type))
{
@@ -7780,7 +7977,8 @@ push_init_level (location_t loc, int implicit,
struct c_expr
pop_init_level (location_t loc, int implicit,
- struct obstack *braced_init_obstack)
+ struct obstack *braced_init_obstack,
+ location_t insert_before)
{
struct constructor_stack *p;
struct c_expr ret;
@@ -7794,10 +7992,15 @@ pop_init_level (location_t loc, int implicit,
pop any inner levels that didn't have explicit braces. */
while (constructor_stack->implicit)
process_init_element (input_location,
- pop_init_level (loc, 1, braced_init_obstack),
+ pop_init_level (loc, 1, braced_init_obstack,
+ insert_before),
true, braced_init_obstack);
gcc_assert (!constructor_range_stack);
}
+ else
+ if (initializer_stack->missing_brace_richloc)
+ initializer_stack->missing_brace_richloc->add_fixit_insert_before
+ (insert_before, "}");
/* Now output all pending elements. */
constructor_incremental = 1;
@@ -7854,8 +8057,12 @@ pop_init_level (location_t loc, int implicit,
/* Warn when some structs are initialized with direct aggregation. */
if (!implicit && found_missing_braces && warn_missing_braces
&& !constructor_zeroinit)
- warning_init (loc, OPT_Wmissing_braces,
- "missing braces around initializer");
+ {
+ gcc_assert (initializer_stack->missing_brace_richloc);
+ warning_at_rich_loc (initializer_stack->missing_brace_richloc,
+ OPT_Wmissing_braces,
+ "missing braces around initializer");
+ }
/* Warn when some struct elements are implicitly initialized to zero. */
if (warn_missing_field_initializers
@@ -7994,7 +8201,8 @@ set_designator (location_t loc, int array,
braces. */
while (constructor_stack->implicit)
process_init_element (input_location,
- pop_init_level (loc, 1, braced_init_obstack),
+ pop_init_level (loc, 1, braced_init_obstack,
+ last_init_list_comma),
true, braced_init_obstack);
constructor_designated = 1;
return 0;
@@ -8150,7 +8358,7 @@ set_init_index (location_t loc, tree first, tree last,
/* Within a struct initializer, specify the next field to be initialized. */
void
-set_init_label (location_t loc, tree fieldname,
+set_init_label (location_t loc, tree fieldname, location_t fieldname_loc,
struct obstack *braced_init_obstack)
{
tree field;
@@ -8169,7 +8377,21 @@ set_init_label (location_t loc, tree fieldname,
field = lookup_field (constructor_type, fieldname);
if (field == 0)
- error_at (loc, "unknown field %qE specified in initializer", fieldname);
+ {
+ tree guessed_id = lookup_field_fuzzy (constructor_type, fieldname);
+ if (guessed_id)
+ {
+ gcc_rich_location rich_loc (fieldname_loc);
+ rich_loc.add_fixit_misspelled_id (fieldname_loc, guessed_id);
+ error_at_rich_loc
+ (&rich_loc,
+ "%qT has no member named %qE; did you mean %qE?",
+ constructor_type, fieldname, guessed_id);
+ }
+ else
+ error_at (fieldname_loc, "%qT has no member named %qE",
+ constructor_type, fieldname);
+ }
else
do
{
@@ -8523,7 +8745,7 @@ set_nonincremental_init_from_string (tree str,
bitpos = ((wchar_bytes - 1) * charwidth) + HOST_BITS_PER_CHAR;
if (bitpos < HOST_BITS_PER_WIDE_INT)
{
- if (val[0] & (((HOST_WIDE_INT) 1) << (bitpos - 1)))
+ if (val[0] & (HOST_WIDE_INT_1 << (bitpos - 1)))
{
val[0] |= HOST_WIDE_INT_M1U << bitpos;
val[1] = -1;
@@ -8534,7 +8756,7 @@ set_nonincremental_init_from_string (tree str,
if (val[0] < 0)
val[1] = -1;
}
- else if (val[1] & (((HOST_WIDE_INT) 1)
+ else if (val[1] & (HOST_WIDE_INT_1
<< (bitpos - 1 - HOST_BITS_PER_WIDE_INT)))
val[1] |= HOST_WIDE_INT_M1U << (bitpos - HOST_BITS_PER_WIDE_INT);
}
@@ -8684,6 +8906,22 @@ output_init_element (location_t loc, tree value, tree origtype,
if (!maybe_const)
constructor_nonconst = 1;
+ /* Digest the initializer and issue any errors about incompatible
+ types before issuing errors about non-constant initializers. */
+ tree new_value = value;
+ if (semantic_type)
+ new_value = build1 (EXCESS_PRECISION_EXPR, semantic_type, value);
+ new_value = digest_init (loc, type, new_value, origtype, npc, strict_string,
+ require_constant_value);
+ if (new_value == error_mark_node)
+ {
+ constructor_erroneous = 1;
+ return;
+ }
+ if (require_constant_value || require_constant_elements)
+ constant_expression_warning (new_value);
+
+ /* Proceed to check the constness of the original initializer. */
if (!initializer_constant_valid_p (value, TREE_TYPE (value)))
{
if (require_constant_value)
@@ -8728,17 +8966,8 @@ output_init_element (location_t loc, tree value, tree origtype,
|| DECL_CHAIN (field)))))
return;
- if (semantic_type)
- value = build1 (EXCESS_PRECISION_EXPR, semantic_type, value);
- value = digest_init (loc, type, value, origtype, npc, strict_string,
- require_constant_value);
- if (value == error_mark_node)
- {
- constructor_erroneous = 1;
- return;
- }
- if (require_constant_value || require_constant_elements)
- constant_expression_warning (value);
+ /* Finally, set VALUE to the initializer value digested above. */
+ value = new_value;
/* If this element doesn't come next in sequence,
put it on constructor_pending_elts. */
@@ -9042,7 +9271,8 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
if (RECORD_OR_UNION_TYPE_P (constructor_type)
&& constructor_fields == 0)
process_init_element (loc,
- pop_init_level (loc, 1, braced_init_obstack),
+ pop_init_level (loc, 1, braced_init_obstack,
+ last_init_list_comma),
true, braced_init_obstack);
else if ((TREE_CODE (constructor_type) == ARRAY_TYPE
|| VECTOR_TYPE_P (constructor_type))
@@ -9050,7 +9280,8 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
&& tree_int_cst_lt (constructor_max_index,
constructor_index))
process_init_element (loc,
- pop_init_level (loc, 1, braced_init_obstack),
+ pop_init_level (loc, 1, braced_init_obstack,
+ last_init_list_comma),
true, braced_init_obstack);
else
break;
@@ -9383,7 +9614,8 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
gcc_assert (constructor_stack->implicit);
process_init_element (loc,
pop_init_level (loc, 1,
- braced_init_obstack),
+ braced_init_obstack,
+ last_init_list_comma),
true, braced_init_obstack);
}
for (p = range_stack;
@@ -9393,7 +9625,8 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
gcc_assert (constructor_stack->implicit);
process_init_element (loc,
pop_init_level (loc, 1,
- braced_init_obstack),
+ braced_init_obstack,
+ last_init_list_comma),
true, braced_init_obstack);
}
@@ -10908,21 +11141,16 @@ build_binary_op (location_t location, enum tree_code code,
Also set SHORT_SHIFT if shifting rightward. */
case RSHIFT_EXPR:
- if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
- {
- result_type = type0;
- converted = 1;
- }
- else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
- && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
- && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+ if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+ && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+ && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+ && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
{
result_type = type0;
converted = 1;
}
- else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+ else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE
+ || code0 == VECTOR_TYPE)
&& code1 == INTEGER_TYPE)
{
doing_shift = true;
@@ -10935,6 +11163,18 @@ build_binary_op (location_t location, enum tree_code code,
warning_at (location, OPT_Wshift_count_negative,
"right shift count is negative");
}
+ else if (code0 == VECTOR_TYPE)
+ {
+ if (compare_tree_int (op1,
+ TYPE_PRECISION (TREE_TYPE (type0)))
+ >= 0)
+ {
+ int_const = false;
+ if (c_inhibit_evaluation_warnings == 0)
+ warning_at (location, OPT_Wshift_count_overflow,
+ "right shift count >= width of vector element");
+ }
+ }
else
{
if (!integer_zerop (op1))
@@ -10958,21 +11198,16 @@ build_binary_op (location_t location, enum tree_code code,
break;
case LSHIFT_EXPR:
- if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
- {
- result_type = type0;
- converted = 1;
- }
- else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
- && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
- && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+ if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+ && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+ && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+ && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
{
result_type = type0;
converted = 1;
}
- else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+ else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE
+ || code0 == VECTOR_TYPE)
&& code1 == INTEGER_TYPE)
{
doing_shift = true;
@@ -10996,6 +11231,18 @@ build_binary_op (location_t location, enum tree_code code,
warning_at (location, OPT_Wshift_count_negative,
"left shift count is negative");
}
+ else if (code0 == VECTOR_TYPE)
+ {
+ if (compare_tree_int (op1,
+ TYPE_PRECISION (TREE_TYPE (type0)))
+ >= 0)
+ {
+ int_const = false;
+ if (c_inhibit_evaluation_warnings == 0)
+ warning_at (location, OPT_Wshift_count_overflow,
+ "left shift count >= width of vector element");
+ }
+ }
else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
{
int_const = false;
@@ -11073,7 +11320,8 @@ build_binary_op (location_t location, enum tree_code code,
else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
{
if (TREE_CODE (op0) == ADDR_EXPR
- && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0)))
+ && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0))
+ && !from_macro_expansion_at (location))
{
if (code == EQ_EXPR)
warning_at (location,
@@ -11093,7 +11341,8 @@ build_binary_op (location_t location, enum tree_code code,
else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
{
if (TREE_CODE (op1) == ADDR_EXPR
- && decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0)))
+ && decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0))
+ && !from_macro_expansion_at (location))
{
if (code == EQ_EXPR)
warning_at (location,
@@ -11374,9 +11623,9 @@ build_binary_op (location_t location, enum tree_code code,
{
op0 = c_save_expr (op0);
real = build_unary_op (EXPR_LOCATION (orig_op0), REALPART_EXPR,
- op0, 1);
+ op0, true);
imag = build_unary_op (EXPR_LOCATION (orig_op0), IMAGPART_EXPR,
- op0, 1);
+ op0, true);
switch (code)
{
case MULT_EXPR:
@@ -11396,9 +11645,9 @@ build_binary_op (location_t location, enum tree_code code,
{
op1 = c_save_expr (op1);
real = build_unary_op (EXPR_LOCATION (orig_op1), REALPART_EXPR,
- op1, 1);
+ op1, true);
imag = build_unary_op (EXPR_LOCATION (orig_op1), IMAGPART_EXPR,
- op1, 1);
+ op1, true);
switch (code)
{
case MULT_EXPR:
@@ -11617,14 +11866,16 @@ build_binary_op (location_t location, enum tree_code code,
else if (TREE_CODE (ret) != INTEGER_CST && int_operands
&& !in_late_binary_op)
ret = note_integer_operands (ret);
- if (semantic_result_type)
- ret = build1 (EXCESS_PRECISION_EXPR, semantic_result_type, ret);
protected_set_expr_location (ret, location);
if (instrument_expr != NULL)
ret = fold_build2 (COMPOUND_EXPR, TREE_TYPE (ret),
instrument_expr, ret);
+ if (semantic_result_type)
+ ret = build1_loc (location, EXCESS_PRECISION_EXPR,
+ semantic_result_type, ret);
+
return ret;
}
@@ -11844,22 +12095,22 @@ c_finish_omp_cancel (location_t loc, tree clauses)
{
tree fn = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
int mask = 0;
- if (find_omp_clause (clauses, OMP_CLAUSE_PARALLEL))
+ if (omp_find_clause (clauses, OMP_CLAUSE_PARALLEL))
mask = 1;
- else if (find_omp_clause (clauses, OMP_CLAUSE_FOR))
+ else if (omp_find_clause (clauses, OMP_CLAUSE_FOR))
mask = 2;
- else if (find_omp_clause (clauses, OMP_CLAUSE_SECTIONS))
+ else if (omp_find_clause (clauses, OMP_CLAUSE_SECTIONS))
mask = 4;
- else if (find_omp_clause (clauses, OMP_CLAUSE_TASKGROUP))
+ else if (omp_find_clause (clauses, OMP_CLAUSE_TASKGROUP))
mask = 8;
else
{
- error_at (loc, "%<#pragma omp cancel must specify one of "
+ error_at (loc, "%<#pragma omp cancel%> must specify one of "
"%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> "
"clauses");
return;
}
- tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
+ tree ifc = omp_find_clause (clauses, OMP_CLAUSE_IF);
if (ifc != NULL_TREE)
{
tree type = TREE_TYPE (OMP_CLAUSE_IF_EXPR (ifc));
@@ -11883,17 +12134,17 @@ c_finish_omp_cancellation_point (location_t loc, tree clauses)
{
tree fn = builtin_decl_explicit (BUILT_IN_GOMP_CANCELLATION_POINT);
int mask = 0;
- if (find_omp_clause (clauses, OMP_CLAUSE_PARALLEL))
+ if (omp_find_clause (clauses, OMP_CLAUSE_PARALLEL))
mask = 1;
- else if (find_omp_clause (clauses, OMP_CLAUSE_FOR))
+ else if (omp_find_clause (clauses, OMP_CLAUSE_FOR))
mask = 2;
- else if (find_omp_clause (clauses, OMP_CLAUSE_SECTIONS))
+ else if (omp_find_clause (clauses, OMP_CLAUSE_SECTIONS))
mask = 4;
- else if (find_omp_clause (clauses, OMP_CLAUSE_TASKGROUP))
+ else if (omp_find_clause (clauses, OMP_CLAUSE_TASKGROUP))
mask = 8;
else
{
- error_at (loc, "%<#pragma omp cancellation point must specify one of "
+ error_at (loc, "%<#pragma omp cancellation point%> must specify one of "
"%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> "
"clauses");
return;
@@ -11926,7 +12177,7 @@ c_finish_omp_cancellation_point (location_t loc, tree clauses)
static tree
handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
bool &maybe_zero_len, unsigned int &first_non_one,
- bool is_omp)
+ enum c_omp_region_type ort)
{
tree ret, low_bound, length, type;
if (TREE_CODE (t) != TREE_LIST)
@@ -11934,8 +12185,15 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
if (error_operand_p (t))
return error_mark_node;
ret = t;
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
+ && TYPE_ATOMIC (strip_array_types (TREE_TYPE (t))))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c), "%<_Atomic%> %qE in %qs clause",
+ t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
if (TREE_CODE (t) == COMPONENT_REF
- && is_omp
+ && ort == C_ORT_OMP
&& (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM))
@@ -11971,18 +12229,40 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
return error_mark_node;
}
else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
- && VAR_P (t) && DECL_THREAD_LOCAL_P (t))
+ && TYPE_ATOMIC (TREE_TYPE (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c), "%<_Atomic%> %qD in %qs clause",
+ t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
+ && VAR_P (t)
+ && DECL_THREAD_LOCAL_P (t))
{
error_at (OMP_CLAUSE_LOCATION (c),
"%qD is threadprivate variable in %qs clause", t,
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
return error_mark_node;
}
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+ && TYPE_ATOMIC (TREE_TYPE (t))
+ && POINTER_TYPE_P (TREE_TYPE (t)))
+ {
+ /* 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;
+ }
return ret;
}
ret = handle_omp_array_sections_1 (c, TREE_CHAIN (t), types,
- maybe_zero_len, first_non_one, is_omp);
+ maybe_zero_len, first_non_one, ort);
if (ret == error_mark_node || ret == NULL_TREE)
return ret;
@@ -12213,14 +12493,14 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
/* Handle array sections for clause C. */
static bool
-handle_omp_array_sections (tree c, bool is_omp)
+handle_omp_array_sections (tree c, enum c_omp_region_type ort)
{
bool maybe_zero_len = false;
unsigned int first_non_one = 0;
auto_vec<tree, 10> types;
tree first = handle_omp_array_sections_1 (c, OMP_CLAUSE_DECL (c), types,
maybe_zero_len, first_non_one,
- is_omp);
+ ort);
if (first == error_mark_node)
return true;
if (first == NULL_TREE)
@@ -12413,7 +12693,7 @@ handle_omp_array_sections (tree c, bool is_omp)
&& TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE))
return false;
gcc_assert (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FORCE_DEVICEPTR);
- if (is_omp)
+ if (ort == C_ORT_OMP || ort == C_ORT_ACC)
switch (OMP_CLAUSE_MAP_KIND (c))
{
case GOMP_MAP_ALLOC:
@@ -12425,13 +12705,17 @@ handle_omp_array_sections (tree c, bool is_omp)
case GOMP_MAP_ALWAYS_TOFROM:
case GOMP_MAP_RELEASE:
case GOMP_MAP_DELETE:
+ case GOMP_MAP_FORCE_TO:
+ case GOMP_MAP_FORCE_FROM:
+ case GOMP_MAP_FORCE_TOFROM:
+ case GOMP_MAP_FORCE_PRESENT:
OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1;
break;
default:
break;
}
tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
- if (!is_omp)
+ if (ort != C_ORT_OMP && ort != C_ORT_ACC)
OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
else if (TREE_CODE (t) == COMPONENT_REF)
OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER);
@@ -12503,10 +12787,10 @@ c_find_omp_placeholder_r (tree *tp, int *, void *data)
Remove any elements from the list that are invalid. */
tree
-c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
+c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
{
bitmap_head generic_head, firstprivate_head, lastprivate_head;
- bitmap_head aligned_head, map_head, map_field_head;
+ bitmap_head aligned_head, map_head, map_field_head, oacc_reduction_head;
tree c, t, type, *pc;
tree simdlen = NULL_TREE, safelen = NULL_TREE;
bool branch_seen = false;
@@ -12515,6 +12799,7 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
tree *nowait_clause = NULL;
bool ordered_seen = false;
tree schedule_clause = NULL_TREE;
+ bool oacc_async = false;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -12523,6 +12808,15 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
bitmap_initialize (&aligned_head, &bitmap_default_obstack);
bitmap_initialize (&map_head, &bitmap_default_obstack);
bitmap_initialize (&map_field_head, &bitmap_default_obstack);
+ bitmap_initialize (&oacc_reduction_head, &bitmap_default_obstack);
+
+ if (ort & C_ORT_ACC)
+ for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ASYNC)
+ {
+ oacc_async = true;
+ break;
+ }
for (pc = &clauses, c = clauses; c ; c = *pc)
{
@@ -12546,7 +12840,7 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
t = OMP_CLAUSE_DECL (c);
if (TREE_CODE (t) == TREE_LIST)
{
- if (handle_omp_array_sections (c, is_omp))
+ if (handle_omp_array_sections (c, ort))
{
remove = true;
break;
@@ -12554,12 +12848,14 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
t = OMP_CLAUSE_DECL (c);
}
- t = require_complete_type (t);
+ t = require_complete_type (OMP_CLAUSE_LOCATION (c), t);
if (t == error_mark_node)
{
remove = true;
break;
}
+ if (oacc_async)
+ c_mark_addressable (t);
type = TREE_TYPE (t);
if (TREE_CODE (t) == MEM_REF)
type = TREE_TYPE (type);
@@ -12596,6 +12892,13 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
t = build2 (MEM_REF, atype, t, build_int_cst (ptype, 0));
OMP_CLAUSE_DECL (c) = t;
}
+ if (TYPE_ATOMIC (type))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<_Atomic%> %qE in %<reduction%> clause", t);
+ remove = true;
+ break;
+ }
if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == NULL_TREE
&& (FLOAT_TYPE_P (type)
|| TREE_CODE (type) == COMPLEX_TYPE))
@@ -12774,10 +13077,10 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
goto check_dup_generic;
case OMP_CLAUSE_LINEAR:
- if (!declare_simd)
+ if (ort != C_ORT_OMP_DECLARE_SIMD)
need_implicitly_determined = true;
t = OMP_CLAUSE_DECL (c);
- if (!declare_simd
+ if (ort != C_ORT_OMP_DECLARE_SIMD
&& OMP_CLAUSE_LINEAR_KIND (c) != OMP_CLAUSE_LINEAR_DEFAULT)
{
error_at (OMP_CLAUSE_LOCATION (c),
@@ -12785,16 +13088,40 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
"clause on %<simd%> or %<for%> constructs");
OMP_CLAUSE_LINEAR_KIND (c) = OMP_CLAUSE_LINEAR_DEFAULT;
}
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
- && TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE)
+ if (ort & C_ORT_CILK)
{
- error_at (OMP_CLAUSE_LOCATION (c),
- "linear clause applied to non-integral non-pointer "
- "variable with type %qT", TREE_TYPE (t));
- remove = true;
- break;
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
+ && !SCALAR_FLOAT_TYPE_P (TREE_TYPE (t))
+ && TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "linear clause applied to non-integral, "
+ "non-floating, non-pointer variable with type %qT",
+ TREE_TYPE (t));
+ remove = true;
+ break;
+ }
}
- if (declare_simd)
+ else
+ {
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
+ && TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "linear clause applied to non-integral non-pointer "
+ "variable with type %qT", TREE_TYPE (t));
+ remove = true;
+ break;
+ }
+ if (TYPE_ATOMIC (TREE_TYPE (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<_Atomic%> %qD in %<linear%> clause", t);
+ remove = true;
+ break;
+ }
+ }
+ if (ort == C_ORT_OMP_DECLARE_SIMD)
{
tree s = OMP_CLAUSE_LINEAR_STEP (c);
if (TREE_CODE (s) == PARM_DECL)
@@ -12843,6 +13170,17 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
+ else if (ort == C_ORT_ACC
+ && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+ {
+ if (bitmap_bit_p (&oacc_reduction_head, DECL_UID (t)))
+ {
+ error ("%qD appears more than once in reduction clauses", t);
+ remove = true;
+ }
+ else
+ bitmap_set_bit (&oacc_reduction_head, DECL_UID (t));
+ }
else if (bitmap_bit_p (&generic_head, DECL_UID (t))
|| bitmap_bit_p (&firstprivate_head, DECL_UID (t))
|| bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
@@ -12854,7 +13192,10 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
&& bitmap_bit_p (&map_head, DECL_UID (t)))
{
- error ("%qD appears both in data and map clauses", t);
+ if (ort == C_ORT_ACC)
+ error ("%qD appears more than once in data clauses", t);
+ else
+ error ("%qD appears both in data and map clauses", t);
remove = true;
}
else
@@ -12880,7 +13221,10 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
}
else if (bitmap_bit_p (&map_head, DECL_UID (t)))
{
- error ("%qD appears both in data and map clauses", t);
+ if (ort == C_ORT_ACC)
+ error ("%qD appears more than once in data clauses", t);
+ else
+ error ("%qD appears both in data and map clauses", t);
remove = true;
}
else
@@ -12924,6 +13268,13 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
"an array", t);
remove = true;
}
+ else if (TYPE_ATOMIC (TREE_TYPE (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<_Atomic%> %qD in %<aligned%> clause", t);
+ remove = true;
+ break;
+ }
else if (bitmap_bit_p (&aligned_head, DECL_UID (t)))
{
error_at (OMP_CLAUSE_LOCATION (c),
@@ -12973,7 +13324,7 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
}
if (TREE_CODE (t) == TREE_LIST)
{
- if (handle_omp_array_sections (c, is_omp))
+ if (handle_omp_array_sections (c, ort))
remove = true;
break;
}
@@ -12996,7 +13347,7 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
t = OMP_CLAUSE_DECL (c);
if (TREE_CODE (t) == TREE_LIST)
{
- if (handle_omp_array_sections (c, is_omp))
+ if (handle_omp_array_sections (c, ort))
remove = true;
else
{
@@ -13009,6 +13360,13 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
+ else if (TYPE_ATOMIC (TREE_TYPE (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<_Atomic%> %qE in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
while (TREE_CODE (t) == ARRAY_REF)
t = TREE_OPERAND (t, 0);
if (TREE_CODE (t) == COMPONENT_REF
@@ -13023,6 +13381,9 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
error ("%qD appears more than once in motion"
" clauses", t);
+ else if (ort == C_ORT_ACC)
+ error ("%qD appears more than once in data"
+ " clauses", t);
else
error ("%qD appears more than once in map"
" clauses", t);
@@ -13043,7 +13404,7 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
break;
}
if (TREE_CODE (t) == COMPONENT_REF
- && is_omp
+ && (ort & C_ORT_OMP)
&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE__CACHE_)
{
if (DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
@@ -13060,6 +13421,13 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
+ else if (TYPE_ATOMIC (TREE_TYPE (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<_Atomic%> %qE in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
while (TREE_CODE (t) == COMPONENT_REF)
{
if (TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0)))
@@ -13113,6 +13481,15 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
+ else if (TREE_TYPE (t) == error_mark_node)
+ remove = true;
+ else if (TYPE_ATOMIC (strip_array_types (TREE_TYPE (t))))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<_Atomic%> %qE in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
&& OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
{
@@ -13124,7 +13501,10 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
}
else if (bitmap_bit_p (&map_head, DECL_UID (t)))
{
- error ("%qD appears both in data and map clauses", t);
+ if (ort == C_ORT_ACC)
+ error ("%qD appears more than once in data clauses", t);
+ else
+ error ("%qD appears both in data and map clauses", t);
remove = true;
}
else
@@ -13134,6 +13514,8 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
{
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
error ("%qD appears more than once in motion clauses", t);
+ else if (ort == C_ORT_ACC)
+ error ("%qD appears more than once in data clauses", t);
else
error ("%qD appears more than once in map clauses", t);
remove = true;
@@ -13141,7 +13523,10 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
else if (bitmap_bit_p (&generic_head, DECL_UID (t))
|| bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
{
- error ("%qD appears both in data and map clauses", t);
+ if (ort == C_ORT_ACC)
+ error ("%qD appears more than once in data clauses", t);
+ else
+ error ("%qD appears both in data and map clauses", t);
remove = true;
}
else
@@ -13348,7 +13733,7 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
if (need_complete)
{
- t = require_complete_type (t);
+ t = require_complete_type (OMP_CLAUSE_LOCATION (c), t);
if (t == error_mark_node)
remove = true;
}
@@ -13445,6 +13830,50 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
return clauses;
}
+/* 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
+ followed by __atomic_store of the temporary to dst. */
+
+tree
+c_omp_clause_copy_ctor (tree clause, tree dst, tree src)
+{
+ if (!really_atomic_lvalue (dst) && !really_atomic_lvalue (src))
+ return build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
+
+ location_t loc = OMP_CLAUSE_LOCATION (clause);
+ tree type = TREE_TYPE (dst);
+ tree nonatomic_type = build_qualified_type (type, TYPE_UNQUALIFIED);
+ tree tmp = create_tmp_var (nonatomic_type);
+ tree tmp_addr = build_fold_addr_expr (tmp);
+ TREE_ADDRESSABLE (tmp) = 1;
+ TREE_NO_WARNING (tmp) = 1;
+ tree src_addr = build_fold_addr_expr (src);
+ tree dst_addr = build_fold_addr_expr (dst);
+ tree seq_cst = build_int_cst (integer_type_node, MEMMODEL_SEQ_CST);
+ vec<tree, va_gc> *params;
+ /* Expansion of a generic atomic load may require an addition
+ element, so allocate enough to prevent a resize. */
+ vec_alloc (params, 4);
+
+ /* Build __atomic_load (&src, &tmp, SEQ_CST); */
+ tree fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_LOAD);
+ params->quick_push (src_addr);
+ params->quick_push (tmp_addr);
+ params->quick_push (seq_cst);
+ tree load = c_build_function_call_vec (loc, vNULL, fndecl, params, NULL);
+
+ vec_alloc (params, 4);
+
+ /* Build __atomic_store (&dst, &tmp, SEQ_CST); */
+ fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_STORE);
+ params->quick_push (dst_addr);
+ params->quick_push (tmp_addr);
+ params->quick_push (seq_cst);
+ tree store = c_build_function_call_vec (loc, vNULL, fndecl, params, NULL);
+ return build2 (COMPOUND_EXPR, void_type_node, load, store);
+}
+
/* Create a transaction node. */
tree
diff --git a/gcc/c/config-lang.in b/gcc/c/config-lang.in
index b9cdc8e66c..0a4c888dd0 100644
--- a/gcc/c/config-lang.in
+++ b/gcc/c/config-lang.in
@@ -1,5 +1,5 @@
# Top level configure fragment for GNU C - C language.
-# Copyright (C) 1994-2016 Free Software Foundation, Inc.
+# Copyright (C) 1994-2017 Free Software Foundation, Inc.
#This file is part of GCC.
@@ -29,4 +29,4 @@ compilers="cc1\$(exeext)"
target_libs=
-gtfiles="\$(srcdir)/c/c-lang.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/c/c-objc-common.c \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-lang.h"
+gtfiles="\$(srcdir)/c/c-lang.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/c/c-objc-common.c \$(srcdir)/c/c-parser.h \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-lang.h"
diff --git a/gcc/c/gccspec.c b/gcc/c/gccspec.c
index cfb0aa0450..8a85430dca 100644
--- a/gcc/c/gccspec.c
+++ b/gcc/c/gccspec.c
@@ -1,5 +1,5 @@
/* Specific flags and argument handling of the C front-end.
- Copyright (C) 1999-2016 Free Software Foundation, Inc.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
This file is part of GCC.
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
new file mode 100644
index 0000000000..0d6384b55c
--- /dev/null
+++ b/gcc/c/gimple-parser.c
@@ -0,0 +1,1567 @@
+/* Parser for GIMPLE.
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "function.h"
+#include "c-tree.h"
+#include "timevar.h"
+#include "stringpool.h"
+#include "cgraph.h"
+#include "attribs.h"
+#include "stor-layout.h"
+#include "varasm.h"
+#include "trans-mem.h"
+#include "c-family/c-pragma.h"
+#include "c-lang.h"
+#include "c-family/c-objc.h"
+#include "plugin.h"
+#include "builtins.h"
+#include "gomp-constants.h"
+#include "c-family/c-indentation.h"
+#include "gimple-expr.h"
+#include "context.h"
+#include "gcc-rich-location.h"
+#include "c-parser.h"
+#include "tree-vrp.h"
+#include "tree-pass.h"
+#include "tree-pretty-print.h"
+#include "tree.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "gimple-pretty-print.h"
+#include "tree-ssa.h"
+#include "pass_manager.h"
+#include "tree-ssanames.h"
+#include "gimple-ssa.h"
+#include "tree-dfa.h"
+#include "tree-dump.h"
+
+
+/* Gimple parsing functions. */
+static bool c_parser_gimple_compound_statement (c_parser *, gimple_seq *);
+static void c_parser_gimple_label (c_parser *, gimple_seq *);
+static void c_parser_gimple_statement (c_parser *, gimple_seq *);
+static struct c_expr c_parser_gimple_binary_expression (c_parser *);
+static struct c_expr c_parser_gimple_unary_expression (c_parser *);
+static struct c_expr c_parser_gimple_postfix_expression (c_parser *);
+static struct c_expr c_parser_gimple_postfix_expression_after_primary (c_parser *,
+ location_t,
+ struct c_expr);
+static void c_parser_gimple_declaration (c_parser *);
+static void c_parser_gimple_goto_stmt (location_t, tree, gimple_seq *);
+static void c_parser_gimple_if_stmt (c_parser *, gimple_seq *);
+static void c_parser_gimple_switch_stmt (c_parser *, gimple_seq *);
+static void c_parser_gimple_return_stmt (c_parser *, gimple_seq *);
+static void c_finish_gimple_return (location_t, tree);
+static tree c_parser_gimple_paren_condition (c_parser *);
+static void c_parser_gimple_expr_list (c_parser *, vec<tree> *);
+
+
+/* Parse the body of a function declaration marked with "__GIMPLE". */
+
+void
+c_parser_parse_gimple_body (c_parser *parser)
+{
+ gimple_seq seq = NULL;
+ gimple_seq body = NULL;
+ tree stmt = push_stmt_list ();
+ push_scope ();
+ location_t loc1 = c_parser_peek_token (parser)->location;
+
+ init_tree_ssa (cfun);
+
+ if (! c_parser_gimple_compound_statement (parser, &seq))
+ {
+ gimple *ret = gimple_build_return (NULL);
+ gimple_seq_add_stmt (&seq, ret);
+ }
+
+ tree block = pop_scope ();
+ stmt = pop_stmt_list (stmt);
+ stmt = c_build_bind_expr (loc1, block, stmt);
+
+ block = DECL_INITIAL (current_function_decl);
+ BLOCK_SUBBLOCKS (block) = NULL_TREE;
+ BLOCK_CHAIN (block) = NULL_TREE;
+ TREE_ASM_WRITTEN (block) = 1;
+
+ gbind *bind_stmt = gimple_build_bind (BIND_EXPR_VARS (stmt), NULL,
+ BIND_EXPR_BLOCK (stmt));
+ gimple_bind_set_body (bind_stmt, seq);
+ gimple_seq_add_stmt (&body, bind_stmt);
+ gimple_set_body (current_function_decl, body);
+
+ /* While we have SSA names in the IL we do not have a CFG built yet
+ and PHIs are represented using a PHI internal function. We do
+ have lowered control flow and exception handling (well, we do not
+ have parser support for EH yet). But as we still have BINDs
+ we have to go through lowering again. */
+ cfun->curr_properties = PROP_gimple_any;
+
+ dump_function (TDI_generic, current_function_decl);
+}
+
+/* Parse a compound statement in gimple function body.
+
+ gimple-statement:
+ gimple-statement
+ gimple-declaration-statement
+ gimple-if-statement
+ gimple-switch-statement
+ gimple-labeled-statement
+ gimple-expression-statement
+ gimple-goto-statement
+ gimple-phi-statement
+ gimple-return-statement
+*/
+
+static bool
+c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
+{
+ bool return_p = false;
+
+ if (! c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+ return false;
+
+ /* A compund statement starts with optional declarations. */
+ while (c_parser_next_tokens_start_declaration (parser))
+ {
+ c_parser_gimple_declaration (parser);
+ if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+ return false;
+ }
+
+ while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+ {
+ if (c_parser_error (parser))
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
+ return return_p;
+ }
+ else if (c_parser_next_token_is (parser, CPP_EOF))
+ {
+ c_parser_error (parser, "expected declaration or statement");
+ return return_p;
+ }
+
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_KEYWORD:
+ switch (c_parser_peek_token (parser)->keyword)
+ {
+ case RID_IF:
+ c_parser_gimple_if_stmt (parser, seq);
+ break;
+ case RID_SWITCH:
+ c_parser_gimple_switch_stmt (parser, seq);
+ break;
+ case RID_GOTO:
+ {
+ location_t loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ c_parser_gimple_goto_stmt (loc,
+ c_parser_peek_token
+ (parser)->value,
+ seq);
+ c_parser_consume_token (parser);
+ if (! c_parser_require (parser, CPP_SEMICOLON,
+ "expected %<;%>"))
+ return return_p;
+ }
+ }
+ break;
+ case RID_RETURN:
+ return_p = true;
+ c_parser_gimple_return_stmt (parser, seq);
+ if (! c_parser_require (parser, CPP_SEMICOLON,
+ "expected %<;%>"))
+ return return_p;
+ break;
+ default:
+ goto expr_stmt;
+ }
+ break;
+ case CPP_NAME:
+ if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ {
+ c_parser_gimple_label (parser, seq);
+ break;
+ }
+ goto expr_stmt;
+
+ case CPP_SEMICOLON:
+ {
+ /* Empty stmt. */
+ location_t loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ gimple *nop = gimple_build_nop ();
+ gimple_set_location (nop, loc);
+ gimple_seq_add_stmt (seq, nop);
+ break;
+ }
+
+ default:
+expr_stmt:
+ c_parser_gimple_statement (parser, seq);
+ if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+ }
+ }
+ c_parser_consume_token (parser);
+ return return_p;
+}
+
+/* Parse a gimple statement.
+
+ gimple-statement:
+ gimple-call-expression
+ gimple-assign-statement
+ gimple-phi-statement
+
+ gimple-assign-statement:
+ gimple-unary-expression = gimple-assign-rhs
+
+ gimple-assign-rhs:
+ gimple-cast-expression
+ gimple-unary-expression
+ gimple-binary-expression
+ gimple-call-expression
+
+ gimple-phi-statement:
+ identifier = __PHI ( label : gimple_primary-expression, ... )
+
+ gimple-call-expr:
+ gimple-primary-expression ( argument-list )
+
+ gimple-cast-expression:
+ ( type-name ) gimple-primary-expression
+
+*/
+
+static void
+c_parser_gimple_statement (c_parser *parser, gimple_seq *seq)
+{
+ struct c_expr lhs, rhs;
+ gimple *assign = NULL;
+ location_t loc;
+ tree arg = NULL_TREE;
+ auto_vec<tree> vargs;
+
+ lhs = c_parser_gimple_unary_expression (parser);
+ loc = EXPR_LOCATION (lhs.value);
+ rhs.set_error ();
+
+ /* GIMPLE call statement without LHS. */
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON)
+ && TREE_CODE (lhs.value) == CALL_EXPR)
+ {
+ gimple *call;
+ call = gimple_build_call_from_tree (lhs.value);
+ gimple_seq_add_stmt (seq, call);
+ gimple_set_location (call, loc);
+ return;
+ }
+
+ /* All following cases are statements with LHS. */
+ if (! c_parser_require (parser, CPP_EQ, "expected %<=%>"))
+ return;
+
+ /* Cast expression. */
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+ && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+ {
+ c_parser_consume_token (parser);
+ struct c_type_name *type_name = c_parser_type_name (parser);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ if (type_name == NULL)
+ return;
+ /* ??? The actual type used in the cast expression is ignored as
+ in GIMPLE it is encoded by the type of the LHS. */
+ rhs = c_parser_gimple_postfix_expression (parser);
+ if (lhs.value != error_mark_node
+ && rhs.value != error_mark_node)
+ {
+ enum tree_code code = NOP_EXPR;
+ if (VECTOR_TYPE_P (TREE_TYPE (lhs.value)))
+ {
+ code = VIEW_CONVERT_EXPR;
+ rhs.value = build1 (VIEW_CONVERT_EXPR,
+ TREE_TYPE (lhs.value), rhs.value);
+ }
+ else if (FLOAT_TYPE_P (TREE_TYPE (lhs.value))
+ && ! FLOAT_TYPE_P (TREE_TYPE (rhs.value)))
+ code = FLOAT_EXPR;
+ else if (! FLOAT_TYPE_P (TREE_TYPE (lhs.value))
+ && FLOAT_TYPE_P (TREE_TYPE (rhs.value)))
+ code = FIX_TRUNC_EXPR;
+ assign = gimple_build_assign (lhs.value, code, rhs.value);
+ gimple_seq_add_stmt (seq, assign);
+ gimple_set_location (assign, loc);
+ return;
+ }
+ }
+
+ /* Unary expression. */
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_NAME:
+ {
+ tree id = c_parser_peek_token (parser)->value;
+ if (strcmp (IDENTIFIER_POINTER (id), "__ABS") == 0)
+ goto build_unary_expr;
+ break;
+ }
+ case CPP_KEYWORD:
+ if (c_parser_peek_token (parser)->keyword != RID_REALPART
+ && c_parser_peek_token (parser)->keyword != RID_IMAGPART)
+ break;
+ /* Fallthru. */
+ case CPP_AND:
+ case CPP_PLUS:
+ case CPP_MINUS:
+ case CPP_COMPL:
+ case CPP_NOT:
+ case CPP_MULT: /* pointer deref */
+ build_unary_expr:
+ rhs = c_parser_gimple_unary_expression (parser);
+ if (rhs.value != error_mark_node)
+ {
+ assign = gimple_build_assign (lhs.value, rhs.value);
+ gimple_set_location (assign, loc);
+ gimple_seq_add_stmt (seq, assign);
+ }
+ return;
+
+ default:;
+ }
+
+ /* GIMPLE PHI statement. */
+ if (c_parser_next_token_is_keyword (parser, RID_PHI))
+ {
+ c_parser_consume_token (parser);
+
+ if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return;
+
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ c_parser_consume_token (parser);
+
+ while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+ {
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ {
+ arg = lookup_label_for_goto (loc,
+ c_parser_peek_token (parser)->value);
+ c_parser_consume_token (parser);
+
+ if (c_parser_next_token_is (parser, CPP_COLON))
+ c_parser_consume_token (parser);
+ vargs.safe_push (arg);
+ }
+ else if (c_parser_next_token_is (parser, CPP_COMMA))
+ c_parser_consume_token (parser);
+ else
+ {
+ arg = c_parser_gimple_unary_expression (parser).value;
+ vargs.safe_push (arg);
+ }
+ }
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+
+ /* Build internal function for PHI. */
+ gcall *call_stmt = gimple_build_call_internal_vec (IFN_PHI, vargs);
+ gimple_call_set_lhs (call_stmt, lhs.value);
+ gimple_set_location (call_stmt, UNKNOWN_LOCATION);
+ gimple_seq_add_stmt (seq, call_stmt);
+ return;
+ }
+
+ /* GIMPLE call with lhs. */
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN
+ && lookup_name (c_parser_peek_token (parser)->value))
+ {
+ rhs = c_parser_gimple_unary_expression (parser);
+ if (rhs.value != error_mark_node)
+ {
+ gimple *call = gimple_build_call_from_tree (rhs.value);
+ gimple_call_set_lhs (call, lhs.value);
+ gimple_seq_add_stmt (seq, call);
+ gimple_set_location (call, loc);
+ }
+ return;
+ }
+
+ rhs = c_parser_gimple_binary_expression (parser);
+ if (lhs.value != error_mark_node
+ && rhs.value != error_mark_node)
+ {
+ assign = gimple_build_assign (lhs.value, rhs.value);
+ gimple_seq_add_stmt (seq, assign);
+ gimple_set_location (assign, loc);
+ }
+ return;
+}
+
+/* Parse gimple binary expr.
+
+ gimple-binary-expression:
+ gimple-unary-expression * gimple-unary-expression
+ gimple-unary-expression / gimple-unary-expression
+ gimple-unary-expression % gimple-unary-expression
+ gimple-unary-expression + gimple-unary-expression
+ gimple-unary-expression - gimple-unary-expression
+ gimple-unary-expression << gimple-unary-expression
+ gimple-unary-expression >> gimple-unary-expression
+ gimple-unary-expression < gimple-unary-expression
+ gimple-unary-expression > gimple-unary-expression
+ gimple-unary-expression <= gimple-unary-expression
+ gimple-unary-expression >= gimple-unary-expression
+ gimple-unary-expression == gimple-unary-expression
+ gimple-unary-expression != gimple-unary-expression
+ gimple-unary-expression & gimple-unary-expression
+ gimple-unary-expression ^ gimple-unary-expression
+ gimple-unary-expression | gimple-unary-expression
+
+*/
+
+static c_expr
+c_parser_gimple_binary_expression (c_parser *parser)
+{
+ /* Location of the binary operator. */
+ struct c_expr ret, lhs, rhs;
+ enum tree_code code = ERROR_MARK;
+ ret.set_error ();
+ lhs = c_parser_gimple_postfix_expression (parser);
+ if (c_parser_error (parser))
+ return ret;
+ tree ret_type = TREE_TYPE (lhs.value);
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_MULT:
+ code = MULT_EXPR;
+ break;
+ case CPP_DIV:
+ code = TRUNC_DIV_EXPR;
+ break;
+ case CPP_MOD:
+ code = TRUNC_MOD_EXPR;
+ break;
+ case CPP_PLUS:
+ if (POINTER_TYPE_P (TREE_TYPE (lhs.value)))
+ code = POINTER_PLUS_EXPR;
+ else
+ code = PLUS_EXPR;
+ break;
+ case CPP_MINUS:
+ code = MINUS_EXPR;
+ break;
+ case CPP_LSHIFT:
+ code = LSHIFT_EXPR;
+ break;
+ case CPP_RSHIFT:
+ code = RSHIFT_EXPR;
+ break;
+ case CPP_LESS:
+ code = LT_EXPR;
+ ret_type = boolean_type_node;
+ break;
+ case CPP_GREATER:
+ code = GT_EXPR;
+ ret_type = boolean_type_node;
+ break;
+ case CPP_LESS_EQ:
+ code = LE_EXPR;
+ ret_type = boolean_type_node;
+ break;
+ case CPP_GREATER_EQ:
+ code = GE_EXPR;
+ ret_type = boolean_type_node;
+ break;
+ case CPP_EQ_EQ:
+ code = EQ_EXPR;
+ ret_type = boolean_type_node;
+ break;
+ case CPP_NOT_EQ:
+ code = NE_EXPR;
+ ret_type = boolean_type_node;
+ break;
+ case CPP_AND:
+ code = BIT_AND_EXPR;
+ break;
+ case CPP_XOR:
+ code = BIT_XOR_EXPR;
+ break;
+ case CPP_OR:
+ code = BIT_IOR_EXPR;
+ break;
+ case CPP_AND_AND:
+ c_parser_error (parser, "%<&&%> not valid in GIMPLE");
+ return ret;
+ case CPP_OR_OR:
+ c_parser_error (parser, "%<||%> not valid in GIMPLE");
+ return ret;
+ default:
+ /* Not a binary expression. */
+ return lhs;
+ }
+ location_t ret_loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ rhs = c_parser_gimple_postfix_expression (parser);
+ if (lhs.value != error_mark_node && rhs.value != error_mark_node)
+ ret.value = build2_loc (ret_loc, code, ret_type, lhs.value, rhs.value);
+ return ret;
+}
+
+/* Parse gimple unary expression.
+
+ gimple-unary-expression:
+ gimple-postfix-expression
+ unary-operator gimple-postfix-expression
+
+ unary-operator: one of
+ & * + - ~ abs_expr
+*/
+
+static c_expr
+c_parser_gimple_unary_expression (c_parser *parser)
+{
+ struct c_expr ret, op;
+ location_t op_loc = c_parser_peek_token (parser)->location;
+ location_t finish;
+ ret.set_error ();
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_AND:
+ c_parser_consume_token (parser);
+ op = c_parser_gimple_postfix_expression (parser);
+ mark_exp_read (op.value);
+ return parser_build_unary_op (op_loc, ADDR_EXPR, op);
+ case CPP_MULT:
+ {
+ c_parser_consume_token (parser);
+ op = c_parser_gimple_postfix_expression (parser);
+ if (op.value == error_mark_node)
+ return ret;
+ finish = op.get_finish ();
+ location_t combined_loc = make_location (op_loc, op_loc, finish);
+ ret.value = build_simple_mem_ref_loc (combined_loc, op.value);
+ TREE_SIDE_EFFECTS (ret.value)
+ = TREE_THIS_VOLATILE (ret.value)
+ = TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (op.value)));
+ ret.src_range.m_start = op_loc;
+ ret.src_range.m_finish = finish;
+ return ret;
+ }
+ case CPP_PLUS:
+ c_parser_consume_token (parser);
+ op = c_parser_gimple_postfix_expression (parser);
+ return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
+ case CPP_MINUS:
+ c_parser_consume_token (parser);
+ op = c_parser_gimple_postfix_expression (parser);
+ return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
+ case CPP_COMPL:
+ c_parser_consume_token (parser);
+ op = c_parser_gimple_postfix_expression (parser);
+ return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
+ case CPP_NOT:
+ c_parser_error (parser, "%<!%> not valid in GIMPLE");
+ return ret;
+ case CPP_KEYWORD:
+ switch (c_parser_peek_token (parser)->keyword)
+ {
+ case RID_REALPART:
+ c_parser_consume_token (parser);
+ op = c_parser_gimple_postfix_expression (parser);
+ return parser_build_unary_op (op_loc, REALPART_EXPR, op);
+ case RID_IMAGPART:
+ c_parser_consume_token (parser);
+ op = c_parser_gimple_postfix_expression (parser);
+ return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
+ default:
+ return c_parser_gimple_postfix_expression (parser);
+ }
+ case CPP_NAME:
+ {
+ tree id = c_parser_peek_token (parser)->value;
+ if (strcmp (IDENTIFIER_POINTER (id), "__ABS") == 0)
+ {
+ c_parser_consume_token (parser);
+ op = c_parser_gimple_postfix_expression (parser);
+ return parser_build_unary_op (op_loc, ABS_EXPR, op);
+ }
+ else
+ return c_parser_gimple_postfix_expression (parser);
+ }
+ default:
+ return c_parser_gimple_postfix_expression (parser);
+ }
+}
+
+/* Decompose ID into base name (ID until ver_offset) and VERSION. Return
+ true if ID matches a SSA name. */
+
+static bool
+c_parser_parse_ssa_name_id (tree id, unsigned *version, unsigned *ver_offset)
+{
+ const char *token = IDENTIFIER_POINTER (id);
+ const char *var_version = strrchr (token, '_');
+ if (! var_version)
+ return false;
+
+ *ver_offset = var_version - token;
+ for (const char *p = var_version + 1; *p; ++p)
+ if (! ISDIGIT (*p))
+ return false;
+ *version = atoi (var_version + 1);
+ return *version > 0;
+}
+
+/* Get at the actual SSA name ID with VERSION starting at VER_OFFSET.
+ TYPE is the type if the SSA name is being declared. */
+
+static tree
+c_parser_parse_ssa_name (c_parser *parser,
+ tree id, tree type, unsigned version,
+ unsigned ver_offset)
+{
+ tree name = NULL_TREE;
+ const char *token = IDENTIFIER_POINTER (id);
+
+ if (ver_offset == 0)
+ {
+ /* Anonymous unnamed SSA name. */
+ if (version < num_ssa_names)
+ name = ssa_name (version);
+ if (! name)
+ {
+ if (! type)
+ {
+ c_parser_error (parser, "SSA name undeclared");
+ return error_mark_node;
+ }
+ name = make_ssa_name_fn (cfun, type, NULL, version);
+ }
+ }
+ else
+ {
+ if (version < num_ssa_names)
+ name = ssa_name (version);
+ if (! name)
+ {
+ /* Separate var name from version. */
+ char *var_name = XNEWVEC (char, ver_offset + 1);
+ memcpy (var_name, token, ver_offset);
+ var_name[ver_offset] = '\0';
+ /* lookup for parent decl. */
+ id = get_identifier (var_name);
+ tree parent = lookup_name (id);
+ XDELETEVEC (var_name);
+ if (! parent || parent == error_mark_node)
+ {
+ c_parser_error (parser, "base variable or SSA name undeclared");
+ return error_mark_node;
+ }
+ if (VECTOR_TYPE_P (TREE_TYPE (parent))
+ || TREE_CODE (TREE_TYPE (parent)) == COMPLEX_TYPE)
+ DECL_GIMPLE_REG_P (parent) = 1;
+ name = make_ssa_name_fn (cfun, parent,
+ gimple_build_nop (), version);
+ }
+ }
+
+ return name;
+}
+
+/* Parse gimple postfix expression.
+
+ gimple-postfix-expression:
+ gimple-primary-expression
+ gimple-primary-xpression [ gimple-primary-expression ]
+ gimple-primary-expression ( gimple-argument-expression-list[opt] )
+ postfix-expression . identifier
+ postfix-expression -> identifier
+
+ gimple-argument-expression-list:
+ gimple-unary-expression
+ gimple-argument-expression-list , gimple-unary-expression
+
+ gimple-primary-expression:
+ identifier
+ constant
+ string-literal
+
+*/
+
+static struct c_expr
+c_parser_gimple_postfix_expression (c_parser *parser)
+{
+ location_t loc = c_parser_peek_token (parser)->location;
+ source_range tok_range = c_parser_peek_token (parser)->get_range ();
+ struct c_expr expr;
+ expr.set_error ();
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_NUMBER:
+ expr.value = c_parser_peek_token (parser)->value;
+ set_c_expr_source_range (&expr, tok_range);
+ loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ break;
+ case CPP_CHAR:
+ case CPP_CHAR16:
+ case CPP_CHAR32:
+ case CPP_WCHAR:
+ expr.value = c_parser_peek_token (parser)->value;
+ set_c_expr_source_range (&expr, tok_range);
+ c_parser_consume_token (parser);
+ break;
+ case CPP_STRING:
+ case CPP_STRING16:
+ case CPP_STRING32:
+ case CPP_WSTRING:
+ case CPP_UTF8STRING:
+ expr.value = c_parser_peek_token (parser)->value;
+ set_c_expr_source_range (&expr, tok_range);
+ expr.original_code = STRING_CST;
+ c_parser_consume_token (parser);
+ break;
+ case CPP_NAME:
+ if (c_parser_peek_token (parser)->id_kind == C_ID_ID)
+ {
+ tree id = c_parser_peek_token (parser)->value;
+ if (strcmp (IDENTIFIER_POINTER (id), "__MEM") == 0)
+ {
+ /* __MEM '<' type-name [ ',' number ] '>'
+ '(' [ '(' type-name ')' ] unary-expression
+ [ '+' number ] ')' */
+ location_t loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ struct c_type_name *type_name = NULL;
+ tree alignment = NULL_TREE;
+ if (c_parser_require (parser, CPP_LESS, "expected %<<%>"))
+ {
+ type_name = c_parser_type_name (parser);
+ /* Optional alignment. */
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ {
+ c_parser_consume_token (parser);
+ alignment
+ = c_parser_gimple_postfix_expression (parser).value;
+ }
+ c_parser_skip_until_found (parser,
+ CPP_GREATER, "expected %<>%>");
+ }
+ struct c_expr ptr;
+ ptr.value = error_mark_node;
+ tree alias_off = NULL_TREE;
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ tree alias_type = NULL_TREE;
+ /* Optional alias-type cast. */
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ {
+ c_parser_consume_token (parser);
+ struct c_type_name *alias_type_name
+ = c_parser_type_name (parser);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ if (alias_type_name)
+ {
+ tree tem;
+ alias_type = groktypename (alias_type_name,
+ &tem, NULL);
+ }
+ }
+ ptr = c_parser_gimple_unary_expression (parser);
+ if (! alias_type)
+ alias_type = TREE_TYPE (ptr.value);
+ /* Optional constant offset. */
+ if (c_parser_next_token_is (parser, CPP_PLUS))
+ {
+ c_parser_consume_token (parser);
+ alias_off
+ = c_parser_gimple_postfix_expression (parser).value;
+ alias_off = fold_convert (alias_type, alias_off);
+ }
+ if (! alias_off)
+ alias_off = build_int_cst (alias_type, 0);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ }
+ if (! type_name || c_parser_error (parser))
+ {
+ c_parser_set_error (parser, false);
+ return expr;
+ }
+ tree tem = NULL_TREE;
+ tree type = groktypename (type_name, &tem, NULL);
+ if (alignment)
+ type = build_aligned_type (type, tree_to_uhwi (alignment));
+ expr.value = build2_loc (loc, MEM_REF,
+ type, ptr.value, alias_off);
+ break;
+ }
+ else if (strcmp (IDENTIFIER_POINTER (id), "_Literal") == 0)
+ {
+ /* _Literal '(' type-name ')' number */
+ c_parser_consume_token (parser);
+ tree type = NULL_TREE;
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ struct c_type_name *type_name = c_parser_type_name (parser);
+ tree tem;
+ if (type_name)
+ type = groktypename (type_name, &tem, NULL);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ }
+ tree val = c_parser_gimple_postfix_expression (parser).value;
+ if (! type
+ || ! val
+ || val == error_mark_node
+ || TREE_CODE (val) != INTEGER_CST)
+ {
+ c_parser_error (parser, "invalid _Literal");
+ return expr;
+ }
+ expr.value = fold_convert (type, val);
+ return expr;
+ }
+ else if (strcmp (IDENTIFIER_POINTER (id), "__FMA") == 0)
+ {
+ c_parser_consume_token (parser);
+ auto_vec<tree> args;
+
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ c_parser_gimple_expr_list (parser, &args);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ }
+ if (args.length () != 3)
+ {
+ error_at (loc, "invalid number of operands to __FMA");
+ expr.value = error_mark_node;
+ return expr;
+ }
+ expr.value = build3_loc (loc, FMA_EXPR, TREE_TYPE (args[0]),
+ args[0], args[1], args[2]);
+ return expr;
+ }
+
+ /* SSA name. */
+ unsigned version, ver_offset;
+ if (! lookup_name (id)
+ && c_parser_parse_ssa_name_id (id, &version, &ver_offset))
+ {
+ c_parser_consume_token (parser);
+ expr.value = c_parser_parse_ssa_name (parser, id, NULL_TREE,
+ version, ver_offset);
+ if (expr.value == error_mark_node)
+ return expr;
+ set_c_expr_source_range (&expr, tok_range);
+ /* For default definition SSA names. */
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+ && c_parser_peek_2nd_token (parser)->type == CPP_NAME
+ && strcmp ("D",
+ IDENTIFIER_POINTER
+ (c_parser_peek_2nd_token (parser)->value)) == 0
+ && c_parser_peek_nth_token (parser, 3)->type == CPP_CLOSE_PAREN)
+ {
+ c_parser_consume_token (parser);
+ c_parser_consume_token (parser);
+ c_parser_consume_token (parser);
+ if (! SSA_NAME_IS_DEFAULT_DEF (expr.value))
+ {
+ if (!SSA_NAME_VAR (expr.value))
+ {
+ error_at (loc, "anonymous SSA name cannot have"
+ " default definition");
+ expr.value = error_mark_node;
+ return expr;
+ }
+ set_ssa_default_def (cfun, SSA_NAME_VAR (expr.value),
+ expr.value);
+ SSA_NAME_DEF_STMT (expr.value) = gimple_build_nop ();
+ }
+ }
+ }
+ else
+ {
+ c_parser_consume_token (parser);
+ expr.value
+ = build_external_ref (loc, id,
+ (c_parser_peek_token (parser)->type
+ == CPP_OPEN_PAREN), &expr.original_type);
+ set_c_expr_source_range (&expr, tok_range);
+ }
+ break;
+ }
+ else
+ {
+ c_parser_error (parser, "expected expression");
+ expr.set_error ();
+ break;
+ }
+ break;
+ default:
+ c_parser_error (parser, "expected expression");
+ expr.set_error ();
+ break;
+ }
+ return c_parser_gimple_postfix_expression_after_primary
+ (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr);
+}
+
+/* Parse a gimple postfix expression after the initial primary or compound
+ literal. */
+
+static struct c_expr
+c_parser_gimple_postfix_expression_after_primary (c_parser *parser,
+ location_t expr_loc,
+ struct c_expr expr)
+{
+ location_t start;
+ location_t finish;
+ tree ident;
+ location_t comp_loc;
+
+ while (true)
+ {
+ location_t op_loc = c_parser_peek_token (parser)->location;
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_OPEN_SQUARE:
+ {
+ c_parser_consume_token (parser);
+ tree idx = c_parser_gimple_unary_expression (parser).value;
+
+ if (! c_parser_require (parser, CPP_CLOSE_SQUARE, "expected %<]%>"))
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
+ break;
+ }
+
+ start = expr.get_start ();
+ finish = c_parser_tokens_buf (parser, 0)->location;
+ expr.value = build_array_ref (op_loc, expr.value, idx);
+ set_c_expr_source_range (&expr, start, finish);
+
+ expr.original_code = ERROR_MARK;
+ expr.original_type = NULL;
+ break;
+ }
+ case CPP_OPEN_PAREN:
+ {
+ /* Function call. */
+ c_parser_consume_token (parser);
+ auto_vec<tree> exprlist;
+ if (! c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ c_parser_gimple_expr_list (parser, &exprlist);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ expr.value = build_call_array_loc
+ (expr_loc, TREE_TYPE (TREE_TYPE (expr.value)),
+ expr.value, exprlist.length (), exprlist.address ());
+ expr.original_code = ERROR_MARK;
+ expr.original_type = NULL;
+ break;
+ }
+ case CPP_DOT:
+ {
+ /* Structure element reference. */
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ c_token *comp_tok = c_parser_peek_token (parser);
+ ident = comp_tok->value;
+ comp_loc = comp_tok->location;
+ }
+ else
+ {
+ c_parser_error (parser, "expected identifier");
+ expr.set_error ();
+ expr.original_code = ERROR_MARK;
+ expr.original_type = NULL;
+ return expr;
+ }
+ start = expr.get_start ();
+ finish = c_parser_peek_token (parser)->get_finish ();
+ c_parser_consume_token (parser);
+ expr.value = build_component_ref (op_loc, expr.value, ident,
+ comp_loc);
+ set_c_expr_source_range (&expr, start, finish);
+ expr.original_code = ERROR_MARK;
+ if (TREE_CODE (expr.value) != COMPONENT_REF)
+ expr.original_type = NULL;
+ else
+ {
+ /* Remember the original type of a bitfield. */
+ tree field = TREE_OPERAND (expr.value, 1);
+ if (TREE_CODE (field) != FIELD_DECL)
+ expr.original_type = NULL;
+ else
+ expr.original_type = DECL_BIT_FIELD_TYPE (field);
+ }
+ break;
+ }
+ case CPP_DEREF:
+ {
+ /* Structure element reference. */
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ c_token *comp_tok = c_parser_peek_token (parser);
+ ident = comp_tok->value;
+ comp_loc = comp_tok->location;
+ }
+ else
+ {
+ c_parser_error (parser, "expected identifier");
+ expr.set_error ();
+ expr.original_code = ERROR_MARK;
+ expr.original_type = NULL;
+ return expr;
+ }
+ start = expr.get_start ();
+ finish = c_parser_peek_token (parser)->get_finish ();
+ c_parser_consume_token (parser);
+ expr.value = build_component_ref (op_loc,
+ build_simple_mem_ref_loc
+ (op_loc, expr.value),
+ ident, comp_loc);
+ set_c_expr_source_range (&expr, start, finish);
+ expr.original_code = ERROR_MARK;
+ if (TREE_CODE (expr.value) != COMPONENT_REF)
+ expr.original_type = NULL;
+ else
+ {
+ /* Remember the original type of a bitfield. */
+ tree field = TREE_OPERAND (expr.value, 1);
+ if (TREE_CODE (field) != FIELD_DECL)
+ expr.original_type = NULL;
+ else
+ expr.original_type = DECL_BIT_FIELD_TYPE (field);
+ }
+ break;
+ }
+ default:
+ return expr;
+ }
+ }
+}
+
+/* Parse expression list.
+
+ gimple-expr-list:
+ gimple-unary-expression
+ gimple-expr-list , gimple-unary-expression
+
+ */
+
+static void
+c_parser_gimple_expr_list (c_parser *parser, vec<tree> *ret)
+{
+ struct c_expr expr;
+
+ expr = c_parser_gimple_unary_expression (parser);
+ ret->safe_push (expr.value);
+ while (c_parser_next_token_is (parser, CPP_COMMA))
+ {
+ c_parser_consume_token (parser);
+ expr = c_parser_gimple_unary_expression (parser);
+ ret->safe_push (expr.value);
+ }
+}
+
+/* Parse gimple label.
+
+ gimple-label:
+ identifier :
+ case constant-expression :
+ default :
+
+*/
+
+static void
+c_parser_gimple_label (c_parser *parser, gimple_seq *seq)
+{
+ tree name = c_parser_peek_token (parser)->value;
+ location_t loc1 = c_parser_peek_token (parser)->location;
+ gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
+ c_parser_consume_token (parser);
+ gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
+ c_parser_consume_token (parser);
+ tree label = define_label (loc1, name);
+ gimple_seq_add_stmt (seq, gimple_build_label (label));
+ return;
+}
+
+/* Parse gimple/RTL pass list.
+
+ gimple-or-rtl-pass-list:
+ startwith("pass-name")
+ */
+
+char *
+c_parser_gimple_or_rtl_pass_list (c_parser *parser)
+{
+ char *pass = NULL;
+
+ /* Accept __GIMPLE/__RTL. */
+ if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
+ return NULL;
+ c_parser_consume_token (parser);
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *op = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ c_parser_consume_token (parser);
+ if (! strcmp (op, "startwith"))
+ {
+ if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return NULL;
+ if (c_parser_next_token_is_not (parser, CPP_STRING))
+ {
+ error_at (c_parser_peek_token (parser)->location,
+ "expected pass name");
+ return NULL;
+ }
+ pass = xstrdup (TREE_STRING_POINTER
+ (c_parser_peek_token (parser)->value));
+ c_parser_consume_token (parser);
+ if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ return NULL;
+ }
+ else
+ {
+ error_at (c_parser_peek_token (parser)->location,
+ "invalid operation");
+ return NULL;
+ }
+ }
+
+ if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ return NULL;
+
+ return pass;
+}
+
+/* Parse gimple local declaration.
+
+ declaration-specifiers:
+ storage-class-specifier declaration-specifiers[opt]
+ type-specifier declaration-specifiers[opt]
+ type-qualifier declaration-specifiers[opt]
+ function-specifier declaration-specifiers[opt]
+ alignment-specifier declaration-specifiers[opt]
+
+ storage-class-specifier:
+ typedef
+ extern
+ static
+ auto
+ register
+
+ type-specifier:
+ void
+ char
+ short
+ int
+ long
+ float
+ double
+ signed
+ unsigned
+ _Bool
+ _Complex
+
+ type-qualifier:
+ const
+ restrict
+ volatile
+ address-space-qualifier
+ _Atomic
+
+ */
+
+static void
+c_parser_gimple_declaration (c_parser *parser)
+{
+ struct c_declarator *declarator;
+ struct c_declspecs *specs = build_null_declspecs ();
+ c_parser_declspecs (parser, specs, true, true, true,
+ true, true, cla_nonabstract_decl);
+ finish_declspecs (specs);
+
+ /* Provide better error recovery. Note that a type name here is usually
+ better diagnosed as a redeclaration. */
+ if (c_parser_next_token_starts_declspecs (parser)
+ && ! c_parser_next_token_is (parser, CPP_NAME))
+ {
+ c_parser_error (parser, "expected %<;%>");
+ c_parser_set_error (parser, false);
+ return;
+ }
+
+ bool dummy = false;
+ declarator = c_parser_declarator (parser,
+ specs->typespec_kind != ctsk_none,
+ C_DTR_NORMAL, &dummy);
+
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ /* Handle SSA name decls specially, they do not go into the identifier
+ table but we simply build the SSA name for later lookup. */
+ unsigned version, ver_offset;
+ if (declarator->kind == cdk_id
+ && is_gimple_reg_type (specs->type)
+ && c_parser_parse_ssa_name_id (declarator->u.id,
+ &version, &ver_offset)
+ /* The following restricts it to unnamed anonymous SSA names
+ which fails parsing of named ones in dumps (we could
+ decide to not dump their name for -gimple). */
+ && ver_offset == 0)
+ c_parser_parse_ssa_name (parser, declarator->u.id, specs->type,
+ version, ver_offset);
+ else
+ {
+ tree postfix_attrs = NULL_TREE;
+ tree all_prefix_attrs = specs->attrs;
+ specs->attrs = NULL;
+ tree decl = start_decl (declarator, specs, false,
+ chainon (postfix_attrs, all_prefix_attrs));
+ if (decl)
+ finish_decl (decl, UNKNOWN_LOCATION, NULL_TREE, NULL_TREE,
+ NULL_TREE);
+ }
+ }
+ else
+ {
+ c_parser_error (parser, "expected %<;%>");
+ return;
+ }
+}
+
+/* Parse gimple goto statement. */
+
+static void
+c_parser_gimple_goto_stmt (location_t loc, tree label, gimple_seq *seq)
+{
+ tree decl = lookup_label_for_goto (loc, label);
+ gimple_seq_add_stmt (seq, gimple_build_goto (decl));
+ return;
+}
+
+/* Parse a parenthesized condition.
+ gimple-condition:
+ ( gimple-binary-expression ) */
+
+static tree
+c_parser_gimple_paren_condition (c_parser *parser)
+{
+ if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return error_mark_node;
+ tree cond = c_parser_gimple_binary_expression (parser).value;
+ if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ return error_mark_node;
+ return cond;
+}
+
+/* Parse gimple if-else statement.
+
+ if-statement:
+ if ( gimple-binary-expression ) gimple-goto-statement
+ if ( gimple-binary-expression ) gimple-goto-statement \
+ else gimple-goto-statement
+ */
+
+static void
+c_parser_gimple_if_stmt (c_parser *parser, gimple_seq *seq)
+{
+ tree t_label, f_label, label;
+ location_t loc;
+ c_parser_consume_token (parser);
+ tree cond = c_parser_gimple_paren_condition (parser);
+
+ if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+ {
+ loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ label = c_parser_peek_token (parser)->value;
+ t_label = lookup_label_for_goto (loc, label);
+ c_parser_consume_token (parser);
+ if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+ return;
+ }
+ else
+ {
+ c_parser_error (parser, "expected goto expression");
+ return;
+ }
+
+ if (c_parser_next_token_is_keyword (parser, RID_ELSE))
+ c_parser_consume_token (parser);
+ else
+ {
+ c_parser_error (parser, "expected else statement");
+ return;
+ }
+
+ if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+ {
+ loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ label = c_parser_peek_token (parser)->value;
+ f_label = lookup_label_for_goto (loc, label);
+ c_parser_consume_token (parser);
+ if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+ return;
+ }
+ else
+ {
+ c_parser_error (parser, "expected goto expression");
+ return;
+ }
+
+ if (cond != error_mark_node)
+ gimple_seq_add_stmt (seq, gimple_build_cond_from_tree (cond, t_label,
+ f_label));
+}
+
+/* Parse gimple switch-statement.
+
+ gimple-switch-statement:
+ switch (gimple-postfix-expression) gimple-case-statement
+
+ gimple-case-statement:
+ gimple-case-statement
+ gimple-label-statement : gimple-goto-statment
+*/
+
+static void
+c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq)
+{
+ c_expr cond_expr;
+ tree case_label, label;
+ auto_vec<tree> labels;
+ tree default_label = NULL_TREE;
+ gimple_seq switch_body = NULL;
+ c_parser_consume_token (parser);
+
+ if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return;
+ cond_expr = c_parser_gimple_postfix_expression (parser);
+ if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ return;
+
+ if (! c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+ return;
+
+ while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+ {
+ if (c_parser_next_token_is (parser, CPP_EOF))
+ {
+ c_parser_error (parser, "expected statement");
+ return;
+ }
+
+ switch (c_parser_peek_token (parser)->keyword)
+ {
+ case RID_CASE:
+ {
+ c_expr exp1;
+ location_t loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ || c_parser_peek_token (parser)->type == CPP_NUMBER)
+ exp1 = c_parser_gimple_postfix_expression (parser);
+ else
+ {
+ c_parser_error (parser, "expected expression");
+ return;
+ }
+
+ if (c_parser_next_token_is (parser, CPP_COLON))
+ {
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ label = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ tree decl = lookup_label_for_goto (loc, label);
+ case_label = build_case_label (exp1.value, NULL_TREE,
+ decl);
+ labels.safe_push (case_label);
+ if (! c_parser_require (parser, CPP_SEMICOLON,
+ "expected %<;%>"))
+ return;
+ }
+ else if (! c_parser_require (parser, CPP_NAME,
+ "expected label"))
+ return;
+ }
+ else if (! c_parser_require (parser, CPP_SEMICOLON,
+ "expected %<:%>"))
+ return;
+ break;
+ }
+ case RID_DEFAULT:
+ {
+ location_t loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_COLON))
+ {
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ label = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ tree decl = lookup_label_for_goto (loc, label);
+ default_label = build_case_label (NULL_TREE, NULL_TREE,
+ decl);
+ if (! c_parser_require (parser, CPP_SEMICOLON,
+ "expected %<;%>"))
+ return;
+ }
+ else if (! c_parser_require (parser, CPP_NAME,
+ "expected label"))
+ return;
+ }
+ else if (! c_parser_require (parser, CPP_SEMICOLON,
+ "expected %<:%>"))
+ return;
+ break;
+ }
+ case RID_GOTO:
+ {
+ location_t loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ c_parser_gimple_goto_stmt (loc,
+ c_parser_peek_token
+ (parser)->value,
+ &switch_body);
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ c_parser_consume_token (parser);
+ else
+ {
+ c_parser_error (parser, "expected semicolon");
+ return;
+ }
+ }
+ else if (! c_parser_require (parser, CPP_NAME,
+ "expected label"))
+ return;
+ break;
+ }
+ default:
+ c_parser_error (parser, "expected case label or goto statement");
+ return;
+ }
+
+ }
+ if (! c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
+ return;
+
+ if (cond_expr.value != error_mark_node)
+ {
+ gimple_seq_add_stmt (seq, gimple_build_switch (cond_expr.value,
+ default_label, labels));
+ gimple_seq_add_seq (seq, switch_body);
+ }
+}
+
+/* Parse gimple return statement. */
+
+static void
+c_parser_gimple_return_stmt (c_parser *parser, gimple_seq *seq)
+{
+ location_t loc = c_parser_peek_token (parser)->location;
+ gimple *ret = NULL;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ c_finish_gimple_return (loc, NULL_TREE);
+ ret = gimple_build_return (NULL);
+ gimple_seq_add_stmt (seq, ret);
+ }
+ else
+ {
+ location_t xloc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_gimple_unary_expression (parser);
+ if (expr.value != error_mark_node)
+ {
+ c_finish_gimple_return (xloc, expr.value);
+ ret = gimple_build_return (expr.value);
+ gimple_seq_add_stmt (seq, ret);
+ }
+ }
+}
+
+/* Support function for c_parser_gimple_return_stmt. */
+
+static void
+c_finish_gimple_return (location_t loc, tree retval)
+{
+ tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
+
+ /* Use the expansion point to handle cases such as returning NULL
+ in a function returning void. */
+ source_location xloc = expansion_point_location_if_in_system_header (loc);
+
+ if (TREE_THIS_VOLATILE (current_function_decl))
+ warning_at (xloc, 0,
+ "function declared %<noreturn%> has a %<return%> statement");
+
+ if (! retval)
+ current_function_returns_null = 1;
+ else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
+ {
+ current_function_returns_null = 1;
+ if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
+ {
+ error_at
+ (xloc, "%<return%> with a value, in function returning void");
+ inform (DECL_SOURCE_LOCATION (current_function_decl),
+ "declared here");
+ }
+ }
+ else if (TREE_CODE (valtype) != TREE_CODE (TREE_TYPE (retval)))
+ {
+ error_at
+ (xloc, "invalid conversion in return statement");
+ inform (DECL_SOURCE_LOCATION (current_function_decl),
+ "declared here");
+ }
+ return;
+}
diff --git a/gcc/c/gimple-parser.h b/gcc/c/gimple-parser.h
new file mode 100644
index 0000000000..85cf13aa4c
--- /dev/null
+++ b/gcc/c/gimple-parser.h
@@ -0,0 +1,27 @@
+/* Declarations for the parser for GIMPLE.
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_GIMPLE_PARSER_H
+#define GCC_GIMPLE_PARSER_H
+
+/* Gimple parsing functions. */
+extern void c_parser_parse_gimple_body (c_parser *);
+extern char *c_parser_gimple_or_rtl_pass_list (c_parser *);
+
+#endif