aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog147
-rw-r--r--gcc/cp/call.cc38
-rw-r--r--gcc/cp/class.cc1
-rw-r--r--gcc/cp/constexpr.cc39
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/cvt.cc13
-rw-r--r--gcc/cp/decl.cc16
-rw-r--r--gcc/cp/lambda.cc8
-rw-r--r--gcc/cp/module.cc84
-rw-r--r--gcc/cp/name-lookup.cc51
-rw-r--r--gcc/cp/parser.cc86
-rw-r--r--gcc/cp/pt.cc73
-rw-r--r--gcc/cp/semantics.cc1
-rw-r--r--gcc/cp/typeck.cc10
14 files changed, 427 insertions, 142 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b7ea75b7..44b592b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,150 @@
+2025-04-05 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/118249
+ * constexpr.cc (potential_constant_expression_1)
+ <case INDIRECT_REF>: Remove obsolete *this handling.
+
+2025-04-05 Jason Merrill <jason@redhat.com>
+
+ PR c++/118629
+ * name-lookup.cc (pushdecl_outermost_localscope): Look for an
+ sk_block.
+
+2025-04-04 Nathaniel Shead <nathanieloshead@gmail.com>
+
+ PR c++/119564
+ * decl.cc (cp_tree_node_structure): Add TU_LOCAL_ENTITY; fix
+ formatting.
+
+2025-04-04 Nathaniel Shead <nathanieloshead@gmail.com>
+
+ PR c++/119608
+ * module.cc (trees_out::decl_node): Maybe require by-value
+ walking not just when streaming.
+
+2025-04-04 Nathaniel Shead <nathanieloshead@gmail.com>
+
+ PR c++/119462
+ * module.cc (trees_in::is_matching_decl): Propagate exception
+ spec and constexpr to DECL_MAYBE_DELETED; clear if appropriate.
+
+2025-04-04 Jason Merrill <jason@redhat.com>
+
+ PR c++/99546
+ PR c++/113925
+ PR c++/106976
+ PR c++/109961
+ PR c++/117336
+ * lambda.cc (build_lambda_object): Handle fake
+ requires-expr processing_template_decl.
+ * parser.cc (cp_parser_lambda_expression): Likewise.
+
+2025-04-04 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/117849
+ * semantics.cc (finish_id_expression_1): Allow use of constraint
+ variable outside an unevaluated context.
+
+2025-04-03 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/119387
+ * constexpr.cc (p2280_active_p): New.
+ (cxx_eval_constant_expression) <case VAR_DECL>: Use it to
+ restrict P2280 relaxations.
+ <case PARM_DECL>: Likewise.
+
+2025-04-03 Jason Merrill <jason@redhat.com>
+
+ * module.cc (module_state::read_cluster)
+ (post_load_processing): Clear DECL_EXTERNAL if DECL_COMDAT.
+
+2025-04-03 Jason Merrill <jason@redhat.com>
+
+ * call.cc (add_candidates): Re-lookup ne_fns if we move into
+ another namespace.
+
+2025-04-03 Andrew Pinski <quic_apinski@quicinc.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/119563
+ * call.cc (build_list_conv): Fix a typo in loop gathering
+ summary information from subsubconvs.
+
+2025-04-02 Sandra Loosemore <sloosemore@baylibre.com>
+
+ PR middle-end/118965
+ * parser.cc (c_parser_omp_clause_init_modifiers): Adjust
+ error message.
+ (cp_parser_omp_clause_init): Remove code for recognizing clauses
+ without modifiers. Diagnose missing target/targetsync modifier.
+ (cp_finish_omp_declare_variant): Diagnose missing target/targetsync
+ modifier.
+
+2025-04-01 Nathaniel Shead <nathanieloshead@gmail.com>
+
+ PR c++/119551
+ * module.cc (trees_out::write_var_def): Only ignore non-inline
+ variable initializers.
+
+2025-04-01 Nathaniel Shead <nathanieloshead@gmail.com>
+
+ * parser.cc (cp_parser_diagnose_invalid_type_name): Replace
+ fmodules-ts with fmodules.
+ (cp_parser_template_declaration): Likewise.
+
+2025-04-01 Marek Polacek <polacek@redhat.com>
+
+ PR c++/119383
+ * call.cc (build_over_call): Use force_lvalue to ensure op= returns
+ an lvalue.
+ * cp-tree.h (force_lvalue): Declare.
+ * cvt.cc (force_lvalue): New.
+ * typeck.cc (cp_build_indirect_ref_1): Revert r15-8011.
+
+2025-03-31 Jason Merrill <jason@redhat.com>
+
+ PR c++/119401
+ * pt.cc (regenerate_decl_from_template): Don't regenerate if the
+ signature involves a lambda.
+
+2025-03-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/119518
+ * decl.cc (finish_function): Don't set TREE_NOTHROW for
+ functions with "noipa" attribute even when we can prove
+ they can't throw.
+
+2025-03-29 Jason Merrill <jason@redhat.com>
+
+ * decl.cc (duplicate_decls): Don't clobber DECL_MODULE_IMPORT_P with
+ an injected friend.
+ * name-lookup.cc (check_module_override): Look at all reachable
+ decls in decl's originating module.
+
+2025-03-29 Jason Merrill <jason@redhat.com>
+
+ PR c++/64500
+ PR c++/116285
+ * name-lookup.cc (push_to_top_level): Don't try to store_bindings
+ for namespace levels.
+
+2025-03-29 Jakub Jelinek <jakub@redhat.com>
+
+ * name-lookup.cc (maybe_lazily_declare): Fix comment typo,
+ anout -> about.
+
+2025-03-29 Nathaniel Shead <nathanieloshead@gmail.com>
+
+ PR c++/118961
+ * class.cc (copy_fndecl_with_name): Mark clones as non-abstract.
+ * cp-tree.h (setup_explicit_instantiation_definition_linkage):
+ Declare new function.
+ * module.cc (trees_in::read_var_def): Use it.
+ (module_state::read_cluster): Likewise.
+ * pt.cc (setup_explicit_instantiation_definition_linkage): New
+ function.
+ (mark_decl_instantiated): Use it.
+
2025-03-27 Tobias Burnus <tburnus@baylibre.com>
* cp-tree.h (cp_finish_omp_init_prefer_type): Add.
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index c1c8987..6caac89 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -917,7 +917,7 @@ build_list_conv (tree type, tree ctor, int flags, tsubst_flags_t complain)
t->rank = cr_exact;
for (j = 0; j < (unsigned) RAW_DATA_LENGTH (val); ++j)
{
- sub = subsubconvs[i];
+ sub = subsubconvs[j];
if (sub->rank > t->rank)
t->rank = sub->rank;
if (sub->user_conv_p)
@@ -6673,6 +6673,7 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args,
bool check_list_ctor = false;
bool check_converting = false;
unification_kind_t strict;
+ tree ne_context = NULL_TREE;
tree ne_fns = NULL_TREE;
if (!fns)
@@ -6719,6 +6720,7 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args,
tree ne_name = ovl_op_identifier (false, NE_EXPR);
if (DECL_CLASS_SCOPE_P (fn))
{
+ ne_context = DECL_CONTEXT (fn);
ne_fns = lookup_fnfields (TREE_TYPE ((*args)[0]), ne_name,
1, tf_none);
if (ne_fns == error_mark_node || ne_fns == NULL_TREE)
@@ -6728,8 +6730,9 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args,
}
else
{
- tree context = decl_namespace_context (fn);
- ne_fns = lookup_qualified_name (context, ne_name, LOOK_want::NORMAL,
+ ne_context = decl_namespace_context (fn);
+ ne_fns = lookup_qualified_name (ne_context, ne_name,
+ LOOK_want::NORMAL,
/*complain*/false);
if (ne_fns == error_mark_node
|| !is_overloaded_fn (ne_fns))
@@ -6828,8 +6831,26 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args,
/* When considering reversed operator==, if there's a corresponding
operator!= in the same scope, it's not a rewrite target. */
- if (ne_fns)
+ if (ne_context)
{
+ if (TREE_CODE (ne_context) == NAMESPACE_DECL)
+ {
+ /* With argument-dependent lookup, fns can span multiple
+ namespaces; make sure we look in the fn's namespace for a
+ corresponding operator!=. */
+ tree fn_ns = decl_namespace_context (fn);
+ if (fn_ns != ne_context)
+ {
+ ne_context = fn_ns;
+ tree ne_name = ovl_op_identifier (false, NE_EXPR);
+ ne_fns = lookup_qualified_name (ne_context, ne_name,
+ LOOK_want::NORMAL,
+ /*complain*/false);
+ if (ne_fns == error_mark_node
+ || !is_overloaded_fn (ne_fns))
+ ne_fns = NULL_TREE;
+ }
+ }
bool found = false;
for (lkp_iterator ne (ne_fns); !found && ne; ++ne)
if (0 && !ne.using_p ()
@@ -10828,10 +10849,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
if (is_really_empty_class (type, /*ignore_vptr*/true))
{
/* Avoid copying empty classes, but ensure op= returns an lvalue even
- if the object argument isn't one. This isn't needed in other cases
- since MODIFY_EXPR is always considered an lvalue. */
- to = cp_build_addr_expr (to, tf_none);
- to = cp_build_indirect_ref (input_location, to, RO_ARROW, complain);
+ if the object argument isn't one. */
+ to = force_lvalue (to, complain);
val = build2 (COMPOUND_EXPR, type, arg, to);
suppress_warning (val, OPT_Wunused);
}
@@ -10852,6 +10871,9 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
tree array_type, alias_set;
arg2 = TYPE_SIZE_UNIT (as_base);
+ /* Ensure op= returns an lvalue even if the object argument isn't
+ one. */
+ to = force_lvalue (to, complain);
to = cp_stabilize_reference (to);
arg0 = cp_build_addr_expr (to, complain);
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index d5ae69b..2b694b9 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -5169,6 +5169,7 @@ copy_fndecl_with_name (tree fn, tree name, tree_code code,
set_constraints (clone, copy_node (ci));
SET_DECL_ASSEMBLER_NAME (clone, NULL_TREE);
+ DECL_ABSTRACT_P (clone) = false;
/* There's no pending inline data for this function. */
DECL_PENDING_INLINE_INFO (clone) = NULL;
DECL_PENDING_INLINE_P (clone) = 0;
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 4820bcc..37ea65c 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -1294,6 +1294,22 @@ struct constexpr_ctx {
mce_value manifestly_const_eval;
};
+/* True if the constexpr relaxations afforded by P2280R4 for unknown
+ references and objects are in effect. */
+
+static bool
+p2280_active_p (const constexpr_ctx *ctx)
+{
+ if (ctx->manifestly_const_eval != mce_true)
+ /* Disable these relaxations during speculative constexpr folding,
+ as it can significantly increase compile time/memory use
+ (PR119387). */
+ return false;
+
+ /* P2280R4 was accepted as a DR against C++11. */
+ return cxx_dialect >= cxx11;
+}
+
/* Remove T from the global values map, checking for attempts to destroy
a value that has already finished its lifetime. */
@@ -7792,7 +7808,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
r = TARGET_EXPR_INITIAL (r);
if (DECL_P (r)
/* P2280 allows references to unknown. */
- && !(VAR_P (t) && TYPE_REF_P (TREE_TYPE (t))))
+ && !(p2280_active_p (ctx) && VAR_P (t) && TYPE_REF_P (TREE_TYPE (t))))
{
if (!ctx->quiet)
non_const_var_error (loc, r, /*fundef_p*/false);
@@ -7844,9 +7860,9 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
r = build_constructor (TREE_TYPE (t), NULL);
TREE_CONSTANT (r) = true;
}
- else if (TYPE_REF_P (TREE_TYPE (t)))
+ else if (p2280_active_p (ctx) && TYPE_REF_P (TREE_TYPE (t)))
/* P2280 allows references to unknown... */;
- else if (is_this_parameter (t))
+ else if (p2280_active_p (ctx) && is_this_parameter (t))
/* ...as well as the this pointer. */;
else
{
@@ -10263,22 +10279,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
return true;
case INDIRECT_REF:
- {
- tree x = TREE_OPERAND (t, 0);
- STRIP_NOPS (x);
- if (is_this_parameter (x) && !is_capture_proxy (x))
- {
- if (now || !var_in_maybe_constexpr_fn (x))
- {
- if (flags & tf_error)
- constexpr_error (loc, fundef_p, "use of %<this%> in a "
- "constant expression");
- return false;
- }
- return true;
- }
- return RECUR (x, rval);
- }
+ return RECUR (TREE_OPERAND (t, 0), rval);
case STATEMENT_LIST:
for (tree stmt : tsi_range (t))
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f0b4484..927f51b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7079,6 +7079,7 @@ extern tree convert_to_reference (tree, tree, int, int, tree,
tsubst_flags_t);
extern tree convert_from_reference (tree);
extern tree force_rvalue (tree, tsubst_flags_t);
+extern tree force_lvalue (tree, tsubst_flags_t);
extern tree ocp_convert (tree, tree, int, int,
tsubst_flags_t);
extern tree cp_convert (tree, tree, tsubst_flags_t);
@@ -7692,6 +7693,7 @@ extern tree fn_type_unification (tree, tree, tree,
tree, unification_kind_t, int,
struct conversion **,
bool, bool);
+extern void setup_explicit_instantiation_definition_linkage (tree);
extern void mark_decl_instantiated (tree, int);
extern int more_specialized_fn (tree, tree, int);
extern tree type_targs_deducible_from (tree, tree);
diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc
index bd1f147..f663a6d 100644
--- a/gcc/cp/cvt.cc
+++ b/gcc/cp/cvt.cc
@@ -575,6 +575,19 @@ force_rvalue (tree expr, tsubst_flags_t complain)
return expr;
}
+/* Force EXPR to be an lvalue, if it isn't already. */
+
+tree
+force_lvalue (tree expr, tsubst_flags_t complain)
+{
+ if (!lvalue_p (expr))
+ {
+ expr = cp_build_addr_expr (expr, complain);
+ expr = cp_build_indirect_ref (input_location, expr, RO_ARROW, complain);
+ }
+ return expr;
+}
+
/* If EXPR and ORIG are INTEGER_CSTs, return a version of EXPR that has
TREE_OVERFLOW set only if it is set in ORIG. Otherwise, return EXPR
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index a785d5e..4e97093 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -2539,8 +2539,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
}
/* Propagate purviewness and importingness as with
- set_instantiating_module. */
- if (modules_p () && DECL_LANG_SPECIFIC (new_result))
+ set_instantiating_module, unless newdecl is a friend injection. */
+ if (modules_p () && DECL_LANG_SPECIFIC (new_result)
+ && !(TREE_CODE (new_result) == FUNCTION_DECL
+ && DECL_UNIQUE_FRIEND_P (new_result)))
{
if (DECL_MODULE_PURVIEW_P (new_result))
DECL_MODULE_PURVIEW_P (old_result) = true;
@@ -19452,7 +19454,8 @@ finish_function (bool inline_p)
&& !cp_function_chain->can_throw
&& !flag_non_call_exceptions
&& !decl_replaceable_p (fndecl,
- opt_for_fn (fndecl, flag_semantic_interposition)))
+ opt_for_fn (fndecl, flag_semantic_interposition))
+ && !lookup_attribute ("noipa", DECL_ATTRIBUTES (fndecl)))
TREE_NOTHROW (fndecl) = 1;
cleanup:
@@ -19831,14 +19834,14 @@ cp_tree_node_structure (union lang_tree_node * t)
{
switch (TREE_CODE (&t->generic))
{
- case ARGUMENT_PACK_SELECT: return TS_CP_ARGUMENT_PACK_SELECT;
+ case ARGUMENT_PACK_SELECT: return TS_CP_ARGUMENT_PACK_SELECT;
case BASELINK: return TS_CP_BASELINK;
- case CONSTRAINT_INFO: return TS_CP_CONSTRAINT_INFO;
+ case CONSTRAINT_INFO: return TS_CP_CONSTRAINT_INFO;
case DEFERRED_NOEXCEPT: return TS_CP_DEFERRED_NOEXCEPT;
case DEFERRED_PARSE: return TS_CP_DEFERRED_PARSE;
case IDENTIFIER_NODE: return TS_CP_IDENTIFIER;
case LAMBDA_EXPR: return TS_CP_LAMBDA_EXPR;
- case BINDING_VECTOR: return TS_CP_BINDING_VECTOR;
+ case BINDING_VECTOR: return TS_CP_BINDING_VECTOR;
case OVERLOAD: return TS_CP_OVERLOAD;
case PTRMEM_CST: return TS_CP_PTRMEM;
case STATIC_ASSERT: return TS_CP_STATIC_ASSERT;
@@ -19846,6 +19849,7 @@ cp_tree_node_structure (union lang_tree_node * t)
case TEMPLATE_INFO: return TS_CP_TEMPLATE_INFO;
case TEMPLATE_PARM_INDEX: return TS_CP_TPI;
case TRAIT_EXPR: return TS_CP_TRAIT_EXPR;
+ case TU_LOCAL_ENTITY: return TS_CP_TU_LOCAL_ENTITY;
case USERDEF_LITERAL: return TS_CP_USERDEF_LITERAL;
default: return TS_CP_GENERIC;
}
diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index ed70bb0..f0a54b6 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -59,7 +59,13 @@ build_lambda_object (tree lambda_expr)
vec<constructor_elt, va_gc> *elts = NULL;
tree node, expr, type;
- if (processing_template_decl || lambda_expr == error_mark_node)
+ if (processing_template_decl && !in_template_context
+ && current_binding_level->requires_expression)
+ /* As in cp_parser_lambda_expression, don't get confused by
+ cp_parser_requires_expression setting processing_template_decl. In that
+ case we want to return the result of finish_compound_literal, to avoid
+ tsubst_lambda_expr. */;
+ else if (processing_template_decl || lambda_expr == error_mark_node)
return lambda_expr;
/* Make sure any error messages refer to the lambda-introducer. */
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 214fb91..37fab5b 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -9004,25 +9004,28 @@ trees_out::decl_node (tree decl, walk_kind ref)
if (streaming_p ())
i (tt_parm);
tree_node (DECL_CONTEXT (decl));
- if (streaming_p ())
- {
- /* That must have put this in the map. */
- walk_kind ref = ref_node (decl);
- if (ref != WK_none)
- // FIXME:OPTIMIZATION We can wander into bits of the
- // template this was instantiated from. For instance
- // deferred noexcept and default parms. Currently we'll
- // end up cloning those bits of tree. It would be nice
- // to reference those specific nodes. I think putting
- // those things in the map when we reference their
- // template by name. See the note in add_indirects.
- return true;
- dump (dumper::TREE)
- && dump ("Wrote %s reference %N",
- TREE_CODE (decl) == PARM_DECL ? "parameter" : "result",
- decl);
- }
+ /* That must have put this in the map. */
+ walk_kind ref = ref_node (decl);
+ if (ref != WK_none)
+ // FIXME:OPTIMIZATION We can wander into bits of the
+ // template this was instantiated from, for instance
+ // deferred noexcept and default parms, or references
+ // to parms from earlier forward-decls (PR c++/119608).
+ //
+ // Currently we'll end up cloning those bits of tree.
+ // It would be nice to reference those specific nodes.
+ // I think putting those things in the map when we
+ // reference their template by name.
+ //
+ // See the note in add_indirects.
+ return true;
+
+ if (streaming_p ())
+ dump (dumper::TREE)
+ && dump ("Wrote %s reference %N",
+ TREE_CODE (decl) == PARM_DECL ? "parameter" : "result",
+ decl);
}
return false;
@@ -12122,7 +12125,7 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef)
instantiate it in the middle of loading. */
tree e_spec = TYPE_RAISES_EXCEPTIONS (e_type);
tree d_spec = TYPE_RAISES_EXCEPTIONS (d_type);
- if (DEFERRED_NOEXCEPT_SPEC_P (e_spec))
+ if (DECL_MAYBE_DELETED (e_inner) || DEFERRED_NOEXCEPT_SPEC_P (e_spec))
{
if (!DEFERRED_NOEXCEPT_SPEC_P (d_spec)
|| (UNEVALUATED_NOEXCEPT_SPEC_P (e_spec)
@@ -12161,6 +12164,20 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef)
else if (type_uses_auto (d_ret)
&& !same_type_p (TREE_TYPE (d_type), TREE_TYPE (e_type)))
goto mismatch;
+
+ /* Similarly if EXISTING has undeduced constexpr, but DECL's
+ is already deduced. */
+ if (DECL_MAYBE_DELETED (e_inner) && !DECL_MAYBE_DELETED (d_inner)
+ && DECL_DECLARED_CONSTEXPR_P (d_inner))
+ DECL_DECLARED_CONSTEXPR_P (e_inner) = true;
+ else if (DECL_DECLARED_CONSTEXPR_P (e_inner)
+ != DECL_DECLARED_CONSTEXPR_P (d_inner))
+ goto mismatch;
+
+ /* Don't synthesize a defaulted function if we're importing one
+ we've already determined. */
+ if (!DECL_MAYBE_DELETED (d_inner))
+ DECL_MAYBE_DELETED (e_inner) = false;
}
else if (is_typedef)
{
@@ -12679,9 +12696,10 @@ trees_in::read_function_def (tree decl, tree maybe_template)
void
trees_out::write_var_def (tree decl)
{
- /* The initializer of a variable or variable template is ignored for
- determining exposures. */
- auto ovr = make_temp_override (dep_hash->ignore_tu_local, VAR_P (decl));
+ /* The initializer of a non-inline variable or variable template is
+ ignored for determining exposures. */
+ auto ovr = make_temp_override (dep_hash->ignore_tu_local,
+ VAR_P (decl) && !DECL_INLINE_VAR_P (decl));
tree init = DECL_INITIAL (decl);
tree_node (init);
@@ -12737,6 +12755,9 @@ trees_in::read_var_def (tree decl, tree maybe_template)
if (maybe_dup && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (maybe_dup))
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true;
tentative_decl_linkage (decl);
+ if (DECL_EXPLICIT_INSTANTIATION (decl)
+ && !DECL_EXTERNAL (decl))
+ setup_explicit_instantiation_definition_linkage (decl);
if (DECL_IMPLICIT_INSTANTIATION (decl)
|| (DECL_EXPLICIT_INSTANTIATION (decl)
&& !DECL_EXTERNAL (decl))
@@ -16657,6 +16678,12 @@ module_state::read_cluster (unsigned snum)
cfun->language->returns_abnormally = pdata.returns_abnormally;
cfun->language->infinite_loop = pdata.infinite_loop;
+ /* Make sure we emit explicit instantiations.
+ FIXME do we want to do this in expand_or_defer_fn instead? */
+ if (DECL_EXPLICIT_INSTANTIATION (decl)
+ && !DECL_EXTERNAL (decl))
+ setup_explicit_instantiation_definition_linkage (decl);
+
if (abstract)
;
else if (DECL_MAYBE_IN_CHARGE_CDTOR_P (decl))
@@ -16669,6 +16696,15 @@ module_state::read_cluster (unsigned snum)
#endif
cfun->returns_struct = aggr;
expand_or_defer_fn (decl);
+
+ /* If we first see this function after at_eof, it doesn't get
+ note_vague_linkage_fn from tentative_decl_linkage, so the loop in
+ c_parse_final_cleanups won't consider it. But with DECL_COMDAT we
+ can just clear DECL_EXTERNAL and let cgraph decide.
+ FIXME handle this outside module.cc after GCC 15. */
+ if (at_eof && DECL_COMDAT (decl) && DECL_EXTERNAL (decl)
+ && DECL_NOT_REALLY_EXTERN (decl))
+ DECL_EXTERNAL (decl) = false;
}
}
@@ -19149,6 +19185,10 @@ post_load_processing ()
gcc_checking_assert (DECL_MAYBE_IN_CHARGE_CDTOR_P (decl));
expand_or_defer_fn (decl);
+ /* As in module_state::read_cluster. */
+ if (at_eof && DECL_COMDAT (decl) && DECL_EXTERNAL (decl)
+ && DECL_NOT_REALLY_EXTERN (decl))
+ DECL_EXTERNAL (decl) = false;
}
cfun = old_cfun;
diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index 7f1ee86..1cd982e 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -2012,8 +2012,8 @@ get_class_binding_direct (tree klass, tree name, bool want_type)
static void
maybe_lazily_declare (tree klass, tree name)
{
- /* See big comment anout module_state::write_pendings regarding adding a check
- bit. */
+ /* See big comment about module_state::write_pendings regarding adding
+ a check bit. */
if (modules_p ())
lazy_load_pendings (TYPE_NAME (klass));
@@ -3777,6 +3777,10 @@ check_module_override (tree decl, tree mvec, bool hiding,
any reachable declaration, so we should check for overriding here too. */
bool any_reachable = deduction_guide_p (decl);
+ /* DECL might have an originating module if it's an instantiation of a
+ friend; we want to look at all reachable decls in that module. */
+ unsigned decl_mod = get_originating_module (decl);
+
if (BINDING_VECTOR_SLOTS_PER_CLUSTER == BINDING_SLOTS_FIXED)
{
cluster++;
@@ -3789,18 +3793,15 @@ check_module_override (tree decl, tree mvec, bool hiding,
/* Are we importing this module? */
if (cluster->indices[jx].span != 1)
continue;
- if (!cluster->indices[jx].base)
+ unsigned cluster_mod = cluster->indices[jx].base;
+ if (!cluster_mod)
continue;
- if (!any_reachable
- && !bitmap_bit_p (imports, cluster->indices[jx].base))
+ bool c_any_reachable = (any_reachable || cluster_mod == decl_mod);
+ if (!c_any_reachable && !bitmap_bit_p (imports, cluster_mod))
continue;
/* Is it loaded? */
if (cluster->slots[jx].is_lazy ())
- {
- gcc_assert (cluster->indices[jx].span == 1);
- lazy_load_binding (cluster->indices[jx].base,
- scope, name, &cluster->slots[jx]);
- }
+ lazy_load_binding (cluster_mod, scope, name, &cluster->slots[jx]);
tree bind = cluster->slots[jx];
if (!bind)
/* Errors could cause there to be nothing. */
@@ -3812,7 +3813,7 @@ check_module_override (tree decl, tree mvec, bool hiding,
/* If there was a matching STAT_TYPE here then xref_tag
should have found it, but we need to check anyway because
a conflicting using-declaration may exist. */
- if (any_reachable)
+ if (c_any_reachable)
{
type = STAT_TYPE (bind);
bind = STAT_DECL (bind);
@@ -5203,9 +5204,11 @@ pushdecl_outermost_localscope (tree x)
cp_binding_level *b = NULL;
auto_cond_timevar tv (TV_NAME_LOOKUP);
- /* Find the scope just inside the function parms. */
- for (cp_binding_level *n = current_binding_level;
- n->kind != sk_function_parms; n = b->level_chain)
+ /* Find the block scope just inside the function parms. */
+ cp_binding_level *n = current_binding_level;
+ while (n && n->kind != sk_block)
+ n = n->level_chain;
+ for (; n && n->kind != sk_function_parms; n = b->level_chain)
b = n;
return b ? do_pushdecl_with_scope (x, b) : error_mark_node;
@@ -8675,6 +8678,9 @@ store_class_bindings (vec<cp_class_binding, va_gc> *names,
static GTY((deletable)) struct saved_scope *free_saved_scope;
+/* Temporarily make the current scope the global namespace, saving away
+ the current scope for pop_from_top_level. */
+
void
push_to_top_level (void)
{
@@ -8716,18 +8722,19 @@ push_to_top_level (void)
store_class_bindings (previous_class_level->class_shadowed,
&s->old_bindings);
- /* Have to include the global scope, because class-scope decls
- aren't listed anywhere useful. */
+ /* Save and clear any IDENTIFIER_BINDING from local scopes. */
for (; b; b = b->level_chain)
{
tree t;
- /* Template IDs are inserted into the global level. If they were
- inserted into namespace level, finish_file wouldn't find them
- when doing pending instantiations. Therefore, don't stop at
- namespace level, but continue until :: . */
- if (global_scope_p (b))
- break;
+ /* We don't need to consider namespace scopes, they don't affect
+ IDENTIFIER_BINDING. */
+ if (b->kind == sk_namespace)
+ {
+ /* Jump straight to '::'. */
+ b = NAMESPACE_LEVEL (global_namespace);
+ break;
+ }
store_bindings (b->names, &s->old_bindings);
/* We also need to check class_shadowed to save class-level type
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 88e722d..812a7c5 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -3901,10 +3901,10 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
inform (location, "%qE is not recognized as a module control-line",
id);
else if (cxx_dialect < cxx20)
- inform (location, "C++20 %qE only available with %<-fmodules-ts%>",
+ inform (location, "C++20 %qE only available with %<-fmodules%>",
id);
else
- inform (location, "C++20 %qE only available with %<-fmodules-ts%>"
+ inform (location, "C++20 %qE only available with %<-fmodules%>"
", which is not yet enabled with %<-std=c++20%>", id);
}
else if (cxx_dialect < cxx11
@@ -11736,21 +11736,34 @@ cp_parser_lambda_expression (cp_parser* parser)
if (cp_parser_error_occurred (parser))
return error_mark_node;
- type = begin_lambda_type (lambda_expr);
- if (type == error_mark_node)
- return error_mark_node;
+ {
+ /* OK, this is a bit tricksy. cp_parser_requires_expression sets
+ processing_template_decl to make checking more normal, but that confuses
+ lambda parsing terribly. In non-template context, we want to parse the
+ lambda once and not tsubst_lambda_expr. So in that case, clear
+ processing_template_decl now, and restore it before the call to
+ build_lambda_object; that way we end up with what looks like a templatey
+ functional cast to the closure type, which is suitable for the
+ requires-expression tsubst_expr. This is PR99546 and friends. */
+ processing_template_decl_sentinel ptds (/*reset*/false);
+ if (processing_template_decl && !in_template_context
+ && current_binding_level->requires_expression)
+ processing_template_decl = 0;
+
+ type = begin_lambda_type (lambda_expr);
+ if (type == error_mark_node)
+ return error_mark_node;
- record_lambda_scope (lambda_expr);
- record_lambda_scope_discriminator (lambda_expr);
+ 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));
+ /* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set. */
+ determine_visibility (TYPE_NAME (type));
- /* Now that we've started the type, add the capture fields for any
- explicit captures. */
- register_capture_members (LAMBDA_EXPR_CAPTURE_LIST (lambda_expr));
+ /* Now that we've started the type, add the capture fields for any
+ explicit captures. */
+ register_capture_members (LAMBDA_EXPR_CAPTURE_LIST (lambda_expr));
- {
/* Inside the class, surrounding template-parameter-lists do not apply. */
unsigned int saved_num_template_parameter_lists
= parser->num_template_parameter_lists;
@@ -18845,7 +18858,7 @@ cp_parser_template_declaration (cp_parser* parser, bool member_p)
else if (cxx_dialect < cxx20)
warning (0, "keyword %<export%> is deprecated, and is ignored");
else
- warning (0, "keyword %<export%> is enabled with %<-fmodules-ts%>");
+ warning (0, "keyword %<export%> is enabled with %<-fmodules%>");
}
cp_parser_template_declaration_after_export (parser, member_p);
@@ -43121,8 +43134,8 @@ cp_parser_omp_clause_init_modifiers (cp_parser *parser, bool *target,
while (true);
fail:
- cp_parser_error (parser, "%<init%> clause with modifier other than "
- "%<prefer_type%>, %<target%> or %<targetsync%>");
+ cp_parser_error (parser,
+ "expected %<prefer_type%>, %<target%>, or %<targetsync%>");
return false;
}
@@ -43140,39 +43153,14 @@ cp_parser_omp_clause_init (cp_parser *parser, tree list)
if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
return list;
- unsigned raw_pos = 1;
- while (cp_lexer_peek_nth_token (parser->lexer, raw_pos)->type == CPP_NAME)
- {
- raw_pos++;
- if (cp_lexer_peek_nth_token (parser->lexer, raw_pos)->type
- == CPP_OPEN_PAREN)
- {
- unsigned n = cp_parser_skip_balanced_tokens (parser, raw_pos);
- if (n == raw_pos)
- {
- raw_pos = 0;
- break;
- }
- raw_pos = n;
- }
- if (cp_lexer_peek_nth_token (parser->lexer, raw_pos)->type == CPP_COLON)
- break;
- if (cp_lexer_peek_nth_token (parser->lexer, raw_pos)->type != CPP_COMMA)
- {
- raw_pos = 0;
- break;
- }
- raw_pos++;
- }
-
bool target = false;
bool targetsync = false;
tree prefer_type_tree = NULL_TREE;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
- if (raw_pos > 1
- && (!cp_parser_omp_clause_init_modifiers (parser, &target, &targetsync,
- &prefer_type_tree)
- || !cp_parser_require (parser, CPP_COLON, RT_COLON)))
+ if (!cp_parser_omp_clause_init_modifiers (parser, &target, &targetsync,
+ &prefer_type_tree)
+ || !cp_parser_require (parser, CPP_COLON, RT_COLON))
{
if (prefer_type_tree == error_mark_node)
return error_mark_node;
@@ -43182,6 +43170,10 @@ cp_parser_omp_clause_init (cp_parser *parser, tree list)
return list;
}
+ if (!target && !targetsync)
+ error_at (loc,
+ "missing required %<target%> and/or %<targetsync%> modifier");
+
tree nl = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_INIT, list,
NULL, false);
for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
@@ -50581,6 +50573,10 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok,
&targetsync,
&prefer_type_tree))
goto fail;
+ if (!target && !targetsync)
+ error_at (loc,
+ "missing required %<target%> and/or "
+ "%<targetsync%> modifier");
tree t = build_tree_list (target ? boolean_true_node
: boolean_false_node,
targetsync ? boolean_true_node
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 1f5ab4e..95b89f12 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -17741,13 +17741,37 @@ maybe_dependent_member_ref (tree t, tree args, tsubst_flags_t complain,
if (TYPE_P (t))
{
+ bool stripped = false;
if (typedef_variant_p (t))
- t = strip_typedefs (t);
- tree decl = TYPE_NAME (t);
+ {
+ /* Since this transformation may undesirably turn a deduced context
+ into a non-deduced one, we'd rather strip typedefs than perform
+ the transformation. */
+ tree u = strip_typedefs (t);
+ if (u != t)
+ {
+ stripped = true;
+ t = u;
+ }
+ }
+ decl = TYPE_NAME (t);
if (decl)
decl = maybe_dependent_member_ref (decl, args, complain, in_decl);
if (!decl)
- return NULL_TREE;
+ {
+ if (stripped)
+ /* The original type was an alias from the current instantiation
+ which we stripped to something outside it. At this point we
+ need to commit to using the stripped type rather than deferring
+ to the caller (which would use the original type), to ensure
+ eligible bits of the stripped type get transformed. */
+ return tsubst (t, args, complain, in_decl);
+ else
+ /* The original type wasn't a typedef, and we decided it doesn't
+ need rewriting, so just let the caller (tsubst) substitute it
+ normally. */
+ return NULL_TREE;
+ }
return cp_build_qualified_type (TREE_TYPE (decl), cp_type_quals (t),
complain);
}
@@ -17765,7 +17789,8 @@ maybe_dependent_member_ref (tree t, tree args, tsubst_flags_t complain,
if (TREE_CODE (t) == TYPE_DECL)
{
- if (TREE_CODE (TREE_TYPE (t)) == TYPENAME_TYPE
+ if (!is_typedef_decl (t)
+ && TREE_CODE (TREE_TYPE (t)) == TYPENAME_TYPE
&& TYPE_NAME (TREE_TYPE (t)) == t)
/* The TYPE_DECL for a typename has DECL_CONTEXT of the typename
scope, but it doesn't need to be rewritten again. */
@@ -25968,6 +25993,23 @@ mark_definable (tree decl)
DECL_NOT_REALLY_EXTERN (clone) = 1;
}
+/* DECL is an explicit instantiation definition, ensure that it will
+ be written out here and that it won't clash with other instantiations
+ in other translation units. */
+
+void
+setup_explicit_instantiation_definition_linkage (tree decl)
+{
+ mark_definable (decl);
+ mark_needed (decl);
+ /* Always make artificials weak. */
+ if (DECL_ARTIFICIAL (decl) && flag_weak)
+ comdat_linkage (decl);
+ /* We also want to put explicit instantiations in linkonce sections. */
+ else if (TREE_PUBLIC (decl))
+ maybe_make_one_only (decl);
+}
+
/* Called if RESULT is explicitly instantiated, or is a member of an
explicitly instantiated class. */
@@ -26005,16 +26047,8 @@ mark_decl_instantiated (tree result, int extern_p)
}
else
{
- mark_definable (result);
- mark_needed (result);
set_instantiating_module (result);
- /* Always make artificials weak. */
- if (DECL_ARTIFICIAL (result) && flag_weak)
- comdat_linkage (result);
- /* For WIN32 we also want to put explicit instantiations in
- linkonce sections. */
- else if (TREE_PUBLIC (result))
- maybe_make_one_only (result);
+ setup_explicit_instantiation_definition_linkage (result);
if (TREE_CODE (result) == FUNCTION_DECL
&& DECL_TEMPLATE_INSTANTIATED (result))
/* If the function has already been instantiated, clear DECL_EXTERNAL,
@@ -27229,6 +27263,19 @@ regenerate_decl_from_template (tree decl, tree tmpl, tree args)
if (DECL_UNIQUE_FRIEND_P (decl))
goto done;
+ /* A template with a lambda in the signature also changes type if
+ regenerated (PR119401). */
+ walk_tree_fn find_lambda
+ = [](tree *tp, int *, void *)
+ {
+ if (TREE_CODE (*tp) == LAMBDA_EXPR)
+ return *tp;
+ return NULL_TREE;
+ };
+ if (cp_walk_tree_without_duplicates
+ (&TREE_TYPE (tmpl), find_lambda, nullptr))
+ goto done;
+
/* Use the source location of the definition. */
DECL_SOURCE_LOCATION (decl) = DECL_SOURCE_LOCATION (tmpl);
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 7d8beb8..a10ef34 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -4755,6 +4755,7 @@ finish_id_expression_1 (tree id_expression,
body, except inside an unevaluated context (i.e. decltype). */
if (TREE_CODE (decl) == PARM_DECL
&& DECL_CONTEXT (decl) == NULL_TREE
+ && !CONSTRAINT_VAR_P (decl)
&& !cp_unevaluated_operand
&& !processing_contract_condition
&& !processing_omp_trait_property_expr)
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index c8e4441..88f8f34 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -3870,13 +3870,11 @@ cp_build_indirect_ref_1 (location_t loc, tree ptr, ref_operator errorstring,
return error_mark_node;
}
else if (do_fold && TREE_CODE (pointer) == ADDR_EXPR
- && same_type_p (t, TREE_TYPE (TREE_OPERAND (pointer, 0)))
- /* Don't let this change the value category. '*&TARGET_EXPR'
- is an lvalue, but folding it into 'TARGET_EXPR' would turn
- it into a prvalue of class type. */
- && lvalue_p (TREE_OPERAND (pointer, 0)))
+ && same_type_p (t, TREE_TYPE (TREE_OPERAND (pointer, 0))))
/* The POINTER was something like `&x'. We simplify `*&x' to
- `x'. */
+ `x'. This can change the value category: '*&TARGET_EXPR'
+ is an lvalue and folding it into 'TARGET_EXPR' turns it into
+ a prvalue of class type. */
return TREE_OPERAND (pointer, 0);
else
{