aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog146
-rw-r--r--gcc/cp/constexpr.cc90
-rw-r--r--gcc/cp/constraint.cc6
-rw-r--r--gcc/cp/cp-gimplify.cc11
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/error.cc59
-rw-r--r--gcc/cp/lambda.cc24
-rw-r--r--gcc/cp/mangle.cc6
-rw-r--r--gcc/cp/module.cc60
-rw-r--r--gcc/cp/pt.cc36
10 files changed, 352 insertions, 87 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 44b592b..aa2f076 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,149 @@
+2025-04-15 Nathaniel Shead <nathanieloshead@gmail.com>
+
+ PR c++/119755
+ * lambda.cc (prune_lambda_captures): Remove pruned capture from
+ function's BLOCK_VARS and BIND_EXPR_VARS.
+
+2025-04-15 Jason Merrill <jason@redhat.com>
+
+ PR c++/111075
+ * constexpr.cc (cxx_eval_call_expression): Allow trivial
+ call from a thunk.
+
+2025-04-15 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/119807
+ PR c++/112288
+ * pt.cc (tsubst_friend_function): Skip remapping an
+ existing specialization if it doesn't match the shape of
+ the new friend definition.
+
+2025-04-15 Jason Merrill <jason@redhat.com>
+
+ PR c++/113835
+ * constexpr.cc (cxx_eval_outermost_constant_expr): Bail out early
+ for std::vector(N).
+
+2025-04-14 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/99214
+ * constraint.cc (satisfy_declaration_constraints): Pass the
+ original ARGS to push_tinst_level.
+
+2025-04-13 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/115639
+ * constexpr.cc (struct constexpr_call): Add NSDMIs to each
+ field. Replace 'result' data member with 3-element 'results'
+ array and a 'result' accessor function. Remove
+ 'manifestly_const_eval' data member.
+ (constexpr_call_hasher::equal): Adjust after constexpr_call
+ layout change.
+ (cxx_eval_call_expression): Likewise. Define some local
+ variables closer to their first use. Use unknown_type_node
+ instead of NULL_TREE as the "in progress" result. After
+ successully evaluating a call with mce_unknown, also cache the
+ result in the corresponding mce_true and mce_false slots.
+
+2025-04-13 Nathaniel Shead <nathanieloshead@gmail.com>
+
+ * module.cc (trees_in::is_matching_decl): Don't check for
+ mismatches when importing a DECL_MAYBE_DELETED function over one
+ that's already finished.
+
+2025-04-13 Nathaniel Shead <nathanieloshead@gmail.com>
+
+ * module.cc (trees_in::is_matching_decl): Add custom errors for
+ different kinds of mismatches.
+
+2025-04-12 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/116416
+ * constexpr.cc (maybe_constant_init_1): Generalize type of
+ of manifestly_const_eval parameter from bool to mce_value.
+ (maybe_constant_init): Define 3-parameter version taking a
+ manifestly_const_eval instead of bool parameter.
+ (cxx_constant_init): Adjust.
+ * cp-gimplify.cc (cp_fold_r) <case TARGET_EXPR>: Pass mce_false
+ to maybe_constant_init during prvalue folding if ff_mce_false is
+ set.
+ * cp-tree.h (maybe_constant_init): Declare new overload.
+
+2025-04-11 Jason Merrill <jason@redhat.com>
+
+ PR c++/114970
+ * cp-gimplify.cc (cp_build_init_expr_for_ctor): Suppress warnings on
+ return_this COMPOUND_EXPR.
+
+2025-04-10 Jason Merrill <jason@redhat.com>
+
+ PR c++/119345
+ * pt.cc (add_extra_args): Also register a specialization
+ of the captured variable.
+
+2025-04-10 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/119687
+ * pt.cc (alias_ctad_tweaks): Use lkp_range / lkp_iterator
+ instead of ovl_iterator.
+
+2025-04-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR translation/119684
+ * error.cc (cp_print_error_function): Use G_ instead of _ for
+ pp_printf arguments.
+ (function_category): Use G_ instead of _.
+ (print_instantiation_full_context): Use G_ instead of _ in pp_verbatim
+ arguments.
+ (print_location): Likewise.
+ (print_instantiation_partial_context): Likewise.
+ (maybe_print_constexpr_context): Likewise.
+ (print_constrained_decl_info): Use G_() around pp_verbatim argument.
+ (print_concept_check_info): Likewise.
+ (print_constraint_context_head): Likewise.
+ (print_requires_expression_info): Likewise. Merge separate pp_verbatim
+ "in requirements " and "with " into one with conditional messages.
+
+2025-04-10 Jason Merrill <jason@redhat.com>
+
+ PR c++/119175
+ * mangle.cc (decl_mangling_context): Look through lambda type.
+
+2025-04-09 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/119574
+ * pt.cc (add_extra_args): Remove checking assert.
+
+2025-04-09 Jason Merrill <jason@redhat.com>
+
+ PR c++/118698
+ * constraint.cc (struct norm_info): Add tf_partial.
+ * pt.cc (any_template_parm_r): Handle LAMBDA_EXPR_EXTRA_ARGS.
+
+2025-04-08 Jason Merrill <jason@redhat.com>
+
+ PR c++/117530
+ * pt.cc (instantiate_template): Check retrieve_specialization after
+ tsubst.
+
+2025-04-07 Jason Merrill <jason@redhat.com>
+
+ PR c++/119652
+ * constexpr.cc (cxx_eval_outermost_constant_expr): Also don't add a
+ TARGET_EXPR around AGGR_INIT_EXPR.
+
+2025-04-06 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/118626
+ * pt.cc (maybe_dependent_member_ref): Restrict TYPENAME_TYPE
+ shortcut to non-typedef TYPE_DECL.
+
+2025-04-06 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/118626
+ * pt.cc (maybe_dependent_member_ref): Substitute and return the
+ stripped type if we decided to not rewrite it directly.
+
2025-04-05 Patrick Palka <ppalka@redhat.com>
PR c++/118249
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 37ea65c..4346b29 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -1119,20 +1119,22 @@ explain_invalid_constexpr_fn (tree fun)
struct GTY((for_user)) constexpr_call {
/* Description of the constexpr function definition. */
- constexpr_fundef *fundef;
+ constexpr_fundef *fundef = nullptr;
/* Parameter bindings environment. A TREE_VEC of arguments. */
- tree bindings;
- /* Result of the call.
- NULL means the call is being evaluated.
+ tree bindings = NULL_TREE;
+ /* Result of the call, indexed by the value of
+ constexpr_ctx::manifestly_const_eval.
+ unknown_type_node means the call is being evaluated.
error_mark_node means that the evaluation was erroneous or otherwise
uncacheable (e.g. because it depends on the caller).
Otherwise, the actual value of the call. */
- tree result;
+ tree results[3] = { NULL_TREE, NULL_TREE, NULL_TREE };
/* The hash of this call; we remember it here to avoid having to
recalculate it when expanding the hash table. */
- hashval_t hash;
- /* The value of constexpr_ctx::manifestly_const_eval. */
- enum mce_value manifestly_const_eval;
+ hashval_t hash = 0;
+
+ /* The result slot corresponding to the given mce_value. */
+ tree& result (mce_value mce) { return results[1 + int(mce)]; }
};
struct constexpr_call_hasher : ggc_ptr_hash<constexpr_call>
@@ -1427,8 +1429,6 @@ constexpr_call_hasher::equal (constexpr_call *lhs, constexpr_call *rhs)
return true;
if (lhs->hash != rhs->hash)
return false;
- if (lhs->manifestly_const_eval != rhs->manifestly_const_eval)
- return false;
if (!constexpr_fundef_hasher::equal (lhs->fundef, rhs->fundef))
return false;
return cp_tree_equal (lhs->bindings, rhs->bindings);
@@ -2855,9 +2855,6 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
{
location_t loc = cp_expr_loc_or_input_loc (t);
tree fun = get_function_named_in_call (t);
- constexpr_call new_call
- = { NULL, NULL, NULL, 0, ctx->manifestly_const_eval };
- int depth_ok;
if (fun == NULL_TREE)
return cxx_eval_internal_function (ctx, t, lval,
@@ -3099,7 +3096,6 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
if (DECL_IMMEDIATE_FUNCTION_P (fun))
{
new_ctx.manifestly_const_eval = mce_true;
- new_call.manifestly_const_eval = mce_true;
ctx = &new_ctx;
}
@@ -3107,11 +3103,15 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
we can only get a trivial function here with -fno-elide-constructors. */
gcc_checking_assert (!trivial_fn_p (fun)
|| !flag_elide_constructors
+ /* Or it's a call from maybe_thunk_body (111075). */
+ || (TREE_CODE (t) == CALL_EXPR ? CALL_FROM_THUNK_P (t)
+ : AGGR_INIT_FROM_THUNK_P (t))
/* We don't elide constructors when processing
a noexcept-expression. */
|| cp_noexcept_operand);
bool non_constant_args = false;
+ constexpr_call new_call;
new_call.bindings
= cxx_bind_parameters_in_call (ctx, t, fun, non_constant_p,
overflow_p, &non_constant_args);
@@ -3185,7 +3185,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
}
}
- depth_ok = push_cx_call_context (t);
+ int depth_ok = push_cx_call_context (t);
/* Remember the object we are constructing or destructing. */
tree new_obj = NULL_TREE;
@@ -3227,8 +3227,6 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
new_call.hash = constexpr_fundef_hasher::hash (new_call.fundef);
new_call.hash
= iterative_hash_template_arg (new_call.bindings, new_call.hash);
- new_call.hash
- = iterative_hash_object (ctx->manifestly_const_eval, new_call.hash);
/* If we have seen this call before, we are done. */
maybe_initialize_constexpr_call_table ();
@@ -3246,22 +3244,23 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
the slot can move during evaluation of the body. */
*slot = entry = ggc_alloc<constexpr_call> ();
*entry = new_call;
+ entry->result (ctx->manifestly_const_eval) = unknown_type_node;
fb.preserve ();
}
}
- /* Calls that are in progress have their result set to NULL, so that we
- can detect circular dependencies. Now that we only cache up to
- constexpr_cache_depth this won't catch circular dependencies that
+ /* Calls that are in progress have their result set to unknown_type_node,
+ so that we can detect circular dependencies. Now that we only cache
+ up to constexpr_cache_depth this won't catch circular dependencies that
start deeper, but they'll hit the recursion or ops limit. */
- else if (entry->result == NULL)
+ else if (entry->result (ctx->manifestly_const_eval) == unknown_type_node)
{
if (!ctx->quiet)
error ("call has circular dependency");
*non_constant_p = true;
- entry->result = result = error_mark_node;
+ entry->result (ctx->manifestly_const_eval) = result = error_mark_node;
}
else
- result = entry->result;
+ result = entry->result (ctx->manifestly_const_eval);
}
if (!depth_ok)
@@ -3482,7 +3481,22 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
else if (!result)
result = void_node;
if (entry)
- entry->result = cacheable ? result : error_mark_node;
+ {
+ entry->result (ctx->manifestly_const_eval)
+ = cacheable ? result : error_mark_node;
+
+ if (result != error_mark_node
+ && ctx->manifestly_const_eval == mce_unknown)
+ {
+ /* Evaluation succeeded and was independent of whether we're in a
+ manifestly constant-evaluated context, so we can also reuse
+ this result when evaluating this call with a fixed context. */
+ if (!entry->result (mce_true))
+ entry->result (mce_true) = entry->result (mce_unknown);
+ if (!entry->result (mce_false))
+ entry->result (mce_false) = entry->result (mce_unknown);
+ }
+ }
}
/* The result of a constexpr function must be completely initialized.
@@ -9116,6 +9130,15 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
tree fndecl = cp_get_callee_fndecl_nofold (x);
if (fndecl && DECL_IMMEDIATE_FUNCTION_P (fndecl))
is_consteval = true;
+ /* Don't try to evaluate a std::vector constructor taking an integer, it
+ will fail in the 'if (heap_var)' block below after doing all the work
+ (c++/113835). This will need adjustment if P3554 is accepted. Note
+ that evaluation of e.g. the vector default constructor can succeed, so
+ we don't shortcut all vector constructors. */
+ if (fndecl && DECL_CONSTRUCTOR_P (fndecl) && allow_non_constant
+ && is_std_class (type, "vector") && call_expr_nargs (x) > 1
+ && TREE_CODE (TREE_TYPE (get_nth_callarg (x, 1))) == INTEGER_TYPE)
+ return t;
}
if (AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type))
{
@@ -9316,7 +9339,8 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
if (TREE_CODE (t) == TARGET_EXPR
&& TARGET_EXPR_INITIAL (t) == r)
return t;
- else if (TREE_CODE (t) == CONSTRUCTOR || TREE_CODE (t) == CALL_EXPR)
+ else if (TREE_CODE (t) == CONSTRUCTOR || TREE_CODE (t) == CALL_EXPR
+ || TREE_CODE (t) == AGGR_INIT_EXPR)
/* Don't add a TARGET_EXPR if our argument didn't have one. */;
else if (TREE_CODE (t) == TARGET_EXPR && TARGET_EXPR_CLEANUP (t))
r = get_target_expr (r);
@@ -9678,7 +9702,7 @@ fold_non_dependent_init (tree t,
static tree
maybe_constant_init_1 (tree t, tree decl, bool allow_non_constant,
- bool manifestly_const_eval)
+ mce_value manifestly_const_eval)
{
if (!t)
return t;
@@ -9708,13 +9732,13 @@ maybe_constant_init_1 (tree t, tree decl, bool allow_non_constant,
bool is_static = (decl && DECL_P (decl)
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)));
if (is_static)
- manifestly_const_eval = true;
+ manifestly_const_eval = mce_true;
- if (cp_unevaluated_operand && !manifestly_const_eval)
+ if (cp_unevaluated_operand && manifestly_const_eval != mce_true)
return fold_to_constant (t);
t = cxx_eval_outermost_constant_expr (t, allow_non_constant, !is_static,
- mce_value (manifestly_const_eval),
+ manifestly_const_eval,
false, decl);
}
if (TREE_CODE (t) == TARGET_EXPR)
@@ -9731,6 +9755,12 @@ maybe_constant_init_1 (tree t, tree decl, bool allow_non_constant,
tree
maybe_constant_init (tree t, tree decl, bool manifestly_const_eval)
{
+ return maybe_constant_init_1 (t, decl, true, mce_value (manifestly_const_eval));
+}
+
+tree
+maybe_constant_init (tree t, tree decl, mce_value manifestly_const_eval)
+{
return maybe_constant_init_1 (t, decl, true, manifestly_const_eval);
}
@@ -9739,7 +9769,7 @@ maybe_constant_init (tree t, tree decl, bool manifestly_const_eval)
tree
cxx_constant_init (tree t, tree decl)
{
- return maybe_constant_init_1 (t, decl, false, true);
+ return maybe_constant_init_1 (t, decl, false, mce_true);
}
#if 0
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index a9caba8..44fb086 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -354,7 +354,7 @@ struct norm_info : subst_info
/* Construct a top-level context for DECL. */
norm_info (tree in_decl, bool diag)
- : subst_info (tf_warning_or_error, in_decl),
+ : subst_info (tf_warning_or_error|tf_partial, in_decl),
generate_diagnostics (diag)
{
if (in_decl)
@@ -2704,6 +2704,8 @@ satisfy_declaration_constraints (tree t, sat_info info)
static tree
satisfy_declaration_constraints (tree t, tree args, sat_info info)
{
+ tree orig_args = args;
+
/* Update the declaration for diagnostics. */
info.in_decl = t;
@@ -2732,7 +2734,7 @@ satisfy_declaration_constraints (tree t, tree args, sat_info info)
tree result = boolean_true_node;
if (tree norm = get_normalized_constraints_from_decl (t, info.noisy ()))
{
- if (!push_tinst_level (t, args))
+ if (!push_tinst_level (t, orig_args))
return result;
tree pattern = DECL_TEMPLATE_RESULT (t);
push_to_top_level ();
diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index 550cea29..d2423fd 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -1199,8 +1199,11 @@ cp_build_init_expr_for_ctor (tree call, tree init)
tree s = build_fold_indirect_ref_loc (loc, a);
init = cp_build_init_expr (s, init);
if (return_this)
- init = build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (call), init,
- fold_convert_loc (loc, TREE_TYPE (call), a));
+ {
+ init = build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (call), init,
+ fold_convert_loc (loc, TREE_TYPE (call), a));
+ suppress_warning (init);
+ }
return init;
}
@@ -1480,7 +1483,9 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data_)
*walk_subtrees = 0;
if (!flag_no_inline)
{
- tree folded = maybe_constant_init (init, TARGET_EXPR_SLOT (stmt));
+ tree folded = maybe_constant_init (init, TARGET_EXPR_SLOT (stmt),
+ (data->flags & ff_mce_false
+ ? mce_false : mce_unknown));
if (folded != init && TREE_CONSTANT (folded))
init = folded;
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 927f51b..55f986e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8837,6 +8837,7 @@ 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, mce_value = mce_unknown);
extern tree maybe_constant_init (tree, tree = NULL_TREE, bool = false);
+extern tree maybe_constant_init (tree, tree, mce_value);
extern tree fold_non_dependent_expr (tree,
tsubst_flags_t = tf_warning_or_error,
bool = false, tree = NULL_TREE);
diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index ec7527e..499eb1b 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -3788,18 +3788,18 @@ cp_print_error_function (diagnostic_text_output_format &text_output,
{
if (text_output.show_column_p () && s.column != 0)
pp_printf (pp,
- _(" inlined from %qD at %r%s:%d:%d%R"),
+ G_(" inlined from %qD at %r%s:%d:%d%R"),
fndecl,
"locus", s.file, s.line, s.column);
else
pp_printf (pp,
- _(" inlined from %qD at %r%s:%d%R"),
+ G_(" inlined from %qD at %r%s:%d%R"),
fndecl,
"locus", s.file, s.line);
}
else
- pp_printf (pp, _(" inlined from %qD"),
+ pp_printf (pp, G_(" inlined from %qD"),
fndecl);
}
}
@@ -3825,22 +3825,22 @@ function_category (tree fn)
&& DECL_FUNCTION_MEMBER_P (fn))
{
if (DECL_STATIC_FUNCTION_P (fn))
- return _("In static member function %qD");
+ return G_("In static member function %qD");
else if (DECL_COPY_CONSTRUCTOR_P (fn))
- return _("In copy constructor %qD");
+ return G_("In copy constructor %qD");
else if (DECL_CONSTRUCTOR_P (fn))
- return _("In constructor %qD");
+ return G_("In constructor %qD");
else if (DECL_DESTRUCTOR_P (fn))
- return _("In destructor %qD");
+ return G_("In destructor %qD");
else if (LAMBDA_FUNCTION_P (fn))
- return _("In lambda function");
+ return G_("In lambda function");
else if (DECL_XOBJ_MEMBER_FUNCTION_P (fn))
- return _("In explicit object member function %qD");
+ return G_("In explicit object member function %qD");
else
- return _("In member function %qD");
+ return G_("In member function %qD");
}
else
- return _("In function %qD");
+ return G_("In function %qD");
}
/* Disable warnings about missing quoting in GCC diagnostics for
@@ -3867,8 +3867,8 @@ print_instantiation_full_context (diagnostic_text_output_format &text_output)
char *indent = text_output.build_indent_prefix (true);
pp_verbatim (text_output.get_printer (),
p->list_p ()
- ? _("%s%s%sIn substitution of %qS:\n")
- : _("%s%s%sIn instantiation of %q#D:\n"),
+ ? G_("%s%s%sIn substitution of %qS:\n")
+ : G_("%s%s%sIn instantiation of %q#D:\n"),
indent,
show_file ? LOCATION_FILE (location) : "",
show_file ? ": " : "",
@@ -3888,10 +3888,10 @@ print_location (diagnostic_text_output_format &text_output,
expanded_location xloc = expand_location (loc);
pretty_printer *const pp = text_output.get_printer ();
if (text_output.show_column_p ())
- pp_verbatim (pp, _("%r%s:%d:%d:%R "),
+ pp_verbatim (pp, G_("%r%s:%d:%d:%R "),
"locus", xloc.file, xloc.line, xloc.column);
else
- pp_verbatim (pp, _("%r%s:%d:%R "),
+ pp_verbatim (pp, G_("%r%s:%d:%R "),
"locus", xloc.file, xloc.line);
}
@@ -3984,22 +3984,22 @@ print_instantiation_partial_context_line (diagnostic_text_output_format &text_ou
if (t->list_p ())
pp_verbatim (pp,
recursive_p
- ? _("recursively required by substitution of %qS\n")
- : _("required by substitution of %qS\n"),
+ ? G_("recursively required by substitution of %qS\n")
+ : G_("required by substitution of %qS\n"),
t->get_node ());
else
pp_verbatim (pp,
recursive_p
- ? _("recursively required from %q#D\n")
- : _("required from %q#D\n"),
+ ? G_("recursively required from %q#D\n")
+ : G_("required from %q#D\n"),
t->get_node ());
}
else
{
pp_verbatim (pp,
recursive_p
- ? _("recursively required from here\n")
- : _("required from here\n"));
+ ? G_("recursively required from here\n")
+ : G_("required from here\n"));
}
}
@@ -4049,8 +4049,8 @@ print_instantiation_partial_context (diagnostic_text_output_format &text_output,
{
auto_context_line sentinel (text_output, loc);
pp_verbatim (text_output.get_printer (),
- _("[ skipping %d instantiation contexts,"
- " use -ftemplate-backtrace-limit=0 to disable ]\n"),
+ G_("[ skipping %d instantiation contexts,"
+ " use -ftemplate-backtrace-limit=0 to disable ]\n"),
skip);
do {
loc = t->locus;
@@ -4101,7 +4101,7 @@ maybe_print_constexpr_context (diagnostic_text_output_format &text_output)
pretty_printer *const pp = text_output.get_printer ();
auto_context_line sentinel (text_output, EXPR_LOCATION (t));
pp_verbatim (pp,
- _("in %<constexpr%> expansion of %qs"),
+ G_("in %<constexpr%> expansion of %qs"),
s);
pp_newline (pp);
}
@@ -4114,7 +4114,7 @@ print_constrained_decl_info (diagnostic_text_output_format &text_output,
{
auto_context_line sentinel (text_output, DECL_SOURCE_LOCATION (decl));
pretty_printer *const pp = text_output.get_printer ();
- pp_verbatim (pp, "required by the constraints of %q#D\n", decl);
+ pp_verbatim (pp, G_("required by the constraints of %q#D\n"), decl);
}
static void
@@ -4129,7 +4129,7 @@ print_concept_check_info (diagnostic_text_output_format &text_output,
cxx_pretty_printer *const pp
= (cxx_pretty_printer *)text_output.get_printer ();
- pp_verbatim (pp, "required for the satisfaction of %qE", expr);
+ pp_verbatim (pp, G_("required for the satisfaction of %qE"), expr);
if (map && map != error_mark_node)
{
tree subst_map = tsubst_parameter_mapping (map, args, tf_none, NULL_TREE);
@@ -4151,7 +4151,7 @@ print_constraint_context_head (diagnostic_text_output_format &text_output,
{
auto_context_line sentinel (text_output, input_location);
pretty_printer *const pp = text_output.get_printer ();
- pp_verbatim (pp, "required for constraint satisfaction\n");
+ pp_verbatim (pp, G_("required for constraint satisfaction\n"));
return NULL_TREE;
}
if (DECL_P (src))
@@ -4180,11 +4180,10 @@ print_requires_expression_info (diagnostic_text_output_format &text_output,
auto_context_line sentinel (text_output, cp_expr_loc_or_input_loc (expr));
cxx_pretty_printer *const pp
= static_cast <cxx_pretty_printer *> (text_output.get_printer ());
- pp_verbatim (pp, "in requirements ");
tree parms = TREE_OPERAND (expr, 0);
- if (parms)
- pp_verbatim (pp, "with ");
+ pp_verbatim (pp, parms ? G_("in requirements with ")
+ : G_("in requirements "));
while (parms)
{
pp_verbatim (pp, "%q#D", parms);
diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index f0a54b6..b2e0ecd 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -1858,6 +1858,13 @@ prune_lambda_captures (tree body)
cp_walk_tree_without_duplicates (&body, mark_const_cap_r, &const_vars);
+ tree bind_expr = expr_single (DECL_SAVED_TREE (lambda_function (lam)));
+ if (bind_expr && TREE_CODE (bind_expr) == MUST_NOT_THROW_EXPR)
+ bind_expr = expr_single (TREE_OPERAND (bind_expr, 0));
+ /* FIXME: We don't currently handle noexcept lambda captures correctly,
+ so bind_expr may not be set; see PR c++/119764. */
+ gcc_assert (!bind_expr || TREE_CODE (bind_expr) == BIND_EXPR);
+
tree *fieldp = &TYPE_FIELDS (LAMBDA_EXPR_CLOSURE (lam));
for (tree *capp = &LAMBDA_EXPR_CAPTURE_LIST (lam); *capp; )
{
@@ -1879,6 +1886,23 @@ prune_lambda_captures (tree body)
fieldp = &DECL_CHAIN (*fieldp);
*fieldp = DECL_CHAIN (*fieldp);
+ /* And out of the bindings for the function. */
+ tree *blockp = &BLOCK_VARS (current_binding_level->blocks);
+ while (*blockp != DECL_EXPR_DECL (**use))
+ blockp = &DECL_CHAIN (*blockp);
+ *blockp = DECL_CHAIN (*blockp);
+
+ /* And maybe out of the vars declared in the containing
+ BIND_EXPR, if it's listed there. */
+ if (bind_expr)
+ {
+ tree *bindp = &BIND_EXPR_VARS (bind_expr);
+ while (*bindp && *bindp != DECL_EXPR_DECL (**use))
+ bindp = &DECL_CHAIN (*bindp);
+ if (*bindp)
+ *bindp = DECL_CHAIN (*bindp);
+ }
+
/* And remove the capture proxy declaration. */
**use = void_node;
continue;
diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index 02129c6..3d5e96b 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -1048,6 +1048,12 @@ decl_mangling_context (tree decl)
tree extra = LAMBDA_TYPE_EXTRA_SCOPE (TREE_TYPE (decl));
if (extra)
return extra;
+ tcontext = CP_DECL_CONTEXT (decl);
+ if (LAMBDA_TYPE_P (tcontext))
+ /* Lambda type context means this lambda appears between the
+ lambda-introducer and the open brace of another lambda (c++/119175).
+ That isn't a real scope; look further into the enclosing scope. */
+ return decl_mangling_context (TYPE_NAME (tcontext));
}
else if (template_type_parameter_p (decl))
/* template type parms have no mangling context. */
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 37fab5b..5ff5c46 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -12090,6 +12090,8 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef)
gcc_checking_assert (TREE_CODE (e_inner) == TREE_CODE (d_inner));
}
+ // FIXME: do more precise errors at point of mismatch
+ const char *mismatch_msg = nullptr;
if (TREE_CODE (d_inner) == FUNCTION_DECL)
{
tree e_ret = fndecl_declared_return_type (existing);
@@ -12099,13 +12101,20 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef)
&& LAMBDA_TYPE_P (DECL_CONTEXT (d_inner)))
/* This has a recursive type that will compare different. */;
else if (!same_type_p (d_ret, e_ret))
- goto mismatch;
+ {
+ mismatch_msg = G_("conflicting type for imported declaration %#qD");
+ goto mismatch;
+ }
tree e_type = TREE_TYPE (e_inner);
tree d_type = TREE_TYPE (d_inner);
if (DECL_EXTERN_C_P (d_inner) != DECL_EXTERN_C_P (e_inner))
- goto mismatch;
+ {
+ mismatch_msg = G_("conflicting language linkage for imported "
+ "declaration %#qD");
+ goto mismatch;
+ }
for (tree e_args = TYPE_ARG_TYPES (e_type),
d_args = TYPE_ARG_TYPES (d_type);
@@ -12113,10 +12122,18 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef)
e_args = TREE_CHAIN (e_args), d_args = TREE_CHAIN (d_args))
{
if (!(e_args && d_args))
- goto mismatch;
+ {
+ mismatch_msg = G_("conflicting argument list for imported "
+ "declaration %#qD");
+ goto mismatch;
+ }
if (!same_type_p (TREE_VALUE (d_args), TREE_VALUE (e_args)))
- goto mismatch;
+ {
+ mismatch_msg = G_("conflicting argument types for imported "
+ "declaration %#qD");
+ goto mismatch;
+ }
}
/* If EXISTING has an undeduced or uninstantiated exception
@@ -12147,9 +12164,14 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef)
}
}
}
- else if (!DEFERRED_NOEXCEPT_SPEC_P (d_spec)
+ else if (!DECL_MAYBE_DELETED (d_inner)
+ && !DEFERRED_NOEXCEPT_SPEC_P (d_spec)
&& !comp_except_specs (d_spec, e_spec, ce_type))
- goto mismatch;
+ {
+ mismatch_msg = G_("conflicting %<noexcept%> specifier for "
+ "imported declaration %#qD");
+ goto mismatch;
+ }
/* Similarly if EXISTING has an undeduced return type, but DECL's
is already deduced. */
@@ -12163,16 +12185,26 @@ 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;
+ {
+ mismatch_msg = G_("conflicting deduced return type for "
+ "imported declaration %#qD");
+ 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_MAYBE_DELETED (e_inner) && DECL_MAYBE_DELETED (d_inner))
+ /* Nothing to do. */;
else if (DECL_DECLARED_CONSTEXPR_P (e_inner)
!= DECL_DECLARED_CONSTEXPR_P (d_inner))
- goto mismatch;
+ {
+ mismatch_msg = G_("conflicting %<constexpr%> for imported "
+ "declaration %#qD");
+ goto mismatch;
+ }
/* Don't synthesize a defaulted function if we're importing one
we've already determined. */
@@ -12184,13 +12216,17 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef)
if (!DECL_ORIGINAL_TYPE (e_inner)
|| !same_type_p (DECL_ORIGINAL_TYPE (d_inner),
DECL_ORIGINAL_TYPE (e_inner)))
- goto mismatch;
+ {
+ mismatch_msg = G_("conflicting imported declaration %q#D");
+ goto mismatch;
+ }
}
/* Using cp_tree_equal because we can meet TYPE_ARGUMENT_PACKs
here. I suspect the entities that directly do that are things
that shouldn't go to duplicate_decls (FIELD_DECLs etc). */
else if (!cp_tree_equal (TREE_TYPE (decl), TREE_TYPE (existing)))
{
+ mismatch_msg = G_("conflicting type for imported declaration %#qD");
mismatch:
if (DECL_IS_UNDECLARED_BUILTIN (existing))
/* Just like duplicate_decls, presum the user knows what
@@ -12203,11 +12239,9 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef)
equality isn't feasible in general for local entities. */;
else
{
- // FIXME:QOI Might be template specialization from a module,
- // not necessarily global module
+ gcc_checking_assert (mismatch_msg);
auto_diagnostic_group d;
- error_at (DECL_SOURCE_LOCATION (decl),
- "conflicting global module declaration %#qD", decl);
+ error_at (DECL_SOURCE_LOCATION (decl), mismatch_msg, decl);
inform (DECL_SOURCE_LOCATION (existing),
"existing declaration %#qD", existing);
return false;
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 95b89f12..4349b19 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -11117,6 +11117,18 @@ any_template_parm_r (tree t, void *data)
case LAMBDA_EXPR:
{
+ /* TREE_STATIC on LAMBDA_EXPR_EXTRA_ARGS means a full set of
+ arguments, so we can just look there; they will replace
+ any template parms in the rest of the LAMBDA_EXPR. */
+ if (tree args = LAMBDA_EXPR_EXTRA_ARGS (t))
+ {
+ WALK_SUBTREE (args);
+ /* Without TREE_STATIC the args are just outer levels, so we'd
+ still need to look through the lambda for just inner
+ parameters. Hopefully that's not necessary. */
+ gcc_checking_assert (TREE_STATIC (args));
+ return 0;
+ }
/* Look in the parms and body. */
tree fn = lambda_function (t);
WALK_SUBTREE (TREE_TYPE (fn));
@@ -11760,6 +11772,10 @@ tsubst_friend_function (tree decl, tree args)
elt.args = DECL_TI_ARGS (spec);
elt.spec = NULL_TREE;
+ if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (DECL_TI_ARGS (spec))
+ && !is_specialization_of_friend (spec, new_template))
+ continue;
+
decl_specializations->remove_elt (&elt);
tree& spec_args = DECL_TI_ARGS (spec);
@@ -13736,11 +13752,12 @@ add_extra_args (tree extra, tree args, tsubst_flags_t complain, tree in_decl)
inst = local;
/* else inst is already a full instantiation of the pack. */
register_local_specialization (inst, gen);
+ if (is_normal_capture_proxy (gen))
+ register_local_specialization (inst, DECL_CAPTURED_VARIABLE (gen));
}
gcc_assert (!TREE_PURPOSE (extra));
extra = TREE_VALUE (extra);
}
- gcc_checking_assert (TREE_STATIC (extra) == uses_template_parms (extra));
if (TREE_STATIC (extra))
/* This is a partial substitution into e.g. a requires-expr or lambda-expr
inside a default template argument; we expect 'extra' to be a full set
@@ -22675,7 +22692,7 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain)
FUNCTION_DECL which is the desired context for access checking
is not built yet. We solve this chicken-and-egg problem by
deferring all checks until we have the FUNCTION_DECL. */
- push_deferring_access_checks (dk_deferred);
+ deferring_access_check_sentinel dacs (dk_deferred);
/* Instantiation of the function happens in the context of the function
template, not the context of the overload resolution we're doing. */
@@ -22733,10 +22750,13 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain)
pop_from_top_level ();
if (fndecl == error_mark_node)
- {
- pop_deferring_access_checks ();
- return error_mark_node;
- }
+ return error_mark_node;
+
+ /* Substituting the type might have recursively instantiated this
+ same alias (c++/117530). */
+ if (DECL_ALIAS_TEMPLATE_P (gen_tmpl)
+ && (spec = retrieve_specialization (gen_tmpl, targ_ptr, hash)))
+ return spec;
/* The DECL_TI_TEMPLATE should always be the immediate parent
template, not the most general template. */
@@ -22771,7 +22791,6 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain)
access_ok = false;
pop_access_scope (fndecl);
}
- pop_deferring_access_checks ();
/* If we've just instantiated the main entry point for a function,
instantiate all the alternate entry points as well. We do this
@@ -30923,9 +30942,8 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
tree aguides = NULL_TREE;
tree atparms = INNERMOST_TEMPLATE_PARMS (fullatparms);
unsigned natparms = TREE_VEC_LENGTH (atparms);
- for (ovl_iterator iter (uguides); iter; ++iter)
+ for (tree f : lkp_range (uguides))
{
- tree f = *iter;
tree in_decl = f;
location_t loc = DECL_SOURCE_LOCATION (f);
tree ret = TREE_TYPE (TREE_TYPE (f));