Skip to content

Commit

Permalink
Merge pull request #7543 from ibuclaw/reg12901
Browse files Browse the repository at this point in the history
Re-fix Issue 12901 in/out contracts on struct constructor must require function body
merged-on-behalf-of: Mike Franklin <JinShil@users.noreply.github.com>
  • Loading branch information
dlang-bot committed Dec 30, 2017
2 parents a6d8665 + f8b5246 commit d0a0b9b
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 12 deletions.
36 changes: 25 additions & 11 deletions src/dmd/dsymbolsem.d
Expand Up @@ -151,6 +151,28 @@ const(char)* getMessage(DeprecatedDeclaration dd)
return dd.msgstr;
}

// Returns true if a contract can appear without a function body.
package bool allowsContractWithoutBody(FuncDeclaration funcdecl)
{
assert(!funcdecl.fbody);

/* Contracts can only appear without a body when they are virtual
* interface functions or abstract.
*/
Dsymbol parent = funcdecl.toParent();
InterfaceDeclaration id = parent.isInterfaceDeclaration();

if (!funcdecl.isAbstract() &&
(funcdecl.fensure || funcdecl.frequire) &&
!(id && funcdecl.isVirtual()))
{
auto cd = parent.isClassDeclaration();
if (!(cd && cd.isAbstract()))
return false;
}
return true;
}

private extern(C++) final class DsymbolSemanticVisitor : Visitor
{
alias visit = Visitor.visit;
Expand Down Expand Up @@ -3149,16 +3171,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// Reflect this.type to f because it could be changed by findVtblIndex
f = funcdecl.type.toTypeFunction();

/* Contracts can only appear without a body when they are virtual interface functions or abstract
*/
if (!funcdecl.fbody && !funcdecl.isAbstract() &&
(funcdecl.fensure || funcdecl.frequire) &&
!(id && funcdecl.isVirtual()))
{
auto cd = parent.isClassDeclaration();
if (!(cd && cd.isAbstract()))
funcdecl.error("in and out contracts on non-virtual/non-abstract functions require function body");
}
Ldone:
if (!funcdecl.fbody && !funcdecl.allowsContractWithoutBody())
funcdecl.error("in and out contracts can only appear without a body when they are virtual interface functions or abstract");

/* Do not allow template instances to add virtual functions
* to a class.
Expand Down Expand Up @@ -3189,7 +3204,6 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (funcdecl.isMain())
funcdecl.checkDmain(); // Check main() parameters and return type

Ldone:
/* Purity and safety can be inferred for some functions by examining
* the function body.
*/
Expand Down
2 changes: 1 addition & 1 deletion src/dmd/semantic3.d
Expand Up @@ -1074,7 +1074,7 @@ extern(C++) final class Semantic3Visitor : Visitor
}

// If declaration has no body, don't set sbody to prevent incorrect codegen.
if (funcdecl.fbody || funcdecl.fdensure || funcdecl.fdrequire)
if (funcdecl.fbody || funcdecl.allowsContractWithoutBody())
funcdecl.fbody = sbody;
}

Expand Down
14 changes: 14 additions & 0 deletions test/fail_compilation/fail12901.d
@@ -0,0 +1,14 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail12901.d(11): Error: constructor fail12901.S.this in and out contracts can only appear without a body when they are virtual interface functions or abstract
---
*/

struct S
{
int a;
this(int n)
in { a = n; }
// no body
}

0 comments on commit d0a0b9b

Please sign in to comment.