diff --git a/changelog/duplicate-implementations-deprecation.dd b/changelog/duplicate-implementations-deprecation.dd new file mode 100644 index 000000000000..2893c192cad4 --- /dev/null +++ b/changelog/duplicate-implementations-deprecation.dd @@ -0,0 +1,23 @@ +Usage of identical functions in a single module + +A binary should never contain multiple versions of a symbol. +Before this version, it was allowed to provide multiple implementation for a function, +even if they result in the same mangling, which can result in undefined behavior: + +--- +extern(C): +void foo(int) { } +void foo(double) { } // will error now +--- + +However, it's still allowed to have multiple declarations as long as there's at +most one implementation: + +--- +extern(C): +void foo(int) { } +void foo(double); +--- + +Note that this change is only relevant for mangling schemes that do no support +overloading like `extern(C)`. diff --git a/src/dmd/semantic2.d b/src/dmd/semantic2.d index 768422dd4b1b..57172c374148 100644 --- a/src/dmd/semantic2.d +++ b/src/dmd/semantic2.d @@ -357,9 +357,6 @@ private extern(C++) final class Semantic2Visitor : Visitor //printf("FuncDeclaration::semantic2 [%s] fd0 = %s %s\n", loc.toChars(), toChars(), type.toChars()); - // https://issues.dlang.org/show_bug.cgi?id=18385 - // Disable for 2.079, s.t. a deprecation cycle can be started with 2.080 - if (0) if (fd.overnext && !fd.errors) { OutBuffer buf1; @@ -413,7 +410,8 @@ private extern(C++) final class Semantic2Visitor : Visitor auto tf1 = cast(TypeFunction)f1.type; auto tf2 = cast(TypeFunction)f2.type; - error(f2.loc, "%s `%s%s` cannot be overloaded with %s`extern(%s)` function at %s", + // @@@DEPRECATED_2.092@@@ + f2.deprecation("%s `%s%s` cannot be overloaded with %s`extern(%s)` function at %s", f2.kind(), f2.toPrettyChars(), parametersTypeToChars(tf2.parameters, tf2.varargs), @@ -434,7 +432,7 @@ private extern(C++) final class Semantic2Visitor : Visitor if (strcmp(s1, s2) == 0) { auto tf2 = cast(TypeFunction)f2.type; - error(f2.loc, "%s `%s%s` conflicts with previous declaration at %s", + f2.error("%s `%s%s` conflicts with previous declaration at %s", f2.kind(), f2.toPrettyChars(), parametersTypeToChars(tf2.parameters, tf2.varargs), diff --git a/test/fail_compilation/fail17492.d b/test/fail_compilation/fail17492.d index dca6f6fc0888..85af4916cefa 100644 --- a/test/fail_compilation/fail17492.d +++ b/test/fail_compilation/fail17492.d @@ -1,11 +1,9 @@ /* -https://issues.dlang.org/show_bug.cgi?id=18385 -Disabled for 2.079, s.t. a deprecation cycle can be started with 2.080 -DISABLED: win32 win64 osx linux freebsd dragonflybsd +REQUIRED_ARGS: -de TEST_OUTPUT: --- -fail_compilation/fail17492.d(20): Error: class `fail17492.C.testE.I` already exists at fail17492.d(13). Perhaps in another function with the same name? -fail_compilation/fail17492.d(37): Error: struct `fail17492.S.testE.I` already exists at fail17492.d(30). Perhaps in another function with the same name? +fail_compilation/fail17492.d(20): Error: function `fail17492.C.testE` function `fail17492.C.testE()` conflicts with previous declaration at fail_compilation/fail17492.d(13) +fail_compilation/fail17492.d(37): Error: function `fail17492.S.testE` function `fail17492.S.testE()` conflicts with previous declaration at fail_compilation/fail17492.d(30) --- https://issues.dlang.org/show_bug.cgi?id=17492 */ diff --git a/test/fail_compilation/fail2789.d b/test/fail_compilation/fail2789.d index ef9d858fcaab..9dccb46d0c5b 100644 --- a/test/fail_compilation/fail2789.d +++ b/test/fail_compilation/fail2789.d @@ -1,11 +1,18 @@ /* -DISABLED: win32 win64 osx linux freebsd dragonflybsd -https://issues.dlang.org/show_bug.cgi?id=18385 -Disabled for 2.079, s.t. a deprecation cycle can be started with 2.080 +REQUIRED_ARGS: -de TEST_OUTPUT: --- -fail_compilation/fail2789.d(15): Error: function `fail2789.A2789.m()` conflicts with previous declaration at fail_compilation/fail2789.d(10) -fail_compilation/fail2789.d(25): Error: function `fail2789.A2789.m()` conflicts with previous declaration at fail_compilation/fail2789.d(10) +fail_compilation/fail2789.d(25): Error: function `fail2789.A2789.m` function `fail2789.A2789.m()` conflicts with previous declaration at fail_compilation/fail2789.d(20) +fail_compilation/fail2789.d(35): Error: function `fail2789.A2789.m` function `fail2789.A2789.m()` conflicts with previous declaration at fail_compilation/fail2789.d(20) +fail_compilation/fail2789.d(47): Error: function `fail2789.f3` function `fail2789.f3()` conflicts with previous declaration at fail_compilation/fail2789.d(46) +fail_compilation/fail2789.d(50): Error: function `fail2789.f4` function `fail2789.f4()` conflicts with previous declaration at fail_compilation/fail2789.d(49) +fail_compilation/fail2789.d(53): Error: function `fail2789.f5` function `fail2789.f5()` conflicts with previous declaration at fail_compilation/fail2789.d(52) +fail_compilation/fail2789.d(56): Error: function `fail2789.f6` function `fail2789.f6()` conflicts with previous declaration at fail_compilation/fail2789.d(55) +fail_compilation/fail2789.d(60): Deprecation: function `fail2789.f_ExternC1` function `fail2789.f_ExternC1()` cannot be overloaded with another `extern(C)` function at fail_compilation/fail2789.d(59) +fail_compilation/fail2789.d(63): Deprecation: function `fail2789.f_ExternC2` function `fail2789.f_ExternC2(int)` cannot be overloaded with another `extern(C)` function at fail_compilation/fail2789.d(62) +fail_compilation/fail2789.d(66): Deprecation: function `fail2789.f_ExternC3` function `fail2789.f_ExternC3()` cannot be overloaded with another `extern(C)` function at fail_compilation/fail2789.d(65) +fail_compilation/fail2789.d(69): Error: function `fail2789.f_MixExtern1` function `fail2789.f_MixExtern1()` conflicts with previous declaration at fail_compilation/fail2789.d(68) +fail_compilation/fail2789.d(90): Error: function `fail2789.mul14147` function `fail2789.mul14147(const(int[]) left, const(int[]) right)` conflicts with previous declaration at fail_compilation/fail2789.d(86) --- */ class A2789 @@ -30,15 +37,6 @@ class A2789 } } -/* -TEST_OUTPUT: ---- -fail_compilation/fail2789.d(46): Error: function `fail2789.f3()` conflicts with previous declaration at fail_compilation/fail2789.d(45) -fail_compilation/fail2789.d(49): Error: function `fail2789.f4()` conflicts with previous declaration at fail_compilation/fail2789.d(48) -fail_compilation/fail2789.d(52): Error: function `fail2789.f5()` conflicts with previous declaration at fail_compilation/fail2789.d(51) -fail_compilation/fail2789.d(55): Error: function `fail2789.f6()` conflicts with previous declaration at fail_compilation/fail2789.d(54) ---- -*/ void f1(); void f1() {} // ok @@ -57,15 +55,7 @@ void f5() @system {} // conflict auto f6() { return 10; } // int() auto f6() { return ""; } // string(), conflict -/* -TEST_OUTPUT: ---- -fail_compilation/fail2789.d(67): Error: function `fail2789.f_ExternC1()` cannot be overloaded with another `extern(C)` function at fail_compilation/fail2789.d(66) -fail_compilation/fail2789.d(70): Error: function `fail2789.f_ExternC2(int)` cannot be overloaded with another `extern(C)` function at fail_compilation/fail2789.d(69) -fail_compilation/fail2789.d(73): Error: function `fail2789.f_ExternC3()` cannot be overloaded with another `extern(C)` function at fail_compilation/fail2789.d(72) -fail_compilation/fail2789.d(76): Error: function `fail2789.f_MixExtern1()` conflicts with previous declaration at fail_compilation/fail2789.d(75) ---- -*/ + extern(C) void f_ExternC1() {} extern(C) void f_ExternC1() {} // conflict @@ -90,12 +80,6 @@ extern (C) void f_ExternC5(int sig) @nogc; // no error extern (C) void f_ExternC6(int sig); extern (C) void f_ExternC6(int sig) @nogc {} // no error -/* -TEST_OUTPUT: ---- -fail_compilation/fail2789.d(103): Error: function `fail2789.mul14147(const(int[]) left, const(int[]) right)` conflicts with previous declaration at fail_compilation/fail2789.d(99) ---- -*/ struct S14147(alias func) { } diff --git a/test/fail_compilation/fail5634.d b/test/fail_compilation/fail5634.d index 0044adf8df29..9c962af329b7 100644 --- a/test/fail_compilation/fail5634.d +++ b/test/fail_compilation/fail5634.d @@ -1,3 +1,10 @@ +// REQUIRED_ARGS: -de +/* +TEST_OUTPUT: +--- +fail_compilation/fail5634.d(9): Error: function `D main` function `D main()` conflicts with previous declaration at fail_compilation/fail5634.d(8) +--- +*/ void main() { } void main() { } diff --git a/test/fail_compilation/fail7443.d b/test/fail_compilation/fail7443.d index 0fb165d5dcc8..4673e491d32d 100644 --- a/test/fail_compilation/fail7443.d +++ b/test/fail_compilation/fail7443.d @@ -2,8 +2,9 @@ /* TEST_OUTPUT: --- -fail_compilation/fail7443.d(12): Deprecation: `static` has no effect on a constructor inside a `static` block. Use `static this()` -fail_compilation/fail7443.d(13): Deprecation: `shared static` has no effect on a constructor inside a `shared static` block. Use `shared static this()` +fail_compilation/fail7443.d(13): Deprecation: `static` has no effect on a constructor inside a `static` block. Use `static this()` +fail_compilation/fail7443.d(14): Deprecation: `shared static` has no effect on a constructor inside a `shared static` block. Use `shared static this()` +fail_compilation/fail7443.d(15): Error: constructor `fail7443.Foo.this` constructor `fail7443.Foo.this()` conflicts with previous declaration at fail_compilation/fail7443.d(13) --- */ diff --git a/test/fail_compilation/test18282.d b/test/fail_compilation/test18282.d index 8e7832ce14ec..cd60daf5f6c2 100644 --- a/test/fail_compilation/test18282.d +++ b/test/fail_compilation/test18282.d @@ -46,7 +46,7 @@ S2000 bar2() } -void bar2() +void bar3() { int i; char c; diff --git a/test/fail_compilation/test18385.d b/test/fail_compilation/test18385.d new file mode 100644 index 000000000000..6db4d8a732c5 --- /dev/null +++ b/test/fail_compilation/test18385.d @@ -0,0 +1,31 @@ +/* +REQUIRED_ARGS: -de +TEST_OUTPUT: +--- +fail_compilation/test18385.d(13): Deprecation: function `test18385.foo` function `test18385.foo(double)` cannot be overloaded with another `extern(C)` function at fail_compilation/test18385.d(12) +fail_compilation/test18385.d(18): Deprecation: function `test18385.S.foo` function `test18385.S.foo(double)` cannot be overloaded with another `extern(C)` function at fail_compilation/test18385.d(17) +--- +*/ + +extern (C): + +void foo(int) { } +void foo(double) { } + +struct S +{ + static void foo(int) {} + static void foo(double) {} +} + +void foo2(int) { } +extern(D) void foo2(double) { } // OK as it has a different mangling + +void foo3(int) { } +void foo3(double); // duplicate declarations are allowed + +void foo4(); +void foo4() { } + +extern(D) void foo5(); +extern(D) void foo5() { }