From 5efa203c22ba4b49f2366f71d1104c2aaf37b144 Mon Sep 17 00:00:00 2001 From: k-hara Date: Wed, 27 Aug 2014 14:42:48 +0900 Subject: [PATCH] fix Issue 13379 - Latest dmd fails with recursive template expansion in std.regex --- src/template.c | 28 ++++++++++++--------------- test/runnable/template9.d | 40 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/template.c b/src/template.c index cd19deae003b..70d9a919ef31 100644 --- a/src/template.c +++ b/src/template.c @@ -5946,10 +5946,15 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) } // If the first instantiation was in speculative context, but this is not: - if (!inst->tinst && inst->speculative && !(sc->flags & (SCOPEstaticif | SCOPEstaticassert | SCOPEcompile))) + if (!inst->tinst && inst->speculative && + tinst && !(sc->flags & (SCOPEstaticif | SCOPEstaticassert | SCOPEcompile))) { // Reconnect the chain if this instantiation is not in speculative context. - inst->tinst = tinst; + TemplateInstance *tix = tinst; + while (tix && tix != inst) + tix = tix->tinst; + if (tix != inst) // Bugzilla 13379: Prevent circular chain + inst->tinst = tinst; } #if LOG @@ -6279,8 +6284,6 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) while (ti && !ti->deferred && ti->tinst) { ti = ti->tinst; - if (ti == tinst) - break; if (++nest > 500) { global.gag = 0; // ensure error message gets printed @@ -7823,21 +7826,14 @@ bool TemplateInstance::needsCodegen() } } - if (speculative) + for (TemplateInstance *ti = this; ti; ti = ti->tinst) { - //printf("\tti = %s spec = %d\n", toChars(), speculative); - TemplateInstance *ti = this; - while (ti->tinst && ti->tinst != this) - { - ti = ti->tinst; - //printf("\tti = %s spec = %d\n", ti->toChars(), ti->speculative); - if (!ti->speculative) - return true; - } - return false; + //printf("\tti = %s spec = %d\n", ti->toChars(), ti->speculative); + if (!ti->speculative) + return true; } - return true; + return false; } /* ======================== TemplateMixin ================================ */ diff --git a/test/runnable/template9.d b/test/runnable/template9.d index feb9e5f12dc9..f6f66f9de589 100644 --- a/test/runnable/template9.d +++ b/test/runnable/template9.d @@ -4149,6 +4149,45 @@ void test13378() doSome13378(v); } +/******************************************/ +// 13379 + +void test13379() +{ + match13379(""); +} + +auto match13379(RegEx )(RegEx re) +if (is(RegEx == Regex13379!char)) // #1 Regex!char (speculative && tinst == NULL) +{} +auto match13379(String)(String re) +{} + +struct Regex13379(Char) +{ + ShiftOr13379!Char kickstart; // #2 ShiftOr!char (speculative && tinst == Regex!char) +} +struct ShiftOr13379(Char) +{ + this(ref Regex13379!Char re) // #3 Regex!Char (speculative && tinst == ShiftOr!char) + { + uint n_length; + uint idx; + n_length = min13379(idx, n_length); + } +} + +template MinType13379(T...) +{ + alias MinType13379 = T[0]; +} +MinType13379!T min13379(T...)(T args) // #4 MinType!uint (speculative && thist == ShiftOr!char) +{ + alias a = args[0]; + alias b = args[$-1]; + return cast(typeof(return)) (a < b ? a : b); +} + /******************************************/ int main() @@ -4253,6 +4292,7 @@ int main() test13299(); test13374(); test13378(); + test13379(); printf("Success\n"); return 0;