diff options
author | Ian Lance Taylor <iant@golang.org> | 2020-11-10 07:26:18 -0800 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2020-11-10 07:26:18 -0800 |
commit | 8d703821c69062c0cd255787d793e44f1a95d463 (patch) | |
tree | 6b1df9cdc36cc47b6164db69a14bc86a63dc77c6 /gcc/cp | |
parent | 9cd320ea6572c577cdf17ce1f9ea5230b166af6d (diff) | |
parent | cf392dbdf17e38026f8e3c0e9af7f5b87f63be56 (diff) | |
download | gcc-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/ChangeLog | 685 | ||||
-rw-r--r-- | gcc/cp/call.c | 35 | ||||
-rw-r--r-- | gcc/cp/class.c | 49 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 136 | ||||
-rw-r--r-- | gcc/cp/constraint.cc | 250 | ||||
-rw-r--r-- | gcc/cp/coroutines.cc | 25 | ||||
-rw-r--r-- | gcc/cp/cp-gimplify.c | 16 | ||||
-rw-r--r-- | gcc/cp/cp-objcp-common.c | 5 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 103 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 38 | ||||
-rw-r--r-- | gcc/cp/cxx-pretty-print.c | 33 | ||||
-rw-r--r-- | gcc/cp/decl.c | 233 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 60 | ||||
-rw-r--r-- | gcc/cp/except.c | 24 | ||||
-rw-r--r-- | gcc/cp/friend.c | 15 | ||||
-rw-r--r-- | gcc/cp/init.c | 2 | ||||
-rw-r--r-- | gcc/cp/logic.cc | 17 | ||||
-rw-r--r-- | gcc/cp/method.c | 17 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 564 | ||||
-rw-r--r-- | gcc/cp/name-lookup.h | 23 | ||||
-rw-r--r-- | gcc/cp/parser.c | 706 | ||||
-rw-r--r-- | gcc/cp/pt.c | 433 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 88 | ||||
-rw-r--r-- | gcc/cp/search.c | 11 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 200 | ||||
-rw-r--r-- | gcc/cp/tree.c | 102 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 137 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 2 |
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 |