Skip to content

Commit

Permalink
Merge pull request #9467 from RazvanN7/Issue_19731
Browse files Browse the repository at this point in the history
Fix Issue 19731 - auto struct methods whose address is taken don't test invariants
merged-on-behalf-of: Nicholas Wilson <thewilsonator@users.noreply.github.com>
  • Loading branch information
dlang-bot committed Mar 20, 2019
2 parents 9df3761 + 3f52528 commit 3a298e5
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 0 deletions.
40 changes: 40 additions & 0 deletions src/dmd/dsymbolsem.d
Expand Up @@ -4212,6 +4212,42 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
funcDeclarationSemantic(deld);
}

/* https://issues.dlang.org/show_bug.cgi?id=19731
*
* Some aggregate member functions might have had
* semantic 3 ran on them despite being in semantic1
* (e.g. auto functions); if that is the case, then
* invariants will not be taken into account for them
* because at the time of the analysis it would appear
* as if the struct declaration does not have any
* invariants. To solve this issue, we need to redo
* semantic3 on the function declaration.
*/
private void reinforceInvariant(AggregateDeclaration ad, Scope* sc)
{
// for each member
for(int i = 0; i < ad.members.dim; i++)
{
if (!(*ad.members)[i])
continue;
auto fd = (*ad.members)[i].isFuncDeclaration();
if (!fd || fd.generated || fd.semanticRun != PASS.semantic3done)
continue;

/* if it's a user defined function declaration and semantic3
* was already performed on it, create a syntax copy and
* redo the first semantic step.
*/
auto err = global.startGagging();
auto fd_temp = fd.syntaxCopy(null);
if (auto cd = ad.isClassDeclaration())
cd.vtbl.remove(fd.vtblIndex);
fd_temp.dsymbolSemantic(sc);
global.endGagging(err);
(*ad.members)[i] = fd_temp;
}
}

override void visit(StructDeclaration sd)
{
//printf("StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok);
Expand Down Expand Up @@ -4359,6 +4395,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
}

sd.inv = buildInv(sd, sc2);
if (sd.inv)
reinforceInvariant(sd, sc2);

Module.dprogress++;
sd.semanticRun = PASS.semanticdone;
Expand Down Expand Up @@ -4983,6 +5021,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
}

cldec.inv = buildInv(cldec, sc2);
if (cldec.inv)
reinforceInvariant(cldec, sc2);

Module.dprogress++;
cldec.semanticRun = PASS.semanticdone;
Expand Down
53 changes: 53 additions & 0 deletions test/runnable/test19731.d
@@ -0,0 +1,53 @@
// PERMUTE_ARGS:
struct Foo
{
Object obj_;

invariant (obj_ !is null);

auto obj7()
{
return this.obj_;
}

enum compiles = __traits(compiles, &Foo.init.obj7);
}

class Foo2
{
Object obj_;

invariant (obj_ !is null);

final auto obj7()
{
return this.obj_;
}

enum compiles = __traits(compiles, &Foo.init.obj7);
}

void main()
{
import core.exception : AssertError;
Foo foo = Foo();
Foo2 foo2 = new Foo2();

try
{
foo.obj7.toString();
}
catch(AssertError)
{
try
{
foo2.obj7.toString();
}
catch(AssertError)
{
return;
}
assert(0);
}
assert(0);
}

0 comments on commit 3a298e5

Please sign in to comment.