Pragmas
PragmaDeclaration: Pragma ; Pragma DeclarationBlock PragmaStatement: Pragma ; Pragma NoScopeStatement Pragma: pragma ( Identifier ) pragma ( Identifier , ArgumentList )
Pragmas pass special information to the implementation and can add vendor specific extensions. Pragmas can be used by themselves terminated with a ;, and can apply to a statement, a block of statements, a declaration, or a block of declarations.
Pragmas can be either a PragmaDeclaration or a PragmaStatement.
pragma(ident); // just by itself pragma(ident) declaration; // influence one declaration pragma(ident): // influence subsequent declarations declaration; declaration; pragma(ident) // influence block of declarations { declaration; declaration; } pragma(ident) statement; // influence one statement pragma(ident) // influence block of statements { statement; statement; }
The kind of pragma it is determined by the Identifier. ArgumentList is a comma-separated list of AssignExpressions. The AssignExpressions must be parsable as expressions, but their meaning is up to the individual pragma semantics.
Predefined Pragmas
All implementations must support these, even if by just ignoring them:
- pragma crt_constructor
- pragma crt_destructor
- pragma inline
- pragma lib
- pragma linkerDirective
- pragma mangle
- pragma msg
- pragma printf
- pragma scanf
- pragma startaddress
pragma crt_constructor
Annotates a function so it is run after the C runtime library is initialized and before the D runtime library is initialized.
The function must:
- be extern (C)
- not have any parameters
- not be a non-static member function
- be a function definition, not a declaration (i.e. it must have a function body)
- not return a type that has a destructor
- not be a nested function
__gshared int initCount; pragma(crt_constructor) extern(C) void initializer() { initCount += 1; }
No arguments to the pragma are allowed.
A function may be annotated with both pragma(crt_constructor) and pragma(crt_destructor).
Annotating declarations other than function definitions has no effect.
Annotating a struct or class definition does not affect the members of the aggregate.
pragma crt_destructor
pragma(crt_destructor) works the same as pragma(crt_constructor) except:
- Annotates a function so it is run after the D runtime library is terminated and before the C runtime library is terminated. Calling C's exit() function also causes the annotated functions to run.
- The order in which the annotated functions are run is the reverse of those functions annotated with pragma(crt_constructor).
__gshared int initCount; pragma(crt_constructor) extern(C) void initialize() { initCount += 1; } pragma(crt_destructor) extern(C) void deinitialize() { initCount -= 1; } pragma(crt_constructor) pragma(crt_destructor) extern(C) void innuendo() { printf("Inside a constructor... Or destructor?\n"); }
pragma inline
Affects whether functions are inlined or not. If at the declaration level, it affects the functions declared in the block it controls. If inside a function, it affects the function it is enclosed by.
It takes two forms:
pragma(inline)
Sets the behavior to match the implementation's default behavior.pragma(inline, AssignExpression)
The AssignExpression is evaluated and must have a type that can be converted to a boolean. If the result is false the functions are never inlined, otherwise they are always inlined.
More than one AssignExpression is not allowed.
If there are multiple pragma inlines in a function, the lexically last one takes effect.
pragma(inline): int foo(int x) // foo() is never inlined { pragma(inline, true); ++x; pragma(inline, false); // supercedes the others return x + 3; }
- The default inline behavior is typically selectable with a compiler switch such as -inline.
- Whether a particular function can be inlined or not is implementation defined.
- What happens for pragma(inline, true) if the function cannot be inlined. An error message is typical.
pragma lib
There must be one AssignExpression and it must evaluate at compile time to a string literal.
pragma(lib, "foo.lib");
pragma linkerDirective
There must be one AssignExpression and it must evaluate at compile time to a string literal.
pragma(linkerDirective, "/FAILIFMISMATCH:_ITERATOR_DEBUG_LEVEL=2");
pragma mangle
Overrides the default mangling for a symbol.
For variables and functions there must be one AssignExpression and it must evaluate at compile time to a string literal. For aggregates there may be one or two AssignExpressions, one of which must evaluate at compile time to a string literal and one which must evaluate to a symbol. If that symbol is a TemplateInstance, the aggregate is treated as a template that has the signature and arguments of the TemplateInstance. The identifier of the symbol is used when no string is supplied. Both arguments may be used used when an aggregate's name is a D keyword.
It only applies to function and variable symbols. Other symbols are ignored.
- Enables linking to symbol names that D cannot represent.
- Enables linking to a symbol which is a D keyword, since an Identifier cannot be a keyword.
pragma(mangle, "body") extern(C) void body_func(); pragma(mangle, "function") extern(C++) struct _function {} template ScopeClass(C) { pragma(mangle, C.stringof, C) struct ScopeClass { align(__traits(classInstanceAlignment, C)) void[__traits(classInstanceSize, C)] buffer; } } extern(C++) { class MyClassA(T) {} void func(ref ScopeClass!(MyClassA!int)); // mangles as MyClass<int>& }
pragma msg
Each AssignExpression is evaluated at compile time and then all are combined into a message.
pragma(msg, "compiling...", 6, 1.0); // prints "compiling...61.0" at compile time
static if (kilroy) pragma(msg, "Kilroy was here"); else pragma(msg, "Kilroy got lost");
pragma printf
pragma(printf) specifies that a function declaration is a printf-like function, meaning it is an extern (C) or extern (C++) function with a format parameter accepting a pointer to a 0-terminated char string conforming to the C99 Standard 7.19.6.1, immediately followed by either a ... variadic argument list or a parameter of type va_list as the last parameter.
If the format argument is a string literal, it is verified to be a valid format string per the C99 Standard. If the format parameter is followed by ..., the number and types of the variadic arguments are checked against the format string.
Diagnosed incompatibilities are:
- incompatible sizes which may cause argument misalignment
- deferencing arguments that are not pointers
- insufficient number of arguments
- struct arguments
- array and slice arguments
- non-pointer arguments to s specifier
- non-standard formats
- undefined behavior per C99
Per the C99 Standard, extra arguments are ignored.
Ignored mismatches are:
- sign mismatches, such as printing an int with a %u format
- integral promotion mismatches, where the format specifies a smaller integral type than int or uint, such as printing a short with the %d format rather than %hd
printf("%k\n", value); // error: non-Standard format k printf("%d\n"); // error: not enough arguments printf("%d\n", 1, 2); // ok, extra arguments ignored
const format = "%k\n"; printf(format.ptr, value); // no error
string s; printf("%.*s\n", s.length, s.ptr); printf("%d\n", s.sizeof); ulong u; scanf("%lld%*c\n", &u);should be replaced with:
string s; printf("%.*s\n", cast(int) s.length, s.ptr); printf("%zd\n", s.sizeof); ulong u; scanf("%llu%*c\n", &u);
pragma(printf) applied to declarations that are not functions are ignored. In particular, it has no effect on the declaration of a pointer to function type.
pragma scanf
pragma(scanf) specifies that a function declaration is a scanf-like function, meaning it is an extern (C) or extern (C++) function with a format parameter accepting a pointer to a 0-terminated char string conforming to the C99 Standard 7.19.6.2, immediately followed by either a ... variadic argument list or a parameter of type va_list as the last parameter.
If the format argument is a string literal, it is verified to be a valid format string per the C99 Standard. If the format parameter is followed by ..., the number and types of the variadic arguments are checked against the format string.
Diagnosed incompatibilities are:
- argument is not a pointer to the format specified type
- insufficient number of arguments
- non-standard formats
- undefined behavior per C99
Per the C99 Standard, extra arguments are ignored.
pragma(scanf) applied to declarations that are not functions are ignored. In particular, it has no effect on the declaration of a pointer to function type.
pragma startaddress
There must be one AssignExpression and it must evaluate at compile time to a function symbol.
void foo() { ... } pragma(startaddress, foo);
Vendor Specific Pragmas
Vendor specific pragma Identifiers can be defined if they are prefixed by the vendor's trademarked name, in a similar manner to version identifiers:
pragma(DigitalMars_extension) { ... }
Implementations must diagnose an error for unrecognized Pragmas, even if they are vendor specific ones.
version (DigitalMars) { pragma(DigitalMars_extension) { ... } }