Skip to content

Commit

Permalink
Start deprecation period of identical functions in a single module
Browse files Browse the repository at this point in the history
  • Loading branch information
wilzbach committed Jul 8, 2018
1 parent 0d12680 commit bb7f7b9
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 42 deletions.
23 changes: 23 additions & 0 deletions changelog/duplicate-implementations-deprecation.dd
Original file line number Diff line number Diff line change
@@ -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)`.
8 changes: 3 additions & 5 deletions src/dmd/semantic2.d
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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),
Expand All @@ -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),
Expand Down
8 changes: 3 additions & 5 deletions test/fail_compilation/fail17492.d
Original file line number Diff line number Diff line change
@@ -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
*/
Expand Down
42 changes: 13 additions & 29 deletions test/fail_compilation/fail2789.d
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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

Expand All @@ -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

Expand All @@ -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)
{
}
Expand Down
7 changes: 7 additions & 0 deletions test/fail_compilation/fail5634.d
Original file line number Diff line number Diff line change
@@ -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() { }

5 changes: 3 additions & 2 deletions test/fail_compilation/fail7443.d
Original file line number Diff line number Diff line change
Expand Up @@ -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)
---
*/

Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/test18282.d
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ S2000 bar2()
}


void bar2()
void bar3()
{
int i;
char c;
Expand Down
31 changes: 31 additions & 0 deletions test/fail_compilation/test18385.d
Original file line number Diff line number Diff line change
@@ -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() { }

0 comments on commit bb7f7b9

Please sign in to comment.