aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-11-10 07:26:18 -0800
committerIan Lance Taylor <iant@golang.org>2020-11-10 07:26:18 -0800
commit8d703821c69062c0cd255787d793e44f1a95d463 (patch)
tree6b1df9cdc36cc47b6164db69a14bc86a63dc77c6 /gcc/cp
parent9cd320ea6572c577cdf17ce1f9ea5230b166af6d (diff)
parentcf392dbdf17e38026f8e3c0e9af7f5b87f63be56 (diff)
downloadgcc-8d703821c69062c0cd255787d793e44f1a95d463.zip
gcc-8d703821c69062c0cd255787d793e44f1a95d463.tar.gz
gcc-8d703821c69062c0cd255787d793e44f1a95d463.tar.bz2
Merge from trunk revision cf392dbdf17e38026f8e3c0e9af7f5b87f63be56.
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog685
-rw-r--r--gcc/cp/call.c35
-rw-r--r--gcc/cp/class.c49
-rw-r--r--gcc/cp/constexpr.c136
-rw-r--r--gcc/cp/constraint.cc250
-rw-r--r--gcc/cp/coroutines.cc25
-rw-r--r--gcc/cp/cp-gimplify.c16
-rw-r--r--gcc/cp/cp-objcp-common.c5
-rw-r--r--gcc/cp/cp-tree.h103
-rw-r--r--gcc/cp/cvt.c38
-rw-r--r--gcc/cp/cxx-pretty-print.c33
-rw-r--r--gcc/cp/decl.c233
-rw-r--r--gcc/cp/decl2.c60
-rw-r--r--gcc/cp/except.c24
-rw-r--r--gcc/cp/friend.c15
-rw-r--r--gcc/cp/init.c2
-rw-r--r--gcc/cp/logic.cc17
-rw-r--r--gcc/cp/method.c17
-rw-r--r--gcc/cp/name-lookup.c564
-rw-r--r--gcc/cp/name-lookup.h23
-rw-r--r--gcc/cp/parser.c706
-rw-r--r--gcc/cp/pt.c433
-rw-r--r--gcc/cp/rtti.c88
-rw-r--r--gcc/cp/search.c11
-rw-r--r--gcc/cp/semantics.c200
-rw-r--r--gcc/cp/tree.c102
-rw-r--r--gcc/cp/typeck.c137
-rw-r--r--gcc/cp/typeck2.c2
28 files changed, 2687 insertions, 1322 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c28ae8c..9c36b80 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,688 @@
+2020-11-09 Marek Polacek <polacek@redhat.com>
+
+ DR 1914
+ * parser.c (cp_parser_check_std_attribute): Return bool. Add a
+ location_t parameter. Return true if the attribute wasn't duplicated.
+ Give a warning instead of an error. Check more attributes.
+ (cp_parser_std_attribute_list): Don't add duplicated attributes to
+ the list. Pass location to cp_parser_check_std_attribute.
+
+2020-11-09 Patrick Palka <ppalka@redhat.com>
+
+ * constraint.cc (norm_info::norm_info): Initialize orig_decl.
+ (norm_info::orig_decl): New data member.
+ (normalize_atom): When caching an atom for the first time,
+ compute a list of template parameters used in the targets of the
+ parameter mapping and store it in the TREE_TYPE of the mapping.
+ (get_normalized_constraints_from_decl): Set current_function_decl
+ appropriately when normalizing. As an optimization, don't
+ set up a push_nested_class_guard when decl has no constraints.
+ (sat_hasher::hash): Use this list to hash only the template
+ arguments that are relevant to the atom.
+ (satisfy_atom): Use this list to compare only the template
+ arguments that are relevant to the atom.
+ * pt.c (keep_template_parm): Do a sanity check on the parameter's
+ index when flag_checking.
+
+2020-11-09 Patrick Palka <ppalka@redhat.com>
+
+ * cp-tree.h (ATOMIC_CONSTR_MAP_INSTANTIATED_P): Define this flag
+ for ATOMIC_CONSTRs.
+ * constraint.cc (sat_hasher::hash): Use hash_atomic_constraint
+ if the flag is set, otherwise keep using a pointer hash.
+ (sat_hasher::equal): Return false if the flag's setting differs
+ on two atoms. Call atomic_constraints_identical_p if the flag
+ is set, otherwise keep using a pointer equality test.
+ (satisfy_atom): After instantiating the parameter mapping, form
+ another ATOMIC_CONSTR using the instantiated mapping and query
+ the cache again. Cache the satisfaction value of both atoms.
+ (diagnose_atomic_constraint): Simplify now that the supplied
+ atom has an instantiated mapping.
+
+2020-11-09 Patrick Palka <ppalka@redhat.com>
+
+ * constraint.cc (atom_cache): Define this deletable hash_table.
+ (normalize_atom): Use it to cache ATOMIC_CONSTRs when not
+ generating diagnostics.
+ (sat_hasher::hash): Use htab_hash_pointer instead of
+ hash_atomic_constraint.
+ (sat_hasher::equal): Test for pointer equality instead of
+ atomic_constraints_identical_p.
+ * cp-tree.h (struct atom_hasher): Moved and renamed from ...
+ * logic.cc (struct constraint_hash): ... here.
+ (clause::m_set): Adjust accordingly.
+
+2020-11-09 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/93907
+ * constraint.cc (tsubst_parameter_mapping): Also canonicalize
+ the type arguments of a TYPE_ARGUMENT_PACk.
+
+2020-11-09 Jason Merrill <jason@redhat.com>
+
+ * pt.c (tsubst): Replace *_ARGUMENT_PACK code with
+ a call to tsubst_argument_pack.
+
+2020-11-09 Jason Merrill <jason@redhat.com>
+
+ * class.c (handle_using_decl): Add an iloc_sentinel.
+
+2020-11-09 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97762
+ * parser.c (warn_about_ambiguous_parse): Handle the case when
+ there is no type in the decl-specifiers.
+
+2020-11-09 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (LOOKUP_FOUND_P): Add ENUMERAL_TYPE.
+ * name-lookup.c (class name_lookup): Add comments.
+ (name_lookup::adl_namespace_only): Replace with ...
+ (name_lookup::adl_class_fns): ... this and ...
+ (name_lookup::adl_namespace_fns): ... this.
+ (name_lookup::adl_namespace): Deal with inline nests here.
+ (name_lookup::adl_class): Complete the type here.
+ (name_lookup::adl_type): Call broken-out enum ..
+ (name_lookup::adl_enum): New. No need to call the namespace adl
+ if it is class-scope.
+ (name_lookup::search_adl): Iterate over collected scopes here.
+
+2020-11-09 Nathan Sidwell <nathan@acm.org>
+
+ * name-lookup.c (lookup_qualified_name): Expose an overload of a
+ singleton with known type.
+ (lookup_name_1): Just check the overload's type to expose it.
+ * parser.c (cp_parser_lookup_name): Do not do that check here.
+
+2020-11-08 Iain Sandoe <iain@sandoe.co.uk>
+
+ * parser.c (cp_parser_objc_at_property_declaration): Handle
+ class keywords in @property attribute context.
+
+2020-11-06 Marek Polacek <polacek@redhat.com>
+
+ PR c++/81660
+ * except.c (can_convert_eh): Change the return type to bool. If
+ the type TO and FROM are the same, return true.
+
+2020-11-06 Iain Sandoe <iain@sandoe.co.uk>
+
+ * parser.c (cp_parser_objc_at_property_declaration):
+ Improve parsing fidelity. Associate better location info
+ with @property attributes. Clean up the interface to
+ objc_add_property_declaration ().
+
+2020-11-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/67453
+ * decl.c (duplicate_decls): Propagate DECL_ATTRIBUTES and
+ DECL_PRESERVE_P from olddecl to its clones if any.
+
+2020-11-06 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (DECL_UNDECLARED_BUILTIN_P): Delete.
+ * cp-objcp-common.c (names_bultin_p): Rename
+ DECL_IS_BUILTIN->DECL_IS_UNDECLARED_BUILTIN.
+ * decl.c (decls_match): Likewise. Replace
+ DECL_UNDECLARED_BUILTIN_P with DECL_IS_UNDECLARED_BUILTIN.
+ (duplicate_decls): Likewise.
+ * decl2.c (collect_source_refs): Likewise.
+ * name-lookup.c (anticipated_builtin_p, print_binding_level)
+ (do_nonmember_using_decl): Likewise.
+ * pt.c (builtin_pack_fn_p): Likewise.
+ * typeck.c (error_args_num): Likewise.
+
+2020-11-06 Nathan Sidwell <nathan@acm.org>
+
+ * parser.c (cp_parser_template_declaration): Adjust 'export' warning.
+ (cp_parser_explicit_specialization): Remove unneeded bool setting.
+
+2020-11-06 Jan Hubicka <jh@suse.cz>
+
+ * tree.c (cp_fix_function_decl_p): Do not access ipa_ref_list dirrectly.
+
+2020-11-06 Tobias Burnus <tobias@codesourcery.com>
+
+ * parser.c (cp_parser_omp_atomic): Add openacc parameter and update
+ OpenACC matching.
+ (cp_parser_omp_construct): Update call.
+
+2020-11-05 Marek Polacek <polacek@redhat.com>
+
+ * except.c (check_handlers_1): Add auto_diagnostic_group.
+
+2020-11-05 Marek Polacek <polacek@redhat.com>
+
+ PR c++/78209
+ * pt.c (do_auto_deduction): If init is REFERENCE_REF_P, use its
+ first operand.
+
+2020-11-05 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97675
+ * except.c (check_handlers_1): Use OPT_Wexceptions for the
+ warning. Use inform for the second part of the warning.
+
+2020-11-05 Marek Polacek <polacek@redhat.com>
+
+ PR c++/25814
+ * cp-tree.h (enum cp_tree_index): Add CPTI_EXPLICIT_VOID_LIST.
+ (explicit_void_list_node): Define.
+ (PARENTHESIZED_LIST_P): New macro.
+ (struct cp_declarator): Add function::parens_loc.
+ * decl.c (cxx_init_decl_processing): Initialize explicit_void_list_node.
+ (grokparms): Also break when explicit_void_list_node.
+ * parser.c (make_call_declarator): New location_t parameter. Use it
+ to set declarator->u.function.parens_loc.
+ (cp_parser_lambda_declarator_opt): Pass UNKNOWN_LOCATION to
+ make_call_declarator.
+ (warn_about_ambiguous_parse): New function.
+ (cp_parser_init_declarator): Call warn_about_ambiguous_parse.
+ (cp_parser_declarator): Set *parenthesized_p to false rather than to
+ true.
+ (cp_parser_direct_declarator): Create a location for the function's
+ parentheses and pass it to make_call_declarator.
+ (cp_parser_parameter_declaration_clause): Return explicit_void_list_node
+ for (void).
+ (cp_parser_parameter_declaration_list): Set PARENTHESIZED_LIST_P
+ in the parameters tree.
+
+2020-11-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/97670
+ * semantics.c (finish_omp_clauses): Look through array reductions to
+ find underlying decl to clear in the aligned_head bitmap. Use
+ DECL_UID (t) instead of DECL_UID (OMP_CLAUSE_DECL (c)) when clearing
+ in the bitmap. Only diagnose errors about allocate vars not being
+ privatized on the same construct on allocate clause if it has
+ a DECL_P OMP_CLAUSE_DECL.
+
+2020-11-04 Iain Sandoe <iain@sandoe.co.uk>
+
+ * constexpr.c (potential_constant_expression_1): Handle
+ expressions known to be non-constant for Objective-C.
+
+2020-11-03 Jason Merrill <jason@redhat.com>
+
+ * tree.c (is_byte_access_type): Don't use char_type_p.
+
+2020-11-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/97663
+ * parser.c (cp_parser_init_declarator): Don't try to parse
+ C++17 deduction guides if there are any type specifiers even when
+ type is NULL.
+
+2020-11-03 Kamlesh Kumar <kamleshbhalui@gmail.com>
+ Jason Merrill <jason@redhat.com>
+
+ PR c++/97453
+ DR2303
+ * pt.c (get_template_base): Consider closest base in template
+ deduction when base of base also matches.
+
+2020-11-03 Nathan Sidwell <nathan@acm.org>
+
+ * pt.c (tsubst_expr): Simplify using decl instantiation, add
+ asserts.
+
+2020-11-03 Nathan Sidwell <nathan@acm.org>
+
+ * class.c (copy_fndecl_with_name): Always not top level.
+ (build_cdtor_clones): Add update_methods parm, use it to
+ conditionally update the method vec. Return void
+ (clone_cdtor): Adjust.
+ (clone_constructors_and_destructors): Adjust comment.
+
+2020-11-03 Nathan Sidwell <nathan@acm.org>
+
+ * pt.c (primary_template_specialization_p): Use
+ VAR_OR_FUNCTION_DECL_P.
+ (tsubst_template_decl): Check for FUNCTION_DECL, not !TYPE && !VAR
+ for registering a specialization.
+
+2020-11-03 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (fixup_deferred_exception_variants): Declare.
+ * parser.c (cp_parser_class_specifier_1): Call it when
+ completing deferred parses rather than creating a variant.
+ (cp_parser_member_declaration): Move comment from ...
+ (cp_parser_noexcept_specification_opt): ... here. Refactor the
+ deferred parse.
+ * tree.c (fixup_deferred_exception_variants): New.
+
+2020-11-03 Nathan Sidwell <nathan@acm.org>
+
+ * pt.c (tsubst_lambda_expr): Reorder extra-scope handling to match
+ the non-template case.
+ (instantiate_body): Move a couple of declarations to their
+ initializers.
+
+2020-11-03 Nathan Sidwell <nathan@acm.org>
+
+ * decl.c (duplicate_decls): Return error_mark_node fo extern-c
+ mismatch.
+
+2020-11-03 Marek Polacek <polacek@redhat.com>
+
+ * constexpr.c (potential_constant_expression_1): Treat
+ __PRETTY_FUNCTION__ inside a template function as
+ potentially-constant.
+ * pt.c (uses_template_parms): Call
+ instantiation_dependent_expression_p instead of
+ value_dependent_expression_p.
+ (instantiation_dependent_expression_p): Check
+ potential_constant_expression before calling
+ value_dependent_expression_p.
+
+2020-11-03 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97632
+ * init.c (build_new_1): Disable -Winit-list-lifetime for an unevaluated
+ operand.
+
+2020-11-03 Nathan Sidwell <nathan@acm.org>
+
+ * tree.c (bind_template_template_parm): Mark the parm as a
+ template parm.
+ (cp_tree_equal): Refactor CALL_EXPR. Use comp_template_args for
+ TREE_VECs.
+
+2020-11-03 Nathan Sidwell <nathan@acm.org>
+
+ * rtti.c (init_rtti_processing): Move var decl to its init.
+ (get_tinfo_decl): Likewise. Break out creation to called helper
+ ...
+ (get_tinfo_decl_direct): ... here.
+ (build_dynamic_cast_1): Move var decls to their initializers.
+ (tinfo_base_init): Set decl's location to BUILTINS_LOCATION.
+ (get_tinfo_desc): Only push ABI namespace when needed. Set type's
+ context.
+
+2020-11-02 Nathan Sidwell <nathan@acm.org>
+
+ * decl.c (start_decl_1): Refactor declarations. Fixup some
+ whitespace.
+ (lookup_and_check_tag): Fixup some whitespace.
+
+2020-11-02 Nathan Sidwell <nathan@acm.org>
+
+ * decl.c (duplicate_decls): Refactor some template & builtin
+ handling.
+
+2020-11-02 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (struct cxx_int_tree_map): Delete.
+ (struct cxx_int_tree_map_hasher): Delete.
+ * cp-gimplify.c (cxx_int_tree_map_hasher::equal): Delete.
+ (cxx_int_tree_map_hasher::hash): Delete.
+
+2020-11-02 Patrick Palka <ppalka@redhat.com>
+
+ * class.c (finish_struct_1): Don't call clear_satisfaction_cache.
+ * constexpr.c (clear_cv_and_fold_caches): Likewise. Remove bool
+ parameter.
+ * constraint.cc (clear_satisfaction_cache): Remove definition.
+ * cp-tree.h (clear_satisfaction_cache): Remove declaration.
+ (clear_cv_and_fold_caches): Remove bool parameter.
+ * typeck2.c (store_init_value): Remove argument to
+ clear_cv_and_fold_caches.
+
+2020-11-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * parser.c (cp_parser_objc_at_property_declaration): Use any
+ exisiting syntax error to suppress complaints about a missing
+ closing parenthesis in parsing property attributes.
+
+2020-10-30 Jakub Jelinek <jakub@redhat.com>
+
+ * semantics.c (finish_omp_clauses) <case OMP_CLAUSE_ALLOCATE>: Handle
+ non-static members in methods.
+ * pt.c (tsubst_omp_clauses): Handle OMP_CLAUSE_ALLOCATE.
+
+2020-10-29 Marek Polacek <polacek@redhat.com>
+
+ DR 625
+ PR c++/97479
+ * parser.c (cp_parser_type_id_1): Reject using auto as
+ a template-argument in C++20.
+
+2020-10-29 Marek Polacek <polacek@redhat.com>
+
+ PR c++/93107
+ * pt.c (do_auto_deduction): Call resolve_nondeduced_context for
+ the elements of a { } list.
+
+2020-10-29 Marek Polacek <polacek@redhat.com>
+
+ * typeck.c (do_warn_enum_conversions): Don't warn for SPACESHIP_EXPR.
+ (cp_build_binary_op): Reject float <=> enum or enum <=> float. Use
+ CP_INTEGRAL_TYPE_P instead of INTEGRAL_OR_ENUMERATION_TYPE_P.
+
+2020-10-29 Patrick Palka <ppalka@redhat.com>
+
+ * constraint.cc (get_normalized_constraints): Remove 'args'
+ parameter. Pass NULL_TREE as the initial template arguments to
+ normalize_expression.
+ (get_normalized_constraints_from_info): Remove 'args' parameter
+ and adjust the call to get_normalized_constraints.
+ (get_normalized_constraints_from_decl): Remove 'args' local
+ variable and adjust call to get_normalized_constraints_from_info.
+ (normalize_concept_definition): Remove 'args' local variable
+ and adjust call to get_normalized_constraints.
+ (normalize_constraint_expression): Remove the two-parameter
+ overload. Remove 'args' parameter from the three-parameter
+ overload and update function comment accordingly. Remove
+ default argument from 'diag' parameter. Adjust call to
+ get_normalized_constraints.
+ (finish_nested_requirement): Adjust call to
+ normalize_constraint_expression.
+ (strictly_subsumes): Remove 'args' parameter. Adjust call to
+ get_normalized_constraints_from_info.
+ (weakly_subsumes): Likewise.
+ * cp-tree.h (strictly_subsumes): Remove 'args' parameter.
+ (weakly_subsumes): Likewise.
+ * pt.c (process_partial_specialization): Adjust call to
+ strictly_subsumes.
+ (is_compatible_template_arg): Adjust call to weakly_subsumes.
+
+2020-10-29 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/97412
+ * constraint.cc (normalize_concept_check): Don't call
+ tsubst_template_args when 'args' is NULL.
+
+2020-10-29 Jason Merrill <jason@redhat.com>
+
+ PR c++/97388
+ * constexpr.c (cxx_eval_outermost_constant_expr): Revert to
+ original expression if evaluation sets non_constant_p.
+
+2020-10-29 Jakub Jelinek <jakub@redhat.com>
+ Jason Merrill <jason@redhat.com>
+
+ PR c++/97388
+ * constexpr.c (cxx_bind_parameters_in_call): Set non_constant_args
+ if the parameter type has a non-trivial destructor.
+ (cxx_eval_call_expression): Only unshare arguments if we're
+ memoizing this evaluation.
+
+2020-10-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/95808
+ * cp-tree.h (enum cp_tree_index): Add CPTI_HEAP_VEC_UNINIT_IDENTIFIER
+ and CPTI_HEAP_VEC_IDENTIFIER.
+ (heap_vec_uninit_identifier, heap_vec_identifier): Define.
+ * decl.c (initialize_predefined_identifiers): Initialize those
+ identifiers.
+ * constexpr.c (cxx_eval_call_expression): Reject array allocations
+ deallocated with non-array deallocation or non-array allocations
+ deallocated with array deallocation.
+ (non_const_var_error): Handle heap_vec_uninit_identifier and
+ heap_vec_identifier too.
+ (cxx_eval_constant_expression): Handle also heap_vec_uninit_identifier
+ and in that case during initialization replace it with
+ heap_vec_identifier.
+ (find_heap_var_refs): Handle heap_vec_uninit_identifier and
+ heap_vec_identifier too.
+
+2020-10-29 Nathan Sidwell <nathan@acm.org>
+
+ * pt.c (push_template_decl): Do not give function-scope entities
+ other than implicit typedefs a template header. Do not readd
+ template info to a redeclared template.
+
+2020-10-28 Marek Polacek <polacek@redhat.com>
+
+ * decl.c (grokdeclarator): Offer a fix-it hint for the "unnecessary
+ parentheses in declaration" warning.
+ * parser.c (cp_parser_direct_declarator): When setting
+ declarator->parenthesized, use a location range.
+
+2020-10-28 Marek Polacek <polacek@redhat.com>
+
+ PR c++/97573
+ * call.c (build_conditional_expr_1): Warn about the deprecated
+ enum/real type conversion in C++20. Also warn about a non-enumerated
+ and enumerated type in ?: when -Wenum-conversion is on.
+ * typeck.c (do_warn_enum_conversions): New function.
+ (cp_build_binary_op): Call it.
+
+2020-10-28 Marek Polacek <polacek@redhat.com>
+
+ PR c++/96675
+ PR c++/96742
+ * pt.c (tsubst_copy_and_build): Call value_dependent_expression_p or
+ type_dependent_expression_p instead of type_dependent_expression_p_push.
+ But only call value_dependent_expression_p for expressions that are
+ potential_constant_expression.
+
+2020-10-28 Marek Polacek <polacek@redhat.com>
+
+ PR c++/94799
+ * parser.c (cp_parser_class_name): Use parser->scope when
+ setting typename_p.
+
+2020-10-28 Marek Polacek <polacek@redhat.com>
+
+ PR c++/86773
+ * parser.c (cp_parser_fold_expression): Return error_mark_node
+ if a left fold is preceded by an expression.
+
+2020-10-28 Nathan Sidwell <nathan@acm.org>
+
+ * parser.c (cp_parser_omp_declare_reduction): Set
+ DECL_LOCAL_DECL_P before push_template_decl.
+ * pt.c (instantiate_body): Nested fns do not have template_info.
+
+2020-10-28 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/95132
+ * decl2.c (mark_used): Move up the constraints_satisfied_p check
+ so that we check constraints before calling maybe_instantiate_decl.
+
+2020-10-28 Nathan Sidwell <nathan@acm.org>
+
+ * pt.c (push_template_decl): Refactor for some RAII.
+
+2020-10-28 Jakub Jelinek <jakub@redhat.com>
+
+ * parser.c (cp_parser_omp_clause_name): Handle allocate.
+ (cp_parser_omp_clause_allocate): New function.
+ (cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_ALLOCATE.
+ (OMP_FOR_CLAUSE_MASK, OMP_SECTIONS_CLAUSE_MASK,
+ OMP_PARALLEL_CLAUSE_MASK, OMP_SINGLE_CLAUSE_MASK,
+ OMP_TASK_CLAUSE_MASK, OMP_TASKGROUP_CLAUSE_MASK,
+ OMP_DISTRIBUTE_CLAUSE_MASK, OMP_TEAMS_CLAUSE_MASK,
+ OMP_TARGET_CLAUSE_MASK, OMP_TASKLOOP_CLAUSE_MASK): Add
+ PRAGMA_OMP_CLAUSE_ALLOCATE.
+ * semantics.c (finish_omp_clauses): Handle OMP_CLAUSE_ALLOCATE.
+ * pt.c (tsubst_omp_clauses): Likewise.
+
+2020-10-27 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (struct lang_type): Delete nested_udts field.
+ (CLASSTYPE_NESTED_UTDS): Delete.
+ * name-lookup.h (binding_table, binding_entry): Delete typedefs.
+ (bt_foreach_proc): Likewise.
+ (struct binding_entry_s): Delete.
+ (SCOPE_DEFAULT_HT_SIZE, CLASS_SCOPE_HT_SIZE)
+ (NAMESPACE_ORDINARY_HT_SIZE, NAMESPACE_STD_HT_SIZE)
+ (GLOBAL_SCOPE_HT_SIZE): Delete.
+ (binding_table_foreach, binding_table_find): Delete declarations.
+ * name-lookup.c (ENTRY_INDEX): Delete.
+ (free_binding_entry): Delete.
+ (binding_entry_make, binding_entry_free): Delete.
+ (struct binding_table_s): Delete.
+ (binding_table_construct, binding_table_free): Delete.
+ (binding_table_new, binding_table_expand): Delete.
+ (binding_table_insert, binding_table_find): Delete.
+ (binding_table_foreach): Delete.
+ (maybe_process_template_type_declaration): Delete
+ CLASSTYPE_NESTED_UTDS insertion.
+ (do_pushtag): Likewise.
+ * decl2.c (bt_reset_linkage_1): Fold into reset_type_linkage_1.
+ (reset_type_linkage_2, bt_reset_linkage_2): Fold into
+ reset_type_linkage.
+ * pt.c (instantiate_class_template_1): Delete NESTED_UTDs comment.
+ (bt_instantiate_type_proc): Delete.
+ (do_type_instantiation): Instantiate implicit typedef fields.
+ Delete NESTED_UTD walk.
+ * search.c (lookup_field_r): Delete unreachable NESTED_UTD
+ search.
+
+2020-10-27 Nathan Sidwell <nathan@acm.org>
+
+ * parser.c (cp_parser_explicit_instantiation): Refactor some RAII.
+ * pt.c (bt_instantiate_type_proc): DATA is the tree, pass type to
+ do_type_instantiation.
+ (do_type_instantiation): Require T to be a type. Refactor for
+ some RAII.
+
+2020-10-26 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ * cp-tree.h (CPTK_IS_NOTHROW_ASSIGNABLE): New.
+ (CPTK_IS_NOTHROW_CONSTRUCTIBLE): Likewise.
+ (is_nothrow_xible): Likewise.
+ * method.c (is_nothrow_xible): New.
+ (is_trivially_xible): Tweak.
+ * parser.c (cp_parser_primary_expression): Handle the new RID_*.
+ (cp_parser_trait_expr): Likewise.
+ * semantics.c (trait_expr_value): Handle the new RID_*.
+ (finish_trait_expr): Likewise.
+
+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
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index bd66251..9861be1 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5643,17 +5643,40 @@ build_conditional_expr_1 (const op_location_t &loc,
"in conditional expression: %qT vs %qT",
arg2_type, arg3_type);
}
- else if (extra_warnings
+ else if ((complain & tf_warning)
+ && warn_deprecated_enum_float_conv
+ && ((TREE_CODE (arg2_type) == ENUMERAL_TYPE
+ && TREE_CODE (arg3_type) == REAL_TYPE)
+ || (TREE_CODE (arg2_type) == REAL_TYPE
+ && TREE_CODE (arg3_type) == ENUMERAL_TYPE)))
+ {
+ if (TREE_CODE (arg2_type) == ENUMERAL_TYPE)
+ warning_at (loc, OPT_Wdeprecated_enum_float_conversion,
+ "conditional expression between enumeration type "
+ "%qT and floating-point type %qT is deprecated",
+ arg2_type, arg3_type);
+ else
+ warning_at (loc, OPT_Wdeprecated_enum_float_conversion,
+ "conditional expression between floating-point "
+ "type %qT and enumeration type %qT is deprecated",
+ arg2_type, arg3_type);
+ }
+ else if ((extra_warnings || warn_enum_conversion)
&& ((TREE_CODE (arg2_type) == ENUMERAL_TYPE
&& !same_type_p (arg3_type, type_promotes_to (arg2_type)))
|| (TREE_CODE (arg3_type) == ENUMERAL_TYPE
&& !same_type_p (arg2_type,
type_promotes_to (arg3_type)))))
- {
- if (complain & tf_warning)
- warning_at (loc, OPT_Wextra, "enumerated and non-enumerated "
- "type in conditional expression");
- }
+ {
+ if (complain & tf_warning)
+ {
+ enum opt_code opt = (warn_enum_conversion
+ ? OPT_Wenum_conversion
+ : OPT_Wextra);
+ warning_at (loc, opt, "enumerated and "
+ "non-enumerated type in conditional expression");
+ }
+ }
arg2 = perform_implicit_conversion (result_type, arg2, complain);
arg3 = perform_implicit_conversion (result_type, arg3, complain);
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 01780fe..7c34d94 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1,4 +1,4 @@
-/* Functions related to building classes and their related objects.
+/* Functions related to building -*- C++ -*- classes and their related objects.
Copyright (C) 1987-2020 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
@@ -1322,6 +1322,8 @@ handle_using_decl (tree using_decl, tree t)
return;
}
+ iloc_sentinel ils (DECL_SOURCE_LOCATION (using_decl));
+
/* Make type T see field decl FDECL with access ACCESS. */
if (flist)
for (ovl_iterator iter (flist); iter; ++iter)
@@ -3283,7 +3285,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
@@ -3292,7 +3295,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)
@@ -4837,7 +4840,10 @@ copy_fndecl_with_name (tree fn, tree name, tree_code code,
/* Create the RTL for this function. */
SET_DECL_RTL (clone, NULL);
- rest_of_decl_compilation (clone, namespace_bindings_p (), at_eof);
+
+ /* Regardless of the current scope, this is a member function, so
+ not at namespace scope. */
+ rest_of_decl_compilation (clone, /*top_level=*/0, at_eof);
return clone;
}
@@ -4897,8 +4903,9 @@ build_clone (tree fn, tree name, bool need_vtt_parm_p,
/* Build the clones of FN, return the number of clones built. These
will be inserted onto DECL_CHAIN of FN. */
-static unsigned
-build_cdtor_clones (tree fn, bool needs_vtt_p, bool base_omits_inherited_p)
+static void
+build_cdtor_clones (tree fn, bool needs_vtt_p, bool base_omits_inherited_p,
+ bool update_methods)
{
unsigned count = 0;
@@ -4934,7 +4941,16 @@ build_cdtor_clones (tree fn, bool needs_vtt_p, bool base_omits_inherited_p)
count += 2;
}
- return count;
+ /* The original is now an abstract function that is never
+ emitted. */
+ DECL_ABSTRACT_P (fn) = true;
+
+ if (update_methods)
+ for (tree clone = fn; count--;)
+ {
+ clone = DECL_CHAIN (clone);
+ add_method (DECL_CONTEXT (clone), clone, false);
+ }
}
/* Produce declarations for all appropriate clones of FN. If
@@ -4957,17 +4973,7 @@ clone_cdtor (tree fn, bool update_methods)
bool base_omits_inherited = (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)
&& base_ctor_omit_inherited_parms (fn));
- 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;
-
- if (update_methods)
- for (tree clone = fn; count--;)
- {
- clone = DECL_CHAIN (clone);
- add_method (DECL_CONTEXT (clone), clone, false);
- }
+ build_cdtor_clones (fn, vtt, base_omits_inherited, update_methods);
}
/* DECL is an in charge constructor, which is being defined. This will
@@ -5054,8 +5060,8 @@ adjust_clone_args (tree decl)
static void
clone_constructors_and_destructors (tree t)
{
- /* While constructors can be via a using declaration, at this point
- we no longer need to know that. */
+ /* We do not need to propagate the usingness to the clone, at this
+ point that is not needed. */
for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter)
clone_cdtor (*iter, /*update_methods=*/true);
@@ -7471,9 +7477,6 @@ finish_struct_1 (tree t)
/* Finish debugging output for this type. */
rest_of_type_compilation (t, ! LOCAL_CLASS_P (t));
- /* Recalculate satisfaction that might depend on completeness. */
- clear_satisfaction_cache ();
-
if (TYPE_TRANSPARENT_AGGR (t))
{
tree field = first_field (t);
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index a118f8a..b6f9c43 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1602,6 +1602,11 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t,
arg = adjust_temp_type (type, arg);
if (!TREE_CONSTANT (arg))
*non_constant_args = true;
+ else if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ /* The destructor needs to see any modifications the callee makes
+ to the argument. */
+ *non_constant_args = true;
+
/* For virtual calls, adjust the this argument, so that it is
the object on which the method is called, rather than
one of its bases. */
@@ -2288,7 +2293,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
{
tree type = build_array_type_nelts (char_type_node,
tree_to_uhwi (arg0));
- tree var = build_decl (loc, VAR_DECL, heap_uninit_identifier,
+ tree var = build_decl (loc, VAR_DECL,
+ (IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (fun))
+ & OVL_OP_FLAG_VEC)
+ ? heap_vec_uninit_identifier
+ : heap_uninit_identifier,
type);
DECL_ARTIFICIAL (var) = 1;
TREE_STATIC (var) = 1;
@@ -2306,6 +2315,42 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
if (DECL_NAME (var) == heap_uninit_identifier
|| DECL_NAME (var) == heap_identifier)
{
+ if (IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (fun))
+ & OVL_OP_FLAG_VEC)
+ {
+ if (!ctx->quiet)
+ {
+ error_at (loc, "array deallocation of object "
+ "allocated with non-array "
+ "allocation");
+ inform (DECL_SOURCE_LOCATION (var),
+ "allocation performed here");
+ }
+ *non_constant_p = true;
+ return t;
+ }
+ DECL_NAME (var) = heap_deleted_identifier;
+ ctx->global->values.remove (var);
+ ctx->global->heap_dealloc_count++;
+ return void_node;
+ }
+ else if (DECL_NAME (var) == heap_vec_uninit_identifier
+ || DECL_NAME (var) == heap_vec_identifier)
+ {
+ if ((IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (fun))
+ & OVL_OP_FLAG_VEC) == 0)
+ {
+ if (!ctx->quiet)
+ {
+ error_at (loc, "non-array deallocation of "
+ "object allocated with array "
+ "allocation");
+ inform (DECL_SOURCE_LOCATION (var),
+ "allocation performed here");
+ }
+ *non_constant_p = true;
+ return t;
+ }
DECL_NAME (var) = heap_deleted_identifier;
ctx->global->values.remove (var);
ctx->global->heap_dealloc_count++;
@@ -2586,14 +2631,14 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
problems with verify_gimple. */
arg = unshare_expr_without_location (arg);
TREE_VEC_ELT (bound, i) = arg;
+
+ /* And then unshare again so the callee doesn't change the
+ argument values in the hash table. XXX Could we unshare
+ lazily in cxx_eval_store_expression? */
+ arg = unshare_constructor (arg);
+ if (TREE_CODE (arg) == CONSTRUCTOR)
+ vec_safe_push (ctors, arg);
}
- /* Don't share a CONSTRUCTOR that might be changed. This is not
- redundant with the unshare just above; we also don't want to
- change the argument values in the hash table. XXX Could we
- unshare lazily in cxx_eval_store_expression? */
- arg = unshare_constructor (arg);
- if (TREE_CODE (arg) == CONSTRUCTOR)
- vec_safe_push (ctors, arg);
ctx->global->values.put (remapped, arg);
remapped = DECL_CHAIN (remapped);
}
@@ -3657,15 +3702,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.
@@ -3954,7 +4006,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;
@@ -3967,7 +4020,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;
@@ -4591,7 +4650,9 @@ non_const_var_error (location_t loc, tree r)
auto_diagnostic_group d;
tree type = TREE_TYPE (r);
if (DECL_NAME (r) == heap_uninit_identifier
- || DECL_NAME (r) == heap_identifier)
+ || DECL_NAME (r) == heap_identifier
+ || DECL_NAME (r) == heap_vec_uninit_identifier
+ || DECL_NAME (r) == heap_vec_identifier)
{
error_at (loc, "the content of uninitialized storage is not usable "
"in a constant expression");
@@ -6351,8 +6412,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
&& TREE_TYPE (op) == ptr_type_node
&& TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR
&& VAR_P (TREE_OPERAND (TREE_OPERAND (op, 0), 0))
- && DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0),
- 0)) == heap_uninit_identifier)
+ && (DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0),
+ 0)) == heap_uninit_identifier
+ || DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0),
+ 0)) == heap_vec_uninit_identifier))
{
tree var = TREE_OPERAND (TREE_OPERAND (op, 0), 0);
tree var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
@@ -6366,7 +6429,9 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
elt_type = TREE_TYPE (TREE_TYPE (fld2));
cookie_size = TYPE_SIZE_UNIT (TREE_TYPE (fld1));
}
- DECL_NAME (var) = heap_identifier;
+ DECL_NAME (var)
+ = (DECL_NAME (var) == heap_uninit_identifier
+ ? heap_identifier : heap_vec_identifier);
TREE_TYPE (var)
= build_new_constexpr_heap_type (elt_type, cookie_size,
var_size);
@@ -6403,9 +6468,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;
@@ -6637,6 +6702,8 @@ find_heap_var_refs (tree *tp, int *walk_subtrees, void */*data*/)
if (VAR_P (*tp)
&& (DECL_NAME (*tp) == heap_uninit_identifier
|| DECL_NAME (*tp) == heap_identifier
+ || DECL_NAME (*tp) == heap_vec_uninit_identifier
+ || DECL_NAME (*tp) == heap_vec_identifier
|| DECL_NAME (*tp) == heap_deleted_identifier))
return *tp;
@@ -6858,6 +6925,10 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
non_constant_p = true;
}
+ if (non_constant_p)
+ /* If we saw something bad, go back to our argument. The wrapping below is
+ only for the cases of TREE_CONSTANT argument or overflow. */
+ r = t;
if (!non_constant_p && overflow_p)
non_constant_p = true;
@@ -6874,12 +6945,6 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
return r;
else if (non_constant_p && TREE_CONSTANT (r))
{
- /* If __builtin_is_constant_evaluated () was evaluated to true
- and the result is not a valid constant expression, we need to
- punt. */
- if (manifestly_const_eval)
- return cxx_eval_outermost_constant_expr (t, true, strict,
- false, false, object);
/* This isn't actually constant, so unset TREE_CONSTANT.
Don't clear TREE_CONSTANT on ADDR_EXPR, as the middle-end requires
it to be set if it is invariant address, even when it is not
@@ -7071,15 +7136,13 @@ clear_cv_cache (void)
cv_cache->empty ();
}
-/* Dispose of the whole CV_CACHE, FOLD_CACHE, and satisfaction caches. */
+/* Dispose of the whole CV_CACHE and FOLD_CACHE. */
void
-clear_cv_and_fold_caches (bool sat /*= true*/)
+clear_cv_and_fold_caches ()
{
clear_cv_cache ();
clear_fold_cache ();
- if (sat)
- clear_satisfaction_cache ();
}
/* Internal function handling expressions in templates for
@@ -7651,6 +7714,11 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
}
return false;
}
+ /* Treat __PRETTY_FUNCTION__ inside a template function as
+ potentially-constant. */
+ else if (DECL_PRETTY_FUNCTION_P (t)
+ && DECL_VALUE_EXPR (t) == error_mark_node)
+ return true;
return RECUR (DECL_VALUE_EXPR (t), rval);
}
if (want_rval
@@ -8186,13 +8254,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;
@@ -8321,7 +8387,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:
{
@@ -8347,7 +8413,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
return false;
default:
- if (objc_is_property_ref (t))
+ if (objc_non_constant_expr_p (t))
return false;
sorry ("unexpected AST of kind %s", get_tree_code_name (TREE_CODE (t)));
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 050b55c..8691281 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -616,7 +616,8 @@ struct norm_info : subst_info
norm_info (tree in_decl, tsubst_flags_t complain)
: subst_info (tf_warning_or_error | complain, in_decl),
- context (make_context (in_decl))
+ context (make_context (in_decl)),
+ orig_decl (in_decl)
{}
bool generate_diagnostics() const
@@ -647,6 +648,12 @@ struct norm_info : subst_info
for that check. */
tree context;
+
+ /* The declaration whose constraints we're normalizing. The targets
+ of the parameter mapping of each atom will be in terms of the
+ template parameters of ORIG_DECL. */
+
+ tree orig_decl = NULL_TREE;
};
static tree normalize_expression (tree, tree, norm_info);
@@ -686,7 +693,8 @@ normalize_concept_check (tree check, tree args, norm_info info)
}
/* Substitute through the arguments of the concept check. */
- targs = tsubst_template_args (targs, args, info.complain, info.in_decl);
+ if (args)
+ targs = tsubst_template_args (targs, args, info.complain, info.in_decl);
if (targs == error_mark_node)
return error_mark_node;
@@ -709,6 +717,10 @@ normalize_concept_check (tree check, tree args, norm_info info)
return normalize_expression (def, subst, info);
}
+/* Used by normalize_atom to cache ATOMIC_CONSTRs. */
+
+static GTY((deletable)) hash_table<atom_hasher> *atom_cache;
+
/* The normal form of an atom depends on the expression. The normal
form of a function call to a function concept is a check constraint
for that concept. The normal form of a reference to a variable
@@ -728,7 +740,41 @@ normalize_atom (tree t, tree args, norm_info info)
/* Build a new info object for the atom. */
tree ci = build_tree_list (t, info.context);
- return build1 (ATOMIC_CONSTR, ci, map);
+ tree atom = build1 (ATOMIC_CONSTR, ci, map);
+ if (!info.generate_diagnostics ())
+ {
+ /* Cache the ATOMIC_CONSTRs that we return, so that sat_hasher::equal
+ later can cheaply compare two atoms using just pointer equality. */
+ if (!atom_cache)
+ atom_cache = hash_table<atom_hasher>::create_ggc (31);
+ tree *slot = atom_cache->find_slot (atom, INSERT);
+ if (*slot)
+ return *slot;
+
+ /* Find all template parameters used in the targets of the parameter
+ mapping, and store a list of them in the TREE_TYPE of the mapping.
+ This list will be used by sat_hasher to determine the subset of
+ supplied template arguments that the satisfaction value of the atom
+ depends on. */
+ if (map)
+ {
+ tree targets = make_tree_vec (list_length (map));
+ int i = 0;
+ for (tree node = map; node; node = TREE_CHAIN (node))
+ {
+ tree target = TREE_PURPOSE (node);
+ TREE_VEC_ELT (targets, i++) = target;
+ }
+ tree ctx_parms = (info.orig_decl
+ ? DECL_TEMPLATE_PARMS (info.orig_decl)
+ : current_template_parms);
+ tree target_parms = find_template_parameters (targets, ctx_parms);
+ TREE_TYPE (map) = target_parms;
+ }
+
+ *slot = atom;
+ }
+ return atom;
}
/* Returns the normal form of an expression. */
@@ -758,20 +804,18 @@ normalize_expression (tree t, tree args, norm_info info)
static GTY((deletable)) hash_map<tree,tree> *normalized_map;
static tree
-get_normalized_constraints (tree t, tree args, norm_info info)
+get_normalized_constraints (tree t, norm_info info)
{
auto_timevar time (TV_CONSTRAINT_NORM);
- return normalize_expression (t, args, info);
+ return normalize_expression (t, NULL_TREE, info);
}
/* Returns the normalized constraints from a constraint-info object
- or NULL_TREE if the constraints are null. ARGS provide the initial
- arguments for normalization and IN_DECL provides the declaration
- to which the constraints belong. */
+ or NULL_TREE if the constraints are null. IN_DECL provides the
+ declaration to which the constraints belong. */
static tree
-get_normalized_constraints_from_info (tree ci, tree args, tree in_decl,
- bool diag = false)
+get_normalized_constraints_from_info (tree ci, tree in_decl, bool diag = false)
{
if (ci == NULL_TREE)
return NULL_TREE;
@@ -779,8 +823,7 @@ get_normalized_constraints_from_info (tree ci, tree args, tree in_decl,
/* Substitution errors during normalization are fatal. */
++processing_template_decl;
norm_info info (in_decl, diag ? tf_norm : tf_none);
- tree t = get_normalized_constraints (CI_ASSOCIATED_CONSTRAINTS (ci),
- args, info);
+ tree t = get_normalized_constraints (CI_ASSOCIATED_CONSTRAINTS (ci), info);
--processing_template_decl;
return t;
@@ -840,11 +883,17 @@ get_normalized_constraints_from_decl (tree d, bool diag = false)
if (tree *p = hash_map_safe_get (normalized_map, tmpl))
return *p;
- push_nested_class_guard pncs (DECL_CONTEXT (d));
+ tree norm = NULL_TREE;
+ if (tree ci = get_constraints (decl))
+ {
+ push_nested_class_guard pncs (DECL_CONTEXT (d));
+
+ temp_override<tree> ovr (current_function_decl);
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ current_function_decl = decl;
- tree args = generic_targs_for (tmpl);
- tree ci = get_constraints (decl);
- tree norm = get_normalized_constraints_from_info (ci, args, tmpl, diag);
+ norm = get_normalized_constraints_from_info (ci, tmpl, diag);
+ }
if (!diag)
hash_map_safe_put<hm_ggc> (normalized_map, tmpl, norm);
@@ -865,11 +914,10 @@ normalize_concept_definition (tree tmpl, bool diag = false)
if (OVL_P (tmpl))
tmpl = OVL_FIRST (tmpl);
gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
- tree args = generic_targs_for (tmpl);
tree def = get_concept_definition (DECL_TEMPLATE_RESULT (tmpl));
++processing_template_decl;
norm_info info (tmpl, diag ? tf_norm : tf_none);
- tree norm = get_normalized_constraints (def, args, info);
+ tree norm = get_normalized_constraints (def, info);
--processing_template_decl;
if (!diag)
@@ -894,42 +942,20 @@ normalize_nontemplate_requirements (tree decl, bool diag = false)
return get_normalized_constraints_from_decl (decl, diag);
}
-/* Normalize an EXPR as a constraint using ARGS. */
+/* Normalize an EXPR as a constraint. */
static tree
-normalize_constraint_expression (tree expr, tree args, bool diag = false)
+normalize_constraint_expression (tree expr, bool diag)
{
if (!expr || expr == error_mark_node)
return expr;
++processing_template_decl;
norm_info info (diag ? tf_norm : tf_none);
- tree norm = get_normalized_constraints (expr, args, info);
+ tree norm = get_normalized_constraints (expr, info);
--processing_template_decl;
return norm;
}
-/* Normalize an EXPR as a constraint. */
-
-static tree
-normalize_constraint_expression (tree expr, bool diag = false)
-{
- if (!expr || expr == error_mark_node)
- return expr;
-
- /* For concept checks, use the supplied template arguments as those used
- for normalization. Otherwise, there are no template arguments. */
- tree args;
- if (concept_check_p (expr))
- {
- tree id = unpack_concept_check (expr);
- args = TREE_OPERAND (id, 1);
- }
- else
- args = NULL_TREE;
-
- return normalize_constraint_expression (expr, args, diag);
-}
-
/* 17.4.1.2p2. Two constraints are identical if they are formed
from the same expression and the targets of the parameter mapping
are equivalent. */
@@ -1201,7 +1227,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 +1243,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))
@@ -2273,6 +2304,16 @@ tsubst_parameter_mapping (tree map, tree args, subst_info info)
new_arg = tsubst_template_arg (arg, args, complain, in_decl);
if (TYPE_P (new_arg))
new_arg = canonicalize_type_argument (new_arg, complain);
+ if (TREE_CODE (new_arg) == TYPE_ARGUMENT_PACK)
+ {
+ tree pack_args = ARGUMENT_PACK_ARGS (new_arg);
+ for (int i = 0; i < TREE_VEC_LENGTH (pack_args); i++)
+ {
+ tree& pack_arg = TREE_VEC_ELT (pack_args, i);
+ if (TYPE_P (pack_arg))
+ pack_arg = canonicalize_type_argument (pack_arg, complain);
+ }
+ }
}
if (new_arg == error_mark_node)
return error_mark_node;
@@ -2305,15 +2346,68 @@ struct sat_hasher : ggc_ptr_hash<sat_entry>
{
static hashval_t hash (sat_entry *e)
{
- hashval_t value = hash_atomic_constraint (e->constr);
- return iterative_hash_template_arg (e->args, value);
+ if (ATOMIC_CONSTR_MAP_INSTANTIATED_P (e->constr))
+ {
+ /* Atoms with instantiated mappings are built during satisfaction.
+ They live only inside the sat_cache, and we build one to query
+ the cache with each time we instantiate a mapping. */
+ gcc_assert (!e->args);
+ return hash_atomic_constraint (e->constr);
+ }
+
+ /* Atoms with uninstantiated mappings are built during normalization.
+ Since normalize_atom caches the atoms it returns, we can assume
+ pointer-based identity for fast hashing and comparison. Even if this
+ assumption is violated, that's okay, we'll just get a cache miss. */
+ hashval_t value = htab_hash_pointer (e->constr);
+
+ if (tree map = ATOMIC_CONSTR_MAP (e->constr))
+ /* Only the parameters that are used in the targets of the mapping
+ affect the satisfaction value of the atom. So we consider only
+ the arguments for these parameters, and ignore the rest. */
+ for (tree target_parms = TREE_TYPE (map);
+ target_parms;
+ target_parms = TREE_CHAIN (target_parms))
+ {
+ int level, index;
+ tree parm = TREE_VALUE (target_parms);
+ template_parm_level_and_index (parm, &level, &index);
+ tree arg = TMPL_ARG (e->args, level, index);
+ value = iterative_hash_template_arg (arg, value);
+ }
+ return value;
}
static bool equal (sat_entry *e1, sat_entry *e2)
{
- if (!atomic_constraints_identical_p (e1->constr, e2->constr))
+ if (ATOMIC_CONSTR_MAP_INSTANTIATED_P (e1->constr)
+ != ATOMIC_CONSTR_MAP_INSTANTIATED_P (e2->constr))
return false;
- return template_args_equal (e1->args, e2->args);
+
+ /* See sat_hasher::hash. */
+ if (ATOMIC_CONSTR_MAP_INSTANTIATED_P (e1->constr))
+ {
+ gcc_assert (!e1->args && !e2->args);
+ return atomic_constraints_identical_p (e1->constr, e2->constr);
+ }
+
+ if (e1->constr != e2->constr)
+ return false;
+
+ if (tree map = ATOMIC_CONSTR_MAP (e1->constr))
+ for (tree target_parms = TREE_TYPE (map);
+ target_parms;
+ target_parms = TREE_CHAIN (target_parms))
+ {
+ int level, index;
+ tree parm = TREE_VALUE (target_parms);
+ template_parm_level_and_index (parm, &level, &index);
+ tree arg1 = TMPL_ARG (e1->args, level, index);
+ tree arg2 = TMPL_ARG (e2->args, level, index);
+ if (!template_args_equal (arg1, arg2))
+ return false;
+ }
+ return true;
}
};
@@ -2348,15 +2442,6 @@ save_satisfaction (tree constr, tree args, tree result)
*slot = entry;
}
-void
-clear_satisfaction_cache ()
-{
- if (sat_cache)
- sat_cache->empty ();
- if (decl_satisfied_cache)
- decl_satisfied_cache->empty ();
-}
-
/* A tool to help manage satisfaction caching in satisfy_constraint_r.
Note the cache is only used when not diagnosing errors. */
@@ -2613,6 +2698,18 @@ satisfy_atom (tree t, tree args, subst_info info)
return cache.save (boolean_false_node);
}
+ /* Now build a new atom using the instantiated mapping. We use
+ this atom as a second key to the satisfaction cache, and we
+ also pass it to diagnose_atomic_constraint so that diagnostics
+ which refer to the atom display the instantiated mapping. */
+ t = copy_node (t);
+ ATOMIC_CONSTR_MAP (t) = map;
+ gcc_assert (!ATOMIC_CONSTR_MAP_INSTANTIATED_P (t));
+ ATOMIC_CONSTR_MAP_INSTANTIATED_P (t) = true;
+ satisfaction_cache inst_cache (t, /*args=*/NULL_TREE, info.complain);
+ if (tree r = inst_cache.get ())
+ return cache.save (r);
+
/* Rebuild the argument vector from the parameter mapping. */
args = get_mapped_args (map);
@@ -2625,19 +2722,19 @@ satisfy_atom (tree t, tree args, subst_info info)
is not satisfied. Replay the substitution. */
if (info.noisy ())
tsubst_expr (expr, args, info.complain, info.in_decl, false);
- return cache.save (boolean_false_node);
+ return cache.save (inst_cache.save (boolean_false_node));
}
/* [17.4.1.2] ... lvalue-to-rvalue conversion is performed as necessary,
and EXPR shall be a constant expression of type bool. */
result = force_rvalue (result, info.complain);
if (result == error_mark_node)
- return cache.save (error_mark_node);
+ return cache.save (inst_cache.save (error_mark_node));
if (!same_type_p (TREE_TYPE (result), boolean_type_node))
{
if (info.noisy ())
diagnose_atomic_constraint (t, map, result, info);
- return cache.save (error_mark_node);
+ return cache.save (inst_cache.save (error_mark_node));
}
/* Compute the value of the constraint. */
@@ -2654,7 +2751,7 @@ satisfy_atom (tree t, tree args, subst_info info)
if (result == boolean_false_node && info.noisy ())
diagnose_atomic_constraint (t, map, result, info);
- return cache.save (result);
+ return cache.save (inst_cache.save (result));
}
/* Determine if the normalized constraint T is satisfied.
@@ -2992,9 +3089,7 @@ finish_compound_requirement (location_t loc, tree expr, tree type, bool noexcept
tree
finish_nested_requirement (location_t loc, tree expr)
{
- /* Currently open template headers have dummy arg vectors, so don't
- pass into normalization. */
- tree norm = normalize_constraint_expression (expr, NULL_TREE, false);
+ tree norm = normalize_constraint_expression (expr, false);
/* Build the constraint, saving its normalization as its type. */
tree r = build1 (NESTED_REQ, norm, expr);
@@ -3099,25 +3194,25 @@ subsumes_constraints (tree a, tree b)
return subsumes (a, b);
}
-/* Returns true when the constraints in CI (with arguments
- ARGS) strictly subsume the associated constraints of TMPL. */
+/* Returns true when the constraints in CI strictly subsume
+ the associated constraints of TMPL. */
bool
-strictly_subsumes (tree ci, tree args, tree tmpl)
+strictly_subsumes (tree ci, tree tmpl)
{
- tree n1 = get_normalized_constraints_from_info (ci, args, NULL_TREE);
+ tree n1 = get_normalized_constraints_from_info (ci, NULL_TREE);
tree n2 = get_normalized_constraints_from_decl (tmpl);
return subsumes (n1, n2) && !subsumes (n2, n1);
}
-/* REturns true when the constraints in CI (with arguments ARGS) subsume
- the associated constraints of TMPL. */
+/* Returns true when the constraints in CI subsume the
+ associated constraints of TMPL. */
bool
-weakly_subsumes (tree ci, tree args, tree tmpl)
+weakly_subsumes (tree ci, tree tmpl)
{
- tree n1 = get_normalized_constraints_from_info (ci, args, NULL_TREE);
+ tree n1 = get_normalized_constraints_from_info (ci, NULL_TREE);
tree n2 = get_normalized_constraints_from_decl (tmpl);
return subsumes (n1, n2);
@@ -3496,14 +3591,11 @@ diagnose_atomic_constraint (tree t, tree map, tree result, subst_info info)
diagnose_requires_expr (expr, map, info.in_decl);
break;
default:
- tree a = copy_node (t);
- ATOMIC_CONSTR_MAP (a) = map;
if (!same_type_p (TREE_TYPE (result), boolean_type_node))
error_at (loc, "constraint %qE has type %qT, not %<bool%>",
- a, TREE_TYPE (result));
+ t, TREE_TYPE (result));
else
- inform (loc, "the expression %qE evaluated to %<false%>", a);
- ggc_free (a);
+ inform (loc, "the expression %qE evaluated to %<false%>", t);
}
}
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index ba81345..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);
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 44c9d24..064a44c 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -680,22 +680,6 @@ is_invisiref_parm (const_tree t)
&& DECL_BY_REFERENCE (t));
}
-/* Return true if the uid in both int tree maps are equal. */
-
-bool
-cxx_int_tree_map_hasher::equal (cxx_int_tree_map *a, cxx_int_tree_map *b)
-{
- return (a->uid == b->uid);
-}
-
-/* Hash a UID in a cxx_int_tree_map. */
-
-unsigned int
-cxx_int_tree_map_hasher::hash (cxx_int_tree_map *item)
-{
- return item->uid;
-}
-
/* A stable comparison routine for use with splay trees and DECLs. */
static int
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index e1397b7..a38bb0a 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -366,7 +366,8 @@ names_builtin_p (const char *name)
tree id = get_identifier (name);
if (tree binding = get_global_binding (id))
{
- if (TREE_CODE (binding) == FUNCTION_DECL && DECL_IS_BUILTIN (binding))
+ if (TREE_CODE (binding) == FUNCTION_DECL
+ && DECL_IS_UNDECLARED_BUILTIN (binding))
return true;
/* Handle the case when an overload for a built-in name exists. */
@@ -376,7 +377,7 @@ names_builtin_p (const char *name)
for (ovl_iterator it (binding); it; ++it)
{
tree decl = *it;
- if (DECL_IS_BUILTIN (decl))
+ if (DECL_IS_UNDECLARED_BUILTIN (decl))
return true;
}
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 4672561..b98d47a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -125,6 +125,7 @@ enum cp_tree_index
CPTI_CLASS_TYPE,
CPTI_UNKNOWN_TYPE,
CPTI_INIT_LIST_TYPE,
+ CPTI_EXPLICIT_VOID_LIST,
CPTI_VTBL_TYPE,
CPTI_VTBL_PTR_TYPE,
CPTI_STD,
@@ -178,6 +179,8 @@ enum cp_tree_index
CPTI_HEAP_UNINIT_IDENTIFIER,
CPTI_HEAP_IDENTIFIER,
CPTI_HEAP_DELETED_IDENTIFIER,
+ CPTI_HEAP_VEC_UNINIT_IDENTIFIER,
+ CPTI_HEAP_VEC_IDENTIFIER,
CPTI_LANG_NAME_C,
CPTI_LANG_NAME_CPLUSPLUS,
@@ -230,6 +233,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
#define class_type_node cp_global_trees[CPTI_CLASS_TYPE]
#define unknown_type_node cp_global_trees[CPTI_UNKNOWN_TYPE]
#define init_list_type_node cp_global_trees[CPTI_INIT_LIST_TYPE]
+#define explicit_void_list_node cp_global_trees[CPTI_EXPLICIT_VOID_LIST]
#define vtbl_type_node cp_global_trees[CPTI_VTBL_TYPE]
#define vtbl_ptr_type_node cp_global_trees[CPTI_VTBL_PTR_TYPE]
#define std_node cp_global_trees[CPTI_STD]
@@ -322,6 +326,8 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
#define heap_uninit_identifier cp_global_trees[CPTI_HEAP_UNINIT_IDENTIFIER]
#define heap_identifier cp_global_trees[CPTI_HEAP_IDENTIFIER]
#define heap_deleted_identifier cp_global_trees[CPTI_HEAP_DELETED_IDENTIFIER]
+#define heap_vec_uninit_identifier cp_global_trees[CPTI_HEAP_VEC_UNINIT_IDENTIFIER]
+#define heap_vec_identifier cp_global_trees[CPTI_HEAP_VEC_IDENTIFIER]
#define lang_name_c cp_global_trees[CPTI_LANG_NAME_C]
#define lang_name_cplusplus cp_global_trees[CPTI_LANG_NAME_CPLUSPLUS]
@@ -409,6 +415,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
ATTR_IS_DEPENDENT (in the TREE_LIST for an attribute)
ABI_TAG_IMPLICIT (in the TREE_LIST for the argument of abi_tag)
LAMBDA_CAPTURE_EXPLICIT_P (in a TREE_LIST in LAMBDA_EXPR_CAPTURE_LIST)
+ PARENTHESIZED_LIST_P (in the TREE_LIST for a parameter-declaration-list)
CONSTRUCTOR_IS_DIRECT_INIT (in CONSTRUCTOR)
LAMBDA_EXPR_CAPTURES_THIS_P (in LAMBDA_EXPR)
DECLTYPE_FOR_LAMBDA_CAPTURE (in DECLTYPE_TYPE)
@@ -431,6 +438,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
REINTERPRET_CAST_P (in NOP_EXPR)
ALIGNOF_EXPR_STD_P (in ALIGNOF_EXPR)
OVL_DEDUP_P (in OVERLOAD)
+ ATOMIC_CONSTR_MAP_INSTANTIATED_P (in ATOMIC_CONSTR)
1: IDENTIFIER_KIND_BIT_1 (in IDENTIFIER_NODE)
TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE.
@@ -480,7 +488,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
DECL_TINFO_P (in VAR_DECL)
FUNCTION_REF_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE)
OVL_LOOKUP_P (in OVERLOAD)
- LOOKUP_FOUND_P (in RECORD_TYPE, UNION_TYPE, NAMESPACE_DECL)
+ LOOKUP_FOUND_P (in RECORD_TYPE, UNION_TYPE, ENUMERAL_TYPE, NAMESPACE_DECL)
5: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
FUNCTION_RVALUE_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE)
CALL_EXPR_REVERSE_ARGS (in CALL_EXPR, AGGR_INIT_EXPR)
@@ -738,9 +746,10 @@ typedef struct ptrmem_cst * ptrmem_cst_t;
&& flag_hosted)
/* Lookup walker marking. */
-#define LOOKUP_SEEN_P(NODE) TREE_VISITED(NODE)
+#define LOOKUP_SEEN_P(NODE) TREE_VISITED (NODE)
#define LOOKUP_FOUND_P(NODE) \
- TREE_LANG_FLAG_4 (TREE_CHECK3(NODE,RECORD_TYPE,UNION_TYPE,NAMESPACE_DECL))
+ TREE_LANG_FLAG_4 (TREE_CHECK4 (NODE,RECORD_TYPE,UNION_TYPE,ENUMERAL_TYPE,\
+ NAMESPACE_DECL))
/* These two accessors should only be used by OVL manipulators.
Other users should use iterators and convenience functions. */
@@ -1323,7 +1332,9 @@ enum cp_trait_kind
CPTK_IS_UNION,
CPTK_UNDERLYING_TYPE,
CPTK_IS_ASSIGNABLE,
- CPTK_IS_CONSTRUCTIBLE
+ CPTK_IS_CONSTRUCTIBLE,
+ CPTK_IS_NOTHROW_ASSIGNABLE,
+ CPTK_IS_NOTHROW_CONSTRUCTIBLE
};
/* The types that we are processing. */
@@ -1587,6 +1598,12 @@ check_constraint_info (tree t)
#define ATOMIC_CONSTR_MAP(NODE) \
TREE_OPERAND (TREE_CHECK (NODE, ATOMIC_CONSTR), 0)
+/* Whether the parameter mapping of this atomic constraint
+ is already instantiated with concrete template arguments.
+ Used only in satisfy_atom and in the satisfaction cache. */
+#define ATOMIC_CONSTR_MAP_INSTANTIATED_P(NODE) \
+ TREE_LANG_FLAG_0 (ATOMIC_CONSTR_CHECK (NODE))
+
/* The expression of an atomic constraint. */
#define ATOMIC_CONSTR_EXPR(NODE) \
CONSTR_EXPR (ATOMIC_CONSTR_CHECK (NODE))
@@ -1861,19 +1878,6 @@ public:
#define cp_noexcept_operand scope_chain->noexcept_operand
-/* A list of private types mentioned, for deferred access checking. */
-
-struct GTY((for_user)) cxx_int_tree_map {
- unsigned int uid;
- tree to;
-};
-
-struct cxx_int_tree_map_hasher : ggc_ptr_hash<cxx_int_tree_map>
-{
- static hashval_t hash (cxx_int_tree_map *);
- static bool equal (cxx_int_tree_map *, cxx_int_tree_map *);
-};
-
struct named_label_entry; /* Defined in decl.c. */
struct named_label_hash : ggc_remove <named_label_entry *>
@@ -2217,7 +2221,6 @@ struct GTY(()) lang_type {
tree vtables;
tree typeinfo_var;
vec<tree, va_gc> *vbases;
- binding_table nested_udts;
tree as_base;
vec<tree, va_gc> *pure_virtuals;
tree friend_classes;
@@ -2370,12 +2373,6 @@ struct GTY(()) lang_type {
#define CLASSTYPE_DESTRUCTOR(NODE) \
(get_class_binding_direct (NODE, dtor_identifier))
-/* A dictionary of the nested user-defined-types (class-types, or enums)
- found within this class. This table includes nested member class
- templates. */
-#define CLASSTYPE_NESTED_UTDS(NODE) \
- (LANG_TYPE_CLASS_CHECK (NODE)->nested_udts)
-
/* Nonzero if NODE has a primary base class, i.e., a base class with
which it shares the virtual function table pointer. */
#define CLASSTYPE_HAS_PRIMARY_BASE_P(NODE) \
@@ -2736,12 +2733,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 +3087,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 +3293,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)
@@ -3390,6 +3393,10 @@ struct GTY(()) lang_decl {
was inherited from a template parameter, not explicitly indicated. */
#define ABI_TAG_IMPLICIT(NODE) TREE_LANG_FLAG_0 (TREE_LIST_CHECK (NODE))
+/* In a TREE_LIST for a parameter-declaration-list, indicates that all the
+ parameters in the list have declarators enclosed in (). */
+#define PARENTHESIZED_LIST_P(NODE) TREE_LANG_FLAG_0 (TREE_LIST_CHECK (NODE))
+
/* Non zero if this is a using decl for a dependent scope. */
#define DECL_DEPENDENT_P(NODE) DECL_LANG_FLAG_0 (USING_DECL_CHECK (NODE))
@@ -4039,11 +4046,6 @@ 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))
-/* 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) \
@@ -6046,6 +6048,7 @@ struct cp_declarator {
tree late_return_type;
/* The trailing requires-clause, if any. */
tree requires_clause;
+ location_t parens_loc;
} function;
/* For arrays. */
struct {
@@ -6746,6 +6749,7 @@ extern void use_thunk (tree, bool);
extern bool trivial_fn_p (tree);
extern tree forward_parm (tree);
extern bool is_trivially_xible (enum tree_code, tree, tree);
+extern bool is_nothrow_xible (enum tree_code, tree, tree);
extern bool is_xible (enum tree_code, tree, tree);
extern tree get_defaulted_eh_spec (tree, tsubst_flags_t = tf_warning_or_error);
extern bool maybe_explain_implicit_delete (tree);
@@ -7367,6 +7371,7 @@ extern const char *cxx_printable_name_translate (tree, int);
extern tree canonical_eh_spec (tree);
extern tree build_cp_fntype_variant (tree, cp_ref_qualifier, tree, bool);
extern tree build_exception_variant (tree, tree);
+extern void fixup_deferred_exception_variants (tree, tree);
extern tree bind_template_template_parm (tree, tree);
extern tree array_type_nelts_total (tree);
extern tree array_type_nelts_top (tree);
@@ -7825,15 +7830,14 @@ extern tree evaluate_concept_check (tree, tsubst_flags_t);
extern tree satisfy_constraint_expression (tree);
extern bool constraints_satisfied_p (tree);
extern bool constraints_satisfied_p (tree, tree);
-extern void clear_satisfaction_cache ();
extern bool* lookup_subsumption_result (tree, tree);
extern bool save_subsumption_result (tree, tree, bool);
extern tree find_template_parameters (tree, tree);
extern bool equivalent_constraints (tree, tree);
extern bool equivalently_constrained (tree, tree);
extern bool subsumes_constraints (tree, tree);
-extern bool strictly_subsumes (tree, tree, tree);
-extern bool weakly_subsumes (tree, tree, tree);
+extern bool strictly_subsumes (tree, tree);
+extern bool weakly_subsumes (tree, tree);
extern int more_constrained (tree, tree);
extern bool at_least_as_constrained (tree, tree);
extern bool constraints_equivalent_p (tree, tree);
@@ -7842,6 +7846,21 @@ extern hashval_t iterative_hash_constraint (tree, hashval_t);
extern hashval_t hash_atomic_constraint (tree);
extern void diagnose_constraints (location_t, tree, tree);
+/* A structural hasher for ATOMIC_CONSTRs. */
+
+struct atom_hasher : default_hash_traits<tree>
+{
+ static hashval_t hash (tree t)
+ {
+ return hash_atomic_constraint (t);
+ }
+
+ static bool equal (tree t1, tree t2)
+ {
+ return atomic_constraints_identical_p (t1, t2);
+ }
+};
+
/* in logic.cc */
extern bool subsumes (tree, tree);
@@ -7895,7 +7914,7 @@ extern bool var_in_maybe_constexpr_fn (tree);
extern void explain_invalid_constexpr_fn (tree);
extern vec<tree> cx_error_context (void);
extern tree fold_sizeof_expr (tree);
-extern void clear_cv_and_fold_caches (bool = true);
+extern void clear_cv_and_fold_caches (void);
extern tree unshare_constructor (tree CXX_MEM_STAT_INFO);
/* An RAII sentinel used to restrict constexpr evaluation so that it
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index c9e7b1f..bcd7c5a 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -1568,12 +1568,13 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
&& warn_unused_value
&& !TREE_NO_WARNING (expr)
&& !processing_template_decl
- && !cp_unevaluated_operand)
+ && !cp_unevaluated_operand
+ && (complain & tf_warning))
{
/* The middle end does not warn about expressions that have
been explicitly cast to void, so we must do so here. */
- if (!TREE_SIDE_EFFECTS (expr)) {
- if (complain & tf_warning)
+ if (!TREE_SIDE_EFFECTS (expr))
+ {
switch (implicit)
{
case ICV_SECOND_OF_COND:
@@ -1605,14 +1606,10 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
default:
gcc_unreachable ();
}
- }
+ }
else
{
- tree e;
- enum tree_code code;
- enum tree_code_class tclass;
-
- e = expr;
+ tree e = expr;
/* We might like to warn about (say) "(int) f()", as the
cast has no effect, but the compiler itself will
generate implicit conversions under some
@@ -1626,21 +1623,14 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
while (TREE_CODE (e) == NOP_EXPR)
e = TREE_OPERAND (e, 0);
- code = TREE_CODE (e);
- tclass = TREE_CODE_CLASS (code);
- if ((tclass == tcc_comparison
- || tclass == tcc_unary
- || (tclass == tcc_binary
- && !(code == MODIFY_EXPR
- || code == INIT_EXPR
- || code == PREDECREMENT_EXPR
- || code == PREINCREMENT_EXPR
- || code == POSTDECREMENT_EXPR
- || code == POSTINCREMENT_EXPR))
- || code == VEC_PERM_EXPR
- || code == VEC_COND_EXPR)
- && (complain & tf_warning))
- warning_at (loc, OPT_Wunused_value, "value computed is not used");
+ enum tree_code code = TREE_CODE (e);
+ enum tree_code_class tclass = TREE_CODE_CLASS (code);
+ if (tclass == tcc_comparison
+ || tclass == tcc_unary
+ || tclass == tcc_binary
+ || code == VEC_PERM_EXPR
+ || code == VEC_COND_EXPR)
+ warn_if_unused_value (e, loc);
}
}
expr = build1 (CONVERT_EXPR, void_type_node, expr);
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index 8bea79b..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:
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 0fe74b2..6264884 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -138,7 +138,7 @@ static location_t smallest_type_location (const cp_decl_specifier_seq*);
tree cp_global_trees[CPTI_MAX];
/* A list of objects which have constructors or destructors
- which reside in the global scope. The decl is stored in
+ which reside in namespace scope. The decl is stored in
the TREE_VALUE slot and the initializer is stored
in the TREE_PURPOSE slot. */
tree static_aggregates;
@@ -1002,7 +1002,7 @@ decls_match (tree newdecl, tree olddecl, bool record_versions /* = true */)
/* A new declaration doesn't match a built-in one unless it
is also extern "C". */
- if (DECL_IS_BUILTIN (olddecl)
+ if (DECL_IS_UNDECLARED_BUILTIN (olddecl)
&& DECL_EXTERN_C_P (olddecl) && !DECL_EXTERN_C_P (newdecl))
return 0;
@@ -1205,7 +1205,7 @@ check_redeclaration_exception_specification (tree new_decl,
all declarations, including the definition and an explicit
specialization, of that function shall have an
exception-specification with the same set of type-ids. */
- if (! DECL_IS_BUILTIN (old_decl)
+ if (! DECL_IS_UNDECLARED_BUILTIN (old_decl)
&& !comp_except_specs (new_exceptions, old_exceptions, ce_normal))
{
const char *const msg
@@ -1340,18 +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_p)
+check_no_redeclaration_friend_default_args (tree olddecl, tree newdecl)
{
- if (!olddecl_hidden_p && !DECL_FRIEND_P (newdecl))
+ if (!DECL_UNIQUE_FRIEND_P (olddecl) && !DECL_UNIQUE_FRIEND_P (newdecl))
return;
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_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),
@@ -1444,8 +1443,7 @@ tree
duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
{
unsigned olddecl_uid = DECL_UID (olddecl);
- int olddecl_friend = 0, types_match = 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);
@@ -1467,7 +1465,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
/* Check for redeclaration and other discrepancies. */
if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_UNDECLARED_BUILTIN_P (olddecl))
+ && DECL_IS_UNDECLARED_BUILTIN (olddecl))
{
if (TREE_CODE (newdecl) != FUNCTION_DECL)
{
@@ -1519,7 +1517,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
/* A new declaration doesn't match a built-in one unless it
is also extern "C". */
- gcc_assert (DECL_IS_BUILTIN (olddecl));
+ gcc_assert (DECL_IS_UNDECLARED_BUILTIN (olddecl));
gcc_assert (DECL_EXTERN_C_P (olddecl));
if (!DECL_EXTERN_C_P (newdecl))
return NULL_TREE;
@@ -1629,11 +1627,11 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
/* Replace the old RTL to avoid problems with inlining. */
COPY_DECL_RTL (newdecl, olddecl);
}
- /* Even if the types match, prefer the new declarations type for
- built-ins which have not been explicitly declared, for
- exception lists, etc... */
- else if (DECL_IS_BUILTIN (olddecl))
+ else
{
+ /* Even if the types match, prefer the new declarations type
+ for built-ins which have not been explicitly declared,
+ for exception lists, etc... */
tree type = TREE_TYPE (newdecl);
tree attribs = (*targetm.merge_type_attributes)
(TREE_TYPE (olddecl), type);
@@ -1778,7 +1776,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
newdecl);
inform (olddecl_loc,
"previous declaration %q#D", olddecl);
- return NULL_TREE;
+ return error_mark_node;
}
/* For function versions, params and types match, but they
are not ambiguous. */
@@ -1987,8 +1985,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
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, was_hidden);
+ check_no_redeclaration_friend_default_args (olddecl, newdecl);
}
}
}
@@ -2005,6 +2002,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
|| 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;
@@ -2135,12 +2135,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
else
DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
- if (DECL_DECLARES_FUNCTION_P (olddecl))
- {
- olddecl_friend = DECL_FRIEND_P (STRIP_TEMPLATE (olddecl));
- olddecl_hidden_friend = olddecl_friend && was_hidden;
- }
-
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
tree old_result = DECL_TEMPLATE_RESULT (olddecl);
@@ -2167,8 +2161,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
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);
@@ -2366,6 +2362,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
&& !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
{
@@ -2472,22 +2471,27 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
}
- DECL_TEMPLATE_INSTANTIATED (newdecl)
- |= DECL_TEMPLATE_INSTANTIATED (olddecl);
- DECL_ODR_USED (newdecl) |= DECL_ODR_USED (olddecl);
- /* If the OLDDECL is an instantiation and/or specialization,
- then the NEWDECL must be too. But, it may not yet be marked
- as such if the caller has created NEWDECL, but has not yet
- figured out that it is a redeclaration. */
- if (!DECL_USE_TEMPLATE (newdecl))
- DECL_USE_TEMPLATE (newdecl) = DECL_USE_TEMPLATE (olddecl);
+ if (TREE_CODE (newdecl) != TYPE_DECL)
+ {
+ DECL_TEMPLATE_INSTANTIATED (newdecl)
+ |= DECL_TEMPLATE_INSTANTIATED (olddecl);
+ DECL_ODR_USED (newdecl) |= DECL_ODR_USED (olddecl);
+
+ /* If the OLDDECL is an instantiation and/or specialization,
+ then the NEWDECL must be too. But, it may not yet be marked
+ as such if the caller has created NEWDECL, but has not yet
+ figured out that it is a redeclaration. */
+ if (!DECL_USE_TEMPLATE (newdecl))
+ DECL_USE_TEMPLATE (newdecl) = DECL_USE_TEMPLATE (olddecl);
+
+ DECL_INITIALIZED_IN_CLASS_P (newdecl)
+ |= DECL_INITIALIZED_IN_CLASS_P (olddecl);
+ }
/* Don't really know how much of the language-specific
values we should copy from old to new. */
DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
- DECL_INITIALIZED_IN_CLASS_P (newdecl)
- |= DECL_INITIALIZED_IN_CLASS_P (olddecl);
if (LANG_DECL_HAS_MIN (newdecl))
{
@@ -2647,19 +2651,20 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL)
{
enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl);
- switch (fncode)
+ if (builtin_decl_explicit_p (fncode))
{
- /* If a compatible prototype of these builtin functions
- is seen, assume the runtime implements it with the
- expected semantics. */
- case BUILT_IN_STPCPY:
- if (builtin_decl_explicit_p (fncode))
- set_builtin_decl_implicit_p (fncode, true);
- break;
- default:
- if (builtin_decl_explicit_p (fncode))
- set_builtin_decl_declared_p (fncode, true);
- break;
+ /* A compatible prototype of these builtin functions
+ is seen, assume the runtime implements it with
+ the expected semantics. */
+ switch (fncode)
+ {
+ case BUILT_IN_STPCPY:
+ set_builtin_decl_implicit_p (fncode, true);
+ break;
+ default:
+ set_builtin_decl_declared_p (fncode, true);
+ break;
+ }
}
copy_attributes_to_builtin (newdecl);
@@ -2885,8 +2890,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
}
DECL_UID (olddecl) = olddecl_uid;
- if (olddecl_friend)
- DECL_FRIEND_P (olddecl) = true;
/* NEWDECL contains the merged attribute lists.
Update OLDDECL to be the same. */
@@ -2918,6 +2921,16 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
snode->remove ();
}
+ if (TREE_CODE (olddecl) == FUNCTION_DECL)
+ {
+ tree clone;
+ FOR_EACH_CLONE (clone, olddecl)
+ {
+ DECL_ATTRIBUTES (clone) = DECL_ATTRIBUTES (olddecl);
+ DECL_PRESERVE_P (clone) |= DECL_PRESERVE_P (olddecl);
+ }
+ }
+
/* Remove the associated constraints for newdecl, if any, before
reclaiming memory. */
if (flag_concepts)
@@ -3062,7 +3075,7 @@ redeclaration_error_message (tree newdecl, tree olddecl)
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)
+ && 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,
@@ -3073,7 +3086,8 @@ redeclaration_error_message (tree newdecl, tree olddecl)
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)))
@@ -4247,6 +4261,8 @@ initialize_predefined_identifiers (void)
{"heap uninit", &heap_uninit_identifier, cik_normal},
{"heap ", &heap_identifier, cik_normal},
{"heap deleted", &heap_deleted_identifier, cik_normal},
+ {"heap [] uninit", &heap_vec_uninit_identifier, cik_normal},
+ {"heap []", &heap_vec_identifier, cik_normal},
{NULL, NULL, cik_normal}
};
@@ -4378,6 +4394,9 @@ cxx_init_decl_processing (void)
init_list_type_node = make_node (LANG_TYPE);
record_unknown_type (init_list_type_node, "init list");
+ /* Used when parsing to distinguish parameter-lists () and (void). */
+ explicit_void_list_node = build_void_list_node ();
+
{
/* Make sure we get a unique function type, so we can give
its pointer type a name. (This wins for gdb.) */
@@ -5452,20 +5471,17 @@ start_decl (const cp_declarator *declarator,
void
start_decl_1 (tree decl, bool initialized)
{
- tree type;
- bool complete_p;
- bool aggregate_definition_p;
-
- gcc_assert (!processing_template_decl);
+ gcc_checking_assert (!processing_template_decl);
if (error_operand_p (decl))
return;
- gcc_assert (VAR_P (decl));
+ gcc_checking_assert (VAR_P (decl));
- type = TREE_TYPE (decl);
- complete_p = COMPLETE_TYPE_P (type);
- aggregate_definition_p = MAYBE_CLASS_TYPE_P (type) && !DECL_EXTERNAL (decl);
+ tree type = TREE_TYPE (decl);
+ bool complete_p = COMPLETE_TYPE_P (type);
+ bool aggregate_definition_p
+ = MAYBE_CLASS_TYPE_P (type) && !DECL_EXTERNAL (decl);
/* If an explicit initializer is present, or if this is a definition
of an aggregate, then we need a complete type at this point.
@@ -5490,6 +5506,7 @@ start_decl_1 (tree decl, bool initialized)
: TCTX_STATIC_STORAGE);
verify_type_context (input_location, context, TREE_TYPE (decl));
}
+
if (initialized)
/* Is it valid for this decl to have an initializer at all? */
{
@@ -12039,8 +12056,17 @@ grokdeclarator (const cp_declarator *declarator,
&& inner_declarator->u.id.qualifying_scope
&& (MAYBE_CLASS_TYPE_P (type)
|| TREE_CODE (type) == ENUMERAL_TYPE)))
- warning_at (declarator->parenthesized, OPT_Wparentheses,
- "unnecessary parentheses in declaration of %qs", name);
+ {
+ if (warning_at (declarator->parenthesized, OPT_Wparentheses,
+ "unnecessary parentheses in declaration of %qs",
+ name))
+ {
+ gcc_rich_location iloc (declarator->parenthesized);
+ iloc.add_fixit_remove (get_start (declarator->parenthesized));
+ iloc.add_fixit_remove (get_finish (declarator->parenthesized));
+ inform (&iloc, "remove parentheses");
+ }
+ }
if (declarator->kind == cdk_id || declarator->kind == cdk_decomp)
break;
@@ -14024,7 +14050,7 @@ grokparms (tree parmlist, tree *parms)
tree init = TREE_PURPOSE (parm);
tree decl = TREE_VALUE (parm);
- if (parm == void_list_node)
+ if (parm == void_list_node || parm == explicit_void_list_node)
break;
if (! decl || TREE_TYPE (decl) == error_mark_node)
@@ -14174,6 +14200,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;
@@ -14247,6 +14277,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;
@@ -14854,7 +14888,6 @@ lookup_and_check_tag (enum tag_types tag_code, tree name,
else
decl = lookup_elaborated_type (name, how);
-
if (!decl)
/* We found nothing. */
return NULL_TREE;
@@ -14875,8 +14908,8 @@ lookup_and_check_tag (enum tag_types tag_code, tree name,
if (TREE_CODE (decl) != TYPE_DECL)
/* Found not-a-type. */
return NULL_TREE;
-
- /* Look for invalid nested type:
+
+ /* Look for invalid nested type:
class C {
class C {};
}; */
@@ -16110,36 +16143,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)
@@ -16206,7 +16224,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
by push_nested_class.) */
if (processing_template_decl)
{
- tree newdecl1 = push_template_decl (decl1, DECL_FRIEND_P (decl1));
+ tree newdecl1 = push_template_decl (decl1, doing_friend);
if (newdecl1 == error_mark_node)
{
if (ctype || DECL_STATIC_FUNCTION_P (decl1))
@@ -16222,7 +16240,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)
{
@@ -16312,7 +16330,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);
@@ -16329,7 +16347,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
@@ -16384,14 +16402,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. */;
@@ -17311,18 +17331,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, DECL_FRIEND_P (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 db3035d..1bc7b7e 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;
@@ -2894,9 +2894,8 @@ constrain_class_visibility (tree type)
/* Functions for adjusting the visibility of a tagged type and its nested
types and declarations when it gets a name for linkage purposes from a
typedef. */
-
-static void bt_reset_linkage_1 (binding_entry, void *);
-static void bt_reset_linkage_2 (binding_entry, void *);
+// FIXME: It is now a DR for such a class type to contain anything
+// other than C. So at minium most of this can probably be deleted.
/* First reset the visibility of all the types. */
@@ -2905,13 +2904,9 @@ reset_type_linkage_1 (tree type)
{
set_linkage_according_to_type (type, TYPE_MAIN_DECL (type));
if (CLASS_TYPE_P (type))
- binding_table_foreach (CLASSTYPE_NESTED_UTDS (type),
- bt_reset_linkage_1, NULL);
-}
-static void
-bt_reset_linkage_1 (binding_entry b, void */*data*/)
-{
- reset_type_linkage_1 (b->type);
+ for (tree member = TYPE_FIELDS (type); member; member = DECL_CHAIN (member))
+ if (DECL_IMPLICIT_TYPEDEF_P (member))
+ reset_type_linkage_1 (TREE_TYPE (member));
}
/* Then reset the visibility of any static data members or member
@@ -2930,9 +2925,10 @@ reset_decl_linkage (tree decl)
tentative_decl_linkage (decl);
}
-static void
-reset_type_linkage_2 (tree type)
+void
+reset_type_linkage (tree type)
{
+ reset_type_linkage_1 (type);
if (CLASS_TYPE_P (type))
{
if (tree vt = CLASSTYPE_VTABLES (type))
@@ -2955,24 +2951,12 @@ reset_type_linkage_2 (tree type)
tree mem = STRIP_TEMPLATE (m);
if (TREE_CODE (mem) == VAR_DECL || TREE_CODE (mem) == FUNCTION_DECL)
reset_decl_linkage (mem);
+ else if (DECL_IMPLICIT_TYPEDEF_P (mem))
+ reset_type_linkage (TREE_TYPE (mem));
}
- binding_table_foreach (CLASSTYPE_NESTED_UTDS (type),
- bt_reset_linkage_2, NULL);
}
}
-static void
-bt_reset_linkage_2 (binding_entry b, void */*data*/)
-{
- reset_type_linkage_2 (b->type);
-}
-void
-reset_type_linkage (tree type)
-{
- reset_type_linkage_1 (type);
- reset_type_linkage_2 (type);
-}
-
/* Set up our initial idea of what the linkage of DECL should be. */
void
@@ -4363,7 +4347,7 @@ collect_source_refs (tree namespc)
{
/* Iterate over names in this name space. */
for (tree t = NAMESPACE_LEVEL (namespc)->names; t; t = TREE_CHAIN (t))
- if (DECL_IS_BUILTIN (t))
+ if (DECL_IS_UNDECLARED_BUILTIN (t))
;
else if (TREE_CODE (t) == NAMESPACE_DECL && !DECL_NAMESPACE_ALIAS (t))
collect_source_refs (t);
@@ -5604,16 +5588,6 @@ mark_used (tree decl, tsubst_flags_t complain)
if (DECL_ODR_USED (decl))
return true;
- /* Normally, we can wait until instantiation-time to synthesize DECL.
- However, if DECL is a static data member initialized with a constant
- or a constexpr function, we need it right now because a reference to
- such a data member or a call to such function is not value-dependent.
- For a function that uses auto in the return type, we need to instantiate
- it to find out its type. For OpenMP user defined reductions, we need
- them instantiated for reduction clauses which inline them by hand
- directly. */
- maybe_instantiate_decl (decl);
-
if (flag_concepts && TREE_CODE (decl) == FUNCTION_DECL
&& !constraints_satisfied_p (decl))
{
@@ -5629,6 +5603,16 @@ mark_used (tree decl, tsubst_flags_t complain)
return false;
}
+ /* Normally, we can wait until instantiation-time to synthesize DECL.
+ However, if DECL is a static data member initialized with a constant
+ or a constexpr function, we need it right now because a reference to
+ such a data member or a call to such function is not value-dependent.
+ For a function that uses auto in the return type, we need to instantiate
+ it to find out its type. For OpenMP user defined reductions, we need
+ them instantiated for reduction clauses which inline them by hand
+ directly. */
+ maybe_instantiate_decl (decl);
+
if (processing_template_decl || in_template_function ())
return true;
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index cb1a410..0f6c76b 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -41,7 +41,6 @@ static tree do_allocate_exception (tree);
static tree wrap_cleanups_r (tree *, int *, void *);
static int complete_ptr_ref_or_void_ptr_p (tree, tree);
static bool is_admissible_throw_operand_or_catch_parameter (tree, bool);
-static int can_convert_eh (tree, tree);
/* Sets up all the global eh stuff that needs to be initialized at the
start of compilation. */
@@ -932,31 +931,34 @@ nothrow_libfn_p (const_tree fn)
/* Returns nonzero if an exception of type FROM will be caught by a
handler for type TO, as per [except.handle]. */
-static int
+static bool
can_convert_eh (tree to, tree from)
{
to = non_reference (to);
from = non_reference (from);
+ if (same_type_ignoring_top_level_qualifiers_p (to, from))
+ return true;
+
if (TYPE_PTR_P (to) && TYPE_PTR_P (from))
{
to = TREE_TYPE (to);
from = TREE_TYPE (from);
if (! at_least_as_qualified_p (to, from))
- return 0;
+ return false;
if (VOID_TYPE_P (to))
- return 1;
+ return true;
/* Else fall through. */
}
if (CLASS_TYPE_P (to) && CLASS_TYPE_P (from)
&& publicly_uniquely_derived_p (to, from))
- return 1;
+ return true;
- return 0;
+ return false;
}
/* Check whether any of the handlers in I are shadowed by another handler
@@ -975,11 +977,11 @@ check_handlers_1 (tree master, tree_stmt_iterator i)
tree handler = tsi_stmt (i);
if (TREE_TYPE (handler) && can_convert_eh (type, TREE_TYPE (handler)))
{
- warning_at (EXPR_LOCATION (handler), 0,
- "exception of type %qT will be caught",
- TREE_TYPE (handler));
- warning_at (EXPR_LOCATION (master), 0,
- " by earlier handler for %qT", type);
+ auto_diagnostic_group d;
+ if (warning_at (EXPR_LOCATION (handler), OPT_Wexceptions,
+ "exception of type %qT will be caught by earlier "
+ "handler", TREE_TYPE (handler)))
+ inform (EXPR_LOCATION (master), "for type %qT", type);
break;
}
}
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c
index 6a783a9..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",
@@ -581,17 +581,11 @@ 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);
@@ -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 1bddb655..ffb84ea 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2957,7 +2957,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
return error_mark_node;
}
- if (is_std_init_list (elt_type))
+ if (is_std_init_list (elt_type) && !cp_unevaluated_operand)
warning (OPT_Winit_list_lifetime,
"%<new%> of %<initializer_list%> does not "
"extend the lifetime of the underlying array");
diff --git a/gcc/cp/logic.cc b/gcc/cp/logic.cc
index 194b743..6701488 100644
--- a/gcc/cp/logic.cc
+++ b/gcc/cp/logic.cc
@@ -47,21 +47,6 @@ along with GCC; see the file COPYING3. If not see
#include "toplev.h"
#include "type-utils.h"
-/* Hash functions for atomic constrains. */
-
-struct constraint_hash : default_hash_traits<tree>
-{
- static hashval_t hash (tree t)
- {
- return hash_atomic_constraint (t);
- }
-
- static bool equal (tree t1, tree t2)
- {
- return atomic_constraints_identical_p (t1, t2);
- }
-};
-
/* A conjunctive or disjunctive clause.
Each clause maintains an iterator that refers to the current
@@ -219,7 +204,7 @@ struct clause
}
std::list<tree> m_terms; /* The list of terms. */
- hash_set<tree, false, constraint_hash> m_set; /* The set of atomic constraints. */
+ hash_set<tree, false, atom_hasher> m_set; /* The set of atomic constraints. */
iterator m_current; /* The current term. */
};
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 6e4c5f7..16e7635 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1924,15 +1924,26 @@ is_xible_helper (enum tree_code code, tree to, tree from, bool trivial)
bool
is_trivially_xible (enum tree_code code, tree to, tree from)
{
- tree expr;
- expr = is_xible_helper (code, to, from, /*trivial*/true);
-
+ tree expr = is_xible_helper (code, to, from, /*trivial*/true);
if (expr == NULL_TREE || expr == error_mark_node)
return false;
tree nt = cp_walk_tree_without_duplicates (&expr, check_nontriv, NULL);
return !nt;
}
+/* Returns true iff TO is nothrow assignable (if CODE is MODIFY_EXPR) or
+ constructible (otherwise) from FROM, which is a single type for
+ assignment or a list of types for construction. */
+
+bool
+is_nothrow_xible (enum tree_code code, tree to, tree from)
+{
+ tree expr = is_xible_helper (code, to, from, /*trivial*/false);
+ if (expr == NULL_TREE || expr == error_mark_node)
+ return false;
+ return expr_noexcept_p (expr, tf_none);
+}
+
/* Returns true iff TO is assignable (if CODE is MODIFY_EXPR) or
constructible (otherwise) from FROM, which is a single type for
assignment or a list of types for construction. */
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index e3f3712..410ec59 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -38,7 +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_with_scope (tree x, cp_binding_level *, bool hiding);
+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,
@@ -171,8 +171,13 @@ public:
public:
tree name; /* The identifier being looked for. */
+
+ /* Usually we just add things to the VALUE binding, but we record
+ (hidden) IMPLICIT_TYPEDEFs on the type binding, which is used for
+ using-decl resolution. */
tree value; /* A (possibly ambiguous) set of things found. */
tree type; /* A type that has been found. */
+
LOOK_want want; /* What kind of entity we want. */
bool deduping; /* Full deduping is needed because using declarations
@@ -263,14 +268,17 @@ private:
private:
void add_fns (tree);
+ private:
void adl_expr (tree);
void adl_type (tree);
void adl_template_arg (tree);
void adl_class (tree);
+ void adl_enum (tree);
void adl_bases (tree);
void adl_class_only (tree);
void adl_namespace (tree);
- void adl_namespace_only (tree);
+ void adl_class_fns (tree);
+ void adl_namespace_fns (tree);
public:
/* Search namespace + inlines + maybe usings as qualified lookup. */
@@ -433,8 +441,8 @@ name_lookup::add_overload (tree fns)
if (probe && TREE_CODE (probe) == OVERLOAD
&& OVL_DEDUP_P (probe))
{
- /* We're about to add something found by a using
- declaration, so need to engage deduping mode. */
+ /* We're about to add something found by multiple paths, so
+ need to engage deduping mode. */
lookup_mark (value, true);
deduping = true;
}
@@ -777,20 +785,56 @@ name_lookup::add_fns (tree fns)
add_overload (fns);
}
-/* Add functions of a namespace to the lookup structure. */
+/* Add the overloaded fns of SCOPE. */
void
-name_lookup::adl_namespace_only (tree scope)
+name_lookup::adl_namespace_fns (tree scope)
{
- mark_seen (scope);
+ if (tree *binding = find_namespace_slot (scope, name))
+ {
+ tree val = *binding;
+ add_fns (ovl_skip_hidden (MAYBE_STAT_DECL (val)));
+ }
+}
- /* Look down into inline namespaces. */
- if (vec<tree, va_gc> *inlinees = DECL_NAMESPACE_INLINEES (scope))
- for (unsigned ix = inlinees->length (); ix--;)
- adl_namespace_only ((*inlinees)[ix]);
+/* Add the hidden friends of SCOPE. */
+
+void
+name_lookup::adl_class_fns (tree type)
+{
+ /* Add friends. */
+ for (tree list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type));
+ list; list = TREE_CHAIN (list))
+ if (name == FRIEND_NAME (list))
+ {
+ tree context = NULL_TREE; /* Lazily computed. */
+ for (tree friends = FRIEND_DECLS (list); friends;
+ friends = TREE_CHAIN (friends))
+ {
+ tree fn = TREE_VALUE (friends);
- if (tree fns = find_namespace_value (scope, name))
- add_fns (ovl_skip_hidden (fns));
+ /* Only interested in global functions with potentially hidden
+ (i.e. unqualified) declarations. */
+ if (!context)
+ context = decl_namespace_context (type);
+ if (CP_DECL_CONTEXT (fn) != context)
+ continue;
+
+ if (!deduping)
+ {
+ lookup_mark (value, true);
+ deduping = true;
+ }
+
+ /* Template specializations are never found by name lookup.
+ (Templates themselves can be found, but not template
+ specializations.) */
+ if (TREE_CODE (fn) == FUNCTION_DECL && DECL_USE_TEMPLATE (fn))
+ continue;
+
+ add_fns (fn);
+ }
+ }
}
/* Find the containing non-inlined namespace, add it and all its
@@ -799,14 +843,17 @@ name_lookup::adl_namespace_only (tree scope)
void
name_lookup::adl_namespace (tree scope)
{
- if (seen_p (scope))
+ if (see_and_mark (scope))
return;
- /* Find the containing non-inline namespace. */
- while (DECL_NAMESPACE_INLINE_P (scope))
- scope = CP_DECL_CONTEXT (scope);
+ /* Look down into inline namespaces. */
+ if (vec<tree, va_gc> *inlinees = DECL_NAMESPACE_INLINEES (scope))
+ for (unsigned ix = inlinees->length (); ix--;)
+ adl_namespace ((*inlinees)[ix]);
- adl_namespace_only (scope);
+ if (DECL_NAMESPACE_INLINE_P (scope))
+ /* Mark parent. */
+ adl_namespace (CP_DECL_CONTEXT (scope));
}
/* Adds the class and its friends to the lookup structure. */
@@ -826,31 +873,6 @@ name_lookup::adl_class_only (tree type)
tree context = decl_namespace_context (type);
adl_namespace (context);
-
- complete_type (type);
-
- /* Add friends. */
- for (tree list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list;
- list = TREE_CHAIN (list))
- if (name == FRIEND_NAME (list))
- for (tree friends = FRIEND_DECLS (list); friends;
- friends = TREE_CHAIN (friends))
- {
- tree fn = TREE_VALUE (friends);
-
- /* Only interested in global functions with potentially hidden
- (i.e. unqualified) declarations. */
- if (CP_DECL_CONTEXT (fn) != context)
- continue;
-
- /* Template specializations are never found by name lookup.
- (Templates themselves can be found, but not template
- specializations.) */
- if (TREE_CODE (fn) == FUNCTION_DECL && DECL_USE_TEMPLATE (fn))
- continue;
-
- add_fns (fn);
- }
}
/* Adds the class and its bases to the lookup structure.
@@ -873,7 +895,7 @@ name_lookup::adl_bases (tree type)
}
/* Adds everything associated with a class argument type to the lookup
- structure. Returns true on error.
+ structure.
If T is a class type (including unions), its associated classes are: the
class itself; the class of which it is a member, if any; and its direct
@@ -897,11 +919,13 @@ name_lookup::adl_class (tree type)
return;
type = TYPE_MAIN_VARIANT (type);
+
/* We don't set found here because we have to have set seen first,
which is done in the adl_bases walk. */
if (found_p (type))
return;
+ complete_type (type);
adl_bases (type);
mark_found (type);
@@ -919,6 +943,19 @@ name_lookup::adl_class (tree type)
}
void
+name_lookup::adl_enum (tree type)
+{
+ type = TYPE_MAIN_VARIANT (type);
+ if (see_and_mark (type))
+ return;
+
+ if (TYPE_CLASS_SCOPE_P (type))
+ adl_class_only (TYPE_CONTEXT (type));
+ else
+ adl_namespace (decl_namespace_context (type));
+}
+
+void
name_lookup::adl_expr (tree expr)
{
if (!expr)
@@ -1003,9 +1040,7 @@ name_lookup::adl_type (tree type)
return;
case ENUMERAL_TYPE:
- if (TYPE_CLASS_SCOPE_P (type))
- adl_class_only (TYPE_CONTEXT (type));
- adl_namespace (decl_namespace_context (type));
+ adl_enum (type);
return;
case LANG_TYPE:
@@ -1074,10 +1109,9 @@ name_lookup::adl_template_arg (tree arg)
tree
name_lookup::search_adl (tree fns, vec<tree, va_gc> *args)
{
- deduping = true;
- lookup_mark (fns, true);
- value = fns;
-
+ gcc_checking_assert (!vec_safe_length (scopes));
+
+ /* Gather each associated entity onto the lookup's scope list. */
unsigned ix;
tree arg;
@@ -1089,7 +1123,27 @@ name_lookup::search_adl (tree fns, vec<tree, va_gc> *args)
else
adl_expr (arg);
- fns = value;
+ if (vec_safe_length (scopes))
+ {
+ /* Now do the lookups. */
+ if (fns)
+ {
+ deduping = true;
+ lookup_mark (fns, true);
+ }
+ value = fns;
+
+ for (unsigned ix = scopes->length (); ix--;)
+ {
+ tree scope = (*scopes)[ix];
+ if (TREE_CODE (scope) == NAMESPACE_DECL)
+ adl_namespace_fns (scope);
+ else if (RECORD_OR_UNION_TYPE_P (scope))
+ adl_class_fns (scope);
+ }
+
+ fns = value;
+ }
return fns;
}
@@ -1738,16 +1792,6 @@ insert_late_enum_def_bindings (tree klass, tree enumtype)
}
}
-/* Compute the chain index of a binding_entry given the HASH value of its
- name and the total COUNT of chains. COUNT is assumed to be a power
- of 2. */
-
-#define ENTRY_INDEX(HASH, COUNT) (((HASH) >> 3) & ((COUNT) - 1))
-
-/* A free list of "binding_entry"s awaiting for re-use. */
-
-static GTY((deletable)) binding_entry free_binding_entry = NULL;
-
/* The binding oracle; see cp-tree.h. */
cp_binding_oracle_function *cp_binding_oracle;
@@ -1770,180 +1814,6 @@ query_oracle (tree name)
cp_binding_oracle (CP_ORACLE_IDENTIFIER, name);
}
-/* Create a binding_entry object for (NAME, TYPE). */
-
-static inline binding_entry
-binding_entry_make (tree name, tree type)
-{
- binding_entry entry;
-
- if (free_binding_entry)
- {
- entry = free_binding_entry;
- free_binding_entry = entry->chain;
- }
- else
- entry = ggc_alloc<binding_entry_s> ();
-
- entry->name = name;
- entry->type = type;
- entry->chain = NULL;
-
- return entry;
-}
-
-/* Put ENTRY back on the free list. */
-#if 0
-static inline void
-binding_entry_free (binding_entry entry)
-{
- entry->name = NULL;
- entry->type = NULL;
- entry->chain = free_binding_entry;
- free_binding_entry = entry;
-}
-#endif
-
-/* The datatype used to implement the mapping from names to types at
- a given scope. */
-struct GTY(()) binding_table_s {
- /* Array of chains of "binding_entry"s */
- binding_entry * GTY((length ("%h.chain_count"))) chain;
-
- /* The number of chains in this table. This is the length of the
- member "chain" considered as an array. */
- size_t chain_count;
-
- /* Number of "binding_entry"s in this table. */
- size_t entry_count;
-};
-
-/* Construct TABLE with an initial CHAIN_COUNT. */
-
-static inline void
-binding_table_construct (binding_table table, size_t chain_count)
-{
- table->chain_count = chain_count;
- table->entry_count = 0;
- table->chain = ggc_cleared_vec_alloc<binding_entry> (table->chain_count);
-}
-
-/* Make TABLE's entries ready for reuse. */
-#if 0
-static void
-binding_table_free (binding_table table)
-{
- size_t i;
- size_t count;
-
- if (table == NULL)
- return;
-
- for (i = 0, count = table->chain_count; i < count; ++i)
- {
- binding_entry temp = table->chain[i];
- while (temp != NULL)
- {
- binding_entry entry = temp;
- temp = entry->chain;
- binding_entry_free (entry);
- }
- table->chain[i] = NULL;
- }
- table->entry_count = 0;
-}
-#endif
-
-/* Allocate a table with CHAIN_COUNT, assumed to be a power of two. */
-
-static inline binding_table
-binding_table_new (size_t chain_count)
-{
- binding_table table = ggc_alloc<binding_table_s> ();
- table->chain = NULL;
- binding_table_construct (table, chain_count);
- return table;
-}
-
-/* Expand TABLE to twice its current chain_count. */
-
-static void
-binding_table_expand (binding_table table)
-{
- const size_t old_chain_count = table->chain_count;
- const size_t old_entry_count = table->entry_count;
- const size_t new_chain_count = 2 * old_chain_count;
- binding_entry *old_chains = table->chain;
- size_t i;
-
- binding_table_construct (table, new_chain_count);
- for (i = 0; i < old_chain_count; ++i)
- {
- binding_entry entry = old_chains[i];
- for (; entry != NULL; entry = old_chains[i])
- {
- const unsigned int hash = IDENTIFIER_HASH_VALUE (entry->name);
- const size_t j = ENTRY_INDEX (hash, new_chain_count);
-
- old_chains[i] = entry->chain;
- entry->chain = table->chain[j];
- table->chain[j] = entry;
- }
- }
- table->entry_count = old_entry_count;
-}
-
-/* Insert a binding for NAME to TYPE into TABLE. */
-
-static void
-binding_table_insert (binding_table table, tree name, tree type)
-{
- const unsigned int hash = IDENTIFIER_HASH_VALUE (name);
- const size_t i = ENTRY_INDEX (hash, table->chain_count);
- binding_entry entry = binding_entry_make (name, type);
-
- entry->chain = table->chain[i];
- table->chain[i] = entry;
- ++table->entry_count;
-
- if (3 * table->chain_count < 5 * table->entry_count)
- binding_table_expand (table);
-}
-
-/* Return the binding_entry, if any, that maps NAME. */
-
-binding_entry
-binding_table_find (binding_table table, tree name)
-{
- const unsigned int hash = IDENTIFIER_HASH_VALUE (name);
- binding_entry entry = table->chain[ENTRY_INDEX (hash, table->chain_count)];
-
- while (entry != NULL && entry->name != name)
- entry = entry->chain;
-
- return entry;
-}
-
-/* Apply PROC -- with DATA -- to all entries in TABLE. */
-
-void
-binding_table_foreach (binding_table table, bt_foreach_proc proc, void *data)
-{
- size_t chain_count;
- size_t i;
-
- if (!table)
- return;
-
- chain_count = table->chain_count;
- for (i = 0; i < chain_count; ++i)
- {
- binding_entry entry = table->chain[i];
- for (; entry != NULL; entry = entry->chain)
- proc (entry, data);
- }
-}
-
#ifndef ENABLE_SCOPE_CHECKING
# define ENABLE_SCOPE_CHECKING 0
#else
@@ -2130,7 +2000,7 @@ anticipated_builtin_p (tree ovl)
{
return (TREE_CODE (ovl) == OVERLOAD
&& OVL_HIDDEN_P (ovl)
- && DECL_UNDECLARED_BUILTIN_P (OVL_FUNCTION (ovl)));
+ && DECL_IS_UNDECLARED_BUILTIN (OVL_FUNCTION (ovl)));
}
/* BINDING records an existing declaration for a name in the current scope.
@@ -2969,14 +2839,61 @@ push_local_extern_decl_alias (tree decl)
{
/* No existing namespace-scope decl. Make one. */
alias = copy_decl (decl);
+ if (TREE_CODE (alias) == FUNCTION_DECL)
+ {
+ /* 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);
- alias = do_pushdecl_with_scope (alias, NAMESPACE_LEVEL (ns),
- /* hiding= */true);
+ push_nested_namespace (ns);
+ alias = do_pushdecl (alias, /* hiding= */true);
+ pop_nested_namespace (ns);
}
}
@@ -3645,7 +3562,7 @@ print_binding_level (cp_binding_level* lvl)
continue;
if (no_print_builtins
&& (TREE_CODE (t) == TYPE_DECL)
- && DECL_IS_BUILTIN (t))
+ && DECL_IS_UNDECLARED_BUILTIN (t))
continue;
/* Function decls tend to have longer names. */
@@ -3848,10 +3765,17 @@ 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 hiding = false)
@@ -3956,7 +3880,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_UNDECLARED_BUILTIN_P (old_fn))
+ else if (old.hidden_p () && DECL_IS_UNDECLARED_BUILTIN (old_fn))
continue; /* This is an anticipated builtin. */
else if (!matching_fn_p (new_fn, old_fn))
continue; /* Parameters do not match. */
@@ -6015,7 +5939,14 @@ lookup_qualified_name (tree scope, tree name, LOOK_want want, bool complain)
name_lookup lookup (name, want);
if (qualified_namespace_lookup (scope, &lookup))
- t = lookup.value;
+ {
+ t = lookup.value;
+
+ /* If we have a known type overload, pull it out. This can happen
+ for using decls. */
+ if (TREE_CODE (t) == OVERLOAD && TREE_TYPE (t) != unknown_type_node)
+ t = OVL_FUNCTION (t);
+ }
}
else if (cxx_dialect != cxx98 && TREE_CODE (scope) == ENUMERAL_TYPE)
t = lookup_enumerator (scope, name);
@@ -6645,8 +6576,9 @@ lookup_name_1 (tree name, LOOK_where where, LOOK_want want)
found:;
- /* If we have a single function from a using decl, pull it out. */
- if (val && TREE_CODE (val) == OVERLOAD && !really_overloaded_fn (val))
+ /* If we have a known type overload, pull it out. This can happen
+ for both using decls and unhidden functions. */
+ if (val && TREE_CODE (val) == OVERLOAD && TREE_TYPE (val) != unknown_type_node)
val = OVL_FUNCTION (val);
return val;
@@ -6711,8 +6643,6 @@ lookup_elaborated_type_1 (tree name, TAG_how how)
typedef struct C {} C;
correctly. */
- tree found = NULL_TREE;
- bool reveal = false;
if (tree type = iter->type)
{
if (qualify_lookup (type, LOOK_want::TYPE)
@@ -6720,9 +6650,11 @@ lookup_elaborated_type_1 (tree name, TAG_how how)
|| LOCAL_BINDING_P (iter)
|| DECL_CONTEXT (type) == iter->scope->this_entity))
{
- found = type;
if (how != TAG_how::HIDDEN_FRIEND)
- reveal = HIDDEN_TYPE_BINDING_P (iter);
+ /* It is no longer a hidden binding. */
+ HIDDEN_TYPE_BINDING_P (iter) = false;
+
+ return type;
}
}
else
@@ -6731,32 +6663,12 @@ lookup_elaborated_type_1 (tree name, TAG_how how)
&& (how != TAG_how::CURRENT_ONLY
|| !INHERITED_VALUE_BINDING_P (iter)))
{
- found = iter->value;
- if (how != TAG_how::HIDDEN_FRIEND)
- reveal = !iter->type && HIDDEN_TYPE_BINDING_P (iter);
- }
- }
-
- if (found)
- {
- if (reveal)
- {
- /* It is no longer a hidden binding. */
- HIDDEN_TYPE_BINDING_P (iter) = false;
-
- /* Unanticipate the decl itself. */
- DECL_FRIEND_P (found) = false;
+ if (how != TAG_how::HIDDEN_FRIEND && !iter->type)
+ /* It is no longer a hidden binding. */
+ HIDDEN_TYPE_BINDING_P (iter) = false;
- gcc_checking_assert (TREE_CODE (found) != TEMPLATE_DECL);
-
- if (tree ti = TYPE_TEMPLATE_INFO (TREE_TYPE (found)))
- {
- tree tmpl = TI_TEMPLATE (ti);
- DECL_FRIEND_P (tmpl) = false;
- }
+ return iter->value;
}
-
- return found;
}
}
@@ -6773,61 +6685,31 @@ lookup_elaborated_type_1 (tree name, TAG_how how)
if (tree *slot = find_namespace_slot (ns, name))
{
/* If this is the kind of thing we're looking for, we're done. */
- tree found = NULL_TREE;
- bool reveal = false;
-
if (tree type = MAYBE_STAT_TYPE (*slot))
{
- found = type;
if (how != TAG_how::HIDDEN_FRIEND)
- {
- reveal = STAT_TYPE_HIDDEN_P (*slot);
- STAT_TYPE_HIDDEN_P (*slot) = false;
- }
+ /* 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))
{
- found = decl;
-
- if (how != TAG_how::HIDDEN_FRIEND && STAT_HACK_P (*slot))
+ if (how != TAG_how::HIDDEN_FRIEND && STAT_HACK_P (*slot)
+ && STAT_DECL_HIDDEN_P (*slot))
{
- reveal = STAT_DECL_HIDDEN_P (*slot);
- if (reveal)
- {
- if (STAT_TYPE (*slot))
- STAT_DECL_HIDDEN_P (*slot) = false;
- else
- /* There is no type, just remove the stat
- hack. */
- *slot = decl;
- }
+ if (STAT_TYPE (*slot))
+ STAT_DECL_HIDDEN_P (*slot) = false;
+ else
+ /* There is no type, just remove the stat
+ hack. */
+ *slot = decl;
}
- }
- }
- if (found)
- {
- if (reveal)
- {
- /* Reveal the previously hidden thing. */
- DECL_FRIEND_P (found) = false;
-
- if (TREE_CODE (found) == TEMPLATE_DECL)
- {
- tree res = DECL_TEMPLATE_RESULT (found);
- if (DECL_LANG_SPECIFIC (res))
- DECL_FRIEND_P (res) = false;
- }
- else if (tree ti = TYPE_TEMPLATE_INFO (TREE_TYPE (found)))
- {
- tree tmpl = TI_TEMPLATE (ti);
- DECL_FRIEND_P (tmpl) = false;
- }
+ return decl;
}
-
- return found;
}
}
@@ -6880,10 +6762,6 @@ maybe_process_template_type_declaration (tree type, int is_friend,
if (processing_template_decl)
{
- /* 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 (decl, is_friend);
if (decl == error_mark_node)
return error_mark_node;
@@ -6902,17 +6780,8 @@ maybe_process_template_type_declaration (tree type, int is_friend,
finish_member_declaration (CLASSTYPE_TI_TEMPLATE (type));
if (!COMPLETE_TYPE_P (current_class_type))
- {
- maybe_add_class_template_decl_list (current_class_type,
- type, /*friend_p=*/0);
- /* Put this UTD in the table of UTDs for the class. */
- if (CLASSTYPE_NESTED_UTDS (current_class_type) == NULL)
- CLASSTYPE_NESTED_UTDS (current_class_type) =
- binding_table_new (SCOPE_DEFAULT_HT_SIZE);
-
- binding_table_insert
- (CLASSTYPE_NESTED_UTDS (current_class_type), name, type);
- }
+ maybe_add_class_template_decl_list (current_class_type,
+ type, /*friend_p=*/0);
}
}
}
@@ -7009,18 +6878,8 @@ do_pushtag (tree name, tree type, TAG_how how)
tdef = create_implicit_typedef (name, type);
DECL_CONTEXT (tdef) = FROB_CONTEXT (context);
- bool is_friend = how == TAG_how::HIDDEN_FRIEND;
- if (is_friend)
- {
- // FIXME: can go away
- /* 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. */
- retrofit_lang_decl (tdef);
- DECL_FRIEND_P (tdef) = 1;
- }
-
- decl = maybe_process_template_type_declaration (type, is_friend, b);
+ decl = maybe_process_template_type_declaration
+ (type, how == TAG_how::HIDDEN_FRIEND, b);
if (decl == error_mark_node)
return decl;
@@ -7083,17 +6942,8 @@ do_pushtag (tree name, tree type, TAG_how how)
if (b->kind == sk_class
&& !COMPLETE_TYPE_P (current_class_type))
- {
- maybe_add_class_template_decl_list (current_class_type,
- type, /*friend_p=*/0);
-
- if (CLASSTYPE_NESTED_UTDS (current_class_type) == NULL)
- CLASSTYPE_NESTED_UTDS (current_class_type)
- = binding_table_new (SCOPE_DEFAULT_HT_SIZE);
-
- binding_table_insert
- (CLASSTYPE_NESTED_UTDS (current_class_type), name, type);
- }
+ maybe_add_class_template_decl_list (current_class_type,
+ type, /*friend_p=*/0);
decl = TYPE_NAME (type);
gcc_assert (TREE_CODE (decl) == TYPE_DECL);
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index d63ff10..6d18539 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -23,29 +23,6 @@ along with GCC; see the file COPYING3. If not see
#include "c-family/c-common.h"
-/* The type of dictionary used to map names to types declared at
- a given scope. */
-typedef struct binding_table_s *binding_table;
-typedef struct binding_entry_s *binding_entry;
-
-/* The type of a routine repeatedly called by binding_table_foreach. */
-typedef void (*bt_foreach_proc) (binding_entry, void *);
-
-struct GTY(()) binding_entry_s {
- binding_entry chain;
- tree name;
- tree type;
-};
-
-/* These macros indicate the initial chains count for binding_table. */
-#define SCOPE_DEFAULT_HT_SIZE (1 << 3)
-#define CLASS_SCOPE_HT_SIZE (1 << 3)
-#define NAMESPACE_ORDINARY_HT_SIZE (1 << 5)
-#define NAMESPACE_STD_HT_SIZE (1 << 8)
-#define GLOBAL_SCOPE_HT_SIZE (1 << 8)
-
-extern void binding_table_foreach (binding_table, bt_foreach_proc, void *);
-extern binding_entry binding_table_find (binding_table, tree);
/* The datatype used to implement C++ scope. */
struct cp_binding_level;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 592ce95..9c08c0e 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1438,7 +1438,8 @@ clear_decl_specs (cp_decl_specifier_seq *decl_specs)
VAR_DECLs or FUNCTION_DECLs) should do that directly. */
static cp_declarator *make_call_declarator
- (cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, cp_ref_qualifier, tree, tree, tree, tree);
+ (cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, cp_ref_qualifier,
+ tree, tree, tree, tree, location_t);
static cp_declarator *make_array_declarator
(cp_declarator *, tree);
static cp_declarator *make_pointer_declarator
@@ -1621,7 +1622,8 @@ make_call_declarator (cp_declarator *target,
tree tx_qualifier,
tree exception_specification,
tree late_return_type,
- tree requires_clause)
+ tree requires_clause,
+ location_t parens_loc)
{
cp_declarator *declarator;
@@ -1635,6 +1637,7 @@ make_call_declarator (cp_declarator *target,
declarator->u.function.exception_specification = exception_specification;
declarator->u.function.late_return_type = late_return_type;
declarator->u.function.requires_clause = requires_clause;
+ declarator->u.function.parens_loc = parens_loc;
if (target)
{
declarator->id_loc = target->id_loc;
@@ -5138,6 +5141,8 @@ cp_parser_fold_expression (cp_parser *parser, tree expr1)
// Left fold.
if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
{
+ if (expr1)
+ return error_mark_node;
cp_lexer_consume_token (parser->lexer);
int op = cp_parser_fold_operator (parser);
if (op == ERROR_MARK)
@@ -5637,6 +5642,8 @@ cp_parser_primary_expression (cp_parser *parser,
case RID_IS_UNION:
case RID_IS_ASSIGNABLE:
case RID_IS_CONSTRUCTIBLE:
+ case RID_IS_NOTHROW_ASSIGNABLE:
+ case RID_IS_NOTHROW_CONSTRUCTIBLE:
return cp_parser_trait_expr (parser, token->keyword);
// C++ concepts
@@ -10501,6 +10508,14 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
kind = CPTK_IS_CONSTRUCTIBLE;
variadic = true;
break;
+ case RID_IS_NOTHROW_ASSIGNABLE:
+ kind = CPTK_IS_NOTHROW_ASSIGNABLE;
+ binary = true;
+ break;
+ case RID_IS_NOTHROW_CONSTRUCTIBLE:
+ kind = CPTK_IS_NOTHROW_CONSTRUCTIBLE;
+ variadic = true;
+ break;
default:
gcc_unreachable ();
}
@@ -11234,7 +11249,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
tx_qual,
exception_spec,
return_type,
- trailing_requires_clause);
+ trailing_requires_clause,
+ UNKNOWN_LOCATION);
declarator->std_attributes = std_attrs;
fco = grokmethod (&return_type_specs,
@@ -13497,10 +13513,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);
@@ -16017,8 +16031,13 @@ cp_parser_template_declaration (cp_parser* parser, bool member_p)
{
/* Consume the `export' token. */
cp_lexer_consume_token (parser->lexer);
- /* Warn that we do not support `export'. */
- warning (0, "keyword %<export%> not implemented, and will be ignored");
+ /* Warn that this use of export is deprecated. */
+ if (cxx_dialect < cxx11)
+ warning (0, "keyword %<export%> not implemented, and will be ignored");
+ else if (cxx_dialect < cxx20)
+ warning (0, "keyword %<export%> is deprecated, and is ignored");
+ else
+ warning (0, "keyword %<export%> not implemented, and will be ignored");
}
cp_parser_template_declaration_after_export (parser, member_p);
@@ -17634,10 +17653,8 @@ cp_parser_explicit_instantiation (cp_parser* parser)
instantiation. */
if (declares_class_or_enum && cp_parser_declares_only_class_p (parser))
{
- tree type;
-
- type = check_tag_decl (&decl_specifiers,
- /*explicit_type_instantiation_p=*/true);
+ tree type = check_tag_decl (&decl_specifiers,
+ /*explicit_type_instantiation_p=*/true);
/* Turn access control back on for names used during
template instantiation. */
pop_deferring_access_checks ();
@@ -17741,7 +17758,6 @@ cp_parser_explicit_specialization (cp_parser* parser)
/* Give it C++ linkage to avoid confusing other parts of the
front end. */
push_lang_context (lang_name_cplusplus);
- need_lang_pop = true;
}
/* Let the front end know that we are beginning a specialization. */
@@ -20605,6 +20621,140 @@ strip_declarator_types (tree type, cp_declarator *declarator)
return type;
}
+/* Warn about the most vexing parse syntactic ambiguity, i.e., warn when
+ a construct looks like a variable definition but is actually a function
+ declaration. DECL_SPECIFIERS is the decl-specifier-seq and DECLARATOR
+ is the declarator for this function declaration. */
+
+static void
+warn_about_ambiguous_parse (const cp_decl_specifier_seq *decl_specifiers,
+ const cp_declarator *declarator)
+{
+ /* Only warn if we are declaring a function at block scope. */
+ if (!at_function_scope_p ())
+ return;
+
+ /* And only if there is no storage class specified. */
+ if (decl_specifiers->storage_class != sc_none
+ || decl_spec_seq_has_spec_p (decl_specifiers, ds_typedef))
+ return;
+
+ if (declarator->kind != cdk_function
+ || !declarator->declarator
+ || declarator->declarator->kind != cdk_id
+ || !identifier_p (get_unqualified_id
+ (const_cast<cp_declarator *>(declarator))))
+ return;
+
+ /* Don't warn when the whole declarator (not just the declarator-id!)
+ was parenthesized. That is, don't warn for int(n()) but do warn
+ for int(f)(). */
+ if (declarator->parenthesized != UNKNOWN_LOCATION)
+ return;
+
+ tree type;
+ if (decl_specifiers->type)
+ {
+ type = decl_specifiers->type;
+ if (TREE_CODE (type) == TYPE_DECL)
+ type = TREE_TYPE (type);
+
+ /* If the return type is void there is no ambiguity. */
+ if (same_type_p (type, void_type_node))
+ return;
+ }
+ else
+ {
+ /* Code like long f(); will have null ->type. If we have any
+ type-specifiers, pretend we've seen int. */
+ gcc_checking_assert (decl_specifiers->any_type_specifiers_p);
+ type = integer_type_node;
+ }
+
+ auto_diagnostic_group d;
+ location_t loc = declarator->u.function.parens_loc;
+ tree params = declarator->u.function.parameters;
+ const bool has_list_ctor_p = CLASS_TYPE_P (type) && TYPE_HAS_LIST_CTOR (type);
+
+ /* The T t() case. */
+ if (params == void_list_node)
+ {
+ if (warning_at (loc, OPT_Wvexing_parse,
+ "empty parentheses were disambiguated as a function "
+ "declaration"))
+ {
+ /* () means value-initialization (C++03 and up); {} (C++11 and up)
+ means value-initialization or aggregate-initialization, nothing
+ means default-initialization. We can only suggest removing the
+ parentheses/adding {} if T has a default constructor. */
+ if (!CLASS_TYPE_P (type) || TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
+ {
+ gcc_rich_location iloc (loc);
+ iloc.add_fixit_remove ();
+ inform (&iloc, "remove parentheses to default-initialize "
+ "a variable");
+ if (cxx_dialect >= cxx11 && !has_list_ctor_p)
+ {
+ if (CP_AGGREGATE_TYPE_P (type))
+ inform (loc, "or replace parentheses with braces to "
+ "aggregate-initialize a variable");
+ else
+ inform (loc, "or replace parentheses with braces to "
+ "value-initialize a variable");
+ }
+ }
+ }
+ return;
+ }
+
+ /* If we had (...) or the parameter-list wasn't parenthesized,
+ we're done. */
+ if (params == NULL_TREE || !PARENTHESIZED_LIST_P (params))
+ return;
+
+ /* The T t(X()) case. */
+ if (list_length (params) == 2)
+ {
+ if (warning_at (loc, OPT_Wvexing_parse,
+ "parentheses were disambiguated as a function "
+ "declaration"))
+ {
+ gcc_rich_location iloc (loc);
+ /* {}-initialization means that we can use an initializer-list
+ constructor if no default constructor is available, so don't
+ suggest using {} for classes that have an initializer_list
+ constructor. */
+ if (cxx_dialect >= cxx11 && !has_list_ctor_p)
+ {
+ iloc.add_fixit_replace (get_start (loc), "{");
+ iloc.add_fixit_replace (get_finish (loc), "}");
+ inform (&iloc, "replace parentheses with braces to declare a "
+ "variable");
+ }
+ else
+ {
+ iloc.add_fixit_insert_after (get_start (loc), "(");
+ iloc.add_fixit_insert_before (get_finish (loc), ")");
+ inform (&iloc, "add parentheses to declare a variable");
+ }
+ }
+ }
+ /* The T t(X(), X()) case. */
+ else if (warning_at (loc, OPT_Wvexing_parse,
+ "parentheses were disambiguated as a function "
+ "declaration"))
+ {
+ gcc_rich_location iloc (loc);
+ if (cxx_dialect >= cxx11 && !has_list_ctor_p)
+ {
+ iloc.add_fixit_replace (get_start (loc), "{");
+ iloc.add_fixit_replace (get_finish (loc), "}");
+ inform (&iloc, "replace parentheses with braces to declare a "
+ "variable");
+ }
+ }
+}
+
/* Declarators [gram.dcl.decl] */
/* Parse an init-declarator.
@@ -20782,6 +20932,7 @@ cp_parser_init_declarator (cp_parser* parser,
{
/* Handle C++17 deduction guides. */
if (!decl_specifiers->type
+ && !decl_specifiers->any_type_specifiers_p
&& ctor_dtor_or_conv_p <= 0
&& cxx_dialect >= cxx17)
{
@@ -20799,6 +20950,9 @@ cp_parser_init_declarator (cp_parser* parser,
}
}
+ if (!member_p && !cp_parser_error_occurred (parser))
+ warn_about_ambiguous_parse (decl_specifiers, declarator);
+
/* Check to see if the token indicates the start of a
function-definition. */
if (cp_parser_token_starts_function_definition_p (token))
@@ -21193,7 +21347,7 @@ cp_parser_declarator (cp_parser* parser,
/* If a ptr-operator was found, then this declarator was not
parenthesized. */
if (parenthesized_p)
- *parenthesized_p = true;
+ *parenthesized_p = false;
/* The dependent declarator is optional if we are parsing an
abstract-declarator. */
if (dcl_kind != CP_PARSER_DECLARATOR_NAMED)
@@ -21340,6 +21494,7 @@ cp_parser_direct_declarator (cp_parser* parser,
cp_parser_parse_tentatively (parser);
/* Consume the `('. */
+ const location_t parens_start = token->location;
matching_parens parens;
parens.consume_open (parser);
if (first)
@@ -21359,6 +21514,8 @@ cp_parser_direct_declarator (cp_parser* parser,
/* Parse the parameter-declaration-clause. */
params
= cp_parser_parameter_declaration_clause (parser, flags);
+ const location_t parens_end
+ = cp_lexer_peek_token (parser->lexer)->location;
/* Consume the `)'. */
parens.require_close (parser);
@@ -21423,6 +21580,9 @@ cp_parser_direct_declarator (cp_parser* parser,
/* Parse the virt-specifier-seq. */
virt_specifiers = cp_parser_virt_specifier_seq_opt (parser);
+ location_t parens_loc = make_location (parens_start,
+ parens_start,
+ parens_end);
/* Create the function-declarator. */
declarator = make_call_declarator (declarator,
params,
@@ -21432,7 +21592,8 @@ cp_parser_direct_declarator (cp_parser* parser,
tx_qual,
exception_specification,
late_return,
- requires_clause);
+ requires_clause,
+ parens_loc);
declarator->std_attributes = attrs;
declarator->attributes = gnu_attrs;
/* Any subsequent parameter lists are to do with
@@ -21858,7 +22019,9 @@ cp_parser_direct_declarator (cp_parser* parser,
open_paren = NULL;
}
if (open_paren)
- declarator->parenthesized = open_paren->location;
+ declarator->parenthesized = make_location (open_paren->location,
+ open_paren->location,
+ close_paren->location);
}
/* If we entered a scope, we must exit it now. */
@@ -22409,9 +22572,20 @@ cp_parser_type_id_1 (cp_parser *parser, cp_parser_flags flags,
if (!cp_parser_parse_definitely (parser))
abstract_declarator = NULL;
+ bool auto_typeid_ok = false;
+ /* The concepts TS allows 'auto' as a type-id. */
+ if (flag_concepts_ts)
+ auto_typeid_ok = !parser->in_type_id_in_expr_p;
+ /* DR 625 prohibits use of auto as a template-argument. We allow 'auto'
+ outside the template-argument-list context here only for the sake of
+ diagnostic: grokdeclarator then can emit a better error message for
+ e.g. using T = auto. */
+ else if (flag_concepts)
+ auto_typeid_ok = (!parser->in_type_id_in_expr_p
+ && !parser->in_template_argument_list_p);
+
if (type_specifier_seq.type
- /* The concepts TS allows 'auto' as a type-id. */
- && (!flag_concepts || parser->in_type_id_in_expr_p)
+ && !auto_typeid_ok
/* None of the valid uses of 'auto' in C++14 involve the type-id
nonterminal, but it is valid in a trailing-return-type. */
&& !(cxx_dialect >= cxx14 && is_trailing_return))
@@ -22438,6 +22612,9 @@ cp_parser_type_id_1 (cp_parser *parser, cp_parser_flags flags,
inform (DECL_SOURCE_LOCATION (tmpl), "%qD declared here",
tmpl);
}
+ else if (parser->in_template_argument_list_p)
+ error_at (loc, "%qT not permitted in template argument",
+ auto_node);
else
error_at (loc, "invalid use of %qT", auto_node);
return error_mark_node;
@@ -22683,7 +22860,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser,
/* Consume the `void' token. */
cp_lexer_consume_token (parser->lexer);
/* There are no parameters. */
- return void_list_node;
+ return explicit_void_list_node;
}
/* Parse the parameter-declaration-list. */
@@ -22807,6 +22984,12 @@ cp_parser_parameter_declaration_list (cp_parser* parser, cp_parser_flags flags)
*tail = build_tree_list (parameter->default_argument, decl);
tail = &TREE_CHAIN (*tail);
+ /* If the parameters were parenthesized, it's the case of
+ T foo(X(x)) which looks like a variable definition but
+ is a function declaration. */
+ if (index == 1 || PARENTHESIZED_LIST_P (parameters))
+ PARENTHESIZED_LIST_P (parameters) = parenthesized_p;
+
/* Peek at the next token. */
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)
|| cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)
@@ -23786,13 +23969,10 @@ cp_parser_class_name (cp_parser *parser,
bool enum_ok)
{
tree decl;
- tree scope;
- bool typename_p;
- cp_token *token;
tree identifier = NULL_TREE;
/* All class-names start with an identifier. */
- token = cp_lexer_peek_token (parser->lexer);
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
if (token->type != CPP_NAME && token->type != CPP_TEMPLATE_ID)
{
cp_parser_error (parser, "expected class-name");
@@ -23808,14 +23988,16 @@ cp_parser_class_name (cp_parser *parser,
where we first want to look up A<T>::a in the class of the object
expression, as per [basic.lookup.classref]. */
- scope = parser->scope ? parser->scope : parser->context->object_type;
+ tree scope = parser->scope ? parser->scope : parser->context->object_type;
if (scope == error_mark_node)
return error_mark_node;
/* Any name names a type if we're following the `typename' keyword
in a qualified name where the enclosing scope is type-dependent. */
- typename_p = (typename_keyword_p && scope && TYPE_P (scope)
- && dependent_type_p (scope));
+ const bool typename_p = (typename_keyword_p
+ && parser->scope
+ && TYPE_P (parser->scope)
+ && dependent_type_p (parser->scope));
/* Handle the common case (an identifier, but not a template-id)
efficiently. */
if (token->type == CPP_NAME
@@ -24311,8 +24493,12 @@ cp_parser_class_specifier_1 (cp_parser* parser)
/* Now we can parse the noexcept-specifier. */
spec = cp_parser_late_noexcept_specifier (parser, spec);
- if (spec != error_mark_node)
- TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl), spec);
+ if (spec == error_mark_node)
+ spec = NULL_TREE;
+
+ /* Update the fn's type directly -- it might have escaped
+ beyond this decl :( */
+ fixup_deferred_exception_variants (TREE_TYPE (decl), spec);
/* Restore the state of local_variables_forbidden_p. */
parser->local_variables_forbidden_p = local_variables_forbidden_p;
@@ -25148,14 +25334,12 @@ cp_parser_member_declaration (cp_parser* parser)
}
else
{
- tree type;
-
/* See if this declaration is a friend. */
friend_p = cp_parser_friend_p (&decl_specifiers);
/* If there were decl-specifiers, check to see if there was
a class-declaration. */
- type = check_tag_decl (&decl_specifiers,
- /*explicit_type_instantiation_p=*/false);
+ tree type = check_tag_decl (&decl_specifiers,
+ /*explicit_type_instantiation_p=*/false);
/* Nested classes have already been added to the class, but
a `friend' needs to be explicitly registered. */
if (friend_p)
@@ -25350,6 +25534,9 @@ cp_parser_member_declaration (cp_parser* parser)
int ctor_dtor_or_conv_p;
bool static_p = (decl_specifiers.storage_class == sc_static);
cp_parser_flags flags = CP_PARSER_FLAGS_TYPENAME_OPTIONAL;
+ /* We can't delay parsing for friends,
+ alias-declarations, and typedefs, even though the
+ standard seems to require it. */
if (!friend_p
&& !decl_spec_seq_has_spec_p (&decl_specifiers, ds_typedef))
flags |= CP_PARSER_FLAGS_DELAY_NOEXCEPT;
@@ -26038,19 +26225,14 @@ cp_parser_noexcept_specification_opt (cp_parser* parser,
a class. So, if the noexcept-specifier has the optional expression,
just save the tokens, and reparse this after we're done with the
class. */
- const bool literal_p
- = ((cp_lexer_nth_token_is (parser->lexer, 3, CPP_NUMBER)
- || cp_lexer_nth_token_is (parser->lexer, 3, CPP_KEYWORD))
- && cp_lexer_nth_token_is (parser->lexer, 4, CPP_CLOSE_PAREN));
- if (cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN)
+ if ((flags & CP_PARSER_FLAGS_DELAY_NOEXCEPT)
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN)
/* No need to delay parsing for a number literal or true/false. */
- && !literal_p
+ && !((cp_lexer_nth_token_is (parser->lexer, 3, CPP_NUMBER)
+ || cp_lexer_nth_token_is (parser->lexer, 3, CPP_KEYWORD))
+ && cp_lexer_nth_token_is (parser->lexer, 4, CPP_CLOSE_PAREN))
&& at_class_scope_p ()
- /* We don't delay parsing for friend member functions,
- alias-declarations, and typedefs, even though the standard seems
- to require it. */
- && (flags & CP_PARSER_FLAGS_DELAY_NOEXCEPT)
&& TYPE_BEING_DEFINED (current_class_type)
&& !LAMBDA_TYPE_P (current_class_type))
return cp_parser_save_noexcept (parser);
@@ -27098,30 +27280,30 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
return attribute;
}
-/* Check that the attribute ATTRIBUTE appears at most once in the
- attribute-list ATTRIBUTES. This is enforced for noreturn (7.6.3),
- nodiscard, and deprecated (7.6.5). Note that
- carries_dependency (7.6.4) isn't implemented yet in GCC. */
+/* Warn if the attribute ATTRIBUTE appears more than once in the
+ attribute-list ATTRIBUTES. This used to be enforced for certain
+ attributes, but the restriction was removed in P2156. Note that
+ carries_dependency ([dcl.attr.depend]) isn't implemented yet in GCC.
+ LOC is the location of ATTRIBUTE. Returns true if ATTRIBUTE was not
+ found in ATTRIBUTES. */
-static void
-cp_parser_check_std_attribute (tree attributes, tree attribute)
+static bool
+cp_parser_check_std_attribute (location_t loc, tree attributes, tree attribute)
{
+ static auto alist = { "noreturn", "deprecated", "nodiscard", "maybe_unused",
+ "likely", "unlikely", "fallthrough",
+ "no_unique_address" };
if (attributes)
- {
- tree name = get_attribute_name (attribute);
- if (is_attribute_p ("noreturn", name)
- && lookup_attribute ("noreturn", attributes))
- error ("attribute %<noreturn%> can appear at most once "
- "in an attribute-list");
- else if (is_attribute_p ("deprecated", name)
- && lookup_attribute ("deprecated", attributes))
- error ("attribute %<deprecated%> can appear at most once "
- "in an attribute-list");
- else if (is_attribute_p ("nodiscard", name)
- && lookup_attribute ("nodiscard", attributes))
- error ("attribute %<nodiscard%> can appear at most once "
- "in an attribute-list");
- }
+ for (const auto &a : alist)
+ if (is_attribute_p (a, get_attribute_name (attribute))
+ && lookup_attribute (a, attributes))
+ {
+ if (!from_macro_expansion_at (loc))
+ warning_at (loc, OPT_Wattributes, "attribute %qs specified "
+ "multiple times", a);
+ return false;
+ }
+ return true;
}
/* Parse a list of standard C++-11 attributes.
@@ -27141,14 +27323,17 @@ cp_parser_std_attribute_list (cp_parser *parser, tree attr_ns)
while (true)
{
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
attribute = cp_parser_std_attribute (parser, attr_ns);
if (attribute == error_mark_node)
break;
if (attribute != NULL_TREE)
{
- cp_parser_check_std_attribute (attributes, attribute);
- TREE_CHAIN (attribute) = attributes;
- attributes = attribute;
+ if (cp_parser_check_std_attribute (loc, attributes, attribute))
+ {
+ TREE_CHAIN (attribute) = attributes;
+ attributes = attribute;
+ }
}
token = cp_lexer_peek_token (parser->lexer);
if (token->type == CPP_ELLIPSIS)
@@ -28462,11 +28647,6 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
prefer_type_arg (tag_type),
/*complain=*/true);
- /* If we have a single function from a using decl, pull it out. */
- if (TREE_CODE (decl) == OVERLOAD
- && !really_overloaded_fn (decl))
- decl = OVL_FUNCTION (decl);
-
if (pushed_scope)
pop_scope (pushed_scope);
}
@@ -33830,30 +34010,11 @@ cp_parser_objc_struct_declaration (cp_parser *parser)
static void
cp_parser_objc_at_property_declaration (cp_parser *parser)
{
- /* The following variables hold the attributes of the properties as
- parsed. They are 'false' or 'NULL_TREE' if the attribute was not
- seen. When we see an attribute, we set them to 'true' (if they
- are boolean properties) or to the identifier (if they have an
- argument, ie, for getter and setter). Note that here we only
- parse the list of attributes, check the syntax and accumulate the
- attributes that we find. objc_add_property_declaration() will
- then process the information. */
- bool property_assign = false;
- bool property_copy = false;
- tree property_getter_ident = NULL_TREE;
- bool property_nonatomic = false;
- bool property_readonly = false;
- bool property_readwrite = false;
- bool property_retain = false;
- tree property_setter_ident = NULL_TREE;
+ /* Parse the optional attribute list.
- /* 'properties' is the list of properties that we read. Usually a
- single one, but maybe more (eg, in "@property int a, b, c;" there
- are three). */
- tree properties;
- location_t loc;
-
- loc = cp_lexer_peek_token (parser->lexer)->location;
+ A list of parsed, but not verified, attributes. */
+ vec<property_attribute_info *> prop_attr_list = vNULL;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
cp_lexer_consume_token (parser->lexer); /* Eat '@property'. */
@@ -33862,132 +34023,176 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
{
/* Eat the '('. */
matching_parens parens;
+ location_t attr_start = cp_lexer_peek_token (parser->lexer)->location;
parens.consume_open (parser);
+ bool syntax_error = false;
- while (true)
+ /* Allow empty @property attribute lists, but with a warning. */
+ location_t attr_end = cp_lexer_peek_token (parser->lexer)->location;
+ location_t attr_comb;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
{
- bool syntax_error = false;
- cp_token *token = cp_lexer_peek_token (parser->lexer);
- enum rid keyword;
+ attr_comb = make_location (attr_end, attr_start, attr_end);
+ warning_at (attr_comb, OPT_Wattributes,
+ "empty property attribute list");
+ }
+ else
+ while (true)
+ {
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ attr_start = token->location;
+ attr_end = get_finish (token->location);
+ attr_comb = make_location (attr_start, attr_start, attr_end);
- if (token->type != CPP_NAME)
- {
- cp_parser_error (parser, "expected identifier");
- break;
- }
- keyword = C_RID_CODE (token->u.value);
- cp_lexer_consume_token (parser->lexer);
- switch (keyword)
- {
- case RID_ASSIGN: property_assign = true; break;
- case RID_COPY: property_copy = true; break;
- case RID_NONATOMIC: property_nonatomic = true; break;
- case RID_READONLY: property_readonly = true; break;
- case RID_READWRITE: property_readwrite = true; break;
- case RID_RETAIN: property_retain = true; break;
-
- case RID_GETTER:
- case RID_SETTER:
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
- {
- if (keyword == RID_GETTER)
- cp_parser_error (parser,
- "missing %<=%> (after %<getter%> attribute)");
- else
- cp_parser_error (parser,
- "missing %<=%> (after %<setter%> attribute)");
- syntax_error = true;
- break;
- }
- cp_lexer_consume_token (parser->lexer); /* eat the = */
- if (!cp_parser_objc_selector_p (cp_lexer_peek_token (parser->lexer)->type))
- {
- cp_parser_error (parser, "expected identifier");
- syntax_error = true;
+ if (token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA)
+ {
+ warning_at (attr_comb, OPT_Wattributes,
+ "missing property attribute");
+ if (token->type == CPP_CLOSE_PAREN)
break;
- }
- if (keyword == RID_SETTER)
- {
- if (property_setter_ident != NULL_TREE)
- {
- cp_parser_error (parser, "the %<setter%> attribute may only be specified once");
- cp_lexer_consume_token (parser->lexer);
- }
- else
- property_setter_ident = cp_parser_objc_selector (parser);
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
- cp_parser_error (parser, "setter name must terminate with %<:%>");
- else
- cp_lexer_consume_token (parser->lexer);
- }
- else
- {
- if (property_getter_ident != NULL_TREE)
- {
- cp_parser_error (parser, "the %<getter%> attribute may only be specified once");
- cp_lexer_consume_token (parser->lexer);
- }
- else
- property_getter_ident = cp_parser_objc_selector (parser);
- }
- break;
- default:
- cp_parser_error (parser, "unknown property attribute");
- syntax_error = true;
- break;
- }
+ cp_lexer_consume_token (parser->lexer);
+ continue;
+ }
- if (syntax_error)
- break;
+ tree attr_name = NULL_TREE;
+ if (identifier_p (token->u.value))
+ attr_name = token->u.value;
- if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ enum rid keyword;
+ if (token->type == CPP_NAME)
+ keyword = C_RID_CODE (token->u.value);
+ else if (token->type == CPP_KEYWORD
+ && token->keyword == RID_CLASS)
+ /* Account for accepting the 'class' keyword in this context. */
+ keyword = RID_CLASS;
+ else
+ keyword = RID_MAX; /* By definition, an unknown property. */
cp_lexer_consume_token (parser->lexer);
- else
- break;
- }
- /* FIXME: "@property (setter, assign);" will generate a spurious
- "error: expected ‘)’ before ‘,’ token". This is because
- cp_parser_require, unlike the C counterpart, will produce an
- error even if we are in error recovery. */
- if (!parens.require_close (parser))
- {
- cp_parser_skip_to_closing_parenthesis (parser,
- /*recovering=*/true,
- /*or_comma=*/false,
- /*consume_paren=*/true);
- }
- }
+ enum objc_property_attribute_kind prop_kind
+ = objc_prop_attr_kind_for_rid (keyword);
+ property_attribute_info *prop
+ = new property_attribute_info (attr_name, attr_comb, prop_kind);
+ prop_attr_list.safe_push (prop);
- /* ... and the property declaration(s). */
- properties = cp_parser_objc_struct_declaration (parser);
+ tree meth_name;
+ switch (prop->prop_kind)
+ {
+ default: break;
+ case OBJC_PROPERTY_ATTR_UNKNOWN:
+ if (attr_name)
+ error_at (attr_start, "unknown property attribute %qE",
+ attr_name);
+ else
+ error_at (attr_start, "unknown property attribute");
+ prop->parse_error = syntax_error = true;
+ break;
- if (properties == error_mark_node)
- {
- cp_parser_skip_to_end_of_statement (parser);
- /* If the next token is now a `;', consume it. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
- cp_lexer_consume_token (parser->lexer);
- return;
+ case OBJC_PROPERTY_ATTR_GETTER:
+ case OBJC_PROPERTY_ATTR_SETTER:
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
+ {
+ attr_comb = make_location (attr_end, attr_start, attr_end);
+ error_at (attr_comb, "expected %<=%> after Objective-C %qE",
+ attr_name);
+ prop->parse_error = syntax_error = true;
+ break;
+ }
+
+ token = cp_lexer_peek_token (parser->lexer);
+ attr_end = token->location;
+ cp_lexer_consume_token (parser->lexer); /* eat the = */
+
+ if (!cp_parser_objc_selector_p
+ (cp_lexer_peek_token (parser->lexer)->type))
+ {
+ attr_comb = make_location (attr_end, attr_start, attr_end);
+ error_at (attr_comb, "expected %qE selector name",
+ attr_name);
+ prop->parse_error = syntax_error = true;
+ break;
+ }
+
+ /* Get the end of the method name, and consume the name. */
+ token = cp_lexer_peek_token (parser->lexer);
+ attr_end = get_finish (token->location);
+ /* Because method names may contain C++ keywords, we have a
+ routine to fetch them (this also consumes the token). */
+ meth_name = cp_parser_objc_selector (parser);
+
+ if (prop->prop_kind == OBJC_PROPERTY_ATTR_SETTER)
+ {
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+ {
+ attr_comb = make_location (attr_end, attr_start,
+ attr_end);
+ error_at (attr_comb, "setter method names must"
+ " terminate with %<:%>");
+ prop->parse_error = syntax_error = true;
+ }
+ else
+ {
+ attr_end = get_finish (cp_lexer_peek_token
+ (parser->lexer)->location);
+ cp_lexer_consume_token (parser->lexer);
+ }
+ attr_comb = make_location (attr_start, attr_start,
+ attr_end);
+ }
+ else
+ attr_comb = make_location (attr_start, attr_start,
+ attr_end);
+ prop->ident = meth_name;
+ /* Updated location including all that was successfully
+ parsed. */
+ prop->prop_loc = attr_comb;
+ break;
+ }
+
+ /* If we see a comma here, then keep going - even if we already
+ saw a syntax error. For simple mistakes e.g. (asign, getter=x)
+ this makes a more useful output and avoid spurious warnings
+ about missing attributes that are, in fact, specified after the
+ one with the syntax error. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+ else
+ break;
+ }
+
+ if (syntax_error || !parens.require_close (parser))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
}
- if (properties == NULL_TREE)
+ /* 'properties' is the list of properties that we read. Usually a
+ single one, but maybe more (eg, in "@property int a, b, c;" there
+ are three).
+ TODO: Update this parsing so that it accepts (erroneous) bitfields so
+ that we can issue a meaningful and consistent (between C/C++) error
+ message from objc_add_property_declaration (). */
+ tree properties = cp_parser_objc_struct_declaration (parser);
+
+ if (properties == error_mark_node)
+ cp_parser_skip_to_end_of_statement (parser);
+ else if (properties == NULL_TREE)
cp_parser_error (parser, "expected identifier");
else
{
- /* Comma-separated properties are chained together in
- reverse order; add them one by one. */
+ /* Comma-separated properties are chained together in reverse order;
+ add them one by one. */
properties = nreverse (properties);
-
for (; properties; properties = TREE_CHAIN (properties))
objc_add_property_declaration (loc, copy_node (properties),
- property_readonly, property_readwrite,
- property_assign, property_retain,
- property_copy, property_nonatomic,
- property_getter_ident, property_setter_ident);
+ prop_attr_list);
}
cp_parser_consume_semicolon_at_end_of_statement (parser);
+
+ while (!prop_attr_list.is_empty())
+ delete prop_attr_list.pop ();
+ prop_attr_list.release ();
}
/* Parse an Objective-C++ @synthesize declaration. The syntax is:
@@ -34123,6 +34328,8 @@ cp_parser_omp_clause_name (cp_parser *parser)
case 'a':
if (!strcmp ("aligned", p))
result = PRAGMA_OMP_CLAUSE_ALIGNED;
+ else if (!strcmp ("allocate", p))
+ result = PRAGMA_OMP_CLAUSE_ALLOCATE;
else if (!strcmp ("async", p))
result = PRAGMA_OACC_CLAUSE_ASYNC;
else if (!strcmp ("attach", p))
@@ -36278,6 +36485,47 @@ cp_parser_omp_clause_aligned (cp_parser *parser, tree list)
return nlist;
}
+/* OpenMP 5.0:
+ allocate ( variable-list )
+ allocate ( expression : variable-list ) */
+
+static tree
+cp_parser_omp_clause_allocate (cp_parser *parser, tree list)
+{
+ tree nlist, c, allocator = NULL_TREE;
+ bool colon;
+
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ return list;
+
+ cp_parser_parse_tentatively (parser);
+ bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
+ parser->colon_corrects_to_scope_p = false;
+ allocator = cp_parser_assignment_expression (parser);
+ parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ {
+ cp_parser_parse_definitely (parser);
+ cp_lexer_consume_token (parser->lexer);
+ if (allocator == error_mark_node)
+ allocator = NULL_TREE;
+ }
+ else
+ {
+ cp_parser_abort_tentative_parse (parser);
+ allocator = NULL_TREE;
+ }
+
+ nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_ALLOCATE, list,
+ &colon);
+
+ for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+
+ return nlist;
+}
+
/* OpenMP 2.5:
lastprivate ( variable-list )
@@ -37595,6 +37843,10 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
clauses = cp_parser_omp_clause_aligned (parser, clauses);
c_name = "aligned";
break;
+ case PRAGMA_OMP_CLAUSE_ALLOCATE:
+ clauses = cp_parser_omp_clause_allocate (parser, clauses);
+ c_name = "allocate";
+ break;
case PRAGMA_OMP_CLAUSE_LINEAR:
{
bool declare_simd = false;
@@ -37785,7 +38037,7 @@ cp_parser_omp_structured_block (cp_parser *parser, bool *if_p)
where x and v are lvalue expressions with scalar type. */
static void
-cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc)
{
tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, lhs1 = NULL_TREE;
tree rhs1 = NULL_TREE, orig_lhs;
@@ -37820,6 +38072,12 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
new_code = OMP_ATOMIC;
else if (!strcmp (p, "capture"))
new_code = OMP_ATOMIC_CAPTURE_NEW;
+ else if (openacc)
+ {
+ p = NULL;
+ error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
+ "or %<capture%> clause");
+ }
else if (!strcmp (p, "seq_cst"))
new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
else if (!strcmp (p, "acq_rel"))
@@ -37847,7 +38105,12 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
{
if (new_code != ERROR_MARK)
{
- if (code != ERROR_MARK)
+ /* OpenACC permits 'update capture'. */
+ if (openacc
+ && code == OMP_ATOMIC
+ && new_code == OMP_ATOMIC_CAPTURE_NEW)
+ code = new_code;
+ else if (code != ERROR_MARK)
error_at (cloc, "too many atomic clauses");
else
code = new_code;
@@ -37869,7 +38132,9 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
if (code == ERROR_MARK)
code = OMP_ATOMIC;
- if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
+ if (openacc)
+ memory_order = OMP_MEMORY_ORDER_RELAXED;
+ else if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
{
omp_requires_mask
= (enum omp_requires) (omp_requires_mask
@@ -39614,6 +39879,7 @@ cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
static tree
@@ -39898,6 +40164,7 @@ cp_parser_omp_sections_scope (cp_parser *parser)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
@@ -39948,6 +40215,7 @@ cp_parser_omp_sections (cp_parser *parser, cp_token *pragma_tok,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND))
static tree
@@ -40093,6 +40361,7 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
@@ -40125,6 +40394,7 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
static tree
@@ -40189,7 +40459,8 @@ cp_parser_omp_taskyield (cp_parser *parser, cp_token *pragma_tok)
# pragma omp taskgroup taskgroup-clause[optseq] new-line */
#define OMP_TASKGROUP_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
static tree
cp_parser_omp_taskgroup (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
@@ -40298,6 +40569,7 @@ cp_parser_omp_cancellation_point (cp_parser *parser, cp_token *pragma_tok,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
static tree
@@ -40396,6 +40668,7 @@ cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT))
static tree
@@ -40512,6 +40785,7 @@ cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
tree clauses
= cp_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
"#pragma omp target data", pragma_tok);
+ c_omp_adjust_map_clauses (clauses, false);
int map_seen = 0;
for (tree *pc = &clauses; *pc;)
{
@@ -40530,6 +40804,7 @@ cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
case GOMP_MAP_ALWAYS_POINTER:
+ case GOMP_MAP_ATTACH_DETACH:
break;
default:
map_seen |= 1;
@@ -40613,6 +40888,7 @@ cp_parser_omp_target_enter_data (cp_parser *parser, cp_token *pragma_tok,
tree clauses
= cp_parser_omp_all_clauses (parser, OMP_TARGET_ENTER_DATA_CLAUSE_MASK,
"#pragma omp target enter data", pragma_tok);
+ c_omp_adjust_map_clauses (clauses, false);
int map_seen = 0;
for (tree *pc = &clauses; *pc;)
{
@@ -40627,6 +40903,7 @@ cp_parser_omp_target_enter_data (cp_parser *parser, cp_token *pragma_tok,
case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
case GOMP_MAP_ALWAYS_POINTER:
+ case GOMP_MAP_ATTACH_DETACH:
break;
default:
map_seen |= 1;
@@ -40701,6 +40978,7 @@ cp_parser_omp_target_exit_data (cp_parser *parser, cp_token *pragma_tok,
tree clauses
= cp_parser_omp_all_clauses (parser, OMP_TARGET_EXIT_DATA_CLAUSE_MASK,
"#pragma omp target exit data", pragma_tok);
+ c_omp_adjust_map_clauses (clauses, false);
int map_seen = 0;
for (tree *pc = &clauses; *pc;)
{
@@ -40716,6 +40994,7 @@ cp_parser_omp_target_exit_data (cp_parser *parser, cp_token *pragma_tok,
case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
case GOMP_MAP_ALWAYS_POINTER:
+ case GOMP_MAP_ATTACH_DETACH:
break;
default:
map_seen |= 1;
@@ -40802,6 +41081,7 @@ cp_parser_omp_target_update (cp_parser *parser, cp_token *pragma_tok,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR))
static bool
@@ -40964,6 +41244,8 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
OMP_TARGET_CLAUSES (stmt)
= cp_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
"#pragma omp target", pragma_tok);
+ c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
+
pc = &OMP_TARGET_CLAUSES (stmt);
keep_next_level (true);
OMP_TARGET_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p);
@@ -40987,6 +41269,7 @@ check_clauses:
case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
case GOMP_MAP_ALWAYS_POINTER:
+ case GOMP_MAP_ATTACH_DETACH:
break;
default:
error_at (OMP_CLAUSE_LOCATION (*pc),
@@ -42640,15 +42923,19 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok,
DECL_ATTRIBUTES (fndecl)
= tree_cons (get_identifier ("gnu_inline"), NULL_TREE,
DECL_ATTRIBUTES (fndecl));
- if (processing_template_decl)
- fndecl = push_template_decl (fndecl);
bool block_scope = false;
- tree block = NULL_TREE;
if (current_function_decl)
{
block_scope = true;
DECL_CONTEXT (fndecl) = current_function_decl;
DECL_LOCAL_DECL_P (fndecl) = true;
+ }
+
+ if (processing_template_decl)
+ fndecl = push_template_decl (fndecl);
+
+ if (block_scope)
+ {
if (!processing_template_decl)
pushdecl (fndecl);
}
@@ -42676,6 +42963,8 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok,
/* We should never meet a matched duplicate decl. */
gcc_checking_assert (d == error_mark_node || d == fndecl);
}
+
+ tree block = NULL_TREE;
if (!block_scope)
start_preparsed_function (fndecl, NULL_TREE, SF_PRE_PARSED);
else
@@ -42951,6 +43240,7 @@ cp_parser_omp_requires (cp_parser *parser, cp_token *pragma_tok)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
@@ -43292,7 +43582,7 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
switch (cp_parser_pragma_kind (pragma_tok))
{
case PRAGMA_OACC_ATOMIC:
- cp_parser_omp_atomic (parser, pragma_tok);
+ cp_parser_omp_atomic (parser, pragma_tok, true);
return;
case PRAGMA_OACC_CACHE:
stmt = cp_parser_oacc_cache (parser, pragma_tok);
@@ -43327,7 +43617,7 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
stmt = cp_parser_oacc_wait (parser, pragma_tok);
break;
case PRAGMA_OMP_ATOMIC:
- cp_parser_omp_atomic (parser, pragma_tok);
+ cp_parser_omp_atomic (parser, pragma_tok, false);
return;
case PRAGMA_OMP_CRITICAL:
stmt = cp_parser_omp_critical (parser, pragma_tok, if_p);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 555dc47..a2655a0 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
@@ -3634,7 +3634,7 @@ primary_template_specialization_p (const_tree t)
if (!t)
return false;
- if (TREE_CODE (t) == FUNCTION_DECL || VAR_P (t))
+ if (VAR_OR_FUNCTION_DECL_P (t))
return (DECL_LANG_SPECIFIC (t)
&& DECL_USE_TEMPLATE (t)
&& DECL_TEMPLATE_INFO (t)
@@ -3767,7 +3767,7 @@ builtin_pack_fn_p (tree fn)
{
if (!fn
|| TREE_CODE (fn) != FUNCTION_DECL
- || !DECL_IS_BUILTIN (fn))
+ || !DECL_IS_UNDECLARED_BUILTIN (fn))
return false;
if (id_equal (DECL_NAME (fn), "__integer_pack"))
@@ -4230,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);
@@ -4244,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)
@@ -5082,8 +5089,7 @@ process_partial_specialization (tree decl)
= TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (maintmpl)));
if (comp_template_args (inner_args, INNERMOST_TEMPLATE_ARGS (main_args))
&& (!flag_concepts
- || !strictly_subsumes (current_template_constraints (),
- main_args, maintmpl)))
+ || !strictly_subsumes (current_template_constraints (), maintmpl)))
{
if (!flag_concepts)
error ("partial specialization %q+D does not specialize "
@@ -5675,34 +5681,24 @@ template_parm_outer_level (tree t, void *data)
tree
push_template_decl (tree decl, bool is_friend)
{
- tree tmpl;
- tree args;
- tree info;
- tree ctx;
- bool is_primary;
- bool is_partial;
- int new_template_p = 0;
- /* True if the template is a member template, in the sense of
- [temp.mem]. */
- bool member_template_p = false;
-
if (decl == error_mark_node || !current_template_parms)
return error_mark_node;
/* See if this is a partial specialization. */
- is_partial = ((DECL_IMPLICIT_TYPEDEF_P (decl)
- && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
- && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
- || (VAR_P (decl)
- && DECL_LANG_SPECIFIC (decl)
- && DECL_TEMPLATE_SPECIALIZATION (decl)
- && TINFO_USED_TEMPLATE_ID (DECL_TEMPLATE_INFO (decl))));
+ bool is_partial = ((DECL_IMPLICIT_TYPEDEF_P (decl)
+ && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
+ || (VAR_P (decl)
+ && DECL_LANG_SPECIFIC (decl)
+ && DECL_TEMPLATE_SPECIALIZATION (decl)
+ && TINFO_USED_TEMPLATE_ID (DECL_TEMPLATE_INFO (decl))));
/* No surprising friend functions. */
gcc_checking_assert (is_friend
|| !(TREE_CODE (decl) == FUNCTION_DECL
- && DECL_FRIEND_P (decl)));
+ && DECL_UNIQUE_FRIEND_P (decl)));
+ tree ctx;
if (is_friend)
/* For a friend, we want the context of the friend, not
the type of which it is a friend. */
@@ -5724,23 +5720,30 @@ push_template_decl (tree decl, bool is_friend)
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
/* See if this is a primary template. */
+ bool is_primary = false;
if (is_friend && ctx
&& uses_template_parms_level (ctx, processing_template_decl))
/* A friend template that specifies a class context, i.e.
template <typename T> friend void A<T>::f();
is not primary. */
- is_primary = false;
+ ;
else if (TREE_CODE (decl) == TYPE_DECL && LAMBDA_TYPE_P (TREE_TYPE (decl)))
- is_primary = false;
+ /* Lambdas are not primary. */
+ ;
else
is_primary = template_parm_scope_p ();
+ /* True if the template is a member template, in the sense of
+ [temp.mem]. */
+ bool member_template_p = false;
+
if (is_primary)
{
warning (OPT_Wtemplates, "template %qD declared", decl);
if (DECL_CLASS_SCOPE_P (decl))
member_template_p = true;
+
if (TREE_CODE (decl) == TYPE_DECL
&& IDENTIFIER_ANON_P (DECL_NAME (decl)))
{
@@ -5808,11 +5811,16 @@ push_template_decl (tree decl, bool is_friend)
}
}
+ bool local_p = (!DECL_IMPLICIT_TYPEDEF_P (decl)
+ && ((ctx && TREE_CODE (ctx) == FUNCTION_DECL)
+ || (VAR_OR_FUNCTION_DECL_P (decl)
+ && DECL_LOCAL_DECL_P (decl))));
+
/* Check to see that the rules regarding the use of default
arguments are not being violated. We check args for a friend
functions when we know whether it's a definition, introducing
declaration or re-declaration. */
- if (!is_friend || TREE_CODE (decl) != FUNCTION_DECL)
+ if (!local_p && (!is_friend || TREE_CODE (decl) != FUNCTION_DECL))
check_default_tmpl_args (decl, current_template_parms,
is_primary, is_partial, is_friend);
@@ -5864,13 +5872,21 @@ push_template_decl (tree decl, bool is_friend)
if (is_partial)
return process_partial_specialization (decl);
- args = current_template_args ();
-
- if (!ctx
- || 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)))
+ tree args = current_template_args ();
+ tree tmpl = NULL_TREE;
+ bool new_template_p = false;
+ if (local_p)
+ {
+ /* Does not get a template head. */
+ tmpl = NULL_TREE;
+ gcc_checking_assert (!is_primary);
+ }
+ else if (!ctx
+ || 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_LANG_SPECIFIC (decl)
+ && DECL_TEMPLATE_INFO (decl))))
{
if (DECL_LANG_SPECIFIC (decl)
&& DECL_TEMPLATE_INFO (decl)
@@ -5897,7 +5913,7 @@ push_template_decl (tree decl, bool is_friend)
{
tmpl = build_template_decl (decl, current_template_parms,
member_template_p);
- new_template_p = 1;
+ new_template_p = true;
if (DECL_LANG_SPECIFIC (decl)
&& DECL_TEMPLATE_SPECIALIZATION (decl))
@@ -5929,8 +5945,6 @@ push_template_decl (tree decl, bool is_friend)
&& DECL_TEMPLATE_SPECIALIZATION (decl)
&& DECL_MEMBER_TEMPLATE_P (tmpl))
{
- tree new_tmpl;
-
/* The declaration is a specialization of a member
template, declared outside the class. Therefore, the
innermost template arguments will be NULL, so we
@@ -5938,7 +5952,7 @@ push_template_decl (tree decl, bool is_friend)
earlier call to check_explicit_specialization. */
args = DECL_TI_ARGS (decl);
- new_tmpl
+ tree new_tmpl
= build_template_decl (decl, current_template_parms,
member_template_p);
DECL_TI_TEMPLATE (decl) = new_tmpl;
@@ -6010,7 +6024,7 @@ push_template_decl (tree decl, bool is_friend)
}
}
- gcc_checking_assert (DECL_TEMPLATE_RESULT (tmpl) == decl);
+ gcc_checking_assert (!tmpl || DECL_TEMPLATE_RESULT (tmpl) == decl);
if (new_template_p)
{
@@ -6022,69 +6036,71 @@ push_template_decl (tree decl, bool is_friend)
if (!ctx
&& !(is_friend && template_class_depth (current_class_type) > 0))
{
- /* Hide template friend classes that haven't been declared yet. */
- if (is_friend && TREE_CODE (decl) == TYPE_DECL)
- DECL_FRIEND_P (tmpl) = 1;
-
- tmpl = pushdecl_namespace_level (tmpl, /*hiding=*/is_friend);
- if (tmpl == error_mark_node)
+ tree pushed = pushdecl_namespace_level (tmpl, /*hiding=*/is_friend);
+ if (pushed == error_mark_node)
return error_mark_node;
+
+ /* pushdecl may have found an existing template. */
+ if (pushed != tmpl)
+ {
+ decl = DECL_TEMPLATE_RESULT (pushed);
+ tmpl = NULL_TREE;
+ }
}
}
- else
+ else if (tmpl)
/* The type may have been completed, or (erroneously) changed. */
TREE_TYPE (tmpl) = TREE_TYPE (decl);
- if (is_primary)
+ if (tmpl)
{
- tree parms = DECL_TEMPLATE_PARMS (tmpl);
+ if (is_primary)
+ {
+ tree parms = DECL_TEMPLATE_PARMS (tmpl);
- DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
+ DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
- /* Give template template parms a DECL_CONTEXT of the template
- for which they are a parameter. */
- parms = INNERMOST_TEMPLATE_PARMS (parms);
- for (int i = TREE_VEC_LENGTH (parms) - 1; i >= 0; --i)
- {
- tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
- if (TREE_CODE (parm) == TEMPLATE_DECL)
- DECL_CONTEXT (parm) = tmpl;
- }
+ /* Give template template parms a DECL_CONTEXT of the template
+ for which they are a parameter. */
+ parms = INNERMOST_TEMPLATE_PARMS (parms);
+ for (int i = TREE_VEC_LENGTH (parms) - 1; i >= 0; --i)
+ {
+ tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
+ if (TREE_CODE (parm) == TEMPLATE_DECL)
+ DECL_CONTEXT (parm) = tmpl;
+ }
- if (TREE_CODE (decl) == TYPE_DECL
- && TYPE_DECL_ALIAS_P (decl))
- {
- if (tree constr
- = TEMPLATE_PARMS_CONSTRAINTS (DECL_TEMPLATE_PARMS (tmpl)))
+ if (TREE_CODE (decl) == TYPE_DECL
+ && TYPE_DECL_ALIAS_P (decl))
{
- /* ??? Why don't we do this here for all templates? */
- constr = build_constraints (constr, NULL_TREE);
- set_constraints (decl, constr);
+ if (tree constr
+ = TEMPLATE_PARMS_CONSTRAINTS (DECL_TEMPLATE_PARMS (tmpl)))
+ {
+ /* ??? Why don't we do this here for all templates? */
+ constr = build_constraints (constr, NULL_TREE);
+ set_constraints (decl, constr);
+ }
+ if (complex_alias_template_p (tmpl))
+ TEMPLATE_DECL_COMPLEX_ALIAS_P (tmpl) = true;
}
- if (complex_alias_template_p (tmpl))
- TEMPLATE_DECL_COMPLEX_ALIAS_P (tmpl) = true;
}
- }
- /* The DECL_TI_ARGS of DECL contains full set of arguments referring
- back to its most general template. If TMPL is a specialization,
- ARGS may only have the innermost set of arguments. Add the missing
- argument levels if necessary. */
- if (DECL_TEMPLATE_INFO (tmpl))
- args = add_outermost_template_args (DECL_TI_ARGS (tmpl), args);
+ /* The DECL_TI_ARGS of DECL contains full set of arguments
+ referring wback to its most general template. If TMPL is a
+ specialization, ARGS may only have the innermost set of
+ arguments. Add the missing argument levels if necessary. */
+ if (DECL_TEMPLATE_INFO (tmpl))
+ args = add_outermost_template_args (DECL_TI_ARGS (tmpl), args);
- info = build_template_info (tmpl, args);
+ tree info = build_template_info (tmpl, args);
- if (DECL_IMPLICIT_TYPEDEF_P (decl))
- SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
- else
- {
- if (is_primary)
- retrofit_lang_decl (decl);
- if (DECL_LANG_SPECIFIC (decl)
- && !(VAR_OR_FUNCTION_DECL_P (decl)
- && DECL_LOCAL_DECL_P (decl)))
- DECL_TEMPLATE_INFO (decl) = info;
+ if (DECL_IMPLICIT_TYPEDEF_P (decl))
+ SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
+ else
+ {
+ retrofit_lang_decl (decl);
+ DECL_TEMPLATE_INFO (decl) = info;
+ }
}
if (flag_implicit_templates
@@ -6096,7 +6112,9 @@ push_template_decl (tree decl, bool is_friend)
mark_needed will tell cgraph to do the right thing. */
DECL_COMDAT (decl) = true;
- return DECL_TEMPLATE_RESULT (tmpl);
+ gcc_checking_assert (!tmpl || DECL_TEMPLATE_RESULT (tmpl) == decl);
+
+ return decl;
}
/* FN is an inheriting constructor that inherits from the constructor
@@ -8159,7 +8177,7 @@ is_compatible_template_arg (tree parm, tree arg)
return false;
}
- return weakly_subsumes (parm_cons, new_args, arg);
+ return weakly_subsumes (parm_cons, arg);
}
// Convert a placeholder argument into a binding to the original
@@ -10599,6 +10617,16 @@ keep_template_parm (tree t, void* data)
if (!ftpi->parms.add (t))
ftpi->parm_list = tree_cons (NULL_TREE, t, ftpi->parm_list);
+ /* Verify the parameter we found has a valid index. */
+ if (flag_checking)
+ {
+ tree parms = ftpi->ctx_parms;
+ while (TMPL_PARMS_DEPTH (parms) > level)
+ parms = TREE_CHAIN (parms);
+ if (int len = TREE_VEC_LENGTH (TREE_VALUE (parms)))
+ gcc_assert (index < len);
+ }
+
return 0;
}
@@ -10737,7 +10765,7 @@ uses_template_parms (tree t)
else if (t == error_mark_node)
dependent_p = false;
else
- dependent_p = value_dependent_expression_p (t);
+ dependent_p = instantiation_dependent_expression_p (t);
processing_template_decl = saved_processing_template_decl;
@@ -11847,7 +11875,6 @@ instantiate_class_template_1 (tree type)
Ignore it; it will be regenerated when needed. */
continue;
- /* Build new CLASSTYPE_NESTED_UTDS. */
bool class_template_p = (TREE_CODE (t) != ENUMERAL_TYPE
&& TYPE_LANG_SPECIFIC (t)
&& CLASSTYPE_IS_TEMPLATE (t));
@@ -12005,10 +12032,10 @@ instantiate_class_template_1 (tree type)
TREE_TYPE (r) = error_mark_node;
}
- /* If it is a TYPE_DECL for a class-scoped ENUMERAL_TYPE,
- such a thing will already have been added to the field
- list by tsubst_enum in finish_member_declaration in the
- CLASSTYPE_NESTED_UTDS case above. */
+ /* If it is a TYPE_DECL for a class-scoped
+ ENUMERAL_TYPE, such a thing will already have
+ been added to the field list by tsubst_enum
+ in finish_member_declaration case above. */
if (!(TREE_CODE (r) == TYPE_DECL
&& TREE_CODE (TREE_TYPE (r)) == ENUMERAL_TYPE
&& DECL_ARTIFICIAL (r)))
@@ -13960,7 +13987,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));
@@ -14203,8 +14230,7 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain,
if (PRIMARY_TEMPLATE_P (t))
DECL_PRIMARY_TEMPLATE (r) = r;
- if (TREE_CODE (decl) != TYPE_DECL && !VAR_P (decl)
- && !lambda_fntype)
+ if (TREE_CODE (decl) == FUNCTION_DECL && !lambda_fntype)
/* Record this non-type partial instantiation. */
register_specialization (r, t,
DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)),
@@ -16044,20 +16070,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK:
- {
- tree r;
-
- if (code == NONTYPE_ARGUMENT_PACK)
- r = make_node (code);
- else
- r = cxx_make_type (code);
-
- tree pack_args = ARGUMENT_PACK_ARGS (t);
- pack_args = tsubst_template_args (pack_args, args, complain, in_decl);
- SET_ARGUMENT_PACK_ARGS (r, pack_args);
-
- return r;
- }
+ return tsubst_argument_pack (t, args, complain, in_decl);
case VOID_CST:
case INTEGER_CST:
@@ -17303,6 +17316,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
break;
case OMP_CLAUSE_GANG:
case OMP_CLAUSE_ALIGNED:
+ case OMP_CLAUSE_ALLOCATE:
OMP_CLAUSE_DECL (nc)
= tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
in_decl, NULL);
@@ -17372,6 +17386,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
case OMP_CLAUSE_IS_DEVICE_PTR:
case OMP_CLAUSE_INCLUSIVE:
case OMP_CLAUSE_EXCLUSIVE:
+ case OMP_CLAUSE_ALLOCATE:
/* tsubst_expr on SCOPE_REF results in returning
finish_non_static_data_member result. Undo that here. */
if (TREE_CODE (OMP_CLAUSE_DECL (oc)) == SCOPE_REF
@@ -18040,11 +18055,18 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
finish_label_decl (DECL_NAME (decl));
else if (TREE_CODE (decl) == USING_DECL)
{
+ /* We cannot have a member-using decl here (until 'using
+ enum T' is a thing). */
+ gcc_checking_assert (!DECL_DEPENDENT_P (decl));
+
+ /* This must be a non-dependent using-decl, and we'll have
+ used the names it found during template parsing. We do
+ not want to do the lookup again, because we might not
+ find the things we found then. (Again, using enum T
+ might mean we have to do things here.) */
tree scope = USING_DECL_SCOPE (decl);
- tree name = DECL_NAME (decl);
-
- scope = tsubst (scope, args, complain, in_decl);
- finish_nonmember_using_decl (scope, name);
+ gcc_checking_assert (scope
+ == tsubst (scope, args, complain, in_decl));
}
else if (is_capture_proxy (decl)
&& !DECL_TEMPLATE_INSTANTIATION (current_function_decl))
@@ -19062,15 +19084,6 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
LAMBDA_EXPR_MUTABLE_P (r) = LAMBDA_EXPR_MUTABLE_P (t);
LAMBDA_EXPR_INSTANTIATED (r) = true;
- if (LAMBDA_EXPR_EXTRA_SCOPE (t) == NULL_TREE)
- /* A lambda in a default argument outside a class gets no
- LAMBDA_EXPR_EXTRA_SCOPE, as specified by the ABI. But
- tsubst_default_argument calls start_lambda_scope, so we need to
- specifically ignore it here, and use the global scope. */
- record_null_lambda_scope (r);
- else
- record_lambda_scope (r);
-
gcc_assert (LAMBDA_EXPR_THIS_CAPTURE (t) == NULL_TREE
&& LAMBDA_EXPR_PENDING_PROXIES (t) == NULL);
@@ -19149,6 +19162,15 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (type == error_mark_node)
return error_mark_node;
+ if (LAMBDA_EXPR_EXTRA_SCOPE (t) == NULL_TREE)
+ /* A lambda in a default argument outside a class gets no
+ LAMBDA_EXPR_EXTRA_SCOPE, as specified by the ABI. But
+ tsubst_default_argument calls start_lambda_scope, so we need to
+ specifically ignore it here, and use the global scope. */
+ record_null_lambda_scope (r);
+ else
+ record_lambda_scope (r);
+
/* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set. */
determine_visibility (TYPE_NAME (type));
@@ -19614,8 +19636,11 @@ tsubst_copy_and_build (tree t,
{
/* If T was type-dependent, suppress warnings that depend on the range
of the types involved. */
- bool was_dep = type_dependent_expression_p_push (t);
-
+ ++processing_template_decl;
+ const bool was_dep = (potential_constant_expression (t)
+ ? value_dependent_expression_p (t)
+ : type_dependent_expression_p (t));
+ --processing_template_decl;
tree op0 = RECUR (TREE_OPERAND (t, 0));
tree op1 = RECUR (TREE_OPERAND (t, 1));
@@ -22671,8 +22696,20 @@ get_template_base (tree tparms, tree targs, tree parm, tree arg,
applies. */
if (rval && !same_type_p (r, rval))
{
- *result = NULL_TREE;
- return tbr_ambiguous_baseclass;
+ /* [temp.deduct.call]/4.3: If there is a class C that is a
+ (direct or indirect) base class of D and derived (directly or
+ indirectly) from a class B and that would be a valid deduced
+ A, the deduced A cannot be B or pointer to B, respectively. */
+ if (DERIVED_FROM_P (r, rval))
+ /* Ignore r. */
+ continue;
+ else if (DERIVED_FROM_P (rval, r))
+ /* Ignore rval. */;
+ else
+ {
+ *result = NULL_TREE;
+ return tbr_ambiguous_baseclass;
+ }
}
rval = r;
@@ -24955,19 +24992,6 @@ mark_class_instantiated (tree t, int extern_p)
}
}
-/* Called from do_type_instantiation through binding_table_foreach to
- do recursive instantiation for the type bound in ENTRY. */
-static void
-bt_instantiate_type_proc (binding_entry entry, void *data)
-{
- tree storage = *(tree *) data;
-
- if (MAYBE_CLASS_TYPE_P (entry->type)
- && CLASSTYPE_TEMPLATE_INFO (entry->type)
- && !uses_template_parms (CLASSTYPE_TI_ARGS (entry->type)))
- do_type_instantiation (TYPE_MAIN_DECL (entry->type), storage, 0);
-}
-
/* Perform an explicit instantiation of template class T. STORAGE, if
non-null, is the RID for extern, inline or static. COMPLAIN is
nonzero if this is called from the parser, zero if called recursively,
@@ -24976,20 +25000,11 @@ bt_instantiate_type_proc (binding_entry entry, void *data)
void
do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
{
- int extern_p = 0;
- int nomem_p = 0;
- int static_p = 0;
- int previous_instantiation_extern_p = 0;
-
- if (TREE_CODE (t) == TYPE_DECL)
- t = TREE_TYPE (t);
-
- if (! CLASS_TYPE_P (t) || ! CLASSTYPE_TEMPLATE_INFO (t))
+ if (!(CLASS_TYPE_P (t) && CLASSTYPE_TEMPLATE_INFO (t)))
{
- tree tmpl =
- (TYPE_TEMPLATE_INFO (t)) ? TYPE_TI_TEMPLATE (t) : NULL;
- if (tmpl)
- error ("explicit instantiation of non-class template %qD", tmpl);
+ if (tree ti = TYPE_TEMPLATE_INFO (t))
+ error ("explicit instantiation of non-class template %qD",
+ TI_TEMPLATE (ti));
else
error ("explicit instantiation of non-template type %qT", t);
return;
@@ -25005,6 +25020,11 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
return;
}
+ /* At most one of these will be true. */
+ bool extern_p = false;
+ bool nomem_p = false;
+ bool static_p = false;
+
if (storage != NULL_TREE)
{
if (storage == ridpointers[(int) RID_EXTERN])
@@ -25020,52 +25040,45 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
" on explicit instantiations", storage);
if (storage == ridpointers[(int) RID_INLINE])
- nomem_p = 1;
+ nomem_p = true;
else if (storage == ridpointers[(int) RID_EXTERN])
- extern_p = 1;
+ extern_p = true;
else if (storage == ridpointers[(int) RID_STATIC])
- static_p = 1;
+ static_p = true;
else
- {
- error ("storage class %qD applied to template instantiation",
- storage);
- extern_p = 0;
- }
+ error ("storage class %qD applied to template instantiation",
+ storage);
}
if (CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
- {
- /* DR 259 [temp.spec].
+ /* DR 259 [temp.spec].
- Both an explicit instantiation and a declaration of an explicit
- specialization shall not appear in a program unless the explicit
- instantiation follows a declaration of the explicit specialization.
+ Both an explicit instantiation and a declaration of an explicit
+ specialization shall not appear in a program unless the
+ explicit instantiation follows a declaration of the explicit
+ specialization.
- For a given set of template parameters, if an explicit
- instantiation of a template appears after a declaration of an
- explicit specialization for that template, the explicit
- instantiation has no effect. */
- return;
- }
- else if (CLASSTYPE_EXPLICIT_INSTANTIATION (t))
+ For a given set of template parameters, if an explicit
+ instantiation of a template appears after a declaration of an
+ explicit specialization for that template, the explicit
+ instantiation has no effect. */
+ return;
+
+ if (CLASSTYPE_EXPLICIT_INSTANTIATION (t) && !CLASSTYPE_INTERFACE_ONLY (t))
{
+ /* We've already instantiated the template. */
+
/* [temp.spec]
No program shall explicitly instantiate any template more
than once.
- If PREVIOUS_INSTANTIATION_EXTERN_P, then the first explicit
- instantiation was `extern'. If EXTERN_P then the second is.
- These cases are OK. */
- previous_instantiation_extern_p = CLASSTYPE_INTERFACE_ONLY (t);
+ If EXTERN_P then this is ok. */
+ if (!extern_p && (complain & tf_error))
+ permerror (input_location,
+ "duplicate explicit instantiation of %q#T", t);
- if (!previous_instantiation_extern_p && !extern_p
- && (complain & tf_error))
- permerror (input_location, "duplicate explicit instantiation of %q#T", t);
-
- /* If we've already instantiated the template, just return now. */
- if (!CLASSTYPE_INTERFACE_ONLY (t))
- return;
+ return;
}
check_explicit_instantiation_namespace (TYPE_NAME (t));
@@ -25102,10 +25115,14 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
instantiate_decl (fld, /*defer_ok=*/true,
/*expl_inst_class_mem_p=*/true);
}
+ else if (DECL_IMPLICIT_TYPEDEF_P (fld))
+ {
+ tree type = TREE_TYPE (fld);
- if (CLASSTYPE_NESTED_UTDS (t))
- binding_table_foreach (CLASSTYPE_NESTED_UTDS (t),
- bt_instantiate_type_proc, &storage);
+ if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INFO (type)
+ && !uses_template_parms (CLASSTYPE_TI_ARGS (type)))
+ do_type_instantiation (type, storage, 0);
+ }
}
/* Given a function DECL, which is a specialization of TMPL, modify
@@ -25569,9 +25586,6 @@ instantiate_body (tree pattern, tree args, tree d, bool nested_p)
if (VAR_P (d))
{
- tree init;
- bool const_init = false;
-
/* Clear out DECL_RTL; whatever was there before may not be right
since we've reset the type of the declaration. */
SET_DECL_RTL (d, NULL);
@@ -25581,7 +25595,8 @@ instantiate_body (tree pattern, tree args, tree d, bool nested_p)
regenerate_decl_from_template so we don't need to
push/pop_access_scope again here. Pull it out so that
cp_finish_decl can process it. */
- init = DECL_INITIAL (d);
+ bool const_init = false;
+ tree init = DECL_INITIAL (d);
DECL_INITIAL (d) = NULL_TREE;
DECL_INITIALIZED_P (d) = 0;
@@ -25613,9 +25628,11 @@ instantiate_body (tree pattern, tree args, tree d, bool nested_p)
if (nested_p)
block = push_stmt_list ();
else
- start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
+ {
+ start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
- perform_instantiation_time_access_checks (code_pattern, args);
+ perform_instantiation_time_access_checks (code_pattern, args);
+ }
/* Create substitution entries for the parameters. */
register_parameter_specializations (code_pattern, d);
@@ -25654,7 +25671,8 @@ instantiate_body (tree pattern, tree args, tree d, bool nested_p)
}
/* We're not deferring instantiation any more. */
- TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (d)) = 0;
+ if (!nested_p)
+ TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (d)) = 0;
if (push_to_top)
pop_from_top_level ();
@@ -27049,7 +27067,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))
@@ -27289,7 +27307,8 @@ bool
instantiation_dependent_expression_p (tree expression)
{
return (instantiation_dependent_uneval_expression_p (expression)
- || value_dependent_expression_p (expression));
+ || (potential_constant_expression (expression)
+ && value_dependent_expression_p (expression)));
}
/* Like type_dependent_expression_p, but it also works while not processing
@@ -29237,7 +29256,13 @@ do_auto_deduction (tree type, tree init, tree auto_node,
if (type == error_mark_node)
return error_mark_node;
- init = resolve_nondeduced_context (init, complain);
+ if (BRACE_ENCLOSED_INITIALIZER_P (init))
+ /* We don't recurse here because we can't deduce from a nested
+ initializer_list. */
+ for (constructor_elt &elt : *CONSTRUCTOR_ELTS (init))
+ elt.value = resolve_nondeduced_context (elt.value, complain);
+ else
+ init = resolve_nondeduced_context (init, complain);
if (context == adc_decomp_type
&& auto_node == type
@@ -29250,6 +29275,8 @@ do_auto_deduction (tree type, tree init, tree auto_node,
else if (AUTO_IS_DECLTYPE (auto_node))
{
tree stripped_init = tree_strip_any_location_wrapper (init);
+ if (REFERENCE_REF_P (stripped_init))
+ stripped_init = TREE_OPERAND (stripped_init, 0);
bool id = (DECL_P (stripped_init)
|| ((TREE_CODE (init) == COMPONENT_REF
|| TREE_CODE (init) == SCOPE_REF)
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 7c4bff7..887aae3 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -123,6 +123,7 @@ static GTY (()) vec<tinfo_s, va_gc> *tinfo_descs;
static tree ifnonnull (tree, tree, tsubst_flags_t);
static tree tinfo_name (tree, bool);
+static tree get_tinfo_decl_direct (tree type, tree name, int pseudo_ix);
static tree build_dynamic_cast_1 (location_t, tree, tree, tsubst_flags_t);
static tree throw_bad_cast (void);
static tree throw_bad_typeid (void);
@@ -166,10 +167,8 @@ pop_abi_namespace (void)
void
init_rtti_processing (void)
{
- tree type_info_type;
-
push_nested_namespace (std_node);
- type_info_type = xref_tag (class_type, get_identifier ("type_info"));
+ tree 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);
@@ -414,9 +413,6 @@ tinfo_name (tree type, bool mark_private)
tree
get_tinfo_decl (tree type)
{
- tree name;
- tree d;
-
if (variably_modified_type_p (type, /*fn=*/NULL_TREE))
{
error ("cannot create type information for type %qT because "
@@ -429,25 +425,41 @@ get_tinfo_decl (tree type)
type = build_function_type (TREE_TYPE (type),
TREE_CHAIN (TYPE_ARG_TYPES (type)));
- type = complete_type (type);
+ return get_tinfo_decl_direct (type, NULL, -1);
+}
+/* Get or create a tinfo VAR_DECL directly from the provided information.
+ The caller must have already checked it is valid to do so. */
+
+static tree
+get_tinfo_decl_direct (tree type, tree name, int pseudo_ix)
+{
/* For a class type, the variable is cached in the type node
itself. */
+ tree d = NULL_TREE;
+
+ gcc_checking_assert (TREE_CODE (type) != METHOD_TYPE);
+
+ if (pseudo_ix < 0)
+ type = complete_type (type);
+
if (CLASS_TYPE_P (type))
- {
- d = CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type));
- if (d)
- return d;
- }
+ d = CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type));
+
+ if (!name)
+ name = mangle_typeinfo_for_type (type);
- name = mangle_typeinfo_for_type (type);
+ if (!CLASS_TYPE_P (type))
+ d = get_global_binding (name);
- d = get_global_binding (name);
if (!d)
{
- int ix = get_pseudo_ti_index (type);
- const tinfo_s *ti = get_tinfo_desc (ix);
-
+ /* Create it. */
+ if (pseudo_ix < 0)
+ pseudo_ix = get_pseudo_ti_index (type);
+
+ const tinfo_s *ti = get_tinfo_desc (pseudo_ix);
+
d = build_lang_decl (VAR_DECL, name, ti->type);
SET_DECL_ASSEMBLER_NAME (d, name);
/* Remember the type it is for. */
@@ -754,23 +766,21 @@ build_dynamic_cast_1 (location_t loc, tree type, tree expr,
dcast_fn = dynamic_cast_node;
if (!dcast_fn)
{
- tree tmp;
- tree tinfo_ptr;
- const char *name;
-
push_abi_namespace ();
- tinfo_ptr = xref_tag (class_type,
- get_identifier ("__class_type_info"));
- tinfo_ptr = build_pointer_type
- (cp_build_qualified_type
- (tinfo_ptr, TYPE_QUAL_CONST));
- name = "__dynamic_cast";
- tmp = build_function_type_list (ptr_type_node,
- const_ptr_type_node,
- tinfo_ptr, tinfo_ptr,
- ptrdiff_type_node, NULL_TREE);
- dcast_fn = build_library_fn_ptr (name, tmp,
- ECF_LEAF | ECF_PURE | ECF_NOTHROW);
+ tree tinfo_ptr = xref_tag (class_type,
+ get_identifier ("__class_type_info"));
+ tinfo_ptr = cp_build_qualified_type (tinfo_ptr, TYPE_QUAL_CONST);
+ tinfo_ptr = build_pointer_type (tinfo_ptr);
+
+ const char *fn_name = "__dynamic_cast";
+ /* void *() (void const *, __class_type_info const *,
+ __class_type_info const *, ptrdiff_t) */
+ tree fn_type = (build_function_type_list
+ (ptr_type_node, const_ptr_type_node,
+ tinfo_ptr, tinfo_ptr, ptrdiff_type_node,
+ NULL_TREE));
+ dcast_fn = (build_library_fn_ptr
+ (fn_name, fn_type, ECF_LEAF | ECF_PURE | ECF_NOTHROW));
pop_abi_namespace ();
dynamic_cast_node = dcast_fn;
}
@@ -947,6 +957,8 @@ tinfo_base_init (tinfo_s *ti, tree target)
{
push_abi_namespace ();
tree real_type = xref_tag (class_type, ti->name);
+ tree real_decl = TYPE_NAME (real_type);
+ DECL_SOURCE_LOCATION (real_decl) = BUILTINS_LOCATION;
pop_abi_namespace ();
if (!COMPLETE_TYPE_P (real_type))
@@ -1450,8 +1462,6 @@ get_tinfo_desc (unsigned ix)
}
}
- push_abi_namespace ();
-
/* Generate the pseudo type name. */
const char *real_name = tinfo_names[ix < TK_VMI_CLASS_TYPES
? ix : unsigned (TK_VMI_CLASS_TYPES)];
@@ -1468,6 +1478,7 @@ get_tinfo_desc (unsigned ix)
/* Pass the fields chained in reverse. */
finish_builtin_struct (pseudo_type, pseudo_name, fields, NULL_TREE);
CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type;
+ DECL_CONTEXT (TYPE_NAME (pseudo_type)) = FROB_CONTEXT (global_namespace);
xref_basetypes (pseudo_type, /*bases=*/NULL_TREE);
res->type = cp_build_qualified_type (pseudo_type, TYPE_QUAL_CONST);
@@ -1477,7 +1488,6 @@ get_tinfo_desc (unsigned ix)
internal linkage. */
TREE_PUBLIC (TYPE_MAIN_DECL (res->type)) = 1;
- pop_abi_namespace ();
return res;
}
@@ -1608,12 +1618,10 @@ emit_support_tinfos (void)
bool
emit_tinfo_decl (tree decl)
{
- tree type = TREE_TYPE (DECL_NAME (decl));
- int in_library = typeinfo_in_lib_p (type);
-
gcc_assert (DECL_TINFO_P (decl));
- if (in_library)
+ tree type = TREE_TYPE (DECL_NAME (decl));
+ if (typeinfo_in_lib_p (type))
{
if (doing_runtime)
DECL_EXTERNAL (decl) = 0;
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index e36a8ae..8a1de7c 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -977,17 +977,6 @@ lookup_field_r (tree binfo, void *data)
nval = get_class_binding (type, lfi->name, lfi->want_type);
- /* If we're looking up a type (as with an elaborated type specifier)
- we ignore all non-types we find. */
- if (lfi->want_type && nval && !DECL_DECLARES_TYPE_P (nval))
- {
- nval = NULL_TREE;
- if (CLASSTYPE_NESTED_UTDS (type))
- if (binding_entry e = binding_table_find (CLASSTYPE_NESTED_UTDS (type),
- lfi->name))
- nval = TYPE_MAIN_DECL (e->type);
- }
-
/* If there is no declaration with the indicated name in this type,
then there's nothing to do. */
if (!nval)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 1e42cd7..33d715e 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5382,11 +5382,7 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
if ((ort & C_ORT_OMP_DECLARE_SIMD) != C_ORT_OMP && ort != C_ORT_ACC)
OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
else if (TREE_CODE (t) == COMPONENT_REF)
- {
- gomp_map_kind k = (ort == C_ORT_ACC) ? GOMP_MAP_ATTACH_DETACH
- : GOMP_MAP_ALWAYS_POINTER;
- OMP_CLAUSE_SET_MAP_KIND (c2, k);
- }
+ OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
else if (REFERENCE_REF_P (t)
&& TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF)
{
@@ -5424,8 +5420,12 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
OMP_CLAUSE_MAP);
OMP_CLAUSE_SET_MAP_KIND (c3, OMP_CLAUSE_MAP_KIND (c2));
OMP_CLAUSE_DECL (c3) = ptr;
- if (OMP_CLAUSE_MAP_KIND (c2) == GOMP_MAP_ALWAYS_POINTER)
- OMP_CLAUSE_DECL (c2) = build_simple_mem_ref (ptr);
+ if (OMP_CLAUSE_MAP_KIND (c2) == GOMP_MAP_ALWAYS_POINTER
+ || OMP_CLAUSE_MAP_KIND (c2) == GOMP_MAP_ATTACH_DETACH)
+ {
+ OMP_CLAUSE_DECL (c2) = build_simple_mem_ref (ptr);
+ OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER);
+ }
else
OMP_CLAUSE_DECL (c2) = convert_from_reference (ptr);
OMP_CLAUSE_SIZE (c3) = size_zero_node;
@@ -6373,6 +6373,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
/* 1 if normal/task reduction has been seen, -1 if inscan reduction
has been seen, -2 if mixed inscan/normal reduction diagnosed. */
int reduction_seen = 0;
+ bool allocate_seen = false;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -7198,6 +7199,80 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
bitmap_set_bit (&oacc_reduction_head, DECL_UID (t));
break;
+ case OMP_CLAUSE_ALLOCATE:
+ t = omp_clause_decl_field (OMP_CLAUSE_DECL (c));
+ if (t)
+ omp_note_field_privatization (t, OMP_CLAUSE_DECL (c));
+ else
+ t = OMP_CLAUSE_DECL (c);
+ if (t == current_class_ptr)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<this%> not allowed in %<allocate%> clause");
+ remove = true;
+ break;
+ }
+ if (!VAR_P (t)
+ && TREE_CODE (t) != PARM_DECL
+ && TREE_CODE (t) != FIELD_DECL)
+ {
+ if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
+ break;
+ if (DECL_P (t))
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is not a variable in %<allocate%> clause", t);
+ else
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in %<allocate%> clause", t);
+ remove = true;
+ }
+ else if (bitmap_bit_p (&aligned_head, DECL_UID (t)))
+ {
+ warning_at (OMP_CLAUSE_LOCATION (c), 0,
+ "%qD appears more than once in %<allocate%> clauses",
+ t);
+ remove = true;
+ }
+ else
+ {
+ bitmap_set_bit (&aligned_head, DECL_UID (t));
+ allocate_seen = true;
+ }
+ tree allocator;
+ allocator = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
+ if (error_operand_p (allocator))
+ {
+ remove = true;
+ break;
+ }
+ if (allocator == NULL_TREE)
+ goto handle_field_decl;
+ tree allocatort;
+ allocatort = TYPE_MAIN_VARIANT (TREE_TYPE (allocator));
+ if (!type_dependent_expression_p (allocator)
+ && (TREE_CODE (allocatort) != ENUMERAL_TYPE
+ || TYPE_NAME (allocatort) == NULL_TREE
+ || TREE_CODE (TYPE_NAME (allocatort)) != TYPE_DECL
+ || (DECL_NAME (TYPE_NAME (allocatort))
+ != get_identifier ("omp_allocator_handle_t"))
+ || (TYPE_CONTEXT (allocatort)
+ != DECL_CONTEXT (global_namespace))))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<allocate%> clause allocator expression has "
+ "type %qT rather than %<omp_allocator_handle_t%>",
+ TREE_TYPE (allocator));
+ remove = true;
+ }
+ else
+ {
+ allocator = mark_rvalue_use (allocator);
+ if (!processing_template_decl)
+ allocator = maybe_constant_value (allocator);
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+ }
+ goto handle_field_decl;
+
case OMP_CLAUSE_DEPEND:
t = OMP_CLAUSE_DECL (c);
if (t == NULL_TREE)
@@ -7411,7 +7486,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
t = TREE_OPERAND (t, 0);
OMP_CLAUSE_DECL (c) = t;
}
- if (ort == C_ORT_ACC
+ if ((ort == C_ORT_ACC || ort == C_ORT_OMP)
&& TREE_CODE (t) == COMPONENT_REF
&& TREE_CODE (TREE_OPERAND (t, 0)) == INDIRECT_REF)
t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
@@ -7457,7 +7532,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
t = TREE_OPERAND (t, 0);
if (VAR_P (t) || TREE_CODE (t) == PARM_DECL)
{
- if (bitmap_bit_p (&map_field_head, DECL_UID (t)))
+ if (bitmap_bit_p (&map_field_head, DECL_UID (t))
+ || (ort == C_ORT_OMP
+ && bitmap_bit_p (&map_head, DECL_UID (t))))
goto handle_map_references;
}
}
@@ -7551,13 +7628,12 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
bitmap_set_bit (&generic_head, DECL_UID (t));
}
else if (bitmap_bit_p (&map_head, DECL_UID (t))
- && (ort != C_ORT_ACC
- || !bitmap_bit_p (&map_field_head, DECL_UID (t))))
+ && !bitmap_bit_p (&map_field_head, DECL_UID (t)))
{
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
error_at (OMP_CLAUSE_LOCATION (c),
"%qD appears more than once in motion clauses", t);
- if (ort == C_ORT_ACC)
+ else if (ort == C_ORT_ACC)
error_at (OMP_CLAUSE_LOCATION (c),
"%qD appears more than once in data clauses", t);
else
@@ -7566,7 +7642,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
remove = true;
}
else if (bitmap_bit_p (&generic_head, DECL_UID (t))
- || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
+ && ort == C_ORT_ACC)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in data clauses", t);
+ remove = true;
+ }
+ else if (bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
{
if (ort == C_ORT_ACC)
error_at (OMP_CLAUSE_LOCATION (c),
@@ -7602,17 +7684,14 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
&& (OMP_CLAUSE_MAP_KIND (c)
!= GOMP_MAP_FIRSTPRIVATE_REFERENCE)
&& (OMP_CLAUSE_MAP_KIND (c)
- != GOMP_MAP_ALWAYS_POINTER))
+ != GOMP_MAP_ALWAYS_POINTER)
+ && (OMP_CLAUSE_MAP_KIND (c)
+ != GOMP_MAP_ATTACH_DETACH))
{
tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
OMP_CLAUSE_MAP);
if (TREE_CODE (t) == COMPONENT_REF)
- {
- gomp_map_kind k
- = (ort == C_ORT_ACC) ? GOMP_MAP_ATTACH_DETACH
- : GOMP_MAP_ALWAYS_POINTER;
- OMP_CLAUSE_SET_MAP_KIND (c2, k);
- }
+ OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
else
OMP_CLAUSE_SET_MAP_KIND (c2,
GOMP_MAP_FIRSTPRIVATE_REFERENCE);
@@ -8115,17 +8194,11 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
}
t = OMP_CLAUSE_DECL (c);
- if (processing_template_decl
- && !VAR_P (t) && TREE_CODE (t) != PARM_DECL)
- {
- pc = &OMP_CLAUSE_CHAIN (c);
- continue;
- }
-
switch (c_kind)
{
case OMP_CLAUSE_LASTPRIVATE:
- if (!bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
+ if (DECL_P (t)
+ && !bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
{
need_default_ctor = true;
need_dtor = true;
@@ -8135,6 +8208,34 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
case OMP_CLAUSE_REDUCTION:
case OMP_CLAUSE_IN_REDUCTION:
case OMP_CLAUSE_TASK_REDUCTION:
+ if (allocate_seen)
+ {
+ if (TREE_CODE (t) == MEM_REF)
+ {
+ t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == ADDR_EXPR
+ || TREE_CODE (t) == INDIRECT_REF)
+ t = TREE_OPERAND (t, 0);
+ if (DECL_P (t))
+ bitmap_clear_bit (&aligned_head, DECL_UID (t));
+ }
+ else if (TREE_CODE (t) == TREE_LIST)
+ {
+ while (TREE_CODE (t) == TREE_LIST)
+ t = TREE_CHAIN (t);
+ if (DECL_P (t))
+ bitmap_clear_bit (&aligned_head, DECL_UID (t));
+ t = OMP_CLAUSE_DECL (c);
+ }
+ else if (DECL_P (t))
+ bitmap_clear_bit (&aligned_head, DECL_UID (t));
+ t = OMP_CLAUSE_DECL (c);
+ }
+ if (processing_template_decl
+ && !VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+ break;
if (finish_omp_reduction_clause (c, &need_default_ctor,
&need_dtor))
remove = true;
@@ -8143,6 +8244,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
break;
case OMP_CLAUSE_COPYIN:
+ if (processing_template_decl
+ && !VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+ break;
if (!VAR_P (t) || !CP_DECL_THREAD_LOCAL_P (t))
{
error_at (OMP_CLAUSE_LOCATION (c),
@@ -8155,6 +8259,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
break;
}
+ if (processing_template_decl
+ && !VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+ {
+ pc = &OMP_CLAUSE_CHAIN (c);
+ continue;
+ }
+
if (need_complete_type || need_copy_assignment)
{
t = require_complete_type (t);
@@ -8169,6 +8280,11 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
{
const char *share_name = NULL;
+ if (allocate_seen
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SHARED
+ && DECL_P (t))
+ bitmap_clear_bit (&aligned_head, DECL_UID (t));
+
if (VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t))
share_name = "threadprivate";
else switch (cxx_omp_predetermined_sharing_1 (t))
@@ -8262,6 +8378,26 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
pc = &OMP_CLAUSE_CHAIN (c);
}
+ if (allocate_seen)
+ for (pc = &clauses, c = clauses; c ; c = *pc)
+ {
+ bool remove = false;
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
+ && !OMP_CLAUSE_ALLOCATE_COMBINED (c)
+ && DECL_P (OMP_CLAUSE_DECL (c))
+ && bitmap_bit_p (&aligned_head, DECL_UID (OMP_CLAUSE_DECL (c))))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD specified in %<allocate%> clause but not in "
+ "an explicit privatization clause", OMP_CLAUSE_DECL (c));
+ remove = true;
+ }
+ if (remove)
+ *pc = OMP_CLAUSE_CHAIN (c);
+ else
+ pc = &OMP_CLAUSE_CHAIN (c);
+ }
+
bitmap_obstack_release (NULL);
return clauses;
}
@@ -10133,6 +10269,12 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
case CPTK_IS_CONSTRUCTIBLE:
return is_xible (INIT_EXPR, type1, type2);
+ case CPTK_IS_NOTHROW_ASSIGNABLE:
+ return is_nothrow_xible (MODIFY_EXPR, type1, type2);
+
+ case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
+ return is_nothrow_xible (INIT_EXPR, type1, type2);
+
default:
gcc_unreachable ();
return false;
@@ -10213,6 +10355,8 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
case CPTK_IS_TRIVIALLY_ASSIGNABLE:
case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
+ case CPTK_IS_NOTHROW_ASSIGNABLE:
+ case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
if (!check_trait_type (type1)
|| !check_trait_type (type2))
return error_mark_node;
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 9bc37ac..28e5910 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2676,6 +2676,52 @@ build_cp_fntype_variant (tree type, cp_ref_qualifier rqual,
return v;
}
+/* TYPE is a function or method type with a deferred exception
+ specification that has been parsed to RAISES. Fixup all the type
+ variants that are affected in place. Via decltype &| noexcept
+ tricks, the unparsed spec could have escaped into the type system.
+ The general case is hard to fixup canonical types for. */
+
+void
+fixup_deferred_exception_variants (tree type, tree raises)
+{
+ tree original = TYPE_RAISES_EXCEPTIONS (type);
+ tree cr = flag_noexcept_type ? canonical_eh_spec (raises) : NULL_TREE;
+
+ gcc_checking_assert (TREE_CODE (TREE_PURPOSE (original))
+ == DEFERRED_PARSE);
+
+ /* Though sucky, this walk will process the canonical variants
+ first. */
+ for (tree variant = TYPE_MAIN_VARIANT (type);
+ variant; variant = TYPE_NEXT_VARIANT (variant))
+ if (TYPE_RAISES_EXCEPTIONS (variant) == original)
+ {
+ gcc_checking_assert (variant != TYPE_MAIN_VARIANT (type));
+
+ if (!TYPE_STRUCTURAL_EQUALITY_P (variant))
+ {
+ cp_cv_quals var_quals = TYPE_QUALS (variant);
+ cp_ref_qualifier rqual = type_memfn_rqual (variant);
+
+ tree v = TYPE_MAIN_VARIANT (type);
+ for (; v; v = TYPE_NEXT_VARIANT (v))
+ if (TYPE_CANONICAL (v) == v
+ && cp_check_qualified_type (v, variant, var_quals,
+ rqual, cr, false))
+ break;
+ TYPE_RAISES_EXCEPTIONS (variant) = raises;
+
+ if (!v)
+ v = build_cp_fntype_variant (TYPE_CANONICAL (variant),
+ rqual, cr, false);
+ TYPE_CANONICAL (variant) = v;
+ }
+ else
+ TYPE_RAISES_EXCEPTIONS (variant) = raises;
+ }
+}
+
/* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions
listed in RAISES. */
@@ -2700,6 +2746,7 @@ bind_template_template_parm (tree t, tree newargs)
t2 = cxx_make_type (BOUND_TEMPLATE_TEMPLATE_PARM);
decl = build_decl (input_location,
TYPE_DECL, DECL_NAME (decl), NULL_TREE);
+ SET_DECL_TEMPLATE_PARM_P (decl);
/* These nodes have to be created to reflect new TYPE_DECL and template
arguments. */
@@ -3671,20 +3718,28 @@ cp_tree_equal (tree t1, tree t2)
case CALL_EXPR:
{
- tree arg1, arg2;
- call_expr_arg_iterator iter1, iter2;
- if (KOENIG_LOOKUP_P (t1) != KOENIG_LOOKUP_P (t2)
- || !called_fns_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2)))
+ if (KOENIG_LOOKUP_P (t1) != KOENIG_LOOKUP_P (t2))
return false;
- for (arg1 = first_call_expr_arg (t1, &iter1),
- arg2 = first_call_expr_arg (t2, &iter2);
- arg1 && arg2;
- arg1 = next_call_expr_arg (&iter1),
- arg2 = next_call_expr_arg (&iter2))
- if (!cp_tree_equal (arg1, arg2))
- return false;
- if (arg1 || arg2)
+
+ if (!called_fns_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2)))
return false;
+
+ call_expr_arg_iterator iter1, iter2;
+ init_call_expr_arg_iterator (t1, &iter1);
+ init_call_expr_arg_iterator (t2, &iter2);
+ if (iter1.n != iter2.n)
+ return false;
+
+ while (more_call_expr_args_p (&iter1))
+ {
+ tree arg1 = next_call_expr_arg (&iter1);
+ tree arg2 = next_call_expr_arg (&iter2);
+
+ gcc_checking_assert (arg1 && arg2);
+ if (!cp_tree_equal (arg1, arg2))
+ return false;
+ }
+
return true;
}
@@ -3779,16 +3834,11 @@ cp_tree_equal (tree t1, tree t2)
CHECK_CONSTR_ARGS (t2)));
case TREE_VEC:
- {
- unsigned ix;
- if (TREE_VEC_LENGTH (t1) != TREE_VEC_LENGTH (t2))
- return false;
- for (ix = TREE_VEC_LENGTH (t1); ix--;)
- if (!cp_tree_equal (TREE_VEC_ELT (t1, ix),
- TREE_VEC_ELT (t2, ix)))
- return false;
- return true;
- }
+ /* These are template args. Really we should be getting the
+ caller to do this as it knows it to be true. */
+ if (!comp_template_args (t1, t2, NULL, NULL, false))
+ return false;
+ return true;
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
@@ -4050,13 +4100,14 @@ is_dummy_object (const_tree ob)
&& TREE_OPERAND (ob, 0) == void_node);
}
-/* Returns true if TYPE is a character type or std::byte. */
+/* Returns true if TYPE is char, unsigned char, or std::byte. */
bool
is_byte_access_type (tree type)
{
type = TYPE_MAIN_VARIANT (type);
- if (char_type_p (type))
+ if (type == char_type_node
+ || type == unsigned_char_type_node)
return true;
return (TREE_CODE (type) == ENUMERAL_TYPE
@@ -5668,8 +5719,7 @@ cp_fix_function_decl_p (tree decl)
/* Don't fix same_body aliases. Although they don't have their own
CFG, they share it with what they alias to. */
- if (!node || !node->alias
- || !vec_safe_length (node->ref_list.references))
+ if (!node || !node->alias || !node->num_references ())
return true;
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 95b36a9..08e0c80 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4062,7 +4062,7 @@ error_args_num (location_t loc, tree fndecl, bool too_many_p)
? G_("too many arguments to function %q#D")
: G_("too few arguments to function %q#D"),
fndecl);
- if (!DECL_IS_BUILTIN (fndecl))
+ if (!DECL_IS_UNDECLARED_BUILTIN (fndecl))
inform (DECL_SOURCE_LOCATION (fndecl), "declared here");
}
else
@@ -4428,6 +4428,107 @@ warn_for_null_address (location_t location, tree op, tsubst_flags_t complain)
}
}
+/* Warn about [expr.arith.conv]/2: If one operand is of enumeration type and
+ the other operand is of a different enumeration type or a floating-point
+ type, this behavior is deprecated ([depr.arith.conv.enum]). CODE is the
+ code of the binary operation, TYPE0 and TYPE1 are the types of the operands,
+ and LOC is the location for the whole binary expression.
+ TODO: Consider combining this with -Wenum-compare in build_new_op_1. */
+
+static void
+do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0,
+ tree type1)
+{
+ if (TREE_CODE (type0) == ENUMERAL_TYPE
+ && TREE_CODE (type1) == ENUMERAL_TYPE
+ && TYPE_MAIN_VARIANT (type0) != TYPE_MAIN_VARIANT (type1))
+ {
+ /* In C++20, -Wdeprecated-enum-enum-conversion is on by default.
+ Otherwise, warn if -Wenum-conversion is on. */
+ enum opt_code opt;
+ if (warn_deprecated_enum_enum_conv)
+ opt = OPT_Wdeprecated_enum_enum_conversion;
+ else if (warn_enum_conversion)
+ opt = OPT_Wenum_conversion;
+ else
+ return;
+
+ switch (code)
+ {
+ case GT_EXPR:
+ case LT_EXPR:
+ case GE_EXPR:
+ case LE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ /* Comparisons are handled by -Wenum-compare. */
+ return;
+ case SPACESHIP_EXPR:
+ /* This is invalid, don't warn. */
+ return;
+ case BIT_AND_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ warning_at (loc, opt, "bitwise operation between different "
+ "enumeration types %qT and %qT is deprecated",
+ type0, type1);
+ return;
+ default:
+ warning_at (loc, opt, "arithmetic between different enumeration "
+ "types %qT and %qT is deprecated", type0, type1);
+ return;
+ }
+ }
+ else if ((TREE_CODE (type0) == ENUMERAL_TYPE
+ && TREE_CODE (type1) == REAL_TYPE)
+ || (TREE_CODE (type0) == REAL_TYPE
+ && TREE_CODE (type1) == ENUMERAL_TYPE))
+ {
+ const bool enum_first_p = TREE_CODE (type0) == ENUMERAL_TYPE;
+ /* In C++20, -Wdeprecated-enum-float-conversion is on by default.
+ Otherwise, warn if -Wenum-conversion is on. */
+ enum opt_code opt;
+ if (warn_deprecated_enum_float_conv)
+ opt = OPT_Wdeprecated_enum_float_conversion;
+ else if (warn_enum_conversion)
+ opt = OPT_Wenum_conversion;
+ else
+ return;
+
+ switch (code)
+ {
+ case GT_EXPR:
+ case LT_EXPR:
+ case GE_EXPR:
+ case LE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ if (enum_first_p)
+ warning_at (loc, opt, "comparison of enumeration type %qT with "
+ "floating-point type %qT is deprecated",
+ type0, type1);
+ else
+ warning_at (loc, opt, "comparison of floating-point type %qT "
+ "with enumeration type %qT is deprecated",
+ type0, type1);
+ return;
+ case SPACESHIP_EXPR:
+ /* This is invalid, don't warn. */
+ return;
+ default:
+ if (enum_first_p)
+ warning_at (loc, opt, "arithmetic between enumeration type %qT "
+ "and floating-point type %qT is deprecated",
+ type0, type1);
+ else
+ warning_at (loc, opt, "arithmetic between floating-point type %qT "
+ "and enumeration type %qT is deprecated",
+ type0, type1);
+ return;
+ }
+ }
+}
+
/* Build a binary-operation expression without default conversions.
CODE is the kind of expression to build.
LOCATION is the location_t of the operator in the source code.
@@ -4706,14 +4807,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 +4829,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
@@ -5439,11 +5546,15 @@ cp_build_binary_op (const op_location_t &location,
{
result_type = cp_common_type (type0, type1);
if (complain & tf_warning)
- do_warn_double_promotion (result_type, type0, type1,
- "implicit conversion from %qH to %qI "
- "to match other operand of binary "
- "expression",
- location);
+ {
+ do_warn_double_promotion (result_type, type0, type1,
+ "implicit conversion from %qH to %qI "
+ "to match other operand of binary "
+ "expression",
+ location);
+ do_warn_enum_conversions (location, code, TREE_TYPE (orig_op0),
+ TREE_TYPE (orig_op1));
+ }
}
if (code == SPACESHIP_EXPR)
@@ -5476,6 +5587,12 @@ cp_build_binary_op (const op_location_t &location,
arithmetic conversions are applied to the operands." So we don't do
arithmetic conversions if the operands both have enumeral type. */
result_type = NULL_TREE;
+ else if ((orig_code0 == ENUMERAL_TYPE && orig_code1 == REAL_TYPE)
+ || (orig_code0 == REAL_TYPE && orig_code1 == ENUMERAL_TYPE))
+ /* [depr.arith.conv.enum]: Three-way comparisons between such operands
+ [where one is of enumeration type and the other is of a different
+ enumeration type or a floating-point type] are ill-formed. */
+ result_type = NULL_TREE;
if (result_type)
{
@@ -5490,12 +5607,12 @@ cp_build_binary_op (const op_location_t &location,
type to a floating point type, the program is ill-formed. */
bool ok = true;
if (TREE_CODE (result_type) == REAL_TYPE
- && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (orig_op0)))
+ && CP_INTEGRAL_TYPE_P (orig_type0))
/* OK */;
else if (!check_narrowing (result_type, orig_op0, complain))
ok = false;
if (TREE_CODE (result_type) == REAL_TYPE
- && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (orig_op1)))
+ && CP_INTEGRAL_TYPE_P (orig_type1))
/* OK */;
else if (!check_narrowing (result_type, orig_op1, complain))
ok = false;
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index e259a42..445e2a2 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -954,7 +954,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
return split_nonconstant_init (decl, value);
/* DECL may change value; purge caches. */
- clear_cv_and_fold_caches (TREE_STATIC (decl));
+ clear_cv_and_fold_caches ();
/* If the value is a constant, just put it in DECL_INITIAL. If DECL
is an automatic variable, the middle end will turn this into a