Bug 3174 – ICE(mtype.c): Compiler crash or compiler error with auto returns and const / immutable / invarient / pure

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86
OS
Windows
Creation time
2009-07-14T10:16:00Z
Last change time
2015-06-09T01:28:06Z
Keywords
ice-on-valid-code, patch, rejects-valid
Assigned to
nobody
Creator
sandford

Comments

Comment #0 by sandford — 2009-07-14T10:16:54Z
DMD either crashes or fails to compile a auto return function marked const/immutable or invarient class A { const foo(int i) { return i; } // DMD crash const auto foo(int i) { return i; } // DMD crash pure auto foo(int i) { return i; } // Okay auto foo(int i) pure { return i; } // Fails to compile foo(int i) const { return i; } // Fails to compile auto foo(int i) const { return i; } // Fails to compile } void main(char[][] args) { const A a = new A(); a.foo(5); return; } Errors for auto foo(int i) const { return i; } (line 146) main.d(147): found 'int' when expecting ')' main.d(147): no identifier for declarator foo main.d(147): semicolon expected, not 'i' main.d(147): no identifier for declarator i main.d(147): semicolon expected, not ')' main.d(147): Declaration expected, not ')' main.d(148): unrecognized declaration The issues using const also apply to immutable / invarient. DMD Crash: Unhandled exception at 0x00410ba3 in dmd.exe: 0xC0000005: Access violation reading location 0x00000000. inside mytype.c, at line 3800: void TypeFunction::toDecoBuffer(OutBuffer *buf, int flag) { unsigned char mc; //printf("TypeFunction::toDecoBuffer() this = %p %s\n", this, toChars()); //static int nest; if (++nest == 50) *(char*)0=0; if (inuse) { inuse = 2; // flag error to caller return; } inuse++; #if 1 if (mod & MODshared) buf->writeByte('O'); if (mod & MODconst) buf->writeByte('x'); else if (mod & MODinvariant) buf->writeByte('y'); #endif switch (linkage) { case LINKd: mc = 'F'; break; case LINKc: mc = 'U'; break; case LINKwindows: mc = 'W'; break; case LINKpascal: mc = 'V'; break; case LINKcpp: mc = 'R'; break; default: assert(0); } buf->writeByte(mc); if (ispure || isnothrow || isref) { if (ispure) buf->writestring("Na"); if (isnothrow) buf->writestring("Nb"); if (isref) buf->writestring("Nc"); } // Write argument types Argument::argsToDecoBuffer(buf, parameters); //if (buf->data[buf->offset - 1] == '@') halt(); buf->writeByte('Z' - varargs); // mark end of arg list next->toDecoBuffer(buf); Watch reports next is null this 0x076471c4 TypeFunction::toDecoBuffer::buf 0x0012faa4 TypeFunction::toDecoBuffer::mc 70 'F' TypeFunction::toDecoBuffer::flag 0 Call Stack: > dmd.exe!TypeFunction::toDecoBuffer(OutBuffer*,int )() Line 3800 + 0x8 bytes C++ dmd.exe!Type::merge()() Line 1122 C++ dmd.exe!FuncDeclaration::semantic(Scope*)() Line 165 + 0x7 bytes C++ dmd.exe!ClassDeclaration::semantic(Scope*)() Line 596 C++ dmd.exe!Module::semantic()() Line 675 C++ dmd.exe!main() Line 1057 C++ dmd.exe!_mainCRTStartup() + 0xa9 bytes kernel32.dll!7c816fe7()
Comment #1 by clugdbug — 2009-10-02T00:08:13Z
There are actually 2 independent bugs here. My patch only deals with the ICE. I've created bug 3359 for the parsing failure. CAUSE: It's trying to do type->deco->merge() on a function, when it doesn't yet know the return type. merge() is never done on plain auto functions, which is why the thrid case doesn't segfault. COMMENT: mtype.c, TypeFunction::toDecoBuffer() desperately needs an assert(next); to generate an ICE instead of a segfault. I have seen at least five different bugs that crash there. PATCH: I've done this by copy-and-paste, you probably want to reorganize this function a bit to avoid duplication. This makes 'const' functions behave the same as 'auto' -- but actually plain 'auto' functions suffer from the other bugs, I think because the merge() never happens. Index: func.c =================================================================== --- func.c (revision 75) +++ func.c (working copy) @@ -144,6 +144,13 @@ * to the function type */ type = type->semantic(loc, sc); + if (type->ty != Tfunction) + { + error("%s must be a function", toChars()); + return; + } + f = (TypeFunction *)(type); + unsigned stc = storage_class; if (type->isInvariant()) stc |= STCimmutable; @@ -159,22 +166,22 @@ case STCimmutable | STCshared: // Don't use toInvariant(), as that will do a merge() type = type->makeInvariant(); - type->deco = type->merge()->deco; + if (f->next) type->deco = type->merge()->deco; break; case STCconst: type = type->makeConst(); - type->deco = type->merge()->deco; + if (f->next) type->deco = type->merge()->deco; break; case STCshared | STCconst: type = type->makeSharedConst(); - type->deco = type->merge()->deco; + if (f->next) type->deco = type->merge()->deco; break; case STCshared: type = type->makeShared(); - type->deco = type->merge()->deco; + if (f->next) type->deco = type->merge()->deco; break; case 0:
Comment #2 by bugzilla — 2009-10-13T13:46:05Z
Fixed dmd 1.049 and 2.034