If the mangler is relied on, functions with extern "C" on them emit multiple definitions of the same name.
gcc/cp/ChangeLog: * contracts.cc (build_contract_condition_function): Add pre/post suffixes to pre- and postcondition clones. * mangle.cc (write_encoding): Don't mangle pre- and postconditions. gcc/testsuite/ChangeLog: * g++.dg/contracts/contracts-externC.C: New test. --- Afternoon, This change prevents contracts from emitting wrapper functions that have the same name as the original function, by moving the logic that disambiguates them from the mangler into the build_contract_condition_function helper. Thanks, have nice day. gcc/cp/contracts.cc | 3 +++ gcc/cp/mangle.cc | 7 ------- .../g++.dg/contracts/contracts-externC.C | 19 +++++++++++++++++++ 3 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/g++.dg/contracts/contracts-externC.C diff --git a/gcc/cp/contracts.cc b/gcc/cp/contracts.cc index 26316372389..f09eb87e283 100644 --- a/gcc/cp/contracts.cc +++ b/gcc/cp/contracts.cc @@ -161,6 +161,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-iterator.h" #include "print-tree.h" #include "stor-layout.h" +#include "cgraph.h" const int max_custom_roles = 32; static contract_role contract_build_roles[max_custom_roles] = { @@ -1451,6 +1452,8 @@ build_contract_condition_function (tree fndecl, bool pre) TREE_TYPE (fn) = build_method_type (class_type, TREE_TYPE (fn)); DECL_NAME (fn) = copy_node (DECL_NAME (fn)); + auto suffix = pre ? "pre" : "post"; + SET_DECL_ASSEMBLER_NAME (fn, clone_function_name (fn, suffix)); DECL_INITIAL (fn) = error_mark_node; DECL_ABSTRACT_ORIGIN (fn) = fndecl; diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc index e363ef35b9f..e97428e8f30 100644 --- a/gcc/cp/mangle.cc +++ b/gcc/cp/mangle.cc @@ -856,13 +856,6 @@ write_encoding (const tree decl) mangle_return_type_p (decl), d); - /* If this is the pre/post function for a guarded function, append - .pre/post, like something from create_virtual_clone. */ - if (DECL_IS_PRE_FN_P (decl)) - write_string (".pre"); - else if (DECL_IS_POST_FN_P (decl)) - write_string (".post"); - /* If this is a coroutine helper, then append an appropriate string to identify which. */ if (tree ramp = DECL_RAMP_FN (decl)) diff --git a/gcc/testsuite/g++.dg/contracts/contracts-externC.C b/gcc/testsuite/g++.dg/contracts/contracts-externC.C new file mode 100644 index 00000000000..873056b742b --- /dev/null +++ b/gcc/testsuite/g++.dg/contracts/contracts-externC.C @@ -0,0 +1,19 @@ +// simple check to ensure we don't emit a function with the same name twice, +// when wrapping functions in pre- and postconditions. +// { dg-do link } +// { dg-options "-std=c++2a -fcontracts -fcontract-continuation-mode=on" } + +volatile int x = 10; + +extern "C" void +f () + [[ pre: x < 10 ]] +{ +} + +int +main () + [[ post: x > 10 ]] +{ + f(); +} -- 2.38.1