https://gcc.gnu.org/g:d3627c78be116ef1941f6819d57c237e71c39444
commit r15-7342-gd3627c78be116ef1941f6819d57c237e71c39444 Author: Nathaniel Shead <nathanielosh...@gmail.com> Date: Sat Feb 1 22:55:22 2025 +1100 c++: Improve contracts support in modules [PR108205] Modules makes some assumptions about types that currently aren't fulfilled by the types created in contracts logic. This patch ensures that exporting inline functions using contracts works again with modules. PR c++/108205 gcc/cp/ChangeLog: * contracts.cc (get_pseudo_contract_violation_type): Give names to generated FIELD_DECLs. (declare_handle_contract_violation): Mark contract_violation type as external linkage. (build_contract_handler_call): Ensure any builtin declarations created here aren't treated as attached to the current module. gcc/testsuite/ChangeLog: * g++.dg/modules/contracts-5_a.C: New test. * g++.dg/modules/contracts-5_b.C: New test. Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com> Diff: --- gcc/cp/contracts.cc | 27 ++++++++++++++++++--------- gcc/testsuite/g++.dg/modules/contracts-5_a.C | 8 ++++++++ gcc/testsuite/g++.dg/modules/contracts-5_b.C | 20 ++++++++++++++++++++ 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/gcc/cp/contracts.cc b/gcc/cp/contracts.cc index 5782ec8bf295..f2b126c8d6be 100644 --- a/gcc/cp/contracts.cc +++ b/gcc/cp/contracts.cc @@ -1633,19 +1633,22 @@ get_pseudo_contract_violation_type () signed char _M_continue; If this changes, also update the initializer in build_contract_violation. */ - const tree types[] = { const_string_type_node, - const_string_type_node, - const_string_type_node, - const_string_type_node, - const_string_type_node, - uint_least32_type_node, - signed_char_type_node }; + struct field_info { tree type; const char* name; }; + const field_info info[] = { + { const_string_type_node, "_M_file" }, + { const_string_type_node, "_M_function" }, + { const_string_type_node, "_M_comment" }, + { const_string_type_node, "_M_level" }, + { const_string_type_node, "_M_role" }, + { uint_least32_type_node, "_M_line" }, + { signed_char_type_node, "_M_continue" } + }; tree fields = NULL_TREE; - for (tree type : types) + for (const field_info& i : info) { /* finish_builtin_struct wants fieldss chained in reverse. */ tree next = build_decl (BUILTINS_LOCATION, FIELD_DECL, - NULL_TREE, type); + get_identifier (i.name), i.type); DECL_CHAIN (next) = fields; fields = next; } @@ -1737,6 +1740,7 @@ declare_handle_contract_violation () create_implicit_typedef (viol_name, violation); DECL_SOURCE_LOCATION (TYPE_NAME (violation)) = BUILTINS_LOCATION; DECL_CONTEXT (TYPE_NAME (violation)) = current_namespace; + TREE_PUBLIC (TYPE_NAME (violation)) = true; pushdecl_namespace_level (TYPE_NAME (violation), /*hidden*/true); pop_namespace (); pop_nested_namespace (std_node); @@ -1761,6 +1765,11 @@ static void build_contract_handler_call (tree contract, contract_continuation cmode) { + /* We may need to declare new types, ensure they are not considered + attached to a named module. */ + auto module_kind_override = make_temp_override + (module_kind, module_kind & ~(MK_PURVIEW | MK_ATTACH | MK_EXPORTING)); + tree violation = build_contract_violation (contract, cmode); tree violation_fn = declare_handle_contract_violation (); tree call = build_call_n (violation_fn, 1, build_address (violation)); diff --git a/gcc/testsuite/g++.dg/modules/contracts-5_a.C b/gcc/testsuite/g++.dg/modules/contracts-5_a.C new file mode 100644 index 000000000000..2ff6701ff3f1 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/contracts-5_a.C @@ -0,0 +1,8 @@ +// PR c++/108205 +// Test that the implicitly declared handle_contract_violation function is +// properly matched with a later declaration in an importing TU. +// { dg-additional-options "-fmodules -fcontracts -fcontract-continuation-mode=on" } +// { dg-module-cmi test } + +export module test; +export inline void foo(int x) noexcept [[ pre: x != 0 ]] {} diff --git a/gcc/testsuite/g++.dg/modules/contracts-5_b.C b/gcc/testsuite/g++.dg/modules/contracts-5_b.C new file mode 100644 index 000000000000..0e794b8ae453 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/contracts-5_b.C @@ -0,0 +1,20 @@ +// PR c++/108205 +// { dg-module-do run } +// { dg-additional-options "-fmodules -fcontracts -fcontract-continuation-mode=on" } + +#include <experimental/contract> +import test; + +bool saw_violation = false; +void handle_contract_violation(const std::experimental::contract_violation& v) { + saw_violation = true; +} + +int main() { + foo(10); + if (saw_violation) + __builtin_abort(); + foo(0); + if (!saw_violation) + __builtin_abort(); +}