$(DDOC $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE ) $(SPEC_S Pragmas, $(DDOC_BLANKLINE ) $(HEADERNAV_TOC $(HEADERNAV_SUBITEMS predefined-pragmas, Predefined Pragmas, $(HEADERNAV_ITEM crtctor, $(D pragma crt_constructor)) $(HEADERNAV_ITEM crtdtor, $(D pragma crt_destructor)) $(HEADERNAV_ITEM inline, $(D pragma inline)) $(HEADERNAV_ITEM lib, $(D pragma lib)) $(HEADERNAV_ITEM linkerDirective, $(D pragma linkerDirective)) $(HEADERNAV_ITEM mangle, $(D pragma mangle)) $(HEADERNAV_ITEM msg, $(D pragma msg)) $(HEADERNAV_ITEM printf, $(D pragma printf)) $(HEADERNAV_ITEM scanf, $(D pragma scanf)) $(HEADERNAV_ITEM startaddress, $(D pragma startaddress)) ) $(HEADERNAV_ITEM vendor_specific_pragmas, Vendor Specific Pragmas) ) $(DDOC_BLANKLINE ) $(GRAMMAR $(GNAME PragmaDeclaration): $(GLINK Pragma) $(D ;) $(GLINK Pragma) $(GLINK2 attribute, DeclarationBlock) $(DDOC_BLANKLINE ) $(GNAME PragmaStatement): $(GLINK Pragma) $(D ;) $(GLINK Pragma) $(GLINK2 statement, NoScopeStatement) $(DDOC_BLANKLINE ) $(GNAME Pragma): $(D pragma) $(D $(LPAREN)) $(GLINK_LEX Identifier) $(D $(RPAREN )) $(D pragma) $(D $(LPAREN)) $(GLINK_LEX Identifier) $(D ,) $(GLINK2 expression, ArgumentList) $(D $(RPAREN )) ) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE ) $(P Pragmas pass special information to the implementation and can add vendor specific extensions. Pragmas can be used by themselves terminated with a $(TT ;), and can apply to a statement, a block of statements, a declaration, or a block of declarations. ) $(DDOC_BLANKLINE ) $(P Pragmas can be either a $(GLINK PragmaDeclaration) or a $(GLINK PragmaStatement). ) $(DDOC_BLANKLINE ) $(D_CODE $(D_KEYWORD pragma)(ident); $(D_COMMENT // just by itself ) $(D_KEYWORD pragma)(ident) declaration; $(D_COMMENT // influence one declaration ) $(D_KEYWORD pragma)(ident): $(D_COMMENT // influence subsequent declarations ) declaration; declaration; $(D_KEYWORD pragma)(ident) $(D_COMMENT // influence block of declarations ){ declaration; declaration; } $(D_KEYWORD pragma)(ident) statement; $(D_COMMENT // influence one statement ) $(D_KEYWORD pragma)(ident) $(D_COMMENT // influence block of statements ){ statement; statement; } ) $(DDOC_BLANKLINE ) $(P The kind of pragma it is determined by the $(I Identifier). $(GLINK2 expression, ArgumentList) is a comma-separated list of $(ASSIGNEXPRESSION )s. The $(ASSIGNEXPRESSION )s must be parsable as expressions, but their meaning is up to the individual pragma semantics. ) $(DDOC_BLANKLINE )
extern (C)
)
$(LI not have any parameters)
$(LI not be a non-static member function)
$(LI be a function definition, not a declaration (i.e. it must have a function body))
$(LI not return a type that has a destructor)
$(LI not be a nested function)
)
$(DDOC_BLANKLINE )
$(D_CODE $(D_KEYWORD __gshared) $(D_KEYWORD int) initCount;
$(D_KEYWORD pragma)(crt_constructor)
$(D_KEYWORD extern)(C) $(D_KEYWORD void) initializer() { initCount += 1; }
)
$(DDOC_BLANKLINE )
$(P No arguments to the pragma are allowed.)
$(DDOC_BLANKLINE )
$(P A function may be annotated with both pragma(crt_constructor)
and pragma(crt_destructor)
.
)
$(DDOC_BLANKLINE )
$(P Annotating declarations other than function definitions has no effect.)
$(DDOC_BLANKLINE )
$(P Annotating a struct or class definition does not affect the members of
the aggregate.)
$(DDOC_BLANKLINE )
$(P A function that is annotated with pragma(crt_constructor)
may initialize
const
or immutable
variables.)
$(DDOC_BLANKLINE )
$(BEST_PRACTICE Use 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
$(DDLINK spec/betterc, betterC mode, betterC mode).
)
$(DDOC_BLANKLINE )
$(IMPLEMENTATION_DEFINED The order in which functions annotated with pragma(crt_constructor)
are run is implementation defined.
)
$(DDOC_BLANKLINE )
$(BEST_PRACTICE to control the order in which the functions are called within one module, write
a single function that calls them in the desired order, and only annotate that function.
)
$(DDOC_BLANKLINE )
$(IMPLEMENTATION_DEFINED This uses the mechanism C compilers use to run
code before main()
is called. C++ compilers use it to run static
constructors and destructors.
For example, GCC's $(LINK2 https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html, __attribute__((constructor))
)
is equivalent.
Digital Mars C uses $(TT _STI) and $(TT _STD) identifier prefixes to mark crt_constructor and crt_destructor functions.
)
$(DDOC_BLANKLINE )
$(IMPLEMENTATION_DEFINED A reference to the annotated function will be inserted in
the $(TT .init_array) section for Elf systems,
the $(TT XI) section for Win32 OMF systems,
the $(TT .CRT$XCU) section for Windows MSCOFF systems,
and the $(TT __mod_init_func) section for OSX systems.
)
$(DDOC_BLANKLINE )
$(NOTE crt_constructor
and crt_destructor
were implemented in
$(LINK2 $(ROOT_DIR )changelog/2.078.0.html, v2.078.0 (2018-01-01)).
Some compilers exposed non-standard, compiler-specific mechanism before.
)
$(DDOC_BLANKLINE )
pragma(crt_destructor)
works the same as pragma(crt_constructor)
except:)
$(DDOC_BLANKLINE )
$(OL $(LI 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.)
$(LI The order in which the annotated functions are run is the reverse of those functions
annotated with pragma(crt_constructor)
.)
)
$(DDOC_BLANKLINE )
$(IMPLEMENTATION_DEFINED This uses the mechanism C compilers use to run
code after main()
returns or exit()
is called. C++ compilers use it to run static
destructors.
For example, GCC's $(LINK2 https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html, __attribute__((destructor))
)
is equivalent.
Digital Mars C uses $(TT _STI) and $(TT _STD) identifier prefixes to mark crt_constructor and crt_destructor functions.
)
$(DDOC_BLANKLINE )
$(IMPLEMENTATION_DEFINED A reference to the annotated function will be inserted in
the $(TT .fini_array) section for Elf systems,
the $(TT XC) section for Win32 OMF systems,
the $(TT .CRT$XPU) section for Windows MSCOFF systems,
and the $(TT __mod_term_func) section for OSX systems.
)
$(DDOC_BLANKLINE )
$(D_CODE $(D_KEYWORD __gshared) $(D_KEYWORD int) initCount;
$(D_KEYWORD pragma)(crt_constructor)
$(D_KEYWORD extern)(C) $(D_KEYWORD void) initialize() { initCount += 1; }
$(D_KEYWORD pragma)(crt_destructor)
$(D_KEYWORD extern)(C) $(D_KEYWORD void) deinitialize() { initCount -= 1; }
$(D_KEYWORD pragma)(crt_constructor)
$(D_KEYWORD pragma)(crt_destructor)
$(D_KEYWORD extern)(C) $(D_KEYWORD void) innuendo() { printf($(D_STRING "Inside a constructor... Or destructor?\n")); }
)
$(DDOC_BLANKLINE )
$(DDOC_BLANKLINE )
pragma(inline, true)
if the function cannot be inlined.
An error message is typical.)
))
$(DDOC_BLANKLINE )
_
) is prepended to the string
since 2.079, as is done by the C/C++ toolchain. This allows using the same pragma(mangle)
for all compatible (POSIX in one case, win64 in another) platforms instead of having to special-case.
)
$(DDOC_BLANKLINE )
$(RATIONALE $(UL $(LI Enables linking to symbol names that D cannot represent.)
$(LI Enables linking to a symbol which is a D keyword, since an $(GLINK_LEX Identifier)
cannot be a keyword.)
)
$(D_CODE $(D_KEYWORD pragma)(mangle, $(D_STRING "body"))
$(D_KEYWORD extern)(C) $(D_KEYWORD void) body_func();
$(D_KEYWORD pragma)(mangle, $(D_STRING "function"))
$(D_KEYWORD extern)(C++) $(D_KEYWORD struct) _function {}
$(D_KEYWORD template) ScopeClass(C)
{
$(D_KEYWORD pragma)(mangle, C.stringof, C)
$(D_KEYWORD struct) ScopeClass { $(D_KEYWORD align)($(D_KEYWORD __traits)(classInstanceAlignment, C)) $(D_KEYWORD void)[$(D_KEYWORD __traits)(classInstanceSize, C)] buffer; }
}
$(D_KEYWORD extern)(C++)
{
$(D_KEYWORD class) MyClassA(T) {}
$(D_KEYWORD void) func($(D_KEYWORD ref) ScopeClass!(MyClassA!$(D_KEYWORD int))); $(D_COMMENT // mangles as MyClass<int>&
)}
)
)
$(DDOC_BLANKLINE )
$(DDOC_BLANKLINE )
writeln()
performs a role of writing informational messages during runtime,
pragma(msg)
performs the equivalent role at compile time.
For example,
$(D_CODE $(D_KEYWORD static) $(D_KEYWORD if) (kilroy)
$(D_KEYWORD pragma)(msg, $(D_STRING "Kilroy was here"));
$(D_KEYWORD else)
$(D_KEYWORD pragma)(msg, $(D_STRING "Kilroy got lost"));
)
)
$(DDOC_BLANKLINE )
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.
)
$(DDOC_BLANKLINE )
$(P 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.)
$(DDOC_BLANKLINE )
$(P Diagnosed incompatibilities are:)
$(DDOC_BLANKLINE )
$(UL $(LI incompatible sizes which may cause argument misalignment)
$(LI deferencing arguments that are not pointers)
$(LI insufficient number of arguments)
$(LI struct arguments)
$(LI array and slice arguments)
$(LI non-pointer arguments to s
specifier)
$(LI non-standard formats)
$(LI undefined behavior per C99)
)
$(DDOC_BLANKLINE )
$(P Per the C99 Standard, extra arguments are ignored.)
$(DDOC_BLANKLINE )
$(P Ignored mismatches are:)
$(DDOC_BLANKLINE )
$(UL $(LI sign mismatches, such as printing an int
with a %u
format)
$(LI 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
)
)
$(DDOC_BLANKLINE )
$(D_CODE printf($(D_STRING "%k\n"), value); $(D_COMMENT // error: non-Standard format k
)printf($(D_STRING "%d\n")); $(D_COMMENT // error: not enough arguments
)printf($(D_STRING "%d\n"), 1, 2); $(D_COMMENT // ok, extra arguments ignored
))
$(DDOC_BLANKLINE )
$(BEST_PRACTICE In order to use non-Standard printf/scanf formats, an easy workaround is:
$(D_CODE $(D_KEYWORD const) format = $(D_STRING "%k\n");
printf(format.ptr, value); $(D_COMMENT // no error
))
)
$(DDOC_BLANKLINE )
$(BEST_PRACTICE Most of the errors detected are portability issues. For instance,
$(DDOC_BLANKLINE )
$(D_CODE string s;
printf($(D_STRING "%.*s\n"), s.length, s.ptr);
printf($(D_STRING "%d\n"), s.sizeof);
$(D_KEYWORD ulong) u;
scanf($(D_STRING "%lld%*c\n"), &u);
)
should be replaced with:
$(D_CODE string s;
printf($(D_STRING "%.*s\n"), $(D_KEYWORD cast)($(D_KEYWORD int)) s.length, s.ptr);
printf($(D_STRING "%zd\n"), s.sizeof);
$(D_KEYWORD ulong) u;
scanf($(D_STRING "%llu%*c\n"), &u);
)
)
$(DDOC_BLANKLINE )
$(P 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.
)
$(DDOC_BLANKLINE )
$(DDOC_BLANKLINE )
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.
)
$(DDOC_BLANKLINE )
$(P 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.)
$(DDOC_BLANKLINE )
$(P Diagnosed incompatibilities are:)
$(DDOC_BLANKLINE )
$(UL $(LI argument is not a pointer to the format specified type)
$(LI insufficient number of arguments)
$(LI non-standard formats)
$(LI undefined behavior per C99)
)
$(DDOC_BLANKLINE )
$(P Per the C99 Standard, extra arguments are ignored.)
$(DDOC_BLANKLINE )
$(P 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.
)
$(DDOC_BLANKLINE )
$(DDOC_BLANKLINE )
$(DDOC_BLANKLINE )
$(DDOC_BLANKLINE )