Skip to content

Commit 19bb027

Browse files
NinaRannsiains
authored andcommitted
fixing an ICE caused by a reused statement tree in contract
1 parent 9ee8c4c commit 19bb027

File tree

2 files changed

+68
-11
lines changed

2 files changed

+68
-11
lines changed

gcc/cp/cp-gimplify.cc

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1895,19 +1895,26 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
18951895
case PRECONDITION_STMT:
18961896
case POSTCONDITION_STMT:
18971897
{
1898-
if (tree check = build_contract_check (stmt))
1899-
{
1900-
*stmt_p = check;
1901-
return cp_genericize_r (stmt_p, walk_subtrees, data);
1902-
}
1903-
1904-
/* If we didn't build a check, replace it with void_node so we don't
1905-
leak contracts into GENERIC. */
1906-
*stmt_p = void_node;
1898+
tree check = build_contract_check (stmt);
1899+
if (check)
1900+
/* We need to genericize the contract independently of everything
1901+
else we genericized until now. When recursively genericizing, we
1902+
keep a track of all the statements that have been seen. Building a
1903+
contract check will create new statements, which may reuse an
1904+
already freed statement. If such an already freed statement has
1905+
been cached in p_set, we will fail to correctly genericize newly
1906+
created contract tree. */
1907+
cp_genericize_tree (&check, wtd->handle_invisiref_parm_p);
1908+
else
1909+
/* If we didn't build a check, replace it with void_node so we don't
1910+
leak contracts into GENERIC. */
1911+
check = void_node;
1912+
*stmt_p = check;
19071913
*walk_subtrees = 0;
1914+
/* Return early and do not add the contract statement into the cache.
1915+
*/
1916+
return NULL_TREE;
19081917
}
1909-
break;
1910-
19111918
case USING_STMT:
19121919
{
19131920
tree block = NULL_TREE;
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// check that we do not get a crash
2+
// { dg-do compile }
3+
// { dg-options "-std=c++2b -fcontracts -fcontracts-nonattr -fcontract-evaluation-semantic=enforce " }
4+
5+
6+
7+
struct Swapper {
8+
static unsigned int swapBytes();
9+
static bool isFinished();
10+
};
11+
12+
13+
struct Capacity {
14+
Capacity(int capacity);
15+
bool operator<( int rhs) const;
16+
bool operator>=(int rhs) const;
17+
};
18+
19+
template <class CAPACITY, class SWAPPER>
20+
struct Utf32ToUtf8Translator {
21+
22+
CAPACITY d_capacity;
23+
24+
Utf32ToUtf8Translator();
25+
26+
static void translate();
27+
};
28+
29+
template <class CAPACITY,class SWAPPER>
30+
void Utf32ToUtf8Translator<CAPACITY, SWAPPER>::translate()
31+
{
32+
Utf32ToUtf8Translator<CAPACITY, SWAPPER> translator;
33+
34+
unsigned int uc =0;
35+
while (!SWAPPER::isFinished()) {
36+
uc = SWAPPER::swapBytes();
37+
if (0 != uc) {
38+
}
39+
}
40+
contract_assert( translator.d_capacity >= 1 );
41+
42+
}
43+
44+
void func()
45+
{
46+
typedef Utf32ToUtf8Translator<Capacity,
47+
Swapper> SwapTranslator;
48+
49+
SwapTranslator::translate();
50+
}

0 commit comments

Comments
 (0)