// generic error tests for contract redecls with generalized redecl // { dg-do compile } // { dg-options "-std=c++2a -fcontracts" } // OK if equivalent -- even through renames. int g0(int a) [[ pre: a > 0 ]]; int g0(int a) [[ pre: a > 0 ]]; int g0b(int a) [[ pre: a > 0 ]]; int g0b(int b) [[ pre: b > 0 ]]; int g0b(int c) [[ pre: c > 0 ]] { return 0; } // OK if specified before. int g1(int a) [[ pre: a > 0 ]]; int g1(int a); // OK if specified after. int g2(int a); int g2(int a) [[ pre: a > 0 ]]; int g2b(int a); int g2b(int b) [[ pre: b > 0 ]]; // can add to non-virtual methods struct G0 { int f(int a); }; // OK to add contracts at the point of definition. int G0::f(int a) [[ pre: a > 0 ]] { return -a; } struct G1 { int f1(int a); }; // OK to redeclare functions and add constraints... int G1::f1(int a) [[ pre: a > 0 ]]; // ...and leave them off later. int G1::f1(int a) { return -a; } int f0(int a) [[ pre: a > 0 ]]; int f0(int a) [[ pre: a > 0 ]] [[ pre: a > 10 ]]; // { dg-error "different number of contracts" } int f1(int a) [[ pre: a > 0 ]] [[ pre: a > 10 ]]; int f1(int a) [[ pre: a > 0 ]]; // { dg-error "different number of contracts" } int f2(int a) [[ pre: a > 0 ]]; int f2(int a) [[ pre: a < 0 ]]; // { dg-error "mismatched contract" } int f3(int a) { return a; } int f3(int a) [[ pre: a < 0 ]]; // { dg-error "cannot add contracts" } struct Base { virtual int f(int a) [[ pre: a > 0 ]]; }; struct Child : Base { int f(int a) [[ pre: a < 0 ]]; // { dg-error "mismatched contract" } }; struct S1 { virtual int f(int a); // contracts are inherited at the point of declarations }; int S1::f(int a) [[ pre: a > 0 ]] // { dg-error "cannot add" } { return -a; } struct S2 { int f() { return 0; } }; int S2::f(); // OK? struct S3 { int f() { return 0; } }; int S3::f() [[pre: true]]; // { dg-error "cannot add contracts" } // The initial decl of a guarded member must appear inside the class. struct S4 { int f(int a); }; int S4::g(int a) [[ pre: a > 0 ]]; // { dg-error "no declaration matches" } struct S5 { template<typename T> S5(T a); }; template<typename T> S5::S5(T a) [[ pre: a > 0 ]] { } struct S6 { template<typename T> S6(T a); }; template<typename T> S6::S6(T a) [[ pre: a > 0 ]]; template<typename T> S6::S6(T a) { } int p0(int n) [[ post r: r > 0 && r == n ]] [[ post r: r > 1 && r == n ]] [[ post r: r > 2 && r == n ]] [[ post r: r > 3 && r == n ]]; int p0(int z) [[ post r: r > 0 && r == z ]] [[ post r1: r1 > 1 && r1 == z ]] [[ post r2: r2 > 2 && r2 == z ]] [[ post r3: r3 > 3 && r3 == z ]] { return z; }