Bug 17819 – static foreach segfaults on __traits(allMembers)

Status
RESOLVED
Resolution
FIXED
Severity
major
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2017-09-09T20:50:12Z
Last change time
2018-06-03T18:30:14Z
Assigned to
No Owner
Creator
Jean-Louis Leroy
See also
https://issues.dlang.org/show_bug.cgi?id=18718

Comments

Comment #0 by jl — 2017-09-09T20:50:12Z
Given: // staticforeach.d import std.traits; static foreach (m; __traits(allMembers, staticforeach)) { pragma(msg, m.stringof); } Try to compile: $ dmd staticforeach.d Segmentation fault (core dumped) $ dmd --version DMD64 D Compiler v2.076.0-dirty Copyright (c) 1999-2017 by Digital Mars written by Walter Bright
Comment #1 by jl — 2018-01-10T20:50:41Z
The bug is still present in 2.078.
Comment #2 by jl — 2018-02-23T20:10:25Z
Still present in v2.078.3 - it seems that no one is looking into this.
Comment #3 by bitter.taste — 2018-03-11T18:01:23Z
There's a stack overflow in Dsymbol's _foreach, every time it recurses into a AttribDeclaration (such as the `static foreach') the stack gets deeper until it explodes.
Comment #4 by greensunny12 — 2018-04-05T03:35:27Z
Not really a fix, but a start https://github.com/dlang/dmd/pull/8125
Comment #5 by greensunny12 — 2018-04-06T02:54:26Z
Comment #6 by timon.gehr — 2018-05-02T17:57:06Z
This is not really a `static foreach` issue, but rather a general issue with how DMD handles (or rather, does not handle) circular dependencies. The following code runs into the same problem: --- module c; static if(__traits(allMembers,__traits(parent,{}))[0]=="c"){} --- Here, DMD explicitly catches the infinite recursion and prints: c.d(3): Error: error evaluating `static if` expression (The code that does this has a bug in it, therefore the error message is not useful: if (exp.op == TOK.error || nest > 100) { error(loc, (nest > 1000) ? "unresolvable circular `static if` expression" : "error evaluating `static if` expression"); return errorReturn(); } ) It is trivial to apply a similar "fix" for `static foreach`, but I doubt this is what Jean-Louis had in mind. Interestingly enough, this "works" with string mixins: module c; mixin("enum "~__traits(allMembers,c)[1]~"2 = 2;"); int x; pragma(msg, x2); pragma(msg, __traits(allMembers,c)[1]); (Clearly, the code actually has no reasonable interpretation, but DMD still successfully compiles it.) This is because `CompileDeclaration.include` just returns null. I can "fix" the `static foreach` case by returning "null" in case a call to "include" is already on the stack. In fact, I could do the same to the `static if` case to make that "work" too.
Comment #7 by timon.gehr — 2018-05-02T19:14:24Z
*** Issue 18718 has been marked as a duplicate of this issue. ***
Comment #8 by timon.gehr — 2018-05-02T20:48:55Z
Comment #9 by github-bugzilla — 2018-06-03T18:29:59Z
Commits pushed to master at https://github.com/dlang/dmd https://github.com/dlang/dmd/commit/ebbd8e92b61bcf05df443b62deeff0786581067c fix Issue 17819 - static foreach segfaults on __traits(allMembers) https://github.com/dlang/dmd/commit/b625e01f4464768d0e7b1b8119d8f6ca3543efa1 Merge pull request #8213 from tgehr/fix17819 fix Issue 17819 - static foreach segfaults on __traits(allMembers) merged-on-behalf-of: Razvan Nitu <[email protected]>