aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorThomas Koenig <tkoenig@gcc.gnu.org>2020-10-28 18:41:24 +0100
committerThomas Koenig <tkoenig@gcc.gnu.org>2020-10-28 18:41:24 +0100
commitbf6dad60c338a42a7fb85f7b2a5870c0fb2e20f8 (patch)
treee513781ef717465e7db0358e987a5a6cbef5665c /gcc/cp
parent0c261d5b5c931d9e9214d06531bdc7e9e16aeaab (diff)
parent47d13acbda9a5d8eb57ff169ba74857cd54108e4 (diff)
downloadgcc-bf6dad60c338a42a7fb85f7b2a5870c0fb2e20f8.zip
gcc-bf6dad60c338a42a7fb85f7b2a5870c0fb2e20f8.tar.gz
gcc-bf6dad60c338a42a7fb85f7b2a5870c0fb2e20f8.tar.bz2
Merge branch 'master' into devel/coarray_native.
Merge into devel/coarray_native to prepare for later merging of coarray_native with master.
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog564
-rw-r--r--gcc/cp/call.c63
-rw-r--r--gcc/cp/class.c264
-rw-r--r--gcc/cp/constexpr.c45
-rw-r--r--gcc/cp/constraint.cc13
-rw-r--r--gcc/cp/coroutines.cc27
-rw-r--r--gcc/cp/cp-gimplify.c28
-rw-r--r--gcc/cp/cp-tree.h92
-rw-r--r--gcc/cp/cxx-pretty-print.c35
-rw-r--r--gcc/cp/decl.c523
-rw-r--r--gcc/cp/decl2.c27
-rw-r--r--gcc/cp/error.c65
-rw-r--r--gcc/cp/friend.c27
-rw-r--r--gcc/cp/init.c346
-rw-r--r--gcc/cp/lambda.c14
-rw-r--r--gcc/cp/method.c36
-rw-r--r--gcc/cp/name-lookup.c1052
-rw-r--r--gcc/cp/name-lookup.h60
-rw-r--r--gcc/cp/parser.c134
-rw-r--r--gcc/cp/pt.c351
-rw-r--r--gcc/cp/ptree.c6
-rw-r--r--gcc/cp/rtti.c11
-rw-r--r--gcc/cp/semantics.c5
-rw-r--r--gcc/cp/tree.c37
-rw-r--r--gcc/cp/typeck.c12
25 files changed, 2345 insertions, 1492 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8e6fd0d..3fe4931 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,567 @@
+2020-10-24 Marek Polacek <polacek@redhat.com>
+
+ PR c++/96241
+ * constexpr.c (cxx_eval_array_reference): Set up ctx->ctor if we
+ are initializing an aggregate. Call free_constructor on the new
+ CONSTRUCTOR if it isn't returned from cxx_eval_constant_expression.
+
+2020-10-23 Marek Polacek <polacek@redhat.com>
+
+ PR c++/91741
+ * typeck.c (cp_build_binary_op): Implement -Wsizeof-array-div.
+
+2020-10-22 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/97328
+ * constexpr.c (init_subob_ctx): Don't punt on RANGE_EXPR
+ indexes, instead build a sub-aggregate initialization context
+ with no subobject.
+
+2020-10-22 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/96575
+ * constexpr.c (cxx_eval_constant_expression)
+ <case EMPTY_CLASS_EXPR>: Lower it to a CONSTRUCTOR.
+ (potential_constant_expression_1) <case COMPOUND_EXPR>: Remove
+ now-redundant handling of COMPOUND_EXPR with EMPTY_CLASS_EXPR
+ second operand.
+ <case EMPTY_CLASS_EXPR>: Return true instead of false.
+
+2020-10-22 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/97511
+ * decl.c (duplicate_decls): Return NULL_TREE if
+ DECL_TEMPLATE_PARM_P differ.
+
+2020-10-20 Nathan Sidwell <nathan@acm.org>
+
+ * name-lookup.c (push_local_extern_decl_alias): Reconstextualize
+ alias' parm decls. Drop any default args.
+
+2020-10-19 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/97438
+ * coroutines.cc (struct coroutine_info): Add a field to
+ record that we emitted a promise type error.
+ (coro_promise_type_found_p): Check for the case that the
+ promise type contains both return_void and return_value.
+ Emit an error if so, with information about the wrong
+ type methods.
+
+2020-10-16 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/97460
+ * pt.c (push_template_decl): Check DECL_LANG_SPECIFIC in friend
+ case.
+
+2020-10-16 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/96258
+ * parser.c (cp_parser_declaration): Make token2 point to EOF if
+ token1 was EOF.
+
+2020-10-15 Jason Merrill <jason@redhat.com>
+
+ PR c++/95844
+ * decl.c (copy_fn_p): Return false for a function that is neither a
+ constructor nor an assignment operator.
+ (move_signature_fn_p): Likewise.
+
+2020-10-15 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97406
+ PR c++/85901
+ * cxx-pretty-print.c (pp_cxx_type_specifier_seq): Handle OFFSET_TYPE.
+ (cxx_pretty_printer::abstract_declarator): Fix the printing of ')'.
+ (cxx_pretty_printer::direct_abstract_declarator): Handle OFFSET_TYPE.
+ (cxx_pretty_printer::type_id): Likewise. Print the abstract declarator
+ for pointers-to-members.
+
+2020-10-14 Jason Merrill <jason@redhat.com>
+
+ PR c++/97358
+ * pt.c (check_for_bare_parameter_packs): Diagnose use of
+ capture pack.
+
+2020-10-14 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (struct lang_decl_fn): Adjust context comment.
+ (DECL_FRIEND_P): Replace with ...
+ (DECL_UNIQUE_FRIEND_P): ... this. Only for FUNCTION_DECLs.
+ (DECL_FRIEND_CONTEXT): Adjust.
+ * class.c (add_implicitly_declared_members): Detect friendly
+ spaceship from context.
+ * constraint.cc (remove_constraints): Use a checking assert.
+ (maybe_substitute_reqs_for): Use DECL_UNIQUE_FRIEND_P.
+ * decl.c (check_no_redeclaration_friend_default_args):
+ DECL_UNIQUE_FRIEND_P is signficant, not hiddenness.
+ (duplicate_decls): Adjust DECL_UNIQUE_FRIEND_P clearing.
+ (redeclaration_error_message): Use DECL_UNIQUE_FRIEND_P.
+ (start_preparsed_function): Correct in-class friend processing.
+ Refactor some initializers.
+ (grokmethod): Directly check friend decl-spec.
+ * decl2.c (grokfield): Check DECL_UNIQUE_FRIEND_P.
+ * friend.c (do_friend): Set DECL_UNIQUE_FRIEND_P first, remove
+ extraneous conditions. Don't re set it afterwards.
+ * name-lookup.c (lookup_elaborated_type_1): Simplify revealing
+ code.
+ (do_pushtag): Likewise.
+ * pt.c (optimize_specialization_lookup_p): Check
+ DECL_UNIQUE_FRIEND_P.
+ (push_template_decl): Likewise. Drop unneeded friend setting.
+ (type_dependent_expression_p): Check DECL_UNIQUE_FRIEND_P.
+
+2020-10-14 Nathan Sidwell <nathan@acm.org>
+
+ * name-lookup.c (push_local_extern_decl_alias): Push into alias's
+ namespace and use pushdecl.
+ (do_pushdecl_with_scope): Clarify behaviour.
+
+2020-10-12 Martin Sebor <msebor@redhat.com>
+
+ PR c++/97201
+ * error.c (dump_type_suffix): Handle both the C and C++ forms of
+ zero-length arrays.
+
+2020-10-12 Martin Sebor <msebor@redhat.com>
+
+ PR c++/96511
+ PR middle-end/96384
+ * init.c (warn_placement_new_too_small): Call builtin_objsize instead
+ of duplicating what it does.
+
+2020-10-08 Jason Merrill <jason@redhat.com>
+
+ PR c++/96805
+ PR c++/96199
+ * pt.c (tsubst_aggr_type): Don't build a TYPENAME_TYPE when
+ entering_scope.
+ (tsubst_template_decl): Use tsubst_aggr_type.
+
+2020-10-08 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/97052
+ * constraint.cc (build_type_constraint): Temporarily increment
+ processing_template_decl before calling build_concept_check.
+ * pt.c (make_constrained_placeholder_type): Likewise.
+
+2020-10-08 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/96229
+ * parser.c (cp_parser_class_specifier_1): Move call to
+ associate_classtype_constraints from here to ...
+ (cp_parser_class_head): ... here.
+ * pt.c (is_compatible_template_arg): Correct documentation to
+ say "argument is _no_ more constrained than the parameter".
+
+2020-10-07 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97010
+ * pt.c (tsubst_copy_and_build) <case TEMPLATE_ID_EXPR>: Call
+ tsubst_copy_and_build explicitly instead of using the RECUR macro.
+ Handle a TEMPLATE_ID_EXPR with an IDENTIFIER_NODE as its operand.
+ <case CALL_EXPR>: Perform ADL for a TEMPLATE_ID_EXPR with an
+ IDENTIFIER_NODE as its operand.
+
+2020-10-07 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/88115
+ PR libstdc++/97273
+ * tree.c (cp_tree_equal) <case ALIGNOF_EXPR>: Return false if
+ ALIGNOF_EXPR_STD_P differ.
+
+2020-10-07 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (struct language_function): Delete extern_decl_map.
+ (DECL_LOCAL_DECL_ALIAS): New.
+ * name-lookup.h (is_local_extern): Delete.
+ * name-lookup.c (set_local_extern_decl_linkage): Replace with ...
+ (push_local_extern_decl): ... this new function.
+ (do_pushdecl): Call new function after pushing new decl. Unhide
+ hidden non-functions.
+ (is_local_extern): Delete.
+ * decl.c (layout_var_decl): Do not allow VLA local externs.
+ * decl2.c (mark_used): Also mark DECL_LOCAL_DECL_ALIAS. Drop old
+ local-extern treatment.
+ * parser.c (cp_parser_oacc_declare): Deal with local extern aliases.
+ * pt.c (tsubst_expr): Adjust local extern instantiation.
+ * cp-gimplify.c (cp_genericize_r): Remap DECL_LOCAL_DECLs.
+
+2020-10-07 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (DECL_BUILTIN_P): Rename to ...
+ (DECL_UNDECLARED_BUILTIN_P): ... here.
+ * decl.c (duplicate_decls): Adjust.
+ * name-lookup.c (anticipated_builtin_p): Adjust.
+ (do_nonmember_using_decl): Likewise.
+
+2020-10-07 Nathan Sidwell <nathan@acm.org>
+
+ * tree.c (build_cp_fntype_variant): Clear
+ TYPE_DEPENDENT_P_VALID if necessary.
+
+2020-10-06 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97297
+ * parser.c (cp_parser_direct_declarator): When checking if a
+ name is a function template declaration for the P0634R3 case,
+ look in uninstantiated templates too.
+
+2020-10-05 Marek Polacek <polacek@redhat.com>
+
+ * cp-tree.h (NON_UNION_CLASS_TYPE_P): Fix typo in a comment.
+
+2020-10-05 Richard Biener <rguenther@suse.de>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/97197
+ * error.c (dump_expr): Handle TARGET_MEM_REF.
+
+2020-10-05 Nathan Sidwell <nathan@acm.org>
+
+ * name-lookup.c (maybe_add_fuzzy_decl): New.
+ (maybe_add_fuzzy_binding): New.
+ (consider_binding_level): Use intermediate sortable vector for
+ namespace bindings.
+
+2020-10-02 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97014
+ * cxx-pretty-print.c (pp_cxx_template_argument_list): If the
+ argument is template_parm_object_p, print its DECL_INITIAL.
+
+2020-10-02 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (lang_decl_base): anticipated_p is not used for
+ anticipatedness.
+ (DECL_ANTICIPATED): Delete.
+ * decl.c (duplicate_decls): Delete DECL_ANTICIPATED_management,
+ use was_hidden.
+ (cxx_builtin_function): Drop DECL_ANTICIPATED setting.
+ (xref_tag_1): Drop DECL_ANTICIPATED assert.
+ * name-lookup.c (name_lookup::adl_class_only): Drop
+ DECL_ANTICIPATED check.
+ (name_lookup::search_adl): Always dedup.
+ (anticipated_builtin_p): Reimplement.
+ (do_pushdecl): Drop DECL_ANTICIPATED asserts & update.
+ (lookup_elaborated_type_1): Drop DECL_ANTICIPATED update.
+ (do_pushtag): Drop DECL_ANTICIPATED setting.
+ * pt.c (push_template_decl): Likewise.
+ (tsubst_friend_class): Likewise.
+
+2020-10-02 Nathan Sidwell <nathan@acm.org>
+
+ * name-lookup.c (consider_decl): New, broken out of ...
+ (consider_binding_level): ... here. Iterate the hash table for
+ namespace bindings.
+
+2020-10-02 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (base_ctor_omit_inherited_parms): Declare.
+ * class.c (add_method): Refactor main loop, only pass fns to
+ ctor_omit_inherited_parms.
+ (build_cdtor_clones): Rename bool parms.
+ (clone_cdtor): Call base_ctor_omit_inherited_parms.
+ * method.c (base_ctor_omit_inherited_parms): New, broken out of
+ ...
+ (ctor_omit_inherited_parms): ... here, call it with
+ DECL_CLONED_FUNCTION.
+
+2020-10-02 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (cp_fname_init): Delete declaration.
+ * decl.c (cp_fname_init): Merge into only caller ...
+ (cp_make_fname): ... here & refactor.
+
+2020-10-02 Jason Merril <jason@redhat.com>
+
+ * call.c (build_operator_new_call): Set CALL_FROM_NEW_OR_DELETE_P.
+ (build_op_delete_call): Likewise.
+ * init.c (build_new_1, build_vec_delete_1, build_delete): Not here.
+ (build_delete):
+
+2020-10-02 Jason Merril <jason@redhat.com>
+
+ * lambda.c (call_from_lambda_thunk_p): New.
+ * cp-gimplify.c (cp_genericize_r): Use it.
+ * pt.c (tsubst_copy_and_build): Use it.
+ * typeck.c (check_return_expr): Use it.
+ * cp-tree.h: Declare it.
+ (CALL_FROM_NEW_OR_DELETE_P): Move to gcc/tree.h.
+
+2020-10-01 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (DECL_ANTICIPATED): Adjust comment.
+ (DECL_HIDDEN_P, TYPE_HIDDEN_P): Delete.
+ * tree.c (ovl_insert): Delete DECL_HIDDEN_P assert.
+ (ovl_skip_hidden): Likewise.
+
+2020-10-01 Nathan Sidwell <nathan@acm.org>
+
+ * name-lookup.c (pushdecl_top_level): Assert incoming context is
+ null, add global_namespace context.
+ (pushdecl_top_level_and_finish): Likewise.
+ * pt.c (get_template_parm_object): Clear decl context before
+ pushing.
+ * semantics.c (finish_compound_literal): Likewise.
+
+2020-10-01 Nathan Sidwell <nathan@acm.org>
+
+ * decl.c (lookup_and_check_tag): Refactor.
+
+2020-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/96994
+ * call.c (build_over_call): If obj_arg is non-NULL, return INIT_EXPR
+ setting obj_arg to call.
+
+2020-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/97195
+ * constexpr.c (cxx_eval_call_expression): Don't VERIFY_CONSTANT the
+ second argument.
+
+2020-10-01 Marek Polacek <polacek@redhat.com>
+
+ PR c++/90210
+ * pt.c (do_class_deduction): Don't prune explicit deduction guides
+ in copy-list-initialization. In copy-list-initialization, if an
+ explicit deduction guide was selected, give an error.
+
+2020-09-30 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (struct lang_decl_fn): Remove hidden_friend_p.
+ (DECL_HIDDEN_FRIEND_P): Delete.
+ * call.c (add_function_candidate): Drop assert about anticipated
+ decl.
+ (build_new_op_1): Drop koenig lookup flagging for hidden friend.
+ * decl.c (duplicate_decls): Drop HIDDEN_FRIEND_P updating.
+ * name-lookup.c (do_pushdecl): Likewise.
+ (set_decl_namespace): Discover hiddenness from OVL_HIDDEN_P.
+ * pt.c (check_explicit_specialization): Record found_hidden
+ explicitly.
+
+2020-09-29 Marek Polacek <polacek@redhat.com>
+
+ PR c++/94695
+ * call.c (ref_conv_binds_directly_p): New function.
+ * cp-tree.h (ref_conv_binds_directly_p): Declare.
+ * parser.c (warn_for_range_copy): New function.
+ (cp_convert_range_for): Call it.
+
+2020-09-29 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (ovl_insert): Change final parm to hidden-or-using
+ indicator.
+ * name-lookup.h (HIDDEN_TYPE_BINDING_P): New.
+ (struct cxx_binding): Add type_is_hidden flag.
+ * tree.c (ovl_insert): Change using_p parm to using_or_hidden,
+ adjust.
+ (ovl_skip_hidden): Assert we never see a naked hidden decl.
+ * decl.c (xref_tag_1): Delete unhiding friend from here (moved to
+ lookup_elaborated_type_1).
+ * name-lookup.c (STAT_TYPE_HIDDEN_P, STAT_DECL_HIDDEN_P): New.
+ (name_lookup::search_namespace_only): Check new hidden markers.
+ (cxx_binding_make): Clear HIDDEN_TYPE_BINDING_P.
+ (update_binding): Update new hidden markers.
+ (lookup_name_1): Check HIDDEN_TYPE_BINDING_P and simplify friend
+ ignoring.
+ (lookup_elaborated_type_1): Use new hidden markers. Reveal the
+ decl here.
+
+2020-09-29 Nathan Sidwell <nathan@acm.org>
+
+ * name-lookup.c (create_local_binding): Do not clear
+ INHERITED_VALUE_BINDING_P here.
+ (name_lookup::process_binding): Move done hidden-decl triage to ...
+ (name_lookup::search_namespace_only): ... here, its only caller.
+ (cxx_binding_make): Clear flags here.
+ (push_binding): Not here.
+ (pop_local_binding): RAII.
+ (update_binding): Refactor.
+ (do_pushdecl): Assert we're never revealing a local binding.
+ (do_pushdecl_with_scope): Directly call do_pushdecl.
+ (get_class_binding): Do not clear LOCAL_BINDING_P here.
+ * pt.c (push_template_decl): Set friend & anticipated before
+ pushing.
+
+2020-09-29 Nathan Sidwell <nathan@acm.org>
+
+ * name-lookup.c (update_binding): We never meet two implicit
+ typedefs.
+ (do_pushdecl): Adjust set_identifier_type_value_with_scope calls.
+ (set_identifier_type_value_with_scope): Do not update binding in
+ the namespace-case. Assert it is already there.
+
+2020-09-25 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (duplicate_decls): Replace 'is_friend' with 'hiding'
+ and add 'was_hidden'.
+ * name-lookup.h (pushdecl_namespace_level): Replace 'is_friend'
+ with 'hiding'.
+ (pushdecl): Likewise.
+ (pushdecl_top_level): Drop is_friend parm.
+ * decl.c (check_no_redeclaration_friend_default_args): Rename parm
+ olddelc_hidden_p.
+ (duplicate_decls): Replace 'is_friend' with 'hiding'
+ and 'was_hidden'. Do minimal adjustments in body.
+ (cxx_builtin_function): Pass 'hiding' to pushdecl.
+ * friend.c (do_friend): Pass 'hiding' to pushdecl.
+ * name-lookup.c (supplement_binding_1): Drop defaulted arg to
+ duplicate_decls.
+ (update_binding): Replace 'is_friend' with 'hiding'. Drop
+ defaulted arg to duplicate_decls.
+ (do_pushdecl): Replace 'is_friend' with 'hiding'. Assert no
+ surprise hidhing. Adjust duplicate_decls calls to inform of old
+ decl's hiddennes.
+ (pushdecl): Replace 'is_friend' with 'hiding'.
+ (set_identifier_type_value_with_scope): Adjust update_binding
+ call.
+ (do_pushdecl_with_scope): Replace 'is_friend' with 'hiding'.
+ (pushdecl_outermost_localscope): Drop default arg to
+ do_pushdecl_with_scope.
+ (pushdecl_namespace_level): Replace 'is_friend' with 'hiding'.
+ (pushdecl_top_level): Drop is_friend parm.
+ * pt.c (register_specialization): Comment duplicate_decls call
+ args.
+ (push_template_decl): Commont pushdecl_namespace_level.
+ (tsubst_friend_function, tsubst_friend_class): Likewise.
+
+2020-09-25 Nathan Sidwell <nathan@acm.org>
+
+ * name-lookup.h (enum tag_scope): Replace with ...
+ (enum class TAG_how): ... this. Add HIDDEN_FRIEND value.
+ (lookup_type_scope): Replace with ...
+ (lookup_elaborated_type): ... this.
+ (pushtag): Use TAG_how, not tag_scope.
+ * cp-tree.h (xref_tag): Parameter is TAG_how, not tag_scope.
+ * decl.c (lookup_and_check_tag): Likewise. Adjust.
+ (xref_tag_1, xref_tag): Likewise. adjust.
+ (start_enum): Adjust lookup_and_check_tag call.
+ * name-lookup.c (lookup_type_scope_1): Rename to ...
+ (lookup_elaborated_type_1) ... here. Use TAG_how, not tag_scope.
+ (lookup_type_scope): Rename to ...
+ (lookup_elaborated_type): ... here. Use TAG_how, not tag_scope.
+ (do_pushtag): Use TAG_how, not tag_scope. Adjust.
+ (pushtag): Likewise.
+ * parser.c (cp_parser_elaborated_type_specifier): Adjust.
+ (cp_parser_class_head): Likewise.
+
+2020-09-25 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (DECL_BUILTIN_P): New.
+ * decl.c (duplicate_decls): Use it. Do not treat omp-udr as a
+ builtin.
+ * name-lookup.c (anticipated_builtin): Use it.
+ (set_decl_context_in_fn): Function-scope OMP UDRs have function context.
+ (do_nonmember_using_decl): Use DECL_BUILTIN_P.
+ * parser.c (cp_parser_omp_declare_reduction): Function-scope OMP
+ UDRs have function context. Assert we never find a valid duplicate.
+ * pt.c (tsubst_expr): Function-scope OMP UDRs have function context.
+
+2020-09-24 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (duplicate_decls): Default is_friend to false.
+ (xref_tag): Default tag_scope & tpl_header_p to ts_current & false.
+ (push_template_decl_real): Default is_friend to false. Rename to
+ ...
+ (push_template_decl): ... here. Delete original decl.
+ * name-lookup.h (pushdecl_namespace_level): Default is_friend to
+ false.
+ (pushtag): Default tag_scope to ts_current.
+ * coroutines.cc (morph_fn_to_coro): Drop default args to xref_tag.
+ * decl.c (start_decl): Drop default args to duplicate_decls.
+ (start_enum): Drop default arg to pushtag & xref_tag.
+ (start_preparsed_function): Pass DECL_FRIEND_P to
+ push_template_decl.
+ (grokmethod): Likewise.
+ * friend.c (do_friend): Rename push_template_decl_real calls.
+ * lambda.c (begin_lamnbda_type): Drop default args to xref_tag.
+ (vla_capture_type): Likewise.
+ * name-lookup.c (maybe_process_template_type_declaration): Rename
+ push_template_decl_real call.
+ (pushdecl_top_level_and_finish): Drop default arg to
+ pushdecl_namespace_level.
+ * pt.c (push_template_decl_real): Assert no surprising friend
+ functions. Rename to ...
+ (push_template_decl): ... here. Delete original function.
+ (lookup_template_class_1): Drop default args from pushtag.
+ (instantiate_class_template_1): Likewise.
+ * ptree.c (debug_overload): Print hidden and using markers.
+ * rtti.c (init_rtti_processing): Drop refault args from xref_tag.
+ (build_dynamic_cast_1, tinfo_base_init): Likewise.
+ * semantics.c (begin_class_definition): Drop default args to
+ pushtag.
+
+2020-09-24 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/97186
+ * pt.c (maybe_instantiate_noexcept): Local externs are never
+ member fns.
+
+2020-09-23 Nathan Sidwell <nathan@acm.org>
+
+ * name-lookup.h (typedef cxx_binding): Delete tdef.
+ (typedef cp_binding_level): Likewise.
+ (struct cxx_binding): Flags are bools.
+
+2020-09-23 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/97171
+ * pt.c (tsubst_copy) [FUNCTION_DECL,VAR_DECL]: Retrieve local
+ specialization for DECL_LOCAL_P decls.
+
+2020-09-22 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/95310
+ * pt.c (corresponding_template_parameter): Define.
+ (keep_template_parm): Use it to adjust the given template
+ parameter to the corresponding in-scope one from ctx_parms.
+
+2020-09-22 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (xref_tag_from_type): Don't declare.
+ * decl.c (xref_tag_from_type): Delete.
+ * pt.c (lookup_template_class_1): Erroneously located class
+ definitions just give error_mark, don't try and inject it into the
+ namespace.
+
+2020-09-22 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/97145
+ * constexpr.c (cxx_eval_builtin_function_call): Return void_node for
+ calls to __sanitize_ptr_{sub,cmp} builtins.
+
+2020-09-22 Nathan Sidwell <nathan@acm.org>
+
+ * pt.c (instantiate_class_template_1): Do not repush and unhide
+ injected friend.
+
+2020-09-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/90583
+ DR 1722
+ * lambda.c (maybe_add_lambda_conv_op): Mark the conversion function
+ as noexcept.
+
+2020-09-21 Marek Polacek <polacek@redhat.com>
+
+ * pt.c (deduction_guides_for): Add a bool parameter. Set it.
+ (do_class_deduction): Warn when CTAD succeeds but the type doesn't
+ have any explicit deduction guides.
+
+2020-09-21 Nathan Sidwell <nathan@acm.org>
+
+ * decl.c (xref_tag_1): Use IDENTIFIER_LAMBDA_P to detect lambdas.
+ * lambda.c (begin_lambda_type): Use ts_current to push the tag.
+ * name-lookup.h (enum tag_scope): Drop ts_lambda.
+
+2020-09-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97099
+ * decl.c (redeclaration_error_message): Detect a redeclaration of
+ deduction guides.
+
2020-09-19 Sandra Loosemore <sandra@codesourcery.com>
* cp-gimplify.c (enum bc_t, bc_label): Move to c-family.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 5606389..bd66251 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -2220,11 +2220,6 @@ add_function_candidate (struct z_candidate **candidates,
int viable = 1;
struct rejection_reason *reason = NULL;
- /* At this point we should not see any functions which haven't been
- explicitly declared, except for friend functions which will have
- been found using argument dependent lookup. */
- gcc_assert (!DECL_ANTICIPATED (fn) || DECL_HIDDEN_FRIEND_P (fn));
-
/* The `this', `in_chrg' and VTT arguments to constructors are not
considered in overload resolution. */
if (DECL_CONSTRUCTOR_P (fn))
@@ -4774,7 +4769,16 @@ build_operator_new_call (tree fnname, vec<tree, va_gc> **args,
*fn = cand->fn;
/* Build the CALL_EXPR. */
- return build_over_call (cand, LOOKUP_NORMAL, complain);
+ tree ret = build_over_call (cand, LOOKUP_NORMAL, complain);
+
+ /* Set this flag for all callers of this function. In addition to
+ new-expressions, this is called for allocating coroutine state; treat
+ that as an implicit new-expression. */
+ tree call = extract_call_expr (ret);
+ if (TREE_CODE (call) == CALL_EXPR)
+ CALL_FROM_NEW_OR_DELETE_P (call) = 1;
+
+ return ret;
}
/* Build a new call to operator(). This may change ARGS. */
@@ -6151,7 +6155,7 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags,
case VEC_NEW_EXPR:
case VEC_DELETE_EXPR:
case DELETE_EXPR:
- /* Use build_op_new_call and build_op_delete_call instead. */
+ /* Use build_operator_new_call and build_op_delete_call instead. */
gcc_unreachable ();
case CALL_EXPR:
@@ -6344,11 +6348,6 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags,
tree call = extract_call_expr (result);
CALL_EXPR_OPERATOR_SYNTAX (call) = true;
- if (processing_template_decl && DECL_HIDDEN_FRIEND_P (cand->fn))
- /* This prevents build_new_function_call from discarding this
- function during instantiation of the enclosing template. */
- KOENIG_LOOKUP_P (call) = 1;
-
/* Specify evaluation order as per P0145R2. */
CALL_EXPR_ORDERED_ARGS (call) = false;
switch (op_is_ordered (code))
@@ -6993,6 +6992,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
if (DECL_DELETED_FN (fn) && alloc_fn)
return NULL_TREE;
+ tree ret;
if (placement)
{
/* The placement args might not be suitable for overload
@@ -7005,7 +7005,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
argarray[i] = CALL_EXPR_ARG (placement, i);
if (!mark_used (fn, complain) && !(complain & tf_error))
return error_mark_node;
- return build_cxx_call (fn, nargs, argarray, complain);
+ ret = build_cxx_call (fn, nargs, argarray, complain);
}
else
{
@@ -7023,7 +7023,6 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
complain);
}
- tree ret;
releasing_vec args;
args->quick_push (addr);
if (destroying)
@@ -7036,8 +7035,18 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
args->quick_push (al);
}
ret = cp_build_function_call_vec (fn, &args, complain);
- return ret;
}
+
+ /* Set this flag for all callers of this function. In addition to
+ delete-expressions, this is called for deallocating coroutine state;
+ treat that as an implicit delete-expression. This is also called for
+ the delete if the constructor throws in a new-expression, and for a
+ deleting destructor (which implements a delete-expression). */
+ tree call = extract_call_expr (ret);
+ if (TREE_CODE (call) == CALL_EXPR)
+ CALL_FROM_NEW_OR_DELETE_P (call) = 1;
+
+ return ret;
}
/* [expr.new]
@@ -8429,6 +8438,28 @@ conv_binds_ref_to_prvalue (conversion *c)
return false;
}
+/* True iff converting EXPR to a reference type TYPE does not involve
+ creating a temporary. */
+
+bool
+ref_conv_binds_directly_p (tree type, tree expr)
+{
+ gcc_assert (TYPE_REF_P (type));
+
+ /* Get the high-water mark for the CONVERSION_OBSTACK. */
+ void *p = conversion_obstack_alloc (0);
+
+ conversion *conv = implicit_conversion (type, TREE_TYPE (expr), expr,
+ /*c_cast_p=*/false,
+ LOOKUP_IMPLICIT, tf_none);
+ bool ret = conv && !conv->bad_p && !conv_binds_ref_to_prvalue (conv);
+
+ /* Free all the conversions we allocated. */
+ obstack_free (&conversion_obstack, p);
+
+ return ret;
+}
+
/* Call the trivial destructor for INSTANCE, which can be either an lvalue of
class type or a pointer to class type. If NO_PTR_DEREF is true and
INSTANCE has pointer type, clobber the pointer rather than what it points
@@ -9200,6 +9231,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
}
}
call = cxx_constant_value (call, obj_arg);
+ if (obj_arg && !error_operand_p (call))
+ call = build2 (INIT_EXPR, void_type_node, obj_arg, call);
}
}
return call;
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index c9a1f75..26f996b 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1006,10 +1006,6 @@ add_method (tree type, tree method, bool via_using)
for (ovl_iterator iter (current_fns); iter; ++iter)
{
tree fn = *iter;
- tree fn_type;
- tree method_type;
- tree parms1;
- tree parms2;
if (TREE_CODE (fn) != TREE_CODE (method))
continue;
@@ -1037,10 +1033,8 @@ add_method (tree type, tree method, bool via_using)
functions in the derived class override and/or hide member
functions with the same name and parameter types in a base
class (rather than conflicting). */
- fn_type = TREE_TYPE (fn);
- method_type = TREE_TYPE (method);
- parms1 = TYPE_ARG_TYPES (fn_type);
- parms2 = TYPE_ARG_TYPES (method_type);
+ tree fn_type = TREE_TYPE (fn);
+ tree method_type = TREE_TYPE (method);
/* Compare the quals on the 'this' parm. Don't compare
the whole types, as used functions are treated as
@@ -1055,137 +1049,149 @@ add_method (tree type, tree method, bool via_using)
|| type_memfn_rqual (fn_type) != type_memfn_rqual (method_type)))
continue;
- /* For templates, the return type and template parameters
- must be identical. */
- if (TREE_CODE (fn) == TEMPLATE_DECL
- && (!same_type_p (TREE_TYPE (fn_type),
- TREE_TYPE (method_type))
- || !comp_template_parms (DECL_TEMPLATE_PARMS (fn),
- DECL_TEMPLATE_PARMS (method))))
+ tree real_fn = fn;
+ tree real_method = method;
+
+ /* Templates and conversion ops must match return types. */
+ if ((DECL_CONV_FN_P (fn) || TREE_CODE (fn) == TEMPLATE_DECL)
+ && !same_type_p (TREE_TYPE (fn_type), TREE_TYPE (method_type)))
continue;
+
+ /* For templates, the template parameters must be identical. */
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ {
+ if (!comp_template_parms (DECL_TEMPLATE_PARMS (fn),
+ DECL_TEMPLATE_PARMS (method)))
+ continue;
- if (! DECL_STATIC_FUNCTION_P (fn))
+ real_fn = DECL_TEMPLATE_RESULT (fn);
+ real_method = DECL_TEMPLATE_RESULT (method);
+ }
+
+ tree parms1 = TYPE_ARG_TYPES (fn_type);
+ tree parms2 = TYPE_ARG_TYPES (method_type);
+ if (! DECL_STATIC_FUNCTION_P (real_fn))
parms1 = TREE_CHAIN (parms1);
- if (! DECL_STATIC_FUNCTION_P (method))
+ if (! DECL_STATIC_FUNCTION_P (real_method))
parms2 = TREE_CHAIN (parms2);
- /* Bring back parameters omitted from an inherited ctor. */
- if (ctor_omit_inherited_parms (fn))
- parms1 = FUNCTION_FIRST_USER_PARMTYPE (DECL_ORIGIN (fn));
- if (ctor_omit_inherited_parms (method))
- parms2 = FUNCTION_FIRST_USER_PARMTYPE (DECL_ORIGIN (method));
+ /* Bring back parameters omitted from an inherited ctor. The
+ method and the function can have different omittedness. */
+ if (ctor_omit_inherited_parms (real_fn))
+ parms1 = FUNCTION_FIRST_USER_PARMTYPE (DECL_CLONED_FUNCTION (real_fn));
+ if (ctor_omit_inherited_parms (real_method))
+ parms2 = (FUNCTION_FIRST_USER_PARMTYPE
+ (DECL_CLONED_FUNCTION (real_method)));
- if (compparms (parms1, parms2)
- && (!DECL_CONV_FN_P (fn)
- || same_type_p (TREE_TYPE (fn_type),
- TREE_TYPE (method_type))))
- {
- if (!equivalently_constrained (fn, method))
- {
- if (processing_template_decl)
- /* We can't check satisfaction in dependent context, wait until
- the class is instantiated. */
- continue;
-
- special_function_kind sfk = special_memfn_p (method);
+ if (!compparms (parms1, parms2))
+ continue;
- if (sfk == sfk_none
- || DECL_INHERITED_CTOR (fn)
- || TREE_CODE (fn) == TEMPLATE_DECL)
- /* Member function templates and non-special member functions
- coexist if they are not equivalently constrained. A member
- function is not hidden by an inherited constructor. */
- continue;
+ if (!equivalently_constrained (fn, method))
+ {
+ if (processing_template_decl)
+ /* We can't check satisfaction in dependent context, wait until
+ the class is instantiated. */
+ continue;
- /* P0848: For special member functions, deleted, unsatisfied, or
- less constrained overloads are ineligible. We implement this
- by removing them from CLASSTYPE_MEMBER_VEC. Destructors don't
- use the notion of eligibility, and the selected destructor can
- be deleted, but removing unsatisfied or less constrained
- overloads has the same effect as overload resolution. */
- bool dtor = (sfk == sfk_destructor);
- if (losem == -1)
- losem = ((!dtor && DECL_DELETED_FN (method))
- || !constraints_satisfied_p (method));
- bool losef = ((!dtor && DECL_DELETED_FN (fn))
- || !constraints_satisfied_p (fn));
- int win;
- if (losem || losef)
- win = losem - losef;
- else
- win = more_constrained (fn, method);
- if (win > 0)
- /* Leave FN in the method vec, discard METHOD. */
- return false;
- else if (win < 0)
- {
- /* Remove FN, add METHOD. */
- current_fns = iter.remove_node (current_fns);
- continue;
- }
- else
- /* Let them coexist for now. */
- continue;
- }
+ special_function_kind sfk = special_memfn_p (method);
- /* If these are versions of the same function, process and
- move on. */
- if (TREE_CODE (fn) == FUNCTION_DECL
- && maybe_version_functions (method, fn, true))
+ if (sfk == sfk_none
+ || DECL_INHERITED_CTOR (fn)
+ || TREE_CODE (fn) == TEMPLATE_DECL)
+ /* Member function templates and non-special member functions
+ coexist if they are not equivalently constrained. A member
+ function is not hidden by an inherited constructor. */
continue;
- if (DECL_INHERITED_CTOR (method))
- {
- if (DECL_INHERITED_CTOR (fn))
- {
- tree basem = DECL_INHERITED_CTOR_BASE (method);
- tree basef = DECL_INHERITED_CTOR_BASE (fn);
- if (flag_new_inheriting_ctors)
- {
- if (basem == basef)
- {
- /* Inheriting the same constructor along different
- paths, combine them. */
- SET_DECL_INHERITED_CTOR
- (fn, ovl_make (DECL_INHERITED_CTOR (method),
- DECL_INHERITED_CTOR (fn)));
- /* And discard the new one. */
- return false;
- }
- else
- /* Inherited ctors can coexist until overload
- resolution. */
- continue;
- }
- error_at (DECL_SOURCE_LOCATION (method),
- "%q#D conflicts with version inherited from %qT",
- method, basef);
- inform (DECL_SOURCE_LOCATION (fn),
- "version inherited from %qT declared here",
- basef);
- }
- /* Otherwise defer to the other function. */
- return false;
- }
-
- if (via_using)
- /* Defer to the local function. */
+ /* P0848: For special member functions, deleted, unsatisfied, or
+ less constrained overloads are ineligible. We implement this
+ by removing them from CLASSTYPE_MEMBER_VEC. Destructors don't
+ use the notion of eligibility, and the selected destructor can
+ be deleted, but removing unsatisfied or less constrained
+ overloads has the same effect as overload resolution. */
+ bool dtor = (sfk == sfk_destructor);
+ if (losem == -1)
+ losem = ((!dtor && DECL_DELETED_FN (method))
+ || !constraints_satisfied_p (method));
+ bool losef = ((!dtor && DECL_DELETED_FN (fn))
+ || !constraints_satisfied_p (fn));
+ int win;
+ if (losem || losef)
+ win = losem - losef;
+ else
+ win = more_constrained (fn, method);
+ if (win > 0)
+ /* Leave FN in the method vec, discard METHOD. */
return false;
- else if (flag_new_inheriting_ctors
- && DECL_INHERITED_CTOR (fn))
+ else if (win < 0)
{
- /* Remove the inherited constructor. */
+ /* Remove FN, add METHOD. */
current_fns = iter.remove_node (current_fns);
continue;
}
else
+ /* Let them coexist for now. */
+ continue;
+ }
+
+ /* If these are versions of the same function, process and
+ move on. */
+ if (TREE_CODE (fn) == FUNCTION_DECL
+ && maybe_version_functions (method, fn, true))
+ continue;
+
+ if (DECL_INHERITED_CTOR (method))
+ {
+ if (!DECL_INHERITED_CTOR (fn))
+ /* Defer to the other function. */
+ return false;
+
+ tree basem = DECL_INHERITED_CTOR_BASE (method);
+ tree basef = DECL_INHERITED_CTOR_BASE (fn);
+ if (flag_new_inheriting_ctors)
{
- error_at (DECL_SOURCE_LOCATION (method),
- "%q#D cannot be overloaded with %q#D", method, fn);
- inform (DECL_SOURCE_LOCATION (fn),
- "previous declaration %q#D", fn);
- return false;
+ if (basem == basef)
+ {
+ /* Inheriting the same constructor along different
+ paths, combine them. */
+ SET_DECL_INHERITED_CTOR
+ (fn, ovl_make (DECL_INHERITED_CTOR (method),
+ DECL_INHERITED_CTOR (fn)));
+ /* And discard the new one. */
+ return false;
+ }
+ else
+ /* Inherited ctors can coexist until overload
+ resolution. */
+ continue;
}
+
+ error_at (DECL_SOURCE_LOCATION (method),
+ "%q#D conflicts with version inherited from %qT",
+ method, basef);
+ inform (DECL_SOURCE_LOCATION (fn),
+ "version inherited from %qT declared here",
+ basef);
+ return false;
+ }
+
+ if (via_using)
+ /* Defer to the local function. */
+ return false;
+ else if (flag_new_inheriting_ctors
+ && DECL_INHERITED_CTOR (fn))
+ {
+ /* Remove the inherited constructor. */
+ current_fns = iter.remove_node (current_fns);
+ continue;
+ }
+ else
+ {
+ error_at (DECL_SOURCE_LOCATION (method),
+ "%q#D cannot be overloaded with %q#D", method, fn);
+ inform (DECL_SOURCE_LOCATION (fn),
+ "previous declaration %q#D", fn);
+ return false;
}
}
@@ -3277,7 +3283,8 @@ add_implicitly_declared_members (tree t, tree* access_decls,
{
tree eq = implicitly_declare_fn (sfk_comparison, t, false, space,
NULL_TREE);
- if (DECL_FRIEND_P (space))
+ bool is_friend = DECL_CONTEXT (space) != t;
+ if (is_friend)
do_friend (NULL_TREE, DECL_NAME (eq), eq,
NULL_TREE, NO_SPECIAL, true);
else
@@ -3286,7 +3293,7 @@ add_implicitly_declared_members (tree t, tree* access_decls,
DECL_CHAIN (eq) = TYPE_FIELDS (t);
TYPE_FIELDS (t) = eq;
}
- maybe_add_class_template_decl_list (t, eq, DECL_FRIEND_P (space));
+ maybe_add_class_template_decl_list (t, eq, is_friend);
}
while (*access_decls)
@@ -4892,7 +4899,7 @@ build_clone (tree fn, tree name, bool need_vtt_parm_p,
will be inserted onto DECL_CHAIN of FN. */
static unsigned
-build_cdtor_clones (tree fn, bool needs_vtt_parm_p, bool omit_inherited_parms_p)
+build_cdtor_clones (tree fn, bool needs_vtt_p, bool base_omits_inherited_p)
{
unsigned count = 0;
@@ -4901,8 +4908,8 @@ build_cdtor_clones (tree fn, bool needs_vtt_parm_p, bool omit_inherited_parms_p)
/* For each constructor, we need two variants: an in-charge version
and a not-in-charge version. */
build_clone (fn, complete_ctor_identifier, false, false);
- build_clone (fn, base_ctor_identifier, needs_vtt_parm_p,
- omit_inherited_parms_p);
+ build_clone (fn, base_ctor_identifier, needs_vtt_p,
+ base_omits_inherited_p);
count += 2;
}
else
@@ -4924,7 +4931,7 @@ build_cdtor_clones (tree fn, bool needs_vtt_parm_p, bool omit_inherited_parms_p)
count++;
}
build_clone (fn, complete_dtor_identifier, false, false);
- build_clone (fn, base_dtor_identifier, needs_vtt_parm_p, false);
+ build_clone (fn, base_dtor_identifier, needs_vtt_p, false);
count += 2;
}
@@ -4948,9 +4955,10 @@ clone_cdtor (tree fn, bool update_methods)
/* Base ctor omits inherited parms it needs a vttparm and inherited
from a virtual nase ctor. */
- bool omit_inherited = ctor_omit_inherited_parms (fn);
+ bool base_omits_inherited = (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)
+ && base_ctor_omit_inherited_parms (fn));
- unsigned count = build_cdtor_clones (fn, vtt, omit_inherited);
+ unsigned count = build_cdtor_clones (fn, vtt, base_omits_inherited);
/* Note that this is an abstract function that is never emitted. */
DECL_ABSTRACT_P (fn) = true;
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 72fbdab..7ebdd30 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1355,6 +1355,12 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
case BUILT_IN_STRSTR:
strops = 2;
strret = 1;
+ break;
+ case BUILT_IN_ASAN_POINTER_COMPARE:
+ case BUILT_IN_ASAN_POINTER_SUBTRACT:
+ /* These builtins shall be ignored during constant expression
+ evaluation. */
+ return void_node;
default:
break;
}
@@ -2336,9 +2342,10 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
tree arg = CALL_EXPR_ARG (t, i);
arg = cxx_eval_constant_expression (ctx, arg, false,
non_constant_p, overflow_p);
- VERIFY_CONSTANT (arg);
if (i == 1)
arg1 = arg;
+ else
+ VERIFY_CONSTANT (arg);
}
gcc_assert (arg1);
return arg1;
@@ -3650,15 +3657,22 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
initializer, it's initialized from {}. But use build_value_init
directly for non-aggregates to avoid creating a garbage CONSTRUCTOR. */
tree val;
+ constexpr_ctx new_ctx;
if (CP_AGGREGATE_TYPE_P (elem_type))
{
tree empty_ctor = build_constructor (init_list_type_node, NULL);
val = digest_init (elem_type, empty_ctor, tf_warning_or_error);
+ new_ctx = *ctx;
+ new_ctx.ctor = build_constructor (elem_type, NULL);
+ ctx = &new_ctx;
}
else
val = build_value_init (elem_type, tf_warning_or_error);
- return cxx_eval_constant_expression (ctx, val, lval, non_constant_p,
- overflow_p);
+ t = cxx_eval_constant_expression (ctx, val, lval, non_constant_p,
+ overflow_p);
+ if (CP_AGGREGATE_TYPE_P (elem_type) && t != ctx->ctor)
+ free_constructor (ctx->ctor);
+ return t;
}
/* Subroutine of cxx_eval_constant_expression.
@@ -3947,7 +3961,8 @@ init_subob_ctx (const constexpr_ctx *ctx, constexpr_ctx &new_ctx,
new_ctx = *ctx;
if (index && TREE_CODE (index) != INTEGER_CST
- && TREE_CODE (index) != FIELD_DECL)
+ && TREE_CODE (index) != FIELD_DECL
+ && TREE_CODE (index) != RANGE_EXPR)
/* This won't have an element in the new CONSTRUCTOR. */
return;
@@ -3960,7 +3975,13 @@ init_subob_ctx (const constexpr_ctx *ctx, constexpr_ctx &new_ctx,
update object to refer to the subobject and ctor to refer to
the (newly created) sub-initializer. */
if (ctx->object)
- new_ctx.object = build_ctor_subob_ref (index, type, ctx->object);
+ {
+ if (index == NULL_TREE || TREE_CODE (index) == RANGE_EXPR)
+ /* There's no well-defined subobject for this index. */
+ new_ctx.object = NULL_TREE;
+ else
+ new_ctx.object = build_ctor_subob_ref (index, type, ctx->object);
+ }
tree elt = build_constructor (type, NULL);
CONSTRUCTOR_NO_CLEARING (elt) = true;
new_ctx.ctor = elt;
@@ -6396,9 +6417,9 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
break;
case EMPTY_CLASS_EXPR:
- /* This is good enough for a function argument that might not get
- used, and they can't do anything with it, so just return it. */
- return t;
+ /* Handle EMPTY_CLASS_EXPR produced by build_call_a by lowering
+ it to an appropriate CONSTRUCTOR. */
+ return build_constructor (TREE_TYPE (t), NULL);
case STATEMENT_LIST:
new_ctx = *ctx;
@@ -8179,13 +8200,11 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case COMPOUND_EXPR:
{
/* check_return_expr sometimes wraps a TARGET_EXPR in a
- COMPOUND_EXPR; don't get confused. Also handle EMPTY_CLASS_EXPR
- introduced by build_call_a. */
+ COMPOUND_EXPR; don't get confused. */
tree op0 = TREE_OPERAND (t, 0);
tree op1 = TREE_OPERAND (t, 1);
STRIP_NOPS (op1);
- if ((TREE_CODE (op0) == TARGET_EXPR && op1 == TARGET_EXPR_SLOT (op0))
- || TREE_CODE (op1) == EMPTY_CLASS_EXPR)
+ if (TREE_CODE (op0) == TARGET_EXPR && op1 == TARGET_EXPR_SLOT (op0))
return RECUR (op0, want_rval);
else
goto binary;
@@ -8314,7 +8333,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
return true;
case EMPTY_CLASS_EXPR:
- return false;
+ return true;
case GOTO_EXPR:
{
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index d49957a..f4f5174 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -1201,7 +1201,7 @@ set_constraints (tree t, tree ci)
void
remove_constraints (tree t)
{
- gcc_assert (DECL_P (t));
+ gcc_checking_assert (DECL_P (t));
if (TREE_CODE (t) == TEMPLATE_DECL)
t = DECL_TEMPLATE_RESULT (t);
@@ -1217,11 +1217,16 @@ maybe_substitute_reqs_for (tree reqs, const_tree decl_)
{
if (reqs == NULL_TREE)
return NULL_TREE;
+
tree decl = CONST_CAST_TREE (decl_);
tree result = STRIP_TEMPLATE (decl);
- if (DECL_FRIEND_P (result))
+
+ if (DECL_UNIQUE_FRIEND_P (result))
{
- tree tmpl = decl == result ? DECL_TI_TEMPLATE (result) : decl;
+ tree tmpl = decl;
+ if (TREE_CODE (decl) != TEMPLATE_DECL)
+ tmpl = DECL_TI_TEMPLATE (result);
+
tree gargs = generic_targs_for (tmpl);
processing_template_decl_sentinel s;
if (uses_template_parms (gargs))
@@ -1427,7 +1432,9 @@ tree
build_type_constraint (tree decl, tree args, tsubst_flags_t complain)
{
tree wildcard = build_nt (WILDCARD_DECL);
+ ++processing_template_decl;
tree check = build_concept_check (decl, wildcard, args, complain);
+ --processing_template_decl;
if (check == error_mark_node)
return error_mark_node;
return unpack_concept_check (check);
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 898b88b..9b9141e 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -94,6 +94,7 @@ struct GTY((for_user)) coroutine_info
/* Flags to avoid repeated errors for per-function issues. */
bool coro_ret_type_error_emitted;
bool coro_promise_error_emitted;
+ bool coro_co_return_error_emitted;
};
struct coroutine_info_hasher : ggc_ptr_hash<coroutine_info>
@@ -470,6 +471,30 @@ coro_promise_type_found_p (tree fndecl, location_t loc)
return false;
}
+ /* Test for errors in the promise type that can be determined now. */
+ tree has_ret_void = lookup_member (coro_info->promise_type,
+ coro_return_void_identifier,
+ /*protect=*/1, /*want_type=*/0,
+ tf_none);
+ tree has_ret_val = lookup_member (coro_info->promise_type,
+ coro_return_value_identifier,
+ /*protect=*/1, /*want_type=*/0,
+ tf_none);
+ if (has_ret_void && has_ret_val)
+ {
+ location_t ploc = DECL_SOURCE_LOCATION (fndecl);
+ if (!coro_info->coro_co_return_error_emitted)
+ error_at (ploc, "the coroutine promise type %qT declares both"
+ " %<return_value%> and %<return_void%>",
+ coro_info->promise_type);
+ inform (DECL_SOURCE_LOCATION (BASELINK_FUNCTIONS (has_ret_void)),
+ "%<return_void%> declared here");
+ inform (DECL_SOURCE_LOCATION (BASELINK_FUNCTIONS (has_ret_val)),
+ "%<return_value%> declared here");
+ coro_info->coro_co_return_error_emitted = true;
+ return false;
+ }
+
/* Try to find the handle type for the promise. */
tree handle_type =
instantiate_coro_handle_for_promise_type (loc, coro_info->promise_type);
@@ -4011,7 +4036,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
/* 2. Types we need to define or look up. */
tree fr_name = get_fn_local_identifier (orig, "frame");
- tree coro_frame_type = xref_tag (record_type, fr_name, ts_current, false);
+ tree coro_frame_type = xref_tag (record_type, fr_name);
DECL_CONTEXT (TYPE_NAME (coro_frame_type)) = current_scope ();
tree coro_frame_ptr = build_pointer_type (coro_frame_type);
tree act_des_fn_type
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index bc8a03c..44c9d24 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -962,7 +962,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
omp_cxx_notice_variable (wtd->omp_ctx, stmt);
/* Don't dereference parms in a thunk, pass the references through. */
- if ((TREE_CODE (stmt) == CALL_EXPR && CALL_FROM_THUNK_P (stmt))
+ if ((TREE_CODE (stmt) == CALL_EXPR && call_from_lambda_thunk_p (stmt))
|| (TREE_CODE (stmt) == AGGR_INIT_EXPR && AGGR_INIT_FROM_THUNK_P (stmt)))
{
*walk_subtrees = 0;
@@ -980,21 +980,17 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
/* Map block scope extern declarations to visible declarations with the
same name and type in outer scopes if any. */
- if (cp_function_chain->extern_decl_map
- && VAR_OR_FUNCTION_DECL_P (stmt)
- && DECL_EXTERNAL (stmt))
- {
- struct cxx_int_tree_map *h, in;
- in.uid = DECL_UID (stmt);
- h = cp_function_chain->extern_decl_map->find_with_hash (&in, in.uid);
- if (h)
- {
- *stmt_p = h->to;
- TREE_USED (h->to) |= TREE_USED (stmt);
- *walk_subtrees = 0;
- return NULL;
- }
- }
+ if (VAR_OR_FUNCTION_DECL_P (stmt) && DECL_LOCAL_DECL_P (stmt))
+ if (tree alias = DECL_LOCAL_DECL_ALIAS (stmt))
+ {
+ if (alias != error_mark_node)
+ {
+ *stmt_p = alias;
+ TREE_USED (alias) |= TREE_USED (stmt);
+ }
+ *walk_subtrees = 0;
+ return NULL;
+ }
if (TREE_CODE (stmt) == INTEGER_CST
&& TYPE_REF_P (TREE_TYPE (stmt))
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7135381..5c06ac3 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -464,7 +464,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
SWITCH_STMT_NO_BREAK_P (in SWITCH_STMT)
LAMBDA_EXPR_CAPTURE_OPTIMIZED (in LAMBDA_EXPR)
IMPLICIT_CONV_EXPR_BRACED_INIT (in IMPLICIT_CONV_EXPR)
- CALL_FROM_NEW_OR_DELETE_P (in CALL_EXPR)
3: IMPLICIT_RVALUE_P (in NON_LVALUE_EXPR or STATIC_CAST_EXPR)
ICS_BAD_FLAG (in _CONV)
FN_TRY_BLOCK_P (in TRY_BLOCK)
@@ -1927,7 +1926,6 @@ struct GTY(()) language_function {
/* Tracking possibly infinite loops. This is a vec<tree> only because
vec<bool> doesn't work with gtype. */
vec<tree, va_gc> *infinite_loops;
- hash_table<cxx_int_tree_map_hasher> *extern_decl_map;
};
/* The current C++-specific per-function global variables. */
@@ -2065,7 +2063,7 @@ enum languages { lang_c, lang_cplusplus };
#define CLASS_TYPE_P(T) \
(RECORD_OR_UNION_CODE_P (TREE_CODE (T)) && TYPE_LANG_FLAG_5 (T))
-/* Nonzero if T is a class type but not an union. */
+/* Nonzero if T is a class type but not a union. */
#define NON_UNION_CLASS_TYPE_P(T) \
(TREE_CODE (T) == RECORD_TYPE && TYPE_LANG_FLAG_5 (T))
@@ -2658,8 +2656,10 @@ struct GTY(()) lang_decl_base {
unsigned not_really_extern : 1; /* var or fn */
unsigned initialized_in_class : 1; /* var or fn */
unsigned threadprivate_or_deleted_p : 1; /* var or fn */
- unsigned anticipated_p : 1; /* fn, type or template */
- /* anticipated_p reused as DECL_OMP_PRIVATIZED_MEMBER in var */
+ /* anticipated_p is no longer used for anticipated_decls (fn, type
+ or template). It is used as DECL_OMP_PRIVATIZED_MEMBER in
+ var. */
+ unsigned anticipated_p : 1;
unsigned friend_or_tls : 1; /* var, fn, type or template */
unsigned unknown_bound_p : 1; /* var */
unsigned odr_used : 1; /* var or fn */
@@ -2696,6 +2696,7 @@ struct GTY(()) lang_decl_min {
In a lambda-capture proxy VAR_DECL, this is DECL_CAPTURED_VARIABLE.
In a function-scope TREE_STATIC VAR_DECL or IMPLICIT_TYPEDEF_P TYPE_DECL,
this is DECL_DISCRIMINATOR.
+ In a DECL_LOCAL_DECL_P decl, this is the namespace decl it aliases.
Otherwise, in a class-scope DECL, this is DECL_ACCESS. */
tree access;
};
@@ -2720,14 +2721,13 @@ struct GTY(()) lang_decl_fn {
unsigned thunk_p : 1;
unsigned this_thunk_p : 1;
- unsigned hidden_friend_p : 1;
unsigned omp_declare_reduction_p : 1;
unsigned has_dependent_explicit_spec_p : 1;
unsigned immediate_fn_p : 1;
unsigned maybe_deleted : 1;
unsigned coroutine_p : 1;
- unsigned spare : 9;
+ unsigned spare : 10;
/* 32-bits padding on 64-bit host. */
@@ -2736,12 +2736,14 @@ struct GTY(()) lang_decl_fn {
thunked to function decl. */
tree befriending_classes;
- /* For a non-virtual FUNCTION_DECL, this is
- DECL_FRIEND_CONTEXT. For a virtual FUNCTION_DECL for which
+ /* For a virtual FUNCTION_DECL for which
DECL_THIS_THUNK_P does not hold, this is DECL_THUNKS. Both
this pointer and result pointer adjusting thunks are
chained here. This pointer thunks to return pointer thunks
- will be chained on the return pointer thunk. */
+ will be chained on the return pointer thunk.
+ For a DECL_CONSTUCTOR_P FUNCTION_DECL, this is the base from
+ whence we inherit. Otherwise, it is the class in which a
+ (namespace-scope) friend is defined (if any). */
tree context;
union lang_decl_u5
@@ -3088,10 +3090,14 @@ struct GTY(()) lang_decl {
(DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL)) \
->u.base.odr_used)
-/* Nonzero for DECL means that this decl is just a friend declaration,
- and should not be added to the list of members for this class. */
-#define DECL_FRIEND_P(NODE) \
- (DECL_LANG_SPECIFIC (TYPE_FUNCTION_OR_TEMPLATE_DECL_CHECK (NODE)) \
+/* Nonzero for FUNCTION_DECL means that this is a friend that is
+ either not pushed into a namespace/looked up in a class (because it
+ is a dependent type, in an uninstantiated template), or it has
+ /only/ been subject to hidden friend injection from one or more
+ befriending classes. Once another decl matches, the flag is
+ cleared. There are requirements on its default parms. */
+#define DECL_UNIQUE_FRIEND_P(NODE) \
+ (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE)) \
->u.base.friend_or_tls)
/* Nonzero if the thread-local variable was declared with __thread as
@@ -3290,8 +3296,8 @@ struct GTY(()) lang_decl {
the DECL_FRIEND_CONTEXT for `f' will be `S'. */
#define DECL_FRIEND_CONTEXT(NODE) \
- ((DECL_DECLARES_FUNCTION_P (NODE) \
- && DECL_FRIEND_P (NODE) && !DECL_FUNCTION_MEMBER_P (NODE)) \
+ ((DECL_DECLARES_FUNCTION_P (NODE) && !DECL_VIRTUAL_P (NODE) \
+ && !DECL_CONSTRUCTOR_P (NODE)) \
? LANG_DECL_FN_CHECK (NODE)->context \
: NULL_TREE)
@@ -3840,11 +3846,6 @@ struct GTY(()) lang_decl {
should be performed at instantiation time. */
#define KOENIG_LOOKUP_P(NODE) TREE_LANG_FLAG_0 (CALL_EXPR_CHECK (NODE))
-/* In a CALL_EXPR, true for allocator calls from new or delete
- expressions. */
-#define CALL_FROM_NEW_OR_DELETE_P(NODE) \
- TREE_LANG_FLAG_2 (CALL_EXPR_CHECK (NODE))
-
/* True if the arguments to NODE should be evaluated in left-to-right
order regardless of PUSH_ARGS_REVERSED. */
#define CALL_EXPR_ORDERED_ARGS(NODE) \
@@ -4028,6 +4029,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define DECL_LOCAL_DECL_P(NODE) \
DECL_LANG_FLAG_0 (VAR_OR_FUNCTION_DECL_CHECK (NODE))
+/* The namespace-scope decl a DECL_LOCAL_DECL_P aliases. */
+#define DECL_LOCAL_DECL_ALIAS(NODE) \
+ DECL_ACCESS ((gcc_checking_assert (DECL_LOCAL_DECL_P (NODE)), NODE))
+
/* Nonzero if NODE is the target for genericization of 'return' stmts
in constructors/destructors of targetm.cxx.cdtor_returns_this targets. */
#define LABEL_DECL_CDTOR(NODE) \
@@ -4040,35 +4045,16 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define FNDECL_USED_AUTO(NODE) \
TREE_LANG_FLAG_2 (FUNCTION_DECL_CHECK (NODE))
-/* Nonzero if NODE is a DECL which we know about but which has not
- been explicitly declared, such as a built-in function or a friend
- declared inside a class. In the latter case DECL_HIDDEN_FRIEND_P
- will be set. */
-#define DECL_ANTICIPATED(NODE) \
- (DECL_LANG_SPECIFIC (TYPE_FUNCTION_OR_TEMPLATE_DECL_CHECK (NODE)) \
- ->u.base.anticipated_p)
-
-/* Is DECL NODE a hidden name? */
-#define DECL_HIDDEN_P(NODE) \
- (DECL_LANG_SPECIFIC (NODE) && TYPE_FUNCTION_OR_TEMPLATE_DECL_P (NODE) \
- && DECL_ANTICIPATED (NODE))
-
-/* True if this is a hidden class type. */
-#define TYPE_HIDDEN_P(NODE) \
- (DECL_LANG_SPECIFIC (TYPE_NAME (NODE)) \
- && DECL_ANTICIPATED (TYPE_NAME (NODE)))
+/* True if NODE is an undeclared builtin decl. As soon as the user
+ declares it, the location will be updated. */
+#define DECL_UNDECLARED_BUILTIN_P(NODE) \
+ (DECL_SOURCE_LOCATION(NODE) == BUILTINS_LOCATION)
/* True for artificial decls added for OpenMP privatized non-static
data members. */
#define DECL_OMP_PRIVATIZED_MEMBER(NODE) \
(DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))->u.base.anticipated_p)
-/* Nonzero if NODE is a FUNCTION_DECL which was declared as a friend
- within a class but has not been declared in the surrounding scope.
- The function is invisible except via argument dependent lookup. */
-#define DECL_HIDDEN_FRIEND_P(NODE) \
- (LANG_DECL_FN_CHECK (DECL_COMMON_CHECK (NODE))->hidden_friend_p)
-
/* Nonzero if NODE is an artificial FUNCTION_DECL for
#pragma omp declare reduction. */
#define DECL_OMP_DECLARE_REDUCTION_P(NODE) \
@@ -6221,6 +6207,7 @@ extern bool sufficient_parms_p (const_tree);
extern tree type_decays_to (tree);
extern tree extract_call_expr (tree);
extern tree build_trivial_dtor_call (tree, bool = false);
+extern bool ref_conv_binds_directly_p (tree, tree);
extern tree build_user_type_conversion (tree, tree, int,
tsubst_flags_t);
extern tree build_new_function_call (tree, vec<tree, va_gc> **,
@@ -6461,7 +6448,9 @@ extern void note_iteration_stmt_body_end (bool);
extern void determine_local_discriminator (tree);
extern int decls_match (tree, tree, bool = true);
extern bool maybe_version_functions (tree, tree, bool);
-extern tree duplicate_decls (tree, tree, bool);
+extern tree duplicate_decls (tree, tree,
+ bool hiding = false,
+ bool was_hidden = false);
extern tree declare_local_label (tree);
extern tree define_label (location_t, tree);
extern void check_goto (tree);
@@ -6501,8 +6490,9 @@ extern tree get_scope_of_declarator (const cp_declarator *);
extern void grok_special_member_properties (tree);
extern bool grok_ctor_properties (const_tree, const_tree);
extern bool grok_op_properties (tree, bool);
-extern tree xref_tag (enum tag_types, tree, tag_scope, bool);
-extern tree xref_tag_from_type (tree, tree, tag_scope);
+extern tree xref_tag (tag_types, tree,
+ TAG_how = TAG_how::CURRENT_ONLY,
+ bool tpl_header_p = false);
extern void xref_basetypes (tree, tree);
extern tree start_enum (tree, tree, tree, tree, bool, bool *);
extern void finish_enum_value_list (tree);
@@ -6530,7 +6520,6 @@ extern tree create_implicit_typedef (tree, tree);
extern int local_variable_p (const_tree);
extern tree register_dtor_fn (tree);
extern tmpl_spec_kind current_tmpl_spec_kind (int);
-extern tree cp_fname_init (const char *, tree *);
extern tree cxx_builtin_function (tree decl);
extern tree cxx_builtin_function_ext_scope (tree decl);
extern tree cxx_simulate_builtin_function_decl (tree);
@@ -6781,6 +6770,7 @@ extern tree get_default_ctor (tree);
extern tree get_dtor (tree, tsubst_flags_t);
extern tree strip_inheriting_ctors (tree);
extern tree inherited_ctor_binfo (tree);
+extern bool base_ctor_omit_inherited_parms (tree);
extern bool ctor_omit_inherited_parms (tree);
extern tree locate_ctor (tree);
extern tree implicitly_declare_fn (special_function_kind, tree,
@@ -6850,8 +6840,7 @@ extern void end_template_parm_list (void);
extern void end_template_decl (void);
extern tree maybe_update_decl_type (tree, tree);
extern bool check_default_tmpl_args (tree, tree, bool, bool, int);
-extern tree push_template_decl (tree);
-extern tree push_template_decl_real (tree, bool);
+extern tree push_template_decl (tree, bool is_friend = false);
extern tree add_inherited_template_parms (tree, tree);
extern void template_parm_level_and_index (tree, int*, int*);
extern bool redeclare_class_template (tree, tree, tree);
@@ -7279,6 +7268,7 @@ extern bool lambda_fn_in_template_p (tree);
extern void maybe_add_lambda_conv_op (tree);
extern bool is_lambda_ignored_entity (tree);
extern bool lambda_static_thunk_p (tree);
+extern bool call_from_lambda_thunk_p (tree);
extern tree finish_builtin_launder (location_t, tree,
tsubst_flags_t);
extern tree cp_build_vec_convert (tree, location_t, tree,
@@ -7365,7 +7355,7 @@ inline tree ovl_first (tree) ATTRIBUTE_PURE;
extern tree ovl_make (tree fn,
tree next = NULL_TREE);
extern tree ovl_insert (tree fn, tree maybe_ovl,
- bool using_p = false);
+ int using_or_hidden = 0);
extern tree ovl_skip_hidden (tree) ATTRIBUTE_PURE;
extern void lookup_mark (tree lookup, bool val);
extern tree lookup_add (tree fns, tree lookup);
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index d10c18d..058b9c2 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -1420,6 +1420,16 @@ pp_cxx_type_specifier_seq (cxx_pretty_printer *pp, tree t)
}
/* fall through */
+ case OFFSET_TYPE:
+ if (TYPE_PTRDATAMEM_P (t))
+ {
+ pp_cxx_type_specifier_seq (pp, TREE_TYPE (t));
+ pp_cxx_whitespace (pp);
+ pp_cxx_ptr_operator (pp, t);
+ break;
+ }
+ /* fall through */
+
default:
if (!(TREE_CODE (t) == FUNCTION_DECL && DECL_CONSTRUCTOR_P (t)))
pp_c_specifier_qualifier_list (pp, t);
@@ -1753,7 +1763,20 @@ pp_cxx_function_definition (cxx_pretty_printer *pp, tree t)
void
cxx_pretty_printer::abstract_declarator (tree t)
{
- if (TYPE_PTRMEM_P (t))
+ /* pp_cxx_ptr_operator prints '(' for a pointer-to-member function,
+ or a pointer-to-data-member of array type:
+
+ void (X::*)()
+ int (X::*)[5]
+
+ but not for a pointer-to-data-member of non-array type:
+
+ int X::*
+
+ so be mindful of that. */
+ if (TYPE_PTRMEMFUNC_P (t)
+ || (TYPE_PTRDATAMEM_P (t)
+ && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE))
pp_cxx_right_paren (this);
else if (INDIRECT_TYPE_P (t))
{
@@ -1785,6 +1808,11 @@ cxx_pretty_printer::direct_abstract_declarator (tree t)
direct_abstract_declarator (TYPE_PTRMEMFUNC_FN_TYPE (t));
break;
+ case OFFSET_TYPE:
+ if (TYPE_PTRDATAMEM_P (t))
+ direct_abstract_declarator (TREE_TYPE (t));
+ break;
+
case METHOD_TYPE:
case FUNCTION_TYPE:
pp_cxx_parameter_declaration_clause (this, t);
@@ -1837,7 +1865,10 @@ cxx_pretty_printer::type_id (tree t)
case UNDERLYING_TYPE:
case DECLTYPE_TYPE:
case TEMPLATE_ID_EXPR:
+ case OFFSET_TYPE:
pp_cxx_type_specifier_seq (this, t);
+ if (TYPE_PTRMEM_P (t))
+ abstract_declarator (t);
break;
case TYPE_PACK_EXPANSION:
@@ -1910,6 +1941,8 @@ pp_cxx_template_argument_list (cxx_pretty_printer *pp, tree t)
if (TYPE_P (arg) || (TREE_CODE (arg) == TEMPLATE_DECL
&& TYPE_P (DECL_TEMPLATE_RESULT (arg))))
pp->type_id (arg);
+ else if (template_parm_object_p (arg))
+ pp->expression (DECL_INITIAL (arg));
else
pp->expression (arg);
}
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 13f065d..2de4e16 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -75,7 +75,7 @@ static void record_unknown_type (tree, const char *);
static int member_function_or_else (tree, tree, enum overload_flags);
static tree local_variable_p_walkfn (tree *, int *, void *);
static const char *tag_name (enum tag_types);
-static tree lookup_and_check_tag (enum tag_types, tree, tag_scope, bool);
+static tree lookup_and_check_tag (enum tag_types, tree, TAG_how, bool);
static void maybe_deduce_size_from_array_init (tree, tree);
static void layout_var_decl (tree);
static tree check_initializer (tree, tree, int, vec<tree, va_gc> **);
@@ -1340,19 +1340,17 @@ check_redeclaration_no_default_args (tree decl)
the function or function template in the translation unit." */
static void
-check_no_redeclaration_friend_default_args (tree olddecl, tree newdecl,
- bool olddecl_hidden_friend_p)
+check_no_redeclaration_friend_default_args (tree olddecl, tree newdecl)
{
- if (!olddecl_hidden_friend_p && !DECL_FRIEND_P (newdecl))
+ if (!DECL_UNIQUE_FRIEND_P (olddecl) && !DECL_UNIQUE_FRIEND_P (newdecl))
return;
- tree t1 = FUNCTION_FIRST_USER_PARMTYPE (olddecl);
- tree t2 = FUNCTION_FIRST_USER_PARMTYPE (newdecl);
-
- for (; t1 && t1 != void_list_node;
+ for (tree t1 = FUNCTION_FIRST_USER_PARMTYPE (olddecl),
+ t2 = FUNCTION_FIRST_USER_PARMTYPE (newdecl);
+ t1 && t1 != void_list_node;
t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
- if ((olddecl_hidden_friend_p && TREE_PURPOSE (t1))
- || (DECL_FRIEND_P (newdecl) && TREE_PURPOSE (t2)))
+ if ((DECL_UNIQUE_FRIEND_P (olddecl) && TREE_PURPOSE (t1))
+ || (DECL_UNIQUE_FRIEND_P (newdecl) && TREE_PURPOSE (t2)))
{
auto_diagnostic_group d;
if (permerror (DECL_SOURCE_LOCATION (newdecl),
@@ -1435,14 +1433,17 @@ duplicate_function_template_decls (tree newdecl, tree olddecl)
If NEWDECL is not a redeclaration of OLDDECL, NULL_TREE is
returned.
- NEWDECL_IS_FRIEND is true if NEWDECL was declared as a friend. */
+ HIDING is true if the new decl is being hidden. WAS_HIDDEN is true
+ if the old decl was hidden.
+
+ Hidden decls can be anticipated builtins, injected friends, or
+ (coming soon) injected from a local-extern decl. */
tree
-duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
+duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
{
unsigned olddecl_uid = DECL_UID (olddecl);
- int olddecl_friend = 0, types_match = 0, hidden_friend = 0;
- int olddecl_hidden_friend = 0;
+ int types_match = 0;
int new_defines_function = 0;
tree new_template_info;
location_t olddecl_loc = DECL_SOURCE_LOCATION (olddecl);
@@ -1464,15 +1465,13 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
/* Check for redeclaration and other discrepancies. */
if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_ARTIFICIAL (olddecl)
- /* A C++20 implicit friend operator== uses the normal path (94462). */
- && !DECL_HIDDEN_FRIEND_P (olddecl))
+ && DECL_UNDECLARED_BUILTIN_P (olddecl))
{
if (TREE_CODE (newdecl) != FUNCTION_DECL)
{
/* Avoid warnings redeclaring built-ins which have not been
explicitly declared. */
- if (DECL_ANTICIPATED (olddecl))
+ if (was_hidden)
{
if (TREE_PUBLIC (newdecl)
&& CP_DECL_CONTEXT (newdecl) == global_namespace)
@@ -1508,20 +1507,11 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
"declaration %q#D", newdecl, olddecl);
return NULL_TREE;
}
- else if (DECL_OMP_DECLARE_REDUCTION_P (olddecl))
- {
- gcc_assert (DECL_OMP_DECLARE_REDUCTION_P (newdecl));
- error_at (newdecl_loc,
- "redeclaration of %<pragma omp declare reduction%>");
- inform (olddecl_loc,
- "previous %<pragma omp declare reduction%> declaration");
- return error_mark_node;
- }
else if (!types_match)
{
/* Avoid warnings redeclaring built-ins which have not been
explicitly declared. */
- if (DECL_ANTICIPATED (olddecl))
+ if (was_hidden)
{
tree t1, t2;
@@ -1561,7 +1551,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
types_match = decls_match (newdecl, olddecl);
if (types_match)
return duplicate_decls (newdecl, olddecl,
- newdecl_is_friend);
+ hiding, was_hidden);
TYPE_ARG_TYPES (TREE_TYPE (olddecl)) = oldargs;
}
goto next_arg;
@@ -1653,7 +1643,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
/* If a function is explicitly declared "throw ()", propagate that to
the corresponding builtin. */
if (DECL_BUILT_IN_CLASS (olddecl) == BUILT_IN_NORMAL
- && DECL_ANTICIPATED (olddecl)
+ && was_hidden
&& TREE_NOTHROW (newdecl)
&& !TREE_NOTHROW (olddecl))
{
@@ -1816,6 +1806,17 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
}
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL
+ && DECL_OMP_DECLARE_REDUCTION_P (newdecl))
+ {
+ /* OMP UDRs are never duplicates. */
+ gcc_assert (DECL_OMP_DECLARE_REDUCTION_P (olddecl));
+ error_at (newdecl_loc,
+ "redeclaration of %<pragma omp declare reduction%>");
+ inform (olddecl_loc,
+ "previous %<pragma omp declare reduction%> declaration");
+ return error_mark_node;
+ }
+ else if (TREE_CODE (newdecl) == FUNCTION_DECL
&& ((DECL_TEMPLATE_SPECIALIZATION (olddecl)
&& (!DECL_TEMPLATE_INFO (newdecl)
|| (DECL_TI_TEMPLATE (newdecl)
@@ -1984,8 +1985,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
argument expression, that declaration... shall be the only
declaration of the function or function template in the
translation unit." */
- check_no_redeclaration_friend_default_args
- (olddecl, newdecl, DECL_HIDDEN_FRIEND_P (olddecl));
+ check_no_redeclaration_friend_default_args (olddecl, newdecl);
}
}
}
@@ -2002,6 +2002,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
|| DECL_IMPLICIT_TYPEDEF_P (newdecl)))
return NULL_TREE;
+ if (DECL_TEMPLATE_PARM_P (olddecl) != DECL_TEMPLATE_PARM_P (newdecl))
+ return NULL_TREE;
+
if (!validate_constexpr_redeclaration (olddecl, newdecl))
return error_mark_node;
@@ -2075,8 +2078,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
&& !(new_defines_function && DECL_INITIAL (olddecl) == NULL_TREE)
/* Don't warn about extern decl followed by definition. */
&& !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))
- /* Don't warn about friends, let add_friend take care of it. */
- && ! (newdecl_is_friend || DECL_FRIEND_P (olddecl))
+ /* Don't warn if at least one is/was hidden. */
+ && !(hiding || was_hidden)
/* Don't warn about declaration followed by specialization. */
&& (! DECL_TEMPLATE_SPECIALIZATION (newdecl)
|| DECL_TEMPLATE_SPECIALIZATION (olddecl)))
@@ -2132,20 +2135,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
else
DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
- if (DECL_DECLARES_FUNCTION_P (olddecl))
- {
- olddecl_friend = DECL_FRIEND_P (olddecl);
- olddecl_hidden_friend = DECL_HIDDEN_FRIEND_P (olddecl);
- hidden_friend = (DECL_ANTICIPATED (olddecl)
- && DECL_HIDDEN_FRIEND_P (olddecl)
- && newdecl_is_friend);
- if (!hidden_friend)
- {
- DECL_ANTICIPATED (olddecl) = 0;
- DECL_HIDDEN_FRIEND_P (olddecl) = 0;
- }
- }
-
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
tree old_result = DECL_TEMPLATE_RESULT (olddecl);
@@ -2172,8 +2161,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
declaration of the function or function template in the
translation unit." */
check_no_redeclaration_friend_default_args
- (old_result, new_result, olddecl_hidden_friend);
+ (old_result, new_result);
}
+ if (!DECL_UNIQUE_FRIEND_P (old_result))
+ DECL_UNIQUE_FRIEND_P (new_result) = false;
check_default_args (newdecl);
@@ -2371,6 +2362,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
&& !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl))
DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl)
= DECL_FUNCTION_SPECIFIC_OPTIMIZATION (olddecl);
+
+ if (!DECL_UNIQUE_FRIEND_P (olddecl))
+ DECL_UNIQUE_FRIEND_P (newdecl) = false;
}
else
{
@@ -2890,13 +2884,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
}
DECL_UID (olddecl) = olddecl_uid;
- if (olddecl_friend)
- DECL_FRIEND_P (olddecl) = 1;
- if (hidden_friend)
- {
- DECL_ANTICIPATED (olddecl) = 1;
- DECL_HIDDEN_FRIEND_P (olddecl) = 1;
- }
/* NEWDECL contains the merged attribute lists.
Update OLDDECL to be the same. */
@@ -3003,6 +2990,10 @@ redeclaration_error_message (tree newdecl, tree olddecl)
}
}
+ if (deduction_guide_p (olddecl)
+ && deduction_guide_p (newdecl))
+ return G_("deduction guide %q+D redeclared");
+
/* [class.compare.default]: A definition of a comparison operator as
defaulted that appears in a class shall be the first declaration of
that function. */
@@ -3053,29 +3044,34 @@ redeclaration_error_message (tree newdecl, tree olddecl)
"%<gnu_inline%> attribute");
else
return G_("%q+D redeclared inline without "
- "%<gnu_inline%> attribute");
+ "%<gnu_inline%> attribute");
}
}
- /* Core issue #226 (C++0x):
-
+ if (deduction_guide_p (olddecl)
+ && deduction_guide_p (newdecl))
+ return G_("deduction guide %q+D redeclared");
+
+ /* Core issue #226 (C++11):
+
If a friend function template declaration specifies a
default template-argument, that declaration shall be a
definition and shall be the only declaration of the
function template in the translation unit. */
- if ((cxx_dialect != cxx98)
- && TREE_CODE (ot) == FUNCTION_DECL && DECL_FRIEND_P (ot)
- && !check_default_tmpl_args (nt, DECL_TEMPLATE_PARMS (newdecl),
+ if ((cxx_dialect != cxx98)
+ && TREE_CODE (ot) == FUNCTION_DECL && DECL_UNIQUE_FRIEND_P (ot)
+ && !check_default_tmpl_args (nt, DECL_TEMPLATE_PARMS (newdecl),
/*is_primary=*/true,
/*is_partial=*/false,
/*is_friend_decl=*/2))
return G_("redeclaration of friend %q#D "
- "may not have default template arguments");
+ "may not have default template arguments");
return NULL;
}
else if (VAR_P (newdecl)
- && CP_DECL_THREAD_LOCAL_P (newdecl) != CP_DECL_THREAD_LOCAL_P (olddecl)
+ && (CP_DECL_THREAD_LOCAL_P (newdecl)
+ != CP_DECL_THREAD_LOCAL_P (olddecl))
&& (! DECL_LANG_SPECIFIC (olddecl)
|| ! CP_DECL_THREADPRIVATE_P (olddecl)
|| CP_DECL_THREAD_LOCAL_P (newdecl)))
@@ -4589,38 +4585,6 @@ cxx_init_decl_processing (void)
using_eh_for_cleanups ();
}
-/* Generate an initializer for a function naming variable from
- NAME. NAME may be NULL, to indicate a dependent name. TYPE_P is
- filled in with the type of the init. */
-
-tree
-cp_fname_init (const char* name, tree *type_p)
-{
- tree domain = NULL_TREE;
- tree type;
- tree init = NULL_TREE;
- size_t length = 0;
-
- if (name)
- {
- length = strlen (name);
- domain = build_index_type (size_int (length));
- init = build_string (length + 1, name);
- }
-
- type = cp_build_qualified_type (char_type_node, TYPE_QUAL_CONST);
- type = build_cplus_array_type (type, domain);
-
- *type_p = type;
-
- if (init)
- TREE_TYPE (init) = type;
- else
- init = error_mark_node;
-
- return init;
-}
-
/* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give
the decl, LOC is the location to give the decl, NAME is the
initialization string and TYPE_DEP indicates whether NAME depended
@@ -4631,31 +4595,45 @@ cp_fname_init (const char* name, tree *type_p)
static tree
cp_make_fname_decl (location_t loc, tree id, int type_dep)
{
- const char * name = NULL;
- bool release_name = false;
+ tree domain = NULL_TREE;
+ tree init = NULL_TREE;
+
if (!(type_dep && in_template_function ()))
{
+ const char *name = NULL;
+ bool release_name = false;
+
if (current_function_decl == NULL_TREE)
name = "top level";
- else if (type_dep == 1) /* __PRETTY_FUNCTION__ */
- name = cxx_printable_name (current_function_decl, 2);
- else if (type_dep == 0) /* __FUNCTION__ */
+ else if (type_dep == 0)
{
+ /* __FUNCTION__ */
name = fname_as_string (type_dep);
release_name = true;
}
else
- gcc_unreachable ();
+ {
+ /* __PRETTY_FUNCTION__ */
+ gcc_checking_assert (type_dep == 1);
+ name = cxx_printable_name (current_function_decl, 2);
+ }
+
+ size_t length = strlen (name);
+ domain = build_index_type (size_int (length));
+ init = build_string (length + 1, name);
+ if (release_name)
+ free (const_cast<char *> (name));
}
- tree type;
- tree init = cp_fname_init (name, &type);
- tree decl = build_decl (loc, VAR_DECL, id, type);
- if (release_name)
- free (CONST_CAST (char *, name));
+ tree type = cp_build_qualified_type (char_type_node, TYPE_QUAL_CONST);
+ type = build_cplus_array_type (type, domain);
- /* As we're using pushdecl_with_scope, we must set the context. */
- DECL_CONTEXT (decl) = current_function_decl;
+ if (init)
+ TREE_TYPE (init) = type;
+ else
+ init = error_mark_node;
+
+ tree decl = build_decl (loc, VAR_DECL, id, type);
TREE_READONLY (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
@@ -4664,13 +4642,10 @@ cp_make_fname_decl (location_t loc, tree id, int type_dep)
TREE_USED (decl) = 1;
- if (init)
- {
- SET_DECL_VALUE_EXPR (decl, init);
- DECL_HAS_VALUE_EXPR_P (decl) = 1;
- /* For decl_constant_var_p. */
- DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
- }
+ SET_DECL_VALUE_EXPR (decl, init);
+ DECL_HAS_VALUE_EXPR_P (decl) = 1;
+ /* For decl_constant_var_p. */
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
if (current_function_decl)
{
@@ -4682,7 +4657,7 @@ cp_make_fname_decl (location_t loc, tree id, int type_dep)
else
{
DECL_THIS_STATIC (decl) = true;
- pushdecl_top_level_and_finish (decl, NULL_TREE);
+ decl = pushdecl_top_level_and_finish (decl, NULL_TREE);
}
return decl;
@@ -4706,16 +4681,17 @@ cxx_builtin_function (tree decl)
tree id = DECL_NAME (decl);
const char *name = IDENTIFIER_POINTER (id);
+ bool hiding = false;
if (name[0] != '_' || name[1] != '_')
/* In the user's namespace, it must be declared before use. */
- DECL_ANTICIPATED (decl) = 1;
+ hiding = true;
else if (IDENTIFIER_LENGTH (id) > strlen ("___chk")
&& 0 != strncmp (name + 2, "builtin_", strlen ("builtin_"))
&& 0 == memcmp (name + IDENTIFIER_LENGTH (id) - strlen ("_chk"),
"_chk", strlen ("_chk") + 1))
/* Treat __*_chk fortification functions as anticipated as well,
unless they are __builtin_*_chk. */
- DECL_ANTICIPATED (decl) = 1;
+ hiding = true;
/* All builtins that don't begin with an '_' should additionally
go in the 'std' namespace. */
@@ -4725,12 +4701,12 @@ cxx_builtin_function (tree decl)
push_nested_namespace (std_node);
DECL_CONTEXT (std_decl) = FROB_CONTEXT (std_node);
- pushdecl (std_decl);
+ pushdecl (std_decl, hiding);
pop_nested_namespace (std_node);
}
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
- decl = pushdecl (decl);
+ decl = pushdecl (decl, hiding);
return decl;
}
@@ -5353,8 +5329,7 @@ start_decl (const cp_declarator *declarator,
about this situation, and so we check here. */
if (initialized && DECL_INITIALIZED_IN_CLASS_P (field))
error ("duplicate initialization of %qD", decl);
- field = duplicate_decls (decl, field,
- /*newdecl_is_friend=*/false);
+ field = duplicate_decls (decl, field);
if (field == error_mark_node)
return error_mark_node;
else if (field)
@@ -5368,8 +5343,7 @@ start_decl (const cp_declarator *declarator,
? current_template_parms
: NULL_TREE);
if (field && field != error_mark_node
- && duplicate_decls (decl, field,
- /*newdecl_is_friend=*/false))
+ && duplicate_decls (decl, field))
decl = field;
}
@@ -5854,7 +5828,8 @@ layout_var_decl (tree decl)
&& DECL_SIZE (decl) != NULL_TREE
&& ! TREE_CONSTANT (DECL_SIZE (decl)))
{
- if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
+ if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST
+ && !DECL_LOCAL_DECL_P (decl))
constant_expression_warning (DECL_SIZE (decl));
else
{
@@ -9919,7 +9894,7 @@ grokfndecl (tree ctype,
/* Attempt to merge the declarations. This can fail, in
the case of some invalid specialization declarations. */
pushed_scope = push_scope (ctype);
- ok = duplicate_decls (decl, old_decl, friendp);
+ ok = duplicate_decls (decl, old_decl);
if (pushed_scope)
pop_scope (pushed_scope);
if (!ok)
@@ -14197,6 +14172,10 @@ copy_fn_p (const_tree d)
accept those as copy functions. */
return 0;
+ if (!DECL_CONSTRUCTOR_P (d)
+ && DECL_NAME (d) != assign_op_identifier)
+ return 0;
+
args = FUNCTION_FIRST_USER_PARMTYPE (d);
if (!args)
return 0;
@@ -14270,6 +14249,10 @@ move_signature_fn_p (const_tree d)
tree arg_type;
bool result = false;
+ if (!DECL_CONSTRUCTOR_P (d)
+ && DECL_NAME (d) != assign_op_identifier)
+ return 0;
+
args = FUNCTION_FIRST_USER_PARMTYPE (d);
if (!args)
return 0;
@@ -14849,18 +14832,17 @@ check_elaborated_type_specifier (enum tag_types tag_code,
return type;
}
-/* Lookup NAME in elaborate type specifier in scope according to
- SCOPE and issue diagnostics if necessary.
- Return *_TYPE node upon success, NULL_TREE when the NAME is not
- found, and ERROR_MARK_NODE for type error. */
+/* Lookup NAME of an elaborated type specifier according to SCOPE and
+ issue diagnostics if necessary. Return *_TYPE node upon success,
+ NULL_TREE when the NAME is not found, and ERROR_MARK_NODE for type
+ error. */
static tree
lookup_and_check_tag (enum tag_types tag_code, tree name,
- tag_scope scope, bool template_header_p)
+ TAG_how how, bool template_header_p)
{
- tree t;
tree decl;
- if (scope == ts_global)
+ if (how == TAG_how::GLOBAL)
{
/* First try ordinary name lookup, ignoring hidden class name
injected via friend declaration. */
@@ -14873,77 +14855,78 @@ lookup_and_check_tag (enum tag_types tag_code, tree name,
If we find one, that name will be made visible rather than
creating a new tag. */
if (!decl)
- decl = lookup_type_scope (name, ts_within_enclosing_non_class);
+ decl = lookup_elaborated_type (name, TAG_how::INNERMOST_NON_CLASS);
}
else
- decl = lookup_type_scope (name, scope);
-
- if (decl
- && (DECL_CLASS_TEMPLATE_P (decl)
- /* If scope is ts_current we're defining a class, so ignore a
- template template parameter. */
- || (scope != ts_current
- && DECL_TEMPLATE_TEMPLATE_PARM_P (decl))))
- decl = DECL_TEMPLATE_RESULT (decl);
-
- if (decl && TREE_CODE (decl) == TYPE_DECL)
- {
- /* Look for invalid nested type:
- class C {
- class C {};
- }; */
- if (scope == ts_current && DECL_SELF_REFERENCE_P (decl))
- {
- error ("%qD has the same name as the class in which it is "
- "declared",
- decl);
- return error_mark_node;
- }
+ decl = lookup_elaborated_type (name, how);
- /* Two cases we need to consider when deciding if a class
- template is allowed as an elaborated type specifier:
- 1. It is a self reference to its own class.
- 2. It comes with a template header.
- For example:
-
- template <class T> class C {
- class C *c1; // DECL_SELF_REFERENCE_P is true
- class D;
- };
- template <class U> class C; // template_header_p is true
- template <class T> class C<T>::D {
- class C *c2; // DECL_SELF_REFERENCE_P is true
- }; */
-
- t = check_elaborated_type_specifier (tag_code,
- decl,
- template_header_p
- | DECL_SELF_REFERENCE_P (decl));
- if (template_header_p && t && CLASS_TYPE_P (t)
- && (!CLASSTYPE_TEMPLATE_INFO (t)
- || (!PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))))
- {
- error ("%qT is not a template", t);
- inform (location_of (t), "previous declaration here");
- if (TYPE_CLASS_SCOPE_P (t)
- && CLASSTYPE_TEMPLATE_INFO (TYPE_CONTEXT (t)))
- inform (input_location,
- "perhaps you want to explicitly add %<%T::%>",
- TYPE_CONTEXT (t));
- t = error_mark_node;
- }
+ if (!decl)
+ /* We found nothing. */
+ return NULL_TREE;
- return t;
- }
- else if (decl && TREE_CODE (decl) == TREE_LIST)
+ if (TREE_CODE (decl) == TREE_LIST)
{
error ("reference to %qD is ambiguous", name);
print_candidates (decl);
return error_mark_node;
}
- else
+
+ if (DECL_CLASS_TEMPLATE_P (decl)
+ /* If scope is TAG_how::CURRENT_ONLY we're defining a class,
+ so ignore a template template parameter. */
+ || (how != TAG_how::CURRENT_ONLY && DECL_TEMPLATE_TEMPLATE_PARM_P (decl)))
+ decl = DECL_TEMPLATE_RESULT (decl);
+
+ if (TREE_CODE (decl) != TYPE_DECL)
+ /* Found not-a-type. */
return NULL_TREE;
+
+ /* Look for invalid nested type:
+ class C {
+ class C {};
+ }; */
+ if (how == TAG_how::CURRENT_ONLY && DECL_SELF_REFERENCE_P (decl))
+ {
+ error ("%qD has the same name as the class in which it is "
+ "declared", decl);
+ return error_mark_node;
+ }
+
+ /* Two cases we need to consider when deciding if a class
+ template is allowed as an elaborated type specifier:
+ 1. It is a self reference to its own class.
+ 2. It comes with a template header.
+
+ For example:
+
+ template <class T> class C {
+ class C *c1; // DECL_SELF_REFERENCE_P is true
+ class D;
+ };
+ template <class U> class C; // template_header_p is true
+ template <class T> class C<T>::D {
+ class C *c2; // DECL_SELF_REFERENCE_P is true
+ }; */
+
+ tree t = check_elaborated_type_specifier (tag_code, decl,
+ template_header_p
+ | DECL_SELF_REFERENCE_P (decl));
+ if (template_header_p && t && CLASS_TYPE_P (t)
+ && (!CLASSTYPE_TEMPLATE_INFO (t)
+ || (!PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))))
+ {
+ error ("%qT is not a template", t);
+ inform (location_of (t), "previous declaration here");
+ if (TYPE_CLASS_SCOPE_P (t)
+ && CLASSTYPE_TEMPLATE_INFO (TYPE_CONTEXT (t)))
+ inform (input_location,
+ "perhaps you want to explicitly add %<%T::%>",
+ TYPE_CONTEXT (t));
+ return error_mark_node;
+ }
+
+ return t;
}
/* Get the struct, enum or union (TAG_CODE says which) with tag NAME.
@@ -14963,7 +14946,7 @@ lookup_and_check_tag (enum tag_types tag_code, tree name,
static tree
xref_tag_1 (enum tag_types tag_code, tree name,
- tag_scope scope, bool template_header_p)
+ TAG_how how, bool template_header_p)
{
enum tree_code code;
tree context = NULL_TREE;
@@ -14989,23 +14972,23 @@ xref_tag_1 (enum tag_types tag_code, tree name,
/* In case of anonymous name, xref_tag is only called to
make type node and push name. Name lookup is not required. */
tree t = NULL_TREE;
- if (scope != ts_lambda && !IDENTIFIER_ANON_P (name))
- t = lookup_and_check_tag (tag_code, name, scope, template_header_p);
-
+ if (!IDENTIFIER_ANON_P (name))
+ t = lookup_and_check_tag (tag_code, name, how, template_header_p);
+
if (t == error_mark_node)
return error_mark_node;
- if (scope != ts_current && t && current_class_type
+ if (how != TAG_how::CURRENT_ONLY && t && current_class_type
&& template_class_depth (current_class_type)
&& template_header_p)
{
if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
return t;
- /* Since SCOPE is not TS_CURRENT, we are not looking at a
- definition of this tag. Since, in addition, we are currently
- processing a (member) template declaration of a template
- class, we must be very careful; consider:
+ /* Since HOW is not TAG_how::CURRENT_ONLY, we are not looking at
+ a definition of this tag. Since, in addition, we are
+ currently processing a (member) template declaration of a
+ template class, we must be very careful; consider:
template <class X> struct S1
@@ -15044,19 +15027,14 @@ xref_tag_1 (enum tag_types tag_code, tree name,
error ("use of enum %q#D without previous declaration", name);
return error_mark_node;
}
- else
- {
- t = make_class_type (code);
- TYPE_CONTEXT (t) = context;
- if (scope == ts_lambda)
- {
- /* Mark it as a lambda type. */
- CLASSTYPE_LAMBDA_EXPR (t) = error_mark_node;
- /* And push it into current scope. */
- scope = ts_current;
- }
- t = pushtag (name, t, scope);
- }
+
+ t = make_class_type (code);
+ TYPE_CONTEXT (t) = context;
+ if (IDENTIFIER_LAMBDA_P (name))
+ /* Mark it as a lambda type right now. Our caller will
+ correct the value. */
+ CLASSTYPE_LAMBDA_EXPR (t) = error_mark_node;
+ t = pushtag (name, t, how);
}
else
{
@@ -15081,23 +15059,6 @@ xref_tag_1 (enum tag_types tag_code, tree name,
inform (location_of (t), "previous declaration %qD", t);
return error_mark_node;
}
-
- if (scope != ts_within_enclosing_non_class && TYPE_HIDDEN_P (t))
- {
- /* This is no longer an invisible friend. Make it
- visible. */
- tree decl = TYPE_NAME (t);
-
- DECL_ANTICIPATED (decl) = false;
- DECL_FRIEND_P (decl) = false;
-
- if (TYPE_TEMPLATE_INFO (t))
- {
- tree tmpl = TYPE_TI_TEMPLATE (t);
- DECL_ANTICIPATED (tmpl) = false;
- DECL_FRIEND_P (tmpl) = false;
- }
- }
}
return t;
@@ -15107,33 +15068,14 @@ xref_tag_1 (enum tag_types tag_code, tree name,
tree
xref_tag (enum tag_types tag_code, tree name,
- tag_scope scope, bool template_header_p)
+ TAG_how how, bool template_header_p)
{
- tree ret;
- bool subtime;
- subtime = timevar_cond_start (TV_NAME_LOOKUP);
- ret = xref_tag_1 (tag_code, name, scope, template_header_p);
+ bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
+ tree ret = xref_tag_1 (tag_code, name, how, template_header_p);
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
return ret;
}
-
-tree
-xref_tag_from_type (tree old, tree id, tag_scope scope)
-{
- enum tag_types tag_kind;
-
- if (TREE_CODE (old) == RECORD_TYPE)
- tag_kind = (CLASSTYPE_DECLARED_CLASS (old) ? class_type : record_type);
- else
- tag_kind = union_type;
-
- if (id == NULL_TREE)
- id = TYPE_IDENTIFIER (old);
-
- return xref_tag (tag_kind, id, scope, false);
-}
-
/* Create the binfo hierarchy for REF with (possibly NULL) base list
BASE_LIST. For each element on BASE_LIST the TREE_PURPOSE is an
access_* node, and the TREE_VALUE is the type of the base-class.
@@ -15428,7 +15370,7 @@ start_enum (tree name, tree enumtype, tree underlying_type,
forward reference. */
if (!enumtype)
enumtype = lookup_and_check_tag (enum_type, name,
- /*tag_scope=*/ts_current,
+ /*tag_scope=*/TAG_how::CURRENT_ONLY,
/*template_header_p=*/false);
/* In case of a template_decl, the only check that should be deferred
@@ -15490,7 +15432,7 @@ start_enum (tree name, tree enumtype, tree underlying_type,
|| TREE_CODE (enumtype) != ENUMERAL_TYPE)
{
enumtype = cxx_make_type (ENUMERAL_TYPE);
- enumtype = pushtag (name, enumtype, /*tag_scope=*/ts_current);
+ enumtype = pushtag (name, enumtype);
/* std::byte aliases anything. */
if (enumtype != error_mark_node
@@ -15499,8 +15441,7 @@ start_enum (tree name, tree enumtype, tree underlying_type,
TYPE_ALIAS_SET (enumtype) = 0;
}
else
- enumtype = xref_tag (enum_type, name, /*tag_scope=*/ts_current,
- false);
+ enumtype = xref_tag (enum_type, name);
if (enumtype == error_mark_node)
return error_mark_node;
@@ -16175,36 +16116,21 @@ bool
start_preparsed_function (tree decl1, tree attrs, int flags)
{
tree ctype = NULL_TREE;
- tree fntype;
- tree restype;
- int doing_friend = 0;
- cp_binding_level *bl;
- tree current_function_parms;
- struct c_fileinfo *finfo
- = get_fileinfo (LOCATION_FILE (DECL_SOURCE_LOCATION (decl1)));
- bool honor_interface;
+ bool doing_friend = false;
/* Sanity check. */
gcc_assert (VOID_TYPE_P (TREE_VALUE (void_list_node)));
gcc_assert (TREE_CHAIN (void_list_node) == NULL_TREE);
- fntype = TREE_TYPE (decl1);
+ tree fntype = TREE_TYPE (decl1);
if (TREE_CODE (fntype) == METHOD_TYPE)
ctype = TYPE_METHOD_BASETYPE (fntype);
-
- /* ISO C++ 11.4/5. A friend function defined in a class is in
- the (lexical) scope of the class in which it is defined. */
- if (!ctype && DECL_FRIEND_P (decl1))
+ else
{
ctype = DECL_FRIEND_CONTEXT (decl1);
- /* CTYPE could be null here if we're dealing with a template;
- for example, `inline friend float foo()' inside a template
- will have no CTYPE set. */
- if (ctype && TREE_CODE (ctype) != RECORD_TYPE)
- ctype = NULL_TREE;
- else
- doing_friend = 1;
+ if (ctype)
+ doing_friend = true;
}
if (DECL_DECLARED_INLINE_P (decl1)
@@ -16271,7 +16197,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
by push_nested_class.) */
if (processing_template_decl)
{
- tree newdecl1 = push_template_decl (decl1);
+ tree newdecl1 = push_template_decl (decl1, doing_friend);
if (newdecl1 == error_mark_node)
{
if (ctype || DECL_STATIC_FUNCTION_P (decl1))
@@ -16287,7 +16213,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
check_function_type (decl1, DECL_ARGUMENTS (decl1));
/* Build the return declaration for the function. */
- restype = TREE_TYPE (fntype);
+ tree restype = TREE_TYPE (fntype);
if (DECL_RESULT (decl1) == NULL_TREE)
{
@@ -16377,7 +16303,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
/* Save the parm names or decls from this function's declarator
where store_parm_decls will find them. */
- current_function_parms = DECL_ARGUMENTS (decl1);
+ tree current_function_parms = DECL_ARGUMENTS (decl1);
/* Let the user know we're compiling this function. */
announce_function (decl1);
@@ -16394,7 +16320,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
even when processing a template; this is how we get
CFUN set up, and our per-function variables initialized.
FIXME factor out the non-RTL stuff. */
- bl = current_binding_level;
+ cp_binding_level *bl = current_binding_level;
allocate_struct_function (decl1, processing_template_decl);
/* Initialize the language data structures. Whenever we start
@@ -16449,14 +16375,16 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
}
}
- honor_interface = (!DECL_TEMPLATE_INSTANTIATION (decl1)
- /* Implicitly-defined methods (like the
- destructor for a class in which no destructor
- is explicitly declared) must not be defined
- until their definition is needed. So, we
- ignore interface specifications for
- compiler-generated functions. */
- && !DECL_ARTIFICIAL (decl1));
+ bool honor_interface = (!DECL_TEMPLATE_INSTANTIATION (decl1)
+ /* Implicitly-defined methods (like the
+ destructor for a class in which no destructor
+ is explicitly declared) must not be defined
+ until their definition is needed. So, we
+ ignore interface specifications for
+ compiler-generated functions. */
+ && !DECL_ARTIFICIAL (decl1));
+ struct c_fileinfo *finfo
+ = get_fileinfo (LOCATION_FILE (DECL_SOURCE_LOCATION (decl1)));
if (processing_template_decl)
/* Don't mess with interface flags. */;
@@ -17376,18 +17304,17 @@ grokmethod (cp_decl_specifier_seq *declspecs,
/* We process method specializations in finish_struct_1. */
if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl))
{
- fndecl = push_template_decl (fndecl);
+ /* Avoid calling decl_spec_seq... until we have to. */
+ bool friendp = decl_spec_seq_has_spec_p (declspecs, ds_friend);
+ fndecl = push_template_decl (fndecl, friendp);
if (fndecl == error_mark_node)
return fndecl;
}
- if (! DECL_FRIEND_P (fndecl))
+ if (DECL_CHAIN (fndecl) && !decl_spec_seq_has_spec_p (declspecs, ds_friend))
{
- if (DECL_CHAIN (fndecl))
- {
- fndecl = copy_node (fndecl);
- TREE_CHAIN (fndecl) = NULL_TREE;
- }
+ fndecl = copy_node (fndecl);
+ TREE_CHAIN (fndecl) = NULL_TREE;
}
cp_finish_decl (fndecl, NULL_TREE, false, NULL_TREE, 0);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index fd48a21..2f0d637 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1021,7 +1021,7 @@ grokfield (const cp_declarator *declarator,
asmspec_tree, flags);
/* Pass friends back this way. */
- if (DECL_FRIEND_P (value))
+ if (DECL_UNIQUE_FRIEND_P (value))
return void_type_node;
DECL_IN_AGGR_P (value) = 1;
@@ -5567,6 +5567,22 @@ mark_used (tree decl, tsubst_flags_t complain)
return false;
}
+ if (VAR_OR_FUNCTION_DECL_P (decl) && DECL_LOCAL_DECL_P (decl))
+ {
+ if (!DECL_LANG_SPECIFIC (decl))
+ /* An unresolved dependent local extern. */
+ return true;
+
+ DECL_ODR_USED (decl) = 1;
+ auto alias = DECL_LOCAL_DECL_ALIAS (decl);
+ if (!alias || alias == error_mark_node)
+ return true;
+
+ /* Process the underlying decl. */
+ decl = alias;
+ TREE_USED (decl) = true;
+ }
+
cp_warn_deprecated_use (decl, complain);
/* We can only check DECL_ODR_USED on variables or functions with
@@ -5650,14 +5666,7 @@ mark_used (tree decl, tsubst_flags_t complain)
&& !DECL_ARTIFICIAL (decl)
&& !decl_defined_p (decl)
&& no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false))
- {
- if (is_local_extern (decl))
- /* There's no way to define a local extern, and adding it to
- the vector interferes with GC, so give an error now. */
- no_linkage_error (decl);
- else
- vec_safe_push (no_linkage_decls, decl);
- }
+ vec_safe_push (no_linkage_decls, decl);
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index ecb41e8..396558b 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -951,8 +951,11 @@ dump_type_suffix (cxx_pretty_printer *pp, tree t, int flags)
if (tree dtype = TYPE_DOMAIN (t))
{
tree max = TYPE_MAX_VALUE (dtype);
- /* Zero-length arrays have an upper bound of SIZE_MAX. */
- if (integer_all_onesp (max))
+ /* Zero-length arrays have a null upper bound in C and SIZE_MAX
+ in C++. Handle both since the type might be constructed by
+ the middle end and end up here as a result of a warning (see
+ PR c++/97201). */
+ if (!max || integer_all_onesp (max))
pp_character (pp, '0');
else if (tree_fits_shwi_p (max))
pp_wide_integer (pp, tree_to_shwi (max) + 1);
@@ -2400,6 +2403,64 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags)
}
break;
+ case TARGET_MEM_REF:
+ /* TARGET_MEM_REF can't appear directly from source, but can appear
+ during late GIMPLE optimizations and through late diagnostic we might
+ need to support it. Print it as dereferencing of a pointer after
+ cast to the TARGET_MEM_REF type, with pointer arithmetics on some
+ pointer to single byte types, so
+ *(type *)((char *) ptr + step * index + index2) if all the operands
+ are present and the casts are needed. */
+ pp_cxx_star (pp);
+ pp_cxx_left_paren (pp);
+ if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (TMR_BASE (t)))) == NULL_TREE
+ || !integer_onep (TYPE_SIZE_UNIT
+ (TREE_TYPE (TREE_TYPE (TMR_BASE (t))))))
+ {
+ if (TYPE_SIZE_UNIT (TREE_TYPE (t))
+ && integer_onep (TYPE_SIZE_UNIT (TREE_TYPE (t))))
+ {
+ pp_cxx_left_paren (pp);
+ dump_type (pp, build_pointer_type (TREE_TYPE (t)), flags);
+ }
+ else
+ {
+ dump_type (pp, build_pointer_type (TREE_TYPE (t)), flags);
+ pp_cxx_right_paren (pp);
+ pp_cxx_left_paren (pp);
+ pp_cxx_left_paren (pp);
+ dump_type (pp, build_pointer_type (char_type_node), flags);
+ }
+ pp_cxx_right_paren (pp);
+ }
+ else if (!same_type_p (TREE_TYPE (t),
+ TREE_TYPE (TREE_TYPE (TMR_BASE (t)))))
+ {
+ dump_type (pp, build_pointer_type (TREE_TYPE (t)), flags);
+ pp_cxx_right_paren (pp);
+ pp_cxx_left_paren (pp);
+ }
+ dump_expr (pp, TMR_BASE (t), flags);
+ if (TMR_STEP (t) && TMR_INDEX (t))
+ {
+ pp_cxx_ws_string (pp, "+");
+ dump_expr (pp, TMR_INDEX (t), flags);
+ pp_cxx_ws_string (pp, "*");
+ dump_expr (pp, TMR_STEP (t), flags);
+ }
+ if (TMR_INDEX2 (t))
+ {
+ pp_cxx_ws_string (pp, "+");
+ dump_expr (pp, TMR_INDEX2 (t), flags);
+ }
+ if (!integer_zerop (TMR_OFFSET (t)))
+ {
+ pp_cxx_ws_string (pp, "+");
+ dump_expr (pp, fold_convert (ssizetype, TMR_OFFSET (t)), flags);
+ }
+ pp_cxx_right_paren (pp);
+ break;
+
case NEGATE_EXPR:
case BIT_NOT_EXPR:
case TRUTH_NOT_EXPR:
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c
index fa20a93..56fa960 100644
--- a/gcc/cp/friend.c
+++ b/gcc/cp/friend.c
@@ -481,8 +481,8 @@ do_friend (tree ctype, tree declarator, tree decl,
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
gcc_assert (!ctype || MAYBE_CLASS_TYPE_P (ctype));
- /* Every decl that gets here is a friend of something. */
- DECL_FRIEND_P (decl) = 1;
+ /* Friend functions are unique, until proved otherwise. */
+ DECL_UNIQUE_FRIEND_P (decl) = 1;
if (DECL_OVERRIDE_P (decl) || DECL_FINAL_P (decl))
error ("friend declaration %qD may not have virt-specifiers",
@@ -558,7 +558,7 @@ do_friend (tree ctype, tree declarator, tree decl,
else if (class_template_depth)
/* We rely on tsubst_friend_function to check the
validity of the declaration later. */
- decl = push_template_decl_real (decl, /*is_friend=*/true);
+ decl = push_template_decl (decl, /*is_friend=*/true);
else
decl = check_classfn (ctype, decl,
template_member_p
@@ -581,25 +581,19 @@ do_friend (tree ctype, tree declarator, tree decl,
error ("member %qD declared as friend before type %qT defined",
decl, ctype);
}
- /* A global friend.
- @@ or possibly a friend from a base class ?!? */
- else if (TREE_CODE (decl) == FUNCTION_DECL)
+ else
{
+ /* Namespace-scope friend function. */
int is_friend_template = PROCESSING_REAL_TEMPLATE_DECL_P ();
- /* Friends must all go through the overload machinery,
- even though they may not technically be overloaded.
-
- Note that because classes all wind up being top-level
- in their scope, their friend wind up in top-level scope as well. */
if (funcdef_flag)
SET_DECL_FRIEND_CONTEXT (decl, current_class_type);
if (! DECL_USE_TEMPLATE (decl))
{
/* We must check whether the decl refers to template
- arguments before push_template_decl_real adds a
- reference to the containing template class. */
+ arguments before push_template_decl adds a reference to
+ the containing template class. */
int warn = (warn_nontemplate_friend
&& ! funcdef_flag && ! is_friend_template
&& current_template_parms
@@ -611,10 +605,10 @@ do_friend (tree ctype, tree declarator, tree decl,
general, such a declaration depends on template
parameters. Instead, we call pushdecl when the class
is instantiated. */
- decl = push_template_decl_real (decl, /*is_friend=*/true);
+ decl = push_template_decl (decl, /*is_friend=*/true);
else if (current_function_decl)
/* pushdecl will check there's a local decl already. */
- decl = pushdecl (decl, /*is_friend=*/true);
+ decl = pushdecl (decl, /*hiding=*/true);
else
{
/* We can't use pushdecl, as we might be in a template
@@ -624,7 +618,7 @@ do_friend (tree ctype, tree declarator, tree decl,
tree ns = decl_namespace_context (decl);
push_nested_namespace (ns);
- decl = pushdecl_namespace_level (decl, /*is_friend=*/true);
+ decl = pushdecl_namespace_level (decl, /*hiding=*/true);
pop_nested_namespace (ns);
}
@@ -653,7 +647,6 @@ do_friend (tree ctype, tree declarator, tree decl,
add_friend (current_class_type,
is_friend_template ? DECL_TI_TEMPLATE (decl) : decl,
/*complain=*/true);
- DECL_FRIEND_P (decl) = 1;
}
return decl;
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index e84e985..1bddb655 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see
#include "attribs.h"
#include "asan.h"
#include "stor-layout.h"
+#include "builtins.h"
static bool begin_init_stmts (tree *, tree *);
static tree finish_init_stmts (bool, tree, tree);
@@ -2564,27 +2565,6 @@ throw_bad_array_new_length (void)
return build_cxx_call (fn, 0, NULL, tf_warning_or_error);
}
-/* Attempt to find the initializer for flexible array field T in the
- initializer INIT, when non-null. Returns the initializer when
- successful and NULL otherwise. */
-static tree
-find_flexarray_init (tree t, tree init)
-{
- if (!init || init == error_mark_node)
- return NULL_TREE;
-
- unsigned HOST_WIDE_INT idx;
- tree field, elt;
-
- /* Iterate over all top-level initializer elements. */
- FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx, field, elt)
- /* If the member T is found, return it. */
- if (field == t)
- return elt;
-
- return NULL_TREE;
-}
-
/* Attempt to verify that the argument, OPER, of a placement new expression
refers to an object sufficiently large for an object of TYPE or an array
of NELTS of such objects when NELTS is non-null, and issue a warning when
@@ -2601,17 +2581,6 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
{
location_t loc = cp_expr_loc_or_input_loc (oper);
- /* The number of bytes to add to or subtract from the size of the provided
- buffer based on an offset into an array or an array element reference.
- Although intermediate results may be negative (as in a[3] - 2) a valid
- final result cannot be. */
- offset_int adjust = 0;
- /* True when the size of the entire destination object should be used
- to compute the possibly optimistic estimate of the available space. */
- bool use_obj_size = false;
- /* True when the reference to the destination buffer is an ADDR_EXPR. */
- bool addr_expr = false;
-
STRIP_NOPS (oper);
/* Using a function argument or a (non-array) variable as an argument
@@ -2625,231 +2594,96 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
/* Evaluate any constant expressions. */
size = fold_non_dependent_expr (size);
- /* Handle the common case of array + offset expression when the offset
- is a constant. */
- if (TREE_CODE (oper) == POINTER_PLUS_EXPR)
- {
- /* If the offset is compile-time constant, use it to compute a more
- accurate estimate of the size of the buffer. Since the operand
- of POINTER_PLUS_EXPR is represented as an unsigned type, convert
- it to signed first.
- Otherwise, use the size of the entire array as an optimistic
- estimate (this may lead to false negatives). */
- tree adj = TREE_OPERAND (oper, 1);
- adj = fold_for_warn (adj);
- if (CONSTANT_CLASS_P (adj))
- adjust += wi::to_offset (convert (ssizetype, adj));
- else
- use_obj_size = true;
-
- oper = TREE_OPERAND (oper, 0);
-
- STRIP_NOPS (oper);
- }
-
- if (TREE_CODE (oper) == TARGET_EXPR)
- oper = TREE_OPERAND (oper, 1);
- else if (TREE_CODE (oper) == ADDR_EXPR)
- {
- addr_expr = true;
- oper = TREE_OPERAND (oper, 0);
- }
-
- STRIP_NOPS (oper);
-
- if (TREE_CODE (oper) == ARRAY_REF
- && (addr_expr || TREE_CODE (TREE_TYPE (oper)) == ARRAY_TYPE))
- {
- /* Similar to the offset computed above, see if the array index
- is a compile-time constant. If so, and unless the offset was
- not a compile-time constant, use the index to determine the
- size of the buffer. Otherwise, use the entire array as
- an optimistic estimate of the size. */
- const_tree adj = fold_non_dependent_expr (TREE_OPERAND (oper, 1));
- if (!use_obj_size && CONSTANT_CLASS_P (adj))
- adjust += wi::to_offset (adj);
- else
- {
- use_obj_size = true;
- adjust = 0;
- }
+ access_ref ref;
+ ref.eval = [](tree x){ return fold_non_dependent_expr (x); };
+ ref.trail1special = warn_placement_new < 2;
+ tree objsize = compute_objsize (oper, 1, &ref);
+ if (!objsize)
+ return;
- oper = TREE_OPERAND (oper, 0);
- }
+ offset_int bytes_avail = wi::to_offset (objsize);
+ offset_int bytes_need;
- /* Refers to the declared object that constains the subobject referenced
- by OPER. When the object is initialized, makes it possible to determine
- the actual size of a flexible array member used as the buffer passed
- as OPER to placement new. */
- tree var_decl = NULL_TREE;
- /* True when operand is a COMPONENT_REF, to distinguish flexible array
- members from arrays of unspecified size. */
- bool compref = TREE_CODE (oper) == COMPONENT_REF;
-
- /* For COMPONENT_REF (i.e., a struct member) the size of the entire
- enclosing struct. Used to validate the adjustment (offset) into
- an array at the end of a struct. */
- offset_int compsize = 0;
-
- /* Descend into a struct or union to find the member whose address
- is being used as the argument. */
- if (TREE_CODE (oper) == COMPONENT_REF)
+ if (CONSTANT_CLASS_P (size))
+ bytes_need = wi::to_offset (size);
+ else if (nelts && CONSTANT_CLASS_P (nelts))
+ bytes_need = (wi::to_offset (nelts)
+ * wi::to_offset (TYPE_SIZE_UNIT (type)));
+ else if (tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
+ bytes_need = wi::to_offset (TYPE_SIZE_UNIT (type));
+ else
{
- tree comptype = TREE_TYPE (TREE_OPERAND (oper, 0));
- compsize = wi::to_offset (TYPE_SIZE_UNIT (comptype));
-
- tree op0 = oper;
- while (TREE_CODE (op0 = TREE_OPERAND (op0, 0)) == COMPONENT_REF);
- STRIP_ANY_LOCATION_WRAPPER (op0);
- if (VAR_P (op0))
- var_decl = op0;
- oper = TREE_OPERAND (oper, 1);
+ /* The type is a VLA. */
+ return;
}
- STRIP_ANY_LOCATION_WRAPPER (oper);
- tree opertype = TREE_TYPE (oper);
- if ((addr_expr || !INDIRECT_TYPE_P (opertype))
- && (VAR_P (oper)
- || TREE_CODE (oper) == FIELD_DECL
- || TREE_CODE (oper) == PARM_DECL))
- {
- /* A possibly optimistic estimate of the number of bytes available
- in the destination buffer. */
- offset_int bytes_avail = 0;
- /* True when the estimate above is in fact the exact size
- of the destination buffer rather than an estimate. */
- bool exact_size = true;
-
- /* Treat members of unions and members of structs uniformly, even
- though the size of a member of a union may be viewed as extending
- to the end of the union itself (it is by __builtin_object_size). */
- if ((VAR_P (oper) || use_obj_size)
- && DECL_SIZE_UNIT (oper)
- && tree_fits_uhwi_p (DECL_SIZE_UNIT (oper)))
- {
- /* Use the size of the entire array object when the expression
- refers to a variable or its size depends on an expression
- that's not a compile-time constant. */
- bytes_avail = wi::to_offset (DECL_SIZE_UNIT (oper));
- exact_size = !use_obj_size;
- }
- else if (tree opersize = TYPE_SIZE_UNIT (opertype))
- {
- /* Use the size of the type of the destination buffer object
- as the optimistic estimate of the available space in it.
- Use the maximum possible size for zero-size arrays and
- flexible array members (except of initialized objects
- thereof). */
- if (TREE_CODE (opersize) == INTEGER_CST)
- bytes_avail = wi::to_offset (opersize);
- }
-
- if (bytes_avail == 0)
- {
- if (var_decl)
- {
- /* Constructing into a buffer provided by the flexible array
- member of a declared object (which is permitted as a G++
- extension). If the array member has been initialized,
- determine its size from the initializer. Otherwise,
- the array size is zero. */
- if (tree init = find_flexarray_init (oper,
- DECL_INITIAL (var_decl)))
- bytes_avail = wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (init)));
- }
- else
- bytes_avail = (wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node))
- - compsize);
- }
-
- tree_code oper_code = TREE_CODE (opertype);
-
- if (compref && oper_code == ARRAY_TYPE)
- {
- tree nelts = array_type_nelts_top (opertype);
- tree nelts_cst = maybe_constant_value (nelts);
- if (TREE_CODE (nelts_cst) == INTEGER_CST
- && integer_onep (nelts_cst)
- && !var_decl
- && warn_placement_new < 2)
- return;
- }
-
- /* Reduce the size of the buffer by the adjustment computed above
- from the offset and/or the index into the array. */
- if (bytes_avail < adjust || adjust < 0)
- bytes_avail = 0;
- else
- {
- tree elttype = (TREE_CODE (opertype) == ARRAY_TYPE
- ? TREE_TYPE (opertype) : opertype);
- if (tree eltsize = TYPE_SIZE_UNIT (elttype))
- {
- bytes_avail -= adjust * wi::to_offset (eltsize);
- if (bytes_avail < 0)
- bytes_avail = 0;
- }
- }
+ if (bytes_avail >= bytes_need)
+ return;
- /* The minimum amount of space needed for the allocation. This
- is an optimistic estimate that makes it possible to detect
- placement new invocation for some undersize buffers but not
- others. */
- offset_int bytes_need;
+ /* True when the size to mention in the warning is exact as opposed
+ to "at least N". */
+ const bool exact_size = (ref.offrng[0] == ref.offrng[1]
+ || ref.sizrng[1] - ref.offrng[0] == 0);
- if (nelts)
- nelts = fold_for_warn (nelts);
-
- if (CONSTANT_CLASS_P (size))
- bytes_need = wi::to_offset (size);
- else if (nelts && CONSTANT_CLASS_P (nelts))
- bytes_need = (wi::to_offset (nelts)
- * wi::to_offset (TYPE_SIZE_UNIT (type)));
- else if (tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
- bytes_need = wi::to_offset (TYPE_SIZE_UNIT (type));
- else
- {
- /* The type is a VLA. */
- return;
- }
+ tree opertype = ref.ref ? TREE_TYPE (ref.ref) : TREE_TYPE (oper);
+ bool warned = false;
+ if (nelts)
+ nelts = fold_for_warn (nelts);
+ if (nelts)
+ if (CONSTANT_CLASS_P (nelts))
+ warned = warning_at (loc, OPT_Wplacement_new_,
+ (exact_size
+ ? G_("placement new constructing an object "
+ "of type %<%T [%wu]%> and size %qwu "
+ "in a region of type %qT and size %qwi")
+ : G_("placement new constructing an object "
+ "of type %<%T [%wu]%> and size %qwu "
+ "in a region of type %qT and size "
+ "at most %qwu")),
+ type, tree_to_uhwi (nelts),
+ bytes_need.to_uhwi (),
+ opertype, bytes_avail.to_uhwi ());
+ else
+ warned = warning_at (loc, OPT_Wplacement_new_,
+ (exact_size
+ ? G_("placement new constructing an array "
+ "of objects of type %qT and size %qwu "
+ "in a region of type %qT and size %qwi")
+ : G_("placement new constructing an array "
+ "of objects of type %qT and size %qwu "
+ "in a region of type %qT and size "
+ "at most %qwu")),
+ type, bytes_need.to_uhwi (), opertype,
+ bytes_avail.to_uhwi ());
+ else
+ warned = warning_at (loc, OPT_Wplacement_new_,
+ (exact_size
+ ? G_("placement new constructing an object "
+ "of type %qT and size %qwu in a region "
+ "of type %qT and size %qwi")
+ : G_("placement new constructing an object "
+ "of type %qT "
+ "and size %qwu in a region of type %qT "
+ "and size at most %qwu")),
+ type, bytes_need.to_uhwi (), opertype,
+ bytes_avail.to_uhwi ());
+
+ if (!warned || !ref.ref)
+ return;
- if (bytes_avail < bytes_need)
- {
- if (nelts)
- if (CONSTANT_CLASS_P (nelts))
- warning_at (loc, OPT_Wplacement_new_,
- exact_size ?
- "placement new constructing an object of type "
- "%<%T [%wu]%> and size %qwu in a region of type %qT "
- "and size %qwi"
- : "placement new constructing an object of type "
- "%<%T [%wu]%> and size %qwu in a region of type %qT "
- "and size at most %qwu",
- type, tree_to_uhwi (nelts), bytes_need.to_uhwi (),
- opertype, bytes_avail.to_uhwi ());
- else
- warning_at (loc, OPT_Wplacement_new_,
- exact_size ?
- "placement new constructing an array of objects "
- "of type %qT and size %qwu in a region of type %qT "
- "and size %qwi"
- : "placement new constructing an array of objects "
- "of type %qT and size %qwu in a region of type %qT "
- "and size at most %qwu",
- type, bytes_need.to_uhwi (), opertype,
- bytes_avail.to_uhwi ());
- else
- warning_at (loc, OPT_Wplacement_new_,
- exact_size ?
- "placement new constructing an object of type %qT "
- "and size %qwu in a region of type %qT and size %qwi"
- : "placement new constructing an object of type %qT "
- "and size %qwu in a region of type %qT and size "
- "at most %qwu",
- type, bytes_need.to_uhwi (), opertype,
- bytes_avail.to_uhwi ());
- }
- }
+ if (ref.offrng[0] == 0 || !ref.offset_bounded ())
+ /* Avoid mentioning the offset when its lower bound is zero
+ or when it's impossibly large. */
+ inform (DECL_SOURCE_LOCATION (ref.ref),
+ "%qD declared here", ref.ref);
+ else if (ref.offrng[0] == ref.offrng[1])
+ inform (DECL_SOURCE_LOCATION (ref.ref),
+ "at offset %wi from %qD declared here",
+ ref.offrng[0].to_shwi (), ref.ref);
+ else
+ inform (DECL_SOURCE_LOCATION (ref.ref),
+ "at offset [%wi, %wi] from %qD declared here",
+ ref.offrng[0].to_shwi (), ref.offrng[1].to_shwi (), ref.ref);
}
/* True if alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__. */
@@ -3433,10 +3267,6 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
}
}
- tree alloc_call_expr = extract_call_expr (alloc_call);
- if (TREE_CODE (alloc_call_expr) == CALL_EXPR)
- CALL_FROM_NEW_OR_DELETE_P (alloc_call_expr) = 1;
-
if (cookie_size)
alloc_call = maybe_wrap_new_for_constexpr (alloc_call, elt_type,
cookie_size);
@@ -4145,10 +3975,6 @@ build_vec_delete_1 (location_t loc, tree base, tree maxindex, tree type,
/*placement=*/NULL_TREE,
/*alloc_fn=*/NULL_TREE,
complain);
-
- tree deallocate_call_expr = extract_call_expr (deallocate_expr);
- if (TREE_CODE (deallocate_call_expr) == CALL_EXPR)
- CALL_FROM_NEW_OR_DELETE_P (deallocate_call_expr) = 1;
}
body = loop;
@@ -5073,12 +4899,6 @@ build_delete (location_t loc, tree otype, tree addr,
if (do_delete == error_mark_node)
return error_mark_node;
- else if (do_delete)
- {
- tree do_delete_call_expr = extract_call_expr (do_delete);
- if (TREE_CODE (do_delete_call_expr) == CALL_EXPR)
- CALL_FROM_NEW_OR_DELETE_P (do_delete_call_expr) = 1;
- }
if (do_delete && !TREE_SIDE_EFFECTS (expr))
expr = do_delete;
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index c94fe8e..1a1647f 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -134,8 +134,7 @@ begin_lambda_type (tree lambda)
IDENTIFIER_LAMBDA_P (name) = true;
/* Create the new RECORD_TYPE for this lambda. */
- tree type = xref_tag (/*tag_code=*/record_type, name,
- /*scope=*/ts_lambda, /*template_header_p=*/false);
+ tree type = xref_tag (/*tag_code=*/record_type, name);
if (type == error_mark_node)
return error_mark_node;
@@ -476,7 +475,7 @@ static GTY(()) tree max_id;
static tree
vla_capture_type (tree array_type)
{
- tree type = xref_tag (record_type, make_anon_name (), ts_current, false);
+ tree type = xref_tag (record_type, make_anon_name ());
xref_basetypes (type, NULL_TREE);
type = begin_class_definition (type);
if (!ptr_id)
@@ -1189,6 +1188,8 @@ maybe_add_lambda_conv_op (tree type)
tree name = make_conv_op_name (rettype);
tree thistype = cp_build_qualified_type (type, TYPE_QUAL_CONST);
tree fntype = build_method_type_directly (thistype, rettype, void_list_node);
+ /* DR 1722: The conversion function should be noexcept. */
+ fntype = build_exception_variant (fntype, noexcept_true_spec);
tree convfn = build_lang_decl (FUNCTION_DECL, name, fntype);
SET_DECL_LANGUAGE (convfn, lang_cplusplus);
tree fn = convfn;
@@ -1324,6 +1325,13 @@ lambda_static_thunk_p (tree fn)
&& LAMBDA_TYPE_P (CP_DECL_CONTEXT (fn)));
}
+bool
+call_from_lambda_thunk_p (tree call)
+{
+ return (CALL_FROM_THUNK_P (call)
+ && lambda_static_thunk_p (current_function_decl));
+}
+
/* Returns true iff VAL is a lambda-related declaration which should
be ignored by unqualified lookup. */
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 1058fd0..6e4c5f7 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -551,31 +551,51 @@ inherited_ctor_binfo (tree fndecl)
return inherited_ctor_binfo (binfo, fndecl);
}
-/* True if we should omit all user-declared parameters from constructor FN,
- because it is a base clone of a ctor inherited from a virtual base. */
+
+/* True if we should omit all user-declared parameters from a base
+ construtor built from complete constructor FN.
+ That's when the ctor is inherited from a virtual base. */
bool
-ctor_omit_inherited_parms (tree fn)
+base_ctor_omit_inherited_parms (tree comp_ctor)
{
+ gcc_checking_assert (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (comp_ctor));
+
if (!flag_new_inheriting_ctors)
/* We only optimize away the parameters in the new model. */
return false;
- if (!DECL_BASE_CONSTRUCTOR_P (fn)
- || !CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn)))
+
+ if (!CLASSTYPE_VBASECLASSES (DECL_CONTEXT (comp_ctor)))
return false;
- if (FUNCTION_FIRST_USER_PARMTYPE (DECL_ORIGIN (fn)) == void_list_node)
+ if (FUNCTION_FIRST_USER_PARMTYPE (comp_ctor) == void_list_node)
/* No user-declared parameters to omit. */
return false;
- tree binfo = inherited_ctor_binfo (fn);
- for (; binfo; binfo = BINFO_INHERITANCE_CHAIN (binfo))
+ for (tree binfo = inherited_ctor_binfo (comp_ctor);
+ binfo;
+ binfo = BINFO_INHERITANCE_CHAIN (binfo))
if (BINFO_VIRTUAL_P (binfo))
return true;
return false;
}
+
+/* True if we should omit all user-declared parameters from constructor FN,
+ because it is a base clone of a ctor inherited from a virtual base. */
+
+bool
+ctor_omit_inherited_parms (tree fn)
+{
+ gcc_checking_assert (TREE_CODE (fn) == FUNCTION_DECL);
+
+ if (!DECL_BASE_CONSTRUCTOR_P (fn))
+ return false;
+
+ return base_ctor_omit_inherited_parms (DECL_CLONED_FUNCTION (fn));
+}
+
/* True iff constructor(s) INH inherited into BINFO initializes INIT_BINFO.
This can be true for multiple virtual bases as well as one direct
non-virtual base. */
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index bbeaf64..4637427 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see
static cxx_binding *cxx_binding_make (tree value, tree type);
static cp_binding_level *innermost_nonclass_level (void);
+static tree do_pushdecl (tree decl, bool hiding);
static void set_identifier_type_value_with_scope (tree id, tree decl,
cp_binding_level *b);
static name_hint maybe_suggest_missing_std_header (location_t location,
@@ -55,6 +56,15 @@ static name_hint suggest_alternatives_for_1 (location_t location, tree name,
#define MAYBE_STAT_DECL(N) (STAT_HACK_P (N) ? STAT_DECL (N) : N)
#define MAYBE_STAT_TYPE(N) (STAT_HACK_P (N) ? STAT_TYPE (N) : NULL_TREE)
+/* For regular (maybe) overloaded functions, we have OVL_HIDDEN_P.
+ But we also need to indicate hiddenness on implicit type decls
+ (injected friend classes), and (coming soon) decls injected from
+ block-scope externs. It is too awkward to press the existing
+ overload marking for that. If we have a hidden non-function, we
+ always create a STAT_HACK, and use these two markers as needed. */
+#define STAT_TYPE_HIDDEN_P(N) OVL_HIDDEN_P (N)
+#define STAT_DECL_HIDDEN_P(N) OVL_DEDUP_P (N)
+
/* Create a STAT_HACK node with DECL as the value binding and TYPE as
the type binding. */
@@ -77,7 +87,6 @@ create_local_binding (cp_binding_level *level, tree name)
{
cxx_binding *binding = cxx_binding_make (NULL, NULL);
- INHERITED_VALUE_BINDING_P (binding) = false;
LOCAL_BINDING_P (binding) = true;
binding->scope = level;
binding->previous = IDENTIFIER_BINDING (name);
@@ -480,22 +489,17 @@ name_lookup::add_type (tree new_type)
}
/* Process a found binding containing NEW_VAL and NEW_TYPE. Returns
- true if we actually found something noteworthy. */
+ true if we actually found something noteworthy. Hiddenness has
+ already been handled in the caller. */
bool
name_lookup::process_binding (tree new_val, tree new_type)
{
/* Did we really see a type? */
if (new_type
- && ((want & LOOK_want::TYPE_NAMESPACE) == LOOK_want::NAMESPACE
- || (!bool (want & LOOK_want::HIDDEN_FRIEND)
- && DECL_LANG_SPECIFIC (new_type)
- && DECL_ANTICIPATED (new_type))))
+ && (want & LOOK_want::TYPE_NAMESPACE) == LOOK_want::NAMESPACE)
new_type = NULL_TREE;
- if (new_val && !bool (want & LOOK_want::HIDDEN_FRIEND))
- new_val = ovl_skip_hidden (new_val);
-
/* Do we really see a value? */
if (new_val)
switch (TREE_CODE (new_val))
@@ -544,8 +548,29 @@ name_lookup::search_namespace_only (tree scope)
bool found = false;
if (tree *binding = find_namespace_slot (scope, name))
- found |= process_binding (MAYBE_STAT_DECL (*binding),
- MAYBE_STAT_TYPE (*binding));
+ {
+ tree value = *binding, type = NULL_TREE;
+
+ if (STAT_HACK_P (value))
+ {
+ type = STAT_TYPE (value);
+ value = STAT_DECL (value);
+
+ if (!bool (want & LOOK_want::HIDDEN_FRIEND))
+ {
+ if (STAT_TYPE_HIDDEN_P (*binding))
+ type = NULL_TREE;
+ if (STAT_DECL_HIDDEN_P (*binding))
+ value = NULL_TREE;
+ else
+ value = ovl_skip_hidden (value);
+ }
+ }
+ else if (!bool (want & LOOK_want::HIDDEN_FRIEND))
+ value = ovl_skip_hidden (value);
+
+ found |= process_binding (value, type);
+ }
return found;
}
@@ -818,12 +843,6 @@ name_lookup::adl_class_only (tree type)
if (CP_DECL_CONTEXT (fn) != context)
continue;
- /* Only interested in anticipated friends. (Non-anticipated
- ones will have been inserted during the namespace
- adl.) */
- if (!DECL_ANTICIPATED (fn))
- continue;
-
/* Template specializations are never found by name lookup.
(Templates themselves can be found, but not template
specializations.) */
@@ -1055,11 +1074,8 @@ name_lookup::adl_template_arg (tree arg)
tree
name_lookup::search_adl (tree fns, vec<tree, va_gc> *args)
{
- if (fns)
- {
- deduping = true;
- lookup_mark (fns, true);
- }
+ deduping = true;
+ lookup_mark (fns, true);
value = fns;
unsigned ix;
@@ -1954,15 +1970,18 @@ cxx_binding_init (cxx_binding *binding, tree value, tree type)
static cxx_binding *
cxx_binding_make (tree value, tree type)
{
- cxx_binding *binding;
- if (free_bindings)
- {
- binding = free_bindings;
- free_bindings = binding->previous;
- }
+ cxx_binding *binding = free_bindings;
+
+ if (binding)
+ free_bindings = binding->previous;
else
binding = ggc_alloc<cxx_binding> ();
+ /* Clear flags by default. */
+ LOCAL_BINDING_P (binding) = false;
+ INHERITED_VALUE_BINDING_P (binding) = false;
+ HIDDEN_TYPE_BINDING_P (binding) = false;
+
cxx_binding_init (binding, value, type);
return binding;
@@ -2009,7 +2028,6 @@ push_binding (tree id, tree decl, cp_binding_level* level)
/* Now, fill in the binding information. */
binding->previous = IDENTIFIER_BINDING (id);
- INHERITED_VALUE_BINDING_P (binding) = 0;
LOCAL_BINDING_P (binding) = (level != class_binding_level);
/* And put it on the front of the list of bindings for ID. */
@@ -2022,8 +2040,6 @@ push_binding (tree id, tree decl, cp_binding_level* level)
void
pop_local_binding (tree id, tree decl)
{
- cxx_binding *binding;
-
if (id == NULL_TREE)
/* It's easiest to write the loops that call this function without
checking whether or not the entities involved have names. We
@@ -2031,18 +2047,20 @@ pop_local_binding (tree id, tree decl)
return;
/* Get the innermost binding for ID. */
- binding = IDENTIFIER_BINDING (id);
+ cxx_binding *binding = IDENTIFIER_BINDING (id);
/* The name should be bound. */
gcc_assert (binding != NULL);
- /* The DECL will be either the ordinary binding or the type
- binding for this identifier. Remove that binding. */
+ /* The DECL will be either the ordinary binding or the type binding
+ for this identifier. Remove that binding. We don't have to
+ clear HIDDEN_TYPE_BINDING_P, as the whole binding will be going
+ away. */
if (binding->value == decl)
binding->value = NULL_TREE;
else
{
- gcc_assert (binding->type == decl);
+ gcc_checking_assert (binding->type == decl);
binding->type = NULL_TREE;
}
@@ -2110,19 +2128,9 @@ strip_using_decl (tree decl)
static bool
anticipated_builtin_p (tree ovl)
{
- if (TREE_CODE (ovl) != OVERLOAD)
- return false;
-
- if (!OVL_HIDDEN_P (ovl))
- return false;
-
- tree fn = OVL_FUNCTION (ovl);
- gcc_checking_assert (DECL_ANTICIPATED (fn));
-
- if (DECL_HIDDEN_FRIEND_P (fn))
- return false;
-
- return true;
+ return (TREE_CODE (ovl) == OVERLOAD
+ && OVL_HIDDEN_P (ovl)
+ && DECL_UNDECLARED_BUILTIN_P (OVL_FUNCTION (ovl)));
}
/* BINDING records an existing declaration for a name in the current scope.
@@ -2232,7 +2240,7 @@ supplement_binding_1 (cxx_binding *binding, tree decl)
&& DECL_EXTERNAL (target_decl) && DECL_EXTERNAL (target_bval)
&& !DECL_CLASS_SCOPE_P (target_decl))
{
- duplicate_decls (decl, binding->value, /*newdecl_is_friend=*/false);
+ duplicate_decls (decl, binding->value);
ok = false;
}
else if (TREE_CODE (decl) == NAMESPACE_DECL
@@ -2354,48 +2362,66 @@ matching_fn_p (tree one, tree two)
static tree
update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
- tree old, tree decl, bool is_friend)
+ tree old, tree decl, bool hiding = false)
{
+ tree old_type = NULL_TREE;
+ bool hide_type = false;
+ bool hide_value = false;
+
+ if (!slot)
+ {
+ old_type = binding->type;
+ hide_type = HIDDEN_TYPE_BINDING_P (binding);
+ if (!old_type)
+ hide_value = hide_type, hide_type = false;
+ }
+ else if (STAT_HACK_P (*slot))
+ {
+ old_type = STAT_TYPE (*slot);
+ hide_type = STAT_TYPE_HIDDEN_P (*slot);
+ hide_value = STAT_DECL_HIDDEN_P (*slot);
+ }
+
tree to_val = decl;
- tree old_type = slot ? MAYBE_STAT_TYPE (*slot) : binding->type;
tree to_type = old_type;
+ bool local_overload = false;
gcc_assert (level->kind == sk_namespace ? !binding
: level->kind != sk_class && !slot);
if (old == error_mark_node)
old = NULL_TREE;
- if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
+ if (DECL_IMPLICIT_TYPEDEF_P (decl))
{
- tree other = to_type;
-
- if (old && TREE_CODE (old) == TYPE_DECL && DECL_ARTIFICIAL (old))
- other = old;
-
- /* Pushing an artificial typedef. See if this matches either
- the type slot or the old value slot. */
- if (!other)
- ;
- else if (same_type_p (TREE_TYPE (other), TREE_TYPE (decl)))
- /* Two artificial decls to same type. Do nothing. */
- return other;
- else
- goto conflict;
+ /* Pushing an artificial decl. We should not find another
+ artificial decl here already -- lookup_elaborated_type will
+ have already found it. */
+ gcc_checking_assert (!to_type
+ && !(old && DECL_IMPLICIT_TYPEDEF_P (old)));
if (old)
{
- /* Slide decl into the type slot, keep old unaltered */
+ /* Put DECL into the type slot. */
+ gcc_checking_assert (!to_type);
+ hide_type = hiding;
to_type = decl;
to_val = old;
- goto done;
}
+ else
+ hide_value = hiding;
+
+ goto done;
}
- if (old && TREE_CODE (old) == TYPE_DECL && DECL_ARTIFICIAL (old))
+ if (old && DECL_IMPLICIT_TYPEDEF_P (old))
{
- /* Slide old into the type slot. */
+ /* OLD is an implicit typedef. Move it to to_type. */
+ gcc_checking_assert (!to_type);
+
to_type = old;
+ hide_type = hide_value;
old = NULL_TREE;
+ hide_value = false;
}
if (DECL_DECLARES_FUNCTION_P (decl))
@@ -2410,13 +2436,14 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
if (iter.using_p () && matching_fn_p (fn, decl))
{
+ gcc_checking_assert (!iter.hidden_p ());
/* If a function declaration in namespace scope or
block scope has the same name and the same
parameter-type- list (8.3.5) as a function
introduced by a using-declaration, and the
declarations do not declare the same function,
the program is ill-formed. [namespace.udecl]/14 */
- if (tree match = duplicate_decls (decl, fn, is_friend))
+ if (tree match = duplicate_decls (decl, fn, hiding))
return match;
else
/* FIXME: To preserve existing error behavior, we
@@ -2436,60 +2463,70 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
warning (OPT_Wshadow, "%q#D hides constructor for %q#D",
decl, to_type);
- to_val = ovl_insert (decl, old);
- }
- else if (!old)
- ;
- else if (TREE_CODE (old) != TREE_CODE (decl))
- /* Different kinds of decls conflict. */
- goto conflict;
- else if (TREE_CODE (old) == TYPE_DECL)
- {
- if (same_type_p (TREE_TYPE (old), TREE_TYPE (decl)))
- /* Two type decls to the same type. Do nothing. */
- return old;
- else
- goto conflict;
+ local_overload = old && level->kind != sk_namespace;
+ to_val = ovl_insert (decl, old, -int (hiding));
}
- else if (TREE_CODE (old) == NAMESPACE_DECL)
+ else if (old)
{
- /* Two maybe-aliased namespaces. If they're to the same target
- namespace, that's ok. */
- if (ORIGINAL_NAMESPACE (old) != ORIGINAL_NAMESPACE (decl))
+ if (TREE_CODE (old) != TREE_CODE (decl))
+ /* Different kinds of decls conflict. */
goto conflict;
-
- /* The new one must be an alias at this point. */
- gcc_assert (DECL_NAMESPACE_ALIAS (decl));
- return old;
- }
- else if (TREE_CODE (old) == VAR_DECL)
- {
- /* There can be two block-scope declarations of the same
- variable, so long as they are `extern' declarations. */
- if (!DECL_EXTERNAL (old) || !DECL_EXTERNAL (decl))
- goto conflict;
- else if (tree match = duplicate_decls (decl, old, false))
- return match;
+ else if (TREE_CODE (old) == TYPE_DECL)
+ {
+ if (same_type_p (TREE_TYPE (old), TREE_TYPE (decl)))
+ {
+ /* Two type decls to the same type. Do nothing. */
+ gcc_checking_assert (!hiding);
+ return old;
+ }
+ else
+ goto conflict;
+ }
+ else if (TREE_CODE (old) == NAMESPACE_DECL)
+ {
+ /* Two maybe-aliased namespaces. If they're to the same target
+ namespace, that's ok. */
+ if (ORIGINAL_NAMESPACE (old) != ORIGINAL_NAMESPACE (decl))
+ goto conflict;
+
+ /* The new one must be an alias at this point. */
+ gcc_assert (DECL_NAMESPACE_ALIAS (decl) && !hiding);
+ return old;
+ }
+ else if (TREE_CODE (old) == VAR_DECL)
+ {
+ /* There can be two block-scope declarations of the same
+ variable, so long as they are `extern' declarations. */
+ if (!DECL_EXTERNAL (old) || !DECL_EXTERNAL (decl))
+ goto conflict;
+ else if (tree match = duplicate_decls (decl, old))
+ {
+ gcc_checking_assert (!hide_value && !hiding);
+ return match;
+ }
+ else
+ goto conflict;
+ }
else
- goto conflict;
- }
- else
- {
- conflict:
- diagnose_name_conflict (decl, old);
- to_val = NULL_TREE;
+ {
+ conflict:
+ diagnose_name_conflict (decl, old);
+ to_val = NULL_TREE;
+ }
}
+ else if (hiding)
+ hide_value = true;
done:
if (to_val)
{
- if (level->kind == sk_namespace || to_type == decl || to_val == decl)
- add_decl_to_level (level, decl);
- else
+ if (local_overload)
{
gcc_checking_assert (binding->value && OVL_P (binding->value));
update_local_overload (binding, to_val);
}
+ else
+ add_decl_to_level (level, decl);
if (slot)
{
@@ -2497,16 +2534,26 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
{
STAT_TYPE (*slot) = to_type;
STAT_DECL (*slot) = to_val;
+ STAT_TYPE_HIDDEN_P (*slot) = hide_type;
+ STAT_DECL_HIDDEN_P (*slot) = hide_value;
+ }
+ else if (to_type || hide_value)
+ {
+ *slot = stat_hack (to_val, to_type);
+ STAT_TYPE_HIDDEN_P (*slot) = hide_type;
+ STAT_DECL_HIDDEN_P (*slot) = hide_value;
}
- else if (to_type)
- *slot = stat_hack (to_val, to_type);
else
- *slot = to_val;
+ {
+ gcc_checking_assert (!hide_type);
+ *slot = to_val;
+ }
}
else
{
binding->type = to_type;
binding->value = to_val;
+ HIDDEN_TYPE_BINDING_P (binding) = hide_type || hide_value;
}
}
@@ -2857,9 +2904,12 @@ set_decl_context_in_fn (tree ctx, tree decl)
{
if (TREE_CODE (decl) == FUNCTION_DECL
|| (VAR_P (decl) && DECL_EXTERNAL (decl)))
- /* Make sure local externs are marked as such. */
+ /* Make sure local externs are marked as such. OMP UDRs really
+ are nested functions. */
gcc_checking_assert (DECL_LOCAL_DECL_P (decl)
- && DECL_NAMESPACE_SCOPE_P (decl));
+ && (DECL_NAMESPACE_SCOPE_P (decl)
+ || (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_OMP_DECLARE_REDUCTION_P (decl))));
if (!DECL_CONTEXT (decl)
/* When parsing the parameter list of a function declarator,
@@ -2872,108 +2922,113 @@ set_decl_context_in_fn (tree ctx, tree decl)
DECL_CONTEXT (decl) = ctx;
}
-/* DECL is a local-scope decl with linkage. SHADOWED is true if the
- name is already bound at the current level.
-
- [basic.link] If there is a visible declaration of an entity with
- linkage having the same name and type, ignoring entities declared
- outside the innermost enclosing namespace scope, the block scope
- declaration declares that same entity and receives the linkage of
- the previous declaration.
-
- Also, make sure that this decl matches any existing external decl
- in the enclosing namespace. */
+/* DECL is a local extern decl. Find or create the namespace-scope
+ decl that it aliases. Also, determines the linkage of DECL. */
static void
-set_local_extern_decl_linkage (tree decl, bool shadowed)
+push_local_extern_decl_alias (tree decl)
{
- tree ns_value = decl; /* Unique marker. */
+ if (dependent_type_p (TREE_TYPE (decl)))
+ return;
+ /* EH specs were not part of the function type prior to c++17, but
+ we still can't go pushing dependent eh specs into the namespace. */
+ if (cxx_dialect < cxx17
+ && TREE_CODE (decl) == FUNCTION_DECL
+ && (value_dependent_expression_p
+ (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)))))
+ return;
- if (!shadowed)
- {
- tree loc_value = innermost_non_namespace_value (DECL_NAME (decl));
- if (!loc_value)
- {
- ns_value
- = find_namespace_value (current_namespace, DECL_NAME (decl));
- loc_value = ns_value;
- }
- if (loc_value == error_mark_node
- /* An ambiguous lookup. */
- || (loc_value && TREE_CODE (loc_value) == TREE_LIST))
- loc_value = NULL_TREE;
-
- for (ovl_iterator iter (loc_value); iter; ++iter)
- if (!iter.hidden_p ()
- && (TREE_STATIC (*iter) || DECL_EXTERNAL (*iter))
- && decls_match (*iter, decl))
- {
- /* The standard only says that the local extern inherits
- linkage from the previous decl; in particular, default
- args are not shared. Add the decl into a hash table to
- make sure only the previous decl in this case is seen
- by the middle end. */
- struct cxx_int_tree_map *h;
-
- /* We inherit the outer decl's linkage. But we're a
- different decl. */
- TREE_PUBLIC (decl) = TREE_PUBLIC (*iter);
-
- if (cp_function_chain->extern_decl_map == NULL)
- cp_function_chain->extern_decl_map
- = hash_table<cxx_int_tree_map_hasher>::create_ggc (20);
-
- h = ggc_alloc<cxx_int_tree_map> ();
- h->uid = DECL_UID (decl);
- h->to = *iter;
- cxx_int_tree_map **loc = cp_function_chain->extern_decl_map
- ->find_slot (h, INSERT);
- *loc = h;
- break;
- }
- }
+ gcc_checking_assert (!DECL_LANG_SPECIFIC (decl)
+ || !DECL_TEMPLATE_INFO (decl));
+ if (DECL_LANG_SPECIFIC (decl) && DECL_LOCAL_DECL_ALIAS (decl))
+ /* We're instantiating a non-dependent local decl, it already
+ knows the alias. */
+ return;
- if (TREE_PUBLIC (decl))
- {
- /* DECL is externally visible. Make sure it matches a matching
- decl in the namespace scope. We only really need to check
- this when inserting the decl, not when we find an existing
- match in the current scope. However, in practice we're
- going to be inserting a new decl in the majority of cases --
- who writes multiple extern decls for the same thing in the
- same local scope? Doing it here often avoids a duplicate
- namespace lookup. */
+ tree alias = NULL_TREE;
- /* Avoid repeating a lookup. */
- if (ns_value == decl)
- ns_value = find_namespace_value (current_namespace, DECL_NAME (decl));
+ if (DECL_SIZE (decl) && !TREE_CONSTANT (DECL_SIZE (decl)))
+ /* Do not let a VLA creep into a namespace. Diagnostic will be
+ emitted in layout_var_decl later. */
+ alias = error_mark_node;
+ else
+ {
+ /* First look for a decl that matches. */
+ tree ns = CP_DECL_CONTEXT (decl);
+ tree binding = find_namespace_value (ns, DECL_NAME (decl));
- if (ns_value == error_mark_node
- || (ns_value && TREE_CODE (ns_value) == TREE_LIST))
- ns_value = NULL_TREE;
+ if (binding && TREE_CODE (binding) != TREE_LIST)
+ for (ovl_iterator iter (binding); iter; ++iter)
+ if (decls_match (*iter, decl))
+ {
+ alias = *iter;
+ break;
+ }
- for (ovl_iterator iter (ns_value); iter; ++iter)
+ if (!alias)
{
- tree other = *iter;
-
- if (!(TREE_PUBLIC (other) || DECL_EXTERNAL (other)))
- ; /* Not externally visible. */
- else if (DECL_EXTERN_C_P (decl) && DECL_EXTERN_C_P (other))
- ; /* Both are extern "C", we'll check via that mechanism. */
- else if (TREE_CODE (other) != TREE_CODE (decl)
- || ((VAR_P (decl) || matching_fn_p (other, decl))
- && !comptypes (TREE_TYPE (decl), TREE_TYPE (other),
- COMPARE_REDECLARATION)))
+ /* No existing namespace-scope decl. Make one. */
+ alias = copy_decl (decl);
+ if (TREE_CODE (alias) == FUNCTION_DECL)
{
- auto_diagnostic_group d;
- if (permerror (DECL_SOURCE_LOCATION (decl),
- "local external declaration %q#D", decl))
- inform (DECL_SOURCE_LOCATION (other),
- "does not match previous declaration %q#D", other);
- break;
+ /* Recontextualize the parms. */
+ for (tree *chain = &DECL_ARGUMENTS (alias);
+ *chain; chain = &DECL_CHAIN (*chain))
+ {
+ *chain = copy_decl (*chain);
+ DECL_CONTEXT (*chain) = alias;
+ }
+
+ tree type = TREE_TYPE (alias);
+ for (tree args = TYPE_ARG_TYPES (type);
+ args; args = TREE_CHAIN (args))
+ if (TREE_PURPOSE (args))
+ {
+ /* There are default args. Lose them. */
+ tree nargs = NULL_TREE;
+ tree *chain = &nargs;
+ for (args = TYPE_ARG_TYPES (type);
+ args; args = TREE_CHAIN (args))
+ if (args == void_list_node)
+ {
+ *chain = args;
+ break;
+ }
+ else
+ {
+ *chain
+ = build_tree_list (NULL_TREE, TREE_VALUE (args));
+ chain = &TREE_CHAIN (*chain);
+ }
+
+ tree fn_type = build_function_type (TREE_TYPE (type), nargs);
+
+ fn_type = apply_memfn_quals
+ (fn_type, type_memfn_quals (type));
+
+ fn_type = build_cp_fntype_variant
+ (fn_type, type_memfn_rqual (type),
+ TYPE_RAISES_EXCEPTIONS (type),
+ TYPE_HAS_LATE_RETURN_TYPE (type));
+
+ TREE_TYPE (alias) = fn_type;
+ break;
+ }
}
+
+ /* This is the real thing. */
+ DECL_LOCAL_DECL_P (alias) = false;
+
+ /* Expected default linkage is from the namespace. */
+ TREE_PUBLIC (alias) = TREE_PUBLIC (ns);
+ push_nested_namespace (ns);
+ alias = do_pushdecl (alias, /* hiding= */true);
+ pop_nested_namespace (ns);
}
}
+
+ retrofit_lang_decl (decl);
+ DECL_LOCAL_DECL_ALIAS (decl) = alias;
}
/* Record DECL as belonging to the current lexical scope. Check for
@@ -2986,12 +3041,12 @@ set_local_extern_decl_linkage (tree decl, bool shadowed)
says. */
static tree
-do_pushdecl (tree decl, bool is_friend)
+do_pushdecl (tree decl, bool hiding)
{
if (decl == error_mark_node)
return error_mark_node;
- if (!DECL_TEMPLATE_PARM_P (decl) && current_function_decl && !is_friend)
+ if (!DECL_TEMPLATE_PARM_P (decl) && current_function_decl && !hiding)
set_decl_context_in_fn (current_function_decl, decl);
/* The binding level we will be pushing into. During local class
@@ -3031,17 +3086,14 @@ do_pushdecl (tree decl, bool is_friend)
old = binding->value;
}
- if (current_function_decl && VAR_OR_FUNCTION_DECL_P (decl)
- && DECL_EXTERNAL (decl))
- set_local_extern_decl_linkage (decl, old != NULL_TREE);
-
if (old == error_mark_node)
old = NULL_TREE;
for (ovl_iterator iter (old); iter; ++iter)
if (iter.using_p ())
; /* Ignore using decls here. */
- else if (tree match = duplicate_decls (decl, *iter, is_friend))
+ else if (tree match
+ = duplicate_decls (decl, *iter, hiding, iter.hidden_p ()))
{
if (match == error_mark_node)
;
@@ -3049,18 +3101,14 @@ do_pushdecl (tree decl, bool is_friend)
/* The IDENTIFIER will have the type referring to the
now-smashed TYPE_DECL, because ...? Reset it. */
SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (match));
- else if (iter.hidden_p () && !DECL_HIDDEN_P (match))
+ else if (iter.hidden_p () && !hiding)
{
/* Unhiding a previously hidden decl. */
tree head = iter.reveal_node (old);
if (head != old)
{
- if (!ns)
- {
- update_local_overload (binding, head);
- binding->value = head;
- }
- else if (STAT_HACK_P (*slot))
+ gcc_checking_assert (ns);
+ if (STAT_HACK_P (*slot))
STAT_DECL (*slot) = head;
else
*slot = head;
@@ -3069,6 +3117,16 @@ do_pushdecl (tree decl, bool is_friend)
/* We need to check and register the decl now. */
check_extern_c_conflict (match);
}
+ else if (slot && !hiding
+ && STAT_HACK_P (*slot) && STAT_DECL_HIDDEN_P (*slot))
+ {
+ /* Unhide the non-function. */
+ gcc_checking_assert (old == match);
+ if (!STAT_TYPE (*slot))
+ *slot = match;
+ else
+ STAT_DECL (*slot) = match;
+ }
return match;
}
@@ -3085,7 +3143,7 @@ do_pushdecl (tree decl, bool is_friend)
{
check_default_args (decl);
- if (is_friend)
+ if (hiding)
{
if (level->kind != sk_namespace)
{
@@ -3098,8 +3156,6 @@ do_pushdecl (tree decl, bool is_friend)
/* Don't attempt to push it. */
return error_mark_node;
}
- /* Hide it from ordinary lookup. */
- DECL_ANTICIPATED (decl) = DECL_HIDDEN_FRIEND_P (decl) = true;
}
}
@@ -3109,7 +3165,7 @@ do_pushdecl (tree decl, bool is_friend)
if (TREE_CODE (decl) == NAMESPACE_DECL)
/* A local namespace alias. */
- set_identifier_type_value (name, NULL_TREE);
+ set_identifier_type_value_with_scope (name, NULL_TREE, level);
if (!binding)
binding = create_local_binding (level, name);
@@ -3123,7 +3179,7 @@ do_pushdecl (tree decl, bool is_friend)
old = MAYBE_STAT_DECL (*slot);
}
- old = update_binding (level, binding, slot, old, decl, is_friend);
+ old = update_binding (level, binding, slot, old, decl, hiding);
if (old != decl)
/* An existing decl matched, use it. */
@@ -3137,10 +3193,7 @@ do_pushdecl (tree decl, bool is_friend)
if (TYPE_NAME (type) != decl)
set_underlying_type (decl);
- if (!ns)
- set_identifier_type_value_with_scope (name, decl, level);
- else
- SET_IDENTIFIER_TYPE_VALUE (name, global_type_node);
+ set_identifier_type_value_with_scope (name, decl, level);
}
/* If this is a locally defined typedef in a function that
@@ -3149,12 +3202,21 @@ do_pushdecl (tree decl, bool is_friend)
if (!instantiating_current_function_p ())
record_locally_defined_typedef (decl);
}
- else if (VAR_P (decl))
- maybe_register_incomplete_var (decl);
+ else
+ {
+ if (VAR_P (decl) && !DECL_LOCAL_DECL_P (decl))
+ maybe_register_incomplete_var (decl);
- if ((VAR_P (decl) || TREE_CODE (decl) == FUNCTION_DECL)
- && DECL_EXTERN_C_P (decl))
- check_extern_c_conflict (decl);
+ if (VAR_OR_FUNCTION_DECL_P (decl))
+ {
+ if (DECL_LOCAL_DECL_P (decl)
+ && TREE_CODE (CP_DECL_CONTEXT (decl)) == NAMESPACE_DECL)
+ push_local_extern_decl_alias (decl);
+
+ if (DECL_EXTERN_C_P (decl))
+ check_extern_c_conflict (decl);
+ }
+ }
}
else
add_decl_to_level (level, decl);
@@ -3167,10 +3229,10 @@ do_pushdecl (tree decl, bool is_friend)
we push it. */
tree
-pushdecl (tree x, bool is_friend)
+pushdecl (tree x, bool hiding)
{
bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
- tree ret = do_pushdecl (x, is_friend);
+ tree ret = do_pushdecl (x, hiding);
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
return ret;
}
@@ -3755,8 +3817,9 @@ identifier_type_value (tree id)
}
/* Push a definition of struct, union or enum tag named ID. into
- binding_level B. DECL is a TYPE_DECL for the type. We assume that
- the tag ID is not already defined. */
+ binding_level B. DECL is a TYPE_DECL for the type. DECL has
+ already been pushed into its binding level. This is bookkeeping to
+ find it easily. */
static void
set_identifier_type_value_with_scope (tree id, tree decl, cp_binding_level *b)
@@ -3768,20 +3831,25 @@ set_identifier_type_value_with_scope (tree id, tree decl, cp_binding_level *b)
/* Shadow the marker, not the real thing, so that the marker
gets restored later. */
tree old_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
- b->type_shadowed
- = tree_cons (id, old_type_value, b->type_shadowed);
+ b->type_shadowed = tree_cons (id, old_type_value, b->type_shadowed);
type = decl ? TREE_TYPE (decl) : NULL_TREE;
TREE_TYPE (b->type_shadowed) = type;
}
else
{
- tree *slot = find_namespace_slot (current_namespace, id, true);
gcc_assert (decl);
- update_binding (b, NULL, slot, MAYBE_STAT_DECL (*slot), decl, false);
+ if (CHECKING_P)
+ {
+ tree *slot = find_namespace_slot (current_namespace, id);
+ gcc_checking_assert (slot
+ && (decl == MAYBE_STAT_TYPE (*slot)
+ || decl == MAYBE_STAT_DECL (*slot)));
+ }
/* Store marker instead of real type. */
type = global_type_node;
}
+
SET_IDENTIFIER_TYPE_VALUE (id, type);
}
@@ -3827,18 +3895,26 @@ constructor_name_p (tree name, tree type)
/* Same as pushdecl, but define X in binding-level LEVEL. We rely on the
caller to set DECL_CONTEXT properly.
- Note that this must only be used when X will be the new innermost
- binding for its name, as we tack it onto the front of IDENTIFIER_BINDING
- without checking to see if the current IDENTIFIER_BINDING comes from a
- closer binding level than LEVEL. */
+ Warning: For class and block-scope this must only be used when X
+ will be the new innermost binding for its name, as we tack it onto
+ the front of IDENTIFIER_BINDING without checking to see if the
+ current IDENTIFIER_BINDING comes from a closer binding level than
+ LEVEL.
+
+ Warning: For namespace scope, this will look in LEVEL for an
+ existing binding to match, but if not found will push the decl into
+ CURRENT_NAMESPACE. Use push_nested_namespace/pushdecl/
+ pop_nested_namespace if you really need to push it into a foreign
+ namespace. */
static tree
-do_pushdecl_with_scope (tree x, cp_binding_level *level, bool is_friend)
+do_pushdecl_with_scope (tree x, cp_binding_level *level, bool hiding = false)
{
cp_binding_level *b;
if (level->kind == sk_class)
{
+ gcc_checking_assert (!hiding);
b = class_binding_level;
class_binding_level = level;
pushdecl_class_level (x);
@@ -3851,7 +3927,7 @@ do_pushdecl_with_scope (tree x, cp_binding_level *level, bool is_friend)
current_function_decl = NULL_TREE;
b = current_binding_level;
current_binding_level = level;
- x = pushdecl (x, is_friend);
+ x = do_pushdecl (x, hiding);
current_binding_level = b;
current_function_decl = function_decl;
}
@@ -3871,7 +3947,7 @@ pushdecl_outermost_localscope (tree x)
n->kind != sk_function_parms; n = b->level_chain)
b = n;
- tree ret = b ? do_pushdecl_with_scope (x, b, false) : error_mark_node;
+ tree ret = b ? do_pushdecl_with_scope (x, b) : error_mark_node;
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
return ret;
@@ -3934,7 +4010,7 @@ do_nonmember_using_decl (name_lookup &lookup, bool fn_scope_p,
}
else if (old.using_p ())
continue; /* This is a using decl. */
- else if (old.hidden_p () && !DECL_HIDDEN_FRIEND_P (old_fn))
+ else if (old.hidden_p () && DECL_UNDECLARED_BUILTIN_P (old_fn))
continue; /* This is an anticipated builtin. */
else if (!matching_fn_p (new_fn, old_fn))
continue; /* Parameters do not match. */
@@ -4390,8 +4466,6 @@ get_class_binding (tree name, cp_binding_level *scope)
value_binding,
type_binding,
scope);
- /* This is a class-scope binding, not a block-scope binding. */
- LOCAL_BINDING_P (binding) = 0;
set_inherited_value_binding_p (binding, value_binding, class_type);
}
else
@@ -4849,8 +4923,15 @@ set_decl_namespace (tree decl, tree scope, bool friendp)
/* Since decl is a function, old should contain a function decl. */
if (!OVL_P (old))
- goto not_found;
+ {
+ not_found:
+ /* It didn't work, go back to the explicit scope. */
+ DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
+ error ("%qD should have been declared inside %qD", decl, scope);
+ return;
+ }
+
/* We handle these in check_explicit_instantiation_namespace. */
if (processing_explicit_instantiation)
return;
@@ -4860,13 +4941,14 @@ set_decl_namespace (tree decl, tree scope, bool friendp)
match. But, we'll check later, when we construct the
template. */
return;
+
/* Instantiations or specializations of templates may be declared as
friends in any namespace. */
if (friendp && DECL_USE_TEMPLATE (decl))
return;
- tree found;
- found = NULL_TREE;
+ tree found = NULL_TREE;
+ bool hidden_p = false;
for (lkp_iterator iter (old); iter; ++iter)
{
@@ -4882,17 +4964,20 @@ set_decl_namespace (tree decl, tree scope, bool friendp)
{
if (found)
{
- /* We found more than one matching declaration. */
+ /* We found more than one matching declaration. This
+ can happen if we have two inline namespace children,
+ each containing a suitable declaration. */
DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
goto ambiguous;
}
found = ofn;
+ hidden_p = iter.hidden_p ();
}
}
if (found)
{
- if (DECL_HIDDEN_FRIEND_P (found))
+ if (hidden_p)
{
pedwarn (DECL_SOURCE_LOCATION (decl), 0,
"%qD has not been declared within %qD", decl, scope);
@@ -4903,10 +4988,7 @@ set_decl_namespace (tree decl, tree scope, bool friendp)
goto found;
}
- not_found:
- /* It didn't work, go back to the explicit scope. */
- DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
- error ("%qD should have been declared inside %qD", decl, scope);
+ goto not_found;
}
/* Return the namespace where the current declaration is declared. */
@@ -5069,14 +5151,13 @@ do_namespace_alias (tree alias, tree name_space)
if appropriate. */
tree
-pushdecl_namespace_level (tree x, bool is_friend)
+pushdecl_namespace_level (tree x, bool hiding)
{
cp_binding_level *b = current_binding_level;
tree t;
bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
- t = do_pushdecl_with_scope
- (x, NAMESPACE_LEVEL (current_namespace), is_friend);
+ t = do_pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace), hiding);
/* Now, the type_shadowed stack may screw us. Munge it so it does
what we want. */
@@ -6024,6 +6105,101 @@ qualified_namespace_lookup (tree scope, name_lookup *lookup)
return found;
}
+/* If DECL is suitably visible to the user, consider its name for
+ spelling correction. */
+
+static void
+consider_decl (tree decl, best_match <tree, const char *> &bm,
+ bool consider_impl_names)
+{
+ /* Skip compiler-generated variables (e.g. __for_begin/__for_end
+ within range for). */
+ if (TREE_CODE (decl) == VAR_DECL && DECL_ARTIFICIAL (decl))
+ return;
+
+ tree suggestion = DECL_NAME (decl);
+ if (!suggestion)
+ return;
+
+ /* Don't suggest names that are for anonymous aggregate types, as
+ they are an implementation detail generated by the compiler. */
+ if (IDENTIFIER_ANON_P (suggestion))
+ return;
+
+ const char *suggestion_str = IDENTIFIER_POINTER (suggestion);
+
+ /* Ignore internal names with spaces in them. */
+ if (strchr (suggestion_str, ' '))
+ return;
+
+ /* Don't suggest names that are reserved for use by the
+ implementation, unless NAME began with an underscore. */
+ if (!consider_impl_names
+ && name_reserved_for_implementation_p (suggestion_str))
+ return;
+
+ bm.consider (suggestion_str);
+}
+
+/* If DECL is suitably visible to the user, add its name to VEC and
+ return true. Otherwise return false. */
+
+static bool
+maybe_add_fuzzy_decl (auto_vec<tree> &vec, tree decl)
+{
+ /* Skip compiler-generated variables (e.g. __for_begin/__for_end
+ within range for). */
+ if (TREE_CODE (decl) == VAR_DECL && DECL_ARTIFICIAL (decl))
+ return false;
+
+ tree suggestion = DECL_NAME (decl);
+ if (!suggestion)
+ return false;
+
+ /* Don't suggest names that are for anonymous aggregate types, as
+ they are an implementation detail generated by the compiler. */
+ if (IDENTIFIER_ANON_P (suggestion))
+ return false;
+
+ vec.safe_push (suggestion);
+
+ return true;
+}
+
+/* Examing the namespace binding BINDING, and add at most one instance
+ of the name, if it contains a visible entity of interest. */
+
+void
+maybe_add_fuzzy_binding (auto_vec<tree> &vec, tree binding,
+ lookup_name_fuzzy_kind kind)
+{
+ tree value = NULL_TREE;
+
+ if (STAT_HACK_P (binding))
+ {
+ if (!STAT_TYPE_HIDDEN_P (binding)
+ && STAT_TYPE (binding))
+ {
+ if (maybe_add_fuzzy_decl (vec, STAT_TYPE (binding)))
+ return;
+ }
+ else if (!STAT_DECL_HIDDEN_P (binding))
+ value = STAT_DECL (binding);
+ }
+ else
+ value = binding;
+
+ value = ovl_skip_hidden (value);
+ if (value)
+ {
+ value = OVL_FIRST (value);
+ if (kind != FUZZY_LOOKUP_TYPENAME
+ || TREE_CODE (STRIP_TEMPLATE (value)) == TYPE_DECL)
+ if (maybe_add_fuzzy_decl (vec, value))
+ return;
+ }
+}
+
/* Helper function for lookup_name_fuzzy.
Traverse binding level LVL, looking for good name matches for NAME
(and BM). */
@@ -6047,54 +6223,71 @@ consider_binding_level (tree name, best_match <tree, const char *> &bm,
with an underscore. */
bool consider_implementation_names = (IDENTIFIER_POINTER (name)[0] == '_');
- for (tree t = lvl->names; t; t = TREE_CHAIN (t))
- {
- tree d = t;
-
- /* OVERLOADs or decls from using declaration are wrapped into
- TREE_LIST. */
- if (TREE_CODE (d) == TREE_LIST)
- d = OVL_FIRST (TREE_VALUE (d));
-
- /* Don't use bindings from implicitly declared functions,
- as they were likely misspellings themselves. */
- if (TREE_TYPE (d) == error_mark_node)
- continue;
-
- /* Skip anticipated decls of builtin functions. */
- if (TREE_CODE (d) == FUNCTION_DECL
- && fndecl_built_in_p (d)
- && DECL_ANTICIPATED (d))
- continue;
-
- /* Skip compiler-generated variables (e.g. __for_begin/__for_end
- within range for). */
- if (TREE_CODE (d) == VAR_DECL
- && DECL_ARTIFICIAL (d))
- continue;
+ if (lvl->kind != sk_namespace)
+ for (tree t = lvl->names; t; t = TREE_CHAIN (t))
+ {
+ tree d = t;
- tree suggestion = DECL_NAME (d);
- if (!suggestion)
- continue;
+ /* OVERLOADs or decls from using declaration are wrapped into
+ TREE_LIST. */
+ if (TREE_CODE (d) == TREE_LIST)
+ d = OVL_FIRST (TREE_VALUE (d));
- /* Don't suggest names that are for anonymous aggregate types, as
- they are an implementation detail generated by the compiler. */
- if (IDENTIFIER_ANON_P (suggestion))
- continue;
+ /* Don't use bindings from implicitly declared functions,
+ as they were likely misspellings themselves. */
+ if (TREE_TYPE (d) == error_mark_node)
+ continue;
- const char *suggestion_str = IDENTIFIER_POINTER (suggestion);
+ /* If we want a typename, ignore non-types. */
+ if (kind == FUZZY_LOOKUP_TYPENAME
+ && TREE_CODE (STRIP_TEMPLATE (d)) != TYPE_DECL)
+ continue;
- /* Ignore internal names with spaces in them. */
- if (strchr (suggestion_str, ' '))
- continue;
+ consider_decl (d, bm, consider_implementation_names);
+ }
+ else
+ {
+ /* We need to iterate over the namespace hash table, in order to
+ not mention hidden entities. But hash table iteration is
+ (essentially) unpredictable, our correction-distance measure
+ is very granular, and we pick the first of equal distances.
+ Hence, we need to call the distance-measurer in a predictable
+ order. So, iterate over the namespace hash, inserting
+ visible names into a vector. Then sort the vector. Then
+ determine spelling distance. */
+
+ tree ns = lvl->this_entity;
+ auto_vec<tree> vec;
+
+ hash_table<named_decl_hash>::iterator end
+ (DECL_NAMESPACE_BINDINGS (ns)->end ());
+ for (hash_table<named_decl_hash>::iterator iter
+ (DECL_NAMESPACE_BINDINGS (ns)->begin ()); iter != end; ++iter)
+ maybe_add_fuzzy_binding (vec, *iter, kind);
+
+ vec.qsort ([] (const void *a_, const void *b_)
+ {
+ return strcmp (IDENTIFIER_POINTER (*(const tree *)a_),
+ IDENTIFIER_POINTER (*(const tree *)b_));
+ });
+
+ /* Examine longest to shortest. */
+ for (unsigned ix = vec.length (); ix--;)
+ {
+ const char *str = IDENTIFIER_POINTER (vec[ix]);
- /* Don't suggest names that are reserved for use by the
- implementation, unless NAME began with an underscore. */
- if (name_reserved_for_implementation_p (suggestion_str)
- && !consider_implementation_names)
- continue;
+ /* Ignore internal names with spaces in them. */
+ if (strchr (str, ' '))
+ continue;
+
+ /* Don't suggest names that are reserved for use by the
+ implementation, unless NAME began with an underscore. */
+ if (!consider_implementation_names
+ && name_reserved_for_implementation_p (str))
+ continue;
- bm.consider (suggestion_str);
+ bm.consider (str);
+ }
}
}
@@ -6461,86 +6654,37 @@ lookup_name_1 (tree name, LOOK_where where, LOOK_want want)
for (cxx_binding *iter = nullptr;
(iter = outer_binding (name, iter, bool (where & LOOK_where::CLASS)));)
{
- tree binding;
-
/* Skip entities we don't want. */
if (!bool (where & (LOCAL_BINDING_P (iter)
? LOOK_where::BLOCK : LOOK_where::CLASS)))
continue;
/* If this is the kind of thing we're looking for, we're done. */
- if (iter->value
- && (bool (want & LOOK_want::HIDDEN_LAMBDA)
- || !is_lambda_ignored_entity (iter->value))
- && qualify_lookup (iter->value, want))
- binding = iter->value;
- else if (bool (want & LOOK_want::TYPE)
- && qualify_lookup (iter->type, want))
- binding = iter->type;
- else
- binding = NULL_TREE;
-
- if (binding)
+ if (iter->value)
{
- if (TREE_CODE (binding) == TYPE_DECL && DECL_HIDDEN_P (binding))
+ tree binding = NULL_TREE;
+
+ if (!(!iter->type && HIDDEN_TYPE_BINDING_P (iter))
+ && (bool (want & LOOK_want::HIDDEN_LAMBDA)
+ || !is_lambda_ignored_entity (iter->value))
+ && qualify_lookup (iter->value, want))
+ binding = iter->value;
+ else if (bool (want & LOOK_want::TYPE)
+ && !HIDDEN_TYPE_BINDING_P (iter)
+ && iter->type)
+ binding = iter->type;
+
+ if (binding)
{
- /* A non namespace-scope binding can only be hidden in the
- presence of a local class, due to friend declarations.
-
- In particular, consider:
-
- struct C;
- void f() {
- struct A {
- friend struct B;
- friend struct C;
- void g() {
- B* b; // error: B is hidden
- C* c; // OK, finds ::C
- }
- };
- B *b; // error: B is hidden
- C *c; // OK, finds ::C
- struct B {};
- B *bb; // OK
- }
-
- The standard says that "B" is a local class in "f"
- (but not nested within "A") -- but that name lookup
- for "B" does not find this declaration until it is
- declared directly with "f".
-
- In particular:
-
- [class.friend]
-
- If a friend declaration appears in a local class and
- the name specified is an unqualified name, a prior
- declaration is looked up without considering scopes
- that are outside the innermost enclosing non-class
- scope. For a friend function declaration, if there is
- no prior declaration, the program is ill-formed. For a
- friend class declaration, if there is no prior
- declaration, the class that is specified belongs to the
- innermost enclosing non-class scope, but if it is
- subsequently referenced, its name is not found by name
- lookup until a matching declaration is provided in the
- innermost enclosing nonclass scope.
-
- So just keep looking for a non-hidden binding.
- */
- gcc_assert (TREE_CODE (binding) == TYPE_DECL);
- continue;
+ /* The saved lookups for an operator record 'nothing
+ found' as error_mark_node. We need to stop the search
+ here, but not return the error mark node. */
+ if (binding == error_mark_node)
+ binding = NULL_TREE;
+
+ val = binding;
+ goto found;
}
-
- /* The saved lookups for an operator record 'nothing
- found' as error_mark_node. We need to stop the search
- here, but not return the error mark node. */
- if (binding == error_mark_node)
- binding = NULL_TREE;
-
- val = binding;
- goto found;
}
}
@@ -6580,22 +6724,20 @@ lookup_name (tree name)
}
/* Look up NAME for type used in elaborated name specifier in
- the scopes given by SCOPE. SCOPE can be either TS_CURRENT or
- TS_WITHIN_ENCLOSING_NON_CLASS. Although not implied by the
- name, more scopes are checked if cleanup or template parameter
- scope is encountered.
+ the scopes given by HOW.
Unlike lookup_name_1, we make sure that NAME is actually
declared in the desired scope, not from inheritance, nor using
directive. For using declaration, there is DR138 still waiting
to be resolved. Hidden name coming from an earlier friend
- declaration is also returned.
+ declaration is also returned, and will be made visible unless HOW
+ is TAG_how::HIDDEN_FRIEND.
A TYPE_DECL best matching the NAME is returned. Catching error
and issuing diagnostics are caller's responsibility. */
static tree
-lookup_type_scope_1 (tree name, tag_scope scope)
+lookup_elaborated_type_1 (tree name, TAG_how how)
{
cp_binding_level *b = current_binding_level;
@@ -6610,30 +6752,46 @@ lookup_type_scope_1 (tree name, tag_scope scope)
if (!(b->kind == sk_cleanup
|| b->kind == sk_template_parms
|| b->kind == sk_function_parms
- || (b->kind == sk_class
- && scope == ts_within_enclosing_non_class)))
+ || (b->kind == sk_class && how != TAG_how::CURRENT_ONLY)))
return NULL_TREE;
/* Check if this is the kind of thing we're looking for. If
- SCOPE is TS_CURRENT, also make sure it doesn't come from
- base class. For ITER->VALUE, we can simply use
- INHERITED_VALUE_BINDING_P. For ITER->TYPE, we have to
- use our own check.
+ HOW is TAG_how::CURRENT_ONLY, also make sure it doesn't
+ come from base class. For ITER->VALUE, we can simply use
+ INHERITED_VALUE_BINDING_P. For ITER->TYPE, we have to use
+ our own check.
We check ITER->TYPE before ITER->VALUE in order to handle
typedef struct C {} C;
correctly. */
+
if (tree type = iter->type)
- if (qualify_lookup (type, LOOK_want::TYPE)
- && (scope != ts_current
- || LOCAL_BINDING_P (iter)
- || DECL_CONTEXT (type) == iter->scope->this_entity))
- return type;
-
- if (qualify_lookup (iter->value, LOOK_want::TYPE)
- && (scope != ts_current
- || !INHERITED_VALUE_BINDING_P (iter)))
- return iter->value;
+ {
+ if (qualify_lookup (type, LOOK_want::TYPE)
+ && (how != TAG_how::CURRENT_ONLY
+ || LOCAL_BINDING_P (iter)
+ || DECL_CONTEXT (type) == iter->scope->this_entity))
+ {
+ if (how != TAG_how::HIDDEN_FRIEND)
+ /* It is no longer a hidden binding. */
+ HIDDEN_TYPE_BINDING_P (iter) = false;
+
+ return type;
+ }
+ }
+ else
+ {
+ if (qualify_lookup (iter->value, LOOK_want::TYPE)
+ && (how != TAG_how::CURRENT_ONLY
+ || !INHERITED_VALUE_BINDING_P (iter)))
+ {
+ if (how != TAG_how::HIDDEN_FRIEND && !iter->type)
+ /* It is no longer a hidden binding. */
+ HIDDEN_TYPE_BINDING_P (iter) = false;
+
+ return iter->value;
+ }
+ }
}
/* Now check if we can look in namespace scope. */
@@ -6641,8 +6799,7 @@ lookup_type_scope_1 (tree name, tag_scope scope)
if (!(b->kind == sk_cleanup
|| b->kind == sk_template_parms
|| b->kind == sk_function_parms
- || (b->kind == sk_class
- && scope == ts_within_enclosing_non_class)))
+ || (b->kind == sk_class && how != TAG_how::CURRENT_ONLY)))
return NULL_TREE;
/* Look in the innermost namespace. */
@@ -6651,43 +6808,47 @@ lookup_type_scope_1 (tree name, tag_scope scope)
{
/* If this is the kind of thing we're looking for, we're done. */
if (tree type = MAYBE_STAT_TYPE (*slot))
- if (qualify_lookup (type, LOOK_want::TYPE))
+ {
+ if (how != TAG_how::HIDDEN_FRIEND)
+ /* No longer hidden. */
+ STAT_TYPE_HIDDEN_P (*slot) = false;
+
return type;
+ }
+ else if (tree decl = MAYBE_STAT_DECL (*slot))
+ {
+ if (qualify_lookup (decl, LOOK_want::TYPE))
+ {
+ if (how != TAG_how::HIDDEN_FRIEND && STAT_HACK_P (*slot)
+ && STAT_DECL_HIDDEN_P (*slot))
+ {
+ if (STAT_TYPE (*slot))
+ STAT_DECL_HIDDEN_P (*slot) = false;
+ else
+ /* There is no type, just remove the stat
+ hack. */
+ *slot = decl;
+ }
- if (tree decl = MAYBE_STAT_DECL (*slot))
- if (qualify_lookup (decl, LOOK_want::TYPE))
- return decl;
+ return decl;
+ }
+ }
}
return NULL_TREE;
}
-
+
/* Wrapper for lookup_type_scope_1. */
tree
-lookup_type_scope (tree name, tag_scope scope)
+lookup_elaborated_type (tree name, TAG_how how)
{
- tree ret;
bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
- ret = lookup_type_scope_1 (name, scope);
+ tree ret = lookup_elaborated_type_1 (name, how);
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
return ret;
}
-/* Returns true iff DECL is a block-scope extern declaration of a function
- or variable. We will already have determined validity of the decl
- when pushing it. So we do not have to redo that lookup. */
-
-bool
-is_local_extern (tree decl)
-{
- if ((TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == VAR_DECL))
- return DECL_LOCAL_DECL_P (decl);
-
- return false;
-}
-
/* The type TYPE is being declared. If it is a class template, or a
specialization of a class template, do any processing required and
perform error-checking. If IS_FRIEND is nonzero, this TYPE is
@@ -6723,11 +6884,11 @@ maybe_process_template_type_declaration (tree type, int is_friend,
if (processing_template_decl)
{
- /* This may change after the call to
- push_template_decl_real, but we want the original value. */
+ /* This may change after the call to push_template_decl, but
+ we want the original value. */
tree name = DECL_NAME (decl);
- decl = push_template_decl_real (decl, is_friend);
+ decl = push_template_decl (decl, is_friend);
if (decl == error_mark_node)
return error_mark_node;
@@ -6779,7 +6940,7 @@ maybe_process_template_type_declaration (tree type, int is_friend,
Returns TYPE upon success and ERROR_MARK_NODE otherwise. */
static tree
-do_pushtag (tree name, tree type, tag_scope scope)
+do_pushtag (tree name, tree type, TAG_how how)
{
tree decl;
@@ -6796,10 +6957,9 @@ do_pushtag (tree name, tree type, tag_scope scope)
declaration, these scopes are not scopes from the point of
view of the language. */
|| (b->kind == sk_template_parms
- && (b->explicit_spec_p || scope == ts_global)))
+ && (b->explicit_spec_p || how == TAG_how::GLOBAL)))
b = b->level_chain;
- else if (b->kind == sk_class
- && scope != ts_current)
+ else if (b->kind == sk_class && how != TAG_how::CURRENT_ONLY)
{
b = b->level_chain;
if (b->kind == sk_template_parms)
@@ -6833,7 +6993,7 @@ do_pushtag (tree name, tree type, tag_scope scope)
: TYPE_P (cs) ? cs == current_class_type
: cs == current_namespace);
- if (scope == ts_current
+ if (how == TAG_how::CURRENT_ONLY
|| (cs && TREE_CODE (cs) == FUNCTION_DECL))
context = cs;
else if (cs && TYPE_P (cs))
@@ -6853,18 +7013,8 @@ do_pushtag (tree name, tree type, tag_scope scope)
tdef = create_implicit_typedef (name, type);
DECL_CONTEXT (tdef) = FROB_CONTEXT (context);
- if (scope == ts_within_enclosing_non_class)
- {
- /* This is a friend. Make this TYPE_DECL node hidden from
- ordinary name lookup. Its corresponding TEMPLATE_DECL
- will be marked in push_template_decl_real. */
- retrofit_lang_decl (tdef);
- DECL_ANTICIPATED (tdef) = 1;
- DECL_FRIEND_P (tdef) = 1;
- }
-
decl = maybe_process_template_type_declaration
- (type, scope == ts_within_enclosing_non_class, b);
+ (type, how == TAG_how::HIDDEN_FRIEND, b);
if (decl == error_mark_node)
return decl;
@@ -6885,7 +7035,8 @@ do_pushtag (tree name, tree type, tag_scope scope)
}
else if (b->kind != sk_template_parms)
{
- decl = do_pushdecl_with_scope (decl, b, /*is_friend=*/false);
+ decl = do_pushdecl_with_scope
+ (decl, b, /*hiding=*/(how == TAG_how::HIDDEN_FRIEND));
if (decl == error_mark_node)
return decl;
@@ -6951,11 +7102,10 @@ do_pushtag (tree name, tree type, tag_scope scope)
/* Wrapper for do_pushtag. */
tree
-pushtag (tree name, tree type, tag_scope scope)
+pushtag (tree name, tree type, TAG_how how)
{
- tree ret;
bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
- ret = do_pushtag (name, type, scope);
+ tree ret = do_pushtag (name, type, how);
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
return ret;
}
@@ -7283,11 +7433,13 @@ finish_using_directive (tree target, tree attribs)
/* Pushes X into the global namespace. */
tree
-pushdecl_top_level (tree x, bool is_friend)
+pushdecl_top_level (tree x)
{
bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
do_push_to_top_level ();
- x = pushdecl_namespace_level (x, is_friend);
+ gcc_checking_assert (!DECL_CONTEXT (x));
+ DECL_CONTEXT (x) = FROB_CONTEXT (global_namespace);
+ x = pushdecl_namespace_level (x);
do_pop_from_top_level ();
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
return x;
@@ -7301,7 +7453,9 @@ pushdecl_top_level_and_finish (tree x, tree init)
{
bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
do_push_to_top_level ();
- x = pushdecl_namespace_level (x, false);
+ gcc_checking_assert (!DECL_CONTEXT (x));
+ DECL_CONTEXT (x) = FROB_CONTEXT (global_namespace);
+ x = pushdecl_namespace_level (x);
cp_finish_decl (x, init, false, NULL_TREE, 0);
do_pop_from_top_level ();
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index 723fbb0..d63ff10 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -47,12 +47,8 @@ struct GTY(()) binding_entry_s {
extern void binding_table_foreach (binding_table, bt_foreach_proc, void *);
extern binding_entry binding_table_find (binding_table, tree);
-/* Datatype that represents binding established by a declaration between
- a name and a C++ entity. */
-typedef struct cxx_binding cxx_binding;
-
/* The datatype used to implement C++ scope. */
-typedef struct cp_binding_level cp_binding_level;
+struct cp_binding_level;
/* Nonzero if this binding is for a local scope, as opposed to a class
or namespace scope. */
@@ -62,6 +58,14 @@ typedef struct cp_binding_level cp_binding_level;
currently being defined. */
#define INHERITED_VALUE_BINDING_P(NODE) ((NODE)->value_is_inherited)
+/* The IMPLICIT_TYPEDEF is hidden from ordinary name lookup (it was
+ injected via a local class's friend decl). The typdef may be in the
+ VALUE or the TYPE slot. We do not get the situation where the
+ value and type slots are both filled and both hidden. */
+#define HIDDEN_TYPE_BINDING_P(NODE) ((NODE)->type_is_hidden)
+
+/* Datatype that represents binding established by a declaration between
+ a name and a C++ entity. */
struct GTY(()) cxx_binding {
/* Link to chain together various bindings for this name. */
cxx_binding *previous;
@@ -71,8 +75,10 @@ struct GTY(()) cxx_binding {
tree type;
/* The scope at which this binding was made. */
cp_binding_level *scope;
- unsigned value_is_inherited : 1;
- unsigned is_local : 1;
+
+ bool value_is_inherited : 1;
+ bool is_local : 1;
+ bool type_is_hidden : 1;
};
/* Datatype used to temporarily save C++ bindings (for implicit
@@ -125,23 +131,6 @@ enum scope_kind {
sk_omp /* An OpenMP structured block. */
};
-/* The scope where the class/struct/union/enum tag applies. */
-enum tag_scope {
- ts_current = 0, /* Current scope only. This is for the
- class-key identifier;
- case mentioned in [basic.lookup.elab]/2,
- or the class/enum definition
- class-key identifier { ... }; */
- ts_global = 1, /* All scopes. This is the 3.4.1
- [basic.lookup.unqual] lookup mentioned
- in [basic.lookup.elab]/2. */
- ts_within_enclosing_non_class = 2, /* Search within enclosing non-class
- only, for friend class lookup
- according to [namespace.memdef]/3
- and [class.friend]/9. */
- ts_lambda = 3 /* Declaring a lambda closure. */
-};
-
struct GTY(()) cp_class_binding {
cxx_binding *base;
/* The bound name. */
@@ -328,7 +317,19 @@ inline tree lookup_name (tree name, LOOK_want want)
return lookup_name (name, LOOK_where::ALL, want);
}
-extern tree lookup_type_scope (tree, tag_scope);
+enum class TAG_how
+{
+ CURRENT_ONLY = 0, // Look and insert only in current scope
+
+ GLOBAL = 1, // Unqualified lookup, innermost-non-class insertion
+
+ INNERMOST_NON_CLASS = 2, // Look and insert only into
+ // innermost-non-class
+
+ HIDDEN_FRIEND = 3, // As INNERMOST_NON_CLASS, but hide it
+};
+
+extern tree lookup_elaborated_type (tree, TAG_how);
extern tree get_namespace_binding (tree ns, tree id);
extern void set_global_binding (tree decl);
inline tree get_global_binding (tree id)
@@ -341,9 +342,8 @@ extern tree lookup_qualified_name (tree scope, tree name,
extern tree lookup_qualified_name (tree scope, const char *name,
LOOK_want = LOOK_want::NORMAL,
bool = true);
-extern bool is_local_extern (tree);
extern bool pushdecl_class_level (tree);
-extern tree pushdecl_namespace_level (tree, bool);
+extern tree pushdecl_namespace_level (tree, bool hiding = false);
extern bool push_class_level_binding (tree, tree);
extern tree get_local_decls ();
extern int function_parm_depth (void);
@@ -369,11 +369,11 @@ extern void cp_emit_debug_info_for_using (tree, tree);
extern void finish_nonmember_using_decl (tree scope, tree name);
extern void finish_using_directive (tree target, tree attribs);
-extern tree pushdecl (tree, bool is_friend = false);
+extern tree pushdecl (tree, bool hiding = false);
extern tree pushdecl_outermost_localscope (tree);
-extern tree pushdecl_top_level (tree, bool is_friend = false);
+extern tree pushdecl_top_level (tree);
extern tree pushdecl_top_level_and_finish (tree, tree);
-extern tree pushtag (tree, tree, tag_scope);
+extern tree pushtag (tree, tree, TAG_how = TAG_how::CURRENT_ONLY);
extern int push_namespace (tree, bool make_inline = false);
extern void pop_namespace (void);
extern void push_nested_namespace (tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index fba3fcc..7ec7d42 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -12646,6 +12646,64 @@ do_range_for_auto_deduction (tree decl, tree range_expr)
}
}
+/* Warns when the loop variable should be changed to a reference type to
+ avoid unnecessary copying. I.e., from
+
+ for (const auto x : range)
+
+ where range returns a reference, to
+
+ for (const auto &x : range)
+
+ if this version doesn't make a copy. DECL is the RANGE_DECL; EXPR is the
+ *__for_begin expression.
+ This function is never called when processing_template_decl is on. */
+
+static void
+warn_for_range_copy (tree decl, tree expr)
+{
+ if (!warn_range_loop_construct
+ || decl == error_mark_node)
+ return;
+
+ location_t loc = DECL_SOURCE_LOCATION (decl);
+ tree type = TREE_TYPE (decl);
+
+ if (from_macro_expansion_at (loc))
+ return;
+
+ if (TYPE_REF_P (type))
+ {
+ /* TODO: Implement reference warnings. */
+ return;
+ }
+ else if (!CP_TYPE_CONST_P (type))
+ return;
+
+ /* Since small trivially copyable types are cheap to copy, we suppress the
+ warning for them. 64B is a common size of a cache line. */
+ if (TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST
+ || (tree_to_uhwi (TYPE_SIZE_UNIT (type)) <= 64
+ && trivially_copyable_p (type)))
+ return;
+
+ tree rtype = cp_build_reference_type (type, /*rval*/false);
+ /* If we could initialize the reference directly, it wouldn't involve any
+ copies. */
+ if (!ref_conv_binds_directly_p (rtype, expr))
+ return;
+
+ auto_diagnostic_group d;
+ if (warning_at (loc, OPT_Wrange_loop_construct,
+ "loop variable %qD creates a copy from type %qT",
+ decl, type))
+ {
+ gcc_rich_location richloc (loc);
+ richloc.add_fixit_insert_before ("&");
+ inform (&richloc, "use reference type to prevent copying");
+ }
+}
+
/* Converts a range-based for-statement into a normal
for-statement, as per the definition.
@@ -12656,7 +12714,7 @@ do_range_for_auto_deduction (tree decl, tree range_expr)
{
auto &&__range = RANGE_EXPR;
- for (auto __begin = BEGIN_EXPR, end = END_EXPR;
+ for (auto __begin = BEGIN_EXPR, __end = END_EXPR;
__begin != __end;
++__begin)
{
@@ -12756,14 +12814,16 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr,
cp_maybe_mangle_decomp (range_decl, decomp_first_name, decomp_cnt);
/* The declaration is initialized with *__begin inside the loop body. */
- cp_finish_decl (range_decl,
- build_x_indirect_ref (input_location, begin, RO_UNARY_STAR,
- tf_warning_or_error),
+ tree deref_begin = build_x_indirect_ref (input_location, begin, RO_UNARY_STAR,
+ tf_warning_or_error);
+ cp_finish_decl (range_decl, deref_begin,
/*is_constant_init*/false, NULL_TREE,
LOOKUP_ONLYCONVERTING);
if (VAR_P (range_decl) && DECL_DECOMPOSITION_P (range_decl))
cp_finish_decomp (range_decl, decomp_first_name, decomp_cnt);
+ warn_for_range_copy (range_decl, deref_begin);
+
return statement;
}
@@ -13437,10 +13497,8 @@ cp_parser_declaration (cp_parser* parser)
/* Try to figure out what kind of declaration is present. */
cp_token *token1 = cp_lexer_peek_token (parser->lexer);
- cp_token *token2 = NULL;
-
- if (token1->type != CPP_EOF)
- token2 = cp_lexer_peek_nth_token (parser->lexer, 2);
+ cp_token *token2 = (token1->type == CPP_EOF
+ ? token1 : cp_lexer_peek_nth_token (parser->lexer, 2));
/* Get the high-water mark for the DECLARATOR_OBSTACK. */
void *p = obstack_alloc (&declarator_obstack, 0);
@@ -19057,21 +19115,20 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
definition of a new type; a new type can only be declared in a
declaration context. */
- tag_scope ts;
- bool template_p;
+ TAG_how how;
if (is_friend)
/* Friends have special name lookup rules. */
- ts = ts_within_enclosing_non_class;
+ how = TAG_how::HIDDEN_FRIEND;
else if (is_declaration
&& cp_lexer_next_token_is (parser->lexer,
CPP_SEMICOLON))
/* This is a `class-key identifier ;' */
- ts = ts_current;
+ how = TAG_how::CURRENT_ONLY;
else
- ts = ts_global;
+ how = TAG_how::GLOBAL;
- template_p =
+ bool template_p =
(template_parm_lists_apply
&& (cp_parser_next_token_starts_class_definition_p (parser)
|| cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)));
@@ -19084,7 +19141,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
token->location,
/*declarator=*/NULL))
return error_mark_node;
- type = xref_tag (tag_type, identifier, ts, template_p);
+
+ type = xref_tag (tag_type, identifier, how, template_p);
}
}
@@ -21728,8 +21786,14 @@ cp_parser_direct_declarator (cp_parser* parser,
templates, assume S::p to name a type. Otherwise,
don't. */
tree decl
- = cp_parser_lookup_name_simple (parser, unqualified_name,
- token->location);
+ = cp_parser_lookup_name (parser, unqualified_name,
+ none_type,
+ /*is_template=*/false,
+ /*is_namespace=*/false,
+ /*check_dependency=*/false,
+ /*ambiguous_decls=*/NULL,
+ token->location);
+
if (!is_overloaded_fn (decl)
/* Allow
template<typename T>
@@ -23978,10 +24042,6 @@ cp_parser_class_specifier_1 (cp_parser* parser)
= parser->in_unbraced_linkage_specification_p;
parser->in_unbraced_linkage_specification_p = false;
- // Associate constraints with the type.
- if (flag_concepts)
- type = associate_classtype_constraints (type);
-
/* Start the class. */
if (nested_name_specifier_p)
{
@@ -24708,10 +24768,10 @@ cp_parser_class_head (cp_parser* parser,
/* If the class was unnamed, create a dummy name. */
if (!id)
id = make_anon_name ();
- tag_scope tag_scope = (parser->in_type_id_in_expr_p
- ? ts_within_enclosing_non_class
- : ts_current);
- type = xref_tag (class_key, id, tag_scope,
+ TAG_how how = (parser->in_type_id_in_expr_p
+ ? TAG_how::INNERMOST_NON_CLASS
+ : TAG_how::CURRENT_ONLY);
+ type = xref_tag (class_key, id, how,
parser->num_template_parameter_lists);
}
@@ -24749,6 +24809,10 @@ cp_parser_class_head (cp_parser* parser,
fixup_attribute_variants (type);
}
+ /* Associate constraints with the type. */
+ if (flag_concepts)
+ type = associate_classtype_constraints (type);
+
/* We will have entered the scope containing the class; the names of
base classes should be looked up in that context. For example:
@@ -41110,6 +41174,10 @@ cp_parser_oacc_declare (cp_parser *parser, cp_token *pragma_tok)
}
if (!found_in_scope)
+ /* This seems to ignore the existence of cleanup scopes?
+ What is the meaning for local extern decls? The local
+ extern is in this scope, but it is referring to a decl that
+ is namespace scope. */
for (tree d = current_binding_level->names; d; d = TREE_CHAIN (d))
if (d == decl)
{
@@ -41139,6 +41207,16 @@ cp_parser_oacc_declare (cp_parser *parser, cp_token *pragma_tok)
{
tree id;
+ if (DECL_LOCAL_DECL_P (decl))
+ /* We need to mark the aliased decl, as that is the entity
+ that is being referred to. This won't work for
+ dependent variables, but it didn't work for them before
+ DECL_LOCAL_DECL_P was a thing either. But then
+ dependent local extern variable decls are as rare as
+ hen's teeth. */
+ if (auto alias = DECL_LOCAL_DECL_ALIAS (decl))
+ decl = alias;
+
if (OMP_CLAUSE_MAP_KIND (t) == GOMP_MAP_LINK)
id = get_identifier ("omp declare target link");
else
@@ -42567,7 +42645,7 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok,
if (current_function_decl)
{
block_scope = true;
- DECL_CONTEXT (fndecl) = global_namespace;
+ DECL_CONTEXT (fndecl) = current_function_decl;
DECL_LOCAL_DECL_P (fndecl) = true;
if (!processing_template_decl)
pushdecl (fndecl);
@@ -42592,7 +42670,9 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok,
else
{
DECL_CONTEXT (fndecl) = current_namespace;
- pushdecl (fndecl);
+ tree d = pushdecl (fndecl);
+ /* We should never meet a matched duplicate decl. */
+ gcc_checking_assert (d == error_mark_node || d == fndecl);
}
if (!block_scope)
start_preparsed_function (fndecl, NULL_TREE, SF_PRE_PARSED);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index fe45de8..dc664ec 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -1181,7 +1181,7 @@ optimize_specialization_lookup_p (tree tmpl)
not have template information. The optimized lookup relies
on having ARGS be the template arguments for both the class
and the function template. */
- && !DECL_FRIEND_P (DECL_TEMPLATE_RESULT (tmpl)));
+ && !DECL_UNIQUE_FRIEND_P (DECL_TEMPLATE_RESULT (tmpl)));
}
/* Make sure ARGS doesn't use any inappropriate typedefs; we should have
@@ -1635,7 +1635,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
for the specialization, we want this to look as if
there were no definition, and vice versa. */
DECL_INITIAL (fn) = NULL_TREE;
- duplicate_decls (spec, fn, is_friend);
+ duplicate_decls (spec, fn, /*hiding=*/is_friend);
/* The call to duplicate_decls will have applied
[temp.expl.spec]:
@@ -1662,7 +1662,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
}
else if (DECL_TEMPLATE_SPECIALIZATION (fn))
{
- tree dd = duplicate_decls (spec, fn, is_friend);
+ tree dd = duplicate_decls (spec, fn, /*hiding=*/is_friend);
if (dd == error_mark_node)
/* We've already complained in duplicate_decls. */
return error_mark_node;
@@ -1677,7 +1677,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
}
}
else if (fn)
- return duplicate_decls (spec, fn, is_friend);
+ return duplicate_decls (spec, fn, /*hiding=*/is_friend);
/* A specialization must be declared in the same namespace as the
template it is specializing. */
@@ -2988,6 +2988,7 @@ check_explicit_specialization (tree declarator,
tree tmpl = NULL_TREE;
tree targs = NULL_TREE;
bool was_template_id = (TREE_CODE (declarator) == TEMPLATE_ID_EXPR);
+ bool found_hidden = false;
/* Make sure that the declarator is a TEMPLATE_ID_EXPR. */
if (!was_template_id)
@@ -3008,12 +3009,15 @@ check_explicit_specialization (tree declarator,
fns = lookup_qualified_name (CP_DECL_CONTEXT (decl), dname,
LOOK_want::NORMAL, true);
if (fns == error_mark_node)
- /* If lookup fails, look for a friend declaration so we can
- give a better diagnostic. */
- fns = (lookup_qualified_name
- (CP_DECL_CONTEXT (decl), dname,
- LOOK_want::NORMAL | LOOK_want::HIDDEN_FRIEND,
- /*complain*/true));
+ {
+ /* If lookup fails, look for a friend declaration so we can
+ give a better diagnostic. */
+ fns = (lookup_qualified_name
+ (CP_DECL_CONTEXT (decl), dname,
+ LOOK_want::NORMAL | LOOK_want::HIDDEN_FRIEND,
+ /*complain*/true));
+ found_hidden = true;
+ }
if (fns == error_mark_node || !is_overloaded_fn (fns))
{
@@ -3122,8 +3126,7 @@ check_explicit_specialization (tree declarator,
return error_mark_node;
else
{
- if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_HIDDEN_FRIEND_P (tmpl))
+ if (found_hidden && TREE_CODE (decl) == FUNCTION_DECL)
{
auto_diagnostic_group d;
if (pedwarn (DECL_SOURCE_LOCATION (decl), 0,
@@ -3132,8 +3135,9 @@ check_explicit_specialization (tree declarator,
inform (DECL_SOURCE_LOCATION (tmpl),
"friend declaration here");
}
- else if (!ctype && !is_friend
- && CP_DECL_CONTEXT (decl) == current_namespace)
+
+ if (!ctype && !is_friend
+ && CP_DECL_CONTEXT (decl) == current_namespace)
check_unqualified_spec_or_inst (tmpl, DECL_SOURCE_LOCATION (decl));
tree gen_tmpl = most_general_template (tmpl);
@@ -4226,11 +4230,6 @@ check_for_bare_parameter_packs (tree t, location_t loc /* = UNKNOWN_LOCATION */)
if (!processing_template_decl || !t || t == error_mark_node)
return false;
- /* A lambda might use a parameter pack from the containing context. */
- if (current_class_type && LAMBDA_TYPE_P (current_class_type)
- && CLASSTYPE_TEMPLATE_INFO (current_class_type))
- return false;
-
if (TREE_CODE (t) == TYPE_DECL)
t = TREE_TYPE (t);
@@ -4240,6 +4239,18 @@ check_for_bare_parameter_packs (tree t, location_t loc /* = UNKNOWN_LOCATION */)
cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
delete ppd.visited;
+ /* It's OK for a lambda to have an unexpanded parameter pack from the
+ containing context, but do complain about unexpanded capture packs. */
+ if (current_class_type && LAMBDA_TYPE_P (current_class_type)
+ && CLASSTYPE_TEMPLATE_INFO (current_class_type))
+ for (; parameter_packs;
+ parameter_packs = TREE_CHAIN (parameter_packs))
+ {
+ tree pack = TREE_VALUE (parameter_packs);
+ if (is_capture_proxy (pack))
+ break;
+ }
+
if (parameter_packs)
{
if (loc == UNKNOWN_LOCATION)
@@ -5669,7 +5680,7 @@ template_parm_outer_level (tree t, void *data)
If IS_FRIEND is true, DECL is a friend declaration. */
tree
-push_template_decl_real (tree decl, bool is_friend)
+push_template_decl (tree decl, bool is_friend)
{
tree tmpl;
tree args;
@@ -5694,8 +5705,10 @@ push_template_decl_real (tree decl, bool is_friend)
&& DECL_TEMPLATE_SPECIALIZATION (decl)
&& TINFO_USED_TEMPLATE_ID (DECL_TEMPLATE_INFO (decl))));
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_FRIEND_P (decl))
- is_friend = true;
+ /* No surprising friend functions. */
+ gcc_checking_assert (is_friend
+ || !(TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_UNIQUE_FRIEND_P (decl)));
if (is_friend)
/* For a friend, we want the context of the friend, not
@@ -5864,7 +5877,8 @@ push_template_decl_real (tree decl, bool is_friend)
|| TREE_CODE (ctx) == FUNCTION_DECL
|| (CLASS_TYPE_P (ctx) && TYPE_BEING_DEFINED (ctx))
|| (TREE_CODE (decl) == TYPE_DECL && LAMBDA_TYPE_P (TREE_TYPE (decl)))
- || (is_friend && !DECL_TEMPLATE_INFO (decl)))
+ || (is_friend && !(DECL_LANG_SPECIFIC (decl)
+ && DECL_TEMPLATE_INFO (decl))))
{
if (DECL_LANG_SPECIFIC (decl)
&& DECL_TEMPLATE_INFO (decl)
@@ -6016,16 +6030,9 @@ push_template_decl_real (tree decl, bool is_friend)
if (!ctx
&& !(is_friend && template_class_depth (current_class_type) > 0))
{
- tmpl = pushdecl_namespace_level (tmpl, is_friend);
+ tmpl = pushdecl_namespace_level (tmpl, /*hiding=*/is_friend);
if (tmpl == error_mark_node)
return error_mark_node;
-
- /* Hide template friend classes that haven't been declared yet. */
- if (is_friend && TREE_CODE (decl) == TYPE_DECL)
- {
- DECL_ANTICIPATED (tmpl) = 1;
- DECL_FRIEND_P (tmpl) = 1;
- }
}
}
else
@@ -6096,12 +6103,6 @@ push_template_decl_real (tree decl, bool is_friend)
return DECL_TEMPLATE_RESULT (tmpl);
}
-tree
-push_template_decl (tree decl)
-{
- return push_template_decl_real (decl, false);
-}
-
/* FN is an inheriting constructor that inherits from the constructor
template INHERITED; turn FN into a constructor template with a matching
template header. */
@@ -7094,12 +7095,12 @@ get_template_parm_object (tree expr, tsubst_flags_t complain)
tree type = cp_build_qualified_type (TREE_TYPE (expr), TYPE_QUAL_CONST);
decl = create_temporary_var (type);
+ DECL_CONTEXT (decl) = NULL_TREE;
TREE_STATIC (decl) = true;
DECL_DECLARED_CONSTEXPR_P (decl) = true;
TREE_READONLY (decl) = true;
DECL_NAME (decl) = name;
SET_DECL_ASSEMBLER_NAME (decl, name);
- DECL_CONTEXT (decl) = global_namespace;
comdat_linkage (decl);
if (!zero_init_p (type))
@@ -8130,9 +8131,10 @@ canonicalize_expr_argument (tree arg, tsubst_flags_t complain)
return canon;
}
-// A template declaration can be substituted for a constrained
-// template template parameter only when the argument is more
-// constrained than the parameter.
+/* A template declaration can be substituted for a constrained
+ template template parameter only when the argument is no more
+ constrained than the parameter. */
+
static bool
is_compatible_template_arg (tree parm, tree arg)
{
@@ -9856,12 +9858,11 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
&& !PRIMARY_TEMPLATE_P (gen_tmpl)
&& !LAMBDA_TYPE_P (TREE_TYPE (gen_tmpl))
&& TREE_CODE (CP_DECL_CONTEXT (gen_tmpl)) == NAMESPACE_DECL)
- {
- found = xref_tag_from_type (TREE_TYPE (gen_tmpl),
- DECL_NAME (gen_tmpl),
- /*tag_scope=*/ts_global);
- return found;
- }
+ /* This occurs when the user has tried to define a tagged type
+ in a scope that forbids it. We emitted an error during the
+ parse. We didn't complete the bail out then, so here we
+ are. */
+ return error_mark_node;
context = DECL_CONTEXT (gen_tmpl);
if (context && TYPE_P (context))
@@ -9944,7 +9945,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
/* A local class. Make sure the decl gets registered properly. */
if (context == current_function_decl)
- if (pushtag (DECL_NAME (gen_tmpl), t, /*tag_scope=*/ts_current)
+ if (pushtag (DECL_NAME (gen_tmpl), t)
== error_mark_node)
return error_mark_node;
@@ -10244,6 +10245,42 @@ lookup_and_finish_template_variable (tree templ, tree targs,
return convert_from_reference (templ);
}
+/* If the set of template parameters PARMS contains a template parameter
+ at the given LEVEL and INDEX, then return this parameter. Otherwise
+ return NULL_TREE. */
+
+static tree
+corresponding_template_parameter (tree parms, int level, int index)
+{
+ while (TMPL_PARMS_DEPTH (parms) > level)
+ parms = TREE_CHAIN (parms);
+
+ if (TMPL_PARMS_DEPTH (parms) != level
+ || TREE_VEC_LENGTH (TREE_VALUE (parms)) <= index)
+ return NULL_TREE;
+
+ tree t = TREE_VALUE (TREE_VEC_ELT (TREE_VALUE (parms), index));
+ /* As in template_parm_to_arg. */
+ if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (t) == TEMPLATE_DECL)
+ t = TREE_TYPE (t);
+ else
+ t = DECL_INITIAL (t);
+
+ gcc_assert (TEMPLATE_PARM_P (t));
+ return t;
+}
+
+/* Return the template parameter from PARMS that positionally corresponds
+ to the template parameter PARM, or else return NULL_TREE. */
+
+static tree
+corresponding_template_parameter (tree parms, tree parm)
+{
+ int level, index;
+ template_parm_level_and_index (parm, &level, &index);
+ return corresponding_template_parameter (parms, level, index);
+}
+
struct pair_fn_data
{
@@ -10550,6 +10587,14 @@ keep_template_parm (tree t, void* data)
BOUND_TEMPLATE_TEMPLATE_PARM itself. */
t = TREE_TYPE (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t));
+ /* This template parameter might be an argument to a cached dependent
+ specalization that was formed earlier inside some other template, in
+ which case the parameter is not among the ones that are in-scope.
+ Look in CTX_PARMS to find the corresponding in-scope template
+ parameter, and use it instead. */
+ if (tree in_scope = corresponding_template_parameter (ftpi->ctx_parms, t))
+ t = in_scope;
+
/* Arguments like const T yield parameters like const T. This means that
a template-id like X<T, const T> would yield two distinct parameters:
T and const T. Adjust types to their unqualified versions. */
@@ -11039,7 +11084,7 @@ tsubst_friend_function (tree decl, tree args)
into the namespace of the template. */
ns = decl_namespace_context (new_friend);
push_nested_namespace (ns);
- old_decl = pushdecl_namespace_level (new_friend, /*is_friend=*/true);
+ old_decl = pushdecl_namespace_level (new_friend, /*hiding=*/true);
pop_nested_namespace (ns);
if (old_decl == error_mark_node)
@@ -11268,11 +11313,6 @@ tsubst_friend_class (tree friend_tmpl, tree args)
CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl))
= INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl)));
- /* It is hidden. */
- retrofit_lang_decl (DECL_TEMPLATE_RESULT (tmpl));
- DECL_ANTICIPATED (tmpl)
- = DECL_ANTICIPATED (DECL_TEMPLATE_RESULT (tmpl)) = true;
-
/* Substitute into and set the constraints on the new declaration. */
if (tree ci = get_constraints (friend_tmpl))
{
@@ -11284,7 +11324,7 @@ tsubst_friend_class (tree friend_tmpl, tree args)
}
/* Inject this template into the enclosing namspace scope. */
- tmpl = pushdecl_namespace_level (tmpl, true);
+ tmpl = pushdecl_namespace_level (tmpl, /*hiding=*/true);
}
}
@@ -11854,7 +11894,7 @@ instantiate_class_template_1 (tree type)
tsubst_enum. */
if (name)
SET_IDENTIFIER_TYPE_VALUE (name, newtag);
- pushtag (name, newtag, /*tag_scope=*/ts_current);
+ pushtag (name, newtag);
}
}
else if (DECL_DECLARES_FUNCTION_P (t))
@@ -12030,29 +12070,11 @@ instantiate_class_template_1 (tree type)
adjust_processing_template_decl = true;
--processing_template_decl;
}
- else if (TREE_CODE (friend_type) != BOUND_TEMPLATE_TEMPLATE_PARM
- && !CLASSTYPE_USE_TEMPLATE (friend_type)
- && TYPE_HIDDEN_P (friend_type))
- {
- /* friend class C;
-
- where C hasn't been declared yet. Let's lookup name
- from namespace scope directly, bypassing any name that
- come from dependent base class. */
- tree ns = decl_namespace_context (TYPE_MAIN_DECL (friend_type));
-
- /* The call to xref_tag_from_type does injection for friend
- classes. */
- push_nested_namespace (ns);
- friend_type =
- xref_tag_from_type (friend_type, NULL_TREE,
- /*tag_scope=*/ts_current);
- pop_nested_namespace (ns);
- }
else if (uses_template_parms (friend_type))
/* friend class C<T>; */
friend_type = tsubst (friend_type, args,
tf_warning_or_error, NULL_TREE);
+
/* Otherwise it's
friend class C;
@@ -13433,7 +13455,8 @@ tsubst_aggr_type (tree t,
complain, in_decl);
if (argvec == error_mark_node)
r = error_mark_node;
- else if (cxx_dialect >= cxx17 && dependent_scope_p (context))
+ else if (!entering_scope
+ && cxx_dialect >= cxx17 && dependent_scope_p (context))
{
/* See maybe_dependent_member_ref. */
tree name = TYPE_IDENTIFIER (t);
@@ -13941,7 +13964,7 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
if (!lambda_fntype)
set_constraints (r, ci);
- if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))
+ if (DECL_FRIEND_CONTEXT (t))
SET_DECL_FRIEND_CONTEXT (r,
tsubst (DECL_FRIEND_CONTEXT (t),
args, complain, in_decl));
@@ -14142,7 +14165,11 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain,
class_p = true;
inner = TREE_TYPE (inner);
}
- inner = tsubst (inner, args, complain, in_decl);
+ if (class_p)
+ inner = tsubst_aggr_type (inner, args, complain,
+ in_decl, /*entering*/1);
+ else
+ inner = tsubst (inner, args, complain, in_decl);
}
--processing_template_decl;
if (inner == error_mark_node)
@@ -16507,6 +16534,14 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case FUNCTION_DECL:
if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t))
r = tsubst (t, args, complain, in_decl);
+ else if (DECL_LOCAL_DECL_P (t))
+ {
+ /* Local specialization will have been created when we
+ instantiated the DECL_EXPR_DECL. */
+ r = retrieve_local_specialization (t);
+ if (!r)
+ r = error_mark_node;
+ }
else if (local_variable_p (t)
&& uses_template_parms (DECL_CONTEXT (t)))
{
@@ -18079,18 +18114,15 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
}
else if (DECL_IMPLICIT_TYPEDEF_P (t))
/* We already did a pushtag. */;
- else if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_OMP_DECLARE_REDUCTION_P (decl)
- && DECL_FUNCTION_SCOPE_P (pattern_decl))
+ else if (VAR_OR_FUNCTION_DECL_P (decl)
+ && DECL_LOCAL_DECL_P (decl))
{
- /* We pretend this is regular local extern decl of
- a namespace-scope fn. Then we make it really
- local, it is a nested function. */
- gcc_checking_assert (DECL_LOCAL_DECL_P (decl));
- DECL_CONTEXT (decl) = global_namespace;
- pushdecl (decl);
- DECL_CONTEXT (decl) = current_function_decl;
- if (cp_check_omp_declare_reduction (decl))
+ if (TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
+ DECL_CONTEXT (decl) = NULL_TREE;
+ decl = pushdecl (decl);
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_OMP_DECLARE_REDUCTION_P (decl)
+ && cp_check_omp_declare_reduction (decl))
instantiate_body (pattern_decl, args, decl, true);
}
else
@@ -19256,7 +19288,8 @@ out:
}
/* Like tsubst but deals with expressions and performs semantic
- analysis. FUNCTION_P is true if T is the "F" in "F (ARGS)". */
+ analysis. FUNCTION_P is true if T is the "F" in "F (ARGS)" or
+ "F<TARGS> (ARGS)". */
tree
tsubst_copy_and_build (tree t,
@@ -19338,7 +19371,10 @@ tsubst_copy_and_build (tree t,
case TEMPLATE_ID_EXPR:
{
tree object;
- tree templ = RECUR (TREE_OPERAND (t, 0));
+ tree templ = tsubst_copy_and_build (TREE_OPERAND (t, 0), args,
+ complain, in_decl,
+ function_p,
+ integral_constant_expression_p);
tree targs = TREE_OPERAND (t, 1);
if (targs)
@@ -19385,13 +19421,21 @@ tsubst_copy_and_build (tree t,
}
else
object = NULL_TREE;
- templ = lookup_template_function (templ, targs);
+
+ tree tid = lookup_template_function (templ, targs);
if (object)
- RETURN (build3 (COMPONENT_REF, TREE_TYPE (templ),
- object, templ, NULL_TREE));
+ RETURN (build3 (COMPONENT_REF, TREE_TYPE (tid),
+ object, tid, NULL_TREE));
+ else if (identifier_p (templ))
+ {
+ /* C++20 P0846: we can encounter an IDENTIFIER_NODE here when
+ name lookup found nothing when parsing the template name. */
+ gcc_assert (cxx_dialect >= cxx20 || seen_error ());
+ RETURN (tid);
+ }
else
- RETURN (baselink_for_fns (templ));
+ RETURN (baselink_for_fns (tid));
}
case INDIRECT_REF:
@@ -19927,7 +19971,7 @@ tsubst_copy_and_build (tree t,
/* Stripped-down processing for a call in a thunk. Specifically, in
the thunk template for a generic lambda. */
- if (CALL_FROM_THUNK_P (t))
+ if (call_from_lambda_thunk_p (t))
{
/* Now that we've expanded any packs, the number of call args
might be different. */
@@ -19982,14 +20026,17 @@ tsubst_copy_and_build (tree t,
/* We do not perform argument-dependent lookup if normal
lookup finds a non-function, in accordance with the
- expected resolution of DR 218. */
+ resolution of DR 218. */
if (koenig_p
&& ((is_overloaded_fn (function)
/* If lookup found a member function, the Koenig lookup is
not appropriate, even if an unqualified-name was used
to denote the function. */
&& !DECL_FUNCTION_MEMBER_P (get_first_fn (function)))
- || identifier_p (function))
+ || identifier_p (function)
+ /* C++20 P0846: Lookup found nothing. */
+ || (TREE_CODE (function) == TEMPLATE_ID_EXPR
+ && identifier_p (TREE_OPERAND (function, 0))))
/* Only do this when substitution turns a dependent call
into a non-dependent call. */
&& type_dependent_expression_p_push (t)
@@ -19997,9 +20044,13 @@ tsubst_copy_and_build (tree t,
function = perform_koenig_lookup (function, call_args, tf_none);
if (function != NULL_TREE
- && identifier_p (function)
+ && (identifier_p (function)
+ || (TREE_CODE (function) == TEMPLATE_ID_EXPR
+ && identifier_p (TREE_OPERAND (function, 0))))
&& !any_type_dependent_arguments_p (call_args))
{
+ if (TREE_CODE (function) == TEMPLATE_ID_EXPR)
+ function = TREE_OPERAND (function, 0);
if (koenig_p && (complain & tf_warning_or_error))
{
/* For backwards compatibility and good diagnostics, try
@@ -25365,15 +25416,20 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
push_deferring_access_checks (dk_no_deferred);
input_location = DECL_SOURCE_LOCATION (fn);
- /* If needed, set current_class_ptr for the benefit of
- tsubst_copy/PARM_DECL. */
- tree tdecl = DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (fn));
- if (DECL_NONSTATIC_MEMBER_FUNCTION_P (tdecl))
+ if (!DECL_LOCAL_DECL_P (fn))
{
- tree this_parm = DECL_ARGUMENTS (tdecl);
- current_class_ptr = NULL_TREE;
- current_class_ref = cp_build_fold_indirect_ref (this_parm);
- current_class_ptr = this_parm;
+ /* If needed, set current_class_ptr for the benefit of
+ tsubst_copy/PARM_DECL. The exception pattern will
+ refer to the parm of the template, not the
+ instantiation. */
+ tree tdecl = DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (fn));
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (tdecl))
+ {
+ tree this_parm = DECL_ARGUMENTS (tdecl);
+ current_class_ptr = NULL_TREE;
+ current_class_ref = cp_build_fold_indirect_ref (this_parm);
+ current_class_ptr = this_parm;
+ }
}
/* If this function is represented by a TEMPLATE_DECL, then
@@ -26997,7 +27053,7 @@ type_dependent_expression_p (tree expression)
&& !(DECL_CLASS_SCOPE_P (expression)
&& dependent_type_p (DECL_CONTEXT (expression)))
&& !(DECL_LANG_SPECIFIC (expression)
- && DECL_FRIEND_P (expression)
+ && DECL_UNIQUE_FRIEND_P (expression)
&& (!DECL_FRIEND_CONTEXT (expression)
|| dependent_type_p (DECL_FRIEND_CONTEXT (expression))))
&& !DECL_LOCAL_DECL_P (expression))
@@ -27881,7 +27937,9 @@ make_constrained_placeholder_type (tree type, tree con, tree args)
tree expr = tmpl;
if (TREE_CODE (con) == FUNCTION_DECL)
expr = ovl_make (tmpl);
+ ++processing_template_decl;
expr = build_concept_check (expr, type, args, tf_warning_or_error);
+ --processing_template_decl;
PLACEHOLDER_TYPE_CONSTRAINTS (type) = expr;
@@ -28830,17 +28888,19 @@ static GTY((deletable)) hash_map<tree, tree_pair_p> *dguide_cache;
/* Return the non-aggregate deduction guides for deducible template TMPL. The
aggregate candidate is added separately because it depends on the
- initializer. */
+ initializer. Set ANY_DGUIDES_P if we find a non-implicit deduction
+ guide. */
static tree
-deduction_guides_for (tree tmpl, tsubst_flags_t complain)
+deduction_guides_for (tree tmpl, bool &any_dguides_p, tsubst_flags_t complain)
{
tree guides = NULL_TREE;
if (DECL_ALIAS_TEMPLATE_P (tmpl))
{
tree under = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
tree tinfo = get_template_info (under);
- guides = deduction_guides_for (TI_TEMPLATE (tinfo), complain);
+ guides = deduction_guides_for (TI_TEMPLATE (tinfo), any_dguides_p,
+ complain);
}
else
{
@@ -28849,6 +28909,8 @@ deduction_guides_for (tree tmpl, tsubst_flags_t complain)
LOOK_want::NORMAL, /*complain*/false);
if (guides == error_mark_node)
guides = NULL_TREE;
+ else
+ any_dguides_p = true;
}
/* Cache the deduction guides for a template. We also remember the result of
@@ -28940,6 +29002,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
tree type = TREE_TYPE (tmpl);
bool try_list_ctor = false;
+ bool list_init_p = false;
releasing_vec rv_args = NULL;
vec<tree,va_gc> *&args = *&rv_args;
@@ -28947,6 +29010,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
args = make_tree_vector ();
else if (BRACE_ENCLOSED_INITIALIZER_P (init))
{
+ list_init_p = true;
try_list_ctor = TYPE_HAS_LIST_CTOR (type);
if (try_list_ctor && CONSTRUCTOR_NELTS (init) == 1)
{
@@ -28974,13 +29038,15 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
if (args == NULL)
return error_mark_node;
- tree cands = deduction_guides_for (tmpl, complain);
+ bool any_dguides_p = false;
+ tree cands = deduction_guides_for (tmpl, any_dguides_p, complain);
if (cands == error_mark_node)
return error_mark_node;
- /* Prune explicit deduction guides in copy-initialization context. */
+ /* Prune explicit deduction guides in copy-initialization context (but
+ not copy-list-initialization). */
bool elided = false;
- if (flags & LOOKUP_ONLYCONVERTING)
+ if (!list_init_p && (flags & LOOKUP_ONLYCONVERTING))
{
for (lkp_iterator iter (cands); !elided && iter; ++iter)
if (DECL_NONCONVERTING_P (STRIP_TEMPLATE (*iter)))
@@ -29049,18 +29115,57 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
--cp_unevaluated_operand;
}
- if (call == error_mark_node
- && (complain & tf_warning_or_error))
+ if (call == error_mark_node)
{
- error ("class template argument deduction failed:");
+ if (complain & tf_warning_or_error)
+ {
+ error ("class template argument deduction failed:");
- ++cp_unevaluated_operand;
- call = build_new_function_call (cands, &args, complain | tf_decltype);
- --cp_unevaluated_operand;
+ ++cp_unevaluated_operand;
+ call = build_new_function_call (cands, &args,
+ complain | tf_decltype);
+ --cp_unevaluated_operand;
- if (elided)
- inform (input_location, "explicit deduction guides not considered "
- "for copy-initialization");
+ if (elided)
+ inform (input_location, "explicit deduction guides not considered "
+ "for copy-initialization");
+ }
+ return error_mark_node;
+ }
+ /* [over.match.list]/1: In copy-list-initialization, if an explicit
+ constructor is chosen, the initialization is ill-formed. */
+ else if (flags & LOOKUP_ONLYCONVERTING)
+ {
+ tree fndecl = cp_get_callee_fndecl_nofold (call);
+ if (fndecl && DECL_NONCONVERTING_P (fndecl))
+ {
+ if (complain & tf_warning_or_error)
+ {
+ // TODO: Pass down location from cp_finish_decl.
+ error ("class template argument deduction for %qT failed: "
+ "explicit deduction guide selected in "
+ "copy-list-initialization", type);
+ inform (DECL_SOURCE_LOCATION (fndecl),
+ "explicit deduction guide declared here");
+
+ }
+ return error_mark_node;
+ }
+ }
+
+ /* If CTAD succeeded but the type doesn't have any explicit deduction
+ guides, this deduction might not be what the user intended. */
+ if (call != error_mark_node && !any_dguides_p)
+ {
+ tree fndecl = cp_get_callee_fndecl_nofold (call);
+ if (fndecl != NULL_TREE
+ && (!DECL_IN_SYSTEM_HEADER (fndecl)
+ || global_dc->dc_warn_system_headers)
+ && warning (OPT_Wctad_maybe_unsupported,
+ "%qT may not intend to support class template argument "
+ "deduction", type))
+ inform (input_location, "add a deduction guide to suppress this "
+ "warning");
}
return cp_build_qualified_type (TREE_TYPE (call), cp_type_quals (ptype));
diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c
index 11833e3..a28b722 100644
--- a/gcc/cp/ptree.c
+++ b/gcc/cp/ptree.c
@@ -332,8 +332,12 @@ debug_overload (tree node)
tree decl = *iter;
auto xloc = expand_location (DECL_SOURCE_LOCATION (decl));
auto fullname = decl_as_string (decl, 0);
+ bool using_p = iter.using_p ();
+ bool hidden_p = iter.hidden_p ();
- fprintf (file, "%p: %s:%d:%d \"%s\"\n", (void *)decl,
+ fprintf (file, "%p:%c%c %s:%d:%d \"%s\"\n", (void *)decl,
+ hidden_p ? 'H' : '-',
+ using_p ? 'U' : '-',
xloc.file, xloc.line, xloc.column, fullname);
}
}
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 0ab3c42..7c4bff7 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -169,8 +169,7 @@ init_rtti_processing (void)
tree type_info_type;
push_nested_namespace (std_node);
- type_info_type = xref_tag (class_type, get_identifier ("type_info"),
- /*tag_scope=*/ts_current, false);
+ type_info_type = xref_tag (class_type, get_identifier ("type_info"));
pop_nested_namespace (std_node);
const_type_info_type_node
= cp_build_qualified_type (type_info_type, TYPE_QUAL_CONST);
@@ -761,9 +760,7 @@ build_dynamic_cast_1 (location_t loc, tree type, tree expr,
push_abi_namespace ();
tinfo_ptr = xref_tag (class_type,
- get_identifier ("__class_type_info"),
- /*tag_scope=*/ts_current, false);
-
+ get_identifier ("__class_type_info"));
tinfo_ptr = build_pointer_type
(cp_build_qualified_type
(tinfo_ptr, TYPE_QUAL_CONST));
@@ -948,10 +945,8 @@ tinfo_base_init (tinfo_s *ti, tree target)
vtable_ptr = ti->vtable;
if (!vtable_ptr)
{
- tree real_type;
push_abi_namespace ();
- real_type = xref_tag (class_type, ti->name,
- /*tag_scope=*/ts_current, false);
+ tree real_type = xref_tag (class_type, ti->name);
pop_abi_namespace ();
if (!COMPLETE_TYPE_P (real_type))
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 11996c9..1e42cd7 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3030,6 +3030,7 @@ finish_compound_literal (tree type, tree compound_literal,
&& initializer_constant_valid_p (compound_literal, type))
{
tree decl = create_temporary_var (type);
+ DECL_CONTEXT (decl) = NULL_TREE;
DECL_INITIAL (decl) = compound_literal;
TREE_STATIC (decl) = 1;
if (literal_type_p (type) && CP_TYPE_CONST_NON_VOLATILE_P (type))
@@ -3216,13 +3217,13 @@ begin_class_definition (tree t)
if (t == error_mark_node || ! MAYBE_CLASS_TYPE_P (t))
{
t = make_class_type (RECORD_TYPE);
- pushtag (make_anon_name (), t, /*tag_scope=*/ts_current);
+ pushtag (make_anon_name (), t);
}
if (TYPE_BEING_DEFINED (t))
{
t = make_class_type (TREE_CODE (t));
- pushtag (TYPE_IDENTIFIER (t), t, /*tag_scope=*/ts_current);
+ pushtag (TYPE_IDENTIFIER (t), t);
}
maybe_process_partial_specialization (t);
pushclass (t);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index e860660..9bc37ac 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2237,13 +2237,13 @@ ovl_make (tree fn, tree next)
return result;
}
-/* Add FN to the (potentially NULL) overload set OVL. USING_P is
- true, if FN is via a using declaration. We also pay attention to
- DECL_HIDDEN. We keep the hidden decls first, but remaining ones
- are unordered. */
+/* Add FN to the (potentially NULL) overload set OVL. USING_OR_HIDDEN
+ is > 0, if FN is via a using declaration. USING_OR_HIDDEN is < 0,
+ if FN is hidden. (A decl cannot be both using and hidden.) We
+ keep the hidden decls first, but remaining ones are unordered. */
tree
-ovl_insert (tree fn, tree maybe_ovl, bool using_p)
+ovl_insert (tree fn, tree maybe_ovl, int using_or_hidden)
{
tree result = maybe_ovl;
tree insert_after = NULL_TREE;
@@ -2257,13 +2257,13 @@ ovl_insert (tree fn, tree maybe_ovl, bool using_p)
insert_after = maybe_ovl;
}
- bool hidden_p = DECL_HIDDEN_P (fn);
- if (maybe_ovl || using_p || hidden_p || TREE_CODE (fn) == TEMPLATE_DECL)
+ if (maybe_ovl || using_or_hidden || TREE_CODE (fn) == TEMPLATE_DECL)
{
maybe_ovl = ovl_make (fn, maybe_ovl);
- if (hidden_p)
+
+ if (using_or_hidden < 0)
OVL_HIDDEN_P (maybe_ovl) = true;
- if (using_p)
+ if (using_or_hidden > 0)
OVL_DEDUP_P (maybe_ovl) = OVL_USING_P (maybe_ovl) = true;
}
else
@@ -2285,18 +2285,8 @@ ovl_insert (tree fn, tree maybe_ovl, bool using_p)
tree
ovl_skip_hidden (tree ovl)
{
- for (;
- ovl && TREE_CODE (ovl) == OVERLOAD && OVL_HIDDEN_P (ovl);
- ovl = OVL_CHAIN (ovl))
- gcc_checking_assert (DECL_HIDDEN_P (OVL_FUNCTION (ovl)));
-
- if (ovl && TREE_CODE (ovl) != OVERLOAD && DECL_HIDDEN_P (ovl))
- {
- /* Any hidden functions should have been wrapped in an
- overload, but injected friend classes will not. */
- gcc_checking_assert (!DECL_DECLARES_FUNCTION_P (ovl));
- ovl = NULL_TREE;
- }
+ while (ovl && TREE_CODE (ovl) == OVERLOAD && OVL_HIDDEN_P (ovl))
+ ovl = OVL_CHAIN (ovl);
return ovl;
}
@@ -2648,6 +2638,9 @@ build_cp_fntype_variant (tree type, cp_ref_qualifier rqual,
/* Need to build a new variant. */
v = build_variant_type_copy (type);
+ if (!TYPE_DEPENDENT_P (v))
+ /* We no longer know that it's not type-dependent. */
+ TYPE_DEPENDENT_P_VALID (v) = false;
TYPE_RAISES_EXCEPTIONS (v) = raises;
TYPE_HAS_LATE_RETURN_TYPE (v) = late;
switch (rqual)
@@ -3810,6 +3803,8 @@ cp_tree_equal (tree t1, tree t2)
if (SIZEOF_EXPR_TYPE_P (t2))
o2 = TREE_TYPE (o2);
}
+ else if (ALIGNOF_EXPR_STD_P (t1) != ALIGNOF_EXPR_STD_P (t2))
+ return false;
if (TREE_CODE (o1) != TREE_CODE (o2))
return false;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 9166156..48d34f1 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4706,14 +4706,13 @@ cp_build_binary_op (const op_location_t &location,
{
tree type0 = TREE_OPERAND (op0, 0);
tree type1 = TREE_OPERAND (op1, 0);
- tree first_arg = type0;
+ tree first_arg = tree_strip_any_location_wrapper (type0);
if (!TYPE_P (type0))
type0 = TREE_TYPE (type0);
if (!TYPE_P (type1))
type1 = TREE_TYPE (type1);
if (INDIRECT_TYPE_P (type0) && same_type_p (TREE_TYPE (type0), type1))
{
- STRIP_ANY_LOCATION_WRAPPER (first_arg);
if (!(TREE_CODE (first_arg) == PARM_DECL
&& DECL_ARRAY_PARAMETER_P (first_arg)
&& warn_sizeof_array_argument)
@@ -4729,6 +4728,13 @@ cp_build_binary_op (const op_location_t &location,
"first %<sizeof%> operand was declared here");
}
}
+ else if (TREE_CODE (type0) == ARRAY_TYPE
+ && !char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type0)))
+ /* Set by finish_parenthesized_expr. */
+ && !TREE_NO_WARNING (op1)
+ && (complain & tf_warning))
+ maybe_warn_sizeof_array_div (location, first_arg, type0,
+ op1, non_reference (type1));
}
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
@@ -10171,7 +10177,7 @@ check_return_expr (tree retval, bool *no_warning)
/* The call in a (lambda) thunk needs no conversions. */
if (TREE_CODE (retval) == CALL_EXPR
- && CALL_FROM_THUNK_P (retval))
+ && call_from_lambda_thunk_p (retval))
converted = true;
/* First convert the value to the function's return type, then