blob: 69b20f0bd3c02747d08c51f222c03ab3ba16494b [file] [log] [blame]
/**
* This module contains UDA's (User Defined Attributes) either used in
* the runtime or special UDA's recognized by compiler.
*
* Copyright: Copyright Jacob Carlborg 2015.
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Authors: Jacob Carlborg
* Source: $(DRUNTIMESRC core/_attribute.d)
*/
/* Copyright Jacob Carlborg 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
module core.attribute;
version (GNU)
public import gcc.attributes;
version (LDC)
public import ldc.attributes;
version (D_ObjectiveC)
{
version = UdaOptional;
version = UdaSelector;
}
version (Posix)
version = UdaGNUAbiTag;
version (CoreDdoc)
{
version = UdaGNUAbiTag;
version = UdaOptional;
version = UdaSelector;
}
/**
* Use this attribute to specify that a global symbol should be emitted with
* weak linkage. This is primarily useful in defining library functions that
* can be overridden by user code, though it can also be used with shared and
* static variables too.
*
* The overriding symbol must have the same type as the weak symbol. In
* addition, if it designates a variable it must also have the same size and
* alignment as the weak symbol.
*
* Quote from the LLVM manual: "Note that weak linkage does not actually allow
* the optimizer to inline the body of this function into callers because it
* doesn’t know if this definition of the function is the definitive definition
* within the program or whether it will be overridden by a stronger
* definition."
*
* This attribute is only meaningful to the GNU and LLVM D compilers. The
* Digital Mars D compiler emits all symbols with weak linkage by default.
*/
version (DigitalMars)
{
enum weak;
}
else
{
// GDC and LDC declare this attribute in their own modules.
}
/**
* Use this attribute to attach an Objective-C selector to a method.
*
* This is a special compiler recognized attribute, it has several
* requirements, which all will be enforced by the compiler:
*
* $(UL
* $(LI
* The attribute can only be attached to methods or constructors which
* have Objective-C linkage. That is, a method or a constructor in a
* class or interface declared as $(D_CODE extern(Objective-C)).
* ),
*
* $(LI It cannot be attached to a method or constructor that is a template),
*
* $(LI
* The number of colons in the string need to match the number of
* arguments the method accept.
* ),
*
* $(LI It can only be used once in a method declaration)
* )
*
* Examples:
* ---
* extern (Objective-C)
* class NSObject
* {
* this() @selector("init");
* static NSObject alloc() @selector("alloc");
* NSObject initWithUTF8String(in char* str) @selector("initWithUTF8String:");
* ObjcObject copyScriptingValue(ObjcObject value, NSString key, NSDictionary properties)
* @selector("copyScriptingValue:forKey:withProperties:");
* }
* ---
*/
version (UdaSelector) struct selector
{
string selector;
}
/**
* Use this attribute to make an Objective-C interface method optional.
*
* An optional method is a method that does **not** have to be implemented in
* the class that implements the interface. To safely call an optional method,
* a runtime check should be performed to make sure the receiver implements the
* method.
*
* This is a special compiler recognized attribute, it has several
* requirements, which all will be enforced by the compiler:
*
* * The attribute can only be attached to methods which have Objective-C
* linkage. That is, a method inside an interface declared as `extern (Objective-C)`
*
* * It can only be used for methods that are declared inside an interface
* * It can only be used once in a method declaration
* * It cannot be attached to a method that is a template
*
* Examples:
* ---
* import core.attribute : optional, selector;
*
* extern (Objective-C):
*
* struct objc_selector;
* alias SEL = objc_selector*;
*
* SEL sel_registerName(in char* str);
*
* extern class NSObject
* {
* bool respondsToSelector(SEL sel) @selector("respondsToSelector:");
* }
*
* interface Foo
* {
* @optional void foo() @selector("foo");
* @optional void bar() @selector("bar");
* }
*
* class Bar : NSObject
* {
* static Bar alloc() @selector("alloc");
* Bar init() @selector("init");
*
* void bar() @selector("bar")
* {
* }
* }
*
* extern (D) void main()
* {
* auto bar = Bar.alloc.init;
*
* if (bar.respondsToSelector(sel_registerName("bar")))
* bar.bar();
* }
* ---
*/
version (UdaOptional)
enum optional;
/**
* Use this attribute to declare an ABI tag on a C++ symbol.
*
* ABI tag is an attribute introduced by the GNU C++ compiler.
* It modifies the mangled name of the symbol to incorporate the tag name,
* in order to distinguish from an earlier version with a different ABI.
*
* This is a special compiler recognized attribute, it has a few
* requirements, which all will be enforced by the compiler:
*
* $(UL
* $(LI
* There can only be one such attribute per symbol.
* ),
* $(LI
* The attribute can only be attached to an `extern(C++)` symbol
* (`struct`, `class`, `enum`, function, and their templated counterparts).
* ),
* $(LI
* The attribute cannot be applied to C++ namespaces.
* This is to prevent confusion with the C++ semantic, which allows it to
* be applied to namespaces.
* ),
* $(LI
* The string arguments must only contain valid characters
* for C++ name mangling which currently include alphanumerics
* and the underscore character.
* ),
* )
*
* This UDA is not transitive, and inner scope do not inherit outer scopes'
* ABI tag. See examples below for how to translate a C++ declaration to D.
* Also note that entries in this UDA will be automatically sorted
* alphabetically, hence `gnuAbiTag("c", "b", "a")` will appear as
* `@gnuAbiTag("a", "b", "c")`.
*
* See_Also:
* $(LINK2 https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.abi-tag, Itanium ABI spec)
* $(LINK2 https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html, GCC attributes documentation).
*
* Examples:
* ---
* // ---- foo.cpp
* struct [[gnu::abi_tag ("tag1", "tag2")]] Tagged1_2
* {
* struct [[gnu::abi_tag ("tag3")]] Tagged3
* {
* [[gnu::abi_tag ("tag4")]]
* int Tagged4 () { return 42; }
* }
* }
* Tagged1_2 inst1;
* // ---- foo.d
* @gnuAbiTag("tag1", "tag2") struct Tagged1_2
* {
* // Notice the repetition
* @gnuAbiTag("tag1", "tag2", "tag3") struct Tagged3
* {
* @gnuAbiTag("tag1", "tag2", "tag3", "tag4") int Tagged4 ();
* }
* }
* extern __gshared Tagged1_2 inst1;
* ---
*/
version (UdaGNUAbiTag) struct gnuAbiTag
{
string[] tags;
this(string[] tags...)
{
this.tags = tags;
}
}
/**
* Use this attribute to ensure that values of a `struct` or `union` type are
* not discarded.
*
* The value of an expression is considered to be discarded if
*
* $(UL
* $(LI
* the expression is the top-level expression in a statement or the
* left-hand expression in a comma expression, and
* ),
* $(LI
* the expression is not an assignment (`=`, `+=`, etc.), increment
* (`++`), or decrement (`--`) expression.
* ),
* )
*
* If the declaration of a `struct` or `union` type has the `@mustuse`
* attribute, the compiler will emit an error any time a value of that type
* would be discarded.
*
* Currently, `@mustuse` is only recognized by the compiler when attached to
* `struct` and `union` declarations. To allow for future expansion, attaching
* `@mustuse` to a `class`, `interface`, `enum`, or function declaration is
* currently forbidden, and will result in a compile-time error. All other uses
* of `@mustuse` are ignored.
*
* Examples:
* ---
* @mustuse struct ErrorCode { int value; }
*
* extern(C) ErrorCode doSomething();
*
* void main()
* {
* // error: would discard a value of type ErrorCode
* //doSomething();
*
* ErrorCode result;
* // ok: value is assigned to a variable
* result = doSomething();
*
* // ok: can ignore the value explicitly with a cast
* cast(void) doSomething();
* }
* ---
*/
enum mustuse;