Skip to content

Commit e3a80eb

Browse files
NinaRannsiains
authored andcommitted
We save the contracts from the first decl for comparison with any
re-declaration. However, the stored copy refers to the parameter of the decl and the stored contracts get modified when the function decl gets genericized. To solve the problem, we store a copy of the original contracts. The copy can't happen for deferred contracts so we only save them when the contracts are not deferred. This means friend declarations can not work correctly. However, we already do not have a solution for recognising mismatched contracts on friend declarations.
1 parent ca751fa commit e3a80eb

File tree

2 files changed

+21
-16
lines changed

2 files changed

+21
-16
lines changed

gcc/cp/contracts.cc

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3314,8 +3314,8 @@ void
33143314
p2900_duplicate_contracts (tree newdecl, tree olddecl)
33153315
{
33163316
/* Aggregate the contracts and strip them from the input decls. */
3317-
tree new_contracts = extract_contract_attributes (newdecl);
3318-
tree old_contracts = extract_contract_attributes (olddecl);
3317+
tree new_contracts = DECL_CONTRACTS (newdecl);
3318+
tree old_contracts = DECL_CONTRACTS (olddecl);
33193319

33203320
if (!old_contracts && !new_contracts)
33213321
return;
@@ -3328,9 +3328,9 @@ p2900_duplicate_contracts (tree newdecl, tree olddecl)
33283328
also be needed when we process deferred contracts. */
33293329
bool existed = false;
33303330
contract_redecl& rd = redeclared_contracts.get_or_insert (olddecl, &existed);
3331-
if (!existed)
3331+
if (!existed && !contract_any_deferred_p (old_contracts))
33323332
{
3333-
rd.original_contracts = old_contracts;
3333+
rd.original_contracts = copy_contracts(olddecl);
33343334
location_t cont_end = old_loc;
33353335
if (old_contracts)
33363336
cont_end = get_contract_end_loc (old_contracts);
@@ -3351,20 +3351,13 @@ p2900_duplicate_contracts (tree newdecl, tree olddecl)
33513351
return;
33523352
}
33533353

3354-
/* If have now parsed deferred contracts for the 'first' decl, update the
3355-
saved record. */
3356-
if (rd.original_contracts
3357-
&& contract_any_deferred_p (rd.original_contracts)
3358-
&& old_contracts
3359-
&& !contract_any_deferred_p (old_contracts))
3360-
rd.original_contracts = old_contracts;
3361-
33623354
if (old_contracts && !new_contracts)
33633355
/* We allow re-declarations to omit contracts declared on the initial decl.
33643356
In fact, this is required if the conditions contain lambdas. Check if
33653357
all the parameters are correctly const qualified. */
33663358
check_param_in_redecl (olddecl, newdecl);
3367-
else if (contract_any_deferred_p (new_contracts))
3359+
else if (contract_any_deferred_p (new_contracts)
3360+
|| contract_any_deferred_p (old_contracts))
33683361
/* TODO: stash these and figure out how to process them later. */
33693362
;
33703363
else
@@ -3377,10 +3370,12 @@ p2900_duplicate_contracts (tree newdecl, tree olddecl)
33773370
}
33783371

33793372
/* We have maybe issued a diagnostic - but because the caller will smash the
3380-
attributes on the old decl with those on the new, we need to copy the old
3381-
ones onto the new. */
3373+
attributes on the old decl with those on the new, we need to remove the
3374+
contracts from the old decl and move the old contracts onto the new decl. */
3375+
remove_contract_attributes (newdecl);
33823376
DECL_ATTRIBUTES (newdecl)
3383-
= attr_chainon (DECL_ATTRIBUTES (newdecl), old_contracts);
3377+
= attr_chainon (DECL_ATTRIBUTES (newdecl),
3378+
extract_contract_attributes (olddecl));
33843379
return;
33853380
}
33863381

gcc/testsuite/g++.dg/contracts/cpp26/contracts-redecl.C

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,13 @@ struct Bar : Foo {
8686
void Bar::f10(int n) pre (n >10) {}; // { dg-error "mismatched contract" }
8787

8888

89+
struct NonTrivial{
90+
NonTrivial(){};
91+
NonTrivial(const NonTrivial&){}
92+
~NonTrivial(){};
93+
int x = 0;
94+
};
95+
96+
void f(const NonTrivial s) pre(s.x >0);
97+
void f(const NonTrivial g) {};
98+
void f(const NonTrivial t) pre(t.x >0);

0 commit comments

Comments
 (0)