Bug 2206 – unnamed template mixin of class inside function or class has incorrect classinfo and mangleof
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D1 (retired)
Platform
x86
OS
Linux
Creation time
2008-07-08T14:16:00Z
Last change time
2014-02-24T15:32:04Z
Keywords
patch, wrong-code
Assigned to
bugzilla
Creator
kamm-removethis
Comments
Comment #0 by kamm-removethis — 2008-07-08T14:16:52Z
Test:
--
template T() {
class C {}
}
void main()
{
mixin T!(); // using a named mixin here fixes it
pragma(msg, T!().C.mangleof);
pragma(msg, C.mangleof); // incorrectly outputs the same as above
assert(T!().C.classinfo !is C.classinfo); // fails
assert(T!().C.mangleof != C.mangleof); // fails
}
--
The types of T!().C and main.C are clearly different as the nested one carries an additional context pointer. This means that allocation relying on classinfo.init.length should be wrong too.
In the frontend the types are initially different and only merged into a single type during semantic. To be specific, Type::mangle unifies them as toDecoBuffer yields the same result for both.
Maybe this could be fixed by adding a TemplateMixin::mangle overload. This frontend bug causes some template-mixin related bugs in LLVMDC that seem to be worked around somehow in DMD.
Comment #1 by kamm-removethis — 2008-07-08T14:37:13Z
To illustrate the resulting problem with class allocation:
--
import std.stdio;
class D {}
template T() {
class C { this() { } }
}
void main()
{
mixin T!();
// all print 8
writefln(T!().C.classinfo.init.length);
writefln(C.classinfo.init.length);
writefln(D.classinfo.init.length);
auto c = new C; // segfault in _d_newclass
}
Comment #2 by kamm-removethis — 2008-07-09T09:58:58Z
Adding the following override for TemplateMixin::mangle seems to have fixed the issue in LLVMDC:
--
char *TemplateMixin::mangle()
{
OutBuffer buf;
char *id;
#if 0
printf("TemplateMixin::mangle() %s", toChars());
if (parent)
printf(" parent = %s %s", parent->kind(), parent->toChars());
printf("\n");
#endif
id = ident ? ident->toChars() : toChars();
// use parent instead of tempdecl->parent here
if (parent)
{
char *p = parent->mangle();
if (p[0] == '_' && p[1] == 'D')
p += 2;
buf.writestring(p);
}
buf.printf("%"PRIuSIZE"%s", strlen(id), id);
id = buf.toChars();
buf.data = NULL;
//printf("TemplateMixin::mangle() %s = %s\n", toChars(), id);
return id;
}
--