-
-
Notifications
You must be signed in to change notification settings - Fork 606
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
Fix bugzilla 23812 - ImportC: allow adding function attributes to imp… #16820
Conversation
Thanks for your pull request and interest in making D better, @tim-dlang! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please see CONTRIBUTING.md for more information. If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment. Bugzilla references
Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub run digger -- build "master + dmd#16820" |
b43403d
to
5170c73
Compare
changelog/dmd.importc-pragma-stc.dd
Outdated
``` | ||
#pragma D nogc nothrow | ||
#include <somelibrary.h> | ||
``` | ||
|
||
Default storage classes can be disabled again by adding a minus: | ||
``` | ||
#pragma D -nogc -nothrow | ||
``` |
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.
Why not pragma D push(nogc, nothrow)
and pop
? Which fits better with pragmas of other C compiler vendors.
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.
would pop
just remove nothrow
in that example?
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.
Good idea.
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.
would
pop
just removenothrow
in that example?
Using pop
now reverses the last push
, which can contain multiple storage classes.
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.
Oh ok, so you could do push(nothrow)
and now the situation is nothrow, but not nogc?
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.
Yes, this use case would be more complicated. The pragma could be combined with the original idea of using minus, like this: #pragma D push(-nothrow)
. But I'm not sure, how common this would be.
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.
I think it would be the most common case to default to nothrow, nogc
in C code.
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.
In any case, my use case is handled by any of these mechanisms. Having something is better than nothing.
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.
I think it would be the most common case to default to
nothrow, nogc
in C code.
The obvious exception being functions that do callbacks via a function-pointer parameter.
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.
I have added tests for callbacks. Function pointers get the same attributes as functions, which should cover most use cases.
I would love to see this merged... |
There are multiple extensions like this, and the only thing they share is inconsistency:
Unfortunately, those only apply to a single declaration. The But https://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Structure_002dPacking-Pragmas.html;
Here we are adding a confusingly different syntax:
I suggest a consistent one would be:
It's not necessary to add the D qualifier. |
All looks decent to me! As long as I can do: #pragma attribute(push, nogc, nothrow);
#include <stdio.h> Then I am happy! |
9de583c
to
1e81fb9
Compare
I have implemented the new syntax:
The functionality is the same. |
``` | ||
#pragma attribute(push, [storage classes...]) | ||
``` | ||
The storage classes `nothrow`, `nogc` and `pure` are supported. |
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.
Note that unrecognized attributes are ignored.
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.
Done.
One thing that I don't like about this is that you actually need to uglify your C code to support what should be the most common case on the D side. Why not simply implement this on the D side as an extension of the import statement? i.e.: @nogc import cmodule : func;
pure import cmodule: gun;
pure nothrow @nogc import othercmodule; That way we don't use ugly pragmas to modify C code. Note that this syntax should be restricted only to C modules. |
When is What you ironically are suggesting is adding more C behavior to D, by configuring behavior before including the file. Besides, this means the compiler has to re-parse the whole thing, and define a separate module for each time you import it. It's a much harder change, and leaves some really nasty corner cases. |
This argument is kind of moot considering that you will need to annotate the functions also.
Well, you are importing C modules so the "adding more C behavior to D" ship has already sailed.
No, there are workarounds for that. A potential solution is have something along the lines of I'm just in the boat that C code should be kept clean C code. If we open the door to annotating C code so that it works with D it feels like a lost battle. |
…orted C functions This adds a new pragma for ImportC, which allows to set default storage classes. Only `nothrow`, `@nogc` and `pure` are supported for now. They can be disabled later using `#pragma attribute(pop)`. Unknown storage classes are ignored.
1e81fb9
to
d956dc0
Compare
ImportC modules and D modules are currently very similar: The modules are independent of the context of the importing module. With your proposal they would depend on attributes of the import statement. This would be similar to C includes, where macros before the include can influence parts of a header.
Updating the attributes of a symbol after it was already used in another module would be problematic. The compilation could then depend on the order of modules on the command line or if separate compilation is used. An alternative would be a mixin, which redeclares all functions from an ImportC module with the correct attributes. |
@tim-dlang I agree. The importer must not be able to modify the importee, or the whole module system falls apart. The module import system must:
Another problem is there would be no control over the attributes applied to individual functions. |
So one thing about C code that D does not have is a really easy mechanism to keep your C code "clean", yet still change things globally -- with For example, your use case: @nogc import cmodule : func;
pure import cmodule: gun; Can be done via: // cmodule_nogc.c
pragma attribute(push, nogc)
#include "cmodule.c" // cmodule_pure.c
pragma(attribute(push, pure)
#include "cmodule.c" // d file
import cmodule_nogc : func;
import cmodule_pure : gun; |
@schveiguy yes, those can work |
The new pragma is implemented in dlang/dmd#16820. The documentation is based on the changelog entry.
The new pragma is implemented in dlang/dmd#16820. The documentation is based on the changelog entry.
…orted C functions (dlang#16820) This adds a new pragma for ImportC, which allows to set default storage classes. Only `nothrow`, `@nogc` and `pure` are supported for now. They can be disabled later using `#pragma attribute(pop)`. Unknown storage classes are ignored.
…orted C functions
This adds a new pragma for ImportC, which allows to set default storage classes. Only
nothrow
,@nogc
andpure
are supported for now. They can be disabled laterwith the same pragma using a minususing#pragma D pop
#pragma attribute(pop)
.Unknown pragmas are ignored.
The pragma starts with identifierD
to avoid conflicts.