Merge pull request #531 from BBasile/upd-const

update constants
merged-on-behalf-of: BBasile <BBasile@users.noreply.github.com>
This commit is contained in:
The Dlang Bot 2018-09-16 12:12:08 +02:00 committed by GitHub
commit 26663f1a59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 463 additions and 315 deletions

View File

@ -49,9 +49,9 @@ pragma(ident) // influence block of statements
----------------- -----------------
$(P The kind of pragma it is determined by the $(I Identifier). $(P The kind of pragma it is determined by the $(I Identifier).
$(I ExpressionList) is a comma-separated list of $(GLINK2 expression, ArgumentList) is a comma-separated list of
$(ASSIGNEXPRESSION)s. The $(ASSIGNEXPRESSION)s must be $(ASSIGNEXPRESSION)s. The $(ASSIGNEXPRESSION)s must be
parsable as expressions, but what they mean semantically parsable as expressions, but their meaning
is up to the individual pragma semantics. is up to the individual pragma semantics.
) )
@ -62,18 +62,19 @@ $(P All implementations must support these, even if by just ignoring them:)
$(UL $(UL
$(LI $(LINK2 #inline, pragma inline)) $(LI $(LINK2 #inline, pragma inline))
$(LI $(LINK2 #lib, pragma lib)) $(LI $(LINK2 #lib, pragma lib))
$(LI $(LINK2 #linkerDirective, pragma linkerDirective))
$(LI $(LINK2 #mangle, pragma mangle)) $(LI $(LINK2 #mangle, pragma mangle))
$(LI $(LINK2 #msg, pragma msg)) $(LI $(LINK2 #msg, pragma msg))
$(LI $(LINK2 #startaddress, pragma startaddress)) $(LI $(LINK2 #startaddress, pragma startaddress))
) )
$(DL $(IMPLEMENTATION_DEFINED An implementation may ignore these pragmas.)
$(DT $(LNAME2 inline, $(D inline))) $(H3 $(LNAME2 inline, $(D pragma inline)))
$(DD $(P Affects whether functions are inlined or not. If at the declaration level, it
$(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 functions declared in the block it controls. If inside a function, it
affects the function it is enclosed by. If there are multiple pragma inlines in a function, affects the function it is enclosed by.)
the lexically last one takes effect.)
$(P It takes three forms:) $(P It takes three forms:)
$(OL $(OL
@ -81,8 +82,7 @@ $(UL
--- ---
pragma(inline) pragma(inline)
--- ---
Sets the behavior to match the default behavior set by the compiler switch Sets the behavior to match the implementation's default behavior.
$(DDSUBLINK dmd, switch-inline, $(TT -inline)).
) )
$(LI $(LI
--- ---
@ -94,12 +94,16 @@ pragma(inline, false)
--- ---
pragma(inline, true) pragma(inline, true)
--- ---
If a function cannot be inlined with the $(DDSUBLINK dmd, switch-inline, $(TT -inline)) Always inline the functions.
switch, an error message is issued. This is expected to be improved in the future to causing
functions to always be inlined regardless of compiler switch settings. Whether a compiler can
inline a particular function or not is implementation defined.
) )
) )
$(P There can be only zero or one $(I AssignExpression)s. If one is there, it must
be `true`, `false`, or an integer value. An integer value is implicitly converted
to a bool.)
$(P If there are multiple pragma inlines in a function,
the lexically last one takes effect.)
--- ---
pragma(inline): pragma(inline):
int foo(int x) // foo() is never inlined int foo(int x) // foo() is never inlined
@ -110,52 +114,96 @@ int foo(int x) // foo() is never inlined
return x + 3; return x + 3;
} }
--- ---
$(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.)
))
$(H3 $(LNAME2 lib, $(D pragma lib)))
$(P There must be one $(ASSIGNEXPRESSION) and it must evaluate at compile time to a string literal.
) )
$(DT $(LNAME2 lib, $(D lib)))
$(DD Inserts a directive in the object file to link in the library
specified by the $(ASSIGNEXPRESSION).
The $(ASSIGNEXPRESSION)s must be a string literal:
----------------- -----------------
pragma(lib, "foo.lib"); pragma(lib, "foo.lib");
----------------- -----------------
$(IMPLEMENTATION_DEFINED
Typically, the string literal specifies the file name of a library file. This name
is inserted into the generated object file, or otherwise is passed to the linker,
so the linker automatically links in that library.
) )
$(H3 $(LNAME2 linkerDirective, $(D pragma linkerDirective)))
$(DT $(LNAME2 mangle, $(D mangle))) $(P There must be one $(ASSIGNEXPRESSION) and it must evaluate at compile time to a string literal.
$(DD Overrides the default mangling for a symbol. It's only effective )
-----------------
pragma(linkerDirective, "/FAILIFMISMATCH:_ITERATOR_DEBUG_LEVEL=2");
-----------------
$(IMPLEMENTATION_DEFINED
$(P The string literal specifies a linker directive to be embedded in the generated object file.)
$(P Linker directives are only supported for MS-COFF output.)
)
$(H3 $(LNAME2 mangle, $(D pragma mangle)))
$(P Overrides the default mangling for a symbol.)
$(P There must be one $(ASSIGNEXPRESSION) and it must evaluate at compile time to a string literal.
)
$(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.
)
$(IMPLEMENTATION_DEFINED It's only effective
when the symbol is a function declaration or a variable declaration. when the symbol is a function declaration or a variable declaration.
For example this allows linking to a symbol which is a D keyword, which would normally For example this allows linking to a symbol which is a D keyword, which would normally
be disallowed as a symbol name: be disallowed as a symbol name:
)
----------------- -----------------
pragma(mangle, "body") pragma(mangle, "body")
extern(C) void body_func(); extern(C) void body_func();
----------------- -----------------
)
$(DT $(LNAME2 msg, $(D msg))) $(H3 $(LNAME2 msg, $(D pragma msg)))
$(DD Constructs a message from the arguments and prints to the standard error stream while compiling:
$(P Constructs a message from the $(I ArgumentList).)
----------------- -----------------
pragma(msg, "compiling...", 1, 1.0); pragma(msg, "compiling...", 1, 1.0);
----------------- -----------------
)
$(IMPLEMENTATION_DEFINED The arguments are typically presented to the user during compilation,
such as by printing them to the standard error stream.)
$(DT $(LNAME2 startaddress, $(D startaddress))) $(H3 $(LNAME2 startaddress, $(D pragma startaddress)))
$(DD Puts a directive into the object file saying that the
function specified in the first argument will be the $(P There must be one $(ASSIGNEXPRESSION) and it must evaluate at compile time to a function symbol.)
start address for the program:
$(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.
----------------- -----------------
void foo() { ... } void foo() { ... }
pragma(startaddress, foo); pragma(startaddress, foo);
----------------- -----------------
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.
)
) )
$(H2 $(LNAME2 vendor_specific_pragmas, Vendor Specific Pragmas)) $(H2 $(LNAME2 vendor_specific_pragmas, Vendor Specific Pragmas))
@ -165,22 +213,28 @@ $(H2 $(LNAME2 vendor_specific_pragmas, Vendor Specific Pragmas))
to version identifiers: to version identifiers:
) )
----------------- ---
pragma(DigitalMars_funky_extension) { ... } pragma(DigitalMars_extension) { ... }
----------------- ---
$(P Compilers must diagnose an error for unrecognized $(I Pragma)s, $(P Implementations must diagnose an error for unrecognized $(I Pragma)s,
even if they are vendor specific ones. This implies that vendor even if they are vendor specific ones.
specific pragmas should be wrapped in version statements: )
)
----------------- $(IMPLEMENTATION_DEFINED Vendor specific pragmas.)
version (DigitalMars)
{
pragma(DigitalMars_funky_extension) $(BEST_PRACTICE vendor
{ ... } specific pragmas should be wrapped in version statements
}
----------------- ---
version (DigitalMars)
{
pragma(DigitalMars_extension)
{ ... }
}
---
)
$(SPEC_SUBNAV_PREV_NEXT attribute, Attributes, expression, Expressions) $(SPEC_SUBNAV_PREV_NEXT attribute, Attributes, expression, Expressions)
) )

View File

@ -18,52 +18,54 @@ $(GNAME TraitsExpression):
$(D __traits) $(D $(LPAREN)) $(GLINK TraitsKeyword) $(D ,) $(GLINK TraitsArguments) $(D $(RPAREN)) $(D __traits) $(D $(LPAREN)) $(GLINK TraitsKeyword) $(D ,) $(GLINK TraitsArguments) $(D $(RPAREN))
$(GNAME TraitsKeyword): $(GNAME TraitsKeyword):
$(GBLINK isAbstractClass) $(GLINK isAbstractClass)
$(GBLINK isArithmetic) $(GLINK isArithmetic)
$(GBLINK isAssociativeArray) $(GLINK isAssociativeArray)
$(GBLINK isFinalClass) $(GLINK isFinalClass)
$(GBLINK isPOD) $(GLINK isPOD)
$(GBLINK isNested) $(GLINK isNested)
$(GBLINK isFuture) $(GLINK isFuture)
$(GBLINK isDeprecated) $(GLINK isDeprecated)
$(GBLINK isFloating) $(GLINK isFloating)
$(GBLINK isIntegral) $(GLINK isIntegral)
$(GBLINK isScalar) $(GLINK isScalar)
$(GBLINK isStaticArray) $(GLINK isStaticArray)
$(GBLINK isUnsigned) $(GLINK isUnsigned)
$(GBLINK isDisabled) $(GLINK isDisabled)
$(GBLINK isVirtualFunction) $(GLINK isVirtualFunction)
$(GBLINK isVirtualMethod) $(GLINK isVirtualMethod)
$(GBLINK isAbstractFunction) $(GLINK isAbstractFunction)
$(GBLINK isFinalFunction) $(GLINK isFinalFunction)
$(GBLINK isStaticFunction) $(GLINK isStaticFunction)
$(GBLINK isOverrideFunction) $(GLINK isOverrideFunction)
$(GBLINK isTemplate) $(GLINK isTemplate)
$(GBLINK isRef) $(GLINK isRef)
$(GBLINK isOut) $(GLINK isOut)
$(GBLINK isLazy) $(GLINK isLazy)
$(GBLINK hasMember) $(GLINK isReturnOnStack)
$(GBLINK identifier) $(GLINK isZeroInit)
$(GBLINK getAliasThis) $(GLINK hasMember)
$(GBLINK getAttributes) $(GLINK identifier)
$(GBLINK getFunctionAttributes) $(GLINK getAliasThis)
$(GBLINK getFunctionVariadicStyle) $(GLINK getAttributes)
$(GBLINK getLinkage) $(GLINK getFunctionAttributes)
$(GBLINK getMember) $(GLINK getFunctionVariadicStyle)
$(GBLINK getOverloads) $(GLINK getLinkage)
$(GBLINK getParameterStorageClasses) $(GLINK getMember)
$(GBLINK getPointerBitmap) $(GLINK getOverloads)
$(GBLINK getProtection) $(GLINK getParameterStorageClasses)
$(GBLINK getVirtualFunctions) $(GLINK getPointerBitmap)
$(GBLINK getVirtualMethods) $(GLINK getProtection)
$(GBLINK getUnitTests) $(GLINK getVirtualFunctions)
$(GBLINK parent) $(GLINK getVirtualMethods)
$(GBLINK classInstanceSize) $(GLINK getUnitTests)
$(GBLINK getVirtualIndex) $(GLINK parent)
$(GBLINK allMembers) $(GLINK classInstanceSize)
$(GBLINK derivedMembers) $(GLINK getVirtualIndex)
$(GBLINK isSame) $(GLINK allMembers)
$(GBLINK compiles) $(GLINK derivedMembers)
$(GLINK isSame)
$(GLINK compiles)
$(GNAME TraitsArguments): $(GNAME TraitsArguments):
$(GLINK TraitsArgument) $(GLINK TraitsArgument)
@ -74,18 +76,6 @@ $(GNAME TraitsArgument):
$(GLINK2 declaration, Type) $(GLINK2 declaration, Type)
) )
$(P Additionally special keywords are provided for debugging purposes:)
$(GRAMMAR
$(GNAME SpecialKeyword):
$(D $(RELATIVE_LINK2 specialkeywords, __FILE__))
$(D $(RELATIVE_LINK2 specialkeywords, __FILE_FULL_PATH__))
$(D $(RELATIVE_LINK2 specialkeywords, __MODULE__))
$(D $(RELATIVE_LINK2 specialkeywords, __LINE__))
$(D $(RELATIVE_LINK2 specialkeywords, __FUNCTION__))
$(D $(RELATIVE_LINK2 specialkeywords, __PRETTY_FUNCTION__))
)
$(H2 $(GNAME isArithmetic)) $(H2 $(GNAME isArithmetic))
$(P If the arguments are all either types that are arithmetic types, $(P If the arguments are all either types that are arithmetic types,
@ -411,6 +401,68 @@ static assert(!__traits(isTemplate,foo!int()));
static assert(!__traits(isTemplate,"string")); static assert(!__traits(isTemplate,"string"));
--- ---
$(H2 $(GNAME isZeroInit))
$(P Takes one argument which must be a type. If the type's
$(DDSUBLINK spec/property, init, default initializer) is all zero
bits then `true` is returned, otherwise `false`.)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
---
struct S1 { int x; }
struct S2 { int x = -1; }
static assert(__traits(isZeroInit, S1));
static assert(!__traits(isZeroInit, S2));
void test()
{
int x = 3;
static assert(__traits(isZeroInit, typeof(x)));
}
// `isZeroInit` will always return true for a class C
// because `C.init` is null reference.
class C { int x = -1; }
static assert(__traits(isZeroInit, C));
---
)
$(H2 $(GNAME isReturnOnStack))
$(P
Takes one argument which must either be a function symbol, function literal,
a delegate, or a function pointer.
It returns a `bool` which is `true` if the return value of the function is
returned on the stack via a pointer to it passed as a hidden extra
parameter to the function.
)
---
struct S { int[20] a; }
int test1();
S test2();
static assert(__traits(isReturnOnStack, test1) == false);
static assert(__traits(isReturnOnStack, test2) == true);
---
$(IMPLEMENTATION_DEFINED
This is determined by the function ABI calling convention in use,
which is often complex.
)
$(BEST_PRACTICE This has applications in:
$(OL
$(LI Returning values in registers is often faster, so this can be used as
a check on a hot function to ensure it is using the fastest method.)
$(LI When using inline assembly to correctly call a function.)
$(LI Testing that the compiler does this correctly is normally hackish and awkward,
this enables efficient, direct, and simple testing.)
))
$(H2 $(GNAME hasMember)) $(H2 $(GNAME hasMember))
$(P The first argument is a type that has members, or $(P The first argument is a type that has members, or
@ -426,6 +478,8 @@ import std.stdio;
struct S struct S
{ {
int m; int m;
import std.stdio; // imports write
} }
void main() void main()
@ -435,6 +489,7 @@ void main()
writeln(__traits(hasMember, S, "m")); // true writeln(__traits(hasMember, S, "m")); // true
writeln(__traits(hasMember, s, "m")); // true writeln(__traits(hasMember, s, "m")); // true
writeln(__traits(hasMember, S, "y")); // false writeln(__traits(hasMember, S, "y")); // false
writeln(__traits(hasMember, S, "write")); // true
writeln(__traits(hasMember, int, "sizeof")); // true writeln(__traits(hasMember, int, "sizeof")); // true
} }
--- ---
@ -578,8 +633,8 @@ pragma(msg, __traits(getFunctionAttributes, (int x) @trusted { return x * 2; }))
$(H2 $(GNAME getLinkage)) $(H2 $(GNAME getLinkage))
$(P Takes one argument, which is a declaration symbol, or the type of a function, $(P Takes one argument, which is a declaration symbol, or the type of a function, delegate,
delegate, or pointer to function. pointer to function, struct, class, or interface.
Returns a string representing the $(LINK2 attribute.html#LinkageAttribute, LinkageAttribute) Returns a string representing the $(LINK2 attribute.html#LinkageAttribute, LinkageAttribute)
of the declaration. of the declaration.
The string is one of: The string is one of:
@ -601,6 +656,14 @@ alias aliasc = fooc;
static assert(__traits(getLinkage, fooc) == "C"); static assert(__traits(getLinkage, fooc) == "C");
static assert(__traits(getLinkage, aliasc) == "C"); static assert(__traits(getLinkage, aliasc) == "C");
extern (C++) struct FooCPPStruct {}
extern (C++) class FooCPPClass {}
extern (C++) interface FooCPPInterface {}
static assert(__traits(getLinkage, FooCPPStruct) == "C++");
static assert(__traits(getLinkage, FooCPPClass) == "C++");
static assert(__traits(getLinkage, FooCPPInterface) == "C++");
--- ---
$(H2 $(GNAME getMember)) $(H2 $(GNAME getMember))
@ -635,9 +698,11 @@ void main()
$(H2 $(GNAME getOverloads)) $(H2 $(GNAME getOverloads))
$(P The first argument is an aggregate (e.g. struct/class/module). $(P The first argument is an aggregate (e.g. struct/class/module).
The second argument is a string that matches the name of The second argument is a `string` that matches the name of
one of the functions in that aggregate. the member(s) to return.
The result is a tuple of all the overloads of that function. The third argument is a `bool`, and is optional. If `true`, the
result will also include template overloads.
The result is a tuple of all the overloads of the supplied name.
) )
--- ---
@ -649,6 +714,8 @@ class D
~this() { } ~this() { }
void foo() { } void foo() { }
int foo(int) { return 2; } int foo(int) { return 2; }
void bar(T)() { return T.init; }
class bar(int n) {}
} }
void main() void main()
@ -664,6 +731,9 @@ void main()
auto i = __traits(getOverloads, d, "foo")[1](1); auto i = __traits(getOverloads, d, "foo")[1](1);
writeln(i); writeln(i);
foreach (t; __traits(getOverloads, D, "bar", true))
writeln(t.stringof);
} }
--- ---
@ -675,6 +745,8 @@ int()
void() void()
int() int()
2 2
bar(T)()
bar(int n)
) )
$(H2 $(GNAME getParameterStorageClasses)) $(H2 $(GNAME getParameterStorageClasses))
@ -705,7 +777,7 @@ $(H2 $(GNAME getPointerBitmap))
The result is an array of $(D size_t) describing the memory used by an instance of the given type. The result is an array of $(D size_t) describing the memory used by an instance of the given type.
) )
$(P The first element of the array is the size of the type (for classes it is $(P The first element of the array is the size of the type (for classes it is
the $(GBLINK classInstanceSize)).) the $(GLINK classInstanceSize)).)
$(P The following elements describe the locations of GC managed pointers within the $(P The following elements describe the locations of GC managed pointers within the
memory occupied by an instance of the type. memory occupied by an instance of the type.
For type T, there are $(D T.sizeof / size_t.sizeof) possible pointers represented For type T, there are $(D T.sizeof / size_t.sizeof) possible pointers represented
@ -1020,6 +1092,76 @@ void main()
$(P If the two arguments are expressions made up of literals $(P If the two arguments are expressions made up of literals
or enums that evaluate to the same value, true is returned.) or enums that evaluate to the same value, true is returned.)
$(P If the two arguments are both lambda functions (or aliases
to lambda functions), then they are compared for equality. For
the comparison to be computed correctly, the following conditions
must be met for both lambda functions:)
$(OL
$(LI The lambda function arguments must not have a template
instantiation as an explicit argument type. Any other argument
types (basic, user-defined, template) are supported.)
$(LI The lambda function body must contain a single expression
(no return statement) which contains only numeric values,
manifest constants, enum values, function arguments and function
calls. If the expression contains local variables or return
statements, the function is considered incomparable.)
)
$(P If these constraints aren't fulfilled, the function is considered
incomparable and `isSame` returns $(D false).)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
---
int f() { return 2; }
void test(alias pred)()
{
// f() from main is a different function from top-level f()
static assert(!__traits(isSame, (int a) => a + f(), pred));
}
void main()
{
static assert(__traits(isSame, (a, b) => a + b, (c, d) => c + d));
static assert(__traits(isSame, a => ++a, b => ++b));
static assert(!__traits(isSame, (int a, int b) => a + b, (a, b) => a + b));
static assert(__traits(isSame, (a, b) => a + b + 10, (c, d) => c + d + 10));
// lambdas accessing local variables are considered incomparable
int b;
static assert(!__traits(isSame, a => a + b, a => a + b));
// lambdas calling other functions are comparable
int f() { return 3;}
static assert(__traits(isSame, a => a + f(), a => a + f()));
test!((int a) => a + f())();
class A
{
int a;
this(int a)
{
this.a = a;
}
}
class B
{
int a;
this(int a)
{
this.a = a;
}
}
static assert(__traits(isSame, (A a) => ++a.a, (A b) => ++b.a));
// lambdas with different data types are considered incomparable,
// even if the memory layout is the same
static assert(!__traits(isSame, (A a) => ++a.a, (B a) => ++a.a));
}
---
)
$(H2 $(GNAME compiles)) $(H2 $(GNAME compiles))
$(P Returns a bool $(D true) if all of the arguments $(P Returns a bool $(D true) if all of the arguments
@ -1068,55 +1210,6 @@ void main()
) )
$(H2 $(LNAME2 specialkeywords, Special Keywords))
$(P $(CODE __FILE__) and $(CODE __LINE__) expand to the source
file name and line number at the point of instantiation. The path of
the source file is left up to the compiler. )
$(P $(CODE __FILE_FULL_PATH__) expands to the absolute source
file name at the point of instantiation.)
$(P $(CODE __MODULE__) expands to the module name at the point of
instantiation.)
$(P $(CODE __FUNCTION__) expands to the fully qualified name of the
function at the point of instantiation.)
$(P $(CODE __PRETTY_FUNCTION__) is similar to $(CODE __FUNCTION__),
but also expands the function return type, its parameter types,
and its attributes.)
$(P Example usage:)
-----
module test;
import std.stdio;
void test(string file = __FILE__, size_t line = __LINE__,
string mod = __MODULE__, string func = __FUNCTION__,
string pretty = __PRETTY_FUNCTION__,
string fileFullPath = __FILE_FULL_PATH__)
{
writefln("file: '%s', line: '%s', module: '%s',\nfunction: '%s', " ~
"pretty function: '%s',\nfile full path: '%s'",
file, line, mod, func, pretty, fileFullPath);
}
int main(string[] args)
{
test();
return 0;
}
-----
$(P Assuming the file was at /example/test.d, this will output:)
$(CONSOLE
file: 'test.d', line: '13', module: 'test',
function: 'test.main', pretty function: 'int test.main(string[] args)',
file full path: '/example/test.d'
)
$(SPEC_SUBNAV_PREV_NEXT version, Conditional Compilation, errors, Error Handling) $(SPEC_SUBNAV_PREV_NEXT version, Conditional Compilation, errors, Error Handling)
) )
@ -1124,4 +1217,3 @@ $(SPEC_SUBNAV_PREV_NEXT version, Conditional Compilation, errors, Error Handling
Macros: Macros:
CHAPTER=25 CHAPTER=25
TITLE=Traits TITLE=Traits
GBLINK=$(RELATIVE_LINK2 $0, $(D $0))

View File

@ -13,101 +13,6 @@ import dcd.common.constants : ConstantCompletion;
*/ */
immutable ConstantCompletion[] pragmas = [ immutable ConstantCompletion[] pragmas = [
// generated from pragma.dd // generated from pragma.dd
ConstantCompletion("inline", `$(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. If there are multiple pragma inlines in a function,
the lexically last one takes effect.)
$(P It takes three forms:)
$(OL
$(LI
---
pragma(inline)
---
Sets the behavior to match the default behavior set by the compiler switch
$(DDSUBLINK dmd, switch-inline, $(TT -inline)).
)
$(LI
---
pragma(inline, false)
---
Functions are never inlined.
)
$(LI
---
pragma(inline, true)
---
If a function cannot be inlined with the $(DDSUBLINK dmd, switch-inline, $(TT -inline))
switch, an error message is issued. This is expected to be improved in the future to causing
functions to always be inlined regardless of compiler switch settings. Whether a compiler can
inline a particular function or not is implementation defined.
)
)
---
pragma(inline):
int foo(int x) // foo() is never inlined
{
pragma(inline, true);
++x;
pragma(inline, false); // supercedes the others
return x + 3;
}
---`),
ConstantCompletion("lib", `Inserts a directive in the object file to link in the library
specified by the $(ASSIGNEXPRESSION).
The $(ASSIGNEXPRESSION)s must be a string literal:
-----------------
pragma(lib, "foo.lib");
-----------------`),
ConstantCompletion("mangle", `Overrides the default mangling for a symbol. It's only effective
when the symbol is a function declaration or a variable declaration.
For example this allows linking to a symbol which is a D keyword, which would normally
be disallowed as a symbol name:
-----------------
pragma(mangle, "body")
extern(C) void body_func();
-----------------`),
ConstantCompletion("msg", `Constructs a message from the arguments and prints to the standard error stream while compiling:
-----------------
pragma(msg, "compiling...", 1, 1.0);
-----------------`),
ConstantCompletion("startaddress", `Puts a directive into the object file saying that the
function specified in the first argument will be the
start address for the program:
-----------------
void foo() { ... }
pragma(startaddress, foo);
-----------------
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.
)
)
$(H2 $(LNAME2 vendor_specific_pragmas, Vendor Specific Pragmas))
$(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:
)
-----------------
pragma(DigitalMars_funky_extension) { ... }
-----------------
$(P Compilers must diagnose an error for unrecognized $(I Pragma)s,
even if they are vendor specific ones. This implies that vendor
specific pragmas should be wrapped in version statements:
)
-----------------
version (DigitalMars)
{
pragma(DigitalMars_funky_extension)
{ ... }
}
-----------------`),
]; ];
/** /**
@ -197,57 +102,6 @@ $(LI Giving better error messages inside generic code than
the sometimes hard to follow compiler ones.) the sometimes hard to follow compiler ones.)
$(LI Doing a finer grained specialization than template $(LI Doing a finer grained specialization than template
partial specialization allows for.) partial specialization allows for.)
)
$(H2 $(LNAME2 specialkeywords, Special Keywords))
$(P $(CODE __FILE__) and $(CODE __LINE__) expand to the source
file name and line number at the point of instantiation. The path of
the source file is left up to the compiler. )
$(P $(CODE __FILE_FULL_PATH__) expands to the absolute source
file name at the point of instantiation.)
$(P $(CODE __MODULE__) expands to the module name at the point of
instantiation.)
$(P $(CODE __FUNCTION__) expands to the fully qualified name of the
function at the point of instantiation.)
$(P $(CODE __PRETTY_FUNCTION__) is similar to $(CODE __FUNCTION__),
but also expands the function return type, its parameter types,
and its attributes.)
$(P Example usage:)
-----
module test;
import std.stdio;
void test(string file = __FILE__, size_t line = __LINE__,
string mod = __MODULE__, string func = __FUNCTION__,
string pretty = __PRETTY_FUNCTION__,
string fileFullPath = __FILE_FULL_PATH__)
{
writefln("file: '%s', line: '%s', module: '%s',\nfunction: '%s', " ~
"pretty function: '%s',\nfile full path: '%s'",
file, line, mod, func, pretty, fileFullPath);
}
int main(string[] args)
{
test();
return 0;
}
-----
$(P Assuming the file was at /example/test.d, this will output:)
$(CONSOLE
file: 'test.d', line: '13', module: 'test',
function: 'test.main', pretty function: 'int test.main(string[] args)',
file full path: '/example/test.d'
)`), )`),
ConstantCompletion("derivedMembers", `$(P Takes a single argument, which must evaluate to either ConstantCompletion("derivedMembers", `$(P Takes a single argument, which must evaluate to either
a type or an expression of type. a type or an expression of type.
@ -391,8 +245,8 @@ static assert(__traits(getFunctionVariadicStyle, (int[] a...) {}) == "typesafe")
static assert(__traits(getFunctionVariadicStyle, typeof(cstyle)) == "stdarg"); static assert(__traits(getFunctionVariadicStyle, typeof(cstyle)) == "stdarg");
--- ---
)`), )`),
ConstantCompletion("getLinkage", `$(P Takes one argument, which is a declaration symbol, or the type of a function, ConstantCompletion("getLinkage", `$(P Takes one argument, which is a declaration symbol, or the type of a function, delegate,
delegate, or pointer to function. pointer to function, struct, class, or interface.
Returns a string representing the $(LINK2 attribute.html#LinkageAttribute, LinkageAttribute) Returns a string representing the $(LINK2 attribute.html#LinkageAttribute, LinkageAttribute)
of the declaration. of the declaration.
The string is one of: The string is one of:
@ -414,6 +268,14 @@ alias aliasc = fooc;
static assert(__traits(getLinkage, fooc) == "C"); static assert(__traits(getLinkage, fooc) == "C");
static assert(__traits(getLinkage, aliasc) == "C"); static assert(__traits(getLinkage, aliasc) == "C");
extern (C++) struct FooCPPStruct {}
extern (C++) class FooCPPClass {}
extern (C++) interface FooCPPInterface {}
static assert(__traits(getLinkage, FooCPPStruct) == "C++");
static assert(__traits(getLinkage, FooCPPClass) == "C++");
static assert(__traits(getLinkage, FooCPPInterface) == "C++");
---`), ---`),
ConstantCompletion("getMember", `$(P Takes two arguments, the second must be a string. ConstantCompletion("getMember", `$(P Takes two arguments, the second must be a string.
The result is an expression formed from the first The result is an expression formed from the first
@ -442,9 +304,11 @@ void main()
} }
---`), ---`),
ConstantCompletion("getOverloads", `$(P The first argument is an aggregate (e.g. struct/class/module). ConstantCompletion("getOverloads", `$(P The first argument is an aggregate (e.g. struct/class/module).
The second argument is a string that matches the name of The second argument is a ` ~ "`" ~ `string` ~ "`" ~ ` that matches the name of
one of the functions in that aggregate. the member(s) to return.
The result is a tuple of all the overloads of that function. The third argument is a ` ~ "`" ~ `bool` ~ "`" ~ `, and is optional. If ` ~ "`" ~ `true` ~ "`" ~ `, the
result will also include template overloads.
The result is a tuple of all the overloads of the supplied name.
) )
--- ---
@ -456,6 +320,8 @@ class D
~this() { } ~this() { }
void foo() { } void foo() { }
int foo(int) { return 2; } int foo(int) { return 2; }
void bar(T)() { return T.init; }
class bar(int n) {}
} }
void main() void main()
@ -471,6 +337,9 @@ void main()
auto i = __traits(getOverloads, d, "foo")[1](1); auto i = __traits(getOverloads, d, "foo")[1](1);
writeln(i); writeln(i);
foreach (t; __traits(getOverloads, D, "bar", true))
writeln(t.stringof);
} }
--- ---
@ -482,6 +351,8 @@ int()
void() void()
int() int()
2 2
bar(T)()
bar(int n)
)`), )`),
ConstantCompletion("getParameterStorageClasses", `$(P ConstantCompletion("getParameterStorageClasses", `$(P
Takes two arguments. Takes two arguments.
@ -506,7 +377,7 @@ static assert(__traits(getParameterStorageClasses, typeof(&foo), 3)[0] == "lazy"
The result is an array of $(D size_t) describing the memory used by an instance of the given type. The result is an array of $(D size_t) describing the memory used by an instance of the given type.
) )
$(P The first element of the array is the size of the type (for classes it is $(P The first element of the array is the size of the type (for classes it is
the $(GBLINK classInstanceSize)).) the $(GLINK classInstanceSize)).)
$(P The following elements describe the locations of GC managed pointers within the $(P The following elements describe the locations of GC managed pointers within the
memory occupied by an instance of the type. memory occupied by an instance of the type.
For type T, there are $(D T.sizeof / size_t.sizeof) possible pointers represented For type T, there are $(D T.sizeof / size_t.sizeof) possible pointers represented
@ -706,6 +577,8 @@ import std.stdio;
struct S struct S
{ {
int m; int m;
import std.stdio; // imports write
} }
void main() void main()
@ -715,6 +588,7 @@ void main()
writeln(__traits(hasMember, S, "m")); // true writeln(__traits(hasMember, S, "m")); // true
writeln(__traits(hasMember, s, "m")); // true writeln(__traits(hasMember, s, "m")); // true
writeln(__traits(hasMember, S, "y")); // false writeln(__traits(hasMember, S, "y")); // false
writeln(__traits(hasMember, S, "write")); // true
writeln(__traits(hasMember, int, "sizeof")); // true writeln(__traits(hasMember, int, "sizeof")); // true
} }
---`), ---`),
@ -995,6 +869,36 @@ void foolazy(lazy int x)
static assert(__traits(isLazy, x)); static assert(__traits(isLazy, x));
} }
---`), ---`),
ConstantCompletion("isReturnOnStack", `$(P
Takes one argument which must either be a function symbol, function literal,
a delegate, or a function pointer.
It returns a ` ~ "`" ~ `bool` ~ "`" ~ ` which is ` ~ "`" ~ `true` ~ "`" ~ ` if the return value of the function is
returned on the stack via a pointer to it passed as a hidden extra
parameter to the function.
)
---
struct S { int[20] a; }
int test1();
S test2();
static assert(__traits(isReturnOnStack, test1) == false);
static assert(__traits(isReturnOnStack, test2) == true);
---
$(IMPLEMENTATION_DEFINED
This is determined by the function ABI calling convention in use,
which is often complex.
)
$(BEST_PRACTICE This has applications in:
$(OL
$(LI Returning values in registers is often faster, so this can be used as
a check on a hot function to ensure it is using the fastest method.)
$(LI When using inline assembly to correctly call a function.)
$(LI Testing that the compiler does this correctly is normally hackish and awkward,
this enables efficient, direct, and simple testing.)
))`),
ConstantCompletion("isSame", `$(P Takes two arguments and returns bool $(D true) if they ConstantCompletion("isSame", `$(P Takes two arguments and returns bool $(D true) if they
are the same symbol, $(D false) if not.) are the same symbol, $(D false) if not.)
@ -1018,7 +922,77 @@ void main()
--- ---
$(P If the two arguments are expressions made up of literals $(P If the two arguments are expressions made up of literals
or enums that evaluate to the same value, true is returned.)`), or enums that evaluate to the same value, true is returned.)
$(P If the two arguments are both lambda functions (or aliases
to lambda functions), then they are compared for equality. For
the comparison to be computed correctly, the following conditions
must be met for both lambda functions:)
$(OL
$(LI The lambda function arguments must not have a template
instantiation as an explicit argument type. Any other argument
types (basic, user-defined, template) are supported.)
$(LI The lambda function body must contain a single expression
(no return statement) which contains only numeric values,
manifest constants, enum values, function arguments and function
calls. If the expression contains local variables or return
statements, the function is considered incomparable.)
)
$(P If these constraints aren't fulfilled, the function is considered
incomparable and ` ~ "`" ~ `isSame` ~ "`" ~ ` returns $(D false).)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
---
int f() { return 2; }
void test(alias pred)()
{
// f() from main is a different function from top-level f()
static assert(!__traits(isSame, (int a) => a + f(), pred));
}
void main()
{
static assert(__traits(isSame, (a, b) => a + b, (c, d) => c + d));
static assert(__traits(isSame, a => ++a, b => ++b));
static assert(!__traits(isSame, (int a, int b) => a + b, (a, b) => a + b));
static assert(__traits(isSame, (a, b) => a + b + 10, (c, d) => c + d + 10));
// lambdas accessing local variables are considered incomparable
int b;
static assert(!__traits(isSame, a => a + b, a => a + b));
// lambdas calling other functions are comparable
int f() { return 3;}
static assert(__traits(isSame, a => a + f(), a => a + f()));
test!((int a) => a + f())();
class A
{
int a;
this(int a)
{
this.a = a;
}
}
class B
{
int a;
this(int a)
{
this.a = a;
}
}
static assert(__traits(isSame, (A a) => ++a.a, (A b) => ++b.a));
// lambdas with different data types are considered incomparable,
// even if the memory layout is the same
static assert(!__traits(isSame, (A a) => ++a.a, (B a) => ++a.a));
}
---
)`),
ConstantCompletion("isScalar", `$(P Works like $(D isArithmetic), except it's for scalar ConstantCompletion("isScalar", `$(P Works like $(D isArithmetic), except it's for scalar
types.)`), types.)`),
ConstantCompletion("isStaticArray", `$(P Works like $(D isArithmetic), except it's for static array ConstantCompletion("isStaticArray", `$(P Works like $(D isArithmetic), except it's for static array
@ -1066,6 +1040,32 @@ void main()
writeln(__traits(isVirtualMethod, S.bar)); // false writeln(__traits(isVirtualMethod, S.bar)); // false
} }
---`), ---`),
ConstantCompletion("isZeroInit", `$(P Takes one argument which must be a type. If the type's
$(DDSUBLINK spec/property, init, default initializer) is all zero
bits then ` ~ "`" ~ `true` ~ "`" ~ ` is returned, otherwise ` ~ "`" ~ `false` ~ "`" ~ `.)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
---
struct S1 { int x; }
struct S2 { int x = -1; }
static assert(__traits(isZeroInit, S1));
static assert(!__traits(isZeroInit, S2));
void test()
{
int x = 3;
static assert(__traits(isZeroInit, typeof(x)));
}
// ` ~ "`" ~ `isZeroInit` ~ "`" ~ ` will always return true for a class C
// because ` ~ "`" ~ `C.init` ~ "`" ~ ` is null reference.
class C { int x = -1; }
static assert(__traits(isZeroInit, C));
---
)`),
ConstantCompletion("parent", `$(P Takes a single argument which must evaluate to a symbol. ConstantCompletion("parent", `$(P Takes a single argument which must evaluate to a symbol.
The result is the symbol that is the parent of it. The result is the symbol that is the parent of it.
)`), )`),

View File

@ -36,6 +36,7 @@ isOut k
isOverrideFunction k isOverrideFunction k
isPOD k isPOD k
isRef k isRef k
isReturnOnStack k
isSame k isSame k
isScalar k isScalar k
isStaticArray k isStaticArray k
@ -44,4 +45,5 @@ isTemplate k
isUnsigned k isUnsigned k
isVirtualFunction k isVirtualFunction k
isVirtualMethod k isVirtualMethod k
isZeroInit k
parent k parent k