aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog313
-rw-r--r--gcc/cp/call.c61
-rw-r--r--gcc/cp/class.c244
-rw-r--r--gcc/cp/constexpr.c1
-rw-r--r--gcc/cp/cp-gimplify.c11
-rw-r--r--gcc/cp/cp-objcp-common.c7
-rw-r--r--gcc/cp/cp-tree.h25
-rw-r--r--gcc/cp/cp-ubsan.c5
-rw-r--r--gcc/cp/cvt.c2
-rw-r--r--gcc/cp/decl.c35
-rw-r--r--gcc/cp/decl2.c59
-rw-r--r--gcc/cp/error.c2
-rw-r--r--gcc/cp/except.c30
-rw-r--r--gcc/cp/init.c59
-rw-r--r--gcc/cp/lambda.c5
-rw-r--r--gcc/cp/lex.c4
-rw-r--r--gcc/cp/method.c55
-rw-r--r--gcc/cp/name-lookup.c17
-rw-r--r--gcc/cp/optimize.c12
-rw-r--r--gcc/cp/parser.c832
-rw-r--r--gcc/cp/pt.c154
-rw-r--r--gcc/cp/search.c172
-rw-r--r--gcc/cp/semantics.c26
-rw-r--r--gcc/cp/tree.c1
-rw-r--r--gcc/cp/typeck.c33
-rw-r--r--gcc/cp/typeck2.c11
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;
}
}