diff options
author | Martin Liska <mliska@suse.cz> | 2022-11-07 08:24:48 +0100 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2022-11-07 08:24:48 +0100 |
commit | 1b09b78ee61bd921ae78ebd0f7905b95b9e1c903 (patch) | |
tree | 9c04b59cdd2cd460f0727501d15402d31ffcf5a4 /gcc/cp | |
parent | 1eb021edb27e26f95cda63df121f6bc951647599 (diff) | |
parent | c4f8f8afd07680f9e718de1331cd09607bdd9ac8 (diff) | |
download | gcc-1b09b78ee61bd921ae78ebd0f7905b95b9e1c903.zip gcc-1b09b78ee61bd921ae78ebd0f7905b95b9e1c903.tar.gz gcc-1b09b78ee61bd921ae78ebd0f7905b95b9e1c903.tar.bz2 |
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 120 | ||||
-rw-r--r-- | gcc/cp/call.cc | 19 | ||||
-rw-r--r-- | gcc/cp/constraint.cc | 3 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 22 | ||||
-rw-r--r-- | gcc/cp/decl.cc | 30 | ||||
-rw-r--r-- | gcc/cp/decl2.cc | 8 | ||||
-rw-r--r-- | gcc/cp/lambda.cc | 236 | ||||
-rw-r--r-- | gcc/cp/mangle.cc | 8 | ||||
-rw-r--r-- | gcc/cp/mapper-client.cc | 4 | ||||
-rw-r--r-- | gcc/cp/module.cc | 6 | ||||
-rw-r--r-- | gcc/cp/parser.cc | 99 | ||||
-rw-r--r-- | gcc/cp/pt.cc | 51 | ||||
-rw-r--r-- | gcc/cp/semantics.cc | 1 | ||||
-rw-r--r-- | gcc/cp/tree.cc | 20 |
14 files changed, 430 insertions, 197 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d065fd1..dd7526e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,123 @@ +2022-11-06 Patrick Palka <ppalka@redhat.com> + + * tree.cc (cxx_attribute_table): Include init_priority entry + only if SUPPORTS_INIT_PRIORITY. + (handle_init_priority_attribute): Add ATTRIBUTE_UNUSED. Assert + SUPPORTS_INIT_PRIORITY is true. + +2022-11-04 Torbjörn SVENSSON <torbjorn.svensson@foss.st.com> + Yvan ROUX <yvan.roux@foss.st.com> + + * mapper-client.cc: Use in-process client when networking is + disabled. + +2022-11-03 Marek Polacek <polacek@redhat.com> + + PR c++/107488 + * call.cc (do_warn_dangling_reference): Quash -Wdangling-reference + for member operator*. + +2022-11-03 Patrick Palka <ppalka@redhat.com> + + PR c++/107179 + * constraint.cc (tsubst_requires_expr): Make sure we're not + deferring access checks. + +2022-11-03 Jason Merrill <jason@redhat.com> + + * parser.cc (cp_parser_template_declaration_after_parameters): Fix + concept parsing below C++20. + +2022-11-03 Patrick Palka <ppalka@redhat.com> + + PR c++/93413 + * decl2.cc (mark_used): Don't defer synthesis of virtual + functions. + +2022-11-01 Nathan Sidwell <nathan@acm.org> + + * cp-tree.h (LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR): New. + (struct tree_lambda_expr): Add discriminator_sig bitfield. + (recrd_lambda_scope_sig_discriminator): Declare. + * lambda.cc (struct lambda_sig_count): New. + (lambda_discriminator): Add signature vector. + (start_lambda_scope): Adjust. + (compare_lambda_template_head, compare_lambda_sig): New. + (record_lambda_scope_sig_discriminator): New. + * mangle.cc (write_closure_type): Use the scope-sig discriminator for + ABI >= 18. Emit abi mangling warning if needed. + * module.cc (trees_out::core_vals): Stream the new discriminator. + (trees_in::core_vals): Likewise. + * parser.cc (cp_parser_lambda_declarator_opt): Call + record_lambda_scope_sig_discriminator. + * pt.cc (tsubst_lambda_expr): Likewise. + +2022-11-01 Nathan Sidwell <nathan@acm.org> + + * cp-tree.h (LAMBDA_EXPR_DISCRIMINATOR): Rename to ... + (LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR): ... here. + (struct tree_lambda_expr): Make default_capture_mode & + discriminator_scope bitfields. + (record_null_lambda_scope) Delete. + (record_lambda_scope_discriminator): Declare. + * lambda.cc (struct lambda_discriminator): New struct. + (lambda_scope, lambda_scope_stack): Adjust types. + (lambda_count): Delete. + (struct tree_int): Delete. + (start_lambda_scope, finish_lambda_scope): Adjust. + (record_lambda_scope): Only record the scope. + (record_lambda_scope_discriminator): New. + * mangle.cc (write_closure_type_name): Adjust. + * module.cc (trees_out::core_vals): Likewise, + (trees_in::core_vals): Likewise. + * parser.cc (cp_parser_lambda_expression): Call + record_lambda_scope_discriminator. + * pt.cc (tsubst_lambda_expr): Adjust record_lambda_scope caling. Call + record_lambda_scope_discriminator. Commonize control flow on tsubsting + the operator function. + +2022-11-01 Jason Merrill <jason@redhat.com> + + * parser.cc (make_call_declarator): Add std_attrs parm. + (cp_parser_lambda_declarator_opt): Pass it. + (cp_parser_direct_declarator): Pass it. + +2022-11-01 Jason Merrill <jason@redhat.com> + + * decl.cc (finish_function): Set TREE_NOTHROW later in the function. + +2022-11-01 Jason Merrill <jason@redhat.com> + + * decl.cc (duplicate_decls): Reformat loop. + * parser.cc (cp_parser_member_declaration): Add newline. + * semantics.cc: Remove newline. + +2022-10-28 Marek Polacek <polacek@redhat.com> + + * call.cc (maybe_warn_dangling_reference): Enable the warning in + system headers if the decl isn't in a system header. + +2022-10-28 Jason Merrill <jason@redhat.com> + + * decl.cc (grokdeclarator): Call decl_attributes before do_friend. + +2022-10-28 Jakub Jelinek <jakub@redhat.com> + + * parser.cc (cp_parser_omp_all_clauses): Allow optional comma + before the first clause even in pragma syntax. + (cp_parser_omp_allocate, cp_parser_omp_atomic, cp_parser_omp_depobj, + cp_parser_omp_flush, cp_parser_omp_scan_loop_body, + cp_parser_omp_ordered, cp_parser_omp_assumption_clauses, + cp_finish_omp_declare_variant, cp_parser_omp_declare_target, + cp_parser_omp_declare_reduction_exprs, cp_parser_omp_requires, + cp_parser_omp_error): Likewise. + +2022-10-28 Joseph Myers <joseph@codesourcery.com> + + PR c/61469 + * cp-tree.h (ENUM_FIXED_UNDERLYING_TYPE_P, ENUM_UNDERLYING_TYPE): + Remove. Moved to c-common.h. + 2022-10-27 Jakub Jelinek <jakub@redhat.com> PR c++/107379 diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 951b9fd..2c0fa37 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -13467,7 +13467,17 @@ do_warn_dangling_reference (tree expr) can be e.g. const int& z = std::min({1, 2, 3, 4, 5, 6, 7}); which doesn't dangle: std::min here returns an int. */ - || !TYPE_REF_OBJ_P (TREE_TYPE (TREE_TYPE (fndecl)))) + || !TYPE_REF_OBJ_P (TREE_TYPE (TREE_TYPE (fndecl))) + /* Don't emit a false positive for: + std::vector<int> v = ...; + std::vector<int>::const_iterator it = v.begin(); + const int &r = *it++; + because R refers to one of the int elements of V, not to + a temporary object. Member operator* may return a reference + but probably not to one of its arguments. */ + || (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl) + && DECL_OVERLOADED_OPERATOR_P (fndecl) + && DECL_OVERLOADED_OPERATOR_IS (fndecl, INDIRECT_REF))) return NULL_TREE; /* Here we're looking to see if any of the arguments is a temporary @@ -13539,6 +13549,13 @@ maybe_warn_dangling_reference (const_tree decl, tree init) return; if (!TYPE_REF_P (TREE_TYPE (decl))) return; + /* Don't suppress the diagnostic just because the call comes from + a system header. If the DECL is not in a system header, or if + -Wsystem-headers was provided, warn. */ + auto wsh + = make_temp_override (global_dc->dc_warn_system_headers, + (!in_system_header_at (DECL_SOURCE_LOCATION (decl)) + || global_dc->dc_warn_system_headers)); if (tree call = do_warn_dangling_reference (init)) { auto_diagnostic_group d; diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 5e6a3bc..f6ef078 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -2252,6 +2252,9 @@ tsubst_requires_expr (tree t, tree args, sat_info info) { local_specialization_stack stack (lss_copy); + /* We need to check access during the substitution. */ + deferring_access_check_sentinel acs (dk_no_deferred); + /* A requires-expression is an unevaluated context. */ cp_unevaluated u; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 6d84514..d13bb3d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1500,9 +1500,13 @@ enum cp_lambda_default_capture_mode_type { #define LAMBDA_EXPR_EXTRA_SCOPE(NODE) \ (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->extra_scope) -/* If EXTRA_SCOPE, this is the number of the lambda within that scope. */ -#define LAMBDA_EXPR_DISCRIMINATOR(NODE) \ - (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->discriminator) +/* Lambdas in the same extra scope might need a discriminating count. + For ABI 17, we have single per-scope count, for ABI 18, we have + per-scope, per-signature numbering. */ +#define LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR(NODE) \ + (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->discriminator_scope) +#define LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR(NODE) \ + (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->discriminator_sig) /* During parsing of the lambda, a vector of capture proxies which need to be pushed once we're done processing a nested lambda. */ @@ -1530,8 +1534,9 @@ struct GTY (()) tree_lambda_expr tree regen_info; vec<tree, va_gc> *pending_proxies; location_t locus; - enum cp_lambda_default_capture_mode_type default_capture_mode : 8; - short int discriminator; + enum cp_lambda_default_capture_mode_type default_capture_mode : 2; + unsigned discriminator_scope : 15; // Per-scope discriminator + unsigned discriminator_sig : 15; // Per-scope, per-signature discriminator }; /* Non-zero if this template specialization has access violations that @@ -7778,10 +7783,11 @@ extern tree cp_build_vec_convert (tree, location_t, tree, tsubst_flags_t); extern tree cp_build_bit_cast (location_t, tree, tree, tsubst_flags_t); -extern void start_lambda_scope (tree); -extern void record_lambda_scope (tree); -extern void record_null_lambda_scope (tree); +extern void start_lambda_scope (tree decl); extern void finish_lambda_scope (void); +extern void record_lambda_scope (tree lambda); +extern void record_lambda_scope_discriminator (tree lambda); +extern void record_lambda_scope_sig_discriminator (tree lambda, tree fn); extern tree start_lambda_function (tree fn, tree lambda_expr); extern void finish_lambda_function (tree body); extern bool regenerated_lambda_fn_p (tree); diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index bc085f8..6e98ea3 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -2343,12 +2343,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) DECL_INITIAL (old_result) = DECL_INITIAL (new_result); if (DECL_FUNCTION_TEMPLATE_P (newdecl)) { - tree parm; - DECL_ARGUMENTS (old_result) - = DECL_ARGUMENTS (new_result); - for (parm = DECL_ARGUMENTS (old_result); parm; - parm = DECL_CHAIN (parm)) - DECL_CONTEXT (parm) = old_result; + DECL_ARGUMENTS (old_result) = DECL_ARGUMENTS (new_result); + for (tree p = DECL_ARGUMENTS (old_result); p; p = DECL_CHAIN (p)) + DECL_CONTEXT (p) = old_result; if (tree fc = DECL_FRIEND_CONTEXT (new_result)) SET_DECL_FRIEND_CONTEXT (old_result, fc); @@ -14206,13 +14203,16 @@ grokdeclarator (const cp_declarator *declarator, else if (decl && DECL_NAME (decl)) { set_originating_module (decl, true); - + if (initialized) /* Kludge: We need funcdef_flag to be true in do_friend for in-class defaulted functions, but that breaks grokfndecl. So set it here. */ funcdef_flag = true; + cplus_decl_attributes (&decl, *attrlist, 0); + *attrlist = NULL_TREE; + decl = do_friend (ctype, unqualified_id, decl, flags, funcdef_flag); return decl; @@ -17867,14 +17867,6 @@ finish_function (bool inline_p) finish_fname_decls (); - /* If this function can't throw any exceptions, remember that. */ - if (!processing_template_decl - && !cp_function_chain->can_throw - && !flag_non_call_exceptions - && !decl_replaceable_p (fndecl, - opt_for_fn (fndecl, flag_semantic_interposition))) - TREE_NOTHROW (fndecl) = 1; - /* This must come after expand_function_end because cleanups might have declarations (from inline functions) that need to go into this function's blocks. */ @@ -18099,6 +18091,14 @@ finish_function (bool inline_p) && !DECL_OMP_DECLARE_REDUCTION_P (fndecl)) cp_genericize (fndecl); + /* If this function can't throw any exceptions, remember that. */ + if (!processing_template_decl + && !cp_function_chain->can_throw + && !flag_non_call_exceptions + && !decl_replaceable_p (fndecl, + opt_for_fn (fndecl, flag_semantic_interposition))) + TREE_NOTHROW (fndecl) = 1; + /* Emit the resumer and destroyer functions now, providing that we have not encountered some fatal error. */ if (coro_emit_helpers) diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc index e677926..eeb59ea 100644 --- a/gcc/cp/decl2.cc +++ b/gcc/cp/decl2.cc @@ -5788,14 +5788,6 @@ mark_used (tree decl, tsubst_flags_t complain /* = tf_warning_or_error */) && !DECL_DEFAULTED_OUTSIDE_CLASS_P (decl) && ! DECL_INITIAL (decl)) { - /* Defer virtual destructors so that thunks get the right - linkage. */ - if (DECL_VIRTUAL_P (decl) && !at_eof) - { - note_vague_linkage_fn (decl); - return true; - } - /* Remember the current location for a function we will end up synthesizing. Then we can inform the user where it was required in the case of error. */ diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc index e9d5d4d..c7a9268 100644 --- a/gcc/cp/lambda.cc +++ b/gcc/cp/lambda.cc @@ -1444,79 +1444,223 @@ is_lambda_ignored_entity (tree val) return false; } -/* Lambdas that appear in variable initializer or default argument scope - get that in their mangling, so we need to record it. We might as well - use the count for function and namespace scopes as well. */ -static GTY(()) tree lambda_scope; -static GTY(()) int lambda_count; -struct GTY(()) tree_int +/* Lambdas that appear in variable initializer or default argument + scope get that in their mangling, so we need to record it. Also, + multiple lambdas in the same scope may need a mangling + discriminator. In ABI <= 17, there is a single per-scope sequence + number. In ABI >= 18, there are per-scope per-signature sequence + numbers. */ +struct GTY(()) lambda_sig_count { - tree t; - int i; + tree fn; // The lambda fn whose sig this is. + unsigned count; +}; +struct GTY(()) lambda_discriminator +{ + tree scope; + unsigned nesting; // Inside a function, VAR_DECLs get the function + // as scope. This counts that nesting. + unsigned count; // The per-scope counter. + vec<lambda_sig_count, va_gc> *discriminators; // Per-signature counters }; -static GTY(()) vec<tree_int, va_gc> *lambda_scope_stack; +// The current scope. +static GTY(()) lambda_discriminator lambda_scope; +// Stack of previous scopes. +static GTY(()) vec<lambda_discriminator, va_gc> *lambda_scope_stack; + +// Push DECL as lambda extra scope, also new discriminator counters. void start_lambda_scope (tree decl) { - tree_int ti; - gcc_assert (decl); - /* Once we're inside a function, we ignore variable scope and just push - the function again so that popping works properly. */ + gcc_checking_assert (decl); if (current_function_decl && TREE_CODE (decl) == VAR_DECL) - decl = current_function_decl; - ti.t = lambda_scope; - ti.i = lambda_count; - vec_safe_push (lambda_scope_stack, ti); - if (lambda_scope != decl) + // If we're inside a function, we ignore variable scope. Don't push. + lambda_scope.nesting++; + else + { + vec_safe_push (lambda_scope_stack, lambda_scope); + lambda_scope.scope = decl; + lambda_scope.nesting = 0; + lambda_scope.count = 0; + lambda_scope.discriminators = nullptr; + } +} + +// Pop from the current lambda extra scope. + +void +finish_lambda_scope (void) +{ + if (!lambda_scope.nesting--) { - /* Don't reset the count if we're still in the same function. */ - lambda_scope = decl; - lambda_count = 0; + lambda_scope = lambda_scope_stack->last (); + lambda_scope_stack->pop (); } } +// Record the current lambda scope into LAMBDA + void record_lambda_scope (tree lambda) { - LAMBDA_EXPR_EXTRA_SCOPE (lambda) = lambda_scope; - LAMBDA_EXPR_DISCRIMINATOR (lambda) = lambda_count++; - if (lambda_scope) + LAMBDA_EXPR_EXTRA_SCOPE (lambda) = lambda_scope.scope; + if (lambda_scope.scope) { tree closure = LAMBDA_EXPR_CLOSURE (lambda); gcc_checking_assert (closure); - maybe_key_decl (lambda_scope, TYPE_NAME (closure)); + maybe_key_decl (lambda_scope.scope, TYPE_NAME (closure)); } } -/* This lambda is an instantiation of a lambda in a template default argument - that got no LAMBDA_EXPR_EXTRA_SCOPE, so this shouldn't either. But we do - need to use and increment the global count to avoid collisions. */ +// Compare lambda template heads TMPL_A and TMPL_B, used for both +// templated lambdas, and template template parameters of said lambda. -void -record_null_lambda_scope (tree lambda) +static bool +compare_lambda_template_head (tree tmpl_a, tree tmpl_b) { - if (vec_safe_is_empty (lambda_scope_stack)) - record_lambda_scope (lambda); - else + // We only need one level of template parms + tree inner_a = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl_a)); + tree inner_b = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl_b)); + + // We only compare explicit template parms, ignoring trailing + // synthetic ones. + int len_a = TREE_VEC_LENGTH (inner_a); + int len_b = TREE_VEC_LENGTH (inner_b); + + for (int ix = 0, len = MAX (len_a, len_b); ix != len; ix++) { - tree_int *p = lambda_scope_stack->begin(); - LAMBDA_EXPR_EXTRA_SCOPE (lambda) = p->t; - LAMBDA_EXPR_DISCRIMINATOR (lambda) = p->i++; + tree parm_a = NULL_TREE; + if (ix < len_a) + { + parm_a = TREE_VEC_ELT (inner_a, ix); + if (parm_a == error_mark_node) + return false; + parm_a = TREE_VALUE (parm_a); + if (DECL_VIRTUAL_P (parm_a)) + parm_a = NULL_TREE; + } + + tree parm_b = NULL_TREE; + if (ix < len_b) + { + parm_b = TREE_VEC_ELT (inner_b, ix); + if (parm_b == error_mark_node) + return false; + parm_b = TREE_VALUE (parm_b); + if (DECL_VIRTUAL_P (parm_b)) + parm_b = NULL_TREE; + } + + if (!parm_a && !parm_b) + // we're done + break; + + if (!(parm_a && parm_b)) + return false; + + if (TREE_CODE (parm_a) != TREE_CODE (parm_b)) + return false; + + if (TREE_CODE (parm_a) == PARM_DECL) + { + if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm_a)) + != TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm_b))) + return false; + + if (!same_type_p (TREE_TYPE (parm_a), TREE_TYPE (parm_b))) + return false; + } + else + { + if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm_a)) + != TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm_b))) + return false; + + if (TREE_CODE (parm_a) != TEMPLATE_DECL) + gcc_checking_assert (TREE_CODE (parm_a) == TYPE_DECL); + else if (!compare_lambda_template_head (parm_a, parm_b)) + return false; + } } - gcc_assert (LAMBDA_EXPR_EXTRA_SCOPE (lambda) == NULL_TREE); + + return true; } -void -finish_lambda_scope (void) +// Compare lambda signatures FN_A and FN_B, they may be TEMPLATE_DECLs too. + +static bool +compare_lambda_sig (tree fn_a, tree fn_b) { - tree_int *p = &lambda_scope_stack->last (); - if (lambda_scope != p->t) + if (TREE_CODE (fn_a) == TEMPLATE_DECL + && TREE_CODE (fn_b) == TEMPLATE_DECL) + { + if (!compare_lambda_template_head (fn_a, fn_b)) + return false; + fn_a = DECL_TEMPLATE_RESULT (fn_a); + fn_b = DECL_TEMPLATE_RESULT (fn_b); + } + else if (TREE_CODE (fn_a) == TEMPLATE_DECL + || TREE_CODE (fn_b) == TEMPLATE_DECL) + return false; + + if (fn_a == error_mark_node + || fn_b == error_mark_node) + return false; + + for (tree args_a = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn_a))), + args_b = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn_b))); + args_a || args_b; + args_a = TREE_CHAIN (args_a), args_b = TREE_CHAIN (args_b)) { - lambda_scope = p->t; - lambda_count = p->i; + if (!args_a || !args_b) + return false; + // This check also deals with differing varadicness + if (!same_type_p (TREE_VALUE (args_a), TREE_VALUE (args_b))) + return false; } - lambda_scope_stack->pop (); + + return true; +} + +// Record the per-scope discriminator of LAMBDA. If the extra scope +// is empty, we must use the empty scope counter, which might not be +// the live one. + +void +record_lambda_scope_discriminator (tree lambda) +{ + auto *slot = (vec_safe_is_empty (lambda_scope_stack) + || LAMBDA_EXPR_EXTRA_SCOPE (lambda) + ? &lambda_scope : lambda_scope_stack->begin ()); + LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR (lambda) = slot->count++; +} + +// Record the per-scope per-signature discriminator of LAMBDA. If the +// extra scope is empty, we must use the empty scope counter, which +// might not be the live one. + +void +record_lambda_scope_sig_discriminator (tree lambda, tree fn) +{ + auto *slot = (vec_safe_is_empty (lambda_scope_stack) + || LAMBDA_EXPR_EXTRA_SCOPE (lambda) + ? &lambda_scope : lambda_scope_stack->begin ()); + gcc_checking_assert (LAMBDA_EXPR_EXTRA_SCOPE (lambda) == slot->scope); + + // A linear search, we're not expecting this to be a big list, and + // this avoids needing a signature hash function. + lambda_sig_count *sig; + if (unsigned ix = vec_safe_length (slot->discriminators)) + for (sig = slot->discriminators->begin (); ix--; sig++) + if (compare_lambda_sig (fn, sig->fn)) + goto found; + { + lambda_sig_count init = {fn, 0}; + sig = vec_safe_push (slot->discriminators, init); + } + found: + LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR (lambda) = sig->count++; } tree @@ -1648,6 +1792,10 @@ prune_lambda_captures (tree body) } } +// Record the per-scope per-signature discriminator of LAMBDA. If the +// extra scope is empty, we must use the empty scope counter, which +// might not be the live one. + void finish_lambda_function (tree body) { diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc index e396218..e97428e 100644 --- a/gcc/cp/mangle.cc +++ b/gcc/cp/mangle.cc @@ -1810,7 +1810,13 @@ write_closure_type_name (const tree type) write_method_parms (parms, /*method_p=*/1, fn); write_char ('E'); - write_compact_number (LAMBDA_EXPR_DISCRIMINATOR (lambda)); + if ((LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR (lambda) + != LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR (lambda)) + && abi_warn_or_compat_version_crosses (18)) + G.need_abi_warning = true; + write_compact_number (abi_version_at_least (18) + ? LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR (lambda) + : LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR (lambda)); } /* Convert NUMBER to ascii using base BASE and generating at least diff --git a/gcc/cp/mapper-client.cc b/gcc/cp/mapper-client.cc index fe9544b..8e331c0 100644 --- a/gcc/cp/mapper-client.cc +++ b/gcc/cp/mapper-client.cc @@ -227,6 +227,8 @@ module_client::open_module_client (location_t loc, const char *o, int fd = -1; #if CODY_NETWORKING fd = Cody::OpenLocal (&errmsg, name.c_str () + 1); +#else + errmsg = "disabled"; #endif if (fd >= 0) c = new module_client (fd, fd); @@ -254,6 +256,8 @@ module_client::open_module_client (location_t loc, const char *o, int fd = -1; #if CODY_NETWORKING fd = Cody::OpenInet6 (&errmsg, name.c_str (), port); +#else + errmsg = "disabled"; #endif name[colon] = ':'; diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 9957df5..0e9af31 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -6327,7 +6327,8 @@ trees_out::core_vals (tree t) if (streaming_p ()) { WU (((lang_tree_node *)t)->lambda_expression.default_capture_mode); - WU (((lang_tree_node *)t)->lambda_expression.discriminator); + WU (((lang_tree_node *)t)->lambda_expression.discriminator_scope); + WU (((lang_tree_node *)t)->lambda_expression.discriminator_sig); } break; @@ -6819,7 +6820,8 @@ trees_in::core_vals (tree t) = state->read_location (*this); RUC (cp_lambda_default_capture_mode_type, ((lang_tree_node *)t)->lambda_expression.default_capture_mode); - RU (((lang_tree_node *)t)->lambda_expression.discriminator); + RU (((lang_tree_node *)t)->lambda_expression.discriminator_scope); + RU (((lang_tree_node *)t)->lambda_expression.discriminator_sig); break; case OVERLOAD: diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index e685f19..9523f73 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -1607,7 +1607,7 @@ clear_decl_specs (cp_decl_specifier_seq *decl_specs) static cp_declarator *make_call_declarator (cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, cp_ref_qualifier, - tree, tree, tree, tree, location_t); + tree, tree, tree, tree, tree, location_t); static cp_declarator *make_array_declarator (cp_declarator *, tree); static cp_declarator *make_pointer_declarator @@ -1780,7 +1780,8 @@ make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type, /* Make a declarator for the function given by TARGET, with the indicated PARMS. The CV_QUALIFIERS apply to the function, as in "const"-qualified member function. The EXCEPTION_SPECIFICATION - indicates what exceptions can be thrown. */ + indicates what exceptions can be thrown. STD_ATTRS contains + attributes that appertain to the function type. */ cp_declarator * make_call_declarator (cp_declarator *target, @@ -1792,6 +1793,7 @@ make_call_declarator (cp_declarator *target, tree exception_specification, tree late_return_type, tree requires_clause, + tree std_attrs, location_t parens_loc) { cp_declarator *declarator; @@ -1816,6 +1818,8 @@ make_call_declarator (cp_declarator *target, else declarator->parameter_pack_p = false; + declarator->std_attributes = std_attrs; + return declarator; } @@ -11031,6 +11035,7 @@ cp_parser_lambda_expression (cp_parser* parser) return error_mark_node; record_lambda_scope (lambda_expr); + record_lambda_scope_discriminator (lambda_expr); /* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set. */ determine_visibility (TYPE_NAME (type)); @@ -11081,9 +11086,7 @@ cp_parser_lambda_expression (cp_parser* parser) ok = false; if (ok) - { - cp_parser_lambda_body (parser, lambda_expr); - } + cp_parser_lambda_body (parser, lambda_expr); else if (cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE)) { if (cp_parser_skip_to_closing_brace (parser)) @@ -11684,8 +11687,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) exception_spec, return_type, trailing_requires_clause, + std_attrs, UNKNOWN_LOCATION); - declarator->std_attributes = std_attrs; fco = grokmethod (&return_type_specs, declarator, @@ -11709,6 +11712,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) fco = finish_fully_implicit_template (parser, fco); finish_member_declaration (fco); + record_lambda_scope_sig_discriminator (lambda_expr, fco); obstack_free (&declarator_obstack, p); @@ -23264,8 +23268,8 @@ cp_parser_direct_declarator (cp_parser* parser, exception_specification, late_return, requires_clause, + attrs, parens_loc); - declarator->std_attributes = attrs; declarator->attributes = gnu_attrs; /* Any subsequent parameter lists are to do with return type, so are not those of the declared @@ -27522,6 +27526,7 @@ cp_parser_member_declaration (cp_parser* parser) decl = grokfield (declarator, &decl_specifiers, initializer, /*init_const_expr_p=*/true, asm_specification, attributes); + if (parser->fully_implicit_function_template_p) { if (friend_p) @@ -31445,10 +31450,11 @@ cp_parser_template_declaration_after_parameters (cp_parser* parser, else if (cxx_dialect >= cxx11 && cp_lexer_next_token_is_keyword (parser->lexer, RID_USING)) decl = cp_parser_alias_declaration (parser); - else if (cxx_dialect >= cxx20 /* Implies flag_concept. */ + else if (flag_concepts && cp_lexer_next_token_is_keyword (parser->lexer, RID_CONCEPT) - && !cp_lexer_nth_token_is_keyword (parser->lexer, 2, RID_BOOL)) - /* Allow 'concept bool' to be handled as per the TS. */ + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) + /* -fconcept-ts 'concept bool' syntax is handled below, in + cp_parser_single_declaration. */ decl = cp_parser_concept_definition (parser); else { @@ -40443,12 +40449,7 @@ 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 - /* 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 (!first || nested != 2) { if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) cp_lexer_consume_token (parser->lexer); @@ -40881,9 +40882,7 @@ 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) + 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); @@ -41004,7 +41003,6 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc) enum tree_code code = ERROR_MARK, opcode = NOP_EXPR; enum omp_memory_order memory_order = OMP_MEMORY_ORDER_UNSPECIFIED; bool structured_block = false; - bool first = true; tree clauses = NULL_TREE; bool capture = false; bool compare = false; @@ -41015,14 +41013,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)) { - /* 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) + 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); - first = false; - if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { tree id = cp_lexer_peek_token (parser->lexer)->u.value; @@ -41976,11 +41970,9 @@ cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok) tree clause = NULL_TREE; enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID; - 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)) + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) cp_lexer_consume_token (parser->lexer); + location_t c_loc = cp_lexer_peek_token (parser->lexer)->location; if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { tree id = cp_lexer_peek_token (parser->lexer)->u.value; @@ -42063,9 +42055,7 @@ 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) + 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); if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) @@ -42790,8 +42780,7 @@ 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)) + if (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)) @@ -43593,9 +43582,7 @@ cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok, location_t loc = pragma_tok->location; int n = 1; - /* 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)) + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) n = 2; if (cp_lexer_nth_token_is (parser->lexer, n, CPP_NAME)) @@ -45949,7 +45936,6 @@ static void cp_parser_omp_assumption_clauses (cp_parser *parser, cp_token *pragma_tok, bool is_assume) { - bool first = true; bool no_openmp = false; bool no_openmp_routines = false; bool no_parallelism = false; @@ -45965,14 +45951,10 @@ cp_parser_omp_assumption_clauses (cp_parser *parser, cp_token *pragma_tok, 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) + 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); - first = false; - if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME)) break; @@ -46209,9 +46191,7 @@ 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) + 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); @@ -46287,11 +46267,6 @@ 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); @@ -46549,9 +46524,7 @@ cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok) int device_type = 0; bool only_device_type = true; 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_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, @@ -46801,9 +46774,7 @@ 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) + 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); @@ -47235,20 +47206,15 @@ cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok, static bool cp_parser_omp_requires (cp_parser *parser, cp_token *pragma_tok) { - bool first = true; enum omp_requires new_req = (enum omp_requires) 0; 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) + 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); - first = false; - if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { tree id = cp_lexer_peek_token (parser->lexer)->u.value; @@ -47402,20 +47368,15 @@ cp_parser_omp_error (cp_parser *parser, cp_token *pragma_tok, 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) + 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); - first = false; - if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME)) break; diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 51bfbbc..c3fc56a 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -19866,21 +19866,13 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (type == error_mark_node) return error_mark_node; - if (LAMBDA_EXPR_EXTRA_SCOPE (t) == NULL_TREE) - { - /* A lambda in a default argument outside a class gets no - LAMBDA_EXPR_EXTRA_SCOPE, as specified by the ABI. But - tsubst_default_argument calls start_lambda_scope, so we need to - specifically ignore it here, and use the global scope. */ - record_null_lambda_scope (r); - - /* If we're pushed into another scope (PR105652), fix it. */ - if (TYPE_NAMESPACE_SCOPE_P (TREE_TYPE (t))) - TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_NAME (type)) - = TYPE_CONTEXT (TREE_TYPE (t)); - } - else + if (LAMBDA_EXPR_EXTRA_SCOPE (t)) record_lambda_scope (r); + else if (TYPE_NAMESPACE_SCOPE_P (TREE_TYPE (t))) + /* If we're pushed into another scope (PR105652), fix it. */ + TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_NAME (type)) + = TYPE_CONTEXT (TREE_TYPE (t)); + record_lambda_scope_discriminator (r); /* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set. */ determine_visibility (TYPE_NAME (type)); @@ -19911,29 +19903,18 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) fntype = build_memfn_type (fntype, type, type_memfn_quals (fntype), type_memfn_rqual (fntype)); - tree fn, tmpl; - if (oldtmpl) + tree inst = (oldtmpl + ? tsubst_template_decl (oldtmpl, args, complain, fntype) + : tsubst_function_decl (oldfn, args, complain, fntype)); + if (inst == error_mark_node) { - tmpl = tsubst_template_decl (oldtmpl, args, complain, fntype); - if (tmpl == error_mark_node) - { - r = error_mark_node; - goto out; - } - fn = DECL_TEMPLATE_RESULT (tmpl); - finish_member_declaration (tmpl); - } - else - { - tmpl = NULL_TREE; - fn = tsubst_function_decl (oldfn, args, complain, fntype); - if (fn == error_mark_node) - { - r = error_mark_node; - goto out; - } - finish_member_declaration (fn); + r = error_mark_node; + goto out; } + finish_member_declaration (inst); + record_lambda_scope_sig_discriminator (r, inst); + + tree fn = oldtmpl ? DECL_TEMPLATE_RESULT (inst) : inst; /* Let finish_function set this. */ DECL_DECLARED_CONSTEXPR_P (fn) = false; diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 36aa9c4..7c5f90b 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -731,7 +731,6 @@ end_maybe_infinite_loop (tree cond) } } - /* Begin a conditional that might contain a declaration. When generating normal code, we want the declaration to appear before the statement containing the conditional. When generating template code, we want the diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index 45348c5..c30bbeb 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -5010,8 +5010,10 @@ const struct attribute_spec cxx_attribute_table[] = { /* { name, min_len, max_len, decl_req, type_req, fn_type_req, affects_type_identity, handler, exclude } */ +#if SUPPORTS_INIT_PRIORITY { "init_priority", 1, 1, true, false, false, false, handle_init_priority_attribute, NULL }, +#endif { "abi_tag", 1, -1, false, false, false, true, handle_abi_tag_attribute, NULL }, { NULL, 0, 0, false, false, false, false, NULL, NULL } @@ -5039,7 +5041,7 @@ const struct attribute_spec std_attribute_table[] = /* Handle an "init_priority" attribute; arguments as in struct attribute_spec.handler. */ -static tree +ATTRIBUTE_UNUSED static tree handle_init_priority_attribute (tree* node, tree name, tree args, @@ -5103,18 +5105,10 @@ handle_init_priority_attribute (tree* node, pri); } - if (SUPPORTS_INIT_PRIORITY) - { - SET_DECL_INIT_PRIORITY (decl, pri); - DECL_HAS_INIT_PRIORITY_P (decl) = 1; - return NULL_TREE; - } - else - { - error ("%qE attribute is not supported on this platform", name); - *no_add_attrs = true; - return NULL_TREE; - } + gcc_assert (SUPPORTS_INIT_PRIORITY); + SET_DECL_INIT_PRIORITY (decl, pri); + DECL_HAS_INIT_PRIORITY_P (decl) = 1; + return NULL_TREE; } /* DECL is being redeclared; the old declaration had the abi tags in OLD, |