diff --git a/src/dsymbol.c b/src/dsymbol.c index 19234215c8a3..aff118ec05c4 100644 --- a/src/dsymbol.c +++ b/src/dsymbol.c @@ -915,7 +915,11 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags) */ Dsymbol *s2 = ss->search(loc, ident, ss->isModule() ? IgnorePrivateMembers : IgnoreNone); if (!s) + { s = s2; + if (s && s->isOverloadSet()) + a = mergeOverloadSet(a, s); + } else if (s2 && s != s2) { if (s->toAlias() == s2->toAlias() || @@ -956,28 +960,10 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags) /* If both s2 and s are overloadable (though we only * need to check s once) */ - if (s2->isOverloadable() && (a || s->isOverloadable())) + if ((s2->isOverloadSet() || s2->isOverloadable()) && + (a || s->isOverloadable())) { - if (!a) - { - a = new OverloadSet(s->ident); - a->parent = this; - } - /* Don't add to a[] if s2 is alias of previous sym - */ - for (size_t j = 0; j < a->a.dim; j++) - { - Dsymbol *s3 = a->a[j]; - if (s2->toAlias() == s3->toAlias()) - { - if (s3->isDeprecated() || - s2->prot() > s3->prot() && s2->prot() != PROTnone) - a->a[j] = s2; - goto Lcontinue; - } - } - a->push(s2); - Lcontinue: + a = mergeOverloadSet(a, s2); continue; } if (flags & IgnoreAmbiguous) // if return NULL on ambiguity @@ -996,7 +982,8 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags) */ if (a) { - a->push(s); + if (!s->isOverloadSet()) + a = mergeOverloadSet(a, s); s = a; } @@ -1012,6 +999,55 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags) return s1; } +OverloadSet *ScopeDsymbol::mergeOverloadSet(OverloadSet *os, Dsymbol *s) +{ + if (!os) + { + os = new OverloadSet(s->ident); + os->parent = this; + } + if (OverloadSet *os2 = s->isOverloadSet()) + { + // Merge the cross-module overload set 'os2' into 'os' + if (os->a.dim == 0) + { + os->a.setDim(os2->a.dim); + memcpy(os->a.tdata(), os2->a.tdata(), sizeof(os->a[0]) * os2->a.dim); + } + else + { + for (size_t i = 0; i < os2->a.dim; i++) + { + os = mergeOverloadSet(os, os2->a[i]); + } + } + } + else + { + assert(s->isOverloadable()); + + /* Don't add to os[] if s is alias of previous sym + */ + for (size_t j = 0; j < os->a.dim; j++) + { + Dsymbol *s2 = os->a[j]; + if (s->toAlias() == s2->toAlias()) + { + if (s2->isDeprecated() || + s->prot() > s2->prot() && s->prot() != PROTnone) + { + os->a[j] = s; + } + goto Lcontinue; + } + } + os->push(s); + Lcontinue: + ; + } + return os; +} + void ScopeDsymbol::importScope(Dsymbol *s, PROT protection) { //printf("%s->ScopeDsymbol::importScope(%s, %d)\n", toChars(), s->toChars(), protection); diff --git a/src/dsymbol.h b/src/dsymbol.h index 672f540c3e8a..48aa0cb90aff 100644 --- a/src/dsymbol.h +++ b/src/dsymbol.h @@ -291,6 +291,7 @@ class ScopeDsymbol : public Dsymbol ScopeDsymbol(Identifier *id); Dsymbol *syntaxCopy(Dsymbol *s); Dsymbol *search(Loc loc, Identifier *ident, int flags = IgnoreNone); + OverloadSet *mergeOverloadSet(OverloadSet *os, Dsymbol *s); void importScope(Dsymbol *s, PROT protection); bool isforwardRef(); static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2); diff --git a/test/compilable/imports/imp12242a.d b/test/compilable/imports/imp12242a.d new file mode 100644 index 000000000000..5e5259dc762f --- /dev/null +++ b/test/compilable/imports/imp12242a.d @@ -0,0 +1,17 @@ +module imports.imp12242a; + +public: +import imports.imp12242a1; // std.string +import imports.imp12242a2; // std.algorithm + + +private mixin template MixTmp(T, int x) +{ + template foo(U) if (is(U == T)) + { + enum foo = x; + } +} + +mixin MixTmp!(int, 1); +mixin MixTmp!(long, 2); diff --git a/test/compilable/imports/imp12242a1.d b/test/compilable/imports/imp12242a1.d new file mode 100644 index 000000000000..5c5e52330687 --- /dev/null +++ b/test/compilable/imports/imp12242a1.d @@ -0,0 +1,8 @@ +module imports.imp12242a1; + +// std.string.strip +int stripA(C)(C[] str) @safe pure + if (is(immutable C == immutable char)) +{ + return 1; +} diff --git a/test/compilable/imports/imp12242a2.d b/test/compilable/imports/imp12242a2.d new file mode 100644 index 000000000000..c0d789031a58 --- /dev/null +++ b/test/compilable/imports/imp12242a2.d @@ -0,0 +1,11 @@ +module imports.imp12242a2; + +// std.algorithm.strip +auto stripA(R, E)(R range, E element) +{ + return 2; +} +auto stripA(alias pred, R)(R range) +{ + return 3; +} diff --git a/test/compilable/imports/imp12242b.d b/test/compilable/imports/imp12242b.d new file mode 100644 index 000000000000..886104f54c9d --- /dev/null +++ b/test/compilable/imports/imp12242b.d @@ -0,0 +1,17 @@ +module imports.imp12242b; + +public: +import imports.imp12242b1; // std.string +import imports.imp12242b2; // std.algorithm + + +private mixin template MixTmp(T, int x) +{ + template foo(U) if (is(U == T)) + { + enum foo = x; + } +} + +mixin MixTmp!(float, 3); +mixin MixTmp!(real, 4); diff --git a/test/compilable/imports/imp12242b1.d b/test/compilable/imports/imp12242b1.d new file mode 100644 index 000000000000..e23fdc8da2e6 --- /dev/null +++ b/test/compilable/imports/imp12242b1.d @@ -0,0 +1,8 @@ +module imports.imp12242b1; + +// std.string.strip +int stripB(C)(C[] str) @safe pure + if (is(immutable C == immutable char)) +{ + return 1; +} diff --git a/test/compilable/imports/imp12242b2.d b/test/compilable/imports/imp12242b2.d new file mode 100644 index 000000000000..0f5599887222 --- /dev/null +++ b/test/compilable/imports/imp12242b2.d @@ -0,0 +1,11 @@ +module imports.imp12242b2; + +// std.algorithm.strip +auto stripB(R, E)(R range, E element) +{ + return 2; +} +auto stripB(alias pred, R)(R range) +{ + return 3; +} diff --git a/test/compilable/testimport12242.d b/test/compilable/testimport12242.d new file mode 100644 index 000000000000..1d1cccd01001 --- /dev/null +++ b/test/compilable/testimport12242.d @@ -0,0 +1,26 @@ +// PERMUTE_ARGS: + +module testimport12242; + +import imports.imp12242a; // test // stripA == OverloadSet +import imports.imp12242a1; // std.string // stripA == template + +import imports.imp12242b1; // std.string // stripB == template +import imports.imp12242b; // test // stripB == OverloadSet + +void main() +{ + static assert(stripA(" af ") == 1); + static assert(" af ".stripA() == 1); // UFCS (1) + static assert(" af ".stripA == 1); // UFCS (2) + + static assert(stripB(" af ") == 1); + static assert(" af ".stripB() == 1); // UFCS (1) + static assert(" af ".stripB == 1); // UFCS (2) + + + static assert(foo!int == 1); + static assert(foo!long == 2); + static assert(foo!float == 3); + static assert(foo!real == 4); +}