public inbox for gcc-cvs@sourceware.org help / color / mirror / Atom feed
From: Jason Merrill <jason@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/c++-contracts] c++: GC problem emitting contract functions Date: Tue, 6 Jul 2021 20:44:16 +0000 (GMT) [thread overview] Message-ID: <20210706204416.54CAF383D803@sourceware.org> (raw) https://gcc.gnu.org/g:d5c78dacbfa17ea45fe0bb9a0e0929e911b9dcc5 commit d5c78dacbfa17ea45fe0bb9a0e0929e911b9dcc5 Author: Jason Merrill <jason@redhat.com> Date: Mon Jul 5 19:52:21 2021 -0400 c++: GC problem emitting contract functions Here, the copied list of contracts was getting garbage collected between compilation of the .pre and .post functions. Instead of copying the list, let's remap the conditions when we are ready to emit them. gcc/cp/ChangeLog: * contracts.cc (emit_contract_statement): Just add_stmt. (emit_contract_attr): Renamed from above. (emit_contract_conditions, emit_assertion): Adjust. (remap_and_emit_conditions): New. (finish_function_contracts): Use it. gcc/testsuite/ChangeLog: * g++.dg/contracts/contracts-deduced1.C: Use aggressive GC. Diff: --- gcc/cp/contracts.cc | 69 +++++++++++++--------- .../g++.dg/contracts/contracts-deduced1.C | 2 +- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/gcc/cp/contracts.cc b/gcc/cp/contracts.cc index 73e6378bf22..1921e062c43 100644 --- a/gcc/cp/contracts.cc +++ b/gcc/cp/contracts.cc @@ -1671,19 +1671,26 @@ build_contract_check (tree contract) return do_poplevel (scope); } -/* Generate the statement for the given contract attribute by adding the - statement to the current block. Returns the next contract in the chain. */ +/* Add the contract statement CONTRACT to the current block if valid. */ -static tree -emit_contract_statement (tree attr) +static void +emit_contract_statement (tree contract) { - gcc_assert (TREE_CODE (attr) == TREE_LIST); - tree contract = CONTRACT_STATEMENT (attr); - /* Only add valid contracts. */ if (get_contract_semantic (contract) != CCS_INVALID && CONTRACT_CONDITION (contract) != error_mark_node) add_stmt (contract); +} + +/* Generate the statement for the given contract attribute by adding the + statement to the current block. Returns the next contract in the chain. */ + +static tree +emit_contract_attr (tree attr) +{ + gcc_assert (TREE_CODE (attr) == TREE_LIST); + + emit_contract_statement (CONTRACT_STATEMENT (attr)); return CONTRACT_CHAIN (attr); } @@ -1700,7 +1707,7 @@ emit_contract_conditions (tree attrs, tree_code code) { tree contract = CONTRACT_STATEMENT (attrs); if (TREE_CODE (contract) == code) - attrs = emit_contract_statement (attrs); + attrs = emit_contract_attr (attrs); else attrs = CONTRACT_CHAIN (attrs); } @@ -1711,7 +1718,7 @@ emit_contract_conditions (tree attrs, tree_code code) void emit_assertion (tree attr) { - emit_contract_statement (attr); + emit_contract_attr (attr); } /* Emit statements for precondition attributes. */ @@ -1730,6 +1737,26 @@ emit_postconditions (tree contracts) return emit_contract_conditions (contracts, POSTCONDITION_STMT); } +/* We're compiling the pre/postcondition function CONDFN; remap any FN + attributes that match CODE and emit them. */ + +static void +remap_and_emit_conditions (tree fn, tree condfn, tree_code code) +{ + gcc_assert (code == PRECONDITION_STMT || code == POSTCONDITION_STMT); + for (tree attr = DECL_CONTRACTS (fn); attr; + attr = CONTRACT_CHAIN (attr)) + { + tree contract = CONTRACT_STATEMENT (attr); + if (TREE_CODE (contract) == code) + { + contract = copy_node (contract); + remap_contract (fn, condfn, contract, /*duplicate_p=*/false); + emit_contract_statement (contract); + } + } +} + /* Converts a contract condition to bool and ensures it has a locaiton. */ tree @@ -1860,7 +1887,6 @@ finish_function_contracts (tree fndecl) } int flags = SF_DEFAULT | SF_PRE_PARSED; - tree finished_pre = NULL_TREE, finished_post = NULL_TREE; /* If either the pre or post functions are bad, don't bother emitting any contracts. The program is already ill-formed. */ @@ -1869,39 +1895,26 @@ finish_function_contracts (tree fndecl) if (pre == error_mark_node || post == error_mark_node) return; - /* Create a copy of the contracts with references to fndecl's args replaced - with references to either the args of pre or post function. */ - tree contracts = copy_list (DECL_CONTRACTS (fndecl)); - for (tree attr = contracts; attr; attr = CONTRACT_CHAIN (attr)) - { - tree contract = copy_node (CONTRACT_STATEMENT (attr)); - if (TREE_CODE (contract) == PRECONDITION_STMT) - remap_contract (fndecl, pre, contract, /*duplicate_p=*/false); - else if (TREE_CODE (contract) == POSTCONDITION_STMT) - remap_contract (fndecl, post, contract, /*duplicate_p=*/false); - TREE_VALUE (attr) = build_tree_list (NULL_TREE, contract); - } - if (pre && DECL_INITIAL (fndecl) != error_mark_node) { DECL_PENDING_INLINE_P (pre) = false; start_preparsed_function (pre, DECL_ATTRIBUTES (pre), flags); - emit_preconditions (contracts); - finished_pre = finish_function (false); + remap_and_emit_conditions (fndecl, pre, PRECONDITION_STMT); + tree finished_pre = finish_function (false); expand_or_defer_fn (finished_pre); } + if (post && DECL_INITIAL (fndecl) != error_mark_node) { DECL_PENDING_INLINE_P (post) = false; start_preparsed_function (post, DECL_ATTRIBUTES (post), flags); - emit_postconditions (contracts); - + remap_and_emit_conditions (fndecl, post, POSTCONDITION_STMT); if (!VOID_TYPE_P (TREE_TYPE (TREE_TYPE (post)))) finish_return_stmt (get_postcondition_result_parameter (fndecl)); - finished_post = finish_function (false); + tree finished_post = finish_function (false); expand_or_defer_fn (finished_post); } } diff --git a/gcc/testsuite/g++.dg/contracts/contracts-deduced1.C b/gcc/testsuite/g++.dg/contracts/contracts-deduced1.C index e78ee6b6a9c..200ec734800 100644 --- a/gcc/testsuite/g++.dg/contracts/contracts-deduced1.C +++ b/gcc/testsuite/g++.dg/contracts/contracts-deduced1.C @@ -1,7 +1,7 @@ // Tests to ensure that deduced return types work with postconditions using // the return value on defining declarations. // { dg-do compile } -// { dg-options "-std=c++2a -fcontracts" } +// { dg-options "-std=c++2a -fcontracts --param ggc-min-heapsize=0 --param ggc-min-expand=0" } auto undeduced(int z) {
reply other threads:[~2021-07-06 20:44 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20210706204416.54CAF383D803@sourceware.org \ --to=jason@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).