June 16, 2018
https://issues.dlang.org/show_bug.cgi?id=18026

--- Comment #11 from JR <zorael@gmail.com> ---
(In reply to ag0aep6g from comment #10)
> Fails a bit less reliably, but still 7 out of 10 times.
I can't reproduce your snippet, which confirms that it's inconsistent on different setups on different machines.

Updated my best dustmite to also segfault ldc on non-Windows (66 lines):
> git clone https://github.com/zorael/kameloso.git -b 2080-overflow1-ldc

Posted as https://forum.dlang.org/post/adigkdqzuuzptujxftui@forum.dlang.org.

--
June 16, 2018
https://issues.dlang.org/show_bug.cgi?id=18026

Stefan Koch <uplink.coder@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |uplink.coder@gmail.com

--- Comment #12 from Stefan Koch <uplink.coder@gmail.com> ---
This is caused by a giant chain of templates.

I will take a look.

--
June 16, 2018
https://issues.dlang.org/show_bug.cgi?id=18026

--- Comment #13 from JR <zorael@gmail.com> ---
(In reply to Stefan Koch from comment #12)
> This is caused by a giant chain of templates.
> 
> I will take a look.

Thank you!

If you need more dustmite examples I can generate those on demand.

--
June 17, 2018
https://issues.dlang.org/show_bug.cgi?id=18026

--- Comment #14 from ag0aep6g <ag0aep6g@gmail.com> ---
Removed Phobos from the test case from comment 10, and made sure that it fails reliably (for me) by raising the number of enum members again:

----
enum Type
{
    x000,x001,x002,x003,x004,x005,x006,x007,x008,x009,x010,x011,x012,x013,x014,
    x015,x016,x017,x018,x019,x020,x021,x022,x023,x024,x025,x026,x027,x028,x029,
    x030,x031,x032,x033,x034,x035,x036,x037,x038,x039,x040,x041,x042,x043,x044,
    x045,x046,x047,x048,x049,x050,x051,x052,x053,x054,x055,x056,x057,x058,x059,
    x060,x061,x062,x063,x064,x065,x066,x067,x068,x069,x070,x071,x072,x073,x074,
    x075,x076,x077,x078,x079,x080,x081,x082,x083,x084,x085,x086,x087,x088,x089,
    x090,x091,x092,x093,x094,x095,x096,x097,x098,x099,x100,x101,x102,x103,x104,
    x105,x106,x107,x108,x109,x110,x111,x112,x113,x114,x115,x116,x117,x118,x119,
    x120,x121,x122,x123,x124,x125,x126,x127,x128,x129,x130,x131,x132,x133,x134,
    x135,x136,x137,x138,x139,x140,x141,x142,x143,x144,x145,x146,x147,x148,x149,
    x150,x151,x152,x153,x154,x155,x156,x157,x158,x159,x160,x161,x162,x163,x164,
    x165,x166,x167,x168,x169,x170,x171,x172,x173,x174,x175,x176,x177,x178,x179,
    x180,x181,x182,x183,x184,x185,x186,x187,x188,x189,x190,x191,x192,x193,x194,
    x195,x196,x197,x198,x199,x200,x201,x202,x203,x204,x205,x206,x207,x208,x209,
    x210,x211,x212,x213,x214,x215,x216,x217,x218,x219,x220,x221,x222,x223,x224,
    x225,x226,x227,x228,x229,x230,x231,x232,x233,x234,x235,x236,x237,x238,x239,
    x240,x241,x242,x243,x244,x245,x246,x247,x248,x249,x250,x251,x252,x253,x254,
    x255,x256,x257,x258,x259,x260,x261,x262,x263,x264,x265,x266,x267,x268,x269,
    x270,x271,x272,x273,x274,x275,x276,x277,x278,x279,x280,x281,x282,x283,x284,
    x285,x286,x287,x288,x289,x290,x291,x292,x293,x294,x295,x296,x297,x298,x299,
    x300,x301,x302,x303,x304,x305,x306,x307,x308,x309,x310,x311,x312,x313,x314,
    x315,x316,x317,x318,x319,x320,x321,x322,x323,x324,x325,x326,x327,x328,x329,
    x330,x331,x332,x333,x334,x335,x336,x337,x338,x339,x340,x341,x342,x343,x344,
    x345,x346,x347,x348,x349,x350,x351,x352,x353,x354,x355,x356,x357,x358,x359,
    x360,x361,x362,x363,x364,x365,x366,x367,x368,x369,x370,x371,x372,x373,x374,
    x375,x376,x377,x378,x379,x380,x381,x382,x383,x384,x385,x386,x387,x388,x389,
    x390,x391,x392,x393,x394,x395,x396,x397,x398,x399,x400,x401,x402,x403,x404,
    x405,x406,x407,x408,x409,x410,x411,x412,x413,x414,x415,x416,x417,x418,x419,
    x420,x421,x422,x423,x424,x425,x426,x427,x428,x429,x430,x431,x432,x433,x434,
    x435,x436,x437,x438,x439,x440,x441,x442,x443,x444,x445,x446,x447,x448,x449,
    x450,x451,x452,x453,x454,x455,x456,x457,x458,x459,x460,x461,x462,x463,x464,
    x465,x466,x467,x468,x469,x470,x471,x472,x473,x474,x475,x476,x477,x478,x479,
    x480,x481,x482,x483,x484,x485,x486,x487,x488,x489,x490,x491,x492,x493,x494,
    x495,x496,x497,x498,x499,x500,x501,x502,x503,x504,x505,x506,x507,x508,x509,
    x510,x511,x512,x513,x514,x515,x516,x517,x518,x519,x520,x521,x522,x523,x524,
    x525,x526,x527,x528,x529,x530,x531,x532,x533,x534,x535,x536,x537,x538,x539,
    x540,x541,x542,x543,x544,x545,x546,x547,x548,x549,x550,x551,x552,x553,x554,
    x555,x556,x557,x558,x559,x560,x561,x562,x563,x564,x565,x566,x567,x568,x569,
    x570,x571,x572,x573,x574,x575,x576,x577,x578,x579,x580,x581,x582,x583,x584,
    x585,x586,x587,x588,x589,x590,x591,x592,x593,x594,x595,x596,x597,x598,x599,
    x600,x601,x602,x603,x604,x605,x606,x607,x608,x609,x610,x611,x612,x613,x614,
    x615,x616,x617,x618,x619,x620,x621,x622,x623,x624,x625,x626,x627,x628,x629,
    x630,x631,x632,x633,x634,x635,x636,x637,x638,x639,x640,x641,x642,x643,x644,
    x645,x646,x647,x648,x649,x650,x651,x652,x653,x654,x655,x656,x657,x658,x659,
    x660,x661,x662,x663,x664,x665,x666,x667,x668,x669,x670,x671,x672,x673,x674,
    x675,x676,x677,x678,x679,x680,x681,x682,x683,x684,x685,x686,x687,x688,x689,
    x690,x691,x692,x693,x694,x695,x696,x697,x698,x699,x700,x701,x702,x703,x704,
    x705,x706,x707,x708,x709,x710,x711,x712,x713,x714,x715,x716,x717,x718,x719,
    x720,x721,x722,x723,x724,x725,x726,x727,x728,x729,x730,x731,x732,x733,x734,
    x735,x736,x737,x738,x739,x740,x741,x742,x743,x744,x745,x746,x747,x748,x749,
    x750,x751,x752,x753,x754,x755,x756,x757,x758,x759,x760,x761,x762,x763,x764,
    x765,x766,x767,x768,x769,x770,x771,x772,x773,x774,x775,x776,x777,x778,x779,
    x780,x781,x782,x783,x784,x785,x786,x787,x788,x789,x790,x791,x792,x793,x794,
    x795,x796,x797,x798,x799,x800,x801,x802,x803,x804,x805,x806,x807,x808,x809,
}

template Unqual() {}
struct FormatSpec() if (is(Unqual!()) || !is(Unqual!())) {}

void formatValueImpl(W, T)(W w, T obj, FormatSpec!() f) if (is(T == string)) {}

void formatValueImpl(W, T)(W w, T val, FormatSpec!() f)
if (is(T == Type))
{
    foreach (i, e; __traits(allMembers, T))
    {
        formatValueImpl!(W, string)(w, e, f);
    }
}

void formatValueImpl(W, T)(W w, T obj, FormatSpec!() f) if (false) {}
void formatValueImpl(W, T)(W w, T obj, FormatSpec!() f) if (false) {}
void formatValueImpl(W, T)(W w, T obj, FormatSpec!() f) if (false) {}
void formatValueImpl(W, T)(W w, T obj, FormatSpec!() f) if (false) {}
void formatValueImpl(W, T)(W w, T obj, FormatSpec!() f) if (false) {}
void formatValueImpl(W, T)(W w, T val, FormatSpec!() f) if (false) {}
void formatValueImpl(W, T)(W w, T obj, FormatSpec!() f) if (false) {}
void formatValueImpl(W, T)(W w, T obj, FormatSpec!() f) if (false) {}
void formatValueImpl(W, T)(W w, T obj, FormatSpec!() f) if (false) {}

alias fvi_Type_1 = formatValueImpl!(void function(char c), Type);
alias fvi_Type_2 = formatValueImpl!(void function(const(char)[] s), Type);
alias fvi_Type_3 = formatValueImpl!(void delegate(char c), Type);
alias fvi_Type_4 = formatValueImpl!(void delegate(const char[]), Type);
alias fvi_Type_5 = formatValueImpl!(void delegate(const(char)[] s), Type);
----

If this happens to not crash on other systems, adding more enum members and/or "false" formatValueImpl overloads and/or fvi_Type_* variants might do the trick.

--
June 18, 2018
https://issues.dlang.org/show_bug.cgi?id=18026

FeepingCreature <default_357-line@yahoo.de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |default_357-line@yahoo.de

--- Comment #15 from FeepingCreature <default_357-line@yahoo.de> ---
Shorter repro:

module test;

struct FormatSpec() {}

void formatValueImpl(W, T)(W w, T obj, FormatSpec!() f) if (is(T == string)) {
}

void formatValueImpl(W, T)(W w, T val, FormatSpec!() f)
if (is(T == int))
{
    import std.range : iota;
    static foreach (_; iota(1000))
    {
        formatValueImpl!(W, string)(w, "", f);
    }
}

void formatValueImpl(W, T)(W w, T obj, FormatSpec!() f) if (false) {}
void formatValueImpl(W, T)(W w, T obj, FormatSpec!() f) if (false) {}
void formatValueImpl(W, T)(W w, T obj, FormatSpec!() f) if (false) {}
void formatValueImpl(W, T)(W w, T obj, FormatSpec!() f) if (false) {}

alias fvi_Type_1 = formatValueImpl!(void function(char c), int);
alias fvi_Type_2 = formatValueImpl!(void function(const(char)[] s), int);
alias fvi_Type_3 = formatValueImpl!(void delegate(char c), int);
alias fvi_Type_4 = formatValueImpl!(void delegate(const char[]), int);
alias fvi_Type_5 = formatValueImpl!(void delegate(const(char)[] s), int);

void main() {}

Seems to happen more reliably in gdb. Since it's a stack overflow, recommended to limit your stack size with ulimit -s 128 to test.

--
July 25, 2018
https://issues.dlang.org/show_bug.cgi?id=18026

Mike Franklin <slavo5150@yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |slavo5150@yahoo.com

--- Comment #16 from Mike Franklin <slavo5150@yahoo.com> ---
I've been looking into fixing this.  The problem is this block of code: https://github.com/dlang/dmd/blob/750f0245c2882887cdb830c171e9221719e0da28/src/dmd/dtemplate.d#L6291-L6320

---
if (!minst)
{
    // If this is a speculative instantiation,
    // 1. do codegen if ancestors really needs codegen.
    // 2. become non-speculative if siblings are not speculative

    TemplateInstance tnext = this.tnext;
    TemplateInstance tinst = this.tinst;
    // At first, disconnect chain first to prevent infinite recursion.
    this.tnext = null;
    this.tinst = null;

    // Determine necessity of tinst before tnext.
    if (tinst && tinst.needsCodegen())
    {
        minst = tinst.minst; // cache result
        assert(minst);
        assert(minst.isRoot() || minst.rootImports());
        return true;
    }

    // Issue 18026 - Stack overerflow due to recursive call to needsCodegen
    if (tnext && (tnext.needsCodegen() || tnext.minst))
    {
        minst = tnext.minst; // cache result
        assert(minst);
        return minst.isRoot() || minst.rootImports();
    }

    // Elide codegen because this is really speculative.
    return false;
}
---

Specifically, the stack overflow occurs at...
---
if (tnext && (tnext.needsCodegen() || tnext.minst))
{
    minst = tnext.minst; // cache result
    assert(minst);
    return minst.isRoot() || minst.rootImports();
}
---
... due to the recursive call to `needsCodegen`

The whole function `needsCodegen` looks like a mess.  There's probably a way to implement the algorithm as a loop instead of recursive function calls, but I'm not yet sure what to do to fix this.

--
July 25, 2018
https://issues.dlang.org/show_bug.cgi?id=18026

Basile B. <b2.temp@gmx.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |b2.temp@gmx.com

--- Comment #17 from Basile B. <b2.temp@gmx.com> ---
(In reply to Mike Franklin from comment #16)
> I've been looking into fixing this.  The problem is this block of code: https://github.com/dlang/dmd/blob/750f0245c2882887cdb830c171e9221719e0da28/ src/dmd/dtemplate.d#L6291-L6320
> 
> The whole function `needsCodegen` looks like a mess.  There's probably a way to implement the algorithm as a loop instead of recursive function calls, but I'm not yet sure what to do to fix this.

Ah, this part of code is indeed source of other issues (speculative sometimes fails). Original op can use `-allinst` as a workaround, waiting for a fix.

--
September 10, 2018
https://issues.dlang.org/show_bug.cgi?id=18026

--- Comment #18 from JR <zorael@gmail.com> ---
On CircleCI build servers it has started to segfault even in debug mode[1]. Travis is still okay and I cannot reproduce it locally.

> [...]
> Compiling source/kameloso/objmanip.d...
> Compiling source/kameloso/plugins/admin.d...
> Compiling source/kameloso/plugins/automode.d...
> Compiling source/kameloso/plugins/bashquotes.d...
> Compiling source/kameloso/plugins/chanqueries.d...
> Compiling source/kameloso/plugins/chatbot.d...
> Segmentation fault
> dmd failed with exit code 139.
> Exited with code 2

(It has to be built with --mode=singleFile there, or else the process gets killed due to high memory usage.)

gdb showed it to be TemplateInstance::needsCodegen(), as before.

Modifying dub.json to make it compile with -allinst lets it successfully build, but it will then instead fail to link. This may be Issue 19123 - -allinst gives undefined reference linker errors[2].


[1]: https://circleci.com/gh/zorael/kameloso/547
[2]: https://issues.dlang.org/show_bug.cgi?id=19123

--
March 21, 2020
https://issues.dlang.org/show_bug.cgi?id=18026

Basile-z <b2.temp@gmx.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|b2.temp@gmx.com             |

--
November 07, 2020
https://issues.dlang.org/show_bug.cgi?id=18026

--- Comment #19 from JR <zorael@gmail.com> ---
Small update.

I no longer experience this with the dmd and ldc from the Arch/Manjaro repository, even when checking out the old `overflow` branch used in the original report.

I do experience it when I build dmd myself (with Digger). It is not possible for me to build and use my own dmd.

> [...]
> #58123 0x00000000006344e2 in TemplateInstance::needsCodegen() (this=0x7fff5d89b910) at src/dmd/dtemplate.d:6265
> #58124 0x00000000006344e2 in TemplateInstance::needsCodegen() (this=0x7fff5d89c2b0) at src/dmd/dtemplate.d:6265
> #58125 0x00000000006347ca in TemplateInstance::needsCodegen() (this=0x7ffff2acf3b0) at src/dmd/dtemplate.d:6352
> #58126 0x000000000078be89 in toObjFile::ToObjFile::visit(TemplateInstance*) (this=0x7fffffffa838, ti=0x7ffff2acf3b0) at src/dmd/toobj.d:829
> #58127 0x00000000006377ba in TemplateInstance::accept(Visitor*) (this=0x7ffff2acf3b0, v=0x7fffffffa838) at src/dmd/dtemplate.d:7488
> #58128 0x000000000078ac13 in toObjFile(Dsymbol*, bool) (ds=0x7ffff2acf3b0, multiobj=false) at src/dmd/toobj.d:1027
> #58129 0x0000000000777352 in genObjFile(Module*, bool) (m=0x7ffff7b331f0, multiobj=false) at src/dmd/glue.d:420
> #58130 0x00000000006d85aa in dmd.mars.tryMain(ulong, const(char)**, ref dmd.globals.Param) (params=..., argv=0x7fffffffcef8, argc=112) at src/dmd/mars.d:696
> #58131 0x00000000006d9571 in D main (_param_0=...) at src/dmd/mars.d:972

Has there been any changes since last? Having a compiler that does work is comforting, but also discomforting to know it may break when it feels like it.

--