$(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 )

$(LEGACY_LNAME2 Predefined-Pragmas, predefined-pragmas, Predefined Pragmas)

$(DDOC_BLANKLINE ) $(P All implementations must support these, even if by just ignoring them:) $(DDOC_BLANKLINE ) $(UL $(LI $(LINK2 #crtctor, pragma crt$(UNDERSCORE )constructor)) $(LI $(LINK2 #crtdtor, pragma crt$(UNDERSCORE )destructor)) $(LI $(LINK2 #inline, pragma inline)) $(LI $(LINK2 #lib, pragma lib)) $(LI $(LINK2 #linkerDirective, pragma linkerDirective)) $(LI $(LINK2 #mangle, pragma mangle)) $(LI $(LINK2 #msg, pragma msg)) $(LI $(LINK2 #printf, pragma printf)) $(LI $(LINK2 #scanf, pragma scanf)) $(LI $(LINK2 #startaddress, pragma startaddress)) ) $(DDOC_BLANKLINE ) $(IMPLEMENTATION_DEFINED An implementation may ignore these pragmas.) $(DDOC_BLANKLINE )

$(LNAME2 crtctor, $(D pragma crt_constructor))

$(DDOC_BLANKLINE ) $(P Annotates a function so it is run after the C runtime library is initialized and before the D runtime library is initialized. ) $(DDOC_BLANKLINE ) $(P The function must:) $(DDOC_BLANKLINE ) $(OL $(LI be 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 )

$(LNAME2 crtdtor, $(D pragma crt_destructor))

$(DDOC_BLANKLINE ) $(P 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 )

$(LNAME2 inline, $(D pragma inline))

$(DDOC_BLANKLINE ) $(P 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.) $(DDOC_BLANKLINE ) $(P It takes two forms:) $(OL $(LI $(D_CODE $(D_KEYWORD pragma)(inline) ) Sets the behavior to match the implementation's default behavior. ) $(LI $(D_CODE $(D_KEYWORD pragma)(inline, AssignExpression) ) The $(GLINK2 expression, 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. ) ) $(DDOC_BLANKLINE ) $(P More than one $(I AssignExpression) is not allowed.) $(DDOC_BLANKLINE ) $(P If there are multiple pragma inlines in a function, the lexically last one takes effect.) $(D_CODE $(D_KEYWORD pragma)(inline): $(D_KEYWORD int) foo($(D_KEYWORD int) x) $(D_COMMENT // foo$(LPAREN)$(RPAREN ) is never inlined ){ $(D_KEYWORD pragma)(inline, $(D_KEYWORD true)); ++x; $(D_KEYWORD pragma)(inline, $(D_KEYWORD false)); $(D_COMMENT // supercedes the others ) $(D_KEYWORD return) x + 3; } ) $(DDOC_BLANKLINE ) $(IMPLEMENTATION_DEFINED $(OL $(LI The default inline behavior is typically selectable with a compiler switch such as $(DDSUBLINK dmd, switch-inline, $(TT -inline).)) $(LI Whether a particular function can be inlined or not is implementation defined.) $(LI What happens for pragma(inline, true) if the function cannot be inlined. An error message is typical.) )) $(DDOC_BLANKLINE )

$(LNAME2 lib, $(D pragma lib))

$(DDOC_BLANKLINE ) $(P There must be one $(ASSIGNEXPRESSION ) and it must evaluate at compile time to a string literal. ) $(D_CODE $(D_KEYWORD pragma)(lib, $(D_STRING "foo.lib")); ) $(DDOC_BLANKLINE ) $(IMPLEMENTATION_DEFINED The string literal specifies the file name of a library file. This name is inserted into the generated object file, or otherwise passed to the linker, so the linker automatically links in that library. ) $(DDOC_BLANKLINE )

$(LNAME2 linkerDirective, $(D pragma linkerDirective))

$(DDOC_BLANKLINE ) $(P There must be one $(ASSIGNEXPRESSION ) and it must evaluate at compile time to a string literal. ) $(D_CODE $(D_KEYWORD pragma)(linkerDirective, $(D_STRING "/FAILIFMISMATCH:_ITERATOR_DEBUG_LEVEL=2")); ) $(DDOC_BLANKLINE ) $(IMPLEMENTATION_DEFINED The string literal specifies a linker directive to be embedded in the generated object file. Linker directives are only supported for MS-COFF output. ) $(DDOC_BLANKLINE )

$(LNAME2 mangle, $(D pragma mangle))

$(DDOC_BLANKLINE ) $(P Overrides the default mangling for a symbol.) $(DDOC_BLANKLINE ) $(P 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 $(ASSIGNEXPRESSION )s, 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 $(I TemplateInstance), the aggregate is treated as a template that has the signature and arguments of the $(I 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. ) $(DDOC_BLANKLINE ) $(P It only applies to function and variable symbols. Other symbols are ignored.) $(DDOC_BLANKLINE ) $(IMPLEMENTATION_DEFINED On macOS and Win32, an extra underscore (_) 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 )

$(LNAME2 msg, $(D pragma msg))

$(DDOC_BLANKLINE ) $(P Each $(ASSIGNEXPRESSION ) is evaluated at compile time and then all are combined into a message.) $(DDOC_BLANKLINE ) $(D_CODE $(D_KEYWORD pragma)(msg, $(D_STRING "compiling..."), 6, 1.0); $(D_COMMENT // prints "compiling...61.0" at compile time )) $(DDOC_BLANKLINE ) $(IMPLEMENTATION_DEFINED The form the message takes and how it is presented to the user. One way is by printing them to the standard error stream.) $(DDOC_BLANKLINE ) $(RATIONALE Analogously to how 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 )

$(LNAME2 printf, $(D pragma printf))

$(DDOC_BLANKLINE ) $(P 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 )

$(LNAME2 scanf, $(D pragma scanf))

$(DDOC_BLANKLINE ) $(P 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 )

$(LNAME2 startaddress, $(D pragma startaddress))

$(DDOC_BLANKLINE ) $(P There must be one $(ASSIGNEXPRESSION ) and it must evaluate at compile time to a function symbol.) $(DDOC_BLANKLINE ) $(IMPLEMENTATION_DEFINED The function symbol specifies the start address for the program. The symbol is inserted into the object file or is otherwise presented to the linker to set the start address. This is not normally used for application level programming, but is for specialized systems work. For applications code, the start address is taken care of by the runtime library. $(DDOC_BLANKLINE ) $(D_CODE $(D_KEYWORD void) foo() { ... } $(D_KEYWORD pragma)(startaddress, foo); ) $(DDOC_BLANKLINE ) ) $(DDOC_BLANKLINE )

$(LNAME2 vendor_specific_pragmas, Vendor Specific Pragmas)

$(DDOC_BLANKLINE ) $(P Vendor specific pragma $(I Identifier)s can be defined if they are prefixed by the vendor's trademarked name, in a similar manner to version identifiers: ) $(DDOC_BLANKLINE ) $(D_CODE $(D_KEYWORD pragma)(DigitalMars_extension) { ... } ) $(DDOC_BLANKLINE ) $(P Implementations must diagnose an error for unrecognized $(I Pragma)s, even if they are vendor specific ones. ) $(DDOC_BLANKLINE ) $(IMPLEMENTATION_DEFINED Vendor specific pragmas.) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE ) $(BEST_PRACTICE vendor specific pragmas should be wrapped in version statements $(DDOC_BLANKLINE ) $(D_CODE $(D_KEYWORD version) (DigitalMars) { $(D_KEYWORD pragma)(DigitalMars_extension) { ... } } ) ) $(DDOC_BLANKLINE ) $(SPEC_SUBNAV_PREV_NEXT attribute, Attributes, expression, Expressions) ) )