c++/contracts: ICE in build_contract_condition_function [PR116490]

We currently do not expect comdat group of the guarded function to
be set at the time of generating pre and post check function.
However, in the case of an explicit instantiation, the guarded
function has been added to a comdat group before generating contract
check functions, which causes the observed ICE. Current assert
removed and an additional check for comdat group of the guarded
function added. With this change, the pre and post check functions
get added to the same comdat group of the guarded function if the
guarded function is already placed in a comdat group.

	PR c++/116490

gcc/cp/ChangeLog:

	* contracts.cc (build_contract_condition_function): added
	a check for comdat group of the guarded function. If set,
	the condition check function is added to the same comdat
	group.

gcc/testsuite/ChangeLog:

	* g++.dg/contracts/pr116490.C: New test.

Signed-off-by: Nina Ranns <dinka.ranns@gmail.com>
This commit is contained in:
Nina Dinka Ranns 2024-08-30 13:49:07 +01:00 committed by Jason Merrill
parent 4cb20dc043
commit ae57e52754
2 changed files with 65 additions and 3 deletions

View file

@ -145,6 +145,7 @@ along with GCC; see the file COPYING3. If not see
#include "print-tree.h"
#include "stor-layout.h"
#include "intl.h"
#include "cgraph.h"
const int max_custom_roles = 32;
static contract_role contract_build_roles[max_custom_roles] = {
@ -1458,9 +1459,14 @@ build_contract_condition_function (tree fndecl, bool pre)
DECL_WEAK (fn) = false;
DECL_COMDAT (fn) = false;
/* We haven't set the comdat group on the guarded function yet, we'll add
this to the same group in comdat_linkage later. */
gcc_assert (!DECL_ONE_ONLY (fndecl));
/* We may not have set the comdat group on the guarded function yet.
If we haven't, we'll add this to the same group in comdat_linkage
later. Otherwise, add it to the same comdat group now. */
if (DECL_ONE_ONLY (fndecl))
{
symtab_node *n = symtab_node::get (fndecl);
cgraph_node::get_create (fn)->add_to_same_comdat_group (n);
}
DECL_INTERFACE_KNOWN (fn) = true;
}

View file

@ -0,0 +1,56 @@
// ICE in explicit instantiation of a function with contracts
// { dg-do run }
// { dg-options "-std=c++20 -fcontracts -fcontract-continuation-mode=on" }
template<class T>
void foo(T t)
[[pre : t == 9 ]] {
}
template void foo<int>(int i);
template<class T>
struct templateS
{
void fooS(T t)
[[pre : t == 9 ]] {
}
};
template struct templateS<int>;
struct S {
template<class T>
void fooS(T t)
[[pre : t == 9 ]] {
}
template<class T>
static void fooStatic(T t)
[[pre : t == 9 ]] {
}
};
template void S::fooS<int>(int i);
template void S::fooStatic<int>(int i);
int main()
{
foo(3);
templateS<int> ts;
ts.fooS(3);
S s;
s.fooS(3);
S::fooStatic(3);
}
// { dg-output "contract violation in function foo<int> at .* t == 9.*(\n|\r\n|\r)" }
// { dg-output "contract violation in function templateS<int>::fooS at .* t == 9.*(\n|\r\n|\r)" }
// { dg-output "contract violation in function S::fooS<int> at .* t == 9.*(\n|\r\n|\r)" }
// { dg-output "contract violation in function S::fooStatic<int> at .* t == 9.*(\n|\r\n|\r)" }