D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 3602 - ICE(tocsym.c) compiling a class, if its super class has preconditions
Summary: ICE(tocsym.c) compiling a class, if its super class has preconditions
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D1 (retired)
Hardware: All All
: P2 regression
Assignee: No Owner
URL:
Keywords: ice-on-valid-code, patch
: 4055 (view as issue list)
Depends on:
Blocks: 340
  Show dependency treegraph
 
Reported: 2009-12-08 08:44 UTC by Qian Xu
Modified: 2017-10-01 20:41 UTC (History)
6 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Qian Xu 2009-12-08 08:44:14 UTC
Dear Developers,

I see an error message while dmd tries to compile a class:

========= ERROR =========
Box.d(7): Error: function __require forward declaration
linkage = 0
dmd: tocsym.c:381: virtual Symbol* FuncDeclaration::toSymbol(): Assertion `0' failed.
Aborted
========= ERROR =========



dmd: tocsym.c:381: virtual Symbol* FuncDeclaration::toSymbol(): Assertion `0' failed.
Comment 1 Qian Xu 2009-12-08 08:49:26 UTC
Sorry for the first commit. The description is incomplete.

Now the part 2:

I have two classes as follows:

====== FILE: Box.d ======
module Box;
class Box {
   void paint(int x, int y)
   in {
       assert(x > 0);
       assert(y > 0);
   }
   body {
   }
}
====== FILE: Box.d ======

====== FILE: ImageBox.d ======
module ImageBox;
class ImageBox: Box {
   void override paint(int x, int y)
   in {
       assert(x > 0);
       assert(y > 0);
   }
   body {
   }
}
====== FILE: ImageBox.d ======

I compile the Box.d using "dmd -w -debug -inline -version=Posix -version=Tango Box.d -c", it works.
And then I compile the ImageBox.d using "dmd -w -debug -inline -version=Posix -version=Tango ImageBox.d -c", the dmd compile returns an error.
========= ERROR =========
Box.d(7): Error: function __require forward declaration
linkage = 0
dmd: tocsym.c:381: virtual Symbol* FuncDeclaration::toSymbol(): Assertion `0'
failed.
Aborted
========= ERROR =========


Note that if I write "private" before this method paint, it works. 


I think this issue is pretty critical, now I have to remove all preconditions in my super classes.
Comment 2 Don 2010-01-27 00:46:38 UTC
This is crashing because the contracts are implemented as functions fdrequire,
fdensure, which are NESTED functions of the function ('paint()') being called.
fdrequire->semantic() and fdensure->semantic() need to be run before code generation of the overridden function.

Because they're nested functions, fdrequire->semantic() is called when running semantic3() on 'box.paint()'.
But, if because box.paint() was only imported, box.paint()->semantic3() never gets run!

To fix the bug, we need to make sure that fdrequire->semantic() does get called sometime before code generation. I've tried running it immediately after fdrequire is created; that allows the test case to compile when the two modules are compiled separately, but it causes a different ICE when they are compiled together. I also tried running semantic() from inside mergeRequire(), but I wasn't successful.
Comment 3 Robert Clipsham 2010-04-03 05:18:21 UTC
*** Issue 4055 has been marked as a duplicate of this issue. ***
Comment 4 Stewart Gordon 2010-06-14 18:30:05 UTC
The given testcase is invalid.  However, by fixing the errors, it's reproducible under Windows:

----- imagebox.d -----
module imagebox;
import box;

class ImageBox: Box {
   override void paint(int x, int y)
   in {
       assert(x > 0);
       assert(y > 0);
   }
   body {
   }
}
----- box.d -----
module box;
class Box {
   void paint(int x, int y)
   in {
       assert(x > 0);
       assert(y > 0);
   }
   body {
   }
}
----------
C:\Users\Stewart\Documents\Programming\D\Tests\bugs\bz3602>dmd -c imagebox.d
box.d(5): Error: function __require forward declaration
linkage = 0
Assertion failure: '0' on line 381 in file 'tocsym.c'

abnormal program termination
----------

This has broken SDWF.
Comment 5 Don 2010-06-15 00:00:53 UTC
(In reply to comment #4)
> The given testcase is invalid.  However, by fixing the errors, it's
> reproducible under Windows.

?? I had no trouble reproducing it under Windows.
Until around DMD 1.050, it used to compile, but that was only because contract inheritance was silently ignored. This code has never worked properly. OTOH I agree that it has the importance of a regression.
Comment 6 Stewart Gordon 2010-06-15 01:39:17 UTC
(In reply to comment #5)
> (In reply to comment #4)
> > The given testcase is invalid.  However, by fixing the errors, it's
> > reproducible under Windows.
> 
> ?? I had no trouble reproducing it under Windows.
> Until around DMD 1.050, it used to compile, but that was only because contract
> inheritance was silently ignored. This code has never worked properly. OTOH I
> agree that it has the importance of a regression.

That's very weird.  How did it use to handle the fact that Box is an undefined symbol in ImageBox.d?
Comment 7 bearophile_hugs 2010-06-15 02:47:30 UTC
I have not seen the ICE but this asserts (v2.047 with warnings):


class A {
   void foo(int x)
       in {
           assert(x > 0); // asserts
       } body {}
}
class B : A {
   override void foo(int y) {}
}
void main() {
    auto b = new B;
    b.foo(10);
}
Comment 8 Stewart Gordon 2010-06-15 02:52:55 UTC
(In reply to comment #7)
>            assert(x > 0); // asserts

Could hardly state the obvious more - unless there was something else you meant to say....
Comment 9 Don 2010-09-15 05:15:58 UTC

PATCH: func.c, line 1658, FuncDeclaration::mergeFrequire()
----------------

    for (int i = 0; i < foverrides.dim; i++)
    {
        FuncDeclaration *fdv = (FuncDeclaration *)foverrides.data[i];
+        /* The semantic pass on the contracts of the overridden functions must
+         * be completed before code generation occurs (bug 3602).
+        */
+        if (fdv->fdrequire && fdv->fdrequire->semanticRun != PASSsemantic3done)
+        {
+            assert(fdv->scope);
+            fdv->semantic3(fdv->scope);
+        }
        sf = fdv->mergeFrequire(sf);
        if (fdv->fdrequire)
        {
            //printf("fdv->frequire: %s\n", fdv->frequire->toChars());
Comment 10 Walter Bright 2010-09-22 06:24:00 UTC
http://www.dsource.org/projects/dmd/changeset/683
Comment 11 github-bugzilla 2017-09-25 21:23:15 UTC
Commit pushed to stable at https://github.com/dlang/dmd

https://github.com/dlang/dmd/commit/b79c250bc27659274aa3a93473cd8f550738e3ad
Handle bug 3602 and 5230, add tests for them.
Comment 12 github-bugzilla 2017-10-01 20:41:08 UTC
Commit pushed to master at https://github.com/dlang/dmd

https://github.com/dlang/dmd/commit/b79c250bc27659274aa3a93473cd8f550738e3ad
Handle bug 3602 and 5230, add tests for them.