Skip to content

Commit 5434abf

Browse files
committed
making contracts on virtual functions invalid
1 parent b0e844a commit 5434abf

File tree

3 files changed

+22
-131
lines changed

3 files changed

+22
-131
lines changed

gcc/cp/class.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3225,6 +3225,14 @@ check_for_override (tree decl, tree ctype)
32253225

32263226
if (DECL_DESTRUCTOR_P (decl))
32273227
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (ctype) = true;
3228+
3229+
if (DECL_HAS_CONTRACTS_P(decl)
3230+
&& flag_contract_nonattr_inheritance_mode
3231+
== CONTRACT_INHERITANCE_NONE)
3232+
{
3233+
error_at (DECL_SOURCE_LOCATION(decl),
3234+
"Contracts can not be added to virtual functions.");
3235+
}
32283236
}
32293237
else if (DECL_FINAL_P (decl))
32303238
error ("%q+#D marked %<final%>, but is not virtual", decl);

gcc/cp/search.cc

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2230,15 +2230,15 @@ check_override_contracts (tree fndecl)
22302230
{
22312231

22322232
if (!flag_contracts || !flag_contracts_nonattr
2233-
|| flag_contract_nonattr_inheritance_mode != CONTRACT_INHERITANCE_P3653 )
2233+
|| flag_contract_nonattr_inheritance_mode != CONTRACT_INHERITANCE_P3653)
22342234
return;
22352235

22362236
/* A constructor for a class T does not override a function T
2237-
in a base class. */
2237+
in a base class. */
22382238
if (DECL_CONSTRUCTOR_P (fndecl))
22392239
return;
22402240

2241-
bool explicit_contracts = DECL_HAS_CONTRACTS_P(fndecl);
2241+
bool explicit_contracts = DECL_HAS_CONTRACTS_P (fndecl);
22422242
tree binfo = TYPE_BINFO (DECL_CONTEXT (fndecl));
22432243
tree base_binfo;
22442244

@@ -2247,13 +2247,13 @@ check_override_contracts (tree fndecl)
22472247
tree basetype = BINFO_TYPE (base_binfo);
22482248

22492249
if (!TYPE_POLYMORPHIC_P (basetype))
2250-
continue;
2250+
continue;
22512251

22522252
tree basefn = look_for_overrides_here (basetype, fndecl);
22532253
if (!basefn)
22542254
continue;
22552255

2256-
if (!explicit_contracts && DECL_HAS_CONTRACTS_P(basefn))
2256+
if (!explicit_contracts && DECL_HAS_CONTRACTS_P (basefn))
22572257
{
22582258
/* We're inheriting basefn's contracts; create a copy of them but
22592259
* replace references to their parms to our parms. */
@@ -2263,19 +2263,18 @@ check_override_contracts (tree fndecl)
22632263
/* remap post conditions */true);
22642264
tree contracts = chainon (DECL_CONTRACTS (fndecl), base_contracts);
22652265

2266-
set_decl_contracts(fndecl, contracts);
2266+
set_decl_contracts (fndecl, contracts);
22672267

22682268
if (suggest_explicit_contract)
22692269
{
2270-
warning_at (DECL_SOURCE_LOCATION(fndecl),
2270+
warning_at (DECL_SOURCE_LOCATION (fndecl),
22712271
suggest_explicit_contract,
22722272
"Function implicitly inherits a contract");
2273-
inform (DECL_SOURCE_LOCATION(basefn),
2273+
inform (DECL_SOURCE_LOCATION (basefn),
22742274
"overridden function is %qD", basefn);
22752275
}
22762276
}
22772277
}
2278-
22792278
}
22802279

22812280
/* Given a class TYPE, and a function decl FNDECL, look for
Lines changed: 6 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,132 +1,16 @@
1-
// test that contracts on overriding functions are found correctly
2-
// { dg-do run }
3-
// { dg-options "-std=c++2a -fcontracts -fcontract-continuation-mode=off -fcontracts-nonattr -fcontracts-nonattr-inheritance-mode=none " }
4-
#include <cassert>
5-
6-
struct contract{
7-
int checked = 0;
8-
};
9-
10-
11-
contract a,b,c;
12-
13-
bool checkA(){
14-
a.checked++;
15-
return true;
16-
}
17-
18-
bool checkB(){
19-
b.checked++;
20-
return true;
21-
}
22-
23-
bool checkC(){
24-
c.checked++;
25-
return true;
26-
}
27-
28-
void clear_checks(){
29-
a.checked = b.checked = c.checked = 0;
30-
31-
}
1+
// { dg-do compile }
2+
// { dg-options "-std=c++2b -fcontracts -fcontracts-nonattr -fcontracts-nonattr-inheritance-mode=none " }
323

334
struct Base
345
{
35-
virtual void f() pre (checkA()){};
36-
};
37-
38-
39-
struct Child0 : Base
40-
{
41-
virtual void f() {}; //no contract
42-
};
6+
virtual int f1() pre(true); // { dg-error "Contracts can not be added to virtual functions" }
7+
virtual int f2();
438

44-
struct Child1 : Base
45-
{
46-
virtual void f() pre (checkB()){};
479
};
48-
49-
50-
struct GChild1 : Child0
10+
struct Child : Base
5111
{
52-
virtual void f() pre (checkC()){};
53-
};
12+
int f2() pre(true); // { dg-error "Contracts can not be added to virtual functions" }
5413

55-
struct GChild2 : Child1
56-
{
57-
virtual void f() {};
5814
};
5915

6016

61-
void fooBase(Base* b)
62-
{
63-
b->f();
64-
}
65-
66-
int main(int, char**)
67-
{
68-
Base b0;
69-
Child0 c0;
70-
Child1 c1;
71-
GChild1 g1;
72-
GChild2 g2;
73-
74-
75-
clear_checks();
76-
fooBase(&b0);
77-
assert(a.checked > 0);
78-
79-
clear_checks();
80-
fooBase(&c0);
81-
assert(a.checked == 0);
82-
83-
clear_checks();
84-
fooBase(&c1);
85-
assert(a.checked == 0);
86-
assert(b.checked > 0);
87-
88-
89-
clear_checks();
90-
fooBase(&g1);
91-
assert(a.checked == 0);
92-
assert(b.checked == 0);
93-
assert(c.checked > 0);
94-
95-
96-
clear_checks();
97-
fooBase(&g2);
98-
assert(a.checked == 0);
99-
assert(b.checked == 0);
100-
assert(c.checked == 0);
101-
102-
clear_checks();
103-
b0.f();
104-
assert(a.checked > 0);
105-
106-
clear_checks();
107-
c0.f();
108-
assert(a.checked == 0);
109-
110-
clear_checks();
111-
c1.f();
112-
assert(a.checked == 0);
113-
assert(b.checked > 0);
114-
115-
116-
clear_checks();
117-
g1.f();;
118-
assert(a.checked == 0);
119-
assert(b.checked == 0);
120-
assert(c.checked > 0);
121-
122-
123-
clear_checks();
124-
g2.f();
125-
assert(a.checked == 0);
126-
assert(b.checked == 0);
127-
assert(c.checked == 0);
128-
129-
return 0;
130-
}
131-
132-

0 commit comments

Comments
 (0)