diff --git a/src/dmd/declaration.d b/src/dmd/declaration.d index ca3378d1e641..1c8e00cbd976 100644 --- a/src/dmd/declaration.d +++ b/src/dmd/declaration.d @@ -315,6 +315,20 @@ extern (C++) abstract class Declaration : Dsymbol } } + if (e1 && e1.op == TOKthis && isField()) + { + VarDeclaration vthis = (cast(ThisExp)e1).var; + for (Scope* scx = sc; scx; scx = scx.enclosing) + { + if (scx.func == vthis.parent && (scx.flags & SCOPEcontract)) + { + if (!flag) + error(loc, "cannot modify parameter 'this' in contract"); + return 2; // do not report type related errors + } + } + } + if (v && (isCtorinit() || isField())) { // It's only modifiable if inside the right constructor diff --git a/src/dmd/semantic3.d b/src/dmd/semantic3.d index f528623354d0..1632a07f6a17 100644 --- a/src/dmd/semantic3.d +++ b/src/dmd/semantic3.d @@ -885,7 +885,6 @@ private extern(C++) final class Semantic3Visitor : Visitor sc2.flags = (sc2.flags & ~SCOPEcontract) | SCOPErequire; // BUG: need to error if accessing out parameters - // BUG: need to treat parameters as const // BUG: need to disallow returns and throws // BUG: verify that all in and ref parameters are read freq = freq.statementSemantic(sc2); @@ -908,7 +907,6 @@ private extern(C++) final class Semantic3Visitor : Visitor sc2 = scout; //push sc2.flags = (sc2.flags & ~SCOPEcontract) | SCOPEensure; - // BUG: need to treat parameters as const // BUG: need to disallow returns and throws if (funcdecl.fensure && f.next.ty != Tvoid) diff --git a/test/fail_compilation/fail18143.d b/test/fail_compilation/fail18143.d new file mode 100644 index 000000000000..2d0f0018afa1 --- /dev/null +++ b/test/fail_compilation/fail18143.d @@ -0,0 +1,43 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/fail18143.d(20): Error: variable fail18143.S.a cannot modify parameter 'this' in contract +fail_compilation/fail18143.d(21): Error: variable fail18143.S.a cannot modify parameter 'this' in contract +fail_compilation/fail18143.d(25): Error: variable fail18143.S.a cannot modify parameter 'this' in contract +fail_compilation/fail18143.d(26): Error: variable fail18143.S.a cannot modify parameter 'this' in contract +fail_compilation/fail18143.d(35): Error: variable fail18143.C.a cannot modify parameter 'this' in contract +fail_compilation/fail18143.d(36): Error: variable fail18143.C.a cannot modify parameter 'this' in contract +fail_compilation/fail18143.d(40): Error: variable fail18143.C.a cannot modify parameter 'this' in contract +fail_compilation/fail18143.d(41): Error: variable fail18143.C.a cannot modify parameter 'this' in contract +--- +*/ + +struct S +{ + int a; + + this(int n) + in { a = n; } // error, modifying this.a in contract + out { a = n; } // error, modifying this.a in contract + do { } + + void foo(int n) + in { a = n; } // error, modifying this.a in contract + out { a = n; } // error, modifying this.a in contract + do { } +} + +class C +{ + int a; + + this(int n) + in { a = n; } // error, modifying this.a in contract + out { a = n; } // error, modifying this.a in contract + do { } + + void foo(int n) + in { a = n; } // error, modifying this.a in contract + out { a = n; } // error, modifying this.a in contract + do { } +}