aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNina Dinka Ranns <dinka.ranns@googlemail.com>2024-08-30 13:49:07 +0100
committerJason Merrill <jason@redhat.com>2024-09-24 11:56:13 -0400
commitae57e52754ca6c96145a1b7504c2c7613a9e54d9 (patch)
treeea943d22ac2c859848dbfa047be5c6f459fc0ff0
parent4cb20dc043cf70b8a1b4846c86599cc1ff9680d9 (diff)
downloadgcc-ae57e52754ca6c96145a1b7504c2c7613a9e54d9.zip
gcc-ae57e52754ca6c96145a1b7504c2c7613a9e54d9.tar.gz
gcc-ae57e52754ca6c96145a1b7504c2c7613a9e54d9.tar.bz2
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>
-rw-r--r--gcc/cp/contracts.cc12
-rw-r--r--gcc/testsuite/g++.dg/contracts/pr116490.C56
2 files changed, 65 insertions, 3 deletions
diff --git a/gcc/cp/contracts.cc b/gcc/cp/contracts.cc
index 39f0487..4d2849a 100644
--- a/gcc/cp/contracts.cc
+++ b/gcc/cp/contracts.cc
@@ -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;
}
diff --git a/gcc/testsuite/g++.dg/contracts/pr116490.C b/gcc/testsuite/g++.dg/contracts/pr116490.C
new file mode 100644
index 0000000..e3a5d77
--- /dev/null
+++ b/gcc/testsuite/g++.dg/contracts/pr116490.C
@@ -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)" }