// test that contracts are matched on friend decls when the type is complete // { dg-do compile } // { dg-options "-std=c++2a -fcontracts" } struct T; int both(int x, T *t) [[ pre: x > 0 ]] { return 0; } int both2(int x, T *t) [[ pre: x > 0 ]]; template<typename Z> int fn(int x, Z *z) [[ pre: x > 0 ]]; template<typename Z> int fn2(int x, Z *z); template<typename Z> int fn3(int x, Z *z) [[ pre: x > 0 ]]; template<> int fn3<T>(int x, T *z) [[ pre: x > 1 ]]; struct T { friend int both2(int x, T *t) [[ pre: x > 1 ]] // { dg-error "mismatched" } { return 0; } friend int hidden(int x, T *t) [[ pre: x > 1 ]] [[ pre: t->pri > 0 ]] { return x; } /* cannot define friend spec, so we never get to matching contracts friend int fn<T>(int x, T *t) [[ pre: t->pri > 0 ]] { return 0; } // error defining explicit spec friend */ // bad, general contracts must match general template<typename Z> friend int fn(int x, Z *z) [[ pre: z->pri > 1 ]] { return 0; } // { dg-error "mismatched" } // fine, can add contracts template<typename Z> friend int fn2(int x, Z *z) [[ pre: z->pri > 1 ]] { return 0; } // { dg-bogus "mismatched" } /* cannot declare without definition, so dup friend can't occur: friend int dup(int x, T *t) [[ pre: t->pri > 0 ]]; // error non-defining friend with contracts friend int dup(int x, T *t) [[ pre: t->pri > 1 ]]; // error non-defining friend with contracts */ int x{1}; private: int pri{-10}; }; int hidden(int x, T *t) [[ pre: x > 0 ]] [[ pre: t->pri > 1 ]]; // { dg-error "mismatched" }