Pragmas
Pragma: pragma ( Identifier ) pragma ( Identifier , ArgumentList )
Pragmas are a way to pass special information to the compiler and to add vendor specific extensions to D. Pragmas can be used by themselves terminated with a ‘;’, they can influence a statement, a block of statements, a declaration, or a block of declarations.
Pragmas can appear as either declarations, Pragma DeclarationBlock, or as statements, 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 startaddress
pragma crt_constructor
This pragma must directly precede an extern(C) function declaration that must take no argument, even default ones. The function this pragma applies to will be inserted in .init_array or .ctors, depending on the target and compiler implementation. It is equivalent to GCC's __attribute__((constructor)).
__gshared int initCount; pragma(crt_constructor) extern(C) void initializer() { initCount += 1; }
It is useful for system programming and interfacing with C/C++, for example to allow for initialization of the runtime when loading a DSO, or as a simple replacement for shared static this in betterC mode.
A module may contain any number of functions annotated with crt_constructor. The order in which functions are called is undefined and shouldn't be relied upon. A function can be annotated as both crt_constructor and crt_destructor (see below). The runtime is not initialized when the function is called. This pragma does not take any argument and can only be applied to a single declaration, so using them in an AttributeSpecifier is disallowed.
crt_constructor and crt_destructor were implemented in v2.078.0 (2018-01-01). Some compilers exposed non-standard, compiler-specific mechanism before.
pragma crt_destructor
Similarly, pragma(crt_destructor) must also directly precede an extern(C) function declaration that must take no argument, even default ones. The function this pragma applies to will be inserted in .fini_array or .dtors, depending on the target and compiler implementation. It is equivalent to GCC's __attribute__((destructor)).
__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"); }
The runtime might have been terminated and not be usable anymore when the destructors are called. Otherwise, usage and requirements of crt_destructor are similar to those of crt_constructor.
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 three forms:
pragma(inline)
Sets the behavior to match the implementation's default behavior.pragma(inline, false)
Functions are never inlined.pragma(inline, true)
Always inline the functions.
There can be only zero or one AssignExpressions. If one is there, it must be true, false, or an integer value. An integer value is implicitly converted to a bool.
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");
The string literal specifies a linker directive to be embedded in the generated object file.
Linker directives are only supported for MS-COFF output.
pragma mangle
Overrides the default mangling for a symbol.
There must be one AssignExpression and it must evaluate at compile time to a string literal.
pragma(mangle, "body") extern(C) void body_func();
pragma msg
Constructs a message from the ArgumentList.
pragma(msg, "compiling...", 1, 1.0);
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) { ... } }