From 68e8c9493a6970eab33569edec8e40253200cfc0 Mon Sep 17 00:00:00 2001 From: k-hara Date: Fri, 24 Oct 2014 19:26:36 +0900 Subject: [PATCH 1/3] fix Issue 12447 - variadic template functions hijack all eponymous enum and alias template overloads --- src/template.c | 9 +++++++-- test/runnable/template9.d | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/template.c b/src/template.c index 49795f7039bb..f2e6b7be461e 100644 --- a/src/template.c +++ b/src/template.c @@ -949,10 +949,15 @@ MATCH TemplateDeclaration::matchWithInstance(Scope *sc, TemplateInstance *ti, // Resolve parameter types and 'auto ref's. tf->fargs = fargs; + unsigned olderrors = global.startGagging(); fd->type = tf->semantic(loc, paramscope); - fd->originalType = fd->type; // for mangling - if (fd->type->ty != Tfunction) + if (global.endGagging(olderrors)) + { + assert(fd->type->ty != Tfunction); goto Lnomatch; + } + assert(fd->type->ty == Tfunction); + fd->originalType = fd->type; // for mangling } // TODO: dedtypes => ti->tiargs ? diff --git a/test/runnable/template9.d b/test/runnable/template9.d index d9eab883ae68..8398a34de3d8 100644 --- a/test/runnable/template9.d +++ b/test/runnable/template9.d @@ -3388,6 +3388,21 @@ void test12376() enum x = __traits(compiles, encode12376!2(x)); } +/******************************************/ +// 12447 + +enum test12447(string str) = str; // [1] +string test12447(T...)(T args) if (T.length) { return args[0]; } // [2] + +// With [1]: The template parameter str cannot be be deduced -> no match +// With [2]: T is deduced to a type tuple (string), then match to the function call. +static assert(test12447("foo") == "foo"); + +// With [1]: template parameter str is deduced to "bar", then match. +// With [2]: T is deduced to an expression tuple ("bar"), but it will make invalid the function signature (T args). +// The failure should be masked silently and prefer the 1st version. +static assert(test12447!("bar") == "bar"); + /******************************************/ // 12651 From 868bc03002c5eca0a615c141f7dcfeccf0a7ab17 Mon Sep 17 00:00:00 2001 From: k-hara Date: Fri, 24 Oct 2014 19:42:23 +0900 Subject: [PATCH 2/3] fix Issue 11916 - [IFTI] Disabled by constraint overload with `out` with IFTI breaks overload resolution --- src/template.c | 19 +++++++++++++------ test/fail_compilation/ice11857.d | 19 ------------------- test/runnable/overload.d | 30 ++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 25 deletions(-) delete mode 100644 test/fail_compilation/ice11857.d diff --git a/src/template.c b/src/template.c index f2e6b7be461e..46ef9032720b 100644 --- a/src/template.c +++ b/src/template.c @@ -2299,9 +2299,7 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc, MATCH mta = (MATCH)(x >> 4); MATCH mfa = (MATCH)(x & 0xF); //printf("match:t/f = %d/%d\n", mta, mfa); - if (!fd) - goto Lerror; - if (mfa == MATCHnomatch) + if (!fd || mfa == MATCHnomatch) continue; Type *tthis_fd = fd->needThis() ? tthis : NULL; @@ -2581,14 +2579,23 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation( tf->next = NULL; fd->type = tf; fd->type = fd->type->addSTC(scx->stc); + + unsigned olderrors = global.startGagging(); fd->type = fd->type->semantic(fd->loc, scx); + scx = scx->pop(); + + if (global.endGagging(olderrors)) + { + assert(fd->type->ty != Tfunction); + return NULL; + } + assert(fd->type->ty == Tfunction); + fd->originalType = fd->type; // for mangling //printf("\t[%s] fd->type = %s, mod = %x, ", loc.toChars(), fd->type->toChars(), fd->type->mod); //printf("fd->needThis() = %d\n", fd->needThis()); - scx = scx->pop(); - - return fd->type->ty == Tfunction ? fd : NULL; + return fd; } bool TemplateDeclaration::hasStaticCtorOrDtor() diff --git a/test/fail_compilation/ice11857.d b/test/fail_compilation/ice11857.d deleted file mode 100644 index ad6b72526854..000000000000 --- a/test/fail_compilation/ice11857.d +++ /dev/null @@ -1,19 +0,0 @@ -/* -TEST_OUTPUT: ---- -fail_compilation/ice11857.d(10): Error: cannot have const out parameter of type const(int) ---- -*/ - - -void t11857(T)(T) { } -void t11857(T)(out T) if(false) { } - - -void main() -{ - const int n = 1; - t11857(n); // causes ICE -} - - diff --git a/test/runnable/overload.d b/test/runnable/overload.d index d122beb9484e..c9d04d6f7ecb 100644 --- a/test/runnable/overload.d +++ b/test/runnable/overload.d @@ -1008,6 +1008,35 @@ void test11785() input.read(v); } +/***************************************************/ +// 11916 + +auto f11916(T)( T) { return 1; } +auto f11916(T)(out T) if (false) { return 2; } + +auto g11916(T)( T) { return 1; } +auto g11916(T)(out T) { return 2; } + +void test11916() +{ + const int c = 1; + int m = 2; + + // 'out const int' is invalid function parameter, so (out T) version will be dropped + // from overload candidates before template constraint evaluated. + assert(f11916(c) == 1); + + // Both (T) and (out T) have valid signatures with T == int, but the 2nd overload will be + // dropped from overload candidates because of the template constraint. + assert(f11916(m) == 1); + + // 'out const int' parameter is invalid, so non-out version is selected. + assert(g11916(c) == 1); + + // MATCHconst for (T) version, and MATCHexact for (out T) version. + assert(g11916(m) == 2); +} + /***************************************************/ int main() @@ -1039,6 +1068,7 @@ int main() test10658a(); test10658b(); test11785(); + test11916(); printf("Success\n"); return 0; From f536d3f46da72ece838caa6d0eb82e051239b288 Mon Sep 17 00:00:00 2001 From: k-hara Date: Sun, 26 Oct 2014 12:36:50 +0900 Subject: [PATCH 3/3] fix Issue 11915 - Inconsistent overload resolution behaviour between `ref` and `out` --- src/mtype.c | 8 +++++++- src/template.c | 2 +- test/runnable/overload.d | 17 +++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/mtype.c b/src/mtype.c index de48960f1d3e..cc225fc63d93 100644 --- a/src/mtype.c +++ b/src/mtype.c @@ -5873,7 +5873,13 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag) goto Nomatch; } else if (p->storageClass & STCout) - { if (m && !arg->isLvalue()) + { + if (m && !arg->isLvalue()) + goto Nomatch; + + Type *targb = targ->toBasetype(); + Type *tprmb = tprm->toBasetype(); + if (!targb->constConv(tprmb)) goto Nomatch; } } diff --git a/src/template.c b/src/template.c index 46ef9032720b..652e1eade953 100644 --- a/src/template.c +++ b/src/template.c @@ -2054,7 +2054,7 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc, if (tiargs && tiargs->dim > 0) return 0; - //printf("fd = %s %s\n", fd->toChars(), fd->type->toChars()); + //printf("fd = %s %s, fargs = %s\n", fd->toChars(), fd->type->toChars(), fargs->toChars()); m->anyf = fd; TypeFunction *tf = (TypeFunction *)fd->type; diff --git a/test/runnable/overload.d b/test/runnable/overload.d index c9d04d6f7ecb..db4243b593cf 100644 --- a/test/runnable/overload.d +++ b/test/runnable/overload.d @@ -1008,6 +1008,22 @@ void test11785() input.read(v); } +/***************************************************/ +// 11915 + +int f11915( int) { return 1; } +int f11915(ref int) { return 2; } + +int g11915( int) { return 1; } +int g11915(out int) { return 2; } + +void test11915() +{ + const int n = 1; + assert(f11915(n) == 1); + assert(g11915(n) == 1); +} + /***************************************************/ // 11916 @@ -1068,6 +1084,7 @@ int main() test10658a(); test10658b(); test11785(); + test11915(); test11916(); printf("Success\n");