digitalmars.D.bugs - [Issue 1978] New: Wrong vtable call
- d-bugmail puremagic.com (154/154) Apr 08 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1978
- d-bugmail puremagic.com (79/79) Apr 08 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1978
- d-bugmail puremagic.com (4/4) Apr 08 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1978
- d-bugmail puremagic.com (28/28) Apr 08 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1978
- d-bugmail puremagic.com (9/9) May 11 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1978
http://d.puremagic.com/issues/show_bug.cgi?id=1978
Summary: Wrong vtable call
Product: D
Version: 1.028
Platform: PC
OS/Version: All
Status: NEW
Severity: critical
Priority: P2
Component: DMD
AssignedTo: bugzilla digitalmars.com
ReportedBy: benoit tionex.de
In the following example, the program block if compiled with -g and dmd
1.026/1.028. See the comments, there are 3 possiblilities of changes, which
should not change behaviour, but does make this program work.
I tested this only on tango. Can someone confirm this bug also on phobos? and
D2?
extern(C) int printf(char*,...);
public interface View(T){
// changing duplicate return type to View!(T) make it work
public Dispenser!(T) duplicate ();
public uint size ();
public uint mutation ();
public int opApply (int delegate (inout T value) dg);
}
public interface Dispenser(T) : View!(T){
public void removeAll (Iterator!(T) e);
public void remove (Iterator!(T) e);
public void removeAll (T element);
public void remove (T element);
}
public interface Seq(T) :
View!(T), // removing View!(T) interface make it work.
Dispenser!(T)
{
public T get(int index);
public alias get opIndex;
}
public interface Iterator(V) {
public bool more();
public V get();
int opApply (int delegate (inout V value) dg);
}
public interface GuardIterator(V) : Iterator!(V){
public uint remaining();
}
public abstract class AbstractIterator(T) : GuardIterator!(T) {
private View!(T) view;
private uint mutation;
private uint togo;
protected this (View!(T) v) {
view = v;
togo = v.size();
mutation = v.mutation();
}
public final uint remaining() {
return togo;
}
public final bool more() {
return togo > 0 && mutation is view.mutation;
}
protected final void decRemaining() {
--togo;
}
}
class ArrayIterator(T) : AbstractIterator!(T)
{
private int row;
private T[] array;
public this (ArraySeq!(T) seq) {
super (seq);
array = seq.array;
}
public final T get() {
decRemaining();
return array[row++];
}
int opApply (int delegate (inout T value) dg) {
int result;
for (auto i=remaining(); i--;)
{
auto value = get();
if ((result = dg(value)) != 0)
break;
}
return result;
}
}
public abstract class Collection(T) : Dispenser!(T)
{
alias View!(T) ViewT;
protected uint count;
public final uint size() {
return count;
}
public final uint mutation() {
return 0;
}
abstract void removeAll(T element);
abstract void remove (T element);
abstract void removeAll (Iterator!(T) e);
abstract void remove (Iterator!(T) e);
}
public abstract class SeqCollection(T) : Collection!(T), Seq!(T) {
public abstract override void remove(T it);
public abstract override void removeAll(T it);
public void removeAll (Iterator!(T) e) {
while (e.more)
removeAll (e.get);
}
public void remove (Iterator!(T) e) {
while (e.more)
remove (e.get);
}
}
public class ArraySeq(T) : SeqCollection!(T), Dispenser!(T) {
public static int minCapacity = 16;
package T array[];
public this () {
this ( null, 0);
}
package this (T[] b, int c) {
array = b;
count = c;
}
public final Dispenser!(T) duplicate() {
return null;
}
int opApply (int delegate (inout T value) dg){
auto scope iterator = new ArrayIterator!(T)(this);
return iterator.opApply (dg);
}
public final T get(int index){
return array[index];
}
public final override void remove(T element){}
public final override void removeAll(T element){}
public void remove(Iterator!(T) it){
super.remove(it);
}
public void removeAll(Iterator!(T) it){
super.removeAll(it);
}
}
// removing this variable decl will make it work
Seq!(Object) seq;
void main(){
auto alist = new ArraySeq!(Object);
foreach( el; alist ){
printf( "shall not come here.\n" );
}
printf( "ready\n" );
}
--
Apr 08 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1978
I reduced it more...
Now the example prints:
remove
ready
It does not block, but remove() is called without call.
extern(C) int printf(char*,...);
public interface View(T){
// changing duplicate return type to View!(T) make it work
public Dispenser!(T) duplicate ();
public uint mutation ();
}
public interface Dispenser(T) : View!(T){
public void removeAll (Iterator!(T) e);
public void remove (Iterator!(T) e);
public void removeAll (T element);
public void remove (T element);
}
public interface Seq(T) :
View!(T), // removing View!(T) interface make it work.
Dispenser!(T)
{
}
public interface Iterator(V) {
int opApply (int delegate (inout V value) dg);
}
public abstract class AbstractIterator(T) : Iterator!(T) {
protected this (View!(T) v) {
v.mutation();
}
}
class ArrayIterator(T) : AbstractIterator!(T) {
public this (ArraySeq!(T) seq) {
super (seq);
}
int opApply (int delegate (inout T value) dg) {
return 0;
}
}
public abstract class Collection(T) : Dispenser!(T)
{
public final uint mutation() {
return 0;
}
}
// removing this intermediate class makes it work
public abstract class SeqCollection(T) : Collection!(T), Seq!(T) {
}
public class ArraySeq(T) : SeqCollection!(T)
, Dispenser!(T) // removing this makes it work, dispenser is already
derived from SeqCollection
{
//
public final Dispenser!(T) duplicate() {
return null;
}
public final override void remove(T element){}
public final override void removeAll(T element){}
public void removeAll (Iterator!(T) e) {
printf( "removeAll\n" );
}
public void remove (Iterator!(T) e) {
printf( "remove\n" );
}
}
//import tango.util.collection.model.Seq;
//import tango.util.collection.ArraySeq;
// removing this variable decl will make it work
Seq!(Object) seq;
void main(){
auto alist = new ArraySeq!(Object);
auto scope iterator = new ArrayIterator!(Object)(alist);
foreach( el; iterator ){
printf( "shall not come here.\n" );
}
printf( "ready\n" );
}
--
Apr 08 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1978 I verified the bug with dmd 1.028 and 2.012 with phobos. --
Apr 08 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1978
kamm-removethis incasoftware.de changed:
What |Removed |Added
----------------------------------------------------------------------------
Keywords| |wrong-code
-------
Further simplification:
extern(C) int printf(char*,...);
interface InterfaceB(T) : InterfaceA {}
interface InterfaceA{
// changing return type to InterfaceA makes it work
InterfaceB!(Object) func ();
}
class Foo(T) : InterfaceB!(T) {
InterfaceB!(Object) func() {
return null;
}
}
void main() {
auto foo = new Foo!(Object);
// without this call, segfault is gone
foo.func();
printf("foo.func() call passed\n");
InterfaceA ifA = foo;
assert(ifA !is null);
ifA.func(); // segfault
}
--
Apr 08 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1978
bugzilla digitalmars.com changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|NEW |RESOLVED
Resolution| |FIXED
Fixed dmd 1.029 and 2.013
--
May 11 2008









d-bugmail puremagic.com 