-
-
Notifications
You must be signed in to change notification settings - Fork 608
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Start deprecation period of identical functions in a single module #8429
Changes from all commits
47a273f
b7cbed5
4070fdb
69b7046
570460d
ca701de
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
Diagnostics for conflicting function definitions within a module | ||
|
||
Previously, multiple definitions of identical functions within a module were not | ||
recognized, although they have the same mangling. This was problematic because a | ||
binary cannot contain multiple definitions of a symbol, which caused undefined | ||
behavior depending on the compiler backend. | ||
|
||
DMD will now raise an error message if there are conflicting implementations | ||
within a single module: | ||
|
||
--- | ||
void foo() {} | ||
void foo() {} // error | ||
--- | ||
|
||
Multiple declarations are still allowed as long as there is at most one definition: | ||
|
||
--- | ||
void bar(int); | ||
void bar(int) { } | ||
void bar(int); | ||
--- | ||
|
||
DMD will issue a deprecation for mangling schemes that don't support overloading | ||
(`extern(C|Windows|System)`): | ||
|
||
--- | ||
extern(C): | ||
void foo(int) { } | ||
void foo(double) { } // deprecation | ||
--- | ||
|
||
This deprecation will become an error in 2.105. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* | ||
Reduced from the assertion failure in the glue layer when compiling DWT. | ||
A `compilable` test because it needs codegen. | ||
|
||
Remove this test once the deprecation for conflicting deprecations ends, | ||
see visit(FuncDeclaration) in semantic2.d for details. | ||
|
||
TEST_OUTPUT: | ||
--- | ||
compilable/test18385.d(23): Deprecation: function `test18385.is_paragraph_start` cannot overload `extern(C)` function at compilable/test18385.d(22) | ||
compilable/test18385.d(26): Deprecation: function `test18385.foo` cannot overload `extern(C)` function at compilable/test18385.d(25) | ||
compilable/test18385.d(29): Deprecation: function `test18385.trust` cannot overload `extern(C)` function at compilable/test18385.d(28) | ||
compilable/test18385.d(32): Deprecation: function `test18385.purity` cannot overload `extern(C)` function at compilable/test18385.d(31) | ||
compilable/test18385.d(35): Deprecation: function `test18385.nogc` cannot overload `extern(C)` function at compilable/test18385.d(34) | ||
compilable/test18385.d(38): Deprecation: function `test18385.nothrow_` cannot overload `extern(C)` function at compilable/test18385.d(37) | ||
compilable/test18385.d(41): Deprecation: function `test18385.live` cannot overload `extern(C)` function at compilable/test18385.d(40) | ||
--- | ||
*/ | ||
|
||
extern(C) | ||
{ | ||
uint is_paragraph_start(){ return 0; } | ||
uint is_paragraph_start(int){ return 0; } | ||
|
||
void foo(char, bool) {} | ||
void foo(byte, char) {} | ||
|
||
void trust() {} | ||
void trust() @safe {} | ||
|
||
void purity() {} | ||
void purity() pure {} | ||
|
||
void nogc() {} | ||
void nogc() @safe {} | ||
|
||
void nothrow_() {} | ||
void nothrow_() nothrow {} | ||
|
||
void live() {} | ||
void live() @live {} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,7 +46,7 @@ S2000 bar2() | |
} | ||
|
||
|
||
void bar2() | ||
void bar3() | ||
{ | ||
int i; | ||
char c; | ||
|
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` cannot overload `extern(C)` function at fail_compilation/test18385.d(12) | ||
fail_compilation/test18385.d(18): Deprecation: function `test18385.S.foo` cannot overload `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 | ||
MoonlightSentinel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
void foo3(int) { } | ||
void foo3(double); // duplicate declarations are allowed | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is not a duplicate declaration, this is declaring an overload. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (so you probably wanted to write There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess the rational is that this is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. argh... disregard my comments on this piece. Perhaps explicitly add There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not convinced this avoid-explicit-casts use-case is worth the ugly inconsistent AST, and having to handle incompatible declarations, incl. casts, in the backend. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I follow. This PR just tries to enable a deprecation of being more restrictive than dmd is currently. It was originally intended for 2.079, but got disabled/reverted due to people already complaining about it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah sorry I meant the test; I'd rather have it check that a compatible declaration ( |
||
|
||
void foo4(); | ||
void foo4() { } | ||
|
||
extern(D) void foo5(); | ||
extern(D) void foo5() { } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remind me why this shouldn't be allowed? These two symbols are part of a struct and therefore will get mangled as D symbols, even though the linkage is
extern (C)
.The changelog entry says: "Note that this change is only relevant for mangling schemes that do no support
overloading". The D mangling scheme does support overloading. Obviously the implementation is not looking at the mangled name when deciding if it should issue a deprecation message or not. Make up your minds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed above, the current behaviour of
extern(C)
not changing the mangling inside of a struct is a bug because the function still adheres to the C ABI.The current implementation could cater for that special case but I don't think that it should. Having the deprecation now will allow for a smoother transition when fixing
extern(C)
insidestruct
s.