diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-05-02 14:43:35 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-05-02 14:43:35 +0000 |
commit | 34efdaf078b01a7387007c4e6bde6db86384c4b7 (patch) | |
tree | d503eaf41d085669d1481bb46ec038bc866fece6 /gcc/c | |
parent | f733cf303bcdc952c92b81dd62199a40a1f555ec (diff) | |
download | gcc-tarball-master.tar.gz |
gcc-7.1.0gcc-7.1.0
Diffstat (limited to 'gcc/c')
-rw-r--r-- | gcc/c/ChangeLog | 1047 | ||||
-rw-r--r-- | gcc/c/Make-lang.in | 31 | ||||
-rw-r--r-- | gcc/c/c-array-notation.c | 12 | ||||
-rw-r--r-- | gcc/c/c-aux-info.c | 2 | ||||
-rw-r--r-- | gcc/c/c-convert.c | 2 | ||||
-rw-r--r-- | gcc/c/c-decl.c | 646 | ||||
-rw-r--r-- | gcc/c/c-errors.c | 8 | ||||
-rw-r--r-- | gcc/c/c-fold.c | 20 | ||||
-rw-r--r-- | gcc/c/c-lang.c | 27 | ||||
-rw-r--r-- | gcc/c/c-lang.h | 2 | ||||
-rw-r--r-- | gcc/c/c-objc-common.c | 2 | ||||
-rw-r--r-- | gcc/c/c-objc-common.h | 10 | ||||
-rw-r--r-- | gcc/c/c-parser.c | 1504 | ||||
-rw-r--r-- | gcc/c/c-parser.h | 189 | ||||
-rw-r--r-- | gcc/c/c-tree.h | 39 | ||||
-rw-r--r-- | gcc/c/c-typeck.c | 821 | ||||
-rw-r--r-- | gcc/c/config-lang.in | 4 | ||||
-rw-r--r-- | gcc/c/gccspec.c | 2 | ||||
-rw-r--r-- | gcc/c/gimple-parser.c | 1567 | ||||
-rw-r--r-- | gcc/c/gimple-parser.h | 27 |
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 |