diff options
author | Ian Lance Taylor <iant@golang.org> | 2021-09-13 10:37:49 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2021-09-13 10:37:49 -0700 |
commit | e252b51ccde010cbd2a146485d8045103cd99533 (patch) | |
tree | e060f101cdc32bf5e520de8e5275db9d4236b74c /gcc/cp | |
parent | f10c7c4596dda99d2ee872c995ae4aeda65adbdf (diff) | |
parent | 104c05c5284b7822d770ee51a7d91946c7e56d50 (diff) | |
download | gcc-e252b51ccde010cbd2a146485d8045103cd99533.zip gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.gz gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.bz2 |
Merge from trunk revision 104c05c5284b7822d770ee51a7d91946c7e56d50.
Diffstat (limited to 'gcc/cp')
39 files changed, 9369 insertions, 2862 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0f91414..8d1ec5d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,2565 @@ +2021-09-10 Jakub Jelinek <jakub@redhat.com> + + * parser.c (cp_parser_omp_atomic): Allow acq_rel on atomic read/write + and acq_rel/acquire clauses on update. + * semantics.c (finish_omp_atomic): Adjust c_finish_omp_atomic caller. + +2021-09-08 Richard Biener <rguenther@suse.de> + + PR c++/102228 + * cp-tree.h (ANON_AGGR_TYPE_FIELD): New define. + * decl.c (fixup_anonymous_aggr): Wipe RTTI info put in + place on invalid code. + * decl2.c (reset_type_linkage): Guard CLASSTYPE_TYPEINFO_VAR + access. + * module.cc (trees_in::read_class_def): Likewise. Reconstruct + ANON_AGGR_TYPE_FIELD. + * semantics.c (finish_member_declaration): Populate + ANON_AGGR_TYPE_FIELD for anon aggregate typed members. + * typeck.c (lookup_anon_field): Remove DFS search and return + ANON_AGGR_TYPE_FIELD directly. + +2021-09-07 Jakub Jelinek <jakub@redhat.com> + + PR c++/100495 + * constexpr.c (maybe_save_constexpr_fundef): Save body even for + constexpr deleting dtors. + (cxx_eval_call_expression): Don't use DECL_CLONED_FUNCTION for + deleting dtors. + +2021-09-07 Marcel Vollweiler <marcel@codesourcery.com> + + * parser.c (cp_parser_omp_flush): Parse 'seq_cst' clause on 'flush' + directive. + * semantics.c (finish_omp_flush): Handle MEMMODEL_SEQ_CST. + +2021-09-03 Iain Sandoe <iain@sandoe.co.uk> + + * coroutines.cc (register_local_var_uses): Do not mangle + frame entries for the outermost scope. Record the outer + scope as nesting depth 0. + +2021-09-03 Iain Sandoe <iain@sandoe.co.uk> + + * coroutines.cc (coro_build_artificial_var): New. + (build_actor_fn): Use var builder, rename vars to use + implementation namespace. + (coro_rewrite_function_body): Likewise. + (morph_fn_to_coro): Likewise. + +2021-09-03 Iain Sandoe <iain@sandoe.co.uk> + + * coroutines.cc (transform_local_var_uses): Record + frame offset expressions as DECL_VALUE_EXPRs instead of + rewriting them. + +2021-09-03 Patrick Palka <ppalka@redhat.com> + + PR c++/101904 + * call.c (build_this_conversion): New function, split out from + add_function_candidate. + (add_function_candidate): New parameter shortcut_bad_convs. + Document it. Use build_this_conversion. Stop at the first bad + argument conversion when shortcut_bad_convs is true. + (add_template_candidate_real): New parameter shortcut_bad_convs. + Use build_this_conversion to check the 'this' conversion before + attempting deduction. When the rejection reason code is + rr_bad_arg_conversion, pass -1 instead of 0 as the viable + parameter to add_candidate. Pass 'convs' to add_candidate. + (add_template_candidate): New parameter shortcut_bad_convs. + (add_template_conv_candidate): Pass false as shortcut_bad_convs + to add_template_candidate_real. + (add_candidates): Prefer to shortcut bad conversions during + overload resolution under the assumption that we'll eventually + see a strictly viable candidate. If this assumption turns out + to be false, re-process the non-strictly viable candidates + without shortcutting those bad conversions. + +2021-09-03 Jason Merrill <jason@redhat.com> + + * pt.c (limit_bad_template_recursion): Suppress -Wunused for decls + we decide not to instantiate. + +2021-09-03 Jakub Jelinek <jakub@redhat.com> + + PR target/102024 + * class.c (build_base_field): Use SET_DECL_FIELD_ABI_IGNORED + instead of writing to DECL_FIELD_ABI_IGNORED. + (layout_class_type): Likewise. In the place where zero-width + bitfields used to be removed, use + SET_DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD on those fields instead. + +2021-09-01 Iain Sandoe <iain@sandoe.co.uk> + + * call.c (build_over_call): Handle unavailable state in addition to + deprecation. + * class.c (type_build_ctor_call): Likewise. + (type_build_dtor_call): Likewise. + * cp-tree.h: Rename cp_warn_deprecated_use to + cp_handle_deprecated_or_unavailable. + * decl.c (duplicate_decls): Merge unavailability. + (grokdeclarator): Handle unavailability in addition to deprecation. + (type_is_unavailable): New. + (grokparms): Handle unavailability in addition to deprecation. + * decl.h (enum deprecated_states): Add + UNAVAILABLE_DEPRECATED_SUPPRESS. + * decl2.c (cplus_decl_attributes): Propagate unavailability to + templates. + (cp_warn_deprecated_use): Rename to ... + (cp_handle_deprecated_or_unavailable): ... this and amend to handle + the unavailable case. It remains a warning in the case of deprecation + but becomes an error in the case of unavailability. + (cp_warn_deprecated_use_scopes): Handle unavailability. + (mark_used): Likewise. + * parser.c (cp_parser_template_name): Likewise. + (cp_parser_template_argument): Likewise. + (cp_parser_parameter_declaration_list): Likewise. + * typeck.c (build_class_member_access_expr): Likewise. + (finish_class_member_access_expr): Likewise. + * typeck2.c (build_functional_cast_1): Likewise. + +2021-09-01 Iain Sandoe <iain@sandoe.co.uk> + + * coroutines.cc (build_actor_fn): Add begin/finish clauses + to the initial test in the actor function. + +2021-09-01 Iain Sandoe <iain@sandoe.co.uk> + + * coroutines.cc (await_statement_walker): Use build_stmt and + add_stmt instead of build1 and finish_expr_stmt. + +2021-08-31 Jason Merrill <jason@redhat.com> + + * coroutines.cc (flatten_await_stmt): Fix copyo. + * decl.c (reshape_init_class): Simplify. + * module.cc (module_state::read_language): Add null check. + * parser.c (build_range_temp): Avoid type_uses_auto. + (cp_parser_class_specifier_1): Add null check. + +2021-08-31 Patrick Palka <ppalka@redhat.com> + + PR c++/12672 + * call.c (rejection_reason::call_varargs_p): Rename this + previously unused member to ... + (rejection_reason::least_p): ... this. + (arity_rejection): Add least_p parameter. + (add_template_candidate_real): When there are explicit + template arguments, check that the arity of the call agrees with + the arity of the function before attempting deduction. + (print_arity_information): Add least_p parameter. + (print_z_candidate): Adjust call to print_arity_information. + +2021-08-31 Martin Sebor <msebor@redhat.com> + + * parser.c (cp_parser_selection_statement): Use direct initialization + instead of copy. + +2021-08-31 Jason Merrill <jason@redhat.com> + + * constexpr.c (explain_invalid_constexpr_fn): Use iloc_sentinel. + +2021-08-31 Jason Merrill <jason@redhat.com> + + PR c++/92193 + * cp-tree.h (FNDECL_MANIFESTLY_CONST_EVALUATED): New. + * constexpr.c (cxx_eval_call_expression): Set it. + * pt.c (neglectable_inst_p): Check it. + +2021-08-31 Marcel Vollweiler <marcel@codesourcery.com> + + * parser.c (cp_parser_omp_clause_device): Parse device-modifiers 'device_num' + and 'ancestor' in 'target device' clauses. + * semantics.c (finish_omp_clauses): Error handling. Constant device ids must + evaluate to '1' if 'ancestor' is used. + +2021-08-30 Jason Merrill <jason@redhat.com> + + PR c++/96286 + * cp-tree.h (struct lang_type): Add erroneous bit-field. + (CLASSTYPE_ERRONEOUS): New. + * pt.c (limit_bad_template_recursion): Check it. + (instantiate_class_template_1): Set it. + +2021-08-30 Jason Merrill <jason@redhat.com> + + * constexpr.c (cxx_eval_outermost_constant_expr): Copy + expr location to result. + +2021-08-30 Jason Merrill <jason@redhat.com> + + PR c++/101460 + * cp-tree.h (cxx_constant_value_sfinae): Declare. + * constexpr.c (cxx_constant_value_sfinae): New. + * pt.c (fold_targs_r, maybe_fold_fn_template_args): New. + (tsubst_copy_and_build) [CALL_EXPR]: Call + maybe_fold_fn_template_args. + +2021-08-30 Jason Merrill <jason@redhat.com> + + * parser.c (cp_parser_simple_requirement): Warn about missing + requires. + +2021-08-27 Jason Merrill <jason@redhat.com> + + * typeck2.c (build_x_arrow): Do set TREE_TYPE when operand is + a dependent pointer. + +2021-08-25 Andrew Pinski <apinski@marvell.com> + + PR c++/66590 + * cp-objcp-common.c (cxx_block_may_fallthru): Handle + CLEANUP_STMT for the case which will be try/finally. + +2021-08-25 Jakub Jelinek <jakub@redhat.com> + + PR c++/102019 + * init.c (build_value_init_noctor): Ignore unnamed zero-width + bitfields. + +2021-08-23 Jakub Jelinek <jakub@redhat.com> + + * parser.c (cp_parser_omp_clause_num_tasks, + cp_parser_omp_clause_grainsize): Parse the optional strict: modifier. + +2021-08-20 Jakub Jelinek <jakub@redhat.com> + + * parser.c (cp_parser_handle_statement_omp_attributes): Determine if + PRAGMA_OMP_ERROR directive is C_OMP_DIR_STANDALONE. + (cp_parser_omp_error): New function. + (cp_parser_pragma): Handle PRAGMA_OMP_ERROR. + +2021-08-20 Jakub Jelinek <jakub@redhat.com> + + * parser.c (cp_parser_omp_clause_depend_sink): Reject spurious + comma at the end of list. Don't parse closing paren here... + (cp_parser_omp_clause_depend): ... but here instead. + +2021-08-19 Patrick Palka <ppalka@redhat.com> + + PR c++/101803 + * cp-tree.h (CONSTRUCTOR_IS_PAREN_INIT): Clarify comment. + +2021-08-19 Jakub Jelinek <jakub@redhat.com> + + * parser.c (cp_parser_omp_requires): Don't call cp_lexer_nth_token_is + and optionally consume token if current token is CPP_EOF, + CPP_PRAGMA_EOL or CPP_CLOSE_PAREN. + +2021-08-19 Jakub Jelinek <jakub@redhat.com> + + * parser.c (cp_parser_omp_nothing): Use cp_parser_require_pragma_eol + instead of cp_parser_skip_to_pragma_eol. + +2021-08-18 Patrick Palka <ppalka@redhat.com> + + PR c++/101344 + PR c++/101803 + * cp-tree.h (CONSTRUCTOR_BRACES_ELIDED_P): Define. + * decl.c (reshape_init_r): Set it. + * pt.c (collect_ctor_idx_types): Recurse into a sub-CONSTRUCTOR + iff CONSTRUCTOR_BRACES_ELIDED_P. + +2021-08-18 Patrick Palka <ppalka@redhat.com> + + PR c++/101883 + * pt.c (convert_template_argument): Pass LOOKUP_IMPLICIT to + do_auto_deduction. + +2021-08-18 Jakub Jelinek <jakub@redhat.com> + + * parser.c (cp_parser_omp_nothing): New function. + (cp_parser_pragma): Handle PRAGMA_OMP_NOTHING. + +2021-08-18 Jakub Jelinek <jakub@redhat.com> + + * parser.c (cp_parser_omp_ordered): Return true instead of + false after emitting errors that the directive is not allowed in + pragma_stmt context. + (cp_parser_omp_target_update): Likewise. + (cp_parser_omp_cancellation_point): Change return type from void to + bool, return false if the directive should be ignored in pragma_stmt + contexts. + (cp_parser_omp_target_enter_data, cp_parser_omp_target_exit_data): + Change return type from tree to bool, return false if the + directive should be ignored in pragma_stmt contexts. + (cp_parser_omp_target): Adjust callers of cp_parser_omp_target_*_data, + return their result directly. + (cp_parser_pragma): For PRAGMA_OMP_CANCELLATION_POINT return what + cp_parser_omp_cancellation_point returned. Return true instead of + false after emitting errors that the directive is not allowed in + pragma_stmt context. + +2021-08-17 Jakub Jelinek <jakub@redhat.com> + + PR c++/101539 + * cp-tree.h (enum cp_trait_kind): Add CPTK_IS_LAYOUT_COMPATIBLE. + (enum cp_built_in_function): Add CP_BUILT_IN_IS_CORRESPONDING_MEMBER. + (fold_builtin_is_corresponding_member, next_common_initial_seqence, + layout_compatible_type_p): Declare. + * parser.c (cp_parser_primary_expression): Handle + RID_IS_LAYOUT_COMPATIBLE. + (cp_parser_trait_expr): Likewise. + * cp-objcp-common.c (names_builtin_p): Likewise. + * constraint.cc (diagnose_trait_expr): Handle + CPTK_IS_LAYOUT_COMPATIBLE. + * decl.c (cxx_init_decl_processing): Register + __builtin_is_corresponding_member builtin. + * constexpr.c (cxx_eval_builtin_function_call): Handle + CP_BUILT_IN_IS_CORRESPONDING_MEMBER builtin. + * semantics.c (is_corresponding_member_union, + is_corresponding_member_aggr, fold_builtin_is_corresponding_member): + New functions. + (trait_expr_value): Handle CPTK_IS_LAYOUT_COMPATIBLE. + (finish_trait_expr): Likewise. + * typeck.c (next_common_initial_seqence, layout_compatible_type_p): + New functions. + * cp-gimplify.c (cp_gimplify_expr): Fold + CP_BUILT_IN_IS_CORRESPONDING_MEMBER. + (cp_fold): Likewise. + * tree.c (builtin_valid_in_constant_expr_p): Handle + CP_BUILT_IN_IS_CORRESPONDING_MEMBER. + * cxx-pretty-print.c (pp_cxx_trait_expression): Handle + CPTK_IS_LAYOUT_COMPATIBLE. + * class.c (remove_zero_width_bit_fields): Remove. + (layout_class_type): Don't call it. + +2021-08-17 Jakub Jelinek <jakub@redhat.com> + + * parser.c (OMP_SCOPE_CLAUSE_MASK): Define. + (cp_parser_omp_scope): New function. + (cp_parser_omp_construct, cp_parser_pragma): Handle PRAGMA_OMP_SCOPE. + * pt.c (tsubst_expr): Handle OMP_SCOPE. + +2021-08-12 Jakub Jelinek <jakub@redhat.com> + + * parser.c (cp_parser_omp_clause_name): Parse filter clause name. + (cp_parser_omp_clause_filter): New function. + (cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_FILTER. + (OMP_MASKED_CLAUSE_MASK): Define. + (cp_parser_omp_masked): New function. + (cp_parser_omp_parallel): Handle parallel masked. + (cp_parser_omp_construct, cp_parser_pragma): Handle PRAGMA_OMP_MASKED. + * semantics.c (finish_omp_clauses): Handle OMP_CLAUSE_FILTER. + * pt.c (tsubst_omp_clauses): Likewise. + (tsubst_expr): Handle OMP_MASKED. + +2021-08-12 Sergei Trofimovich <siarheit@google.com> + + PR c++/101219 + * pt.c (tsubst_copy_and_build): Use build_ptrmemfunc_access_expr + to construct ptrmemfunc expression instantiation. + +2021-08-12 Tobias Burnus <tobias@codesourcery.com> + + * parser.c (cp_parser_omp_clause_proc_bind): Accept + 'primary' as alias for 'master'. + +2021-08-12 Jakub Jelinek <jakub@redhat.com> + + * cp-tree.h (omp_declare_target_attr): New type. + (struct saved_scope): Change type of omp_declare_target_attribute + from int to vec<omp_declare_target_attr, va_gc> * and move it. + * parser.c (cp_parser_omp_declare_target): Instead of + incrementing scope_chain->omp_declare_target_attribute, push + a struct containing parser->lexer->in_omp_attribute_pragma to + the vector. + (cp_parser_omp_end_declare_target): Instead of decrementing + scope_chain->omp_declare_target_attribute, pop a structure + from it. Diagnose mismatching declare target vs. + end declare target syntax. + * semantics.c (finish_translation_unit): Use vec_safe_length + and vec_safe_truncate on scope_chain->omp_declare_target_attributes. + * decl2.c (cplus_decl_attributes): Use vec_safe_length + on scope_chain->omp_declare_target_attributes. + +2021-08-12 Jakub Jelinek <jakub@redhat.com> + + * parser.c (cp_parser_lambda_body): Add temp overrides + for parser->{omp_declare_simd,oacc_routine,omp_attrs_forbidden_p}. + (cp_parser_statement): Restore parser->omp_attrs_forbidden_p for + cp_parser_declaration_statement. + (cp_parser_default_argument): Add temp override for + parser->omp_attrs_forbidden_p. + (cp_parser_late_parsing_omp_declare_simd): Diagnose declare simd + or declare variant in attribute syntax on a declaration immediately + following an OpenMP construct in pragma syntax. + +2021-08-12 Jakub Jelinek <jakub@redhat.com> + + PR c++/94162 + * method.c (cat_tag_for): Return cc_last for !CLASS_TYPE_P + or for classes not in std namespace. + +2021-08-12 Jakub Jelinek <jakub@redhat.com> + + * name-lookup.c (finish_using_directive): Diagnose omp::directive + or omp::sequence attributes on using-directive. + +2021-08-12 Jakub Jelinek <jakub@redhat.com> + + * parser.c (cp_parser_block_declaration): Call + cp_parser_using_directive for C++11 attributes followed by + using namespace tokens. + (cp_parser_using_directive): Parse C++11 attributes at the start + of the directive rather than at the end, only parse GNU attributes + at the end. + +2021-08-12 Patrick Palka <ppalka@redhat.com> + + PR c++/101663 + * constexpr.c (cxx_eval_store_expression): Handle the lval=true + case in the early exit code path for empty stores with mismatched + types. + +2021-08-11 Patrick Palka <ppalka@redhat.com> + + PR c++/101725 + DR 2082 + * cp-tree.h (unevaluated_p): Return true for REQUIRES_EXPR. + * decl.c (local_variable_p_walkfn): Don't walk into unevaluated + operands. + * parser.c (cp_parser_primary_expression) <case CPP_NAME>: Never + reject uses of local variables in unevaluated contexts. + * tree.c (cp_walk_subtrees) <case REQUIRES_EXPR>: Increment + cp_unevaluated_operand. Use cp_walk_tree directly instead of + WALK_SUBTREE to avoid the goto. Use REQUIRES_EXPR_REQS instead + of TREE_OPERAND directly. + +2021-08-11 Jakub Jelinek <jakub@redhat.com> + + PR c++/101786 + * decl2.c (var_defined_without_dynamic_init): Return true for + DECL_DECLARED_CONSTINIT_P with complete type and trivial destructor. + +2021-08-11 Patrick Palka <ppalka@redhat.com> + + PR c++/79501 + * parser.c (maybe_adjust_declarator_for_dguide): New, split + out from ... + (cp_parser_init_declarator): ... here. + (cp_parser_member_declaration): Use it. + +2021-08-11 Patrick Palka <ppalka@redhat.com> + + PR c++/89062 + * parser.c (cp_parser_parameter_declaration_list): Don't call + grokdeclarator if cp_parser_error_occurred. + (cp_parser_parameter_declaration): Simulate an error if we see + the beginning of a CTAD form, i.e. if we see an opening brace + after the decl-specifier-seq and the type is a CTAD placeholder. + +2021-08-10 Jakub Jelinek <jakub@redhat.com> + + * parser.c (cp_parser_member_declaration): Move odsd declaration + before cp_parser_using_declaration call to avoid errors with + GCC 4.8 to 6. + +2021-08-10 Jakub Jelinek <jakub@redhat.com> + + * parser.h (struct cp_omp_declare_simd_data): Remove + in_omp_attribute_pragma and clauses members, add loc and attribs. + (struct cp_oacc_routine_data): Remove loc member, add clauses + member. + * parser.c (cp_finalize_omp_declare_simd): New function. + (cp_parser_handle_statement_omp_attributes): Mention in + function comment the function is used also for + attribute-declaration. + (cp_parser_handle_directive_omp_attributes): New function. + (cp_parser_statement): Don't call + cp_parser_handle_statement_omp_attributes if statement doesn't + have attribute-specifier-seq at the beginning at all or if + if those attributes don't appertain to the statement. + (cp_parser_simple_declaration): Call + cp_parser_handle_directive_omp_attributes and + cp_finalize_omp_declare_simd. + (cp_parser_explicit_instantiation): Likewise. + (cp_parser_init_declarator): Initialize prefix_attributes + only after parsing declarators. + (cp_parser_direct_declarator): Call + cp_parser_handle_directive_omp_attributes and + cp_finalize_omp_declare_simd. + (cp_parser_member_declaration): Likewise. + (cp_parser_single_declaration): Likewise. + (cp_parser_omp_declare_simd): Don't initialize + data.in_omp_attribute_pragma, instead initialize + data.attribs[0] and data.attribs[1]. + (cp_finish_omp_declare_variant): Remove + in_omp_attribute_pragma argument, instead use + parser->lexer->in_omp_attribute_pragma. + (cp_parser_late_parsing_omp_declare_simd): Adjust + cp_finish_omp_declare_variant caller. Handle attribute-syntax + declare simd/variant. + +2021-08-06 Tamar Christina <tamar.christina@arm.com> + + * cp-objcp-common.h (cxx_simulate_enum_decl): Pass vec<> by pointer. + * decl.c (cxx_simulate_enum_decl): Likewise. + +2021-08-04 Jakub Jelinek <jakub@redhat.com> + + PR c++/101759 + * parser.c (cp_parser_default_argument): Temporarily override + parser->omp_declare_simd and parser->oacc_routine to NULL. + +2021-08-02 Patrick Palka <ppalka@redhat.com> + + PR c++/100828 + * logic.cc (formula::formula): Use emplace_back instead of + push_back. + (formula::branch): Insert a copy of m_current directly after + m_current instead of at the end of the list. + (formula::erase): Define. + (decompose_formula): Remove. + (decompose_antecedents): Remove. + (decompose_consequents): Remove. + (derive_proofs): Remove. + (max_problem_size): Remove. + (diagnose_constraint_size): Remove. + (subsumes_constraints_nonnull): Rewrite directly in terms of + decompose_clause and derive_proof, interleaving decomposition + with implication checking. Remove limit on constraint complexity. + Use formula::erase to free the current clause before moving on to + the next one. + +2021-07-31 Jason Merrill <jason@redhat.com> + + PR c++/96636 + * decl.c (fixup_anonymous_aggr): Clear TYPE_NEEDS_CONSTRUCTING + after error. + +2021-07-31 Jason Merrill <jason@redhat.com> + + * ptree.c (cxx_print_type) [TYPE_PACK_EXPANSION]: Also print + PACK_EXPANSION_PATTERN. + +2021-07-31 Jakub Jelinek <jakub@redhat.com> + + * parser.c (cp_parser_declaration): Handle OpenMP directives + in attribute-declaration. + +2021-07-30 Jakub Jelinek <jakub@redhat.com> + + PR c++/101539 + * cp-tree.h (enum cp_trait_kind): Add + CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF. + (enum cp_built_in_function): Add + CP_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS. + (fold_builtin_is_pointer_inverconvertible_with_class): Declare. + * parser.c (cp_parser_primary_expression): Handle + RID_IS_POINTER_INTERCONVERTIBLE_BASE_OF. + (cp_parser_trait_expr): Likewise. + * cp-objcp-common.c (names_builtin_p): Likewise. + * constraint.cc (diagnose_trait_expr): Handle + CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF. + * decl.c (cxx_init_decl_processing): Register + __builtin_is_pointer_interconvertible_with_class builtin. + * constexpr.c (cxx_eval_builtin_function_call): Handle + CP_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS builtin. + * semantics.c (pointer_interconvertible_base_of_p, + first_nonstatic_data_member_p, + fold_builtin_is_pointer_inverconvertible_with_class): New functions. + (trait_expr_value): Handle CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF. + (finish_trait_expr): Likewise. Formatting fix. + * cp-gimplify.c (cp_gimplify_expr): Fold + CP_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS. Call + fndecl_built_in_p just once. + (cp_fold): Likewise. + * tree.c (builtin_valid_in_constant_expr_p): Handle + CP_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS. Call + fndecl_built_in_p just once. + * cxx-pretty-print.c (pp_cxx_trait_expression): Handle + CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF. + +2021-07-30 Jason Merrill <jason@redhat.com> + + * class.c (finish_struct_anon): Improve comment. + * decl.c (fixup_anonymous_aggr): Reject anonymous struct + with bases. + +2021-07-30 Jakub Jelinek <jakub@redhat.com> + + * parser.c (cp_parser_statement): Rollback attributes not just + when std_attrs is non-NULL, but whenever + cp_parser_std_attribute_spec_seq parsed any tokens. + +2021-07-30 Jakub Jelinek <jakub@redhat.com> + + PR c++/101582 + * parser.c (cp_parser_skip_std_attribute_spec_seq): Add a forward + declaration. + (cp_parser_declaration): Parse empty-declaration and + attribute-declaration. + (cp_parser_toplevel_declaration): Don't parse empty-declaration here. + +2021-07-28 Martin Sebor <msebor@redhat.com> + + * init.c: Include new header. + +2021-07-27 Marek Polacek <polacek@redhat.com> + + DR 1512 + PR c++/99701 + * cp-gimplify.c (cp_fold): Remove {LE,LT,GE,GT_EXPR} from + a switch. + * typeck.c (cp_build_binary_op): Reject ordered comparison + of two null pointers. + +2021-07-26 Jakub Jelinek <jakub@redhat.com> + + * parser.h (struct cp_lexer): Add orphan_p member. + * parser.c (cp_parser_statement): Don't change in_omp_attribute_pragma + upon restart from CPP_PRAGMA handling. Fix up condition when a lexer + should be destroyed and adjust saved_tokens if it records tokens from + the to be destroyed lexer. + (cp_parser_omp_section_scan): New function. + (cp_parser_omp_scan_loop_body): Use it. If + parser->lexer->in_omp_attribute_pragma, allow optional comma + after scan. + (cp_parser_omp_sections_scope): Use cp_parser_omp_section_scan. + +2021-07-23 Jakub Jelinek <jakub@redhat.com> + + * parser.h (struct cp_parser): Add omp_attrs_forbidden_p member. + * parser.c (cp_parser_handle_statement_omp_attributes): Diagnose + mixing of attribute and pragma syntax directives when seeing + omp::directive if parser->omp_attrs_forbidden_p or if attribute syntax + directives are followed by OpenMP pragma. + (cp_parser_statement): Clear parser->omp_attrs_forbidden_p after + the cp_parser_handle_statement_omp_attributes call. + (cp_parser_omp_structured_block): Add disallow_omp_attrs argument, + if true, set parser->omp_attrs_forbidden_p. + (cp_parser_omp_scan_loop_body, cp_parser_omp_sections_scope): Pass + false as disallow_omp_attrs to cp_parser_omp_structured_block. + (cp_parser_omp_parallel, cp_parser_omp_task): Set + parser->omp_attrs_forbidden_p. + +2021-07-21 Thomas Schwinge <thomas@codesourcery.com> + Joseph Myers <joseph@codesourcery.com> + Cesar Philippidis <cesar@codesourcery.com> + + * parser.c (cp_parser_omp_clause_name): Handle 'nohost'. + (cp_parser_oacc_all_clauses): Handle 'PRAGMA_OACC_CLAUSE_NOHOST'. + (OACC_ROUTINE_CLAUSE_MASK): Add 'PRAGMA_OACC_CLAUSE_NOHOST'. + * pt.c (tsubst_omp_clauses): Handle 'OMP_CLAUSE_NOHOST'. + * semantics.c (finish_omp_clauses): Likewise. + +2021-07-21 Jakub Jelinek <jakub@redhat.com> + + PR c++/101516 + * semantics.c (finish_omp_reduction_clause): Also call + complete_type_or_else and return true if it fails. + +2021-07-19 Iain Sandoe <iain@sandoe.co.uk> + + PR c++/95520 + * coroutines.cc (struct coroutine_info): Add fields for + actor and destroy function decls. + (to_ramp): New. + (coro_get_ramp_function): New. + (coro_get_actor_function): New. + (coro_get_destroy_function): New. + (act_des_fn): Set up mapping between ramp, actor and + destroy functions. + (morph_fn_to_coro): Adjust interface to the builder for + helper function decls. + * cp-tree.h (DECL_ACTOR_FN, DECL_DESTROY_FN, DECL_RAMP_FN, + JOIN_STR): New. + * mangle.c (write_encoding): Handle coroutine helpers. + (write_unqualified_name): Handle lambda coroutine helpers. + +2021-07-16 Patrick Palka <ppalka@redhat.com> + + PR c++/101233 + * pt.c (alias_ctad_tweaks): Clear cp_unevaluated_operand for + substituting DECL_ARGUMENTS. + +2021-07-16 Patrick Palka <ppalka@redhat.com> + + DR 960 + PR c++/99664 + * search.c (check_final_overrider): Compare TYPE_REF_IS_RVALUE + when the return types are references. + +2021-07-16 Marek Polacek <polacek@redhat.com> + + * typeck2.c (check_narrowing): Don't suppress the pedantic error + in system headers. + +2021-07-15 Jakub Jelinek <jakub@redhat.com> + + PR c++/101443 + * cp-gimplify.c (cp_fold): For comparisons with NULLPTR_TYPE + operands, fold them right away to true or false. + +2021-07-15 Jason Merrill <jason@redhat.com> + + PR c++/101095 + * cp-objcp-common.c (cp_common_init_ts): Mark types as types. + (cp_tree_size): Remove redundant entries. + +2021-07-14 Patrick Palka <ppalka@redhat.com> + + PR c++/88252 + * cp-tree.h (TEMPLATE_TYPE_PARM_FOR_CLASS): Remove. + * pt.c (push_template_decl): Remove TEMPLATE_TYPE_PARM_FOR_CLASS + handling. + (redeclare_class_template): Likewise. + (forwarding_reference_p): Define. + (maybe_adjust_types_for_deduction): Use it instead. Add 'tparms' + parameter. + (unify_one_argument): Pass tparms to + maybe_adjust_types_for_deduction. + (try_one_overload): Likewise. + (unify): Likewise. + (rewrite_template_parm): Remove TEMPLATE_TYPE_PARM_FOR_CLASS + handling. + +2021-07-14 Jason Merrill <jason@redhat.com> + + * class.c (struct find_final_overrider_data): Use auto_vec. + (find_final_overrider): Remove explicit release. + * coroutines.cc (process_conditional): Use auto_vec. + * cp-gimplify.c (struct cp_genericize_data): Use auto_vec. + (cp_genericize_tree): Remove explicit release. + * parser.c (cp_parser_objc_at_property_declaration): Use + auto_delete_vec. + * semantics.c (omp_reduction_lookup): Use auto_vec. + +2021-07-14 Marek Polacek <polacek@redhat.com> + + PR c++/101371 + * constexpr.c (cxx_eval_array_reference): Create a new .object + and .ctor for the non-aggregate non-scalar case too when + value-initializing. + +2021-07-12 Patrick Palka <ppalka@redhat.com> + + PR c++/79501 + PR c++/100983 + * decl.c (grokfndecl): Don't require that deduction guides are + declared at namespace scope. Check that class-scope deduction + guides have the same access as the member class template. + (grokdeclarator): Pretend class-scope deduction guides are static. + * search.c (lookup_member): Don't use a BASELINK for (class-scope) + deduction guides. + +2021-07-10 Patrick Palka <ppalka@redhat.com> + + PR c++/82110 + * init.c (build_aggr_init): Return error_mark_node if + expand_aggr_init_1 returns false. + (expand_default_init): Change return type to bool. Return false + on error, true on success. + (expand_aggr_init_1): Likewise. + +2021-07-09 Jason Merrill <jason@redhat.com> + + PR c++/101098 + * decl.c (function_requirements_equivalent_p): Only compare + trailing requirements on a specialization. + +2021-07-09 Iain Sandoe <iain@sandoe.co.uk> + + * coroutines.cc (build_actor_fn): Move common code to + act_des_fn. + (build_destroy_fn): Likewise. + (act_des_fn): Build the void return here. Ensure that the + source location matches the original function. + +2021-07-09 Iain Sandoe <iain@sandoe.co.uk> + + * coroutines.cc + (coro_rewrite_function_body): Connect the replacement + function block to the block nest correctly. + +2021-07-09 Patrick Palka <ppalka@redhat.com> + + PR c++/101181 + * constraint.cc (tsubst_requires_expr): Pass complain/in_decl to + add_extra_args. + * cp-tree.h (add_extra_args): Add complain/in_decl parameters. + * pt.c (build_extra_args): Make a copy of args. + (add_extra_args): Add complain/in_decl parameters. Enable the + code for handling the case where the extra arguments are + dependent. + (tsubst_pack_expansion): Pass complain/in_decl to + add_extra_args. + (tsubst_template_args): Handle missing template arguments. + (tsubst_expr) <case IF_STMT>: Pass complain/in_decl to + add_extra_args. + +2021-07-09 Patrick Palka <ppalka@redhat.com> + + PR c++/101247 + * pt.c (any_template_parm_r) <case TEMPLATE_DECL>: Just walk the + DECL_CONTEXT. + +2021-07-08 Martin Sebor <msebor@redhat.com> + + PR bootstrap/101372 + * module.cc (identifier): Suppress warning. + (module_state::read_macro_maps): Remove warning suppression. + (module_state::install_macros): Ditto. + +2021-07-08 Marek Polacek <polacek@redhat.com> + + PR c++/101087 + * cp-tree.h (unevaluated_p): New. + * except.c (check_noexcept_r): Use it. Don't walk into + unevaluated operands. + +2021-07-08 Martin Sebor <msebor@redhat.com> + + PR bootstrap/101374 + * module.cc (module_state::read_macro_maps): Temporarily disable + -Warray-bounds. + (module_state::install_macros): Same. + +2021-07-06 Martin Sebor <msebor@redhat.com> + + * error.c (cp_printer): Remove support for %G and %K. + +2021-07-02 Jakub Jelinek <jakub@redhat.com> + + * parser.h (struct cp_lexer): Add in_omp_attribute_pragma member. + (struct cp_omp_declare_simd_data): Likewise. + * cp-tree.h (enum cp_tree_index): Add CPTI_OMP_IDENTIFIER. + (omp_identifier): Define. + * parser.c (cp_parser_skip_to_pragma_eol): Handle + in_omp_attribute_pragma CPP_PRAGMA_EOL followed by CPP_EOF. + (cp_parser_require_pragma_eol): Likewise. + (struct cp_omp_attribute_data): New type. + (cp_parser_handle_statement_omp_attributes): New function. + (cp_parser_statement): Handle OpenMP directives in statement's + attribute-specifier-seq. + (cp_parser_omp_directive_args, cp_parser_omp_sequence_args): New + functions. + (cp_parser_std_attribute): Handle omp::directive and omp::sequence + attributes. + (cp_parser_omp_all_clauses): If in_omp_attribute_pragma, allow + a comma also before the first clause. + (cp_parser_omp_allocate): Likewise. + (cp_parser_omp_atomic): Likewise. + (cp_parser_omp_depobj): Likewise. + (cp_parser_omp_flush): Likewise. + (cp_parser_omp_ordered): Likewise. + (cp_parser_omp_declare_simd): Save in_omp_attribute_pragma + into struct cp_omp_declare_simd_data. + (cp_finish_omp_declare_variant): Add in_omp_attribute_pragma + argument. If set, allow a comma also before match clause. + (cp_parser_late_parsing_omp_declare_simd): If in_omp_attribute_pragma, + allow a comma also before the first clause. Adjust + cp_finish_omp_declare_variant caller. + (cp_parser_omp_declare_target): If in_omp_attribute_pragma, allow + a comma also before the first clause. + (cp_parser_omp_declare_reduction_exprs): Likewise. + (cp_parser_omp_requires): Likewise. + * decl.c (initialize_predefined_identifiers): Initialize + omp_identifier. + * decl2.c (cplus_decl_attributes): Reject omp::directive and + omp::sequence attributes. + +2021-07-02 Jakub Jelinek <jakub@redhat.com> + + PR c/101297 + * parser.c (cp_parser_omp_atomic): Consume comma only if it + appears before a CPP_NAME. + +2021-07-02 Patrick Palka <ppalka@redhat.com> + + PR c++/101247 + * pt.c (any_template_parm_r) <case TEMPLATE_DECL>: Rewrite to + use common_enclosing_class and to not depend on the TREE_TYPE + of outer levels pointing to the corresponding primary template. + +2021-07-01 Patrick Palka <ppalka@redhat.com> + + PR c++/101194 + * constexpr.c (cxx_eval_array_reference): When the element type + is an empty type and the corresponding element is omitted, just + return an empty CONSTRUCTOR instead of attempting value + initialization. + +2021-07-01 Patrick Palka <ppalka@redhat.com> + + PR c++/96204 + * pt.c (finish_template_variable): Pass the partially + instantiated template and its args to instantiate_template. + (instantiate_class_template_1): No need to call + push_nested_class and pop_nested_class around the call to + most_specialized_partial_spec. + (instantiate_template_1): Pass the partially instantiated + template to lookup_template_variable. + (most_specialized_partial_spec): Use push_access_scope_guard + to set the access scope appropriately. Use + deferring_access_check_sentinel to force access to get checked + immediately. + (instantiate_decl): Just pass the VAR_DECL to + most_specialized_partial_spec. + +2021-06-30 Patrick Palka <ppalka@redhat.com> + + * constraint.cc (get_normalized_constraints_from_decl): Use + push_access_scope_guard instead of push_nested_class_guard. + * cp-tree.h (struct push_nested_class_guard): Replace with ... + (struct push_access_scope_guard): ... this. + * pt.c (push_access_scope): When the argument corresponds to + a class type, push the class instead of its context. + (pop_access_scope): Adjust accordingly. + +2021-06-30 Marek Polacek <polacek@redhat.com> + + PR c++/100975 + DR 2397 + * decl.c (create_array_type_for_decl): Allow array of auto. + +2021-06-29 Jason Merrill <jason@redhat.com> + + * pt.c (instantiate_decl): Only consider partial specializations of + actual variable templates. + +2021-06-26 Patrick Palka <ppalka@redhat.com> + + PR c++/96204 + * pt.c (instantiate_class_template_1): Enter the scope of the + type when calling most_specialized_partial_spec. + +2021-06-26 Jason Merrill <jason@redhat.com> + + PR c++/101040 + PR c++/97566 + * class.c (is_empty_field): Handle null argument. + * constexpr.c (cxx_eval_bare_aggregate): Discard initializer + for empty field. + +2021-06-26 Marek Polacek <polacek@redhat.com> + + PR c++/100752 + * parser.c (cp_parser_declarator): Pass flags down to + cp_parser_declarator. Also pass static_p/member_p. + +2021-06-25 Martin Sebor <msebor@redhat.com> + + * call.c (build_over_call): Replace direct uses of TREE_NO_WARNING + with warning_suppressed_p, suppress_warning, and copy_no_warning, or + nothing if not necessary. + (set_up_extended_ref_temp): Same. + * class.c (layout_class_type): Same. + * constraint.cc (constraint_satisfaction_value): Same. + * coroutines.cc (finish_co_await_expr): Same. + (finish_co_yield_expr): Same. + (finish_co_return_stmt): Same. + (build_actor_fn): Same. + (coro_rewrite_function_body): Same. + (morph_fn_to_coro): Same. + * cp-gimplify.c (genericize_eh_spec_block): Same. + (gimplify_expr_stmt): Same. + (cp_genericize_r): Same. + (cp_fold): Same. + * cp-ubsan.c (cp_ubsan_instrument_vptr): Same. + * cvt.c (cp_fold_convert): Same. + (convert_to_void): Same. + * decl.c (wrapup_namespace_globals): Same. + (grokdeclarator): Same. + (finish_function): Same. + (require_deduced_type): Same. + * decl2.c (no_linkage_error): Same. + (c_parse_final_cleanups): Same. + * except.c (expand_end_catch_block): Same. + * init.c (build_new_1): Same. + (build_new): Same. + (build_vec_delete_1): Same. + (build_vec_init): Same. + (build_delete): Same. + * method.c (defaultable_fn_check): Same. + * parser.c (cp_parser_fold_expression): Same. + (cp_parser_primary_expression): Same. + * pt.c (push_tinst_level_loc): Same. + (tsubst_copy): Same. + (tsubst_omp_udr): Same. + (tsubst_copy_and_build): Same. + * rtti.c (build_if_nonnull): Same. + * semantics.c (maybe_convert_cond): Same. + (finish_return_stmt): Same. + (finish_parenthesized_expr): Same. + (cp_check_omp_declare_reduction): Same. + * tree.c (build_cplus_array_type): Same. + * typeck.c (build_ptrmemfunc_access_expr): Same. + (cp_build_indirect_ref_1): Same. + (cp_build_function_call_vec): Same. + (warn_for_null_address): Same. + (cp_build_binary_op): Same. + (unary_complex_lvalue): Same. + (cp_build_modify_expr): Same. + (build_x_modify_expr): Same. + (convert_for_assignment): Same. + +2021-06-24 Patrick Palka <ppalka@redhat.com> + + PR c++/98832 + * pt.c (maybe_aggr_guide): Handle alias templates appropriately. + +2021-06-24 Patrick Palka <ppalka@redhat.com> + + PR c++/101182 + * constraint.cc (evaluate_requires_expr): Adjust function comment. + * cp-gimplify.c (cp_genericize_r) <case REQUIRES_EXPR>: Move to ... + (cp_fold) <case REQUIRES_EXPR>: ... here. + +2021-06-24 Jakub Jelinek <jakub@redhat.com> + + * parser.c (cp_omp_split_clauses): Pass C_ORT_OMP_TARGET instead of + C_ORT_OMP for clauses on target construct. + (OMP_TARGET_CLAUSE_MASK): Add in_reduction clause. + (cp_parser_omp_target): For non-combined target add + map (always, tofrom:) clauses for OMP_CLAUSE_IN_REDUCTION. Pass + C_ORT_OMP_TARGET to finish_omp_clauses. + * semantics.c (handle_omp_array_sections_1): Adjust ort handling + for addition of C_ORT_OMP_TARGET and simplify, mapping clauses are + never present on C_ORT_*DECLARE_SIMD. + (handle_omp_array_sections): Likewise. + (finish_omp_clauses): Likewise. Handle OMP_CLAUSE_IN_REDUCTION + on C_ORT_OMP_TARGET, set OMP_CLAUSE_MAP_IN_REDUCTION on + corresponding map clauses. + * pt.c (tsubst_expr): Pass C_ORT_OMP_TARGET instead of C_ORT_OMP for + clauses on target construct. + +2021-06-23 Patrick Palka <ppalka@redhat.com> + + PR c++/101174 + * pt.c (push_access_scope): For artificial deduction guides, + set the access scope to that of the constructor. + (pop_access_scope): Likewise. + (build_deduction_guide): Don't set DECL_CONTEXT on the guide. + +2021-06-23 Patrick Palka <ppalka@redhat.com> + + PR c++/86439 + * call.c (print_error_for_call_failure): Constify 'args' parameter. + (perform_dguide_overload_resolution): Define. + * cp-tree.h: (perform_dguide_overload_resolution): Declare. + * pt.c (do_class_deduction): Use perform_dguide_overload_resolution + instead of build_new_function_call. Don't use tf_decltype or + set cp_unevaluated_operand. Remove unnecessary NULL_TREE tests. + +2021-06-21 Patrick Palka <ppalka@redhat.com> + + PR c++/67302 + * typeck.c (check_return_expr): Call maybe_undo_parenthesized_ref + sooner, before the NRVO handling. + +2021-06-21 Patrick Palka <ppalka@redhat.com> + + PR c++/80431 + * tree.c (bot_replace): Use convert_to_base to build the + conversion to the (morally) virtual base. + +2021-06-21 Jakub Jelinek <jakub@redhat.com> + + PR inline-asm/100785 + * typeck.c (cxx_mark_addressable): Diagnose trying to make + bit-fields addressable. + +2021-06-17 Jason Merrill <jason@redhat.com> + + PR c++/101106 + * decl.c (duplicate_decls): Make 'deleted after first declaration' + pedwarn on by default. + +2021-06-17 Jason Merrill <jason@redhat.com> + + PR c++/101029 + * init.c (build_vec_init): Preserve the type of base. + +2021-06-16 Jason Merrill <jason@redhat.com> + + PR c++/101078 + PR c++/91706 + * pt.c (tsubst_baselink): Update binfos in non-dependent case. + +2021-06-15 Robin Dapp <rdapp@linux.ibm.com> + + * decl.c (duplicate_decls): Likewise. + +2021-06-14 Tobias Burnus <tobias@codesourcery.com> + + PR c/100913 + * parser.c (cp_parser_omp_clause_affinity): No need to set iterator + var in the error case. + +2021-06-13 Trevor Saunders <tbsaunde@tbsaunde.org> + + * constexpr.c (cxx_eval_call_expression): Iterate over vec<> + with range based for. + (cxx_eval_store_expression): Likewise. + (cxx_eval_loop_expr): Likewise. + * decl.c (wrapup_namespace_globals): Likewise. + (cp_finish_decl): Likewise. + (cxx_simulate_enum_decl): Likewise. + * parser.c (cp_parser_postfix_expression): Likewise. + +2021-06-12 Jason Merrill <jason@redhat.com> + + PR c++/101029 + * init.c (build_vec_init): Shortcut [0] case. + +2021-06-12 Jason Merrill <jason@redhat.com> + + * pt.c (lookup_template_class_1): Shortcut current_class_type. + +2021-06-11 Patrick Palka <ppalka@redhat.com> + + DR 1227 + PR c++/96560 + * pt.c (tsubst_arg_types): Rearrange so that we substitute into + TYPE_ARG_TYPES in forward order while short circuiting + appropriately. Adjust formatting. + +2021-06-11 Jakub Jelinek <jakub@redhat.com> + + PR c++/100974 + * cp-tree.h (struct saved_scope): Add consteval_if_p + member. Formatting fix for the discarded_stmt comment. + (in_consteval_if_p, IF_STMT_CONSTEVAL_P): Define. + * parser.c (cp_parser_lambda_expression): Temporarily disable + in_consteval_if_p when parsing lambda body. + (cp_parser_selection_statement): Parse consteval if. + * decl.c (struct named_label_entry): Add in_consteval_if member. + (level_for_consteval_if): New function. + (poplevel_named_label_1, check_previous_goto_1, check_goto): Handle + consteval if. + * constexpr.c (cxx_eval_builtin_function_call): Clarify in comment + why CP_BUILT_IN_IS_CONSTANT_EVALUATED needs to *non_constant_p + for !ctx->manifestly_const_eval. + (cxx_eval_conditional_expression): For IF_STMT_CONSTEVAL_P evaluate + condition as if it was __builtin_is_constant_evaluated call. + (potential_constant_expression_1): For IF_STMT_CONSTEVAL_P always + recurse on both branches. + * cp-gimplify.c (genericize_if_stmt): Genericize IF_STMT_CONSTEVAL_P + as the else branch. + * pt.c (tsubst_expr) <case IF_STMT>: Copy IF_STMT_CONSTEVAL_P. + Temporarily set in_consteval_if_p when recursing on + IF_STMT_CONSTEVAL_P then branch. + (tsubst_lambda_expr): Temporarily disable + in_consteval_if_p when instantiating lambda body. + * call.c (immediate_invocation_p): Return false when + in_consteval_if_p. + +2021-06-11 Marek Polacek <polacek@redhat.com> + + PR c++/100995 + * constexpr.c (maybe_constexpr_fn): New. + * cp-tree.h (maybe_constexpr_fn): Declare. + * semantics.c (find_std_constant_evaluated_r): New. + (maybe_warn_for_constant_evaluated): New. + (finish_if_stmt_cond): Call it. + +2021-06-10 Patrick Palka <ppalka@redhat.com> + + PR c++/67829 + * pt.c (unify) <case BOUND_TEMPLATE_TEMPLATE_PARM>: When + the TEMPLATE_DECL of a BOUND_TEMPLATE_TEMPLATE_PARM argument is + a template template parameter, adjust to the + TEMPLATE_TEMPLATE_PARAMETER before falling through. + +2021-06-10 Patrick Palka <ppalka@redhat.com> + + PR c++/100946 + * constraint.cc (normalize_placeholder_type_constraints): When + normalizing a non-templated return-type-requirement, add a dummy + level to initial_parms. + +2021-06-08 Marek Polacek <polacek@redhat.com> + + PR c++/100065 + * decl.c (grokdeclarator): Store a value-dependent + explicit-specifier even for deduction guides. + +2021-06-08 Jason Merrill <jason@redhat.com> + + * parser.c (cp_parser_string_literal): Adjust diagnostic. + +2021-06-08 Jason Merrill <jason@redhat.com> + + PR c++/100963 + * call.c (perfect_conversion_p): Check check_narrowing. + +2021-06-08 Jason Merrill <jason@redhat.com> + + PR c++/91706 + * name-lookup.c (get_class_binding): Keep a BASELINK. + (set_inherited_value_binding_p): Adjust. + * lambda.c (is_lambda_ignored_entity): Adjust. + * pt.c (lookup_template_function): Copy a BASELINK before + modifying it. + +2021-06-08 Jason Merrill <jason@redhat.com> + + PR c++/91706 + * semantics.c (baselink_for_fns): Fix BASELINK_BINFO. + +2021-06-08 Jason Merrill <jason@redhat.com> + + * module.cc (duplicate_hash::hash): Comment out. + (trees_in::tree_value): Adjust loop counter. + +2021-06-08 Jason Merrill <jason@redhat.com> + + PR c++/100102 + * init.c (build_offset_ref): Return the BASELINK for a static + member function. + +2021-06-07 Patrick Palka <ppalka@redhat.com> + + PR c++/100918 + * parser.c (cp_parser_lookup_name): Check access of the lookup + result before we potentially adjust an injected-class-name to + its TEMPLATE_DECL. + +2021-06-06 Jakub Jelinek <jakub@redhat.com> + + PR c/100902 + * parser.c (cp_parser_omp_target): Call c_omp_adjust_map_clauses + even when target is combined with other constructs. + +2021-06-04 Patrick Palka <ppalka@redhat.com> + + PR c++/100893 + * pt.c (convert_template_argument): Strip top-level cv-quals + on the substituted type of a non-type template parameter. + +2021-06-04 Patrick Palka <ppalka@redhat.com> + + PR c++/100102 + * pt.c (tsubst_function_decl): Remove old code for reducing + args when it has excess levels. + +2021-06-04 Jakub Jelinek <jakub@redhat.com> + + PR c++/100872 + * name-lookup.c (maybe_save_operator_binding): Add op_attr after all + ATTR_IS_DEPENDENT attributes in the DECL_ATTRIBUTES list rather than + to the start. + +2021-06-03 Patrick Palka <ppalka@redhat.com> + + PR c++/100592 + * decl.c (make_typename_type): After calling + lookup_template_class, adjust the result to its TYPE_NAME and + then consider the tf_keep_type_decl flag. + +2021-06-03 Patrick Palka <ppalka@redhat.com> + + PR c++/100862 + * pt.c (set_current_access_from_decl): Move to ... + * class.c (set_current_access_from_decl): ... here. + (handle_using_decl): Use it to propagate the access of the + using-enum decl to the copy of the imported enumerator. + * cp-tree.h (set_current_access_from_decl): Declare. + * decl.c (build_enumerator): Simplify using make_temp_override + and set_current_access_from_decl. + +2021-06-03 Jakub Jelinek <jakub@redhat.com> + + PR c++/100859 + * semantics.c (handle_omp_array_sections_1): For + OMP_CLAUSE_{AFFINITY,DEPEND} handle FIELD_DECL base using + finish_non_static_data_member and allow this as base. + (finish_omp_clauses): Move OMP_CLAUSE_AFFINITY + after depend only cases. Let this be diagnosed by !lvalue_p + case for OMP_CLAUSE_{AFFINITY,DEPEND} and remove useless + assert. + * pt.c (tsubst_omp_clauses): Handle OMP_CLAUSE_AFFINITY. + +2021-06-02 Jason Merrill <jason@redhat.com> + + PR c++/100838 + * call.c (convert_like_internal): Clear tf_no_cleanup when + recursing. + (build_user_type_conversion_1): Only add ck_rvalue if + LOOKUP_ONLYCONVERTING. + +2021-06-01 Patrick Palka <ppalka@redhat.com> + + PR c++/65816 + * init.c (expand_aggr_init_1): Check + type_has_non_user_provided_default_constructor instead of + type_has_user_provided_constructor. + +2021-06-01 Jason Merrill <jason@redhat.com> + + PR c++/91859 + * call.c (build_op_delete_call): Don't set CALL_FROM_NEW_OR_DELETE_P + for destroying delete. + * init.c (build_delete): Don't clobber before destroying delete. + +2021-06-01 Jason Merrill <jason@redhat.com> + + PR c++/94492 + * decl2.c (cp_warn_deprecated_use): Check warning_enabled_at. + +2021-05-31 Richard Biener <rguenther@suse.de> + + PR c++/88601 + * cp-objcp-common.c (names_builtin_p): Handle + RID_BUILTIN_SHUFFLEVECTOR. + * cp-tree.h (build_x_shufflevector): Declare. + * parser.c (cp_parser_postfix_expression): Handle + RID_BUILTIN_SHUFFLEVECTOR. + * pt.c (tsubst_copy_and_build): Handle IFN_SHUFFLEVECTOR. + * typeck.c (build_x_shufflevector): Build either a lowered + VEC_PERM_EXPR or an unlowered shufflevector via a temporary + internal function IFN_SHUFFLEVECTOR. + +2021-05-28 Jason Merrill <jason@redhat.com> + + * constexpr.c (build_data_member_initialization): Use tsi_range. + (build_constexpr_constructor_member_initializers): Likewise. + (constexpr_fn_retval, cxx_eval_statement_list): Likewise. + (potential_constant_expression_1): Likewise. + * coroutines.cc (await_statement_expander): Likewise. + (await_statement_walker): Likewise. + * module.cc (trees_out::core_vals): Likewise. + * pt.c (tsubst_expr): Likewise. + * semantics.c (set_cleanup_locs): Likewise. + +2021-05-28 Jason Merrill <jason@redhat.com> + + PR c++/100797 + PR c++/95719 + * call.c (build_over_call): Adjust base_binfo in + resolves_to_fixed_type_p case. + +2021-05-28 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/99928 + * semantics.c (handle_omp_array_sections): Copy + OMP_CLAUSE_MAP_IMPLICIT. + (finish_omp_clauses): Move not just OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT + marked clauses last, but also OMP_CLAUSE_MAP_IMPLICIT. Add + map_firstprivate_head bitmap, set it for GOMP_MAP_FIRSTPRIVATE_POINTER + maps and silently remove OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT if it is + present too. For OMP_CLAUSE_MAP_IMPLICIT silently remove the clause + if present in map_head, map_field_head or map_firstprivate_head + bitmaps. + +2021-05-28 Tobias Burnus <tobias@codesourcery.com> + + * parser.c (cp_parser_omp_clause_affinity): New. + (cp_parser_omp_clause_name, cp_parser_omp_var_list_no_open, + cp_parser_omp_all_clauses, OMP_TASK_CLAUSE_MASK): Handle affinity + clause. + * semantics.c (handle_omp_array_sections_1, handle_omp_array_sections, + finish_omp_clauses): Likewise. + +2021-05-27 Matthias Kretz <kretz@kde.org> + + PR c++/100716 + * error.c (dump_template_bindings): Include code to print + "[with" and ']', conditional on whether anything is printed at + all. This is tied to whether a semicolon is needed to separate + multiple template parameters. If the template argument repeats + the template parameter (T = T), then skip the parameter. + (dump_substitution): Moved code to print "[with" and ']' to + dump_template_bindings. + (dump_function_decl): Partial revert of PR50828, which masked + TFF_TEMPLATE_NAME for all of dump_function_decl. Now + TFF_TEMPLATE_NAME is masked for the scope of the function and + only carries through to dump_function_name. + (dump_function_name): Avoid calling dump_template_parms if + TFF_TEMPLATE_NAME is set. + +2021-05-27 Matthias Kretz <kretz@kde.org> + + PR c++/100763 + * error.c: Call dump_scope when printing a typedef. + +2021-05-27 Patrick Palka <ppalka@redhat.com> + + PR c++/99893 + * tree.c (cp_walk_subtrees) <case STATIC_ASSERT>: New case. + +2021-05-27 Jason Merrill <jason@redhat.com> + + PR c++/86355 + * pt.c (use_pack_expansion_extra_args_p): Don't compare + args from the same argument pack. + +2021-05-27 Patrick Palka <ppalka@redhat.com> + + DR 1315 + PR c++/67593 + PR c++/96555 + * pt.c (process_partial_specialization): Don't error on a + non-simple non-type template argument that involves template + parameters. + (for_each_template_parm_r): Don't walk TRAIT_EXPR, PLUS_EXPR, + MULT_EXPR, or SCOPE_REF when include_nondeduced_p is false. + +2021-05-26 Patrick Palka <ppalka@redhat.com> + + PR c++/100502 + * typeck.c (finish_class_member_access_expr): Disable ahead + of time access checking during the member lookup. + +2021-05-26 Patrick Palka <ppalka@redhat.com> + + PR c++/100368 + * tree.c (build_target_expr_with_type): Don't call force_rvalue + on CALL_EXPR initializer. Simplify now that bot_manip is no + longer a caller. + (bot_manip): Use force_target_expr instead of + build_target_expr_with_type. + +2021-05-26 Patrick Palka <ppalka@redhat.com> + + PR c++/97420 + * cvt.c (noexcept_conv_p): Remove redundant checks and simplify. + (fnptr_conv_p): Don't call non_reference. Use INDIRECT_TYPE_P + instead of TYPE_PTR_P. + * pt.c (convert_nontype_argument_function): Look through + implicit INDIRECT_REFs before calling strip_fnptr_conv. + +2021-05-25 Jakub Jelinek <jakub@redhat.com> + + PR c++/100666 + * call.c (convert_arg_to_ellipsis): For expressions with NULLPTR_TYPE + and side-effects, temporarily disable -Wunused-result warning when + building COMPOUND_EXPR. + +2021-05-21 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/99928 + * semantics.c (finish_omp_clauses): Move firstprivate clauses with + OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT to the end of the chain. Don't error + if a decl is mentioned both in map clause and in such firstprivate + clause unless OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET is also set. + +2021-05-20 Jason Merrill <jason@redhat.com> + + * call.c (reference_binding): Check for designator. + (implicit_conversion_1, build_special_member_call): Likewise. + * decl.c (reshape_init_r): Likewise. + * pt.c (do_class_deduction): Likewise. + * typeck2.c (digest_init_r): Likewise. + +2021-05-20 Jason Merrill <jason@redhat.com> + + PR c++/100489 + * decl.c (reshape_init_class): Handle designator for + member of anonymous aggregate here. + * typeck2.c (process_init_constructor_record): Not here. + +2021-05-20 Jonathan Wakely <jwakely@redhat.com> + + * call.c (maybe_warn_array_conv): Use new warning option. + * decl.c (mark_inline_variable, grokdeclarator): Likewise. + * error.c (maybe_warn_cpp0x): Likewise. + * parser.c (cp_parser_primary_expression) + (cp_parser_unqualified_id) + (cp_parser_pseudo_destructor_name) + (cp_parser_lambda_introducer) + (cp_parser_lambda_declarator_opt) + (cp_parser_selection_statement) + (cp_parser_init_statement) + (cp_parser_decomposition_declaration) + (cp_parser_function_specifier_opt) + (cp_parser_static_assert) + (cp_parser_namespace_definition) + (cp_parser_using_declaration) + (cp_parser_asm_definition) + (cp_parser_ctor_initializer_opt_and_function_body) + (cp_parser_initializer_list) + (cp_parser_type_parameter_key) + (cp_parser_member_declaration) + (cp_parser_try_block) + (cp_parser_std_attribute_spec): Likewise. + * pt.c (check_template_variable): Likewise. + +2021-05-20 Jason Merrill <jason@redhat.com> + + PR c++/100634 + * pt.c (invalid_nontype_parm_type_p): Return true for COMPLEX_TYPE. + +2021-05-20 Jason Merrill <jason@redhat.com> + + PR c++/100659 + * cp-tree.h (CONST_DECL_USING_P): Check for null TREE_TYPE. + +2021-05-19 Jason Merrill <jason@redhat.com> + + PR c++/100367 + PR c++/96299 + * method.c (genericize_spaceship): Use fold_build2 for scalar + operands. + +2021-05-19 Jason Merrill <jason@redhat.com> + + * pt.c (build_deduction_guide): Treat the implicit deduction guide + as a member of the class. + +2021-05-19 Marek Polacek <polacek@redhat.com> + + PR c++/100596 + * cp-tree.h (any_non_type_attribute_p): Remove. + * decl.c (grokdeclarator): Turn an error into a warning and only + warn for standard attributes. + * decl2.c (any_non_type_attribute_p): Remove. + * parser.c (cp_parser_elaborated_type_specifier): Turn an error + into a warning and only warn for standard attributes. + (cp_parser_member_declaration): Likewise. + +2021-05-19 Martin Liska <mliska@suse.cz> + + PR testsuite/100658 + * mangle.c (write_encoding): Fix typos. + +2021-05-19 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/99928 + * parser.c (cp_parser_omp_master): Set OMP_MASTER_COMBINED on + master when combined with taskloop. + (cp_parser_omp_parallel): Don't set OMP_PARALLEL_COMBINED on + parallel master when not combined with taskloop. + +2021-05-19 Jason Merrill <jason@redhat.com> + + PR c++/100261 + * rtti.c (get_tinfo_decl_direct): Check TYPE_TRANSPARENT_AGGR. + +2021-05-19 Jason Merrill <jason@redhat.com> + + PR c++/100372 + * tree.c (strip_typedefs): Only look at the pattern of a + TYPE_PACK_EXPANSION if it's a type. + +2021-05-18 Marek Polacek <polacek@redhat.com> + + * class.c (classtype_has_non_deleted_copy_ctor): Remove. + * constraint.cc (contains_wildcard_p): Likewise. + (get_template_head_requirements): Likewise. + (check_constrained_friend): Likewise. + (subsumes_constraints): Likewise. + * cp-tree.h (classtype_has_non_deleted_copy_ctor): Likewise. + (push_void_library_fn): Likewise. + (get_pattern_parm): Likewise. + (get_template_parms_at_level): Likewise. + (lambda_return_type): Likewise. + (get_template_head_requirements): Likewise. + (check_constrained_friend): Likewise. + (subsumes_constraints): Likewise. + * decl.c (push_void_library_fn): Likewise. + * lambda.c (lambda_return_type): Likewise. + * pt.c (get_template_parms_at_level): Likewise. + (get_pattern_parm): Likewise. + +2021-05-18 Jason Merrill <jason@redhat.com> + + PR c++/100644 + * call.c (perfect_candidate_p): An implicitly deleted move + is not perfect. + +2021-05-18 Andreas Krebbel <krebbel@linux.ibm.com> + + PR c++/100281 + * cvt.c (cp_convert_to_pointer): Use the size of the target + pointer type. + * tree.c (cp_build_reference_type): Call + cp_build_reference_type_for_mode with VOIDmode. + (cp_build_reference_type_for_mode): Rename from + cp_build_reference_type. Add MODE argument and invoke + build_reference_type_for_mode. + (strip_typedefs): Use build_pointer_type_for_mode and + cp_build_reference_type_for_mode for pointers and references. + +2021-05-17 Jonathan Wakely <jwakely@redhat.com> + + PR c++/100635 + * call.c (convert_like_internal): Print different diagnostic if + the lvalue reference is const. + +2021-05-14 Jason Merrill <jason@redhat.com> + + PR c++/95870 + * pt.c (enclosing_instantiation_of): Just compare + DECL_SOURCE_LOCATION. + (regenerate_decl_from_template): Copy DECL_SOURCE_LOCATION. + +2021-05-14 Marek Polacek <polacek@redhat.com> + Jason Merrill <jason@redhat.com> + + PR c++/99032 + * cp-tree.h (any_non_type_attribute_p): Declare. + * decl.c (grokdeclarator): Diagnose when an attribute appertains to + a friend declaration that is not a definition. + * decl2.c (any_non_type_attribute_p): New. + * parser.c (cp_parser_decl_specifier_seq): Diagnose standard attributes + in the middle of decl-specifiers. + (cp_parser_elaborated_type_specifier): Diagnose when an attribute + appertains to a friend declaration that is not a definition. + (cp_parser_member_declaration): Likewise. + +2021-05-12 Marek Polacek <polacek@redhat.com> + + * pt.c (tsubst_copy_and_build): Add warn_int_in_bool_context + sentinel. + +2021-05-12 Marcel Vollweiler <marcel@codesourcery.com> + + * parser.c (cp_parser_omp_clause_map): Support map-type-modifier + 'close'. + +2021-05-11 Jason Merrill <jason@redhat.com> + + PR c++/100517 + * typeck.c (build_reinterpret_cast_1): Check intype on + cast to vector. + +2021-05-11 Patrick Palka <ppalka@redhat.com> + + PR c++/51577 + * name-lookup.c (maybe_save_operator_binding): Unconditionally + enable for all function templates, not just generic lambdas. + Handle compound-assignment operator expressions. + * typeck.c (build_x_compound_expr): Call maybe_save_operator_binding + in the type-dependent case. + (build_x_modify_expr): Likewise. Move declaration of 'op' closer + to its first use. + +2021-05-11 Patrick Palka <ppalka@redhat.com> + + PR c++/100138 + * constraint.cc (tsubst_constraint): Set up cp_unevaluated. + (satisfy_atom): Set up iloc_sentinel before calling + cxx_constant_value. + * pt.c (tsubst_pack_expansion): When returning a rebuilt pack + expansion, carry over PACK_EXPANSION_LOCAL_P and + PACK_EXPANSION_SIZEOF_P from the original pack expansion. + +2021-05-10 Richard Biener <rguenther@suse.de> + + PR middle-end/100464 + PR c++/100468 + * call.c (set_up_extended_ref_temp): Mark the temporary + addressable if the TARGET_EXPR was. + +2021-05-10 Martin Liska <mliska@suse.cz> + + * decl.c (duplicate_decls): Use startswith + function instead of strncmp. + (cxx_builtin_function): Likewise. + (omp_declare_variant_finalize_one): Likewise. + (grokfndecl): Likewise. + * error.c (dump_decl_name): Likewise. + * mangle.c (find_decomp_unqualified_name): Likewise. + (write_guarded_var_name): Likewise. + (decl_tls_wrapper_p): Likewise. + * parser.c (cp_parser_simple_type_specifier): Likewise. + (cp_parser_tx_qualifier_opt): Likewise. + * pt.c (template_parm_object_p): Likewise. + (dguide_name_p): Likewise. + +2021-05-10 Martin Liska <mliska@suse.cz> + + PR c++/99616 + * decl.c (grokdeclarator): Remove redundant NULL check. + +2021-05-07 Jason Merrill <jason@redhat.com> + + * tree.c (rvalue): Assert expr is not a class lvalue. + +2021-05-07 Jason Merrill <jason@redhat.com> + + * cp-tree.h (build_stub_object): Declare. + * method.c (build_stub_object): No longer static. + * call.c (can_convert): Use it. + * tree.c (build_dummy_object): Adjust comment. + * typeck.c (cp_build_binary_op): Wrap SPACESHIP_EXPR in a + TARGET_EXPR. + +2021-05-07 Jason Merrill <jason@redhat.com> + + * coroutines.cc (build_co_await): Don't call 'rvalue'. + (flatten_await_stmt): Simplify initialization. + (morph_fn_to_coro): Change 'rvalue' to 'move'. Simplify. + +2021-05-04 Tobias Burnus <tobias@codesourcery.com> + + * semantics.c (finish_omp_reduction_clause): Accept float + complex + for || and && reductions. + +2021-05-03 Patrick Palka <ppalka@redhat.com> + + PR c++/100362 + * parser.c (cp_parser_class_head): Reinstate calls to pushclass + and popclass when parsing the base-clause that were removed in + r11-6815. + +2021-05-03 Patrick Palka <ppalka@redhat.com> + + PR c++/68942 + PR c++/100344 + * pt.c (tsubst_copy_and_build) <case CALL_EXPR>: Set tf_conv + only when the callee is a FUNCTION_DECL. + +2021-05-03 Marek Polacek <polacek@redhat.com> + + PR c++/100055 + * decl.c (grokfndecl): Check current_template_parms. + +2021-05-03 Marek Polacek <polacek@redhat.com> + + DR 1312 + * constexpr.c (cxx_eval_constant_expression): Don't check + integer_zerop. + +2021-05-01 Jason Merrill <jason@redhat.com> + + * cp-tree.h (class ovl_iterator): Allow copying. Add op==. + (class ovl_range, class lkp_range): New. + * call.c (build_op_call_1, add_candidates): Use them. + (build_op_delete_call, has_trivial_copy_assign_p): Likewise. + (has_trivial_copy_p): Likewise. + * class.c (handle_using_decl, get_basefndecls): Likewise. + (maybe_warn_about_overly_private_class): Likewise. + (warn_hidden, add_implicitly_declared_members): Likewise. + (check_methods, clone_constructors_and_destructors): Likewise. + (type_has_user_nondefault_constructor): Likewise. + +2021-04-29 Jason Merrill <jason@redhat.com> + + * constexpr.c (cxx_fold_indirect_ref_1): Only set *empty_base if we + don't find a field. + +2021-04-29 Jason Merrill <jason@redhat.com> + + PR c++/51344 + * decl2.c (grokfield): Call cplus_decl_attributes for friend. + (save_template_attributes): Use chainon. + * friend.c (do_friend): Remove attrlist parm. + * cp-tree.h (do_friend): Adjust. + * class.c (add_implicitly_declared_members): Adjust. + * decl.c (grokdeclarator): Adjust. + * pt.c (apply_late_template_attributes): Optimize. + +2021-04-29 Jason Merrill <jason@redhat.com> + + PR c++/97974 + * class.c (finish_struct_anon_r): Drop complain parm. + Remove non-field diagnostic. + (finish_struct_anon): Adjust. + * decl.c (fixup_anonymous_aggr): Move non-field diagnostic here. + +2021-04-29 Jason Merrill <jason@redhat.com> + + * cp-tree.h (cp_evaluated): Add reset parm to constructor. + * parser.c (cp_parser_constant_expression): Change + allow_non_constant_p to int. Use cp_evaluated. + (cp_parser_initializer_clause): Pass 2 to allow_non_constant_p. + * semantics.c (finish_id_expression_1): Don't mess with + cp_unevaluated_operand here. + +2021-04-29 Jason Merrill <jason@redhat.com> + + * cp-tree.h: Clarify comments. + * pt.c (get_template_parm_object): Add assert. + * semantics.c (finish_compound_literal): Clear TREE_HAS_CONSTRUCTOR. + * tree.c (zero_init_expr_p): Check TREE_HAS_CONSTRUCTOR. + * typeck2.c (store_init_value): Likewise. + +2021-04-29 Patrick Palka <ppalka@redhat.com> + + PR c++/68942 + * pt.c (tsubst_copy_and_build) <case CALL_EXPR>: When KOENIG_P, + set tf_conv during the initial substitution into the function. + +2021-04-29 Jakub Jelinek <jakub@redhat.com> + + PR c++/100319 + * semantics.c (finish_omp_clauses): Fix up check that variable + mentioned in detach clause doesn't appear in data-sharing clauses. + +2021-04-28 Jakub Jelinek <jakub@redhat.com> + + * module.cc: Remove #error that triggers if DEV-PHASE is empty. + +2021-04-27 Jason Merrill <jason@redhat.com> + + PR c++/92145 + * class.c (classtype_has_depr_implicit_copy): Check DECL_CONTEXT + of operator=. + +2021-04-27 Patrick Palka <ppalka@redhat.com> + + PR c++/88580 + * pt.c (tsubst_initializer_list): Correctly handle the case + where an argument inside a base initializer pack expansion is + itself a pack expansion. + +2021-04-26 Patrick Palka <ppalka@redhat.com> + + PR c++/100209 + * constexpr.c (cxx_fold_indirect_ref): Try to canonicalize the + object/offset pair for a POINTER_PLUS_EXPR of a COMPONENT_REF + with a negative offset into one whose offset is nonnegative + before calling cxx_fold_indirect_ref_1. + +2021-04-24 Patrick Palka <ppalka@redhat.com> + + PR c++/89565 + PR c++/93383 + PR c++/95291 + PR c++/99200 + PR c++/99683 + * pt.c (do_class_deduction): Punt if the initializer is + type-dependent. + +2021-04-24 Patrick Palka <ppalka@redhat.com> + + PR c++/87709 + * parser.c (cp_parser_type_id_1): If we see a template + placeholder, first try simulating an error before issuing + a real error. + +2021-04-23 Patrick Palka <ppalka@redhat.com> + + PR c++/98767 + * cxx-pretty-print.c (pp_cxx_parameter_declaration_clause): + Adjust parameter list loop to iterate over 'types' instead of + 'args'. Output the trailing '...' for a variadic function. + Remove PARM_DECL support. + (pp_cxx_requires_expr): Pretty print the parameter list directly + instead of going through pp_cxx_parameter_declaration_clause. + +2021-04-23 Patrick Palka <ppalka@redhat.com> + + DR 2374 + * decl.c (is_direct_enum_init): Check the implicit + convertibility requirement added by CWG 2374. + +2021-04-23 Martin Liska <mliska@suse.cz> + + * cp-tree.h (STATIC_ASSERT): Prefer static assert. + * lex.c (init_operators): Remove run-time check. + +2021-04-22 Marek Polacek <polacek@redhat.com> + + PR c++/100161 + * pt.c (tsubst_copy_and_build) <case PLUS_EXPR>: Test op0 and + op1 separately for value- or type-dependence. + +2021-04-21 Marek Polacek <polacek@redhat.com> + + PR c++/96380 + * parser.c (cp_parser_enum_specifier): Don't allow defining + types in enum-base. + +2021-04-21 Martin Liska <mliska@suse.cz> + + Revert: + 2021-04-21 Martin Liska <mliska@suse.cz> + + * error.c (dump_decl): Use flags in dump_generic_node call. + +2021-04-21 Martin Liska <mliska@suse.cz> + + * error.c (dump_decl): Use flags in dump_generic_node call. + +2021-04-21 Martin Liska <mliska@suse.cz> + + * error.c (dump_decl): Support anonymous labels. + +2021-04-20 Jason Merrill <jason@redhat.com> + + PR c++/100109 + * pt.c (find_parameter_packs_r): Look into enum initializers. + +2021-04-19 Marek Polacek <polacek@redhat.com> + + PR c++/97536 + * decl.c (grokvardecl): Given an error when a concept is not defined + at namespace scope. + +2021-04-16 Jakub Jelinek <jakub@redhat.com> + + PR c++/100111 + * constexpr.c (cxx_eval_store_expression): Don't add CONSTRUCTORs + for empty classes into *valp when types don't match even when *valp + is NULL. + +2021-04-16 Marek Polacek <polacek@redhat.com> + + PR c++/99803 + * decl.c (make_typename_type): Give an error and return when + name is is_overloaded_fn. + * parser.c (cp_parser_class_name): Don't check is_overloaded_fn + before calling make_typename_type. + +2021-04-16 Patrick Palka <ppalka@redhat.com> + + PR c++/99700 + * constexpr.c (reduced_constant_expression_p): For array + CONSTRUCTORs, use a dedicated loop that additionally verifies + the CONSTRUCTOR spans the entire array. + +2021-04-16 Jakub Jelinek <jakub@redhat.com> + + PR c++/99850 + * parser.c (cp_parser_constraint_requires_parens) <case CPP_DEREF>: + If lambda_p, return pce_ok instead of pce_maybe_postfix. + +2021-04-16 Jakub Jelinek <jakub@redhat.com> + + PR c++/99833 + * pt.c (extract_locals_r): When handling DECL_EXPR of a structured + binding, add to data.internal also all corresponding structured + binding decls. + +2021-04-16 Jason Merrill <jason@redhat.com> + + PR c++/100079 + * cp-tree.h (first_field): Declare. + * mangle.c (range_expr_nelts): New. + (write_expression): Improve class NTTP mangling. + * pt.c (get_template_parm_object): Clear TREE_HAS_CONSTRUCTOR. + * tree.c (zero_init_expr_p): Improve class NTTP handling. + * decl.c: Adjust comment. + +2021-04-15 Jason Merrill <jason@redhat.com> + + PR c++/80456 + * call.c (build_new_method_call_1): Check again for side-effects + with a volatile object. + +2021-04-15 Jason Merrill <jason@redhat.com> + + PR c++/100101 + PR c++/99583 + * pt.c (find_parameter_packs_r) [FUNCTION_TYPE]: Walk into + TYPE_RAISES_EXCEPTIONS here. + * tree.c (cp_walk_subtrees): Not here. + +2021-04-15 Jason Merrill <jason@redhat.com> + + PR c++/100091 + PR c++/99478 + * parser.c (cp_parser_default_type_template_argument): Set + parser->local_variables_forbidden_p. + +2021-04-15 Richard Sandiford <richard.sandiford@arm.com> + + PR c++/98852 + * typeck.c (merge_type_attributes_from): New function. + (cp_common_type): Use it for vector types. + +2021-04-14 Jason Merrill <jason@redhat.com> + + PR c++/100078 + PR c++/93085 + * pt.c (uses_outer_template_parms): Also look at default + template argument. + +2021-04-14 Jason Merrill <jason@redhat.com> + + PR c++/93314 + * semantics.c (finish_id_expression_1): Clear cp_unevaluated_operand + for a non-static data member in a constant-expression. + +2021-04-14 Patrick Palka <ppalka@redhat.com> + + PR c++/83476 + PR c++/99885 + * pt.c (deducible_expression): Look through implicit + INDIRECT_REFs as well. + +2021-04-14 Jason Merrill <jason@redhat.com> + + PR c++/99478 + * parser.c (cp_parser_lambda_expression): Reject lambda + in template parameter type. + +2021-04-14 Jason Merrill <jason@redhat.com> + + PR c++/90674 + * decl.c (duplicate_decls): Don't propagate + DECL_INITIALIZED_IN_CLASS_P to a specialization. + +2021-04-14 Jason Merrill <jason@redhat.com> + + PR c++/88742 + PR c++/49951 + PR c++/58123 + * semantics.c (set_cleanup_locs): New. + (do_poplevel): Call it. + * parser.c (cp_parser_compound_statement): Consume the } + before finish_compound_stmt. + +2021-04-13 Jason Merrill <jason@redhat.com> + + PR c++/100032 + * pt.c (get_underlying_template): Compare TYPE_QUALS. + +2021-04-13 Jason Merrill <jason@redhat.com> + + PR c++/100054 + PR c++/90479 + * init.c (get_nsdmi): Do more context adjustment for local classes. + +2021-04-13 Patrick Palka <ppalka@redhat.com> + + PR c++/99008 + * pt.c (do_class_deduction): Reject alias CTAD in C++17 mode + rather than issuing a pedwarn. + * typeck2.c (build_functional_cast_1): Handle CTAD uniformly + for consistent diagnostics. + +2021-04-13 Jason Merrill <jason@redhat.com> + + PR c++/91933 + * class.c (build_base_path): Shortcut simple non-pointer case. + +2021-04-13 Eric Botcazou <ebotcazou@adacore.com> + + * module.cc (ordinary_loc_of): Test LINEMAPS_MACRO_LOWEST_LOCATION + of the linemap. + (module_state::write_location): Likewise. + +2021-04-13 Patrick Palka <ppalka@redhat.com> + + PR c++/97134 + * pt.c (do_class_deduction): Look through EXPR_PACK_EXPANSION + when checking if the initializer is an equivalent class + placeholder template parameter. + +2021-04-13 Patrick Palka <ppalka@redhat.com> + + PR c++/99961 + PR c++/99994 + * constraint.cc (satisfy_normalized_constraints): Set + cp_unevaluated. + * parser.c (cp_parser_concept_definition): Likewise. + (cp_parser_requires_clause_opt): Likewise. + +2021-04-12 Jason Merrill <jason@redhat.com> + + PR c++/93085 + * pt.c (uses_outer_template_parms): Handle non-type and template + template parameters specifically. + +2021-04-11 Jason Merrill <jason@redhat.com> + + PR c++/97974 + * decl.c (fixup_anonymous_aggr): Prune all functions from + CLASSTYPE_MEMBER_VEC. + +2021-04-10 Jason Merrill <jason@redhat.com> + + PR c++/98800 + PR c++/97399 + * parser.c (cp_parser_direct_declarator): Don't + inject_this_parameter if static_p. + (cp_parser_omp_var_list_no_open): Parse 'this' even if + current_class_ptr isn't set for a better diagnostic. + +2021-04-10 Jason Merrill <jason@redhat.com> + + PR c++/99180 + PR c++/93295 + PR c++/93867 + PR c++/99118 + PR c++/96873 + * pt.c (alias_ctad_tweaks): Handle failure better. + +2021-04-10 Jason Merrill <jason@redhat.com> + + PR c++/100006 + * pt.c (find_parameter_packs_r) [TAG_DEFN]: Look into bases. + +2021-04-09 Patrick Palka <ppalka@redhat.com> + + * cp-tree.h (LAMBDA_EXPR_REGENERATED_FROM) + (LAMBDA_EXPR_REGENERATING_TARGS): Replace these with ... + (LAMBDA_EXPR_REGEN_INFO): ... this. + (tree_lambda_expr::regenerated_from) + (tree_lambda_expr::regenerating_targs): Replace these with ... + (tree_lambda_expr::regen_info): ... this. + * constraint.cc (satisfy_declaration_constraints): Adjust + accordingly. + * lambda.c (build_lambda_expr): Likewise. + * pt.c (regenerated_lambda_fn_p): Likewise. + (most_general_lambda): Likewise. + (tsubst_lambda_expr): Likewise. + +2021-04-09 Marek Polacek <polacek@redhat.com> + + PR c++/99806 + * parser.c (cp_parser_member_declaration): Call + cp_parser_save_default_args even for function templates. Use + STRIP_TEMPLATE on the declaration we're passing. + +2021-04-08 Patrick Palka <ppalka@redhat.com> + + PR c++/99874 + * constraint.cc (get_normalized_constraints_from_decl): Handle + regenerated lambdas. + (satisfy_declaration_constraints): Likewise. Check for + dependent args later. + * cp-tree.h (LAMBDA_EXPR_INSTANTIATED): Replace with ... + (LAMBDA_EXPR_REGENERATED_FROM): ... this. + (LAMBDA_EXPR_REGENERATING_TARGS): New. + (tree_lambda_expr::regenerated_from): New data member. + (tree_lambda_expr::regenerating_targs): New data member. + (add_to_template_args): Declare. + (regenerated_lambda_fn_p): Likewise. + (most_general_lambda): Likewise. + * lambda.c (build_lambda_expr): Set LAMBDA_EXPR_REGENERATED_FROM + and LAMBDA_EXPR_REGENERATING_TARGS. + * pt.c (add_to_template_args): No longer static. + (tsubst_function_decl): Unconditionally propagate constraints on + the substituted function decl. + (instantiated_lambda_fn_p): Rename to ... + (regenerated_lambda_fn_p): ... this. Check + LAMBDA_EXPR_REGENERATED_FROM instead of + LAMBDA_EXPR_INSTANTIATED. + (most_general_lambda): Define. + (enclosing_instantiation_of): Adjust after renaming + instantiated_lambda_fn_p. + (tsubst_lambda_expr): Don't set LAMBDA_EXPR_INSTANTIATED. Set + LAMBDA_EXPR_REGENERATED_FROM and LAMBDA_EXPR_REGENERATING_TARGS. + Don't substitute or set constraints on the regenerated lambda. + +2021-04-08 Patrick Palka <ppalka@redhat.com> + + PR c++/97679 + * pt.c (build_deduction_guide): Document OUTER_ARGS. Substitute + them into the propagated constraints. + +2021-04-08 Jason Merrill <jason@redhat.com> + + PR c++/91849 + * call.c (convert_like_internal): Improve reference diagnostic. + +2021-04-08 Jakub Jelinek <jakub@redhat.com> + + PR c++/99859 + * constexpr.c (addr_of_non_const_var): New function. + (cxx_bind_parameters_in_call): Set *non_constant_args to true + even if cp_walk_tree on arg with addr_of_non_const_var callback + returns true. + +2021-04-08 Jason Merrill <jason@redhat.com> + + PR c++/94529 + * pt.c (determine_specialization): Improve diagnostic. + +2021-04-08 Marek Polacek <polacek@redhat.com> + + PR c++/99844 + * decl.c (build_explicit_specifier): Call + check_for_bare_parameter_packs. + * except.c (build_noexcept_spec): Likewise. + +2021-04-07 Jason Merrill <jason@redhat.com> + + PR c++/41723 + * parser.c (cp_parser_class_name): Check dependent_scope_p. + +2021-04-07 Jason Merrill <jason@redhat.com> + + PR c++/52625 + * pt.c (maybe_process_partial_specialization): Check + DECL_SELF_REFERENCE_P. + +2021-04-07 Jason Merrill <jason@redhat.com> + + PR c++/92918 + * name-lookup.c (push_class_level_binding_1): Do overload a new + function with a previous using-declaration. + +2021-04-06 Jason Merrill <jason@redhat.com> + + PR c++/96673 + * init.c (get_nsdmi): Don't defer access checking. + +2021-04-06 Jason Merrill <jason@redhat.com> + + PR c++/99901 + * decl.c (cp_finish_decl): mark_needed an implicitly inline + static data member with an out-of-class redeclaration. + +2021-04-06 Jason Merrill <jason@redhat.com> + + PR c++/91241 + * mangle.c (write_compact_number): Add sanity check. + (write_local_name): Use list_length for parm number. + +2021-04-06 Patrick Palka <ppalka@redhat.com> + + PR c++/99899 + * pt.c (do_auto_deduction): Don't exit early when deducing the + array type of a structured binding. Also handle adc_decomp_type + during constraint checking. + +2021-04-05 Jason Merrill <jason@redhat.com> + + PR c++/96311 + * typeck.c (check_return_expr): Call mark_exp_read in dependent + case. + +2021-04-05 Jason Merrill <jason@redhat.com> + + PR c++/98440 + * typeck.c (build_reinterpret_cast_1): Don't perform + temporary materialization. + +2021-04-05 Jason Merrill <jason@redhat.com> + + PR c++/95317 + * pt.c (lookup_template_class_1): Do tsubst_enum when + tsubsting a generic lambda. + +2021-04-05 Jason Merrill <jason@redhat.com> + + PR c++/95870 + * pt.c (enclosing_instantiation_of): Compare DECL_SOURCE_LOCATION if + there is no enclosing non-lambda function. + +2021-04-05 Nathan Sidwell <nathan@acm.org> + + PR c++/99380 + * module.cc (name_pending_imports): Drop 'atend' parm. Don't + query export when not needed. + (preprocess_module, preprocessed_module): Adjust. + +2021-04-05 Jason Merrill <jason@redhat.com> + + PR c++/99066 + * pt.c (mark_decl_instantiated): Set DECL_EXTERNAL. + +2021-04-05 Jason Merrill <jason@redhat.com> + + PR c++/99201 + * pt.c (class el_data): Add visited field. + (extract_local_specs): Pass it to cp_walk_tree. + (extract_locals_r): Walk into the body of a lambda. + +2021-04-05 Jason Merrill <jason@redhat.com> + + * ptree.c (cxx_print_decl): Check DECL_MODULE_IMPORT_P on + template result. + +2021-04-04 Jason Merrill <jason@redhat.com> + + PR c++/99643 + * typeck2.c (massage_init_elt): Don't strip TARGET_EXPR. + +2021-04-03 Marek Polacek <polacek@redhat.com> + + PR c++/91416 + * parser.c: Create a GC root for attributes in a decl specifier. + (cp_parser_type_specifier): Push/pop ->attributes onto/from it. + +2021-04-03 Jason Merrill <jason@redhat.com> + + PR c++/91217 + * pt.c (tsubst_lambda_expr): Skip the body block from + DECL_SAVED_TREE. + +2021-04-03 Jason Merrill <jason@redhat.com> + + PR c++/90664 + * cvt.c (can_convert_qual): Check fnptr_conv_p. + +2021-04-03 Jason Merrill <jason@redhat.com> + + PR c++/97900 + * pt.c (regenerate_decl_from_template): tsubst_decl + the parms. + +2021-04-02 Patrick Palka <ppalka@redhat.com> + + PR c++/99869 + * parser.c (do_range_for_auto_deduction): Pass adc_variable_type + to do_auto_deduction. + +2021-04-02 Patrick Palka <ppalka@redhat.com> + + PR c++/99586 + * semantics.c (finish_compound_literal): Check + template_placeholder_p instead of type_uses_auto. + +2021-04-02 Jason Merrill <jason@redhat.com> + + PR c++/97938 + * cp-tree.h (PACK_EXPANSION_AUTO_P): New. + * lambda.c (add_capture): Set it. + * pt.c (tsubst_pack_expansion): Handle it. + +2021-04-02 Nathan Sidwell <nathan@acm.org> + + * cp-tree.h (lang_decl_base): Correct module flag comment. + * module.cc (trees_in::assert_definition): Break out + not_tmpl var. + (trees_out::lang_decl_bools): Do not write purview for header units. + +2021-04-01 Marek Polacek <polacek@redhat.com> + + PR c++/99831 + * method.c (defaulted_late_check): ++ and -- function_depth around + the call to synthesize_method. + * pt.c: Remove the saved_trees global. + +2021-04-01 Jason Merrill <jason@redhat.com> + + PR c++/99583 + PR c++/99584 + * tree.c (cp_walk_subtrees) [FUNCTION_TYPE]: Walk into + TYPE_RAISES_EXCEPTIONS. + +2021-04-01 Iain Sandoe <iain@sandoe.co.uk> + + * mapper-client.cc (INCLUDE_MAP): New; require map to be + included from system.h. + * mapper-resolver.cc (INCLUDE_MAP): Likewise. + +2021-04-01 Jason Merrill <jason@redhat.com> + + PR c++/98481 + * mangle.c (write_expression): Adjust. + * class.c (find_abi_tags_r): Disable PR98481 fix for ABI v14. + (mark_abi_tags_r): Likewise. + +2021-04-01 Nathan Sidwell <nathan@acm.org> + + PR c++/99283 + * module.cc (trees_out::decl_node): Adjust importedness reference + assert. + (module_state::intercluster_seed): New. Seed both imports and + inter-cluster references. Broken out of ... + (module_state::write_cluster): ... here. Call it. + +2021-03-31 Jason Merrill <jason@redhat.com> + + PR c++/99445 + * tree.c (strip_typedefs): Handle TYPE_PACK_EXPANSION. + +2021-03-31 Patrick Palka <ppalka@redhat.com> + + PR c++/88115 + * mangle.c (write_expression): Adjust the mangling of + __alignof__. + +2021-03-31 Patrick Palka <ppalka@redhat.com> + + PR c++/99815 + * pt.c (placeholder_type_constraint_dependent_p): Expand + argument packs to separate the first non-pack argument + from the rest. + +2021-03-30 Nathan Sidwell <nathan@acm.org> + + PR c++/99283 + * module.cc (dumper::operator): Make less brittle. + (trees_out::core_bools): VAR_DECLs always have a context. + (trees_out::key_mergeable): Use same_type_p for asserting. + (trees_in::read_var_def): Propagate + DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P. + +2021-03-30 Jakub Jelinek <jakub@redhat.com> + + PR c++/99790 + * cp-gimplify.c (cp_gimplify_expr): Handle PTRMEM_CST. + +2021-03-26 Marek Polacek <polacek@redhat.com> + + PR c++/98352 + * method.c (implicitly_declare_fn): Pass &raises to + synthesized_method_walk. + +2021-03-26 Nathan Sidwell <nathan@acm.org> + + PR c++/99283 + * cp-tree.h (DECL_MODULE_CHECK): Ban TEMPLATE_DECL. + (SET_TYPE_TEMPLATE_INFO): Restore Alias template setting. + * decl.c (duplicate_decls): Remove template_decl module flag + propagation. + * module.cc (merge_kind_name): Add alias tmpl spec as a thing. + (dumper::impl::nested_name): Adjust for template-decl module flag + change. + (trees_in::assert_definition): Likewise. + (trees_in::install_entity): Likewise. + (trees_out::decl_value): Likewise. Remove alias template + separation of template and type_decl. + (trees_in::decl_value): Likewise. + (trees_out::key_mergeable): Likewise, + (trees_in::key_mergeable): Likewise. + (trees_out::decl_node): Adjust for template-decl module flag + change. + (depset::hash::make_dependency): Likewise. + (get_originating_module, module_may_redeclare): Likewise. + (set_instantiating_module, set_defining_module): Likewise. + * name-lookup.c (name_lookup::search_adl): Likewise. + (do_pushdecl): Likewise. + * pt.c (build_template_decl): Likewise. + (lookup_template_class_1): Remove special alias_template handling + of DECL_TI_TEMPLATE. + (tsubst_template_decl): Likewise. + +2021-03-26 Jakub Jelinek <jakub@redhat.com> + + PR c++/99705 + * tree.c (bot_manip): Remap artificial automatic temporaries mentioned + in DECL_EXPR or in BIND_EXPR_VARS. + +2021-03-25 Jakub Jelinek <jakub@redhat.com> + + PR c++/99672 + * parser.c (cp_parser_postfix_expression): For calls, create + combined_loc and temporarily set input_location to it before + calling finish_call_expr. + +2021-03-25 Marek Polacek <polacek@redhat.com> + + PR c++/94751 + * call.c (build_over_call): Maybe call mark_used in case + deduce_inheriting_ctor fails and return error_mark_node. + * cp-tree.h (deduce_inheriting_ctor): Adjust declaration. + * method.c (deduce_inheriting_ctor): Return bool if the deduction + fails. + (implicitly_declare_fn): If raises is error_mark_node, call + synthesized_method_walk with diag being true. + +2021-03-25 Jakub Jelinek <jakub@redhat.com> + + PR c++/99745 + * decl2.c (grokbitfield): Diagnose bitfields containing bare parameter + packs and don't set DECL_BIT_FIELD_REPRESENTATIVE in that case. + +2021-03-25 Marek Polacek <polacek@redhat.com> + + PR c++/99331 + * call.c (build_converted_constant_expr_internal): Don't emit + -Wconversion warnings. + +2021-03-25 Jakub Jelinek <jakub@redhat.com> + + PR c++/99565 + * call.c (build_conditional_expr_1): Pass OEP_ADDRESS_OF_SAME_FIELD + to operand_equal_p. + * cvt.c (convert_to_void): Preserve location_t on COND_EXPR or + or COMPOUND_EXPR. + +2021-03-23 Nathan Sidwell <nathan@acm.org> + + PR c++/99283 + * name-lookup.c (check_module_override): Set global or partition + DUP on the binding vector. + +2021-03-23 Marek Polacek <polacek@redhat.com> + + PR c++/99318 + * decl2.c (cp_warn_deprecated_use_scopes): Only call + cp_warn_deprecated_use when decl is a namespace, class, or enum. + +2021-03-23 Nathan Sidwell <nathan@acm.org> + + PR c++/99239 + * decl.c (duplicate_decls): Remove assert about maybe-imported + artificial decls. + +2021-03-23 Jakub Jelinek <jakub@redhat.com> + + PR c++/99650 + * decl.c (cp_finish_decomp): Diagnose void initializers when + using tuple_element and get. + +2021-03-22 Nathan Sidwell <nathan@acm.org> + + PR c++/99480 + * module.cc (depset::hash::make_dependency): Propagate flags for + partial specialization. + (module_may_redeclare): Handle partial specialization. + +2021-03-22 Nathan Sidwell <nathan@acm.org> + + PR c++/99425 + * cp-tree.h (map_context_from, map_context_to): Delete. + (add_mergeable_specialization): Add is_alias parm. + * pt.c (add_mergeable_specialization): Add is_alias parm, add them. + * module.cc (map_context_from, map_context_to): Delete. + (trees_in::decl_value): Add specializations later, adjust call. + Drop useless alias lookup. Set duplicate fn parm context. + (check_mergeable_decl): Drop context mapping. + (trees_in::is_matching_decl): Likewise. + (trees_in::read_function_def): Drop parameter context adjustment + here. + +2021-03-22 Martin Liska <mliska@suse.cz> + + PR c++/99687 + * module.cc (fini_modules): Call vec_free instead of delete. + +2021-03-20 Jakub Jelinek <jakub@redhat.com> + + PR debug/99230 + * cp-gimplify.c (cp_genericize_r) <case STATEMENT_LIST>: Remove + special code, instead call c_genericize_control_stmt. + +2021-03-19 Jakub Jelinek <jakub@redhat.com> + + PR c++/99456 + * constexpr.c (cxx_eval_constant_expression): For CONVERT_EXPR from + INDIRECT_TYPE_P to ARITHMETIC_TYPE_P, when !ctx->manifestly_const_eval + don't diagnose it, set *non_constant_p nor return t. + +2021-03-19 Marek Polacek <polacek@redhat.com> + + PR c++/99500 + * parser.c (cp_parser_requirement_parameter_list): Handle + error_mark_node. + +2021-03-18 Marek Polacek <polacek@redhat.com> + + * pt.c (tsubst_copy_and_build) <case FLOAT_EXPR>: Remove. + +2021-03-18 Marek Polacek <polacek@redhat.com> + + * pt.c (tsubst_copy_and_build): Add assert. + +2021-03-18 Iain Sandoe <iain@sandoe.co.uk> + + PR objc++/49070 + * parser.c (cp_debug_parser): Add Objective-C++ message + state flag. + (cp_parser_nested_name_specifier_opt): Allow colon to + terminate an assignment-expression when parsing Objective- + C++ messages. + (cp_parser_objc_message_expression): Set and clear message + parsing state on entry and exit. + * parser.h (struct cp_parser): Add a context flag for + Objective-C++ message state. + +2021-03-18 Martin Liska <mliska@suse.cz> + + PR c++/99617 + * coroutines.cc (struct var_nest_node): Init then_cl and else_cl + to NULL. + +2021-03-17 Marek Polacek <polacek@redhat.com> + + PR c++/97973 + * call.c (conv_unsafe_in_template_p): New. + (convert_like): Use it. + +2021-03-17 Anthony Sharp <anthonysharp15@gmail.com> + Jason Merrill <jason@redhat.com> + + * semantics.c (get_class_access_diagnostic_decl): New + function that examines special cases when a parent + class causes a private access failure. + (enforce_access): Slightly modified to call function + above. + 2021-03-16 Jason Merrill <jason@redhat.com> * tree.c (cp_tree_equal): Use real_identical. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 29f4b50..b6011c1 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -175,17 +175,17 @@ static struct z_candidate *splice_viable (struct z_candidate *, bool, bool *); static bool any_strictly_viable (struct z_candidate *); static struct z_candidate *add_template_candidate (struct z_candidate **, tree, tree, tree, tree, const vec<tree, va_gc> *, - tree, tree, tree, int, unification_kind_t, tsubst_flags_t); + tree, tree, tree, int, unification_kind_t, bool, tsubst_flags_t); static struct z_candidate *add_template_candidate_real (struct z_candidate **, tree, tree, tree, tree, const vec<tree, va_gc> *, - tree, tree, tree, int, tree, unification_kind_t, tsubst_flags_t); + tree, tree, tree, int, tree, unification_kind_t, bool, tsubst_flags_t); static bool is_complete (tree); static struct z_candidate *add_conv_candidate (struct z_candidate **, tree, tree, const vec<tree, va_gc> *, tree, tree, tsubst_flags_t); static struct z_candidate *add_function_candidate (struct z_candidate **, tree, tree, tree, const vec<tree, va_gc> *, tree, - tree, int, conversion**, tsubst_flags_t); + tree, int, conversion**, bool, tsubst_flags_t); static conversion *implicit_conversion (tree, tree, tree, bool, int, tsubst_flags_t); static conversion *reference_binding (tree, tree, tree, bool, int, @@ -455,8 +455,8 @@ struct rejection_reason { int expected; /* The actual number of arguments in the call. */ int actual; - /* Whether the call was a varargs call. */ - bool call_varargs_p; + /* Whether EXPECTED should be treated as a lower bound. */ + bool least_p; } arity; /* Information about an argument conversion mismatch. */ struct conversion_info conversion; @@ -628,12 +628,13 @@ alloc_rejection (enum rejection_reason_code code) } static struct rejection_reason * -arity_rejection (tree first_arg, int expected, int actual) +arity_rejection (tree first_arg, int expected, int actual, bool least_p = false) { struct rejection_reason *r = alloc_rejection (rr_arity); int adjust = first_arg != NULL_TREE; r->u.arity.expected = expected - adjust; r->u.arity.actual = actual - adjust; + r->u.arity.least_p = least_p; return r; } @@ -1731,7 +1732,8 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, because A[] and A[2] are reference-related. But we don't do it because grok_reference_init has deduced the array size (to 1), and A[1] and A[2] aren't reference-related. */ - if (CONSTRUCTOR_NELTS (expr) == 1) + if (CONSTRUCTOR_NELTS (expr) == 1 + && !CONSTRUCTOR_IS_DESIGNATED_INIT (expr)) { tree elt = CONSTRUCTOR_ELT (expr, 0)->value; if (error_operand_p (elt)) @@ -2095,6 +2097,7 @@ implicit_conversion_1 (tree to, tree from, tree expr, bool c_cast_p, { if (BRACE_ENCLOSED_INITIALIZER_P (expr) && CONSTRUCTOR_NELTS (expr) == 1 + && !CONSTRUCTOR_IS_DESIGNATED_INIT (expr) && !is_list_ctor (cand->fn)) { /* "If C is not an initializer-list constructor and the @@ -2239,6 +2242,56 @@ conv_flags (int i, int nargs, tree fn, tree arg, int flags) return lflags; } +/* Build an appropriate 'this' conversion for the method FN and class + type CTYPE from the value ARG (having type ARGTYPE) to the type PARMTYPE. + This function modifies PARMTYPE, ARGTYPE and ARG. */ + +static conversion * +build_this_conversion (tree fn, tree ctype, + tree& parmtype, tree& argtype, tree& arg, + int flags, tsubst_flags_t complain) +{ + gcc_assert (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn) + && !DECL_CONSTRUCTOR_P (fn)); + + /* The type of the implicit object parameter ('this') for + overload resolution is not always the same as for the + function itself; conversion functions are considered to + be members of the class being converted, and functions + introduced by a using-declaration are considered to be + members of the class that uses them. + + Since build_over_call ignores the ICS for the `this' + parameter, we can just change the parm type. */ + parmtype = cp_build_qualified_type (ctype, + cp_type_quals (TREE_TYPE (parmtype))); + bool this_p = true; + if (FUNCTION_REF_QUALIFIED (TREE_TYPE (fn))) + { + /* If the function has a ref-qualifier, the implicit + object parameter has reference type. */ + bool rv = FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (fn)); + parmtype = cp_build_reference_type (parmtype, rv); + /* The special handling of 'this' conversions in compare_ics + does not apply if there is a ref-qualifier. */ + this_p = false; + } + else + { + parmtype = build_pointer_type (parmtype); + /* We don't use build_this here because we don't want to + capture the object argument until we've chosen a + non-static member function. */ + arg = build_address (arg); + argtype = lvalue_type (arg); + } + flags |= LOOKUP_ONLYCONVERTING; + conversion *t = implicit_conversion (parmtype, argtype, arg, + /*c_cast_p=*/false, flags, complain); + t->this_p = this_p; + return t; +} + /* Create an overload candidate for the function or method FN called with the argument list FIRST_ARG/ARGS and add it to CANDIDATES. FLAGS is passed on to implicit_conversion. @@ -2246,7 +2299,14 @@ conv_flags (int i, int nargs, tree fn, tree arg, int flags) This does not change ARGS. CTYPE, if non-NULL, is the type we want to pretend this function - comes from for purposes of overload resolution. */ + comes from for purposes of overload resolution. + + SHORTCUT_BAD_CONVS controls how we handle "bad" argument conversions. + If true, we stop computing conversions upon seeing the first bad + conversion. This is used by add_candidates to avoid computing + more conversions than necessary in the presence of a strictly viable + candidate, while preserving the defacto behavior of overload resolution + when it turns out there are only non-strictly viable candidates. */ static struct z_candidate * add_function_candidate (struct z_candidate **candidates, @@ -2254,6 +2314,7 @@ add_function_candidate (struct z_candidate **candidates, const vec<tree, va_gc> *args, tree access_path, tree conversion_path, int flags, conversion **convs, + bool shortcut_bad_convs, tsubst_flags_t complain) { tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn)); @@ -2375,8 +2436,6 @@ add_function_candidate (struct z_candidate **candidates, { tree argtype, to_type; tree arg; - conversion *t; - int is_this; if (parmnode == void_list_node) break; @@ -2395,54 +2454,23 @@ add_function_candidate (struct z_candidate **candidates, (*args)[i + skip - (first_arg != NULL_TREE ? 1 : 0)]); argtype = lvalue_type (arg); - is_this = (i == 0 && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn) - && ! DECL_CONSTRUCTOR_P (fn)); - + conversion *t; if (parmnode) { tree parmtype = TREE_VALUE (parmnode); - - parmnode = TREE_CHAIN (parmnode); - - /* The type of the implicit object parameter ('this') for - overload resolution is not always the same as for the - function itself; conversion functions are considered to - be members of the class being converted, and functions - introduced by a using-declaration are considered to be - members of the class that uses them. - - Since build_over_call ignores the ICS for the `this' - parameter, we can just change the parm type. */ - if (ctype && is_this) + if (i == 0 + && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn) + && !DECL_CONSTRUCTOR_P (fn)) + t = build_this_conversion (fn, ctype, parmtype, argtype, arg, + flags, complain); + else { - parmtype = cp_build_qualified_type - (ctype, cp_type_quals (TREE_TYPE (parmtype))); - if (FUNCTION_REF_QUALIFIED (TREE_TYPE (fn))) - { - /* If the function has a ref-qualifier, the implicit - object parameter has reference type. */ - bool rv = FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (fn)); - parmtype = cp_build_reference_type (parmtype, rv); - /* The special handling of 'this' conversions in compare_ics - does not apply if there is a ref-qualifier. */ - is_this = false; - } - else - { - parmtype = build_pointer_type (parmtype); - /* We don't use build_this here because we don't want to - capture the object argument until we've chosen a - non-static member function. */ - arg = build_address (arg); - argtype = lvalue_type (arg); - } + int lflags = conv_flags (i, len-skip, fn, arg, flags); + t = implicit_conversion (parmtype, argtype, arg, + /*c_cast_p=*/false, lflags, complain); } - - int lflags = conv_flags (i, len-skip, fn, arg, flags); - - t = implicit_conversion (parmtype, argtype, arg, - /*c_cast_p=*/false, lflags, complain); to_type = parmtype; + parmnode = TREE_CHAIN (parmnode); } else { @@ -2451,9 +2479,6 @@ add_function_candidate (struct z_candidate **candidates, to_type = argtype; } - if (t && is_this) - t->this_p = true; - convs[i] = t; if (! t) { @@ -2468,7 +2493,8 @@ add_function_candidate (struct z_candidate **candidates, viable = -1; reason = bad_arg_conversion_rejection (first_arg, i, arg, to_type, EXPR_LOCATION (arg)); - + if (shortcut_bad_convs) + break; } } @@ -3352,7 +3378,9 @@ add_builtin_candidates (struct z_candidate **candidates, enum tree_code code, This does not change ARGLIST. The RETURN_TYPE is the desired type for conversion operators. If OBJ is NULL_TREE, FLAGS and CTYPE are as for add_function_candidate. If an OBJ is supplied, FLAGS and - CTYPE are ignored, and OBJ is as for add_conv_candidate. */ + CTYPE are ignored, and OBJ is as for add_conv_candidate. + + SHORTCUT_BAD_CONVS is as in add_function_candidate. */ static struct z_candidate* add_template_candidate_real (struct z_candidate **candidates, tree tmpl, @@ -3360,7 +3388,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, const vec<tree, va_gc> *arglist, tree return_type, tree access_path, tree conversion_path, int flags, tree obj, unification_kind_t strict, - tsubst_flags_t complain) + bool shortcut_bad_convs, tsubst_flags_t complain) { int ntparms = DECL_NTPARMS (tmpl); tree targs = make_tree_vec (ntparms); @@ -3450,9 +3478,73 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, } gcc_assert (ia == nargs_without_in_chrg); + if (!obj && explicit_targs) + { + /* Check that there's no obvious arity mismatch before proceeding with + deduction. This avoids substituting explicit template arguments + into the template (which could result in an error outside the + immediate context) when the resulting candidate would be unviable + anyway. */ + int min_arity = 0, max_arity = 0; + tree parms = TYPE_ARG_TYPES (TREE_TYPE (tmpl)); + parms = skip_artificial_parms_for (tmpl, parms); + for (; parms != void_list_node; parms = TREE_CHAIN (parms)) + { + if (!parms || PACK_EXPANSION_P (TREE_VALUE (parms))) + { + max_arity = -1; + break; + } + if (TREE_PURPOSE (parms)) + /* A parameter with a default argument. */ + ++max_arity; + else + ++min_arity, ++max_arity; + } + if (ia < (unsigned)min_arity) + { + /* Too few arguments. */ + reason = arity_rejection (NULL_TREE, min_arity, ia, + /*least_p=*/(max_arity == -1)); + goto fail; + } + else if (max_arity != -1 && ia > (unsigned)max_arity) + { + /* Too many arguments. */ + reason = arity_rejection (NULL_TREE, max_arity, ia); + goto fail; + } + } + errs = errorcount+sorrycount; if (!obj) - convs = alloc_conversions (nargs); + { + convs = alloc_conversions (nargs); + + if (shortcut_bad_convs + && DECL_NONSTATIC_MEMBER_FUNCTION_P (tmpl) + && !DECL_CONSTRUCTOR_P (tmpl)) + { + /* Check the 'this' conversion before proceeding with deduction. + This is effectively an extension of the DR 1391 resolution + that we perform in check_non_deducible_conversions, though it's + convenient to do this extra check here instead of there. */ + tree parmtype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (tmpl))); + tree argtype = lvalue_type (first_arg); + tree arg = first_arg; + conversion *t = build_this_conversion (tmpl, ctype, + parmtype, argtype, arg, + flags, complain); + convs[0] = t; + if (t->bad_p) + { + reason = bad_arg_conversion_rejection (first_arg, 0, + arg, parmtype, + EXPR_LOCATION (arg)); + goto fail; + } + } + } fn = fn_type_unification (tmpl, explicit_targs, targs, args_without_in_chrg, nargs_without_in_chrg, @@ -3499,7 +3591,8 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, else cand = add_function_candidate (candidates, fn, ctype, first_arg, arglist, access_path, - conversion_path, flags, convs, complain); + conversion_path, flags, convs, + shortcut_bad_convs, complain); if (DECL_TI_TEMPLATE (fn) != tmpl) /* This situation can occur if a member template of a template class is specialized. Then, instantiate_template might return @@ -3525,8 +3618,9 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, return cand; fail: - return add_candidate (candidates, tmpl, first_arg, arglist, nargs, NULL, - access_path, conversion_path, 0, reason, flags); + int viable = (reason->code == rr_bad_arg_conversion ? -1 : 0); + return add_candidate (candidates, tmpl, first_arg, arglist, nargs, convs, + access_path, conversion_path, viable, reason, flags); } @@ -3535,13 +3629,15 @@ add_template_candidate (struct z_candidate **candidates, tree tmpl, tree ctype, tree explicit_targs, tree first_arg, const vec<tree, va_gc> *arglist, tree return_type, tree access_path, tree conversion_path, int flags, - unification_kind_t strict, tsubst_flags_t complain) + unification_kind_t strict, bool shortcut_bad_convs, + tsubst_flags_t complain) { return add_template_candidate_real (candidates, tmpl, ctype, explicit_targs, first_arg, arglist, return_type, access_path, conversion_path, - flags, NULL_TREE, strict, complain); + flags, NULL_TREE, strict, shortcut_bad_convs, + complain); } /* Create an overload candidate for the conversion function template TMPL, @@ -3567,7 +3663,7 @@ add_template_conv_candidate (struct z_candidate **candidates, tree tmpl, add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE, NULL_TREE, arglist, return_type, access_path, conversion_path, 0, obj, DEDUCE_CALL, - complain); + /*shortcut_bad_convs=*/false, complain); } /* The CANDS are the set of candidates that were considered for @@ -3723,12 +3819,19 @@ print_conversion_rejection (location_t loc, struct conversion_info *info, HAVE. */ static void -print_arity_information (location_t loc, unsigned int have, unsigned int want) -{ - inform_n (loc, want, - " candidate expects %d argument, %d provided", - " candidate expects %d arguments, %d provided", - want, have); +print_arity_information (location_t loc, unsigned int have, unsigned int want, + bool least_p) +{ + if (least_p) + inform_n (loc, want, + " candidate expects at least %d argument, %d provided", + " candidate expects at least %d arguments, %d provided", + want, have); + else + inform_n (loc, want, + " candidate expects %d argument, %d provided", + " candidate expects %d arguments, %d provided", + want, have); } /* Print information about one overload candidate CANDIDATE. MSGSTR @@ -3792,7 +3895,8 @@ print_z_candidate (location_t loc, const char *msgstr, { case rr_arity: print_arity_information (cloc, r->u.arity.actual, - r->u.arity.expected); + r->u.arity.expected, + r->u.arity.least_p); break; case rr_arg_conversion: print_conversion_rejection (cloc, &r->u.conversion, fn); @@ -4108,7 +4212,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags, { cand->second_conv = build_identity_conv (totype, NULL_TREE); - /* If totype isn't a reference, and LOOKUP_NO_TEMP_BIND isn't + /* If totype isn't a reference, and LOOKUP_ONLYCONVERTING is set, then this is copy-initialization. In that case, "The result of the call is then used to direct-initialize the object that is the destination of the copy-initialization." @@ -4117,6 +4221,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags, We represent this in the conversion sequence with an rvalue conversion, which means a constructor call. */ if (!TYPE_REF_P (totype) + && cxx_dialect < cxx17 + && (flags & LOOKUP_ONLYCONVERTING) && !(convflags & LOOKUP_NO_TEMP_BIND)) cand->second_conv = build_conv (ck_rvalue, totype, cand->second_conv); @@ -4484,6 +4590,9 @@ build_converted_constant_expr_internal (tree type, tree expr, && processing_template_decl) conv = next_conversion (conv); + /* Issuing conversion warnings for value-dependent expressions is + likely too noisy. */ + warning_sentinel w (warn_conversion); conv->check_narrowing = true; conv->check_narrowing_const_only = true; expr = convert_like (conv, expr, complain); @@ -4622,7 +4731,7 @@ perform_overload_resolution (tree fn, functions. */ static void -print_error_for_call_failure (tree fn, vec<tree, va_gc> *args, +print_error_for_call_failure (tree fn, const vec<tree, va_gc> *args, struct z_candidate *candidates) { tree targs = NULL_TREE; @@ -4647,6 +4756,40 @@ print_error_for_call_failure (tree fn, vec<tree, va_gc> *args, print_z_candidates (loc, candidates); } +/* Perform overload resolution on the set of deduction guides DGUIDES + using ARGS. Returns the selected deduction guide, or error_mark_node + if overload resolution fails. */ + +tree +perform_dguide_overload_resolution (tree dguides, const vec<tree, va_gc> *args, + tsubst_flags_t complain) +{ + z_candidate *candidates; + bool any_viable_p; + tree result; + + gcc_assert (deduction_guide_p (OVL_FIRST (dguides))); + + /* Get the high-water mark for the CONVERSION_OBSTACK. */ + void *p = conversion_obstack_alloc (0); + + z_candidate *cand = perform_overload_resolution (dguides, args, &candidates, + &any_viable_p, complain); + if (!cand) + { + if (complain & tf_error) + print_error_for_call_failure (dguides, args, candidates); + result = error_mark_node; + } + else + result = cand->fn; + + /* Free all the conversions we allocated. */ + obstack_free (&conversion_obstack, p); + + return result; +} + /* Return an expression for a call to FN (a namespace-scope function, or a static member function) with the ARGS. This may change ARGS. */ @@ -4911,10 +5054,8 @@ build_op_call_1 (tree obj, vec<tree, va_gc> **args, tsubst_flags_t complain) || TYPE_REFFN_P (totype) || (TYPE_REF_P (totype) && TYPE_PTRFN_P (TREE_TYPE (totype)))) - for (ovl_iterator iter (TREE_VALUE (convs)); iter; ++iter) + for (tree fn : ovl_range (TREE_VALUE (convs))) { - tree fn = *iter; - if (DECL_NONCONVERTING_P (fn)) continue; @@ -5798,7 +5939,8 @@ build_conditional_expr_1 (const op_location_t &loc, warn here, because the COND_EXPR will be turned into ARG2. */ if (warn_duplicated_branches && (complain & tf_warning) - && (arg2 == arg3 || operand_equal_p (arg2, arg3, 0))) + && (arg2 == arg3 || operand_equal_p (arg2, arg3, + OEP_ADDRESS_OF_SAME_FIELD))) warning_at (EXPR_LOCATION (result), OPT_Wduplicated_branches, "this condition has identical branches"); @@ -5874,6 +6016,9 @@ perfect_conversion_p (conversion *conv) next_conversion (conv)->type)) return false; } + if (conv->check_narrowing) + /* Brace elision is imperfect. */ + return false; return true; } @@ -5888,6 +6033,11 @@ perfect_candidate_p (z_candidate *cand) { if (cand->viable < 1) return false; + /* CWG1402 makes an implicitly deleted move op worse than other + candidates. */ + if (DECL_DELETED_FN (cand->fn) && DECL_DEFAULTED_FN (cand->fn) + && move_fn_p (cand->fn)) + return false; int len = cand->num_convs; for (int i = 0; i < len; ++i) if (!perfect_conversion_p (cand->convs[i])) @@ -5965,6 +6115,7 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args, /* Delay creating the implicit this parameter until it is needed. */ non_static_args = NULL; + bool seen_strictly_viable = any_strictly_viable (*candidates); /* If there's a non-template perfect match, we don't need to consider templates. So check non-templates first. This optimization is only really needed for the defaulted copy constructor of tuple and the like @@ -5976,11 +6127,22 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args, else /*if (flags & LOOKUP_DEFAULTED)*/ which = non_templates; + /* During overload resolution, we first consider each function under the + assumption that we'll eventually find a strictly viable candidate. + This allows us to circumvent our defacto behavior when checking + argument conversions and shortcut consideration of the candidate + upon encountering the first bad conversion. If this assumption + turns out to be false, and all candidates end up being non-strictly + viable, then we reconsider such candidates under the defacto behavior. + This trick is important for pruning member function overloads according + to their const/ref-qualifiers (since all 'this' conversions are at + worst bad) without breaking -fpermissive. */ + tree bad_fns = NULL_TREE; + bool shortcut_bad_convs = true; + again: - for (lkp_iterator iter (fns); iter; ++iter) + for (tree fn : lkp_range (fns)) { - fn = *iter; - if (check_converting && DECL_NONCONVERTING_P (fn)) continue; if (check_list_ctor && !is_list_ctor (fn)) @@ -6024,18 +6186,22 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args, } if (TREE_CODE (fn) == TEMPLATE_DECL) - add_template_candidate (candidates, - fn, - ctype, - explicit_targs, - fn_first_arg, - fn_args, - return_type, - access_path, - conversion_path, - flags, - strict, - complain); + { + if (!add_template_candidate (candidates, + fn, + ctype, + explicit_targs, + fn_first_arg, + fn_args, + return_type, + access_path, + conversion_path, + flags, + strict, + shortcut_bad_convs, + complain)) + continue; + } else { add_function_candidate (candidates, @@ -6047,16 +6213,47 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args, conversion_path, flags, NULL, + shortcut_bad_convs, complain); if (perfect_candidate_p (*candidates)) seen_perfect = true; } + + z_candidate *cand = *candidates; + if (cand->viable == 1) + seen_strictly_viable = true; + + if (cand->viable == -1 + && shortcut_bad_convs + && !cand->convs[cand->reversed () ? 0 : cand->num_convs - 1]) + { + /* This candidate has been tentatively marked non-strictly viable, + and we didn't compute all argument conversions for it (having + stopped at the first bad conversion). Add the function to BAD_FNS + to fully reconsider later if we don't find any strictly viable + candidates. */ + bad_fns = lookup_add (fn, bad_fns); + *candidates = (*candidates)->next; + } } if (which == non_templates && !seen_perfect) { which = templates; goto again; } + else if (which == templates + && !seen_strictly_viable + && shortcut_bad_convs + && bad_fns) + { + /* None of the candidates are strictly viable, so consider again those + functions in BAD_FNS, this time without shortcutting bad conversions + so that all their argument conversions are computed. */ + which = either; + fns = bad_fns; + shortcut_bad_convs = false; + goto again; + } } /* Returns 1 if P0145R2 says that the LHS of operator CODE is evaluated first, @@ -7012,10 +7209,8 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, the usual deallocation function, so we shouldn't complain about using the operator delete (void *, size_t). */ if (DECL_CLASS_SCOPE_P (fn)) - for (lkp_iterator iter (MAYBE_BASELINK_FUNCTIONS (fns)); - iter; ++iter) + for (tree elt : lkp_range (MAYBE_BASELINK_FUNCTIONS (fns))) { - tree elt = *iter; if (usual_deallocation_fn_p (elt) && FUNCTION_ARG_CHAIN (elt) == void_list_node) goto ok; @@ -7058,9 +7253,8 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, allocation function. If the lookup finds a single matching deallocation function, that function will be called; otherwise, no deallocation function will be called." */ - for (lkp_iterator iter (MAYBE_BASELINK_FUNCTIONS (fns)); iter; ++iter) + for (tree elt : lkp_range (MAYBE_BASELINK_FUNCTIONS (fns))) { - tree elt = *iter; dealloc_info di_elt; if (usual_deallocation_fn_p (elt, &di_elt)) { @@ -7202,8 +7396,10 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, treat that as an implicit delete-expression. This is also called for the delete if the constructor throws in a new-expression, and for a deleting destructor (which implements a delete-expression). */ + /* But leave this flag off for destroying delete to avoid wrong + assumptions in the optimizers. */ tree call = extract_call_expr (ret); - if (TREE_CODE (call) == CALL_EXPR) + if (TREE_CODE (call) == CALL_EXPR && !destroying_delete_p (fn)) CALL_FROM_NEW_OR_DELETE_P (call) = 1; return ret; @@ -7467,8 +7663,9 @@ maybe_warn_array_conv (location_t loc, conversion *c, tree expr) || TYPE_DOMAIN (type) == NULL_TREE) return; - if (conv_binds_to_array_of_unknown_bound (c)) - pedwarn (loc, OPT_Wpedantic, "conversions to arrays of unknown bound " + if (pedantic && conv_binds_to_array_of_unknown_bound (c)) + pedwarn (loc, OPT_Wc__20_extensions, + "conversions to arrays of unknown bound " "are only available with %<-std=c++20%> or %<-std=gnu++20%>"); } @@ -7793,7 +7990,7 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, expr = convert_like (next_conversion (convs), expr, fn, argnum, convs->kind == ck_ref_bind ? issue_conversion_warnings : false, - c_cast_p, complain); + c_cast_p, complain & ~tf_no_cleanup); if (expr == error_mark_node) return error_mark_node; @@ -7894,8 +8091,23 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, "lvalue of type %qI", totype, extype); else if (!TYPE_REF_IS_RVALUE (ref_type) && !lvalue_p (expr) && !CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type))) - error_at (loc, "cannot bind non-const lvalue reference of " - "type %qH to an rvalue of type %qI", totype, extype); + { + conversion *next = next_conversion (convs); + if (next->kind == ck_std) + { + next = next_conversion (next); + error_at (loc, "cannot bind non-const lvalue reference of " + "type %qH to a value of type %qI", + totype, next->type); + } + else if (!CP_TYPE_CONST_P (TREE_TYPE (ref_type))) + error_at (loc, "cannot bind non-const lvalue reference of " + "type %qH to an rvalue of type %qI", totype, extype); + else // extype is volatile + error_at (loc, "cannot bind lvalue reference of type " + "%qH to an rvalue of type %qI", totype, + extype); + } else if (!reference_compatible_p (TREE_TYPE (totype), extype)) { /* If we're converting from T[] to T[N], don't talk @@ -8048,6 +8260,27 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, return expr; } +/* Return true if converting FROM to TO is unsafe in a template. */ + +static bool +conv_unsafe_in_template_p (tree to, tree from) +{ + /* Converting classes involves TARGET_EXPR. */ + if (CLASS_TYPE_P (to) || CLASS_TYPE_P (from)) + return true; + + /* Converting real to integer produces FIX_TRUNC_EXPR which tsubst + doesn't handle. */ + if (SCALAR_FLOAT_TYPE_P (from) && INTEGRAL_OR_ENUMERATION_TYPE_P (to)) + return true; + + /* Converting integer to real isn't a trivial conversion, either. */ + if (INTEGRAL_OR_ENUMERATION_TYPE_P (from) && SCALAR_FLOAT_TYPE_P (to)) + return true; + + return false; +} + /* Wrapper for convert_like_internal that handles creating IMPLICIT_CONV_EXPR. */ @@ -8064,7 +8297,7 @@ convert_like (conversion *convs, tree expr, tree fn, int argnum, tree conv_expr = NULL_TREE; if (processing_template_decl && convs->kind != ck_identity - && (CLASS_TYPE_P (convs->type) || CLASS_TYPE_P (TREE_TYPE (expr)))) + && conv_unsafe_in_template_p (convs->type, TREE_TYPE (expr))) { conv_expr = build1 (IMPLICIT_CONV_EXPR, convs->type, expr); if (convs->kind != ck_ref_bind) @@ -8137,7 +8370,10 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain) { arg = mark_rvalue_use (arg); if (TREE_SIDE_EFFECTS (arg)) - arg = cp_build_compound_expr (arg, null_pointer_node, complain); + { + warning_sentinel w(warn_unused_result); + arg = cp_build_compound_expr (arg, null_pointer_node, complain); + } else arg = null_pointer_node; } @@ -8789,6 +9025,7 @@ immediate_invocation_p (tree fn, int nargs) || !DECL_IMMEDIATE_FUNCTION_P (current_function_decl)) && (current_binding_level->kind != sk_function_parms || !current_binding_level->immediate_fn_ctx_p) + && !in_consteval_if_p /* As an exception, we defer std::source_location::current () invocations until genericization because LWG3396 mandates special behavior for it. */ @@ -8922,8 +9159,13 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) /* OK, we're actually calling this inherited constructor; set its deletedness appropriately. We can get away with doing this here because calling is the only way to refer to a constructor. */ - if (DECL_INHERITED_CTOR (fn)) - deduce_inheriting_ctor (fn); + if (DECL_INHERITED_CTOR (fn) + && !deduce_inheriting_ctor (fn)) + { + if (complain & tf_error) + mark_used (fn); + return error_mark_node; + } /* Make =delete work with SFINAE. */ if (DECL_DELETED_FN (fn)) @@ -9103,18 +9345,32 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) if (base_binfo == error_mark_node) return error_mark_node; } - tree converted_arg = build_base_path (PLUS_EXPR, arg, - base_binfo, 1, complain); /* If we know the dynamic type of the object, look up the final overrider in the BINFO. */ if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0 && resolves_to_fixed_type_p (arg)) { - fn = lookup_vfn_in_binfo (DECL_VINDEX (fn), base_binfo); - flags |= LOOKUP_NONVIRTUAL; + tree ov = lookup_vfn_in_binfo (DECL_VINDEX (fn), base_binfo); + + /* And unwind base_binfo to match. If we don't find the type we're + looking for in BINFO_INHERITANCE_CHAIN, we're looking at diamond + inheritance; for now do a normal virtual call in that case. */ + tree octx = DECL_CONTEXT (ov); + tree obinfo = base_binfo; + while (obinfo && !SAME_BINFO_TYPE_P (BINFO_TYPE (obinfo), octx)) + obinfo = BINFO_INHERITANCE_CHAIN (obinfo); + if (obinfo) + { + fn = ov; + base_binfo = obinfo; + flags |= LOOKUP_NONVIRTUAL; + } } + tree converted_arg = build_base_path (PLUS_EXPR, arg, + base_binfo, 1, complain); + argarray[j++] = converted_arg; parm = TREE_CHAIN (parm); if (first_arg != NULL_TREE) @@ -9354,7 +9610,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) already_used = true; } else - cp_warn_deprecated_use (fn, complain); + cp_handle_deprecated_or_unavailable (fn, complain); if (eliding_temp && DECL_BASE_CONSTRUCTOR_P (fn) && !make_base_init_ok (arg)) @@ -9394,7 +9650,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) { /* Avoid copying empty classes. */ val = build2 (COMPOUND_EXPR, type, arg, to); - TREE_NO_WARNING (val) = 1; + suppress_warning (val, OPT_Wunused); } else if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base))) { @@ -9425,10 +9681,10 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) build2 (MEM_REF, array_type, arg0, alias_set), build2 (MEM_REF, array_type, arg, alias_set)); val = build2 (COMPOUND_EXPR, TREE_TYPE (to), t, to); - TREE_NO_WARNING (val) = 1; + suppress_warning (val, OPT_Wunused); } - cp_warn_deprecated_use (fn, complain); + cp_handle_deprecated_or_unavailable (fn, complain); return val; } @@ -9499,7 +9755,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) { tree c = extract_call_expr (call); if (TREE_CODE (c) == CALL_EXPR) - TREE_NO_WARNING (c) = 1; + suppress_warning (c /* Suppress all warnings. */); } if (TREE_CODE (fn) == ADDR_EXPR) { @@ -9628,10 +9884,8 @@ has_trivial_copy_assign_p (tree type, bool access, bool *hasassign) /* Iterate over overloads of the assignment operator, checking accessible copy assignments for triviality. */ - for (ovl_iterator oi (fns); oi; ++oi) + for (tree f : ovl_range (fns)) { - tree f = *oi; - /* Skip operators that aren't copy assignments. */ if (!copy_fn_p (f)) continue; @@ -9674,10 +9928,8 @@ has_trivial_copy_p (tree type, bool access, bool hasctor[2]) tree fns = get_class_binding (type, complete_ctor_identifier); bool all_trivial = true; - for (ovl_iterator oi (fns); oi; ++oi) + for (tree f : ovl_range (fns)) { - tree f = *oi; - /* Skip template constructors. */ if (TREE_CODE (f) != FUNCTION_DECL) continue; @@ -10159,6 +10411,7 @@ build_special_member_call (tree instance, tree name, vec<tree, va_gc> **args, if (BRACE_ENCLOSED_INITIALIZER_P (arg) && !TYPE_HAS_LIST_CTOR (class_type) + && !CONSTRUCTOR_IS_DESIGNATED_INIT (arg) && CONSTRUCTOR_NELTS (arg) == 1) arg = CONSTRUCTOR_ELT (arg, 0)->value; @@ -10752,7 +11005,8 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, tree a = instance; if (TREE_THIS_VOLATILE (a)) a = build_this (a); - call = build2 (COMPOUND_EXPR, TREE_TYPE (call), a, call); + if (TREE_SIDE_EFFECTS (a)) + call = build2 (COMPOUND_EXPR, TREE_TYPE (call), a, call); } else if (call != error_mark_node && DECL_DESTRUCTOR_P (cand->fn) @@ -12146,7 +12400,7 @@ can_convert (tree to, tree from, tsubst_flags_t complain) /* implicit_conversion only considers user-defined conversions if it has an expression for the call argument list. */ if (CLASS_TYPE_P (from) || CLASS_TYPE_P (to)) - arg = build1 (CAST_EXPR, from, NULL_TREE); + arg = build_stub_object (from); return can_convert_arg (to, from, arg, LOOKUP_IMPLICIT, complain); } @@ -12447,13 +12701,15 @@ set_up_extended_ref_temp (tree decl, tree expr, vec<tree, va_gc> **cleanups, VAR. */ if (TREE_CODE (expr) != TARGET_EXPR) expr = get_target_expr (expr); + else if (TREE_ADDRESSABLE (expr)) + TREE_ADDRESSABLE (var) = 1; if (TREE_CODE (decl) == FIELD_DECL - && extra_warnings && !TREE_NO_WARNING (decl)) + && extra_warnings && !warning_suppressed_p (decl)) { warning (OPT_Wextra, "a temporary bound to %qD only persists " "until the constructor exits", decl); - TREE_NO_WARNING (decl) = true; + suppress_warning (decl); } /* Recursively extend temps in this initializer. */ diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 856e81e..fe225c6 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -136,7 +136,6 @@ static bool check_field_decl (tree, tree, int *, int *); static void check_field_decls (tree, tree *, int *, int *); static void build_base_fields (record_layout_info, splay_tree, tree *); static void check_methods (tree); -static void remove_zero_width_bit_fields (tree); static bool accessible_nvdtor_p (tree); /* Used by find_flexarrays and related functions. */ @@ -207,6 +206,19 @@ static bool type_maybe_constexpr_default_constructor (tree); static bool type_maybe_constexpr_destructor (tree); static bool field_poverlapping_p (tree); +/* Set CURRENT_ACCESS_SPECIFIER based on the protection of DECL. */ + +void +set_current_access_from_decl (tree decl) +{ + if (TREE_PRIVATE (decl)) + current_access_specifier = access_private_node; + else if (TREE_PROTECTED (decl)) + current_access_specifier = access_protected_node; + else + current_access_specifier = access_public_node; +} + /* Return a COND_EXPR that executes TRUE_STMT if this execution of the 'structor is in charge of 'structing virtual bases, or FALSE_STMT otherwise. */ @@ -330,6 +342,15 @@ build_base_path (enum tree_code code, return error_mark_node; } + bool uneval = (cp_unevaluated_operand != 0 + || processing_template_decl + || in_template_function ()); + + /* For a non-pointer simple base reference, express it as a COMPONENT_REF + without taking its address (and so causing lambda capture, 91933). */ + if (code == PLUS_EXPR && !v_binfo && !want_pointer && !has_empty && !uneval) + return build_simple_base_path (expr, binfo); + if (!want_pointer) { rvalue = !lvalue_p (expr); @@ -357,9 +378,7 @@ build_base_path (enum tree_code code, template (even in instantiate_non_dependent_expr), we don't have vtables set up properly yet, and the value doesn't matter there either; we're just interested in the result of overload resolution. */ - if (cp_unevaluated_operand != 0 - || processing_template_decl - || in_template_function ()) + if (uneval) { expr = build_nop (ptr_target_type, expr); goto indout; @@ -1340,10 +1359,10 @@ handle_using_decl (tree using_decl, tree t) /* Make type T see field decl FDECL with access ACCESS. */ if (flist) - for (ovl_iterator iter (flist); iter; ++iter) + for (tree f : ovl_range (flist)) { - add_method (t, *iter, true); - alter_access (t, *iter, access); + add_method (t, f, true); + alter_access (t, f, access); } else if (USING_DECL_UNRELATED_P (using_decl)) { @@ -1352,6 +1371,8 @@ handle_using_decl (tree using_decl, tree t) CONST_DECL_USING_P is true. */ gcc_assert (TREE_CODE (decl) == CONST_DECL); + auto cas = make_temp_override (current_access_specifier); + set_current_access_from_decl (using_decl); tree copy = copy_decl (decl); DECL_CONTEXT (copy) = t; DECL_ARTIFICIAL (copy) = true; @@ -1494,8 +1515,8 @@ mark_or_check_tags (tree t, tree *tp, abi_tag_data *p, bool val) static tree find_abi_tags_r (tree *tp, int *walk_subtrees, void *data) { - if (TYPE_P (*tp) && *walk_subtrees == 1) - /* Tell cp_walk_subtrees to look though typedefs. */ + if (TYPE_P (*tp) && *walk_subtrees == 1 && flag_abi_version != 14) + /* Tell cp_walk_subtrees to look though typedefs. [PR98481] */ *walk_subtrees = 2; if (!OVERLOAD_TYPE_P (*tp)) @@ -1518,7 +1539,7 @@ find_abi_tags_r (tree *tp, int *walk_subtrees, void *data) static tree mark_abi_tags_r (tree *tp, int *walk_subtrees, void *data) { - if (TYPE_P (*tp) && *walk_subtrees == 1) + if (TYPE_P (*tp) && *walk_subtrees == 1 && flag_abi_version != 14) /* Tell cp_walk_subtrees to look though typedefs. */ *walk_subtrees = 2; @@ -2252,18 +2273,20 @@ maybe_warn_about_overly_private_class (tree t) if (!TYPE_HAS_COPY_CTOR (t)) nonprivate_ctor = true; else - for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); - !nonprivate_ctor && iter; ++iter) - if (TREE_PRIVATE (*iter)) + for (tree fn : ovl_range (CLASSTYPE_CONSTRUCTORS (t))) + if (TREE_PRIVATE (fn)) continue; - else if (copy_fn_p (*iter) || move_fn_p (*iter)) + else if (copy_fn_p (fn) || move_fn_p (fn)) /* Ideally, we wouldn't count any constructor that takes an argument of the class type as a parameter, because such things cannot be used to construct an instance of the class unless you already have one. */ - copy_or_move = *iter; + copy_or_move = fn; else - nonprivate_ctor = true; + { + nonprivate_ctor = true; + break; + } if (!nonprivate_ctor) { @@ -2367,7 +2390,7 @@ struct find_final_overrider_data { /* The candidate overriders. */ tree candidates; /* Path to most derived. */ - vec<tree> path; + auto_vec<tree> path; }; /* Add the overrider along the current path to FFOD->CANDIDATES. @@ -2480,8 +2503,6 @@ find_final_overrider (tree derived, tree binfo, tree fn) dfs_walk_all (derived, dfs_find_final_overrider_pre, dfs_find_final_overrider_post, &ffod); - ffod.path.release (); - /* If there was no winner, issue an error message. */ if (!ffod.candidates || TREE_CHAIN (ffod.candidates)) return error_mark_node; @@ -2869,10 +2890,8 @@ get_basefndecls (tree name, tree t, vec<tree> *base_fndecls) bool found_decls = false; /* Find virtual functions in T with the indicated NAME. */ - for (ovl_iterator iter (get_class_binding (t, name)); iter; ++iter) + for (tree method : ovl_range (get_class_binding (t, name))) { - tree method = *iter; - if (TREE_CODE (method) == FUNCTION_DECL && DECL_VINDEX (method)) { base_fndecls->safe_push (method); @@ -2981,9 +3000,8 @@ warn_hidden (tree t) continue; /* Remove any overridden functions. */ - for (ovl_iterator iter (fns); iter; ++iter) + for (tree fndecl : ovl_range (fns)) { - tree fndecl = *iter; if (TREE_CODE (fndecl) == FUNCTION_DECL && DECL_VINDEX (fndecl)) { @@ -3016,7 +3034,7 @@ warn_hidden (tree t) /* Recursive helper for finish_struct_anon. */ static void -finish_struct_anon_r (tree field, bool complain) +finish_struct_anon_r (tree field) { for (tree elt = TYPE_FIELDS (TREE_TYPE (field)); elt; elt = DECL_CHAIN (elt)) { @@ -3032,34 +3050,6 @@ finish_struct_anon_r (tree field, bool complain) || TYPE_UNNAMED_P (TREE_TYPE (elt)))) continue; - if (complain - && (TREE_CODE (elt) != FIELD_DECL - || (TREE_PRIVATE (elt) || TREE_PROTECTED (elt)))) - { - /* We already complained about static data members in - finish_static_data_member_decl. */ - if (!VAR_P (elt)) - { - auto_diagnostic_group d; - if (permerror (DECL_SOURCE_LOCATION (elt), - TREE_CODE (TREE_TYPE (field)) == UNION_TYPE - ? "%q#D invalid; an anonymous union may " - "only have public non-static data members" - : "%q#D invalid; an anonymous struct may " - "only have public non-static data members", elt)) - { - static bool hint; - if (flag_permissive && !hint) - { - hint = true; - inform (DECL_SOURCE_LOCATION (elt), - "this flexibility is deprecated and will be " - "removed"); - } - } - } - } - TREE_PRIVATE (elt) = TREE_PRIVATE (field); TREE_PROTECTED (elt) = TREE_PROTECTED (field); @@ -3077,12 +3067,11 @@ finish_struct_anon_r (tree field, bool complain) int j=A().i; */ if (DECL_NAME (elt) == NULL_TREE && ANON_AGGR_TYPE_P (TREE_TYPE (elt))) - finish_struct_anon_r (elt, /*complain=*/false); + finish_struct_anon_r (elt); } } -/* Check for things that are invalid. There are probably plenty of other - things we should check for also. */ +/* Fix up any anonymous union/struct members of T. */ static void finish_struct_anon (tree t) @@ -3096,7 +3085,7 @@ finish_struct_anon (tree t) if (DECL_NAME (field) == NULL_TREE && ANON_AGGR_TYPE_P (TREE_TYPE (field))) - finish_struct_anon_r (field, /*complain=*/true); + finish_struct_anon_r (field); } } @@ -3335,7 +3324,7 @@ add_implicitly_declared_members (tree t, tree* access_decls, bool is_friend = DECL_CONTEXT (space) != t; if (is_friend) do_friend (NULL_TREE, DECL_NAME (eq), eq, - NULL_TREE, NO_SPECIAL, true); + NO_SPECIAL, true); else { add_method (t, eq, false); @@ -3355,8 +3344,8 @@ add_implicitly_declared_members (tree t, tree* access_decls, tree ctor_list = decl; location_t loc = input_location; input_location = DECL_SOURCE_LOCATION (using_decl); - for (ovl_iterator iter (ctor_list); iter; ++iter) - one_inherited_ctor (*iter, t, using_decl); + for (tree fn : ovl_range (ctor_list)) + one_inherited_ctor (fn, t, using_decl); *access_decls = TREE_CHAIN (*access_decls); input_location = loc; } @@ -4227,7 +4216,7 @@ field_poverlapping_p (tree decl) bool is_empty_field (tree decl) { - if (TREE_CODE (decl) != FIELD_DECL) + if (!decl || TREE_CODE (decl) != FIELD_DECL) return false; bool r = (is_empty_class (TREE_TYPE (decl)) @@ -4645,7 +4634,7 @@ build_base_field (record_layout_info rli, tree binfo, tree access, DECL_FIELD_OFFSET (decl) = BINFO_OFFSET (binfo); DECL_FIELD_BIT_OFFSET (decl) = bitsize_zero_node; SET_DECL_OFFSET_ALIGN (decl, BITS_PER_UNIT); - DECL_FIELD_ABI_IGNORED (decl) = 1; + SET_DECL_FIELD_ABI_IGNORED (decl, 1); } /* An empty virtual base causes a class to be non-empty @@ -4772,9 +4761,8 @@ check_methods (tree t) TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = true; } - for (ovl_iterator i (CLASSTYPE_CONSTRUCTORS (t)); i; ++i) + for (tree fn : ovl_range (CLASSTYPE_CONSTRUCTORS (t))) { - tree fn = *i; if (!user_provided_p (fn)) /* Might be trivial. */; else if (copy_fn_p (fn)) @@ -4783,10 +4771,8 @@ check_methods (tree t) TYPE_HAS_COMPLEX_MOVE_CTOR (t) = true; } - for (ovl_iterator i (get_class_binding_direct (t, assign_op_identifier)); - i; ++i) + for (tree fn : ovl_range (get_class_binding_direct (t, assign_op_identifier))) { - tree fn = *i; if (!user_provided_p (fn)) /* Might be trivial. */; else if (copy_fn_p (fn)) @@ -5128,8 +5114,8 @@ clone_constructors_and_destructors (tree t) { /* 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); + for (tree fn : ovl_range (CLASSTYPE_CONSTRUCTORS (t))) + clone_cdtor (fn, /*update_methods=*/true); if (tree dtor = CLASSTYPE_DESTRUCTOR (t)) clone_cdtor (dtor, /*update_methods=*/true); @@ -5304,9 +5290,8 @@ type_has_user_nondefault_constructor (tree t) if (!TYPE_HAS_USER_CONSTRUCTOR (t)) return false; - for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter) + for (tree fn : ovl_range (CLASSTYPE_CONSTRUCTORS (t))) { - tree fn = *iter; if (user_provided_p (fn) && (TREE_CODE (fn) == TEMPLATE_DECL || (skip_artificial_parms_for (fn, DECL_ARGUMENTS (fn)) @@ -5630,19 +5615,6 @@ classtype_has_non_deleted_move_ctor (tree t) return false; } -/* True iff T has a copy constructor that is not deleted. */ - -bool -classtype_has_non_deleted_copy_ctor (tree t) -{ - if (CLASSTYPE_LAZY_COPY_CTOR (t)) - lazily_declare_fn (sfk_copy_constructor, t); - for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter) - if (copy_fn_p (*iter) && !DECL_DELETED_FN (*iter)) - return true; - return false; -} - /* If T, a class, has a user-provided copy constructor, copy assignment operator, or destructor, returns that function. Otherwise, null. */ @@ -5663,7 +5635,8 @@ classtype_has_depr_implicit_copy (tree t) iter; ++iter) { tree fn = *iter; - if (user_provided_p (fn) && copy_fn_p (fn)) + if (DECL_CONTEXT (fn) == t + && user_provided_p (fn) && copy_fn_p (fn)) return fn; } @@ -5746,6 +5719,7 @@ type_build_ctor_call (tree t) tree fn = *iter; if (!DECL_ARTIFICIAL (fn) || TREE_DEPRECATED (fn) + || TREE_UNAVAILABLE (fn) || DECL_DELETED_FN (fn)) return true; } @@ -5774,37 +5748,13 @@ type_build_dtor_call (tree t) tree fn = *iter; if (!DECL_ARTIFICIAL (fn) || TREE_DEPRECATED (fn) + || TREE_UNAVAILABLE (fn) || DECL_DELETED_FN (fn)) return true; } return false; } -/* Remove all zero-width bit-fields from T. */ - -static void -remove_zero_width_bit_fields (tree t) -{ - tree *fieldsp; - - fieldsp = &TYPE_FIELDS (t); - while (*fieldsp) - { - if (TREE_CODE (*fieldsp) == FIELD_DECL - && DECL_C_BIT_FIELD (*fieldsp) - /* We should not be confused by the fact that grokbitfield - temporarily sets the width of the bit field into - DECL_BIT_FIELD_REPRESENTATIVE (*fieldsp). - check_bitfield_decl eventually sets DECL_SIZE (*fieldsp) - to that width. */ - && (DECL_SIZE (*fieldsp) == NULL_TREE - || integer_zerop (DECL_SIZE (*fieldsp)))) - *fieldsp = DECL_CHAIN (*fieldsp); - else - fieldsp = &DECL_CHAIN (*fieldsp); - } -} - /* Returns TRUE iff we need a cookie when dynamically allocating an array whose elements have the indicated class TYPE. */ @@ -6708,7 +6658,7 @@ layout_class_type (tree t, tree *virtuals_p) } else if (might_overlap && is_empty_class (type)) { - DECL_FIELD_ABI_IGNORED (field) = 1; + SET_DECL_FIELD_ABI_IGNORED (field, 1); layout_empty_base_or_field (rli, field, empty_base_offsets); } else @@ -6727,7 +6677,7 @@ layout_class_type (tree t, tree *virtuals_p) laying out an Objective-C class. The ObjC ABI differs from the C++ ABI, and so we do not want a warning here. */ - && !TREE_NO_WARNING (field) + && !warning_suppressed_p (field, OPT_Wabi) && !last_field_was_bitfield && !integer_zerop (size_binop (TRUNC_MOD_EXPR, DECL_FIELD_BIT_OFFSET (field), @@ -6796,9 +6746,22 @@ layout_class_type (tree t, tree *virtuals_p) normalize_rli (rli); } - /* Delete all zero-width bit-fields from the list of fields. Now - that the type is laid out they are no longer important. */ - remove_zero_width_bit_fields (t); + /* We used to remove zero width bitfields at this point since PR42217, + while the C FE never did that. That caused ABI differences on various + targets. Set the DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD flag on them + instead, so that the backends can emit -Wpsabi warnings in the cases + where the ABI changed. */ + for (field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field)) + if (TREE_CODE (field) == FIELD_DECL + && DECL_C_BIT_FIELD (field) + /* We should not be confused by the fact that grokbitfield + temporarily sets the width of the bit field into + DECL_BIT_FIELD_REPRESENTATIVE (field). + check_bitfield_decl eventually sets DECL_SIZE (field) + to that width. */ + && (DECL_SIZE (field) == NULL_TREE + || integer_zerop (DECL_SIZE (field)))) + SET_DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD (field, 1); if (CLASSTYPE_NON_LAYOUT_POD_P (t) || CLASSTYPE_EMPTY_P (t)) { diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index c946744..0c2498a 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -46,6 +46,7 @@ do { \ static HOST_WIDE_INT find_array_ctor_elt (tree ary, tree dindex, bool insert = false); +static int array_index_cmp (tree key, tree index); /* Returns true iff FUN is an instantiation of a constexpr function template or a defaulted constexpr function. */ @@ -329,12 +330,9 @@ build_data_member_initialization (tree t, vec<constructor_elt, va_gc> **vec) return false; if (TREE_CODE (t) == STATEMENT_LIST) { - tree_stmt_iterator i; - for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) - { - if (! build_data_member_initialization (tsi_stmt (i), vec)) - return false; - } + for (tree stmt : tsi_range (t)) + if (! build_data_member_initialization (stmt, vec)) + return false; return true; } if (TREE_CODE (t) == CLEANUP_STMT) @@ -576,10 +574,9 @@ build_constexpr_constructor_member_initializers (tree type, tree body) break; case STATEMENT_LIST: - for (tree_stmt_iterator i = tsi_start (body); - !tsi_end_p (i); tsi_next (&i)) + for (tree stmt : tsi_range (body)) { - body = tsi_stmt (i); + body = stmt; if (TREE_CODE (body) == BIND_EXPR) break; } @@ -616,10 +613,9 @@ build_constexpr_constructor_member_initializers (tree type, tree body) } else if (TREE_CODE (body) == STATEMENT_LIST) { - tree_stmt_iterator i; - for (i = tsi_start (body); !tsi_end_p (i); tsi_next (&i)) + for (tree stmt : tsi_range (body)) { - ok = build_data_member_initialization (tsi_stmt (i), &vec); + ok = build_data_member_initialization (stmt, &vec); if (!ok) break; } @@ -674,11 +670,10 @@ constexpr_fn_retval (tree body) { case STATEMENT_LIST: { - tree_stmt_iterator i; tree expr = NULL_TREE; - for (i = tsi_start (body); !tsi_end_p (i); tsi_next (&i)) + for (tree stmt : tsi_range (body)) { - tree s = constexpr_fn_retval (tsi_stmt (i)); + tree s = constexpr_fn_retval (stmt); if (s == error_mark_node) return error_mark_node; else if (s == NULL_TREE) @@ -870,7 +865,7 @@ maybe_save_constexpr_fundef (tree fun) if (processing_template_decl || !DECL_DECLARED_CONSTEXPR_P (fun) || cp_function_chain->invalid_constexpr - || DECL_CLONED_FUNCTION_P (fun)) + || (DECL_CLONED_FUNCTION_P (fun) && !DECL_DELETING_DESTRUCTOR_P (fun))) return; if (!is_valid_constexpr_fn (fun, !DECL_GENERATED_P (fun))) @@ -947,7 +942,6 @@ explain_invalid_constexpr_fn (tree fun) { static hash_set<tree> *diagnosed; tree body; - location_t save_loc; /* Only diagnose defaulted functions, lambdas, or instantiations. */ if (!DECL_DEFAULTED_FN (fun) && !LAMBDA_TYPE_P (CP_DECL_CONTEXT (fun)) @@ -962,7 +956,7 @@ explain_invalid_constexpr_fn (tree fun) /* Already explained. */ return; - save_loc = input_location; + iloc_sentinel ils = input_location; if (!lambda_static_thunk_p (fun)) { /* Diagnostics should completely ignore the static thunk, so leave @@ -990,7 +984,6 @@ explain_invalid_constexpr_fn (tree fun) cx_check_missing_mem_inits (DECL_CONTEXT (fun), body, true); } } - input_location = save_loc; } /* Objects of this type represent calls to constexpr functions @@ -1320,7 +1313,10 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, } /* For __builtin_is_constant_evaluated, defer it if not - ctx->manifestly_const_eval, otherwise fold it to true. */ + ctx->manifestly_const_eval (as sometimes we try to constant evaluate + without manifestly_const_eval even expressions or parts thereof which + will later be manifestly const_eval evaluated), otherwise fold it to + true. */ if (fndecl_built_in_p (fun, CP_BUILT_IN_IS_CONSTANT_EVALUATED, BUILT_IN_FRONTEND)) { @@ -1429,8 +1425,32 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, && ctx->call && ctx->call->fundef) current_function_decl = ctx->call->fundef->decl; - new_call = fold_builtin_call_array (EXPR_LOCATION (t), TREE_TYPE (t), - CALL_EXPR_FN (t), nargs, args); + if (fndecl_built_in_p (fun, + CP_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS, + BUILT_IN_FRONTEND)) + { + location_t loc = EXPR_LOCATION (t); + if (nargs >= 1) + VERIFY_CONSTANT (args[0]); + new_call + = fold_builtin_is_pointer_inverconvertible_with_class (loc, nargs, + args); + } + else if (fndecl_built_in_p (fun, + CP_BUILT_IN_IS_CORRESPONDING_MEMBER, + BUILT_IN_FRONTEND)) + { + location_t loc = EXPR_LOCATION (t); + if (nargs >= 2) + { + VERIFY_CONSTANT (args[0]); + VERIFY_CONSTANT (args[1]); + } + new_call = fold_builtin_is_corresponding_member (loc, nargs, args); + } + else + new_call = fold_builtin_call_array (EXPR_LOCATION (t), TREE_TYPE (t), + CALL_EXPR_FN (t), nargs, args); current_function_decl = save_cur_fn; force_folding_builtin_constant_p = save_ffbcp; if (new_call == NULL) @@ -1555,6 +1575,32 @@ free_constructor (tree t) } } +/* Helper function of cxx_bind_parameters_in_call. Return non-NULL + if *TP is address of a static variable (or part of it) currently being + constructed or of a heap artificial variable. */ + +static tree +addr_of_non_const_var (tree *tp, int *walk_subtrees, void *data) +{ + if (TREE_CODE (*tp) == ADDR_EXPR) + if (tree var = get_base_address (TREE_OPERAND (*tp, 0))) + if (VAR_P (var) && TREE_STATIC (var)) + { + if (DECL_NAME (var) == heap_uninit_identifier + || DECL_NAME (var) == heap_identifier + || DECL_NAME (var) == heap_vec_uninit_identifier + || DECL_NAME (var) == heap_vec_identifier) + return var; + + constexpr_global_ctx *global = (constexpr_global_ctx *) data; + if (global->values.get (var)) + return var; + } + if (TYPE_P (*tp)) + *walk_subtrees = false; + return NULL_TREE; +} + /* Subroutine of cxx_eval_call_expression. We are processing a call expression (either CALL_EXPR or AGGR_INIT_EXPR) in the context of CTX. Evaluate @@ -1616,6 +1662,15 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, /* The destructor needs to see any modifications the callee makes to the argument. */ *non_constant_args = true; + /* If arg is or contains address of a heap artificial variable or + of a static variable being constructed, avoid caching the + function call, as those variables might be modified by the + function, or might be modified by the callers in between + the cached function and just read by the function. */ + else if (!*non_constant_args + && cp_walk_tree (&arg, addr_of_non_const_var, ctx->global, + NULL)) + *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 @@ -2317,7 +2372,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, *non_constant_p = true; return t; } - if (DECL_CLONED_FUNCTION_P (fun)) + if (DECL_CLONED_FUNCTION_P (fun) && !DECL_DELETING_DESTRUCTOR_P (fun)) fun = DECL_CLONED_FUNCTION (fun); if (is_ubsan_builtin_p (fun)) @@ -2515,6 +2570,8 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, location_t save_loc = input_location; input_location = loc; ++function_depth; + if (ctx->manifestly_const_eval) + FNDECL_MANIFESTLY_CONST_EVALUATED (fun) = true; instantiate_decl (fun, /*defer_ok*/false, /*expl_inst*/false); --function_depth; input_location = save_loc; @@ -2760,9 +2817,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, /* Forget the saved values of the callee's SAVE_EXPRs and TARGET_EXPRs. */ - unsigned int i; - tree save_expr; - FOR_EACH_VEC_ELT (save_exprs, i, save_expr) + for (tree save_expr : save_exprs) ctx->global->values.remove (save_expr); /* Remove the parms/result from the values map. Is it worth @@ -2875,9 +2930,27 @@ reduced_constant_expression_p (tree t) /* An initialized vector would have a VECTOR_CST. */ return false; else if (cxx_dialect >= cxx20 - /* An ARRAY_TYPE doesn't have any TYPE_FIELDS. */ && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE) - field = NULL_TREE; + { + /* There must be a valid constant initializer at every array + index. */ + tree min = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (t))); + tree max = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (t))); + tree cursor = min; + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), i, idx, val) + { + if (!reduced_constant_expression_p (val)) + return false; + if (array_index_cmp (cursor, idx) != 0) + return false; + if (TREE_CODE (idx) == RANGE_EXPR) + cursor = TREE_OPERAND (idx, 1); + cursor = int_const_binop (PLUS_EXPR, cursor, size_one_node); + } + if (find_array_ctor_elt (t, max) == -1) + return false; + goto ok; + } else if (cxx_dialect >= cxx20 && TREE_CODE (TREE_TYPE (t)) == UNION_TYPE) { @@ -2911,6 +2984,7 @@ reduced_constant_expression_p (tree t) for (; field; field = next_initializable_field (DECL_CHAIN (field))) if (!is_really_empty_class (TREE_TYPE (field), /*ignore_vptr*/false)) return false; +ok: if (CONSTRUCTOR_NO_CLEARING (t)) /* All the fields are initialized. */ CONSTRUCTOR_NO_CLEARING (t) = false; @@ -3249,6 +3323,22 @@ cxx_eval_conditional_expression (const constexpr_ctx *ctx, tree t, /*lval*/false, non_constant_p, overflow_p); VERIFY_CONSTANT (val); + if (TREE_CODE (t) == IF_STMT && IF_STMT_CONSTEVAL_P (t)) + { + /* Evaluate the condition as if it was + if (__builtin_is_constant_evaluated ()), i.e. defer it if not + ctx->manifestly_const_eval (as sometimes we try to constant evaluate + without manifestly_const_eval even expressions or parts thereof which + will later be manifestly const_eval evaluated), otherwise fold it to + true. */ + if (ctx->manifestly_const_eval) + val = boolean_true_node; + else + { + *non_constant_p = true; + return t; + } + } /* Don't VERIFY_CONSTANT the other operands. */ if (integer_zerop (val)) val = TREE_OPERAND (t, 2); @@ -3779,20 +3869,29 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, directly for non-aggregates to avoid creating a garbage CONSTRUCTOR. */ tree val; constexpr_ctx new_ctx; - if (CP_AGGREGATE_TYPE_P (elem_type)) + if (is_really_empty_class (elem_type, /*ignore_vptr*/false)) + return build_constructor (elem_type, NULL); + else 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); + } + else + val = build_value_init (elem_type, tf_warning_or_error); + + if (!SCALAR_TYPE_P (elem_type)) + { new_ctx = *ctx; - new_ctx.object = t; + if (ctx->object) + /* If there was no object, don't add one: it could confuse us + into thinking we're modifying a const object. */ + new_ctx.object = t; new_ctx.ctor = build_constructor (elem_type, NULL); ctx = &new_ctx; } - else - val = build_value_init (elem_type, tf_warning_or_error); t = cxx_eval_constant_expression (ctx, val, lval, non_constant_p, overflow_p); - if (CP_AGGREGATE_TYPE_P (elem_type) && t != ctx->ctor) + if (!SCALAR_TYPE_P (elem_type) && t != ctx->ctor) free_constructor (ctx->ctor); return t; } @@ -4383,7 +4482,12 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t, FOR_EACH_CONSTRUCTOR_ELT (v, i, index, value) { tree orig_value = value; - init_subob_ctx (ctx, new_ctx, index, value); + /* Like in cxx_eval_store_expression, omit entries for empty fields. */ + bool no_slot = TREE_CODE (type) == RECORD_TYPE && is_empty_field (index); + if (no_slot) + new_ctx = *ctx; + else + init_subob_ctx (ctx, new_ctx, index, value); int pos_hint = -1; if (new_ctx.ctor != ctx->ctor) { @@ -4429,6 +4533,8 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t, gcc_assert (is_empty_class (TREE_TYPE (TREE_TYPE (index)))); changed = true; } + else if (no_slot) + changed = true; else { if (TREE_CODE (type) == UNION_TYPE @@ -4679,28 +4785,17 @@ cxx_fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, { tree optype = TREE_TYPE (op); unsigned HOST_WIDE_INT const_nunits; - if (off == 0) + if (off == 0 && similar_type_p (optype, type)) + return op; + else if (TREE_CODE (optype) == COMPLEX_TYPE + && similar_type_p (type, TREE_TYPE (optype))) { - if (similar_type_p (optype, type)) - return op; - /* Also handle conversion to an empty base class, which - is represented with a NOP_EXPR. */ /* *(foo *)&complexfoo => __real__ complexfoo */ - else if (TREE_CODE (optype) == COMPLEX_TYPE - && similar_type_p (type, TREE_TYPE (optype))) + if (off == 0) return build1_loc (loc, REALPART_EXPR, type, op); - } - /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */ - else if (TREE_CODE (optype) == COMPLEX_TYPE - && similar_type_p (type, TREE_TYPE (optype)) - && tree_to_uhwi (TYPE_SIZE_UNIT (type)) == off) - return build1_loc (loc, IMAGPART_EXPR, type, op); - if (is_empty_class (type) - && CLASS_TYPE_P (optype) - && DERIVED_FROM_P (type, optype)) - { - *empty_base = true; - return op; + /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */ + else if (tree_to_uhwi (TYPE_SIZE_UNIT (type)) == off) + return build1_loc (loc, IMAGPART_EXPR, type, op); } /* ((foo*)&vectorfoo)[x] => BIT_FIELD_REF<vectorfoo,...> */ else if (VECTOR_TYPE_P (optype) @@ -4779,6 +4874,15 @@ cxx_fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, return ret; } } + /* Also handle conversion to an empty base class, which + is represented with a NOP_EXPR. */ + if (is_empty_class (type) + && CLASS_TYPE_P (optype) + && DERIVED_FROM_P (type, optype)) + { + *empty_base = true; + return op; + } } return NULL_TREE; @@ -4839,12 +4943,26 @@ cxx_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type, && tree_fits_uhwi_p (TREE_OPERAND (sub, 1))) { tree op00 = TREE_OPERAND (sub, 0); - tree op01 = TREE_OPERAND (sub, 1); + tree off = TREE_OPERAND (sub, 1); STRIP_NOPS (op00); if (TREE_CODE (op00) == ADDR_EXPR) - return cxx_fold_indirect_ref_1 (ctx, loc, type, TREE_OPERAND (op00, 0), - tree_to_uhwi (op01), empty_base); + { + tree obj = TREE_OPERAND (op00, 0); + while (TREE_CODE (obj) == COMPONENT_REF + && tree_int_cst_sign_bit (off)) + { + /* Canonicalize this object/offset pair by iteratively absorbing + the innermost component into the offset until the offset is + nonnegative, so that cxx_fold_indirect_ref_1 can identify + more folding opportunities. */ + tree field = TREE_OPERAND (obj, 1); + off = int_const_binop (PLUS_EXPR, off, byte_position (field)); + obj = TREE_OPERAND (obj, 0); + } + return cxx_fold_indirect_ref_1 (ctx, loc, type, obj, + tree_to_uhwi (off), empty_base); + } } /* *(foo *)fooarrptr => (*fooarrptr)[0] */ else if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE @@ -5060,6 +5178,16 @@ var_in_constexpr_fn (tree t) && DECL_DECLARED_CONSTEXPR_P (ctx)); } +/* True if a function might be constexpr: either a function that was + declared constexpr, or a C++17 lambda op(). */ + +bool +maybe_constexpr_fn (tree t) +{ + return (DECL_DECLARED_CONSTEXPR_P (t) + || (cxx_dialect >= cxx17 && LAMBDA_FUNCTION_P (t))); +} + /* True if T was declared in a function that might be constexpr: either a function that was declared constexpr, or a C++17 lambda op(). */ @@ -5405,9 +5533,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, semantics are not applied on an object under construction. They come into effect when the constructor for the most derived object ends." */ - tree elt; - unsigned int i; - FOR_EACH_VEC_ELT (*ctors, i, elt) + for (tree elt : *ctors) if (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (const_object_being_modified), TREE_TYPE (elt))) { @@ -5474,8 +5600,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, argument, which has the derived type rather than the base type. In this situation, just evaluate the initializer and return, since there's no actual data to store. */ - gcc_assert (is_empty_class (TREE_TYPE (init)) && !lval); - return init; + gcc_assert (is_empty_class (TREE_TYPE (init))); + return lval ? target : init; } CONSTRUCTOR_ELTS (*valp) = CONSTRUCTOR_ELTS (init); TREE_CONSTANT (*valp) = TREE_CONSTANT (init); @@ -5483,6 +5609,14 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, CONSTRUCTOR_NO_CLEARING (*valp) = CONSTRUCTOR_NO_CLEARING (init); } + else if (TREE_CODE (init) == CONSTRUCTOR + && !same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (init), + type)) + { + /* See above on initialization of empty bases. */ + gcc_assert (is_empty_class (TREE_TYPE (init)) && !lval); + return init; + } else *valp = init; @@ -5507,12 +5641,10 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, /* Update TREE_CONSTANT and TREE_SIDE_EFFECTS on enclosing CONSTRUCTORs, if any. */ - tree elt; - unsigned i; bool c = TREE_CONSTANT (init); bool s = TREE_SIDE_EFFECTS (init); if (!c || s || activated_union_member_p) - FOR_EACH_VEC_ELT (*ctors, i, elt) + for (tree elt : *ctors) { if (!c) TREE_CONSTANT (elt) = false; @@ -5697,7 +5829,6 @@ cxx_eval_statement_list (const constexpr_ctx *ctx, tree t, bool *non_constant_p, bool *overflow_p, tree *jump_target) { - tree_stmt_iterator i; tree local_target; /* In a statement-expression we want to return the last value. For empty statement expression return void_node. */ @@ -5707,9 +5838,8 @@ cxx_eval_statement_list (const constexpr_ctx *ctx, tree t, local_target = NULL_TREE; jump_target = &local_target; } - for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) + for (tree stmt : tsi_range (t)) { - tree stmt = tsi_stmt (i); /* We've found a continue, so skip everything until we reach the label its jumping to. */ if (continues (jump_target)) @@ -5832,9 +5962,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, } /* Forget saved values of SAVE_EXPRs and TARGET_EXPRs. */ - unsigned int i; - tree save_expr; - FOR_EACH_VEC_ELT (save_exprs, i, save_expr) + for (tree save_expr : save_exprs) ctx->global->values.remove (save_expr); save_exprs.truncate (0); @@ -5856,9 +5984,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, && !*non_constant_p); /* Forget saved values of SAVE_EXPRs and TARGET_EXPRs. */ - unsigned int i; - tree save_expr; - FOR_EACH_VEC_ELT (save_exprs, i, save_expr) + for (tree save_expr : save_exprs) ctx->global->values.remove (save_expr); return NULL_TREE; @@ -5949,6 +6075,37 @@ inline_asm_in_constexpr_error (location_t loc) "%<constexpr%> function in C++20"); } +/* We're getting the constant value of DECL in a manifestly constant-evaluated + context; maybe complain about that. */ + +static void +maybe_warn_about_constant_value (location_t loc, tree decl) +{ + static bool explained = false; + if (cxx_dialect >= cxx17 + && warn_interference_size + && !global_options_set.x_param_destruct_interfere_size + && DECL_CONTEXT (decl) == std_node + && id_equal (DECL_NAME (decl), "hardware_destructive_interference_size") + && (LOCATION_FILE (input_location) != main_input_filename + || module_exporting_p ()) + && warning_at (loc, OPT_Winterference_size, "use of %qD", decl) + && !explained) + { + explained = true; + inform (loc, "its value can vary between compiler versions or " + "with different %<-mtune%> or %<-mcpu%> flags"); + inform (loc, "if this use is part of a public ABI, change it to " + "instead use a constant variable you define"); + inform (loc, "the default value for the current CPU tuning " + "is %d bytes", param_destruct_interfere_size); + inform (loc, "you can stabilize this value with %<--param " + "hardware_destructive_interference_size=%d%>, or disable " + "this warning with %<-Wno-interference-size%>", + param_destruct_interfere_size); + } +} + /* Attempt to reduce the expression T to a constant value. On failure, issue diagnostic and return error_mark_node. */ /* FIXME unify with c_fully_fold */ @@ -6093,6 +6250,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, r = *p; break; } + if (ctx->manifestly_const_eval) + maybe_warn_about_constant_value (loc, t); if (COMPLETE_TYPE_P (TREE_TYPE (t)) && is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false)) { @@ -6656,7 +6815,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, if (TREE_CODE (t) == CONVERT_EXPR && ARITHMETIC_TYPE_P (type) - && INDIRECT_TYPE_P (TREE_TYPE (op))) + && INDIRECT_TYPE_P (TREE_TYPE (op)) + && ctx->manifestly_const_eval) { if (!ctx->quiet) error_at (loc, @@ -6669,8 +6829,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, /* [expr.const]: a conversion from type cv void* to a pointer-to-object type cannot be part of a core constant expression as a resolution to DR 1312. */ - if (integer_zerop (op) /* FIXME: Remove in GCC 12. */ - && TYPE_PTROB_P (type) + if (TYPE_PTROB_P (type) && TYPE_PTR_P (TREE_TYPE (op)) && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (op))) /* Inside a call to std::construct_at or to @@ -7319,6 +7478,11 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, } } + /* Remember the original location if that wouldn't need a wrapper. */ + if (location_t loc = EXPR_LOCATION (t)) + if (CAN_HAVE_LOCATION_P (r)) + SET_EXPR_LOCATION (r, loc); + return r; } @@ -7332,6 +7496,18 @@ cxx_constant_value (tree t, tree decl) return cxx_eval_outermost_constant_expr (t, false, true, true, false, decl); } +/* As above, but respect SFINAE. */ + +tree +cxx_constant_value_sfinae (tree t, tsubst_flags_t complain) +{ + bool sfinae = !(complain & tf_error); + tree r = cxx_eval_outermost_constant_expr (t, sfinae, true, true); + if (sfinae && !TREE_CONSTANT (r)) + r = error_mark_node; + return r; +} + /* Like cxx_constant_value, but used for evaluation of constexpr destructors of constexpr variables. The actual initializer of DECL is not modified. */ @@ -8207,16 +8383,10 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, } case STATEMENT_LIST: - { - tree_stmt_iterator i; - for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) - { - if (!RECUR (tsi_stmt (i), any)) - return false; - } - return true; - } - break; + for (tree stmt : tsi_range (t)) + if (!RECUR (stmt, any)) + return false; + return true; case MODIFY_EXPR: if (cxx_dialect < cxx14) @@ -8738,10 +8908,17 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, return false; if (!processing_template_decl) tmp = cxx_eval_outermost_constant_expr (tmp, true); - if (integer_zerop (tmp)) - return RECUR (TREE_OPERAND (t, 2), want_rval); - else if (TREE_CODE (tmp) == INTEGER_CST) - return RECUR (TREE_OPERAND (t, 1), want_rval); + /* potential_constant_expression* isn't told if it is called for + manifestly_const_eval or not, so for consteval if always + process both branches as if the condition is not a known + constant. */ + if (TREE_CODE (t) != IF_STMT || !IF_STMT_CONSTEVAL_P (t)) + { + if (integer_zerop (tmp)) + return RECUR (TREE_OPERAND (t, 2), want_rval); + else if (TREE_CODE (tmp) == INTEGER_CST) + return RECUR (TREE_OPERAND (t, 1), want_rval); + } tmp = *jump_target; for (i = 1; i < 3; ++i) { diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 5cf43bd..1aaf1e2 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -278,21 +278,6 @@ get_concept_check_template (tree t) return tmpl; } -/* Returns true if any of the arguments in the template argument list is - a wildcard or wildcard pack. */ - -bool -contains_wildcard_p (tree args) -{ - for (int i = 0; i < TREE_VEC_LENGTH (args); ++i) - { - tree arg = TREE_VEC_ELT (args, i); - if (TREE_CODE (arg) == WILDCARD_DECL) - return true; - } - return false; -} - /*--------------------------------------------------------------------------- Resolution of qualified concept names ---------------------------------------------------------------------------*/ @@ -886,6 +871,16 @@ get_normalized_constraints_from_decl (tree d, bool diag = false) it has the correct template information attached. */ d = strip_inheriting_ctors (d); + if (regenerated_lambda_fn_p (d)) + { + /* If this lambda was regenerated, DECL_TEMPLATE_PARMS doesn't contain + all in-scope template parameters, but the lambda from which it was + ultimately regenerated does, so use that instead. */ + tree lambda = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (d)); + lambda = most_general_lambda (lambda); + d = lambda_function (lambda); + } + if (TREE_CODE (d) == TEMPLATE_DECL) { tmpl = d; @@ -931,12 +926,7 @@ get_normalized_constraints_from_decl (tree d, bool diag = false) 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; - + push_access_scope_guard pas (decl); norm = get_normalized_constraints_from_info (ci, tmpl, diag); } @@ -1300,18 +1290,6 @@ maybe_substitute_reqs_for (tree reqs, const_tree decl_) return reqs; } -/* Returns the template-head requires clause for the template - declaration T or NULL_TREE if none. */ - -tree -get_template_head_requirements (tree t) -{ - tree ci = get_constraints (t); - if (!ci) - return NULL_TREE; - return CI_TEMPLATE_REQS (ci); -} - /* Returns the trailing requires clause of the declarator of a template declaration T or NULL_TREE if none. */ @@ -2288,7 +2266,8 @@ tsubst_requires_expr (tree t, tree args, sat_info info) /* A requires-expression is an unevaluated context. */ cp_unevaluated u; - args = add_extra_args (REQUIRES_EXPR_EXTRA_ARGS (t), args); + args = add_extra_args (REQUIRES_EXPR_EXTRA_ARGS (t), args, + info.complain, info.in_decl); if (processing_template_decl) { /* We're partially instantiating a generic lambda. Substituting into @@ -2737,6 +2716,7 @@ tsubst_constraint (tree t, tree args, tsubst_flags_t complain, tree in_decl) /* We also don't want to evaluate concept-checks when substituting the constraint-expressions of a declaration. */ processing_constraint_expression_sentinel s; + cp_unevaluated u; tree expr = tsubst_expr (t, args, complain, in_decl, false); return expr; } @@ -2995,7 +2975,10 @@ satisfy_atom (tree t, tree args, sat_info info) /* Compute the value of the constraint. */ if (info.noisy ()) - result = cxx_constant_value (result); + { + iloc_sentinel ils (EXPR_LOCATION (result)); + result = cxx_constant_value (result); + } else { result = maybe_constant_value (result, NULL_TREE, @@ -3056,6 +3039,9 @@ satisfy_normalized_constraints (tree t, tree args, sat_info info) /* We need to check access during satisfaction. */ deferring_access_check_sentinel acs (dk_no_deferred); + /* Constraints are unevaluated operands. */ + cp_unevaluated u; + return satisfy_constraint_r (t, args, info); } @@ -3075,6 +3061,15 @@ normalize_placeholder_type_constraints (tree t, bool diag) scope for this placeholder type; use them as the initial template parameters for normalization. */ tree initial_parms = TREE_PURPOSE (ci); + + if (!initial_parms && TEMPLATE_TYPE_LEVEL (t) == 2) + /* This is a return-type-requirement of a non-templated requires-expression, + which are parsed under processing_template_decl == 1 and empty + current_template_parms; hence the 'auto' has level 2 and initial_parms + is empty. Fix up initial_parms to be consistent with the value of + processing_template_decl whence the 'auto' was created. */ + initial_parms = build_tree_list (size_int (1), make_tree_vec (0)); + /* The 'auto' itself is used as the first argument in its own constraints, and its level is one greater than its template depth. So in order to capture all used template parameters, we need to add an extra level of @@ -3174,13 +3169,27 @@ satisfy_declaration_constraints (tree t, sat_info info) args = TI_ARGS (ti); if (inh_ctor_targs) args = add_outermost_template_args (args, inh_ctor_targs); + } - /* If any arguments depend on template parameters, we can't - check constraints. Pretend they're satisfied for now. */ - if (uses_template_parms (args)) - return boolean_true_node; + if (regenerated_lambda_fn_p (t)) + { + /* The TI_ARGS of a regenerated lambda contains only the innermost + set of template arguments. Augment this with the outer template + arguments that were used to regenerate the lambda. */ + gcc_assert (!args || TMPL_ARGS_DEPTH (args) == 1); + tree lambda = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (t)); + tree outer_args = TI_ARGS (LAMBDA_EXPR_REGEN_INFO (lambda)); + if (args) + args = add_to_template_args (outer_args, args); + else + args = outer_args; } + /* If any arguments depend on template parameters, we can't + check constraints. Pretend they're satisfied for now. */ + if (uses_template_parms (args)) + return boolean_true_node; + /* Get the normalized constraints. */ tree norm = get_normalized_constraints_from_decl (t, info.noisy ()); @@ -3227,7 +3236,16 @@ satisfy_declaration_constraints (tree t, tree args, sat_info info) gcc_assert (TREE_CODE (t) == TEMPLATE_DECL); - args = add_outermost_template_args (t, args); + if (regenerated_lambda_fn_p (t)) + { + /* As in the two-parameter version of this function. */ + gcc_assert (TMPL_ARGS_DEPTH (args) == 1); + tree lambda = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (t)); + tree outer_args = TI_ARGS (LAMBDA_EXPR_REGEN_INFO (lambda)); + args = add_to_template_args (outer_args, args); + } + else + args = add_outermost_template_args (t, args); /* If any arguments depend on template parameters, we can't check constraints. Pretend they're satisfied for now. */ @@ -3268,14 +3286,14 @@ constraint_satisfaction_value (tree t, tree args, sat_info info) else r = satisfy_nondeclaration_constraints (t, args, info); if (r == error_mark_node && info.quiet () - && !(DECL_P (t) && TREE_NO_WARNING (t))) + && !(DECL_P (t) && warning_suppressed_p (t))) { /* Replay the error noisily. */ sat_info noisy (tf_warning_or_error, info.in_decl); constraint_satisfaction_value (t, args, noisy); if (DECL_P (t) && !args) /* Avoid giving these errors again. */ - TREE_NO_WARNING (t) = true; + suppress_warning (t); } return r; } @@ -3318,7 +3336,7 @@ evaluate_concept_check (tree check) } /* Evaluate the requires-expression T, returning either boolean_true_node - or boolean_false_node. This is used during gimplification and constexpr + or boolean_false_node. This is used during folding and constexpr evaluation. */ tree @@ -3429,31 +3447,6 @@ check_function_concept (tree fn) return NULL_TREE; } - -// Check that a constrained friend declaration function declaration, -// FN, is admissible. This is the case only when the declaration depends -// on template parameters and does not declare a specialization. -void -check_constrained_friend (tree fn, tree reqs) -{ - if (fn == error_mark_node) - return; - gcc_assert (TREE_CODE (fn) == FUNCTION_DECL); - - // If there are not constraints, this cannot be an error. - if (!reqs) - return; - - // Constrained friend functions that don't depend on template - // arguments are effectively meaningless. - if (!uses_template_parms (TREE_TYPE (fn))) - { - error_at (location_of (fn), - "constrained friend does not depend on template parameters"); - return; - } -} - /*--------------------------------------------------------------------------- Equivalence of constraints ---------------------------------------------------------------------------*/ @@ -3481,16 +3474,6 @@ equivalently_constrained (tree d1, tree d2) Partial ordering of constraints ---------------------------------------------------------------------------*/ -/* Returns true when the constraints in A subsume those in B. */ - -bool -subsumes_constraints (tree a, tree b) -{ - gcc_assert (!a || TREE_CODE (a) == CONSTRAINT_INFO); - gcc_assert (!b || TREE_CODE (b) == CONSTRAINT_INFO); - return subsumes (a, b); -} - /* Returns true when the constraints in CI strictly subsume the associated constraints of TMPL. */ @@ -3645,9 +3628,16 @@ diagnose_trait_expr (tree expr, tree args) case CPTK_IS_FINAL: inform (loc, " %qT is not a final class", t1); break; + case CPTK_IS_LAYOUT_COMPATIBLE: + inform (loc, " %qT is not layout compatible with %qT", t1, t2); + break; case CPTK_IS_LITERAL_TYPE: inform (loc, " %qT is not a literal type", t1); break; + case CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF: + inform (loc, " %qT is not pointer-interconvertible base of %qT", + t1, t2); + break; case CPTK_IS_POD: inform (loc, " %qT is not a POD type", t1); break; diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index 51984ef..9ab2be0 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -82,11 +82,13 @@ static bool coro_promise_type_found_p (tree, location_t); struct GTY((for_user)) coroutine_info { tree function_decl; /* The original function decl. */ - tree promise_type; /* The cached promise type for this function. */ - tree handle_type; /* The cached coroutine handle for this function. */ - tree self_h_proxy; /* A handle instance that is used as the proxy for the - one that will eventually be allocated in the coroutine - frame. */ + tree actor_decl; /* The synthesized actor function. */ + tree destroy_decl; /* The synthesized destroy function. */ + tree promise_type; /* The cached promise type for this function. */ + tree handle_type; /* The cached coroutine handle for this function. */ + tree self_h_proxy; /* A handle instance that is used as the proxy for the + one that will eventually be allocated in the coroutine + frame. */ tree promise_proxy; /* Likewise, a proxy promise instance. */ tree return_void; /* The expression for p.return_void() if it exists. */ location_t first_coro_keyword; /* The location of the keyword that made this @@ -526,6 +528,46 @@ coro_promise_type_found_p (tree fndecl, location_t loc) return true; } +/* Map from actor or destroyer to ramp. */ +static GTY(()) hash_map<tree, tree> *to_ramp; + +/* Given a tree that is an actor or destroy, find the ramp function. */ + +tree +coro_get_ramp_function (tree decl) +{ + if (!to_ramp) + return NULL_TREE; + tree *p = to_ramp->get (decl); + if (p) + return *p; + return NULL_TREE; +} + +/* Given the DECL for a ramp function (the user's original declaration) return + the actor function if it has been defined. */ + +tree +coro_get_actor_function (tree decl) +{ + if (coroutine_info *info = get_coroutine_info (decl)) + return info->actor_decl; + + return NULL_TREE; +} + +/* Given the DECL for a ramp function (the user's original declaration) return + the destroy function if it has been defined. */ + +tree +coro_get_destroy_function (tree decl) +{ + if (coroutine_info *info = get_coroutine_info (decl)) + return info->destroy_decl; + + return NULL_TREE; +} + /* These functions assumes that the caller has verified that the state for the decl has been initialized, we try to minimize work here. */ @@ -950,18 +992,11 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind) e_proxy = o; o = NULL_TREE; /* The var is already present. */ } - else if (type_build_ctor_call (o_type)) - { - e_proxy = get_awaitable_var (suspend_kind, o_type); - releasing_vec arg (make_tree_vector_single (rvalue (o))); - o = build_special_member_call (e_proxy, complete_ctor_identifier, - &arg, o_type, LOOKUP_NORMAL, - tf_warning_or_error); - } else { e_proxy = get_awaitable_var (suspend_kind, o_type); - o = build2 (INIT_EXPR, o_type, e_proxy, rvalue (o)); + o = cp_build_modify_expr (loc, e_proxy, INIT_EXPR, o, + tf_warning_or_error); } /* I suppose we could check that this is contextually convertible to bool. */ @@ -1085,7 +1120,7 @@ finish_co_await_expr (location_t kw, tree expr) is declared to return non-void (most likely). This is correct - we synthesize the return for the ramp in the compiler. So suppress any extraneous warnings during substitution. */ - TREE_NO_WARNING (current_function_decl) = true; + suppress_warning (current_function_decl, OPT_Wreturn_type); /* If we don't know the promise type, we can't proceed, build the co_await with the expression unchanged. */ @@ -1161,7 +1196,7 @@ finish_co_yield_expr (location_t kw, tree expr) is declared to return non-void (most likely). This is correct - we synthesize the return for the ramp in the compiler. So suppress any extraneous warnings during substitution. */ - TREE_NO_WARNING (current_function_decl) = true; + suppress_warning (current_function_decl, OPT_Wreturn_type); /* If we don't know the promise type, we can't proceed, build the co_await with the expression unchanged. */ @@ -1242,7 +1277,7 @@ finish_co_return_stmt (location_t kw, tree expr) is declared to return non-void (most likely). This is correct - we synthesize the return for the ramp in the compiler. So suppress any extraneous warnings during substitution. */ - TREE_NO_WARNING (current_function_decl) = true; + suppress_warning (current_function_decl, OPT_Wreturn_type); if (processing_template_decl && check_for_bare_parameter_packs (expr)) @@ -1266,7 +1301,7 @@ finish_co_return_stmt (location_t kw, tree expr) /* Suppress -Wreturn-type for co_return, we need to check indirectly whether the promise type has a suitable return_void/return_value. */ - TREE_NO_WARNING (current_function_decl) = true; + suppress_warning (current_function_decl, OPT_Wreturn_type); if (!processing_template_decl && warn_sequence_point) verify_sequence_points (expr); @@ -1439,6 +1474,29 @@ coro_build_cvt_void_expr_stmt (tree expr, location_t loc) return coro_build_expr_stmt (t, loc); } +/* Helpers to build an artificial var, with location LOC, NAME and TYPE, in + CTX, and with initializer INIT. */ + +static tree +coro_build_artificial_var (location_t loc, tree name, tree type, tree ctx, + tree init) +{ + tree res = build_lang_decl (VAR_DECL, name, type); + DECL_SOURCE_LOCATION (res) = loc; + DECL_CONTEXT (res) = ctx; + DECL_ARTIFICIAL (res) = true; + DECL_INITIAL (res) = init; + return res; +} + +static tree +coro_build_artificial_var (location_t loc, const char *name, tree type, + tree ctx, tree init) +{ + return coro_build_artificial_var (loc, get_identifier (name), + type, ctx, init); +} + /* Helpers for label creation: 1. Create a named label in the specified context. */ @@ -1771,10 +1829,9 @@ await_statement_expander (tree *stmt, int *do_subtree, void *d) return NULL_TREE; /* Just process the sub-trees. */ else if (TREE_CODE (*stmt) == STATEMENT_LIST) { - tree_stmt_iterator i; - for (i = tsi_start (*stmt); !tsi_end_p (i); tsi_next (&i)) + for (tree &s : tsi_range (*stmt)) { - res = cp_walk_tree (tsi_stmt_ptr (i), await_statement_expander, + res = cp_walk_tree (&s, await_statement_expander, d, NULL); if (res) return res; @@ -1940,8 +1997,7 @@ transform_local_var_uses (tree *stmt, int *do_subtree, void *d) local_vars_transform *lvd = (local_vars_transform *) d; /* For each var in this bind expr (that has a frame id, which means it was - accessed), build a frame reference for each and then walk the bind expr - statements, substituting the frame ref for the original var. */ + accessed), build a frame reference and add it as the DECL_VALUE_EXPR. */ if (TREE_CODE (*stmt) == BIND_EXPR) { @@ -1957,13 +2013,9 @@ transform_local_var_uses (tree *stmt, int *do_subtree, void *d) /* Re-write the variable's context to be in the actor func. */ DECL_CONTEXT (lvar) = lvd->context; - /* For capture proxies, this could include the decl value expr. */ - if (local_var.is_lambda_capture || local_var.has_value_expr_p) - { - tree ve = DECL_VALUE_EXPR (lvar); - cp_walk_tree (&ve, transform_local_var_uses, d, NULL); + /* For capture proxies, this could include the decl value expr. */ + if (local_var.is_lambda_capture || local_var.has_value_expr_p) continue; /* No frame entry for this. */ - } /* TODO: implement selective generation of fields when vars are known not-used. */ @@ -1977,103 +2029,13 @@ transform_local_var_uses (tree *stmt, int *do_subtree, void *d) tree fld_idx = build3_loc (lvd->loc, COMPONENT_REF, TREE_TYPE (lvar), lvd->actor_frame, fld_ref, NULL_TREE); local_var.field_idx = fld_idx; - } - /* FIXME: we should be able to do this in the loop above, but (at least - for range for) there are cases where the DECL_INITIAL contains - forward references. - So, now we've built the revised var in the frame, substitute uses of - it in initializers and the bind expr body. */ - for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL; - lvar = DECL_CHAIN (lvar)) - { - /* we need to walk some of the decl trees, which might contain - references to vars replaced at a higher level. */ - cp_walk_tree (&DECL_INITIAL (lvar), transform_local_var_uses, d, - NULL); - cp_walk_tree (&DECL_SIZE (lvar), transform_local_var_uses, d, NULL); - cp_walk_tree (&DECL_SIZE_UNIT (lvar), transform_local_var_uses, d, - NULL); + SET_DECL_VALUE_EXPR (lvar, fld_idx); + DECL_HAS_VALUE_EXPR_P (lvar) = true; } cp_walk_tree (&BIND_EXPR_BODY (*stmt), transform_local_var_uses, d, NULL); - - /* Now we have processed and removed references to the original vars, - we can drop those from the bind - leaving capture proxies alone. */ - for (tree *pvar = &BIND_EXPR_VARS (*stmt); *pvar != NULL;) - { - bool existed; - local_var_info &local_var - = lvd->local_var_uses->get_or_insert (*pvar, &existed); - gcc_checking_assert (existed); - - /* Leave lambda closure captures alone, we replace the *this - pointer with the frame version and let the normal process - deal with the rest. - Likewise, variables with their value found elsewhere. - Skip past unused ones too. */ - if (local_var.is_lambda_capture - || local_var.has_value_expr_p - || local_var.field_id == NULL_TREE) - { - pvar = &DECL_CHAIN (*pvar); - continue; - } - - /* Discard this one, we replaced it. */ - *pvar = DECL_CHAIN (*pvar); - } - *do_subtree = 0; /* We've done the body already. */ return NULL_TREE; } - - tree var_decl = *stmt; - /* Look inside cleanups, we don't want to wrap a statement list in a - cleanup. */ - bool needs_cleanup = true; - if (TREE_CODE (var_decl) == CLEANUP_POINT_EXPR) - var_decl = TREE_OPERAND (var_decl, 0); - else - needs_cleanup = false; - - /* Look inside the decl_expr for the actual var. */ - bool decl_expr_p = TREE_CODE (var_decl) == DECL_EXPR; - if (decl_expr_p && TREE_CODE (DECL_EXPR_DECL (var_decl)) == VAR_DECL) - var_decl = DECL_EXPR_DECL (var_decl); - else if (TREE_CODE (var_decl) != VAR_DECL) - return NULL_TREE; - - /* VAR_DECLs that are not recorded can belong to the proxies we've placed - for the promise and coroutine handle(s), to global vars or to compiler - temporaries. Skip past these, we will handle them later. */ - local_var_info *local_var_i = lvd->local_var_uses->get (var_decl); - - if (local_var_i == NULL) - return NULL_TREE; - - if (local_var_i->is_lambda_capture - || local_var_i->is_static - || local_var_i->has_value_expr_p) - return NULL_TREE; - - /* This is our revised 'local' i.e. a frame slot. */ - tree revised = local_var_i->field_idx; - gcc_checking_assert (DECL_CONTEXT (var_decl) == lvd->context); - - if (decl_expr_p && DECL_INITIAL (var_decl)) - { - location_t loc = DECL_SOURCE_LOCATION (var_decl); - tree r - = cp_build_modify_expr (loc, revised, INIT_EXPR, - DECL_INITIAL (var_decl), tf_warning_or_error); - if (needs_cleanup) - r = coro_build_cvt_void_expr_stmt (r, EXPR_LOCATION (*stmt)); - *stmt = r; - } - else - *stmt = revised; - - if (decl_expr_p) - *do_subtree = 0; /* We've accounted for the nested use. */ return NULL_TREE; } @@ -2163,13 +2125,6 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody, /* One param, the coro frame pointer. */ tree actor_fp = DECL_ARGUMENTS (actor); - /* A void return. */ - tree resdecl = build_decl (loc, RESULT_DECL, 0, void_type_node); - DECL_ARTIFICIAL (resdecl) = 1; - DECL_IGNORED_P (resdecl) = 1; - DECL_RESULT (actor) = resdecl; - DECL_COROUTINE_P (actor) = 1; - /* We have a definition here. */ TREE_STATIC (actor) = 1; @@ -2181,12 +2136,10 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody, tree top_block = make_node (BLOCK); BIND_EXPR_BLOCK (actor_bind) = top_block; - tree continuation = build_lang_decl (VAR_DECL, - get_identifier ("actor.continue"), - void_coro_handle_type); - DECL_ARTIFICIAL (continuation) = 1; - DECL_IGNORED_P (continuation) = 1; - DECL_CONTEXT (continuation) = actor; + tree continuation = coro_build_artificial_var (loc, "_Coro_actor_continue", + void_coro_handle_type, actor, + NULL_TREE); + BIND_EXPR_VARS (actor_bind) = continuation; /* Link in the block associated with the outer scope of the re-written @@ -2304,6 +2257,7 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody, finish_switch_stmt (destroy_dispatcher); finish_then_clause (lsb_if); + begin_else_clause (lsb_if); tree dispatcher = begin_switch_stmt (); finish_switch_cond (rat, dispatcher); @@ -2341,6 +2295,7 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody, /* Insert the prototype dispatcher. */ finish_switch_stmt (dispatcher); + finish_else_clause (lsb_if); finish_if_stmt (lsb_if); @@ -2466,7 +2421,7 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody, /* done. */ r = build_stmt (loc, RETURN_EXPR, NULL); - TREE_NO_WARNING (r) |= 1; /* We don't want a warning about this. */ + suppress_warning (r); /* We don't want a warning about this. */ r = maybe_cleanup_point_expr_void (r); add_stmt (r); @@ -2475,7 +2430,7 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody, add_stmt (r); r = build_stmt (loc, RETURN_EXPR, NULL); - TREE_NO_WARNING (r) |= 1; /* We don't want a warning about this. */ + suppress_warning (r); /* We don't want a warning about this. */ r = maybe_cleanup_point_expr_void (r); add_stmt (r); @@ -2540,15 +2495,8 @@ build_destroy_fn (location_t loc, tree coro_frame_type, tree destroy, /* One param, the coro frame pointer. */ tree destr_fp = DECL_ARGUMENTS (destroy); - /* A void return. */ - tree resdecl = build_decl (loc, RESULT_DECL, 0, void_type_node); - DECL_ARTIFICIAL (resdecl) = 1; - DECL_IGNORED_P (resdecl) = 1; - DECL_RESULT (destroy) = resdecl; - /* We have a definition here. */ TREE_STATIC (destroy) = 1; - DECL_COROUTINE_P (destroy) = 1; tree destr_outer = push_stmt_list (); current_stmt_tree ()->stmts_are_full_exprs_p = 1; @@ -2805,7 +2753,7 @@ struct var_nest_node { var_nest_node () = default; var_nest_node (tree v, tree i, var_nest_node *p, var_nest_node *n) - : var(v), init(i), prev(p), next(n) + : var(v), init(i), prev(p), next(n), then_cl (NULL), else_cl (NULL) { if (p) p->next = this; @@ -2885,7 +2833,7 @@ flatten_await_stmt (var_nest_node *n, hash_set<tree> *promoted, tree else_cl = COND_EXPR_ELSE (old_expr); if (!VOID_TYPE_P (TREE_TYPE (else_cl))) { - gcc_checking_assert (TREE_CODE (then_cl) != STATEMENT_LIST); + gcc_checking_assert (TREE_CODE (else_cl) != STATEMENT_LIST); else_cl = build2 (init_expr ? INIT_EXPR : MODIFY_EXPR, var_type, var, else_cl); @@ -2989,15 +2937,8 @@ flatten_await_stmt (var_nest_node *n, hash_set<tree> *promoted, gcc_checking_assert (!already_present); tree inner = TREE_OPERAND (init, 1); gcc_checking_assert (TREE_CODE (inner) != COND_EXPR); - if (type_build_ctor_call (var_type)) - { - releasing_vec p_in (make_tree_vector_single (init)); - init = build_special_member_call (var, complete_ctor_identifier, - &p_in, var_type, LOOKUP_NORMAL, - tf_warning_or_error); - } - else - init = build2 (INIT_EXPR, var_type, var, init); + init = cp_build_modify_expr (input_location, var, INIT_EXPR, init, + tf_warning_or_error); /* Simplify for the case that we have an init containing the temp alone. */ if (t == n->init && n->var == NULL_TREE) @@ -3110,7 +3051,7 @@ process_conditional (var_nest_node *n, tree& vlist) { tree init = n->init; hash_map<tree, tree> var_flags; - vec<tree> var_list = vNULL; + auto_vec<tree> var_list; tree new_then = push_stmt_list (); handle_nested_conditionals (n->then_cl, var_list, var_flags); new_then = pop_stmt_list (new_then); @@ -3523,10 +3464,9 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d) } else if (TREE_CODE (*stmt) == STATEMENT_LIST) { - tree_stmt_iterator i; - for (i = tsi_start (*stmt); !tsi_end_p (i); tsi_next (&i)) + for (tree &s : tsi_range (*stmt)) { - res = cp_walk_tree (tsi_stmt_ptr (i), await_statement_walker, + res = cp_walk_tree (&s, await_statement_walker, d, NULL); if (res) return res; @@ -3812,8 +3752,8 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d) the parameter to return_value(). */ if (!maybe_await_stmt) maybe_await_stmt = tsi_stmt_ptr (tsi_last (ret_list)); - expr = build1_loc (loc, GOTO_EXPR, void_type_node, awpts->fs_label); - finish_expr_stmt (expr); + TREE_USED (awpts->fs_label) = 1; + add_stmt (build_stmt (loc, GOTO_EXPR, awpts->fs_label)); *stmt = pop_stmt_list (ret_list); /* Once this is complete, we will have processed subtrees. */ *do_subtree = 0; @@ -3945,8 +3885,6 @@ register_local_var_uses (tree *stmt, int *do_subtree, void *d) if (TREE_CODE (*stmt) == BIND_EXPR) { - lvd->bind_indx++; - lvd->nest_depth++; tree lvar; for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL; lvar = DECL_CHAIN (lvar)) @@ -3985,11 +3923,17 @@ register_local_var_uses (tree *stmt, int *do_subtree, void *d) continue; /* Make names depth+index unique, so that we can support nested - scopes with identically named locals. */ + scopes with identically named locals and still be able to + identify them in the coroutine frame. */ tree lvname = DECL_NAME (lvar); char *buf; - if (lvname != NULL_TREE) - buf = xasprintf ("__%s.%u.%u", IDENTIFIER_POINTER (lvname), + /* The outermost bind scope contains the artificial variables that + we inject to implement the coro state machine. We want to be able + to inspect these in debugging. */ + if (lvname != NULL_TREE && lvd->nest_depth == 0) + buf = xasprintf ("%s", IDENTIFIER_POINTER (lvname)); + else if (lvname != NULL_TREE) + buf = xasprintf ("%s_%u_%u", IDENTIFIER_POINTER (lvname), lvd->nest_depth, lvd->bind_indx); else buf = xasprintf ("_D%u.%u.%u", DECL_UID (lvar), lvd->nest_depth, @@ -4002,6 +3946,8 @@ register_local_var_uses (tree *stmt, int *do_subtree, void *d) /* We don't walk any of the local var sub-trees, they won't contain any bind exprs. */ } + lvd->bind_indx++; + lvd->nest_depth++; cp_walk_tree (&BIND_EXPR_BODY (*stmt), register_local_var_uses, d, NULL); *do_subtree = 0; /* We've done this. */ lvd->nest_depth--; @@ -4009,22 +3955,34 @@ register_local_var_uses (tree *stmt, int *do_subtree, void *d) return NULL_TREE; } -/* Build, return FUNCTION_DECL node with its coroutine frame pointer argument - for either actor or destroy functions. */ +/* Build, return FUNCTION_DECL node based on ORIG with a type FN_TYPE which has + a single argument of type CORO_FRAME_PTR. Build the actor function if + ACTOR_P is true, otherwise the destroy. */ static tree -act_des_fn (tree orig, tree fn_type, tree coro_frame_ptr, const char* name) +coro_build_actor_or_destroy_function (tree orig, tree fn_type, + tree coro_frame_ptr, bool actor_p) { - tree fn_name = get_fn_local_identifier (orig, name); - tree fn = build_lang_decl (FUNCTION_DECL, fn_name, fn_type); + location_t loc = DECL_SOURCE_LOCATION (orig); + tree fn + = build_lang_decl (FUNCTION_DECL, copy_node (DECL_NAME (orig)), fn_type); + + /* Allow for locating the ramp (original) function from this one. */ + if (!to_ramp) + to_ramp = hash_map<tree, tree>::create_ggc (10); + to_ramp->put (fn, orig); + DECL_CONTEXT (fn) = DECL_CONTEXT (orig); + DECL_SOURCE_LOCATION (fn) = loc; DECL_ARTIFICIAL (fn) = true; DECL_INITIAL (fn) = error_mark_node; + tree id = get_identifier ("frame_ptr"); tree fp = build_lang_decl (PARM_DECL, id, coro_frame_ptr); DECL_CONTEXT (fp) = fn; DECL_ARG_TYPE (fp) = type_passed_as (coro_frame_ptr); DECL_ARGUMENTS (fn) = fp; + /* Copy selected attributes from the original function. */ TREE_USED (fn) = TREE_USED (orig); if (DECL_SECTION_NAME (orig)) @@ -4036,6 +3994,28 @@ act_des_fn (tree orig, tree fn_type, tree coro_frame_ptr, const char* name) DECL_USER_ALIGN (fn) = DECL_USER_ALIGN (orig); /* Apply attributes from the original fn. */ DECL_ATTRIBUTES (fn) = copy_list (DECL_ATTRIBUTES (orig)); + + /* A void return. */ + tree resdecl = build_decl (loc, RESULT_DECL, 0, void_type_node); + DECL_CONTEXT (resdecl) = fn; + DECL_ARTIFICIAL (resdecl) = 1; + DECL_IGNORED_P (resdecl) = 1; + DECL_RESULT (fn) = resdecl; + + /* This is a coroutine component. */ + DECL_COROUTINE_P (fn) = 1; + + /* Set up a means to find out if a decl is one of the helpers and, if so, + which one. */ + if (coroutine_info *info = get_coroutine_info (orig)) + { + gcc_checking_assert ((actor_p && info->actor_decl == NULL_TREE) + || info->destroy_decl == NULL_TREE); + if (actor_p) + info->actor_decl = fn; + else + info->destroy_decl = fn; + } return fn; } @@ -4071,8 +4051,8 @@ coro_rewrite_function_body (location_t fn_start, tree fnbody, tree orig, BIND_EXPR_BLOCK (first) = replace_blk; /* The top block has one child, so far, and we have now got a superblock. */ - BLOCK_SUPERCONTEXT (block) = top_block; - BLOCK_SUBBLOCKS (top_block) = block; + BLOCK_SUPERCONTEXT (replace_blk) = top_block; + BLOCK_SUBBLOCKS (top_block) = replace_blk; } /* Wrap the function body in a try {} catch (...) {} block, if exceptions @@ -4116,12 +4096,13 @@ coro_rewrite_function_body (location_t fn_start, tree fnbody, tree orig, fn_start, NULL, /*musthave=*/true); /* Create and initialize the initial-await-resume-called variable per [dcl.fct.def.coroutine] / 5.3. */ - tree i_a_r_c = build_lang_decl (VAR_DECL, get_identifier ("i_a_r_c"), - boolean_type_node); - DECL_ARTIFICIAL (i_a_r_c) = true; + tree i_a_r_c + = coro_build_artificial_var (fn_start, + "_Coro_initial_await_resume_called", + boolean_type_node, orig, + boolean_false_node); DECL_CHAIN (i_a_r_c) = var_list; var_list = i_a_r_c; - DECL_INITIAL (i_a_r_c) = boolean_false_node; add_decl_expr (i_a_r_c); /* Start the try-catch. */ tree tcb = build_stmt (fn_start, TRY_BLOCK, NULL_TREE, NULL_TREE); @@ -4158,7 +4139,7 @@ coro_rewrite_function_body (location_t fn_start, tree fnbody, tree orig, finish_if_stmt_cond (not_iarc, not_iarc_if); /* If the initial await resume called value is false, rethrow... */ tree rethrow = build_throw (fn_start, NULL_TREE); - TREE_NO_WARNING (rethrow) = true; + suppress_warning (rethrow); finish_expr_stmt (rethrow); finish_then_clause (not_iarc_if); tree iarc_scope = IF_SCOPE (not_iarc_if); @@ -4259,7 +4240,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) /* For early errors, we do not want a diagnostic about the missing ramp return value, since the user cannot fix this - a 'return' is not allowed in a coroutine. */ - TREE_NO_WARNING (orig) = true; + suppress_warning (orig, OPT_Wreturn_type); /* Discard the body, we can't process it further. */ pop_stmt_list (DECL_SAVED_TREE (orig)); DECL_SAVED_TREE (orig) = push_stmt_list (); @@ -4285,7 +4266,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) DECL_SAVED_TREE (orig) = push_stmt_list (); append_to_statement_list (fnbody, &DECL_SAVED_TREE (orig)); /* Suppress warnings about the missing return value. */ - TREE_NO_WARNING (orig) = true; + suppress_warning (orig, OPT_Wreturn_type); return false; } @@ -4344,8 +4325,10 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) tree act_des_fn_ptr = build_pointer_type (act_des_fn_type); /* Declare the actor and destroyer function. */ - tree actor = act_des_fn (orig, act_des_fn_type, coro_frame_ptr, "actor"); - tree destroy = act_des_fn (orig, act_des_fn_type, coro_frame_ptr, "destroy"); + tree actor = coro_build_actor_or_destroy_function (orig, act_des_fn_type, + coro_frame_ptr, true); + tree destroy = coro_build_actor_or_destroy_function (orig, act_des_fn_type, + coro_frame_ptr, false); /* Construct the wrapped function body; we will analyze this to determine the requirements for the coroutine frame. */ @@ -4504,8 +4487,10 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) add_stmt (ramp_bind); tree ramp_body = push_stmt_list (); - tree coro_fp = build_lang_decl (VAR_DECL, get_identifier ("coro.frameptr"), - coro_frame_ptr); + tree zeroinit = build1_loc (fn_start, CONVERT_EXPR, + coro_frame_ptr, integer_zero_node); + tree coro_fp = coro_build_artificial_var (fn_start, "_Coro_frameptr", + coro_frame_ptr, orig, zeroinit); tree varlist = coro_fp; /* To signal that we need to cleanup copied function args. */ @@ -4523,21 +4508,19 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) /* Signal that we need to clean up the promise object on exception. */ tree coro_promise_live - = build_lang_decl (VAR_DECL, get_identifier ("coro.promise.live"), - boolean_type_node); - DECL_ARTIFICIAL (coro_promise_live) = true; + = coro_build_artificial_var (fn_start, "_Coro_promise_live", + boolean_type_node, orig, boolean_false_node); DECL_CHAIN (coro_promise_live) = varlist; varlist = coro_promise_live; - DECL_INITIAL (coro_promise_live) = boolean_false_node; + /* When the get-return-object is in the RETURN slot, we need to arrange for cleanup on exception. */ tree coro_gro_live - = build_lang_decl (VAR_DECL, get_identifier ("coro.gro.live"), - boolean_type_node); - DECL_ARTIFICIAL (coro_gro_live) = true; + = coro_build_artificial_var (fn_start, "_Coro_gro_live", + boolean_type_node, orig, boolean_false_node); + DECL_CHAIN (coro_gro_live) = varlist; varlist = coro_gro_live; - DECL_INITIAL (coro_gro_live) = boolean_false_node; /* Collected the scope vars we need ... only one for now. */ BIND_EXPR_VARS (ramp_bind) = nreverse (varlist); @@ -4553,8 +4536,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) /* The decl_expr for the coro frame pointer, initialize to zero so that we can pass it to the IFN_CO_FRAME (since there's no way to pass a type, directly apparently). This avoids a "used uninitialized" warning. */ - tree zeroinit = build1 (CONVERT_EXPR, coro_frame_ptr, integer_zero_node); - DECL_INITIAL (coro_fp) = zeroinit; + add_decl_expr (coro_fp); if (flag_exceptions && DECL_ARGUMENTS (orig)) for (tree arg = DECL_ARGUMENTS (orig); arg != NULL; @@ -4862,43 +4844,19 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) vec_safe_push (promise_args, this_ref); } else if (parm.rv_ref) - vec_safe_push (promise_args, rvalue(fld_idx)); + vec_safe_push (promise_args, move (fld_idx)); else vec_safe_push (promise_args, fld_idx); if (parm.rv_ref || parm.pt_ref) /* Initialise the frame reference field directly. */ - r = build_modify_expr (fn_start, TREE_OPERAND (fld_idx, 0), - parm.frame_type, INIT_EXPR, - DECL_SOURCE_LOCATION (arg), arg, - DECL_ARG_TYPE (arg)); - else if (type_build_ctor_call (parm.frame_type)) - { - vec<tree, va_gc> *p_in; - if (CLASS_TYPE_P (parm.frame_type) - && classtype_has_non_deleted_move_ctor (parm.frame_type)) - p_in = make_tree_vector_single (move (arg)); - else if (lvalue_p (arg)) - p_in = make_tree_vector_single (rvalue (arg)); - else - p_in = make_tree_vector_single (arg); - /* Construct in place or move as relevant. */ - r = build_special_member_call (fld_idx, complete_ctor_identifier, - &p_in, parm.frame_type, - LOOKUP_NORMAL, - tf_warning_or_error); - release_tree_vector (p_in); - } + r = cp_build_modify_expr (fn_start, TREE_OPERAND (fld_idx, 0), + INIT_EXPR, arg, tf_warning_or_error); else { - if (!same_type_p (parm.frame_type, DECL_ARG_TYPE (arg))) - r = build1_loc (DECL_SOURCE_LOCATION (arg), CONVERT_EXPR, - parm.frame_type, arg); - else - r = arg; - r = build_modify_expr (fn_start, fld_idx, parm.frame_type, - INIT_EXPR, DECL_SOURCE_LOCATION (arg), r, - TREE_TYPE (r)); + r = forward_parm (arg); + r = cp_build_modify_expr (fn_start, fld_idx, INIT_EXPR, r, + tf_warning_or_error); } finish_expr_stmt (r); if (!parm.trivial_dtor) @@ -4988,7 +4946,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) BIND_EXPR_BODY (ramp_bind) = pop_stmt_list (ramp_body); DECL_SAVED_TREE (orig) = newbody; /* Suppress warnings about the missing return value. */ - TREE_NO_WARNING (orig) = true; + suppress_warning (orig, OPT_Wreturn_type); return false; } @@ -5038,22 +4996,12 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) { /* ... or ... Construct an object that will be used as the single param to the CTOR for the return object. */ - gro = build_lang_decl (VAR_DECL, get_identifier ("coro.gro"), gro_type); - DECL_CONTEXT (gro) = current_scope (); - DECL_ARTIFICIAL (gro) = true; - DECL_IGNORED_P (gro) = true; + gro = coro_build_artificial_var (fn_start, "_Coro_gro", gro_type, orig, + NULL_TREE); add_decl_expr (gro); gro_bind_vars = gro; - if (type_build_ctor_call (gro_type)) - { - vec<tree, va_gc> *arg = make_tree_vector_single (get_ro); - r = build_special_member_call (gro, complete_ctor_identifier, - &arg, gro_type, LOOKUP_NORMAL, - tf_warning_or_error); - release_tree_vector (arg); - } - else - r = build2_loc (fn_start, INIT_EXPR, gro_type, gro, get_ro); + r = cp_build_modify_expr (input_location, gro, INIT_EXPR, get_ro, + tf_warning_or_error); /* The constructed object might require a cleanup. */ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (gro_type)) { @@ -5111,37 +5059,26 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) if (same_type_p (gro_type, fn_return_type)) r = gro_is_void_p ? NULL_TREE : DECL_RESULT (orig); + else if (!gro_is_void_p) + /* check_return_expr will automatically return gro as an rvalue via + treat_lvalue_as_rvalue_p. */ + r = gro; + else if (CLASS_TYPE_P (fn_return_type)) + { + /* For class type return objects, we can attempt to construct, + even if the gro is void. ??? Citation ??? c++/100476 */ + r = build_special_member_call (NULL_TREE, + complete_ctor_identifier, NULL, + fn_return_type, LOOKUP_NORMAL, + tf_warning_or_error); + r = build_cplus_new (fn_return_type, r, tf_warning_or_error); + } else { - if (CLASS_TYPE_P (fn_return_type)) - { - /* For class type return objects, we can attempt to construct, - even if the gro is void. */ - vec<tree, va_gc> *args = NULL; - vec<tree, va_gc> **arglist = NULL; - if (!gro_is_void_p) - { - args = make_tree_vector_single (rvalue (gro)); - arglist = &args; - } - r = build_special_member_call (NULL_TREE, - complete_ctor_identifier, arglist, - fn_return_type, LOOKUP_NORMAL, - tf_warning_or_error); - r = build_cplus_new (fn_return_type, r, tf_warning_or_error); - if (args) - release_tree_vector (args); - } - else if (gro_is_void_p) - { - /* We can't initialize a non-class return value from void. */ - error_at (input_location, "cannot initialize a return object of type" - " %qT with an rvalue of type %<void%>", fn_return_type); - r = error_mark_node; - } - else - r = build1_loc (input_location, CONVERT_EXPR, - fn_return_type, rvalue (gro)); + /* We can't initialize a non-class return value from void. */ + error_at (input_location, "cannot initialize a return object of type" + " %qT with an rvalue of type %<void%>", fn_return_type); + r = error_mark_node; } finish_return_stmt (r); @@ -5218,7 +5155,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) promise_type, fn_start); finish_expr_stmt (del_coro_fr); tree rethrow = build_throw (fn_start, NULL_TREE); - TREE_NO_WARNING (rethrow) = true; + suppress_warning (rethrow); finish_expr_stmt (rethrow); finish_handler (handler); TRY_HANDLERS (ramp_cleanup) = pop_stmt_list (TRY_HANDLERS (ramp_cleanup)); diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index df89ff3..bf928a8 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -101,8 +101,8 @@ genericize_eh_spec_block (tree *stmt_p) tree failure = build_call_n (call_unexpected_fn, 1, build_exc_ptr ()); *stmt_p = build_gimple_eh_filter_tree (body, allowed, failure); - TREE_NO_WARNING (*stmt_p) = true; - TREE_NO_WARNING (TREE_OPERAND (*stmt_p, 1)) = true; + suppress_warning (*stmt_p); + suppress_warning (TREE_OPERAND (*stmt_p, 1)); } /* Return the first non-compound statement in STMT. */ @@ -161,7 +161,13 @@ genericize_if_stmt (tree *stmt_p) if (!else_) else_ = build_empty_stmt (locus); - if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_)) + /* consteval if has been verified not to have the then_/else_ blocks + entered by gotos/case labels from elsewhere, and as then_ block + can contain unfolded immediate function calls, we have to discard + the then_ block regardless of whether else_ has side-effects or not. */ + if (IF_STMT_CONSTEVAL_P (stmt)) + stmt = else_; + else if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_)) stmt = then_; else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_)) stmt = else_; @@ -214,7 +220,7 @@ gimplify_expr_stmt (tree *stmt_p) { if (!IS_EMPTY_STMT (stmt) && !VOID_TYPE_P (TREE_TYPE (stmt)) - && !TREE_NO_WARNING (stmt)) + && !warning_suppressed_p (stmt, OPT_Wunused_value)) warning (OPT_Wunused_value, "statement with no effect"); } else @@ -642,14 +648,31 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) if (ret != GS_ERROR) { tree decl = cp_get_callee_fndecl_nofold (*expr_p); - if (decl - && fndecl_built_in_p (decl, CP_BUILT_IN_IS_CONSTANT_EVALUATED, - BUILT_IN_FRONTEND)) - *expr_p = boolean_false_node; - else if (decl - && fndecl_built_in_p (decl, CP_BUILT_IN_SOURCE_LOCATION, - BUILT_IN_FRONTEND)) - *expr_p = fold_builtin_source_location (EXPR_LOCATION (*expr_p)); + if (decl && fndecl_built_in_p (decl, BUILT_IN_FRONTEND)) + switch (DECL_FE_FUNCTION_CODE (decl)) + { + case CP_BUILT_IN_IS_CONSTANT_EVALUATED: + *expr_p = boolean_false_node; + break; + case CP_BUILT_IN_SOURCE_LOCATION: + *expr_p + = fold_builtin_source_location (EXPR_LOCATION (*expr_p)); + break; + case CP_BUILT_IN_IS_CORRESPONDING_MEMBER: + *expr_p + = fold_builtin_is_corresponding_member + (EXPR_LOCATION (*expr_p), call_expr_nargs (*expr_p), + &CALL_EXPR_ARG (*expr_p, 0)); + break; + case CP_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS: + *expr_p + = fold_builtin_is_pointer_inverconvertible_with_class + (EXPR_LOCATION (*expr_p), call_expr_nargs (*expr_p), + &CALL_EXPR_ARG (*expr_p, 0)); + break; + default: + break; + } } break; @@ -660,6 +683,14 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) ret = GS_UNHANDLED; break; + case PTRMEM_CST: + *expr_p = cplus_expand_constant (*expr_p); + if (TREE_CODE (*expr_p) == PTRMEM_CST) + ret = GS_ERROR; + else + ret = GS_OK; + break; + case RETURN_EXPR: if (TREE_OPERAND (*expr_p, 0) && (TREE_CODE (TREE_OPERAND (*expr_p, 0)) == INIT_EXPR @@ -793,7 +824,7 @@ omp_cxx_notice_variable (struct cp_genericize_omp_taskreg *omp_ctx, tree decl) struct cp_genericize_data { hash_set<tree> *p_set; - vec<tree> bind_expr_stack; + auto_vec<tree> bind_expr_stack; struct cp_genericize_omp_taskreg *omp_ctx; tree try_block; bool no_sanitize_p; @@ -1314,7 +1345,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) case THROW_EXPR: { location_t loc = location_of (stmt); - if (TREE_NO_WARNING (stmt)) + if (warning_suppressed_p (stmt /* What warning? */)) /* Never mind. */; else if (wtd->try_block) { @@ -1451,12 +1482,6 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) TARGET_EXPR_NO_ELIDE (stmt) = 1; break; - case REQUIRES_EXPR: - /* Emit the value of the requires-expression. */ - *stmt_p = evaluate_requires_expr (stmt); - *walk_subtrees = 0; - break; - case TEMPLATE_ID_EXPR: gcc_assert (concept_check_p (stmt)); /* Emit the value of the concept check. */ @@ -1464,35 +1489,6 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) walk_subtrees = 0; break; - case STATEMENT_LIST: - if (TREE_SIDE_EFFECTS (stmt)) - { - tree_stmt_iterator i; - int nondebug_stmts = 0; - bool clear_side_effects = true; - /* Genericization can clear TREE_SIDE_EFFECTS, e.g. when - transforming an IF_STMT into COND_EXPR. If such stmt - appears in a STATEMENT_LIST that contains only that - stmt and some DEBUG_BEGIN_STMTs, without -g where the - STATEMENT_LIST wouldn't be present at all the resulting - expression wouldn't have TREE_SIDE_EFFECTS set, so make sure - to clear it even on the STATEMENT_LIST in such cases. */ - for (i = tsi_start (stmt); !tsi_end_p (i); tsi_next (&i)) - { - tree t = tsi_stmt (i); - if (TREE_CODE (t) != DEBUG_BEGIN_STMT && nondebug_stmts < 2) - nondebug_stmts++; - cp_walk_tree (tsi_stmt_ptr (i), cp_genericize_r, data, NULL); - if (TREE_CODE (t) != DEBUG_BEGIN_STMT - && (nondebug_stmts > 1 || TREE_SIDE_EFFECTS (tsi_stmt (i)))) - clear_side_effects = false; - } - if (clear_side_effects) - TREE_SIDE_EFFECTS (stmt) = 0; - *walk_subtrees = 0; - } - break; - case OMP_DISTRIBUTE: /* Need to explicitly instantiate copy ctors on class iterators of composite distribute parallel for. */ @@ -1566,6 +1562,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) case OMP_SIMD: case OMP_LOOP: case OACC_LOOP: + case STATEMENT_LIST: /* These cases are handled by shared code. */ c_genericize_control_stmt (stmt_p, walk_subtrees, data, cp_genericize_r, cp_walk_subtrees); @@ -1602,7 +1599,6 @@ cp_genericize_tree (tree* t_p, bool handle_invisiref_parm_p) wtd.handle_invisiref_parm_p = handle_invisiref_parm_p; cp_walk_tree (t_p, cp_genericize_r, &wtd, NULL); delete wtd.p_set; - wtd.bind_expr_stack.release (); if (sanitize_flags_p (SANITIZE_VPTR)) cp_ubsan_instrument_member_accesses (t_p); } @@ -2444,6 +2440,28 @@ cp_fold (tree x) op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval_ops); op1 = cp_fold_rvalue (TREE_OPERAND (x, 1)); + /* decltype(nullptr) has only one value, so optimize away all comparisons + with that type right away, keeping them in the IL causes troubles for + various optimizations. */ + if (COMPARISON_CLASS_P (org_x) + && TREE_CODE (TREE_TYPE (op0)) == NULLPTR_TYPE + && TREE_CODE (TREE_TYPE (op1)) == NULLPTR_TYPE) + { + switch (code) + { + case EQ_EXPR: + x = constant_boolean_node (true, TREE_TYPE (x)); + break; + case NE_EXPR: + x = constant_boolean_node (false, TREE_TYPE (x)); + break; + default: + gcc_unreachable (); + } + return omit_two_operands_loc (loc, TREE_TYPE (x), x, + op0, op1); + } + if (op0 != TREE_OPERAND (x, 0) || op1 != TREE_OPERAND (x, 1)) { if (op0 == error_mark_node || op1 == error_mark_node) @@ -2463,8 +2481,9 @@ cp_fold (tree x) ; else if (COMPARISON_CLASS_P (x)) { - if (TREE_NO_WARNING (org_x) && warn_nonnull_compare) - TREE_NO_WARNING (x) = 1; + if (warn_nonnull_compare + && warning_suppressed_p (org_x, OPT_Wnonnull_compare)) + suppress_warning (x, OPT_Wnonnull_compare); } /* Otherwise give up on optimizing these, let GIMPLE folders optimize those later on. */ @@ -2472,8 +2491,9 @@ cp_fold (tree x) || op1 != TREE_OPERAND (org_x, 1)) { x = build2_loc (loc, code, TREE_TYPE (org_x), op0, op1); - if (TREE_NO_WARNING (org_x) && warn_nonnull_compare) - TREE_NO_WARNING (x) = 1; + if (warn_nonnull_compare + && warning_suppressed_p (org_x, OPT_Wnonnull_compare)) + suppress_warning (x, OPT_Wnonnull_compare); } else x = org_x; @@ -2557,11 +2577,31 @@ cp_fold (tree x) && DECL_DECLARED_CONSTEXPR_P (current_function_decl)) nw = 1; - /* Defer folding __builtin_is_constant_evaluated. */ - if (callee - && fndecl_built_in_p (callee, CP_BUILT_IN_IS_CONSTANT_EVALUATED, - BUILT_IN_FRONTEND)) - break; + if (callee && fndecl_built_in_p (callee, BUILT_IN_FRONTEND)) + { + switch (DECL_FE_FUNCTION_CODE (callee)) + { + /* Defer folding __builtin_is_constant_evaluated. */ + case CP_BUILT_IN_IS_CONSTANT_EVALUATED: + break; + case CP_BUILT_IN_SOURCE_LOCATION: + x = fold_builtin_source_location (EXPR_LOCATION (x)); + break; + case CP_BUILT_IN_IS_CORRESPONDING_MEMBER: + x = fold_builtin_is_corresponding_member + (EXPR_LOCATION (x), call_expr_nargs (x), + &CALL_EXPR_ARG (x, 0)); + break; + case CP_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS: + x = fold_builtin_is_pointer_inverconvertible_with_class + (EXPR_LOCATION (x), call_expr_nargs (x), + &CALL_EXPR_ARG (x, 0)); + break; + default: + break; + } + break; + } if (callee && fndecl_built_in_p (callee, CP_BUILT_IN_SOURCE_LOCATION, @@ -2722,6 +2762,10 @@ cp_fold (tree x) x = r; break; + case REQUIRES_EXPR: + x = evaluate_requires_expr (x); + break; + default: return org_x; } @@ -2729,7 +2773,7 @@ cp_fold (tree x) if (EXPR_P (x) && TREE_CODE (x) == code) { TREE_THIS_VOLATILE (x) = TREE_THIS_VOLATILE (org_x); - TREE_NO_WARNING (x) = TREE_NO_WARNING (org_x); + copy_warning (x, org_x); } if (!c.evaluation_restricted_p ()) diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c index 9847270..28f2d7b 100644 --- a/gcc/cp/cp-objcp-common.c +++ b/gcc/cp/cp-objcp-common.c @@ -72,10 +72,13 @@ cp_tree_size (enum tree_code code) case DEFERRED_NOEXCEPT: return sizeof (tree_deferred_noexcept); case OVERLOAD: return sizeof (tree_overload); case STATIC_ASSERT: return sizeof (tree_static_assert); - case TYPE_ARGUMENT_PACK: - case TYPE_PACK_EXPANSION: return sizeof (tree_type_non_common); - case NONTYPE_ARGUMENT_PACK: - case EXPR_PACK_EXPANSION: return sizeof (tree_exp); +#if 0 + /* This would match cp_common_init_ts, but breaks GC because + tree_node_structure_for_code returns TS_TYPE_NON_COMMON for all + types. */ + case UNBOUND_CLASS_TEMPLATE: + case TYPE_ARGUMENT_PACK: return sizeof (tree_type_common); +#endif case ARGUMENT_PACK_SELECT: return sizeof (tree_argument_pack_select); case TRAIT_EXPR: return sizeof (tree_trait_expr); case LAMBDA_EXPR: return sizeof (tree_lambda_expr); @@ -314,6 +317,15 @@ cxx_block_may_fallthru (const_tree stmt) return true; return block_may_fallthru (ELSE_CLAUSE (stmt)); + case CLEANUP_STMT: + /* Just handle the try/finally cases. */ + if (!CLEANUP_EH_ONLY (stmt)) + { + return (block_may_fallthru (CLEANUP_BODY (stmt)) + && block_may_fallthru (CLEANUP_EXPR (stmt))); + } + return true; + default: return c_block_may_fallthru (stmt); } @@ -390,6 +402,7 @@ names_builtin_p (const char *name) case RID_BUILTIN_CONVERTVECTOR: case RID_BUILTIN_HAS_ATTRIBUTE: case RID_BUILTIN_SHUFFLE: + case RID_BUILTIN_SHUFFLEVECTOR: case RID_BUILTIN_LAUNDER: case RID_BUILTIN_BIT_CAST: case RID_OFFSETOF: @@ -409,7 +422,9 @@ names_builtin_p (const char *name) case RID_IS_EMPTY: case RID_IS_ENUM: case RID_IS_FINAL: + case RID_IS_LAYOUT_COMPATIBLE: case RID_IS_LITERAL_TYPE: + case RID_IS_POINTER_INTERCONVERTIBLE_BASE_OF: case RID_IS_POD: case RID_IS_POLYMORPHIC: case RID_IS_SAME_AS: @@ -455,13 +470,8 @@ cp_common_init_ts (void) /* Random new trees. */ MARK_TS_COMMON (BASELINK); - MARK_TS_COMMON (DECLTYPE_TYPE); MARK_TS_COMMON (OVERLOAD); MARK_TS_COMMON (TEMPLATE_PARM_INDEX); - MARK_TS_COMMON (TYPENAME_TYPE); - MARK_TS_COMMON (TYPEOF_TYPE); - MARK_TS_COMMON (UNBOUND_CLASS_TEMPLATE); - MARK_TS_COMMON (UNDERLYING_TYPE); /* New decls. */ MARK_TS_DECL_COMMON (TEMPLATE_DECL); @@ -471,10 +481,16 @@ cp_common_init_ts (void) MARK_TS_DECL_NON_COMMON (USING_DECL); /* New Types. */ + MARK_TS_TYPE_COMMON (UNBOUND_CLASS_TEMPLATE); + MARK_TS_TYPE_COMMON (TYPE_ARGUMENT_PACK); + + MARK_TS_TYPE_NON_COMMON (DECLTYPE_TYPE); + MARK_TS_TYPE_NON_COMMON (TYPENAME_TYPE); + MARK_TS_TYPE_NON_COMMON (TYPEOF_TYPE); + MARK_TS_TYPE_NON_COMMON (UNDERLYING_TYPE); MARK_TS_TYPE_NON_COMMON (BOUND_TEMPLATE_TEMPLATE_PARM); MARK_TS_TYPE_NON_COMMON (TEMPLATE_TEMPLATE_PARM); MARK_TS_TYPE_NON_COMMON (TEMPLATE_TYPE_PARM); - MARK_TS_TYPE_NON_COMMON (TYPE_ARGUMENT_PACK); MARK_TS_TYPE_NON_COMMON (TYPE_PACK_EXPANSION); /* Statements. */ diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h index 53c6e4c..f1704aa 100644 --- a/gcc/cp/cp-objcp-common.h +++ b/gcc/cp/cp-objcp-common.h @@ -38,7 +38,7 @@ extern bool cp_handle_option (size_t, const char *, HOST_WIDE_INT, int, location_t, const struct cl_option_handlers *); extern tree cxx_make_type_hook (tree_code); extern tree cxx_simulate_enum_decl (location_t, const char *, - vec<string_int_pair>); + vec<string_int_pair> *); /* Lang hooks that are shared between C++ and ObjC++ are defined here. Hooks specific to C++ or ObjC++ go in cp/cp-lang.c and objcp/objcp-lang.c, diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 81ff375..a82747c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -176,6 +176,7 @@ enum cp_tree_index CPTI_HEAP_DELETED_IDENTIFIER, CPTI_HEAP_VEC_UNINIT_IDENTIFIER, CPTI_HEAP_VEC_IDENTIFIER, + CPTI_OMP_IDENTIFIER, CPTI_LANG_NAME_C, CPTI_LANG_NAME_CPLUSPLUS, @@ -337,6 +338,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; #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 omp_identifier cp_global_trees[CPTI_OMP_IDENTIFIER] #define lang_name_c cp_global_trees[CPTI_LANG_NAME_C] #define lang_name_cplusplus cp_global_trees[CPTI_LANG_NAME_CPLUSPLUS] @@ -441,7 +443,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; BLOCK_OUTER_CURLY_BRACE_P (in BLOCK) FOLD_EXPR_MODOP_P (*_FOLD_EXPR) IF_STMT_CONSTEXPR_P (IF_STMT) - TEMPLATE_TYPE_PARM_FOR_CLASS (TEMPLATE_TYPE_PARM) DECL_NAMESPACE_INLINE_P (in NAMESPACE_DECL) SWITCH_STMT_ALL_CASES_P (in SWITCH_STMT) REINTERPRET_CAST_P (in NOP_EXPR) @@ -478,9 +479,11 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; AGGR_INIT_ZERO_FIRST (in AGGR_INIT_EXPR) CONSTRUCTOR_MUTABLE_POISON (in CONSTRUCTOR) OVL_HIDDEN_P (in OVERLOAD) + IF_STMT_CONSTEVAL_P (in IF_STMT) SWITCH_STMT_NO_BREAK_P (in SWITCH_STMT) LAMBDA_EXPR_CAPTURE_OPTIMIZED (in LAMBDA_EXPR) IMPLICIT_CONV_EXPR_BRACED_INIT (in IMPLICIT_CONV_EXPR) + PACK_EXPANSION_AUTO_P (in *_PACK_EXPANSION) 3: IMPLICIT_RVALUE_P (in NON_LVALUE_EXPR or STATIC_CAST_EXPR) ICS_BAD_FLAG (in _CONV) FN_TRY_BLOCK_P (in TRY_BLOCK) @@ -489,8 +492,8 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; DECLTYPE_FOR_REF_CAPTURE (in DECLTYPE_TYPE) CONSTRUCTOR_C99_COMPOUND_LITERAL (in CONSTRUCTOR) OVL_NESTED_P (in OVERLOAD) - LAMBDA_EXPR_INSTANTIATED (in LAMBDA_EXPR) DECL_MODULE_EXPORT_P (in _DECL) + PACK_EXPANSION_FORCE_EXTRA_ARGS_P (in *_PACK_EXPANSION) 4: IDENTIFIER_MARKED (IDENTIFIER_NODEs) TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, CALL_EXPR, or FIELD_DECL). @@ -498,6 +501,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; FUNCTION_REF_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE) OVL_LOOKUP_P (in OVERLOAD) LOOKUP_FOUND_P (in RECORD_TYPE, UNION_TYPE, ENUMERAL_TYPE, NAMESPACE_DECL) + FNDECL_MANIFESTLY_CONST_EVALUATED (in FUNCTION_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) @@ -817,11 +821,6 @@ class ovl_iterator { { } - private: - /* Do not duplicate. */ - ovl_iterator &operator= (const ovl_iterator &); - ovl_iterator (const ovl_iterator &); - public: operator bool () const { @@ -841,6 +840,10 @@ class ovl_iterator { return fn; } + bool operator== (const ovl_iterator &o) const + { + return ovl == o.ovl; + } tree get_using () const { gcc_checking_assert (using_p ()); @@ -903,6 +906,19 @@ class ovl_iterator { static tree reveal_node (tree ovl, tree node); }; +/* Treat a tree as a range of ovl_iterator, e.g. + for (tree f : ovl_range (fns)) { ... } */ + +class ovl_range +{ + tree t; + bool allow; +public: + explicit ovl_range (tree t, bool allow = false): t(t), allow(allow) { } + ovl_iterator begin() { return ovl_iterator (t, allow); } + ovl_iterator end() { return ovl_iterator (NULL_TREE, allow); } +}; + /* Iterator over a (potentially) 2 dimensional overload, which is produced by name lookup. */ @@ -935,6 +951,18 @@ class lkp_iterator : public ovl_iterator { } }; +/* Treat a tree as a range of lkp_iterator, e.g. + for (tree f : lkp_range (fns)) { ... } */ + +class lkp_range +{ + tree t; +public: + lkp_range (tree t): t(t) { } + lkp_iterator begin() { return lkp_iterator (t); } + lkp_iterator end() { return lkp_iterator (NULL_TREE); } +}; + /* hash traits for declarations. Hashes potential overload sets via DECL_NAME. */ @@ -1339,7 +1367,9 @@ enum cp_trait_kind CPTK_IS_EMPTY, CPTK_IS_ENUM, CPTK_IS_FINAL, + CPTK_IS_LAYOUT_COMPATIBLE, CPTK_IS_LITERAL_TYPE, + CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF, CPTK_IS_POD, CPTK_IS_POLYMORPHIC, CPTK_IS_SAME_AS, @@ -1433,10 +1463,6 @@ enum cp_lambda_default_capture_mode_type { #define LAMBDA_EXPR_CAPTURE_OPTIMIZED(NODE) \ TREE_LANG_FLAG_2 (LAMBDA_EXPR_CHECK (NODE)) -/* True iff this LAMBDA_EXPR was generated in tsubst_lambda_expr. */ -#define LAMBDA_EXPR_INSTANTIATED(NODE) \ - TREE_LANG_FLAG_3 (LAMBDA_EXPR_CHECK (NODE)) - /* True if this TREE_LIST in LAMBDA_EXPR_CAPTURE_LIST is for an explicit capture. */ #define LAMBDA_CAPTURE_EXPLICIT_P(NODE) \ @@ -1460,6 +1486,13 @@ enum cp_lambda_default_capture_mode_type { #define LAMBDA_EXPR_PENDING_PROXIES(NODE) \ (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->pending_proxies) +/* If NODE was regenerated via tsubst_lambda_expr, this is a TEMPLATE_INFO + whose TI_TEMPLATE is the immediate LAMBDA_EXPR from which NODE was + regenerated, and TI_ARGS is the full set of template arguments used + to regenerate NODE from the most general lambda. */ +#define LAMBDA_EXPR_REGEN_INFO(NODE) \ + (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->regen_info) + /* The closure type of the lambda, which is also the type of the LAMBDA_EXPR. */ #define LAMBDA_EXPR_CLOSURE(NODE) \ @@ -1471,6 +1504,7 @@ struct GTY (()) tree_lambda_expr tree capture_list; tree this_capture; tree extra_scope; + tree regen_info; vec<tree, va_gc> *pending_proxies; location_t locus; enum cp_lambda_default_capture_mode_type default_capture_mode : 8; @@ -1661,9 +1695,11 @@ check_constraint_info (tree t) #define CONSTRAINED_PARM_PROTOTYPE(NODE) \ DECL_INITIAL (TYPE_DECL_CHECK (NODE)) -/* Module defines. */ -// Too many _DECLS: FUNCTION,VAR,TYPE,TEMPLATE,CONCEPT or NAMESPACE -#define DECL_MODULE_CHECK(NODE) (NODE) +/* Module flags on FUNCTION,VAR,TYPE,CONCEPT or NAMESPACE + A TEMPLATE_DECL holds them on the DECL_TEMPLATE_RESULT object -- + it's just not practical to keep them consistent. */ +#define DECL_MODULE_CHECK(NODE) \ + TREE_NOT_CHECK (NODE, TEMPLATE_DECL) /* In the purview of a module (including header unit). */ #define DECL_MODULE_PURVIEW_P(N) \ @@ -1756,6 +1792,10 @@ union GTY((desc ("cp_tree_node_structure (&%h)"), }; +struct GTY(()) omp_declare_target_attr { + bool attr_syntax; +}; + /* Global state. */ struct GTY(()) saved_scope { @@ -1783,16 +1823,16 @@ struct GTY(()) saved_scope { BOOL_BITFIELD x_processing_explicit_instantiation : 1; BOOL_BITFIELD need_pop_function_context : 1; -/* Nonzero if we are parsing the discarded statement of a constexpr - if-statement. */ + /* Nonzero if we are parsing the discarded statement of a constexpr + if-statement. */ BOOL_BITFIELD discarded_stmt : 1; + /* Nonzero if we are parsing or instantiating the compound-statement + of consteval if statement. */ + BOOL_BITFIELD consteval_if_p : 1; int unevaluated_operand; int inhibit_evaluation_warnings; int noexcept_operand; - /* If non-zero, implicit "omp declare target" attribute is added into the - attribute lists. */ - int omp_declare_target_attribute; int ref_temp_count; struct stmt_tree_s x_stmt_tree; @@ -1801,6 +1841,7 @@ struct GTY(()) saved_scope { cp_binding_level *bindings; hash_map<tree, tree> *GTY((skip)) x_local_specializations; + vec<omp_declare_target_attr, va_gc> *omp_declare_target_attribute; struct saved_scope *prev; }; @@ -1849,6 +1890,7 @@ extern GTY(()) struct saved_scope *scope_chain; #define processing_explicit_instantiation scope_chain->x_processing_explicit_instantiation #define in_discarded_stmt scope_chain->discarded_stmt +#define in_consteval_if_p scope_chain->consteval_if_p #define current_ref_temp_count scope_chain->ref_temp_count @@ -2296,6 +2338,7 @@ struct GTY(()) lang_type { unsigned has_constexpr_ctor : 1; unsigned unique_obj_representations : 1; unsigned unique_obj_representations_set : 1; + bool erroneous : 1; /* When adding a flag here, consider whether or not it ought to apply to a template instance if it applies to the template. If @@ -2304,7 +2347,7 @@ struct GTY(()) lang_type { /* There are some bits left to fill out a 32-bit word. Keep track of this by updating the size of this bitfield whenever you add or remove a flag. */ - unsigned dummy : 5; + unsigned dummy : 4; tree primary_base; vec<tree_pair_s, va_gc> *vcall_indices; @@ -2620,6 +2663,10 @@ struct GTY(()) lang_type { /* Nonzero if a _DECL node requires us to output debug info for this class. */ #define CLASSTYPE_DEBUG_REQUESTED(NODE) \ (LANG_TYPE_CLASS_CHECK (NODE)->debug_requested) + +/* True if we saw errors while instantiating this class. */ +#define CLASSTYPE_ERRONEOUS(NODE) \ + (LANG_TYPE_CLASS_CHECK (NODE)->erroneous) /* Additional macros for inheritance information. */ @@ -2754,8 +2801,8 @@ struct GTY(()) lang_decl_base { unsigned var_declared_inline_p : 1; /* var */ unsigned dependent_init_p : 1; /* var */ - /* The following apply to VAR, FUNCTION, TYPE, CONCEPT, TEMPLATE, - NAMESPACE decls. */ + /* The following apply to VAR, FUNCTION, TYPE, CONCEPT, & NAMESPACE + decls. */ unsigned module_purview_p : 1; /* in module purview (not GMF) */ unsigned module_import_p : 1; /* from an import */ unsigned module_entity_p : 1; /* is in the entitity ary & @@ -3523,6 +3570,7 @@ struct GTY(()) lang_decl { created by handle_using_decl. */ #define CONST_DECL_USING_P(NODE) \ (TREE_CODE (NODE) == CONST_DECL \ + && TREE_TYPE (NODE) \ && TREE_CODE (TREE_TYPE (NODE)) == ENUMERAL_TYPE \ && DECL_CONTEXT (NODE) != TREE_TYPE (NODE)) @@ -3626,9 +3674,10 @@ struct GTY(()) lang_decl { /* Set the template information for a non-alias n ENUMERAL_, RECORD_, or UNION_TYPE to VAL. ALIAS's are dealt with separately. */ #define SET_TYPE_TEMPLATE_INFO(NODE, VAL) \ - (gcc_checking_assert (TREE_CODE (NODE) == ENUMERAL_TYPE \ - || (CLASS_TYPE_P (NODE) && !TYPE_ALIAS_P (NODE))), \ - (TYPE_LANG_SLOT_1 (NODE) = (VAL))) \ + (TREE_CODE (NODE) == ENUMERAL_TYPE \ + || (CLASS_TYPE_P (NODE) && !TYPE_ALIAS_P (NODE)) \ + ? (TYPE_LANG_SLOT_1 (NODE) = (VAL)) \ + : (DECL_TEMPLATE_INFO (TYPE_NAME (NODE)) = (VAL))) \ #define TI_TEMPLATE(NODE) \ ((struct tree_template_info*)TEMPLATE_INFO_CHECK (NODE))->tmpl @@ -3852,6 +3901,13 @@ struct GTY(()) lang_decl { /* True iff this pack expansion is for sizeof.... */ #define PACK_EXPANSION_SIZEOF_P(NODE) TREE_LANG_FLAG_1 (NODE) +/* True iff this pack expansion is for auto... in lambda init-capture. */ +#define PACK_EXPANSION_AUTO_P(NODE) TREE_LANG_FLAG_2 (NODE) + +/* True if we must use PACK_EXPANSION_EXTRA_ARGS and avoid partial + instantiation of this pack expansion. */ +#define PACK_EXPANSION_FORCE_EXTRA_ARGS_P(NODE) TREE_LANG_FLAG_3 (NODE) + /* True iff the wildcard can match a template parameter pack. */ #define WILDCARD_PACK_P(NODE) TREE_LANG_FLAG_0 (NODE) @@ -4163,6 +4219,13 @@ 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 needed for a manifestly constant-evaluated expression. + This doesn't especially need to be a flag, since currently it's only + used for error recovery; if we run out of function flags it could move + to an attribute. */ +#define FNDECL_MANIFESTLY_CONST_EVALUATED(NODE) \ + TREE_LANG_FLAG_4 (FUNCTION_DECL_CHECK (NODE)) + /* True for artificial decls added for OpenMP privatized non-static data members. */ #define DECL_OMP_PRIVATIZED_MEMBER(NODE) \ @@ -4397,7 +4460,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) When appearing in a SAVE_EXPR, it means that underneath is a call to a constructor. - When appearing in a CONSTRUCTOR, the expression is a + When appearing in a CONSTRUCTOR, the expression is an unconverted compound literal. When appearing in a FIELD_DECL, it means that this field @@ -4409,7 +4472,9 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) (TREE_CODE (NODE) == CONSTRUCTOR && TREE_TYPE (NODE) == init_list_type_node) /* True if NODE is a compound-literal, i.e., a brace-enclosed - initializer cast to a particular type. */ + initializer cast to a particular type. This is mostly only set during + template parsing; once the initializer has been digested into an actual + value of the type, the expression is represented by a TARGET_EXPR. */ #define COMPOUND_LITERAL_P(NODE) \ (TREE_CODE (NODE) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (NODE)) @@ -4456,6 +4521,12 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define CONSTRUCTOR_IS_PAREN_INIT(NODE) \ (CONSTRUCTOR_CHECK(NODE)->base.private_flag) +/* True if reshape_init built this sub-CONSTRUCTOR to undo the brace elision + of the original CONSTRUCTOR. This flag is used during C++20 aggregate + CTAD. */ +#define CONSTRUCTOR_BRACES_ELIDED_P(NODE) \ + (CONSTRUCTOR_CHECK (NODE)->base.protected_flag) + /* True if NODE represents a conversion for direct-initialization in a template. Set by perform_implicit_conversion_flags. */ #define IMPLICIT_CONV_EXPR_DIRECT_INIT(NODE) \ @@ -4734,6 +4805,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define ANON_UNION_TYPE_P(NODE) \ (TREE_CODE (NODE) == UNION_TYPE && ANON_AGGR_TYPE_P (NODE)) +/* For an ANON_AGGR_TYPE_P the single FIELD_DECL it is used with. */ +#define ANON_AGGR_TYPE_FIELD(NODE) \ + (LANG_TYPE_CLASS_CHECK (NODE)->typeinfo_var) + /* Define fields and accessors for nodes representing declared names. */ /* True if TYPE is an unnamed structured type with a typedef for @@ -5123,6 +5198,21 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define DECL_COROUTINE_P(NODE) \ (LANG_DECL_FN_CHECK (DECL_COMMON_CHECK (NODE))->coroutine_p) +/* For a FUNCTION_DECL of a coroutine, this holds the ACTOR helper function + decl. */ +#define DECL_ACTOR_FN(NODE) \ + (coro_get_actor_function ((NODE))) + +/* For a FUNCTION_DECL of a coroutine, this holds the DESTROY helper function + decl. */ +#define DECL_DESTROY_FN(NODE) \ + (coro_get_destroy_function ((NODE))) + +/* For a FUNCTION_DECL of a coroutine helper (ACTOR or DESTROY), this points + back to the original (ramp) function. */ +#define DECL_RAMP_FN(NODE) \ + (coro_get_ramp_function (NODE)) + /* True for an OMP_ATOMIC that has dependent parameters. These are stored as an expr in operand 1, and integer_zero_node or clauses in operand 0. */ #define OMP_ATOMIC_DEPENDENT_P(NODE) \ @@ -5174,6 +5264,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define ELSE_CLAUSE(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 2) #define IF_SCOPE(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 3) #define IF_STMT_CONSTEXPR_P(NODE) TREE_LANG_FLAG_0 (IF_STMT_CHECK (NODE)) +#define IF_STMT_CONSTEVAL_P(NODE) TREE_LANG_FLAG_2 (IF_STMT_CHECK (NODE)) /* Like PACK_EXPANSION_EXTRA_ARGS, for constexpr if. IF_SCOPE is used while building an IF_STMT; IF_STMT_EXTRA_ARGS is used after it is complete. */ @@ -5444,10 +5535,6 @@ extern int comparing_specializations; FIXME we should always do this except during deduction/ordering. */ extern int comparing_dependent_aliases; -/* When comparing specializations permit context _FROM to match _TO. */ -extern tree map_context_from; -extern tree map_context_to; - /* In parser.c. */ /* Nonzero if we are parsing an unevaluated operand: an operand to @@ -5474,9 +5561,10 @@ class cp_evaluated public: int uneval; int inhibit; - cp_evaluated () + cp_evaluated (bool reset = true) : uneval(cp_unevaluated_operand), inhibit(c_inhibit_evaluation_warnings) - { cp_unevaluated_operand = c_inhibit_evaluation_warnings = 0; } + { if (reset) + cp_unevaluated_operand = c_inhibit_evaluation_warnings = 0; } ~cp_evaluated () { cp_unevaluated_operand = uneval; c_inhibit_evaluation_warnings = inhibit; } @@ -5543,6 +5631,7 @@ extern GTY(()) vec<tree, va_gc> *keyed_classes; #ifndef NO_DOT_IN_LABEL #define JOINER '.' +#define JOIN_STR "." #define AUTO_TEMP_NAME "_.tmp_" #define VFIELD_BASE ".vf" @@ -5554,6 +5643,7 @@ extern GTY(()) vec<tree, va_gc> *keyed_classes; #ifndef NO_DOLLAR_IN_LABEL #define JOINER '$' +#define JOIN_STR "$" #define AUTO_TEMP_NAME "_$tmp_" #define VFIELD_BASE "$vf" @@ -5562,6 +5652,8 @@ extern GTY(()) vec<tree, va_gc> *keyed_classes; #else /* NO_DOLLAR_IN_LABEL */ +#define JOIN_STR "_" + #define VTABLE_NAME "__vt_" #define VTABLE_NAME_P(ID_NODE) \ (!strncmp (IDENTIFIER_POINTER (ID_NODE), VTABLE_NAME, \ @@ -5821,11 +5913,6 @@ enum auto_deduction_context adc_decomp_type /* Decomposition declaration initializer deduction */ }; -/* True if this type-parameter belongs to a class template, used by C++17 - class template argument deduction. */ -#define TEMPLATE_TYPE_PARM_FOR_CLASS(NODE) \ - (TREE_LANG_FLAG_0 (TEMPLATE_TYPE_PARM_CHECK (NODE))) - /* True iff this TEMPLATE_TYPE_PARM represents decltype(auto). */ #define AUTO_IS_DECLTYPE(NODE) \ (TYPE_LANG_FLAG_5 (TEMPLATE_TYPE_PARM_CHECK (NODE))) @@ -5916,6 +6003,9 @@ enum ovl_op_code { OVL_OP_MAX }; +/* Make sure it fits in lang_decl_fn::ovl_op_code. */ +STATIC_ASSERT (OVL_OP_MAX < (1 << 6)); + struct GTY(()) ovl_op_info_t { /* The IDENTIFIER_NODE for the operator. */ tree identifier; @@ -6297,6 +6387,8 @@ struct GTY((chain_next ("%h.next"))) tinst_level { enum cp_built_in_function { CP_BUILT_IN_IS_CONSTANT_EVALUATED, CP_BUILT_IN_INTEGER_PACK, + CP_BUILT_IN_IS_CORRESPONDING_MEMBER, + CP_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS, CP_BUILT_IN_SOURCE_LOCATION, CP_BUILT_IN_LAST }; @@ -6394,6 +6486,8 @@ extern void complain_about_bad_argument (location_t arg_loc, tree from_type, tree to_type, tree fndecl, int parmnum); extern void maybe_inform_about_fndecl_for_bogus_argument_init (tree, int); +extern tree perform_dguide_overload_resolution (tree, const vec<tree, va_gc> *, + tsubst_flags_t); /* A class for recording information about access failures (e.g. private @@ -6464,7 +6558,7 @@ extern void validate_conversion_obstack (void); extern void mark_versions_used (tree); extern int unsafe_return_slot_p (tree); extern bool make_safe_copy_elision (tree, tree); -extern bool cp_warn_deprecated_use (tree, tsubst_flags_t = tf_warning_or_error); +extern bool cp_handle_deprecated_or_unavailable (tree, tsubst_flags_t = tf_warning_or_error); extern void cp_warn_deprecated_use_scopes (tree); extern tree get_function_version_dispatcher (tree); @@ -6532,7 +6626,6 @@ extern bool type_has_constexpr_destructor (tree); extern bool type_has_virtual_destructor (tree); extern bool classtype_has_move_assign_or_move_ctor_p (tree, bool user_declared); extern bool classtype_has_non_deleted_move_ctor (tree); -extern bool classtype_has_non_deleted_copy_ctor (tree); extern tree classtype_has_depr_implicit_copy (tree); extern bool classtype_has_op (tree, tree_code); extern tree classtype_has_defaulted_op (tree, tree_code); @@ -6618,7 +6711,6 @@ extern void pop_abi_namespace (unsigned flags, extern tree build_library_fn_ptr (const char *, tree, int); extern tree build_cp_library_fn_ptr (const char *, tree, int); extern tree push_library_fn (tree, tree, tree, int); -extern tree push_void_library_fn (tree, tree, int); extern tree push_throw_library_fn (tree, tree); extern void warn_misplaced_attr_for_class_type (location_t location, tree class_type); @@ -6689,6 +6781,7 @@ extern void initialize_artificial_var (tree, vec<constructor_elt, va_gc> *); extern tree check_var_type (tree, tree, location_t); extern tree reshape_init (tree, tree, tsubst_flags_t); extern tree next_initializable_field (tree); +extern tree first_field (const_tree); extern tree fndecl_declared_return_type (tree); extern bool undeduced_auto_decl (tree); extern bool require_deduced_type (tree, tsubst_flags_t = tf_warning_or_error); @@ -6835,7 +6928,7 @@ extern void mark_exp_read (tree); extern int is_friend (tree, tree); extern void make_friend_class (tree, tree, bool); extern void add_friend (tree, tree, bool); -extern tree do_friend (tree, tree, tree, tree, +extern tree do_friend (tree, tree, tree, enum overload_flags, bool); extern void set_global_friend (tree); @@ -6919,7 +7012,7 @@ 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); extern void explain_implicit_non_constexpr (tree); -extern void deduce_inheriting_ctor (tree); +extern bool deduce_inheriting_ctor (tree); extern bool decl_remember_implicit_trigger_p (tree); extern void synthesize_method (tree); extern tree lazily_declare_fn (special_function_kind, @@ -6931,6 +7024,7 @@ extern tree get_copy_ctor (tree, tsubst_flags_t); extern tree get_copy_assign (tree); extern tree get_default_ctor (tree); extern tree get_dtor (tree, tsubst_flags_t); +extern tree build_stub_object (tree); extern tree strip_inheriting_ctors (tree); extern tree inherited_ctor_binfo (tree); extern bool base_ctor_omit_inherited_parms (tree); @@ -7140,7 +7234,6 @@ extern tree get_template_info (const_tree); extern int template_class_depth (tree); extern int is_specialization_of (tree, tree); extern bool is_specialization_of_friend (tree, tree); -extern tree get_pattern_parm (tree, tree); extern int comp_template_args (tree, tree, tree * = NULL, tree * = NULL, bool = false); extern int template_args_equal (tree, tree, bool = false); @@ -7214,7 +7307,6 @@ bool template_template_parameter_p (const_tree); bool template_type_parameter_p (const_tree); extern bool primary_template_specialization_p (const_tree); extern tree get_primary_template_innermost_parameters (const_tree); -extern tree get_template_parms_at_level (tree, int); extern tree get_template_innermost_arguments (const_tree); extern tree get_template_argument_pack_elems (const_tree); extern tree get_function_template_decl (const_tree); @@ -7241,10 +7333,12 @@ extern void walk_specializations (bool, void *); extern tree match_mergeable_specialization (bool is_decl, spec_entry *); extern unsigned get_mergeable_specialization_flags (tree tmpl, tree spec); -extern void add_mergeable_specialization (bool is_decl, spec_entry *, +extern void add_mergeable_specialization (bool is_decl, bool is_alias, + spec_entry *, tree outer, unsigned); +extern tree add_to_template_args (tree, tree); extern tree add_outermost_template_args (tree, tree); -extern tree add_extra_args (tree, tree); +extern tree add_extra_args (tree, tree, tsubst_flags_t, tree); extern tree build_extra_args (tree, tree, tsubst_flags_t); /* in rtti.c */ @@ -7510,12 +7604,13 @@ extern tree baselink_for_fns (tree); extern void finish_static_assert (tree, tree, location_t, bool, bool); extern tree finish_decltype_type (tree, bool, tsubst_flags_t); +extern tree fold_builtin_is_corresponding_member (location_t, int, tree *); +extern tree fold_builtin_is_pointer_inverconvertible_with_class (location_t, int, tree *); extern tree finish_trait_expr (location_t, enum cp_trait_kind, tree, tree); extern tree build_lambda_expr (void); extern tree build_lambda_object (tree); extern tree begin_lambda_type (tree); extern tree lambda_capture_field_type (tree, bool, bool); -extern tree lambda_return_type (tree); extern tree lambda_proxy_type (tree); extern tree lambda_function (tree); extern void apply_deduced_return_type (tree, tree); @@ -7553,6 +7648,8 @@ extern void record_null_lambda_scope (tree); extern void finish_lambda_scope (void); extern tree start_lambda_function (tree fn, tree lambda_expr); extern void finish_lambda_function (tree body); +extern bool regenerated_lambda_fn_p (tree); +extern tree most_general_lambda (tree); /* in tree.c */ extern int cp_tree_operand_length (const_tree); @@ -7734,6 +7831,8 @@ extern bool comp_except_specs (const_tree, const_tree, int); extern bool comptypes (tree, tree, int); extern bool same_type_ignoring_top_level_qualifiers_p (tree, tree); extern bool similar_type_p (tree, tree); +extern bool next_common_initial_seqence (tree &, tree &); +extern bool layout_compatible_type_p (tree, tree); extern bool compparms (const_tree, const_tree); extern int comp_cv_qualification (const_tree, const_tree); extern int comp_cv_qualification (int, int); @@ -7857,6 +7956,9 @@ extern tree cp_build_binary_op (const op_location_t &, extern tree build_x_vec_perm_expr (location_t, tree, tree, tree, tsubst_flags_t); +extern tree build_x_shufflevector (location_t, + vec<tree, va_gc> *, + tsubst_flags_t); #define cxx_sizeof(T) cxx_sizeof_or_alignof_type (input_location, T, SIZEOF_EXPR, false, true) extern tree build_simple_component_ref (tree, tree); extern tree build_ptrmemfunc_access_expr (tree, tree); @@ -8066,7 +8168,6 @@ extern tree current_template_constraints (void); extern tree associate_classtype_constraints (tree); extern tree build_constraints (tree, tree); extern tree maybe_substitute_reqs_for (tree, const_tree); -extern tree get_template_head_requirements (tree); extern tree get_trailing_function_requirements (tree); extern tree get_shorthand_constraints (tree); @@ -8092,7 +8193,6 @@ extern tree finish_simple_requirement (location_t, tree); extern tree finish_type_requirement (location_t, tree); extern tree finish_compound_requirement (location_t, tree, tree, bool); extern tree finish_nested_requirement (location_t, tree); -extern void check_constrained_friend (tree, tree); extern tree tsubst_requires_expr (tree, tree, tsubst_flags_t, tree); extern tree evaluate_requires_expr (tree); extern tree tsubst_constraint (tree, tree, tsubst_flags_t, tree); @@ -8116,7 +8216,6 @@ 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); extern bool weakly_subsumes (tree, tree); extern int more_constrained (tree, tree); @@ -8148,6 +8247,7 @@ struct atom_hasher : default_hash_traits<tree> extern bool subsumes (tree, tree); /* In class.c */ +extern void set_current_access_from_decl (tree); extern void cp_finish_injected_record_type (tree); /* in vtable-class-hierarchy.c */ @@ -8188,6 +8288,7 @@ extern bool require_constant_expression (tree); extern bool require_rvalue_constant_expression (tree); extern bool require_potential_rvalue_constant_expression (tree); extern tree cxx_constant_value (tree, tree = NULL_TREE); +extern tree cxx_constant_value_sfinae (tree, tsubst_flags_t); extern void cxx_constant_dtor (tree, tree); extern tree cxx_constant_init (tree, tree = NULL_TREE); extern tree maybe_constant_value (tree, tree = NULL_TREE, bool = false); @@ -8205,6 +8306,7 @@ extern bool reduced_constant_expression_p (tree); extern bool is_instantiation_of_constexpr (tree); extern bool var_in_constexpr_fn (tree); extern bool var_in_maybe_constexpr_fn (tree); +extern bool maybe_constexpr_fn (tree); extern void explain_invalid_constexpr_fn (tree); extern vec<tree> cx_error_context (void); extern tree fold_sizeof_expr (tree); @@ -8248,6 +8350,9 @@ extern tree finish_co_yield_expr (location_t, tree); extern tree coro_validate_builtin_call (tree, tsubst_flags_t = tf_warning_or_error); extern bool morph_fn_to_coro (tree, tree *, tree *); +extern tree coro_get_actor_function (tree); +extern tree coro_get_destroy_function (tree); +extern tree coro_get_ramp_function (tree); /* Inline bodies. */ @@ -8415,21 +8520,38 @@ is_constrained_auto (const_tree t) return is_auto (t) && PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t); } -/* RAII class to push/pop class scope T; if T is not a class, do nothing. */ +/* True if CODE, a tree code, denotes a tree whose operand is not evaluated + as per [expr.context], i.e., an operand to sizeof, typeof, decltype, or + alignof. */ + +inline bool +unevaluated_p (tree_code code) +{ + return (code == DECLTYPE_TYPE + || code == ALIGNOF_EXPR + || code == SIZEOF_EXPR + || code == NOEXCEPT_EXPR + || code == REQUIRES_EXPR); +} + +/* RAII class to push/pop the access scope for T. */ -struct push_nested_class_guard +struct push_access_scope_guard { - bool push; - push_nested_class_guard (tree t) - : push (t && CLASS_TYPE_P (t)) + tree decl; + push_access_scope_guard (tree t) + : decl (t) { - if (push) - push_nested_class (t); + if (VAR_OR_FUNCTION_DECL_P (decl) + || TREE_CODE (decl) == TYPE_DECL) + push_access_scope (decl); + else + decl = NULL_TREE; } - ~push_nested_class_guard () + ~push_access_scope_guard () { - if (push) - pop_nested_class (); + if (decl) + pop_access_scope (decl); } }; diff --git a/gcc/cp/cp-ubsan.c b/gcc/cp/cp-ubsan.c index 3dabb6a..7854594 100644 --- a/gcc/cp/cp-ubsan.c +++ b/gcc/cp/cp-ubsan.c @@ -81,7 +81,7 @@ cp_ubsan_instrument_vptr (location_t loc, tree op, tree type, bool is_addr, build_zero_cst (TREE_TYPE (op))); /* This is a compiler generated comparison, don't emit e.g. -Wnonnull-compare warning for it. */ - TREE_NO_WARNING (cond) = 1; + suppress_warning (cond, OPT_Wnonnull_compare); vptr = build3_loc (loc, COND_EXPR, uint64_type_node, cond, vptr, build_int_cst (uint64_type_node, 0)); } diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 2ea3210..d035e61 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -232,7 +232,7 @@ cp_convert_to_pointer (tree type, tree expr, bool dofold, { if (TYPE_PRECISION (intype) == POINTER_SIZE) return build1 (CONVERT_EXPR, type, expr); - expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 0), expr, + expr = cp_convert (c_common_type_for_size (TYPE_PRECISION (type), 0), expr, complain); /* Modes may be different but sizes should be the same. There is supposed to be some integral type that is the same width @@ -605,8 +605,6 @@ ignore_overflows (tree expr, tree orig) tree cp_fold_convert (tree type, tree expr) { - bool nowarn = TREE_NO_WARNING (expr); - tree conv; if (TREE_TYPE (expr) == type) conv = expr; @@ -630,8 +628,8 @@ cp_fold_convert (tree type, tree expr) conv = ignore_overflows (conv, expr); } - if (nowarn && TREE_CODE (expr) == TREE_CODE (conv)) - TREE_NO_WARNING (conv) = nowarn; + if (TREE_CODE (expr) == TREE_CODE (conv)) + copy_warning (conv, expr); return conv; } @@ -1198,8 +1196,8 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain) new_op2 = convert_to_void (op2, ICV_CAST, complain); } - expr = build3 (COND_EXPR, TREE_TYPE (new_op2), - TREE_OPERAND (expr, 0), new_op1, new_op2); + expr = build3_loc (loc, COND_EXPR, TREE_TYPE (new_op2), + TREE_OPERAND (expr, 0), new_op1, new_op2); break; } @@ -1208,15 +1206,15 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain) /* The second part of a compound expr contains the value. */ tree op1 = TREE_OPERAND (expr,1); tree new_op1; - if (implicit != ICV_CAST && !TREE_NO_WARNING (expr)) + if (implicit != ICV_CAST && !warning_suppressed_p (expr /* What warning? */)) new_op1 = convert_to_void (op1, ICV_RIGHT_OF_COMMA, complain); else new_op1 = convert_to_void (op1, ICV_CAST, complain); if (new_op1 != op1) { - tree t = build2 (COMPOUND_EXPR, TREE_TYPE (new_op1), - TREE_OPERAND (expr, 0), new_op1); + tree t = build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (new_op1), + TREE_OPERAND (expr, 0), new_op1); expr = t; } @@ -1394,7 +1392,7 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain) if (warn_unused_value && implicit != ICV_CAST && (complain & tf_warning) - && !TREE_NO_WARNING (expr) + && !warning_suppressed_p (expr, OPT_Wunused_value) && !is_reference) warning_at (loc, OPT_Wunused_value, "value computed is not used"); expr = TREE_OPERAND (expr, 0); @@ -1578,7 +1576,7 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain) { if (implicit != ICV_CAST && warn_unused_value - && !TREE_NO_WARNING (expr) + && !warning_suppressed_p (expr, OPT_Wunused_value) && !processing_template_decl && !cp_unevaluated_operand && (complain & tf_warning)) @@ -2013,6 +2011,11 @@ can_convert_qual (tree type, tree expr) tree expr_type = TREE_TYPE (expr); gcc_assert (!same_type_p (type, expr_type)); + /* A function pointer conversion also counts as a Qualification Adjustment + under [over.ics.scs]. */ + if (fnptr_conv_p (type, expr_type)) + return true; + if (TYPE_PTR_P (type) && TYPE_PTR_P (expr_type)) return comp_ptr_ttypes (TREE_TYPE (type), TREE_TYPE (expr_type)); else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (expr_type)) @@ -2076,7 +2079,8 @@ can_convert_tx_safety (tree to, tree from) && same_type_p (to, tx_unsafe_fn_variant (from))); } -/* Return true iff FROM can convert to TO by dropping noexcept. */ +/* Return true iff FROM can convert to TO by dropping noexcept. + This is just a subroutine of of fnptr_conv_p. */ static bool noexcept_conv_p (tree to, tree from) @@ -2084,30 +2088,15 @@ noexcept_conv_p (tree to, tree from) if (!flag_noexcept_type) return false; - tree t = non_reference (to); - tree f = from; - if (TYPE_PTRMEMFUNC_P (t) - && TYPE_PTRMEMFUNC_P (f)) - { - t = TYPE_PTRMEMFUNC_FN_TYPE (t); - f = TYPE_PTRMEMFUNC_FN_TYPE (f); - } - if (TYPE_PTR_P (t) - && TYPE_PTR_P (f)) - { - t = TREE_TYPE (t); - f = TREE_TYPE (f); - } - tree_code code = TREE_CODE (f); - if (TREE_CODE (t) != code) + if (TREE_CODE (to) != TREE_CODE (from)) return false; - if (code != FUNCTION_TYPE && code != METHOD_TYPE) + if (!FUNC_OR_METHOD_TYPE_P (from)) return false; - if (!type_throw_all_p (t) - || type_throw_all_p (f)) + if (!type_throw_all_p (to) + || type_throw_all_p (from)) return false; - tree v = build_exception_variant (f, NULL_TREE); - return same_type_p (t, v); + tree v = build_exception_variant (from, NULL_TREE); + return same_type_p (to, v); } /* Return true iff FROM can convert to TO by a function pointer conversion. */ @@ -2115,7 +2104,7 @@ noexcept_conv_p (tree to, tree from) bool fnptr_conv_p (tree to, tree from) { - tree t = non_reference (to); + tree t = to; tree f = from; if (TYPE_PTRMEMFUNC_P (t) && TYPE_PTRMEMFUNC_P (f)) @@ -2123,8 +2112,8 @@ fnptr_conv_p (tree to, tree from) t = TYPE_PTRMEMFUNC_FN_TYPE (t); f = TYPE_PTRMEMFUNC_FN_TYPE (f); } - if (TYPE_PTR_P (t) - && TYPE_PTR_P (f)) + if (INDIRECT_TYPE_P (t) + && INDIRECT_TYPE_P (f)) { t = TREE_TYPE (t); f = TREE_TYPE (f); diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c index a22eea5..25cabfe 100644 --- a/gcc/cp/cxx-pretty-print.c +++ b/gcc/cp/cxx-pretty-print.c @@ -1537,38 +1537,36 @@ pp_cxx_parameter_declaration (cxx_pretty_printer *pp, tree t) static void pp_cxx_parameter_declaration_clause (cxx_pretty_printer *pp, tree t) { - tree args; - tree types; - bool abstract; - - // For a requires clause or the explicit printing of a parameter list - // we expect T to be a chain of PARM_DECLs. Otherwise, the list of - // args and types are taken from the function decl T. - if (TREE_CODE (t) == PARM_DECL) + gcc_assert (FUNC_OR_METHOD_TYPE_P (t) || TREE_CODE (t) == FUNCTION_DECL); + tree types, args; + if (TYPE_P (t)) { - args = t; - types = t; - abstract = false; + types = TYPE_ARG_TYPES (t); + args = NULL_TREE; } else { - bool type_p = TYPE_P (t); - args = type_p ? NULL : FUNCTION_FIRST_USER_PARM (t); - types = type_p ? TYPE_ARG_TYPES (t) : FUNCTION_FIRST_USER_PARMTYPE (t); - abstract = args == NULL || pp->flags & pp_c_flag_abstract; + types = FUNCTION_FIRST_USER_PARMTYPE (t); + args = FUNCTION_FIRST_USER_PARM (t); } - bool first = true; + bool abstract = !args || (pp->flags & pp_c_flag_abstract); /* Skip artificial parameter for non-static member functions. */ if (TREE_CODE (t) == METHOD_TYPE) types = TREE_CHAIN (types); + bool first = true; pp_cxx_left_paren (pp); - for (; args; args = TREE_CHAIN (args), types = TREE_CHAIN (types)) + for (; types != void_list_node; types = TREE_CHAIN (types)) { if (!first) pp_cxx_separate_with (pp, ','); first = false; + if (!types) + { + pp_cxx_ws_string (pp, "..."); + break; + } pp_cxx_parameter_declaration (pp, abstract ? TREE_VALUE (types) : args); if (!abstract && pp->flags & pp_cxx_flag_default_argument) { @@ -1577,6 +1575,8 @@ pp_cxx_parameter_declaration_clause (cxx_pretty_printer *pp, tree t) pp_cxx_whitespace (pp); pp->assignment_expression (TREE_PURPOSE (types)); } + if (!abstract) + args = TREE_CHAIN (args); } pp_cxx_right_paren (pp); } @@ -2645,6 +2645,12 @@ pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t) case CPTK_IS_FINAL: pp_cxx_ws_string (pp, "__is_final"); break; + case CPTK_IS_LAYOUT_COMPATIBLE: + pp_cxx_ws_string (pp, "__is_layout_compatible"); + break; + case CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF: + pp_cxx_ws_string (pp, "__is_pointer_interconvertible_base_of"); + break; case CPTK_IS_POD: pp_cxx_ws_string (pp, "__is_pod"); break; @@ -2695,7 +2701,10 @@ pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t) pp_cxx_left_paren (pp); pp->type_id (TRAIT_EXPR_TYPE1 (t)); - if (kind == CPTK_IS_BASE_OF || kind == CPTK_IS_SAME_AS) + if (kind == CPTK_IS_BASE_OF + || kind == CPTK_IS_SAME_AS + || kind == CPTK_IS_LAYOUT_COMPATIBLE + || kind == CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF) { pp_cxx_separate_with (pp, ','); pp->type_id (TRAIT_EXPR_TYPE2 (t)); @@ -2775,9 +2784,18 @@ void pp_cxx_requires_expr (cxx_pretty_printer *pp, tree t) { pp_string (pp, "requires"); - if (tree parms = TREE_OPERAND (t, 0)) + if (tree parms = REQUIRES_EXPR_PARMS (t)) { - pp_cxx_parameter_declaration_clause (pp, parms); + bool first = true; + pp_cxx_left_paren (pp); + for (; parms; parms = TREE_CHAIN (parms)) + { + if (!first) + pp_cxx_separate_with (pp, ',' ); + first = false; + pp_cxx_parameter_declaration (pp, parms); + } + pp_cxx_right_paren (pp); pp_cxx_whitespace (pp); } pp_cxx_requirement_body (pp, TREE_OPERAND (t, 1)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 8e8f37d..c206502 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -222,6 +222,7 @@ struct GTY((for_user)) named_label_entry { bool in_omp_scope; bool in_transaction_scope; bool in_constexpr_if; + bool in_consteval_if; }; #define named_labels cp_function_chain->x_named_labels @@ -491,6 +492,16 @@ level_for_constexpr_if (cp_binding_level *b) && IF_STMT_CONSTEXPR_P (b->this_entity)); } +/* True if B is the level for the condition of a consteval if. */ + +static bool +level_for_consteval_if (cp_binding_level *b) +{ + return (b->kind == sk_cond && b->this_entity + && TREE_CODE (b->this_entity) == IF_STMT + && IF_STMT_CONSTEVAL_P (b->this_entity)); +} + /* Update data for defined and undefined labels when leaving a scope. */ int @@ -530,6 +541,8 @@ poplevel_named_label_1 (named_label_entry **slot, cp_binding_level *bl) case sk_block: if (level_for_constexpr_if (bl->level_chain)) ent->in_constexpr_if = true; + else if (level_for_consteval_if (bl->level_chain)) + ent->in_consteval_if = true; break; default: break; @@ -828,9 +841,7 @@ wrapup_namespace_globals () { if (vec<tree, va_gc> *statics = static_decls) { - tree decl; - unsigned int i; - FOR_EACH_VEC_ELT (*statics, i, decl) + for (tree decl : *statics) { if (warn_unused_function && TREE_CODE (decl) == FUNCTION_DECL @@ -839,7 +850,7 @@ wrapup_namespace_globals () && !TREE_PUBLIC (decl) && !DECL_ARTIFICIAL (decl) && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl) - && !TREE_NO_WARNING (decl)) + && !warning_suppressed_p (decl, OPT_Wunused_function)) warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wunused_function, "%qF declared %<static%> but never defined", decl); @@ -944,7 +955,9 @@ static bool function_requirements_equivalent_p (tree newfn, tree oldfn) { /* In the concepts TS, the combined constraints are compared. */ - if (cxx_dialect < cxx20) + if (cxx_dialect < cxx20 + && (DECL_TEMPLATE_SPECIALIZATION (newfn) + <= DECL_TEMPLATE_SPECIALIZATION (oldfn))) { tree ci1 = get_constraints (oldfn); tree ci2 = get_constraints (newfn); @@ -1609,8 +1622,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) if (name[0] == '_' && name[1] == '_' - && (strncmp (name + 2, "builtin_", - strlen ("builtin_")) == 0 + && (startswith (name + 2, "builtin_") || (len = strlen (name)) <= strlen ("___chk") || memcmp (name + len - strlen ("_chk"), "_chk", strlen ("_chk") + 1) != 0)) @@ -2041,8 +2053,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) { if (DECL_ARTIFICIAL (olddecl)) { - gcc_checking_assert (!(DECL_LANG_SPECIFIC (olddecl) - && DECL_MODULE_IMPORT_P (olddecl))); if (!(global_purview_p () || not_module_p ())) error ("declaration %qD conflicts with builtin", newdecl); else @@ -2162,11 +2172,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) if (DECL_DELETED_FN (newdecl)) { auto_diagnostic_group d; - pedwarn (newdecl_loc, OPT_Wpedantic, - "deleted definition of %qD is not first declaration", - newdecl); - inform (olddecl_loc, - "previous declaration of %qD", olddecl); + if (pedwarn (newdecl_loc, 0, "deleted definition of %qD " + "is not first declaration", newdecl)) + inform (olddecl_loc, + "previous declaration of %qD", olddecl); } DECL_DELETED_FN (newdecl) |= DECL_DELETED_FN (olddecl); } @@ -2277,10 +2286,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) } } - DECL_MODULE_IMPORT_P (olddecl) - = DECL_MODULE_IMPORT_P (old_result) - = DECL_MODULE_IMPORT_P (newdecl); - return olddecl; } @@ -2413,6 +2418,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) if (TREE_DEPRECATED (newdecl)) TREE_DEPRECATED (olddecl) = 1; + /* Merge unavailability. */ + if (TREE_UNAVAILABLE (newdecl)) + TREE_UNAVAILABLE (olddecl) = 1; + /* Preserve function specific target and optimization options */ if (TREE_CODE (newdecl) == FUNCTION_DECL) { @@ -2562,8 +2571,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) 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); + if (!DECL_TEMPLATE_SPECIALIZATION (newdecl)) + DECL_INITIALIZED_IN_CLASS_P (newdecl) + |= DECL_INITIALIZED_IN_CLASS_P (olddecl); } /* Don't really know how much of the language-specific @@ -2800,6 +2810,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) SET_DECL_ALIGN (newdecl, DECL_ALIGN (olddecl)); DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl); } + else if (DECL_ALIGN (olddecl) == DECL_ALIGN (newdecl) + && DECL_USER_ALIGN (olddecl) != DECL_USER_ALIGN (newdecl)) + DECL_USER_ALIGN (newdecl) = 1; + DECL_USER_ALIGN (olddecl) = DECL_USER_ALIGN (newdecl); if (DECL_WARN_IF_NOT_ALIGN (olddecl) > DECL_WARN_IF_NOT_ALIGN (newdecl)) @@ -2933,19 +2947,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) } } - if (DECL_LANG_SPECIFIC (olddecl) && DECL_TEMPLATE_INFO (olddecl)) - { - /* Repropagate the module information to the template. */ - tree tmpl = DECL_TI_TEMPLATE (olddecl); - - if (DECL_TEMPLATE_RESULT (tmpl) == olddecl) - { - DECL_MODULE_PURVIEW_P (tmpl) = DECL_MODULE_PURVIEW_P (olddecl); - gcc_checking_assert (!DECL_MODULE_IMPORT_P (olddecl)); - DECL_MODULE_IMPORT_P (tmpl) = false; - } - } - if (VAR_OR_FUNCTION_DECL_P (newdecl)) { if (DECL_EXTERNAL (olddecl) @@ -3410,6 +3411,7 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names, bool complained = false; int identified = 0; bool saw_eh = false, saw_omp = false, saw_tm = false, saw_cxif = false; + bool saw_ceif = false; if (exited_omp) { @@ -3489,6 +3491,12 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names, loc = EXPR_LOCATION (b->level_chain->this_entity); saw_cxif = true; } + else if (!saw_ceif && level_for_consteval_if (b->level_chain)) + { + inf = G_(" enters %<consteval if%> statement"); + loc = EXPR_LOCATION (b->level_chain->this_entity); + saw_ceif = true; + } break; default: @@ -3570,12 +3578,13 @@ check_goto (tree decl) unsigned ix; if (ent->in_try_scope || ent->in_catch_scope || ent->in_transaction_scope - || ent->in_constexpr_if + || ent->in_constexpr_if || ent->in_consteval_if || ent->in_omp_scope || !vec_safe_is_empty (ent->bad_decls)) { diagnostic_t diag_kind = DK_PERMERROR; if (ent->in_try_scope || ent->in_catch_scope || ent->in_constexpr_if - || ent->in_transaction_scope || ent->in_omp_scope) + || ent->in_consteval_if || ent->in_transaction_scope + || ent->in_omp_scope) diag_kind = DK_ERROR; complained = identify_goto (decl, DECL_SOURCE_LOCATION (decl), &input_location, diag_kind); @@ -3621,6 +3630,8 @@ check_goto (tree decl) inform (input_location, " enters synchronized or atomic statement"); else if (ent->in_constexpr_if) inform (input_location, " enters %<constexpr if%> statement"); + else if (ent->in_consteval_if) + inform (input_location, " enters %<consteval if%> statement"); } if (ent->in_omp_scope) @@ -4073,6 +4084,12 @@ make_typename_type (tree context, tree name, enum tag_types tag_type, error ("%qD used without template arguments", name); return error_mark_node; } + else if (is_overloaded_fn (name)) + { + if (complain & tf_error) + error ("%qD is a function, not a type", name); + return error_mark_node; + } gcc_assert (identifier_p (name)); gcc_assert (TYPE_P (context)); @@ -4084,7 +4101,7 @@ make_typename_type (tree context, tree name, enum tag_types tag_type, error ("%q#T is not a class", context); return error_mark_node; } - + /* When the CONTEXT is a dependent type, NAME could refer to a dependent base class of CONTEXT. But look inside it anyway if CONTEXT is a currently open scope, in case it refers to a @@ -4149,10 +4166,15 @@ make_typename_type (tree context, tree name, enum tag_types tag_type, return error_mark_node; if (want_template) - return lookup_template_class (t, TREE_OPERAND (fullname, 1), - NULL_TREE, context, - /*entering_scope=*/0, - complain | tf_user); + { + t = lookup_template_class (t, TREE_OPERAND (fullname, 1), + NULL_TREE, context, + /*entering_scope=*/0, + complain | tf_user); + if (t == error_mark_node) + return error_mark_node; + t = TYPE_NAME (t); + } if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl)) t = TREE_TYPE (t); @@ -4371,6 +4393,7 @@ initialize_predefined_identifiers (void) {"heap deleted", &heap_deleted_identifier, cik_normal}, {"heap [] uninit", &heap_vec_uninit_identifier, cik_normal}, {"heap []", &heap_vec_identifier, cik_normal}, + {"omp", &omp_identifier, cik_normal}, {NULL, NULL, cik_normal} }; @@ -4448,6 +4471,22 @@ cxx_init_decl_processing (void) BUILT_IN_FRONTEND, NULL, NULL_TREE); set_call_expr_flags (decl, ECF_CONST | ECF_NOTHROW | ECF_LEAF); + tree bool_vaftype = build_varargs_function_type_list (boolean_type_node, + NULL_TREE); + decl + = add_builtin_function ("__builtin_is_corresponding_member", + bool_vaftype, + CP_BUILT_IN_IS_CORRESPONDING_MEMBER, + BUILT_IN_FRONTEND, NULL, NULL_TREE); + set_call_expr_flags (decl, ECF_CONST | ECF_NOTHROW | ECF_LEAF); + + decl + = add_builtin_function ("__builtin_is_pointer_interconvertible_with_class", + bool_vaftype, + CP_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS, + BUILT_IN_FRONTEND, NULL, NULL_TREE); + set_call_expr_flags (decl, ECF_CONST | ECF_NOTHROW | ECF_LEAF); + integer_two_node = build_int_cst (NULL_TREE, 2); /* Guess at the initial static decls size. */ @@ -4713,6 +4752,38 @@ cxx_init_decl_processing (void) /* Show we use EH for cleanups. */ if (flag_exceptions) using_eh_for_cleanups (); + + /* Check that the hardware interference sizes are at least + alignof(max_align_t), as required by the standard. */ + const int max_align = max_align_t_align () / BITS_PER_UNIT; + if (param_destruct_interfere_size) + { + if (param_destruct_interfere_size < max_align) + error ("%<--param destructive-interference-size=%d%> is less than " + "%d", param_destruct_interfere_size, max_align); + else if (param_destruct_interfere_size < param_l1_cache_line_size) + warning (OPT_Winterference_size, + "%<--param destructive-interference-size=%d%> " + "is less than %<--param l1-cache-line-size=%d%>", + param_destruct_interfere_size, param_l1_cache_line_size); + } + else if (param_l1_cache_line_size >= max_align) + param_destruct_interfere_size = param_l1_cache_line_size; + /* else leave it unset. */ + + if (param_construct_interfere_size) + { + if (param_construct_interfere_size < max_align) + error ("%<--param constructive-interference-size=%d%> is less than " + "%d", param_construct_interfere_size, max_align); + else if (param_construct_interfere_size > param_l1_cache_line_size) + warning (OPT_Winterference_size, + "%<--param constructive-interference-size=%d%> " + "is greater than %<--param l1-cache-line-size=%d%>", + param_construct_interfere_size, param_l1_cache_line_size); + } + else if (param_l1_cache_line_size >= max_align) + param_construct_interfere_size = param_l1_cache_line_size; } /* Enter an abi node in global-module context. returns a cookie to @@ -4840,7 +4911,7 @@ cxx_builtin_function (tree decl) /* In the user's namespace, it must be declared before use. */ hiding = true; else if (IDENTIFIER_LENGTH (id) > strlen ("___chk") - && 0 != strncmp (name + 2, "builtin_", strlen ("builtin_")) + && !startswith (name + 2, "builtin_") && 0 == memcmp (name + IDENTIFIER_LENGTH (id) - strlen ("_chk"), "_chk", strlen ("_chk") + 1)) /* Treat __*_chk fortification functions as anticipated as well, @@ -4976,16 +5047,6 @@ push_cp_library_fn (enum tree_code operator_code, tree type, return fn; } -/* Like push_library_fn, but takes a TREE_LIST of parm types rather than - a FUNCTION_TYPE. */ - -tree -push_void_library_fn (tree name, tree parmtypes, int ecf_flags) -{ - tree type = build_function_type (void_type_node, parmtypes); - return push_library_fn (name, type, NULL_TREE, ecf_flags); -} - /* Like push_library_fn, but also note that this function throws and does not return. Used for __throw_foo and the like. */ @@ -5017,12 +5078,58 @@ fixup_anonymous_aggr (tree t) TYPE_HAS_COPY_ASSIGN (t) = 0; TYPE_HAS_CONST_COPY_ASSIGN (t) = 0; - /* Splice the implicitly generated functions out of TYPE_FIELDS. */ + /* Splice the implicitly generated functions out of TYPE_FIELDS and diagnose + invalid members. */ for (tree probe, *prev_p = &TYPE_FIELDS (t); (probe = *prev_p);) - if (TREE_CODE (probe) == FUNCTION_DECL && DECL_ARTIFICIAL (probe)) - *prev_p = DECL_CHAIN (probe); - else - prev_p = &DECL_CHAIN (probe); + { + if (TREE_CODE (probe) == FUNCTION_DECL && DECL_ARTIFICIAL (probe)) + *prev_p = DECL_CHAIN (probe); + else + prev_p = &DECL_CHAIN (probe); + + if (DECL_ARTIFICIAL (probe) + && (!DECL_IMPLICIT_TYPEDEF_P (probe) + || TYPE_ANON_P (TREE_TYPE (probe)))) + continue; + + if (TREE_CODE (probe) != FIELD_DECL + || (TREE_PRIVATE (probe) || TREE_PROTECTED (probe))) + { + /* We already complained about static data members in + finish_static_data_member_decl. */ + if (!VAR_P (probe)) + { + auto_diagnostic_group d; + if (permerror (DECL_SOURCE_LOCATION (probe), + TREE_CODE (t) == UNION_TYPE + ? "%q#D invalid; an anonymous union may " + "only have public non-static data members" + : "%q#D invalid; an anonymous struct may " + "only have public non-static data members", probe)) + { + static bool hint; + if (flag_permissive && !hint) + { + hint = true; + inform (DECL_SOURCE_LOCATION (probe), + "this flexibility is deprecated and will be " + "removed"); + } + } + } + } + } + + /* Splice all functions out of CLASSTYPE_MEMBER_VEC. */ + vec<tree,va_gc>* vec = CLASSTYPE_MEMBER_VEC (t); + unsigned store = 0; + for (tree elt : vec) + if (!is_overloaded_fn (elt)) + (*vec)[store++] = elt; + vec_safe_truncate (vec, store); + + /* Wipe RTTI info. */ + CLASSTYPE_TYPEINFO_VAR (t) = NULL_TREE; /* Anonymous aggregates cannot have fields with ctors, dtors or complex assignment operators (because they cannot have these methods themselves). @@ -5032,6 +5139,13 @@ fixup_anonymous_aggr (tree t) { tree field, type; + if (BINFO_N_BASE_BINFOS (TYPE_BINFO (t))) + { + error_at (location_of (t), "anonymous struct with base classes"); + /* Avoid ICE after error on anon-struct9.C. */ + TYPE_NEEDS_CONSTRUCTING (t) = false; + } + for (field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL) { @@ -6162,7 +6276,7 @@ struct reshape_iter static tree reshape_init_r (tree, reshape_iter *, tree, tsubst_flags_t); -/* FIELD is a FIELD_DECL or NULL. In the former case, the value +/* FIELD is an element of TYPE_FIELDS or NULL. In the former case, the value returned is the next FIELD_DECL (possibly FIELD itself) that can be initialized. If there are no more such fields, the return value will be NULL. */ @@ -6195,7 +6309,13 @@ is_direct_enum_init (tree type, tree init) && ENUM_FIXED_UNDERLYING_TYPE_P (type) && TREE_CODE (init) == CONSTRUCTOR && CONSTRUCTOR_IS_DIRECT_INIT (init) - && CONSTRUCTOR_NELTS (init) == 1) + && CONSTRUCTOR_NELTS (init) == 1 + /* DR 2374: The single element needs to be implicitly + convertible to the underlying type of the enum. */ + && can_convert_arg (ENUM_UNDERLYING_TYPE (type), + TREE_TYPE (CONSTRUCTOR_ELT (init, 0)->value), + CONSTRUCTOR_ELT (init, 0)->value, + LOOKUP_IMPLICIT, tf_none)) return true; return false; } @@ -6392,10 +6512,9 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p, /* We already reshaped this. */ if (field != d->cur->index) { - tree id = DECL_NAME (d->cur->index); - gcc_assert (id); - gcc_checking_assert (d->cur->index - == get_class_binding (type, id)); + if (tree id = DECL_NAME (d->cur->index)) + gcc_checking_assert (d->cur->index + == get_class_binding (type, id)); field = d->cur->index; } } @@ -6416,6 +6535,32 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p, d->cur->index); return error_mark_node; } + + /* If the element is an anonymous union object and the initializer + list is a designated-initializer-list, the anonymous union object + is initialized by the designated-initializer-list { D }, where D + is the designated-initializer-clause naming a member of the + anonymous union object. */ + tree ictx = DECL_CONTEXT (field); + if (!same_type_ignoring_top_level_qualifiers_p (ictx, type)) + { + gcc_assert (ANON_AGGR_TYPE_P (ictx)); + /* Find the anon aggr that is a direct member of TYPE. */ + while (true) + { + tree cctx = TYPE_CONTEXT (ictx); + if (same_type_ignoring_top_level_qualifiers_p (cctx, type)) + break; + ictx = cctx; + } + /* And then the TYPE member with that anon aggr type. */ + tree aafield = TYPE_FIELDS (type); + for (; aafield; aafield = TREE_CHAIN (aafield)) + if (TREE_TYPE (aafield) == ictx) + break; + gcc_assert (aafield); + field = aafield; + } } /* If we processed all the member of the class, we are done. */ @@ -6457,8 +6602,7 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p, continue_: if (base_binfo) { - BINFO_BASE_ITERATE (binfo, ++binfo_idx, base_binfo); - if (base_binfo) + if (BINFO_BASE_ITERATE (binfo, ++binfo_idx, base_binfo)) field = base_binfo; else field = next_initializable_field (TYPE_FIELDS (type)); @@ -6551,7 +6695,8 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p, /* A non-aggregate type is always initialized with a single initializer. */ if (!CP_AGGREGATE_TYPE_P (type) - /* As is an array with dependent bound. */ + /* As is an array with dependent bound, which we can see + during C++20 aggregate CTAD. */ || (cxx_dialect >= cxx20 && TREE_CODE (type) == ARRAY_TYPE && uses_template_parms (TYPE_DOMAIN (type)))) @@ -6599,6 +6744,8 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p, initialized from that element." Even if T is an aggregate. */ if (cxx_dialect >= cxx11 && (CLASS_TYPE_P (type) || VECTOR_TYPE_P (type)) && first_initializer_p + /* But not if it's a designated init. */ + && !d->cur->index && d->end - d->cur == 1 && reference_related_p (type, TREE_TYPE (init))) { @@ -6666,6 +6813,7 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p, initializer already, and there is not a CONSTRUCTOR, it means that there is a missing set of braces (that is, we are processing the case for which reshape_init exists). */ + bool braces_elided_p = false; if (!first_initializer_p) { if (TREE_CODE (stripped_init) == CONSTRUCTOR) @@ -6701,17 +6849,25 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p, warning (OPT_Wmissing_braces, "missing braces around initializer for %qT", type); + braces_elided_p = true; } /* Dispatch to specialized routines. */ + tree new_init; if (CLASS_TYPE_P (type)) - return reshape_init_class (type, d, first_initializer_p, complain); + new_init = reshape_init_class (type, d, first_initializer_p, complain); else if (TREE_CODE (type) == ARRAY_TYPE) - return reshape_init_array (type, d, first_initializer_p, complain); + new_init = reshape_init_array (type, d, first_initializer_p, complain); else if (VECTOR_TYPE_P (type)) - return reshape_init_vector (type, d, complain); + new_init = reshape_init_vector (type, d, complain); else gcc_unreachable(); + + if (braces_elided_p + && TREE_CODE (new_init) == CONSTRUCTOR) + CONSTRUCTOR_BRACES_ELIDED_P (new_init) = true; + + return new_init; } /* Undo the brace-elision allowed by [dcl.init.aggr] in a @@ -7569,9 +7725,9 @@ omp_declare_variant_finalize_one (tree decl, tree attr) return true; } if (fndecl_built_in_p (variant) - && (strncmp (varname, "__builtin_", strlen ("__builtin_")) == 0 - || strncmp (varname, "__sync_", strlen ("__sync_")) == 0 - || strncmp (varname, "__atomic_", strlen ("__atomic_")) == 0)) + && (startswith (varname, "__builtin_") + || startswith (varname, "__sync_") + || startswith (varname, "__atomic_"))) { error_at (varid_loc, "variant %qD is a built-in", variant); return true; @@ -7712,10 +7868,13 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, if (asmspec_tree && asmspec_tree != error_mark_node) asmspec = TREE_STRING_POINTER (asmspec_tree); - if (current_class_type - && CP_DECL_CONTEXT (decl) == current_class_type - && TYPE_BEING_DEFINED (current_class_type) - && !CLASSTYPE_TEMPLATE_INSTANTIATION (current_class_type) + bool in_class_decl + = (current_class_type + && CP_DECL_CONTEXT (decl) == current_class_type + && TYPE_BEING_DEFINED (current_class_type) + && !CLASSTYPE_TEMPLATE_INSTANTIATION (current_class_type)); + + if (in_class_decl && (DECL_INITIAL (decl) || init)) DECL_INITIALIZED_IN_CLASS_P (decl) = 1; @@ -8088,6 +8247,13 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, if (!flag_weak) /* Check again now that we have an initializer. */ maybe_commonize_var (decl); + /* A class-scope constexpr variable with an out-of-class declaration. + C++17 makes them implicitly inline, but still force it out. */ + if (DECL_INLINE_VAR_P (decl) + && !DECL_VAR_DECLARED_INLINE_P (decl) + && !DECL_TEMPLATE_INSTANTIATION (decl) + && !in_class_decl) + mark_needed (decl); } if (var_definition_p @@ -8169,8 +8335,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, reference, insert it in the statement-tree now. */ if (cleanups) { - unsigned i; tree t; - FOR_EACH_VEC_ELT (*cleanups, i, t) + for (tree t : *cleanups) push_cleanup (decl, t, false); release_tree_vector (cleanups); } @@ -8629,6 +8794,12 @@ cp_finish_decomp (tree decl, tree first, unsigned int count) : get_tuple_element_type (type, i)); input_location = sloc; + if (VOID_TYPE_P (eltype)) + { + error ("%<std::tuple_element<%u, %T>::type%> is %<void%>", + i, type); + eltype = error_mark_node; + } if (init == error_mark_node || eltype == error_mark_node) { inform (dloc, "in initialization of structured binding " @@ -9684,7 +9855,14 @@ grokfndecl (tree ctype, && (processing_template_decl > template_class_depth (ctx))); if (memtmpl) - tmpl_reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms); + { + if (!current_template_parms) + /* If there are no template parameters, something must have + gone wrong. */ + gcc_assert (seen_error ()); + else + tmpl_reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms); + } tree ci = build_constraints (tmpl_reqs, decl_reqs); if (concept_p && ci) { @@ -9821,8 +9999,8 @@ grokfndecl (tree ctype, || (IDENTIFIER_LENGTH (declarator) > 10 && IDENTIFIER_POINTER (declarator)[0] == '_' && IDENTIFIER_POINTER (declarator)[1] == '_' - && strncmp (IDENTIFIER_POINTER (declarator)+2, - "builtin_", 8) == 0) + && startswith (IDENTIFIER_POINTER (declarator) + 2, + "builtin_")) || (targetcm.cxx_implicit_extern_c && (targetcm.cxx_implicit_extern_c (IDENTIFIER_POINTER (declarator)))))) @@ -9935,12 +10113,6 @@ grokfndecl (tree ctype, if (deduction_guide_p (decl)) { - if (!DECL_NAMESPACE_SCOPE_P (decl)) - { - error_at (location, "deduction guide %qD must be declared at " - "namespace scope", decl); - return NULL_TREE; - } tree type = TREE_TYPE (DECL_NAME (decl)); if (in_namespace == NULL_TREE && CP_DECL_CONTEXT (decl) != CP_TYPE_CONTEXT (type)) @@ -9950,6 +10122,13 @@ grokfndecl (tree ctype, inform (location_of (type), " declared here"); return NULL_TREE; } + if (DECL_CLASS_SCOPE_P (decl) + && current_access_specifier != declared_access (TYPE_NAME (type))) + { + error_at (location, "deduction guide %qD must have the same access " + "as %qT", decl, type); + inform (location_of (type), " declared here"); + } if (funcdef_flag) error_at (location, "deduction guide %qD must not have a function body", decl); @@ -10353,6 +10532,12 @@ grokvardecl (tree type, "a non-template variable cannot be %<concept%>"); return NULL_TREE; } + else if (!at_namespace_scope_p ()) + { + error_at (declspecs->locations[ds_concept], + "concept must be defined at namespace scope"); + return NULL_TREE; + } else DECL_DECLARED_CONCEPT_P (decl) = true; if (!same_type_ignoring_top_level_qualifiers_p (type, boolean_type_node)) @@ -10859,17 +11044,6 @@ create_array_type_for_decl (tree name, tree type, tree size, location_t loc) if (type == error_mark_node || size == error_mark_node) return error_mark_node; - /* 8.3.4/1: If the type of the identifier of D contains the auto - type-specifier, the program is ill-formed. */ - if (type_uses_auto (type)) - { - if (name) - error_at (loc, "%qD declared as array of %qT", name, type); - else - error ("creating array of %qT", type); - return error_mark_node; - } - /* If there are some types which cannot be array elements, issue an error-message and return. */ switch (TREE_CODE (type)) @@ -11111,7 +11285,7 @@ mark_inline_variable (tree decl, location_t loc) inlinep = false; } else if (cxx_dialect < cxx17) - pedwarn (loc, 0, "inline variables are only available " + pedwarn (loc, OPT_Wc__17_extensions, "inline variables are only available " "with %<-std=c++17%> or %<-std=gnu++17%>"); if (inlinep) { @@ -11622,20 +11796,24 @@ grokdeclarator (const cp_declarator *declarator, if (attrlist && *attrlist == error_mark_node) *attrlist = NULL_TREE; - /* An object declared as __attribute__((deprecated)) suppresses - warnings of uses of other deprecated items. */ + /* An object declared as __attribute__((unavailable)) suppresses + any reports of being declared with unavailable or deprecated + items. An object declared as __attribute__((deprecated)) + suppresses warnings of uses of other deprecated items. */ auto ds = make_temp_override (deprecated_state); - if (attrlist && lookup_attribute ("deprecated", *attrlist)) + if (attrlist && lookup_attribute ("unavailable", *attrlist)) + deprecated_state = UNAVAILABLE_DEPRECATED_SUPPRESS; + else if (attrlist && lookup_attribute ("deprecated", *attrlist)) deprecated_state = DEPRECATED_SUPPRESS; - cp_warn_deprecated_use (type); + cp_handle_deprecated_or_unavailable (type); if (type && TREE_CODE (type) == TYPE_DECL) { cp_warn_deprecated_use_scopes (CP_DECL_CONTEXT (type)); typedef_decl = type; type = TREE_TYPE (typedef_decl); if (DECL_ARTIFICIAL (typedef_decl)) - cp_warn_deprecated_use (type); + cp_handle_deprecated_or_unavailable (type); } /* No type at all: default to `int', and set DEFAULTED_INT because it was not a user-defined typedef. */ @@ -11935,6 +12113,10 @@ grokdeclarator (const cp_declarator *declarator, storage_class = declspecs->storage_class; if (storage_class == sc_static) staticp = 1 + (decl_context == FIELD); + else if (decl_context == FIELD && sfk == sfk_deduction_guide) + /* Treat class-scope deduction guides as static member functions + so that they get a FUNCTION_TYPE instead of a METHOD_TYPE. */ + staticp = 2; if (virtualp) { @@ -11947,13 +12129,13 @@ grokdeclarator (const cp_declarator *declarator, storage_class = sc_none; staticp = 0; } - if (constexpr_p && cxx_dialect < cxx20) + if (constexpr_p && pedantic && cxx_dialect < cxx20) { gcc_rich_location richloc (declspecs->locations[ds_virtual]); richloc.add_range (declspecs->locations[ds_constexpr]); - pedwarn (&richloc, OPT_Wpedantic, "member %qD can be declared both " - "%<virtual%> and %<constexpr%> only in %<-std=c++20%> or " - "%<-std=gnu++20%>", dname); + pedwarn (&richloc, OPT_Wc__20_extensions, "member %qD can be " + "declared both %<virtual%> and %<constexpr%> only in " + "%<-std=c++20%> or %<-std=gnu++20%>", dname); } } friendp = decl_spec_seq_has_spec_p (declspecs, ds_friend); @@ -12041,7 +12223,7 @@ grokdeclarator (const cp_declarator *declarator, error_at (declspecs->locations[ds_consteval], "structured " "binding declaration cannot be %qs", "consteval"); if (thread_p && cxx_dialect < cxx20) - pedwarn (declspecs->locations[ds_thread], 0, + pedwarn (declspecs->locations[ds_thread], OPT_Wc__20_extensions, "structured binding declaration can be %qs only in " "%<-std=c++20%> or %<-std=gnu++20%>", declspecs->gnu_thread_keyword_p @@ -12063,7 +12245,7 @@ grokdeclarator (const cp_declarator *declarator, break; case sc_static: if (cxx_dialect < cxx20) - pedwarn (loc, 0, + pedwarn (loc, OPT_Wc__20_extensions, "structured binding declaration can be %qs only in " "%<-std=c++20%> or %<-std=gnu++20%>", "static"); break; @@ -12244,7 +12426,7 @@ grokdeclarator (const cp_declarator *declarator, int attr_flags; attr_flags = 0; - if (declarator == NULL || declarator->kind == cdk_id) + if (declarator->kind == cdk_id) attr_flags |= (int) ATTR_FLAG_DECL_NEXT; if (declarator->kind == cdk_function) attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT; @@ -13676,6 +13858,15 @@ grokdeclarator (const cp_declarator *declarator, if (friendp) { + /* Packages tend to use GNU attributes on friends, so we only + warn for standard attributes. */ + if (attrlist && !funcdef_flag && cxx11_attribute_p (*attrlist)) + { + *attrlist = NULL_TREE; + if (warning_at (id_loc, OPT_Wattributes, "attribute ignored")) + inform (id_loc, "an attribute that appertains to a friend " + "declaration that is not a definition is ignored"); + } /* Friends are treated specially. */ if (ctype == current_class_type) ; /* We already issued a permerror. */ @@ -13699,8 +13890,7 @@ grokdeclarator (const cp_declarator *declarator, } decl = do_friend (ctype, unqualified_id, decl, - *attrlist, flags, - funcdef_flag); + flags, funcdef_flag); return decl; } else @@ -13788,10 +13978,7 @@ grokdeclarator (const cp_declarator *declarator, decl = build_decl (id_loc, FIELD_DECL, unqualified_id, type); DECL_NONADDRESSABLE_P (decl) = bitfield; if (bitfield && !unqualified_id) - { - TREE_NO_WARNING (decl) = 1; - DECL_PADDING_P (decl) = 1; - } + DECL_PADDING_P (decl) = 1; if (storage_class == sc_mutable) { @@ -13948,6 +14135,8 @@ grokdeclarator (const cp_declarator *declarator, storage_class = sc_none; } } + if (declspecs->explicit_specifier) + store_explicit_specifier (decl, declspecs->explicit_specifier); } else { @@ -14140,6 +14329,14 @@ static tree local_variable_p_walkfn (tree *tp, int *walk_subtrees, void * /*data*/) { + if (unevaluated_p (TREE_CODE (*tp))) + { + /* DR 2082 permits local variables in unevaluated contexts + within a default argument. */ + *walk_subtrees = 0; + return NULL_TREE; + } + if (local_variable_p (*tp) && (!DECL_ARTIFICIAL (*tp) || DECL_NAME (*tp) == this_identifier)) return *tp; @@ -14263,6 +14460,43 @@ type_is_deprecated (tree type) return NULL_TREE; } +/* Returns an unavailable type used within TYPE, or NULL_TREE if none. */ + +static tree +type_is_unavailable (tree type) +{ + enum tree_code code; + if (TREE_UNAVAILABLE (type)) + return type; + if (TYPE_NAME (type)) + { + if (TREE_UNAVAILABLE (TYPE_NAME (type))) + return type; + else + { + cp_warn_deprecated_use_scopes (CP_DECL_CONTEXT (TYPE_NAME (type))); + return NULL_TREE; + } + } + + /* Do warn about using typedefs to a deprecated class. */ + if (OVERLOAD_TYPE_P (type) && type != TYPE_MAIN_VARIANT (type)) + return type_is_deprecated (TYPE_MAIN_VARIANT (type)); + + code = TREE_CODE (type); + + if (code == POINTER_TYPE || code == REFERENCE_TYPE + || code == OFFSET_TYPE || code == FUNCTION_TYPE + || code == METHOD_TYPE || code == ARRAY_TYPE) + return type_is_unavailable (TREE_TYPE (type)); + + if (TYPE_PTRMEMFUNC_P (type)) + return type_is_unavailable + (TREE_TYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type)))); + + return NULL_TREE; +} + /* Decode the list of parameter types for a function type. Given the list of things declared inside the parens, return a list of types. @@ -14322,11 +14556,18 @@ grokparms (tree parmlist, tree *parms) if (type != error_mark_node) { - if (deprecated_state != DEPRECATED_SUPPRESS) + if (deprecated_state != UNAVAILABLE_DEPRECATED_SUPPRESS) + { + tree unavailtype = type_is_unavailable (type); + if (unavailtype) + cp_handle_deprecated_or_unavailable (unavailtype); + } + if (deprecated_state != DEPRECATED_SUPPRESS + && deprecated_state != UNAVAILABLE_DEPRECATED_SUPPRESS) { tree deptype = type_is_deprecated (type); if (deptype) - cp_warn_deprecated_use (deptype); + cp_handle_deprecated_or_unavailable (deptype); } /* [dcl.fct] "A parameter with volatile-qualified type is @@ -16243,17 +16484,9 @@ incremented enumerator value is too large for %<long%>")); For which case we need to make sure that the access of `S::i' matches the access of `S::E'. */ - tree saved_cas = current_access_specifier; - if (TREE_PRIVATE (TYPE_NAME (enumtype))) - current_access_specifier = access_private_node; - else if (TREE_PROTECTED (TYPE_NAME (enumtype))) - current_access_specifier = access_protected_node; - else - current_access_specifier = access_public_node; - + auto cas = make_temp_override (current_access_specifier); + set_current_access_from_decl (TYPE_NAME (enumtype)); finish_member_declaration (decl); - - current_access_specifier = saved_cas; } else pushdecl (decl); @@ -16286,7 +16519,7 @@ lookup_enumerator (tree enumtype, tree name) tree cxx_simulate_enum_decl (location_t loc, const char *name, - vec<string_int_pair> values) + vec<string_int_pair> *values) { location_t saved_loc = input_location; input_location = loc; @@ -16303,11 +16536,9 @@ cxx_simulate_enum_decl (location_t loc, const char *name, SET_OPAQUE_ENUM_P (enumtype, false); DECL_SOURCE_LOCATION (TYPE_NAME (enumtype)) = loc; - string_int_pair *value; - unsigned int i; - FOR_EACH_VEC_ELT (values, i, value) - build_enumerator (get_identifier (value->first), - build_int_cst (integer_type_node, value->second), + for (const string_int_pair &value : values) + build_enumerator (get_identifier (value.first), + build_int_cst (integer_type_node, value.second), enumtype, NULL_TREE, loc); finish_enum_value_list (enumtype); @@ -17385,7 +17616,7 @@ finish_function (bool inline_p) /* Don't complain if we are declared noreturn. */ && !TREE_THIS_VOLATILE (fndecl) && !DECL_NAME (DECL_RESULT (fndecl)) - && !TREE_NO_WARNING (fndecl) + && !warning_suppressed_p (fndecl, OPT_Wreturn_type) /* Structor return values (if any) are set by the compiler. */ && !DECL_CONSTRUCTOR_P (fndecl) && !DECL_DESTRUCTOR_P (fndecl) @@ -17413,7 +17644,7 @@ finish_function (bool inline_p) else if (warning_at (&richloc, OPT_Wreturn_type, "no return statement in function returning " "non-void")) - TREE_NO_WARNING (fndecl) = 1; + suppress_warning (fndecl, OPT_Wreturn_type); } /* Lambda closure members are implicitly constexpr if possible. */ @@ -17487,7 +17718,7 @@ finish_function (bool inline_p) && !DECL_READ_P (decl) && DECL_NAME (decl) && !DECL_ARTIFICIAL (decl) - && !TREE_NO_WARNING (decl) + && !warning_suppressed_p (decl,OPT_Wunused_but_set_parameter) && !DECL_IN_SYSTEM_HEADER (decl) && TREE_TYPE (decl) != error_mark_node && !TYPE_REF_P (TREE_TYPE (decl)) @@ -17978,7 +18209,7 @@ require_deduced_type (tree decl, tsubst_flags_t complain) { if (undeduced_auto_decl (decl)) { - if (TREE_NO_WARNING (decl) && seen_error ()) + if (warning_suppressed_p (decl) && seen_error ()) /* We probably already complained about deduction failure. */; else if (complain & tf_error) error ("use of %qD before deduction of %<auto%>", decl); @@ -17994,6 +18225,9 @@ require_deduced_type (tree decl, tsubst_flags_t complain) tree build_explicit_specifier (tree expr, tsubst_flags_t complain) { + if (check_for_bare_parameter_packs (expr)) + return error_mark_node; + if (instantiation_dependent_expression_p (expr)) /* Wait for instantiation, tsubst_function_decl will handle it. */ return expr; diff --git a/gcc/cp/decl.h b/gcc/cp/decl.h index 387d807..4a9b399 100644 --- a/gcc/cp/decl.h +++ b/gcc/cp/decl.h @@ -44,7 +44,8 @@ extern void name_unnamed_type (tree, tree); enum deprecated_states { DEPRECATED_NORMAL, - DEPRECATED_SUPPRESS + DEPRECATED_SUPPRESS, + UNAVAILABLE_DEPRECATED_SUPPRESS }; extern enum deprecated_states deprecated_state; diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index c46100d..a79a70b 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -974,7 +974,11 @@ grokfield (const cp_declarator *declarator, if ((TREE_CODE (value) == FUNCTION_DECL || TREE_CODE (value) == TEMPLATE_DECL) && DECL_CONTEXT (value) != current_class_type) - return value; + { + if (attrlist) + cplus_decl_attributes (&value, attrlist, 0); + return value; + } /* Need to set this before push_template_decl. */ if (VAR_P (value)) @@ -1117,7 +1121,7 @@ grokbitfield (const cp_declarator *declarator, && !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (width))) error ("width of bit-field %qD has non-integral type %qT", value, TREE_TYPE (width)); - else + else if (!check_for_bare_parameter_packs (width)) { /* Temporarily stash the width in DECL_BIT_FIELD_REPRESENTATIVE. check_bitfield_decl picks it from there later and sets DECL_SIZE @@ -1278,9 +1282,9 @@ save_template_attributes (tree *attr_p, tree *decl_p, int flags) tree old_attrs = *q; - /* Merge the late attributes at the beginning with the attribute + /* Place the late attributes at the beginning of the attribute list. */ - late_attrs = merge_attributes (late_attrs, *q); + late_attrs = chainon (late_attrs, *q); if (*q != late_attrs && !DECL_P (*decl_p) && !(flags & ATTR_FLAG_TYPE_IN_PLACE)) @@ -1547,7 +1551,7 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags) return; /* Add implicit "omp declare target" attribute if requested. */ - if (scope_chain->omp_declare_target_attribute + if (vec_safe_length (scope_chain->omp_declare_target_attribute) && ((VAR_P (*decl) && (TREE_STATIC (*decl) || DECL_EXTERNAL (*decl))) || TREE_CODE (*decl) == FUNCTION_DECL)) @@ -1580,6 +1584,31 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags) cp_check_const_attributes (attributes); + if ((flag_openmp || flag_openmp_simd) && attributes != error_mark_node) + { + bool diagnosed = false; + for (tree *pa = &attributes; *pa; ) + { + if (get_attribute_namespace (*pa) == omp_identifier) + { + tree name = get_attribute_name (*pa); + if (is_attribute_p ("directive", name) + || is_attribute_p ("sequence", name)) + { + if (!diagnosed) + { + error ("%<omp::%E%> not allowed to be specified in this " + "context", name); + diagnosed = true; + } + *pa = TREE_CHAIN (*pa); + continue; + } + } + pa = &TREE_CHAIN (*pa); + } + } + if (TREE_CODE (*decl) == TEMPLATE_DECL) decl = &DECL_TEMPLATE_RESULT (*decl); @@ -1606,6 +1635,17 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags) if (*decl == pattern) TREE_DEPRECATED (tmpl) = true; } + + /* Likewise, propagate unavailability out to the template. */ + if (TREE_UNAVAILABLE (*decl)) + if (tree ti = get_template_info (*decl)) + { + tree tmpl = TI_TEMPLATE (ti); + tree pattern = (TYPE_P (*decl) ? TREE_TYPE (tmpl) + : DECL_TEMPLATE_RESULT (tmpl)); + if (*decl == pattern) + TREE_UNAVAILABLE (tmpl) = true; + } } /* Walks through the namespace- or function-scope anonymous union @@ -2937,14 +2977,15 @@ reset_type_linkage (tree type) SET_DECL_ASSEMBLER_NAME (vt, name); reset_decl_linkage (vt); } - if (tree ti = CLASSTYPE_TYPEINFO_VAR (type)) - { - tree name = mangle_typeinfo_for_type (type); - DECL_NAME (ti) = name; - SET_DECL_ASSEMBLER_NAME (ti, name); - TREE_TYPE (name) = type; - reset_decl_linkage (ti); - } + if (!ANON_AGGR_TYPE_P (type)) + if (tree ti = CLASSTYPE_TYPEINFO_VAR (type)) + { + tree name = mangle_typeinfo_for_type (type); + DECL_NAME (ti) = name; + SET_DECL_ASSEMBLER_NAME (ti, name); + TREE_TYPE (name) = type; + reset_decl_linkage (ti); + } for (tree m = TYPE_FIELDS (type); m; m = DECL_CHAIN (m)) { tree mem = STRIP_TEMPLATE (m); @@ -3418,6 +3459,12 @@ set_guard (tree guard) static bool var_defined_without_dynamic_init (tree var) { + /* constinit vars are guaranteed to not have dynamic initializer, + but still registering the destructor counts as dynamic initialization. */ + if (DECL_DECLARED_CONSTINIT_P (var) + && COMPLETE_TYPE_P (TREE_TYPE (var)) + && !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (var))) + return true; /* If it's defined in another TU, we can't tell. */ if (DECL_EXTERNAL (var)) return false; @@ -4525,7 +4572,7 @@ no_linkage_error (tree decl) || (errorcount + sorrycount > 0 && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl) - && TREE_NO_WARNING (decl)))) + && warning_suppressed_p (decl /* What warning? */)))) /* In C++11 it's ok if the decl is defined. */ return; @@ -5200,7 +5247,7 @@ c_parse_final_cleanups (void) && warning_at (DECL_SOURCE_LOCATION (decl), 0, "inline function %qD used but never defined", decl)) /* Avoid a duplicate warning from check_global_declaration. */ - TREE_NO_WARNING (decl) = 1; + suppress_warning (decl, OPT_Wunused); } /* So must decls that use a type with no linkage. */ @@ -5463,14 +5510,47 @@ maybe_instantiate_decl (tree decl) } } -/* Maybe warn if DECL is deprecated, subject to COMPLAIN. Returns whether or - not a warning was emitted. */ +/* Error if the DECL is unavailable (unless this is currently suppressed). + Maybe warn if DECL is deprecated, subject to COMPLAIN. Returns true if + an error or warning was emitted. */ bool -cp_warn_deprecated_use (tree decl, tsubst_flags_t complain) +cp_handle_deprecated_or_unavailable (tree decl, tsubst_flags_t complain) { - if (!(complain & tf_warning) || !decl - || deprecated_state == DEPRECATED_SUPPRESS) + if (!decl) + return false; + + if ((complain & tf_error) + && deprecated_state != UNAVAILABLE_DEPRECATED_SUPPRESS) + { + if (TREE_UNAVAILABLE (decl)) + { + error_unavailable_use (decl, NULL_TREE); + return true; + } + else + { + /* Perhaps this is an unavailable typedef. */ + if (TYPE_P (decl) + && TYPE_NAME (decl) + && TREE_UNAVAILABLE (TYPE_NAME (decl))) + { + decl = TYPE_NAME (decl); + /* Don't error within members of a unavailable type. */ + if (TYPE_P (decl) + && currently_open_class (decl)) + return false; + + error_unavailable_use (decl, NULL_TREE); + return true; + } + } + /* Carry on to consider deprecatedness. */ + } + + if (!(complain & tf_warning) + || deprecated_state == DEPRECATED_SUPPRESS + || deprecated_state == UNAVAILABLE_DEPRECATED_SUPPRESS) return false; if (!TREE_DEPRECATED (decl)) @@ -5495,10 +5575,10 @@ cp_warn_deprecated_use (tree decl, tsubst_flags_t complain) && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl) && copy_fn_p (decl)) { - if (warn_deprecated_copy - /* Don't warn about system library classes (c++/86342). */ - && (!DECL_IN_SYSTEM_HEADER (decl) - || global_dc->dc_warn_system_headers)) + /* Don't warn if the flag was disabled around the class definition + (c++/94492). */ + if (warning_enabled_at (DECL_SOURCE_LOCATION (decl), + OPT_Wdeprecated_copy)) { auto_diagnostic_group d; tree ctx = DECL_CONTEXT (decl); @@ -5529,7 +5609,8 @@ cp_warn_deprecated_use_scopes (tree scope) && scope != error_mark_node && scope != global_namespace) { - if (cp_warn_deprecated_use (scope)) + if ((TREE_CODE (scope) == NAMESPACE_DECL || OVERLOAD_TYPE_P (scope)) + && cp_handle_deprecated_or_unavailable (scope)) return; if (TYPE_P (scope)) scope = CP_TYPE_CONTEXT (scope); @@ -5641,7 +5722,7 @@ mark_used (tree decl, tsubst_flags_t complain) TREE_USED (decl) = true; } - cp_warn_deprecated_use (decl, complain); + cp_handle_deprecated_or_unavailable (decl, complain); /* We can only check DECL_ODR_USED on variables or functions with DECL_LANG_SPECIFIC set, and these are also the only decls that we diff --git a/gcc/cp/error.c b/gcc/cp/error.c index ff4ae6f..012a4ec 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -371,7 +371,35 @@ static void dump_template_bindings (cxx_pretty_printer *pp, tree parms, tree args, vec<tree, va_gc> *typenames) { - bool need_semicolon = false; + /* Print "[with" and ']', conditional on whether anything is printed at all. + This is tied to whether a semicolon is needed to separate multiple template + parameters. */ + struct prepost_semicolon + { + cxx_pretty_printer *pp; + bool need_semicolon; + + void operator() () + { + if (need_semicolon) + pp_separate_with_semicolon (pp); + else + { + pp_cxx_whitespace (pp); + pp_cxx_left_bracket (pp); + pp->translate_string ("with"); + pp_cxx_whitespace (pp); + need_semicolon = true; + } + } + + ~prepost_semicolon () + { + if (need_semicolon) + pp_cxx_right_bracket (pp); + } + } semicolon_or_introducer = {pp, false}; + int i; tree t; @@ -395,10 +423,20 @@ dump_template_bindings (cxx_pretty_printer *pp, tree parms, tree args, if (lvl_args && NUM_TMPL_ARGS (lvl_args) > arg_idx) arg = TREE_VEC_ELT (lvl_args, arg_idx); - if (need_semicolon) - pp_separate_with_semicolon (pp); - dump_template_parameter (pp, TREE_VEC_ELT (p, i), - TFF_PLAIN_IDENTIFIER); + tree parm_i = TREE_VEC_ELT (p, i); + /* If the template argument repeats the template parameter (T = T), + skip the parameter.*/ + if (arg && TREE_CODE (arg) == TEMPLATE_TYPE_PARM + && TREE_CODE (parm_i) == TREE_LIST + && TREE_CODE (TREE_VALUE (parm_i)) == TYPE_DECL + && TREE_CODE (TREE_TYPE (TREE_VALUE (parm_i))) + == TEMPLATE_TYPE_PARM + && DECL_NAME (TREE_VALUE (parm_i)) + == DECL_NAME (TREE_CHAIN (arg))) + continue; + + semicolon_or_introducer (); + dump_template_parameter (pp, parm_i, TFF_PLAIN_IDENTIFIER); pp_cxx_whitespace (pp); pp_equal (pp); pp_cxx_whitespace (pp); @@ -414,7 +452,6 @@ dump_template_bindings (cxx_pretty_printer *pp, tree parms, tree args, pp_string (pp, M_("<missing>")); ++arg_idx; - need_semicolon = true; } parms = TREE_CHAIN (parms); @@ -436,8 +473,7 @@ dump_template_bindings (cxx_pretty_printer *pp, tree parms, tree args, FOR_EACH_VEC_SAFE_ELT (typenames, i, t) { - if (need_semicolon) - pp_separate_with_semicolon (pp); + semicolon_or_introducer (); dump_type (pp, t, TFF_PLAIN_IDENTIFIER); pp_cxx_whitespace (pp); pp_equal (pp); @@ -501,6 +537,8 @@ dump_type (cxx_pretty_printer *pp, tree t, int flags) else { pp_cxx_cv_qualifier_seq (pp, t); + if (! (flags & TFF_UNQUALIFIED_NAME)) + dump_scope (pp, CP_DECL_CONTEXT (decl), flags); pp_cxx_tree_identifier (pp, TYPE_IDENTIFIER (t)); return; } @@ -1138,7 +1176,7 @@ dump_decl_name (cxx_pretty_printer *pp, tree t, int flags) } const char *str = IDENTIFIER_POINTER (t); - if (!strncmp (str, "_ZGR", 4)) + if (startswith (str, "_ZGR")) { pp_cxx_ws_string (pp, "<temporary>"); return; @@ -1362,7 +1400,10 @@ dump_decl (cxx_pretty_printer *pp, tree t, int flags) break; case LABEL_DECL: - pp_cxx_tree_identifier (pp, DECL_NAME (t)); + if (DECL_NAME (t)) + pp_cxx_tree_identifier (pp, DECL_NAME (t)); + else + dump_generic_node (pp, t, 0, TDF_SLIM, false); break; case CONST_DECL: @@ -1594,12 +1635,7 @@ dump_substitution (cxx_pretty_printer *pp, && !(flags & TFF_NO_TEMPLATE_BINDINGS)) { vec<tree, va_gc> *typenames = t ? find_typenames (t) : NULL; - pp_cxx_whitespace (pp); - pp_cxx_left_bracket (pp); - pp->translate_string ("with"); - pp_cxx_whitespace (pp); dump_template_bindings (pp, template_parms, template_args, typenames); - pp_cxx_right_bracket (pp); } } @@ -1640,7 +1676,8 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags) bool constexpr_p; tree ret = NULL_TREE; - flags &= ~(TFF_UNQUALIFIED_NAME | TFF_TEMPLATE_NAME); + int dump_function_name_flags = flags & ~TFF_UNQUALIFIED_NAME; + flags = dump_function_name_flags & ~TFF_TEMPLATE_NAME; if (TREE_CODE (t) == TEMPLATE_DECL) t = DECL_TEMPLATE_RESULT (t); @@ -1718,7 +1755,7 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags) else dump_scope (pp, CP_DECL_CONTEXT (t), flags); - dump_function_name (pp, t, flags); + dump_function_name (pp, t, dump_function_name_flags); if (!(flags & TFF_NO_FUNCTION_ARGUMENTS)) { @@ -1932,6 +1969,7 @@ dump_function_name (cxx_pretty_printer *pp, tree t, int flags) dump_module_suffix (pp, t); if (DECL_TEMPLATE_INFO (t) + && !(flags & TFF_TEMPLATE_NAME) && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t) && (TREE_CODE (DECL_TI_TEMPLATE (t)) != TEMPLATE_DECL || PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t)))) @@ -4300,10 +4338,8 @@ defer_phase_2_of_type_diff (deferred_printed_type *deferred, %D declaration. %E expression. %F function declaration. - %G gcall * %H type difference (from). %I type difference (to). - %K tree %L language as used in extern "lang". %O binary operator. %P function parameter whose position is indicated by an integer. @@ -4353,9 +4389,6 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec, break; case 'E': result = expr_to_string (next_tree); break; case 'F': result = fndecl_to_string (next_tree, verbose); break; - case 'G': - percent_G_format (text); - return true; case 'H': defer_phase_2_of_type_diff (&postprocessor->m_type_a, next_tree, buffer_ptr, verbose, *quoted); @@ -4364,10 +4397,6 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec, defer_phase_2_of_type_diff (&postprocessor->m_type_b, next_tree, buffer_ptr, verbose, *quoted); return true; - case 'K': - t = va_arg (*text->args_ptr, tree); - percent_K_format (text, EXPR_LOCATION (t), TREE_BLOCK (t)); - return true; case 'L': result = language_to_string (next_lang); break; case 'O': result = op_to_string (false, next_tcode); break; case 'P': result = parm_to_string (next_int); break; @@ -4404,77 +4433,78 @@ maybe_warn_cpp0x (cpp0x_warn_str str) switch (str) { case CPP0X_INITIALIZER_LISTS: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "extended initializer lists " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_EXPLICIT_CONVERSION: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "explicit conversion operators " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_VARIADIC_TEMPLATES: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "variadic templates " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_LAMBDA_EXPR: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "lambda expressions " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_AUTO: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "C++11 auto only available with %<-std=c++11%> or " "%<-std=gnu++11%>"); break; case CPP0X_SCOPED_ENUMS: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "scoped enums only available with %<-std=c++11%> or " "%<-std=gnu++11%>"); break; case CPP0X_DEFAULTED_DELETED: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "defaulted and deleted functions " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_INLINE_NAMESPACES: - pedwarn (input_location, OPT_Wpedantic, - "inline namespaces " - "only available with %<-std=c++11%> or %<-std=gnu++11%>"); + if (pedantic) + pedwarn (input_location, OPT_Wc__11_extensions, + "inline namespaces " + "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_OVERRIDE_CONTROLS: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "override controls (override/final) " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_NSDMI: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "non-static data member initializers " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_USER_DEFINED_LITERALS: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "user-defined literals " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_DELEGATING_CTORS: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "delegating constructors " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_INHERITING_CTORS: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "inheriting constructors " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_ATTRIBUTES: - pedwarn (input_location, 0, - "c++11 attributes " + pedwarn (input_location, OPT_Wc__11_extensions, + "C++11 attributes " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_REF_QUALIFIER: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "ref-qualifiers " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 0bbc229..a8acbc4 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -466,7 +466,8 @@ expand_end_catch_block (void) || DECL_DESTRUCTOR_P (current_function_decl))) { tree rethrow = build_throw (input_location, NULL_TREE); - TREE_NO_WARNING (rethrow) = true; + /* Disable all warnings for the generated rethrow statement. */ + suppress_warning (rethrow); finish_expr_stmt (rethrow); } } @@ -1032,12 +1033,15 @@ check_handlers (tree handlers) expression whose type is a polymorphic class type (10.3). */ static tree -check_noexcept_r (tree *tp, int * /*walk_subtrees*/, void * /*data*/) +check_noexcept_r (tree *tp, int *walk_subtrees, void *) { tree t = *tp; enum tree_code code = TREE_CODE (t); - if ((code == CALL_EXPR && CALL_EXPR_FN (t)) - || code == AGGR_INIT_EXPR) + + if (unevaluated_p (code)) + *walk_subtrees = false; + else if ((code == CALL_EXPR && CALL_EXPR_FN (t)) + || code == AGGR_INIT_EXPR) { /* We can only use the exception specification of the called function for determining the value of a noexcept expression; we can't use @@ -1228,6 +1232,8 @@ type_throw_all_p (const_tree type) tree build_noexcept_spec (tree expr, tsubst_flags_t complain) { + if (check_for_bare_parameter_packs (expr)) + return error_mark_node; if (TREE_CODE (expr) != DEFERRED_NOEXCEPT && !value_dependent_expression_p (expr)) { diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index ee73adb..4f62884 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -475,7 +475,7 @@ make_friend_class (tree type, tree friend_type, bool complain) tree do_friend (tree ctype, tree declarator, tree decl, - tree attrlist, enum overload_flags flags, + enum overload_flags flags, bool funcdef_flag) { gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); @@ -488,13 +488,6 @@ do_friend (tree ctype, tree declarator, tree decl, error ("friend declaration %qD may not have virt-specifiers", decl); - /* Unfortunately, we have to handle attributes here. Normally we would - handle them in start_decl_1, but since this is a friend decl start_decl_1 - never gets to see it. */ - - /* Set attributes here so if duplicate decl, will have proper attributes. */ - cplus_decl_attributes (&decl, attrlist, 0); - if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR) { declarator = TREE_OPERAND (declarator, 0); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 7d598f6..1426f9a 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -34,13 +34,13 @@ along with GCC; see the file COPYING3. If not see #include "attribs.h" #include "asan.h" #include "stor-layout.h" -#include "builtins.h" +#include "pointer-query.h" static bool begin_init_stmts (tree *, tree *); static tree finish_init_stmts (bool, tree, tree); static void construct_virtual_base (tree, tree); -static void expand_aggr_init_1 (tree, tree, tree, tree, int, tsubst_flags_t); -static void expand_default_init (tree, tree, tree, tree, int, tsubst_flags_t); +static bool expand_aggr_init_1 (tree, tree, tree, tree, int, tsubst_flags_t); +static bool expand_default_init (tree, tree, tree, tree, int, tsubst_flags_t); static void perform_member_init (tree, tree); static int member_init_ok_or_else (tree, tree, tree); static void expand_virtual_init (tree, tree); @@ -427,6 +427,11 @@ build_value_init_noctor (tree type, tsubst_flags_t complain) == NULL_TREE)) continue; + /* Ignore unnamed zero-width bitfields. */ + if (DECL_UNNAMED_BIT_FIELD (field) + && integer_zerop (DECL_SIZE (field))) + continue; + /* We could skip vfields and fields of types with user-defined constructors, but I think that won't improve performance at all; it should be simpler in general just @@ -586,16 +591,21 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain) bool pushed = false; tree ctx = DECL_CONTEXT (member); - if (!currently_open_class (ctx) - && !LOCAL_CLASS_P (ctx)) + + processing_template_decl_sentinel ptds (/*reset*/false); + if (!currently_open_class (ctx)) { - push_to_top_level (); + if (!LOCAL_CLASS_P (ctx)) + push_to_top_level (); + else + /* push_to_top_level would lose the necessary function context, + just reset processing_template_decl. */ + processing_template_decl = 0; push_nested_class (ctx); + push_deferring_access_checks (dk_no_deferred); pushed = true; } - gcc_checking_assert (!processing_template_decl); - inject_this_parameter (ctx, TYPE_UNQUALIFIED); start_lambda_scope (member); @@ -616,8 +626,10 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain) if (pushed) { + pop_deferring_access_checks (); pop_nested_class (); - pop_from_top_level (); + if (!LOCAL_CLASS_P (ctx)) + pop_from_top_level (); } input_location = sloc; @@ -1831,12 +1843,14 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain) is_global = begin_init_stmts (&stmt_expr, &compound_stmt); destroy_temps = stmts_are_full_exprs_p (); current_stmt_tree ()->stmts_are_full_exprs_p = 0; - expand_aggr_init_1 (TYPE_BINFO (type), exp, exp, - init, LOOKUP_NORMAL|flags, complain); + bool ok = expand_aggr_init_1 (TYPE_BINFO (type), exp, exp, + init, LOOKUP_NORMAL|flags, complain); stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt); current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps; TREE_READONLY (exp) = was_const; TREE_THIS_VOLATILE (exp) = was_volatile; + if (!ok) + return error_mark_node; if ((VAR_P (exp) || TREE_CODE (exp) == PARM_DECL) && TREE_SIDE_EFFECTS (stmt_expr) @@ -1847,7 +1861,7 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain) return stmt_expr; } -static void +static bool expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, tsubst_flags_t complain) { @@ -1882,6 +1896,9 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, happen for direct-initialization, too. */ init = digest_init (type, init, complain); + if (init == error_mark_node) + return false; + /* A CONSTRUCTOR of the target's type is a previously digested initializer, whether that happened just above or in cp_parser_late_parsing_nsdmi. @@ -1903,7 +1920,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init); TREE_SIDE_EFFECTS (init) = 1; finish_expr_stmt (init); - return; + return true; } if (init && TREE_CODE (init) != TREE_LIST @@ -1920,8 +1937,12 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, have already built up the constructor call so we could wrap it in an exception region. */; else - init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, - flags, complain | tf_no_cleanup); + { + init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, + flags, complain | tf_no_cleanup); + if (init == error_mark_node) + return false; + } if (TREE_CODE (init) == MUST_NOT_THROW_EXPR) /* We need to protect the initialization of a catch parm with a @@ -1937,7 +1958,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init); TREE_SIDE_EFFECTS (init) = 1; finish_expr_stmt (init); - return; + return true; } if (init == NULL_TREE) @@ -1975,6 +1996,8 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, &parms, binfo, flags, complain); base = fold_build_cleanup_point_expr (void_type_node, base); + if (complete == error_mark_node || base == error_mark_node) + return false; rval = build_if_in_charge (complete, base); } else @@ -1984,6 +2007,8 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, rval = build_special_member_call (exp, ctor_name, &parms, binfo, flags, complain); + if (rval == error_mark_node) + return false; } if (parms != NULL) @@ -2003,10 +2028,12 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, /* FIXME put back convert_to_void? */ if (TREE_SIDE_EFFECTS (rval)) finish_expr_stmt (rval); + + return true; } /* This function is responsible for initializing EXP with INIT - (if any). + (if any). Returns true on success, false on failure. BINFO is the binfo of the type for who we are performing the initialization. For example, if W is a virtual base class of A and B, @@ -2025,7 +2052,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, FLAGS is just passed to `build_new_method_call'. See that function for its description. */ -static void +static bool expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, tsubst_flags_t complain) { @@ -2051,7 +2078,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, if (init) finish_expr_stmt (init); gcc_assert (!cleanups); - return; + return true; } /* List-initialization from {} becomes value-initialization for non-aggregate @@ -2071,9 +2098,9 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, that's value-initialization. */ if (init == void_type_node) { - /* If the type has data but no user-provided ctor, we need to zero + /* If the type has data but no user-provided default ctor, we need to zero out the object. */ - if (!type_has_user_provided_constructor (type) + if (type_has_non_user_provided_default_constructor (type) && !is_really_empty_class (type, /*ignore_vptr*/true)) { tree field_size = NULL_TREE; @@ -2089,7 +2116,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, /* If we don't need to mess with the constructor at all, then we're done. */ if (! type_build_ctor_call (type)) - return; + return true; /* Otherwise fall through and call the constructor. */ init = NULL_TREE; @@ -2097,7 +2124,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, /* We know that expand_default_init can handle everything we want at this point. */ - expand_default_init (binfo, true_exp, exp, init, flags, complain); + return expand_default_init (binfo, true_exp, exp, init, flags, complain); } /* Report an error if TYPE is not a user-defined, class type. If @@ -2207,7 +2234,7 @@ build_offset_ref (tree type, tree member, bool address_p, if (!ok) return error_mark_node; if (DECL_STATIC_FUNCTION_P (t)) - return t; + return member; member = t; } else @@ -3529,11 +3556,11 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, the arguments to the constructor call. */ { /* CLEANUP is compiler-generated, so no diagnostics. */ - TREE_NO_WARNING (cleanup) = true; + suppress_warning (cleanup); init_expr = build2 (TRY_CATCH_EXPR, void_type_node, init_expr, cleanup); /* Likewise, this try-catch is compiler-generated. */ - TREE_NO_WARNING (init_expr) = true; + suppress_warning (init_expr); } else /* Ack! First we allocate the memory. Then we set our sentry @@ -3555,7 +3582,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, sentry = TARGET_EXPR_SLOT (begin); /* CLEANUP is compiler-generated, so no diagnostics. */ - TREE_NO_WARNING (cleanup) = true; + suppress_warning (cleanup); TARGET_EXPR_CLEANUP (begin) = build3 (COND_EXPR, void_type_node, sentry, @@ -3569,7 +3596,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, build2 (COMPOUND_EXPR, void_type_node, init_expr, end)); /* Likewise, this is compiler-generated. */ - TREE_NO_WARNING (init_expr) = true; + suppress_warning (init_expr); } } } @@ -3816,7 +3843,7 @@ build_new (location_t loc, vec<tree, va_gc> **placement, tree type, /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain. */ rval = build1_loc (loc, NOP_EXPR, TREE_TYPE (rval), rval); - TREE_NO_WARNING (rval) = 1; + suppress_warning (rval, OPT_Wunused_value); return rval; } @@ -3988,7 +4015,7 @@ build_vec_delete_1 (location_t loc, tree base, tree maxindex, tree type, fold_convert (TREE_TYPE (base), nullptr_node)); /* This is a compiler generated comparison, don't emit e.g. -Wnonnull-compare warning for it. */ - TREE_NO_WARNING (cond) = 1; + suppress_warning (cond, OPT_Wnonnull_compare); body = build3_loc (loc, COND_EXPR, void_type_node, cond, body, integer_zero_node); COND_EXPR_IS_VEC_DELETE (body) = true; @@ -4215,6 +4242,14 @@ build_vec_init (tree base, tree maxindex, tree init, else ptype = atype; + if (integer_all_onesp (maxindex)) + { + /* Shortcut zero element case to avoid unneeded constructor synthesis. */ + if (init && TREE_SIDE_EFFECTS (init)) + base = build2 (COMPOUND_EXPR, ptype, init, base); + return base; + } + /* The code we are generating looks like: ({ T* t1 = (T*) base; @@ -4650,7 +4685,7 @@ build_vec_init (tree base, tree maxindex, tree init, atype = build_pointer_type (atype); stmt_expr = build1 (NOP_EXPR, atype, stmt_expr); stmt_expr = cp_build_fold_indirect_ref (stmt_expr); - TREE_NO_WARNING (stmt_expr) = 1; + suppress_warning (stmt_expr /* What warning? */); } return stmt_expr; @@ -4874,7 +4909,10 @@ build_delete (location_t loc, tree otype, tree addr, complain); } - if (!destroying_delete && type_build_dtor_call (type)) + if (destroying_delete) + /* The operator delete will call the destructor. */ + expr = addr; + else if (type_build_dtor_call (type)) expr = build_dtor_call (cp_build_fold_indirect_ref (addr), auto_delete, flags, complain); else @@ -4917,7 +4955,7 @@ build_delete (location_t loc, tree otype, tree addr, /* This is a compiler generated comparison, don't emit e.g. -Wnonnull-compare warning for it. */ else if (TREE_CODE (ifexp) == NE_EXPR) - TREE_NO_WARNING (ifexp) = 1; + suppress_warning (ifexp, OPT_Wnonnull_compare); if (!integer_nonzerop (ifexp)) expr = build3 (COND_EXPR, void_type_node, ifexp, expr, void_node); diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c index 421685c..2e9d38b 100644 --- a/gcc/cp/lambda.c +++ b/gcc/cp/lambda.c @@ -41,6 +41,7 @@ build_lambda_expr (void) LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) = CPLD_NONE; LAMBDA_EXPR_CAPTURE_LIST (lambda) = NULL_TREE; LAMBDA_EXPR_THIS_CAPTURE (lambda) = NULL_TREE; + LAMBDA_EXPR_REGEN_INFO (lambda) = NULL_TREE; LAMBDA_EXPR_PENDING_PROXIES (lambda) = NULL; LAMBDA_EXPR_MUTABLE_P (lambda) = false; return lambda; @@ -159,24 +160,6 @@ begin_lambda_type (tree lambda) return type; } -/* Returns the type to use for the return type of the operator() of a - closure class. */ - -tree -lambda_return_type (tree expr) -{ - if (expr == NULL_TREE) - return void_type_node; - if (type_unknown_p (expr) - || BRACE_ENCLOSED_INITIALIZER_P (expr)) - { - cxx_incomplete_type_error (expr, TREE_TYPE (expr)); - return error_mark_node; - } - gcc_checking_assert (!type_dependent_expression_p (expr)); - return cv_unqualified (type_decays_to (unlowered_expr_type (expr))); -} - /* Given a LAMBDA_EXPR or closure type LAMBDA, return the op() of the closure type. */ @@ -606,8 +589,11 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p, parameter pack in this context. We will want as many fields as we have elements in the expansion of the initializer, so use its packs instead. */ - PACK_EXPANSION_PARAMETER_PACKS (type) - = uses_parameter_packs (initializer); + { + PACK_EXPANSION_PARAMETER_PACKS (type) + = uses_parameter_packs (initializer); + PACK_EXPANSION_AUTO_P (type) = true; + } } /* Make member variable. */ @@ -1352,9 +1338,9 @@ is_lambda_ignored_entity (tree val) /* None of the lookups that use qualify_lookup want the op() from the lambda; they want the one from the enclosing class. */ - val = OVL_FIRST (val); - if (LAMBDA_FUNCTION_P (val)) - return true; + if (tree fns = maybe_get_fns (val)) + if (LAMBDA_FUNCTION_P (OVL_FIRST (fns))) + return true; return false; } diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 73e14b8..43abd01 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -166,8 +166,6 @@ init_operators (void) if (op_ptr->name) { - /* Make sure it fits in lang_decl_fn::operator_code. */ - gcc_checking_assert (op_ptr->ovl_op_code < (1 << 6)); tree ident = set_operator_ident (op_ptr); if (unsigned index = IDENTIFIER_CP_INDEX (ident)) { diff --git a/gcc/cp/logic.cc b/gcc/cp/logic.cc index 142457e..9d892b1 100644 --- a/gcc/cp/logic.cc +++ b/gcc/cp/logic.cc @@ -223,9 +223,7 @@ struct formula formula (tree t) { - /* This should call emplace_back(). There's an extra copy being - invoked by using push_back(). */ - m_clauses.push_back (t); + m_clauses.emplace_back (t); m_current = m_clauses.begin (); } @@ -248,8 +246,7 @@ struct formula clause& branch () { gcc_assert (!done ()); - m_clauses.push_back (*m_current); - return m_clauses.back (); + return *m_clauses.insert (std::next (m_current), *m_current); } /* Returns the position of the current clause. */ @@ -287,6 +284,14 @@ struct formula return m_clauses.end (); } + /* Remove the specified clause from the formula. */ + + void erase (iterator i) + { + gcc_assert (i != m_current); + m_clauses.erase (i); + } + std::list<clause> m_clauses; /* The list of clauses. */ iterator m_current; /* The current clause. */ }; @@ -659,39 +664,6 @@ decompose_clause (formula& f, clause& c, rules r) f.advance (); } -/* Decompose the logical formula F according to the logical - rules determined by R. The result is a formula containing - clauses that contain only atomic terms. */ - -void -decompose_formula (formula& f, rules r) -{ - while (!f.done ()) - decompose_clause (f, *f.current (), r); -} - -/* Fully decomposing T into a list of sequents, each comprised of - a list of atomic constraints, as if T were an antecedent. */ - -static formula -decompose_antecedents (tree t) -{ - formula f (t); - decompose_formula (f, left); - return f; -} - -/* Fully decomposing T into a list of sequents, each comprised of - a list of atomic constraints, as if T were a consequent. */ - -static formula -decompose_consequents (tree t) -{ - formula f (t); - decompose_formula (f, right); - return f; -} - static bool derive_proof (clause&, tree, rules); /* Derive a proof of both operands of T. */ @@ -744,28 +716,6 @@ derive_proof (clause& c, tree t, rules r) } } -/* Derive a proof of T from disjunctive clauses in F. */ - -static bool -derive_proofs (formula& f, tree t, rules r) -{ - for (formula::iterator i = f.begin(); i != f.end(); ++i) - if (!derive_proof (*i, t, r)) - return false; - return true; -} - -/* The largest number of clauses in CNF or DNF we accept as input - for subsumption. This an upper bound of 2^16 expressions. */ -static int max_problem_size = 16; - -static inline bool -diagnose_constraint_size (tree t) -{ - error_at (input_location, "%qE exceeds the maximum constraint complexity", t); - return false; -} - /* Key/value pair for caching subsumption results. This associates a pair of constraints with a boolean value indicating the result. */ @@ -845,31 +795,33 @@ subsumes_constraints_nonnull (tree lhs, tree rhs) if (bool *b = lookup_subsumption(lhs, rhs)) return *b; - int n1 = dnf_size (lhs); - int n2 = cnf_size (rhs); - - /* Make sure we haven't exceeded the largest acceptable problem. */ - if (std::min (n1, n2) >= max_problem_size) - { - if (n1 < n2) - diagnose_constraint_size (lhs); - else - diagnose_constraint_size (rhs); - return false; - } - - /* Decompose the smaller of the two formulas, and recursively - check for implication of the larger. */ - bool result; - if (n1 <= n2) - { - formula dnf = decompose_antecedents (lhs); - result = derive_proofs (dnf, rhs, left); - } + tree x, y; + rules r; + if (dnf_size (lhs) <= cnf_size (rhs)) + /* When LHS looks simpler than RHS, we'll determine subsumption by + decomposing LHS into its disjunctive normal form and checking that + each (conjunctive) clause in the decomposed LHS implies RHS. */ + x = lhs, y = rhs, r = left; else + /* Otherwise, we'll determine subsumption by decomposing RHS into its + conjunctive normal form and checking that each (disjunctive) clause + in the decomposed RHS implies LHS. */ + x = rhs, y = lhs, r = right; + + /* Decompose X into a list of sequents according to R, and recursively + check for implication of Y. */ + bool result = true; + formula f (x); + while (!f.done ()) { - formula cnf = decompose_consequents (rhs); - result = derive_proofs (cnf, lhs, right); + auto i = f.current (); + decompose_clause (f, *i, r); + if (!derive_proof (*i, y, r)) + { + result = false; + break; + } + f.erase (i); } return save_subsumption (lhs, rhs, result); diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 0a9e5aa..bf4abba 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -832,10 +832,22 @@ write_encoding (const tree decl) write_bare_function_type (fn_type, mangle_return_type_p (decl), d); + + /* If this is a coroutine helper, then append an appropriate string to + identify which. */ + if (tree ramp = DECL_RAMP_FN (decl)) + { + if (DECL_ACTOR_FN (ramp) == decl) + write_string (JOIN_STR "actor"); + else if (DECL_DESTROY_FN (ramp) == decl) + write_string (JOIN_STR "destroy"); + else + gcc_unreachable (); + } } } -/* Interface to substitution and identifer mangling, used by the +/* Interface to substitution and identifier mangling, used by the module name mangler. */ void @@ -1308,10 +1320,10 @@ find_decomp_unqualified_name (tree decl, size_t *len) const char *p = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); const char *end = p + IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl)); bool nested = false; - if (strncmp (p, "_Z", 2)) + if (!startswith (p, "_Z")) return NULL; p += 2; - if (!strncmp (p, "St", 2)) + if (startswith (p, "St")) p += 2; else if (*p == 'N') { @@ -1327,7 +1339,7 @@ find_decomp_unqualified_name (tree decl, size_t *len) break; } } - if (strncmp (p, "DC", 2)) + if (!startswith (p, "DC")) return NULL; if (nested) { @@ -1423,9 +1435,12 @@ write_unqualified_name (tree decl) } else if (DECL_OVERLOADED_OPERATOR_P (decl)) { + tree t; + if (!(t = DECL_RAMP_FN (decl))) + t = decl; const char *mangled_name - = (ovl_op_info[DECL_ASSIGNMENT_OPERATOR_P (decl)] - [DECL_OVERLOADED_OPERATOR_CODE_RAW (decl)].mangled_name); + = (ovl_op_info[DECL_ASSIGNMENT_OPERATOR_P (t)] + [DECL_OVERLOADED_OPERATOR_CODE_RAW (t)].mangled_name); write_string (mangled_name); } else if (UDLIT_OPER_P (DECL_NAME (decl))) @@ -1628,6 +1643,7 @@ write_literal_operator_name (tree identifier) static void write_compact_number (int num) { + gcc_checking_assert (num >= 0); if (num > 0) write_unsigned_number (num - 1); write_char ('_'); @@ -2027,15 +2043,7 @@ write_local_name (tree function, const tree local_entity, /* For this purpose, parameters are numbered from right-to-left. */ if (parm) { - tree t; - int i = 0; - for (t = DECL_ARGUMENTS (function); t; t = DECL_CHAIN (t)) - { - if (t == parm) - i = 1; - else if (i) - ++i; - } + int i = list_length (parm); write_char ('d'); write_compact_number (i - 1); } @@ -2947,6 +2955,16 @@ write_base_ref (tree expr, tree base = NULL_TREE) return true; } +/* The number of elements spanned by a RANGE_EXPR. */ + +unsigned HOST_WIDE_INT +range_expr_nelts (tree expr) +{ + tree lo = TREE_OPERAND (expr, 0); + tree hi = TREE_OPERAND (expr, 1); + return tree_to_uhwi (hi) - tree_to_uhwi (lo) + 1; +} + /* <expression> ::= <unary operator-name> <expression> ::= <binary operator-name> <expression> <expression> ::= <expr-primary> @@ -3119,16 +3137,14 @@ write_expression (tree expr) { if (!ALIGNOF_EXPR_STD_P (expr)) { - if (abi_warn_or_compat_version_crosses (15)) + if (abi_warn_or_compat_version_crosses (16)) G.need_abi_warning = true; - if (abi_version_at_least (15)) + if (abi_version_at_least (16)) { /* We used to mangle __alignof__ like alignof. */ - write_string ("v111__alignof__"); - if (TYPE_P (TREE_OPERAND (expr, 0))) - write_type (TREE_OPERAND (expr, 0)); - else - write_expression (TREE_OPERAND (expr, 0)); + write_string ("u11__alignof__"); + write_template_arg (TREE_OPERAND (expr, 0)); + write_char ('E'); return; } } @@ -3293,8 +3309,14 @@ write_expression (tree expr) write_type (etype); } - bool nontriv = !trivial_type_p (etype); - if (nontriv || !zero_init_expr_p (expr)) + /* If this is an undigested initializer, mangle it as written. + COMPOUND_LITERAL_P doesn't actually distinguish between digested and + undigested braced casts, but it should work to use it to distinguish + between braced casts in a template signature (undigested) and template + parm object values (digested), and all CONSTRUCTORS that get here + should be one of those two cases. */ + bool undigested = braced_init || COMPOUND_LITERAL_P (expr); + if (undigested || !zero_init_expr_p (expr)) { /* Convert braced initializer lists to STRING_CSTs so that A<"Foo"> mangles the same as A<{'F', 'o', 'o', 0}> while @@ -3305,28 +3327,32 @@ write_expression (tree expr) if (TREE_CODE (expr) == CONSTRUCTOR) { vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (expr); - unsigned last_nonzero = UINT_MAX, i; + unsigned last_nonzero = UINT_MAX; constructor_elt *ce; - tree val; - if (!nontriv) - FOR_EACH_CONSTRUCTOR_VALUE (elts, i, val) - if (!zero_init_expr_p (val)) + if (!undigested) + for (HOST_WIDE_INT i = 0; vec_safe_iterate (elts, i, &ce); ++i) + if ((TREE_CODE (etype) == UNION_TYPE + && ce->index != first_field (etype)) + || !zero_init_expr_p (ce->value)) last_nonzero = i; - if (nontriv || last_nonzero != UINT_MAX) + if (undigested || last_nonzero != UINT_MAX) for (HOST_WIDE_INT i = 0; vec_safe_iterate (elts, i, &ce); ++i) { if (i > last_nonzero) break; - /* FIXME handle RANGE_EXPR */ if (TREE_CODE (etype) == UNION_TYPE) { /* Express the active member as a designator. */ write_string ("di"); write_unqualified_name (ce->index); } - write_expression (ce->value); + unsigned reps = 1; + if (ce->index && TREE_CODE (ce->index) == RANGE_EXPR) + reps = range_expr_nelts (ce->index); + for (unsigned j = 0; j < reps; ++j) + write_expression (ce->value); } } else @@ -3352,9 +3378,9 @@ write_expression (tree expr) tree name = dependent_name (expr); if (IDENTIFIER_ANY_OP_P (name)) { - if (abi_version_at_least (15)) + if (abi_version_at_least (16)) write_string ("on"); - if (abi_warn_or_compat_version_crosses (15)) + if (abi_warn_or_compat_version_crosses (16)) G.need_abi_warning = 1; } write_unqualified_id (name); @@ -4419,7 +4445,7 @@ static void write_guarded_var_name (const tree variable) { if (DECL_NAME (variable) - && strncmp (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR", 4) == 0) + && startswith (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR")) /* The name of a guard variable for a reference temporary should refer to the reference, not the temporary. */ write_string (IDENTIFIER_POINTER (DECL_NAME (variable)) + 4); @@ -4477,8 +4503,7 @@ decl_tls_wrapper_p (const tree fn) if (TREE_CODE (fn) != FUNCTION_DECL) return false; tree name = DECL_NAME (fn); - return strncmp (IDENTIFIER_POINTER (name), TLS_WRAPPER_PREFIX, - strlen (TLS_WRAPPER_PREFIX)) == 0; + return startswith (IDENTIFIER_POINTER (name), TLS_WRAPPER_PREFIX); } /* Return an identifier for the name of a temporary variable used to diff --git a/gcc/cp/mapper-client.cc b/gcc/cp/mapper-client.cc index 774e2b2..b9e0216 100644 --- a/gcc/cp/mapper-client.cc +++ b/gcc/cp/mapper-client.cc @@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see #endif #define INCLUDE_STRING #define INCLUDE_VECTOR +#define INCLUDE_MAP #include "system.h" #include "line-map.h" diff --git a/gcc/cp/mapper-resolver.cc b/gcc/cp/mapper-resolver.cc index bcf6c88..db443fb 100644 --- a/gcc/cp/mapper-resolver.cc +++ b/gcc/cp/mapper-resolver.cc @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see #define INCLUDE_STRING #define INCLUDE_VECTOR #define INCLUDE_ALGORITHM +#define INCLUDE_MAP #include "system.h" // We don't want or need to be aware of networking diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 3fe3bd8..353046d 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1029,6 +1029,8 @@ is_cat (tree type, comp_cat_tag tag) static comp_cat_tag cat_tag_for (tree type) { + if (!CLASS_TYPE_P (type) || !decl_in_std_namespace_p (TYPE_MAIN_DECL (type))) + return cc_last; for (int i = 0; i < cc_last; ++i) { comp_cat_tag tag = (comp_cat_tag)i; @@ -1087,7 +1089,8 @@ genericize_spaceship (location_t loc, tree type, tree op0, tree op1) gcc_checking_assert (tag < cc_last); tree r; - if (SCALAR_TYPE_P (TREE_TYPE (op0))) + bool scalar = SCALAR_TYPE_P (TREE_TYPE (op0)); + if (scalar) { op0 = save_expr (op0); op1 = save_expr (op1); @@ -1097,26 +1100,53 @@ genericize_spaceship (location_t loc, tree type, tree op0, tree op1) int flags = LOOKUP_NORMAL; tsubst_flags_t complain = tf_none; + tree comp; if (tag == cc_partial_ordering) { /* op0 == op1 ? equivalent : op0 < op1 ? less : op1 < op0 ? greater : unordered */ tree uo = lookup_comparison_result (tag, type, 3); - tree comp = build_new_op (loc, LT_EXPR, flags, op1, op0, complain); - r = build_conditional_expr (loc, comp, gt, uo, complain); + if (scalar) + { + /* For scalars use the low level operations; using build_new_op causes + trouble with constexpr eval in the middle of genericize (100367). */ + comp = fold_build2 (LT_EXPR, boolean_type_node, op1, op0); + r = fold_build3 (COND_EXPR, type, comp, gt, uo); + } + else + { + comp = build_new_op (loc, LT_EXPR, flags, op1, op0, complain); + r = build_conditional_expr (loc, comp, gt, uo, complain); + } } else /* op0 == op1 ? equal : op0 < op1 ? less : greater */ r = gt; tree lt = lookup_comparison_result (tag, type, 2); - tree comp = build_new_op (loc, LT_EXPR, flags, op0, op1, complain); - r = build_conditional_expr (loc, comp, lt, r, complain); + if (scalar) + { + comp = fold_build2 (LT_EXPR, boolean_type_node, op0, op1); + r = fold_build3 (COND_EXPR, type, comp, lt, r); + } + else + { + comp = build_new_op (loc, LT_EXPR, flags, op0, op1, complain); + r = build_conditional_expr (loc, comp, lt, r, complain); + } tree eq = lookup_comparison_result (tag, type, 0); - comp = build_new_op (loc, EQ_EXPR, flags, op0, op1, complain); - r = build_conditional_expr (loc, comp, eq, r, complain); + if (scalar) + { + comp = fold_build2 (EQ_EXPR, boolean_type_node, op0, op1); + r = fold_build3 (COND_EXPR, type, comp, eq, r); + } + else + { + comp = build_new_op (loc, EQ_EXPR, flags, op0, op1, complain); + r = build_conditional_expr (loc, comp, eq, r, complain); + } return r; } @@ -1793,7 +1823,7 @@ build_stub_type (tree type, int quals, bool rvalue) /* Build a dummy glvalue from dereferencing a dummy reference of type REFTYPE. */ -static tree +tree build_stub_object (tree reftype) { if (!TYPE_REF_P (reftype)) @@ -2789,9 +2819,9 @@ explain_implicit_non_constexpr (tree decl) /* DECL is an instantiation of an inheriting constructor template. Deduce the correct exception-specification and deletedness for this particular - specialization. */ + specialization. Return true if the deduction succeeds; false otherwise. */ -void +bool deduce_inheriting_ctor (tree decl) { decl = DECL_ORIGIN (decl); @@ -2804,6 +2834,8 @@ deduce_inheriting_ctor (tree decl) /*diag*/false, &inh, FUNCTION_FIRST_USER_PARMTYPE (decl)); + if (spec == error_mark_node) + return false; if (TREE_CODE (inherited_ctor_binfo (decl)) != TREE_BINFO) /* Inherited the same constructor from different base subobjects. */ deleted = true; @@ -2818,6 +2850,8 @@ deduce_inheriting_ctor (tree decl) TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone), spec); SET_DECL_INHERITED_CTOR (clone, inh); } + + return true; } /* Implicitly declare the special function indicated by KIND, as a @@ -2993,9 +3027,17 @@ implicitly_declare_fn (special_function_kind kind, tree type, if (raises != error_mark_node) fn_type = build_exception_variant (fn_type, raises); else - /* Can happen, eg, in C++98 mode for an ill-formed non-static data - member initializer (c++/89914). */ - gcc_assert (seen_error ()); + { + /* Can happen, e.g., in C++98 mode for an ill-formed non-static data + member initializer (c++/89914). Also, in C++98, we might have + failed to deduce RAISES, so try again but complain this time. */ + if (cxx_dialect < cxx11) + synthesized_method_walk (type, kind, const_p, &raises, nullptr, + nullptr, nullptr, /*diag=*/true, + &inherited_ctor, inherited_parms); + /* We should have seen an error at this point. */ + gcc_assert (seen_error ()); + } } fn = build_lang_decl (FUNCTION_DECL, name, fn_type); if (kind != sfk_inheriting_constructor) @@ -3119,7 +3161,12 @@ defaulted_late_check (tree fn) /* If the function was declared constexpr, check that the definition qualifies. Otherwise we can define the function lazily. */ if (DECL_DECLARED_CONSTEXPR_P (fn) && !DECL_INITIAL (fn)) - synthesize_method (fn); + { + /* Prevent GC. */ + function_depth++; + synthesize_method (fn); + function_depth--; + } return; } @@ -3239,7 +3286,7 @@ defaultable_fn_check (tree fn) /* Avoid do_warn_unused_parameter warnings. */ for (tree p = FUNCTION_FIRST_USER_PARM (fn); p; p = DECL_CHAIN (p)) if (DECL_NAME (p)) - TREE_NO_WARNING (p) = 1; + suppress_warning (p, OPT_Wunused_parameter); if (current_class_type && TYPE_BEING_DEFINED (current_class_type)) /* Defer checking. */; diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 6dbdc92..71d0fab 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -194,8 +194,6 @@ Classes used: #define MODULE_MINOR(V) ((V) % 10000) #define EXPERIMENT(A,B) (IS_EXPERIMENTAL (MODULE_VERSION) ? (A) : (B)) #ifndef MODULE_VERSION -// Be sure you're ready! Remove #error this before release! -#error "Shtopp! What are you doing? This is not ready yet." #include "bversion.h" #define MODULE_VERSION (BUILDING_GCC_MAJOR * 10000U + BUILDING_GCC_MINOR) #elif !IS_EXPERIMENTAL (MODULE_VERSION) @@ -276,14 +274,16 @@ static inline cpp_hashnode *cpp_node (tree id) static inline tree identifier (const cpp_hashnode *node) { + /* HT_NODE() expands to node->ident that HT_IDENT_TO_GCC_IDENT() + then subtracts a nonzero constant, deriving a pointer to + a different member than ident. That's strictly undefined + and detected by -Warray-bounds. Suppress it. See PR 101372. */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" return HT_IDENT_TO_GCC_IDENT (HT_NODE (const_cast<cpp_hashnode *> (node))); +#pragma GCC diagnostic pop } -/* During duplicate detection we need to tell some comparators that - these are equivalent. */ -tree map_context_from; -tree map_context_to; - /* Id for dumping module information. */ int module_dump_id; @@ -2802,7 +2802,7 @@ static char const *const merge_kind_name[MK_hwm] = NULL, NULL, "decl spec", "decl tmpl spec", /* 20,21 decl (template). */ - "alias spec", NULL, /* 22,23 alias. */ + "alias spec", "alias tmpl spec", /* 22,23 alias (template). */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; @@ -2827,12 +2827,16 @@ struct merge_key { struct duplicate_hash : nodel_ptr_hash<tree_node> { +#if 0 + /* This breaks variadic bases in the xtreme_header tests. Since ::equal is + the default pointer_hash::equal, let's use the default hash as well. */ inline static hashval_t hash (value_type decl) { if (TREE_CODE (decl) == TREE_BINFO) decl = TYPE_NAME (BINFO_TYPE (decl)); return hashval_t (DECL_UID (decl)); } +#endif }; /* Hashmap of merged duplicates. Usually decls, but can contain @@ -3575,6 +3579,7 @@ class GTY((chain_next ("%h.parent"), for_user)) module_state { unsigned, unsigned *crc_ptr); bool read_namespaces (unsigned); + void intercluster_seed (trees_out &sec, unsigned index, depset *dep); unsigned write_cluster (elf_out *to, depset *depsets[], unsigned size, depset::hash &, unsigned *counts, unsigned *crc_ptr); bool read_cluster (unsigned snum); @@ -4149,10 +4154,17 @@ dumper::impl::nested_name (tree t) if (ti && TREE_CODE (TI_TEMPLATE (ti)) == TEMPLATE_DECL && (DECL_TEMPLATE_RESULT (TI_TEMPLATE (ti)) == t)) t = TI_TEMPLATE (ti); + tree not_tmpl = t; if (TREE_CODE (t) == TEMPLATE_DECL) - fputs ("template ", stream); + { + fputs ("template ", stream); + not_tmpl = DECL_TEMPLATE_RESULT (t); + } - if (DECL_LANG_SPECIFIC (t) && DECL_MODULE_IMPORT_P (t)) + if (not_tmpl + && DECL_P (not_tmpl) + && DECL_LANG_SPECIFIC (not_tmpl) + && DECL_MODULE_IMPORT_P (not_tmpl)) { /* We need to be careful here, so as to not explode on inconsistent data -- we're probably debugging, because @@ -4323,8 +4335,8 @@ dumper::operator () (const char *format, ...) case 'N': /* Name. */ { tree t = va_arg (args, tree); - if (t && TREE_CODE (t) == OVERLOAD) - t = OVL_FIRST (t); + while (t && TREE_CODE (t) == OVERLOAD) + t = OVL_FUNCTION (t); fputc ('\'', dumps->stream); dumps->nested_name (t); fputc ('\'', dumps->stream); @@ -4474,6 +4486,7 @@ trees_in::assert_definition (tree decl ATTRIBUTE_UNUSED, { #if CHECKING_P tree *slot = note_defs->find_slot (decl, installing ? INSERT : NO_INSERT); + tree not_tmpl = STRIP_TEMPLATE (decl); if (installing) { /* We must be inserting for the first time. */ @@ -4489,13 +4502,13 @@ trees_in::assert_definition (tree decl ATTRIBUTE_UNUSED, gcc_assert (!is_duplicate (decl) ? !slot : (slot - || !DECL_LANG_SPECIFIC (decl) - || !DECL_MODULE_PURVIEW_P (decl) - || (!DECL_MODULE_IMPORT_P (decl) + || !DECL_LANG_SPECIFIC (not_tmpl) + || !DECL_MODULE_PURVIEW_P (not_tmpl) + || (!DECL_MODULE_IMPORT_P (not_tmpl) && header_module_p ()))); - if (TREE_CODE (decl) == TEMPLATE_DECL) - gcc_assert (!note_defs->find_slot (DECL_TEMPLATE_RESULT (decl), NO_INSERT)); + if (not_tmpl != decl) + gcc_assert (!note_defs->find_slot (not_tmpl, NO_INSERT)); #endif } @@ -5204,8 +5217,7 @@ trees_out::core_bools (tree t) else if (code == VAR_DECL) { /* This is DECL_INITIALIZED_P. */ - if (DECL_CONTEXT (t) - && TREE_CODE (DECL_CONTEXT (t)) != FUNCTION_DECL) + if (TREE_CODE (DECL_CONTEXT (t)) != FUNCTION_DECL) /* We'll set this when reading the definition. */ flag_1 = false; } @@ -5517,7 +5529,9 @@ trees_out::lang_decl_bools (tree t) WB (lang->u.base.concept_p); WB (lang->u.base.var_declared_inline_p); WB (lang->u.base.dependent_init_p); - WB (lang->u.base.module_purview_p); + /* When building a header unit, everthing is marked as purview, but + that's the GM purview, so not what the importer will mean */ + WB (lang->u.base.module_purview_p && !header_module_p ()); if (VAR_OR_FUNCTION_DECL_P (t)) WB (lang->u.base.module_attached_p); switch (lang->u.base.selector) @@ -6091,9 +6105,8 @@ trees_out::core_vals (tree t) break; case STATEMENT_LIST: - for (tree_stmt_iterator iter = tsi_start (t); - !tsi_end_p (iter); tsi_next (&iter)) - if (tree stmt = tsi_stmt (iter)) + for (tree stmt : tsi_range (t)) + if (stmt) WT (stmt); WT (NULL_TREE); break; @@ -7450,11 +7463,12 @@ trees_in::install_entity (tree decl) (*entity_ary)[ident] = decl; /* And into the entity map, if it's not already there. */ - if (!DECL_LANG_SPECIFIC (decl) - || !DECL_MODULE_ENTITY_P (decl)) + tree not_tmpl = STRIP_TEMPLATE (decl); + if (!DECL_LANG_SPECIFIC (not_tmpl) + || !DECL_MODULE_ENTITY_P (not_tmpl)) { - retrofit_lang_decl (decl); - DECL_MODULE_ENTITY_P (decl) = true; + retrofit_lang_decl (not_tmpl); + DECL_MODULE_ENTITY_P (not_tmpl) = true; /* Insert into the entity hash (it cannot already be there). */ bool existed; @@ -7515,12 +7529,11 @@ trees_out::decl_value (tree decl, depset *dep) tree o = get_originating_module_decl (decl); bool is_mod = false; - if (dep && dep->is_alias_tmpl_inst ()) - /* Alias template instantiations are templatey, but - found by name. */ - is_mod = false; - else if (DECL_LANG_SPECIFIC (o) && DECL_MODULE_PURVIEW_P (o)) + tree not_tmpl = STRIP_TEMPLATE (o); + if (DECL_LANG_SPECIFIC (not_tmpl) + && DECL_MODULE_PURVIEW_P (not_tmpl)) is_mod = true; + b (is_mod); } b (dep && dep->has_defn ()); @@ -7538,26 +7551,18 @@ trees_out::decl_value (tree decl, depset *dep) int inner_tag = 0; if (TREE_CODE (decl) == TEMPLATE_DECL) { - if (dep && dep->is_alias_tmpl_inst ()) - inner = NULL_TREE; - else - { - inner = DECL_TEMPLATE_RESULT (decl); - inner_tag = insert (inner, WK_value); - } + inner = DECL_TEMPLATE_RESULT (decl); + inner_tag = insert (inner, WK_value); if (streaming_p ()) { - int code = inner ? TREE_CODE (inner) : 0; + int code = TREE_CODE (inner); u (code); - if (inner) - { - start (inner, true); - tree_node_bools (inner); - dump (dumper::TREE) - && dump ("Writing %s:%d %C:%N%S", merge_kind_name[mk], inner_tag, - TREE_CODE (inner), inner, inner); - } + start (inner, true); + tree_node_bools (inner); + dump (dumper::TREE) + && dump ("Writing %s:%d %C:%N%S", merge_kind_name[mk], inner_tag, + TREE_CODE (inner), inner, inner); } } @@ -7565,7 +7570,7 @@ trees_out::decl_value (tree decl, depset *dep) int type_tag = 0; tree stub_decl = NULL_TREE; int stub_tag = 0; - if (inner && TREE_CODE (inner) == TYPE_DECL) + if (TREE_CODE (inner) == TYPE_DECL) { type = TREE_TYPE (inner); bool has_type = (type == TYPE_MAIN_VARIANT (type) @@ -7617,7 +7622,7 @@ trees_out::decl_value (tree decl, depset *dep) unsigned tpl_levels = 0; if (decl != inner) tpl_header (decl, &tpl_levels); - if (inner && TREE_CODE (inner) == FUNCTION_DECL) + if (TREE_CODE (inner) == FUNCTION_DECL) fn_parms_init (inner); /* Now write out the merging information, and then really @@ -7629,7 +7634,7 @@ trees_out::decl_value (tree decl, depset *dep) && dump ("Wrote:%d's %s merge key %C:%N", tag, merge_kind_name[mk], TREE_CODE (decl), decl); - if (inner && TREE_CODE (inner) == FUNCTION_DECL) + if (TREE_CODE (inner) == FUNCTION_DECL) fn_parms_fini (inner); if (!is_key_order ()) @@ -7641,18 +7646,6 @@ trees_out::decl_value (tree decl, depset *dep) tree_node_vals (inner); tpl_parms_fini (decl, tpl_levels); } - else if (!inner) - { - /* A template alias instantiation. */ - inner = DECL_TEMPLATE_RESULT (decl); - if (!is_key_order ()) - tree_node (inner); - if (streaming_p ()) - dump (dumper::TREE) - && dump ("Wrote(%d) alias template %C:%N", - get_tag (inner), TREE_CODE (inner), inner); - inner = NULL_TREE; - } if (type && !is_key_order ()) { @@ -7698,8 +7691,7 @@ trees_out::decl_value (tree decl, depset *dep) install_entity (decl, dep); } - if (inner - && VAR_OR_FUNCTION_DECL_P (inner) + if (VAR_OR_FUNCTION_DECL_P (inner) && DECL_LANG_SPECIFIC (inner) && DECL_MODULE_ATTACHMENTS_P (inner) && !is_key_order ()) @@ -7720,7 +7712,7 @@ trees_out::decl_value (tree decl, depset *dep) } bool is_typedef = false; - if (!type && inner && TREE_CODE (inner) == TYPE_DECL) + if (!type && TREE_CODE (inner) == TYPE_DECL) { tree t = TREE_TYPE (inner); unsigned tdef_flags = 0; @@ -7771,10 +7763,9 @@ trees_out::decl_value (tree decl, depset *dep) dump (dumper::TREE) && dump ("Written decl:%d %C:%N", tag, TREE_CODE (decl), decl); - if (!inner || NAMESPACE_SCOPE_P (inner)) - gcc_checking_assert (!inner - || !dep == (VAR_OR_FUNCTION_DECL_P (inner) - && DECL_LOCAL_DECL_P (inner))); + if (NAMESPACE_SCOPE_P (inner)) + gcc_checking_assert (!dep == (VAR_OR_FUNCTION_DECL_P (inner) + && DECL_LOCAL_DECL_P (inner))); else if ((TREE_CODE (inner) == TYPE_DECL && !is_typedef && TYPE_NAME (TREE_TYPE (inner)) == inner) @@ -7833,31 +7824,23 @@ trees_in::decl_value () if (decl && TREE_CODE (decl) == TEMPLATE_DECL) { int code = u (); - if (!code) - { - inner = NULL_TREE; - DECL_TEMPLATE_RESULT (decl) = error_mark_node; - } + inner = start (code); + if (inner && tree_node_bools (inner)) + DECL_TEMPLATE_RESULT (decl) = inner; else - { - inner = start (code); - if (inner && tree_node_bools (inner)) - DECL_TEMPLATE_RESULT (decl) = inner; - else - decl = NULL_TREE; + decl = NULL_TREE; - inner_tag = insert (inner); - if (decl) - dump (dumper::TREE) - && dump ("Reading:%d %C", inner_tag, TREE_CODE (inner)); - } + inner_tag = insert (inner); + if (decl) + dump (dumper::TREE) + && dump ("Reading:%d %C", inner_tag, TREE_CODE (inner)); } tree type = NULL_TREE; int type_tag = 0; tree stub_decl = NULL_TREE; int stub_tag = 0; - if (decl && inner && TREE_CODE (inner) == TYPE_DECL) + if (decl && TREE_CODE (inner) == TYPE_DECL) { if (unsigned type_code = u ()) { @@ -7922,7 +7905,7 @@ trees_in::decl_value () if (decl != inner) if (!tpl_header (decl, &tpl_levels)) goto bail; - if (inner && TREE_CODE (inner) == FUNCTION_DECL) + if (TREE_CODE (inner) == FUNCTION_DECL) parm_tag = fn_parms_init (inner); tree existing = key_mergeable (tag, mk, decl, inner, type, container, is_mod); @@ -7977,15 +7960,6 @@ trees_in::decl_value () if (!tpl_parms_fini (decl, tpl_levels)) goto bail; } - else if (!inner) - { - inner = tree_node (); - DECL_TEMPLATE_RESULT (decl) = inner; - TREE_TYPE (decl) = TREE_TYPE (inner); - dump (dumper::TREE) - && dump ("Read alias template %C:%N", TREE_CODE (inner), inner); - inner = NULL_TREE; - } if (type && (!tree_node_vals (type) || (stub_decl && !tree_node_vals (stub_decl)))) @@ -8014,8 +7988,7 @@ trees_in::decl_value () bool installed = install_entity (existing); bool is_new = existing == decl; - if (inner - && VAR_OR_FUNCTION_DECL_P (inner) + if (VAR_OR_FUNCTION_DECL_P (inner) && DECL_LANG_SPECIFIC (inner) && DECL_MODULE_ATTACHMENTS_P (inner)) { @@ -8044,7 +8017,7 @@ trees_in::decl_value () /* Regular typedefs will have a NULL TREE_TYPE at this point. */ unsigned tdef_flags = 0; bool is_typedef = false; - if (!type && inner && TREE_CODE (inner) == TYPE_DECL) + if (!type && TREE_CODE (inner) == TYPE_DECL) { tdef_flags = u (); if (tdef_flags & 1) @@ -8061,29 +8034,13 @@ trees_in::decl_value () if (installed) { - /* Mark the entity as imported and add it to the entity - array and map. */ - retrofit_lang_decl (decl); - DECL_MODULE_IMPORT_P (decl) = true; - if (inner_tag) - { - retrofit_lang_decl (inner); - DECL_MODULE_IMPORT_P (inner) = true; - } + /* Mark the entity as imported. */ + retrofit_lang_decl (inner); + DECL_MODULE_IMPORT_P (inner) = true; } if (spec.spec) set_constraints (decl, spec.spec); - if (mk & MK_template_mask - || mk == MK_partial) - { - /* Add to specialization tables now that constraints etc are - added. */ - bool is_type = mk == MK_partial || !(mk & MK_tmpl_decl_mask); - - spec.spec = is_type ? type : mk & MK_tmpl_tmpl_mask ? inner : decl; - add_mergeable_specialization (!is_type, &spec, decl, spec_flags); - } if (TREE_CODE (decl) == INTEGER_CST && !TREE_OVERFLOW (decl)) { @@ -8111,28 +8068,25 @@ trees_in::decl_value () /* Set the TEMPLATE_DECL's type. */ TREE_TYPE (decl) = TREE_TYPE (inner); + if (mk & MK_template_mask + || mk == MK_partial) + { + /* Add to specialization tables now that constraints etc are + added. */ + bool is_type = mk == MK_partial || !(mk & MK_tmpl_decl_mask); + + spec.spec = is_type ? type : mk & MK_tmpl_tmpl_mask ? inner : decl; + add_mergeable_specialization (!is_type, + !is_type && mk & MK_tmpl_alias_mask, + &spec, decl, spec_flags); + } + if (NAMESPACE_SCOPE_P (decl) && (mk == MK_named || mk == MK_unique || mk == MK_enum || mk == MK_friend_spec) && !(VAR_OR_FUNCTION_DECL_P (decl) && DECL_LOCAL_DECL_P (decl))) add_module_namespace_decl (CP_DECL_CONTEXT (decl), decl); - /* The late insertion of an alias here or an implicit member - (next block), is ok, because we ensured that all imports were - loaded up before we started this cluster. Thus an insertion - from some other import cannot have happened between the - merged insertion above and these insertions down here. */ - if (mk == MK_alias_spec) - { - /* Insert into type table. */ - tree ti = DECL_TEMPLATE_INFO (inner); - spec_entry elt = - {TI_TEMPLATE (ti), TI_ARGS (ti), TREE_TYPE (inner)}; - tree texist = match_mergeable_specialization (false, &elt); - if (texist) - set_overrun (); - } - if (DECL_ARTIFICIAL (decl) && TREE_CODE (decl) == FUNCTION_DECL && !DECL_TEMPLATE_INFO (decl) @@ -8176,6 +8130,14 @@ trees_in::decl_value () if (!is_matching_decl (existing, decl, is_typedef)) unmatched_duplicate (existing); + if (TREE_CODE (inner) == FUNCTION_DECL) + { + tree e_inner = STRIP_TEMPLATE (existing); + for (auto parm = DECL_ARGUMENTS (inner); + parm; parm = DECL_CHAIN (parm)) + DECL_CONTEXT (parm) = e_inner; + } + /* And our result is the existing node. */ decl = existing; } @@ -8186,7 +8148,7 @@ trees_in::decl_value () if (!e) { spec.spec = inner; - add_mergeable_specialization (true, &spec, decl, spec_flags); + add_mergeable_specialization (true, false, &spec, decl, spec_flags); } else if (e != existing) set_overrun (); @@ -8221,8 +8183,7 @@ trees_in::decl_value () } } - if (inner - && !NAMESPACE_SCOPE_P (inner) + if (!NAMESPACE_SCOPE_P (inner) && ((TREE_CODE (inner) == TYPE_DECL && !is_typedef && TYPE_NAME (TREE_TYPE (inner)) == inner) @@ -8560,7 +8521,8 @@ trees_out::decl_node (tree decl, walk_kind ref) else if (TREE_CODE (ctx) != FUNCTION_DECL || TREE_CODE (decl) == TEMPLATE_DECL || (dep_hash->sneakoscope && DECL_IMPLICIT_TYPEDEF_P (decl)) - || (DECL_LANG_SPECIFIC (decl) && DECL_MODULE_IMPORT_P (decl))) + || (DECL_LANG_SPECIFIC (decl) + && DECL_MODULE_IMPORT_P (decl))) { auto kind = (TREE_CODE (decl) == NAMESPACE_DECL && !DECL_NAMESPACE_ALIAS (decl) @@ -8598,8 +8560,7 @@ trees_out::decl_node (tree decl, walk_kind ref) gcc_checking_assert (index == ~import_entity_index (decl)); #if CHECKING_P - if (importedness) - gcc_assert (!import == (importedness < 0)); + gcc_assert (!import || importedness >= 0); #endif i (tt_entity); u (import); @@ -8617,6 +8578,7 @@ trees_out::decl_node (tree decl, walk_kind ref) else { tree o = get_originating_module_decl (decl); + o = STRIP_TEMPLATE (o); kind = (DECL_LANG_SPECIFIC (o) && DECL_MODULE_PURVIEW_P (o) ? "purview" : "GMF"); } @@ -8957,7 +8919,7 @@ trees_in::tree_value () dump (dumper::MERGE) && dump ("Deduping binfo %N[%u]", type, ix); existing = TYPE_BINFO (type); - while (existing && ix) + while (existing && ix--) existing = TREE_CHAIN (existing); if (existing) register_duplicate (t, existing); @@ -10378,9 +10340,10 @@ trees_out::key_mergeable (int tag, merge_kind mk, tree decl, tree inner, { if (mk & MK_tmpl_alias_mask) /* It should be in both tables. */ - gcc_assert (match_mergeable_specialization (false, entry) - == TREE_TYPE (existing)); - else if (mk & MK_tmpl_tmpl_mask) + gcc_checking_assert + (same_type_p (match_mergeable_specialization (false, entry), + TREE_TYPE (existing))); + if (mk & MK_tmpl_tmpl_mask) existing = DECL_TI_TEMPLATE (existing); } else @@ -10392,7 +10355,10 @@ trees_out::key_mergeable (int tag, merge_kind mk, tree decl, tree inner, } /* The walkabout should have found ourselves. */ - gcc_assert (existing == decl); + gcc_checking_assert (TREE_CODE (decl) == TYPE_DECL + ? same_type_p (TREE_TYPE (decl), + TREE_TYPE (existing)) + : existing == decl); } } else if (mk != MK_unique) @@ -10410,7 +10376,7 @@ trees_out::key_mergeable (int tag, merge_kind mk, tree decl, tree inner, if (IDENTIFIER_CONV_OP_P (name)) name = conv_op_identifier; - if (inner && TREE_CODE (inner) == FUNCTION_DECL) + if (TREE_CODE (inner) == FUNCTION_DECL) { /* Functions are distinguished by parameter types. */ tree fn_type = TREE_TYPE (inner); @@ -10622,8 +10588,6 @@ check_mergeable_decl (merge_kind mk, tree decl, tree ovl, merge_key const &key) break; case FUNCTION_DECL: - map_context_from = d_inner; - map_context_to = m_inner; if (tree m_type = TREE_TYPE (m_inner)) if ((!key.ret || same_type_p (key.ret, fndecl_declared_return_type (m_inner))) @@ -10647,7 +10611,6 @@ check_mergeable_decl (merge_kind mk, tree decl, tree ovl, merge_key const &key) if (cp_tree_equal (key.constraints, m_reqs)) found = match; } - map_context_from = map_context_to = NULL_TREE; break; case TYPE_DECL: @@ -10749,7 +10712,7 @@ trees_in::key_mergeable (int tag, merge_kind mk, tree decl, tree inner, key.ret = tree_node (); else if (mk == MK_partial || ((mk == MK_named || mk == MK_friend_spec) - && inner && TREE_CODE (inner) == FUNCTION_DECL)) + && TREE_CODE (inner) == FUNCTION_DECL)) { key.ret = tree_node (); tree arg, *arg_ptr = &key.args; @@ -10772,11 +10735,8 @@ trees_in::key_mergeable (int tag, merge_kind mk, tree decl, tree inner, DECL_NAME (decl) = name; DECL_CONTEXT (decl) = FROB_CONTEXT (container); } - if (inner) - { - DECL_NAME (inner) = DECL_NAME (decl); - DECL_CONTEXT (inner) = DECL_CONTEXT (decl); - } + DECL_NAME (inner) = DECL_NAME (decl); + DECL_CONTEXT (inner) = DECL_CONTEXT (decl); if (mk == MK_partial) { @@ -11022,12 +10982,6 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef) gcc_checking_assert (TREE_CODE (e_inner) == TREE_CODE (d_inner)); } - gcc_checking_assert (!map_context_from); - /* This mapping requres the new decl on the lhs and the existing - entity on the rhs of the comparitors below. */ - map_context_from = d_inner; - map_context_to = e_inner; - if (TREE_CODE (d_inner) == FUNCTION_DECL) { tree e_ret = fndecl_declared_return_type (existing); @@ -11104,7 +11058,6 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef) else if (!cp_tree_equal (TREE_TYPE (decl), TREE_TYPE (existing))) { mismatch: - map_context_from = map_context_to = NULL_TREE; if (DECL_IS_UNDECLARED_BUILTIN (existing)) /* Just like duplicate_decls, presum the user knows what they're doing in overriding a builtin. */ @@ -11121,8 +11074,6 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef) } } - map_context_from = map_context_to = NULL_TREE; - if (DECL_IS_UNDECLARED_BUILTIN (existing) && !DECL_IS_UNDECLARED_BUILTIN (decl)) { @@ -11364,7 +11315,7 @@ trees_in::register_duplicate (tree decl, tree existing) /* We've read a definition of MAYBE_EXISTING. If not a duplicate, return MAYBE_EXISTING (into which the definition should be installed). Otherwise return NULL if already known bad, or the - duplicate we read (for ODR checking, or extracting addtional merge + duplicate we read (for ODR checking, or extracting additional merge information). */ tree @@ -11463,10 +11414,6 @@ trees_in::read_function_def (tree decl, tree maybe_template) tree maybe_dup = odr_duplicate (maybe_template, DECL_SAVED_TREE (decl)); bool installing = maybe_dup && !DECL_SAVED_TREE (decl); - if (maybe_dup) - for (auto parm = DECL_ARGUMENTS (maybe_dup); parm; parm = DECL_CHAIN (parm)) - DECL_CONTEXT (parm) = decl; - if (int wtag = i ()) { int tag = 1; @@ -11579,7 +11526,11 @@ trees_in::read_var_def (tree decl, tree maybe_template) if (DECL_EXTERNAL (decl)) DECL_NOT_REALLY_EXTERN (decl) = true; if (VAR_P (decl)) - DECL_INITIALIZED_P (decl) = true; + { + DECL_INITIALIZED_P (decl) = true; + if (maybe_dup && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (maybe_dup)) + DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true; + } DECL_INITIAL (decl) = init; if (!dyn_init) ; @@ -11908,8 +11859,9 @@ trees_in::read_class_def (tree defn, tree maybe_template) { CLASSTYPE_BEFRIENDING_CLASSES (type_dup) = CLASSTYPE_BEFRIENDING_CLASSES (type); - CLASSTYPE_TYPEINFO_VAR (type_dup) - = CLASSTYPE_TYPEINFO_VAR (type); + if (!ANON_AGGR_TYPE_P (type)) + CLASSTYPE_TYPEINFO_VAR (type_dup) + = CLASSTYPE_TYPEINFO_VAR (type); } for (tree v = type; v; v = TYPE_NEXT_VARIANT (v)) TYPE_LANG_SPECIFIC (v) = ls; @@ -11940,6 +11892,11 @@ trees_in::read_class_def (tree defn, tree maybe_template) *chain = decl; chain = &DECL_CHAIN (decl); + if (TREE_CODE (decl) == FIELD_DECL + && ANON_AGGR_TYPE_P (TREE_TYPE (decl))) + ANON_AGGR_TYPE_FIELD + (TYPE_MAIN_VARIANT (TREE_TYPE (decl))) = decl; + if (TREE_CODE (decl) == USING_DECL && TREE_CODE (USING_DECL_SCOPE (decl)) == RECORD_TYPE) { @@ -12408,20 +12365,9 @@ depset::hash::make_dependency (tree decl, entity_kind ek) gcc_checking_assert (TREE_CODE (decl) == OVERLOAD); if (TREE_CODE (decl) == TEMPLATE_DECL) - { - /* The template should have copied these from its result decl. */ - tree res = DECL_TEMPLATE_RESULT (decl); - - gcc_checking_assert (DECL_MODULE_EXPORT_P (decl) - == DECL_MODULE_EXPORT_P (res)); - if (DECL_LANG_SPECIFIC (res)) - { - gcc_checking_assert (DECL_MODULE_PURVIEW_P (decl) - == DECL_MODULE_PURVIEW_P (res)); - gcc_checking_assert ((DECL_MODULE_IMPORT_P (decl) - == DECL_MODULE_IMPORT_P (res))); - } - } + /* The template should have copied these from its result decl. */ + gcc_checking_assert (DECL_MODULE_EXPORT_P (decl) + == DECL_MODULE_EXPORT_P (DECL_TEMPLATE_RESULT (decl))); depset **slot = entity_slot (decl, true); depset *dep = *slot; @@ -12498,46 +12444,48 @@ depset::hash::make_dependency (tree decl, entity_kind ek) && !(*eslot)->deps.length ()); } - if (ek != EK_USING - && DECL_LANG_SPECIFIC (decl) - && DECL_MODULE_IMPORT_P (decl)) + if (ek != EK_USING) { - /* Store the module number and index in cluster/section, so - we don't have to look them up again. */ - unsigned index = import_entity_index (decl); - module_state *from = import_entity_module (index); - /* Remap will be zero for imports from partitions, which we - want to treat as-if declared in this TU. */ - if (from->remap) + tree not_tmpl = STRIP_TEMPLATE (decl); + + if (DECL_LANG_SPECIFIC (not_tmpl) + && DECL_MODULE_IMPORT_P (not_tmpl)) { - dep->cluster = index - from->entity_lwm; - dep->section = from->remap; - dep->set_flag_bit<DB_IMPORTED_BIT> (); + /* Store the module number and index in cluster/section, + so we don't have to look them up again. */ + unsigned index = import_entity_index (decl); + module_state *from = import_entity_module (index); + /* Remap will be zero for imports from partitions, which + we want to treat as-if declared in this TU. */ + if (from->remap) + { + dep->cluster = index - from->entity_lwm; + dep->section = from->remap; + dep->set_flag_bit<DB_IMPORTED_BIT> (); + } } - } - if (ek == EK_DECL - && !dep->is_import () - && TREE_CODE (CP_DECL_CONTEXT (decl)) == NAMESPACE_DECL - && !(TREE_CODE (decl) == TEMPLATE_DECL - && DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (decl))) - { - tree ctx = CP_DECL_CONTEXT (decl); - tree not_tmpl = STRIP_TEMPLATE (decl); - - if (!TREE_PUBLIC (ctx)) - /* Member of internal namespace. */ - dep->set_flag_bit<DB_IS_INTERNAL_BIT> (); - else if (VAR_OR_FUNCTION_DECL_P (not_tmpl) - && DECL_THIS_STATIC (not_tmpl)) + if (ek == EK_DECL + && !dep->is_import () + && TREE_CODE (CP_DECL_CONTEXT (decl)) == NAMESPACE_DECL + && !(TREE_CODE (decl) == TEMPLATE_DECL + && DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (decl))) { - /* An internal decl. This is ok in a GM entity. */ - if (!(header_module_p () - || !DECL_LANG_SPECIFIC (not_tmpl) - || !DECL_MODULE_PURVIEW_P (not_tmpl))) + tree ctx = CP_DECL_CONTEXT (decl); + + if (!TREE_PUBLIC (ctx)) + /* Member of internal namespace. */ dep->set_flag_bit<DB_IS_INTERNAL_BIT> (); + else if (VAR_OR_FUNCTION_DECL_P (not_tmpl) + && DECL_THIS_STATIC (not_tmpl)) + { + /* An internal decl. This is ok in a GM entity. */ + if (!(header_module_p () + || !DECL_LANG_SPECIFIC (not_tmpl) + || !DECL_MODULE_PURVIEW_P (not_tmpl))) + dep->set_flag_bit<DB_IS_INTERNAL_BIT> (); + } } - } if (!dep->is_import ()) @@ -12881,10 +12829,11 @@ specialization_add (bool decl_p, spec_entry *entry, void *data_) || DECL_CLASS_TEMPLATE_P (entry->tmpl)); /* Only alias templates can appear in both tables (and - if they're in the type table they must also be in the decl table). */ + if they're in the type table they must also be in the decl + table). */ gcc_checking_assert (!match_mergeable_specialization (true, entry) - == (decl_p || !DECL_ALIAS_TEMPLATE_P (entry->tmpl))); + == !DECL_ALIAS_TEMPLATE_P (entry->tmpl)); } else if (VAR_OR_FUNCTION_DECL_P (entry->spec)) gcc_checking_assert (!DECL_LOCAL_DECL_P (entry->spec)); @@ -13774,7 +13723,7 @@ ordinary_loc_of (line_maps *lmaps, location_t from) { if (IS_ADHOC_LOC (from)) from = get_location_from_adhoc_loc (lmaps, from); - if (IS_MACRO_LOC (from)) + if (from >= LINEMAPS_MACRO_LOWEST_LOCATION (lmaps)) { /* Find the ordinary location nearest FROM. */ const line_map *map = linemap_lookup (lmaps, from); @@ -14487,7 +14436,33 @@ enum ct_bind_flags cbf_wrapped = 0x8, /* ... that is wrapped. */ }; -/* Write the cluster of depsets in SCC[0-SIZE). */ +/* DEP belongs to a different cluster, seed it to prevent + unfortunately timed duplicate import. */ +// FIXME: QOI For inter-cluster references we could just only pick +// one entity from an earlier cluster. Even better track +// dependencies between earlier clusters + +void +module_state::intercluster_seed (trees_out &sec, unsigned index_hwm, depset *dep) +{ + if (dep->is_import () + || dep->cluster < index_hwm) + { + tree ent = dep->get_entity (); + if (!TREE_VISITED (ent)) + { + sec.tree_node (ent); + dump (dumper::CLUSTER) + && dump ("Seeded %s %N", + dep->is_import () ? "import" : "intercluster", ent); + } + } +} + +/* Write the cluster of depsets in SCC[0-SIZE). + dep->section -> section number + dep->cluster -> entity number + */ unsigned module_state::write_cluster (elf_out *to, depset *scc[], unsigned size, @@ -14499,6 +14474,7 @@ module_state::write_cluster (elf_out *to, depset *scc[], unsigned size, trees_out sec (to, this, table, table.section); sec.begin (); + unsigned index_lwm = counts[MSC_entities]; /* Determine entity numbers, mark for writing. */ dump (dumper::CLUSTER) && dump ("Cluster members:") && (dump.indent (), true); @@ -14552,10 +14528,10 @@ module_state::write_cluster (elf_out *to, depset *scc[], unsigned size, } dump (dumper::CLUSTER) && (dump.outdent (), true); - /* Ensure every imported decl is referenced before we start - streaming. This ensures that we never encounter the situation - where this cluster instantiates some implicit member that - importing some other decl causes to be instantiated. */ + /* Ensure every out-of-cluster decl is referenced before we start + streaming. We must do both imports *and* earlier clusters, + because the latter could reach into the former and cause a + duplicate loop. */ sec.set_importing (+1); for (unsigned ix = 0; ix != size; ix++) { @@ -14573,30 +14549,14 @@ module_state::write_cluster (elf_out *to, depset *scc[], unsigned size, depset *bind = dep->deps[ix]; if (bind->get_entity_kind () == depset::EK_USING) bind = bind->deps[1]; - if (bind->is_import ()) - { - tree import = bind->get_entity (); - if (!TREE_VISITED (import)) - { - sec.tree_node (import); - dump (dumper::CLUSTER) - && dump ("Seeded import %N", import); - } - } + + intercluster_seed (sec, index_lwm, bind); } /* Also check the namespace itself. */ dep = dep->deps[0]; } - if (dep->is_import ()) - { - tree import = dep->get_entity (); - if (!TREE_VISITED (import)) - { - sec.tree_node (import); - dump (dumper::CLUSTER) && dump ("Seeded import %N", import); - } - } + intercluster_seed (sec, index_lwm, dep); } } sec.tree_node (NULL_TREE); @@ -15608,7 +15568,7 @@ module_state::write_location (bytes_out &sec, location_t loc) write_location (sec, range.m_start); write_location (sec, range.m_finish); } - else if (IS_MACRO_LOC (loc)) + else if (loc >= LINEMAPS_MACRO_LOWEST_LOCATION (line_table)) { if (const loc_spans::span *span = spans.macro (loc)) { @@ -18023,7 +17983,7 @@ module_state::read_language (bool outermost) function_depth++; /* Prevent unexpected GCs. */ - if (counts[MSC_entities] != entity_num) + if (ok && counts[MSC_entities] != entity_num) ok = false; if (ok && counts[MSC_entities] && !read_entities (counts[MSC_entities], @@ -18413,15 +18373,16 @@ int get_originating_module (tree decl, bool for_mangle) { tree owner = get_originating_module_decl (decl); + tree not_tmpl = STRIP_TEMPLATE (owner); - if (!DECL_LANG_SPECIFIC (owner)) + if (!DECL_LANG_SPECIFIC (not_tmpl)) return for_mangle ? -1 : 0; if (for_mangle - && (DECL_MODULE_EXPORT_P (owner) || !DECL_MODULE_PURVIEW_P (owner))) + && (DECL_MODULE_EXPORT_P (owner) || !DECL_MODULE_PURVIEW_P (not_tmpl))) return -1; - if (!DECL_MODULE_IMPORT_P (owner)) + if (!DECL_MODULE_IMPORT_P (not_tmpl)) return 0; return get_importing_module (owner); @@ -18445,7 +18406,8 @@ module_may_redeclare (tree decl) { module_state *me = (*modules)[0]; module_state *them = me; - if (DECL_LANG_SPECIFIC (decl) && DECL_MODULE_IMPORT_P (decl)) + tree not_tmpl = STRIP_TEMPLATE (decl); + if (DECL_LANG_SPECIFIC (not_tmpl) && DECL_MODULE_IMPORT_P (not_tmpl)) { /* We can be given the TEMPLATE_RESULT. We want the TEMPLATE_DECL. */ @@ -18453,13 +18415,20 @@ module_may_redeclare (tree decl) if (tree ti = node_template_info (decl, use_tpl)) { tree tmpl = TI_TEMPLATE (ti); - if (DECL_TEMPLATE_RESULT (tmpl) == decl) + if (use_tpl == 2) + { + /* A partial specialization. Find that specialization's + template_decl. */ + for (tree list = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); + list; list = TREE_CHAIN (list)) + if (DECL_TEMPLATE_RESULT (TREE_VALUE (list)) == decl) + { + decl = TREE_VALUE (list); + break; + } + } + else if (DECL_TEMPLATE_RESULT (tmpl) == decl) decl = tmpl; - // FIXME: What about partial specializations? We need to - // look at the specialization list in that case. Unless our - // caller's given us the right thing. An alternative would - // be to put both the template and the result into the - // entity hash, but that seems expensive? } unsigned index = import_entity_index (decl); them = import_entity_module (index); @@ -18480,15 +18449,15 @@ module_may_redeclare (tree decl) } if (me == them) - return ((DECL_LANG_SPECIFIC (decl) && DECL_MODULE_PURVIEW_P (decl)) + return ((DECL_LANG_SPECIFIC (not_tmpl) && DECL_MODULE_PURVIEW_P (not_tmpl)) == module_purview_p ()); if (!me->name) me = me->parent; /* We can't have found a GMF entity from a named module. */ - gcc_checking_assert (DECL_LANG_SPECIFIC (decl) - && DECL_MODULE_PURVIEW_P (decl)); + gcc_checking_assert (DECL_LANG_SPECIFIC (not_tmpl) + && DECL_MODULE_PURVIEW_P (not_tmpl)); return me && get_primary (them) == get_primary (me); } @@ -18512,20 +18481,16 @@ set_instantiating_module (tree decl) if (!modules_p ()) return; + decl = STRIP_TEMPLATE (decl); + if (!DECL_LANG_SPECIFIC (decl) && module_purview_p ()) retrofit_lang_decl (decl); + if (DECL_LANG_SPECIFIC (decl)) { DECL_MODULE_PURVIEW_P (decl) = module_purview_p (); /* If this was imported, we'll still be in the entity_hash. */ DECL_MODULE_IMPORT_P (decl) = false; - if (TREE_CODE (decl) == TEMPLATE_DECL) - { - tree res = DECL_TEMPLATE_RESULT (decl); - retrofit_lang_decl (res); - DECL_MODULE_PURVIEW_P (res) = DECL_MODULE_PURVIEW_P (decl); - DECL_MODULE_IMPORT_P (res) = false; - } } } @@ -18559,7 +18524,6 @@ set_defining_module (tree decl) gcc_checking_assert (!use_tpl); /* Get to the TEMPLATE_DECL. */ decl = TI_TEMPLATE (ti); - gcc_checking_assert (!DECL_MODULE_IMPORT_P (decl)); } /* Record it on the class_members list. */ @@ -19312,15 +19276,11 @@ module_begin_main_file (cpp_reader *reader, line_maps *lmaps, filenames. */ static void -name_pending_imports (cpp_reader *reader, bool at_end) +name_pending_imports (cpp_reader *reader) { auto *mapper = get_mapper (cpp_main_loc (reader)); - bool only_headers = (flag_preprocess_only - && !bool (mapper->get_flags () & Cody::Flags::NameOnly) - && !cpp_get_deps (reader)); - if (at_end - && (!vec_safe_length (pending_imports) || only_headers)) + if (!vec_safe_length (pending_imports)) /* Not doing anything. */ return; @@ -19328,40 +19288,56 @@ name_pending_imports (cpp_reader *reader, bool at_end) auto n = dump.push (NULL); dump () && dump ("Resolving direct import names"); + bool want_deps = (bool (mapper->get_flags () & Cody::Flags::NameOnly) + || cpp_get_deps (reader)); + bool any = false; - mapper->Cork (); for (unsigned ix = 0; ix != pending_imports->length (); ix++) { module_state *module = (*pending_imports)[ix]; gcc_checking_assert (module->is_direct ()); - if (!module->filename - && !module->visited_p - && (module->is_header () || !only_headers)) + if (!module->filename && !module->visited_p) { - module->visited_p = true; - Cody::Flags flags = (flag_preprocess_only - ? Cody::Flags::None : Cody::Flags::NameOnly); + bool export_p = (module->module_p + && (module->is_partition () || module->exported_p)); - if (module->module_p - && (module->is_partition () || module->exported_p)) + Cody::Flags flags = Cody::Flags::None; + if (flag_preprocess_only + && !(module->is_header () && !export_p)) + { + if (!want_deps) + continue; + flags = Cody::Flags::NameOnly; + } + + if (!any) + { + any = true; + mapper->Cork (); + } + if (export_p) mapper->ModuleExport (module->get_flatname (), flags); else mapper->ModuleImport (module->get_flatname (), flags); + module->visited_p = true; } } - - auto response = mapper->Uncork (); - auto r_iter = response.begin (); - for (unsigned ix = 0; ix != pending_imports->length (); ix++) + + if (any) { - module_state *module = (*pending_imports)[ix]; - if (module->visited_p) + auto response = mapper->Uncork (); + auto r_iter = response.begin (); + for (unsigned ix = 0; ix != pending_imports->length (); ix++) { - module->visited_p = false; - gcc_checking_assert (!module->filename); + module_state *module = (*pending_imports)[ix]; + if (module->visited_p) + { + module->visited_p = false; + gcc_checking_assert (!module->filename); - module->set_filename (*r_iter); - ++r_iter; + module->set_filename (*r_iter); + ++r_iter; + } } } @@ -19434,7 +19410,7 @@ preprocess_module (module_state *module, location_t from_loc, unsigned n = dump.push (NULL); dump () && dump ("Reading %M preprocessor state", module); - name_pending_imports (reader, false); + name_pending_imports (reader); /* Preserve the state of the line-map. */ unsigned pre_hwm = LINEMAPS_ORDINARY_USED (line_table); @@ -19496,7 +19472,7 @@ preprocessed_module (cpp_reader *reader) dump () && dump ("Completed phase-4 (tokenization) processing"); - name_pending_imports (reader, true); + name_pending_imports (reader); vec_free (pending_imports); spans.maybe_init (); @@ -20009,7 +19985,7 @@ fini_modules () modules_hash = NULL; /* Or entity array. We still need the entity map to find import numbers. */ - delete entity_ary; + vec_free (entity_ary); entity_ary = NULL; /* Or remember any pending entities. */ diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index a6257f5..8e9c61e 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -1666,8 +1666,9 @@ name_lookup::search_adl (tree fns, vec<tree, va_gc> *args) continue; tree origin = get_originating_module_decl (TYPE_NAME (scope)); - if (!DECL_LANG_SPECIFIC (origin) - || !DECL_MODULE_IMPORT_P (origin)) + tree not_tmpl = STRIP_TEMPLATE (origin); + if (!DECL_LANG_SPECIFIC (not_tmpl) + || !DECL_MODULE_IMPORT_P (not_tmpl)) /* Not imported. */ continue; @@ -3528,6 +3529,7 @@ static tree check_module_override (tree decl, tree mvec, bool hiding, tree scope, tree name) { + tree match = NULL_TREE; bitmap imports = get_import_bitmap (); binding_cluster *cluster = BINDING_VECTOR_CLUSTER_BASE (mvec); unsigned ix = BINDING_VECTOR_NUM_CLUSTERS (mvec); @@ -3566,13 +3568,15 @@ check_module_override (tree decl, tree mvec, bool hiding, bind = STAT_VISIBLE (bind); for (ovl_iterator iter (bind); iter; ++iter) - if (iter.using_p ()) - ; - else if (tree match = duplicate_decls (decl, *iter, hiding)) - return match; + if (!iter.using_p ()) + { + match = duplicate_decls (decl, *iter, hiding); + if (match) + goto matched; + } } - if (TREE_PUBLIC (scope) && TREE_PUBLIC (decl) && !not_module_p () + if (TREE_PUBLIC (scope) && TREE_PUBLIC (STRIP_TEMPLATE (decl)) /* Namespaces are dealt with specially in make_namespace_finish. */ && !(TREE_CODE (decl) == NAMESPACE_DECL && !DECL_NAMESPACE_ALIAS (decl))) @@ -3588,14 +3592,26 @@ check_module_override (tree decl, tree mvec, bool hiding, for (ovl_iterator iter (mergeable); iter; ++iter) { - tree match = *iter; - - if (duplicate_decls (decl, match, hiding)) - return match; + match = duplicate_decls (decl, *iter, hiding); + if (match) + goto matched; } } return NULL_TREE; + + matched: + if (match != error_mark_node) + { + if (named_module_p ()) + BINDING_VECTOR_PARTITION_DUPS_P (mvec) = true; + else + BINDING_VECTOR_GLOBAL_DUPS_P (mvec) = true; + } + + return match; + + } /* Record DECL as belonging to the current lexical scope. Check for @@ -3665,6 +3681,7 @@ do_pushdecl (tree decl, bool hiding) if (iter.using_p ()) ; /* Ignore using decls here. */ else if (iter.hidden_p () + && TREE_CODE (*iter) == FUNCTION_DECL && DECL_LANG_SPECIFIC (*iter) && DECL_MODULE_IMPORT_P (*iter)) ; /* An undeclared builtin imported from elsewhere. */ @@ -5219,7 +5236,7 @@ set_inherited_value_binding_p (cxx_binding *binding, tree decl, { tree context; - if (TREE_CODE (decl) == OVERLOAD) + if (is_overloaded_fn (decl)) context = ovl_scope (decl); else { @@ -5321,28 +5338,6 @@ get_class_binding (tree name, cp_binding_level *scope) /*protect=*/2, /*want_type=*/false, tf_warning_or_error); - if (value_binding - && (TREE_CODE (value_binding) == TYPE_DECL - || DECL_CLASS_TEMPLATE_P (value_binding) - || (TREE_CODE (value_binding) == TREE_LIST - && TREE_TYPE (value_binding) == error_mark_node - && (TREE_CODE (TREE_VALUE (value_binding)) - == TYPE_DECL)))) - /* We found a type binding, even when looking for a non-type - binding. This means that we already processed this binding - above. */ - ; - else if (value_binding) - { - if (TREE_CODE (value_binding) == TREE_LIST - && TREE_TYPE (value_binding) == error_mark_node) - /* NAME is ambiguous. */ - ; - else if (BASELINK_P (value_binding)) - /* NAME is some overloaded functions. */ - value_binding = BASELINK_FUNCTIONS (value_binding); - } - /* If we found either a type binding or a value binding, create a new binding object. */ if (type_binding || value_binding) @@ -5503,7 +5498,7 @@ push_class_level_binding_1 (tree name, tree x) old_decl = bval; else if (TREE_CODE (bval) == USING_DECL && OVL_P (target_decl)) - return true; + old_decl = bval; else if (OVL_P (target_decl) && OVL_P (target_bval)) old_decl = bval; @@ -8565,6 +8560,7 @@ finish_using_directive (tree target, tree attribs) add_using_namespace (current_binding_level->using_directives, ORIGINAL_NAMESPACE (target)); + bool diagnosed = false; if (attribs != error_mark_node) for (tree a = attribs; a; a = TREE_CHAIN (a)) { @@ -8577,6 +8573,16 @@ finish_using_directive (tree target, tree attribs) inform (DECL_SOURCE_LOCATION (target), "you can use an inline namespace instead"); } + else if ((flag_openmp || flag_openmp_simd) + && get_attribute_namespace (a) == omp_identifier + && (is_attribute_p ("directive", name) + || is_attribute_p ("sequence", name))) + { + if (!diagnosed) + error ("%<omp::%E%> not allowed to be specified in this " + "context", name); + diagnosed = true; + } else warning (OPT_Wattributes, "%qD attribute directive ignored", name); } @@ -9099,7 +9105,7 @@ static const char *const op_bind_attrname = "operator bindings"; void maybe_save_operator_binding (tree e) { - /* This is only useful in a generic lambda. */ + /* This is only useful in a template. */ if (!processing_template_decl) return; @@ -9107,22 +9113,24 @@ maybe_save_operator_binding (tree e) if (!cfn) return; - /* Do this for lambdas and code that will emit a CMI. In a module's - GMF we don't yet know whether there will be a CMI. */ - if (!module_has_cmi_p () && !global_purview_p () && !current_lambda_expr()) - return; - - tree fnname = ovl_op_identifier (false, TREE_CODE (e)); - if (!fnname) + tree fnname; + if(TREE_CODE (e) == MODOP_EXPR) + fnname = ovl_op_identifier (true, TREE_CODE (TREE_OPERAND (e, 1))); + else + fnname = ovl_op_identifier (false, TREE_CODE (e)); + if (!fnname || fnname == assign_op_identifier) return; tree attributes = DECL_ATTRIBUTES (cfn); tree op_attr = lookup_attribute (op_bind_attrname, attributes); if (!op_attr) { + tree *ap = &DECL_ATTRIBUTES (cfn); + while (*ap && ATTR_IS_DEPENDENT (*ap)) + ap = &TREE_CHAIN (*ap); op_attr = tree_cons (get_identifier (op_bind_attrname), - NULL_TREE, attributes); - DECL_ATTRIBUTES (cfn) = op_attr; + NULL_TREE, *ap); + *ap = op_attr; } tree op_bind = purpose_member (fnname, TREE_VALUE (op_attr)); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 0a7d18a..e44c5c6 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -572,6 +572,8 @@ cp_debug_parser (FILE *file, cp_parser *parser) parser->colon_corrects_to_scope_p); cp_debug_print_flag (file, "Colon doesn't start a class definition", parser->colon_doesnt_start_class_def_p); + cp_debug_print_flag (file, "Parsing an Objective-C++ message context", + parser->objective_c_message_context_p); if (parser->type_definition_forbidden_message) fprintf (file, "Error message for forbidden type definitions: %s %s\n", parser->type_definition_forbidden_message, @@ -1438,6 +1440,24 @@ cp_finalize_omp_declare_simd (cp_parser *parser, tree fndecl) } } +/* Similarly, but for use in declaration parsing functions + which call cp_parser_handle_directive_omp_attributes. */ + +static inline void +cp_finalize_omp_declare_simd (cp_parser *parser, cp_omp_declare_simd_data *data) +{ + if (parser->omp_declare_simd != data) + return; + + if (!parser->omp_declare_simd->error_seen + && !parser->omp_declare_simd->fndecl_seen) + error_at (parser->omp_declare_simd->loc, + "%<declare %s%> directive not immediately followed by " + "function declaration or definition", + parser->omp_declare_simd->variant_p ? "variant" : "simd"); + parser->omp_declare_simd = NULL; +} + /* Diagnose if #pragma acc routine isn't followed immediately by function declaration or definition. */ @@ -2161,7 +2181,7 @@ static enum tree_code cp_parser_assignment_operator_opt static cp_expr cp_parser_expression (cp_parser *, cp_id_kind * = NULL, bool = false, bool = false, bool = false); static cp_expr cp_parser_constant_expression - (cp_parser *, bool = false, bool * = NULL, bool = false); + (cp_parser *, int = 0, bool * = NULL, bool = false); static cp_expr cp_parser_builtin_offsetof (cp_parser *); static cp_expr cp_parser_lambda_expression @@ -2505,6 +2525,8 @@ static tree cp_parser_std_attribute_spec (cp_parser *); static tree cp_parser_std_attribute_spec_seq (cp_parser *); +static size_t cp_parser_skip_std_attribute_spec_seq + (cp_parser *, size_t); static size_t cp_parser_skip_attributes_opt (cp_parser *, size_t); static bool cp_parser_extension_opt @@ -4058,6 +4080,14 @@ cp_parser_skip_to_pragma_eol (cp_parser* parser, cp_token *pragma_tok) /* Ensure that the pragma is not parsed again. */ cp_lexer_purge_tokens_after (parser->lexer, pragma_tok); parser->lexer->in_pragma = false; + if (parser->lexer->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_EOF)) + { + parser->lexer = parser->lexer->next; + /* Put the current source position back where it was before this + lexer was pushed. */ + cp_lexer_set_source_position_from_token (parser->lexer->next_token); + } } } @@ -4070,6 +4100,14 @@ cp_parser_require_pragma_eol (cp_parser *parser, cp_token *pragma_tok) parser->lexer->in_pragma = false; if (!cp_parser_require (parser, CPP_PRAGMA_EOL, RT_PRAGMA_EOL)) cp_parser_skip_to_pragma_eol (parser, pragma_tok); + else if (parser->lexer->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_EOF)) + { + parser->lexer = parser->lexer->next; + /* Put the current source position back where it was before this + lexer was pushed. */ + cp_lexer_set_source_position_from_token (parser->lexer->next_token); + } } /* This is a simple wrapper around make_typename_type. When the id is @@ -4376,8 +4414,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok, rich_location rich_loc (line_table, tok->location); rich_loc.add_range (last_tok_loc); error_at (&rich_loc, - "unsupported non-standard concatenation " - "of string literals"); + "concatenation of string literals with " + "conflicting encoding prefixes"); } } @@ -5320,7 +5358,7 @@ cp_parser_fold_expression (cp_parser *parser, tree expr1) /* The operands of a fold-expression are cast-expressions, so binary or conditional expressions are not allowed. We check this here to avoid tentative parsing. */ - if (EXPR_P (expr1) && TREE_NO_WARNING (expr1)) + if (EXPR_P (expr1) && warning_suppressed_p (expr1, OPT_Wparentheses)) /* OK, the expression was parenthesized. */; else if (is_binary_op (TREE_CODE (expr1))) error_at (location_of (expr1), @@ -5575,8 +5613,9 @@ cp_parser_primary_expression (cp_parser *parser, expr = cp_parser_fold_expression (parser, expr); if (expr != error_mark_node && cxx_dialect < cxx17) - pedwarn (input_location, 0, "fold-expressions only available " - "with %<-std=c++17%> or %<-std=gnu++17%>"); + pedwarn (input_location, OPT_Wc__17_extensions, + "fold-expressions only available with %<-std=c++17%> " + "or %<-std=gnu++17%>"); } else /* Let the front end know that this expression was @@ -5601,7 +5640,10 @@ cp_parser_primary_expression (cp_parser *parser, /* Consume the `)'. */ token = cp_lexer_peek_token (parser->lexer); location_t close_paren_loc = token->location; + bool no_wparens = warning_suppressed_p (expr, OPT_Wparentheses); expr.set_range (open_paren_loc, close_paren_loc); + if (no_wparens) + suppress_warning (expr, OPT_Wparentheses); if (!parens.require_close (parser) && !cp_parser_uncommitted_to_tentative_parse_p (parser)) cp_parser_skip_to_end_of_statement (parser); @@ -5774,7 +5816,9 @@ cp_parser_primary_expression (cp_parser *parser, case RID_IS_EMPTY: case RID_IS_ENUM: case RID_IS_FINAL: + case RID_IS_LAYOUT_COMPATIBLE: case RID_IS_LITERAL_TYPE: + case RID_IS_POINTER_INTERCONVERTIBLE_BASE_OF: case RID_IS_POD: case RID_IS_POLYMORPHIC: case RID_IS_SAME_AS: @@ -5946,7 +5990,10 @@ cp_parser_primary_expression (cp_parser *parser, /* Check to see if DECL is a local variable in a context where that is forbidden. */ if ((parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN) - && local_variable_p (decl)) + && local_variable_p (decl) + /* DR 2082 permits local variables in unevaluated contexts + within a default argument. */ + && !cp_unevaluated_operand) { const char *msg = (TREE_CODE (decl) == PARM_DECL @@ -6323,7 +6370,7 @@ cp_parser_unqualified_id (cp_parser* parser, if (cp_parser_is_keyword (token, RID_AUTO)) { if (cxx_dialect < cxx14) - pedwarn (loc, 0, + pedwarn (loc, OPT_Wc__14_extensions, "%<~auto%> only available with " "%<-std=c++14%> or %<-std=gnu++14%>"); cp_lexer_consume_token (parser->lexer); @@ -6626,7 +6673,9 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, if (token->type == CPP_COLON && parser->colon_corrects_to_scope_p - && cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_NAME) + && cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_NAME + /* name:name is a valid sequence in an Objective C message. */ + && !parser->objective_c_message_context_p) { gcc_rich_location richloc (token->location); richloc.add_fixit_replace ("::"); @@ -7290,11 +7339,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, case RID_ADDRESSOF: case RID_BUILTIN_SHUFFLE: + case RID_BUILTIN_SHUFFLEVECTOR: case RID_BUILTIN_LAUNDER: { vec<tree, va_gc> *vec; - unsigned int i; - tree p; cp_lexer_consume_token (parser->lexer); vec = cp_parser_parenthesized_expression_list (parser, non_attr, @@ -7306,7 +7354,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, break; } - FOR_EACH_VEC_ELT (*vec, i, p) + for (tree p : *vec) mark_exp_read (p); switch (keyword) @@ -7352,6 +7400,20 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, } break; + case RID_BUILTIN_SHUFFLEVECTOR: + if (vec->length () < 3) + { + error_at (loc, "wrong number of arguments to " + "%<__builtin_shufflevector%>"); + postfix_expression = error_mark_node; + } + else + { + postfix_expression + = build_x_shufflevector (loc, vec, tf_warning_or_error); + } + break; + default: gcc_unreachable (); } @@ -7560,6 +7622,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, tsubst_flags_t complain = complain_flags (decltype_p); vec<tree, va_gc> *args; location_t close_paren_loc = UNKNOWN_LOCATION; + location_t combined_loc = UNKNOWN_LOCATION; is_member_access = false; @@ -7665,6 +7728,17 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, } } + /* Temporarily set input_location to the combined location + with call expression range, as e.g. build_out_target_exprs + called from convert_default_arg relies on input_location, + so updating it only when the call is fully built results + in inconsistencies between location handling in templates + and outside of templates. */ + if (close_paren_loc != UNKNOWN_LOCATION) + combined_loc = make_location (token->location, start_loc, + close_paren_loc); + iloc_sentinel ils (combined_loc); + if (TREE_CODE (postfix_expression) == COMPONENT_REF) { tree instance = TREE_OPERAND (postfix_expression, 0); @@ -7722,12 +7796,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, complain); if (close_paren_loc != UNKNOWN_LOCATION) - { - location_t combined_loc = make_location (token->location, - start_loc, - close_paren_loc); - postfix_expression.set_location (combined_loc); - } + postfix_expression.set_location (combined_loc); /* The POSTFIX_EXPRESSION is certainly no longer an id. */ idk = CP_ID_KIND_NONE; @@ -8342,7 +8411,7 @@ cp_parser_pseudo_destructor_name (cp_parser* parser, && !type_dependent_expression_p (object)) { if (cxx_dialect < cxx14) - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__14_extensions, "%<~auto%> only available with " "%<-std=c++14%> or %<-std=gnu++14%>"); cp_lexer_consume_token (parser->lexer); @@ -10363,13 +10432,15 @@ cp_parser_expression (cp_parser* parser, cp_id_kind * pidk, If ALLOW_NON_CONSTANT_P a non-constant expression is silently accepted. If ALLOW_NON_CONSTANT_P is true and the expression is not constant, *NON_CONSTANT_P is set to TRUE. If ALLOW_NON_CONSTANT_P - is false, NON_CONSTANT_P should be NULL. If STRICT_P is true, + is false, NON_CONSTANT_P should be NULL. If ALLOW_NON_CONSTANT_P is + greater than 1, this isn't really a constant-expression, only a + potentially constant-evaluated expression. If STRICT_P is true, only parse a conditional-expression, otherwise parse an assignment-expression. See below for rationale. */ static cp_expr cp_parser_constant_expression (cp_parser* parser, - bool allow_non_constant_p, + int allow_non_constant_p, bool *non_constant_p, bool strict_p) { @@ -10405,6 +10476,11 @@ cp_parser_constant_expression (cp_parser* parser, parser->allow_non_integral_constant_expression_p = (allow_non_constant_p || cxx_dialect >= cxx11); parser->non_integral_constant_expression_p = false; + + /* A manifestly constant-evaluated expression is evaluated even in an + unevaluated operand. */ + cp_evaluated ev (/*reset if*/allow_non_constant_p <= 1); + /* Although the grammar says "conditional-expression", when not STRICT_P, we parse an "assignment-expression", which also permits "throw-expression" and the use of assignment operators. In the case @@ -10632,9 +10708,17 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword) case RID_IS_FINAL: kind = CPTK_IS_FINAL; break; + case RID_IS_LAYOUT_COMPATIBLE: + kind = CPTK_IS_LAYOUT_COMPATIBLE; + binary = true; + break; case RID_IS_LITERAL_TYPE: kind = CPTK_IS_LITERAL_TYPE; break; + case RID_IS_POINTER_INTERCONVERTIBLE_BASE_OF: + kind = CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF; + binary = true; + break; case RID_IS_POD: kind = CPTK_IS_POD; break; @@ -10785,7 +10869,21 @@ cp_parser_lambda_expression (cp_parser* parser) LAMBDA_EXPR_LOCATION (lambda_expr) = token->location; if (cxx_dialect >= cxx20) - /* C++20 allows lambdas in unevaluated context. */; + { + /* C++20 allows lambdas in unevaluated context, but one in the type of a + non-type parameter is nonsensical. + + Distinguish a lambda in the parameter type from a lambda in the + default argument by looking at local_variables_forbidden_p, which is + only set in default arguments. */ + if (processing_template_parmlist && !parser->local_variables_forbidden_p) + { + error_at (token->location, + "lambda-expression in template parameter type"); + token->error_reported = true; + ok = false; + } + } else if (cp_unevaluated_operand) { if (!token->error_reported) @@ -10854,6 +10952,11 @@ cp_parser_lambda_expression (cp_parser* parser) bool discarded = in_discarded_stmt; in_discarded_stmt = 0; + /* Similarly the body of a lambda in immediate function context is not + in immediate function context. */ + bool save_in_consteval_if_p = in_consteval_if_p; + in_consteval_if_p = false; + /* By virtue of defining a local class, a lambda expression has access to the private variables of enclosing classes. */ @@ -10884,6 +10987,7 @@ cp_parser_lambda_expression (cp_parser* parser) finish_struct (type, /*attributes=*/NULL_TREE); + in_consteval_if_p = save_in_consteval_if_p; in_discarded_stmt = discarded; parser->num_template_parameter_lists = saved_num_template_parameter_lists; @@ -11010,8 +11114,9 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) { location_t loc = cp_lexer_peek_token (parser->lexer)->location; if (cxx_dialect < cxx17) - pedwarn (loc, 0, "%<*this%> capture only available with " - "%<-std=c++17%> or %<-std=gnu++17%>"); + pedwarn (loc, OPT_Wc__17_extensions, + "%<*this%> capture only available with " + "%<-std=c++17%> or %<-std=gnu++17%>"); cp_lexer_consume_token (parser->lexer); cp_lexer_consume_token (parser->lexer); if (LAMBDA_EXPR_THIS_CAPTURE (lambda_expr)) @@ -11049,7 +11154,8 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) { ellipsis_loc = cp_lexer_peek_token (parser->lexer)->location; if (cxx_dialect < cxx20) - pedwarn (ellipsis_loc, 0, "pack init-capture only available with " + pedwarn (ellipsis_loc, OPT_Wc__20_extensions, + "pack init-capture only available with " "%<-std=c++20%> or %<-std=gnu++20%>"); cp_lexer_consume_token (parser->lexer); init_pack_expansion = true; @@ -11090,7 +11196,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) bool direct, non_constant; /* An explicit initializer exists. */ if (cxx_dialect < cxx14) - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__14_extensions, "lambda capture initializers " "only available with %<-std=c++14%> or %<-std=gnu++14%>"); capture_init_expr = cp_parser_initializer (parser, &direct, @@ -11264,11 +11370,11 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) if (cp_lexer_next_token_is (parser->lexer, CPP_LESS)) { if (cxx_dialect < cxx14) - pedwarn (parser->lexer->next_token->location, 0, + pedwarn (parser->lexer->next_token->location, OPT_Wc__14_extensions, "lambda templates are only available with " "%<-std=c++14%> or %<-std=gnu++14%>"); - else if (cxx_dialect < cxx20) - pedwarn (parser->lexer->next_token->location, OPT_Wpedantic, + else if (pedantic && cxx_dialect < cxx20) + pedwarn (parser->lexer->next_token->location, OPT_Wc__20_extensions, "lambda templates are only available with " "%<-std=c++20%> or %<-std=gnu++20%>"); @@ -11333,10 +11439,11 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) /* Default arguments shall not be specified in the parameter-declaration-clause of a lambda-declarator. */ - if (cxx_dialect < cxx14) + if (pedantic && cxx_dialect < cxx14) for (tree t = param_list; t; t = TREE_CHAIN (t)) if (TREE_PURPOSE (t) && DECL_P (TREE_VALUE (t))) - pedwarn (DECL_SOURCE_LOCATION (TREE_VALUE (t)), OPT_Wpedantic, + pedwarn (DECL_SOURCE_LOCATION (TREE_VALUE (t)), + OPT_Wc__14_extensions, "default argument specified for lambda parameter"); parens.require_close (parser); @@ -11356,7 +11463,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) if (omitted_parms_loc && lambda_specs.any_specifiers_p) { - pedwarn (omitted_parms_loc, 0, + pedwarn (omitted_parms_loc, OPT_Wc__23_extensions, "parameter declaration before lambda declaration " "specifiers only optional with %<-std=c++2b%> or " "%<-std=gnu++2b%>"); @@ -11375,7 +11482,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) tx_qual = cp_parser_tx_qualifier_opt (parser); if (omitted_parms_loc && tx_qual) { - pedwarn (omitted_parms_loc, 0, + pedwarn (omitted_parms_loc, OPT_Wc__23_extensions, "parameter declaration before lambda transaction " "qualifier only optional with %<-std=c++2b%> or " "%<-std=gnu++2b%>"); @@ -11388,7 +11495,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) if (omitted_parms_loc && exception_spec) { - pedwarn (omitted_parms_loc, 0, + pedwarn (omitted_parms_loc, OPT_Wc__23_extensions, "parameter declaration before lambda exception " "specification only optional with %<-std=c++2b%> or " "%<-std=gnu++2b%>"); @@ -11406,7 +11513,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) if (cp_lexer_next_token_is (parser->lexer, CPP_DEREF)) { if (omitted_parms_loc) - pedwarn (omitted_parms_loc, 0, + pedwarn (omitted_parms_loc, OPT_Wc__23_extensions, "parameter declaration before lambda trailing " "return type only optional with %<-std=c++2b%> or " "%<-std=gnu++2b%>"); @@ -11526,6 +11633,9 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr) middle of an expression. */ ++function_depth; + auto odsd = make_temp_override (parser->omp_declare_simd, NULL); + auto ord = make_temp_override (parser->oacc_routine, NULL); + auto oafp = make_temp_override (parser->omp_attrs_forbidden_p, false); vec<tree> omp_privatization_save; save_omp_privatization_clauses (omp_privatization_save); /* Clear this in case we're in the middle of a default argument. */ @@ -11572,6 +11682,323 @@ add_debug_begin_stmt (location_t loc) add_stmt (stmt); } +struct cp_omp_attribute_data +{ + cp_token_cache *tokens; + const c_omp_directive *dir; + c_omp_directive_kind kind; +}; + +/* Handle omp::directive and omp::sequence attributes in ATTRS + (if any) at the start of a statement or in attribute-declaration. */ + +static tree +cp_parser_handle_statement_omp_attributes (cp_parser *parser, tree attrs) +{ + if (!flag_openmp && !flag_openmp_simd) + return attrs; + + auto_vec<cp_omp_attribute_data, 16> vec; + int cnt = 0; + int tokens = 0; + bool bad = false; + for (tree *pa = &attrs; *pa; ) + if (get_attribute_namespace (*pa) == omp_identifier + && is_attribute_p ("directive", get_attribute_name (*pa))) + { + cnt++; + for (tree a = TREE_VALUE (*pa); a; a = TREE_CHAIN (a)) + { + tree d = TREE_VALUE (a); + gcc_assert (TREE_CODE (d) == DEFERRED_PARSE); + cp_token *first = DEFPARSE_TOKENS (d)->first; + cp_token *last = DEFPARSE_TOKENS (d)->last; + if (parser->omp_attrs_forbidden_p) + { + error_at (first->location, + "mixing OpenMP directives with attribute and pragma " + "syntax on the same statement"); + parser->omp_attrs_forbidden_p = false; + bad = true; + } + const char *directive[3] = {}; + for (int i = 0; i < 3; i++) + { + tree id = NULL_TREE; + if (first + i == last) + break; + if (first[i].type == CPP_NAME) + id = first[i].u.value; + else if (first[i].type == CPP_KEYWORD) + id = ridpointers[(int) first[i].keyword]; + else + break; + directive[i] = IDENTIFIER_POINTER (id); + } + const c_omp_directive *dir = NULL; + if (directive[0]) + dir = c_omp_categorize_directive (directive[0], directive[1], + directive[2]); + if (dir == NULL) + { + error_at (first->location, + "unknown OpenMP directive name in %<omp::directive%>" + " attribute argument"); + continue; + } + c_omp_directive_kind kind = dir->kind; + if (dir->id == PRAGMA_OMP_ORDERED) + { + /* ordered is C_OMP_DIR_CONSTRUCT only if it doesn't contain + depend clause. */ + if (directive[1] && strcmp (directive[1], "depend") == 0) + kind = C_OMP_DIR_STANDALONE; + else if (first + 2 < last + && first[1].type == CPP_COMMA + && first[2].type == CPP_NAME + && strcmp (IDENTIFIER_POINTER (first[2].u.value), + "depend") == 0) + kind = C_OMP_DIR_STANDALONE; + } + else if (dir->id == PRAGMA_OMP_ERROR) + { + /* error with at(execution) clause is C_OMP_DIR_STANDALONE. */ + int paren_depth = 0; + for (int i = 1; first + i < last; i++) + if (first[i].type == CPP_OPEN_PAREN) + paren_depth++; + else if (first[i].type == CPP_CLOSE_PAREN) + paren_depth--; + else if (paren_depth == 0 + && first + i + 2 < last + && first[i].type == CPP_NAME + && first[i + 1].type == CPP_OPEN_PAREN + && first[i + 2].type == CPP_NAME + && !strcmp (IDENTIFIER_POINTER (first[i].u.value), + "at") + && !strcmp (IDENTIFIER_POINTER (first[i + + 2].u.value), + "execution")) + { + kind = C_OMP_DIR_STANDALONE; + break; + } + } + cp_omp_attribute_data v = { DEFPARSE_TOKENS (d), dir, kind }; + vec.safe_push (v); + if (flag_openmp || dir->simd) + tokens += (last - first) + 1; + } + cp_omp_attribute_data v = {}; + vec.safe_push (v); + *pa = TREE_CHAIN (*pa); + } + else + pa = &TREE_CHAIN (*pa); + + if (bad) + return attrs; + + unsigned int i; + cp_omp_attribute_data *v; + cp_omp_attribute_data *construct_seen = nullptr; + cp_omp_attribute_data *standalone_seen = nullptr; + cp_omp_attribute_data *prev_standalone_seen = nullptr; + FOR_EACH_VEC_ELT (vec, i, v) + if (v->tokens) + { + if (v->kind == C_OMP_DIR_CONSTRUCT && !construct_seen) + construct_seen = v; + else if (v->kind == C_OMP_DIR_STANDALONE && !standalone_seen) + standalone_seen = v; + } + else + { + if (standalone_seen && !prev_standalone_seen) + { + prev_standalone_seen = standalone_seen; + standalone_seen = nullptr; + } + } + + if (cnt > 1 && construct_seen) + { + error_at (construct_seen->tokens->first->location, + "OpenMP construct among %<omp::directive%> attributes" + " requires all %<omp::directive%> attributes on the" + " same statement to be in the same %<omp::sequence%>"); + return attrs; + } + if (cnt > 1 && standalone_seen && prev_standalone_seen) + { + error_at (standalone_seen->tokens->first->location, + "multiple OpenMP standalone directives among" + " %<omp::directive%> attributes must be all within the" + " same %<omp::sequence%>"); + return attrs; + } + + if (prev_standalone_seen) + standalone_seen = prev_standalone_seen; + if (standalone_seen + && !cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) + { + error_at (standalone_seen->tokens->first->location, + "standalone OpenMP directives in %<omp::directive%> attribute" + " can only appear on an empty statement"); + return attrs; + } + if (cnt && cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA)) + { + cp_token *token = cp_lexer_peek_token (parser->lexer); + enum pragma_kind kind = cp_parser_pragma_kind (token); + if (kind >= PRAGMA_OMP__START_ && kind <= PRAGMA_OMP__LAST_) + { + error_at (token->location, + "mixing OpenMP directives with attribute and pragma " + "syntax on the same statement"); + return attrs; + } + } + + if (!tokens) + return attrs; + tokens++; + cp_lexer *lexer = cp_lexer_alloc (); + lexer->debugging_p = parser->lexer->debugging_p; + vec_safe_reserve (lexer->buffer, tokens, true); + FOR_EACH_VEC_ELT (vec, i, v) + { + if (!v->tokens) + continue; + if (!flag_openmp && !v->dir->simd) + continue; + cp_token *first = v->tokens->first; + cp_token *last = v->tokens->last; + cp_token tok = {}; + tok.type = CPP_PRAGMA; + tok.keyword = RID_MAX; + tok.u.value = build_int_cst (NULL, v->dir->id); + tok.location = first->location; + lexer->buffer->quick_push (tok); + while (++first < last) + lexer->buffer->quick_push (*first); + tok = {}; + tok.type = CPP_PRAGMA_EOL; + tok.keyword = RID_MAX; + tok.location = last->location; + lexer->buffer->quick_push (tok); + } + cp_token tok = {}; + tok.type = CPP_EOF; + tok.keyword = RID_MAX; + tok.location = lexer->buffer->last ().location; + lexer->buffer->quick_push (tok); + lexer->next = parser->lexer; + lexer->next_token = lexer->buffer->address (); + lexer->last_token = lexer->next_token + + lexer->buffer->length () + - 1; + lexer->in_omp_attribute_pragma = true; + parser->lexer = lexer; + /* Move the current source position to that of the first token in the + new lexer. */ + cp_lexer_set_source_position_from_token (lexer->next_token); + return attrs; +} + +/* Handle omp::directive and omp::sequence attributes in *PATTRS + (if any) at the start or after declaration-id of a declaration. */ + +static void +cp_parser_handle_directive_omp_attributes (cp_parser *parser, tree *pattrs, + cp_omp_declare_simd_data *data, + bool start) +{ + if (!flag_openmp && !flag_openmp_simd) + return; + + int cnt = 0; + bool bad = false; + bool variant_p = false; + location_t loc = UNKNOWN_LOCATION; + for (tree pa = *pattrs; pa; pa = TREE_CHAIN (pa)) + if (get_attribute_namespace (pa) == omp_identifier + && is_attribute_p ("directive", get_attribute_name (pa))) + { + for (tree a = TREE_VALUE (pa); a; a = TREE_CHAIN (a)) + { + tree d = TREE_VALUE (a); + gcc_assert (TREE_CODE (d) == DEFERRED_PARSE); + cp_token *first = DEFPARSE_TOKENS (d)->first; + cp_token *last = DEFPARSE_TOKENS (d)->last; + const char *directive[3] = {}; + for (int i = 0; i < 3; i++) + { + tree id = NULL_TREE; + if (first + i == last) + break; + if (first[i].type == CPP_NAME) + id = first[i].u.value; + else if (first[i].type == CPP_KEYWORD) + id = ridpointers[(int) first[i].keyword]; + else + break; + directive[i] = IDENTIFIER_POINTER (id); + } + const c_omp_directive *dir = NULL; + if (directive[0]) + dir = c_omp_categorize_directive (directive[0], directive[1], + directive[2]); + if (dir == NULL) + continue; + if (dir->id == PRAGMA_OMP_DECLARE + && (strcmp (directive[1], "simd") == 0 + || strcmp (directive[1], "variant") == 0)) + { + if (cnt++ == 0) + { + variant_p = strcmp (directive[1], "variant") == 0; + loc = first->location; + } + if (start && parser->omp_declare_simd && !bad) + { + error_at (first->location, + "mixing OpenMP directives with attribute and " + "pragma syntax on the same declaration"); + bad = true; + } + } + } + } + + if (bad) + { + for (tree *pa = pattrs; *pa; ) + if (get_attribute_namespace (*pa) == omp_identifier + && is_attribute_p ("directive", get_attribute_name (*pa))) + *pa = TREE_CHAIN (*pa); + else + pa = &TREE_CHAIN (*pa); + return; + } + if (cnt == 0) + return; + + if (parser->omp_declare_simd == NULL) + { + data->error_seen = false; + data->fndecl_seen = false; + data->variant_p = variant_p; + data->loc = loc; + data->tokens = vNULL; + data->attribs[0] = NULL; + data->attribs[1] = NULL; + parser->omp_declare_simd = data; + } + parser->omp_declare_simd->attribs[!start] = pattrs; +} + /* Parse a statement. statement: @@ -11622,6 +12049,8 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, tree statement, std_attrs = NULL_TREE; cp_token *token; location_t statement_location, attrs_loc; + bool in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; + bool has_std_attrs; restart: if (if_p != NULL) @@ -11630,7 +12059,8 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, statement = NULL_TREE; saved_token_sentinel saved_tokens (parser->lexer); - attrs_loc = cp_lexer_peek_token (parser->lexer)->location; + token = cp_lexer_peek_token (parser->lexer); + attrs_loc = token->location; if (c_dialect_objc ()) /* In obj-c++, seeing '[[' might be the either the beginning of c++11 attributes, or a nested objc-message-expression. So @@ -11644,9 +12074,59 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, if (!cp_parser_parse_definitely (parser)) std_attrs = NULL_TREE; } + has_std_attrs = cp_lexer_peek_token (parser->lexer) != token; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); + bool omp_attrs_forbidden_p; + omp_attrs_forbidden_p = parser->omp_attrs_forbidden_p; + + if (std_attrs && (flag_openmp || flag_openmp_simd)) + { + bool handle_omp_attribs = false; + if (token->type == CPP_KEYWORD) + switch (token->keyword) + { + case RID_IF: + case RID_SWITCH: + case RID_WHILE: + case RID_DO: + case RID_FOR: + case RID_BREAK: + case RID_CONTINUE: + case RID_RETURN: + case RID_CO_RETURN: + case RID_GOTO: + case RID_AT_TRY: + case RID_AT_CATCH: + case RID_AT_FINALLY: + case RID_AT_SYNCHRONIZED: + case RID_AT_THROW: + case RID_TRY: + case RID_TRANSACTION_ATOMIC: + case RID_TRANSACTION_RELAXED: + case RID_SYNCHRONIZED: + case RID_ATOMIC_NOEXCEPT: + case RID_ATOMIC_CANCEL: + case RID_TRANSACTION_CANCEL: + handle_omp_attribs = true; + break; + default: + break; + } + else if (token->type == CPP_SEMICOLON + || token->type == CPP_OPEN_BRACE + || token->type == CPP_PRAGMA) + handle_omp_attribs = true; + if (handle_omp_attribs) + { + std_attrs = cp_parser_handle_statement_omp_attributes (parser, + std_attrs); + token = cp_lexer_peek_token (parser->lexer); + } + } + parser->omp_attrs_forbidden_p = false; + /* Remember the location of the first token in the statement. */ cp_token *statement_token = token; statement_location = token->location; @@ -11666,6 +12146,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, the statement. */ cp_parser_label_for_labeled_statement (parser, std_attrs); in_compound = false; + in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; goto restart; case RID_IF: @@ -11707,7 +12188,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, case RID_NAMESPACE: /* This must be a namespace alias definition. */ - if (std_attrs != NULL_TREE) + if (has_std_attrs) { /* Attributes should be parsed as part of the declaration, so let's un-parse them. */ @@ -11749,6 +12230,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, cp_parser_label_for_labeled_statement (parser, std_attrs); in_compound = false; + in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; goto restart; } } @@ -11762,6 +12244,9 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, a statement all its own. */ else if (token->type == CPP_PRAGMA) { + do_pragma:; + cp_lexer *lexer = parser->lexer; + bool do_restart = false; /* Only certain OpenMP pragmas are attached to statements, and thus are considered statements themselves. All others are not. In the context of a compound, accept the pragma as a "statement" and @@ -11770,7 +12255,29 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, if (in_compound) cp_parser_pragma (parser, pragma_compound, if_p); else if (!cp_parser_pragma (parser, pragma_stmt, if_p)) + do_restart = true; + if (parser->lexer != lexer + && lexer->in_omp_attribute_pragma + && (!in_omp_attribute_pragma || lexer->orphan_p)) + { + if (saved_tokens.lexer == lexer) + { + if (saved_tokens.commit) + cp_lexer_commit_tokens (lexer); + gcc_assert (lexer->saved_tokens.length () == saved_tokens.len); + saved_tokens.lexer = parser->lexer; + saved_tokens.commit = false; + saved_tokens.len = parser->lexer->saved_tokens.length (); + } + cp_lexer_destroy (lexer); + lexer = parser->lexer; + } + if (do_restart) goto restart; + if (parser->lexer == lexer + && lexer->in_omp_attribute_pragma + && !in_omp_attribute_pragma) + parser->lexer->orphan_p = true; return; } else if (token->type == CPP_EOF) @@ -11787,20 +12294,61 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, { if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) { - if (std_attrs != NULL_TREE) + if (has_std_attrs) /* Attributes should be parsed as part of the declaration, so let's un-parse them. */ saved_tokens.rollback(); + parser->omp_attrs_forbidden_p = omp_attrs_forbidden_p; cp_parser_parse_tentatively (parser); /* Try to parse the declaration-statement. */ cp_parser_declaration_statement (parser); + parser->omp_attrs_forbidden_p = false; /* If that worked, we're done. */ if (cp_parser_parse_definitely (parser)) return; /* It didn't work, restore the post-attribute position. */ - if (std_attrs) - cp_lexer_set_token_position (parser->lexer, statement_token); + if (has_std_attrs) + { + cp_lexer_set_token_position (parser->lexer, statement_token); + if (flag_openmp || flag_openmp_simd) + { + size_t i = 1; + bool handle_omp_attribs = true; + while (cp_lexer_peek_nth_token (parser->lexer, i)->keyword + == RID_EXTENSION) + i++; + switch (cp_lexer_peek_nth_token (parser->lexer, i)->keyword) + { + case RID_ASM: + case RID_NAMESPACE: + case RID_USING: + case RID_LABEL: + case RID_STATIC_ASSERT: + /* Don't handle OpenMP attribs on keywords that + always start a declaration statement but don't + accept attribute before it and therefore + the tentative cp_parser_declaration_statement + fails to parse because of that. */ + handle_omp_attribs = false; + break; + default: + break; + } + + if (handle_omp_attribs) + { + parser->omp_attrs_forbidden_p = omp_attrs_forbidden_p; + std_attrs + = cp_parser_handle_statement_omp_attributes + (parser, std_attrs); + parser->omp_attrs_forbidden_p = false; + token = cp_lexer_peek_token (parser->lexer); + if (token->type == CPP_PRAGMA) + goto do_pragma; + } + } + } } /* All preceding labels have been parsed at this point. */ if (loc_after_labels != NULL) @@ -12115,11 +12663,12 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr, if (function_body) maybe_splice_retval_cleanup (compound_stmt); - /* Finish the compound-statement. */ - finish_compound_stmt (compound_stmt); /* Consume the `}'. */ braces.require_close (parser); + /* Finish the compound-statement. */ + finish_compound_stmt (compound_stmt); + return compound_stmt; } @@ -12268,8 +12817,105 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p, cx = true; cp_token *tok = cp_lexer_consume_token (parser->lexer); if (cxx_dialect < cxx17) - pedwarn (tok->location, 0, "%<if constexpr%> only available " - "with %<-std=c++17%> or %<-std=gnu++17%>"); + pedwarn (tok->location, OPT_Wc__17_extensions, + "%<if constexpr%> only available with " + "%<-std=c++17%> or %<-std=gnu++17%>"); + } + int ce = 0; + if (keyword == RID_IF && !cx) + { + if (cp_lexer_next_token_is_keyword (parser->lexer, + RID_CONSTEVAL)) + ce = 1; + else if (cp_lexer_next_token_is (parser->lexer, CPP_NOT) + && cp_lexer_nth_token_is_keyword (parser->lexer, 2, + RID_CONSTEVAL)) + { + ce = -1; + cp_lexer_consume_token (parser->lexer); + } + } + if (ce) + { + cp_token *tok = cp_lexer_consume_token (parser->lexer); + if (cxx_dialect < cxx23) + pedwarn (tok->location, OPT_Wc__23_extensions, + "%<if consteval%> only available with " + "%<-std=c++2b%> or %<-std=gnu++2b%>"); + + bool save_in_consteval_if_p = in_consteval_if_p; + statement = begin_if_stmt (); + IF_STMT_CONSTEVAL_P (statement) = true; + condition = finish_if_stmt_cond (boolean_false_node, statement); + + gcc_rich_location richloc (tok->location); + bool non_compound_stmt_p = false; + if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)) + { + non_compound_stmt_p = true; + richloc.add_fixit_insert_after (tok->location, "{"); + } + + in_consteval_if_p |= ce > 0; + cp_parser_implicitly_scoped_statement (parser, NULL, guard_tinfo); + + if (non_compound_stmt_p) + { + location_t before_loc + = cp_lexer_peek_token (parser->lexer)->location; + richloc.add_fixit_insert_before (before_loc, "}"); + error_at (&richloc, + "%<if consteval%> requires compound statement"); + non_compound_stmt_p = false; + } + + finish_then_clause (statement); + + /* If the next token is `else', parse the else-clause. */ + if (cp_lexer_next_token_is_keyword (parser->lexer, + RID_ELSE)) + { + cp_token *else_tok = cp_lexer_peek_token (parser->lexer); + gcc_rich_location else_richloc (else_tok->location); + guard_tinfo = get_token_indent_info (else_tok); + /* Consume the `else' keyword. */ + cp_lexer_consume_token (parser->lexer); + + begin_else_clause (statement); + + if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)) + { + non_compound_stmt_p = true; + else_richloc.add_fixit_insert_after (else_tok->location, + "{"); + } + + in_consteval_if_p = save_in_consteval_if_p | (ce < 0); + cp_parser_implicitly_scoped_statement (parser, NULL, + guard_tinfo); + + if (non_compound_stmt_p) + { + location_t before_loc + = cp_lexer_peek_token (parser->lexer)->location; + else_richloc.add_fixit_insert_before (before_loc, "}"); + error_at (&else_richloc, + "%<if consteval%> requires compound statement"); + } + + finish_else_clause (statement); + } + + in_consteval_if_p = save_in_consteval_if_p; + if (ce < 0) + { + std::swap (THEN_CLAUSE (statement), ELSE_CLAUSE (statement)); + if (THEN_CLAUSE (statement) == NULL_TREE) + THEN_CLAUSE (statement) = build_empty_stmt (tok->location); + } + + finish_if_stmt (statement); + return statement; } /* Look for the `('. */ @@ -12294,7 +12940,8 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p, { tree decl; if (cxx_dialect < cxx17) - pedwarn (cp_lexer_peek_token (parser->lexer)->location, 0, + pedwarn (cp_lexer_peek_token (parser->lexer)->location, + OPT_Wc__17_extensions, "init-statement in selection statements only available " "with %<-std=c++17%> or %<-std=gnu++17%>"); if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) @@ -12827,17 +13474,15 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl, static tree build_range_temp (tree range_expr) { - tree range_type, range_temp; - /* Find out the type deduced by the declaration `auto &&__range = range_expr'. */ - range_type = cp_build_reference_type (make_auto (), true); - range_type = do_auto_deduction (range_type, range_expr, - type_uses_auto (range_type)); + tree auto_node = make_auto (); + tree range_type = cp_build_reference_type (auto_node, true); + range_type = do_auto_deduction (range_type, range_expr, auto_node); /* Create the __range variable. */ - range_temp = build_decl (input_location, VAR_DECL, for_range__identifier, - range_type); + tree range_temp = build_decl (input_location, VAR_DECL, + for_range__identifier, range_type); TREE_USED (range_temp) = 1; DECL_ARTIFICIAL (range_temp) = 1; @@ -12867,7 +13512,9 @@ do_range_for_auto_deduction (tree decl, tree range_expr) RO_UNARY_STAR, tf_warning_or_error); TREE_TYPE (decl) = do_auto_deduction (TREE_TYPE (decl), - iter_decl, auto_node); + iter_decl, auto_node, + tf_warning_or_error, + adc_variable_type); } } } @@ -13363,7 +14010,8 @@ cp_parser_init_statement (cp_parser *parser, tree *decl) if (cxx_dialect < cxx20) { - pedwarn (cp_lexer_peek_token (parser->lexer)->location, 0, + pedwarn (cp_lexer_peek_token (parser->lexer)->location, + OPT_Wc__20_extensions, "range-based %<for%> loops with initializer only " "available with %<-std=c++20%> or %<-std=gnu++20%>"); *decl = error_mark_node; @@ -13387,7 +14035,8 @@ cp_parser_init_statement (cp_parser *parser, tree *decl) cp_lexer_consume_token (parser->lexer); is_range_for = true; if (cxx_dialect < cxx11) - pedwarn (cp_lexer_peek_token (parser->lexer)->location, 0, + pedwarn (cp_lexer_peek_token (parser->lexer)->location, + OPT_Wc__11_extensions, "range-based %<for%> loops only available with " "%<-std=c++11%> or %<-std=gnu++11%>"); } @@ -13992,6 +14641,49 @@ cp_parser_declaration (cp_parser* parser, tree prefix_attrs) cp_token *token2 = (token1->type == CPP_EOF ? token1 : cp_lexer_peek_nth_token (parser->lexer, 2)); + if (token1->type == CPP_SEMICOLON) + { + cp_lexer_consume_token (parser->lexer); + /* A declaration consisting of a single semicolon is invalid + * before C++11. Allow it unless we're being pedantic. */ + if (cxx_dialect < cxx11) + pedwarn (input_location, OPT_Wpedantic, "extra %<;%>"); + return; + } + else if (cp_lexer_nth_token_is (parser->lexer, + cp_parser_skip_std_attribute_spec_seq (parser, + 1), + CPP_SEMICOLON)) + { + location_t attrs_loc = token1->location; + tree std_attrs = cp_parser_std_attribute_spec_seq (parser); + + if (std_attrs && (flag_openmp || flag_openmp_simd)) + { + gcc_assert (!parser->lexer->in_omp_attribute_pragma); + std_attrs = cp_parser_handle_statement_omp_attributes (parser, + std_attrs); + if (parser->lexer->in_omp_attribute_pragma) + { + cp_lexer *lexer = parser->lexer; + while (parser->lexer->in_omp_attribute_pragma) + { + gcc_assert (cp_lexer_next_token_is (parser->lexer, + CPP_PRAGMA)); + cp_parser_pragma (parser, pragma_external, NULL); + } + cp_lexer_destroy (lexer); + } + } + + if (std_attrs != NULL_TREE) + warning_at (make_location (attrs_loc, attrs_loc, parser->lexer), + OPT_Wattributes, "attribute ignored"); + if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) + cp_lexer_consume_token (parser->lexer); + return; + } + /* Get the high-water mark for the DECLARATOR_OBSTACK. */ void *p = obstack_alloc (&declarator_obstack, 0); @@ -14142,14 +14834,6 @@ cp_parser_toplevel_declaration (cp_parser* parser) cp_parser_declaration. (A #pragma at block scope is handled in cp_parser_statement.) */ cp_parser_pragma (parser, pragma_external, NULL); - else if (token->type == CPP_SEMICOLON) - { - cp_lexer_consume_token (parser->lexer); - /* A declaration consisting of a single semicolon is invalid - * before C++11. Allow it unless we're being pedantic. */ - if (cxx_dialect < cxx11) - pedwarn (input_location, OPT_Wpedantic, "extra %<;%>"); - } else /* Parse the declaration itself. */ cp_parser_declaration (parser, NULL_TREE); @@ -14197,6 +14881,7 @@ cp_parser_block_declaration (cp_parser *parser, /* Peek at the next token to figure out which kind of declaration is present. */ cp_token *token1 = cp_lexer_peek_token (parser->lexer); + size_t attr_idx; /* If the next keyword is `asm', we have an asm-definition. */ if (token1->keyword == RID_ASM) @@ -14250,6 +14935,18 @@ cp_parser_block_declaration (cp_parser *parser, /* If the next token is `static_assert' we have a static assertion. */ else if (token1->keyword == RID_STATIC_ASSERT) cp_parser_static_assert (parser, /*member_p=*/false); + /* If the next tokens after attributes is `using namespace', then we have + a using-directive. */ + else if ((attr_idx = cp_parser_skip_std_attribute_spec_seq (parser, 1)) != 1 + && cp_lexer_nth_token_is_keyword (parser->lexer, attr_idx, + RID_USING) + && cp_lexer_nth_token_is_keyword (parser->lexer, attr_idx + 1, + RID_NAMESPACE)) + { + if (statement_p) + cp_parser_commit_to_tentative_parse (parser); + cp_parser_using_directive (parser); + } /* Anything else must be a simple-declaration. */ else cp_parser_simple_declaration (parser, !statement_p, @@ -14312,6 +15009,12 @@ cp_parser_simple_declaration (cp_parser* parser, /* We no longer need to defer access checks. */ stop_deferring_access_checks (); + cp_omp_declare_simd_data odsd; + if (decl_specifiers.attributes && (flag_openmp || flag_openmp_simd)) + cp_parser_handle_directive_omp_attributes (parser, + &decl_specifiers.attributes, + &odsd, true); + /* In a block scope, a valid declaration must always have a decl-specifier-seq. By not trying to parse declarators, we can resolve the declaration/expression ambiguity more quickly. */ @@ -14504,6 +15207,7 @@ cp_parser_simple_declaration (cp_parser* parser, else { pop_deferring_access_checks (); + cp_finalize_omp_declare_simd (parser, &odsd); return; } } @@ -14584,6 +15288,7 @@ cp_parser_simple_declaration (cp_parser* parser, done: pop_deferring_access_checks (); + cp_finalize_omp_declare_simd (parser, &odsd); } /* Helper of cp_parser_simple_declaration, parse a decomposition declaration. @@ -14630,8 +15335,9 @@ cp_parser_decomposition_declaration (cp_parser *parser, } if (cxx_dialect < cxx17) - pedwarn (loc, 0, "structured bindings only available with " - "%<-std=c++17%> or %<-std=gnu++17%>"); + pedwarn (loc, OPT_Wc__17_extensions, + "structured bindings only available with " + "%<-std=c++17%> or %<-std=gnu++17%>"); tree pushed_scope; cp_declarator *declarator = make_declarator (cdk_decomp); @@ -15111,6 +15817,16 @@ cp_parser_decl_specifier_seq (cp_parser* parser, if (!found_decl_spec) break; + if (decl_specs->std_attributes) + { + error_at (decl_specs->locations[ds_std_attribute], + "standard attributes in middle of decl-specifiers"); + inform (decl_specs->locations[ds_std_attribute], + "standard attributes must precede the decl-specifiers to " + "apply to the declaration, or follow them to apply to " + "the type"); + } + decl_specs->any_specifiers_p = true; /* After we see one decl-specifier, further decl-specifiers are always optional. */ @@ -15216,7 +15932,7 @@ cp_parser_function_specifier_opt (cp_parser* parser, = G_("types may not be defined in explicit-specifier"); if (cxx_dialect < cxx20) - pedwarn (token->location, 0, + pedwarn (token->location, OPT_Wc__20_extensions, "%<explicit(bool)%> only available with %<-std=c++20%> " "or %<-std=gnu++20%>"); @@ -15383,8 +16099,8 @@ cp_parser_static_assert(cp_parser *parser, bool member_p) if (cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN) { - if (cxx_dialect < cxx17) - pedwarn (input_location, OPT_Wpedantic, + if (pedantic && cxx_dialect < cxx17) + pedwarn (input_location, OPT_Wc__17_extensions, "%<static_assert%> without a message " "only available with %<-std=c++17%> or %<-std=gnu++17%>"); /* Eat the ')' */ @@ -16895,6 +17611,10 @@ cp_parser_default_type_template_argument (cp_parser *parser) cp_token *token = cp_lexer_peek_token (parser->lexer); + /* Tell cp_parser_lambda_expression this is a default argument. */ + auto lvf = make_temp_override (parser->local_variables_forbidden_p); + parser->local_variables_forbidden_p = LOCAL_VARS_AND_THIS_FORBIDDEN; + /* Parse the default-argument. */ push_deferring_access_checks (dk_no_deferred); tree default_argument = cp_parser_type_id (parser, @@ -17708,18 +18428,26 @@ cp_parser_template_name (cp_parser* parser, /* If DECL is a template, then the name was a template-name. */ if (TREE_CODE (decl) == TEMPLATE_DECL) { - if (TREE_DEPRECATED (decl) - && deprecated_state != DEPRECATED_SUPPRESS) + if ((TREE_DEPRECATED (decl) || TREE_UNAVAILABLE (decl)) + && deprecated_state != UNAVAILABLE_DEPRECATED_SUPPRESS) { tree d = DECL_TEMPLATE_RESULT (decl); tree attr; if (TREE_CODE (d) == TYPE_DECL) - attr = lookup_attribute ("deprecated", - TYPE_ATTRIBUTES (TREE_TYPE (d))); + attr = TYPE_ATTRIBUTES (TREE_TYPE (d)); else - attr = lookup_attribute ("deprecated", - DECL_ATTRIBUTES (d)); - warn_deprecated_use (decl, attr); + attr = DECL_ATTRIBUTES (d); + if (TREE_UNAVAILABLE (decl)) + { + attr = lookup_attribute ("unavailable", attr); + error_unavailable_use (decl, attr); + } + else if (TREE_DEPRECATED (decl) + && deprecated_state != DEPRECATED_SUPPRESS) + { + attr = lookup_attribute ("deprecated", attr); + warn_deprecated_use (decl, attr); + } } } else @@ -17970,7 +18698,9 @@ cp_parser_template_argument (cp_parser* parser) } if (cp_parser_parse_definitely (parser)) { - if (TREE_DEPRECATED (argument)) + if (TREE_UNAVAILABLE (argument)) + error_unavailable_use (argument, NULL_TREE); + else if (TREE_DEPRECATED (argument)) warn_deprecated_use (argument, NULL_TREE); return argument; } @@ -18186,6 +18916,13 @@ cp_parser_explicit_instantiation (cp_parser* parser) CP_PARSER_FLAGS_OPTIONAL, &decl_specifiers, &declares_class_or_enum); + + cp_omp_declare_simd_data odsd; + if (decl_specifiers.attributes && (flag_openmp || flag_openmp_simd)) + cp_parser_handle_directive_omp_attributes (parser, + &decl_specifiers.attributes, + &odsd, true); + /* If there was exactly one decl-specifier, and it declared a class, and there's no declarator, then we have an explicit type instantiation. */ @@ -18254,6 +18991,8 @@ cp_parser_explicit_instantiation (cp_parser* parser) cp_parser_consume_semicolon_at_end_of_statement (parser); timevar_pop (TV_TEMPLATE_INST); + + cp_finalize_omp_declare_simd (parser, &odsd); } /* Parse an explicit-specialization. @@ -18333,6 +19072,11 @@ cp_parser_explicit_specialization (cp_parser* parser) --parser->num_template_parameter_lists; } +/* Preserve the attributes across a garbage collect (by making it a GC + root), which can occur when parsing a member function. */ + +static GTY(()) vec<tree, va_gc> *cp_parser_decl_specs_attrs; + /* Parse a type-specifier. type-specifier: @@ -18425,8 +19169,12 @@ cp_parser_type_specifier (cp_parser* parser, /* Parse tentatively so that we can back up if we don't find a class-specifier. */ cp_parser_parse_tentatively (parser); + if (decl_specs->attributes) + vec_safe_push (cp_parser_decl_specs_attrs, decl_specs->attributes); /* Look for the class-specifier. */ type_spec = cp_parser_class_specifier (parser); + if (decl_specs->attributes) + cp_parser_decl_specs_attrs->pop (); invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, type_spec); /* If that worked, we're done. */ if (cp_parser_parse_definitely (parser)) @@ -18620,9 +19368,8 @@ cp_parser_simple_type_specifier (cp_parser* parser, decl_specs->int_n_idx = idx; /* Check if the alternate "__intN__" form has been used instead of "__intN". */ - if (strncmp (IDENTIFIER_POINTER (token->u.value) - + (IDENTIFIER_LENGTH (token->u.value) - 2), - "__", 2) == 0) + if (startswith (IDENTIFIER_POINTER (token->u.value) + + (IDENTIFIER_LENGTH (token->u.value) - 2), "__")) decl_specs->int_n_alt = true; } type = int_n_trees [idx].signed_type; @@ -19717,11 +20464,18 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, && ! processing_explicit_instantiation) warning (OPT_Wattributes, "attributes ignored on template instantiation"); + else if (is_friend && cxx11_attribute_p (attributes)) + { + if (warning (OPT_Wattributes, "attribute ignored")) + inform (input_location, "an attribute that appertains to a friend " + "declaration that is not a definition is ignored"); + } else if (is_declaration && cp_parser_declares_only_class_p (parser)) cplus_decl_attributes (&type, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE); else warning (OPT_Wattributes, - "attributes ignored on elaborated-type-specifier that is not a forward declaration"); + "attributes ignored on elaborated-type-specifier that is " + "not a forward declaration"); } if (tag_type == enum_type) @@ -19901,6 +20655,10 @@ cp_parser_enum_specifier (cp_parser* parser) /* Consume the `:'. */ cp_lexer_consume_token (parser->lexer); + auto tdf + = make_temp_override (parser->type_definition_forbidden_message, + G_("types may not be defined in enum-base")); + /* Parse the type-specifier-seq. */ cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE, /*is_declaration=*/false, @@ -20350,10 +21108,11 @@ cp_parser_namespace_definition (cp_parser* parser) RID_INLINE); if (nested_inline_p && nested_definition_count != 0) { - if (cxx_dialect < cxx20) + if (pedantic && cxx_dialect < cxx20) pedwarn (cp_lexer_peek_token (parser->lexer)->location, - OPT_Wpedantic, "nested inline namespace definitions only " - "available with %<-std=c++20%> or %<-std=gnu++20%>"); + OPT_Wc__20_extensions, "nested inline namespace " + "definitions only available with %<-std=c++20%> or " + "%<-std=gnu++20%>"); cp_lexer_consume_token (parser->lexer); } @@ -20380,8 +21139,8 @@ cp_parser_namespace_definition (cp_parser* parser) break; } - if (!nested_definition_count && cxx_dialect < cxx17) - pedwarn (input_location, OPT_Wpedantic, + if (!nested_definition_count && pedantic && cxx_dialect < cxx17) + pedwarn (input_location, OPT_Wc__17_extensions, "nested namespace definitions only available with " "%<-std=c++17%> or %<-std=gnu++17%>"); @@ -20640,7 +21399,7 @@ cp_parser_using_declaration (cp_parser* parser, { cp_token *ell = cp_lexer_consume_token (parser->lexer); if (cxx_dialect < cxx17) - pedwarn (ell->location, 0, + pedwarn (ell->location, OPT_Wc__17_extensions, "pack expansion in using-declaration only available " "with %<-std=c++17%> or %<-std=gnu++17%>"); qscope = make_pack_expansion (qscope); @@ -20673,7 +21432,7 @@ cp_parser_using_declaration (cp_parser* parser, { cp_token *comma = cp_lexer_consume_token (parser->lexer); if (cxx_dialect < cxx17) - pedwarn (comma->location, 0, + pedwarn (comma->location, OPT_Wc__17_extensions, "comma-separated list in using-declaration only available " "with %<-std=c++17%> or %<-std=gnu++17%>"); goto again; @@ -20901,14 +21660,21 @@ cp_parser_alias_declaration (cp_parser* parser) /* Parse a using-directive. using-directive: - using namespace :: [opt] nested-name-specifier [opt] - namespace-name ; */ + attribute-specifier-seq [opt] using namespace :: [opt] + nested-name-specifier [opt] namespace-name ; */ static void cp_parser_using_directive (cp_parser* parser) { tree namespace_decl; - tree attribs; + tree attribs = cp_parser_std_attribute_spec_seq (parser); + if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) + { + /* Error during attribute parsing that resulted in skipping + to next semicolon. */ + cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); + return; + } /* Look for the `using' keyword. */ cp_parser_require_keyword (parser, RID_USING, RT_USING); @@ -20925,8 +21691,9 @@ cp_parser_using_directive (cp_parser* parser) /* Get the namespace being used. */ namespace_decl = cp_parser_namespace_name (parser); cp_warn_deprecated_use_scopes (namespace_decl); - /* And any specified attributes. */ - attribs = cp_parser_attributes_opt (parser); + /* And any specified GNU attributes. */ + if (cp_next_tokens_can_be_gnu_attribute_p (parser)) + attribs = chainon (attribs, cp_parser_gnu_attributes_opt (parser)); /* Update the symbol table. */ finish_using_directive (namespace_decl, attribs); @@ -20989,9 +21756,10 @@ cp_parser_asm_definition (cp_parser* parser) functions. */ if (parser->in_function_body && DECL_DECLARED_CONSTEXPR_P (current_function_decl) - && (cxx_dialect < cxx20)) - pedwarn (asm_loc, 0, "%<asm%> in %<constexpr%> function only available " - "with %<-std=c++20%> or %<-std=gnu++20%>"); + && cxx_dialect < cxx20) + pedwarn (asm_loc, OPT_Wc__20_extensions, "%<asm%> in %<constexpr%> " + "function only available with %<-std=c++20%> or " + "%<-std=gnu++20%>"); /* Handle the asm-qualifier-list. */ location_t volatile_loc = UNKNOWN_LOCATION; @@ -21372,6 +22140,37 @@ warn_about_ambiguous_parse (const cp_decl_specifier_seq *decl_specifiers, } } +/* If DECLARATOR with DECL_SPECS is a function declarator that has + the form of a deduction guide, tag it as such. CTOR_DTOR_OR_CONV_P + has the same meaning as in cp_parser_declarator. */ + +static void +cp_parser_maybe_adjust_declarator_for_dguide (cp_parser *parser, + cp_decl_specifier_seq *decl_specs, + cp_declarator *declarator, + int *ctor_dtor_or_conv_p) +{ + if (cxx_dialect >= cxx17 + && *ctor_dtor_or_conv_p <= 0 + && !decl_specs->type + && !decl_specs->any_type_specifiers_p + && function_declarator_p (declarator)) + { + cp_declarator *id = get_id_declarator (declarator); + tree name = id->u.id.unqualified_name; + parser->scope = id->u.id.qualifying_scope; + tree tmpl = cp_parser_lookup_name_simple (parser, name, id->id_loc); + if (tmpl + && (DECL_CLASS_TEMPLATE_P (tmpl) + || DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))) + { + id->u.id.unqualified_name = dguide_name (tmpl); + id->u.id.sfk = sfk_deduction_guide; + *ctor_dtor_or_conv_p = 1; + } + } +} + /* Declarators [gram.dcl.decl] */ /* Parse an init-declarator. @@ -21470,10 +22269,6 @@ cp_parser_init_declarator (cp_parser* parser, if (decl_spec_seq_has_spec_p (decl_specifiers, ds_consteval)) flags |= CP_PARSER_FLAGS_CONSTEVAL; - /* Gather the attributes that were provided with the - decl-specifiers. */ - prefix_attributes = decl_specifiers->attributes; - /* Assume that this is not the declarator for a function definition. */ if (function_definition_p) @@ -21537,6 +22332,10 @@ cp_parser_init_declarator (cp_parser* parser, else asm_specification = NULL_TREE; + /* Gather the attributes that were provided with the + decl-specifiers. */ + prefix_attributes = decl_specifiers->attributes; + /* Look for attributes. */ attributes_start_token = cp_lexer_peek_token (parser->lexer); attributes = cp_parser_attributes_opt (parser); @@ -21548,25 +22347,13 @@ cp_parser_init_declarator (cp_parser* parser, if (function_declarator_p (declarator)) { - /* Handle C++17 deduction guides. */ - if (!decl_specifiers->type - && !decl_specifiers->any_type_specifiers_p - && ctor_dtor_or_conv_p <= 0 - && cxx_dialect >= cxx17) - { - cp_declarator *id = get_id_declarator (declarator); - tree name = id->u.id.unqualified_name; - parser->scope = id->u.id.qualifying_scope; - tree tmpl = cp_parser_lookup_name_simple (parser, name, id->id_loc); - if (tmpl - && (DECL_CLASS_TEMPLATE_P (tmpl) - || DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))) - { - id->u.id.unqualified_name = dguide_name (tmpl); - id->u.id.sfk = sfk_deduction_guide; - ctor_dtor_or_conv_p = 1; - } - } + /* Handle C++17 deduction guides. Note that class-scope + non-template deduction guides are instead handled in + cp_parser_member_declaration. */ + cp_parser_maybe_adjust_declarator_for_dguide (parser, + decl_specifiers, + declarator, + &ctor_dtor_or_conv_p); if (!member_p && !cp_parser_error_occurred (parser)) warn_about_ambiguous_parse (decl_specifiers, declarator); @@ -21972,12 +22759,10 @@ cp_parser_declarator (cp_parser* parser, cp_parser_parse_tentatively (parser); /* Parse the dependent declarator. */ - declarator = cp_parser_declarator (parser, dcl_kind, - CP_PARSER_FLAGS_NONE, + declarator = cp_parser_declarator (parser, dcl_kind, flags, /*ctor_dtor_or_conv_p=*/NULL, /*parenthesized_p=*/NULL, - /*member_p=*/false, - friend_p, /*static_p=*/false); + member_p, friend_p, static_p); /* If we are parsing an abstract-declarator, we must handle the case where the dependent declarator is absent. */ @@ -22171,7 +22956,7 @@ cp_parser_direct_declarator (cp_parser* parser, tree save_ccp = current_class_ptr; tree save_ccr = current_class_ref; - if (memfn && !friend_p) + if (memfn && !friend_p && !static_p) /* DR 1207: 'this' is in scope after the cv-quals. */ inject_this_parameter (current_class_type, cv_quals); @@ -22187,13 +22972,27 @@ cp_parser_direct_declarator (cp_parser* parser, attrs = cp_parser_std_attribute_spec_seq (parser); + cp_omp_declare_simd_data odsd; + if ((flag_openmp || flag_openmp_simd) + && declarator + && declarator->std_attributes + && declarator->kind == cdk_id) + { + tree *pa = &declarator->std_attributes; + cp_parser_handle_directive_omp_attributes (parser, pa, + &odsd, false); + } + /* In here, we handle cases where attribute is used after the function declaration. For example: void func (int x) __attribute__((vector(..))); */ tree gnu_attrs = NULL_TREE; tree requires_clause = NULL_TREE; - late_return = (cp_parser_late_return_type_opt - (parser, declarator, requires_clause)); + late_return + = cp_parser_late_return_type_opt (parser, declarator, + requires_clause); + + cp_finalize_omp_declare_simd (parser, &odsd); /* Parse the virt-specifier-seq. */ virt_specifiers = cp_parser_virt_specifier_seq_opt (parser); @@ -22909,7 +23708,7 @@ cp_parser_tx_qualifier_opt (cp_parser *parser) tree name = token->u.value; const char *p = IDENTIFIER_POINTER (name); const int len = strlen ("transaction_safe"); - if (!strncmp (p, "transaction_safe", len)) + if (startswith (p, "transaction_safe")) { p += len; if (*p == '\0' @@ -23225,10 +24024,13 @@ cp_parser_type_id_1 (cp_parser *parser, cp_parser_flags flags, location_t loc = type_specifier_seq.locations[ds_type_spec]; if (tree tmpl = CLASS_PLACEHOLDER_TEMPLATE (auto_node)) { - error_at (loc, "missing template arguments after %qT", - auto_node); - inform (DECL_SOURCE_LOCATION (tmpl), "%qD declared here", - tmpl); + if (!cp_parser_simulate_error (parser)) + { + error_at (loc, "missing template arguments after %qT", + auto_node); + 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", @@ -23559,11 +24361,11 @@ cp_parser_parameter_declaration_list (cp_parser* parser, cp_parser_flags flags) /*template_parm_p=*/false, &parenthesized_p); - /* We don't know yet if the enclosing context is deprecated, so wait - and warn in grokparms if appropriate. */ - deprecated_state = DEPRECATED_SUPPRESS; + /* We don't know yet if the enclosing context is unavailable or deprecated, + so wait and deal with it in grokparms if appropriate. */ + deprecated_state = UNAVAILABLE_DEPRECATED_SUPPRESS; - if (parameter) + if (parameter && !cp_parser_error_occurred (parser)) { decl = grokdeclarator (parameter->declarator, ¶meter->decl_specifiers, @@ -23778,7 +24580,7 @@ cp_parser_parameter_declaration (cp_parser *parser, parser->default_arg_ok_p = false; /* After seeing a decl-specifier-seq, if the next token is not a - "(", there is no possibility that the code is a valid + "(" or "{", there is no possibility that the code is a valid expression. Therefore, if parsing tentatively, we commit at this point. */ if (!parser->in_template_argument_list_p @@ -23791,9 +24593,18 @@ cp_parser_parameter_declaration (cp_parser *parser, of some object of type "char" to "int". */ && !parser->in_type_id_in_expr_p && cp_parser_uncommitted_to_tentative_parse_p (parser) - && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE) && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)) - cp_parser_commit_to_tentative_parse (parser); + { + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + { + if (decl_specifiers.type + && template_placeholder_p (decl_specifiers.type)) + /* This is a CTAD expression, not a parameter declaration. */ + cp_parser_simulate_error (parser); + } + else + cp_parser_commit_to_tentative_parse (parser); + } /* Parse the declarator. */ declarator_token_start = token; declarator = cp_parser_declarator (parser, @@ -23993,6 +24804,10 @@ cp_parser_default_argument (cp_parser *parser, bool template_parm_p) set correctly. */ saved_greater_than_is_operator_p = parser->greater_than_is_operator_p; parser->greater_than_is_operator_p = !template_parm_p; + auto odsd = make_temp_override (parser->omp_declare_simd, NULL); + auto ord = make_temp_override (parser->oacc_routine, NULL); + auto oafp = make_temp_override (parser->omp_attrs_forbidden_p, false); + /* Local variable names (and the `this' keyword) may not appear in a default argument. */ saved_local_variables_forbidden_p = parser->local_variables_forbidden_p; @@ -24060,11 +24875,11 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser, && cxx_dialect < cxx20) { if (DECL_CONSTRUCTOR_P (current_function_decl)) - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__20_extensions, "function-try-block body of %<constexpr%> constructor only " "available with %<-std=c++20%> or %<-std=gnu++20%>"); else - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__20_extensions, "function-try-block body of %<constexpr%> function only " "available with %<-std=c++20%> or %<-std=gnu++20%>"); } @@ -24191,7 +25006,7 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p) { initializer = cp_parser_constant_expression (parser, - /*allow_non_constant_p=*/true, + /*allow_non_constant_p=*/2, non_constant_p); } else @@ -24387,8 +25202,8 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p, || (cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_OPEN_BRACE))) { - if (cxx_dialect < cxx20) - pedwarn (loc, OPT_Wpedantic, + if (pedantic && cxx_dialect < cxx20) + pedwarn (loc, OPT_Wc__20_extensions, "C++ designated initializers only available with " "%<-std=c++20%> or %<-std=gnu++20%>"); /* Consume the `.'. */ @@ -24617,7 +25432,7 @@ cp_parser_class_name (cp_parser *parser, const bool typename_p = (typename_keyword_p && parser->scope && TYPE_P (parser->scope) - && dependent_type_p (parser->scope)); + && dependent_scope_p (parser->scope)); /* Handle the common case (an identifier, but not a template-id) efficiently. */ if (token->type == CPP_NAME @@ -24689,9 +25504,7 @@ cp_parser_class_name (cp_parser *parser, decl = cp_parser_maybe_treat_template_as_class (decl, class_head_p); /* If this is a typename, create a TYPENAME_TYPE. */ - if (typename_p - && decl != error_mark_node - && !is_overloaded_fn (decl)) + if (typename_p && decl != error_mark_node) { decl = make_typename_type (scope, decl, typename_type, /*complain=*/tf_error); @@ -25105,7 +25918,8 @@ cp_parser_class_specifier_1 (cp_parser* parser) so that maybe_instantiate_noexcept can tsubst the NOEXCEPT_EXPR in the pattern. */ for (tree i : DEFPARSE_INSTANTIATIONS (def_parse)) - DEFERRED_NOEXCEPT_PATTERN (TREE_PURPOSE (i)) = TREE_PURPOSE (spec); + DEFERRED_NOEXCEPT_PATTERN (TREE_PURPOSE (i)) + = spec ? TREE_PURPOSE (spec) : error_mark_node; /* Restore the state of local_variables_forbidden_p. */ parser->local_variables_forbidden_p = local_variables_forbidden_p; @@ -25637,7 +26451,13 @@ cp_parser_class_head (cp_parser* parser, until the entire list has been seen, as per [class.access.general]. */ push_deferring_access_checks (dk_deferred); if (cp_lexer_next_token_is (parser->lexer, CPP_COLON)) - bases = cp_parser_base_clause (parser); + { + if (type) + pushclass (type); + bases = cp_parser_base_clause (parser); + if (type) + popclass (); + } else bases = NULL_TREE; @@ -25725,10 +26545,11 @@ cp_parser_type_parameter_key (cp_parser* parser) if ((tag_type = cp_parser_token_is_type_parameter_key (token)) != none_type) { cp_lexer_consume_token (parser->lexer); - if (pedantic && tag_type == typename_type && cxx_dialect < cxx17) + if (pedantic && tag_type == typename_type + && cxx_dialect < cxx17) /* typename is not allowed in a template template parameter by the standard until C++17. */ - pedwarn (token->location, OPT_Wpedantic, + pedwarn (token->location, OPT_Wc__17_extensions, "ISO C++ forbids typename key in template template parameter;" " use %<-std=c++17%> or %<-std=gnu++17%>"); } @@ -25923,8 +26744,9 @@ cp_parser_member_declaration (cp_parser* parser) parser->colon_corrects_to_scope_p = false; + cp_omp_declare_simd_data odsd; if (cp_parser_using_declaration (parser, /*access_declaration=*/true)) - goto out; + goto out; /* Parse the decl-specifier-seq. */ decl_spec_token_start = cp_lexer_peek_token (parser->lexer); @@ -25933,6 +26755,12 @@ cp_parser_member_declaration (cp_parser* parser) | CP_PARSER_FLAGS_TYPENAME_OPTIONAL), &decl_specifiers, &declares_class_or_enum); + + if (decl_specifiers.attributes && (flag_openmp || flag_openmp_simd)) + cp_parser_handle_directive_omp_attributes (parser, + &decl_specifiers.attributes, + &odsd, true); + /* Check for an invalid type-name. */ if (!decl_specifiers.any_type_specifiers_p && cp_parser_parse_and_diagnose_invalid_type_name (parser)) @@ -25992,6 +26820,19 @@ cp_parser_member_declaration (cp_parser* parser) if (type && TREE_CODE (type) == TYPE_DECL) type = TREE_TYPE (type); } + /* Warn if an attribute cannot appear here, as per + [dcl.attr.grammar]/5. But not when declares_class_or_enum: + we ignore attributes in elaborated-type-specifiers. */ + if (!declares_class_or_enum + && cxx11_attribute_p (decl_specifiers.attributes)) + { + decl_specifiers.attributes = NULL_TREE; + if (warning_at (decl_spec_token_start->location, + OPT_Wattributes, "attribute ignored")) + inform (decl_spec_token_start->location, "an attribute " + "that appertains to a friend declaration that " + "is not a definition is ignored"); + } if (!type || !TYPE_P (type)) error_at (decl_spec_token_start->location, "friend declaration does not name a class or " @@ -26039,6 +26880,10 @@ cp_parser_member_declaration (cp_parser* parser) being declared. */ prefix_attributes = decl_specifiers.attributes; decl_specifiers.attributes = NULL_TREE; + if (parser->omp_declare_simd + && (parser->omp_declare_simd->attribs[0] + == &decl_specifiers.attributes)) + parser->omp_declare_simd->attribs[0] = &prefix_attributes; /* See if these declarations will be friends. */ friend_p = cp_parser_friend_p (&decl_specifiers); @@ -26109,7 +26954,7 @@ cp_parser_member_declaration (cp_parser* parser) = cp_lexer_peek_token (parser->lexer)->location; if (cxx_dialect < cxx20 && identifier != NULL_TREE) - pedwarn (loc, 0, + pedwarn (loc, OPT_Wc__20_extensions, "default member initializers for bit-fields " "only available with %<-std=c++20%> or " "%<-std=gnu++20%>"); @@ -26195,6 +27040,12 @@ cp_parser_member_declaration (cp_parser* parser) goto out; } + /* Handle class-scope non-template C++17 deduction guides. */ + cp_parser_maybe_adjust_declarator_for_dguide (parser, + &decl_specifiers, + declarator, + &ctor_dtor_or_conv_p); + if (declares_class_or_enum & 2) cp_parser_check_for_definition_in_return_type (declarator, decl_specifiers.type, @@ -26411,8 +27262,8 @@ cp_parser_member_declaration (cp_parser* parser) || !DECL_DECLARES_FUNCTION_P (decl)) finish_member_declaration (decl); - if (TREE_CODE (decl) == FUNCTION_DECL) - cp_parser_save_default_args (parser, decl); + if (DECL_DECLARES_FUNCTION_P (decl)) + cp_parser_save_default_args (parser, STRIP_TEMPLATE (decl)); else if (TREE_CODE (decl) == FIELD_DECL && DECL_INITIAL (decl)) /* Add DECL to the queue of NSDMI to be parsed later. */ @@ -26427,6 +27278,7 @@ cp_parser_member_declaration (cp_parser* parser) cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); out: parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; + cp_finalize_omp_declare_simd (parser, &odsd); } /* Parse a pure-specifier. @@ -27070,7 +27922,7 @@ cp_parser_try_block (cp_parser* parser) if (parser->in_function_body && DECL_DECLARED_CONSTEXPR_P (current_function_decl) && cxx_dialect < cxx20) - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__20_extensions, "%<try%> in %<constexpr%> function only " "available with %<-std=c++20%> or %<-std=gnu++20%>"); @@ -27718,6 +28570,92 @@ cp_parser_gnu_attribute_list (cp_parser* parser, bool exactly_one /* = false */) return nreverse (attribute_list); } +/* Parse arguments of omp::directive attribute. + + ( directive-name ,[opt] clause-list[opt] ) + + For directive just remember the first/last tokens for subsequent + parsing. */ + +static void +cp_parser_omp_directive_args (cp_parser *parser, tree attribute) +{ + cp_token *first = cp_lexer_peek_nth_token (parser->lexer, 2); + if (first->type == CPP_CLOSE_PAREN) + { + cp_lexer_consume_token (parser->lexer); + error_at (first->location, "expected OpenMP directive name"); + cp_lexer_consume_token (parser->lexer); + TREE_VALUE (attribute) = NULL_TREE; + return; + } + for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 2; n; --n) + cp_lexer_consume_token (parser->lexer); + cp_token *last = cp_lexer_peek_token (parser->lexer); + cp_lexer_consume_token (parser->lexer); + tree arg = make_node (DEFERRED_PARSE); + DEFPARSE_TOKENS (arg) = cp_token_cache_new (first, last); + DEFPARSE_INSTANTIATIONS (arg) = nullptr; + TREE_VALUE (attribute) = tree_cons (NULL_TREE, arg, TREE_VALUE (attribute)); +} + +/* Parse arguments of omp::sequence attribute. + + ( omp::[opt] directive-attr [ , omp::[opt] directive-attr ]... ) */ + +static void +cp_parser_omp_sequence_args (cp_parser *parser, tree attribute) +{ + matching_parens parens; + parens.consume_open (parser); + do + { + cp_token *token = cp_lexer_peek_token (parser->lexer); + if (token->type == CPP_NAME + && token->u.value == omp_identifier + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_SCOPE)) + { + cp_lexer_consume_token (parser->lexer); + cp_lexer_consume_token (parser->lexer); + token = cp_lexer_peek_token (parser->lexer); + } + bool directive = false; + const char *p; + if (token->type != CPP_NAME) + p = ""; + else + p = IDENTIFIER_POINTER (token->u.value); + if (strcmp (p, "directive") == 0) + directive = true; + else if (strcmp (p, "sequence") != 0) + { + error_at (token->location, "expected %<directive%> or %<sequence%>"); + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/true, + /*consume_paren=*/false); + if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) + break; + cp_lexer_consume_token (parser->lexer); + } + cp_lexer_consume_token (parser->lexer); + if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)) + cp_parser_required_error (parser, RT_OPEN_PAREN, false, + UNKNOWN_LOCATION); + else if (directive) + cp_parser_omp_directive_args (parser, attribute); + else + cp_parser_omp_sequence_args (parser, attribute); + if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) + break; + cp_lexer_consume_token (parser->lexer); + } + while (1); + if (!parens.require_close (parser)) + cp_parser_skip_to_closing_parenthesis (parser, true, false, + /*consume_paren=*/true); +} + /* Parse a standard C++11 attribute. The returned representation is a TREE_LIST which TREE_PURPOSE is @@ -27849,7 +28787,18 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns) /* Now parse the optional argument clause of the attribute. */ if (token->type != CPP_OPEN_PAREN) - return attribute; + { + if ((flag_openmp || flag_openmp_simd) + && attr_ns == omp_identifier + && (is_attribute_p ("directive", attr_id) + || is_attribute_p ("sequence", attr_id))) + { + error_at (token->location, "%<omp::%E%> attribute requires argument", + attr_id); + return NULL_TREE; + } + return attribute; + } { vec<tree, va_gc> *vec; @@ -27876,6 +28825,23 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns) if (as == NULL) { + if ((flag_openmp || flag_openmp_simd) && attr_ns == omp_identifier) + { + if (is_attribute_p ("directive", attr_id)) + { + cp_parser_omp_directive_args (parser, attribute); + return attribute; + } + else if (is_attribute_p ("sequence", attr_id)) + { + TREE_VALUE (TREE_PURPOSE (attribute)) + = get_identifier ("directive"); + cp_parser_omp_sequence_args (parser, attribute); + TREE_VALUE (attribute) = nreverse (TREE_VALUE (attribute)); + return attribute; + } + } + /* For unknown attributes, just skip balanced tokens instead of trying to parse the arguments. */ for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 1; n; --n) @@ -28029,7 +28995,7 @@ cp_parser_std_attribute_spec (cp_parser *parser) && cp_lexer_nth_token_is (parser->lexer, 3, CPP_COLON)) { if (cxx_dialect < cxx17) - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__17_extensions, "attribute using prefix only available " "with %<-std=c++17%> or %<-std=gnu++17%>"); @@ -28331,6 +29297,9 @@ cp_parser_label_declaration (cp_parser* parser) static tree cp_parser_concept_definition (cp_parser *parser) { + /* A concept definition is an unevaluated context. */ + cp_unevaluated u; + gcc_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_CONCEPT)); cp_lexer_consume_token (parser->lexer); @@ -28486,7 +29455,20 @@ cp_parser_constraint_requires_parens (cp_parser *parser, bool lambda_p) case CPP_PLUS_PLUS: case CPP_MINUS_MINUS: case CPP_DOT: + /* Unenclosed postfix operator. */ + return pce_maybe_postfix; + case CPP_DEREF: + /* A primary constraint that precedes the lambda-declarator of a + lambda expression is followed by trailing return type. + + []<typename T> requires C -> void {} + + Don't try to re-parse this as a postfix expression in + C++23 and later. In C++20 ( needs to come in between but we + allow it to be omitted with pedwarn. */ + if (lambda_p) + return pce_ok; /* Unenclosed postfix operator. */ return pce_maybe_postfix; } @@ -28692,6 +29674,9 @@ cp_parser_constraint_expression (cp_parser *parser) static tree cp_parser_requires_clause_opt (cp_parser *parser, bool lambda_p) { + /* A requires clause is an unevaluated context. */ + cp_unevaluated u; + cp_token *tok = cp_lexer_peek_token (parser->lexer); if (tok->keyword != RID_REQUIRES) { @@ -28835,8 +29820,11 @@ cp_parser_requirement_parameter_list (cp_parser *parser) if (parm == void_list_node || parm == explicit_void_list_node) break; tree decl = TREE_VALUE (parm); - DECL_CONTEXT (decl) = NULL_TREE; - CONSTRAINT_VAR_P (decl) = true; + if (decl != error_mark_node) + { + DECL_CONTEXT (decl) = NULL_TREE; + CONSTRAINT_VAR_P (decl) = true; + } } return parms; @@ -28932,6 +29920,25 @@ cp_parser_simple_requirement (cp_parser *parser) if (expr.get_location() == UNKNOWN_LOCATION) expr.set_location (start); + for (tree t = expr; ; ) + { + if (TREE_CODE (t) == TRUTH_ANDIF_EXPR + || TREE_CODE (t) == TRUTH_ORIF_EXPR) + { + t = TREE_OPERAND (t, 0); + continue; + } + if (concept_check_p (t)) + { + gcc_rich_location richloc (get_start (start)); + richloc.add_fixit_insert_before (start, "requires "); + warning_at (&richloc, OPT_Wmissing_requires, "testing " + "if a concept-id is a valid expression; add " + "%<requires%> to check satisfaction"); + } + break; + } + return finish_simple_requirement (expr.get_location (), expr); } @@ -29368,6 +30375,19 @@ cp_parser_lookup_name (cp_parser *parser, tree name, if (!decl || decl == error_mark_node) return error_mark_node; + /* If we have resolved the name of a member declaration, check to + see if the declaration is accessible. When the name resolves to + set of overloaded functions, accessibility is checked when + overload resolution is done. If we have a TREE_LIST, then the lookup + is either ambiguous or it found multiple injected-class-names, the + accessibility of which is trivially satisfied. + + During an explicit instantiation, access is not checked at all, + as per [temp.explicit]. */ + if (DECL_P (decl)) + check_accessibility_of_qualified_id (decl, object_type, parser->scope, + tf_warning_or_error); + /* Pull out the template from an injected-class-name (or multiple). */ if (is_template) decl = maybe_get_template_decl_from_type_decl (decl); @@ -29394,17 +30414,6 @@ cp_parser_lookup_name (cp_parser *parser, tree name, || TREE_CODE (decl) == UNBOUND_CLASS_TEMPLATE || BASELINK_P (decl)); - /* If we have resolved the name of a member declaration, check to - see if the declaration is accessible. When the name resolves to - set of overloaded functions, accessibility is checked when - overload resolution is done. - - During an explicit instantiation, access is not checked at all, - as per [temp.explicit]. */ - if (DECL_P (decl)) - check_accessibility_of_qualified_id (decl, object_type, parser->scope, - tf_warning_or_error); - maybe_record_typedef_use (decl); return cp_expr (decl, name_location); @@ -30414,6 +31423,13 @@ cp_parser_single_declaration (cp_parser* parser, | CP_PARSER_FLAGS_TYPENAME_OPTIONAL), &decl_specifiers, &declares_class_or_enum); + + cp_omp_declare_simd_data odsd; + if (decl_specifiers.attributes && (flag_openmp || flag_openmp_simd)) + cp_parser_handle_directive_omp_attributes (parser, + &decl_specifiers.attributes, + &odsd, true); + if (friend_p) *friend_p = cp_parser_friend_p (&decl_specifiers); @@ -30542,6 +31558,8 @@ cp_parser_single_declaration (cp_parser* parser, parser->qualifying_scope = NULL_TREE; parser->object_scope = NULL_TREE; + cp_finalize_omp_declare_simd (parser, &odsd); + return decl; } @@ -33034,6 +34052,7 @@ cp_parser_objc_message_expression (cp_parser* parser) { tree receiver, messageargs; + parser->objective_c_message_context_p = true; location_t start_loc = cp_lexer_peek_token (parser->lexer)->location; cp_lexer_consume_token (parser->lexer); /* Eat '['. */ receiver = cp_parser_objc_message_receiver (parser); @@ -33050,6 +34069,7 @@ cp_parser_objc_message_expression (cp_parser* parser) location_t combined_loc = make_location (start_loc, start_loc, end_loc); protected_set_expr_location (result, combined_loc); + parser->objective_c_message_context_p = false; return result; } @@ -34680,7 +35700,7 @@ cp_parser_objc_at_property_declaration (cp_parser *parser) /* Parse the optional attribute list. A list of parsed, but not verified, attributes. */ - vec<property_attribute_info *> prop_attr_list = vNULL; + auto_delete_vec<property_attribute_info> prop_attr_list; location_t loc = cp_lexer_peek_token (parser->lexer)->location; cp_lexer_consume_token (parser->lexer); /* Eat '@property'. */ @@ -34856,10 +35876,6 @@ cp_parser_objc_at_property_declaration (cp_parser *parser) } 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: @@ -34993,7 +36009,9 @@ cp_parser_omp_clause_name (cp_parser *parser) switch (p[0]) { case 'a': - if (!strcmp ("aligned", p)) + if (!strcmp ("affinity", p)) + result = PRAGMA_OMP_CLAUSE_AFFINITY; + else if (!strcmp ("aligned", p)) result = PRAGMA_OMP_CLAUSE_ALIGNED; else if (!strcmp ("allocate", p)) result = PRAGMA_OMP_CLAUSE_ALLOCATE; @@ -35039,7 +36057,9 @@ cp_parser_omp_clause_name (cp_parser *parser) result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE; break; case 'f': - if (!strcmp ("final", p)) + if (!strcmp ("filter", p)) + result = PRAGMA_OMP_CLAUSE_FILTER; + else if (!strcmp ("final", p)) result = PRAGMA_OMP_CLAUSE_FINAL; else if (!strcmp ("finalize", p)) result = PRAGMA_OACC_CLAUSE_FINALIZE; @@ -35091,6 +36111,8 @@ cp_parser_omp_clause_name (cp_parser *parser) result = PRAGMA_OACC_CLAUSE_NO_CREATE; else if (!strcmp ("nogroup", p)) result = PRAGMA_OMP_CLAUSE_NOGROUP; + else if (!strcmp ("nohost", p)) + result = PRAGMA_OACC_CLAUSE_NOHOST; else if (!strcmp ("nontemporal", p)) result = PRAGMA_OMP_CLAUSE_NONTEMPORAL; else if (!strcmp ("notinbranch", p)) @@ -35252,11 +36274,10 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, { tree name, decl; - if (kind == OMP_CLAUSE_DEPEND) + if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) cp_parser_parse_tentatively (parser); token = cp_lexer_peek_token (parser->lexer); if (kind != 0 - && current_class_ptr && cp_parser_is_keyword (token, RID_THIS)) { decl = finish_this_expr (); @@ -35282,7 +36303,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, /*optional_p=*/false); if (name == error_mark_node) { - if (kind == OMP_CLAUSE_DEPEND + if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) && cp_parser_simulate_error (parser)) goto depend_lvalue; goto skip_comma; @@ -35294,7 +36315,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, decl = name; if (decl == error_mark_node) { - if (kind == OMP_CLAUSE_DEPEND + if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) && cp_parser_simulate_error (parser)) goto depend_lvalue; cp_parser_name_lookup_error (parser, name, decl, NLE_NULL, @@ -35340,6 +36361,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, &idk, loc); } /* FALLTHROUGH. */ + case OMP_CLAUSE_AFFINITY: case OMP_CLAUSE_DEPEND: case OMP_CLAUSE_REDUCTION: case OMP_CLAUSE_IN_REDUCTION: @@ -35366,12 +36388,12 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, /* Look for `:'. */ if (!cp_parser_require (parser, CPP_COLON, RT_COLON)) { - if (kind == OMP_CLAUSE_DEPEND + if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) && cp_parser_simulate_error (parser)) goto depend_lvalue; goto skip_comma; } - if (kind == OMP_CLAUSE_DEPEND) + if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) cp_parser_commit_to_tentative_parse (parser); if (!cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_SQUARE)) @@ -35385,7 +36407,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE)) { - if (kind == OMP_CLAUSE_DEPEND + if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) && cp_parser_simulate_error (parser)) goto depend_lvalue; goto skip_comma; @@ -35398,7 +36420,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, break; } - if (kind == OMP_CLAUSE_DEPEND) + if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) { if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA) && cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN) @@ -36243,7 +37265,10 @@ cp_parser_omp_clause_num_threads (cp_parser *parser, tree list, } /* OpenMP 4.5: - num_tasks ( expression ) */ + num_tasks ( expression ) + + OpenMP 5.1: + num_tasks ( strict : expression ) */ static tree cp_parser_omp_clause_num_tasks (cp_parser *parser, tree list, @@ -36255,6 +37280,19 @@ cp_parser_omp_clause_num_tasks (cp_parser *parser, tree list, if (!parens.require_open (parser)) return list; + bool strict = false; + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON)) + { + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + if (!strcmp (IDENTIFIER_POINTER (id), "strict")) + { + strict = true; + cp_lexer_consume_token (parser->lexer); + cp_lexer_consume_token (parser->lexer); + } + } + t = cp_parser_assignment_expression (parser); if (t == error_mark_node @@ -36268,13 +37306,17 @@ cp_parser_omp_clause_num_tasks (cp_parser *parser, tree list, c = build_omp_clause (location, OMP_CLAUSE_NUM_TASKS); OMP_CLAUSE_NUM_TASKS_EXPR (c) = t; + OMP_CLAUSE_NUM_TASKS_STRICT (c) = strict; OMP_CLAUSE_CHAIN (c) = list; return c; } /* OpenMP 4.5: - grainsize ( expression ) */ + grainsize ( expression ) + + OpenMP 5.1: + grainsize ( strict : expression ) */ static tree cp_parser_omp_clause_grainsize (cp_parser *parser, tree list, @@ -36286,6 +37328,19 @@ cp_parser_omp_clause_grainsize (cp_parser *parser, tree list, if (!parens.require_open (parser)) return list; + bool strict = false; + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON)) + { + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + if (!strcmp (IDENTIFIER_POINTER (id), "strict")) + { + strict = true; + cp_lexer_consume_token (parser->lexer); + cp_lexer_consume_token (parser->lexer); + } + } + t = cp_parser_assignment_expression (parser); if (t == error_mark_node @@ -36299,6 +37354,7 @@ cp_parser_omp_clause_grainsize (cp_parser *parser, tree list, c = build_omp_clause (location, OMP_CLAUSE_GRAINSIZE); OMP_CLAUSE_GRAINSIZE_EXPR (c) = t; + OMP_CLAUSE_GRAINSIZE_STRICT (c) = strict; OMP_CLAUSE_CHAIN (c) = list; return c; @@ -36373,6 +37429,34 @@ cp_parser_omp_clause_hint (cp_parser *parser, tree list, location_t location) return c; } +/* OpenMP 5.1: + filter ( integer-expression ) */ + +static tree +cp_parser_omp_clause_filter (cp_parser *parser, tree list, location_t location) +{ + tree t, c; + + matching_parens parens; + if (!parens.require_open (parser)) + return list; + + t = cp_parser_assignment_expression (parser); + + if (t == error_mark_node + || !parens.require_close (parser)) + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + check_no_duplicate_clause (list, OMP_CLAUSE_FILTER, "filter", location); + + c = build_omp_clause (location, OMP_CLAUSE_FILTER); + OMP_CLAUSE_FILTER_EXPR (c) = t; + OMP_CLAUSE_CHAIN (c) = list; + + return c; +} + /* OpenMP 4.5: defaultmap ( tofrom : scalar ) @@ -37463,13 +38547,14 @@ cp_parser_omp_clause_depend_sink (cp_parser *parser, location_t clause_loc, OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1; } - if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) + if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA) + || !cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) break; cp_lexer_consume_token (parser->lexer); } - if (cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN) && vec) + if (vec) { tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND); OMP_CLAUSE_DEPEND_KIND (u) = OMP_CLAUSE_DEPEND_SINK; @@ -37638,6 +38723,64 @@ cp_parser_omp_iterators (cp_parser *parser) return ret ? ret : error_mark_node; } +/* OpenMP 5.0: + affinity ( [aff-modifier :] variable-list ) + aff-modifier: + iterator ( iterators-definition ) */ + +static tree +cp_parser_omp_clause_affinity (cp_parser *parser, tree list) +{ + tree nlist, c, iterators = NULL_TREE; + + matching_parens parens; + if (!parens.require_open (parser)) + return list; + + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + const char *p = IDENTIFIER_POINTER (id); + bool parse_iter = ((strcmp ("iterator", p) == 0) + && (cp_lexer_nth_token_is (parser->lexer, 2, + CPP_OPEN_PAREN))); + if (parse_iter) + { + size_t n = cp_parser_skip_balanced_tokens (parser, 2); + parse_iter = cp_lexer_nth_token_is (parser->lexer, n, CPP_COLON); + } + if (parse_iter) + { + begin_scope (sk_omp, NULL); + iterators = cp_parser_omp_iterators (parser); + if (!cp_parser_require (parser, CPP_COLON, RT_COLON)) + { + if (iterators) + poplevel (0, 1, 0); + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return list; + } + } + } + nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_AFFINITY, + list, NULL); + if (iterators) + { + tree block = poplevel (1, 1, 0); + if (iterators != error_mark_node) + { + TREE_VEC_ELT (iterators, 5) = block; + for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) + OMP_CLAUSE_DECL (c) = build_tree_list (iterators, + OMP_CLAUSE_DECL (c)); + } + } + return nlist; +} + /* OpenMP 4.0: depend ( depend-kind : variable-list ) @@ -37731,7 +38874,13 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc) goto resync_fail; if (kind == OMP_CLAUSE_DEPEND_SINK) - nlist = cp_parser_omp_clause_depend_sink (parser, loc, list); + { + nlist = cp_parser_omp_clause_depend_sink (parser, loc, list); + if (!parens.require_close (parser)) + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + } else { nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_DEPEND, @@ -37778,40 +38927,90 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc) map-kind: alloc | to | from | tofrom | release | delete - map ( always [,] map-kind: variable-list ) */ + map ( always [,] map-kind: variable-list ) + + OpenMP 5.0: + map ( [map-type-modifier[,] ...] map-kind: variable-list ) + + map-type-modifier: + always | close */ static tree cp_parser_omp_clause_map (cp_parser *parser, tree list) { tree nlist, c; enum gomp_map_kind kind = GOMP_MAP_TOFROM; - bool always = false; if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) return list; - if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + int pos = 1; + int map_kind_pos = 0; + while (cp_lexer_peek_nth_token (parser->lexer, pos)->type == CPP_NAME + || cp_lexer_peek_nth_token (parser->lexer, pos)->keyword == RID_DELETE) { - tree id = cp_lexer_peek_token (parser->lexer)->u.value; - const char *p = IDENTIFIER_POINTER (id); + if (cp_lexer_peek_nth_token (parser->lexer, pos + 1)->type == CPP_COLON) + { + map_kind_pos = pos; + break; + } + + if (cp_lexer_peek_nth_token (parser->lexer, pos + 1)->type == CPP_COMMA) + pos++; + pos++; + } + + bool always_modifier = false; + bool close_modifier = false; + for (int pos = 1; pos < map_kind_pos; ++pos) + { + cp_token *tok = cp_lexer_peek_token (parser->lexer); + if (tok->type == CPP_COMMA) + { + cp_lexer_consume_token (parser->lexer); + continue; + } + const char *p = IDENTIFIER_POINTER (tok->u.value); if (strcmp ("always", p) == 0) { - int nth = 2; - if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_COMMA) - nth++; - if ((cp_lexer_peek_nth_token (parser->lexer, nth)->type == CPP_NAME - || (cp_lexer_peek_nth_token (parser->lexer, nth)->keyword - == RID_DELETE)) - && (cp_lexer_peek_nth_token (parser->lexer, nth + 1)->type - == CPP_COLON)) + if (always_modifier) { - always = true; - cp_lexer_consume_token (parser->lexer); - if (nth == 3) - cp_lexer_consume_token (parser->lexer); + cp_parser_error (parser, "too many %<always%> modifiers"); + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return list; + } + always_modifier = true; + } + else if (strcmp ("close", p) == 0) + { + if (close_modifier) + { + cp_parser_error (parser, "too many %<close%> modifiers"); + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return list; } + close_modifier = true; + } + else + { + cp_parser_error (parser, "%<#pragma omp target%> with " + "modifier other than %<always%> or %<close%>" + "on %<map%> clause"); + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return list; } + + cp_lexer_consume_token (parser->lexer); } if (cp_lexer_next_token_is (parser->lexer, CPP_NAME) @@ -37823,11 +39022,11 @@ cp_parser_omp_clause_map (cp_parser *parser, tree list) if (strcmp ("alloc", p) == 0) kind = GOMP_MAP_ALLOC; else if (strcmp ("to", p) == 0) - kind = always ? GOMP_MAP_ALWAYS_TO : GOMP_MAP_TO; + kind = always_modifier ? GOMP_MAP_ALWAYS_TO : GOMP_MAP_TO; else if (strcmp ("from", p) == 0) - kind = always ? GOMP_MAP_ALWAYS_FROM : GOMP_MAP_FROM; + kind = always_modifier ? GOMP_MAP_ALWAYS_FROM : GOMP_MAP_FROM; else if (strcmp ("tofrom", p) == 0) - kind = always ? GOMP_MAP_ALWAYS_TOFROM : GOMP_MAP_TOFROM; + kind = always_modifier ? GOMP_MAP_ALWAYS_TOFROM : GOMP_MAP_TOFROM; else if (strcmp ("release", p) == 0) kind = GOMP_MAP_RELEASE; else @@ -37859,18 +39058,57 @@ cp_parser_omp_clause_map (cp_parser *parser, tree list) } /* OpenMP 4.0: - device ( expression ) */ + device ( expression ) + + OpenMP 5.0: + device ( [device-modifier :] integer-expression ) + + device-modifier: + ancestor | device_num */ static tree cp_parser_omp_clause_device (cp_parser *parser, tree list, location_t location) { tree t, c; + bool ancestor = false; matching_parens parens; if (!parens.require_open (parser)) return list; + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON)) + { + cp_token *tok = cp_lexer_peek_token (parser->lexer); + const char *p = IDENTIFIER_POINTER (tok->u.value); + if (strcmp ("ancestor", p) == 0) + { + ancestor = true; + + /* A requires directive with the reverse_offload clause must be + specified. */ + if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0) + { + error_at (tok->location, "%<ancestor%> device modifier not " + "preceded by %<requires%> directive " + "with %<reverse_offload%> clause"); + cp_parser_skip_to_closing_parenthesis (parser, true, false, true); + return list; + } + } + else if (strcmp ("device_num", p) == 0) + ; + else + { + error_at (tok->location, "expected %<ancestor%> or %<device_num%>"); + cp_parser_skip_to_closing_parenthesis (parser, true, false, true); + return list; + } + cp_lexer_consume_token (parser->lexer); + cp_lexer_consume_token (parser->lexer); + } + t = cp_parser_assignment_expression (parser); if (t == error_mark_node @@ -37885,6 +39123,7 @@ cp_parser_omp_clause_device (cp_parser *parser, tree list, c = build_omp_clause (location, OMP_CLAUSE_DEVICE); OMP_CLAUSE_DEVICE_ID (c) = t; OMP_CLAUSE_CHAIN (c) = list; + OMP_CLAUSE_DEVICE_ANCESTOR (c) = ancestor; return c; } @@ -37945,7 +39184,8 @@ cp_parser_omp_clause_dist_schedule (cp_parser *parser, tree list, proc_bind ( proc-bind-kind ) proc-bind-kind: - master | close | spread */ + primary | master | close | spread + where OpenMP 5.1 added 'primary' and deprecated the alias 'master'. */ static tree cp_parser_omp_clause_proc_bind (cp_parser *parser, tree list, @@ -37962,7 +39202,9 @@ cp_parser_omp_clause_proc_bind (cp_parser *parser, tree list, tree id = cp_lexer_peek_token (parser->lexer)->u.value; const char *p = IDENTIFIER_POINTER (id); - if (strcmp ("master", p) == 0) + if (strcmp ("primary", p) == 0) + kind = OMP_CLAUSE_PROC_BIND_PRIMARY; + else if (strcmp ("master", p) == 0) kind = OMP_CLAUSE_PROC_BIND_MASTER; else if (strcmp ("close", p) == 0) kind = OMP_CLAUSE_PROC_BIND_CLOSE; @@ -38206,6 +39448,11 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask, clauses = cp_parser_oacc_data_clause (parser, c_kind, clauses); c_name = "no_create"; break; + case PRAGMA_OACC_CLAUSE_NOHOST: + clauses = cp_parser_oacc_simple_clause (here, OMP_CLAUSE_NOHOST, + clauses); + c_name = "nohost"; + break; case PRAGMA_OACC_CLAUSE_NUM_GANGS: code = OMP_CLAUSE_NUM_GANGS; c_name = "num_gangs"; @@ -38322,7 +39569,12 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, if (nested && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)) break; - if (!first) + if (!first + /* OpenMP 5.1 allows optional comma in between directive-name and + clauses everywhere, but as we aren't done with OpenMP 5.0 + implementation yet, let's allow it for now only in C++11 + attributes. */ + || (parser->lexer->in_omp_attribute_pragma && nested != 2)) { if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) cp_lexer_consume_token (parser->lexer); @@ -38361,6 +39613,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, token->location, false); c_name = "default"; break; + case PRAGMA_OMP_CLAUSE_FILTER: + clauses = cp_parser_omp_clause_filter (parser, clauses, + token->location); + c_name = "filter"; + break; case PRAGMA_OMP_CLAUSE_FINAL: clauses = cp_parser_omp_clause_final (parser, clauses, token->location); c_name = "final"; @@ -38580,6 +39837,10 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, } c_name = "linear"; break; + case PRAGMA_OMP_CLAUSE_AFFINITY: + clauses = cp_parser_omp_clause_affinity (parser, clauses); + c_name = "affinity"; + break; case PRAGMA_OMP_CLAUSE_DEPEND: clauses = cp_parser_omp_clause_depend (parser, clauses, token->location); @@ -38702,11 +39963,14 @@ cp_parser_end_omp_structured_block (cp_parser *parser, unsigned save) } static tree -cp_parser_omp_structured_block (cp_parser *parser, bool *if_p) +cp_parser_omp_structured_block (cp_parser *parser, bool *if_p, + bool disallow_omp_attrs = true) { tree stmt = begin_omp_structured_block (); unsigned int save = cp_parser_begin_omp_structured_block (parser); + if (disallow_omp_attrs) + parser->omp_attrs_forbidden_p = true; cp_parser_statement (parser, NULL_TREE, false, if_p); cp_parser_end_omp_structured_block (parser, save); @@ -38723,6 +39987,12 @@ cp_parser_omp_allocate (cp_parser *parser, cp_token *pragma_tok) location_t loc = pragma_tok->location; tree nl = cp_parser_omp_var_list (parser, OMP_CLAUSE_ALLOCATE, NULL_TREE); + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if (parser->lexer->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) + cp_lexer_consume_token (parser->lexer); + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { matching_parens parens; @@ -38814,7 +40084,10 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc) while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) { - if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if ((!first || parser->lexer->in_omp_attribute_pragma) + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) cp_lexer_consume_token (parser->lexer); first = false; @@ -38920,7 +40193,6 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc) memory_order = OMP_MEMORY_ORDER_ACQUIRE; break; case NOP_EXPR: /* atomic write */ - case OMP_ATOMIC: memory_order = OMP_MEMORY_ORDER_RELEASE; break; default: @@ -38936,31 +40208,24 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc) switch (code) { case OMP_ATOMIC_READ: - if (memory_order == OMP_MEMORY_ORDER_ACQ_REL - || memory_order == OMP_MEMORY_ORDER_RELEASE) + if (memory_order == OMP_MEMORY_ORDER_RELEASE) { error_at (loc, "%<#pragma omp atomic read%> incompatible with " - "%<acq_rel%> or %<release%> clauses"); + "%<release%> clause"); memory_order = OMP_MEMORY_ORDER_SEQ_CST; } + else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL) + memory_order = OMP_MEMORY_ORDER_ACQUIRE; break; case NOP_EXPR: /* atomic write */ - if (memory_order == OMP_MEMORY_ORDER_ACQ_REL - || memory_order == OMP_MEMORY_ORDER_ACQUIRE) + if (memory_order == OMP_MEMORY_ORDER_ACQUIRE) { error_at (loc, "%<#pragma omp atomic write%> incompatible with " - "%<acq_rel%> or %<acquire%> clauses"); - memory_order = OMP_MEMORY_ORDER_SEQ_CST; - } - break; - case OMP_ATOMIC: - if (memory_order == OMP_MEMORY_ORDER_ACQ_REL - || memory_order == OMP_MEMORY_ORDER_ACQUIRE) - { - error_at (loc, "%<#pragma omp atomic update%> incompatible with " - "%<acq_rel%> or %<acquire%> clauses"); + "%<acquire%> clause"); memory_order = OMP_MEMORY_ORDER_SEQ_CST; } + else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL) + memory_order = OMP_MEMORY_ORDER_RELEASE; break; default: break; @@ -39376,6 +40641,10 @@ cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok) tree clause = NULL_TREE; enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_SOURCE; location_t c_loc = cp_lexer_peek_token (parser->lexer)->location; + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if (parser->lexer->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + cp_lexer_consume_token (parser->lexer); if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { tree id = cp_lexer_peek_token (parser->lexer)->u.value; @@ -39456,11 +40725,18 @@ static void cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok) { enum memmodel mo = MEMMODEL_LAST; + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if (parser->lexer->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) + cp_lexer_consume_token (parser->lexer); if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { tree id = cp_lexer_peek_token (parser->lexer)->u.value; const char *p = IDENTIFIER_POINTER (id); - if (!strcmp (p, "acq_rel")) + if (!strcmp (p, "seq_cst")) + mo = MEMMODEL_SEQ_CST; + else if (!strcmp (p, "acq_rel")) mo = MEMMODEL_ACQ_REL; else if (!strcmp (p, "release")) mo = MEMMODEL_RELEASE; @@ -39468,7 +40744,8 @@ cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok) mo = MEMMODEL_ACQUIRE; else error_at (cp_lexer_peek_token (parser->lexer)->location, - "expected %<acq_rel%>, %<release%> or %<acquire%>"); + "expected %<seq_cst%>, %<acq_rel%>, %<release%> or " + "%<acquire%>"); cp_lexer_consume_token (parser->lexer); } if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) @@ -40040,6 +41317,77 @@ cp_finish_omp_range_for (tree orig, tree begin) cp_finish_decomp (decl, decomp_first_name, decomp_cnt); } +/* Return true if next tokens contain a standard attribute that contains + omp::directive (DIRECTIVE). */ + +static bool +cp_parser_omp_section_scan (cp_parser *parser, const char *directive, + bool tentative) +{ + size_t n = cp_parser_skip_attributes_opt (parser, 1), i; + if (n < 10) + return false; + for (i = 5; i < n - 4; i++) + if (cp_lexer_nth_token_is (parser->lexer, i, CPP_NAME) + && cp_lexer_nth_token_is (parser->lexer, i + 1, CPP_OPEN_PAREN) + && cp_lexer_nth_token_is (parser->lexer, i + 2, CPP_NAME)) + { + tree first = cp_lexer_peek_nth_token (parser->lexer, i)->u.value; + tree second = cp_lexer_peek_nth_token (parser->lexer, i + 2)->u.value; + if (strcmp (IDENTIFIER_POINTER (first), "directive")) + continue; + if (strcmp (IDENTIFIER_POINTER (second), directive) == 0) + break; + } + if (i == n - 4) + return false; + cp_parser_parse_tentatively (parser); + location_t first_loc = cp_lexer_peek_token (parser->lexer)->location; + location_t last_loc + = cp_lexer_peek_nth_token (parser->lexer, n - 1)->location; + location_t middle_loc = UNKNOWN_LOCATION; + tree std_attrs = cp_parser_std_attribute_spec_seq (parser); + int cnt = 0; + bool seen = false; + for (tree attr = std_attrs; attr; attr = TREE_CHAIN (attr)) + if (get_attribute_namespace (attr) == omp_identifier + && is_attribute_p ("directive", get_attribute_name (attr))) + { + for (tree a = TREE_VALUE (attr); a; a = TREE_CHAIN (a)) + { + tree d = TREE_VALUE (a); + gcc_assert (TREE_CODE (d) == DEFERRED_PARSE); + cp_token *first = DEFPARSE_TOKENS (d)->first; + cnt++; + if (first->type == CPP_NAME + && strcmp (IDENTIFIER_POINTER (first->u.value), + directive) == 0) + { + seen = true; + if (middle_loc == UNKNOWN_LOCATION) + middle_loc = first->location; + } + } + } + if (!seen || tentative) + { + cp_parser_abort_tentative_parse (parser); + return seen; + } + if (cnt != 1 || TREE_CHAIN (std_attrs)) + { + error_at (make_location (first_loc, last_loc, middle_loc), + "%<[[omp::directive(%s)]]%> must be the only specified " + "attribute on a statement", directive); + cp_parser_abort_tentative_parse (parser); + return false; + } + if (!cp_parser_parse_definitely (parser)) + return false; + cp_parser_handle_statement_omp_attributes (parser, std_attrs); + return true; +} + /* OpenMP 5.0: scan-loop-body: @@ -40054,10 +41402,11 @@ cp_parser_omp_scan_loop_body (cp_parser *parser) if (!braces.require_open (parser)) return; - substmt = cp_parser_omp_structured_block (parser, NULL); + substmt = cp_parser_omp_structured_block (parser, NULL, false); substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE); add_stmt (substmt); + cp_parser_omp_section_scan (parser, "scan", false); cp_token *tok = cp_lexer_peek_token (parser->lexer); if (cp_parser_pragma_kind (tok) == PRAGMA_OMP_SCAN) { @@ -40065,6 +41414,10 @@ cp_parser_omp_scan_loop_body (cp_parser *parser) cp_lexer_consume_token (parser->lexer); + if (parser->lexer->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + cp_lexer_consume_token (parser->lexer); + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { tree id = cp_lexer_peek_token (parser->lexer)->u.value; @@ -40089,7 +41442,7 @@ cp_parser_omp_scan_loop_body (cp_parser *parser) error ("expected %<#pragma omp scan%>"); clauses = finish_omp_clauses (clauses, C_ORT_OMP); - substmt = cp_parser_omp_structured_block (parser, NULL); + substmt = cp_parser_omp_structured_block (parser, NULL, false); substmt = build2_loc (tok->location, OMP_SCAN, void_type_node, substmt, clauses); add_stmt (substmt); @@ -40522,7 +41875,9 @@ cp_omp_split_clauses (location_t loc, enum tree_code code, c_omp_split_clauses (loc, code, mask, clauses, cclauses); for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++) if (cclauses[i]) - cclauses[i] = finish_omp_clauses (cclauses[i], C_ORT_OMP); + cclauses[i] = finish_omp_clauses (cclauses[i], + i == C_OMP_CLAUSE_SPLIT_TARGET + ? C_ORT_OMP_TARGET : C_ORT_OMP); } /* OpenMP 5.0: @@ -40770,7 +42125,9 @@ cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok, tree body = finish_omp_structured_block (sb); if (ret == NULL) return ret; - return c_finish_omp_master (loc, body); + ret = c_finish_omp_master (loc, body); + OMP_MASTER_COMBINED (ret) = 1; + return ret; } } if (!flag_openmp) /* flag_openmp_simd */ @@ -40792,6 +42149,73 @@ cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok, cp_parser_omp_structured_block (parser, if_p)); } +/* OpenMP 5.1: + # pragma omp masked masked-clauses new-line + structured-block */ + +#define OMP_MASKED_CLAUSE_MASK \ + (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER) + +static tree +cp_parser_omp_masked (cp_parser *parser, cp_token *pragma_tok, + char *p_name, omp_clause_mask mask, tree *cclauses, + bool *if_p) +{ + tree clauses, sb, ret; + unsigned int save; + location_t loc = cp_lexer_peek_token (parser->lexer)->location; + + strcat (p_name, " masked"); + mask |= OMP_MASKED_CLAUSE_MASK; + + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + const char *p = IDENTIFIER_POINTER (id); + + if (strcmp (p, "taskloop") == 0) + { + tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; + if (cclauses == NULL) + cclauses = cclauses_buf; + + cp_lexer_consume_token (parser->lexer); + if (!flag_openmp) /* flag_openmp_simd */ + return cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask, + cclauses, if_p); + sb = begin_omp_structured_block (); + save = cp_parser_begin_omp_structured_block (parser); + ret = cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask, + cclauses, if_p); + cp_parser_end_omp_structured_block (parser, save); + tree body = finish_omp_structured_block (sb); + if (ret == NULL) + return ret; + ret = c_finish_omp_masked (loc, body, + cclauses[C_OMP_CLAUSE_SPLIT_MASKED]); + OMP_MASKED_COMBINED (ret) = 1; + return ret; + } + } + if (!flag_openmp) /* flag_openmp_simd */ + { + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return NULL_TREE; + } + + clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok, + cclauses == NULL); + if (cclauses) + { + cp_omp_split_clauses (loc, OMP_MASTER, mask, clauses, cclauses); + clauses = cclauses[C_OMP_CLAUSE_SPLIT_MASKED]; + } + + return c_finish_omp_masked (loc, + cp_parser_omp_structured_block (parser, if_p), + clauses); +} + /* OpenMP 2.5: # pragma omp ordered new-line structured-block @@ -40812,10 +42236,16 @@ cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok, enum pragma_context context, bool *if_p) { location_t loc = pragma_tok->location; + int n = 1; - if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if (parser->lexer->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + n = 2; + + if (cp_lexer_nth_token_is (parser->lexer, n, CPP_NAME)) { - tree id = cp_lexer_peek_token (parser->lexer)->u.value; + tree id = cp_lexer_peek_nth_token (parser->lexer, n)->u.value; const char *p = IDENTIFIER_POINTER (id); if (strcmp (p, "depend") == 0) @@ -40831,7 +42261,7 @@ cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok, "%<depend%> clause may only be used in compound " "statements"); cp_parser_skip_to_pragma_eol (parser, pragma_tok); - return false; + return true; } tree clauses = cp_parser_omp_all_clauses (parser, @@ -40878,9 +42308,10 @@ cp_parser_omp_sections_scope (cp_parser *parser) stmt = push_stmt_list (); if (cp_parser_pragma_kind (cp_lexer_peek_token (parser->lexer)) - != PRAGMA_OMP_SECTION) + != PRAGMA_OMP_SECTION + && !cp_parser_omp_section_scan (parser, "section", true)) { - substmt = cp_parser_omp_structured_block (parser, NULL); + substmt = cp_parser_omp_structured_block (parser, NULL, false); substmt = build1 (OMP_SECTION, void_type_node, substmt); add_stmt (substmt); } @@ -40893,6 +42324,8 @@ cp_parser_omp_sections_scope (cp_parser *parser) if (tok->type == CPP_EOF) break; + if (cp_parser_omp_section_scan (parser, "section", false)) + tok = cp_lexer_peek_token (parser->lexer); if (cp_parser_pragma_kind (tok) == PRAGMA_OMP_SECTION) { cp_lexer_consume_token (parser->lexer); @@ -40905,7 +42338,7 @@ cp_parser_omp_sections_scope (cp_parser *parser) error_suppress = true; } - substmt = cp_parser_omp_structured_block (parser, NULL); + substmt = cp_parser_omp_structured_block (parser, NULL, false); substmt = build1 (OMP_SECTION, void_type_node, substmt); add_stmt (substmt); } @@ -41036,7 +42469,37 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok, { tree id = cp_lexer_peek_token (parser->lexer)->u.value; const char *p = IDENTIFIER_POINTER (id); - if (cclauses == NULL && strcmp (p, "master") == 0) + if (cclauses == NULL && strcmp (p, "masked") == 0) + { + tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; + cclauses = cclauses_buf; + + cp_lexer_consume_token (parser->lexer); + if (!flag_openmp) /* flag_openmp_simd */ + return cp_parser_omp_masked (parser, pragma_tok, p_name, mask, + cclauses, if_p); + block = begin_omp_parallel (); + save = cp_parser_begin_omp_structured_block (parser); + tree ret = cp_parser_omp_masked (parser, pragma_tok, p_name, mask, + cclauses, if_p); + cp_parser_end_omp_structured_block (parser, save); + stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL], + block); + if (ret == NULL_TREE) + return ret; + /* masked does have just filter clause, but during gimplification + isn't represented by a gimplification omp context, so for + #pragma omp parallel masked don't set OMP_PARALLEL_COMBINED, + so that + #pragma omp parallel masked + #pragma omp taskloop simd lastprivate (x) + isn't confused with + #pragma omp parallel masked taskloop simd lastprivate (x) */ + if (OMP_MASKED_COMBINED (ret)) + OMP_PARALLEL_COMBINED (stmt) = 1; + return stmt; + } + else if (cclauses == NULL && strcmp (p, "master") == 0) { tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; cclauses = cclauses_buf; @@ -41054,7 +42517,16 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok, block); if (ret == NULL_TREE) return ret; - OMP_PARALLEL_COMBINED (stmt) = 1; + /* master doesn't have any clauses and during gimplification + isn't represented by a gimplification omp context, so for + #pragma omp parallel master don't set OMP_PARALLEL_COMBINED, + so that + #pragma omp parallel master + #pragma omp taskloop simd lastprivate (x) + isn't confused with + #pragma omp parallel master taskloop simd lastprivate (x) */ + if (OMP_MASTER_COMBINED (ret)) + OMP_PARALLEL_COMBINED (stmt) = 1; return stmt; } else if (strcmp (p, "loop") == 0) @@ -41116,6 +42588,7 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok, block = begin_omp_parallel (); save = cp_parser_begin_omp_structured_block (parser); + parser->omp_attrs_forbidden_p = true; cp_parser_statement (parser, NULL_TREE, false, if_p); cp_parser_end_omp_structured_block (parser, save); stmt = finish_omp_parallel (clauses, block); @@ -41148,6 +42621,30 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok, bool *if_p) return add_stmt (stmt); } +/* OpenMP 5.1: + # pragma omp scope scope-clause[optseq] new-line + structured-block */ + +#define OMP_SCOPE_CLAUSE_MASK \ + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) + +static tree +cp_parser_omp_scope (cp_parser *parser, cp_token *pragma_tok, bool *if_p) +{ + tree stmt = make_node (OMP_SCOPE); + TREE_TYPE (stmt) = void_type_node; + SET_EXPR_LOCATION (stmt, pragma_tok->location); + + OMP_SCOPE_CLAUSES (stmt) + = cp_parser_omp_all_clauses (parser, OMP_SCOPE_CLAUSE_MASK, + "#pragma omp scope", pragma_tok); + OMP_SCOPE_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p); + + return add_stmt (stmt); +} + /* OpenMP 3.0: # pragma omp task task-clause[optseq] new-line structured-block */ @@ -41165,7 +42662,8 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok, bool *if_p) | (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) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DETACH)) + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DETACH) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_AFFINITY)) static tree cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok, bool *if_p) @@ -41177,6 +42675,7 @@ cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok, bool *if_p) "#pragma omp task", pragma_tok); block = begin_omp_task (); save = cp_parser_begin_omp_structured_block (parser); + parser->omp_attrs_forbidden_p = true; cp_parser_statement (parser, NULL_TREE, false, if_p); cp_parser_end_omp_structured_block (parser, save); return finish_omp_task (clauses, block); @@ -41286,7 +42785,7 @@ cp_parser_omp_cancel (cp_parser *parser, cp_token *pragma_tok) | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP)) -static void +static bool cp_parser_omp_cancellation_point (cp_parser *parser, cp_token *pragma_tok, enum pragma_context context) { @@ -41308,7 +42807,7 @@ cp_parser_omp_cancellation_point (cp_parser *parser, cp_token *pragma_tok, { cp_parser_error (parser, "expected %<point%>"); cp_parser_skip_to_pragma_eol (parser, pragma_tok); - return; + return false; } if (context != pragma_compound) @@ -41320,7 +42819,7 @@ cp_parser_omp_cancellation_point (cp_parser *parser, cp_token *pragma_tok, else cp_parser_error (parser, "expected declaration specifiers"); cp_parser_skip_to_pragma_eol (parser, pragma_tok); - return; + return true; } clauses = cp_parser_omp_all_clauses (parser, @@ -41328,6 +42827,7 @@ cp_parser_omp_cancellation_point (cp_parser *parser, cp_token *pragma_tok, "#pragma omp cancellation point", pragma_tok); finish_omp_cancellation_point (clauses); + return true; } /* OpenMP 4.0: @@ -41623,7 +43123,7 @@ cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p) | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) -static tree +static bool cp_parser_omp_target_enter_data (cp_parser *parser, cp_token *pragma_tok, enum pragma_context context) { @@ -41643,7 +43143,7 @@ cp_parser_omp_target_enter_data (cp_parser *parser, cp_token *pragma_tok, { cp_parser_error (parser, "expected %<data%>"); cp_parser_skip_to_pragma_eol (parser, pragma_tok); - return NULL_TREE; + return false; } if (context == pragma_stmt) @@ -41652,7 +43152,7 @@ cp_parser_omp_target_enter_data (cp_parser *parser, cp_token *pragma_tok, "%<#pragma %s%> may only be used in compound statements", "omp target enter data"); cp_parser_skip_to_pragma_eol (parser, pragma_tok); - return NULL_TREE; + return true; } tree clauses @@ -41692,14 +43192,15 @@ cp_parser_omp_target_enter_data (cp_parser *parser, cp_token *pragma_tok, error_at (pragma_tok->location, "%<#pragma omp target enter data%> must contain at least " "one %<map%> clause"); - return NULL_TREE; + return true; } tree stmt = make_node (OMP_TARGET_ENTER_DATA); TREE_TYPE (stmt) = void_type_node; OMP_TARGET_ENTER_DATA_CLAUSES (stmt) = clauses; SET_EXPR_LOCATION (stmt, pragma_tok->location); - return add_stmt (stmt); + add_stmt (stmt); + return true; } /* OpenMP 4.5: @@ -41713,7 +43214,7 @@ cp_parser_omp_target_enter_data (cp_parser *parser, cp_token *pragma_tok, | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) -static tree +static bool cp_parser_omp_target_exit_data (cp_parser *parser, cp_token *pragma_tok, enum pragma_context context) { @@ -41733,7 +43234,7 @@ cp_parser_omp_target_exit_data (cp_parser *parser, cp_token *pragma_tok, { cp_parser_error (parser, "expected %<data%>"); cp_parser_skip_to_pragma_eol (parser, pragma_tok); - return NULL_TREE; + return false; } if (context == pragma_stmt) @@ -41742,7 +43243,7 @@ cp_parser_omp_target_exit_data (cp_parser *parser, cp_token *pragma_tok, "%<#pragma %s%> may only be used in compound statements", "omp target exit data"); cp_parser_skip_to_pragma_eol (parser, pragma_tok); - return NULL_TREE; + return true; } tree clauses @@ -41784,14 +43285,15 @@ cp_parser_omp_target_exit_data (cp_parser *parser, cp_token *pragma_tok, error_at (pragma_tok->location, "%<#pragma omp target exit data%> must contain at least " "one %<map%> clause"); - return NULL_TREE; + return true; } tree stmt = make_node (OMP_TARGET_EXIT_DATA); TREE_TYPE (stmt) = void_type_node; OMP_TARGET_EXIT_DATA_CLAUSES (stmt) = clauses; SET_EXPR_LOCATION (stmt, pragma_tok->location); - return add_stmt (stmt); + add_stmt (stmt); + return true; } /* OpenMP 4.0: @@ -41815,7 +43317,7 @@ cp_parser_omp_target_update (cp_parser *parser, cp_token *pragma_tok, "%<#pragma %s%> may only be used in compound statements", "omp target update"); cp_parser_skip_to_pragma_eol (parser, pragma_tok); - return false; + return true; } tree clauses @@ -41827,7 +43329,7 @@ cp_parser_omp_target_update (cp_parser *parser, cp_token *pragma_tok, error_at (pragma_tok->location, "%<#pragma omp target update%> must contain at least one " "%<from%> or %<to%> clauses"); - return false; + return true; } tree stmt = make_node (OMP_TARGET_UPDATE); @@ -41835,7 +43337,7 @@ cp_parser_omp_target_update (cp_parser *parser, cp_token *pragma_tok, OMP_TARGET_UPDATE_CLAUSES (stmt) = clauses; SET_EXPR_LOCATION (stmt, pragma_tok->location); add_stmt (stmt); - return false; + return true; } /* OpenMP 4.0: @@ -41852,6 +43354,7 @@ cp_parser_omp_target_update (cp_parser *parser, cp_token *pragma_tok, | (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_IN_REDUCTION) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR)) static bool @@ -41966,6 +43469,7 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok, tree stmt = make_node (OMP_TARGET); TREE_TYPE (stmt) = void_type_node; OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET]; + c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true); OMP_TARGET_BODY (stmt) = body; OMP_TARGET_COMBINED (stmt) = 1; SET_EXPR_LOCATION (stmt, pragma_tok->location); @@ -41987,14 +43491,12 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok, else if (strcmp (p, "enter") == 0) { cp_lexer_consume_token (parser->lexer); - cp_parser_omp_target_enter_data (parser, pragma_tok, context); - return false; + return cp_parser_omp_target_enter_data (parser, pragma_tok, context); } else if (strcmp (p, "exit") == 0) { cp_lexer_consume_token (parser->lexer); - cp_parser_omp_target_exit_data (parser, pragma_tok, context); - return false; + return cp_parser_omp_target_exit_data (parser, pragma_tok, context); } else if (strcmp (p, "update") == 0) { @@ -42013,7 +43515,18 @@ 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); + "#pragma omp target", pragma_tok, false); + for (tree c = OMP_TARGET_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c)) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION) + { + tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP); + OMP_CLAUSE_DECL (nc) = OMP_CLAUSE_DECL (c); + OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_ALWAYS_TOFROM); + OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c); + OMP_CLAUSE_CHAIN (c) = nc; + } + OMP_TARGET_CLAUSES (stmt) + = finish_omp_clauses (OMP_TARGET_CLAUSES (stmt), C_ORT_OMP_TARGET); c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true); pc = &OMP_TARGET_CLAUSES (stmt); @@ -42635,7 +44148,9 @@ cp_parser_omp_declare_simd (cp_parser *parser, cp_token *pragma_tok, data.fndecl_seen = false; data.variant_p = variant_p; data.tokens = vNULL; - data.clauses = NULL_TREE; + data.attribs[0] = NULL; + data.attribs[1] = NULL; + data.loc = UNKNOWN_LOCATION; /* It is safe to take the address of a local variable; it will only be used while this scope is live. */ parser->omp_declare_simd = &data; @@ -43130,6 +44645,12 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok, location_t finish_loc = get_finish (varid.get_location ()); location_t varid_loc = make_location (caret_loc, start_loc, finish_loc); + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if (parser->lexer->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) + cp_lexer_consume_token (parser->lexer); + const char *clause = ""; location_t match_loc = cp_lexer_peek_token (parser->lexer)->location; if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) @@ -43202,6 +44723,11 @@ cp_parser_late_parsing_omp_declare_simd (cp_parser *parser, tree attrs) cp_lexer_consume_token (parser->lexer); if (strcmp (kind, "simd") == 0) { + /* For now only in C++ attributes, do it always for OpenMP 5.1. + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) + cp_lexer_consume_token (parser->lexer); */ + cl = cp_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK, "#pragma omp declare simd", pragma_tok); @@ -43216,11 +44742,151 @@ cp_parser_late_parsing_omp_declare_simd (cp_parser *parser, tree attrs) else { gcc_assert (strcmp (kind, "variant") == 0); - attrs = cp_finish_omp_declare_variant (parser, pragma_tok, attrs); + attrs + = cp_finish_omp_declare_variant (parser, pragma_tok, attrs); } cp_parser_pop_lexer (parser); } + cp_lexer *lexer = NULL; + for (int i = 0; i < 2; i++) + { + if (data->attribs[i] == NULL) + continue; + for (tree *pa = data->attribs[i]; *pa; ) + if (get_attribute_namespace (*pa) == omp_identifier + && is_attribute_p ("directive", get_attribute_name (*pa))) + { + for (tree a = TREE_VALUE (*pa); a; a = TREE_CHAIN (a)) + { + tree d = TREE_VALUE (a); + gcc_assert (TREE_CODE (d) == DEFERRED_PARSE); + cp_token *first = DEFPARSE_TOKENS (d)->first; + cp_token *last = DEFPARSE_TOKENS (d)->last; + const char *directive[3] = {}; + for (int j = 0; j < 3; j++) + { + tree id = NULL_TREE; + if (first + j == last) + break; + if (first[j].type == CPP_NAME) + id = first[j].u.value; + else if (first[j].type == CPP_KEYWORD) + id = ridpointers[(int) first[j].keyword]; + else + break; + directive[j] = IDENTIFIER_POINTER (id); + } + const c_omp_directive *dir = NULL; + if (directive[0]) + dir = c_omp_categorize_directive (directive[0], directive[1], + directive[2]); + if (dir == NULL) + { + error_at (first->location, + "unknown OpenMP directive name in " + "%<omp::directive%> attribute argument"); + continue; + } + if (dir->id != PRAGMA_OMP_DECLARE + || (strcmp (directive[1], "simd") != 0 + && strcmp (directive[1], "variant") != 0)) + { + error_at (first->location, + "OpenMP directive other than %<declare simd%> " + "or %<declare variant%> appertains to a " + "declaration"); + continue; + } + + if (parser->omp_attrs_forbidden_p) + { + error_at (first->location, + "mixing OpenMP directives with attribute and " + "pragma syntax on the same statement"); + parser->omp_attrs_forbidden_p = false; + } + + if (!flag_openmp && strcmp (directive[1], "simd") != 0) + continue; + if (lexer == NULL) + { + lexer = cp_lexer_alloc (); + lexer->debugging_p = parser->lexer->debugging_p; + } + vec_safe_reserve (lexer->buffer, (last - first) + 2); + cp_token tok = {}; + tok.type = CPP_PRAGMA; + tok.keyword = RID_MAX; + tok.u.value = build_int_cst (NULL, PRAGMA_OMP_DECLARE); + tok.location = first->location; + lexer->buffer->quick_push (tok); + while (++first < last) + lexer->buffer->quick_push (*first); + tok = {}; + tok.type = CPP_PRAGMA_EOL; + tok.keyword = RID_MAX; + tok.location = last->location; + lexer->buffer->quick_push (tok); + tok = {}; + tok.type = CPP_EOF; + tok.keyword = RID_MAX; + tok.location = last->location; + lexer->buffer->quick_push (tok); + lexer->next = parser->lexer; + lexer->next_token = lexer->buffer->address (); + lexer->last_token = lexer->next_token + + lexer->buffer->length () + - 1; + lexer->in_omp_attribute_pragma = true; + parser->lexer = lexer; + /* Move the current source position to that of the first token + in the new lexer. */ + cp_lexer_set_source_position_from_token (lexer->next_token); + + cp_token *pragma_tok = cp_lexer_consume_token (parser->lexer); + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + const char *kind = IDENTIFIER_POINTER (id); + cp_lexer_consume_token (parser->lexer); + + tree c, cl; + if (strcmp (kind, "simd") == 0) + { + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) + cp_lexer_consume_token (parser->lexer); + + omp_clause_mask mask = OMP_DECLARE_SIMD_CLAUSE_MASK; + cl = cp_parser_omp_all_clauses (parser, mask, + "#pragma omp declare simd", + pragma_tok); + if (cl) + cl = tree_cons (NULL_TREE, cl, NULL_TREE); + c = build_tree_list (get_identifier ("omp declare simd"), + cl); + TREE_CHAIN (c) = attrs; + if (processing_template_decl) + ATTR_IS_DEPENDENT (c) = 1; + attrs = c; + } + else + { + gcc_assert (strcmp (kind, "variant") == 0); + attrs + = cp_finish_omp_declare_variant (parser, pragma_tok, + attrs); + } + gcc_assert (parser->lexer != lexer); + vec_safe_truncate (lexer->buffer, 0); + } + *pa = TREE_CHAIN (*pa); + } + else + pa = &TREE_CHAIN (*pa); + } + if (lexer) + cp_lexer_destroy (lexer); + data->fndecl_seen = true; return attrs; } @@ -43247,7 +44913,11 @@ cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok) tree clauses = NULL_TREE; int device_type = 0; bool only_device_type = true; - if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME) + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + || (parser->lexer->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME))) clauses = cp_parser_omp_all_clauses (parser, OMP_DECLARE_TARGET_CLAUSE_MASK, "#pragma omp declare target", pragma_tok); @@ -43260,8 +44930,10 @@ cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok) } else { + struct omp_declare_target_attr a + = { parser->lexer->in_omp_attribute_pragma }; + vec_safe_push (scope_chain->omp_declare_target_attribute, a); cp_parser_require_pragma_eol (parser, pragma_tok); - scope_chain->omp_declare_target_attribute++; return; } for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) @@ -43342,6 +45014,7 @@ static void cp_parser_omp_end_declare_target (cp_parser *parser, cp_token *pragma_tok) { const char *p = ""; + bool in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { tree id = cp_lexer_peek_token (parser->lexer)->u.value; @@ -43372,12 +45045,26 @@ cp_parser_omp_end_declare_target (cp_parser *parser, cp_token *pragma_tok) return; } cp_parser_require_pragma_eol (parser, pragma_tok); - if (!scope_chain->omp_declare_target_attribute) + if (!vec_safe_length (scope_chain->omp_declare_target_attribute)) error_at (pragma_tok->location, "%<#pragma omp end declare target%> without corresponding " "%<#pragma omp declare target%>"); else - scope_chain->omp_declare_target_attribute--; + { + omp_declare_target_attr + a = scope_chain->omp_declare_target_attribute->pop (); + if (a.attr_syntax != in_omp_attribute_pragma) + { + if (a.attr_syntax) + error_at (pragma_tok->location, + "%<declare target%> in attribute syntax terminated " + "with %<end declare target%> in pragma syntax"); + else + error_at (pragma_tok->location, + "%<declare target%> in pragma syntax terminated " + "with %<end declare target%> in attribute syntax"); + } + } } /* Helper function of cp_parser_omp_declare_reduction. Parse the combiner @@ -43426,6 +45113,12 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser) if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) return false; + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if (parser->lexer->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) + cp_lexer_consume_token (parser->lexer); + const char *p = ""; if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { @@ -43860,7 +45553,10 @@ cp_parser_omp_requires (cp_parser *parser, cp_token *pragma_tok) location_t loc = pragma_tok->location; while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) { - if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if ((!first || parser->lexer->in_omp_attribute_pragma) + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) cp_lexer_consume_token (parser->lexer); first = false; @@ -43907,9 +45603,18 @@ cp_parser_omp_requires (cp_parser *parser, cp_token *pragma_tok) error_at (cp_lexer_peek_token (parser->lexer)->location, "expected %<seq_cst%>, %<relaxed%> or " "%<acq_rel%>"); - if (cp_lexer_nth_token_is (parser->lexer, 2, - CPP_CLOSE_PAREN)) - cp_lexer_consume_token (parser->lexer); + switch (cp_lexer_peek_token (parser->lexer)->type) + { + case CPP_EOF: + case CPP_PRAGMA_EOL: + case CPP_CLOSE_PAREN: + break; + default: + if (cp_lexer_nth_token_is (parser->lexer, 2, + CPP_CLOSE_PAREN)) + cp_lexer_consume_token (parser->lexer); + break; + } } else cp_lexer_consume_token (parser->lexer); @@ -43992,6 +45697,194 @@ cp_parser_omp_requires (cp_parser *parser, cp_token *pragma_tok) } +/* OpenMP 5.1: + #pragma omp nothing new-line */ + +static void +cp_parser_omp_nothing (cp_parser *parser, cp_token *pragma_tok) +{ + cp_parser_require_pragma_eol (parser, pragma_tok); +} + + +/* OpenMP 5.1 + #pragma omp error clauses[optseq] new-line */ + +static bool +cp_parser_omp_error (cp_parser *parser, cp_token *pragma_tok, + enum pragma_context context) +{ + int at_compilation = -1; + int severity_fatal = -1; + tree message = NULL_TREE; + bool first = true; + bool bad = false; + location_t loc = pragma_tok->location; + + while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) + { + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if ((!first || parser->lexer->in_omp_attribute_pragma) + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) + cp_lexer_consume_token (parser->lexer); + + first = false; + + if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME)) + break; + + const char *p + = IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value); + location_t cloc = cp_lexer_peek_token (parser->lexer)->location; + static const char *args[] = { + "execution", "compilation", "warning", "fatal" + }; + int *v = NULL; + int idx = 0, n = -1; + tree m = NULL_TREE; + + if (!strcmp (p, "at")) + v = &at_compilation; + else if (!strcmp (p, "severity")) + { + v = &severity_fatal; + idx += 2; + } + else if (strcmp (p, "message")) + { + error_at (cloc, + "expected %<at%>, %<severity%> or %<message%> clause"); + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return false; + } + + cp_lexer_consume_token (parser->lexer); + + matching_parens parens; + if (parens.require_open (parser)) + { + if (v == NULL) + { + m = cp_parser_assignment_expression (parser); + if (type_dependent_expression_p (m)) + m = build1 (IMPLICIT_CONV_EXPR, const_string_type_node, m); + else + m = perform_implicit_conversion_flags (const_string_type_node, m, + tf_warning_or_error, + LOOKUP_NORMAL); + } + else + { + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + tree val = cp_lexer_peek_token (parser->lexer)->u.value; + const char *q = IDENTIFIER_POINTER (val); + + if (!strcmp (q, args[idx])) + n = 0; + else if (!strcmp (q, args[idx + 1])) + n = 1; + } + if (n == -1) + { + error_at (cp_lexer_peek_token (parser->lexer)->location, + "expected %qs or %qs", args[idx], args[idx + 1]); + bad = true; + switch (cp_lexer_peek_token (parser->lexer)->type) + { + case CPP_EOF: + case CPP_PRAGMA_EOL: + case CPP_CLOSE_PAREN: + break; + default: + if (cp_lexer_nth_token_is (parser->lexer, 2, + CPP_CLOSE_PAREN)) + cp_lexer_consume_token (parser->lexer); + break; + } + } + else + cp_lexer_consume_token (parser->lexer); + } + + if (!parens.require_close (parser)) + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/ + true); + + if (v == NULL) + { + if (message) + { + error_at (cloc, "too many %qs clauses", p); + bad = true; + } + else + message = m; + } + else if (n != -1) + { + if (*v != -1) + { + error_at (cloc, "too many %qs clauses", p); + bad = true; + } + else + *v = n; + } + } + else + bad = true; + } + cp_parser_require_pragma_eol (parser, pragma_tok); + if (bad) + return true; + + if (at_compilation == -1) + at_compilation = 1; + if (severity_fatal == -1) + severity_fatal = 1; + if (!at_compilation) + { + if (context != pragma_compound) + { + error_at (loc, "%<#pragma omp error%> with %<at(execution)%> clause " + "may only be used in compound statements"); + return true; + } + tree fndecl + = builtin_decl_explicit (severity_fatal ? BUILT_IN_GOMP_ERROR + : BUILT_IN_GOMP_WARNING); + if (!message) + message = build_zero_cst (const_string_type_node); + tree stmt = build_call_expr_loc (loc, fndecl, 2, message, + build_all_ones_cst (size_type_node)); + add_stmt (stmt); + return true; + } + + if (in_discarded_stmt) + return false; + + const char *msg = NULL; + if (message) + { + msg = c_getstr (fold_for_warn (message)); + if (msg == NULL) + msg = _("<message unknown at compile time>"); + } + if (msg) + emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0, + "%<pragma omp error%> encountered: %s", msg); + else + emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0, + "%<pragma omp error%> encountered"); + return false; +} + /* OpenMP 4.5: #pragma omp taskloop taskloop-clause[optseq] new-line for-loop @@ -44105,8 +45998,8 @@ cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok, ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ)) - + | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NOHOST) ) /* Parse the OpenACC routine pragma. This has an optional '( name )' component, which must resolve to a declared namespace-scope @@ -44414,6 +46307,11 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p) stmt = cp_parser_omp_loop (parser, pragma_tok, p_name, mask, NULL, if_p); break; + case PRAGMA_OMP_MASKED: + strcpy (p_name, "#pragma omp"); + stmt = cp_parser_omp_masked (parser, pragma_tok, p_name, mask, NULL, + if_p); + break; case PRAGMA_OMP_MASTER: strcpy (p_name, "#pragma omp"); stmt = cp_parser_omp_master (parser, pragma_tok, p_name, mask, NULL, @@ -44424,6 +46322,9 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p) stmt = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask, NULL, if_p); break; + case PRAGMA_OMP_SCOPE: + stmt = cp_parser_omp_scope (parser, pragma_tok, if_p); + break; case PRAGMA_OMP_SECTIONS: strcpy (p_name, "#pragma omp"); stmt = cp_parser_omp_sections (parser, pragma_tok, p_name, mask, NULL); @@ -44853,7 +46754,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) cp_token *pragma_tok; unsigned int id; tree stmt; - bool ret; + bool ret = false; pragma_tok = cp_lexer_consume_token (parser->lexer); gcc_assert (pragma_tok->type == CPP_PRAGMA); @@ -44878,6 +46779,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) case pragma_stmt: error_at (pragma_tok->location, "%<#pragma %s%> may only be " "used in compound statements", "omp barrier"); + ret = true; break; default: goto bad_stmt; @@ -44893,6 +46795,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) case pragma_stmt: error_at (pragma_tok->location, "%<#pragma %s%> may only be " "used in compound statements", "omp depobj"); + ret = true; break; default: goto bad_stmt; @@ -44908,6 +46811,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) case pragma_stmt: error_at (pragma_tok->location, "%<#pragma %s%> may only be " "used in compound statements", "omp flush"); + ret = true; break; default: goto bad_stmt; @@ -44924,6 +46828,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) error_at (pragma_tok->location, "%<#pragma %s%> may only be used in compound statements", "omp taskwait"); + ret = true; break; default: goto bad_stmt; @@ -44940,6 +46845,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) error_at (pragma_tok->location, "%<#pragma %s%> may only be used in compound statements", "omp taskyield"); + ret = true; break; default: goto bad_stmt; @@ -44956,6 +46862,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) error_at (pragma_tok->location, "%<#pragma %s%> may only be used in compound statements", "omp cancel"); + ret = true; break; default: goto bad_stmt; @@ -44963,8 +46870,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) break; case PRAGMA_OMP_CANCELLATION_POINT: - cp_parser_omp_cancellation_point (parser, pragma_tok, context); - return false; + return cp_parser_omp_cancellation_point (parser, pragma_tok, context); case PRAGMA_OMP_THREADPRIVATE: cp_parser_omp_threadprivate (parser, pragma_tok); @@ -44983,6 +46889,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) error_at (pragma_tok->location, "%<#pragma %s%> may only be used in compound statements", "acc enter data"); + ret = true; break; } else if (context != pragma_compound) @@ -44996,6 +46903,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) error_at (pragma_tok->location, "%<#pragma %s%> may only be used in compound statements", "acc exit data"); + ret = true; break; } else if (context != pragma_compound) @@ -45008,6 +46916,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) { error_at (pragma_tok->location, "%<#pragma acc routine%> must be at file scope"); + ret = true; break; } cp_parser_oacc_routine (parser, pragma_tok, context); @@ -45019,6 +46928,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) error_at (pragma_tok->location, "%<#pragma %s%> may only be used in compound statements", "acc update"); + ret = true; break; } else if (context != pragma_compound) @@ -45032,6 +46942,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) error_at (pragma_tok->location, "%<#pragma %s%> may only be used in compound statements", "acc wait"); + ret = true; break; } else if (context != pragma_compound) @@ -45054,8 +46965,10 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) case PRAGMA_OMP_DISTRIBUTE: case PRAGMA_OMP_FOR: case PRAGMA_OMP_LOOP: + case PRAGMA_OMP_MASKED: case PRAGMA_OMP_MASTER: case PRAGMA_OMP_PARALLEL: + case PRAGMA_OMP_SCOPE: case PRAGMA_OMP_SECTIONS: case PRAGMA_OMP_SIMD: case PRAGMA_OMP_SINGLE: @@ -45076,10 +46989,18 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) error_at (pragma_tok->location, "%<#pragma omp requires%> may only be used at file or " "namespace scope"); + ret = true; break; } return cp_parser_omp_requires (parser, pragma_tok); + case PRAGMA_OMP_NOTHING: + cp_parser_omp_nothing (parser, pragma_tok); + return false; + + case PRAGMA_OMP_ERROR: + return cp_parser_omp_error (parser, pragma_tok, context); + case PRAGMA_OMP_ORDERED: if (context != pragma_stmt && context != pragma_compound) goto bad_stmt; @@ -45188,7 +47109,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) } cp_parser_skip_to_pragma_eol (parser, pragma_tok); - return false; + return ret; } /* The interface the pragma parsers have to the lexer. */ diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h index d587cf2..3669587 100644 --- a/gcc/cp/parser.h +++ b/gcc/cp/parser.h @@ -113,6 +113,14 @@ struct GTY (()) cp_lexer { /* True if we're in the context of parsing a pragma, and should not increment past the end-of-line marker. */ bool in_pragma; + + /* True if we're in the context of OpenMP directives written as C++11 + attributes turned into pragma. */ + bool in_omp_attribute_pragma; + + /* True for in_omp_attribute_pragma lexer that should be destroyed + when it is no longer in use. */ + bool orphan_p; }; @@ -208,13 +216,14 @@ struct cp_omp_declare_simd_data { bool error_seen; /* Set if error has been reported. */ bool fndecl_seen; /* Set if one fn decl/definition has been seen already. */ bool variant_p; /* Set for #pragma omp declare variant. */ + location_t loc; vec<cp_token_cache_ptr> tokens; - tree clauses; + tree *attribs[2]; }; /* Helper data structure for parsing #pragma acc routine. */ struct cp_oacc_routine_data : cp_omp_declare_simd_data { - location_t loc; + tree clauses; }; /* The cp_parser structure represents the C++ parser. */ @@ -350,6 +359,10 @@ struct GTY(()) cp_parser { is terminated by colon. */ bool colon_doesnt_start_class_def_p; + /* TRUE if we are parsing an objective c message, and ':' is permitted + to terminate an assignment-expression. */ + bool objective_c_message_context_p; + /* If non-NULL, then we are parsing a construct where new type definitions are not permitted. The string stored here will be issued as an error message if a type is defined. */ @@ -388,6 +401,9 @@ struct GTY(()) cp_parser { identifiers) rather than an explicit template parameter list. */ bool fully_implicit_function_template_p; + /* TRUE if omp::directive or omp::sequence attributes may not appear. */ + bool omp_attrs_forbidden_p; + /* Tracks the function's template parameter list when declaring a function using generic type parameters. This is either a new chain in the case of a fully implicit function template or an extension of the function's existing diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 5e485f1..224dd9e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -65,7 +65,6 @@ static GTY(()) struct pending_template *last_pending_template; int processing_template_parmlist; static int template_header_count; -static GTY(()) tree saved_trees; static vec<int> inline_parm_levels; static GTY(()) struct tinst_level *current_tinst_level; @@ -152,12 +151,11 @@ static tree coerce_template_parms (tree, tree, tree, tsubst_flags_t, static tree coerce_innermost_template_parms (tree, tree, tree, tsubst_flags_t, bool, bool); static void tsubst_enum (tree, tree, tree); -static tree add_to_template_args (tree, tree); static bool check_instantiated_args (tree, tree, tsubst_flags_t); static int check_non_deducible_conversion (tree, tree, int, int, struct conversion **, bool); -static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*, - tree); +static int maybe_adjust_types_for_deduction (tree, unification_kind_t, + tree*, tree*, tree); static int type_unification_real (tree, tree, tree, const tree *, unsigned int, int, unification_kind_t, vec<deferred_access_check, va_gc> **, @@ -192,7 +190,6 @@ static tree tsubst_arg_types (tree, tree, tree, tsubst_flags_t, tree); static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree); static bool check_specialization_scope (void); static tree process_partial_specialization (tree); -static void set_current_access_from_decl (tree); static enum template_base_result get_template_base (tree, tree, tree, tree, bool , tree *); static tree try_class_unification (tree, tree, tree, tree, bool); @@ -227,7 +224,7 @@ static void instantiate_body (tree pattern, tree args, tree d, bool nested); /* Make the current scope suitable for access checking when we are processing T. T can be FUNCTION_DECL for instantiated function template, VAR_DECL for static member variable, or TYPE_DECL for - alias template (needed by instantiate_decl). */ + for a class or alias template (needed by instantiate_decl). */ void push_access_scope (tree t) @@ -237,8 +234,15 @@ push_access_scope (tree t) if (DECL_FRIEND_CONTEXT (t)) push_nested_class (DECL_FRIEND_CONTEXT (t)); + else if (DECL_IMPLICIT_TYPEDEF_P (t) + && CLASS_TYPE_P (TREE_TYPE (t))) + push_nested_class (TREE_TYPE (t)); else if (DECL_CLASS_SCOPE_P (t)) push_nested_class (DECL_CONTEXT (t)); + else if (deduction_guide_p (t) && DECL_ARTIFICIAL (t)) + /* An artificial deduction guide should have the same access as + the constructor. */ + push_nested_class (TREE_TYPE (TREE_TYPE (t))); else push_to_top_level (); @@ -258,7 +262,11 @@ pop_access_scope (tree t) if (TREE_CODE (t) == FUNCTION_DECL) current_function_decl = saved_access_scope->pop(); - if (DECL_FRIEND_CONTEXT (t) || DECL_CLASS_SCOPE_P (t)) + if (DECL_FRIEND_CONTEXT (t) + || (DECL_IMPLICIT_TYPEDEF_P (t) + && CLASS_TYPE_P (TREE_TYPE (t))) + || DECL_CLASS_SCOPE_P (t) + || (deduction_guide_p (t) && DECL_ARTIFICIAL (t))) pop_nested_class (); else pop_from_top_level (); @@ -554,7 +562,7 @@ maybe_end_member_template_processing (void) /* Return a new template argument vector which contains all of ARGS, but has as its innermost set of arguments the EXTRA_ARGS. */ -static tree +tree add_to_template_args (tree args, tree extra_args) { tree new_args; @@ -985,6 +993,10 @@ maybe_process_partial_specialization (tree type) if (CLASS_TYPE_P (type) && CLASSTYPE_LAMBDA_EXPR (type)) return type; + /* An injected-class-name is not a specialization. */ + if (DECL_SELF_REFERENCE_P (TYPE_NAME (type))) + return type; + if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM) { error ("name of class shadows template template parameter %qD", @@ -2198,6 +2210,7 @@ determine_specialization (tree template_id, ++header_count; tree orig_fns = fns; + bool header_mismatch = false; if (variable_template_p (fns)) { @@ -2245,7 +2258,10 @@ determine_specialization (tree template_id, specialization but rather a template instantiation, so there is no check we can perform here. */ if (header_count && header_count != template_count + 1) - continue; + { + header_mismatch = true; + continue; + } /* Check that the number of template arguments at the innermost level for DECL is the same as for FN. */ @@ -2479,13 +2495,12 @@ determine_specialization (tree template_id, { error ("template-id %qD for %q+D does not match any template " "declaration", template_id, decl); - if (header_count && header_count != template_count + 1) + if (header_mismatch) inform (DECL_SOURCE_LOCATION (decl), "saw %d %<template<>%>, need %d for " "specializing a member function template", header_count, template_count + 1); - else - print_candidates (orig_fns); + print_candidates (orig_fns); return error_mark_node; } else if ((templates && TREE_CHAIN (templates)) @@ -2698,7 +2713,7 @@ check_template_variable (tree decl) && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl))) { if (cxx_dialect < cxx14) - pedwarn (DECL_SOURCE_LOCATION (decl), 0, + pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wc__14_extensions, "variable templates only available with " "%<-std=c++14%> or %<-std=gnu++14%>"); @@ -3688,25 +3703,6 @@ get_primary_template_innermost_parameters (const_tree t) return parms; } -/* Return the template parameters of the LEVELth level from the full list - of template parameters PARMS. */ - -tree -get_template_parms_at_level (tree parms, int level) -{ - tree p; - if (!parms - || TREE_CODE (parms) != TREE_LIST - || level > TMPL_PARMS_DEPTH (parms)) - return NULL_TREE; - - for (p = parms; p; p = TREE_CHAIN (p)) - if (TMPL_PARMS_DEPTH (p) == level) - return p; - - return NULL_TREE; -} - /* Returns the template arguments of T if T is a template instantiation, NULL otherwise. */ @@ -3859,6 +3855,18 @@ expand_builtin_pack_call (tree call, tree args, tsubst_flags_t complain, return NULL_TREE; } +/* Return true if the tree T has the extra args mechanism for + avoiding partial instantiation. */ + +static bool +has_extra_args_mechanism_p (const_tree t) +{ + return (PACK_EXPANSION_P (t) /* PACK_EXPANSION_EXTRA_ARGS */ + || TREE_CODE (t) == REQUIRES_EXPR /* REQUIRES_EXPR_EXTRA_ARGS */ + || (TREE_CODE (t) == IF_STMT + && IF_STMT_CONSTEXPR_P (t))); /* IF_STMT_EXTRA_ARGS */ +} + /* Structure used to track the progress of find_parameter_packs_r. */ struct find_parameter_pack_data { @@ -3871,6 +3879,9 @@ struct find_parameter_pack_data /* True iff we're making a type pack expansion. */ bool type_pack_expansion_p; + + /* True iff we found a subtree that has the extra args mechanism. */ + bool found_extra_args_tree_p = false; }; /* Identifies all of the argument packs that occur in a template @@ -3885,6 +3896,10 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data) (struct find_parameter_pack_data*)data; bool parameter_pack_p = false; +#define WALK_SUBTREE(NODE) \ + cp_walk_tree (&(NODE), &find_parameter_packs_r, \ + ppd, ppd->visited) \ + /* Don't look through typedefs; we are interested in whether a parameter pack is actually written in the expression/type we're looking at, not the target type. */ @@ -3968,6 +3983,9 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data) *ppd->parameter_packs = tree_cons (NULL_TREE, t, *ppd->parameter_packs); } + if (has_extra_args_mechanism_p (t) && !PACK_EXPANSION_P (t)) + ppd->found_extra_args_tree_p = true; + if (TYPE_P (t)) cp_walk_tree (&TYPE_CONTEXT (t), &find_parameter_packs_r, ppd, ppd->visited); @@ -4056,10 +4074,32 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data) *walk_subtrees = 0; return NULL_TREE; + case TAG_DEFN: + t = TREE_TYPE (t); + if (CLASS_TYPE_P (t)) + /* Local class, need to look through the whole definition. */ + for (tree bb : BINFO_BASE_BINFOS (TYPE_BINFO (t))) + cp_walk_tree (&BINFO_TYPE (bb), &find_parameter_packs_r, + ppd, ppd->visited); + else + /* Enum, look at the values. */ + for (tree l = TYPE_VALUES (t); l; l = TREE_CHAIN (l)) + cp_walk_tree (&DECL_INITIAL (TREE_VALUE (l)), + &find_parameter_packs_r, + ppd, ppd->visited); + return NULL_TREE; + + case FUNCTION_TYPE: + case METHOD_TYPE: + WALK_SUBTREE (TYPE_RAISES_EXCEPTIONS (t)); + break; + default: return NULL_TREE; } +#undef WALK_SUBTREE + return NULL_TREE; } @@ -4207,6 +4247,14 @@ make_pack_expansion (tree arg, tsubst_flags_t complain) PACK_EXPANSION_PARAMETER_PACKS (result) = parameter_packs; PACK_EXPANSION_LOCAL_P (result) = at_function_scope_p (); + if (ppd.found_extra_args_tree_p) + /* If the pattern of this pack expansion contains a subtree that has + the extra args mechanism for avoiding partial instantiation, then + force this pack expansion to also use extra args. Otherwise + partial instantiation of this pack expansion may not lower the + level of some parameter packs within the pattern, which would + confuse tsubst_pack_expansion later (PR101764). */ + PACK_EXPANSION_FORCE_EXTRA_ARGS_P (result) = true; return result; } @@ -4930,16 +4978,8 @@ build_template_decl (tree decl, tree parms, bool member_template_p) DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl); DECL_MEMBER_TEMPLATE_P (tmpl) = member_template_p; - if (modules_p ()) - { - /* Propagate module information from the decl. */ - DECL_MODULE_EXPORT_P (tmpl) = DECL_MODULE_EXPORT_P (decl); - if (DECL_LANG_SPECIFIC (decl)) - { - DECL_MODULE_PURVIEW_P (tmpl) = DECL_MODULE_PURVIEW_P (decl); - gcc_checking_assert (!DECL_MODULE_IMPORT_P (decl)); - } - } + /* Propagate module information from the decl. */ + DECL_MODULE_EXPORT_P (tmpl) = DECL_MODULE_EXPORT_P (decl); return tmpl; } @@ -5153,11 +5193,7 @@ process_partial_specialization (tree decl) maintmpl); } - /* [temp.class.spec] - - A partially specialized non-type argument expression shall not - involve template parameters of the partial specialization except - when the argument expression is a simple identifier. + /* [temp.spec.partial] The type of a template parameter corresponding to a specialized non-type argument shall not be dependent on a parameter of the @@ -5218,63 +5254,55 @@ process_partial_specialization (tree decl) || TREE_CODE (arg) == VIEW_CONVERT_EXPR) && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_PARM_INDEX)) { - if ((!packed_args && tpd.arg_uses_template_parms[i]) - || (packed_args && uses_template_parms (arg))) - error_at (cp_expr_loc_or_input_loc (arg), - "template argument %qE involves template " - "parameter(s)", arg); - else - { - /* Look at the corresponding template parameter, - marking which template parameters its type depends - upon. */ - tree type = TREE_TYPE (parm); + /* Look at the corresponding template parameter, + marking which template parameters its type depends + upon. */ + tree type = TREE_TYPE (parm); - if (!tpd2.parms) - { - /* We haven't yet initialized TPD2. Do so now. */ - tpd2.arg_uses_template_parms = XALLOCAVEC (int, nargs); - /* The number of parameters here is the number in the - main template, which, as checked in the assertion - above, is NARGS. */ - tpd2.parms = XALLOCAVEC (int, nargs); - tpd2.level = - TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (maintmpl)); - } + if (!tpd2.parms) + { + /* We haven't yet initialized TPD2. Do so now. */ + tpd2.arg_uses_template_parms = XALLOCAVEC (int, nargs); + /* The number of parameters here is the number in the + main template, which, as checked in the assertion + above, is NARGS. */ + tpd2.parms = XALLOCAVEC (int, nargs); + tpd2.level = + TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (maintmpl)); + } - /* Mark the template parameters. But this time, we're - looking for the template parameters of the main - template, not in the specialization. */ - tpd2.current_arg = i; - tpd2.arg_uses_template_parms[i] = 0; - memset (tpd2.parms, 0, sizeof (int) * nargs); - for_each_template_parm (type, - &mark_template_parm, - &tpd2, - NULL, - /*include_nondeduced_p=*/false); - - if (tpd2.arg_uses_template_parms [i]) - { - /* The type depended on some template parameters. - If they are fully specialized in the - specialization, that's OK. */ - int j; - int count = 0; - for (j = 0; j < nargs; ++j) - if (tpd2.parms[j] != 0 - && tpd.arg_uses_template_parms [j]) - ++count; - if (count != 0) - error_n (input_location, count, - "type %qT of template argument %qE depends " - "on a template parameter", - "type %qT of template argument %qE depends " - "on template parameters", - type, - arg); - } - } + /* Mark the template parameters. But this time, we're + looking for the template parameters of the main + template, not in the specialization. */ + tpd2.current_arg = i; + tpd2.arg_uses_template_parms[i] = 0; + memset (tpd2.parms, 0, sizeof (int) * nargs); + for_each_template_parm (type, + &mark_template_parm, + &tpd2, + NULL, + /*include_nondeduced_p=*/false); + + if (tpd2.arg_uses_template_parms [i]) + { + /* The type depended on some template parameters. + If they are fully specialized in the + specialization, that's OK. */ + int j; + int count = 0; + for (j = 0; j < nargs; ++j) + if (tpd2.parms[j] != 0 + && tpd.arg_uses_template_parms [j]) + ++count; + if (count != 0) + error_n (input_location, count, + "type %qT of template argument %qE depends " + "on a template parameter", + "type %qT of template argument %qE depends " + "on template parameters", + type, + arg); + } } } } @@ -5799,18 +5827,7 @@ push_template_decl (tree decl, bool is_friend) } else if (DECL_IMPLICIT_TYPEDEF_P (decl) && CLASS_TYPE_P (TREE_TYPE (decl))) - { - /* Class template, set TEMPLATE_TYPE_PARM_FOR_CLASS. */ - tree parms = INNERMOST_TEMPLATE_PARMS (current_template_parms); - for (int i = 0; i < TREE_VEC_LENGTH (parms); ++i) - { - tree t = TREE_VALUE (TREE_VEC_ELT (parms, i)); - if (TREE_CODE (t) == TYPE_DECL) - t = TREE_TYPE (t); - if (TREE_CODE (t) == TEMPLATE_TYPE_PARM) - TEMPLATE_TYPE_PARM_FOR_CLASS (t) = true; - } - } + /* Class template. */; else if (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_ALIAS_P (decl)) /* alias-declaration */ @@ -6290,9 +6307,6 @@ redeclare_class_template (tree type, tree parms, tree cons) gcc_assert (DECL_CONTEXT (parm) == NULL_TREE); DECL_CONTEXT (parm) = tmpl; } - - if (TREE_CODE (parm) == TYPE_DECL) - TEMPLATE_TYPE_PARM_FOR_CLASS (TREE_TYPE (parm)) = true; } tree ci = get_constraints (tmpl); @@ -6578,6 +6592,10 @@ get_underlying_template (tree tmpl) != num_innermost_template_parms (underlying))) break; + /* Does the alias add cv-quals? */ + if (TYPE_QUALS (TREE_TYPE (underlying)) != TYPE_QUALS (TREE_TYPE (tmpl))) + break; + tree alias_args = INNERMOST_TEMPLATE_ARGS (generic_targs_for (tmpl)); if (!comp_template_args (TI_ARGS (tinfo), alias_args)) break; @@ -6614,7 +6632,10 @@ convert_nontype_argument_function (tree type, tree expr, if (value_dependent_expression_p (fn)) goto accept; - fn_no_ptr = strip_fnptr_conv (fn); + fn_no_ptr = fn; + if (REFERENCE_REF_P (fn_no_ptr)) + fn_no_ptr = TREE_OPERAND (fn_no_ptr, 0); + fn_no_ptr = strip_fnptr_conv (fn_no_ptr); if (TREE_CODE (fn_no_ptr) == ADDR_EXPR) fn_no_ptr = TREE_OPERAND (fn_no_ptr, 0); if (BASELINK_P (fn_no_ptr)) @@ -6967,7 +6988,7 @@ bool template_parm_object_p (const_tree t) { return (TREE_CODE (t) == VAR_DECL && DECL_ARTIFICIAL (t) && DECL_NAME (t) - && !strncmp (IDENTIFIER_POINTER (DECL_NAME (t)), "_ZTA", 4)); + && startswith (IDENTIFIER_POINTER (DECL_NAME (t)), "_ZTA")); } /* Subroutine of convert_nontype_argument, to check whether EXPR, as an @@ -7129,6 +7150,9 @@ get_template_parm_object (tree expr, tsubst_flags_t complain) if (invalid_tparm_referent_p (TREE_TYPE (expr), expr, complain)) return error_mark_node; + /* This is no longer a compound literal. */ + gcc_assert (!TREE_HAS_CONSTRUCTOR (expr)); + tree name = mangle_template_parm_object (expr); tree decl = get_global_binding (name); if (decl) @@ -8488,7 +8512,8 @@ convert_template_argument (tree parm, can happen in the context of -fnew-ttp-matching. */; else if (tree a = type_uses_auto (t)) { - t = do_auto_deduction (t, arg, a, complain, adc_unify, args); + t = do_auto_deduction (t, arg, a, complain, adc_unify, args, + LOOKUP_IMPLICIT); if (t == error_mark_node) return error_mark_node; } @@ -8498,6 +8523,10 @@ convert_template_argument (tree parm, if (invalid_nontype_parm_type_p (t, complain)) return error_mark_node; + /* Drop top-level cv-qualifiers on the substituted/deduced type of + this non-type template parameter, as per [temp.param]/6. */ + t = cv_unqualified (t); + if (t != TREE_TYPE (parm)) t = canonicalize_type_argument (t, complain); @@ -9592,6 +9621,7 @@ lookup_template_function (tree fns, tree arglist) if (BASELINK_P (fns)) { + fns = copy_node (fns); BASELINK_FUNCTIONS (fns) = build2 (TEMPLATE_ID_EXPR, unknown_type_node, BASELINK_FUNCTIONS (fns), @@ -9827,6 +9857,13 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, /* From here on, we're only interested in the most general template. */ + /* Shortcut looking up the current class scope again. */ + if (current_class_type) + if (tree ti = CLASSTYPE_TEMPLATE_INFO (current_class_type)) + if (gen_tmpl == most_general_template (TI_TEMPLATE (ti)) + && comp_template_args (arglist, TI_ARGS (ti))) + return current_class_type; + /* Calculate the BOUND_ARGS. These will be the args that are actually tsubst'd into the definition to create the instantiation. */ @@ -10167,25 +10204,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, } /* Build template info for the new specialization. */ - if (TYPE_ALIAS_P (t)) - { - /* This is constructed during instantiation of the alias - decl. But for member templates of template classes, that - is not correct as we need to refer to the partially - instantiated template, not the most general template. - The incorrect knowledge will not have escaped this - instantiation process, so we're good just updating the - template_info we made then. */ - tree ti = DECL_TEMPLATE_INFO (TYPE_NAME (t)); - gcc_checking_assert (template_args_equal (TI_ARGS (ti), arglist)); - if (TI_TEMPLATE (ti) != found) - { - gcc_checking_assert (DECL_TI_TEMPLATE (found) == TI_TEMPLATE (ti)); - TI_TEMPLATE (ti) = found; - } - } - else - SET_TYPE_TEMPLATE_INFO (t, build_template_info (found, arglist)); + SET_TYPE_TEMPLATE_INFO (t, build_template_info (found, arglist)); elt.spec = t; slot = type_specializations->find_slot_with_hash (&elt, hash, INSERT); @@ -10200,7 +10219,8 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, = tree_cons (arglist, t, DECL_TEMPLATE_INSTANTIATIONS (found)); - if (TREE_CODE (template_type) == ENUMERAL_TYPE && !is_dependent_type + if (TREE_CODE (template_type) == ENUMERAL_TYPE + && !uses_template_parms (current_nonlambda_scope ()) && !DECL_ALIAS_TEMPLATE_P (gen_tmpl)) /* Now that the type has been registered on the instantiations list, we set up the enumerators. Because the enumeration @@ -10261,10 +10281,6 @@ finish_template_variable (tree var, tsubst_flags_t complain) tree templ = TREE_OPERAND (var, 0); tree arglist = TREE_OPERAND (var, 1); - tree tmpl_args = DECL_TI_ARGS (DECL_TEMPLATE_RESULT (templ)); - arglist = add_outermost_template_args (tmpl_args, arglist); - - templ = most_general_template (templ); tree parms = DECL_TEMPLATE_PARMS (templ); arglist = coerce_innermost_template_parms (parms, arglist, templ, complain, /*req_all*/true, @@ -10505,6 +10521,15 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d) return error_mark_node; break; + case TRAIT_EXPR: + case PLUS_EXPR: + case MULT_EXPR: + case SCOPE_REF: + /* These are non-deduced contexts. */ + if (!pfd->include_nondeduced_p) + *walk_subtrees = 0; + break; + case MODOP_EXPR: case CAST_EXPR: case IMPLICIT_CONV_EXPR: @@ -10520,11 +10545,6 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d) return error_mark_node; break; - case SCOPE_REF: - if (pfd->include_nondeduced_p) - WALK_SUBTREE (TREE_OPERAND (t, 0)); - break; - case REQUIRES_EXPR: { if (!fn) @@ -10721,28 +10741,11 @@ any_template_parm_r (tree t, void *data) break; case TEMPLATE_DECL: - { - /* If T is a member template that shares template parameters with - ctx_parms, we need to mark all those parameters for mapping. */ - tree dparms = DECL_TEMPLATE_PARMS (t); - tree cparms = ftpi->ctx_parms; - while (TMPL_PARMS_DEPTH (dparms) > ftpi->max_depth) - dparms = TREE_CHAIN (dparms); - while (TMPL_PARMS_DEPTH (cparms) > TMPL_PARMS_DEPTH (dparms)) - cparms = TREE_CHAIN (cparms); - while (dparms - && (TREE_TYPE (TREE_VALUE (dparms)) - != TREE_TYPE (TREE_VALUE (cparms)))) - dparms = TREE_CHAIN (dparms), - cparms = TREE_CHAIN (cparms); - if (dparms) - { - int ddepth = TMPL_PARMS_DEPTH (dparms); - tree dargs = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (t))); - for (int i = 0; i < ddepth; ++i) - WALK_SUBTREE (TMPL_ARGS_LEVEL (dargs, i+1)); - } - } + /* If T is a member template that shares template parameters with + ctx_parms, we need to mark all those parameters for mapping. + To that end, it should suffice to just walk the DECL_CONTEXT of + the template (assuming the template is not overly general). */ + WALK_SUBTREE (DECL_CONTEXT (t)); break; case LAMBDA_EXPR: @@ -10857,11 +10860,27 @@ uses_outer_template_parms (tree decl) &depth, NULL, /*include_nondeduced_p=*/true)) return true; if (PRIMARY_TEMPLATE_P (decl) - && for_each_template_parm (INNERMOST_TEMPLATE_PARMS - (DECL_TEMPLATE_PARMS (decl)), - template_parm_outer_level, - &depth, NULL, /*include_nondeduced_p=*/true)) - return true; + || DECL_TEMPLATE_TEMPLATE_PARM_P (decl)) + { + tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (decl)); + for (int i = TREE_VEC_LENGTH (parms) - 1; i >= 0; --i) + { + tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i)); + tree defarg = TREE_PURPOSE (TREE_VEC_ELT (parms, i)); + if (TREE_CODE (parm) == PARM_DECL + && for_each_template_parm (TREE_TYPE (parm), + template_parm_outer_level, + &depth, NULL, /*nondeduced*/true)) + return true; + if (TREE_CODE (parm) == TEMPLATE_DECL + && uses_outer_template_parms (parm)) + return true; + if (defarg + && for_each_template_parm (defarg, template_parm_outer_level, + &depth, NULL, /*nondeduced*/true)) + return true; + } + } tree ci = get_constraints (decl); if (ci) ci = CI_ASSOCIATED_CONSTRAINTS (ci); @@ -10880,7 +10899,8 @@ neglectable_inst_p (tree d) { return (d && DECL_P (d) && !undeduced_auto_decl (d) - && !(TREE_CODE (d) == FUNCTION_DECL ? DECL_DECLARED_CONSTEXPR_P (d) + && !(TREE_CODE (d) == FUNCTION_DECL + ? FNDECL_MANIFESTLY_CONST_EVALUATED (d) : decl_maybe_constant_var_p (d))); } @@ -10892,14 +10912,31 @@ limit_bad_template_recursion (tree decl) { struct tinst_level *lev = current_tinst_level; int errs = errorcount + sorrycount; - if (lev == NULL || errs == 0 || !neglectable_inst_p (decl)) + if (errs == 0 || !neglectable_inst_p (decl)) return false; - for (; lev; lev = lev->next) - if (neglectable_inst_p (lev->maybe_get_node ())) - break; + /* Avoid instantiating members of an ill-formed class. */ + bool refuse + = (DECL_CLASS_SCOPE_P (decl) + && CLASSTYPE_ERRONEOUS (DECL_CONTEXT (decl))); - return (lev && errs > lev->errors); + if (!refuse) + { + for (; lev; lev = lev->next) + if (neglectable_inst_p (lev->maybe_get_node ())) + break; + refuse = (lev && errs > lev->errors); + } + + if (refuse) + { + /* Don't warn about it not being defined. */ + suppress_warning (decl, OPT_Wunused); + tree clone; + FOR_EACH_CLONE (clone, decl) + suppress_warning (clone, OPT_Wunused); + } + return refuse; } static int tinst_depth; @@ -10932,9 +10969,9 @@ push_tinst_level_loc (tree tldcl, tree targs, location_t loc) constant expressions. */ if (!targs && limit_bad_template_recursion (tldcl)) { - /* Avoid no_linkage_errors and unused function warnings for this - decl. */ - TREE_NO_WARNING (tldcl) = 1; + /* Avoid no_linkage_errors and unused function (and all other) + warnings for this decl. */ + suppress_warning (tldcl); return false; } @@ -11630,7 +11667,6 @@ static bool apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags, tree args, tsubst_flags_t complain, tree in_decl) { - tree last_dep = NULL_TREE; tree t; tree *p; @@ -11656,39 +11692,35 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags, p = &TREE_CHAIN (*p); } + /* save_template_attributes puts the dependent attributes at the beginning of + the list; find the non-dependent ones. */ for (t = attributes; t; t = TREE_CHAIN (t)) - if (ATTR_IS_DEPENDENT (t)) - { - last_dep = t; - attributes = copy_list (attributes); - break; - } + if (!ATTR_IS_DEPENDENT (t)) + break; + tree nondep = t; - *p = attributes; - if (last_dep) - { - tree late_attrs = NULL_TREE; - tree *q = &late_attrs; + /* Apply any non-dependent attributes. */ + *p = nondep; - for (; *p; ) + /* And then any dependent ones. */ + tree late_attrs = NULL_TREE; + tree *q = &late_attrs; + for (t = attributes; t != nondep; t = TREE_CHAIN (t)) + { + *q = tsubst_attribute (t, decl_p, args, complain, in_decl); + if (*q == error_mark_node) + return false; + if (*q == t) { - t = *p; - if (ATTR_IS_DEPENDENT (t)) - { - *q = tsubst_attribute (t, decl_p, args, complain, in_decl); - if (*q == error_mark_node) - return false; - *p = TREE_CHAIN (t); - TREE_CHAIN (t) = NULL_TREE; - while (*q) - q = &TREE_CHAIN (*q); - } - else - p = &TREE_CHAIN (t); + *q = copy_node (t); + TREE_CHAIN (*q) = NULL_TREE; } - - cplus_decl_attributes (decl_p, late_attrs, attr_flags); + while (*q) + q = &TREE_CHAIN (*q); } + + cplus_decl_attributes (decl_p, late_attrs, attr_flags); + return true; } @@ -12224,6 +12256,13 @@ instantiate_class_template_1 (tree type) finish_struct_1 (type); TYPE_BEING_DEFINED (type) = 0; + /* Remember if instantiating this class ran into errors, so we can avoid + instantiating member functions in limit_bad_template_recursion. We set + this flag even if the problem was in another instantiation triggered by + this one, as that will likely also cause trouble for member functions. */ + if (errorcount + sorrycount > current_tinst_level->errors) + CLASSTYPE_ERRONEOUS (type) = true; + /* We don't instantiate default arguments for member functions. 14.7.1: The implicit instantiation of a class template specialization causes @@ -12392,10 +12431,15 @@ make_argument_pack_select (tree arg_pack, unsigned index) substitution. */ static bool -use_pack_expansion_extra_args_p (tree parm_packs, +use_pack_expansion_extra_args_p (tree t, + tree parm_packs, int arg_pack_len, bool has_empty_arg) { + if (has_empty_arg + && PACK_EXPANSION_FORCE_EXTRA_ARGS_P (t)) + return true; + /* If one pack has an expansion and another pack has a normal argument or if one pack has an empty argument and an another one hasn't then tsubst_pack_expansion cannot perform the @@ -12422,9 +12466,9 @@ use_pack_expansion_extra_args_p (tree parm_packs, return false; } - bool has_expansion_arg = false; for (int i = 0 ; i < arg_pack_len; ++i) { + bool has_expansion_arg = false; bool has_non_expansion_arg = false; for (tree parm_pack = parm_packs; parm_pack; @@ -12444,7 +12488,10 @@ use_pack_expansion_extra_args_p (tree parm_packs, } if (has_expansion_arg && has_non_expansion_arg) - return true; + { + gcc_checking_assert (false); + return true; + } } return false; } @@ -12784,7 +12831,11 @@ tsubst_binary_right_fold (tree t, tree args, tsubst_flags_t complain, class el_data { public: + /* Set of variables declared within the pattern. */ hash_set<tree> internal; + /* Set of AST nodes that have been visited by the traversal. */ + hash_set<tree> visited; + /* List of local_specializations used within the pattern. */ tree extra; tsubst_flags_t complain; @@ -12803,7 +12854,36 @@ extract_locals_r (tree *tp, int */*walk_subtrees*/, void *data_) tp = &TYPE_NAME (*tp); if (TREE_CODE (*tp) == DECL_EXPR) - data.internal.add (DECL_EXPR_DECL (*tp)); + { + tree decl = DECL_EXPR_DECL (*tp); + data.internal.add (decl); + if (VAR_P (decl) + && DECL_DECOMPOSITION_P (decl) + && TREE_TYPE (decl) != error_mark_node) + { + gcc_assert (DECL_NAME (decl) == NULL_TREE); + for (tree decl2 = DECL_CHAIN (decl); + decl2 + && VAR_P (decl2) + && DECL_DECOMPOSITION_P (decl2) + && DECL_NAME (decl2) + && TREE_TYPE (decl2) != error_mark_node; + decl2 = DECL_CHAIN (decl2)) + { + gcc_assert (DECL_DECOMP_BASE (decl2) == decl); + data.internal.add (decl2); + } + } + } + else if (TREE_CODE (*tp) == LAMBDA_EXPR) + { + /* Since we defer implicit capture, look in the parms and body. */ + tree fn = lambda_function (*tp); + cp_walk_tree (&TREE_TYPE (fn), &extract_locals_r, &data, + &data.visited); + cp_walk_tree (&DECL_SAVED_TREE (fn), &extract_locals_r, &data, + &data.visited); + } else if (tree spec = retrieve_local_specialization (*tp)) { if (data.internal.contains (*tp)) @@ -12860,7 +12940,7 @@ static tree extract_local_specs (tree pattern, tsubst_flags_t complain) { el_data data (complain); - cp_walk_tree_without_duplicates (&pattern, extract_locals_r, &data); + cp_walk_tree (&pattern, extract_locals_r, &data, &data.visited); return data.extra; } @@ -12870,7 +12950,9 @@ extract_local_specs (tree pattern, tsubst_flags_t complain) tree build_extra_args (tree pattern, tree args, tsubst_flags_t complain) { - tree extra = args; + /* Make a copy of the extra arguments so that they won't get changed + out from under us. */ + tree extra = copy_template_args (args); if (local_specializations) if (tree locals = extract_local_specs (pattern, complain)) extra = tree_cons (NULL_TREE, extra, locals); @@ -12881,7 +12963,7 @@ build_extra_args (tree pattern, tree args, tsubst_flags_t complain) normal template args to ARGS. */ tree -add_extra_args (tree extra, tree args) +add_extra_args (tree extra, tree args, tsubst_flags_t complain, tree in_decl) { if (extra && TREE_CODE (extra) == TREE_LIST) { @@ -12901,20 +12983,14 @@ add_extra_args (tree extra, tree args) gcc_assert (!TREE_PURPOSE (extra)); extra = TREE_VALUE (extra); } -#if 1 - /* I think we should always be able to substitute dependent args into the - pattern. If that turns out to be incorrect in some cases, enable the - alternate code (and add complain/in_decl parms to this function). */ - gcc_checking_assert (!uses_template_parms (extra)); -#else - if (!uses_template_parms (extra)) + if (uses_template_parms (extra)) { - gcc_unreachable (); + /* This can happen after dependent substitution into a + requires-expr or a lambda that uses constexpr if. */ extra = tsubst_template_args (extra, args, complain, in_decl); args = add_outermost_template_args (args, extra); } else -#endif args = add_to_template_args (extra, args); return args; } @@ -12940,7 +13016,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, pattern = PACK_EXPANSION_PATTERN (t); /* Add in any args remembered from an earlier partial instantiation. */ - args = add_extra_args (PACK_EXPANSION_EXTRA_ARGS (t), args); + args = add_extra_args (PACK_EXPANSION_EXTRA_ARGS (t), args, complain, in_decl); levels = TMPL_ARGS_DEPTH (args); @@ -13116,7 +13192,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, /* We cannot expand this expansion expression, because we don't have all of the argument packs we need. */ - if (use_pack_expansion_extra_args_p (packs, len, unsubstituted_packs)) + if (use_pack_expansion_extra_args_p (t, packs, len, unsubstituted_packs)) { /* We got some full packs, but we can't substitute them in until we have values for all the packs. So remember these until then. */ @@ -13141,12 +13217,25 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, pattern and return a PACK_EXPANSION_*. The caller will need to deal with that. */ if (TREE_CODE (t) == EXPR_PACK_EXPANSION) - t = tsubst_expr (pattern, args, complain, in_decl, + result = tsubst_expr (pattern, args, complain, in_decl, /*integral_constant_expression_p=*/false); else - t = tsubst (pattern, args, complain, in_decl); - t = make_pack_expansion (t, complain); - return t; + result = tsubst (pattern, args, complain, in_decl); + result = make_pack_expansion (result, complain); + PACK_EXPANSION_LOCAL_P (result) = PACK_EXPANSION_LOCAL_P (t); + PACK_EXPANSION_SIZEOF_P (result) = PACK_EXPANSION_SIZEOF_P (t); + if (PACK_EXPANSION_AUTO_P (t)) + { + /* This is a fake auto... pack expansion created in add_capture with + _PACKS that don't appear in the pattern. Copy one over. */ + packs = PACK_EXPANSION_PARAMETER_PACKS (t); + pack = retrieve_local_specialization (TREE_VALUE (packs)); + gcc_checking_assert (DECL_PACK_P (pack)); + PACK_EXPANSION_PARAMETER_PACKS (result) + = build_tree_list (NULL_TREE, pack); + PACK_EXPANSION_AUTO_P (result) = true; + } + return result; } gcc_assert (len >= 0); @@ -13206,36 +13295,6 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, return result; } -/* Given PARM_DECL PARM, find the corresponding PARM_DECL in the template - TMPL. We do this using DECL_PARM_INDEX, which should work even with - parameter packs; all parms generated from a function parameter pack will - have the same DECL_PARM_INDEX. */ - -tree -get_pattern_parm (tree parm, tree tmpl) -{ - tree pattern = DECL_TEMPLATE_RESULT (tmpl); - tree patparm; - - if (DECL_ARTIFICIAL (parm)) - { - for (patparm = DECL_ARGUMENTS (pattern); - patparm; patparm = DECL_CHAIN (patparm)) - if (DECL_ARTIFICIAL (patparm) - && DECL_NAME (parm) == DECL_NAME (patparm)) - break; - } - else - { - patparm = FUNCTION_FIRST_USER_PARM (DECL_TEMPLATE_RESULT (tmpl)); - patparm = chain_index (DECL_PARM_INDEX (parm)-1, patparm); - gcc_assert (DECL_PARM_INDEX (patparm) - == DECL_PARM_INDEX (parm)); - } - - return patparm; -} - /* Make an argument pack out of the TREE_VEC VEC. */ static tree @@ -13329,7 +13388,9 @@ tsubst_template_args (tree t, tree args, tsubst_flags_t complain, tree in_decl) tree orig_arg = TREE_VEC_ELT (t, i); tree new_arg; - if (TREE_CODE (orig_arg) == TREE_VEC) + if (!orig_arg) + new_arg = NULL_TREE; + else if (TREE_CODE (orig_arg) == TREE_VEC) new_arg = tsubst_template_args (orig_arg, args, complain, in_decl); else if (PACK_EXPANSION_P (orig_arg)) { @@ -13379,8 +13440,9 @@ tsubst_template_args (tree t, tree args, tsubst_flags_t complain, tree in_decl) } for (i = 0, out = 0; i < len; i++) { - if ((PACK_EXPANSION_P (TREE_VEC_ELT (orig_t, i)) - || ARGUMENT_PACK_P (TREE_VEC_ELT (orig_t, i))) + tree orig_arg = TREE_VEC_ELT (orig_t, i); + if (orig_arg + && (PACK_EXPANSION_P (orig_arg) || ARGUMENT_PACK_P (orig_arg)) && TREE_CODE (elts[i]) == TREE_VEC) { int idx; @@ -13887,45 +13949,6 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain, if (tree spec = retrieve_specialization (gen_tmpl, argvec, hash)) return spec; } - - /* We can see more levels of arguments than parameters if - there was a specialization of a member template, like - this: - - template <class T> struct S { template <class U> void f(); } - template <> template <class U> void S<int>::f(U); - - Here, we'll be substituting into the specialization, - because that's where we can find the code we actually - want to generate, but we'll have enough arguments for - the most general template. - - We also deal with the peculiar case: - - template <class T> struct S { - template <class U> friend void f(); - }; - template <class U> void f() {} - template S<int>; - template void f<double>(); - - Here, the ARGS for the instantiation of will be {int, - double}. But, we only need as many ARGS as there are - levels of template parameters in CODE_PATTERN. We are - careful not to get fooled into reducing the ARGS in - situations like: - - template <class T> struct S { template <class U> void f(U); } - template <class T> template <> void S<T>::f(int) {} - - which we can spot because the pattern will be a - specialization in this case. */ - int args_depth = TMPL_ARGS_DEPTH (args); - int parms_depth = - TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (t))); - - if (args_depth > parms_depth && !DECL_TEMPLATE_SPECIALIZATION (t)) - args = get_innermost_template_args (args, parms_depth); } else { @@ -14060,10 +14083,7 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain, don't substitute through the constraints; that's only done when they are checked. */ if (tree ci = get_constraints (t)) - /* Unless we're regenerating a lambda, in which case we'll set the - lambda's constraints in tsubst_lambda_expr. */ - if (!lambda_fntype) - set_constraints (r, ci); + set_constraints (r, ci); if (DECL_FRIEND_CONTEXT (t)) SET_DECL_FRIEND_CONTEXT (r, @@ -14297,8 +14317,7 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain, } else { - if (TREE_CODE (decl) != TYPE_DECL || !TYPE_DECL_ALIAS_P (decl)) - DECL_TI_TEMPLATE (inner) = r; + DECL_TI_TEMPLATE (inner) = r; DECL_TI_ARGS (r) = DECL_TI_ARGS (inner); } @@ -14311,17 +14330,13 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain, /* Propagate module information from the decl. */ DECL_MODULE_EXPORT_P (r) = DECL_MODULE_EXPORT_P (inner); if (DECL_LANG_SPECIFIC (inner)) - { - DECL_MODULE_PURVIEW_P (r) = DECL_MODULE_PURVIEW_P (inner); - /* If this is a constrained template, the above tsubst of - inner can find the unconstrained template, which may have - come from an import. This is ok, because we don't - register this instantiation (see below). */ - gcc_checking_assert (!DECL_MODULE_IMPORT_P (inner) - || (TEMPLATE_PARMS_CONSTRAINTS - (DECL_TEMPLATE_PARMS (t)))); - DECL_MODULE_IMPORT_P (r) = false; - } + /* If this is a constrained template, the above tsubst of + inner can find the unconstrained template, which may have + come from an import. This is ok, because we don't + register this instantiation (see below). */ + gcc_checking_assert (!DECL_MODULE_IMPORT_P (inner) + || (TEMPLATE_PARMS_CONSTRAINTS + (DECL_TEMPLATE_PARMS (t)))); } DECL_TEMPLATE_INSTANTIATIONS (r) = NULL_TREE; @@ -14354,52 +14369,43 @@ lambda_fn_in_template_p (tree fn) which the above is true. */ bool -instantiated_lambda_fn_p (tree fn) +regenerated_lambda_fn_p (tree fn) { if (!fn || !LAMBDA_FUNCTION_P (fn)) return false; tree closure = DECL_CONTEXT (fn); tree lam = CLASSTYPE_LAMBDA_EXPR (closure); - return LAMBDA_EXPR_INSTANTIATED (lam); + return LAMBDA_EXPR_REGEN_INFO (lam) != NULL_TREE; +} + +/* Return the LAMBDA_EXPR from which T was ultimately regenerated. + If T is not a regenerated LAMBDA_EXPR, return T. */ + +tree +most_general_lambda (tree t) +{ + while (tree ti = LAMBDA_EXPR_REGEN_INFO (t)) + t = TI_TEMPLATE (ti); + return t; } /* We're instantiating a variable from template function TCTX. Return the - corresponding current enclosing scope. This gets complicated because lambda - functions in templates are regenerated rather than instantiated, but generic - lambda functions are subsequently instantiated. */ + corresponding current enclosing scope. We can match them up using + DECL_SOURCE_LOCATION because lambdas only ever have one source location, and + the DECL_SOURCE_LOCATION for a function instantiation is updated to match + the template definition in regenerate_decl_from_template. */ static tree -enclosing_instantiation_of (tree otctx) +enclosing_instantiation_of (tree tctx) { - tree tctx = otctx; tree fn = current_function_decl; - int lambda_count = 0; - for (; tctx && (lambda_fn_in_template_p (tctx) - || instantiated_lambda_fn_p (tctx)); - tctx = decl_function_context (tctx)) - ++lambda_count; + /* We shouldn't ever need to do this for other artificial functions. */ + gcc_assert (!DECL_ARTIFICIAL (tctx) || LAMBDA_FUNCTION_P (tctx)); + for (; fn; fn = decl_function_context (fn)) - { - tree ofn = fn; - int flambda_count = 0; - for (; fn && instantiated_lambda_fn_p (fn); - fn = decl_function_context (fn)) - ++flambda_count; - if ((fn && DECL_TEMPLATE_INFO (fn)) - ? most_general_template (fn) != most_general_template (tctx) - : fn != tctx) - continue; - if (flambda_count != lambda_count) - { - gcc_assert (flambda_count > lambda_count); - for (; flambda_count > lambda_count; --flambda_count) - ofn = decl_function_context (ofn); - } - gcc_assert (DECL_NAME (ofn) == DECL_NAME (otctx) - || DECL_CONV_FN_P (ofn)); - return ofn; - } + if (DECL_SOURCE_LOCATION (fn) == DECL_SOURCE_LOCATION (tctx)) + return fn; gcc_unreachable (); } @@ -14979,20 +14985,13 @@ tsubst_arg_types (tree arg_types, tsubst_flags_t complain, tree in_decl) { - tree remaining_arg_types; tree type = NULL_TREE; - int i = 1; + int len = 1; tree expanded_args = NULL_TREE; - tree default_arg; if (!arg_types || arg_types == void_list_node || arg_types == end) return arg_types; - remaining_arg_types = tsubst_arg_types (TREE_CHAIN (arg_types), - args, end, complain, in_decl); - if (remaining_arg_types == error_mark_node) - return error_mark_node; - if (PACK_EXPANSION_P (TREE_VALUE (arg_types))) { /* For a pack expansion, perform substitution on the @@ -15003,7 +15002,7 @@ tsubst_arg_types (tree arg_types, if (TREE_CODE (expanded_args) == TREE_VEC) /* So that we'll spin through the parameters, one by one. */ - i = TREE_VEC_LENGTH (expanded_args); + len = TREE_VEC_LENGTH (expanded_args); else { /* We only partially substituted into the parameter @@ -15012,59 +15011,71 @@ tsubst_arg_types (tree arg_types, expanded_args = NULL_TREE; } } + else + type = tsubst (TREE_VALUE (arg_types), args, complain, in_decl); - while (i > 0) { - --i; - - if (expanded_args) - type = TREE_VEC_ELT (expanded_args, i); - else if (!type) - type = tsubst (TREE_VALUE (arg_types), args, complain, in_decl); + /* Check if a substituted type is erroneous before substituting into + the rest of the chain. */ + for (int i = 0; i < len; i++) + { + if (expanded_args) + type = TREE_VEC_ELT (expanded_args, i); - if (type == error_mark_node) - return error_mark_node; - if (VOID_TYPE_P (type)) - { - if (complain & tf_error) - { - error ("invalid parameter type %qT", type); - if (in_decl) - error ("in declaration %q+D", in_decl); - } - return error_mark_node; + if (type == error_mark_node) + return error_mark_node; + if (VOID_TYPE_P (type)) + { + if (complain & tf_error) + { + error ("invalid parameter type %qT", type); + if (in_decl) + error ("in declaration %q+D", in_decl); + } + return error_mark_node; + } } - /* Do array-to-pointer, function-to-pointer conversion, and ignore - top-level qualifiers as required. */ - type = cv_unqualified (type_decays_to (type)); + /* We do not substitute into default arguments here. The standard + mandates that they be instantiated only when needed, which is + done in build_over_call. */ + tree default_arg = TREE_PURPOSE (arg_types); + + /* Except that we do substitute default arguments under tsubst_lambda_expr, + since the new op() won't have any associated template arguments for us + to refer to later. */ + if (lambda_fn_in_template_p (in_decl)) + default_arg = tsubst_copy_and_build (default_arg, args, complain, in_decl, + false/*fn*/, false/*constexpr*/); + + tree remaining_arg_types = tsubst_arg_types (TREE_CHAIN (arg_types), + args, end, complain, in_decl); + if (remaining_arg_types == error_mark_node) + return error_mark_node; - /* We do not substitute into default arguments here. The standard - mandates that they be instantiated only when needed, which is - done in build_over_call. */ - default_arg = TREE_PURPOSE (arg_types); + for (int i = len-1; i >= 0; i--) + { + if (expanded_args) + type = TREE_VEC_ELT (expanded_args, i); - /* Except that we do substitute default arguments under tsubst_lambda_expr, - since the new op() won't have any associated template arguments for us - to refer to later. */ - if (lambda_fn_in_template_p (in_decl)) - default_arg = tsubst_copy_and_build (default_arg, args, complain, in_decl, - false/*fn*/, false/*constexpr*/); + /* Do array-to-pointer, function-to-pointer conversion, and ignore + top-level qualifiers as required. */ + type = cv_unqualified (type_decays_to (type)); - if (default_arg && TREE_CODE (default_arg) == DEFERRED_PARSE) - { - /* We've instantiated a template before its default arguments - have been parsed. This can happen for a nested template - class, and is not an error unless we require the default - argument in a call of this function. */ - remaining_arg_types = - tree_cons (default_arg, type, remaining_arg_types); - vec_safe_push (DEFPARSE_INSTANTIATIONS (default_arg), - remaining_arg_types); - } - else - remaining_arg_types = - hash_tree_cons (default_arg, type, remaining_arg_types); - } + if (default_arg && TREE_CODE (default_arg) == DEFERRED_PARSE) + { + /* We've instantiated a template before its default arguments + have been parsed. This can happen for a nested template + class, and is not an error unless we require the default + argument in a call of this function. */ + remaining_arg_types + = tree_cons (default_arg, type, remaining_arg_types); + vec_safe_push (DEFPARSE_INSTANTIATIONS (default_arg), + remaining_arg_types); + } + else + remaining_arg_types + = hash_tree_cons (default_arg, type, remaining_arg_types); + } return remaining_arg_types; } @@ -16270,8 +16281,19 @@ tsubst_baselink (tree baselink, tree object_type, fns = BASELINK_FUNCTIONS (baselink); } else - /* We're going to overwrite pieces below, make a duplicate. */ - baselink = copy_node (baselink); + { + /* We're going to overwrite pieces below, make a duplicate. */ + baselink = copy_node (baselink); + + if (qualifying_scope != BINFO_TYPE (BASELINK_ACCESS_BINFO (baselink))) + { + /* The decl we found was from non-dependent scope, but we still need + to update the binfos for the instantiated qualifying_scope. */ + BASELINK_ACCESS_BINFO (baselink) = TYPE_BINFO (qualifying_scope); + BASELINK_BINFO (baselink) = lookup_base (qualifying_scope, binfo_type, + ba_unique, nullptr, complain); + } + } /* If lookup found a single function, mark it as used at this point. (If lookup found multiple functions the one selected later by @@ -17083,7 +17105,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl); tree op2 = tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl); r = build_nt (code, op0, op1, op2); - TREE_NO_WARNING (r) = TREE_NO_WARNING (t); + copy_warning (r, t); return r; } @@ -17397,6 +17419,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort, case OMP_CLAUSE_COPYPRIVATE: case OMP_CLAUSE_UNIFORM: case OMP_CLAUSE_DEPEND: + case OMP_CLAUSE_AFFINITY: case OMP_CLAUSE_FROM: case OMP_CLAUSE_TO: case OMP_CLAUSE_MAP: @@ -17428,6 +17451,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort, case OMP_CLAUSE_PRIORITY: case OMP_CLAUSE_ORDERED: case OMP_CLAUSE_HINT: + case OMP_CLAUSE_FILTER: case OMP_CLAUSE_NUM_GANGS: case OMP_CLAUSE_NUM_WORKERS: case OMP_CLAUSE_VECTOR_LENGTH: @@ -17513,6 +17537,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort, case OMP_CLAUSE_SEQ: case OMP_CLAUSE_IF_PRESENT: case OMP_CLAUSE_FINALIZE: + case OMP_CLAUSE_NOHOST: break; default: gcc_unreachable (); @@ -18150,9 +18175,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, { case STATEMENT_LIST: { - tree_stmt_iterator i; - for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) - RECUR (tsi_stmt (i)); + for (tree stmt : tsi_range (t)) + RECUR (stmt); break; } @@ -18446,8 +18470,9 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, case IF_STMT: stmt = begin_if_stmt (); IF_STMT_CONSTEXPR_P (stmt) = IF_STMT_CONSTEXPR_P (t); + IF_STMT_CONSTEVAL_P (stmt) = IF_STMT_CONSTEVAL_P (t); if (IF_STMT_CONSTEXPR_P (t)) - args = add_extra_args (IF_STMT_EXTRA_ARGS (t), args); + args = add_extra_args (IF_STMT_EXTRA_ARGS (t), args, complain, in_decl); tmp = RECUR (IF_COND (t)); tmp = finish_if_stmt_cond (tmp, stmt); if (IF_STMT_CONSTEXPR_P (t) @@ -18466,6 +18491,13 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, } if (IF_STMT_CONSTEXPR_P (t) && integer_zerop (tmp)) /* Don't instantiate the THEN_CLAUSE. */; + else if (IF_STMT_CONSTEVAL_P (t)) + { + bool save_in_consteval_if_p = in_consteval_if_p; + in_consteval_if_p = true; + RECUR (THEN_CLAUSE (t)); + in_consteval_if_p = save_in_consteval_if_p; + } else { tree folded = fold_non_dependent_expr (tmp, complain); @@ -18812,9 +18844,11 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, break; case OMP_SECTIONS: + case OMP_MASKED: omp_parallel_combined_clauses = NULL; /* FALLTHRU */ case OMP_SINGLE: + case OMP_SCOPE: case OMP_TEAMS: case OMP_CRITICAL: case OMP_TASKGROUP: @@ -18882,9 +18916,12 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, case OACC_DATA: case OMP_TARGET_DATA: case OMP_TARGET: - tmp = tsubst_omp_clauses (OMP_CLAUSES (t), (TREE_CODE (t) == OACC_DATA) - ? C_ORT_ACC : C_ORT_OMP, args, complain, - in_decl); + tmp = tsubst_omp_clauses (OMP_CLAUSES (t), + TREE_CODE (t) == OACC_DATA + ? C_ORT_ACC + : TREE_CODE (t) == OMP_TARGET + ? C_ORT_OMP_TARGET : C_ORT_OMP, + args, complain, in_decl); keep_next_level (true); stmt = begin_omp_structured_block (); @@ -19165,8 +19202,7 @@ tsubst_omp_udr (tree t, tree args, tsubst_flags_t complain, tree in_decl) block = finish_omp_structured_block (block); block = maybe_cleanup_point_expr_void (block); add_decl_expr (omp_out); - if (TREE_NO_WARNING (DECL_EXPR_DECL (stmts[0]))) - TREE_NO_WARNING (omp_out) = 1; + copy_warning (omp_out, DECL_EXPR_DECL (stmts[0])); add_decl_expr (omp_in); finish_expr_stmt (block); } @@ -19258,7 +19294,12 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (r) = LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (t); LAMBDA_EXPR_MUTABLE_P (r) = LAMBDA_EXPR_MUTABLE_P (t); - LAMBDA_EXPR_INSTANTIATED (r) = true; + if (tree ti = LAMBDA_EXPR_REGEN_INFO (t)) + LAMBDA_EXPR_REGEN_INFO (r) + = build_template_info (t, add_to_template_args (TI_ARGS (ti), args)); + else + LAMBDA_EXPR_REGEN_INFO (r) + = build_template_info (t, args); gcc_assert (LAMBDA_EXPR_THIS_CAPTURE (t) == NULL_TREE && LAMBDA_EXPR_PENDING_PROXIES (t) == NULL); @@ -19400,17 +19441,6 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) finish_member_declaration (fn); } - if (tree ci = get_constraints (oldfn)) - { - /* Substitute into the lambda's constraints. */ - if (oldtmpl) - ++processing_template_decl; - ci = tsubst_constraint_info (ci, args, complain, in_decl); - if (oldtmpl) - --processing_template_decl; - set_constraints (fn, ci); - } - /* Let finish_function set this. */ DECL_DECLARED_CONSTEXPR_P (fn) = false; @@ -19424,6 +19454,9 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) local_specialization_stack s (lss_copy); + bool save_in_consteval_if_p = in_consteval_if_p; + in_consteval_if_p = false; + tree body = start_lambda_function (fn, r); /* Now record them for lookup_init_capture_pack. */ @@ -19454,11 +19487,18 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) the purposes of template argument deduction. */ complain = tf_warning_or_error; - tsubst_expr (DECL_SAVED_TREE (oldfn), args, complain, r, - /*constexpr*/false); + tree saved = DECL_SAVED_TREE (oldfn); + if (TREE_CODE (saved) == BIND_EXPR && BIND_EXPR_BODY_BLOCK (saved)) + /* We already have a body block from start_lambda_function, we don't + need another to confuse NRV (91217). */ + saved = BIND_EXPR_BODY (saved); + + tsubst_expr (saved, args, complain, r, /*constexpr*/false); finish_lambda_function (body); + in_consteval_if_p = save_in_consteval_if_p; + if (nested) pop_function_context (); else @@ -19481,6 +19521,63 @@ out: return r; } +/* Subroutine of maybe_fold_fn_template_args. */ + +static bool +fold_targs_r (tree targs, tsubst_flags_t complain) +{ + int len = TREE_VEC_LENGTH (targs); + for (int i = 0; i < len; ++i) + { + tree &elt = TREE_VEC_ELT (targs, i); + if (!elt || TYPE_P (elt) + || TREE_CODE (elt) == TEMPLATE_DECL) + continue; + if (TREE_CODE (elt) == NONTYPE_ARGUMENT_PACK) + { + if (!fold_targs_r (ARGUMENT_PACK_ARGS (elt), complain)) + return false; + } + else if (/* We can only safely preevaluate scalar prvalues. */ + SCALAR_TYPE_P (TREE_TYPE (elt)) + && !glvalue_p (elt) + && !TREE_CONSTANT (elt)) + { + elt = cxx_constant_value_sfinae (elt, complain); + if (elt == error_mark_node) + return false; + } + } + + return true; +} + +/* Try to do constant evaluation of any explicit template arguments in FN + before overload resolution, to get any errors only once. Return true iff + we didn't have any problems folding. */ + +static bool +maybe_fold_fn_template_args (tree fn, tsubst_flags_t complain) +{ + if (processing_template_decl || fn == NULL_TREE) + return true; + if (fn == error_mark_node) + return false; + if (TREE_CODE (fn) == OFFSET_REF + || TREE_CODE (fn) == COMPONENT_REF) + fn = TREE_OPERAND (fn, 1); + if (BASELINK_P (fn)) + fn = BASELINK_FUNCTIONS (fn); + if (TREE_CODE (fn) != TEMPLATE_ID_EXPR) + return true; + tree targs = TREE_OPERAND (fn, 1); + if (targs == NULL_TREE) + return true; + if (targs == error_mark_node) + return false; + return fold_targs_r (targs, complain); +} + /* Like tsubst but deals with expressions and performs semantic analysis. FUNCTION_P is true if T is the "F" in "F (ARGS)" or "F<TARGS> (ARGS)". */ @@ -19716,6 +19813,7 @@ tsubst_copy_and_build (tree t, warning_sentinel s(warn_useless_cast); warning_sentinel s2(warn_ignored_qualifiers); + warning_sentinel s3(warn_int_in_bool_context); switch (TREE_CODE (t)) { case CAST_EXPR: @@ -19770,6 +19868,7 @@ tsubst_copy_and_build (tree t, complain|decltype_flag)); case FIX_TRUNC_EXPR: + /* convert_like should have created an IMPLICIT_CONV_EXPR. */ gcc_unreachable (); case ADDR_EXPR: @@ -19817,15 +19916,21 @@ tsubst_copy_and_build (tree t, case MEMBER_REF: case DOTSTAR_EXPR: { - /* If T was type-dependent, suppress warnings that depend on the range - of the types involved. */ - ++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)); + /* If either OP0 or OP1 was value- or type-dependent, suppress + warnings that depend on the range of the types involved. */ + tree op0 = TREE_OPERAND (t, 0); + tree op1 = TREE_OPERAND (t, 1); + auto dep_p = [](tree t) { + ++processing_template_decl; + bool r = (potential_constant_expression (t) + ? value_dependent_expression_p (t) + : type_dependent_expression_p (t)); + --processing_template_decl; + return r; + }; + const bool was_dep = dep_p (op0) || dep_p (op1); + op0 = RECUR (op0); + op1 = RECUR (op1); warning_sentinel s1(warn_type_limits, was_dep); warning_sentinel s2(warn_div_by_zero, was_dep); @@ -19835,17 +19940,17 @@ tsubst_copy_and_build (tree t, tree r = build_x_binary_op (input_location, TREE_CODE (t), op0, - (TREE_NO_WARNING (TREE_OPERAND (t, 0)) + (warning_suppressed_p (TREE_OPERAND (t, 0)) ? ERROR_MARK : TREE_CODE (TREE_OPERAND (t, 0))), op1, - (TREE_NO_WARNING (TREE_OPERAND (t, 1)) + (warning_suppressed_p (TREE_OPERAND (t, 1)) ? ERROR_MARK : TREE_CODE (TREE_OPERAND (t, 1))), /*overload=*/NULL, complain|decltype_flag); - if (EXPR_P (r) && TREE_NO_WARNING (t)) - TREE_NO_WARNING (r) = TREE_NO_WARNING (t); + if (EXPR_P (r)) + copy_warning (r, t); RETURN (r); } @@ -19981,8 +20086,8 @@ tsubst_copy_and_build (tree t, set and must be copied. In the latter case, build_x_modify_expr sets it and it must not be reset here. */ - if (TREE_NO_WARNING (t)) - TREE_NO_WARNING (r) = TREE_NO_WARNING (t); + if (warning_suppressed_p (t, OPT_Wparentheses)) + suppress_warning (r, OPT_Wparentheses); RETURN (r); } @@ -20137,7 +20242,13 @@ tsubst_copy_and_build (tree t, /* Avoid error about taking the address of a constructor. */ function = TREE_OPERAND (function, 0); - function = tsubst_copy_and_build (function, args, complain, + tsubst_flags_t subcomplain = complain; + if (koenig_p && TREE_CODE (function) == FUNCTION_DECL) + /* When KOENIG_P, we don't want to mark_used the callee before + augmenting the overload set via ADL, so during this initial + substitution we disable mark_used by setting tf_conv (68942). */ + subcomplain |= tf_conv; + function = tsubst_copy_and_build (function, args, subcomplain, in_decl, !qualified_p, integral_constant_expression_p); @@ -20345,6 +20456,9 @@ tsubst_copy_and_build (tree t, && !mark_used (function, complain) && !(complain & tf_error)) RETURN (error_mark_node); + if (!maybe_fold_fn_template_args (function, complain)) + return error_mark_node; + /* Put back tf_decltype for the actual call. */ complain |= decltype_flag; @@ -20383,6 +20497,15 @@ tsubst_copy_and_build (tree t, RETURN (ret); break; + case IFN_SHUFFLEVECTOR: + { + ret = build_x_shufflevector (input_location, call_args, + complain); + if (ret != error_mark_node) + RETURN (ret); + break; + } + default: /* Unsupported internal function with arguments. */ gcc_unreachable (); @@ -20527,7 +20650,13 @@ tsubst_copy_and_build (tree t, if (member == error_mark_node) RETURN (error_mark_node); - if (TREE_CODE (member) == FIELD_DECL) + if (object_type && TYPE_PTRMEMFUNC_P (object_type) + && TREE_CODE (member) == FIELD_DECL) + { + r = build_ptrmemfunc_access_expr (object, DECL_NAME (member)); + RETURN (r); + } + else if (TREE_CODE (member) == FIELD_DECL) { r = finish_non_static_data_member (member, object, NULL_TREE); if (TREE_CODE (r) == COMPONENT_REF) @@ -21093,7 +21222,7 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain) /* We need to determine if we're using a partial or explicit specialization now, because the type of the variable could be different. */ - tree tid = lookup_template_variable (gen_tmpl, targ_ptr); + tree tid = lookup_template_variable (tmpl, targ_ptr); tree elt = most_specialized_partial_spec (tid, complain); if (elt == error_mark_node) pattern = error_mark_node; @@ -21693,6 +21822,41 @@ fn_type_unification (tree fn, return r; } +/* Returns true iff PARM is a forwarding reference in the context of + template argument deduction for TMPL. */ + +static bool +forwarding_reference_p (tree parm, tree tmpl) +{ + /* [temp.deduct.call], "A forwarding reference is an rvalue reference to a + cv-unqualified template parameter ..." */ + if (TYPE_REF_P (parm) + && TYPE_REF_IS_RVALUE (parm) + && TREE_CODE (TREE_TYPE (parm)) == TEMPLATE_TYPE_PARM + && cp_type_quals (TREE_TYPE (parm)) == TYPE_UNQUALIFIED) + { + parm = TREE_TYPE (parm); + /* [temp.deduct.call], "... that does not represent a template parameter + of a class template (during class template argument deduction)." */ + if (tmpl + && deduction_guide_p (tmpl) + && DECL_ARTIFICIAL (tmpl)) + { + /* Since the template parameters of a synthesized guide consist of + the template parameters of the class template followed by those of + the constructor (if any), we can tell if PARM represents a template + parameter of the class template by comparing its index with the + arity of the class template. */ + tree ctmpl = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (TREE_TYPE (tmpl))); + if (TEMPLATE_TYPE_IDX (parm) + < TREE_VEC_LENGTH (DECL_INNERMOST_TEMPLATE_PARMS (ctmpl))) + return false; + } + return true; + } + return false; +} + /* Adjust types before performing type deduction, as described in [temp.deduct.call] and [temp.deduct.conv]. The rules in these two sections are symmetric. PARM is the type of a function parameter @@ -21702,7 +21866,8 @@ fn_type_unification (tree fn, ARG_EXPR is the original argument expression, which may be null. */ static int -maybe_adjust_types_for_deduction (unification_kind_t strict, +maybe_adjust_types_for_deduction (tree tparms, + unification_kind_t strict, tree* parm, tree* arg, tree arg_expr) @@ -21725,10 +21890,7 @@ maybe_adjust_types_for_deduction (unification_kind_t strict, /* Core issue #873: Do the DR606 thing (see below) for these cases, too, but here handle it by stripping the reference from PARM rather than by adding it to ARG. */ - if (TYPE_REF_P (*parm) - && TYPE_REF_IS_RVALUE (*parm) - && TREE_CODE (TREE_TYPE (*parm)) == TEMPLATE_TYPE_PARM - && cp_type_quals (TREE_TYPE (*parm)) == TYPE_UNQUALIFIED + if (forwarding_reference_p (*parm, TPARMS_PRIMARY_TEMPLATE (tparms)) && TYPE_REF_P (*arg) && !TYPE_REF_IS_RVALUE (*arg)) *parm = TREE_TYPE (*parm); @@ -21765,17 +21927,10 @@ maybe_adjust_types_for_deduction (unification_kind_t strict, *arg = TYPE_MAIN_VARIANT (*arg); } - /* [14.8.2.1/3 temp.deduct.call], "A forwarding reference is an rvalue - reference to a cv-unqualified template parameter that does not represent a - template parameter of a class template (during class template argument - deduction (13.3.1.8)). If P is a forwarding reference and the argument is - an lvalue, the type "lvalue reference to A" is used in place of A for type - deduction. */ - if (TYPE_REF_P (*parm) - && TYPE_REF_IS_RVALUE (*parm) - && TREE_CODE (TREE_TYPE (*parm)) == TEMPLATE_TYPE_PARM - && !TEMPLATE_TYPE_PARM_FOR_CLASS (TREE_TYPE (*parm)) - && cp_type_quals (TREE_TYPE (*parm)) == TYPE_UNQUALIFIED + /* [temp.deduct.call], "If P is a forwarding reference and the argument is + an lvalue, the type 'lvalue reference to A' is used in place of A for + type deduction." */ + if (forwarding_reference_p (*parm, TPARMS_PRIMARY_TEMPLATE (tparms)) && (arg_expr ? lvalue_p (arg_expr) /* try_one_overload doesn't provide an arg_expr, but functions are always lvalues. */ @@ -21858,8 +22013,10 @@ static bool uses_deducible_template_parms (tree type); static bool deducible_expression (tree expr) { - /* Strip implicit conversions. */ - while (CONVERT_EXPR_P (expr) || TREE_CODE (expr) == VIEW_CONVERT_EXPR) + /* Strip implicit conversions and implicit INDIRECT_REFs. */ + while (CONVERT_EXPR_P (expr) + || TREE_CODE (expr) == VIEW_CONVERT_EXPR + || REFERENCE_REF_P (expr)) expr = TREE_OPERAND (expr, 0); return (TREE_CODE (expr) == TEMPLATE_PARM_INDEX); } @@ -22062,8 +22219,8 @@ unify_one_argument (tree tparms, tree targs, tree parm, tree arg, return unify_invalid (explain_p); } - arg_strict |= - maybe_adjust_types_for_deduction (strict, &parm, &arg, arg_expr); + arg_strict |= maybe_adjust_types_for_deduction (tparms, strict, + &parm, &arg, arg_expr); } else if ((TYPE_P (parm) || TREE_CODE (parm) == TEMPLATE_DECL) @@ -22732,7 +22889,8 @@ try_one_overload (tree tparms, else if (addr_p) arg = build_pointer_type (arg); - sub_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg, NULL); + sub_strict |= maybe_adjust_types_for_deduction (tparms, strict, + &parm, &arg, NULL_TREE); /* We don't copy orig_targs for this because if we have already deduced some template args from previous args, unify would complain when we @@ -23431,7 +23589,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, /* It should only be possible to get here for a call. */ gcc_assert (elt_strict & UNIFY_ALLOW_OUTER_LEVEL); elt_strict |= maybe_adjust_types_for_deduction - (DEDUCE_CALL, &elttype, &type, elt); + (tparms, DEDUCE_CALL, &elttype, &type, elt); elt = type; } @@ -23564,6 +23722,10 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, return 1; arg = TYPE_TI_TEMPLATE (arg); + if (DECL_TEMPLATE_TEMPLATE_PARM_P (arg)) + /* If the template is a template template parameter, use the + TEMPLATE_TEMPLATE_PARM for matching. */ + arg = TREE_TYPE (arg); /* Fall through to deduce template name. */ } @@ -24206,7 +24368,10 @@ mark_decl_instantiated (tree result, int extern_p) DECL_COMDAT (result) = 0; if (extern_p) - DECL_NOT_REALLY_EXTERN (result) = 0; + { + DECL_EXTERNAL (result) = 1; + DECL_NOT_REALLY_EXTERN (result) = 0; + } else { mark_definable (result); @@ -24937,26 +25102,33 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain) tree outer_args = NULL_TREE; tree tmpl, args; + tree decl; if (TYPE_P (target)) { tree tinfo = CLASSTYPE_TEMPLATE_INFO (target); tmpl = TI_TEMPLATE (tinfo); args = TI_ARGS (tinfo); + decl = TYPE_NAME (target); } else if (TREE_CODE (target) == TEMPLATE_ID_EXPR) { tmpl = TREE_OPERAND (target, 0); args = TREE_OPERAND (target, 1); + decl = DECL_TEMPLATE_RESULT (tmpl); } else if (VAR_P (target)) { tree tinfo = DECL_TEMPLATE_INFO (target); tmpl = TI_TEMPLATE (tinfo); args = TI_ARGS (tinfo); + decl = target; } else gcc_unreachable (); + push_access_scope_guard pas (decl); + deferring_access_check_sentinel acs (dk_no_deferred); + tree main_tmpl = most_general_template (tmpl); /* For determining which partial specialization to use, only the @@ -25384,12 +25556,13 @@ regenerate_decl_from_template (tree decl, tree tmpl, tree args) if (TREE_CODE (decl) == FUNCTION_DECL) { - tree decl_parm; - tree pattern_parm; tree specs; int args_depth; int parms_depth; + /* Use the source location of the definition. */ + DECL_SOURCE_LOCATION (decl) = DECL_SOURCE_LOCATION (tmpl); + args_depth = TMPL_ARGS_DEPTH (args); parms_depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)); if (args_depth > parms_depth) @@ -25409,65 +25582,18 @@ regenerate_decl_from_template (tree decl, tree tmpl, tree args) } /* Merge parameter declarations. */ - decl_parm = skip_artificial_parms_for (decl, - DECL_ARGUMENTS (decl)); - pattern_parm - = skip_artificial_parms_for (code_pattern, - DECL_ARGUMENTS (code_pattern)); - while (decl_parm && !DECL_PACK_P (pattern_parm)) - { - tree parm_type; - tree attributes; - - if (DECL_NAME (decl_parm) != DECL_NAME (pattern_parm)) - DECL_NAME (decl_parm) = DECL_NAME (pattern_parm); - parm_type = tsubst (TREE_TYPE (pattern_parm), args, tf_error, - NULL_TREE); - parm_type = type_decays_to (parm_type); - if (!same_type_p (TREE_TYPE (decl_parm), parm_type)) - TREE_TYPE (decl_parm) = parm_type; - attributes = DECL_ATTRIBUTES (pattern_parm); - if (DECL_ATTRIBUTES (decl_parm) != attributes) - { - DECL_ATTRIBUTES (decl_parm) = attributes; - cplus_decl_attributes (&decl_parm, attributes, /*flags=*/0); - } - decl_parm = DECL_CHAIN (decl_parm); - pattern_parm = DECL_CHAIN (pattern_parm); + if (tree pattern_parm + = skip_artificial_parms_for (code_pattern, + DECL_ARGUMENTS (code_pattern))) + { + tree *p = &DECL_ARGUMENTS (decl); + for (int skip = num_artificial_parms_for (decl); skip; --skip) + p = &DECL_CHAIN (*p); + *p = tsubst_decl (pattern_parm, args, tf_error); + for (tree t = *p; t; t = DECL_CHAIN (t)) + DECL_CONTEXT (t) = decl; } - /* Merge any parameters that match with the function parameter - pack. */ - if (pattern_parm && DECL_PACK_P (pattern_parm)) - { - int i, len; - tree expanded_types; - /* Expand the TYPE_PACK_EXPANSION that provides the types for - the parameters in this function parameter pack. */ - expanded_types = tsubst_pack_expansion (TREE_TYPE (pattern_parm), - args, tf_error, NULL_TREE); - len = TREE_VEC_LENGTH (expanded_types); - for (i = 0; i < len; i++) - { - tree parm_type; - tree attributes; - - if (DECL_NAME (decl_parm) != DECL_NAME (pattern_parm)) - /* Rename the parameter to include the index. */ - DECL_NAME (decl_parm) = - make_ith_pack_parameter_name (DECL_NAME (pattern_parm), i); - parm_type = TREE_VEC_ELT (expanded_types, i); - parm_type = type_decays_to (parm_type); - if (!same_type_p (TREE_TYPE (decl_parm), parm_type)) - TREE_TYPE (decl_parm) = parm_type; - attributes = DECL_ATTRIBUTES (pattern_parm); - if (DECL_ATTRIBUTES (decl_parm) != attributes) - { - DECL_ATTRIBUTES (decl_parm) = attributes; - cplus_decl_attributes (&decl_parm, attributes, /*flags=*/0); - } - decl_parm = DECL_CHAIN (decl_parm); - } - } + /* Merge additional specifiers from the CODE_PATTERN. */ if (DECL_DECLARED_INLINE_P (code_pattern) && !DECL_DECLARED_INLINE_P (decl)) @@ -26004,11 +26130,10 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p) td = template_for_substitution (d); args = gen_args; - if (VAR_P (d)) + if (variable_template_specialization_p (d)) { /* Look up an explicit specialization, if any. */ - tree tid = lookup_template_variable (gen_tmpl, gen_args); - tree elt = most_specialized_partial_spec (tid, tf_warning_or_error); + tree elt = most_specialized_partial_spec (d, tf_warning_or_error); if (elt && elt != error_mark_node) { td = TREE_VALUE (elt); @@ -26338,9 +26463,16 @@ tsubst_initializer_list (tree t, tree argvec) tree expanded_exprs; /* Expand the argument. */ - SET_PACK_EXPANSION_PATTERN (expr, TREE_VALUE (arg)); + tree value; + if (TREE_CODE (TREE_VALUE (arg)) == EXPR_PACK_EXPANSION) + value = TREE_VALUE (arg); + else + { + value = expr; + SET_PACK_EXPANSION_PATTERN (value, TREE_VALUE (arg)); + } expanded_exprs - = tsubst_pack_expansion (expr, argvec, + = tsubst_pack_expansion (value, argvec, tf_warning_or_error, NULL_TREE); if (expanded_exprs == error_mark_node) @@ -26349,12 +26481,17 @@ tsubst_initializer_list (tree t, tree argvec) /* Prepend each of the expanded expressions to the corresponding TREE_LIST in EXPANDED_ARGUMENTS. */ for (i = 0; i < len; i++) - { - TREE_VEC_ELT (expanded_arguments, i) = - tree_cons (NULL_TREE, - TREE_VEC_ELT (expanded_exprs, i), - TREE_VEC_ELT (expanded_arguments, i)); - } + if (TREE_CODE (TREE_VALUE (arg)) == EXPR_PACK_EXPANSION) + for (int j = 0; j < TREE_VEC_LENGTH (expanded_exprs); j++) + TREE_VEC_ELT (expanded_arguments, i) + = tree_cons (NULL_TREE, + TREE_VEC_ELT (expanded_exprs, j), + TREE_VEC_ELT (expanded_arguments, i)); + else + TREE_VEC_ELT (expanded_arguments, i) + = tree_cons (NULL_TREE, + TREE_VEC_ELT (expanded_exprs, i), + TREE_VEC_ELT (expanded_arguments, i)); } in_base_initializer = 0; @@ -26437,19 +26574,6 @@ tsubst_initializer_list (tree t, tree argvec) return inits; } -/* Set CURRENT_ACCESS_SPECIFIER based on the protection of DECL. */ - -static void -set_current_access_from_decl (tree decl) -{ - if (TREE_PRIVATE (decl)) - current_access_specifier = access_private_node; - else if (TREE_PROTECTED (decl)) - current_access_specifier = access_protected_node; - else - current_access_specifier = access_public_node; -} - /* Instantiate an enumerated type. TAG is the template type, NEWTAG is the instantiation (which should have been created with start_enum) and ARGS are the template arguments to use. */ @@ -26575,6 +26699,8 @@ invalid_nontype_parm_type_p (tree type, tsubst_flags_t complain) else if (cxx_dialect >= cxx11 && TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM) return false; + else if (TREE_CODE (type) == COMPLEX_TYPE) + /* Fall through. */; else if (VOID_TYPE_P (type)) /* Fall through. */; else if (cxx_dialect >= cxx20) @@ -28219,6 +28345,11 @@ placeholder_type_constraint_dependent_p (tree t) tree id = unpack_concept_check (t); tree args = TREE_OPERAND (id, 1); tree first = TREE_VEC_ELT (args, 0); + if (ARGUMENT_PACK_P (first)) + { + args = expand_template_argument_pack (args); + first = TREE_VEC_ELT (args, 0); + } gcc_checking_assert (TREE_CODE (first) == WILDCARD_DECL || is_auto (first)); for (int i = 1; i < TREE_VEC_LENGTH (args); ++i) @@ -28424,8 +28555,7 @@ dguide_name_p (tree name) { return (TREE_CODE (name) == IDENTIFIER_NODE && TREE_TYPE (name) - && !strncmp (IDENTIFIER_POINTER (name), dguide_base, - strlen (dguide_base))); + && startswith (IDENTIFIER_POINTER (name), dguide_base)); } /* True if FN is a deduction guide. */ @@ -28505,9 +28635,6 @@ rewrite_template_parm (tree olddecl, unsigned index, unsigned level, tree oldtype = TREE_TYPE (olddecl); newtype = cxx_make_type (TREE_CODE (oldtype)); TYPE_MAIN_VARIANT (newtype) = newtype; - if (TREE_CODE (oldtype) == TEMPLATE_TYPE_PARM) - TEMPLATE_TYPE_PARM_FOR_CLASS (newtype) - = TEMPLATE_TYPE_PARM_FOR_CLASS (oldtype); } else { @@ -28624,7 +28751,8 @@ rewrite_tparm_list (tree oldelt, unsigned index, unsigned level, /* Returns a C++17 class deduction guide template based on the constructor CTOR. As a special case, CTOR can be a RECORD_TYPE for an implicit default guide, REFERENCE_TYPE for an implicit copy/move guide, or TREE_LIST for an - aggregate initialization guide. */ + aggregate initialization guide. OUTER_ARGS are the template arguments + for the enclosing scope of the class. */ static tree build_deduction_guide (tree type, tree ctor, tree outer_args, tsubst_flags_t complain) @@ -28750,7 +28878,15 @@ build_deduction_guide (tree type, tree ctor, tree outer_args, tsubst_flags_t com if (fparms == error_mark_node) ok = false; if (ci) - ci = tsubst_constraint_info (ci, tsubst_args, complain, ctor); + { + if (outer_args) + /* FIXME: We'd like to avoid substituting outer template + arguments into the constraint ahead of time, but the + construction of tsubst_args assumes that outer arguments + are already substituted in. */ + ci = tsubst_constraint_info (ci, outer_args, complain, ctor); + ci = tsubst_constraint_info (ci, tsubst_args, complain, ctor); + } /* Parms are to have DECL_CHAIN tsubsted, which would be skipped if cp_unevaluated_operand. */ @@ -28766,7 +28902,12 @@ build_deduction_guide (tree type, tree ctor, tree outer_args, tsubst_flags_t com fparms = tsubst_arg_types (fparms, targs, NULL_TREE, complain, ctor); fargs = tsubst (fargs, targs, complain, ctor); if (ci) - ci = tsubst_constraint_info (ci, targs, complain, ctor); + { + if (outer_args) + /* FIXME: As above. */ + ci = tsubst_constraint_info (ci, outer_args, complain, ctor); + ci = tsubst_constraint_info (ci, targs, complain, ctor); + } } --processing_template_decl; @@ -28812,12 +28953,7 @@ collect_ctor_idx_types (tree ctor, tree list, tree elt = NULL_TREE) { tree ftype = elt ? elt : TREE_TYPE (idx); if (BRACE_ENCLOSED_INITIALIZER_P (val) - && CONSTRUCTOR_NELTS (val) - /* As in reshape_init_r, a non-aggregate or array-of-dependent-bound - type gets a single initializer. */ - && CP_AGGREGATE_TYPE_P (ftype) - && !(TREE_CODE (ftype) == ARRAY_TYPE - && uses_template_parms (TYPE_DOMAIN (ftype)))) + && CONSTRUCTOR_BRACES_ELIDED_P (val)) { tree subelt = NULL_TREE; if (TREE_CODE (ftype) == ARRAY_TYPE) @@ -28870,6 +29006,8 @@ is_spec_or_derived (tree etype, tree tmpl) return !err; } +static tree alias_ctad_tweaks (tree, tree); + /* Return a C++20 aggregate deduction candidate for TYPE initialized from INIT. */ @@ -28882,6 +29020,15 @@ maybe_aggr_guide (tree tmpl, tree init, vec<tree,va_gc> *args) if (init == NULL_TREE) return NULL_TREE; + if (DECL_ALIAS_TEMPLATE_P (tmpl)) + { + tree under = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl)); + tree tinfo = get_template_info (under); + if (tree guide = maybe_aggr_guide (TI_TEMPLATE (tinfo), init, args)) + return alias_ctad_tweaks (tmpl, guide); + return NULL_TREE; + } + /* We might be creating a guide for a class member template, e.g., template<typename U> struct A { @@ -29040,7 +29187,8 @@ alias_ctad_tweaks (tree tmpl, tree uguides) unsigned len = TREE_VEC_LENGTH (ftparms); tree targs = make_tree_vec (len); int err = unify (ftparms, targs, ret, utype, UNIFY_ALLOW_NONE, false); - gcc_assert (!err); + if (err) + continue; /* The number of parms for f' is the number of parms for A plus non-deduced parms of f. */ @@ -29071,9 +29219,15 @@ alias_ctad_tweaks (tree tmpl, tree uguides) /* Substitute the deduced arguments plus the rewritten template parameters into f to get g. This covers the type, copyness, guideness, and explicit-specifier. */ - tree g = tsubst_decl (DECL_TEMPLATE_RESULT (f), targs, complain); + tree g; + { + /* Parms are to have DECL_CHAIN tsubsted, which would be skipped + if cp_unevaluated_operand. */ + cp_evaluated ev; + g = tsubst_decl (DECL_TEMPLATE_RESULT (f), targs, complain); + } if (g == error_mark_node) - return error_mark_node; + continue; DECL_USE_TEMPLATE (g) = 0; fprime = build_template_decl (g, gtparms, false); DECL_TEMPLATE_RESULT (fprime) = g; @@ -29087,7 +29241,7 @@ alias_ctad_tweaks (tree tmpl, tree uguides) if (ci) ci = tsubst_constraint_info (ci, targs, complain, in_decl); if (ci == error_mark_node) - return error_mark_node; + continue; /* Add a constraint that the return type matches the instantiation of A with the same template arguments. */ @@ -29272,7 +29426,11 @@ do_class_deduction (tree ptype, tree tmpl, tree init, return ptype; /* Initializing one placeholder from another. */ - if (init && TREE_CODE (init) == TEMPLATE_PARM_INDEX + if (init + && (TREE_CODE (init) == TEMPLATE_PARM_INDEX + || (TREE_CODE (init) == EXPR_PACK_EXPANSION + && (TREE_CODE (PACK_EXPANSION_PATTERN (init)) + == TEMPLATE_PARM_INDEX))) && is_auto (TREE_TYPE (init)) && CLASS_PLACEHOLDER_TEMPLATE (TREE_TYPE (init)) == tmpl) return cp_build_qualified_type (TREE_TYPE (init), cp_type_quals (ptype)); @@ -29287,12 +29445,16 @@ do_class_deduction (tree ptype, tree tmpl, tree init, } else if (cxx_dialect < cxx20 && DECL_ALIAS_TEMPLATE_P (tmpl)) { - /* This doesn't affect conforming C++17 code, so just pedwarn. */ - if (complain & tf_warning_or_error) - pedwarn (input_location, 0, "alias template deduction only available " - "with %<-std=c++20%> or %<-std=gnu++20%>"); + if (complain & tf_error) + error ("alias template deduction only available " + "with %<-std=c++20%> or %<-std=gnu++20%>"); + return error_mark_node; } + /* Wait until the initializer is non-dependent. */ + if (type_dependent_expression_p (init)) + return ptype; + tree type = TREE_TYPE (tmpl); bool try_list_ctor = false; @@ -29306,7 +29468,8 @@ do_class_deduction (tree ptype, tree tmpl, tree init, { list_init_p = true; try_list_ctor = TYPE_HAS_LIST_CTOR (type); - if (try_list_ctor && CONSTRUCTOR_NELTS (init) == 1) + if (try_list_ctor && CONSTRUCTOR_NELTS (init) == 1 + && !CONSTRUCTOR_IS_DESIGNATED_INIT (init)) { /* As an exception, the first phase in 16.3.1.7 (considering the initializer list as a single argument) is omitted if the @@ -29362,7 +29525,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init, if (tree guide = maybe_aggr_guide (tmpl, init, args)) cands = lookup_add (guide, cands); - tree call = error_mark_node; + tree fndecl = error_mark_node; /* If this is list-initialization and the class has a list constructor, first try deducing from the list as a single argument, as [over.match.list]. */ @@ -29376,11 +29539,9 @@ do_class_deduction (tree ptype, tree tmpl, tree init, } if (list_cands) { - ++cp_unevaluated_operand; - call = build_new_function_call (list_cands, &args, tf_decltype); - --cp_unevaluated_operand; + fndecl = perform_dguide_overload_resolution (list_cands, args, tf_none); - if (call == error_mark_node) + if (fndecl == error_mark_node) { /* That didn't work, now try treating the list as a sequence of arguments. */ @@ -29396,31 +29557,22 @@ do_class_deduction (tree ptype, tree tmpl, tree init, "user-declared constructors", type); return error_mark_node; } - else if (!cands && call == error_mark_node) + else if (!cands && fndecl == error_mark_node) { error ("cannot deduce template arguments of %qT, as it has no viable " "deduction guides", type); return error_mark_node; } - if (call == error_mark_node) - { - ++cp_unevaluated_operand; - call = build_new_function_call (cands, &args, tf_decltype); - --cp_unevaluated_operand; - } + if (fndecl == error_mark_node) + fndecl = perform_dguide_overload_resolution (cands, args, tf_none); - if (call == error_mark_node) + if (fndecl == error_mark_node) { if (complain & tf_warning_or_error) { error ("class template argument deduction failed:"); - - ++cp_unevaluated_operand; - call = build_new_function_call (cands, &args, - complain | tf_decltype); - --cp_unevaluated_operand; - + perform_dguide_overload_resolution (cands, args, complain); if (elided) inform (input_location, "explicit deduction guides not considered " "for copy-initialization"); @@ -29431,8 +29583,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init, constructor is chosen, the initialization is ill-formed. */ else if (flags & LOOKUP_ONLYCONVERTING) { - tree fndecl = cp_get_callee_fndecl_nofold (call); - if (fndecl && DECL_NONCONVERTING_P (fndecl)) + if (DECL_NONCONVERTING_P (fndecl)) { if (complain & tf_warning_or_error) { @@ -29450,12 +29601,10 @@ do_class_deduction (tree ptype, tree tmpl, tree init, /* If CTAD succeeded but the type doesn't have any explicit deduction guides, this deduction might not be what the user intended. */ - if (call != error_mark_node && !any_dguides_p) + if (fndecl != error_mark_node && !any_dguides_p) { - tree fndecl = cp_get_callee_fndecl_nofold (call); - if (fndecl != NULL_TREE - && (!DECL_IN_SYSTEM_HEADER (fndecl) - || global_dc->dc_warn_system_headers) + if ((!DECL_IN_SYSTEM_HEADER (fndecl) + || global_dc->dc_warn_system_headers) && warning (OPT_Wctad_maybe_unsupported, "%qT may not intend to support class template argument " "deduction", type)) @@ -29463,7 +29612,8 @@ do_class_deduction (tree ptype, tree tmpl, tree init, "warning"); } - return cp_build_qualified_type (TREE_TYPE (call), cp_type_quals (ptype)); + return cp_build_qualified_type (TREE_TYPE (TREE_TYPE (fndecl)), + cp_type_quals (ptype)); } /* Replace occurrences of 'auto' in TYPE with the appropriate type deduced @@ -29484,8 +29634,6 @@ do_auto_deduction (tree type, tree init, tree auto_node, tsubst_flags_t complain, auto_deduction_context context, tree outer_targs, int flags) { - tree targs; - if (init == error_mark_node) return error_mark_node; @@ -29549,14 +29697,17 @@ do_auto_deduction (tree type, tree init, tree auto_node, else init = resolve_nondeduced_context (init, complain); + tree targs; if (context == adc_decomp_type && auto_node == type && init != error_mark_node && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE) - /* [dcl.decomp]/1 - if decomposition declaration has no ref-qualifiers - and initializer has array type, deduce cv-qualified array type. */ - return cp_build_qualified_type_real (TREE_TYPE (init), TYPE_QUALS (type), - complain); + { + /* [dcl.struct.bind]/1 - if decomposition declaration has no ref-qualifiers + and initializer has array type, deduce cv-qualified array type. */ + targs = make_tree_vec (1); + TREE_VEC_ELT (targs, 0) = TREE_TYPE (init); + } else if (AUTO_IS_DECLTYPE (auto_node)) { tree stripped_init = tree_strip_any_location_wrapper (init); @@ -29642,7 +29793,8 @@ do_auto_deduction (tree type, tree init, tree auto_node, if (processing_template_decl) { gcc_checking_assert (context == adc_variable_type - || context == adc_return_type); + || context == adc_return_type + || context == adc_decomp_type); gcc_checking_assert (!type_dependent_expression_p (init)); /* If the constraint is dependent, we need to wait until instantiation time to resolve the placeholder. */ @@ -29650,7 +29802,9 @@ do_auto_deduction (tree type, tree init, tree auto_node, return type; } - if ((context == adc_return_type || context == adc_variable_type) + if ((context == adc_return_type + || context == adc_variable_type + || context == adc_decomp_type) && current_function_decl && DECL_TEMPLATE_INFO (current_function_decl)) outer_targs = DECL_TI_ARGS (current_function_decl); @@ -30008,25 +30162,41 @@ get_mergeable_specialization_flags (tree tmpl, tree decl) get_mergeable_specialization_flags. */ void -add_mergeable_specialization (bool decl_p, spec_entry *elt, +add_mergeable_specialization (bool decl_p, bool alias_p, spec_entry *elt, tree decl, unsigned flags) { - hash_table<spec_hasher> *specializations - = decl_p ? decl_specializations : type_specializations; - hashval_t hash = spec_hasher::hash (elt); - auto *slot = specializations->find_slot_with_hash (elt, hash, INSERT); - - /* We don't distinguish different constrained partial type - specializations, so there could be duplicates. Everything else - must be new. */ - if (!(flags & 2 && *slot)) + if (decl_p) { - gcc_checking_assert (!*slot); + auto *slot = decl_specializations->find_slot_with_hash (elt, hash, INSERT); + gcc_checking_assert (!*slot); auto entry = ggc_alloc<spec_entry> (); *entry = *elt; *slot = entry; + + if (alias_p) + { + elt->spec = TREE_TYPE (elt->spec); + gcc_checking_assert (elt->spec); + } + } + + if (!decl_p || alias_p) + { + auto *slot = type_specializations->find_slot_with_hash (elt, hash, INSERT); + + /* We don't distinguish different constrained partial type + specializations, so there could be duplicates. Everything else + must be new. */ + if (!(flags & 2 && *slot)) + { + gcc_checking_assert (!*slot); + + auto entry = ggc_alloc<spec_entry> (); + *entry = *elt; + *slot = entry; + } } if (flags & 1) diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c index 95a4fdf..7f140f5 100644 --- a/gcc/cp/ptree.c +++ b/gcc/cp/ptree.c @@ -59,16 +59,16 @@ cxx_print_decl (FILE *file, tree node, int indent) bool need_indent = true; - if (TREE_CODE (node) == FUNCTION_DECL - || TREE_CODE (node) == VAR_DECL - || TREE_CODE (node) == TYPE_DECL - || TREE_CODE (node) == TEMPLATE_DECL - || TREE_CODE (node) == CONCEPT_DECL - || TREE_CODE (node) == NAMESPACE_DECL) + tree ntnode = STRIP_TEMPLATE (node); + if (TREE_CODE (ntnode) == FUNCTION_DECL + || TREE_CODE (ntnode) == VAR_DECL + || TREE_CODE (ntnode) == TYPE_DECL + || TREE_CODE (ntnode) == CONCEPT_DECL + || TREE_CODE (ntnode) == NAMESPACE_DECL) { unsigned m = 0; - if (DECL_LANG_SPECIFIC (node) && DECL_MODULE_IMPORT_P (node)) - m = get_importing_module (node, true); + if (DECL_LANG_SPECIFIC (ntnode) && DECL_MODULE_IMPORT_P (ntnode)) + m = get_importing_module (ntnode, true); if (const char *name = m == ~0u ? "" : module_name (m, true)) { @@ -78,7 +78,7 @@ cxx_print_decl (FILE *file, tree node, int indent) need_indent = false; } - if (DECL_LANG_SPECIFIC (node) && DECL_MODULE_PURVIEW_P (node)) + if (DECL_LANG_SPECIFIC (ntnode) && DECL_MODULE_PURVIEW_P (ntnode)) { if (need_indent) indent_to (file, indent + 3); @@ -171,6 +171,7 @@ cxx_print_type (FILE *file, tree node, int indent) return; case TYPE_PACK_EXPANSION: + print_node (file, "pattern", PACK_EXPANSION_PATTERN (node), indent + 4); print_node (file, "args", PACK_EXPANSION_EXTRA_ARGS (node), indent + 4); return; diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 5a33b83..fcb3308 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -433,7 +433,7 @@ get_tinfo_decl_direct (tree type, tree name, int pseudo_ix) if (!name) name = mangle_typeinfo_for_type (type); - if (!CLASS_TYPE_P (type)) + if (!CLASS_TYPE_P (type) || TYPE_TRANSPARENT_AGGR (type)) d = get_global_binding (name); if (!d) @@ -536,14 +536,14 @@ build_if_nonnull (tree test, tree result, tsubst_flags_t complain) /* This is a compiler generated comparison, don't emit e.g. -Wnonnull-compare warning for it. */ - TREE_NO_WARNING (cond) = 1; + suppress_warning (cond, OPT_Wnonnull); null_ptr = cp_convert (TREE_TYPE (result), nullptr_node, complain); cond = build3 (COND_EXPR, TREE_TYPE (result), cond, result, null_ptr); /* Likewise, don't emit -Wnonnull for using the result to call a member function. */ - TREE_NO_WARNING (cond) = 1; + suppress_warning (cond, OPT_Wnonnull); return cond; } diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 7b18368..943671a 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -1226,7 +1226,10 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type, rval = error_mark_node; } - if (rval && is_overloaded_fn (rval)) + if (rval && is_overloaded_fn (rval) + /* Don't use a BASELINK for class-scope deduction guides since + they're not actually member functions. */ + && !dguide_name_p (name)) rval = build_baselink (rval_binfo, basetype_path, rval, (IDENTIFIER_CONV_OP_P (name) ? TREE_TYPE (name): NULL_TREE)); @@ -1945,7 +1948,13 @@ check_final_overrider (tree overrider, tree basefn) fail = !INDIRECT_TYPE_P (base_return); if (!fail) { - fail = cp_type_quals (base_return) != cp_type_quals (over_return); + if (cp_type_quals (base_return) != cp_type_quals (over_return)) + fail = 1; + + if (TYPE_REF_P (base_return) + && (TYPE_REF_IS_RVALUE (base_return) + != TYPE_REF_IS_RVALUE (over_return))) + fail = 1; base_return = TREE_TYPE (base_return); over_return = TREE_TYPE (over_return); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 30dd206..94e6b18 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -256,6 +256,72 @@ pop_to_parent_deferring_access_checks (void) } } +/* Called from enforce_access. A class has attempted (but failed) to access + DECL. It is already established that a baseclass of that class, + PARENT_BINFO, has private access to DECL. Examine certain special cases + to find a decl that accurately describes the source of the problem. If + none of the special cases apply, simply return DECL as the source of the + problem. */ + +static tree +get_class_access_diagnostic_decl (tree parent_binfo, tree decl) +{ + /* When a class is denied access to a decl in a baseclass, most of the + time it is because the decl itself was declared as private at the point + of declaration. + + However, in C++, there are (at least) two situations in which a decl + can be private even though it was not originally defined as such. + These two situations only apply if a baseclass had private access to + DECL (this function is only called if that is the case). */ + + /* We should first check whether the reason the parent had private access + to DECL was simply because DECL was created and declared as private in + the parent. If it was, then DECL is definitively the source of the + problem. */ + if (SAME_BINFO_TYPE_P (context_for_name_lookup (decl), + BINFO_TYPE (parent_binfo))) + return decl; + + /* 1. If the "using" keyword is used to inherit DECL within the parent, + this may cause DECL to be private, so we should return the using + statement as the source of the problem. + + Scan the fields of PARENT_BINFO and see if there are any using decls. If + there are, see if they inherit DECL. If they do, that's where DECL must + have been declared private. */ + + for (tree parent_field = TYPE_FIELDS (BINFO_TYPE (parent_binfo)); + parent_field; + parent_field = DECL_CHAIN (parent_field)) + /* Not necessary, but also check TREE_PRIVATE for the sake of + eliminating obviously non-relevant using decls. */ + if (TREE_CODE (parent_field) == USING_DECL + && TREE_PRIVATE (parent_field)) + { + tree decl_stripped = strip_using_decl (parent_field); + + /* The using statement might be overloaded. If so, we need to + check all of the overloads. */ + for (ovl_iterator iter (decl_stripped); iter; ++iter) + /* If equal, the using statement inherits DECL, and so is the + source of the access failure, so return it. */ + if (*iter == decl) + return parent_field; + } + + /* 2. If DECL was privately inherited by the parent class, then DECL will + be inaccessible, even though it may originally have been accessible to + deriving classes. In that case, the fault lies with the parent, since it + used a private inheritance, so we return the parent as the source of the + problem. + + Since this is the last check, we just assume it's true. At worst, it + will simply point to the class that failed to give access, which is + technically true. */ + return TYPE_NAME (BINFO_TYPE (parent_binfo)); +} + /* If the current scope isn't allowed to access DECL along BASETYPE_PATH, give an error, or if we're parsing a function or class template, defer the access check to be performed at instantiation time. @@ -317,34 +383,33 @@ enforce_access (tree basetype_path, tree decl, tree diag_decl, diag_decl = strip_inheriting_ctors (diag_decl); if (complain & tf_error) { - /* We will usually want to point to the same place as - diag_decl but not always. */ + access_kind access_failure_reason = ak_none; + + /* By default, using the decl as the source of the problem will + usually give correct results. */ tree diag_location = diag_decl; - access_kind parent_access = ak_none; - /* See if any of BASETYPE_PATH's parents had private access - to DECL. If they did, that will tell us why we don't. */ + /* However, if a parent of BASETYPE_PATH had private access to decl, + then it actually might be the case that the source of the problem + is not DECL. */ tree parent_binfo = get_parent_with_private_access (decl, basetype_path); - /* If a parent had private access, then the diagnostic - location DECL should be that of the parent class, since it - failed to give suitable access by using a private - inheritance. But if DECL was actually defined in the parent, - it wasn't privately inherited, and so we don't need to do - this, and complain_about_access will figure out what to - do. */ - if (parent_binfo != NULL_TREE - && (context_for_name_lookup (decl) - != BINFO_TYPE (parent_binfo))) + /* So if a parent did have private access, then we need to do + special checks to obtain the best diagnostic location decl. */ + if (parent_binfo != NULL_TREE) { - diag_location = TYPE_NAME (BINFO_TYPE (parent_binfo)); - parent_access = ak_private; + diag_location = get_class_access_diagnostic_decl (parent_binfo, + diag_decl); + + /* We also at this point know that the reason access failed was + because decl was private. */ + access_failure_reason = ak_private; } /* Finally, generate an error message. */ complain_about_access (decl, diag_decl, diag_location, true, - parent_access); + access_failure_reason); } if (afi) afi->record_access_failure (basetype_path, decl, diag_decl); @@ -537,6 +602,21 @@ add_decl_expr (tree decl) add_stmt (r); } +/* Set EXPR_LOCATION of the cleanups of any CLEANUP_STMT in STMTS to LOC. */ + +static void +set_cleanup_locs (tree stmts, location_t loc) +{ + if (TREE_CODE (stmts) == CLEANUP_STMT) + { + protected_set_expr_location (CLEANUP_EXPR (stmts), loc); + set_cleanup_locs (CLEANUP_BODY (stmts), loc); + } + else if (TREE_CODE (stmts) == STATEMENT_LIST) + for (tree stmt : tsi_range (stmts)) + set_cleanup_locs (stmt, loc); +} + /* Finish a scope. */ tree @@ -549,6 +629,9 @@ do_poplevel (tree stmt_list) stmt_list = pop_stmt_list (stmt_list); + /* input_location is the last token of the scope, usually a }. */ + set_cleanup_locs (stmt_list, input_location); + if (!processing_template_decl) { stmt_list = c_build_bind_expr (input_location, block, stmt_list); @@ -752,12 +835,12 @@ maybe_convert_cond (tree cond) cond = convert_from_reference (cond); if (TREE_CODE (cond) == MODIFY_EXPR - && !TREE_NO_WARNING (cond) && warn_parentheses + && !warning_suppressed_p (cond, OPT_Wparentheses) && warning_at (cp_expr_loc_or_input_loc (cond), OPT_Wparentheses, "suggest parentheses around " "assignment used as truth value")) - TREE_NO_WARNING (cond) = 1; + suppress_warning (cond, OPT_Wparentheses); return condition_conversion (cond); } @@ -844,6 +927,71 @@ is_std_constant_evaluated_p (tree fn) return name && id_equal (name, "is_constant_evaluated"); } +/* Callback function for maybe_warn_for_constant_evaluated that looks + for calls to std::is_constant_evaluated in TP. */ + +static tree +find_std_constant_evaluated_r (tree *tp, int *walk_subtrees, void *) +{ + tree t = *tp; + + if (TYPE_P (t) || TREE_CONSTANT (t)) + { + *walk_subtrees = false; + return NULL_TREE; + } + + switch (TREE_CODE (t)) + { + case CALL_EXPR: + if (is_std_constant_evaluated_p (t)) + return t; + break; + case EXPR_STMT: + /* Don't warn in statement expressions. */ + *walk_subtrees = false; + return NULL_TREE; + default: + break; + } + + return NULL_TREE; +} + +/* In certain contexts, std::is_constant_evaluated() is always true (for + instance, in a consteval function or in a constexpr if), or always false + (e.g., in a non-constexpr non-consteval function) so give the user a clue. */ + +static void +maybe_warn_for_constant_evaluated (tree cond, bool constexpr_if) +{ + if (!warn_tautological_compare) + return; + + /* Suppress warning for std::is_constant_evaluated if the conditional + comes from a macro. */ + if (from_macro_expansion_at (EXPR_LOCATION (cond))) + return; + + cond = cp_walk_tree_without_duplicates (&cond, find_std_constant_evaluated_r, + NULL); + if (cond) + { + if (constexpr_if) + warning_at (EXPR_LOCATION (cond), OPT_Wtautological_compare, + "%<std::is_constant_evaluated%> always evaluates to " + "true in %<if constexpr%>"); + else if (!maybe_constexpr_fn (current_function_decl)) + warning_at (EXPR_LOCATION (cond), OPT_Wtautological_compare, + "%<std::is_constant_evaluated%> always evaluates to " + "false in a non-%<constexpr%> function"); + else if (DECL_IMMEDIATE_FUNCTION_P (current_function_decl)) + warning_at (EXPR_LOCATION (cond), OPT_Wtautological_compare, + "%<std::is_constant_evaluated%> always evaluates to " + "true in a %<consteval%> function"); + } +} + /* Process the COND of an if-statement, which may be given by IF_STMT. */ @@ -859,23 +1007,12 @@ finish_if_stmt_cond (tree cond, tree if_stmt) converted to bool. */ && TYPE_MAIN_VARIANT (TREE_TYPE (cond)) == boolean_type_node) { - /* if constexpr (std::is_constant_evaluated()) is always true, - so give the user a clue. */ - if (warn_tautological_compare) - { - tree t = cond; - if (TREE_CODE (t) == CLEANUP_POINT_EXPR) - t = TREE_OPERAND (t, 0); - if (TREE_CODE (t) == CALL_EXPR - && is_std_constant_evaluated_p (t)) - warning_at (EXPR_LOCATION (cond), OPT_Wtautological_compare, - "%qs always evaluates to true in %<if constexpr%>", - "std::is_constant_evaluated"); - } - + maybe_warn_for_constant_evaluated (cond, /*constexpr_if=*/true); cond = instantiate_non_dependent_expr (cond); cond = cxx_constant_value (cond, NULL_TREE); } + else + maybe_warn_for_constant_evaluated (cond, /*constexpr_if=*/false); finish_cond (&IF_COND (if_stmt), cond); add_stmt (if_stmt); THEN_CLAUSE (if_stmt) = push_stmt_list (); @@ -1060,7 +1197,7 @@ finish_return_stmt (tree expr) { /* Suppress -Wreturn-type for this function. */ if (warn_return_type) - TREE_NO_WARNING (current_function_decl) = true; + suppress_warning (current_function_decl, OPT_Wreturn_type); return error_mark_node; } @@ -1082,7 +1219,8 @@ finish_return_stmt (tree expr) } r = build_stmt (input_location, RETURN_EXPR, expr); - TREE_NO_WARNING (r) |= no_warning; + if (no_warning) + suppress_warning (r, OPT_Wreturn_type); r = maybe_cleanup_point_expr_void (r); r = add_stmt (r); @@ -1968,7 +2106,7 @@ finish_parenthesized_expr (cp_expr expr) { if (EXPR_P (expr)) /* This inhibits warnings in c_common_truthvalue_conversion. */ - TREE_NO_WARNING (expr) = 1; + suppress_warning (expr, OPT_Wparentheses); if (TREE_CODE (expr) == OFFSET_REF || TREE_CODE (expr) == SCOPE_REF) @@ -2971,14 +3109,13 @@ finish_compound_literal (tree type, tree compound_literal, return error_mark_node; } - if (tree anode = type_uses_auto (type)) - if (CLASS_PLACEHOLDER_TEMPLATE (anode)) - { - type = do_auto_deduction (type, compound_literal, anode, complain, - adc_variable_type); - if (type == error_mark_node) - return error_mark_node; - } + if (template_placeholder_p (type)) + { + type = do_auto_deduction (type, compound_literal, type, complain, + adc_variable_type); + if (type == error_mark_node) + return error_mark_node; + } /* Used to hold a copy of the compound literal in a template. */ tree orig_cl = NULL_TREE; @@ -3094,9 +3231,13 @@ finish_compound_literal (tree type, tree compound_literal, } /* Represent other compound literals with TARGET_EXPR so we produce - an lvalue, but can elide copies. */ + a prvalue, and can elide copies. */ if (!VECTOR_TYPE_P (type)) - compound_literal = get_target_expr_sfinae (compound_literal, complain); + { + /* The CONSTRUCTOR is now an initializer, not a compound literal. */ + TREE_HAS_CONSTRUCTOR (compound_literal) = false; + compound_literal = get_target_expr_sfinae (compound_literal, complain); + } return compound_literal; } @@ -3130,12 +3271,12 @@ finish_translation_unit (void) /* Do file scope __FUNCTION__ et al. */ finish_fname_decls (); - if (scope_chain->omp_declare_target_attribute) + if (vec_safe_length (scope_chain->omp_declare_target_attribute)) { if (!errorcount) error ("%<#pragma omp declare target%> without corresponding " "%<#pragma omp end declare target%>"); - scope_chain->omp_declare_target_attribute = 0; + vec_safe_truncate (scope_chain->omp_declare_target_attribute, 0); } } @@ -3348,6 +3489,14 @@ finish_member_declaration (tree decl) if (TREE_CODE (decl) != CONST_DECL) DECL_CONTEXT (decl) = current_class_type; + /* Remember the single FIELD_DECL an anonymous aggregate type is used for. */ + if (TREE_CODE (decl) == FIELD_DECL + && ANON_AGGR_TYPE_P (TREE_TYPE (decl))) + { + gcc_assert (!ANON_AGGR_TYPE_FIELD (TYPE_MAIN_VARIANT (TREE_TYPE (decl)))); + ANON_AGGR_TYPE_FIELD (TYPE_MAIN_VARIANT (TREE_TYPE (decl))) = decl; + } + if (TREE_CODE (decl) == USING_DECL) /* For now, ignore class-scope USING_DECLS, so that debugging backends do not see them. */ @@ -3577,8 +3726,10 @@ baselink_for_fns (tree fns) cl = currently_open_derived_class (scope); if (!cl) cl = scope; - cl = TYPE_BINFO (cl); - return build_baselink (cl, cl, fns, /*optype=*/NULL_TREE); + tree access_path = TYPE_BINFO (cl); + tree conv_path = (cl == scope ? access_path + : lookup_base (cl, scope, ba_any, NULL, tf_none)); + return build_baselink (conv_path, access_path, fns, /*optype=*/NULL_TREE); } /* Returns true iff DECL is a variable from a function outside @@ -4882,7 +5033,11 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, if (REFERENCE_REF_P (t)) t = TREE_OPERAND (t, 0); } - if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) + if (TREE_CODE (t) == FIELD_DECL + && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)) + ret = finish_non_static_data_member (t, NULL_TREE, NULL_TREE); + else if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) { if (processing_template_decl && TREE_CODE (t) != OVERLOAD) return NULL_TREE; @@ -4896,17 +5051,20 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, omp_clause_code_name[OMP_CLAUSE_CODE (c)]); return error_mark_node; } - else if (ort == C_ORT_OMP + else if ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP && TREE_CODE (t) == PARM_DECL && DECL_ARTIFICIAL (t) - && DECL_NAME (t) == this_identifier) + && DECL_NAME (t) == this_identifier + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND) { error_at (OMP_CLAUSE_LOCATION (c), "%<this%> allowed in OpenMP only in %<declare simd%>" " clauses"); return error_mark_node; } - else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND + else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND && VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t)) { error_at (OMP_CLAUSE_LOCATION (c), @@ -4920,7 +5078,7 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, return ret; } - if (ort == C_ORT_OMP + if ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION) @@ -4993,7 +5151,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, { if (!integer_nonzerop (length)) { - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION) @@ -5061,7 +5220,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, } if (tree_int_cst_equal (size, low_bound)) { - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION) @@ -5082,7 +5242,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, } else if (length == NULL_TREE) { - if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND + if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TASK_REDUCTION) @@ -5120,7 +5281,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, } else if (length == NULL_TREE) { - if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND + if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TASK_REDUCTION) @@ -5164,7 +5326,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, } /* If there is a pointer type anywhere but in the very first array-section-subscript, the array section can't be contiguous. */ - if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND + if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND && TREE_CODE (TREE_CHAIN (t)) == TREE_LIST) { error_at (OMP_CLAUSE_LOCATION (c), @@ -5212,7 +5375,8 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort) unsigned int first_non_one = 0; auto_vec<tree, 10> types; tree *tp = &OMP_CLAUSE_DECL (c); - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND + if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY) && TREE_CODE (*tp) == TREE_LIST && TREE_PURPOSE (*tp) && TREE_CODE (TREE_PURPOSE (*tp)) == TREE_VEC) @@ -5224,7 +5388,8 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort) return true; if (first == NULL_TREE) return false; - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY) { tree t = *tp; tree tem = NULL_TREE; @@ -5415,33 +5580,30 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort) || (TREE_CODE (t) == COMPONENT_REF && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)) return false; - if (ort == C_ORT_OMP || ort == C_ORT_ACC) - switch (OMP_CLAUSE_MAP_KIND (c)) - { - case GOMP_MAP_ALLOC: - case GOMP_MAP_IF_PRESENT: - case GOMP_MAP_TO: - case GOMP_MAP_FROM: - case GOMP_MAP_TOFROM: - case GOMP_MAP_ALWAYS_TO: - case GOMP_MAP_ALWAYS_FROM: - case GOMP_MAP_ALWAYS_TOFROM: - case GOMP_MAP_RELEASE: - case GOMP_MAP_DELETE: - case GOMP_MAP_FORCE_TO: - case GOMP_MAP_FORCE_FROM: - case GOMP_MAP_FORCE_TOFROM: - case GOMP_MAP_FORCE_PRESENT: - OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1; - break; - default: - break; - } + switch (OMP_CLAUSE_MAP_KIND (c)) + { + case GOMP_MAP_ALLOC: + case GOMP_MAP_IF_PRESENT: + case GOMP_MAP_TO: + case GOMP_MAP_FROM: + case GOMP_MAP_TOFROM: + case GOMP_MAP_ALWAYS_TO: + case GOMP_MAP_ALWAYS_FROM: + case GOMP_MAP_ALWAYS_TOFROM: + case GOMP_MAP_RELEASE: + case GOMP_MAP_DELETE: + case GOMP_MAP_FORCE_TO: + case GOMP_MAP_FORCE_FROM: + case GOMP_MAP_FORCE_TOFROM: + case GOMP_MAP_FORCE_PRESENT: + OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1; + break; + default: + break; + } tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP); - 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) + if (TREE_CODE (t) == COMPONENT_REF) OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH); else if (REFERENCE_REF_P (t) && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF) @@ -5453,6 +5615,7 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort) } else OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER); + OMP_CLAUSE_MAP_IMPLICIT (c2) = OMP_CLAUSE_MAP_IMPLICIT (c); if (OMP_CLAUSE_MAP_KIND (c2) != GOMP_MAP_FIRSTPRIVATE_POINTER && !cxx_mark_addressable (t)) return false; @@ -5479,6 +5642,7 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort) tree c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP); OMP_CLAUSE_SET_MAP_KIND (c3, OMP_CLAUSE_MAP_KIND (c2)); + OMP_CLAUSE_MAP_IMPLICIT (c2) = OMP_CLAUSE_MAP_IMPLICIT (c); OMP_CLAUSE_DECL (c3) = ptr; if (OMP_CLAUSE_MAP_KIND (c2) == GOMP_MAP_ALWAYS_POINTER || OMP_CLAUSE_MAP_KIND (c2) == GOMP_MAP_ATTACH_DETACH) @@ -5618,7 +5782,7 @@ omp_reduction_lookup (location_t loc, tree id, tree type, tree *baselinkp, if (!id && CLASS_TYPE_P (type) && TYPE_BINFO (type)) { - vec<tree> ambiguous = vNULL; + auto_vec<tree> ambiguous; tree binfo = TYPE_BINFO (type), base_binfo, ret = NULL_TREE; unsigned int ix; if (ambiguousp == NULL) @@ -5655,7 +5819,6 @@ omp_reduction_lookup (location_t loc, tree id, tree type, tree *baselinkp, if (idx == 0) str = get_spaces (str); } - ambiguous.release (); ret = error_mark_node; baselink = NULL_TREE; } @@ -5824,12 +5987,12 @@ cp_check_omp_declare_reduction (tree udr) { gcc_assert (TREE_CODE (data.stmts[0]) == DECL_EXPR && TREE_CODE (data.stmts[1]) == DECL_EXPR); - if (TREE_NO_WARNING (DECL_EXPR_DECL (data.stmts[0]))) + if (warning_suppressed_p (DECL_EXPR_DECL (data.stmts[0]) /* What warning? */)) return true; data.combiner_p = true; if (cp_walk_tree (&data.stmts[2], cp_check_omp_declare_reduction_r, &data, NULL)) - TREE_NO_WARNING (DECL_EXPR_DECL (data.stmts[0])) = 1; + suppress_warning (DECL_EXPR_DECL (data.stmts[0]) /* What warning? */); } if (i >= 6) { @@ -5840,7 +6003,7 @@ cp_check_omp_declare_reduction (tree udr) &data, NULL) || cp_walk_tree (&DECL_INITIAL (DECL_EXPR_DECL (data.stmts[3])), cp_check_omp_declare_reduction_r, &data, NULL)) - TREE_NO_WARNING (DECL_EXPR_DECL (data.stmts[0])) = 1; + suppress_warning (DECL_EXPR_DECL (data.stmts[0]) /* Wat warning? */); if (i == 7) gcc_assert (TREE_CODE (data.stmts[6]) == DECL_EXPR); } @@ -5915,7 +6078,8 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor) if (!processing_template_decl) { t = require_complete_type (t); - if (t == error_mark_node) + if (t == error_mark_node + || !complete_type_or_else (oatype, NULL_TREE)) return true; tree size = size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (oatype), TYPE_SIZE_UNIT (type)); @@ -5945,6 +6109,8 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor) case PLUS_EXPR: case MULT_EXPR: case MINUS_EXPR: + case TRUTH_ANDIF_EXPR: + case TRUTH_ORIF_EXPR: predefined = true; break; case MIN_EXPR: @@ -5960,12 +6126,6 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor) break; predefined = true; break; - case TRUTH_ANDIF_EXPR: - case TRUTH_ORIF_EXPR: - if (FLOAT_TYPE_P (type)) - break; - predefined = true; - break; default: break; } @@ -6419,7 +6579,8 @@ tree finish_omp_clauses (tree clauses, enum c_omp_region_type ort) { bitmap_head generic_head, firstprivate_head, lastprivate_head; - bitmap_head aligned_head, map_head, map_field_head, oacc_reduction_head; + bitmap_head aligned_head, map_head, map_field_head, map_firstprivate_head; + bitmap_head oacc_reduction_head; tree c, t, *pc; tree safelen = NULL_TREE; bool branch_seen = false; @@ -6434,8 +6595,10 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) has been seen, -2 if mixed inscan/normal reduction diagnosed. */ int reduction_seen = 0; bool allocate_seen = false; - bool detach_seen = false; + tree detach_seen = NULL_TREE; bool mergeable_seen = false; + bool implicit_moved = false; + bool target_in_reduction_seen = false; bitmap_obstack_initialize (NULL); bitmap_initialize (&generic_head, &bitmap_default_obstack); @@ -6445,8 +6608,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) /* If ort == C_ORT_OMP_DECLARE_SIMD used as uniform_head instead. */ bitmap_initialize (&map_head, &bitmap_default_obstack); bitmap_initialize (&map_field_head, &bitmap_default_obstack); + bitmap_initialize (&map_firstprivate_head, &bitmap_default_obstack); /* If ort == C_ORT_OMP used as nontemporal_head or use_device_xxx_head - instead. */ + instead and for ort == C_ORT_OMP_TARGET used as in_reduction_head. */ bitmap_initialize (&oacc_reduction_head, &bitmap_default_obstack); if (ort & C_ORT_ACC) @@ -6709,8 +6873,22 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) || (ort == C_ORT_OMP && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR || (OMP_CLAUSE_CODE (c) - == OMP_CLAUSE_USE_DEVICE_ADDR)))) + == OMP_CLAUSE_USE_DEVICE_ADDR))) + || (ort == C_ORT_OMP_TARGET + && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)) { + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION + && (bitmap_bit_p (&generic_head, DECL_UID (t)) + || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in data-sharing " + "clauses", t); + remove = true; + break; + } + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION) + target_in_reduction_seen = true; if (bitmap_bit_p (&oacc_reduction_head, DECL_UID (t))) { error_at (OMP_CLAUSE_LOCATION (c), @@ -6725,7 +6903,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } else if (bitmap_bit_p (&generic_head, DECL_UID (t)) || bitmap_bit_p (&firstprivate_head, DECL_UID (t)) - || bitmap_bit_p (&lastprivate_head, DECL_UID (t))) + || bitmap_bit_p (&lastprivate_head, DECL_UID (t)) + || bitmap_bit_p (&map_firstprivate_head, DECL_UID (t))) { error_at (OMP_CLAUSE_LOCATION (c), "%qD appears more than once in data clauses", t); @@ -6760,6 +6939,37 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) break; case OMP_CLAUSE_FIRSTPRIVATE: + if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) && !implicit_moved) + { + move_implicit: + implicit_moved = true; + /* Move firstprivate and map clauses with + OMP_CLAUSE_{FIRSTPRIVATE,MAP}_IMPLICIT set to the end of + clauses chain. */ + tree cl1 = NULL_TREE, cl2 = NULL_TREE; + tree *pc1 = pc, *pc2 = &cl1, *pc3 = &cl2; + while (*pc1) + if (OMP_CLAUSE_CODE (*pc1) == OMP_CLAUSE_FIRSTPRIVATE + && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (*pc1)) + { + *pc3 = *pc1; + pc3 = &OMP_CLAUSE_CHAIN (*pc3); + *pc1 = OMP_CLAUSE_CHAIN (*pc1); + } + else if (OMP_CLAUSE_CODE (*pc1) == OMP_CLAUSE_MAP + && OMP_CLAUSE_MAP_IMPLICIT (*pc1)) + { + *pc2 = *pc1; + pc2 = &OMP_CLAUSE_CHAIN (*pc2); + *pc1 = OMP_CLAUSE_CHAIN (*pc1); + } + else + pc1 = &OMP_CLAUSE_CHAIN (*pc1); + *pc3 = NULL; + *pc2 = cl2; + *pc1 = cl1; + continue; + } t = omp_clause_decl_field (OMP_CLAUSE_DECL (c)); if (t) omp_note_field_privatization (t, OMP_CLAUSE_DECL (c)); @@ -6789,8 +6999,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) t); remove = true; } + else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) + && !OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (c) + && bitmap_bit_p (&map_firstprivate_head, DECL_UID (t))) + remove = true; else if (bitmap_bit_p (&generic_head, DECL_UID (t)) - || bitmap_bit_p (&firstprivate_head, DECL_UID (t))) + || bitmap_bit_p (&firstprivate_head, DECL_UID (t)) + || bitmap_bit_p (&map_firstprivate_head, DECL_UID (t))) { error_at (OMP_CLAUSE_LOCATION (c), "%qD appears more than once in data clauses", t); @@ -6801,6 +7016,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (ort == C_ORT_ACC) error_at (OMP_CLAUSE_LOCATION (c), "%qD appears more than once in data clauses", t); + else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) + && !OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (c)) + /* Silently drop the clause. */; else error_at (OMP_CLAUSE_LOCATION (c), "%qD appears both in data and map clauses", t); @@ -7124,6 +7342,15 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) "%<device%> id must be integral"); remove = true; } + else if (OMP_CLAUSE_DEVICE_ANCESTOR (c) + && TREE_CODE (t) == INTEGER_CST + && !integer_onep (t)) + { + error_at (OMP_CLAUSE_LOCATION (c), + "the %<device%> clause expression must evaluate to " + "%<1%>"); + remove = true; + } else { t = mark_rvalue_use (t); @@ -7349,6 +7576,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) remove = true; break; } + /* FALLTHRU */ + case OMP_CLAUSE_AFFINITY: + t = OMP_CLAUSE_DECL (c); if (TREE_CODE (t) == TREE_LIST && TREE_PURPOSE (t) && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC) @@ -7368,7 +7598,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) { if (handle_omp_array_sections (c, ort)) remove = true; - else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_DEPOBJ) + else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND + && (OMP_CLAUSE_DEPEND_KIND (c) + == OMP_CLAUSE_DEPEND_DEPOBJ)) { error_at (OMP_CLAUSE_LOCATION (c), "%<depend%> clause with %<depobj%> dependence " @@ -7379,13 +7611,6 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } if (t == error_mark_node) remove = true; - else if (ort != C_ORT_ACC && t == current_class_ptr) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<this%> allowed in OpenMP only in %<declare simd%>" - " clauses"); - remove = true; - } else if (processing_template_decl && TREE_CODE (t) != OVERLOAD) break; else if (!lvalue_p (t)) @@ -7393,11 +7618,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (DECL_P (t)) error_at (OMP_CLAUSE_LOCATION (c), "%qD is not lvalue expression nor array section " - "in %<depend%> clause", t); + "in %qs clause", t, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); else error_at (OMP_CLAUSE_LOCATION (c), "%qE is not lvalue expression nor array section " - "in %<depend%> clause", t); + "in %qs clause", t, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); remove = true; } else if (TREE_CODE (t) == COMPONENT_REF @@ -7405,10 +7632,12 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) && DECL_BIT_FIELD (TREE_OPERAND (t, 1))) { error_at (OMP_CLAUSE_LOCATION (c), - "bit-field %qE in %qs clause", t, "depend"); + "bit-field %qE in %qs clause", t, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); remove = true; } - else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_DEPOBJ) + else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND + && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_DEPOBJ) { if (!c_omp_depend_t_p (TYPE_REF_P (TREE_TYPE (t)) ? TREE_TYPE (TREE_TYPE (t)) @@ -7421,9 +7650,10 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) remove = true; } } - else if (c_omp_depend_t_p (TYPE_REF_P (TREE_TYPE (t)) - ? TREE_TYPE (TREE_TYPE (t)) - : TREE_TYPE (t))) + else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND + && c_omp_depend_t_p (TYPE_REF_P (TREE_TYPE (t)) + ? TREE_TYPE (TREE_TYPE (t)) + : TREE_TYPE (t))) { error_at (OMP_CLAUSE_LOCATION (c), "%qE should not have %<omp_depend_t%> type in " @@ -7485,12 +7715,15 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) type); remove = true; } - detach_seen = true; + detach_seen = c; cxx_mark_addressable (t); } break; case OMP_CLAUSE_MAP: + if (OMP_CLAUSE_MAP_IMPLICIT (c) && !implicit_moved) + goto move_implicit; + /* FALLTHRU */ case OMP_CLAUSE_TO: case OMP_CLAUSE_FROM: case OMP_CLAUSE__CACHE_: @@ -7522,6 +7755,16 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) t = TREE_OPERAND (t, 0); if (REFERENCE_REF_P (t)) t = TREE_OPERAND (t, 0); + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP + && OMP_CLAUSE_MAP_IMPLICIT (c) + && (bitmap_bit_p (&map_head, DECL_UID (t)) + || bitmap_bit_p (&map_field_head, DECL_UID (t)) + || bitmap_bit_p (&map_firstprivate_head, + DECL_UID (t)))) + { + remove = true; + break; + } if (bitmap_bit_p (&map_field_head, DECL_UID (t))) break; if (bitmap_bit_p (&map_head, DECL_UID (t))) @@ -7584,13 +7827,10 @@ 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 || ort == C_ORT_OMP) - && TREE_CODE (t) == COMPONENT_REF + if (TREE_CODE (t) == COMPONENT_REF && TREE_CODE (TREE_OPERAND (t, 0)) == INDIRECT_REF) t = TREE_OPERAND (TREE_OPERAND (t, 0), 0); if (TREE_CODE (t) == COMPONENT_REF - && ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP - || ort == C_ORT_ACC) && OMP_CLAUSE_CODE (c) != OMP_CLAUSE__CACHE_) { if (type_dependent_expression_p (t)) @@ -7631,7 +7871,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (VAR_P (t) || TREE_CODE (t) == PARM_DECL) { if (bitmap_bit_p (&map_field_head, DECL_UID (t)) - || (ort == C_ORT_OMP + || (ort != C_ORT_ACC && bitmap_bit_p (&map_head, DECL_UID (t)))) goto handle_map_references; } @@ -7703,10 +7943,18 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) remove = true; } else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP + && OMP_CLAUSE_MAP_IMPLICIT (c) + && (bitmap_bit_p (&map_head, DECL_UID (t)) + || bitmap_bit_p (&map_field_head, DECL_UID (t)) + || bitmap_bit_p (&map_firstprivate_head, + DECL_UID (t)))) + remove = true; + else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER) { if (bitmap_bit_p (&generic_head, DECL_UID (t)) - || bitmap_bit_p (&firstprivate_head, DECL_UID (t))) + || bitmap_bit_p (&firstprivate_head, DECL_UID (t)) + || bitmap_bit_p (&map_firstprivate_head, DECL_UID (t))) { error_at (OMP_CLAUSE_LOCATION (c), "%qD appears more than once in data clauses", t); @@ -7723,7 +7971,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) remove = true; } else - bitmap_set_bit (&generic_head, DECL_UID (t)); + bitmap_set_bit (&map_firstprivate_head, DECL_UID (t)); } else if (bitmap_bit_p (&map_head, DECL_UID (t)) && !bitmap_bit_p (&map_field_head, DECL_UID (t))) @@ -7739,8 +7987,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) "%qD appears more than once in map clauses", t); remove = true; } - else if (bitmap_bit_p (&generic_head, DECL_UID (t)) - && ort == C_ORT_ACC) + else if (ort == C_ORT_ACC + && bitmap_bit_p (&generic_head, DECL_UID (t))) { error_at (OMP_CLAUSE_LOCATION (c), "%qD appears more than once in data clauses", t); @@ -7973,6 +8221,29 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } break; + case OMP_CLAUSE_FILTER: + t = OMP_CLAUSE_FILTER_EXPR (c); + if (t == error_mark_node) + remove = true; + else if (!type_dependent_expression_p (t) + && !INTEGRAL_TYPE_P (TREE_TYPE (t))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<filter%> expression must be integral"); + remove = true; + } + else + { + t = mark_rvalue_use (t); + if (!processing_template_decl) + { + t = maybe_constant_value (t); + t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); + } + OMP_CLAUSE_FILTER_EXPR (c) = t; + } + break; + case OMP_CLAUSE_IS_DEVICE_PTR: case OMP_CLAUSE_USE_DEVICE_PTR: field_ok = (ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP; @@ -8036,6 +8307,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) case OMP_CLAUSE_SEQ: case OMP_CLAUSE_IF_PRESENT: case OMP_CLAUSE_FINALIZE: + case OMP_CLAUSE_NOHOST: break; case OMP_CLAUSE_MERGEABLE: @@ -8290,6 +8562,22 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } pc = &OMP_CLAUSE_CHAIN (c); continue; + case OMP_CLAUSE_MAP: + if (target_in_reduction_seen && !processing_template_decl) + { + t = OMP_CLAUSE_DECL (c); + while (handled_component_p (t) + || TREE_CODE (t) == INDIRECT_REF + || TREE_CODE (t) == ADDR_EXPR + || TREE_CODE (t) == MEM_REF + || TREE_CODE (t) == NON_LVALUE_EXPR) + t = TREE_OPERAND (t, 0); + if (DECL_P (t) + && bitmap_bit_p (&oacc_reduction_head, DECL_UID (t))) + OMP_CLAUSE_MAP_IN_REDUCTION (c) = 1; + } + pc = &OMP_CLAUSE_CHAIN (c); + continue; case OMP_CLAUSE_NOWAIT: if (copyprivate_seen) { @@ -8455,7 +8743,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE) - && OMP_CLAUSE_DECL (c) == t) + && OMP_CLAUSE_DECL (c) == OMP_CLAUSE_DECL (detach_seen)) { error_at (OMP_CLAUSE_LOCATION (c), "the event handle of a %<detach%> clause " @@ -9668,7 +9956,7 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode, return; } stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, - v, lhs1, rhs1, swapped, mo, + v, lhs1, rhs1, NULL_TREE, swapped, mo, false, processing_template_decl != 0); if (stmt == error_mark_node) return; @@ -9759,7 +10047,7 @@ finish_omp_flush (int mo) { tree fn = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE); releasing_vec vec; - if (mo != MEMMODEL_LAST) + if (mo != MEMMODEL_LAST && mo != MEMMODEL_SEQ_CST) { fn = builtin_decl_explicit (BUILT_IN_ATOMIC_THREAD_FENCE); vec->quick_push (build_int_cst (integer_type_node, mo)); @@ -10318,6 +10606,362 @@ classtype_has_nothrow_assign_or_copy_p (tree type, bool assign_p) return saw_copy; } +/* Return true if DERIVED is pointer interconvertible base of BASE. */ + +static bool +pointer_interconvertible_base_of_p (tree base, tree derived) +{ + if (base == error_mark_node || derived == error_mark_node) + return false; + base = TYPE_MAIN_VARIANT (base); + derived = TYPE_MAIN_VARIANT (derived); + if (!NON_UNION_CLASS_TYPE_P (base) + || !NON_UNION_CLASS_TYPE_P (derived)) + return false; + + if (same_type_p (base, derived)) + return true; + + if (!std_layout_type_p (derived)) + return false; + + return uniquely_derived_from_p (base, derived); +} + +/* Helper function for fold_builtin_is_pointer_inverconvertible_with_class, + return true if MEMBERTYPE is the type of the first non-static data member + of TYPE or for unions of any members. */ +static bool +first_nonstatic_data_member_p (tree type, tree membertype) +{ + for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + { + if (TREE_CODE (field) != FIELD_DECL) + continue; + if (DECL_FIELD_IS_BASE (field) && is_empty_field (field)) + continue; + if (DECL_FIELD_IS_BASE (field)) + return first_nonstatic_data_member_p (TREE_TYPE (field), membertype); + if (ANON_AGGR_TYPE_P (TREE_TYPE (field))) + { + if ((TREE_CODE (TREE_TYPE (field)) == UNION_TYPE + || std_layout_type_p (TREE_TYPE (field))) + && first_nonstatic_data_member_p (TREE_TYPE (field), membertype)) + return true; + } + else if (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (field), + membertype)) + return true; + if (TREE_CODE (type) != UNION_TYPE) + return false; + } + return false; +} + +/* Fold __builtin_is_pointer_interconvertible_with_class call. */ + +tree +fold_builtin_is_pointer_inverconvertible_with_class (location_t loc, int nargs, + tree *args) +{ + /* Unless users call the builtin directly, the following 3 checks should be + ensured from std::is_pointer_interconvertible_with_class function + template. */ + if (nargs != 1) + { + error_at (loc, "%<__builtin_is_pointer_interconvertible_with_class%> " + "needs a single argument"); + return boolean_false_node; + } + tree arg = args[0]; + if (error_operand_p (arg)) + return boolean_false_node; + if (!TYPE_PTRMEM_P (TREE_TYPE (arg))) + { + error_at (loc, "%<__builtin_is_pointer_interconvertible_with_class%> " + "argument is not pointer to member"); + return boolean_false_node; + } + + if (!TYPE_PTRDATAMEM_P (TREE_TYPE (arg))) + return boolean_false_node; + + tree membertype = TREE_TYPE (TREE_TYPE (arg)); + tree basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (arg)); + if (!complete_type_or_else (basetype, NULL_TREE)) + return boolean_false_node; + + if (TREE_CODE (basetype) != UNION_TYPE + && !std_layout_type_p (basetype)) + return boolean_false_node; + + if (!first_nonstatic_data_member_p (basetype, membertype)) + return boolean_false_node; + + if (TREE_CODE (arg) == PTRMEM_CST) + arg = cplus_expand_constant (arg); + + if (integer_nonzerop (arg)) + return boolean_false_node; + if (integer_zerop (arg)) + return boolean_true_node; + + return fold_build2 (EQ_EXPR, boolean_type_node, arg, + build_zero_cst (TREE_TYPE (arg))); +} + +/* Helper function for is_corresponding_member_aggr. Return true if + MEMBERTYPE pointer-to-data-member ARG can be found in anonymous + union or structure BASETYPE. */ + +static bool +is_corresponding_member_union (tree basetype, tree membertype, tree arg) +{ + for (tree field = TYPE_FIELDS (basetype); field; field = DECL_CHAIN (field)) + if (TREE_CODE (field) != FIELD_DECL || DECL_BIT_FIELD_TYPE (field)) + continue; + else if (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (field), + membertype)) + { + if (TREE_CODE (arg) != INTEGER_CST + || tree_int_cst_equal (arg, byte_position (field))) + return true; + } + else if (ANON_AGGR_TYPE_P (TREE_TYPE (field))) + { + tree narg = arg; + if (TREE_CODE (basetype) != UNION_TYPE + && TREE_CODE (narg) == INTEGER_CST) + narg = size_binop (MINUS_EXPR, arg, byte_position (field)); + if (is_corresponding_member_union (TREE_TYPE (field), + membertype, narg)) + return true; + } + return false; +} + +/* Helper function for fold_builtin_is_corresponding_member call. + Return boolean_false_node if MEMBERTYPE1 BASETYPE1::*ARG1 and + MEMBERTYPE2 BASETYPE2::*ARG2 aren't corresponding members, + boolean_true_node if they are corresponding members, or for + non-constant ARG2 the highest member offset for corresponding + members. */ + +static tree +is_corresponding_member_aggr (location_t loc, tree basetype1, tree membertype1, + tree arg1, tree basetype2, tree membertype2, + tree arg2) +{ + tree field1 = TYPE_FIELDS (basetype1); + tree field2 = TYPE_FIELDS (basetype2); + tree ret = boolean_false_node; + while (1) + { + bool r = next_common_initial_seqence (field1, field2); + if (field1 == NULL_TREE || field2 == NULL_TREE) + break; + if (r + && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (field1), + membertype1) + && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (field2), + membertype2)) + { + tree pos = byte_position (field1); + if (TREE_CODE (arg1) == INTEGER_CST + && tree_int_cst_equal (arg1, pos)) + { + if (TREE_CODE (arg2) == INTEGER_CST) + return boolean_true_node; + return pos; + } + else if (TREE_CODE (arg1) != INTEGER_CST) + ret = pos; + } + else if (ANON_AGGR_TYPE_P (TREE_TYPE (field1)) + && ANON_AGGR_TYPE_P (TREE_TYPE (field2))) + { + if ((!lookup_attribute ("no_unique_address", + DECL_ATTRIBUTES (field1))) + != !lookup_attribute ("no_unique_address", + DECL_ATTRIBUTES (field2))) + break; + if (!tree_int_cst_equal (bit_position (field1), + bit_position (field2))) + break; + bool overlap = true; + tree pos = byte_position (field1); + if (TREE_CODE (arg1) == INTEGER_CST) + { + tree off1 = fold_convert (sizetype, arg1); + tree sz1 = TYPE_SIZE_UNIT (TREE_TYPE (field1)); + if (tree_int_cst_lt (off1, pos) + || tree_int_cst_le (size_binop (PLUS_EXPR, pos, sz1), off1)) + overlap = false; + } + if (TREE_CODE (arg2) == INTEGER_CST) + { + tree off2 = fold_convert (sizetype, arg2); + tree sz2 = TYPE_SIZE_UNIT (TREE_TYPE (field2)); + if (tree_int_cst_lt (off2, pos) + || tree_int_cst_le (size_binop (PLUS_EXPR, pos, sz2), off2)) + overlap = false; + } + if (overlap + && NON_UNION_CLASS_TYPE_P (TREE_TYPE (field1)) + && NON_UNION_CLASS_TYPE_P (TREE_TYPE (field2))) + { + tree narg1 = arg1; + if (TREE_CODE (arg1) == INTEGER_CST) + narg1 = size_binop (MINUS_EXPR, + fold_convert (sizetype, arg1), pos); + tree narg2 = arg2; + if (TREE_CODE (arg2) == INTEGER_CST) + narg2 = size_binop (MINUS_EXPR, + fold_convert (sizetype, arg2), pos); + tree t1 = TREE_TYPE (field1); + tree t2 = TREE_TYPE (field2); + tree nret = is_corresponding_member_aggr (loc, t1, membertype1, + narg1, t2, membertype2, + narg2); + if (nret != boolean_false_node) + { + if (nret == boolean_true_node) + return nret; + if (TREE_CODE (arg1) == INTEGER_CST) + return size_binop (PLUS_EXPR, nret, pos); + ret = size_binop (PLUS_EXPR, nret, pos); + } + } + else if (overlap + && TREE_CODE (TREE_TYPE (field1)) == UNION_TYPE + && TREE_CODE (TREE_TYPE (field2)) == UNION_TYPE) + { + tree narg1 = arg1; + if (TREE_CODE (arg1) == INTEGER_CST) + narg1 = size_binop (MINUS_EXPR, + fold_convert (sizetype, arg1), pos); + tree narg2 = arg2; + if (TREE_CODE (arg2) == INTEGER_CST) + narg2 = size_binop (MINUS_EXPR, + fold_convert (sizetype, arg2), pos); + if (is_corresponding_member_union (TREE_TYPE (field1), + membertype1, narg1) + && is_corresponding_member_union (TREE_TYPE (field2), + membertype2, narg2)) + { + sorry_at (loc, "%<__builtin_is_corresponding_member%> " + "not well defined for anonymous unions"); + return boolean_false_node; + } + } + } + if (!r) + break; + field1 = DECL_CHAIN (field1); + field2 = DECL_CHAIN (field2); + } + return ret; +} + +/* Fold __builtin_is_corresponding_member call. */ + +tree +fold_builtin_is_corresponding_member (location_t loc, int nargs, + tree *args) +{ + /* Unless users call the builtin directly, the following 3 checks should be + ensured from std::is_corresponding_member function template. */ + if (nargs != 2) + { + error_at (loc, "%<__builtin_is_corresponding_member%> " + "needs two arguments"); + return boolean_false_node; + } + tree arg1 = args[0]; + tree arg2 = args[1]; + if (error_operand_p (arg1) || error_operand_p (arg2)) + return boolean_false_node; + if (!TYPE_PTRMEM_P (TREE_TYPE (arg1)) + || !TYPE_PTRMEM_P (TREE_TYPE (arg2))) + { + error_at (loc, "%<__builtin_is_corresponding_member%> " + "argument is not pointer to member"); + return boolean_false_node; + } + + if (!TYPE_PTRDATAMEM_P (TREE_TYPE (arg1)) + || !TYPE_PTRDATAMEM_P (TREE_TYPE (arg2))) + return boolean_false_node; + + tree membertype1 = TREE_TYPE (TREE_TYPE (arg1)); + tree basetype1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (arg1)); + if (!complete_type_or_else (basetype1, NULL_TREE)) + return boolean_false_node; + + tree membertype2 = TREE_TYPE (TREE_TYPE (arg2)); + tree basetype2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (arg2)); + if (!complete_type_or_else (basetype2, NULL_TREE)) + return boolean_false_node; + + if (!NON_UNION_CLASS_TYPE_P (basetype1) + || !NON_UNION_CLASS_TYPE_P (basetype2) + || !std_layout_type_p (basetype1) + || !std_layout_type_p (basetype2)) + return boolean_false_node; + + /* If the member types aren't layout compatible, then they + can't be corresponding members. */ + if (!layout_compatible_type_p (membertype1, membertype2)) + return boolean_false_node; + + if (TREE_CODE (arg1) == PTRMEM_CST) + arg1 = cplus_expand_constant (arg1); + if (TREE_CODE (arg2) == PTRMEM_CST) + arg2 = cplus_expand_constant (arg2); + + if (null_member_pointer_value_p (arg1) + || null_member_pointer_value_p (arg2)) + return boolean_false_node; + + if (TREE_CODE (arg1) == INTEGER_CST + && TREE_CODE (arg2) == INTEGER_CST + && !tree_int_cst_equal (arg1, arg2)) + return boolean_false_node; + + if (TREE_CODE (arg2) == INTEGER_CST + && TREE_CODE (arg1) != INTEGER_CST) + { + std::swap (arg1, arg2); + std::swap (membertype1, membertype2); + std::swap (basetype1, basetype2); + } + + tree ret = is_corresponding_member_aggr (loc, basetype1, membertype1, arg1, + basetype2, membertype2, arg2); + if (TREE_TYPE (ret) == boolean_type_node) + return ret; + /* If both arg1 and arg2 are INTEGER_CSTs, is_corresponding_member_aggr + already returns boolean_{true,false}_node whether those particular + members are corresponding members or not. Otherwise, if only + one of them is INTEGER_CST (canonicalized to first being INTEGER_CST + above), it returns boolean_false_node if it is certainly not a + corresponding member and otherwise we need to do a runtime check that + those two OFFSET_TYPE offsets are equal. + If neither of the operands is INTEGER_CST, is_corresponding_member_aggr + returns the largest offset at which the members would be corresponding + members, so perform arg1 <= ret && arg1 == arg2 runtime check. */ + gcc_assert (TREE_CODE (arg2) != INTEGER_CST); + if (TREE_CODE (arg1) == INTEGER_CST) + return fold_build2 (EQ_EXPR, boolean_type_node, arg1, + fold_convert (TREE_TYPE (arg1), arg2)); + ret = fold_build2 (LE_EXPR, boolean_type_node, + fold_convert (pointer_sized_int_node, arg1), + fold_convert (pointer_sized_int_node, ret)); + return fold_build2 (TRUTH_AND_EXPR, boolean_type_node, ret, + fold_build2 (EQ_EXPR, boolean_type_node, arg1, + fold_convert (TREE_TYPE (arg1), arg2))); +} + /* Actually evaluates the trait. */ static bool @@ -10408,9 +11052,15 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) case CPTK_IS_FINAL: return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1); + case CPTK_IS_LAYOUT_COMPATIBLE: + return layout_compatible_type_p (type1, type2); + case CPTK_IS_LITERAL_TYPE: return literal_type_p (type1); + case CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF: + return pointer_interconvertible_base_of_p (type1, type2); + case CPTK_IS_POD: return pod_type_p (type1); @@ -10538,6 +11188,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2) break; case CPTK_IS_BASE_OF: + case CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF: if (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2) && !same_type_ignoring_top_level_qualifiers_p (type1, type2) && !complete_type_or_else (type2, NULL_TREE)) @@ -10551,13 +11202,26 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2) case CPTK_IS_SAME_AS: break; + case CPTK_IS_LAYOUT_COMPATIBLE: + if (!array_of_unknown_bound_p (type1) + && TREE_CODE (type1) != VOID_TYPE + && !complete_type_or_else (type1, NULL_TREE)) + /* We already issued an error. */ + return error_mark_node; + if (!array_of_unknown_bound_p (type2) + && TREE_CODE (type2) != VOID_TYPE + && !complete_type_or_else (type2, NULL_TREE)) + /* We already issued an error. */ + return error_mark_node; + break; + default: gcc_unreachable (); } -tree val = (trait_expr_value (kind, type1, type2) - ? boolean_true_node : boolean_false_node); - return maybe_wrap_with_location (val, loc); + tree val = (trait_expr_value (kind, type1, type2) + ? boolean_true_node : boolean_false_node); + return maybe_wrap_with_location (val, loc); } /* Do-nothing variants of functions to handle pragma FLOAT_CONST_DECIMAL64, diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 3acb643..3c62dd7 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -450,11 +450,17 @@ builtin_valid_in_constant_expr_p (const_tree decl) return false; if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL) { - if (fndecl_built_in_p (decl, CP_BUILT_IN_IS_CONSTANT_EVALUATED, - BUILT_IN_FRONTEND) - || fndecl_built_in_p (decl, CP_BUILT_IN_SOURCE_LOCATION, - BUILT_IN_FRONTEND)) - return true; + if (fndecl_built_in_p (decl, BUILT_IN_FRONTEND)) + switch (DECL_FE_FUNCTION_CODE (decl)) + { + case CP_BUILT_IN_IS_CONSTANT_EVALUATED: + case CP_BUILT_IN_SOURCE_LOCATION: + case CP_BUILT_IN_IS_CORRESPONDING_MEMBER: + case CP_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS: + return true; + default: + break; + } /* Not a built-in. */ return false; } @@ -843,21 +849,22 @@ tree build_target_expr_with_type (tree init, tree type, tsubst_flags_t complain) { gcc_assert (!VOID_TYPE_P (type)); + gcc_assert (!VOID_TYPE_P (TREE_TYPE (init))); if (TREE_CODE (init) == TARGET_EXPR || init == error_mark_node) return init; else if (CLASS_TYPE_P (type) && type_has_nontrivial_copy_init (type) - && !VOID_TYPE_P (TREE_TYPE (init)) && TREE_CODE (init) != COND_EXPR && TREE_CODE (init) != CONSTRUCTOR - && TREE_CODE (init) != VA_ARG_EXPR) - /* We need to build up a copy constructor call. A void initializer - means we're being called from bot_manip. COND_EXPR is a special + && TREE_CODE (init) != VA_ARG_EXPR + && TREE_CODE (init) != CALL_EXPR) + /* We need to build up a copy constructor call. COND_EXPR is a special case because we already have copies on the arms and we don't want another one here. A CONSTRUCTOR is aggregate initialization, which is handled separately. A VA_ARG_EXPR is magic creation of an - aggregate; there's no additional work to be done. */ + aggregate; there's no additional work to be done. A CALL_EXPR + already creates a prvalue. */ return force_rvalue (init, complain); return force_target_expr (type, init, complain); @@ -940,7 +947,12 @@ rvalue (tree expr) /* We need to do this for rvalue refs as well to get the right answer from decltype; see c++/36628. */ if (!processing_template_decl && glvalue_p (expr)) - expr = build1 (NON_LVALUE_EXPR, type, expr); + { + /* But don't use this function for class lvalues; use move (to treat an + lvalue as an xvalue) or force_rvalue (to make a prvalue copy). */ + gcc_checking_assert (!CLASS_TYPE_P (type)); + expr = build1 (NON_LVALUE_EXPR, type, expr); + } else if (type != TREE_TYPE (expr)) expr = build_nop (type, expr); @@ -1121,7 +1133,7 @@ build_cplus_array_type (tree elt_type, tree index_type, int dependent) /* Avoid spurious warnings with VLAs (c++/54583). */ if (TYPE_SIZE (t) && EXPR_P (TYPE_SIZE (t))) - TREE_NO_WARNING (TYPE_SIZE (t)) = 1; + suppress_warning (TYPE_SIZE (t), OPT_Wunused); /* Push these needs up to the ARRAY_TYPE so that initialization takes place more easily. */ @@ -1201,12 +1213,14 @@ vla_type_p (tree t) return false; } -/* Return a reference type node referring to TO_TYPE. If RVAL is + +/* Return a reference type node of MODE referring to TO_TYPE. If MODE + is VOIDmode the standard pointer mode will be picked. If RVAL is true, return an rvalue reference type, otherwise return an lvalue reference type. If a type node exists, reuse it, otherwise create a new one. */ tree -cp_build_reference_type (tree to_type, bool rval) +cp_build_reference_type_for_mode (tree to_type, machine_mode mode, bool rval) { tree lvalue_ref, t; @@ -1219,7 +1233,8 @@ cp_build_reference_type (tree to_type, bool rval) to_type = TREE_TYPE (to_type); } - lvalue_ref = build_reference_type (to_type); + lvalue_ref = build_reference_type_for_mode (to_type, mode, false); + if (!rval) return lvalue_ref; @@ -1245,7 +1260,7 @@ cp_build_reference_type (tree to_type, bool rval) SET_TYPE_STRUCTURAL_EQUALITY (t); else if (TYPE_CANONICAL (to_type) != to_type) TYPE_CANONICAL (t) - = cp_build_reference_type (TYPE_CANONICAL (to_type), rval); + = cp_build_reference_type_for_mode (TYPE_CANONICAL (to_type), mode, rval); else TYPE_CANONICAL (t) = t; @@ -1255,6 +1270,16 @@ cp_build_reference_type (tree to_type, bool rval) } +/* Return a reference type node referring to TO_TYPE. If RVAL is + true, return an rvalue reference type, otherwise return an lvalue + reference type. If a type node exists, reuse it, otherwise create + a new one. */ +tree +cp_build_reference_type (tree to_type, bool rval) +{ + return cp_build_reference_type_for_mode (to_type, VOIDmode, rval); +} + /* Returns EXPR cast to rvalue reference type, like std::move. */ tree @@ -1556,11 +1581,11 @@ strip_typedefs (tree t, bool *remove_attributes, unsigned int flags) { case POINTER_TYPE: type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags); - result = build_pointer_type (type); + result = build_pointer_type_for_mode (type, TYPE_MODE (t), false); break; case REFERENCE_TYPE: type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags); - result = cp_build_reference_type (type, TYPE_REF_IS_RVALUE (t)); + result = cp_build_reference_type_for_mode (type, TYPE_MODE (t), TYPE_REF_IS_RVALUE (t)); break; case OFFSET_TYPE: t0 = strip_typedefs (TYPE_OFFSET_BASETYPE (t), remove_attributes, flags); @@ -1722,6 +1747,20 @@ strip_typedefs (tree t, bool *remove_attributes, unsigned int flags) remove_attributes, flags); result = finish_underlying_type (type); break; + case TYPE_PACK_EXPANSION: + { + tree pat = PACK_EXPANSION_PATTERN (t); + if (TYPE_P (pat)) + { + type = strip_typedefs (pat, remove_attributes, flags); + if (type != pat) + { + result = copy_node (t); + PACK_EXPANSION_PATTERN (result) = type; + } + } + } + break; default: break; } @@ -3080,8 +3119,8 @@ bot_manip (tree* tp, int* walk_subtrees, void* data_) AGGR_INIT_ZERO_FIRST (TREE_OPERAND (u, 1)) = true; } else - u = build_target_expr_with_type (TREE_OPERAND (t, 1), TREE_TYPE (t), - tf_warning_or_error); + u = force_target_expr (TREE_TYPE (t), TREE_OPERAND (t, 1), + tf_warning_or_error); TARGET_EXPR_IMPLICIT_P (u) = TARGET_EXPR_IMPLICIT_P (t); TARGET_EXPR_LIST_INIT_P (u) = TARGET_EXPR_LIST_INIT_P (t); @@ -3128,6 +3167,48 @@ bot_manip (tree* tp, int* walk_subtrees, void* data_) } return NULL_TREE; } + if (TREE_CODE (*tp) == DECL_EXPR + && VAR_P (DECL_EXPR_DECL (*tp)) + && DECL_ARTIFICIAL (DECL_EXPR_DECL (*tp)) + && !TREE_STATIC (DECL_EXPR_DECL (*tp))) + { + tree t; + splay_tree_node n + = splay_tree_lookup (target_remap, + (splay_tree_key) DECL_EXPR_DECL (*tp)); + if (n) + t = (tree) n->value; + else + { + t = create_temporary_var (TREE_TYPE (DECL_EXPR_DECL (*tp))); + DECL_INITIAL (t) = DECL_INITIAL (DECL_EXPR_DECL (*tp)); + splay_tree_insert (target_remap, + (splay_tree_key) DECL_EXPR_DECL (*tp), + (splay_tree_value) t); + } + copy_tree_r (tp, walk_subtrees, NULL); + DECL_EXPR_DECL (*tp) = t; + if (data.clear_location && EXPR_HAS_LOCATION (*tp)) + SET_EXPR_LOCATION (*tp, input_location); + return NULL_TREE; + } + if (TREE_CODE (*tp) == BIND_EXPR && BIND_EXPR_VARS (*tp)) + { + copy_tree_r (tp, walk_subtrees, NULL); + for (tree *p = &BIND_EXPR_VARS (*tp); *p; p = &DECL_CHAIN (*p)) + { + gcc_assert (VAR_P (*p) && DECL_ARTIFICIAL (*p) && !TREE_STATIC (*p)); + tree t = create_temporary_var (TREE_TYPE (*p)); + DECL_INITIAL (t) = DECL_INITIAL (*p); + DECL_CHAIN (t) = DECL_CHAIN (*p); + splay_tree_insert (target_remap, (splay_tree_key) *p, + (splay_tree_value) t); + *p = t; + } + if (data.clear_location && EXPR_HAS_LOCATION (*tp)) + SET_EXPR_LOCATION (*tp, input_location); + return NULL_TREE; + } /* Make a copy of this node. */ t = copy_tree_r (tp, walk_subtrees, NULL); @@ -3167,15 +3248,11 @@ bot_replace (tree* t, int* /*walk_subtrees*/, void* data_) else if (TREE_CODE (*t) == CONVERT_EXPR && CONVERT_EXPR_VBASE_PATH (*t)) { - /* In an NSDMI build_base_path defers building conversions to virtual - bases, and we handle it here. */ - tree basetype = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (*t))); - vec<tree, va_gc> *vbases = CLASSTYPE_VBASECLASSES (current_class_type); - int i; tree binfo; - FOR_EACH_VEC_SAFE_ELT (vbases, i, binfo) - if (BINFO_TYPE (binfo) == basetype) - break; - *t = build_base_path (PLUS_EXPR, TREE_OPERAND (*t, 0), binfo, true, + /* In an NSDMI build_base_path defers building conversions to morally + virtual bases, and we handle it here. */ + tree basetype = TREE_TYPE (*t); + *t = convert_to_base (TREE_OPERAND (*t, 0), basetype, + /*check_access=*/false, /*nonnull=*/true, tf_warning_or_error); } @@ -4124,7 +4201,8 @@ member_p (const_tree decl) } /* Create a placeholder for member access where we don't actually have an - object that the access is against. */ + object that the access is against. For a general declval<T> equivalent, + use build_stub_object instead. */ tree build_dummy_object (tree type) @@ -4629,20 +4707,26 @@ zero_init_expr_p (tree t) tree type = TREE_TYPE (t); if (!type || uses_template_parms (type)) return false; - if (zero_init_p (type)) - return initializer_zerop (t); if (TYPE_PTRMEM_P (type)) return null_member_pointer_value_p (t); - if (TREE_CODE (t) == CONSTRUCTOR - && CP_AGGREGATE_TYPE_P (type)) + if (TREE_CODE (t) == CONSTRUCTOR) { - tree elt_init; - unsigned HOST_WIDE_INT i; - FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (t), i, elt_init) - if (!zero_init_expr_p (elt_init)) - return false; + if (COMPOUND_LITERAL_P (t) + || BRACE_ENCLOSED_INITIALIZER_P (t)) + /* Undigested, conversions might change the zeroness. */ + return false; + for (constructor_elt &elt : CONSTRUCTOR_ELTS (t)) + { + if (TREE_CODE (type) == UNION_TYPE + && elt.index != first_field (type)) + return false; + if (!zero_init_expr_p (elt.value)) + return false; + } return true; } + if (zero_init_p (type)) + return initializer_zerop (t); return false; } @@ -5303,7 +5387,9 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, // walk the parameter list. Doing so causes false // positives in the pack expansion checker since the // requires parameters are introduced as pack expansions. - WALK_SUBTREE (TREE_OPERAND (*tp, 1)); + ++cp_unevaluated_operand; + result = cp_walk_tree (&REQUIRES_EXPR_REQS (*tp), func, data, pset); + --cp_unevaluated_operand; *walk_subtrees_p = 0; break; @@ -5364,6 +5450,11 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, } break; + case STATIC_ASSERT: + WALK_SUBTREE (STATIC_ASSERT_CONDITION (*tp)); + WALK_SUBTREE (STATIC_ASSERT_MESSAGE (*tp)); + break; + default: return NULL_TREE; } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index dff4e9b..a2398db 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -261,6 +261,17 @@ original_type (tree t) return cp_build_qualified_type (t, quals); } +/* Merge the attributes of type OTHER_TYPE into the attributes of type TYPE + and return a variant of TYPE with the merged attributes. */ + +static tree +merge_type_attributes_from (tree type, tree other_type) +{ + tree attrs = targetm.merge_type_attributes (type, other_type); + attrs = restrict_type_identity_attributes_to (attrs, TYPE_ATTRIBUTES (type)); + return cp_build_type_attribute_variant (type, attrs); +} + /* Return the common type for two arithmetic types T1 and T2 under the usual arithmetic conversions. The default conversions have already been applied, and enumerated types converted to their compatible @@ -320,9 +331,9 @@ cp_common_type (tree t1, tree t2) /* When we get here we should have two vectors of the same size. Just prefer the unsigned one if present. */ if (TYPE_UNSIGNED (t1)) - return build_type_attribute_variant (t1, attributes); + return merge_type_attributes_from (t1, t2); else - return build_type_attribute_variant (t2, attributes); + return merge_type_attributes_from (t2, t1); } /* If only one is real, use it as the result. */ @@ -1610,6 +1621,176 @@ similar_type_p (tree type1, tree type2) return false; } +/* Helper function for layout_compatible_type_p and + is_corresponding_member_aggr. Advance to next members (NULL if + no further ones) and return true if those members are still part of + the common initial sequence. */ + +bool +next_common_initial_seqence (tree &memb1, tree &memb2) +{ + while (memb1) + { + if (TREE_CODE (memb1) != FIELD_DECL + || (DECL_FIELD_IS_BASE (memb1) && is_empty_field (memb1))) + { + memb1 = DECL_CHAIN (memb1); + continue; + } + if (DECL_FIELD_IS_BASE (memb1)) + { + memb1 = TYPE_FIELDS (TREE_TYPE (memb1)); + continue; + } + break; + } + while (memb2) + { + if (TREE_CODE (memb2) != FIELD_DECL + || (DECL_FIELD_IS_BASE (memb2) && is_empty_field (memb2))) + { + memb2 = DECL_CHAIN (memb2); + continue; + } + if (DECL_FIELD_IS_BASE (memb2)) + { + memb2 = TYPE_FIELDS (TREE_TYPE (memb2)); + continue; + } + break; + } + if (memb1 == NULL_TREE && memb2 == NULL_TREE) + return true; + if (memb1 == NULL_TREE || memb2 == NULL_TREE) + return false; + if (DECL_BIT_FIELD_TYPE (memb1)) + { + if (!DECL_BIT_FIELD_TYPE (memb2)) + return false; + if (!layout_compatible_type_p (DECL_BIT_FIELD_TYPE (memb1), + DECL_BIT_FIELD_TYPE (memb2))) + return false; + if (TYPE_PRECISION (TREE_TYPE (memb1)) + != TYPE_PRECISION (TREE_TYPE (memb2))) + return false; + } + else if (DECL_BIT_FIELD_TYPE (memb2)) + return false; + else if (!layout_compatible_type_p (TREE_TYPE (memb1), TREE_TYPE (memb2))) + return false; + if ((!lookup_attribute ("no_unique_address", DECL_ATTRIBUTES (memb1))) + != !lookup_attribute ("no_unique_address", DECL_ATTRIBUTES (memb2))) + return false; + if (!tree_int_cst_equal (bit_position (memb1), bit_position (memb2))) + return false; + return true; +} + +/* Return true if TYPE1 and TYPE2 are layout-compatible types. */ + +bool +layout_compatible_type_p (tree type1, tree type2) +{ + if (type1 == error_mark_node || type2 == error_mark_node) + return false; + if (type1 == type2) + return true; + if (TREE_CODE (type1) != TREE_CODE (type2)) + return false; + + type1 = cp_build_qualified_type (type1, TYPE_UNQUALIFIED); + type2 = cp_build_qualified_type (type2, TYPE_UNQUALIFIED); + + if (TREE_CODE (type1) == ENUMERAL_TYPE) + return (TYPE_ALIGN (type1) == TYPE_ALIGN (type2) + && tree_int_cst_equal (TYPE_SIZE (type1), TYPE_SIZE (type2)) + && same_type_p (finish_underlying_type (type1), + finish_underlying_type (type2))); + + if (CLASS_TYPE_P (type1) + && std_layout_type_p (type1) + && std_layout_type_p (type2) + && TYPE_ALIGN (type1) == TYPE_ALIGN (type2) + && tree_int_cst_equal (TYPE_SIZE (type1), TYPE_SIZE (type2))) + { + tree field1 = TYPE_FIELDS (type1); + tree field2 = TYPE_FIELDS (type2); + if (TREE_CODE (type1) == RECORD_TYPE) + { + while (1) + { + if (!next_common_initial_seqence (field1, field2)) + return false; + if (field1 == NULL_TREE) + return true; + field1 = DECL_CHAIN (field1); + field2 = DECL_CHAIN (field2); + } + } + /* Otherwise both types must be union types. + The standard says: + "Two standard-layout unions are layout-compatible if they have + the same number of non-static data members and corresponding + non-static data members (in any order) have layout-compatible + types." + but the code anticipates that bitfield vs. non-bitfield, + different bitfield widths or presence/absence of + [[no_unique_address]] should be checked as well. */ + auto_vec<tree, 16> vec; + unsigned int count = 0; + for (; field1; field1 = DECL_CHAIN (field1)) + if (TREE_CODE (field1) == FIELD_DECL) + count++; + for (; field2; field2 = DECL_CHAIN (field2)) + if (TREE_CODE (field2) == FIELD_DECL) + vec.safe_push (field2); + /* Discussions on core lean towards treating multiple union fields + of the same type as the same field, so this might need changing + in the future. */ + if (count != vec.length ()) + return false; + for (field1 = TYPE_FIELDS (type1); field1; field1 = DECL_CHAIN (field1)) + { + if (TREE_CODE (field1) != FIELD_DECL) + continue; + unsigned int j; + tree t1 = DECL_BIT_FIELD_TYPE (field1); + if (t1 == NULL_TREE) + t1 = TREE_TYPE (field1); + FOR_EACH_VEC_ELT (vec, j, field2) + { + tree t2 = DECL_BIT_FIELD_TYPE (field2); + if (t2 == NULL_TREE) + t2 = TREE_TYPE (field2); + if (DECL_BIT_FIELD_TYPE (field1)) + { + if (!DECL_BIT_FIELD_TYPE (field2)) + continue; + if (TYPE_PRECISION (TREE_TYPE (field1)) + != TYPE_PRECISION (TREE_TYPE (field2))) + continue; + } + else if (DECL_BIT_FIELD_TYPE (field2)) + continue; + if (!layout_compatible_type_p (t1, t2)) + continue; + if ((!lookup_attribute ("no_unique_address", + DECL_ATTRIBUTES (field1))) + != !lookup_attribute ("no_unique_address", + DECL_ATTRIBUTES (field2))) + continue; + break; + } + if (j == vec.length ()) + return false; + vec.unordered_remove (j); + } + return true; + } + + return same_type_p (type1, type2); +} + /* Returns 1 if TYPE1 is at least as qualified as TYPE2. */ bool @@ -2437,36 +2618,14 @@ rationalize_conditional_expr (enum tree_code code, tree t, that are directly reachable. */ tree -lookup_anon_field (tree t, tree type) +lookup_anon_field (tree, tree type) { tree field; - t = TYPE_MAIN_VARIANT (t); - - for (field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field)) - { - if (TREE_STATIC (field)) - continue; - if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) - continue; - - /* If we find it directly, return the field. */ - if (DECL_NAME (field) == NULL_TREE - && type == TYPE_MAIN_VARIANT (TREE_TYPE (field))) - { - return field; - } - - /* Otherwise, it could be nested, search harder. */ - if (DECL_NAME (field) == NULL_TREE - && ANON_AGGR_TYPE_P (TREE_TYPE (field))) - { - tree subfield = lookup_anon_field (TREE_TYPE (field), type); - if (subfield) - return subfield; - } - } - return NULL_TREE; + type = TYPE_MAIN_VARIANT (type); + field = ANON_AGGR_TYPE_FIELD (type); + gcc_assert (field); + return field; } /* Build an expression representing OBJECT.MEMBER. OBJECT is an @@ -2528,7 +2687,10 @@ build_class_member_access_expr (cp_expr object, tree member, member_scope = DECL_CLASS_CONTEXT (member); if (!mark_used (member, complain) && !(complain & tf_error)) return error_mark_node; - if (TREE_DEPRECATED (member)) + + if (TREE_UNAVAILABLE (member)) + error_unavailable_use (member, NULL_TREE); + else if (TREE_DEPRECATED (member)) warn_deprecated_use (member, NULL_TREE); } else @@ -3190,9 +3352,19 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p, { /* Look up the member. */ access_failure_info afi; + if (processing_template_decl) + /* Even though this class member access expression is at this + point not dependent, the member itself may be dependent, and + we must not potentially push a access check for a dependent + member onto TI_DEFERRED_ACCESS_CHECKS. So don't check access + ahead of time here; we're going to redo this member lookup at + instantiation time anyway. */ + push_deferring_access_checks (dk_no_check); member = lookup_member (access_path, name, /*protect=*/1, /*want_type=*/false, complain, &afi); + if (processing_template_decl) + pop_deferring_access_checks (); afi.maybe_suggest_accessor (TYPE_READONLY (object_type)); if (member == NULL_TREE) { @@ -3233,7 +3405,9 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p, } } - if (TREE_DEPRECATED (member)) + if (TREE_UNAVAILABLE (member)) + error_unavailable_use (member, NULL_TREE); + else if (TREE_DEPRECATED (member)) warn_deprecated_use (member, NULL_TREE); if (template_p) @@ -3305,10 +3479,7 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name) member = DECL_CHAIN (member)) if (DECL_NAME (member) == member_name) break; - tree res = build_simple_component_ref (ptrmem, member); - - TREE_NO_WARNING (res) = 1; - return res; + return build_simple_component_ref (ptrmem, member); } /* Given an expression PTR for a pointer, return an expression @@ -3422,7 +3593,7 @@ cp_build_indirect_ref_1 (location_t loc, tree ptr, ref_operator errorstring, if (warn_strict_aliasing > 2 && cp_strict_aliasing_warning (EXPR_LOCATION (ptr), type, TREE_OPERAND (ptr, 0))) - TREE_NO_WARNING (ptr) = 1; + suppress_warning (ptr, OPT_Wstrict_aliasing); } if (VOID_TYPE_P (t)) @@ -4047,7 +4218,7 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params, { tree c = extract_call_expr (ret); if (TREE_CODE (c) == CALL_EXPR) - TREE_NO_WARNING (c) = 1; + suppress_warning (c, OPT_Wnonnull); } if (allocated != NULL) @@ -4429,14 +4600,14 @@ warn_for_null_address (location_t location, tree op, tsubst_flags_t complain) if (!warn_address || (complain & tf_warning) == 0 || c_inhibit_evaluation_warnings != 0 - || TREE_NO_WARNING (op)) + || warning_suppressed_p (op, OPT_Waddress)) return; tree cop = fold_for_warn (op); if (TREE_CODE (cop) == ADDR_EXPR && decl_with_nonnull_addr_p (TREE_OPERAND (cop, 0)) - && !TREE_NO_WARNING (cop)) + && !warning_suppressed_p (cop, OPT_Waddress)) warning_at (location, OPT_Waddress, "the address of %qD will never " "be NULL", TREE_OPERAND (cop, 0)); @@ -4857,7 +5028,7 @@ cp_build_binary_op (const op_location_t &location, 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) + && !warning_suppressed_p (op1, OPT_Wsizeof_array_div) && (complain & tf_warning)) maybe_warn_sizeof_array_div (location, first_arg, type0, op1, non_reference (type1)); @@ -5276,7 +5447,7 @@ cp_build_binary_op (const op_location_t &location, pfn0 = cp_fully_fold (pfn0); /* Avoid -Waddress warnings (c++/64877). */ if (TREE_CODE (pfn0) == ADDR_EXPR) - TREE_NO_WARNING (pfn0) = 1; + suppress_warning (pfn0, OPT_Waddress); pfn1 = pfn_from_ptrmemfunc (op1); pfn1 = cp_fully_fold (pfn1); delta0 = delta_from_ptrmemfunc (op0); @@ -5465,7 +5636,9 @@ cp_build_binary_op (const op_location_t &location, result_type = composite_pointer_type (location, type0, type1, op0, op1, CPO_COMPARISON, complain); - else if (code0 == POINTER_TYPE && null_ptr_cst_p (orig_op1)) + else if ((code0 == POINTER_TYPE && null_ptr_cst_p (orig_op1)) + || (code1 == POINTER_TYPE && null_ptr_cst_p (orig_op0)) + || (null_ptr_cst_p (orig_op0) && null_ptr_cst_p (orig_op1))) { /* Core Issue 1512 made this ill-formed. */ if (complain & tf_error) @@ -5473,17 +5646,6 @@ cp_build_binary_op (const op_location_t &location, "integer zero (%qT and %qT)", type0, type1); return error_mark_node; } - else if (code1 == POINTER_TYPE && null_ptr_cst_p (orig_op0)) - { - /* Core Issue 1512 made this ill-formed. */ - if (complain & tf_error) - error_at (location, "ordered comparison of pointer with " - "integer zero (%qT and %qT)", type0, type1); - return error_mark_node; - } - else if (null_ptr_cst_p (orig_op0) && null_ptr_cst_p (orig_op1)) - /* One of the operands must be of nullptr_t type. */ - result_type = TREE_TYPE (nullptr_node); else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { result_type = type0; @@ -5920,6 +6082,8 @@ cp_build_binary_op (const op_location_t &location, if (!processing_template_decl) { + if (resultcode == SPACESHIP_EXPR) + result = get_target_expr_sfinae (result, complain); op0 = cp_fully_fold (op0); /* Only consider the second argument if the first isn't overflowed. */ if (!CONSTANT_CLASS_P (op0) || TREE_OVERFLOW_P (op0)) @@ -5966,6 +6130,42 @@ build_x_vec_perm_expr (location_t loc, orig_arg1, orig_arg2); return exp; } + +/* Build a VEC_PERM_EXPR. + This is a simple wrapper for c_build_shufflevector. */ +tree +build_x_shufflevector (location_t loc, vec<tree, va_gc> *args, + tsubst_flags_t complain) +{ + tree arg0 = (*args)[0]; + tree arg1 = (*args)[1]; + if (processing_template_decl) + { + for (unsigned i = 0; i < args->length (); ++i) + if (type_dependent_expression_p ((*args)[i])) + { + tree exp = build_min_nt_call_vec (NULL, args); + CALL_EXPR_IFN (exp) = IFN_SHUFFLEVECTOR; + return exp; + } + arg0 = build_non_dependent_expr (arg0); + arg1 = build_non_dependent_expr (arg1); + /* ??? Nothing needed for the index arguments? */ + } + auto_vec<tree, 16> mask; + for (unsigned i = 2; i < args->length (); ++i) + { + tree idx = maybe_constant_value ((*args)[i]); + mask.safe_push (idx); + } + tree exp = c_build_shufflevector (loc, arg0, arg1, mask, complain & tf_error); + if (processing_template_decl && exp != error_mark_node) + { + exp = build_min_non_dep_call_vec (exp, NULL, args); + CALL_EXPR_IFN (exp) = IFN_SHUFFLEVECTOR; + } + return exp; +} /* Return a tree for the sum or difference (RESULTCODE says which) of pointer PTROP and integer INTOP. */ @@ -7003,7 +7203,7 @@ unary_complex_lvalue (enum tree_code code, tree arg) tf_warning_or_error); arg = build2 (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result); - TREE_NO_WARNING (arg) = 1; + suppress_warning (arg /* What warning? */); return arg; } @@ -7060,9 +7260,14 @@ cxx_mark_addressable (tree exp, bool array_ref_p) && TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0)))) return true; + x = TREE_OPERAND (x, 0); + break; + + case COMPONENT_REF: + if (bitfield_p (x)) + error ("attempt to take address of bit-field"); /* FALLTHRU */ case ADDR_EXPR: - case COMPONENT_REF: case ARRAY_REF: case REALPART_EXPR: case IMAGPART_EXPR: @@ -7261,7 +7466,11 @@ build_x_compound_expr (location_t loc, tree op1, tree op2, { if (type_dependent_expression_p (op1) || type_dependent_expression_p (op2)) - return build_min_nt_loc (loc, COMPOUND_EXPR, op1, op2); + { + result = build_min_nt_loc (loc, COMPOUND_EXPR, op1, op2); + maybe_save_operator_binding (result); + return result; + } op1 = build_non_dependent_expr (op1); op2 = build_non_dependent_expr (op2); } @@ -7938,22 +8147,18 @@ build_reinterpret_cast_1 (location_t loc, tree type, tree expr, type = cv_unqualified (type); /* [expr.reinterpret.cast] - A glvalue expression of type T1 can be cast to the type + A glvalue of type T1, designating an object x, can be cast to the type "reference to T2" if an expression of type "pointer to T1" can be - explicitly converted to the type "pointer to T2" using a - reinterpret_cast. */ + explicitly converted to the type "pointer to T2" using a reinterpret_cast. + The result is that of *reinterpret_cast<T2 *>(p) where p is a pointer to x + of type "pointer to T1". No temporary is created, no copy is made, and no + constructors (11.4.4) or conversion functions (11.4.7) are called. */ if (TYPE_REF_P (type)) { - if (TYPE_REF_IS_RVALUE (type) && !VOID_TYPE_P (intype)) - { - if (!obvalue_p (expr)) - /* Perform the temporary materialization conversion. */ - expr = get_target_expr_sfinae (expr, complain); - } - else if (!lvalue_p (expr)) + if (!glvalue_p (expr)) { if (complain & tf_error) - error_at (loc, "invalid cast of an rvalue expression of type " + error_at (loc, "invalid cast of a prvalue expression of type " "%qT to type %qT", intype, type); return error_mark_node; @@ -8101,7 +8306,7 @@ build_reinterpret_cast_1 (location_t loc, tree type, tree expr, "pointer-to-object is conditionally-supported"); return build_nop_reinterpret (type, expr); } - else if (gnu_vector_type_p (type)) + else if (gnu_vector_type_p (type) && scalarish_type_p (intype)) return convert_to_vector (type, rvalue (expr)); else if (gnu_vector_type_p (intype) && INTEGRAL_OR_ENUMERATION_TYPE_P (type)) @@ -8914,7 +9119,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, TREE_SIDE_EFFECTS (result) = 1; if (!plain_assign) - TREE_NO_WARNING (result) = 1; + suppress_warning (result, OPT_Wparentheses); ret: if (preeval) @@ -8929,7 +9134,6 @@ build_x_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, tree orig_lhs = lhs; tree orig_rhs = rhs; tree overload = NULL_TREE; - tree op = build_nt (modifycode, NULL_TREE, NULL_TREE); if (lhs == error_mark_node || rhs == error_mark_node) return cp_expr (error_mark_node, loc); @@ -8939,9 +9143,12 @@ build_x_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, if (modifycode == NOP_EXPR || type_dependent_expression_p (lhs) || type_dependent_expression_p (rhs)) - return build_min_nt_loc (loc, MODOP_EXPR, lhs, - build_min_nt_loc (loc, modifycode, NULL_TREE, - NULL_TREE), rhs); + { + tree op = build_min_nt_loc (loc, modifycode, NULL_TREE, NULL_TREE); + tree rval = build_min_nt_loc (loc, MODOP_EXPR, lhs, op, rhs); + maybe_save_operator_binding (rval); + return rval; + } lhs = build_non_dependent_expr (lhs); rhs = build_non_dependent_expr (rhs); @@ -8949,13 +9156,14 @@ build_x_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, if (modifycode != NOP_EXPR) { + tree op = build_nt (modifycode, NULL_TREE, NULL_TREE); tree rval = build_new_op (loc, MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs, op, &overload, complain); if (rval) { if (rval == error_mark_node) return rval; - TREE_NO_WARNING (rval) = 1; + suppress_warning (rval /* What warning? */); if (processing_template_decl) { if (overload != NULL_TREE) @@ -9562,13 +9770,13 @@ convert_for_assignment (tree type, tree rhs, if (warn_parentheses && TREE_CODE (type) == BOOLEAN_TYPE && TREE_CODE (rhs) == MODIFY_EXPR - && !TREE_NO_WARNING (rhs) + && !warning_suppressed_p (rhs, OPT_Wparentheses) && TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE && (complain & tf_warning) && warning_at (rhs_loc, OPT_Wparentheses, "suggest parentheses around assignment used as " "truth value")) - TREE_NO_WARNING (rhs) = 1; + suppress_warning (rhs, OPT_Wparentheses); if (complain & tf_warning) warn_for_address_or_pointer_of_packed_member (type, rhs); @@ -10219,6 +10427,9 @@ check_return_expr (tree retval, bool *no_warning) dependent: /* We should not have changed the return value. */ gcc_assert (retval == saved_retval); + /* We don't know if this is an lvalue or rvalue use, but + either way we can mark it as read. */ + mark_exp_read (retval); return retval; } @@ -10241,7 +10452,10 @@ check_return_expr (tree retval, bool *no_warning) See finish_function and finalize_nrv for the rest of this optimization. */ if (retval) - STRIP_ANY_LOCATION_WRAPPER (retval); + { + retval = maybe_undo_parenthesized_ref (retval); + STRIP_ANY_LOCATION_WRAPPER (retval); + } bool named_return_value_okay_p = can_do_nrvo_p (retval, functype); if (fn_returns_value_p && flag_elide_constructors) @@ -10275,10 +10489,6 @@ check_return_expr (tree retval, bool *no_warning) if (VOID_TYPE_P (functype)) return error_mark_node; - /* If we had an id-expression obfuscated by force_paren_expr, we need - to undo it so we can try to treat it as an rvalue below. */ - retval = maybe_undo_parenthesized_ref (retval); - if (processing_template_decl) retval = build_non_dependent_expr (retval); diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index bde305b..f78dbf2 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -818,6 +818,12 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags) /* Handle aggregate NSDMI in non-constant initializers, too. */ value = replace_placeholders (value, decl); + /* A COMPOUND_LITERAL_P CONSTRUCTOR is the syntactic form; by the time we get + here it should have been digested into an actual value for the type. */ + gcc_checking_assert (TREE_CODE (value) != CONSTRUCTOR + || processing_template_decl + || !TREE_HAS_CONSTRUCTOR (value)); + /* If the initializer is not a constant, fill in DECL_INITIAL with the bits that are constant, and then return an expression that will perform the dynamic initialization. */ @@ -980,6 +986,7 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain, { int savederrorcount = errorcount; global_dc->pedantic_errors = 1; + auto s = make_temp_override (global_dc->dc_warn_system_headers, true); pedwarn (loc, OPT_Wnarrowing, "narrowing conversion of %qE from %qH to %qI", init, ftype, type); @@ -1177,6 +1184,7 @@ digest_init_r (tree type, tree init, int nested, int flags, the object is initialized from that element." */ if (cxx_dialect >= cxx11 && BRACE_ENCLOSED_INITIALIZER_P (stripped_init) + && !CONSTRUCTOR_IS_DESIGNATED_INIT (stripped_init) && CONSTRUCTOR_NELTS (stripped_init) == 1 && ((CLASS_TYPE_P (type) && !CLASSTYPE_NON_AGGREGATE (type)) || VECTOR_TYPE_P (type))) @@ -1320,9 +1328,6 @@ massage_init_elt (tree type, tree init, int nested, int flags, if (flags & LOOKUP_AGGREGATE_PAREN_INIT) new_flags |= LOOKUP_AGGREGATE_PAREN_INIT; init = digest_init_r (type, init, nested ? 2 : 1, new_flags, complain); - /* Strip a simple TARGET_EXPR when we know this is an initializer. */ - if (SIMPLE_TARGET_EXPR_P (init)) - init = TARGET_EXPR_INITIAL (init); /* When we defer constant folding within a statement, we may want to defer this folding as well. */ tree t = fold_non_dependent_init (init, complain); @@ -1514,19 +1519,6 @@ process_init_constructor_record (tree type, tree init, int nested, int flags, || identifier_p (ce->index)); if (ce->index == field || ce->index == DECL_NAME (field)) next = ce->value; - else if (ANON_AGGR_TYPE_P (fldtype) - && search_anon_aggr (fldtype, - TREE_CODE (ce->index) == FIELD_DECL - ? DECL_NAME (ce->index) - : ce->index)) - /* If the element is an anonymous union object and the - initializer list is a designated-initializer-list, the - anonymous union object is initialized by the - designated-initializer-list { D }, where D is the - designated-initializer-clause naming a member of the - anonymous union object. */ - next = build_constructor_single (init_list_type_node, - ce->index, ce->value); else { ce = NULL; @@ -1672,19 +1664,6 @@ process_init_constructor_record (tree type, tree init, int nested, int flags, if (ce->index == field || ce->index == DECL_NAME (field)) break; - if (ANON_AGGR_TYPE_P (TREE_TYPE (field))) - { - tree t - = search_anon_aggr (TREE_TYPE (field), - TREE_CODE (ce->index) == FIELD_DECL - ? DECL_NAME (ce->index) - : ce->index); - if (t) - { - field = t; - break; - } - } } } if (field) @@ -1934,11 +1913,17 @@ build_x_arrow (location_t loc, tree expr, tsubst_flags_t complain) if (processing_template_decl) { - if (type && TYPE_PTR_P (type) - && !dependent_scope_p (TREE_TYPE (type))) + tree ttype = NULL_TREE; + if (type && TYPE_PTR_P (type)) + ttype = TREE_TYPE (type); + if (ttype && !dependent_scope_p (ttype)) /* Pointer to current instantiation, don't treat as dependent. */; else if (type_dependent_expression_p (expr)) - return build_min_nt_loc (loc, ARROW_EXPR, expr); + { + expr = build_min_nt_loc (loc, ARROW_EXPR, expr); + TREE_TYPE (expr) = ttype; + return expr; + } expr = build_non_dependent_expr (expr); } @@ -2178,7 +2163,7 @@ build_functional_cast_1 (location_t loc, tree exp, tree parms, type = TREE_TYPE (exp); if (DECL_ARTIFICIAL (exp)) - cp_warn_deprecated_use (type); + cp_handle_deprecated_or_unavailable (type); } else type = exp; @@ -2200,24 +2185,13 @@ build_functional_cast_1 (location_t loc, tree exp, tree parms, error_at (loc, "invalid use of %qT", anode); return error_mark_node; } - else if (!parms) + else { - /* Even if there are no parameters, we might be able to deduce from - default template arguments. Pass TF_NONE so that we don't - generate redundant diagnostics. */ - type = do_auto_deduction (type, parms, anode, tf_none, + type = do_auto_deduction (type, parms, anode, complain, adc_variable_type); if (type == error_mark_node) - { - if (complain & tf_error) - error_at (loc, "cannot deduce template arguments " - "for %qT from %<()%>", anode); - return error_mark_node; - } + return error_mark_node; } - else - type = do_auto_deduction (type, parms, anode, complain, - adc_variable_type); } if (processing_template_decl) |