-
-
Notifications
You must be signed in to change notification settings - Fork 606
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix bugzilla 23812 - ImportC: allow adding function attributes to imp…
…orted C functions (#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.
- Loading branch information
Showing
4 changed files
with
261 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
A pragma for ImportC allows to set `nothrow`, `@nogc` or `pure` | ||
|
||
The following new pragma for ImportC allows to set default storage | ||
classes for function declarations: | ||
``` | ||
#pragma attribute(push, [storage classes...]) | ||
``` | ||
The storage classes `nothrow`, `nogc` and `pure` are supported. | ||
Unrecognized attributes are ignored. | ||
Enabling a default storage class affects all function declarations | ||
after the pragma until it is disabled with another pragma. | ||
Declarations in includes are also affected. The following example | ||
enables `@nogc` and `nothrow` for a library: | ||
|
||
``` | ||
#pragma attribute(push, nogc, nothrow) | ||
#include <somelibrary.h> | ||
``` | ||
|
||
The changed storage classes are pushed on a stack. The last change can | ||
be undone with the following pragma: | ||
``` | ||
#pragma attribute(pop) | ||
``` | ||
This can also disable multiple default storage classes at the same time, | ||
if they were enabled with a single `#pragma attribute(push, ...)` directive. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
|
||
void funcDefault(void); | ||
|
||
#pragma attribute(push, nothrow) | ||
void funcNothrow(void); | ||
#pragma attribute(pop) | ||
|
||
#pragma attribute(push, nogc) | ||
void funcNogc(void); | ||
#pragma attribute(pop) | ||
|
||
#pragma attribute(push, pure) | ||
void funcPure(void); | ||
#pragma attribute(pop) | ||
|
||
#pragma attribute(push, nothrow, nogc) | ||
void funcNothrowNogc(void); | ||
#pragma attribute(pop) | ||
|
||
void funcDefault2(void); | ||
|
||
#pragma attribute(push, nothrow) | ||
#pragma attribute(push, nogc) | ||
void funcNothrowNogc2(void); | ||
#pragma attribute(pop) | ||
void funcNothrow2(void); | ||
#pragma attribute(pop) | ||
|
||
#pragma attribute(push, nothrow) | ||
void funcWithCallback(void (*f)(void)); | ||
struct Callbacks | ||
{ | ||
void (*f)(void); | ||
}; | ||
#pragma attribute(pop) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// EXTRA_FILES: imports/imp23812.c | ||
|
||
import imports.imp23812; | ||
|
||
void callDefault() | ||
{ | ||
funcDefault(); | ||
funcDefault2(); | ||
} | ||
|
||
static assert(!__traits(compiles, () nothrow { funcDefault(); } )); | ||
static assert(!__traits(compiles, () @nogc { funcDefault(); } )); | ||
static assert(!__traits(compiles, () pure { funcDefault(); } )); | ||
|
||
static assert(!__traits(compiles, () nothrow { funcDefault2(); } )); | ||
static assert(!__traits(compiles, () @nogc { funcDefault2(); } )); | ||
static assert(!__traits(compiles, () pure { funcDefault2(); } )); | ||
|
||
void callNothrow() nothrow | ||
{ | ||
funcNothrow(); | ||
funcNothrow2(); | ||
} | ||
|
||
static assert(!__traits(compiles, () @nogc { funcNothrow(); } )); | ||
static assert(!__traits(compiles, () pure { funcNothrow(); } )); | ||
|
||
static assert(!__traits(compiles, () @nogc { funcNothrow2(); } )); | ||
static assert(!__traits(compiles, () pure { funcNothrow2(); } )); | ||
|
||
void callNogc() @nogc | ||
{ | ||
funcNogc(); | ||
} | ||
|
||
static assert(!__traits(compiles, () nothrow { funcNogc(); } )); | ||
static assert(!__traits(compiles, () pure { funcNogc(); } )); | ||
|
||
void callPure() pure | ||
{ | ||
funcPure(); | ||
} | ||
|
||
static assert(!__traits(compiles, () nothrow { funcPure(); } )); | ||
static assert(!__traits(compiles, () @nogc { funcPure(); } )); | ||
|
||
void callNothrowNogc() nothrow @nogc | ||
{ | ||
funcNothrowNogc(); | ||
funcNothrowNogc2(); | ||
} | ||
|
||
static assert(!__traits(compiles, () pure { funcNothrowNogc(); } )); | ||
|
||
static assert(!__traits(compiles, () pure { funcNothrowNogc2(); } )); | ||
|
||
extern(C) void callbackDefault() | ||
{ | ||
} | ||
|
||
extern(C) void callbackNothrow() nothrow | ||
{ | ||
} | ||
|
||
void callFuncWithCallback() nothrow | ||
{ | ||
funcWithCallback(&callbackNothrow); | ||
|
||
Callbacks callbacks; | ||
callbacks.f = &callbackNothrow; | ||
} | ||
|
||
static assert(!__traits(compiles, () { funcWithCallback(&callbackDefault); } )); | ||
|
||
static assert(!__traits(compiles, () { Callbacks callbacks; callbacks.f = &callbackDefault; } )); |