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).
$(I ExpressionList) is a comma-separated list of
$(GLINK2 expression, ArgumentList) is a comma-separated list of
$(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.
)
@ -62,18 +62,19 @@ $(P All implementations must support these, even if by just ignoring them:)
$(UL
$(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 #startaddress, pragma startaddress))
)
$(DL
$(IMPLEMENTATION_DEFINED An implementation may ignore these pragmas.)
$(DT $(LNAME2 inline, $(D inline)))
$(DD $(P Affects whether functions are inlined or not. If at the declaration level, it
$(H3 $(LNAME2 inline, $(D pragma 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.)
affects the function it is enclosed by.)
$(P It takes three forms:)
$(OL
@ -81,8 +82,7 @@ $(UL
---
pragma(inline)
---
Sets the behavior to match the default behavior set by the compiler switch
$(DDSUBLINK dmd, switch-inline, $(TT -inline)).
Sets the behavior to match the implementation's default behavior.
)
$(LI
---
@ -94,12 +94,16 @@ pragma(inline, false)
---
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.
Always inline the functions.
)
)
$(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):
int foo(int x) // foo() is never inlined
@ -110,52 +114,96 @@ int foo(int x) // foo() is never inlined
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");
-----------------
$(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)))
$(DD Overrides the default mangling for a symbol. It's only effective
$(P There must be one $(ASSIGNEXPRESSION) and it must evaluate at compile time to a string literal.
)
-----------------
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.
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();
-----------------
)
$(DT $(LNAME2 msg, $(D msg)))
$(DD Constructs a message from the arguments and prints to the standard error stream while compiling:
$(H3 $(LNAME2 msg, $(D pragma msg)))
$(P Constructs a message from the $(I ArgumentList).)
-----------------
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)))
$(DD Puts a directive into the object file saying that the
function specified in the first argument will be the
start address for the program:
$(H3 $(LNAME2 startaddress, $(D pragma startaddress)))
$(P There must be one $(ASSIGNEXPRESSION) and it must evaluate at compile time to a function symbol.)
$(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() { ... }
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))
@ -165,22 +213,28 @@ $(H2 $(LNAME2 vendor_specific_pragmas, Vendor Specific Pragmas))
to version identifiers:
)
-----------------
pragma(DigitalMars_funky_extension) { ... }
-----------------
---
pragma(DigitalMars_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:
)
$(P Implementations must diagnose an error for unrecognized $(I Pragma)s,
even if they are vendor specific ones.
)
-----------------
version (DigitalMars)
{
pragma(DigitalMars_funky_extension)
{ ... }
}
-----------------
$(IMPLEMENTATION_DEFINED Vendor specific pragmas.)
$(BEST_PRACTICE vendor
specific pragmas should be wrapped in version statements
---
version (DigitalMars)
{
pragma(DigitalMars_extension)
{ ... }
}
---
)
$(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))
$(GNAME TraitsKeyword):
$(GBLINK isAbstractClass)
$(GBLINK isArithmetic)
$(GBLINK isAssociativeArray)
$(GBLINK isFinalClass)
$(GBLINK isPOD)
$(GBLINK isNested)
$(GBLINK isFuture)
$(GBLINK isDeprecated)
$(GBLINK isFloating)
$(GBLINK isIntegral)
$(GBLINK isScalar)
$(GBLINK isStaticArray)
$(GBLINK isUnsigned)
$(GBLINK isDisabled)
$(GBLINK isVirtualFunction)
$(GBLINK isVirtualMethod)
$(GBLINK isAbstractFunction)
$(GBLINK isFinalFunction)
$(GBLINK isStaticFunction)
$(GBLINK isOverrideFunction)
$(GBLINK isTemplate)
$(GBLINK isRef)
$(GBLINK isOut)
$(GBLINK isLazy)
$(GBLINK hasMember)
$(GBLINK identifier)
$(GBLINK getAliasThis)
$(GBLINK getAttributes)
$(GBLINK getFunctionAttributes)
$(GBLINK getFunctionVariadicStyle)
$(GBLINK getLinkage)
$(GBLINK getMember)
$(GBLINK getOverloads)
$(GBLINK getParameterStorageClasses)
$(GBLINK getPointerBitmap)
$(GBLINK getProtection)
$(GBLINK getVirtualFunctions)
$(GBLINK getVirtualMethods)
$(GBLINK getUnitTests)
$(GBLINK parent)
$(GBLINK classInstanceSize)
$(GBLINK getVirtualIndex)
$(GBLINK allMembers)
$(GBLINK derivedMembers)
$(GBLINK isSame)
$(GBLINK compiles)
$(GLINK isAbstractClass)
$(GLINK isArithmetic)
$(GLINK isAssociativeArray)
$(GLINK isFinalClass)
$(GLINK isPOD)
$(GLINK isNested)
$(GLINK isFuture)
$(GLINK isDeprecated)
$(GLINK isFloating)
$(GLINK isIntegral)
$(GLINK isScalar)
$(GLINK isStaticArray)
$(GLINK isUnsigned)
$(GLINK isDisabled)
$(GLINK isVirtualFunction)
$(GLINK isVirtualMethod)
$(GLINK isAbstractFunction)
$(GLINK isFinalFunction)
$(GLINK isStaticFunction)
$(GLINK isOverrideFunction)
$(GLINK isTemplate)
$(GLINK isRef)
$(GLINK isOut)
$(GLINK isLazy)
$(GLINK isReturnOnStack)
$(GLINK isZeroInit)
$(GLINK hasMember)
$(GLINK identifier)
$(GLINK getAliasThis)
$(GLINK getAttributes)
$(GLINK getFunctionAttributes)
$(GLINK getFunctionVariadicStyle)
$(GLINK getLinkage)
$(GLINK getMember)
$(GLINK getOverloads)
$(GLINK getParameterStorageClasses)
$(GLINK getPointerBitmap)
$(GLINK getProtection)
$(GLINK getVirtualFunctions)
$(GLINK getVirtualMethods)
$(GLINK getUnitTests)
$(GLINK parent)
$(GLINK classInstanceSize)
$(GLINK getVirtualIndex)
$(GLINK allMembers)
$(GLINK derivedMembers)
$(GLINK isSame)
$(GLINK compiles)
$(GNAME TraitsArguments):
$(GLINK TraitsArgument)
@ -74,18 +76,6 @@ $(GNAME TraitsArgument):
$(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))
$(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"));
---
$(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))
$(P The first argument is a type that has members, or
@ -426,6 +478,8 @@ import std.stdio;
struct S
{
int m;
import std.stdio; // imports write
}
void main()
@ -435,6 +489,7 @@ void main()
writeln(__traits(hasMember, S, "m")); // true
writeln(__traits(hasMember, s, "m")); // true
writeln(__traits(hasMember, S, "y")); // false
writeln(__traits(hasMember, S, "write")); // true
writeln(__traits(hasMember, int, "sizeof")); // true
}
---
@ -578,8 +633,8 @@ pragma(msg, __traits(getFunctionAttributes, (int x) @trusted { return x * 2; }))
$(H2 $(GNAME getLinkage))
$(P Takes one argument, which is a declaration symbol, or the type of a function,
delegate, or pointer to function.
$(P Takes one argument, which is a declaration symbol, or the type of a function, delegate,
pointer to function, struct, class, or interface.
Returns a string representing the $(LINK2 attribute.html#LinkageAttribute, LinkageAttribute)
of the declaration.
The string is one of:
@ -601,6 +656,14 @@ alias aliasc = fooc;
static assert(__traits(getLinkage, fooc) == "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))
@ -635,9 +698,11 @@ void main()
$(H2 $(GNAME getOverloads))
$(P The first argument is an aggregate (e.g. struct/class/module).
The second argument is a string that matches the name of
one of the functions in that aggregate.
The result is a tuple of all the overloads of that function.
The second argument is a `string` that matches the name of
the member(s) to return.
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() { }
void foo() { }
int foo(int) { return 2; }
void bar(T)() { return T.init; }
class bar(int n) {}
}
void main()
@ -664,6 +731,9 @@ void main()
auto i = __traits(getOverloads, d, "foo")[1](1);
writeln(i);
foreach (t; __traits(getOverloads, D, "bar", true))
writeln(t.stringof);
}
---
@ -675,6 +745,8 @@ int()
void()
int()
2
bar(T)()
bar(int n)
)
$(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.
)
$(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
memory occupied by an instance of the type.
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
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))
$(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)
)
@ -1124,4 +1217,3 @@ $(SPEC_SUBNAV_PREV_NEXT version, Conditional Compilation, errors, Error Handling
Macros:
CHAPTER=25
TITLE=Traits
GBLINK=$(RELATIVE_LINK2 $0, $(D $0))

View File

@ -13,101 +13,6 @@ import dcd.common.constants : ConstantCompletion;
*/
immutable ConstantCompletion[] pragmas = [
// 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.)
$(LI Doing a finer grained specialization than template
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
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");
---
)`),
ConstantCompletion("getLinkage", `$(P Takes one argument, which is a declaration symbol, or the type of a function,
delegate, or pointer to function.
ConstantCompletion("getLinkage", `$(P Takes one argument, which is a declaration symbol, or the type of a function, delegate,
pointer to function, struct, class, or interface.
Returns a string representing the $(LINK2 attribute.html#LinkageAttribute, LinkageAttribute)
of the declaration.
The string is one of:
@ -414,6 +268,14 @@ alias aliasc = fooc;
static assert(__traits(getLinkage, fooc) == "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.
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).
The second argument is a string that matches the name of
one of the functions in that aggregate.
The result is a tuple of all the overloads of that function.
The second argument is a ` ~ "`" ~ `string` ~ "`" ~ ` that matches the name of
the member(s) to return.
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() { }
void foo() { }
int foo(int) { return 2; }
void bar(T)() { return T.init; }
class bar(int n) {}
}
void main()
@ -471,6 +337,9 @@ void main()
auto i = __traits(getOverloads, d, "foo")[1](1);
writeln(i);
foreach (t; __traits(getOverloads, D, "bar", true))
writeln(t.stringof);
}
---
@ -482,6 +351,8 @@ int()
void()
int()
2
bar(T)()
bar(int n)
)`),
ConstantCompletion("getParameterStorageClasses", `$(P
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.
)
$(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
memory occupied by an instance of the type.
For type T, there are $(D T.sizeof / size_t.sizeof) possible pointers represented
@ -706,6 +577,8 @@ import std.stdio;
struct S
{
int m;
import std.stdio; // imports write
}
void main()
@ -715,6 +588,7 @@ void main()
writeln(__traits(hasMember, S, "m")); // true
writeln(__traits(hasMember, s, "m")); // true
writeln(__traits(hasMember, S, "y")); // false
writeln(__traits(hasMember, S, "write")); // true
writeln(__traits(hasMember, int, "sizeof")); // true
}
---`),
@ -995,6 +869,36 @@ void foolazy(lazy int 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
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
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
types.)`),
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
}
---`),
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.
The result is the symbol that is the parent of it.
)`),

View File

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