aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/cp-tree.h10
-rw-r--r--gcc/cp/lambda.cc41
-rw-r--r--gcc/cp/pt.cc10
4 files changed, 49 insertions, 18 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index d9f0298..cd128e2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2025-04-24 Jason Merrill <jason@redhat.com>
+
+ PR c++/116954
+ * contracts.cc (remove_contract_attributes): Return early if
+ not enabled.
+
2025-04-22 Nathaniel Shead <nathanieloshead@gmail.com>
* name-lookup.cc (lookup_imported_hidden_friend): Remove
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7798efb..856202c 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6755,8 +6755,14 @@ struct GTY((chain_next ("%h.next"))) tinst_level {
/* The location where the template is instantiated. */
location_t locus;
- /* errorcount + sorrycount when we pushed this level. */
- unsigned short errors;
+ /* errorcount + sorrycount when we pushed this level. If the value
+ overflows, it will always seem like we currently have more errors, so we
+ will limit template recursion even from non-erroneous templates. In a TU
+ with over 32k errors, that's fine. */
+ unsigned short errors : 15;
+
+ /* set in pop_tinst_level if there have been errors since we pushed. */
+ bool had_errors : 1;
/* Count references to this object. If refcount reaches
refcount_infinity value, we don't increment or decrement the
diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index b2e0ecd..a2bed9f 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -348,7 +348,11 @@ insert_capture_proxy (tree var)
/* And put a DECL_EXPR in the STATEMENT_LIST for the same block. */
var = build_stmt (DECL_SOURCE_LOCATION (var), DECL_EXPR, var);
- tree stmt_list = (*stmt_list_stack)[1];
+ /* The first stmt_list is from start_preparsed_function. Then there's a
+ possible stmt_list from begin_eh_spec_block, then the one from the
+ lambda's outer {}. */
+ unsigned index = 1 + use_eh_spec_block (current_function_decl);
+ tree stmt_list = (*stmt_list_stack)[index];
gcc_assert (stmt_list);
append_to_statement_list_force (var, &stmt_list);
}
@@ -1859,11 +1863,10 @@ 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)
+ bool noexcept_p = (bind_expr
+ && TREE_CODE (bind_expr) == MUST_NOT_THROW_EXPR);
+ if (noexcept_p)
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; )
@@ -1872,11 +1875,23 @@ prune_lambda_captures (tree body)
if (tree var = var_to_maybe_prune (cap))
{
tree **use = const_vars.get (var);
- if (use && TREE_CODE (**use) == DECL_EXPR)
+ if (TREE_CODE (**use) == DECL_EXPR)
{
/* All uses of this capture were folded away, leaving only the
proxy declaration. */
+ if (noexcept_p)
+ {
+ /* We didn't handle noexcept lambda captures correctly before
+ the fix for PR c++/119764. */
+ if (abi_version_crosses (21))
+ warning_at (location_of (lam), OPT_Wabi, "%qD is no longer"
+ " captured in noexcept lambda in ABI v21 "
+ "(GCC 16)", var);
+ if (!abi_version_at_least (21))
+ goto next;
+ }
+
/* Splice the capture out of LAMBDA_EXPR_CAPTURE_LIST. */
*capp = TREE_CHAIN (cap);
@@ -1894,14 +1909,11 @@ prune_lambda_captures (tree body)
/* 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);
- }
+ 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;
@@ -1909,6 +1921,7 @@ prune_lambda_captures (tree body)
}
}
+ next:
capp = &TREE_CHAIN (cap);
}
}
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index a71705f..e8d342f 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -11418,6 +11418,7 @@ push_tinst_level_loc (tree tldcl, tree targs, location_t loc)
new_level->targs = targs;
new_level->locus = loc;
new_level->errors = errorcount + sorrycount;
+ new_level->had_errors = false;
new_level->next = NULL;
new_level->refcount = 0;
new_level->path = new_level->visible = nullptr;
@@ -11468,6 +11469,9 @@ pop_tinst_level (void)
/* Restore the filename and line number stashed away when we started
this instantiation. */
input_location = current_tinst_level->locus;
+ if (unsigned errs = errorcount + sorrycount)
+ if (errs > current_tinst_level->errors)
+ current_tinst_level->had_errors = true;
set_refcount_ptr (current_tinst_level, current_tinst_level->next);
--tinst_depth;
}
@@ -11487,7 +11491,7 @@ reopen_tinst_level (struct tinst_level *level)
set_refcount_ptr (current_tinst_level, level);
pop_tinst_level ();
- if (current_tinst_level)
+ if (current_tinst_level && !current_tinst_level->had_errors)
current_tinst_level->errors = errorcount+sorrycount;
tree decl = level->maybe_get_node ();
@@ -28072,7 +28076,9 @@ instantiate_pending_templates (int retries)
tree instantiation = reopen_tinst_level ((*t)->tinst);
bool complete = false;
- if (TYPE_P (instantiation))
+ if (limit_bad_template_recursion (instantiation))
+ /* Do nothing. */;
+ else if (TYPE_P (instantiation))
{
if (!COMPLETE_TYPE_P (instantiation))
{