Bug 19668 – Using init instead of construction causes crash if type is parameterized on alias to function that accesses frame
Status
RESOLVED
Resolution
INVALID
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2019-02-11T18:15:45Z
Last change time
2023-01-09T15:33:55Z
Keywords
wrong-code
Assigned to
No Owner
Creator
Ali Ak
Comments
Comment #0 by ali.akhtarzada — 2019-02-11T18:15:45Z
The following code causes a crash at runtime:
struct S(alias fun) {
auto call(Args...)(Args args) {
return fun(args);
}
static auto construct() {
auto a = typeof(this).init; // 1
return a;
}
}
void main() {
int count = 0;
auto func() {
return count++; // 2
}
auto s = S!func.construct; // 3
s.call(); // crashes
}
@1 if you change it to S!fun you get a compiler Error: cannot access frame pointer of onlineapp.main.S!(func).S.
@2 if you remove the "count" variable access from inside func, and just return some literal, then there's no crash (no frame pointer access)
@3 if you don't use construct and just call S!func() then s.call doesn't crash (frame pointer is accessed fine in this case??)
It seems like a regression from dmd version 2.071.2 since it gave a compiler error from 2.061 up till 2.071.2
Up to 2.060 : Failure with output: --- killed by signal 11
2.061 to 2.071.2: Failure with output:
-----
onlineapp.d(5): Error: function onlineapp.main.S!(func).S.call!().call cannot access frame of function D main
onlineapp.d(20): Error: template instance onlineapp.main.S!(func).S.call!() error instantiating
-----
Since 2.072.2: Failure with output: Error: program killed by signal 11
Comment #1 by ali.akhtarzada — 2019-02-11T18:51:35Z
Actually you don't need a static func. This crashes:
struct S(alias fun) {
auto call(Args...)(Args args) {
return fun(args);
}
}
auto construct(alias fun)() {
auto a = S!fun.init; // 1
return a;
}
void main() {
int count = 0;
auto func() { return count++; }
auto s = construct!func;
s.call(); // crashes
}
And if you change @1 to "auto a = S!fun();" then all is well.
Comment #2 by nick — 2023-01-09T15:33:55Z
main.func captures a runtime variable `count` whose address is not known at compile-time. S.init must be known at compile-time. So using S.init will cause a null context pointer for func instead of one pointing to main.count. You need to call S's constructor, not use S.init.