diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 313 | ||||
-rw-r--r-- | gcc/cp/call.c | 61 | ||||
-rw-r--r-- | gcc/cp/class.c | 244 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 1 | ||||
-rw-r--r-- | gcc/cp/cp-gimplify.c | 11 | ||||
-rw-r--r-- | gcc/cp/cp-objcp-common.c | 7 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 25 | ||||
-rw-r--r-- | gcc/cp/cp-ubsan.c | 5 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 2 | ||||
-rw-r--r-- | gcc/cp/decl.c | 35 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 59 | ||||
-rw-r--r-- | gcc/cp/error.c | 2 | ||||
-rw-r--r-- | gcc/cp/except.c | 30 | ||||
-rw-r--r-- | gcc/cp/init.c | 59 | ||||
-rw-r--r-- | gcc/cp/lambda.c | 5 | ||||
-rw-r--r-- | gcc/cp/lex.c | 4 | ||||
-rw-r--r-- | gcc/cp/method.c | 55 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 17 | ||||
-rw-r--r-- | gcc/cp/optimize.c | 12 | ||||
-rw-r--r-- | gcc/cp/parser.c | 832 | ||||
-rw-r--r-- | gcc/cp/pt.c | 154 | ||||
-rw-r--r-- | gcc/cp/search.c | 172 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 26 | ||||
-rw-r--r-- | gcc/cp/tree.c | 1 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 33 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 11 |
26 files changed, 1383 insertions, 793 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 597c6b3f6c8..a8a3fccdcd1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,316 @@ +2017-08-11 Martin Liska <mliska@suse.cz> + + * decl2.c (get_tls_init_fn): Replace ASM_OUTPUT_DEF with + TARGET_SUPPORTS_ALIASES. + (handle_tls_init): Likewise. + (note_mangling_alias): Likewise. Remove ATTRIBUTE_UNUSED for + both arguments. + * optimize.c (can_alias_cdtor): Likewise. + +2017-08-11 Jason Merrill <jason@redhat.com> + + PR c++/81671 - nullptr_t template parameter + * pt.c (convert_nontype_argument): Fix nullptr_t check. + +2017-08-10 Jason Merrill <jason@redhat.com> + + PR c++/81359 - Unparsed NSDMI error from SFINAE context. + * method.c (synthesized_method_walk): Don't diagnose lack of + operator delete. + + PR c++/80452 - Core 1579, implicit move semantics on return/throw + * cp-tree.h (LOOKUP_PREFER_RVALUE): Now means that we've already + tentatively changed the lvalue to an rvalue. + * call.c (reference_binding): Remove LOOKUP_PREFER_RVALUE handling. + (build_over_call): If LOOKUP_PREFER_RVALUE, check that the first + parameter is an rvalue reference. + * except.c (build_throw): Do maybe-rvalue overload resolution twice. + * typeck.c (check_return_expr): Likewise. + +2017-08-10 David Malcolm <dmalcolm@redhat.com> + + * parser.c (cp_parser_error): Update for new param to + c_parse_error. + (class token_pair): New class. + (struct matching_paren_traits): New struct. + (matching_parens): New typedef. + (struct matching_brace_traits): New struct. + (matching_braces): New typedef. + (cp_parser_statement_expr): Convert explicit parsing of + CPP_OPEN_PAREN and CPP_CLOSE_PAREN to use of + class matching_parens, so that the pertinent open parenthesis is + highlighted when there are problems locating the close + parenthesis. + (cp_parser_primary_expression): Likewise. + (cp_parser_compound_literal_p): Remove consumption of opening + paren. + (cp_parser_postfix_expression): Convert explicit parsing of + CPP_OPEN_PAREN and CPP_CLOSE_PAREN to use matching parens, as + above. Use it to consume the opening paren previously consumed by + cp_parser_compound_literal_p. + (cp_parser_parenthesized_expression_list): Likewise. + (cp_parser_unary_expression): Likewise. + (cp_parser_new_expression): Likewise. + (cp_parser_cast_expression): Likewise. + (cp_parser_builtin_offsetof): Likewise. + (cp_parser_trait_expr): Likewise. + (cp_parser_lambda_declarator_opt): Likewise. + (cp_parser_lambda_body): Likewise, for matching_braces. + (cp_parser_compound_statement): Likewise. + (cp_parser_selection_statement): Likewise, for matching_parens. + (cp_parser_iteration_statement): Likewise. + (cp_parser_already_scoped_statement): Likewise, for + matching_braces. + (cp_parser_linkage_specification): Likewise. + (cp_parser_static_assert): Likewise, for matching_parens. + (cp_parser_decltype): Likewise. + (cp_parser_operator): Likewise. + (cp_parser_enum_specifier): Likewise. + (cp_parser_namespace_definition): Likewise. + (cp_parser_direct_declarator): Likewise. + (cp_parser_braced_list): Likewise. + (cp_parser_class_specifier_1): Likewise, for matching_braces. + (cp_parser_constant_initializer): Likewise. + (cp_parser_noexcept_specification_opt): Likewise, for + matching_parens. + (cp_parser_exception_specification_opt): Likewise. + (cp_parser_handler): Likewise. + (cp_parser_asm_specification_opt): Likewise. + (cp_parser_asm_operand_list): Likewise. + (cp_parser_gnu_attributes_opt): Likewise. + (cp_parser_std_attribute_spec): Likewise. + (cp_parser_requirement_parameter_list): Likewise. + (cp_parser_requirement_body): Likewise, for matching_braces. + (cp_parser_compound_requirement): Likewise. + (cp_parser_template_introduction): Likewise. + (cp_parser_sizeof_pack): Likewise, for matching_parens. + (cp_parser_sizeof_operand): Likewise; use it to consume the + opening paren previously consumed by cp_parser_compound_literal_p. + (get_matching_symbol): New function. + (cp_parser_required_error): Add param "matching_location". Remove + calls to cp_parser_error, instead setting a non-NULL gmsgid, and + handling it if set by calling c_parse_error, potentially with a + secondary location if matching_location was set. + (cp_parser_require): Add param "matching_location", with a default + value of UNKNOWN_LOCATION. + (cp_parser_require_keyword): Update for new param of + cp_parser_required_error. + (cp_parser_objc_encode_expression): Update to class matching_parens + as above. + (cp_parser_objc_defs_expression): Likewise. + (cp_parser_objc_protocol_expression): Likewise. + (cp_parser_objc_selector_expression): Likewise. + (cp_parser_objc_typename): Likewise. + (cp_parser_objc_superclass_or_category): Likewise. + (cp_parser_objc_try_catch_finally_statement): Likewise. + (cp_parser_objc_synchronized_statement): Likewise. + (cp_parser_objc_at_property_declaration): Likewise. + (cp_parser_oacc_single_int_clause): Likewise. + (cp_parser_oacc_shape_clause): Likewise. + (cp_parser_omp_clause_collapse): Likewise. + (cp_parser_omp_clause_default): Likewise. + (cp_parser_omp_clause_final): Likewise. + (cp_parser_omp_clause_if): Likewise. + (cp_parser_omp_clause_num_threads): Likewise. + (cp_parser_omp_clause_num_tasks): Likewise. + (cp_parser_omp_clause_grainsize): Likewise. + (cp_parser_omp_clause_priority): Likewise. + (cp_parser_omp_clause_hint): Likewise. + (cp_parser_omp_clause_defaultmap): Likewise. + (cp_parser_omp_clause_ordered): Likewise. + (cp_parser_omp_clause_schedule): Likewise. + (cp_parser_omp_clause_num_teams): Likewise. + (cp_parser_omp_clause_thread_limit): Likewise. + (cp_parser_omp_clause_aligned): Likewise. + (cp_parser_omp_clause_linear): Likewise. + (cp_parser_omp_clause_safelen): Likewise. + (cp_parser_omp_clause_simdlen): Likewise. + (cp_parser_omp_clause_depend): Likewise. + (cp_parser_omp_clause_device): Likewise. + (cp_parser_omp_clause_dist_schedule): Likewise. + (cp_parser_oacc_clause_async): Likewise. + (cp_parser_omp_critical): Likewise. + (cp_parser_omp_for_loop): Likewise. + (cp_parser_omp_sections_scope): Likewise. + (cp_parser_omp_declare_reduction_exprs): Likewise. + Update for new param to cp_parser_required_error. + (cp_parser_oacc_routine): Likewise. + (cp_parser_transaction_expression): Likewise. + (cp_parser_cilk_simd_vectorlength): Likewise. + +2017-08-09 Jason Merrill <jason@redhat.com> + + PR c++/81525 - wrong constant value with generic lambda + * pt.c (tsubst_decl) [VAR_DECL]: Avoid clobbering auto. + (tsubst_copy) [VAR_DECL]: Handle auto. + + PR c++/81359 - Unparsed NSDMI error from SFINAE context. + * init.c (get_nsdmi): Add complain parm. + * typeck2.c (digest_nsdmi_init): Add complain parm. + (process_init_constructor_record): Pass complain to get_nsdmi. + * pt.c (maybe_instantiate_noexcept): Add complain parm, return bool. + * method.c (get_defaulted_eh_spec): Add complain parm. Pass it into + synthesized_method_walk. + (synthesized_method_walk): Adjust. + (walk_field_subobs): Pass complain to get_nsdmi. + (defaulted_late_check): Skip other checks if deleted. + * decl2.c (mark_used): Pass complain to maybe_instantiate_noexcept. + * call.c (build_aggr_conv): Pass complain to get_nsdmi. + * parser.c (defarg_location): New. + * error.c (location_of): Use it. + +2017-08-09 Marek Polacek <polacek@redhat.com> + + * parser.c (cp_parser_perform_range_for_lookup): Use false instead of 0. + * typeck.c (build_binary_op): Change the type of a parameter to bool. + (cp_truthvalue_conversion): Use true instead of 1. + +2017-08-08 Marek Polacek <polacek@redhat.com> + + PR c++/81607 + * cp-gimplify.c (cp_fold): If folding exposed a branch of + a COND_EXPR, convert it to the original type of the COND_EXPR, if + they differ. + +2017-08-08 Martin Liska <mliska@suse.cz> + + * call.c: Include header files. + * cp-gimplify.c: Likewise. + * cp-ubsan.c: Likewise. + * cvt.c: Likewise. + * init.c: Likewise. + * search.c: Likewise. + * semantics.c: Likewise. + * typeck.c: Likewise. + +2017-08-07 Martin Liska <mliska@suse.cz> + + * parser.c (cp_parser_gnu_attribute_list): Canonicalize name of an + attribute. + (cp_parser_std_attribute): Likewise. + * tree.c: Add new include. + +2017-08-04 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/79790 + * pt.c (do_class_deduction): Handle the case of no viable implicit + deduction guides; simplify the code generating implicit deduction + guides. + +2017-08-03 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/71440 + * typeck.c (build_x_unary_op): Avoid pretty-printing constructor / + destructor as expressions. + +2017-08-02 Jakub Jelinek <jakub@redhat.com> + + PR c++/81640 + * call.c (build_user_type_conversion_1): Only call + lookup_fnfields_slot if totype is CLASS_TYPE_P. + +2017-07-31 Jason Merrill <jason@redhat.com> + + * decl.c (declare_global_var): Set DECL_CONTEXT. + +2017-07-31 Jan Hubicka <hubicka@ucw.cz> + Martin Liska <mliska@suse.cz> + + * pt.c (tsubst_copy): Copy PREDICT_EXPR. + * semantics.c (finish_goto_stmt): Build gimple predict + stament. + * constexpr.c (potential_constant_expression_1): Handle + PREDICT_EXPR. + +2017-07-31 Martin Liska <mliska@suse.cz> + + PR sanitize/81530 + * cp-gimplify.c (cp_genericize): Guard condition with flag_sanitize_p + also with current_function_decl non-null equality. + * cp-ubsan.c (cp_ubsan_instrument_vptr_p): Likewise. + * decl.c (compute_array_index_type): Likewise. + * init.c (finish_length_check): Likewise. + * typeck.c (cp_build_binary_op): Likewise. + +2017-07-29 Jakub Jelinek <jakub@redhat.com> + + * cp-objcp-common.c (cp_decl_dwarf_attribute): Handle + DW_AT_export_symbols. + * name-lookup.c (emit_debug_info_using_namespace): Add IMPLICIT + argument, pass it through to the debug hook. + (finish_namespace_using_directive): Adjust + emit_debug_info_using_namespace caller. + (push_namespace): Likewise. Call it after setting + DECL_NAMESPACE_INLINE_P. + (cp_emit_debug_info_for_using): Pass false as new argument to + the imported_module_or_decl debug hook. + +2017-07-28 Trevor Saunders <tbsaunde+gcc@tbsaunde.org> + + * lex.c (copy_decl): Adjust. + (copy_type): Likewise. + +2017-07-26 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/71570 + * lambda.c (add_capture): Early return if we cannot capture by + reference. + +2017-07-26 Jason Merrill <jason@redhat.com> + + P0702R1 - List deduction of vector. + * pt.c (do_class_deduction): Special-case deduction from a single + element of related type. + +2017-07-26 Leonid Koppel <lkoppel@uwaterloo.ca> + + PR c++/67054 - Inherited ctor with non-default-constructible members + * method.c (walk_field_subobs) Consider member initializers (NSDMIs) + when deducing an inheriting constructor. + +2017-07-21 Nathan Sidwell <nathan@acm.org> + + * search.c (lookup_conversion_operator): Return overloads. + (lookup_fnfields_idx_nolazy): Absorb into ... + (lookup_fnfields_slot_nolaxy): ... here. + (lookup_fnfields_1): Absorb into ... + (lookup_fnfields_slot): ... here. + + Remove special CDtor METHOD_VEC slots. + * cp-tree.h (CLASSTYPE_CONSTRUCTOR_SLOT, + CLASSTYPE_DESTRUCTOR_SLOT): Delete. + (CLASSTYPE_CONSTRUCTORS): Use lookup_fnfields_slot_nolazy. + (CLASSTYPE_DESTRUCTOR): Likewise. + * class (add_method): Don't use special cdtor slots. + * search.c (lookup_fnfields_idx_nolazy): Likewise. + (look_for_overrides_here): Use lookup_fnfields_slot. + * semantics (classtype_has_nothrow_assign_or_copy_p): Likewise. + + * call.c (add_candidates): Move decls to initialization. Don't + use !!. + +2017-07-20 Nathan Sidwell <nathan@acm.org> + + Remove TYPE_METHODS. + * class.c (maybe_warn_about_overly_private_class, + finish_struct_methods, one_inheriting_sig, count_fields, + add_fields_to_record_type, check_field_decls, check_methods, + clone_function_decl, set_method_tm_attributes, + finalize_literal_type_property, check_bases_and_members, + create_vtable_ptr, determine_key_method, + unreverse_member_declarations, finish_struct, + add_vcall_offset_vtbl_entries_1): Member fns are on TYPE_FIELDS. + * decl.c (fixup_anonymous_aggr): Likewise. + * decl2.c (reset_type_linkage_2): Likewise. + * method.c (after_nsdmi_defaulted_late_checks, + lazily_declare_fn): Likewise. + * optimize.c (maybe_thunk_body, maybe_clone_body): Likewise. + * pt.c (instantiate_class_template_1, tsubst_expr, + do_type_instantiation, instantiate_pending_templates): Likewise. + * search.c (lookup_field_1): Likewise. + * semantics.c (finish_member_declaration, + finish_omp_declare_simd_methods): Likewise. + 2017-07-19 Nathan Sidwell <nathan@acm.org> * class.c (add_implicitly_declared_members): Use diff --git a/gcc/cp/call.c b/gcc/cp/call.c index fac6b6c16ac..37902991f3f 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -39,6 +39,8 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "c-family/c-objc.h" #include "internal-fn.h" +#include "stringpool.h" +#include "attribs.h" /* The various kinds of conversion. */ @@ -99,7 +101,7 @@ struct conversion { /* If KIND is ck_ref_bind, true when either an lvalue reference is being bound to an lvalue expression or an rvalue reference is being bound to an rvalue expression. If KIND is ck_rvalue, - true when we should treat an lvalue as an rvalue (12.8p33). If + true when we are treating an lvalue as an rvalue (12.8p33). If KIND is ck_base, always false. */ BOOL_BITFIELD rvaluedness_matches_p: 1; BOOL_BITFIELD check_narrowing: 1; @@ -914,7 +916,7 @@ build_aggr_conv (tree type, tree ctor, int flags, tsubst_flags_t complain) if (i < CONSTRUCTOR_NELTS (ctor)) val = CONSTRUCTOR_ELT (ctor, i)->value; else if (DECL_INITIAL (field)) - val = get_nsdmi (field, /*ctor*/false); + val = get_nsdmi (field, /*ctor*/false, complain); else if (TREE_CODE (ftype) == REFERENCE_TYPE) /* Value-initialization of reference is ill-formed. */ return NULL; @@ -1159,6 +1161,7 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p, } conv = build_conv (ck_rvalue, from, conv); if (flags & LOOKUP_PREFER_RVALUE) + /* Tell convert_like_real to set LOOKUP_PREFER_RVALUE. */ conv->rvaluedness_matches_p = true; } @@ -1627,11 +1630,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, conv = build_identity_conv (tfrom, expr); conv = direct_reference_binding (rto, conv); - if (flags & LOOKUP_PREFER_RVALUE) - /* The top-level caller requested that we pretend that the lvalue - be treated as an rvalue. */ - conv->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto); - else if (TREE_CODE (rfrom) == REFERENCE_TYPE) + if (TREE_CODE (rfrom) == REFERENCE_TYPE) /* Handle rvalue reference to function properly. */ conv->rvaluedness_matches_p = (TYPE_REF_IS_RVALUE (rto) == TYPE_REF_IS_RVALUE (rfrom)); @@ -1657,8 +1656,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, /* Don't allow binding of lvalues (other than function lvalues) to rvalue references. */ if (is_lvalue && TYPE_REF_IS_RVALUE (rto) - && TREE_CODE (to) != FUNCTION_TYPE - && !(flags & LOOKUP_PREFER_RVALUE)) + && TREE_CODE (to) != FUNCTION_TYPE) conv->bad_p = true; /* Nor the reverse. */ @@ -3735,7 +3733,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags, gcc_assert (!MAYBE_CLASS_TYPE_P (fromtype) || !MAYBE_CLASS_TYPE_P (totype) || !DERIVED_FROM_P (totype, fromtype)); - if (MAYBE_CLASS_TYPE_P (totype)) + if (CLASS_TYPE_P (totype)) /* Use lookup_fnfields_slot instead of lookup_fnfields to avoid creating a garbage BASELINK; constructors can't be inherited. */ ctors = lookup_fnfields_slot (totype, complete_ctor_identifier); @@ -5423,8 +5421,8 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args, { tree ctype; const vec<tree, va_gc> *non_static_args; - bool check_list_ctor; - bool check_converting; + bool check_list_ctor = false; + bool check_converting = false; unification_kind_t strict; if (!fns) @@ -5435,7 +5433,7 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args, if (DECL_CONV_FN_P (fn)) { check_list_ctor = false; - check_converting = !!(flags & LOOKUP_ONLYCONVERTING); + check_converting = (flags & LOOKUP_ONLYCONVERTING) != 0; if (flags & LOOKUP_NO_CONVERSION) /* We're doing return_type(x). */ strict = DEDUCE_CONV; @@ -5452,18 +5450,13 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args, { if (DECL_CONSTRUCTOR_P (fn)) { - check_list_ctor = !!(flags & LOOKUP_LIST_ONLY); + check_list_ctor = (flags & LOOKUP_LIST_ONLY) != 0; /* For list-initialization we consider explicit constructors and complain if one is chosen. */ check_converting = ((flags & (LOOKUP_ONLYCONVERTING|LOOKUP_LIST_INIT_CTOR)) == LOOKUP_ONLYCONVERTING); } - else - { - check_list_ctor = false; - check_converting = false; - } strict = DEDUCE_CALL; ctype = conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE; } @@ -5476,9 +5469,6 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args, for (lkp_iterator iter (fns); iter; ++iter) { - tree fn_first_arg; - const vec<tree, va_gc> *fn_args; - fn = *iter; if (check_converting && DECL_NONCONVERTING_P (fn)) @@ -5486,10 +5476,13 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args, if (check_list_ctor && !is_list_ctor (fn)) continue; - /* Figure out which set of arguments to use. */ + tree fn_first_arg = NULL_TREE; + const vec<tree, va_gc> *fn_args = args; + if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)) { - /* If this function is a non-static member and we didn't get an + /* Figure out where the object arg comes from. If this + function is a non-static member and we didn't get an implicit object argument, move it out of args. */ if (first_arg == NULL_TREE) { @@ -5506,12 +5499,6 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args, fn_first_arg = first_arg; fn_args = non_static_args; } - else - { - /* Otherwise, just use the list of arguments provided. */ - fn_first_arg = NULL_TREE; - fn_args = args; - } if (TREE_CODE (fn) == TEMPLATE_DECL) add_template_candidate (candidates, @@ -6926,6 +6913,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, else flags |= LOOKUP_ONLYCONVERTING; if (convs->rvaluedness_matches_p) + /* standard_conversion got LOOKUP_PREFER_RVALUE. */ flags |= LOOKUP_PREFER_RVALUE; if (TREE_CODE (expr) == TARGET_EXPR && TARGET_EXPR_LIST_INIT_P (expr)) @@ -7725,6 +7713,19 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) ++arg_index; parm = TREE_CHAIN (parm); } + + if (flags & LOOKUP_PREFER_RVALUE) + { + /* The implicit move specified in 15.8.3/3 fails "...if the type of + the first parameter of the selected constructor is not an rvalue + reference to the object’s type (possibly cv-qualified)...." */ + gcc_assert (!(complain & tf_error)); + tree ptype = convs[0]->type; + if (TREE_CODE (ptype) != REFERENCE_TYPE + || !TYPE_REF_IS_RVALUE (ptype) + || CONVERSION_RANK (convs[0]) > cr_exact) + return error_mark_node; + } } /* Bypass access control for 'this' parameter. */ else if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 4b9b93a77a7..94738bd8f78 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1039,50 +1039,39 @@ add_method (tree type, tree method, bool via_using) we're going to end up with an assignment operator at some point as well. */ vec_alloc (method_vec, 8); - /* Create slots for constructors and destructors. */ - method_vec->quick_push (NULL_TREE); - method_vec->quick_push (NULL_TREE); CLASSTYPE_METHOD_VEC (type) = method_vec; } /* Maintain TYPE_HAS_USER_CONSTRUCTOR, etc. */ grok_special_member_properties (method); - /* Constructors and destructors go in special slots. */ - if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (method)) - slot = CLASSTYPE_CONSTRUCTOR_SLOT; - else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method)) - slot = CLASSTYPE_DESTRUCTOR_SLOT; - else - { - tree m; + tree m; - insert_p = true; - /* See if we already have an entry with this name. */ - for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; - vec_safe_iterate (method_vec, slot, &m); - ++slot) + insert_p = true; + /* See if we already have an entry with this name. */ + for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; + vec_safe_iterate (method_vec, slot, &m); + ++slot) + { + m = OVL_FIRST (m); + if (template_conv_p) { - m = OVL_FIRST (m); - if (template_conv_p) - { - if (TREE_CODE (m) == TEMPLATE_DECL - && DECL_TEMPLATE_CONV_FN_P (m)) - insert_p = false; - break; - } - if (conv_p && !DECL_CONV_FN_P (m)) - break; - if (DECL_NAME (m) == DECL_NAME (method)) - { - insert_p = false; - break; - } - if (complete_p - && !DECL_CONV_FN_P (m) - && DECL_NAME (m) > DECL_NAME (method)) - break; + if (TREE_CODE (m) == TEMPLATE_DECL + && DECL_TEMPLATE_CONV_FN_P (m)) + insert_p = false; + break; } + if (conv_p && !DECL_CONV_FN_P (m)) + break; + if (DECL_NAME (m) == DECL_NAME (method)) + { + insert_p = false; + break; + } + if (complete_p + && !DECL_CONV_FN_P (m) + && DECL_NAME (m) > DECL_NAME (method)) + break; } current_fns = insert_p ? NULL_TREE : (*method_vec)[slot]; @@ -1256,7 +1245,7 @@ add_method (tree type, tree method, bool via_using) if (conv_p) TYPE_HAS_CONVERSION (type) = 1; - else if (slot >= CLASSTYPE_FIRST_CONVERSION_SLOT && !complete_p) + else if (!complete_p && !IDENTIFIER_CDTOR_P (DECL_NAME (method))) push_class_level_binding (DECL_NAME (method), current_fns); if (insert_p) @@ -2149,7 +2138,6 @@ maybe_warn_about_overly_private_class (tree t) { int has_member_fn = 0; int has_nonprivate_method = 0; - tree fn; if (!warn_ctor_dtor_privacy /* If the class has friends, those entities might create and @@ -2179,26 +2167,26 @@ maybe_warn_about_overly_private_class (tree t) functions are private. (Since there are no friends or non-private statics, we can't ever call any of the private member functions.) */ - for (fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn)) - /* We're not interested in compiler-generated methods; they don't - provide any way to call private members. */ - if (!DECL_ARTIFICIAL (fn)) + for (tree fn = TYPE_FIELDS (t); fn; fn = DECL_CHAIN (fn)) + if (!DECL_DECLARES_FUNCTION_P (fn)) + /* Not a function. */; + else if (DECL_ARTIFICIAL (fn)) + /* We're not interested in compiler-generated methods; they don't + provide any way to call private members. */; + else if (!TREE_PRIVATE (fn)) { - if (!TREE_PRIVATE (fn)) - { - if (DECL_STATIC_FUNCTION_P (fn)) - /* A non-private static member function is just like a - friend; it can create and invoke private member - functions, and be accessed without a class - instance. */ - return; + if (DECL_STATIC_FUNCTION_P (fn)) + /* A non-private static member function is just like a + friend; it can create and invoke private member + functions, and be accessed without a class + instance. */ + return; - has_nonprivate_method = 1; - /* Keep searching for a static member function. */ - } - else if (!DECL_CONSTRUCTOR_P (fn) && !DECL_DESTRUCTOR_P (fn)) - has_member_fn = 1; + has_nonprivate_method = 1; + /* Keep searching for a static member function. */ } + else if (!DECL_CONSTRUCTOR_P (fn) && !DECL_DESTRUCTOR_P (fn)) + has_member_fn = 1; if (!has_nonprivate_method && has_member_fn) { @@ -2228,14 +2216,14 @@ maybe_warn_about_overly_private_class (tree t) /* Even if some of the member functions are non-private, the class won't be useful for much if all the constructors or destructors are private: such an object can never be created or destroyed. */ - fn = CLASSTYPE_DESTRUCTOR (t); - if (fn && TREE_PRIVATE (fn)) - { - warning (OPT_Wctor_dtor_privacy, - "%q#T only defines a private destructor and has no friends", - t); - return; - } + if (tree dtor = CLASSTYPE_DESTRUCTOR (t)) + if (TREE_PRIVATE (dtor)) + { + warning (OPT_Wctor_dtor_privacy, + "%q#T only defines a private destructor and has no friends", + t); + return; + } /* Warn about classes that have private constructors and no friends. */ if (TYPE_HAS_USER_CONSTRUCTOR (t) @@ -2373,7 +2361,6 @@ resort_type_method_vec (void* obj, static void finish_struct_methods (tree t) { - tree fn_fields; vec<tree, va_gc> *method_vec; int slot, len; @@ -2384,9 +2371,9 @@ finish_struct_methods (tree t) len = method_vec->length (); /* Clear DECL_IN_AGGR_P for all functions. */ - for (fn_fields = TYPE_METHODS (t); fn_fields; - fn_fields = DECL_CHAIN (fn_fields)) - DECL_IN_AGGR_P (fn_fields) = 0; + for (tree fn = TYPE_FIELDS (t); fn; fn = DECL_CHAIN (fn)) + if (DECL_DECLARES_FUNCTION_P (fn)) + DECL_IN_AGGR_P (fn) = false; /* Issue warnings about private constructors and such. If there are no methods, then some public defaults are generated. */ @@ -2394,6 +2381,7 @@ finish_struct_methods (tree t) /* The type conversion ops have to live at the front of the vec, so we can't sort them. */ + tree fn_fields; for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; method_vec->iterate (slot, &fn_fields); ++slot) @@ -3305,6 +3293,8 @@ declare_virt_assop_and_dtor (tree t) static void one_inheriting_sig (tree t, tree ctor, tree *parms, int nparms) { + gcc_assert (TYPE_MAIN_VARIANT (t) == t); + /* We don't declare an inheriting ctor that would be a default, copy or move ctor for derived or base. */ if (nparms == 0) @@ -3322,11 +3312,11 @@ one_inheriting_sig (tree t, tree ctor, tree *parms, int nparms) parmlist = tree_cons (NULL_TREE, parms[i], parmlist); tree fn = implicitly_declare_fn (sfk_inheriting_constructor, t, false, ctor, parmlist); - gcc_assert (TYPE_MAIN_VARIANT (t) == t); + if (add_method (t, fn, false)) { - DECL_CHAIN (fn) = TYPE_METHODS (t); - TYPE_METHODS (t) = fn; + DECL_CHAIN (fn) = TYPE_FIELDS (t); + TYPE_FIELDS (t) = fn; } } @@ -3465,7 +3455,9 @@ count_fields (tree fields) int n_fields = 0; for (x = fields; x; x = DECL_CHAIN (x)) { - if (TREE_CODE (x) == FIELD_DECL && ANON_AGGR_TYPE_P (TREE_TYPE (x))) + if (DECL_DECLARES_FUNCTION_P (x)) + /* Functions are dealt with separately. */; + else if (TREE_CODE (x) == FIELD_DECL && ANON_AGGR_TYPE_P (TREE_TYPE (x))) n_fields += count_fields (TYPE_FIELDS (TREE_TYPE (x))); else n_fields += 1; @@ -3483,7 +3475,9 @@ add_fields_to_record_type (tree fields, struct sorted_fields_type *field_vec, in tree x; for (x = fields; x; x = DECL_CHAIN (x)) { - if (TREE_CODE (x) == FIELD_DECL && ANON_AGGR_TYPE_P (TREE_TYPE (x))) + if (DECL_DECLARES_FUNCTION_P (x)) + /* Functions are handled separately. */; + else if (TREE_CODE (x) == FIELD_DECL && ANON_AGGR_TYPE_P (TREE_TYPE (x))) idx = add_fields_to_record_type (TYPE_FIELDS (TREE_TYPE (x)), field_vec, idx); else field_vec->elts[idx++] = x; @@ -3740,6 +3734,10 @@ check_field_decls (tree t, tree *access_decls, || TREE_CODE (x) == TEMPLATE_DECL) continue; + if (TREE_CODE (x) == FUNCTION_DECL) + /* FIXME: We should fold in the checking from check_methods. */ + continue; + /* If we've gotten this far, it's a data member, possibly static, or an enumerator. */ if (TREE_CODE (x) != CONST_DECL) @@ -4664,39 +4662,42 @@ build_base_fields (record_layout_info rli, } } -/* Go through the TYPE_METHODS of T issuing any appropriate +/* Go through the TYPE_FIELDS of T issuing any appropriate diagnostics, figuring out which methods override which other methods, and so forth. */ static void check_methods (tree t) { - tree x; + for (tree x = TYPE_FIELDS (t); x; x = DECL_CHAIN (x)) + if (DECL_DECLARES_FUNCTION_P (x)) + { + check_for_override (x, t); + + if (DECL_PURE_VIRTUAL_P (x) + && (TREE_CODE (x) != FUNCTION_DECL || ! DECL_VINDEX (x))) + error ("initializer specified for non-virtual method %q+D", x); + /* The name of the field is the original field name + Save this in auxiliary field for later overloading. */ + if (TREE_CODE (x) == FUNCTION_DECL && DECL_VINDEX (x)) + { + TYPE_POLYMORPHIC_P (t) = 1; + if (DECL_PURE_VIRTUAL_P (x)) + vec_safe_push (CLASSTYPE_PURE_VIRTUALS (t), x); + } - for (x = TYPE_METHODS (t); x; x = DECL_CHAIN (x)) - { - check_for_override (x, t); - if (DECL_PURE_VIRTUAL_P (x) && (TREE_CODE (x) != FUNCTION_DECL || ! DECL_VINDEX (x))) - error ("initializer specified for non-virtual method %q+D", x); - /* The name of the field is the original field name - Save this in auxiliary field for later overloading. */ - if (TREE_CODE (x) == FUNCTION_DECL && DECL_VINDEX (x)) - { - TYPE_POLYMORPHIC_P (t) = 1; - if (DECL_PURE_VIRTUAL_P (x)) - vec_safe_push (CLASSTYPE_PURE_VIRTUALS (t), x); - } - /* All user-provided destructors are non-trivial. - Constructors and assignment ops are handled in - grok_special_member_properties. */ - if (DECL_DESTRUCTOR_P (x) && user_provided_p (x)) - TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 1; - if (!DECL_VIRTUAL_P (x) - && lookup_attribute ("transaction_safe_dynamic", DECL_ATTRIBUTES (x))) - error_at (DECL_SOURCE_LOCATION (x), - "%<transaction_safe_dynamic%> may only be specified for " - "a virtual function"); - } + /* All user-provided destructors are non-trivial. + Constructors and assignment ops are handled in + grok_special_member_properties. */ + if (DECL_DESTRUCTOR_P (x) && user_provided_p (x)) + TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 1; + if (!DECL_VIRTUAL_P (x) + && lookup_attribute ("transaction_safe_dynamic", + DECL_ATTRIBUTES (x))) + error_at (DECL_SOURCE_LOCATION (x), + "%<transaction_safe_dynamic%> may only be specified for " + "a virtual function"); + } } /* FN is a constructor or destructor. Clone the declaration to create @@ -4902,7 +4903,7 @@ clone_function_decl (tree fn, bool update_methods) /* For each destructor, we need three variants: an in-charge version, a not-in-charge version, and an in-charge deleting version. We clone the deleting version first because that - means it will go second on the TYPE_METHODS list -- and that + means it will go second on the TYPE_FIELDS list -- and that corresponds to the correct layout order in the virtual function table. @@ -5174,11 +5175,10 @@ set_method_tm_attributes (tree t) /* Any method that does not yet have a tm attribute inherits the one from the class. */ - for (fndecl = TYPE_METHODS (t); fndecl; fndecl = TREE_CHAIN (fndecl)) - { - if (!find_tm_attribute (TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))) - apply_tm_attr (fndecl, class_tm_attr); - } + for (fndecl = TYPE_FIELDS (t); fndecl; fndecl = DECL_CHAIN (fndecl)) + if (DECL_DECLARES_FUNCTION_P (fndecl) + && !find_tm_attribute (TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))) + apply_tm_attr (fndecl, class_tm_attr); } /* Returns true if FN is a default constructor. */ @@ -5660,9 +5660,9 @@ finalize_literal_type_property (tree t) /* C++14 DR 1684 removed this restriction. */ if (cxx_dialect < cxx14 && !CLASSTYPE_LITERAL_P (t) && !LAMBDA_TYPE_P (t)) - for (fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn)) - if (DECL_DECLARED_CONSTEXPR_P (fn) - && TREE_CODE (fn) != TEMPLATE_DECL + for (fn = TYPE_FIELDS (t); fn; fn = DECL_CHAIN (fn)) + if (TREE_CODE (fn) == FUNCTION_DECL + && DECL_DECLARED_CONSTEXPR_P (fn) && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn) && !DECL_CONSTRUCTOR_P (fn)) { @@ -5924,8 +5924,10 @@ check_bases_and_members (tree t) /* Check defaulted declarations here so we have cant_have_const_ctor and don't need to worry about clones. */ - for (fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn)) - if (!DECL_ARTIFICIAL (fn) && DECL_DEFAULTED_IN_CLASS_P (fn)) + for (fn = TYPE_FIELDS (t); fn; fn = DECL_CHAIN (fn)) + if (DECL_DECLARES_FUNCTION_P (fn) + && !DECL_ARTIFICIAL (fn) + && DECL_DEFAULTED_IN_CLASS_P (fn)) { int copy = copy_fn_p (fn); if (copy > 0) @@ -5984,7 +5986,7 @@ create_vtable_ptr (tree t, tree* virtuals_p) tree fn; /* Collect the virtual functions declared in T. */ - for (fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn)) + for (fn = TYPE_FIELDS (t); fn; fn = DECL_CHAIN (fn)) if (TREE_CODE (fn) == FUNCTION_DECL && DECL_VINDEX (fn) && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn) && TREE_CODE (DECL_VINDEX (fn)) != INTEGER_CST) @@ -6643,8 +6645,7 @@ determine_key_method (tree type) inline at the point of class definition. On some targets the key function may not be inline; those targets should not call this function until the end of the translation unit. */ - for (method = TYPE_METHODS (type); method != NULL_TREE; - method = DECL_CHAIN (method)) + for (method = TYPE_FIELDS (type); method; method = DECL_CHAIN (method)) if (TREE_CODE (method) == FUNCTION_DECL && DECL_VINDEX (method) != NULL_TREE && ! DECL_DECLARED_INLINE_P (method) @@ -7336,11 +7337,11 @@ unreverse_member_declarations (tree t) /* The following lists are all in reverse order. Put them in declaration order now. */ - TYPE_METHODS (t) = nreverse (TYPE_METHODS (t)); CLASSTYPE_DECL_LIST (t) = nreverse (CLASSTYPE_DECL_LIST (t)); - /* Actually, for the TYPE_FIELDS, only the non TYPE_DECLs are in - reverse order, so we can't just use nreverse. */ + /* For the TYPE_FIELDS, only the non TYPE_DECLs are in reverse + order, so we can't just use nreverse. Due to stat_hack + chicanery in finish_member_declarations. */ prev = NULL_TREE; for (x = TYPE_FIELDS (t); x && TREE_CODE (x) != TYPE_DECL; @@ -7350,6 +7351,7 @@ unreverse_member_declarations (tree t) DECL_CHAIN (x) = prev; prev = x; } + if (prev) { DECL_CHAIN (TYPE_FIELDS (t)) = x; @@ -7390,8 +7392,8 @@ finish_struct (tree t, tree attributes) CLASSTYPE_PURE_VIRTUALS contains the list of the inline friends (see CLASSTYPE_INLINE_FRIENDS) so we need to clear it. */ CLASSTYPE_PURE_VIRTUALS (t) = NULL; - for (x = TYPE_METHODS (t); x; x = DECL_CHAIN (x)) - if (DECL_PURE_VIRTUAL_P (x)) + for (x = TYPE_FIELDS (t); x; x = DECL_CHAIN (x)) + if (TREE_CODE (x) == FUNCTION_DECL && DECL_PURE_VIRTUAL_P (x)) vec_safe_push (CLASSTYPE_PURE_VIRTUALS (t), x); complete_vars (t); /* We need to add the target functions to the CLASSTYPE_METHOD_VEC if @@ -7416,7 +7418,6 @@ finish_struct (tree t, tree attributes) TYPE_SIZE (x) = TYPE_SIZE (t); TYPE_SIZE_UNIT (x) = TYPE_SIZE_UNIT (t); TYPE_FIELDS (x) = TYPE_FIELDS (t); - TYPE_METHODS (x) = TYPE_METHODS (t); } } else @@ -8092,8 +8093,9 @@ resolve_address_of_overloaded_function (tree target_type, continue; /* In C++17 we need the noexcept-qualifier to compare types. */ - if (flag_noexcept_type) - maybe_instantiate_noexcept (fn); + if (flag_noexcept_type + && !maybe_instantiate_noexcept (fn, complain)) + continue; /* See if there's a match. */ tree fntype = static_fn_type (fn); @@ -8175,7 +8177,7 @@ resolve_address_of_overloaded_function (tree target_type, /* In C++17 we need the noexcept-qualifier to compare types. */ if (flag_noexcept_type) - maybe_instantiate_noexcept (instantiation); + maybe_instantiate_noexcept (instantiation, complain); /* See if there's a match. */ tree fntype = static_fn_type (instantiation); @@ -9922,7 +9924,7 @@ add_vcall_offset_vtbl_entries_1 (tree binfo, vtbl_init_data* vid) /* The ABI requires that the methods be processed in declaration order. */ - for (orig_fn = TYPE_METHODS (BINFO_TYPE (binfo)); + for (orig_fn = TYPE_FIELDS (BINFO_TYPE (binfo)); orig_fn; orig_fn = DECL_CHAIN (orig_fn)) if (TREE_CODE (orig_fn) == FUNCTION_DECL && DECL_VINDEX (orig_fn)) diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 32180a74c3f..29ba2c3dac2 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -5782,6 +5782,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, case CLEANUP_STMT: case EMPTY_CLASS_EXPR: + case PREDICT_EXPR: return false; case GOTO_EXPR: diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index f010f6c63be..4a52aa50e77 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -33,6 +33,8 @@ along with GCC; see the file COPYING3. If not see #include "c-family/c-ubsan.h" #include "cilk.h" #include "cp-cilkplus.h" +#include "stringpool.h" +#include "attribs.h" #include "asan.h" /* Forward declarations. */ @@ -1668,7 +1670,8 @@ cp_genericize (tree fndecl) walk_tree's hash functionality. */ cp_genericize_tree (&DECL_SAVED_TREE (fndecl), true); - if (sanitize_flags_p (SANITIZE_RETURN)) + if (sanitize_flags_p (SANITIZE_RETURN) + && current_function_decl != NULL_TREE) cp_ubsan_maybe_instrument_return (fndecl); /* Do everything else. */ @@ -2313,9 +2316,9 @@ cp_fold (tree x) /* A COND_EXPR might have incompatible types in branches if one or both arms are bitfields. If folding exposed such a branch, fix it up. */ - if (TREE_CODE (x) != code) - if (tree type = is_bitfield_expr_with_lowered_type (x)) - x = fold_convert (type, x); + if (TREE_CODE (x) != code + && !useless_type_conversion_p (TREE_TYPE (org_x), TREE_TYPE (x))) + x = fold_convert (TREE_TYPE (org_x), x); break; diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c index 5a7da5b4957..4475b6cb911 100644 --- a/gcc/cp/cp-objcp-common.c +++ b/gcc/cp/cp-objcp-common.c @@ -212,6 +212,13 @@ cp_decl_dwarf_attribute (const_tree decl, int attr) } break; + case DW_AT_export_symbols: + if (TREE_CODE (decl) == NAMESPACE_DECL + && (DECL_NAMESPACE_INLINE_P (decl) + || (DECL_NAME (decl) == NULL_TREE && dwarf_version >= 5))) + return 1; + break; + default: break; } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a76906d1baf..6c4153d558b 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2148,29 +2148,21 @@ struct GTY(()) lang_type { and the RECORD_TYPE for the class template otherwise. */ #define CLASSTYPE_DECL_LIST(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->decl_list) -/* The slot in the CLASSTYPE_METHOD_VEC where constructors go. */ -#define CLASSTYPE_CONSTRUCTOR_SLOT 0 - -/* The slot in the CLASSTYPE_METHOD_VEC where destructors go. */ -#define CLASSTYPE_DESTRUCTOR_SLOT 1 - /* The first slot in the CLASSTYPE_METHOD_VEC where conversion operators can appear. */ -#define CLASSTYPE_FIRST_CONVERSION_SLOT 2 +#define CLASSTYPE_FIRST_CONVERSION_SLOT 0 /* A FUNCTION_DECL or OVERLOAD for the constructors for NODE. These are the constructors that take an in-charge parameter. */ #define CLASSTYPE_CONSTRUCTORS(NODE) \ - ((*CLASSTYPE_METHOD_VEC (NODE))[CLASSTYPE_CONSTRUCTOR_SLOT]) + (lookup_fnfields_slot_nolazy (NODE, ctor_identifier)) /* A FUNCTION_DECL for the destructor for NODE. This is the destructors that take an in-charge parameter. If CLASSTYPE_LAZY_DESTRUCTOR is true, then this entry will be NULL until the destructor is created with lazily_declare_fn. */ #define CLASSTYPE_DESTRUCTOR(NODE) \ - (CLASSTYPE_METHOD_VEC (NODE) \ - ? (*CLASSTYPE_METHOD_VEC (NODE))[CLASSTYPE_DESTRUCTOR_SLOT] \ - : NULL_TREE) + (lookup_fnfields_slot_nolazy (NODE, dtor_identifier)) /* A dictionary of the nested user-defined-types (class-types, or enums) found within this class. This table includes nested member class @@ -5304,7 +5296,7 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG }; (Normally, these entities are registered in the symbol table, but not found by lookup.) */ #define LOOKUP_HIDDEN (LOOKUP_PREFER_NAMESPACES << 1) -/* Prefer that the lvalue be treated as an rvalue. */ +/* We're trying to treat an lvalue as an rvalue. */ #define LOOKUP_PREFER_RVALUE (LOOKUP_HIDDEN << 1) /* We're inside an init-list, so narrowing conversions are ill-formed. */ #define LOOKUP_NO_NARROWING (LOOKUP_PREFER_RVALUE << 1) @@ -6305,7 +6297,7 @@ extern tree get_type_value (tree); extern tree build_zero_init (tree, tree, bool); extern tree build_value_init (tree, tsubst_flags_t); extern tree build_value_init_noctor (tree, tsubst_flags_t); -extern tree get_nsdmi (tree, bool); +extern tree get_nsdmi (tree, bool, tsubst_flags_t); extern tree build_offset_ref (tree, tree, bool, tsubst_flags_t); extern tree throw_bad_array_new_length (void); @@ -6363,7 +6355,7 @@ extern bool trivial_fn_p (tree); extern tree forward_parm (tree); extern bool is_trivially_xible (enum tree_code, tree, tree); extern bool is_xible (enum tree_code, tree, tree); -extern tree get_defaulted_eh_spec (tree); +extern tree get_defaulted_eh_spec (tree, tsubst_flags_t = tf_warning_or_error); extern void after_nsdmi_defaulted_late_checks (tree); extern bool maybe_explain_implicit_delete (tree); extern void explain_implicit_non_constexpr (tree); @@ -6393,6 +6385,7 @@ extern tree cp_convert_range_for (tree, tree, tree, tree, unsigned int, bool); extern bool parsing_nsdmi (void); extern bool parsing_default_capturing_generic_lambda_in_template (void); extern void inject_this_parameter (tree, cp_cv_quals); +extern location_t defarg_location (tree); /* in pt.c */ extern bool check_template_shadow (tree); @@ -6456,7 +6449,7 @@ extern int more_specialized_fn (tree, tree, int); extern void do_decl_instantiation (tree, tree); extern void do_type_instantiation (tree, tree, tsubst_flags_t); extern bool always_instantiate_p (tree); -extern void maybe_instantiate_noexcept (tree); +extern bool maybe_instantiate_noexcept (tree, tsubst_flags_t = tf_warning_or_error); extern tree instantiate_decl (tree, bool, bool); extern int comp_template_parms (const_tree, const_tree); extern bool builtin_pack_fn_p (tree); @@ -7174,7 +7167,7 @@ extern tree split_nonconstant_init (tree, tree); extern bool check_narrowing (tree, tree, tsubst_flags_t); extern tree digest_init (tree, tree, tsubst_flags_t); extern tree digest_init_flags (tree, tree, int, tsubst_flags_t); -extern tree digest_nsdmi_init (tree, tree); +extern tree digest_nsdmi_init (tree, tree, tsubst_flags_t); extern tree build_scoped_ref (tree, tree, tree *); extern tree build_x_arrow (location_t, tree, tsubst_flags_t); diff --git a/gcc/cp/cp-ubsan.c b/gcc/cp/cp-ubsan.c index f00f870bd3e..cd2b60ad488 100644 --- a/gcc/cp/cp-ubsan.c +++ b/gcc/cp/cp-ubsan.c @@ -23,6 +23,8 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "cp-tree.h" #include "ubsan.h" +#include "stringpool.h" +#include "attribs.h" #include "asan.h" /* Test if we should instrument vptr access. */ @@ -36,6 +38,9 @@ cp_ubsan_instrument_vptr_p (tree type) if (!sanitize_flags_p (SANITIZE_VPTR)) return false; + if (current_function_decl == NULL_TREE) + return false; + if (type) { type = TYPE_MAIN_VARIANT (type); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 631ff49673f..fd758d3c2dc 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -33,6 +33,8 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "intl.h" #include "convert.h" +#include "stringpool.h" +#include "attribs.h" static tree convert_to_pointer_force (tree, tree, tsubst_flags_t); static tree build_type_conversion (tree, tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 5b8e6a22b01..aab2019f9cd 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4549,8 +4549,6 @@ push_throw_library_fn (tree name, tree type) void fixup_anonymous_aggr (tree t) { - tree *q; - /* Wipe out memory of synthesized methods. */ TYPE_HAS_USER_CONSTRUCTOR (t) = 0; TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 0; @@ -4559,29 +4557,12 @@ fixup_anonymous_aggr (tree t) TYPE_HAS_COPY_ASSIGN (t) = 0; TYPE_HAS_CONST_COPY_ASSIGN (t) = 0; - /* Splice the implicitly generated functions out of the TYPE_METHODS - list. */ - q = &TYPE_METHODS (t); - while (*q) - { - if (DECL_ARTIFICIAL (*q)) - *q = TREE_CHAIN (*q); - else - q = &DECL_CHAIN (*q); - } - - /* ISO C++ 9.5.3. Anonymous unions may not have function members. */ - if (TYPE_METHODS (t)) - { - tree decl = TYPE_MAIN_DECL (t); - - if (TREE_CODE (t) != UNION_TYPE) - error_at (DECL_SOURCE_LOCATION (decl), - "an anonymous struct cannot have function members"); - else - error_at (DECL_SOURCE_LOCATION (decl), - "an anonymous union cannot have function members"); - } + /* Splice the implicitly generated functions out of TYPE_FIELDS. */ + for (tree probe, *prev_p = &TYPE_FIELDS (t); (probe = *prev_p);) + if (TREE_CODE (probe) == FUNCTION_DECL && DECL_ARTIFICIAL (probe)) + *prev_p = DECL_CHAIN (probe); + else + prev_p = &DECL_CHAIN (probe); /* Anonymous aggregates cannot have fields with ctors, dtors or complex assignment operators (because they cannot have these methods themselves). @@ -7602,6 +7583,7 @@ declare_global_var (tree name, tree type) TREE_PUBLIC (decl) = 1; DECL_EXTERNAL (decl) = 1; DECL_ARTIFICIAL (decl) = 1; + DECL_CONTEXT (decl) = FROB_CONTEXT (global_namespace); /* If the user has explicitly declared this variable (perhaps because the code we are compiling is part of a low-level runtime library), then it is possible that our declaration will be merged @@ -9501,7 +9483,8 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain) stabilize_vla_size (itype); - if (sanitize_flags_p (SANITIZE_VLA)) + if (sanitize_flags_p (SANITIZE_VLA) + && current_function_decl != NULL_TREE) { /* We have to add 1 -- in the ubsan routine we generate LE_EXPR rather than LT_EXPR. */ diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 4fa4ad9740f..37393a1a253 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -2592,6 +2592,7 @@ reset_decl_linkage (tree decl) determine_visibility (decl); tentative_decl_linkage (decl); } + static void reset_type_linkage_2 (tree type) { @@ -2615,18 +2616,14 @@ reset_type_linkage_2 (tree type) for (tree m = TYPE_FIELDS (type); m; m = DECL_CHAIN (m)) { tree mem = STRIP_TEMPLATE (m); - if (VAR_P (mem)) + if (TREE_CODE (mem) == VAR_DECL || TREE_CODE (mem) == FUNCTION_DECL) reset_decl_linkage (mem); } - for (tree m = TYPE_METHODS (type); m; m = DECL_CHAIN (m)) - { - tree mem = STRIP_TEMPLATE (m); - reset_decl_linkage (mem); - } binding_table_foreach (CLASSTYPE_NESTED_UTDS (type), bt_reset_linkage_2, NULL); } } + static void bt_reset_linkage_2 (binding_entry b, void */*data*/) { @@ -3159,11 +3156,9 @@ get_tls_init_fn (tree var) if (!flag_extern_tls_init && DECL_EXTERNAL (var)) return NULL_TREE; -#ifdef ASM_OUTPUT_DEF /* If the variable is internal, or if we can't generate aliases, call the local init function directly. */ - if (!TREE_PUBLIC (var)) -#endif + if (!TREE_PUBLIC (var) || !TARGET_SUPPORTS_ALIASES) return get_local_tls_init_fn (); tree sname = mangle_tls_init_fn (var); @@ -4244,9 +4239,8 @@ handle_tls_init (void) tree init = TREE_PURPOSE (vars); one_static_initialization_or_destruction (var, init, true); -#ifdef ASM_OUTPUT_DEF /* Output init aliases even with -fno-extern-tls-init. */ - if (TREE_PUBLIC (var)) + if (TARGET_SUPPORTS_ALIASES && TREE_PUBLIC (var)) { tree single_init_fn = get_tls_init_fn (var); if (single_init_fn == NULL_TREE) @@ -4256,7 +4250,6 @@ handle_tls_init (void) (single_init_fn, fn); gcc_assert (alias != NULL); } -#endif } finish_then_clause (if_stmt); @@ -4301,17 +4294,18 @@ generate_mangling_alias (tree decl, tree id2) implementation. */ void -note_mangling_alias (tree decl ATTRIBUTE_UNUSED, tree id2 ATTRIBUTE_UNUSED) +note_mangling_alias (tree decl, tree id2) { -#ifdef ASM_OUTPUT_DEF - if (!defer_mangling_aliases) - generate_mangling_alias (decl, id2); - else + if (TARGET_SUPPORTS_ALIASES) { - vec_safe_push (mangling_aliases, decl); - vec_safe_push (mangling_aliases, id2); + if (!defer_mangling_aliases) + generate_mangling_alias (decl, id2); + else + { + vec_safe_push (mangling_aliases, decl); + vec_safe_push (mangling_aliases, id2); + } } -#endif } /* Emit all mangling aliases that were deferred up to this point. */ @@ -4991,25 +4985,20 @@ mark_used (tree decl, tsubst_flags_t complain) if (TREE_CODE (decl) == CONST_DECL) used_types_insert (DECL_CONTEXT (decl)); - if (TREE_CODE (decl) == FUNCTION_DECL) - maybe_instantiate_noexcept (decl); + if (TREE_CODE (decl) == FUNCTION_DECL + && !maybe_instantiate_noexcept (decl, complain)) + return false; if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DELETED_FN (decl)) { - if (DECL_ARTIFICIAL (decl)) - { - if (DECL_OVERLOADED_OPERATOR_P (decl) == TYPE_EXPR - && LAMBDA_TYPE_P (DECL_CONTEXT (decl))) - { - /* We mark a lambda conversion op as deleted if we can't - generate it properly; see maybe_add_lambda_conv_op. */ - sorry ("converting lambda which uses %<...%> to " - "function pointer"); - return false; - } - } - if (complain & tf_error) + if (DECL_ARTIFICIAL (decl) + && DECL_OVERLOADED_OPERATOR_P (decl) == TYPE_EXPR + && LAMBDA_TYPE_P (DECL_CONTEXT (decl))) + /* We mark a lambda conversion op as deleted if we can't + generate it properly; see maybe_add_lambda_conv_op. */ + sorry ("converting lambda which uses %<...%> to function pointer"); + else if (complain & tf_error) { error ("use of deleted function %qD", decl); if (!maybe_explain_implicit_delete (decl)) diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 2497c7f6d23..31ca8fe1eb2 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -3046,6 +3046,8 @@ location_of (tree t) if (DECL_P (t)) return DECL_SOURCE_LOCATION (t); + if (TREE_CODE (t) == DEFAULT_ARG) + return defarg_location (t); return EXPR_LOC_OR_LOC (t, input_location); } diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 208e52a405b..b25b91b97be 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -665,6 +665,7 @@ build_throw (tree exp) { int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING; vec<tree, va_gc> *exp_vec; + bool converted = false; /* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes treated as an rvalue for the purposes of overload resolution @@ -675,14 +676,31 @@ build_throw (tree exp) && ! TREE_STATIC (exp) /* The variable must not have the `volatile' qualifier. */ && !(cp_type_quals (TREE_TYPE (exp)) & TYPE_QUAL_VOLATILE)) - flags = flags | LOOKUP_PREFER_RVALUE; + { + tree moved = move (exp); + exp_vec = make_tree_vector_single (moved); + moved = (build_special_member_call + (object, complete_ctor_identifier, &exp_vec, + TREE_TYPE (object), flags|LOOKUP_PREFER_RVALUE, + tf_none)); + release_tree_vector (exp_vec); + if (moved != error_mark_node) + { + exp = moved; + converted = true; + } + } /* Call the copy constructor. */ - exp_vec = make_tree_vector_single (exp); - exp = (build_special_member_call - (object, complete_ctor_identifier, &exp_vec, - TREE_TYPE (object), flags, tf_warning_or_error)); - release_tree_vector (exp_vec); + if (!converted) + { + exp_vec = make_tree_vector_single (exp); + exp = (build_special_member_call + (object, complete_ctor_identifier, &exp_vec, + TREE_TYPE (object), flags, tf_warning_or_error)); + release_tree_vector (exp_vec); + } + if (exp == error_mark_node) { error (" in thrown expression"); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 14335388a50..83e685c0011 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -30,6 +30,8 @@ along with GCC; see the file COPYING3. If not see #include "gimplify.h" #include "c-family/c-ubsan.h" #include "intl.h" +#include "stringpool.h" +#include "attribs.h" #include "asan.h" static bool begin_init_stmts (tree *, tree *); @@ -534,7 +536,7 @@ perform_target_ctor (tree init) /* Return the non-static data initializer for FIELD_DECL MEMBER. */ tree -get_nsdmi (tree member, bool in_ctor) +get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain) { tree init; tree save_ccp = current_class_ptr; @@ -552,50 +554,54 @@ get_nsdmi (tree member, bool in_ctor) { init = DECL_INITIAL (DECL_TI_TEMPLATE (member)); if (TREE_CODE (init) == DEFAULT_ARG) - goto unparsed; - + /* Unparsed. */; /* Check recursive instantiation. */ - if (DECL_INSTANTIATING_NSDMI_P (member)) + else if (DECL_INSTANTIATING_NSDMI_P (member)) { - error ("recursive instantiation of non-static data member " - "initializer for %qD", member); + if (complain & tf_error) + error ("recursive instantiation of default member " + "initializer for %qD", member); init = error_mark_node; } else { DECL_INSTANTIATING_NSDMI_P (member) = 1; - + /* Do deferred instantiation of the NSDMI. */ init = (tsubst_copy_and_build (init, DECL_TI_ARGS (member), - tf_warning_or_error, member, /*function_p=*/false, + complain, member, /*function_p=*/false, /*integral_constant_expression_p=*/false)); - init = digest_nsdmi_init (member, init); + init = digest_nsdmi_init (member, init, complain); DECL_INSTANTIATING_NSDMI_P (member) = 0; } } else + init = DECL_INITIAL (member); + + if (init && TREE_CODE (init) == DEFAULT_ARG) { - init = DECL_INITIAL (member); - if (init && TREE_CODE (init) == DEFAULT_ARG) + if (complain & tf_error) { - unparsed: - error ("constructor required before non-static data member " - "for %qD has been parsed", member); + error ("default member initializer for %qD required before the end " + "of its enclosing class", member); + inform (location_of (init), "defined here"); DECL_INITIAL (member) = error_mark_node; - init = error_mark_node; } - /* Strip redundant TARGET_EXPR so we don't need to remap it, and - so the aggregate init code below will see a CONSTRUCTOR. */ - bool simple_target = (init && SIMPLE_TARGET_EXPR_P (init)); - if (simple_target) - init = TARGET_EXPR_INITIAL (init); - init = break_out_target_exprs (init); - if (simple_target && TREE_CODE (init) != CONSTRUCTOR) - /* Now put it back so C++17 copy elision works. */ - init = get_target_expr (init); + init = error_mark_node; } + + /* Strip redundant TARGET_EXPR so we don't need to remap it, and + so the aggregate init code below will see a CONSTRUCTOR. */ + bool simple_target = (init && SIMPLE_TARGET_EXPR_P (init)); + if (simple_target) + init = TARGET_EXPR_INITIAL (init); + init = break_out_target_exprs (init); + if (simple_target && TREE_CODE (init) != CONSTRUCTOR) + /* Now put it back so C++17 copy elision works. */ + init = get_target_expr (init); + current_class_ptr = save_ccp; current_class_ref = save_ccr; return init; @@ -642,7 +648,7 @@ perform_member_init (tree member, tree init) /* Use the non-static data member initializer if there was no mem-initializer for this field. */ if (init == NULL_TREE) - init = get_nsdmi (member, /*ctor*/true); + init = get_nsdmi (member, /*ctor*/true, tf_warning_or_error); if (init == error_mark_node) return; @@ -3910,7 +3916,8 @@ finish_length_check (tree atype, tree iterator, tree obase, unsigned n) } /* Don't check an array new when -fno-exceptions. */ } - else if (sanitize_flags_p (SANITIZE_BOUNDS)) + else if (sanitize_flags_p (SANITIZE_BOUNDS) + && current_function_decl != NULL_TREE) { /* Make sure the last element of the initializer is in bounds. */ finish_expr_stmt diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c index 0e02375fa1b..14ff6c2ae43 100644 --- a/gcc/cp/lambda.c +++ b/gcc/cp/lambda.c @@ -529,7 +529,10 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p, else if (id != this_identifier && by_reference_p) { if (!lvalue_p (initializer)) - error ("cannot capture %qE by reference", initializer); + { + error ("cannot capture %qE by reference", initializer); + return error_mark_node; + } } else { diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 961b705a546..097fbb547d2 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -766,7 +766,7 @@ copy_decl (tree decl MEM_STAT_DECL) { tree copy; - copy = copy_node_stat (decl PASS_MEM_STAT); + copy = copy_node (decl PASS_MEM_STAT); cxx_dup_lang_specific_decl (copy); return copy; } @@ -799,7 +799,7 @@ copy_type (tree type MEM_STAT_DECL) { tree copy; - copy = copy_node_stat (type PASS_MEM_STAT); + copy = copy_node (type PASS_MEM_STAT); copy_lang_type (copy); return copy; } diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 3c57b41c8d9..809ebc8311c 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1342,7 +1342,7 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk, if (bad && deleted_p) *deleted_p = true; } - else if (sfk == sfk_constructor) + else if (sfk == sfk_constructor || sfk == sfk_inheriting_constructor) { bool bad; @@ -1357,7 +1357,7 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk, default constructor is noexcept(false). */ if (spec_p) { - tree nsdmi = get_nsdmi (field, /*ctor*/false); + tree nsdmi = get_nsdmi (field, /*ctor*/false, complain); if (!expr_noexcept_p (nsdmi, complain)) *spec_p = noexcept_false_spec; } @@ -1660,6 +1660,10 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, flags |= LOOKUP_DEFAULTED; tsubst_flags_t complain = diag ? tf_warning_or_error : tf_none; + if (diag && spec_p) + /* We're in get_defaulted_eh_spec; we don't actually want any walking + diagnostics, we just want complain set. */ + diag = false; int quals = const_p ? TYPE_QUAL_CONST : TYPE_UNQUALIFIED; for (binfo = TYPE_BINFO (ctype), i = 0; @@ -1689,12 +1693,18 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, if (check_vdtor && type_has_virtual_destructor (BINFO_TYPE (base_binfo))) { - fn = locate_fn_flags (ctype, cp_operator_id (DELETE_EXPR), - ptr_type_node, flags, complain); /* Unlike for base ctor/op=/dtor, for operator delete it's fine to have a null fn (no class-specific op delete). */ - if (fn && fn == error_mark_node && deleted_p) - *deleted_p = true; + fn = locate_fn_flags (ctype, cp_operator_id (DELETE_EXPR), + ptr_type_node, flags, tf_none); + if (fn && fn == error_mark_node) + { + if (complain & tf_error) + locate_fn_flags (ctype, cp_operator_id (DELETE_EXPR), + ptr_type_node, flags, complain); + if (deleted_p) + *deleted_p = true; + } check_vdtor = false; } } @@ -1749,7 +1759,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, needed. Return what it should be. */ tree -get_defaulted_eh_spec (tree decl) +get_defaulted_eh_spec (tree decl, tsubst_flags_t complain) { if (DECL_CLONED_FUNCTION_P (decl)) decl = DECL_CLONED_FUNCTION (decl); @@ -1759,8 +1769,9 @@ get_defaulted_eh_spec (tree decl) tree parm_type = TREE_VALUE (parms); bool const_p = CP_TYPE_CONST_P (non_reference (parm_type)); tree spec = empty_except_spec; + bool diag = !DECL_DELETED_FN (decl) && (complain & tf_error); synthesized_method_walk (ctype, sfk, const_p, &spec, NULL, NULL, - NULL, false, DECL_INHERITED_CTOR (decl), + NULL, diag, DECL_INHERITED_CTOR (decl), parms); return spec; } @@ -2173,6 +2184,12 @@ defaulted_late_check (tree fn) "does not match expected signature %qD", implicit_fn); } + if (DECL_DELETED_FN (implicit_fn)) + { + DECL_DELETED_FN (fn) = 1; + return; + } + /* 8.4.2/2: An explicitly-defaulted function (...) may have an explicit exception-specification only if it is compatible (15.4) with the exception-specification on the implicit declaration. If a function @@ -2231,9 +2248,6 @@ defaulted_late_check (tree fn) } DECL_DECLARED_CONSTEXPR_P (fn) = false; } - - if (DECL_DELETED_FN (implicit_fn)) - DECL_DELETED_FN (fn) = 1; } /* OK, we've parsed the NSDMI for class T, now we can check any explicit @@ -2246,8 +2260,10 @@ after_nsdmi_defaulted_late_checks (tree t) return; if (t == error_mark_node) return; - for (tree fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn)) - if (!DECL_ARTIFICIAL (fn) && DECL_DEFAULTED_IN_CLASS_P (fn)) + for (tree fn = TYPE_FIELDS (t); fn; fn = DECL_CHAIN (fn)) + if (!DECL_ARTIFICIAL (fn) + && DECL_DECLARES_FUNCTION_P (fn) + && DECL_DEFAULTED_IN_CLASS_P (fn)) { tree fn_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)); if (UNEVALUATED_NOEXCEPT_SPEC_P (fn_spec)) @@ -2379,20 +2395,25 @@ lazily_declare_fn (special_function_kind sfk, tree type) || sfk == sfk_move_assignment || sfk == sfk_copy_assignment) check_for_override (fn, type); + /* Add it to CLASSTYPE_METHOD_VEC. */ bool added = add_method (type, fn, false); gcc_assert (added); - /* Add it to TYPE_METHODS. */ + + /* Add it to TYPE_FIELDS. */ if (sfk == sfk_destructor && DECL_VIRTUAL_P (fn)) /* The ABI requires that a virtual destructor go at the end of the vtable. */ - TYPE_METHODS (type) = chainon (TYPE_METHODS (type), fn); + TYPE_FIELDS (type) = chainon (TYPE_FIELDS (type), fn); else { - DECL_CHAIN (fn) = TYPE_METHODS (type); - TYPE_METHODS (type) = fn; + DECL_CHAIN (fn) = TYPE_FIELDS (type); + TYPE_FIELDS (type) = fn; } + /* Propagate TYPE_FIELDS. */ + fixup_type_variants (type); + maybe_add_class_template_decl_list (type, fn, /*friend_p=*/0); if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn) || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)) diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index cd7428a4ea4..4dc19da6ade 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -6045,11 +6045,12 @@ add_using_namespace (vec<tree, va_gc> *&usings, tree target) /* Tell the debug system of a using directive. */ static void -emit_debug_info_using_namespace (tree from, tree target) +emit_debug_info_using_namespace (tree from, tree target, bool implicit) { /* Emit debugging info. */ tree context = from != global_namespace ? from : NULL_TREE; - debug_hooks->imported_module_or_decl (target, NULL_TREE, context, false); + debug_hooks->imported_module_or_decl (target, NULL_TREE, context, false, + implicit); } /* Process a namespace-scope using directive. */ @@ -6064,7 +6065,7 @@ finish_namespace_using_directive (tree target, tree attribs) add_using_namespace (DECL_NAMESPACE_USING (current_namespace), ORIGINAL_NAMESPACE (target)); emit_debug_info_using_namespace (current_namespace, - ORIGINAL_NAMESPACE (target)); + ORIGINAL_NAMESPACE (target), false); if (attribs == error_mark_node) return; @@ -6223,14 +6224,14 @@ push_namespace (tree name, bool make_inline) else if (TREE_PUBLIC (current_namespace)) TREE_PUBLIC (ns) = 1; - if (name == anon_identifier || make_inline) - emit_debug_info_using_namespace (current_namespace, ns); - if (make_inline) { DECL_NAMESPACE_INLINE_P (ns) = true; vec_safe_push (DECL_NAMESPACE_INLINEES (current_namespace), ns); } + + if (name == anon_identifier || make_inline) + emit_debug_info_using_namespace (current_namespace, ns, true); } } @@ -6358,8 +6359,8 @@ cp_emit_debug_info_for_using (tree t, tree context) if (building_stmt_list_p ()) add_stmt (build_stmt (input_location, USING_STMT, fn)); else - debug_hooks->imported_module_or_decl (fn, - NULL_TREE, context, false); + debug_hooks->imported_module_or_decl (fn, NULL_TREE, context, + false, false); } } } diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index d646ef73803..09ffbda7ca8 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -184,10 +184,10 @@ cdtor_comdat_group (tree complete, tree base) static bool can_alias_cdtor (tree fn) { -#ifndef ASM_OUTPUT_DEF /* If aliases aren't supported by the assembler, fail. */ - return false; -#endif + if (!TARGET_SUPPORTS_ALIASES) + return false; + /* We can't use an alias if there are virtual bases. */ if (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn))) return false; @@ -326,7 +326,7 @@ maybe_thunk_body (tree fn, bool force) } args = XALLOCAVEC (tree, max_parms); - /* We know that any clones immediately follow FN in TYPE_METHODS. */ + /* We know that any clones immediately follow FN in TYPE_FIELDS. */ FOR_EACH_CLONE (clone, fn) { tree clone_parm; @@ -447,7 +447,7 @@ maybe_clone_body (tree fn) if (!tree_versionable_function_p (fn)) need_alias = true; - /* We know that any clones immediately follow FN in the TYPE_METHODS + /* We know that any clones immediately follow FN in the TYPE_FIELDS list. */ push_to_top_level (); for (idx = 0; idx < 3; idx++) @@ -516,7 +516,7 @@ maybe_clone_body (tree fn) /* Emit the DWARF1 abstract instance. */ (*debug_hooks->deferred_inline_function) (fn); - /* We know that any clones immediately follow FN in the TYPE_METHODS list. */ + /* We know that any clones immediately follow FN in the TYPE_FIELDS. */ for (idx = 0; idx < 3; idx++) { tree parm; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 88d0b2b250d..b849824fcd0 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2551,9 +2551,9 @@ static void set_and_check_decl_spec_loc static bool cp_parser_friend_p (const cp_decl_specifier_seq *); static void cp_parser_required_error - (cp_parser *, required_token, bool); + (cp_parser *, required_token, bool, location_t); static cp_token *cp_parser_require - (cp_parser *, enum cpp_ttype, required_token); + (cp_parser *, enum cpp_ttype, required_token, location_t = UNKNOWN_LOCATION); static cp_token *cp_parser_require_keyword (cp_parser *, enum rid, required_token); static bool cp_parser_token_starts_function_definition_p @@ -2804,12 +2804,13 @@ cp_parser_error (cp_parser* parser, const char* gmsgid) } } + rich_location richloc (line_table, input_location); c_parse_error (gmsgid, /* Because c_parser_error does not understand CPP_KEYWORD, keywords are treated like identifiers. */ (token->type == CPP_KEYWORD ? CPP_NAME : token->type), - token->u.value, token->flags); + token->u.value, token->flags, &richloc); } } @@ -4503,6 +4504,90 @@ struct tentative_firewall } }; +/* Some tokens naturally come in pairs e.g.'(' and ')'. + This class is for tracking such a matching pair of symbols. + In particular, it tracks the location of the first token, + so that if the second token is missing, we can highlight the + location of the first token when notifying the user about the + problem. */ + +template <typename traits_t> +class token_pair +{ + public: + /* token_pair's ctor. */ + token_pair () : m_open_loc (UNKNOWN_LOCATION) {} + + /* If the next token is the opening symbol for this pair, consume it and + return true. + Otherwise, issue an error and return false. + In either case, record the location of the opening token. */ + + bool require_open (cp_parser *parser) + { + m_open_loc = cp_lexer_peek_token (parser->lexer)->location; + return cp_parser_require (parser, traits_t::open_token_type, + traits_t::required_token_open); + } + + /* Consume the next token from PARSER, recording its location as + that of the opening token within the pair. */ + + cp_token * consume_open (cp_parser *parser) + { + cp_token *tok = cp_lexer_consume_token (parser->lexer); + gcc_assert (tok->type == traits_t::open_token_type); + m_open_loc = tok->location; + return tok; + } + + /* If the next token is the closing symbol for this pair, consume it + and return it. + Otherwise, issue an error, highlighting the location of the + corresponding opening token, and return NULL. */ + + cp_token *require_close (cp_parser *parser) const + { + return cp_parser_require (parser, traits_t::close_token_type, + traits_t::required_token_close, + m_open_loc); + } + + private: + location_t m_open_loc; +}; + +/* Traits for token_pair<T> for tracking matching pairs of parentheses. */ + +struct matching_paren_traits +{ + static const enum cpp_ttype open_token_type = CPP_OPEN_PAREN; + static const enum required_token required_token_open = RT_OPEN_PAREN; + static const enum cpp_ttype close_token_type = CPP_CLOSE_PAREN; + static const enum required_token required_token_close = RT_CLOSE_PAREN; +}; + +/* "matching_parens" is a token_pair<T> class for tracking matching + pairs of parentheses. */ + +typedef token_pair<matching_paren_traits> matching_parens; + +/* Traits for token_pair<T> for tracking matching pairs of braces. */ + +struct matching_brace_traits +{ + static const enum cpp_ttype open_token_type = CPP_OPEN_BRACE; + static const enum required_token required_token_open = RT_OPEN_BRACE; + static const enum cpp_ttype close_token_type = CPP_CLOSE_BRACE; + static const enum required_token required_token_close = RT_CLOSE_BRACE; +}; + +/* "matching_braces" is a token_pair<T> class for tracking matching + pairs of braces. */ + +typedef token_pair<matching_brace_traits> matching_braces; + + /* Parse a GNU statement-expression, i.e. ({ stmts }), except for the enclosing parentheses. */ @@ -4513,7 +4598,8 @@ cp_parser_statement_expr (cp_parser *parser) /* Consume the '('. */ location_t start_loc = cp_lexer_peek_token (parser->lexer)->location; - cp_lexer_consume_token (parser->lexer); + matching_parens parens; + parens.consume_open (parser); /* Start the statement-expression. */ tree expr = begin_stmt_expr (); /* Parse the compound-statement. */ @@ -4522,7 +4608,7 @@ cp_parser_statement_expr (cp_parser *parser) expr = finish_stmt_expr (expr, false); /* Consume the ')'. */ location_t finish_loc = cp_lexer_peek_token (parser->lexer)->location; - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) cp_parser_skip_to_end_of_statement (parser); cp_parser_end_tentative_firewall (parser, start, expr); @@ -4928,7 +5014,8 @@ cp_parser_primary_expression (cp_parser *parser, location_t open_paren_loc = token->location; /* Consume the `('. */ - cp_lexer_consume_token (parser->lexer); + matching_parens parens; + parens.consume_open (parser); /* Within a parenthesized expression, a `>' token is always the greater-than operator. */ saved_greater_than_is_operator_p @@ -4976,7 +5063,7 @@ cp_parser_primary_expression (cp_parser *parser, token = cp_lexer_peek_token (parser->lexer); location_t close_paren_loc = token->location; expr.set_range (open_paren_loc, close_paren_loc); - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN) + if (!parens.require_close (parser) && !cp_parser_uncommitted_to_tentative_parse_p (parser)) cp_parser_skip_to_end_of_statement (parser); @@ -5098,7 +5185,8 @@ cp_parser_primary_expression (cp_parser *parser, `va_arg'. Consume the `__builtin_va_arg' token. */ cp_lexer_consume_token (parser->lexer); /* Look for the opening `('. */ - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); /* Now, parse the assignment-expression. */ expression = cp_parser_assignment_expression (parser); /* Look for the `,'. */ @@ -5112,7 +5200,7 @@ cp_parser_primary_expression (cp_parser *parser, /* Look for the closing `)'. */ location_t finish_loc = cp_lexer_peek_token (parser->lexer)->location; - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); /* Using `va_arg' in a constant-expression is not allowed. */ if (cp_parser_non_integral_constant_expression (parser, @@ -6345,9 +6433,6 @@ cp_parser_qualifying_entity (cp_parser *parser, static bool cp_parser_compound_literal_p (cp_parser *parser) { - /* Consume the `('. */ - cp_lexer_consume_token (parser->lexer); - cp_lexer_save_tokens (parser->lexer); /* Skip tokens until the next token is a closing parenthesis. @@ -6465,7 +6550,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, parser->greater_than_is_operator_p = true; /* And the expression which is being cast. */ - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); expression = cp_parser_expression (parser, & idk, /*cast_p=*/true); cp_token *close_paren = cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); @@ -6526,7 +6612,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, /* Consume the `typeid' token. */ cp_lexer_consume_token (parser->lexer); /* Look for the `(' token. */ - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); /* Types cannot be defined in a `typeid' expression. */ saved_message = parser->type_definition_forbidden_message; parser->type_definition_forbidden_message @@ -6542,8 +6629,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, /* Look for the `)' token. Otherwise, we can't be sure that we're not looking at an expression: consider `typeid (int (3))', for example. */ - cp_token *close_paren = cp_parser_require (parser, CPP_CLOSE_PAREN, - RT_CLOSE_PAREN); + cp_token *close_paren = parens.require_close (parser); /* If all went well, simply lookup the type-id. */ if (cp_parser_parse_definitely (parser)) postfix_expression = get_typeid (type, tf_warning_or_error); @@ -6557,8 +6643,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, /* Compute its typeid. */ postfix_expression = build_typeid (expression, tf_warning_or_error); /* Look for the `)' token. */ - close_paren - = cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + close_paren = parens.require_close (parser); } /* Restore the saved message. */ parser->type_definition_forbidden_message = saved_message; @@ -6759,6 +6844,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, cp_parser_parse_tentatively (parser); + matching_parens parens; + parens.consume_open (parser); + /* Avoid calling cp_parser_type_id pointlessly, see comment in cp_parser_cast_expression about c++/29234. */ if (!cp_parser_compound_literal_p (parser)) @@ -6770,8 +6858,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, parser->in_type_id_in_expr_p = true; type = cp_parser_type_id (parser); parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; - /* Look for the `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); } /* If things aren't going well, there's no need to @@ -7561,7 +7648,8 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, if (non_constant_p) *non_constant_p = false; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return NULL; expression_list = make_tree_vector (); @@ -7657,7 +7745,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, if (close_paren_loc) *close_paren_loc = cp_lexer_peek_token (parser->lexer)->location; - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) { int ending; @@ -7957,7 +8045,8 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk, bool saved_greater_than_is_operator_p; cp_lexer_consume_token (parser->lexer); - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); saved_message = parser->type_definition_forbidden_message; parser->type_definition_forbidden_message @@ -7991,7 +8080,7 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk, parser->type_definition_forbidden_message = saved_message; - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); return finish_noexcept_expr (expr, tf_warning_or_error); } @@ -8235,7 +8324,8 @@ cp_parser_new_expression (cp_parser* parser) const char *saved_message = parser->type_definition_forbidden_message; /* Consume the `('. */ - cp_lexer_consume_token (parser->lexer); + matching_parens parens; + parens.consume_open (parser); /* Parse the type-id. */ parser->type_definition_forbidden_message @@ -8247,7 +8337,7 @@ cp_parser_new_expression (cp_parser* parser) parser->type_definition_forbidden_message = saved_message; /* Look for the closing `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); token = cp_lexer_peek_token (parser->lexer); /* There should not be a direct-new-declarator in this production, but GCC used to allowed this, so we check and emit a sensible error @@ -8787,7 +8877,8 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, parser->type_definition_forbidden_message = G_("types may not be defined in casts"); /* Consume the `('. */ - cp_token *open_paren = cp_lexer_consume_token (parser->lexer); + matching_parens parens; + cp_token *open_paren = parens.consume_open (parser); location_t open_paren_loc = open_paren->location; location_t close_paren_loc = UNKNOWN_LOCATION; @@ -8852,8 +8943,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, /* Look for the type-id. */ type = cp_parser_type_id (parser); /* Look for the closing `)'. */ - cp_token *close_paren - = cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + cp_token *close_paren = parens.require_close (parser); if (close_paren) close_paren_loc = close_paren->location; parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; @@ -9638,7 +9728,8 @@ cp_parser_builtin_offsetof (cp_parser *parser) /* Consume the "__builtin_offsetof" token. */ cp_lexer_consume_token (parser->lexer); /* Consume the opening `('. */ - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); /* Parse the type-id. */ location_t loc = cp_lexer_peek_token (parser->lexer)->location; type = cp_parser_type_id (parser); @@ -9688,7 +9779,7 @@ cp_parser_builtin_offsetof (cp_parser *parser) default: /* Error. We know the following require will fail, but that gives the proper error message. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); cp_parser_skip_to_closing_parenthesis (parser, true, false, true); expr = error_mark_node; goto failure; @@ -9834,7 +9925,8 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword) /* Consume the token. */ cp_lexer_consume_token (parser->lexer); - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); { type_id_in_expr_sentinel s (parser); @@ -9873,7 +9965,7 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword) } } - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); /* Complete the trait expression, which may mean either processing the trait expr now or saving it for template instantiation. */ @@ -10354,7 +10446,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) opening parenthesis if present. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) { - cp_lexer_consume_token (parser->lexer); + matching_parens parens; + parens.consume_open (parser); begin_scope (sk_function_parms, /*entity=*/NULL_TREE); @@ -10369,7 +10462,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) pedwarn (DECL_SOURCE_LOCATION (TREE_VALUE (t)), OPT_Wpedantic, "default argument specified for lambda parameter"); - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); attributes = cp_parser_attributes_opt (parser); @@ -10526,7 +10619,8 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr) start_lambda_scope (fco); body = begin_function_body (); - if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE)) + matching_braces braces; + if (!braces.require_open (parser)) goto out; /* Push the proxies for any explicit captures. */ @@ -10567,7 +10661,7 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr) expr = cp_parser_expression (parser, &idk); cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); - cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); + braces.require_close (parser); if (cp_parser_parse_definitely (parser)) { @@ -10591,7 +10685,7 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr) while (cp_lexer_next_token_is_keyword (parser->lexer, RID_LABEL)) cp_parser_label_declaration (parser); cp_parser_statement_seq_opt (parser, NULL_TREE); - cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); + braces.require_close (parser); } finish_compound_stmt (compound_stmt); @@ -11127,9 +11221,10 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr, int bcs_flags, bool function_body) { tree compound_stmt; + matching_braces braces; /* Consume the `{'. */ - if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE)) + if (!braces.require_open (parser)) return error_mark_node; if (DECL_DECLARED_CONSTEXPR_P (current_function_decl) && !function_body && cxx_dialect < cxx14) @@ -11145,7 +11240,7 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr, /* Finish the compound-statement. */ finish_compound_stmt (compound_stmt); /* Consume the `}'. */ - cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); + braces.require_close (parser); return compound_stmt; } @@ -11266,7 +11361,8 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p, } /* Look for the `('. */ - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) { cp_parser_skip_to_end_of_statement (parser); return error_mark_node; @@ -11295,7 +11391,7 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p, /* Parse the condition. */ condition = cp_parser_condition (parser); /* Look for the `)'. */ - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, true, false, /*consume_paren=*/true); @@ -11925,7 +12021,7 @@ cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end) *end = build_binary_op (input_location, PLUS_EXPR, range, array_type_nelts_top (TREE_TYPE (range)), - 0); + false); return TREE_TYPE (*begin); } else @@ -12082,12 +12178,13 @@ cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep) /* Begin the while-statement. */ statement = begin_while_stmt (); /* Look for the `('. */ - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); /* Parse the condition. */ condition = cp_parser_condition (parser); finish_while_stmt_cond (condition, statement, ivdep); /* Look for the `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); /* Parse the dependent statement. */ parser->in_statement = IN_ITERATION_STMT; cp_parser_already_scoped_statement (parser, if_p, guard_tinfo); @@ -12111,13 +12208,14 @@ cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep) /* Look for the `while' keyword. */ cp_parser_require_keyword (parser, RID_WHILE, RT_WHILE); /* Look for the `('. */ - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); /* Parse the expression. */ expression = cp_parser_expression (parser); /* We're done with the do-statement. */ finish_do_stmt (expression, statement, ivdep); /* Look for the `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); /* Look for the `;'. */ cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); } @@ -12126,12 +12224,13 @@ cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep) case RID_FOR: { /* Look for the `('. */ - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); statement = cp_parser_for (parser, ivdep); /* Look for the `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); /* Parse the body of the for-statement. */ parser->in_statement = IN_ITERATION_STMT; @@ -12481,13 +12580,14 @@ cp_parser_already_scoped_statement (cp_parser* parser, bool *if_p, { /* Avoid calling cp_parser_compound_statement, so that we don't create a new scope. Do everything else by hand. */ - cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE); + matching_braces braces; + braces.require_open (parser); /* If the next keyword is `__label__' we have a label declaration. */ while (cp_lexer_next_token_is_keyword (parser->lexer, RID_LABEL)) cp_parser_label_declaration (parser); /* Parse an (optional) statement-seq. */ cp_parser_statement_seq_opt (parser, NULL_TREE); - cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); + braces.require_close (parser); } } @@ -13714,11 +13814,12 @@ cp_parser_linkage_specification (cp_parser* parser) cp_ensure_no_oacc_routine (parser); /* Consume the `{' token. */ - cp_lexer_consume_token (parser->lexer); + matching_braces braces; + braces.consume_open (parser)->location; /* Parse the declarations. */ cp_parser_declaration_seq_opt (parser); /* Look for the closing `}'. */ - cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); + braces.require_close (parser); } /* Otherwise, there's just one declaration. */ else @@ -13770,7 +13871,8 @@ cp_parser_static_assert(cp_parser *parser, bool member_p) cp_parser_commit_to_tentative_parse (parser); /* Parse the `(' starting the static assertion condition. */ - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); /* Parse the constant-expression. Allow a non-constant expression here in order to give better diagnostics in finish_static_assert. */ @@ -13802,7 +13904,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p) /*wide_ok=*/true); /* A `)' completes the static assertion. */ - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, @@ -13956,7 +14058,8 @@ cp_parser_decltype (cp_parser *parser) return error_mark_node; /* Parse the opening `('. */ - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return error_mark_node; /* decltype (auto) */ @@ -13964,7 +14067,7 @@ cp_parser_decltype (cp_parser *parser) && cp_lexer_next_token_is_keyword (parser->lexer, RID_AUTO)) { cp_lexer_consume_token (parser->lexer); - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) return error_mark_node; expr = make_decltype_auto (); AUTO_IS_DECLTYPE (expr) = true; @@ -14019,7 +14122,7 @@ cp_parser_decltype (cp_parser *parser) = saved_non_integral_constant_expression_p; /* Parse to the closing `)'. */ - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) { cp_parser_skip_to_closing_parenthesis (parser, true, false, /*consume_paren=*/true); @@ -14718,11 +14821,14 @@ cp_parser_operator (cp_parser* parser) break; case CPP_OPEN_PAREN: - /* Consume the `('. */ - cp_lexer_consume_token (parser->lexer); - /* Look for the matching `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); - return cp_operator_id (CALL_EXPR); + { + /* Consume the `('. */ + matching_parens parens; + parens.consume_open (parser); + /* Look for the matching `)'. */ + parens.require_close (parser); + return cp_operator_id (CALL_EXPR); + } case CPP_OPEN_SQUARE: /* Consume the `['. */ @@ -18095,7 +18201,8 @@ cp_parser_enum_specifier (cp_parser* parser) begin_scope (sk_scoped_enum, type); /* Consume the opening brace. */ - cp_lexer_consume_token (parser->lexer); + matching_braces braces; + braces.consume_open (parser); if (type == error_mark_node) ; /* Nothing to add */ @@ -18128,7 +18235,7 @@ cp_parser_enum_specifier (cp_parser* parser) cp_parser_enumerator_list (parser, type); /* Consume the final '}'. */ - cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); + braces.require_close (parser); if (scoped_enum_p) finish_scope (); @@ -18421,13 +18528,14 @@ cp_parser_namespace_definition (cp_parser* parser) warning (OPT_Wnamespaces, "namespace %qD entered", current_namespace); /* Look for the `{' to validate starting the namespace. */ - if (cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE)) + matching_braces braces; + if (braces.require_open (parser)) { /* Parse the body of the namespace. */ cp_parser_namespace_body (parser); /* Look for the final `}'. */ - cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); + braces.require_close (parser); } if (has_visibility) @@ -19808,7 +19916,8 @@ cp_parser_direct_declarator (cp_parser* parser, cp_parser_parse_tentatively (parser); /* Consume the `('. */ - cp_lexer_consume_token (parser->lexer); + matching_parens parens; + parens.consume_open (parser); if (first) { /* If this is going to be an abstract declarator, we're @@ -19823,7 +19932,7 @@ cp_parser_direct_declarator (cp_parser* parser, params = cp_parser_parameter_declaration_clause (parser); /* Consume the `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); /* If all went well, parse the cv-qualifier-seq, ref-qualifier and the exception-specification. */ @@ -19919,7 +20028,8 @@ cp_parser_direct_declarator (cp_parser* parser, parser->in_declarator_p = saved_in_declarator_p; /* Consume the `('. */ - cp_lexer_consume_token (parser->lexer); + matching_parens parens; + parens.consume_open (parser); /* Parse the nested declarator. */ saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; parser->in_type_id_in_expr_p = true; @@ -19930,7 +20040,7 @@ cp_parser_direct_declarator (cp_parser* parser, parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; first = false; /* Expect a `)'. */ - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) declarator = cp_error_declarator; if (declarator == cp_error_declarator) break; @@ -21778,7 +21888,8 @@ cp_parser_braced_list (cp_parser* parser, bool* non_constant_p) location_t start_loc = cp_lexer_peek_token (parser->lexer)->location; /* Consume the `{' token. */ - cp_lexer_consume_token (parser->lexer); + matching_braces braces; + braces.consume_open (parser); /* Create a CONSTRUCTOR to represent the braced-initializer. */ initializer = make_node (CONSTRUCTOR); /* If it's not a `}', then there is a non-trivial initializer. */ @@ -21795,7 +21906,7 @@ cp_parser_braced_list (cp_parser* parser, bool* non_constant_p) *non_constant_p = false; /* Now, there should be a trailing `}'. */ location_t finish_loc = cp_lexer_peek_token (parser->lexer)->location; - cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); + braces.require_close (parser); TREE_TYPE (initializer) = init_list_type_node; cp_expr result (initializer); @@ -22222,7 +22333,8 @@ cp_parser_class_specifier_1 (cp_parser* parser) } /* Look for the `{'. */ - if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE)) + matching_braces braces; + if (!braces.require_open (parser)) { pop_deferring_access_checks (); return error_mark_node; @@ -22274,7 +22386,7 @@ cp_parser_class_specifier_1 (cp_parser* parser) cp_parser_member_specification_opt (parser); /* Look for the trailing `}'. */ - closing_brace = cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); + closing_brace = braces.require_close (parser); /* Look for trailing attributes to apply to this class. */ if (cp_parser_allow_gnu_extensions_p (parser)) attributes = cp_parser_gnu_attributes_opt (parser); @@ -23753,11 +23865,12 @@ cp_parser_constant_initializer (cp_parser* parser) cp_parser_error (parser, "a brace-enclosed initializer is not allowed here"); /* Consume the opening brace. */ - cp_lexer_consume_token (parser->lexer); + matching_braces braces; + braces.consume_open (parser); /* Skip the initializer. */ cp_parser_skip_to_closing_brace (parser); /* Look for the trailing `}'. */ - cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); + braces.require_close (parser); return error_mark_node; } @@ -24013,7 +24126,8 @@ cp_parser_noexcept_specification_opt (cp_parser* parser, if (cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN) { - cp_lexer_consume_token (parser->lexer); + matching_parens parens; + parens.consume_open (parser); if (require_constexpr) { @@ -24033,7 +24147,7 @@ cp_parser_noexcept_specification_opt (cp_parser* parser, *consumed_expr = true; } - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); } else { @@ -24087,7 +24201,8 @@ cp_parser_exception_specification_opt (cp_parser* parser) cp_lexer_consume_token (parser->lexer); /* Look for the `('. */ - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); @@ -24123,7 +24238,7 @@ cp_parser_exception_specification_opt (cp_parser* parser) type_id_list = empty_except_spec; /* Look for the `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); return type_id_list; } @@ -24270,10 +24385,11 @@ cp_parser_handler (cp_parser* parser) cp_parser_require_keyword (parser, RID_CATCH, RT_CATCH); handler = begin_handler (); - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); declaration = cp_parser_exception_declaration (parser); finish_handler_parms (declaration, handler); - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); cp_parser_compound_statement (parser, NULL, BCS_NORMAL, false); finish_handler (handler); } @@ -24389,13 +24505,14 @@ cp_parser_asm_specification_opt (cp_parser* parser) /* Consume the `asm' token. */ cp_lexer_consume_token (parser->lexer); /* Look for the `('. */ - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); /* Look for the string-literal. */ asm_specification = cp_parser_string_literal (parser, false, false); /* Look for the `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); return asm_specification; } @@ -24447,11 +24564,12 @@ cp_parser_asm_operand_list (cp_parser* parser) string_literal = cp_parser_string_literal (parser, false, false); /* Look for the `('. */ - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); /* Parse the expression. */ expression = cp_parser_expression (parser); /* Look for the `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); if (name == error_mark_node || string_literal == error_mark_node @@ -24705,8 +24823,10 @@ cp_parser_gnu_attributes_opt (cp_parser* parser) /* Consume the `__attribute__' keyword. */ cp_lexer_consume_token (parser->lexer); /* Look for the two `(' tokens. */ - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens outer_parens; + outer_parens.require_open (parser); + matching_parens inner_parens; + inner_parens.require_open (parser); /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); @@ -24719,9 +24839,9 @@ cp_parser_gnu_attributes_opt (cp_parser* parser) attribute_list = NULL; /* Look for the two `)' tokens. */ - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!inner_parens.require_close (parser)) ok = false; - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!outer_parens.require_close (parser)) ok = false; if (!ok) cp_parser_skip_to_end_of_statement (parser); @@ -24782,7 +24902,8 @@ cp_parser_gnu_attribute_list (cp_parser* parser) parsed identifier. */ ? ridpointers[(int) token->keyword] : id_token->u.value; - + + identifier = canonicalize_attr_name (identifier); attribute = build_tree_list (identifier, NULL_TREE); /* Peek at the next token. */ @@ -24928,6 +25049,8 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns) "expected an identifier for the attribute name"); return error_mark_node; } + + attr_id = canonicalize_attr_name (attr_id); attribute = build_tree_list (build_tree_list (attr_ns, attr_id), NULL_TREE); token = cp_lexer_peek_token (parser->lexer); @@ -24937,6 +25060,7 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns) NULL_TREE); else { + attr_id = canonicalize_attr_name (attr_id); attribute = build_tree_list (build_tree_list (NULL_TREE, attr_id), NULL_TREE); /* C++11 noreturn attribute is equivalent to GNU's. */ @@ -25144,7 +25268,8 @@ cp_parser_std_attribute_spec (cp_parser *parser) cp_lexer_consume_token (parser->lexer); maybe_warn_cpp0x (CPP0X_ATTRIBUTES); - if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN) == NULL) + matching_parens parens; + if (!parens.require_open (parser)) { cp_parser_error (parser, "expected %<(%>"); return error_mark_node; @@ -25177,7 +25302,7 @@ cp_parser_std_attribute_spec (cp_parser *parser) if (alignas_expr == error_mark_node) return error_mark_node; - if (cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN) == NULL) + if (!parens.require_close (parser)) { cp_parser_error (parser, "expected %<)%>"); return error_mark_node; @@ -25409,12 +25534,13 @@ cp_parser_requires_expression (cp_parser *parser) static tree cp_parser_requirement_parameter_list (cp_parser *parser) { - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return error_mark_node; tree parms = cp_parser_parameter_declaration_clause (parser); - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) return error_mark_node; return parms; @@ -25427,12 +25553,13 @@ cp_parser_requirement_parameter_list (cp_parser *parser) static tree cp_parser_requirement_body (cp_parser *parser) { - if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE)) + matching_braces braces; + if (!braces.require_open (parser)) return error_mark_node; tree reqs = cp_parser_requirement_list (parser); - if (!cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE)) + if (!braces.require_close (parser)) return error_mark_node; return reqs; @@ -25571,14 +25698,15 @@ static tree cp_parser_compound_requirement (cp_parser *parser) { /* Parse an expression enclosed in '{ }'s. */ - if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE)) + matching_braces braces; + if (!braces.require_open (parser)) return error_mark_node; tree expr = cp_parser_expression (parser, NULL, false, false); if (!expr || expr == error_mark_node) return error_mark_node; - if (!cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE)) + if (!braces.require_close (parser)) return error_mark_node; /* Parse the optional noexcept. */ @@ -26649,7 +26777,8 @@ cp_parser_template_introduction (cp_parser* parser, bool member_p) cp_parser_simulate_error (parser); /* Look for opening brace for introduction. */ - cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE); + matching_braces braces; + braces.require_open (parser); if (!cp_parser_parse_definitely (parser)) return false; @@ -26669,7 +26798,7 @@ cp_parser_template_introduction (cp_parser* parser, bool member_p) } /* Look for closing brace for introduction. */ - if (!cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE)) + if (!braces.require_close (parser)) return true; if (tmpl_decl == error_mark_node) @@ -27427,7 +27556,7 @@ cp_parser_late_parse_one_default_arg (cp_parser *parser, tree decl, else if (maybe_reject_flexarray_init (decl, parsed_arg)) parsed_arg = error_mark_node; else - parsed_arg = digest_nsdmi_init (decl, parsed_arg); + parsed_arg = digest_nsdmi_init (decl, parsed_arg, tf_warning_or_error); } /* If the token stream has not been completely used up, then @@ -27554,9 +27683,10 @@ cp_parser_sizeof_pack (cp_parser *parser) cp_lexer_consume_token (parser->lexer); maybe_warn_variadic_templates (); + matching_parens parens; bool paren = cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN); if (paren) - cp_lexer_consume_token (parser->lexer); + parens.consume_open (parser); else permerror (cp_lexer_peek_token (parser->lexer)->location, "%<sizeof...%> argument must be surrounded by parentheses"); @@ -27581,7 +27711,7 @@ cp_parser_sizeof_pack (cp_parser *parser) PACK_EXPANSION_SIZEOF_P (expr) = true; if (paren) - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); return expr; } @@ -27635,6 +27765,10 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword) /* We can't be sure yet whether we're looking at a type-id or an expression. */ cp_parser_parse_tentatively (parser); + + matching_parens parens; + parens.consume_open (parser); + /* Note: as a GNU Extension, compound literals are considered postfix-expressions as they are in C99, so they are valid arguments to sizeof. See comment in cp_parser_cast_expression @@ -27648,7 +27782,7 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword) /* Look for the type-id. */ type = cp_parser_type_id (parser); /* Look for the closing `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; } @@ -27930,187 +28064,245 @@ cp_parser_friend_p (const cp_decl_specifier_seq *decl_specifiers) return decl_spec_seq_has_spec_p (decl_specifiers, ds_friend); } +/* Get a description of the matching symbol to TOKEN_DESC e.g. "(" for + RT_CLOSE_PAREN. */ + +static const char * +get_matching_symbol (required_token token_desc) +{ + switch (token_desc) + { + default: + gcc_unreachable (); + return ""; + case RT_CLOSE_BRACE: + return "{"; + case RT_CLOSE_PAREN: + return "("; + } +} + /* Issue an error message indicating that TOKEN_DESC was expected. If KEYWORD is true, it indicated this function is called by cp_parser_require_keword and the required token can only be - a indicated keyword. */ + a indicated keyword. + + If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it + within any error as the location of an "opening" token matching + the close token TYPE (e.g. the location of the '(' when TOKEN_DESC is + RT_CLOSE_PAREN). */ static void cp_parser_required_error (cp_parser *parser, required_token token_desc, - bool keyword) + bool keyword, + location_t matching_location) { + if (cp_parser_simulate_error (parser)) + return; + + const char *gmsgid = NULL; switch (token_desc) { case RT_NEW: - cp_parser_error (parser, "expected %<new%>"); - return; + gmsgid = G_("expected %<new%>"); + break; case RT_DELETE: - cp_parser_error (parser, "expected %<delete%>"); - return; + gmsgid = G_("expected %<delete%>"); + break; case RT_RETURN: - cp_parser_error (parser, "expected %<return%>"); - return; + gmsgid = G_("expected %<return%>"); + break; case RT_WHILE: - cp_parser_error (parser, "expected %<while%>"); - return; + gmsgid = G_("expected %<while%>"); + break; case RT_EXTERN: - cp_parser_error (parser, "expected %<extern%>"); - return; + gmsgid = G_("expected %<extern%>"); + break; case RT_STATIC_ASSERT: - cp_parser_error (parser, "expected %<static_assert%>"); - return; + gmsgid = G_("expected %<static_assert%>"); + break; case RT_DECLTYPE: - cp_parser_error (parser, "expected %<decltype%>"); - return; + gmsgid = G_("expected %<decltype%>"); + break; case RT_OPERATOR: - cp_parser_error (parser, "expected %<operator%>"); - return; + gmsgid = G_("expected %<operator%>"); + break; case RT_CLASS: - cp_parser_error (parser, "expected %<class%>"); - return; + gmsgid = G_("expected %<class%>"); + break; case RT_TEMPLATE: - cp_parser_error (parser, "expected %<template%>"); - return; + gmsgid = G_("expected %<template%>"); + break; case RT_NAMESPACE: - cp_parser_error (parser, "expected %<namespace%>"); - return; + gmsgid = G_("expected %<namespace%>"); + break; case RT_USING: - cp_parser_error (parser, "expected %<using%>"); - return; + gmsgid = G_("expected %<using%>"); + break; case RT_ASM: - cp_parser_error (parser, "expected %<asm%>"); - return; + gmsgid = G_("expected %<asm%>"); + break; case RT_TRY: - cp_parser_error (parser, "expected %<try%>"); - return; + gmsgid = G_("expected %<try%>"); + break; case RT_CATCH: - cp_parser_error (parser, "expected %<catch%>"); - return; + gmsgid = G_("expected %<catch%>"); + break; case RT_THROW: - cp_parser_error (parser, "expected %<throw%>"); - return; + gmsgid = G_("expected %<throw%>"); + break; case RT_LABEL: - cp_parser_error (parser, "expected %<__label__%>"); - return; + gmsgid = G_("expected %<__label__%>"); + break; case RT_AT_TRY: - cp_parser_error (parser, "expected %<@try%>"); - return; + gmsgid = G_("expected %<@try%>"); + break; case RT_AT_SYNCHRONIZED: - cp_parser_error (parser, "expected %<@synchronized%>"); - return; + gmsgid = G_("expected %<@synchronized%>"); + break; case RT_AT_THROW: - cp_parser_error (parser, "expected %<@throw%>"); - return; + gmsgid = G_("expected %<@throw%>"); + break; case RT_TRANSACTION_ATOMIC: - cp_parser_error (parser, "expected %<__transaction_atomic%>"); - return; + gmsgid = G_("expected %<__transaction_atomic%>"); + break; case RT_TRANSACTION_RELAXED: - cp_parser_error (parser, "expected %<__transaction_relaxed%>"); - return; + gmsgid = G_("expected %<__transaction_relaxed%>"); + break; default: break; } - if (!keyword) + + if (!gmsgid && !keyword) { switch (token_desc) { case RT_SEMICOLON: - cp_parser_error (parser, "expected %<;%>"); - return; + gmsgid = G_("expected %<;%>"); + break; case RT_OPEN_PAREN: - cp_parser_error (parser, "expected %<(%>"); - return; + gmsgid = G_("expected %<(%>"); + break; case RT_CLOSE_BRACE: - cp_parser_error (parser, "expected %<}%>"); - return; + gmsgid = G_("expected %<}%>"); + break; case RT_OPEN_BRACE: - cp_parser_error (parser, "expected %<{%>"); - return; + gmsgid = G_("expected %<{%>"); + break; case RT_CLOSE_SQUARE: - cp_parser_error (parser, "expected %<]%>"); - return; + gmsgid = G_("expected %<]%>"); + break; case RT_OPEN_SQUARE: - cp_parser_error (parser, "expected %<[%>"); - return; + gmsgid = G_("expected %<[%>"); + break; case RT_COMMA: - cp_parser_error (parser, "expected %<,%>"); - return; + gmsgid = G_("expected %<,%>"); + break; case RT_SCOPE: - cp_parser_error (parser, "expected %<::%>"); - return; + gmsgid = G_("expected %<::%>"); + break; case RT_LESS: - cp_parser_error (parser, "expected %<<%>"); - return; + gmsgid = G_("expected %<<%>"); + break; case RT_GREATER: - cp_parser_error (parser, "expected %<>%>"); - return; + gmsgid = G_("expected %<>%>"); + break; case RT_EQ: - cp_parser_error (parser, "expected %<=%>"); - return; + gmsgid = G_("expected %<=%>"); + break; case RT_ELLIPSIS: - cp_parser_error (parser, "expected %<...%>"); - return; + gmsgid = G_("expected %<...%>"); + break; case RT_MULT: - cp_parser_error (parser, "expected %<*%>"); - return; + gmsgid = G_("expected %<*%>"); + break; case RT_COMPL: - cp_parser_error (parser, "expected %<~%>"); - return; + gmsgid = G_("expected %<~%>"); + break; case RT_COLON: - cp_parser_error (parser, "expected %<:%>"); - return; + gmsgid = G_("expected %<:%>"); + break; case RT_COLON_SCOPE: - cp_parser_error (parser, "expected %<:%> or %<::%>"); - return; + gmsgid = G_("expected %<:%> or %<::%>"); + break; case RT_CLOSE_PAREN: - cp_parser_error (parser, "expected %<)%>"); - return; + gmsgid = G_("expected %<)%>"); + break; case RT_COMMA_CLOSE_PAREN: - cp_parser_error (parser, "expected %<,%> or %<)%>"); - return; + gmsgid = G_("expected %<,%> or %<)%>"); + break; case RT_PRAGMA_EOL: - cp_parser_error (parser, "expected end of line"); - return; + gmsgid = G_("expected end of line"); + break; case RT_NAME: - cp_parser_error (parser, "expected identifier"); - return; + gmsgid = G_("expected identifier"); + break; case RT_SELECT: - cp_parser_error (parser, "expected selection-statement"); - return; + gmsgid = G_("expected selection-statement"); + break; case RT_ITERATION: - cp_parser_error (parser, "expected iteration-statement"); - return; + gmsgid = G_("expected iteration-statement"); + break; case RT_JUMP: - cp_parser_error (parser, "expected jump-statement"); - return; + gmsgid = G_("expected jump-statement"); + break; case RT_CLASS_KEY: - cp_parser_error (parser, "expected class-key"); - return; + gmsgid = G_("expected class-key"); + break; case RT_CLASS_TYPENAME_TEMPLATE: - cp_parser_error (parser, - "expected %<class%>, %<typename%>, or %<template%>"); - return; + gmsgid = G_("expected %<class%>, %<typename%>, or %<template%>"); + break; default: gcc_unreachable (); } } - else - gcc_unreachable (); -} + if (gmsgid) + { + /* Emulate rest of cp_parser_error. */ + cp_token *token = cp_lexer_peek_token (parser->lexer); + cp_lexer_set_source_position_from_token (token); + + gcc_rich_location richloc (input_location); + + /* If matching_location != UNKNOWN_LOCATION, highlight it. + Attempt to consolidate diagnostics by printing it as a + secondary range within the main diagnostic. */ + bool added_matching_location = false; + if (matching_location != UNKNOWN_LOCATION) + added_matching_location + = richloc.add_location_if_nearby (matching_location); + + c_parse_error (gmsgid, + (token->type == CPP_KEYWORD ? CPP_NAME : token->type), + token->u.value, token->flags, &richloc); + + /* If we weren't able to consolidate matching_location, then + print it as a secondary diagnostic. */ + if (matching_location != UNKNOWN_LOCATION && !added_matching_location) + inform (matching_location, "to match this %qs", + get_matching_symbol (token_desc)); + } +} /* If the next token is of the indicated TYPE, consume it. Otherwise, issue an error message indicating that TOKEN_DESC was expected. Returns the token consumed, if the token had the appropriate type. - Otherwise, returns NULL. */ + Otherwise, returns NULL. + + If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it + within any error as the location of an "opening" token matching + the close token TYPE (e.g. the location of the '(' when TOKEN_DESC is + RT_CLOSE_PAREN). */ static cp_token * cp_parser_require (cp_parser* parser, enum cpp_ttype type, - required_token token_desc) + required_token token_desc, + location_t matching_location) { if (cp_lexer_next_token_is (parser->lexer, type)) return cp_lexer_consume_token (parser->lexer); @@ -28118,7 +28310,8 @@ cp_parser_require (cp_parser* parser, { /* Output the MESSAGE -- unless we're parsing tentatively. */ if (!cp_parser_simulate_error (parser)) - cp_parser_required_error (parser, token_desc, /*keyword=*/false); + cp_parser_required_error (parser, token_desc, /*keyword=*/false, + matching_location); return NULL; } } @@ -28220,7 +28413,8 @@ cp_parser_require_keyword (cp_parser* parser, if (token && token->keyword != keyword) { - cp_parser_required_error (parser, token_desc, /*keyword=*/true); + cp_parser_required_error (parser, token_desc, /*keyword=*/true, + UNKNOWN_LOCATION); return NULL; } @@ -28677,6 +28871,17 @@ cp_parser_cache_defarg (cp_parser *parser, bool nsdmi) return default_argument; } +/* A location to use for diagnostics about an unparsed DEFAULT_ARG. */ + +location_t +defarg_location (tree default_argument) +{ + cp_token_cache *tokens = DEFARG_TOKENS (default_argument); + location_t start = tokens->first->location; + location_t end = tokens->last->location; + return make_location (start, start, end); +} + /* Begin parsing tentatively. We always save tokens while parsing tentatively so that if the tentative parsing fails we can restore the tokens. */ @@ -29031,10 +29236,11 @@ cp_parser_objc_encode_expression (cp_parser* parser) location_t start_loc = cp_lexer_peek_token (parser->lexer)->location; cp_lexer_consume_token (parser->lexer); /* Eat '@encode'. */ - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); token = cp_lexer_peek_token (parser->lexer); type = complete_type (cp_parser_type_id (parser)); - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); if (!type) { @@ -29076,9 +29282,10 @@ cp_parser_objc_defs_expression (cp_parser *parser) tree name; cp_lexer_consume_token (parser->lexer); /* Eat '@defs'. */ - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); name = cp_parser_identifier (parser); - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); return objc_get_class_ivars (name); } @@ -29097,9 +29304,10 @@ cp_parser_objc_protocol_expression (cp_parser* parser) location_t start_loc = cp_lexer_peek_token (parser->lexer)->location; cp_lexer_consume_token (parser->lexer); /* Eat '@protocol'. */ - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); proto = cp_parser_identifier (parser); - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); /* Build a location of the form: @protocol(prot) @@ -29137,7 +29345,8 @@ cp_parser_objc_selector_expression (cp_parser* parser) location_t loc = cp_lexer_peek_token (parser->lexer)->location; cp_lexer_consume_token (parser->lexer); /* Eat '@selector'. */ - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); token = cp_lexer_peek_token (parser->lexer); while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON @@ -29184,7 +29393,7 @@ cp_parser_objc_selector_expression (cp_parser* parser) } finish_selector: - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); /* Build a location of the form: @@ -29391,7 +29600,8 @@ cp_parser_objc_typename (cp_parser* parser) { tree proto_quals, cp_type = NULL_TREE; - cp_lexer_consume_token (parser->lexer); /* Eat '('. */ + matching_parens parens; + parens.consume_open (parser); /* Eat '('. */ proto_quals = cp_parser_objc_protocol_qualifiers (parser); /* An ObjC type name may consist of just protocol qualifiers, in which @@ -29417,7 +29627,7 @@ cp_parser_objc_typename (cp_parser* parser) } } - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); type_name = build_tree_list (proto_quals, cp_type); } @@ -30031,7 +30241,8 @@ cp_parser_objc_superclass_or_category (cp_parser *parser, } else if (next->type == CPP_OPEN_PAREN) { - cp_lexer_consume_token (parser->lexer); /* Eat '('. */ + matching_parens parens; + parens.consume_open (parser); /* Eat '('. */ /* If there is no category name, and this is an @interface, we have a class extension. */ @@ -30043,7 +30254,7 @@ cp_parser_objc_superclass_or_category (cp_parser *parser, else *categ = cp_parser_identifier (parser); - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); } } @@ -30231,9 +30442,10 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) cp_parameter_declarator *parm; tree parameter_declaration = error_mark_node; bool seen_open_paren = false; + matching_parens parens; cp_lexer_consume_token (parser->lexer); - if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + if (parens.require_open (parser)) seen_open_paren = true; if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)) { @@ -30259,7 +30471,7 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) /*attrlist=*/NULL); } if (seen_open_paren) - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); else { /* If there was no open parenthesis, we are recovering from @@ -30313,9 +30525,10 @@ cp_parser_objc_synchronized_statement (cp_parser *parser) location = cp_lexer_peek_token (parser->lexer)->location; objc_maybe_warn_exceptions (location); - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); lock = cp_parser_expression (parser); - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); /* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST node, lest it get absorbed into the surrounding block. */ @@ -30556,7 +30769,8 @@ cp_parser_objc_at_property_declaration (cp_parser *parser) if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) { /* Eat the '('. */ - cp_lexer_consume_token (parser->lexer); + matching_parens parens; + parens.consume_open (parser); while (true) { @@ -30644,7 +30858,7 @@ cp_parser_objc_at_property_declaration (cp_parser *parser) "error: expected ‘)’ before ‘,’ token". This is because cp_parser_require, unlike the C counterpart, will produce an error even if we are in error recovery. */ - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) { cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, @@ -31335,13 +31549,14 @@ cp_parser_oacc_single_int_clause (cp_parser *parser, omp_clause_code code, { location_t loc = cp_lexer_peek_token (parser->lexer)->location; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; tree t = cp_parser_assignment_expression (parser, NULL, false, false); if (t == error_mark_node - || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + || !parens.require_close (parser)) { cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, @@ -31388,7 +31603,8 @@ cp_parser_oacc_shape_clause (cp_parser *parser, omp_clause_code kind, if (cp_lexer_next_token_is (lexer, CPP_OPEN_PAREN)) { - cp_lexer_consume_token (lexer); + matching_parens parens; + parens.consume_open (parser); do { @@ -31462,7 +31678,7 @@ cp_parser_oacc_shape_clause (cp_parser *parser, omp_clause_code kind, } while (1); - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) goto cleanup_error; } @@ -31608,12 +31824,13 @@ cp_parser_omp_clause_collapse (cp_parser *parser, tree list, location_t location HOST_WIDE_INT n; loc = cp_lexer_peek_token (parser->lexer)->location; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; num = cp_parser_constant_expression (parser); - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -31652,7 +31869,8 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list, enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED; tree c; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { @@ -31695,7 +31913,7 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list, } if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED - || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + || !parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -31719,13 +31937,14 @@ cp_parser_omp_clause_final (cp_parser *parser, tree list, location_t location) { tree t, c; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; t = cp_parser_condition (parser); if (t == error_mark_node - || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + || !parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -31756,7 +31975,8 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location, tree t, c; enum tree_code if_modifier = ERROR_MARK; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (is_omp && cp_lexer_next_token_is (parser->lexer, CPP_NAME)) @@ -31839,7 +32059,7 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location, t = cp_parser_condition (parser); if (t == error_mark_node - || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + || !parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -31934,13 +32154,14 @@ cp_parser_omp_clause_num_threads (cp_parser *parser, tree list, { tree t, c; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; t = cp_parser_expression (parser); if (t == error_mark_node - || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + || !parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -31964,13 +32185,14 @@ cp_parser_omp_clause_num_tasks (cp_parser *parser, tree list, { tree t, c; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; t = cp_parser_expression (parser); if (t == error_mark_node - || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + || !parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -31994,13 +32216,14 @@ cp_parser_omp_clause_grainsize (cp_parser *parser, tree list, { tree t, c; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; t = cp_parser_expression (parser); if (t == error_mark_node - || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + || !parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -32024,13 +32247,14 @@ cp_parser_omp_clause_priority (cp_parser *parser, tree list, { tree t, c; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; t = cp_parser_expression (parser); if (t == error_mark_node - || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + || !parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -32054,13 +32278,14 @@ cp_parser_omp_clause_hint (cp_parser *parser, tree list, { tree t, c; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; t = cp_parser_expression (parser); if (t == error_mark_node - || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + || !parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -32084,7 +32309,8 @@ cp_parser_omp_clause_defaultmap (cp_parser *parser, tree list, tree c, id; const char *p; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME)) @@ -32116,7 +32342,7 @@ cp_parser_omp_clause_defaultmap (cp_parser *parser, tree list, goto out_err; } cp_lexer_consume_token (parser->lexer); - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) goto out_err; check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULTMAP, "defaultmap", @@ -32151,11 +32377,12 @@ cp_parser_omp_clause_ordered (cp_parser *parser, if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) { - cp_lexer_consume_token (parser->lexer); + matching_parens parens; + parens.consume_open (parser); num = cp_parser_constant_expression (parser); - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -32312,7 +32539,8 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list, location_t location tree c, t; int modifiers = 0, nmodifiers = 0; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; c = build_omp_clause (location, OMP_CLAUSE_SCHEDULE); @@ -32406,7 +32634,7 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list, location_t location else OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t; - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) goto resync_fail; } else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_COMMA_CLOSE_PAREN)) @@ -32512,13 +32740,14 @@ cp_parser_omp_clause_num_teams (cp_parser *parser, tree list, { tree t, c; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; t = cp_parser_expression (parser); if (t == error_mark_node - || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + || !parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -32542,13 +32771,14 @@ cp_parser_omp_clause_thread_limit (cp_parser *parser, tree list, { tree t, c; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; t = cp_parser_expression (parser); if (t == error_mark_node - || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + || !parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -32573,7 +32803,8 @@ cp_parser_omp_clause_aligned (cp_parser *parser, tree list) tree nlist, c, alignment = NULL_TREE; bool colon; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_ALIGNED, list, @@ -32583,7 +32814,7 @@ cp_parser_omp_clause_aligned (cp_parser *parser, tree list) { alignment = cp_parser_constant_expression (parser); - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -32614,7 +32845,8 @@ cp_parser_omp_clause_linear (cp_parser *parser, tree list, bool colon; enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (!is_cilk_simd_fn @@ -32644,7 +32876,7 @@ cp_parser_omp_clause_linear (cp_parser *parser, tree list, colon = cp_lexer_next_token_is (parser->lexer, CPP_COLON); if (colon) cp_parser_require (parser, CPP_COLON, RT_COLON); - else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + else if (!parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -32682,7 +32914,7 @@ cp_parser_omp_clause_linear (cp_parser *parser, tree list, sorry ("using parameters for %<linear%> step is not supported yet"); step = integer_one_node; } - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -32709,13 +32941,14 @@ cp_parser_omp_clause_safelen (cp_parser *parser, tree list, { tree t, c; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; t = cp_parser_constant_expression (parser); if (t == error_mark_node - || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + || !parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -32738,13 +32971,14 @@ cp_parser_omp_clause_simdlen (cp_parser *parser, tree list, { tree t, c; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; t = cp_parser_constant_expression (parser); if (t == error_mark_node - || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + || !parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -32860,7 +33094,8 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc) tree nlist, c; enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) @@ -32892,7 +33127,7 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc) OMP_CLAUSE_DEPEND_KIND (c) = kind; OMP_CLAUSE_DECL (c) = NULL_TREE; OMP_CLAUSE_CHAIN (c) = list; - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -33023,13 +33258,14 @@ cp_parser_omp_clause_device (cp_parser *parser, tree list, { tree t, c; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; t = cp_parser_expression (parser); if (t == error_mark_node - || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + || !parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -33054,7 +33290,8 @@ cp_parser_omp_clause_dist_schedule (cp_parser *parser, tree list, { tree c, t; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return list; c = build_omp_clause (location, OMP_CLAUSE_DIST_SCHEDULE); @@ -33073,7 +33310,7 @@ cp_parser_omp_clause_dist_schedule (cp_parser *parser, tree list, goto resync_fail; OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t; - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) goto resync_fail; } else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_COMMA_CLOSE_PAREN)) @@ -33159,11 +33396,12 @@ cp_parser_oacc_clause_async (cp_parser *parser, tree list) if (cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN) { - cp_lexer_consume_token (parser->lexer); + matching_parens parens; + parens.consume_open (parser); t = cp_parser_expression (parser); if (t == error_mark_node - || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + || !parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -34213,12 +34451,13 @@ cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok, bool *if_p) if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) { - cp_lexer_consume_token (parser->lexer); + matching_parens parens; + parens.consume_open (parser); name = cp_parser_identifier (parser); if (name == error_mark_node - || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + || !parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -34716,7 +34955,8 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, } loc = cp_lexer_consume_token (parser->lexer)->location; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return NULL; init = orig_init = decl = real_decl = NULL; @@ -34848,7 +35088,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, protected_set_expr_location (incr, input_location); } - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); @@ -35207,7 +35447,8 @@ cp_parser_omp_sections_scope (cp_parser *parser) bool error_suppress = false; cp_token *tok; - if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE)) + matching_braces braces; + if (!braces.require_open (parser)) return NULL_TREE; stmt = push_stmt_list (); @@ -35244,7 +35485,7 @@ cp_parser_omp_sections_scope (cp_parser *parser) substmt = build1 (OMP_SECTION, void_type_node, substmt); add_stmt (substmt); } - cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); + braces.require_close (parser); substmt = pop_stmt_list (stmt); @@ -37106,7 +37347,8 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser) if (strcmp (p, "initializer") == 0) { cp_lexer_consume_token (parser->lexer); - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return false; p = ""; @@ -37197,12 +37439,13 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser) if (ctor) add_decl_expr (omp_orig); - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) return false; } if (!cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA_EOL)) - cp_parser_required_error (parser, RT_PRAGMA_EOL, /*keyword=*/false); + cp_parser_required_error (parser, RT_PRAGMA_EOL, /*keyword=*/false, + UNKNOWN_LOCATION); return true; } @@ -37630,7 +37873,8 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token *pragma_tok, /* Look for optional '( name )'. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) { - cp_lexer_consume_token (parser->lexer); /* '(' */ + matching_parens parens; + parens.consume_open (parser); /* '(' */ /* We parse the name as an id-expression. If it resolves to anything other than a non-overloaded function at namespace @@ -37647,7 +37891,7 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token *pragma_tok, cp_parser_name_lookup_error (parser, name, decl, NLE_NULL, name_loc); if (decl == error_mark_node - || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + || !parens.require_close (parser)) { cp_parser_skip_to_pragma_eol (parser, pragma_tok); parser->oacc_routine = NULL; @@ -38079,12 +38323,13 @@ cp_parser_transaction_expression (cp_parser *parser, enum rid keyword) if (!noex || !noex_expr || cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN) { - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + matching_parens parens; + parens.require_open (parser); expr = cp_parser_expression (parser); expr = finish_parenthesized_expr (expr); - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + parens.require_close (parser); } else { @@ -38672,7 +38917,8 @@ cp_parser_cilk_simd_vectorlength (cp_parser *parser, tree clauses, check_no_duplicate_clause (clauses, OMP_CLAUSE_SIMDLEN, "vectorlength", loc); - if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + matching_parens parens; + if (!parens.require_open (parser)) return error_mark_node; expr = cp_parser_constant_expression (parser); @@ -38709,7 +38955,7 @@ cp_parser_cilk_simd_vectorlength (cp_parser *parser, tree clauses, } } - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + if (!parens.require_close (parser)) return error_mark_node; return clauses; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index da133bd1863..bf1f75de1e7 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -6879,7 +6879,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) } else if (NULLPTR_TYPE_P (type)) { - if (expr != nullptr_node) + if (!NULLPTR_TYPE_P (TREE_TYPE (expr))) { if (complain & tf_error) error ("%qE is not a valid template argument for type %qT " @@ -10551,7 +10551,6 @@ instantiate_class_template_1 (tree type) } else if (DECL_DECLARES_FUNCTION_P (t)) { - /* Build new TYPE_METHODS. */ tree r; if (TREE_CODE (t) == TEMPLATE_DECL) @@ -12876,7 +12875,15 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) && VAR_HAD_UNKNOWN_BOUND (t) && type != error_mark_node) type = strip_array_domain (type); + tree auto_node = type_uses_auto (type); + int len = TREE_VEC_LENGTH (args); + if (auto_node) + /* Mask off any template args past the variable's context so we + don't replace the auto with an unrelated argument. */ + TREE_VEC_LENGTH (args) = TEMPLATE_TYPE_LEVEL (auto_node) - 1; type = tsubst (type, args, complain, in_decl); + if (auto_node) + TREE_VEC_LENGTH (args) = len; } if (VAR_P (r)) { @@ -14657,6 +14664,10 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r) = TREE_CONSTANT (r) = true; DECL_INITIAL (r) = init; + if (tree auto_node = type_uses_auto (TREE_TYPE (r))) + TREE_TYPE (r) + = do_auto_deduction (TREE_TYPE (r), init, auto_node, + complain, adc_variable_type); } gcc_assert (cp_unevaluated_operand || TREE_STATIC (r) || decl_constant_var_p (r) @@ -15106,6 +15117,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) return tsubst_binary_left_fold (t, args, complain, in_decl); case BINARY_RIGHT_FOLD_EXPR: return tsubst_binary_right_fold (t, args, complain, in_decl); + case PREDICT_EXPR: + return t; default: /* We shouldn't get here, but keep going if !flag_checking. */ @@ -16137,13 +16150,15 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, instantiated along with their containing function. And this way we don't have to deal with pushing out of one local class to instantiate a member of another local class. */ - tree fn; /* Closures are handled by the LAMBDA_EXPR. */ gcc_assert (!LAMBDA_TYPE_P (TREE_TYPE (t))); complete_type (tmp); - for (fn = TYPE_METHODS (tmp); fn; fn = DECL_CHAIN (fn)) - if (!DECL_ARTIFICIAL (fn)) - instantiate_decl (fn, /*defer_ok=*/false, + for (tree fld = TYPE_FIELDS (tmp); fld; fld = DECL_CHAIN (fld)) + if ((VAR_P (fld) + || (TREE_CODE (fld) == FUNCTION_DECL + && !DECL_ARTIFICIAL (fld))) + && DECL_TEMPLATE_INSTANTIATION (fld)) + instantiate_decl (fld, /*defer_ok=*/false, /*expl_inst_class=*/false); } break; @@ -22133,18 +22148,6 @@ bt_instantiate_type_proc (binding_entry entry, void *data) do_type_instantiation (TYPE_MAIN_DECL (entry->type), storage, 0); } -/* Called from do_type_instantiation to instantiate a member - (a member function or a static member variable) of an - explicitly instantiated class template. */ -static void -instantiate_class_member (tree decl, int extern_p) -{ - mark_decl_instantiated (decl, extern_p); - if (! extern_p) - instantiate_decl (decl, /*defer_ok=*/true, - /*expl_inst_class_mem_p=*/true); -} - /* Perform an explicit instantiation of template class T. STORAGE, if non-null, is the RID for extern, inline or static. COMPLAIN is nonzero if this is called from the parser, zero if called recursively, @@ -22254,12 +22257,9 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain) if (nomem_p) return; - { - tree tmp; - - /* In contrast to implicit instantiation, where only the - declarations, and not the definitions, of members are - instantiated, we have here: + /* In contrast to implicit instantiation, where only the + declarations, and not the definitions, of members are + instantiated, we have here: [temp.explicit] @@ -22268,27 +22268,28 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain) previously explicitly specialized in the translation unit containing the explicit instantiation. - Of course, we can't instantiate member template classes, since - we don't have any arguments for them. Note that the standard - is unclear on whether the instantiation of the members are - *explicit* instantiations or not. However, the most natural - interpretation is that it should be an explicit instantiation. */ - - if (! static_p) - for (tmp = TYPE_METHODS (t); tmp; tmp = DECL_CHAIN (tmp)) - if (TREE_CODE (tmp) == FUNCTION_DECL - && DECL_TEMPLATE_INSTANTIATION (tmp) - && user_provided_p (tmp)) - instantiate_class_member (tmp, extern_p); - - for (tmp = TYPE_FIELDS (t); tmp; tmp = DECL_CHAIN (tmp)) - if (VAR_P (tmp) && DECL_TEMPLATE_INSTANTIATION (tmp)) - instantiate_class_member (tmp, extern_p); - - if (CLASSTYPE_NESTED_UTDS (t)) - binding_table_foreach (CLASSTYPE_NESTED_UTDS (t), - bt_instantiate_type_proc, &storage); - } + Of course, we can't instantiate member template classes, since we + don't have any arguments for them. Note that the standard is + unclear on whether the instantiation of the members are + *explicit* instantiations or not. However, the most natural + interpretation is that it should be an explicit + instantiation. */ + for (tree fld = TYPE_FIELDS (t); fld; fld = DECL_CHAIN (fld)) + if ((VAR_P (fld) + || (TREE_CODE (fld) == FUNCTION_DECL + && !static_p + && user_provided_p (fld))) + && DECL_TEMPLATE_INSTANTIATION (fld)) + { + mark_decl_instantiated (fld, extern_p); + if (! extern_p) + instantiate_decl (fld, /*defer_ok=*/true, + /*expl_inst_class_mem_p=*/true); + } + + if (CLASSTYPE_NESTED_UTDS (t)) + binding_table_foreach (CLASSTYPE_NESTED_UTDS (t), + bt_instantiate_type_proc, &storage); } /* Given a function DECL, which is a specialization of TMPL, modify @@ -22504,16 +22505,17 @@ always_instantiate_p (tree decl) } /* If FN has a noexcept-specifier that hasn't been instantiated yet, - instantiate it now, modifying TREE_TYPE (fn). */ + instantiate it now, modifying TREE_TYPE (fn). Returns false on + error, true otherwise. */ -void -maybe_instantiate_noexcept (tree fn) +bool +maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain) { tree fntype, spec, noex, clone; /* Don't instantiate a noexcept-specification from template context. */ if (processing_template_decl) - return; + return true; if (DECL_CLONED_FUNCTION_P (fn)) fn = DECL_CLONED_FUNCTION (fn); @@ -22521,7 +22523,7 @@ maybe_instantiate_noexcept (tree fn) spec = TYPE_RAISES_EXCEPTIONS (fntype); if (!spec || !TREE_PURPOSE (spec)) - return; + return true; noex = TREE_PURPOSE (spec); @@ -22530,7 +22532,7 @@ maybe_instantiate_noexcept (tree fn) static hash_set<tree>* fns = new hash_set<tree>; bool added = false; if (DEFERRED_NOEXCEPT_PATTERN (noex) == NULL_TREE) - spec = get_defaulted_eh_spec (fn); + spec = get_defaulted_eh_spec (fn, complain); else if (!(added = !fns->add (fn))) { /* If hash_set::add returns true, the element was already there. */ @@ -22564,6 +22566,9 @@ maybe_instantiate_noexcept (tree fn) if (added) fns->remove (fn); + if (spec == error_mark_node) + return false; + TREE_TYPE (fn) = build_exception_variant (fntype, spec); } @@ -22574,6 +22579,8 @@ maybe_instantiate_noexcept (tree fn) else TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone), spec); } + + return true; } /* Produce the definition of D, a _DECL generated from a template. If @@ -23080,19 +23087,20 @@ instantiate_pending_templates (int retries) if (TYPE_P (instantiation)) { - tree fn; - if (!COMPLETE_TYPE_P (instantiation)) { instantiate_class_template (instantiation); if (CLASSTYPE_TEMPLATE_INSTANTIATION (instantiation)) - for (fn = TYPE_METHODS (instantiation); - fn; - fn = TREE_CHAIN (fn)) - if (! DECL_ARTIFICIAL (fn)) - instantiate_decl (fn, + for (tree fld = TYPE_FIELDS (instantiation); + fld; fld = TREE_CHAIN (fld)) + if ((VAR_P (fld) + || (TREE_CODE (fld) == FUNCTION_DECL + && !DECL_ARTIFICIAL (fld))) + && DECL_TEMPLATE_INSTANTIATION (fld)) + instantiate_decl (fld, /*defer_ok=*/false, /*expl_inst_class_mem_p=*/false); + if (COMPLETE_TYPE_P (instantiation)) reconsider = 1; } @@ -25343,6 +25351,24 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags, else if (BRACE_ENCLOSED_INITIALIZER_P (init)) { try_list_ctor = TYPE_HAS_LIST_CTOR (type); + if (try_list_ctor && CONSTRUCTOR_NELTS (init) == 1) + { + /* As an exception, the first phase in 16.3.1.7 (considering the + initializer list as a single argument) is omitted if the + initializer list consists of a single expression of type cv U, + where U is a specialization of C or a class derived from a + specialization of C. */ + tree elt = CONSTRUCTOR_ELT (init, 0)->value; + tree etype = TREE_TYPE (elt); + + tree tparms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl)); + tree targs = make_tree_vec (TREE_VEC_LENGTH (tparms)); + int err = unify (tparms, targs, type, etype, + UNIFY_ALLOW_DERIVED, /*explain*/false); + if (err == 0) + try_list_ctor = false; + ggc_free (targs); + } if (try_list_ctor || is_std_init_list (type)) args = make_tree_vector_single (init); else @@ -25444,11 +25470,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags, if (gtype) { tree guide = build_deduction_guide (gtype, outer_args, complain); - if ((flags & LOOKUP_ONLYCONVERTING) - && DECL_NONCONVERTING_P (STRIP_TEMPLATE (guide))) - elided = true; - else - cands = lookup_add (guide, cands); + cands = lookup_add (guide, cands); } } @@ -25459,6 +25481,12 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags, "user-declared constructors", type); return error_mark_node; } + else if (!cands && call == error_mark_node) + { + error ("cannot deduce template arguments of %qT, as it has no viable " + "deduction guides", type); + return error_mark_node; + } if (call == error_mark_node) { diff --git a/gcc/cp/search.c b/gcc/cp/search.c index cd06e529fb9..ced82da6117 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -28,6 +28,8 @@ along with GCC; see the file COPYING3. If not see #include "intl.h" #include "toplev.h" #include "spellcheck-tree.h" +#include "stringpool.h" +#include "attribs.h" static int is_subobject_of_p (tree, tree); static tree dfs_lookup_base (tree, void *); @@ -444,6 +446,10 @@ lookup_field_1 (tree type, tree name, bool want_type) { tree decl = field; + if (DECL_DECLARES_FUNCTION_P (decl)) + /* Functions are kep separately, at the moment. */ + continue; + if (GATHER_STATISTICS) n_fields_searched++; @@ -1526,86 +1532,67 @@ lookup_fnfields (tree xbasetype, tree name, int protect) return rval; } -/* Return the index in the CLASSTYPE_METHOD_VEC for CLASS_TYPE - corresponding to "operator TYPE ()", or -1 if there is no such - operator. Only CLASS_TYPE itself is searched; this routine does - not scan the base classes of CLASS_TYPE. */ +/* Return the conversion operators in CLASS_TYPE corresponding to + "operator TYPE ()". Only CLASS_TYPE itself is searched; this + routine does not scan the base classes of CLASS_TYPE. */ -static int +static tree lookup_conversion_operator (tree class_type, tree type) { - int tpl_slot = -1; + tree tpls = NULL_TREE; if (TYPE_HAS_CONVERSION (class_type)) { - int i; - tree fn; + tree fns; vec<tree, va_gc> *methods = CLASSTYPE_METHOD_VEC (class_type); - for (i = CLASSTYPE_FIRST_CONVERSION_SLOT; - vec_safe_iterate (methods, i, &fn); ++i) + for (int i = CLASSTYPE_FIRST_CONVERSION_SLOT; + vec_safe_iterate (methods, i, &fns); ++i) { /* All the conversion operators come near the beginning of the class. Therefore, if FN is not a conversion operator, there is no matching conversion operator in CLASS_TYPE. */ - fn = OVL_FIRST (fn); + tree fn = OVL_FIRST (fns); if (!DECL_CONV_FN_P (fn)) break; if (TREE_CODE (fn) == TEMPLATE_DECL) /* All the templated conversion functions are on the same slot, so remember it. */ - tpl_slot = i; + tpls = fns; else if (same_type_p (DECL_CONV_FN_TYPE (fn), type)) - return i; + return fns; } } - return tpl_slot; + return tpls; } -/* TYPE is a class type. Return the index of the fields within - the method vector with name NAME, or -1 if no such field exists. - Does not lazily declare implicitly-declared member functions. */ +/* TYPE is a class type. Return the member functions in the method + vector with name NAME. Does not lazily declare implicitly-declared + member functions. */ -static int -lookup_fnfields_idx_nolazy (tree type, tree name) +tree +lookup_fnfields_slot_nolazy (tree type, tree name) { - vec<tree, va_gc> *method_vec; - tree fn; - size_t i; - - if (!CLASS_TYPE_P (type)) - return -1; - - method_vec = CLASSTYPE_METHOD_VEC (type); + vec<tree, va_gc> *method_vec = CLASSTYPE_METHOD_VEC (type); if (!method_vec) - return -1; + return NULL_TREE; if (GATHER_STATISTICS) n_calls_lookup_fnfields_1++; - /* Constructors are first... */ - if (name == ctor_identifier) - { - fn = CLASSTYPE_CONSTRUCTORS (type); - return fn ? CLASSTYPE_CONSTRUCTOR_SLOT : -1; - } - /* and destructors are second. */ - if (name == dtor_identifier) - { - fn = CLASSTYPE_DESTRUCTOR (type); - return fn ? CLASSTYPE_DESTRUCTOR_SLOT : -1; - } if (IDENTIFIER_CONV_OP_P (name)) return lookup_conversion_operator (type, TREE_TYPE (name)); /* Skip the conversion operators. */ + int i; + tree fns; for (i = CLASSTYPE_FIRST_CONVERSION_SLOT; - vec_safe_iterate (method_vec, i, &fn); + vec_safe_iterate (method_vec, i, &fns); ++i) - if (!DECL_CONV_FN_P (OVL_FIRST (fn))) + if (!DECL_CONV_FN_P (OVL_FIRST (fns))) break; /* If the type is complete, use binary search. */ @@ -1623,36 +1610,35 @@ lookup_fnfields_idx_nolazy (tree type, tree name) if (GATHER_STATISTICS) n_outer_fields_searched++; - tree tmp = (*method_vec)[i]; - tmp = OVL_NAME (tmp); - if (tmp > name) + fns = (*method_vec)[i]; + tree fn_name = OVL_NAME (fns); + if (fn_name > name) hi = i; - else if (tmp < name) + else if (fn_name < name) lo = i + 1; else - return i; + return fns; } } else - for (; vec_safe_iterate (method_vec, i, &fn); ++i) + for (; vec_safe_iterate (method_vec, i, &fns); ++i) { if (GATHER_STATISTICS) n_outer_fields_searched++; - if (OVL_NAME (fn) == name) - return i; + if (OVL_NAME (fns) == name) + return fns; } - return -1; + return NULL_TREE; } -/* TYPE is a class type. Return the index of the fields within - the method vector with name NAME, or -1 if no such field exists. */ +/* TYPE is a class type. Return the overloads in + the method vector with name NAME. Lazily create ctors etc. */ -static int -lookup_fnfields_1 (tree type, tree name) +tree +lookup_fnfields_slot (tree type, tree name) { - if (!CLASS_TYPE_P (type)) - return -1; + type = complete_type (type); if (COMPLETE_TYPE_P (type)) { @@ -1679,30 +1665,7 @@ lookup_fnfields_1 (tree type, tree name) } } - return lookup_fnfields_idx_nolazy (type, name); -} - -/* TYPE is a class type. Return the field within the method vector with - name NAME, or NULL_TREE if no such field exists. */ - -tree -lookup_fnfields_slot (tree type, tree name) -{ - int ix = lookup_fnfields_1 (complete_type (type), name); - if (ix < 0) - return NULL_TREE; - return (*CLASSTYPE_METHOD_VEC (type))[ix]; -} - -/* As above, but avoid lazily declaring functions. */ - -tree -lookup_fnfields_slot_nolazy (tree type, tree name) -{ - int ix = lookup_fnfields_idx_nolazy (complete_type (type), name); - if (ix < 0) - return NULL_TREE; - return (*CLASSTYPE_METHOD_VEC (type))[ix]; + return lookup_fnfields_slot_nolazy (type, name); } /* Collect all the conversion operators of KLASS. */ @@ -2424,37 +2387,26 @@ look_for_overrides (tree type, tree fndecl) tree look_for_overrides_here (tree type, tree fndecl) { - int ix; - - /* If there are no methods in TYPE (meaning that only implicitly - declared methods will ever be provided for TYPE), then there are - no virtual functions. */ - if (!CLASSTYPE_METHOD_VEC (type)) - return NULL_TREE; + tree ovl = lookup_fnfields_slot (type, DECL_NAME (fndecl)); - if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fndecl)) - ix = CLASSTYPE_DESTRUCTOR_SLOT; - else - ix = lookup_fnfields_1 (type, DECL_NAME (fndecl)); - if (ix >= 0) - for (ovl_iterator iter ((*CLASSTYPE_METHOD_VEC (type))[ix]); iter; ++iter) - { - tree fn = *iter; + for (ovl_iterator iter (ovl); iter; ++iter) + { + tree fn = *iter; - if (!DECL_VIRTUAL_P (fn)) - /* Not a virtual. */; - else if (DECL_CONTEXT (fn) != type) - /* Introduced with a using declaration. */; - else if (DECL_STATIC_FUNCTION_P (fndecl)) - { - tree btypes = TYPE_ARG_TYPES (TREE_TYPE (fn)); - tree dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); - if (compparms (TREE_CHAIN (btypes), dtypes)) - return fn; - } - else if (same_signature_p (fndecl, fn)) - return fn; - } + if (!DECL_VIRTUAL_P (fn)) + /* Not a virtual. */; + else if (DECL_CONTEXT (fn) != type) + /* Introduced with a using declaration. */; + else if (DECL_STATIC_FUNCTION_P (fndecl)) + { + tree btypes = TYPE_ARG_TYPES (TREE_TYPE (fn)); + tree dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); + if (compparms (TREE_CHAIN (btypes), dtypes)) + return fn; + } + else if (same_signature_p (fndecl, fn)) + return fn; + } return NULL_TREE; } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index cf19e5fd96a..5401e78fbc6 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -40,7 +40,10 @@ along with GCC; see the file COPYING3. If not see #include "tree-iterator.h" #include "omp-general.h" #include "convert.h" +#include "stringpool.h" +#include "attribs.h" #include "gomp-constants.h" +#include "predict.h" /* There routines provide a modular interface to perform many parsing operations. They may therefore be used during actual parsing, or @@ -630,6 +633,7 @@ finish_goto_stmt (tree destination) check_goto (destination); + add_stmt (build_predict_expr (PRED_GOTO, NOT_TAKEN)); return add_stmt (build_stmt (input_location, GOTO_EXPR, destination)); } @@ -3037,9 +3041,9 @@ finish_member_declaration (tree decl) if (DECL_LANG_SPECIFIC (decl) && DECL_LANGUAGE (decl) == lang_c) SET_DECL_LANGUAGE (decl, lang_cplusplus); - /* Put functions on the TYPE_METHODS list and everything else on the - TYPE_FIELDS list. Note that these are built up in reverse order. - We reverse them (to obtain declaration order) in finish_struct. */ + /* Put the decl on the TYPE_FIELDS list. Note that this is built up + in reverse order. We reverse it (to obtain declaration order) in + finish_struct. */ if (DECL_DECLARES_FUNCTION_P (decl)) { /* We also need to add this function to the @@ -3047,8 +3051,8 @@ finish_member_declaration (tree decl) if (add_method (current_class_type, decl, false)) { gcc_assert (TYPE_MAIN_VARIANT (current_class_type) == current_class_type); - DECL_CHAIN (decl) = TYPE_METHODS (current_class_type); - TYPE_METHODS (current_class_type) = decl; + DECL_CHAIN (decl) = TYPE_FIELDS (current_class_type); + TYPE_FIELDS (current_class_type) = decl; maybe_add_class_template_decl_list (current_class_type, decl, /*friend_p=*/0); @@ -5794,7 +5798,7 @@ finish_omp_declare_simd_methods (tree t) if (processing_template_decl) return; - for (tree x = TYPE_METHODS (t); x; x = DECL_CHAIN (x)) + for (tree x = TYPE_FIELDS (t); x; x = DECL_CHAIN (x)) { if (TREE_CODE (TREE_TYPE (x)) != METHOD_TYPE) continue; @@ -9083,15 +9087,7 @@ classtype_has_nothrow_assign_or_copy_p (tree type, bool assign_p) if (assign_p) fns = lookup_fnfields_slot (type, cp_assignment_operator_id (NOP_EXPR)); else if (TYPE_HAS_COPY_CTOR (type)) - { - /* If construction of the copy constructor was postponed, create - it now. */ - if (CLASSTYPE_LAZY_COPY_CTOR (type)) - lazily_declare_fn (sfk_copy_constructor, type); - if (CLASSTYPE_LAZY_MOVE_CTOR (type)) - lazily_declare_fn (sfk_move_constructor, type); - fns = CLASSTYPE_CONSTRUCTORS (type); - } + fns = lookup_fnfields_slot (type, ctor_identifier); bool saw_copy = false; for (ovl_iterator iter (fns); iter; ++iter) diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 2122450c653..8f18665da41 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "debug.h" #include "convert.h" #include "gimplify.h" +#include "stringpool.h" #include "attribs.h" #include "flags.h" diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 316d57fb38c..a5a363bc942 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -37,6 +37,8 @@ along with GCC; see the file COPYING3. If not see #include "c-family/c-ubsan.h" #include "params.h" #include "gcc-rich-location.h" +#include "stringpool.h" +#include "attribs.h" #include "asan.h" static tree cp_build_addr_expr_strict (tree, tsubst_flags_t); @@ -4048,7 +4050,7 @@ enum_cast_to_int (tree op) /* For the c-common bits. */ tree build_binary_op (location_t location, enum tree_code code, tree op0, tree op1, - int /*convert_p*/) + bool /*convert_p*/) { return cp_build_binary_op (location, code, op0, op1, tf_warning_or_error); } @@ -5256,6 +5258,7 @@ cp_build_binary_op (location_t location, if (sanitize_flags_p ((SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE)) + && current_function_decl != NULL_TREE && !processing_template_decl && (doing_div_or_mod || doing_shift)) { @@ -5486,9 +5489,9 @@ build_x_unary_op (location_t loc, enum tree_code code, cp_expr xarg, { if (complain & tf_error) error (DECL_CONSTRUCTOR_P (fn) - ? G_("taking address of constructor %qE") - : G_("taking address of destructor %qE"), - xarg.get_value ()); + ? G_("taking address of constructor %qD") + : G_("taking address of destructor %qD"), + fn); return error_mark_node; } } @@ -5589,7 +5592,7 @@ cp_truthvalue_conversion (tree expr) if (TYPE_PTR_OR_PTRMEM_P (type) /* Avoid ICE on invalid use of non-static member function. */ || TREE_CODE (expr) == FUNCTION_DECL) - return build_binary_op (input_location, NE_EXPR, expr, nullptr_node, 1); + return build_binary_op (input_location, NE_EXPR, expr, nullptr_node, true); else return c_common_truthvalue_conversion (input_location, expr); } @@ -9153,6 +9156,7 @@ check_return_expr (tree retval, bool *no_warning) Note that these conditions are similar to, but not as strict as, the conditions for the named return value optimization. */ + bool converted = false; if ((cxx_dialect != cxx98) && ((VAR_P (retval) && !DECL_HAS_VALUE_EXPR_P (retval)) || TREE_CODE (retval) == PARM_DECL) @@ -9160,14 +9164,25 @@ check_return_expr (tree retval, bool *no_warning) && !TREE_STATIC (retval) /* This is only interesting for class type. */ && CLASS_TYPE_P (functype)) - flags = flags | LOOKUP_PREFER_RVALUE; + { + tree moved = move (retval); + moved = convert_for_initialization + (NULL_TREE, functype, moved, flags|LOOKUP_PREFER_RVALUE, + ICR_RETURN, NULL_TREE, 0, tf_none); + if (moved != error_mark_node) + { + retval = moved; + converted = true; + } + } /* First convert the value to the function's return type, then to the type of return value's location to handle the case that functype is smaller than the valtype. */ - retval = convert_for_initialization - (NULL_TREE, functype, retval, flags, ICR_RETURN, NULL_TREE, 0, - tf_warning_or_error); + if (!converted) + retval = convert_for_initialization + (NULL_TREE, functype, retval, flags, ICR_RETURN, NULL_TREE, 0, + tf_warning_or_error); retval = convert (valtype, retval); /* If the conversion failed, treat this just like `return;'. */ diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 430ba30536a..06c079e41be 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1182,7 +1182,7 @@ digest_init_flags (tree type, tree init, int flags, tsubst_flags_t complain) /* Process the initializer INIT for an NSDMI DECL (a FIELD_DECL). */ tree -digest_nsdmi_init (tree decl, tree init) +digest_nsdmi_init (tree decl, tree init, tsubst_flags_t complain) { gcc_assert (TREE_CODE (decl) == FIELD_DECL); @@ -1192,8 +1192,8 @@ digest_nsdmi_init (tree decl, tree init) flags = LOOKUP_NORMAL; if (BRACE_ENCLOSED_INITIALIZER_P (init) && CP_AGGREGATE_TYPE_P (type)) - init = reshape_init (type, init, tf_warning_or_error); - init = digest_init_flags (type, init, flags, tf_warning_or_error); + init = reshape_init (type, init, complain); + init = digest_init_flags (type, init, flags, complain); if (TREE_CODE (init) == TARGET_EXPR) /* This represents the whole initialization. */ TARGET_EXPR_DIRECT_INIT_P (init) = true; @@ -1427,7 +1427,7 @@ process_init_constructor_record (tree type, tree init, goto restart; } /* C++14 aggregate NSDMI. */ - next = get_nsdmi (field, /*ctor*/false); + next = get_nsdmi (field, /*ctor*/false, complain); } else if (type_build_ctor_call (TREE_TYPE (field))) { @@ -1525,7 +1525,8 @@ process_init_constructor_union (tree type, tree init, { CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (init), field, - get_nsdmi (field, /*in_ctor=*/false)); + get_nsdmi (field, /*in_ctor=*/false, + complain)); break; } } |