d: Merge upstream dmd a5c86f5b9
Adds the following new `__traits' to the D language. - isDeprecated: used to detect if a function is deprecated. - isDisabled: used to detect if a function is marked with @disable. - isFuture: used to detect if a function is marked with @__future. - isModule: used to detect if a given symbol represents a module, this enhancement also adds support using `is(sym == module)'. - isPackage: used to detect if a given symbol represents a package, this enhancement also adds support using `is(sym == package)'. - child: takes two arguments. The first must be a symbol or expression and the second must be a symbol, such as an alias to a member of the first 'parent' argument. The result is the second 'member' argument interpreted with its 'this' context set to 'parent'. This is the inverse of `__traits(parent, member)'. - isReturnOnStack: determines if a function's return value is placed on the stack, or is returned via registers. - isZeroInit: used to detect if a type's default initializer has no non-zero bits. - getTargetInfo: used to query features of the target being compiled for, the back-end can expand this to register any key to handle the given argument, however a reliable subset exists which includes "cppRuntimeLibrary", "cppStd", "floatAbi", and "objectFormat". - getLocation: returns a tuple whose entries correspond to the filename, line number, and column number of where the argument was declared. - hasPostblit: used to detect if a type is a struct with a postblit. - isCopyable: used to detect if a type allows copying its value. - getVisibility: an alias for the getProtection trait. Reviewed-on: https://github.com/dlang/dmd/pull/12093 gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd a5c86f5b9. * d-builtins.cc (d_eval_constant_expression): Handle ADDR_EXPR trees created by build_string_literal. * d-frontend.cc (retStyle): Remove function. * d-target.cc (d_language_target_info): New variable. (d_target_info_table): Likewise. (Target::_init): Initialize d_target_info_table. (Target::isReturnOnStack): New function. (d_add_target_info_handlers): Likewise. (d_handle_target_cpp_std): Likewise. (d_handle_target_cpp_runtime_library): Likewise. (Target::getTargetInfo): Likewise. * d-target.h (struct d_target_info_spec): New type. (d_add_target_info_handlers): Declare.
This commit is contained in:
parent
ae1ada95fe
commit
c5e94699ef
47 changed files with 1882 additions and 427 deletions
|
@ -393,6 +393,20 @@ d_eval_constant_expression (const Loc &loc, tree cst)
|
|||
|
||||
return VectorExp::create (loc, e, type);
|
||||
}
|
||||
else if (code == ADDR_EXPR)
|
||||
{
|
||||
/* Special handling for trees constructed by build_string_literal.
|
||||
What we receive is an `&"string"[0]' expression, strip off the
|
||||
outer ADDR_EXPR and ARRAY_REF to get to the underlying CST. */
|
||||
tree pointee = TREE_OPERAND (cst, 0);
|
||||
|
||||
if (TREE_CODE (pointee) != ARRAY_REF
|
||||
|| TREE_OPERAND (pointee, 1) != integer_zero_node
|
||||
|| TREE_CODE (TREE_OPERAND (pointee, 0)) != STRING_CST)
|
||||
return NULL;
|
||||
|
||||
return d_eval_constant_expression (loc, TREE_OPERAND (pointee, 0));
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
|
@ -139,26 +139,6 @@ Loc::equals (const Loc &loc)
|
|||
|
||||
/* Implements back-end specific interfaces used by the frontend. */
|
||||
|
||||
/* Determine return style of function - whether in registers or through a
|
||||
hidden pointer to the caller's stack. */
|
||||
|
||||
RET
|
||||
retStyle (TypeFunction *tf)
|
||||
{
|
||||
/* Need the backend type to determine this, but this is called from the
|
||||
frontend before semantic processing is finished. An accurate value
|
||||
is not currently needed anyway. */
|
||||
if (tf->isref)
|
||||
return RETregs;
|
||||
|
||||
Type *tn = tf->next->toBasetype ();
|
||||
|
||||
if (tn->ty == Tstruct || tn->ty == Tsarray)
|
||||
return RETstack;
|
||||
|
||||
return RETregs;
|
||||
}
|
||||
|
||||
/* Determine if function FD is a builtin one that we can evaluate in CTFE. */
|
||||
|
||||
BUILTIN
|
||||
|
|
|
@ -44,6 +44,25 @@ along with GCC; see the file COPYING3. If not see
|
|||
|
||||
Target target;
|
||||
|
||||
/* Internal key handlers for `__traits(getTargetInfo)'. */
|
||||
static tree d_handle_target_cpp_std (void);
|
||||
static tree d_handle_target_cpp_runtime_library (void);
|
||||
|
||||
/* In [traits/getTargetInfo], a reliable subset of getTargetInfo keys exists
|
||||
which are always available. */
|
||||
static const struct d_target_info_spec d_language_target_info[] =
|
||||
{
|
||||
/* { name, handler } */
|
||||
{ "cppStd", d_handle_target_cpp_std },
|
||||
{ "cppRuntimeLibrary", d_handle_target_cpp_runtime_library },
|
||||
{ "floatAbi", NULL },
|
||||
{ "objectFormat", NULL },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
/* Table `__traits(getTargetInfo)' keys. */
|
||||
static vec<d_target_info_spec> d_target_info_table;
|
||||
|
||||
|
||||
/* Initialize the floating-point constants for TYPE. */
|
||||
|
||||
|
@ -167,6 +186,10 @@ Target::_init (const Param &)
|
|||
real_convert (&CTFloat::one.rv (), mode, &dconst1);
|
||||
real_convert (&CTFloat::minusone.rv (), mode, &dconstm1);
|
||||
real_convert (&CTFloat::half.rv (), mode, &dconsthalf);
|
||||
|
||||
/* Initialize target info tables, the keys required by the language are added
|
||||
last, so that the OS and CPU handlers can override. */
|
||||
d_add_target_info_handlers (d_language_target_info);
|
||||
}
|
||||
|
||||
/* Return GCC memory alignment size for type TYPE. */
|
||||
|
@ -413,3 +436,84 @@ Target::toArgTypes (Type *)
|
|||
/* Not implemented, however this is not currently used anywhere. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Determine return style of function, whether in registers or through a
|
||||
hidden pointer to the caller's stack. */
|
||||
|
||||
bool
|
||||
Target::isReturnOnStack (TypeFunction *tf, bool)
|
||||
{
|
||||
/* Need the back-end type to determine this, but this is called from the
|
||||
frontend before semantic processing is finished. An accurate value
|
||||
is not currently needed anyway. */
|
||||
if (tf->isref)
|
||||
return false;
|
||||
|
||||
Type *tn = tf->next->toBasetype ();
|
||||
|
||||
return (tn->ty == Tstruct || tn->ty == Tsarray);
|
||||
}
|
||||
|
||||
/* Add all target info in HANDLERS to D_TARGET_INFO_TABLE for use by
|
||||
Target::getTargetInfo(). */
|
||||
|
||||
void
|
||||
d_add_target_info_handlers (const d_target_info_spec *handlers)
|
||||
{
|
||||
gcc_assert (handlers != NULL);
|
||||
|
||||
if (d_target_info_table.is_empty ())
|
||||
d_target_info_table.create (8);
|
||||
|
||||
for (size_t i = 0; handlers[i].name != NULL; i++)
|
||||
d_target_info_table.safe_push (handlers[i]);
|
||||
}
|
||||
|
||||
/* Handle a call to `__traits(getTargetInfo, "cppStd")'. */
|
||||
|
||||
tree
|
||||
d_handle_target_cpp_std (void)
|
||||
{
|
||||
return build_integer_cst (global.params.cplusplus);
|
||||
}
|
||||
|
||||
/* Handle a call to `__traits(getTargetInfo, "cppRuntimeLibrary")'. */
|
||||
|
||||
tree
|
||||
d_handle_target_cpp_runtime_library (void)
|
||||
{
|
||||
/* The driver only ever optionally links to libstdc++. */
|
||||
const char *libstdcxx = "libstdc++";
|
||||
return build_string_literal (strlen (libstdcxx) + 1, libstdcxx);
|
||||
}
|
||||
|
||||
/* Look up the target info KEY in the available getTargetInfo tables, and return
|
||||
the result as an Expression, or NULL if KEY is not found. When the key must
|
||||
always exist, but is not supported, an empty string expression is returned.
|
||||
LOC is the location to use for the returned expression. */
|
||||
|
||||
Expression *
|
||||
Target::getTargetInfo (const char *key, const Loc &loc)
|
||||
{
|
||||
unsigned ix;
|
||||
d_target_info_spec *spec;
|
||||
|
||||
FOR_EACH_VEC_ELT (d_target_info_table, ix, spec)
|
||||
{
|
||||
tree result;
|
||||
|
||||
if (strcmp (key, spec->name) != 0)
|
||||
continue;
|
||||
|
||||
/* Get the requested information, or empty string if unhandled. */
|
||||
if (spec->handler)
|
||||
result = (spec->handler) ();
|
||||
else
|
||||
result = build_string_literal (1, "");
|
||||
|
||||
gcc_assert (result);
|
||||
return d_eval_constant_expression (loc, result);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -31,4 +31,19 @@ extern struct gcc_targetdm targetdm;
|
|||
/* Used by target to add predefined version idenditiers. */
|
||||
extern void d_add_builtin_version (const char *);
|
||||
|
||||
/* Structure describing a supported key for `__traits(getTargetInfo)' and a
|
||||
function to handle it. */
|
||||
struct d_target_info_spec
|
||||
{
|
||||
/* The name of the key or NULL to mark the end of a table of keys. */
|
||||
const char *name;
|
||||
/* Function to handle this key, the return value of the handler must be a CST.
|
||||
This pointer may be NULL if no special handling is required, for instance,
|
||||
the key must always be available according to the D language spec. */
|
||||
tree (*handler) ();
|
||||
};
|
||||
|
||||
/* Used by target to add getTargetInfo handlers. */
|
||||
extern void d_add_target_info_handlers (const d_target_info_spec *);
|
||||
|
||||
#endif /* GCC_D_TARGET_H */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
2bd4fc3fed8b8cd9760e77c6b2a1905cd84d0e70
|
||||
a5c86f5b92c4cd3afde910c89881ccaea11de554
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the dlang/dmd repository.
|
||||
|
|
|
@ -149,6 +149,7 @@ public:
|
|||
bool isSynchronized() { return (storage_class & STCsynchronized) != 0; }
|
||||
bool isParameter() { return (storage_class & STCparameter) != 0; }
|
||||
bool isDeprecated() { return (storage_class & STCdeprecated) != 0; }
|
||||
bool isDisabled() { return (storage_class & STCdisable) != 0; }
|
||||
bool isOverride() { return (storage_class & STCoverride) != 0; }
|
||||
bool isResult() { return (storage_class & STCresult) != 0; }
|
||||
bool isField() { return (storage_class & STCfield) != 0; }
|
||||
|
@ -669,7 +670,7 @@ public:
|
|||
static FuncDeclaration *genCfunc(Parameters *args, Type *treturn, const char *name, StorageClass stc=0);
|
||||
static FuncDeclaration *genCfunc(Parameters *args, Type *treturn, Identifier *id, StorageClass stc=0);
|
||||
void checkDmain();
|
||||
bool checkNrvo();
|
||||
bool checkNRVO();
|
||||
|
||||
FuncDeclaration *isFuncDeclaration() { return this; }
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ Dsymbols Module::deferred2; // deferred Dsymbol's needing semantic2() run on the
|
|||
Dsymbols Module::deferred3; // deferred Dsymbol's needing semantic3() run on them
|
||||
unsigned Module::dprogress;
|
||||
|
||||
const char *lookForSourceFile(const char **path, const char *filename);
|
||||
StringExp *semanticString(Scope *sc, Expression *exp, const char *s);
|
||||
|
||||
void Module::_init()
|
||||
|
@ -72,7 +71,6 @@ Module::Module(const char *filename, Identifier *ident, int doDocComment, int do
|
|||
sfilename = NULL;
|
||||
importedFrom = NULL;
|
||||
srcfile = NULL;
|
||||
srcfilePath = NULL;
|
||||
docfile = NULL;
|
||||
|
||||
debuglevel = 0;
|
||||
|
@ -109,9 +107,6 @@ Module::Module(const char *filename, Identifier *ident, int doDocComment, int do
|
|||
fatal();
|
||||
}
|
||||
srcfile = new File(srcfilename);
|
||||
if (!FileName::absolute(srcfilename))
|
||||
srcfilePath = getcwd(NULL, 0);
|
||||
|
||||
objfile = setOutfile(global.params.objname.ptr, global.params.objdir.ptr, filename, global.obj_ext.ptr);
|
||||
|
||||
if (doDocComment)
|
||||
|
@ -215,6 +210,133 @@ static void checkModFileAlias(OutBuffer *buf, OutBuffer *dotmods,
|
|||
dotmods->writeByte('.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a chain of identifiers to the filename of the module
|
||||
*
|
||||
* Params:
|
||||
* packages = the names of the "parent" packages
|
||||
* ident = the name of the child package or module
|
||||
*
|
||||
* Returns:
|
||||
* the filename of the child package or module
|
||||
*/
|
||||
static const char *getFilename(Identifiers *packages, Identifier *ident)
|
||||
{
|
||||
const char *filename = ident->toChars();
|
||||
|
||||
if (packages == NULL || packages->length == 0)
|
||||
return filename;
|
||||
|
||||
OutBuffer buf;
|
||||
OutBuffer dotmods;
|
||||
Array<const char *> *ms = &global.params.modFileAliasStrings;
|
||||
const size_t msdim = ms ? ms->length : 0;
|
||||
|
||||
for (size_t i = 0; i < packages->length; i++)
|
||||
{
|
||||
Identifier *pid = (*packages)[i];
|
||||
const char *p = pid->toChars();
|
||||
buf.writestring(p);
|
||||
if (msdim)
|
||||
checkModFileAlias(&buf, &dotmods, ms, msdim, p);
|
||||
#if _WIN32
|
||||
buf.writeByte('\\');
|
||||
#else
|
||||
buf.writeByte('/');
|
||||
#endif
|
||||
}
|
||||
buf.writestring(filename);
|
||||
if (msdim)
|
||||
checkModFileAlias(&buf, &dotmods, ms, msdim, filename);
|
||||
buf.writeByte(0);
|
||||
filename = (char *)buf.extractData();
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* Look for the source file if it's different from filename.
|
||||
* Look for .di, .d, directory, and along global.path.
|
||||
* Does not open the file.
|
||||
* Input:
|
||||
* filename as supplied by the user
|
||||
* global.path
|
||||
* Returns:
|
||||
* NULL if it's not different from filename.
|
||||
*/
|
||||
|
||||
static const char *lookForSourceFile(const char *filename)
|
||||
{
|
||||
/* Search along global.path for .di file, then .d file.
|
||||
*/
|
||||
const char *sdi = FileName::forceExt(filename, global.hdr_ext.ptr);
|
||||
if (FileName::exists(sdi) == 1)
|
||||
return sdi;
|
||||
|
||||
const char *sd = FileName::forceExt(filename, global.mars_ext.ptr);
|
||||
if (FileName::exists(sd) == 1)
|
||||
return sd;
|
||||
|
||||
if (FileName::exists(filename) == 2)
|
||||
{
|
||||
/* The filename exists and it's a directory.
|
||||
* Therefore, the result should be: filename/package.d
|
||||
* iff filename/package.d is a file
|
||||
*/
|
||||
const char *ni = FileName::combine(filename, "package.di");
|
||||
if (FileName::exists(ni) == 1)
|
||||
return ni;
|
||||
FileName::free(ni);
|
||||
const char *n = FileName::combine(filename, "package.d");
|
||||
if (FileName::exists(n) == 1)
|
||||
return n;
|
||||
FileName::free(n);
|
||||
}
|
||||
|
||||
if (FileName::absolute(filename))
|
||||
return NULL;
|
||||
|
||||
if (!global.path)
|
||||
return NULL;
|
||||
|
||||
for (size_t i = 0; i < global.path->length; i++)
|
||||
{
|
||||
const char *p = (*global.path)[i];
|
||||
const char *n = FileName::combine(p, sdi);
|
||||
if (FileName::exists(n) == 1)
|
||||
{
|
||||
return n;
|
||||
}
|
||||
FileName::free(n);
|
||||
|
||||
n = FileName::combine(p, sd);
|
||||
if (FileName::exists(n) == 1)
|
||||
{
|
||||
return n;
|
||||
}
|
||||
FileName::free(n);
|
||||
|
||||
const char *b = FileName::removeExt(filename);
|
||||
n = FileName::combine(p, b);
|
||||
FileName::free(b);
|
||||
if (FileName::exists(n) == 2)
|
||||
{
|
||||
const char *n2i = FileName::combine(n, "package.di");
|
||||
if (FileName::exists(n2i) == 1)
|
||||
return n2i;
|
||||
FileName::free(n2i);
|
||||
const char *n2 = FileName::combine(n, "package.d");
|
||||
if (FileName::exists(n2) == 1)
|
||||
{
|
||||
return n2;
|
||||
}
|
||||
FileName::free(n2);
|
||||
}
|
||||
FileName::free(n);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
|
||||
{
|
||||
//printf("Module::load(ident = '%s')\n", ident->toChars());
|
||||
|
@ -223,50 +345,15 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
|
|||
// foo.bar.baz
|
||||
// into:
|
||||
// foo\bar\baz
|
||||
const char *filename = ident->toChars();
|
||||
if (packages && packages->length)
|
||||
{
|
||||
OutBuffer buf;
|
||||
OutBuffer dotmods;
|
||||
Array<const char *> *ms = &global.params.modFileAliasStrings;
|
||||
const size_t msdim = ms ? ms->length : 0;
|
||||
|
||||
for (size_t i = 0; i < packages->length; i++)
|
||||
{
|
||||
Identifier *pid = (*packages)[i];
|
||||
const char *p = pid->toChars();
|
||||
buf.writestring(p);
|
||||
if (msdim)
|
||||
checkModFileAlias(&buf, &dotmods, ms, msdim, p);
|
||||
#if _WIN32
|
||||
buf.writeByte('\\');
|
||||
#else
|
||||
buf.writeByte('/');
|
||||
#endif
|
||||
}
|
||||
buf.writestring(filename);
|
||||
if (msdim)
|
||||
checkModFileAlias(&buf, &dotmods, ms, msdim, filename);
|
||||
buf.writeByte(0);
|
||||
filename = (char *)buf.extractData();
|
||||
}
|
||||
const char *filename = getFilename(packages, ident);
|
||||
// Look for the source file
|
||||
const char *result = lookForSourceFile(filename);
|
||||
if (result)
|
||||
filename = result;
|
||||
|
||||
Module *m = new Module(filename, ident, 0, 0);
|
||||
m->loc = loc;
|
||||
|
||||
/* Look for the source file
|
||||
*/
|
||||
const char *path;
|
||||
const char *result = lookForSourceFile(&path, filename);
|
||||
if (result)
|
||||
{
|
||||
m->srcfile = new File(result);
|
||||
if (path)
|
||||
m->srcfilePath = path;
|
||||
else if (!FileName::absolute(result))
|
||||
m->srcfilePath = getcwd(NULL, 0);
|
||||
}
|
||||
|
||||
if (!m->read(loc))
|
||||
return NULL;
|
||||
|
||||
|
@ -1158,6 +1245,27 @@ Module *Package::isPackageMod()
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for the existence of a package.d to set isPkgMod appropriately
|
||||
* if isPkgMod == PKGunknown
|
||||
*/
|
||||
void Package::resolvePKGunknown()
|
||||
{
|
||||
if (isModule())
|
||||
return;
|
||||
if (isPkgMod != PKGunknown)
|
||||
return;
|
||||
|
||||
Identifiers packages;
|
||||
for (Dsymbol *s = this->parent; s; s = s->parent)
|
||||
packages.insert(0, s->ident);
|
||||
|
||||
if (lookForSourceFile(getFilename(&packages, ident)))
|
||||
Module::load(Loc(), &packages, this->ident);
|
||||
else
|
||||
isPkgMod = PKGpackage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if pkg is a sub-package of this
|
||||
*
|
||||
|
@ -1266,96 +1374,3 @@ Dsymbol *Package::search(const Loc &loc, Identifier *ident, int flags)
|
|||
|
||||
return ScopeDsymbol::search(loc, ident, flags);
|
||||
}
|
||||
|
||||
/* =========================== ===================== */
|
||||
|
||||
/********************************************
|
||||
* Look for the source file if it's different from filename.
|
||||
* Look for .di, .d, directory, and along global.path.
|
||||
* Does not open the file.
|
||||
* Output:
|
||||
* path the path where the file was found if it was not the current directory
|
||||
* Input:
|
||||
* filename as supplied by the user
|
||||
* global.path
|
||||
* Returns:
|
||||
* NULL if it's not different from filename.
|
||||
*/
|
||||
|
||||
const char *lookForSourceFile(const char **path, const char *filename)
|
||||
{
|
||||
/* Search along global.path for .di file, then .d file.
|
||||
*/
|
||||
*path = NULL;
|
||||
|
||||
const char *sdi = FileName::forceExt(filename, global.hdr_ext.ptr);
|
||||
if (FileName::exists(sdi) == 1)
|
||||
return sdi;
|
||||
|
||||
const char *sd = FileName::forceExt(filename, global.mars_ext.ptr);
|
||||
if (FileName::exists(sd) == 1)
|
||||
return sd;
|
||||
|
||||
if (FileName::exists(filename) == 2)
|
||||
{
|
||||
/* The filename exists and it's a directory.
|
||||
* Therefore, the result should be: filename/package.d
|
||||
* iff filename/package.d is a file
|
||||
*/
|
||||
const char *ni = FileName::combine(filename, "package.di");
|
||||
if (FileName::exists(ni) == 1)
|
||||
return ni;
|
||||
FileName::free(ni);
|
||||
const char *n = FileName::combine(filename, "package.d");
|
||||
if (FileName::exists(n) == 1)
|
||||
return n;
|
||||
FileName::free(n);
|
||||
}
|
||||
|
||||
if (FileName::absolute(filename))
|
||||
return NULL;
|
||||
|
||||
if (!global.path)
|
||||
return NULL;
|
||||
|
||||
for (size_t i = 0; i < global.path->length; i++)
|
||||
{
|
||||
const char *p = (*global.path)[i];
|
||||
|
||||
const char *n = FileName::combine(p, sdi);
|
||||
if (FileName::exists(n) == 1)
|
||||
{
|
||||
*path = p;
|
||||
return n;
|
||||
}
|
||||
FileName::free(n);
|
||||
|
||||
n = FileName::combine(p, sd);
|
||||
if (FileName::exists(n) == 1)
|
||||
{
|
||||
*path = p;
|
||||
return n;
|
||||
}
|
||||
FileName::free(n);
|
||||
|
||||
const char *b = FileName::removeExt(filename);
|
||||
n = FileName::combine(p, b);
|
||||
FileName::free(b);
|
||||
if (FileName::exists(n) == 2)
|
||||
{
|
||||
const char *n2i = FileName::combine(n, "package.di");
|
||||
if (FileName::exists(n2i) == 1)
|
||||
return n2i;
|
||||
FileName::free(n2i);
|
||||
const char *n2 = FileName::combine(n, "package.d");
|
||||
if (FileName::exists(n2) == 1)
|
||||
{
|
||||
*path = p;
|
||||
return n2;
|
||||
}
|
||||
FileName::free(n2);
|
||||
}
|
||||
FileName::free(n);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "template.h"
|
||||
#include "tokens.h"
|
||||
#include "target.h"
|
||||
#include "utf.h"
|
||||
#include "root/ctfloat.h"
|
||||
|
||||
Type *getTypeInfoType(Loc loc, Type *t, Scope *sc);
|
||||
void unSpeculative(Scope *sc, RootObject *o);
|
||||
|
@ -1245,6 +1247,102 @@ Dsymbol *StructDeclaration::search(const Loc &loc, Identifier *ident, int flags)
|
|||
return ScopeDsymbol::search(loc, ident, flags);
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Determine if exp is all binary zeros.
|
||||
* Params:
|
||||
* exp = expression to check
|
||||
* Returns:
|
||||
* true if it's all binary 0
|
||||
*/
|
||||
static bool isZeroInit(Expression *exp)
|
||||
{
|
||||
switch (exp->op)
|
||||
{
|
||||
case TOKint64:
|
||||
return exp->toInteger() == 0;
|
||||
|
||||
case TOKnull:
|
||||
case TOKfalse:
|
||||
return true;
|
||||
|
||||
case TOKstructliteral:
|
||||
{
|
||||
StructLiteralExp *sle = (StructLiteralExp *) exp;
|
||||
for (size_t i = 0; i < sle->sd->fields.length; i++)
|
||||
{
|
||||
VarDeclaration *field = sle->sd->fields[i];
|
||||
if (field->type->size(field->loc))
|
||||
{
|
||||
Expression *e = (*sle->elements)[i];
|
||||
if (e ? !isZeroInit(e)
|
||||
: !field->type->isZeroInit(field->loc))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case TOKarrayliteral:
|
||||
{
|
||||
ArrayLiteralExp *ale = (ArrayLiteralExp *) exp;
|
||||
|
||||
const size_t dim = ale->elements ? ale->elements->length : 0;
|
||||
|
||||
if (ale->type->toBasetype()->ty == Tarray) // if initializing a dynamic array
|
||||
return dim == 0;
|
||||
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
{
|
||||
if (!isZeroInit(ale->getElement(i)))
|
||||
return false;
|
||||
}
|
||||
/* Note that true is returned for all T[0]
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
case TOKstring:
|
||||
{
|
||||
StringExp *se = exp->toStringExp();
|
||||
|
||||
if (se->type->toBasetype()->ty == Tarray) // if initializing a dynamic array
|
||||
return se->len == 0;
|
||||
|
||||
void *s = se->string;
|
||||
for (size_t i = 0; i < se->len; i++)
|
||||
{
|
||||
dinteger_t val;
|
||||
switch (se->sz)
|
||||
{
|
||||
case 1: val = (( utf8_t *)s)[i]; break;
|
||||
case 2: val = ((utf16_t *)s)[i]; break;
|
||||
case 4: val = ((utf32_t *)s)[i]; break;
|
||||
default: assert(0); break;
|
||||
}
|
||||
if (val)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case TOKvector:
|
||||
{
|
||||
VectorExp *ve = (VectorExp *) exp;
|
||||
return isZeroInit(ve->e1);
|
||||
}
|
||||
|
||||
case TOKfloat64:
|
||||
case TOKcomplex80:
|
||||
{
|
||||
return (exp->toReal() == CTFloat::zero) &&
|
||||
(exp->toImaginary() == CTFloat::zero);
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void StructDeclaration::finalizeSize()
|
||||
{
|
||||
//printf("StructDeclaration::finalizeSize() %s, sizeok = %d\n", toChars(), sizeok);
|
||||
|
@ -1301,9 +1399,23 @@ void StructDeclaration::finalizeSize()
|
|||
VarDeclaration *vd = fields[i];
|
||||
if (vd->_init)
|
||||
{
|
||||
// Should examine init to see if it is really all 0's
|
||||
zeroInit = 0;
|
||||
break;
|
||||
if (vd->_init->isVoidInitializer())
|
||||
/* Treat as 0 for the purposes of putting the initializer
|
||||
* in the BSS segment, or doing a mass set to 0
|
||||
*/
|
||||
continue;
|
||||
|
||||
// Zero size fields are zero initialized
|
||||
if (vd->type->size(vd->loc) == 0)
|
||||
continue;
|
||||
|
||||
// Examine init to see if it is all 0s.
|
||||
Expression *exp = vd->getConstInitializer();
|
||||
if (!exp || !isZeroInit(exp))
|
||||
{
|
||||
zeroInit = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!vd->type->isZeroInit(loc))
|
||||
{
|
||||
|
|
|
@ -6783,7 +6783,7 @@ bool TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
|
|||
{
|
||||
//printf("type %s\n", ta->toChars());
|
||||
// It might really be an Expression or an Alias
|
||||
ta->resolve(loc, sc, &ea, &ta, &sa);
|
||||
ta->resolve(loc, sc, &ea, &ta, &sa, (flags & 1) != 0);
|
||||
if (ea) goto Lexpr;
|
||||
if (sa) goto Ldsym;
|
||||
if (ta == NULL)
|
||||
|
@ -6914,7 +6914,7 @@ bool TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
|
|||
//goto Ldsym;
|
||||
}
|
||||
}
|
||||
if (ea->op == TOKdotvar)
|
||||
if (ea->op == TOKdotvar && !(flags & 1))
|
||||
{
|
||||
// translate expression to dsymbol.
|
||||
sa = ((DotVarExp *)ea)->var;
|
||||
|
@ -6925,7 +6925,7 @@ bool TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
|
|||
sa = ((TemplateExp *)ea)->td;
|
||||
goto Ldsym;
|
||||
}
|
||||
if (ea->op == TOKdottd)
|
||||
if (ea->op == TOKdottd && !(flags & 1))
|
||||
{
|
||||
// translate expression to dsymbol.
|
||||
sa = ((DotTemplateExp *)ea)->td;
|
||||
|
|
|
@ -3337,7 +3337,7 @@ ClassReferenceExp *Expression::isClassReferenceExp()
|
|||
|
||||
|
||||
/****************************************
|
||||
* Resolve __FILE__, __LINE__, __MODULE__, __FUNCTION__, __PRETTY_FUNCTION__ to loc.
|
||||
* Resolve __FILE__, __LINE__, __MODULE__, __FUNCTION__, __PRETTY_FUNCTION__, __FILE__FULL_PATH__ to loc.
|
||||
*/
|
||||
|
||||
Expression *Expression::resolveLoc(Loc, Scope *)
|
||||
|
@ -7170,9 +7170,12 @@ FileInitExp::FileInitExp(Loc loc, TOK tok)
|
|||
Expression *FileInitExp::resolveLoc(Loc loc, Scope *sc)
|
||||
{
|
||||
//printf("FileInitExp::resolve() %s\n", toChars());
|
||||
const char *s = loc.filename ? loc.filename : sc->_module->ident->toChars();
|
||||
const char *s;
|
||||
if (subop == TOKfilefullpath)
|
||||
s = FileName::combine(sc->_module->srcfilePath, s);
|
||||
s = FileName::toAbsolute(loc.filename != NULL ? loc.filename : sc->_module->srcfile->name->toChars());
|
||||
else
|
||||
s = loc.filename != NULL ? loc.filename : sc->_module->ident->toChars();
|
||||
|
||||
Expression *e = new StringExp(loc, const_cast<char *>(s));
|
||||
e = semantic(e, sc);
|
||||
e = e->castTo(sc, type);
|
||||
|
|
|
@ -119,6 +119,36 @@ static bool preFunctionParameters(Scope *sc, Expressions *exps)
|
|||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a symbol represents a module or package
|
||||
* (Used as a helper for is(type == module) and is(type == package))
|
||||
*
|
||||
* Params:
|
||||
* sym = the symbol to be checked
|
||||
*
|
||||
* Returns:
|
||||
* the symbol which `sym` represents (or `null` if it doesn't represent a `Package`)
|
||||
*/
|
||||
Package *resolveIsPackage(Dsymbol *sym)
|
||||
{
|
||||
Package *pkg;
|
||||
if (Import *imp = sym->isImport())
|
||||
{
|
||||
if (imp->pkg == NULL)
|
||||
{
|
||||
error(sym->loc, "Internal Compiler Error: unable to process forward-referenced import `%s`",
|
||||
imp->toChars());
|
||||
assert(0);
|
||||
}
|
||||
pkg = imp->pkg;
|
||||
}
|
||||
else
|
||||
pkg = sym->isPackage();
|
||||
if (pkg)
|
||||
pkg->resolvePKGunknown();
|
||||
return pkg;
|
||||
}
|
||||
|
||||
class ExpressionSemanticVisitor : public Visitor
|
||||
{
|
||||
public:
|
||||
|
@ -1920,15 +1950,34 @@ public:
|
|||
}
|
||||
|
||||
Type *tded = NULL;
|
||||
Scope *sc2 = sc->copy(); // keep sc->flags
|
||||
sc2->tinst = NULL;
|
||||
sc2->minst = NULL;
|
||||
sc2->flags |= SCOPEfullinst;
|
||||
Type *t = e->targ->trySemantic(e->loc, sc2);
|
||||
sc2->pop();
|
||||
if (!t)
|
||||
goto Lno; // errors, so condition is false
|
||||
e->targ = t;
|
||||
if (e->tok2 == TOKpackage || e->tok2 == TOKmodule) // These is() expressions are special because they can work on modules, not just types.
|
||||
{
|
||||
Dsymbol *sym = e->targ->toDsymbol(sc);
|
||||
if (sym == NULL)
|
||||
goto Lno;
|
||||
Package *p = resolveIsPackage(sym);
|
||||
if (p == NULL)
|
||||
goto Lno;
|
||||
if (e->tok2 == TOKpackage && p->isModule()) // Note that isModule() will return null for package modules because they're not actually instances of Module.
|
||||
goto Lno;
|
||||
else if(e->tok2 == TOKmodule && !(p->isModule() || p->isPackageMod()))
|
||||
goto Lno;
|
||||
tded = e->targ;
|
||||
goto Lyes;
|
||||
}
|
||||
|
||||
{
|
||||
Scope *sc2 = sc->copy(); // keep sc->flags
|
||||
sc2->tinst = NULL;
|
||||
sc2->minst = NULL;
|
||||
sc2->flags |= SCOPEfullinst;
|
||||
Type *t = e->targ->trySemantic(e->loc, sc2);
|
||||
sc2->pop();
|
||||
if (!t) // errors, so condition is false
|
||||
goto Lno;
|
||||
e->targ = t;
|
||||
}
|
||||
|
||||
if (e->tok2 != TOKreserved)
|
||||
{
|
||||
switch (e->tok2)
|
||||
|
|
|
@ -41,7 +41,6 @@ Expression *semantic(Expression *e, Scope *sc);
|
|||
int blockExit(Statement *s, FuncDeclaration *func, bool mustNotThrow);
|
||||
TypeIdentifier *getThrowable();
|
||||
|
||||
RET retStyle(TypeFunction *tf);
|
||||
void MODtoBuffer(OutBuffer *buf, MOD mod);
|
||||
char *MODtoChars(MOD mod);
|
||||
bool MODimplicitConv(MOD modfrom, MOD modto);
|
||||
|
@ -970,7 +969,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||
{
|
||||
if (fdv->isFuture())
|
||||
{
|
||||
::deprecation(loc, "@future base class method %s is being overridden by %s; rename the latter",
|
||||
::deprecation(loc, "@__future base class method %s is being overridden by %s; rename the latter",
|
||||
fdv->toPrettyChars(), toPrettyChars());
|
||||
// Treat 'this' as an introducing function, giving it a separate hierarchy in the vtbl[]
|
||||
goto Lintro;
|
||||
|
@ -1758,7 +1757,7 @@ void FuncDeclaration::semantic3(Scope *sc)
|
|||
if (storage_class & STCauto)
|
||||
storage_class &= ~STCauto;
|
||||
}
|
||||
if (retStyle(f) != RETstack || checkNrvo())
|
||||
if (!target.isReturnOnStack(f, needThis()) || !checkNRVO())
|
||||
nrvo_can = 0;
|
||||
|
||||
if (fbody->isErrorStatement())
|
||||
|
@ -4275,19 +4274,16 @@ void FuncDeclaration::checkDmain()
|
|||
* using NRVO is possible.
|
||||
*
|
||||
* Returns:
|
||||
* true if the result cannot be returned by hidden reference.
|
||||
* `false` if the result cannot be returned by hidden reference.
|
||||
*/
|
||||
bool FuncDeclaration::checkNrvo()
|
||||
bool FuncDeclaration::checkNRVO()
|
||||
{
|
||||
if (!nrvo_can)
|
||||
return true;
|
||||
|
||||
if (returns == NULL)
|
||||
return true;
|
||||
if (!nrvo_can || returns == NULL)
|
||||
return false;
|
||||
|
||||
TypeFunction *tf = type->toTypeFunction();
|
||||
if (tf->isref)
|
||||
return true;
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < returns->length; i++)
|
||||
{
|
||||
|
@ -4297,24 +4293,23 @@ bool FuncDeclaration::checkNrvo()
|
|||
{
|
||||
VarDeclaration *v = ve->var->isVarDeclaration();
|
||||
if (!v || v->isOut() || v->isRef())
|
||||
return true;
|
||||
return false;
|
||||
else if (nrvo_var == NULL)
|
||||
{
|
||||
if (!v->isDataseg() && !v->isParameter() && v->toParent2() == this)
|
||||
{
|
||||
//printf("Setting nrvo to %s\n", v->toChars());
|
||||
nrvo_var = v;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
// Variables in the data segment (e.g. globals, TLS or not),
|
||||
// parameters and closure variables cannot be NRVOed.
|
||||
if (v->isDataseg() || v->isParameter() || v->toParent2() != this)
|
||||
return false;
|
||||
//printf("Setting nrvo to %s\n", v->toChars());
|
||||
nrvo_var = v;
|
||||
}
|
||||
else if (nrvo_var != v)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
else //if (!exp->isLvalue()) // keep NRVO-ability
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *FuncDeclaration::kind() const
|
||||
|
|
|
@ -286,7 +286,7 @@ typedef uint64_t d_uns64;
|
|||
// file location
|
||||
struct Loc
|
||||
{
|
||||
const char *filename;
|
||||
const char *filename; // either absolute or relative to cwd
|
||||
unsigned linnum;
|
||||
unsigned charnum;
|
||||
|
||||
|
|
|
@ -322,6 +322,9 @@ Msgtable msgtable[] =
|
|||
{ "isFinalClass", NULL },
|
||||
{ "isTemplate", NULL },
|
||||
{ "isPOD", NULL },
|
||||
{ "isDeprecated", NULL },
|
||||
{ "isDisabled", NULL },
|
||||
{ "isFuture" , NULL },
|
||||
{ "isNested", NULL },
|
||||
{ "isFloating", NULL },
|
||||
{ "isIntegral", NULL },
|
||||
|
@ -334,13 +337,17 @@ Msgtable msgtable[] =
|
|||
{ "isFinalFunction", NULL },
|
||||
{ "isOverrideFunction", NULL },
|
||||
{ "isStaticFunction", NULL },
|
||||
{ "isModule", NULL },
|
||||
{ "isPackage", NULL },
|
||||
{ "isRef", NULL },
|
||||
{ "isOut", NULL },
|
||||
{ "isLazy", NULL },
|
||||
{ "hasMember", NULL },
|
||||
{ "identifier", NULL },
|
||||
{ "getProtection", NULL },
|
||||
{ "getVisibility", NULL },
|
||||
{ "parent", NULL },
|
||||
{ "child", NULL },
|
||||
{ "getMember", NULL },
|
||||
{ "getOverloads", NULL },
|
||||
{ "getVirtualFunctions", NULL },
|
||||
|
@ -360,6 +367,12 @@ Msgtable msgtable[] =
|
|||
{ "getUnitTests", NULL },
|
||||
{ "getVirtualIndex", NULL },
|
||||
{ "getPointerBitmap", NULL },
|
||||
{ "isReturnOnStack", NULL },
|
||||
{ "isZeroInit", NULL },
|
||||
{ "getTargetInfo", NULL },
|
||||
{ "getLocation", NULL },
|
||||
{ "hasPostblit", NULL },
|
||||
{ "isCopyable", NULL },
|
||||
|
||||
// For C++ mangling
|
||||
{ "allocator", NULL },
|
||||
|
|
|
@ -48,6 +48,7 @@ public:
|
|||
void accept(Visitor *v) { v->visit(this); }
|
||||
|
||||
Module *isPackageMod();
|
||||
void resolvePKGunknown();
|
||||
};
|
||||
|
||||
class Module : public Package
|
||||
|
@ -68,7 +69,6 @@ public:
|
|||
const char *arg; // original argument name
|
||||
ModuleDeclaration *md; // if !NULL, the contents of the ModuleDeclaration declaration
|
||||
File *srcfile; // input source file
|
||||
const char* srcfilePath; // the path prefix to the srcfile if it applies
|
||||
File *objfile; // output .obj file
|
||||
File *hdrfile; // 'header' file
|
||||
File *docfile; // output documentation file
|
||||
|
|
|
@ -6682,6 +6682,7 @@ Type *TypeTraits::semantic(Loc, Scope *sc)
|
|||
exp->ident != Id::derivedMembers &&
|
||||
exp->ident != Id::getMember &&
|
||||
exp->ident != Id::parent &&
|
||||
exp->ident != Id::child &&
|
||||
exp->ident != Id::getOverloads &&
|
||||
exp->ident != Id::getVirtualFunctions &&
|
||||
exp->ident != Id::getVirtualMethods &&
|
||||
|
|
|
@ -5949,7 +5949,10 @@ bool Parser::isDeclaration(Token *t, int needId, TOK endtok, Token **pt)
|
|||
}
|
||||
if (!isDeclarator(&t, &haveId, &haveTpl, endtok, needId != 3))
|
||||
goto Lisnot;
|
||||
if (needId == 1 || (needId == 0 && !haveId) || ((needId == 2 || needId == 3) && haveId))
|
||||
if ((needId == 0 && !haveId) ||
|
||||
(needId == 1) ||
|
||||
(needId == 2 && haveId) ||
|
||||
(needId == 3 && haveId))
|
||||
{
|
||||
if (pt)
|
||||
*pt = t;
|
||||
|
@ -6821,12 +6824,8 @@ Expression *Parser::parsePrimaryExp()
|
|||
|
||||
case TOKfilefullpath:
|
||||
{
|
||||
const char *srcfile = mod->srcfile->name->toChars();
|
||||
const char *s;
|
||||
if (loc.filename && !FileName::equals(loc.filename, srcfile))
|
||||
s = loc.filename;
|
||||
else
|
||||
s = FileName::combine(mod->srcfilePath, srcfile);
|
||||
assert(loc.filename); // __FILE_FULL_PATH__ does not work with an invalid location
|
||||
const char *s = FileName::toAbsolute(loc.filename);
|
||||
e = new StringExp(loc, const_cast<char *>(s), strlen(s), 0);
|
||||
nextToken();
|
||||
break;
|
||||
|
@ -7039,6 +7038,8 @@ Expression *Parser::parsePrimaryExp()
|
|||
token.value == TOKsuper ||
|
||||
token.value == TOKenum ||
|
||||
token.value == TOKinterface ||
|
||||
token.value == TOKmodule ||
|
||||
token.value == TOKpackage ||
|
||||
token.value == TOKargTypes ||
|
||||
token.value == TOKparameters ||
|
||||
(token.value == TOKconst && peek(&token)->value == TOKrparen) ||
|
||||
|
|
|
@ -175,6 +175,20 @@ bool FileName::absolute(const char *name)
|
|||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
Return the given name as an absolute path
|
||||
|
||||
Params:
|
||||
name = path
|
||||
base = the absolute base to prefix name with if it is relative
|
||||
|
||||
Returns: name as an absolute path relative to base
|
||||
*/
|
||||
const char *FileName::toAbsolute(const char *name, const char *base)
|
||||
{
|
||||
return absolute(name) ? name : combine(base ? base : getcwd(NULL, 0), name);
|
||||
}
|
||||
|
||||
/********************************
|
||||
* Return filename extension (read-only).
|
||||
* Points past '.' of extension.
|
||||
|
|
|
@ -24,6 +24,7 @@ struct FileName
|
|||
int compare(RootObject *obj);
|
||||
static int compare(const char *name1, const char *name2);
|
||||
static bool absolute(const char *name);
|
||||
static const char *toAbsolute(const char *name, const char *base = NULL);
|
||||
static const char *ext(const char *);
|
||||
const char *ext();
|
||||
static const char *removeExt(const char *str);
|
||||
|
|
|
@ -22,6 +22,7 @@ class Expression;
|
|||
class FuncDeclaration;
|
||||
class Parameter;
|
||||
class Type;
|
||||
class TypeFunction;
|
||||
class TypeTuple;
|
||||
struct OutBuffer;
|
||||
|
||||
|
@ -105,6 +106,8 @@ public:
|
|||
// ABI and backend.
|
||||
LINK systemLinkage();
|
||||
TypeTuple *toArgTypes(Type *t);
|
||||
bool isReturnOnStack(TypeFunction *tf, bool needsThis);
|
||||
Expression *getTargetInfo(const char* name, const Loc& loc);
|
||||
};
|
||||
|
||||
extern Target target;
|
||||
|
|
File diff suppressed because it is too large
Load diff
28
gcc/testsuite/gdc.test/compilable/Test16206.d
Normal file
28
gcc/testsuite/gdc.test/compilable/Test16206.d
Normal file
|
@ -0,0 +1,28 @@
|
|||
struct S {
|
||||
static int foo()() { return 0; }
|
||||
static int foo()(int n) { return 1; }
|
||||
static int foo(string s) { return 2; }
|
||||
enum foo(int[] arr) = arr.length;
|
||||
}
|
||||
|
||||
alias AliasSeq(T...) = T;
|
||||
|
||||
alias allFoos = AliasSeq!(__traits(getOverloads, S, "foo", true));
|
||||
|
||||
static assert(allFoos.length == 4);
|
||||
|
||||
static assert(allFoos[0]("") == 2);
|
||||
static assert(allFoos[1]() == 0);
|
||||
static assert(allFoos[2](1) == 1);
|
||||
alias foo3 = allFoos[3];
|
||||
static assert(foo3!([]) == 0);
|
||||
|
||||
static assert(S.foo() == 0);
|
||||
static assert(S.foo(1) == 1);
|
||||
static assert(S.foo("") == 2);
|
||||
static assert(S.foo!([]) == 0);
|
||||
|
||||
|
||||
alias fooFuns = AliasSeq!(__traits(getOverloads, S, "foo"));
|
||||
static assert(fooFuns.length == 1);
|
||||
static assert(fooFuns[0]("") == 2);
|
|
@ -0,0 +1,3 @@
|
|||
/// Used to test is(x == package) and is(x == module)
|
||||
|
||||
module imports.pkgmodule;
|
|
@ -0,0 +1,2 @@
|
|||
/// Used to test is(x == module)
|
||||
module imports.pkgmodule.plainmodule;
|
|
@ -0,0 +1,4 @@
|
|||
/// Used to test is(x == module)
|
||||
|
||||
module imports.plainpackage.plainmodule;
|
||||
|
78
gcc/testsuite/gdc.test/compilable/isZeroInit.d
Normal file
78
gcc/testsuite/gdc.test/compilable/isZeroInit.d
Normal file
|
@ -0,0 +1,78 @@
|
|||
alias AliasSeq(T...) = T;
|
||||
|
||||
struct Holder(T, ubyte val)
|
||||
{
|
||||
T x = val;
|
||||
}
|
||||
|
||||
struct SArrayHolder(T, ubyte val)
|
||||
{
|
||||
T[2] x = val;
|
||||
}
|
||||
|
||||
static foreach (T; AliasSeq!(bool, byte, short, int, long,
|
||||
ubyte, ushort, uint, ulong,
|
||||
char, wchar, dchar,
|
||||
float, double, real))
|
||||
{
|
||||
static assert(__traits(isZeroInit, T) == (T.init is T(0)));
|
||||
static assert(__traits(isZeroInit, T[2]) == (T.init is T(0)));
|
||||
|
||||
static assert(!__traits(isZeroInit, Holder!(T, 1)));
|
||||
static assert(__traits(isZeroInit, Holder!(T, 0)));
|
||||
|
||||
static assert(__traits(isZeroInit, SArrayHolder!(T, 0)));
|
||||
static assert(!__traits(isZeroInit, SArrayHolder!(T, 1)));
|
||||
|
||||
}
|
||||
|
||||
static assert(__traits(isZeroInit, void)); // For initializing arrays of element type `void`.
|
||||
static assert(__traits(isZeroInit, void*));
|
||||
static assert(__traits(isZeroInit, void[]));
|
||||
static assert(__traits(isZeroInit, float[]));
|
||||
static assert(__traits(isZeroInit, Object));
|
||||
class C1 : Object
|
||||
{
|
||||
int x = 1;
|
||||
}
|
||||
static assert(__traits(isZeroInit, C1)); // An Object's fields are irrelevant.
|
||||
|
||||
struct S1
|
||||
{
|
||||
int[] a;
|
||||
int b;
|
||||
}
|
||||
static assert(__traits(isZeroInit, S1));
|
||||
|
||||
struct S2
|
||||
{
|
||||
alias H = Holder!(int, 1);
|
||||
H h;
|
||||
int a;
|
||||
}
|
||||
static assert(!__traits(isZeroInit, S2));
|
||||
|
||||
struct S3
|
||||
{
|
||||
S1 h;
|
||||
float f = 0;
|
||||
}
|
||||
static assert(__traits(isZeroInit, S3));
|
||||
|
||||
struct S4
|
||||
{
|
||||
S2 h = S2(S2.H(0), 0);
|
||||
int a;
|
||||
}
|
||||
static assert(__traits(isZeroInit, S4));
|
||||
|
||||
struct S5
|
||||
{
|
||||
Object o = null;
|
||||
}
|
||||
static assert(__traits(isZeroInit, S5));
|
||||
|
||||
version(D_SIMD):
|
||||
import core.simd : int4;
|
||||
static assert(__traits(isZeroInit, Holder!(int4, 0)));
|
||||
static assert(!__traits(isZeroInit, Holder!(int4, 1)));
|
7
gcc/testsuite/gdc.test/compilable/isreturnonstack.d
Normal file
7
gcc/testsuite/gdc.test/compilable/isreturnonstack.d
Normal file
|
@ -0,0 +1,7 @@
|
|||
struct S { int[10] a; }
|
||||
int test1();
|
||||
S test2();
|
||||
|
||||
static assert(__traits(isReturnOnStack, test1) == false);
|
||||
static assert(__traits(isReturnOnStack, test2) == true);
|
||||
|
|
@ -19,12 +19,12 @@ static assert(__FILE_FULL_PATH__[$-__FILE__.length..$] == __FILE__);
|
|||
|
||||
static assert(__LINE__ == 101);
|
||||
static assert(__FILE__ == "newfile.d");
|
||||
static assert(__FILE_FULL_PATH__ == "newfile.d");
|
||||
static assert(__FILE_FULL_PATH__[$ - 9 .. $] == "newfile.d");
|
||||
|
||||
# line 200
|
||||
|
||||
static assert(__LINE__ == 201);
|
||||
static assert(__FILE__ == "newfile.d");
|
||||
static assert(__FILE_FULL_PATH__ == "newfile.d");
|
||||
static assert(__FILE_FULL_PATH__[$ - 9 .. $] == "newfile.d");
|
||||
|
||||
|
||||
|
|
24
gcc/testsuite/gdc.test/compilable/test16002.d
Normal file
24
gcc/testsuite/gdc.test/compilable/test16002.d
Normal file
|
@ -0,0 +1,24 @@
|
|||
module test.compilable.test16002;
|
||||
|
||||
import imports.plainpackage.plainmodule;
|
||||
import imports.pkgmodule.plainmodule;
|
||||
|
||||
struct MyStruct;
|
||||
|
||||
alias a = imports.plainpackage;
|
||||
alias b = imports.pkgmodule.plainmodule;
|
||||
|
||||
static assert(is(imports.plainpackage == package));
|
||||
static assert(is(a == package));
|
||||
static assert(!is(imports.plainpackage.plainmodule == package));
|
||||
static assert(!is(b == package));
|
||||
static assert(is(imports.pkgmodule == package));
|
||||
static assert(!is(MyStruct == package));
|
||||
|
||||
static assert(!is(imports.plainpackage == module));
|
||||
static assert(!is(a == module));
|
||||
static assert(is(imports.plainpackage.plainmodule == module));
|
||||
static assert(is(b == module));
|
||||
// This is supposed to work even though we haven't directly imported imports.pkgmodule.
|
||||
static assert(is(imports.pkgmodule == module));
|
||||
static assert(!is(MyStruct == module));
|
28
gcc/testsuite/gdc.test/compilable/test17791.d
Normal file
28
gcc/testsuite/gdc.test/compilable/test17791.d
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
REQUIRED_ARGS: -de
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
---
|
||||
*/
|
||||
deprecated("A deprecated class") {
|
||||
class DepClass
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class NewClass
|
||||
{
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// test that a symbol (which is not likely to be deprecated)
|
||||
// is not depercated
|
||||
static assert(!__traits(isDeprecated, int));
|
||||
// check that a class marked deprecated "isDeprecated"
|
||||
static assert(__traits(isDeprecated, DepClass));
|
||||
// check that a class not marked deprecated is not deprecated
|
||||
static assert(!__traits(isDeprecated, NewClass));
|
||||
// Check for expressions (18617)
|
||||
static assert(__traits(isDeprecated, { scope foo = new DepClass; }));
|
||||
}
|
|
@ -1,10 +1,140 @@
|
|||
// REQUIRED_ARGS:
|
||||
// EXTRA_FILES: imports/plainpackage/plainmodule.d imports/pkgmodule/package.d imports/pkgmodule/plainmodule.d
|
||||
|
||||
// This file is intended to contain all compilable traits-related tests in an
|
||||
// effort to keep the number of files in the `compilable` folder to a minimum.
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=19152
|
||||
module traits;
|
||||
|
||||
class C19152
|
||||
{
|
||||
int OnExecute()
|
||||
{
|
||||
auto name = __traits(getOverloads, this, "OnExecute").stringof;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static assert(is(typeof(__traits(getTargetInfo, "cppRuntimeLibrary")) == string));
|
||||
version (CppRuntime_Microsoft)
|
||||
{
|
||||
static assert(__traits(getTargetInfo, "cppRuntimeLibrary") == "libcmt");
|
||||
}
|
||||
|
||||
import imports.plainpackage.plainmodule;
|
||||
import imports.pkgmodule.plainmodule;
|
||||
|
||||
#line 40
|
||||
struct MyStruct;
|
||||
|
||||
alias a = imports.plainpackage;
|
||||
alias b = imports.pkgmodule.plainmodule;
|
||||
|
||||
static assert(__traits(isPackage, imports.plainpackage));
|
||||
static assert(__traits(isPackage, a));
|
||||
static assert(!__traits(isPackage, imports.plainpackage.plainmodule));
|
||||
static assert(!__traits(isPackage, b));
|
||||
static assert(__traits(isPackage, imports.pkgmodule));
|
||||
static assert(!__traits(isPackage, MyStruct));
|
||||
|
||||
static assert(!__traits(isModule, imports.plainpackage));
|
||||
static assert(!__traits(isModule, a));
|
||||
static assert(__traits(isModule, imports.plainpackage.plainmodule));
|
||||
static assert(__traits(isModule, b));
|
||||
// This is supposed to work even though we haven't directly imported imports.pkgmodule.
|
||||
static assert(__traits(isModule, imports.pkgmodule));
|
||||
static assert(!__traits(isModule, MyStruct));
|
||||
|
||||
/******************************************/
|
||||
// https://issues.dlang.org/show_bug.cgi?id=19942
|
||||
|
||||
static assert(!__traits(compiles, { a.init; }));
|
||||
static assert(!__traits(compiles, { import m : a; a.init; }));
|
||||
|
||||
version(Windows)
|
||||
static assert(__traits(getLocation, MyStruct)[0] == `compilable\traits.d`);
|
||||
else
|
||||
static assert(__traits(getLocation, MyStruct)[0] == "compilable/traits.d");
|
||||
static assert(__traits(getLocation, MyStruct)[1] == 40);
|
||||
static assert(__traits(getLocation, MyStruct)[2] == 1);
|
||||
|
||||
int foo();
|
||||
int foo(int);
|
||||
|
||||
static assert(__traits(getLocation, __traits(getOverloads, traits, "foo")[1])[1] == 74);
|
||||
|
||||
mixin("int bar;");
|
||||
static assert(__traits(getLocation, bar)[1] == 78);
|
||||
|
||||
struct Outer
|
||||
{
|
||||
struct Nested{}
|
||||
|
||||
void method() {}
|
||||
}
|
||||
static assert(__traits(getLocation, Outer.Nested)[1] == 83);
|
||||
static assert(__traits(getLocation, Outer.method)[1] == 85);
|
||||
|
||||
/******************************************/
|
||||
// https://issues.dlang.org/show_bug.cgi?id=19902
|
||||
// Define hasElaborateCopyConstructor trait
|
||||
// but done as two independent traits per conversation
|
||||
// in https://github.com/dlang/dmd/pull/10265
|
||||
|
||||
struct S
|
||||
{
|
||||
this (ref S rhs) {}
|
||||
}
|
||||
|
||||
struct OuterS
|
||||
{
|
||||
struct S
|
||||
{
|
||||
this (ref S rhs) {}
|
||||
}
|
||||
|
||||
S s;
|
||||
}
|
||||
|
||||
void foo(T)()
|
||||
{
|
||||
struct S(U)
|
||||
{
|
||||
this (ref S rhs) {}
|
||||
}
|
||||
}
|
||||
|
||||
struct U(T)
|
||||
{
|
||||
this (ref U rhs) {}
|
||||
}
|
||||
|
||||
struct SPostblit
|
||||
{
|
||||
this(this) {}
|
||||
}
|
||||
|
||||
struct DisabledPostblit
|
||||
{
|
||||
@disable this(this);
|
||||
}
|
||||
|
||||
struct NoCpCtor { }
|
||||
class C19902 { }
|
||||
|
||||
static assert(__traits(compiles, foo!int));
|
||||
static assert(__traits(compiles, foo!S));
|
||||
static assert(!__traits(hasPostblit, U!S));
|
||||
static assert(__traits(hasPostblit, SPostblit));
|
||||
|
||||
static assert(!__traits(hasPostblit, NoCpCtor));
|
||||
static assert(!__traits(hasPostblit, C19902));
|
||||
static assert(!__traits(hasPostblit, int));
|
||||
|
||||
// Check that invalid use cases don't compile
|
||||
static assert(!__traits(compiles, __traits(hasPostblit)));
|
||||
static assert(!__traits(compiles, __traits(hasPostblit, S())));
|
||||
|
||||
static assert(__traits(isCopyable, int));
|
||||
static assert(!__traits(isCopyable, DisabledPostblit));
|
||||
|
|
12
gcc/testsuite/gdc.test/fail_compilation/fail16206a.d
Normal file
12
gcc/testsuite/gdc.test/fail_compilation/fail16206a.d
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/fail16206a.d(12): Error: `bool` expected as third argument of `__traits(getOverloads)`, not `"Not a bool"` of type `string`
|
||||
---
|
||||
*/
|
||||
|
||||
struct S {
|
||||
static int foo()() { return 0; }
|
||||
}
|
||||
alias AliasSeq(T...) = T;
|
||||
alias allFoos = AliasSeq!(__traits(getOverloads, S, "foo", "Not a bool"));
|
12
gcc/testsuite/gdc.test/fail_compilation/fail16206b.d
Normal file
12
gcc/testsuite/gdc.test/fail_compilation/fail16206b.d
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/fail16206b.d(12): Error: expected 2 arguments for `hasMember` but had 3
|
||||
---
|
||||
*/
|
||||
|
||||
struct S {
|
||||
static int foo()() { return 0; }
|
||||
}
|
||||
alias AliasSeq(T...) = T;
|
||||
alias allFoos = AliasSeq!(__traits(hasMember, S, "foo", true));
|
12
gcc/testsuite/gdc.test/fail_compilation/fail_isZeroInit.d
Normal file
12
gcc/testsuite/gdc.test/fail_compilation/fail_isZeroInit.d
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/fail_isZeroInit.d(11): Error: type expected as second argument of __traits `isZeroInit` instead of `a`
|
||||
---
|
||||
*/
|
||||
void test()
|
||||
{
|
||||
int a = 3;
|
||||
// Providing a specific variable rather than a type isn't allowed.
|
||||
enum bool az = __traits(isZeroInit, a);
|
||||
}
|
12
gcc/testsuite/gdc.test/fail_compilation/isreturnonstack.d
Normal file
12
gcc/testsuite/gdc.test/fail_compilation/isreturnonstack.d
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/isreturnonstack.d(11): Error: argument to `__traits(isReturnOnStack, int)` is not a function
|
||||
fail_compilation/isreturnonstack.d(12): Error: expected 1 arguments for `isReturnOnStack` but had 2
|
||||
---
|
||||
*/
|
||||
|
||||
int test() { return 0; }
|
||||
|
||||
enum b = __traits(isReturnOnStack, int);
|
||||
enum c = __traits(isReturnOnStack, test, int);
|
15
gcc/testsuite/gdc.test/fail_compilation/test16002.d
Normal file
15
gcc/testsuite/gdc.test/fail_compilation/test16002.d
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
REQUIRED_ARGS:
|
||||
PERMUTE_ARGS:
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/test16002.d(100): Error: undefined identifier `imports.nonexistent`
|
||||
fail_compilation/test16002.d(101): Error: undefined identifier `imports.nonexistent`
|
||||
---
|
||||
*/
|
||||
|
||||
module test.fail_compilation.test16002;
|
||||
|
||||
#line 100
|
||||
enum A = is(imports.nonexistent == package);
|
||||
enum B = is(imports.nonexistent == module);
|
50
gcc/testsuite/gdc.test/fail_compilation/test17096.d
Normal file
50
gcc/testsuite/gdc.test/fail_compilation/test17096.d
Normal file
|
@ -0,0 +1,50 @@
|
|||
/* TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/test17096.d(28): Error: expected 1 arguments for `isPOD` but had 2
|
||||
fail_compilation/test17096.d(29): Error: expected 1 arguments for `isNested` but had 2
|
||||
fail_compilation/test17096.d(30): Error: expected 1 arguments for `isVirtualFunction` but had 2
|
||||
fail_compilation/test17096.d(31): Error: expected 1 arguments for `isVirtualMethod` but had 2
|
||||
fail_compilation/test17096.d(32): Error: expected 1 arguments for `isAbstractFunction` but had 2
|
||||
fail_compilation/test17096.d(33): Error: expected 1 arguments for `isFinalFunction` but had 2
|
||||
fail_compilation/test17096.d(34): Error: expected 1 arguments for `isOverrideFunction` but had 2
|
||||
fail_compilation/test17096.d(35): Error: expected 1 arguments for `isStaticFunction` but had 2
|
||||
fail_compilation/test17096.d(36): Error: expected 1 arguments for `isRef` but had 2
|
||||
fail_compilation/test17096.d(37): Error: expected 1 arguments for `isOut` but had 2
|
||||
fail_compilation/test17096.d(38): Error: expected 1 arguments for `isLazy` but had 2
|
||||
fail_compilation/test17096.d(39): Error: expected 1 arguments for `identifier` but had 2
|
||||
fail_compilation/test17096.d(40): Error: expected 1 arguments for `getProtection` but had 2
|
||||
fail_compilation/test17096.d(41): Error: expected 1 arguments for `parent` but had 2
|
||||
fail_compilation/test17096.d(42): Error: expected 1 arguments for `classInstanceSize` but had 2
|
||||
fail_compilation/test17096.d(43): Error: expected 1 arguments for `allMembers` but had 2
|
||||
fail_compilation/test17096.d(44): Error: expected 1 arguments for `derivedMembers` but had 2
|
||||
fail_compilation/test17096.d(45): Error: expected 1 arguments for `getAliasThis` but had 2
|
||||
fail_compilation/test17096.d(46): Error: expected 1 arguments for `getAttributes` but had 2
|
||||
fail_compilation/test17096.d(47): Error: expected 1 arguments for `getFunctionAttributes` but had 2
|
||||
fail_compilation/test17096.d(48): Error: expected 1 arguments for `getUnitTests` but had 2
|
||||
fail_compilation/test17096.d(49): Error: expected 1 arguments for `getVirtualIndex` but had 2
|
||||
fail_compilation/test17096.d(50): Error: a single type expected for trait pointerBitmap
|
||||
---
|
||||
*/
|
||||
enum b03 = __traits(isPOD, 1, 2);
|
||||
enum b04 = __traits(isNested, 1, 2);
|
||||
enum b05 = __traits(isVirtualFunction, 1, 2);
|
||||
enum b06 = __traits(isVirtualMethod, 1, 2);
|
||||
enum b07 = __traits(isAbstractFunction, 1, 2);
|
||||
enum b08 = __traits(isFinalFunction, 1, 2);
|
||||
enum b09 = __traits(isOverrideFunction, 1, 2);
|
||||
enum b10 = __traits(isStaticFunction, 1, 2);
|
||||
enum b11 = __traits(isRef, 1, 2);
|
||||
enum b12 = __traits(isOut, 1, 2);
|
||||
enum b13 = __traits(isLazy, 1, 2);
|
||||
enum b14 = __traits(identifier, 1, 2);
|
||||
enum b15 = __traits(getProtection, 1, 2);
|
||||
enum b16 = __traits(parent, 1, 2);
|
||||
enum b17 = __traits(classInstanceSize, 1, 2);
|
||||
enum b18 = __traits(allMembers, 1, 2);
|
||||
enum b19 = __traits(derivedMembers, 1, 2);
|
||||
enum b20 = __traits(getAliasThis, 1, 2);
|
||||
enum b21 = __traits(getAttributes, 1, 2);
|
||||
enum b22 = __traits(getFunctionAttributes, 1, 2);
|
||||
enum b23 = __traits(getUnitTests, 1, 2);
|
||||
enum b24 = __traits(getVirtualIndex, 1, 2);
|
||||
enum b25 = __traits(getPointerBitmap, 1, 2);
|
15
gcc/testsuite/gdc.test/fail_compilation/trait_loc_err.d
Normal file
15
gcc/testsuite/gdc.test/fail_compilation/trait_loc_err.d
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/trait_loc_err.d(13): Error: can only get the location of a symbol, not `trait_loc_err`
|
||||
fail_compilation/trait_loc_err.d(14): Error: can only get the location of a symbol, not `std`
|
||||
---
|
||||
*/
|
||||
module trait_loc_err;
|
||||
import std.stdio;
|
||||
|
||||
void main()
|
||||
{
|
||||
__traits(getLocation, __traits(parent, main));
|
||||
__traits(getLocation, __traits(parent, std.stdio));
|
||||
}
|
40
gcc/testsuite/gdc.test/fail_compilation/trait_loc_ov_err.d
Normal file
40
gcc/testsuite/gdc.test/fail_compilation/trait_loc_ov_err.d
Normal file
|
@ -0,0 +1,40 @@
|
|||
module trait_loc_ov_err;
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/trait_loc_ov_err.d(24): Error: cannot get location of an overload set, use `__traits(getOverloads, ..., "ov1")[N]` to get the Nth overload
|
||||
fail_compilation/trait_loc_ov_err.d(25): Error: cannot get location of an overload set, use `__traits(getOverloads, ..., "ov2")[N]` to get the Nth overload
|
||||
---
|
||||
*/
|
||||
|
||||
void ov1(){}
|
||||
void ov1(int){}
|
||||
|
||||
void ov21(){}
|
||||
void ov22(int){}
|
||||
alias ov2 = ov21;
|
||||
alias ov2 = ov22;
|
||||
|
||||
template OvT(T, U){}
|
||||
template OvT(T){}
|
||||
|
||||
auto func(T)(T t) {}
|
||||
auto func(T,U)(T t,U u) {}
|
||||
|
||||
enum e1 = __traits(getLocation, ov1);
|
||||
enum e2 = __traits(getLocation, ov2);
|
||||
|
||||
enum e3 = __traits(getLocation, OvT);
|
||||
enum e4 = __traits(getLocation, func);
|
||||
|
||||
enum e5 = __traits(getLocation, __traits(getOverloads, trait_loc_ov_err, "ov1")[0]);
|
||||
enum e6 = __traits(getLocation, __traits(getOverloads, trait_loc_ov_err, "ov1")[1]);
|
||||
|
||||
enum e7 = __traits(getLocation, __traits(getOverloads, trait_loc_ov_err, "ov2")[0]);
|
||||
enum e8 = __traits(getLocation, __traits(getOverloads, trait_loc_ov_err, "ov2")[1]);
|
||||
|
||||
enum e9 = __traits(getLocation, __traits(getOverloads, trait_loc_ov_err, "OvT", true)[1]);
|
||||
enum e10 = __traits(getLocation, __traits(getOverloads, trait_loc_ov_err, "OvT", true)[0]);
|
||||
|
||||
enum e11 = __traits(getLocation, __traits(getOverloads, trait_loc_ov_err, "func", true)[0]);
|
||||
enum e12 = __traits(getLocation, __traits(getOverloads, trait_loc_ov_err, "func", true)[1]);
|
27
gcc/testsuite/gdc.test/fail_compilation/traits.d
Normal file
27
gcc/testsuite/gdc.test/fail_compilation/traits.d
Normal file
|
@ -0,0 +1,27 @@
|
|||
/************************************************************/
|
||||
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/traits.d(100): Error: `getTargetInfo` key `"not_a_target_info"` not supported by this implementation
|
||||
fail_compilation/traits.d(101): Error: string expected as argument of __traits `getTargetInfo` instead of `100`
|
||||
fail_compilation/traits.d(102): Error: expected 1 arguments for `getTargetInfo` but had 2
|
||||
fail_compilation/traits.d(103): Error: expected 1 arguments for `getTargetInfo` but had 0
|
||||
fail_compilation/traits.d(200): Error: undefined identifier `imports.nonexistent`
|
||||
fail_compilation/traits.d(201): Error: undefined identifier `imports.nonexistent`
|
||||
fail_compilation/traits.d(202): Error: expected 1 arguments for `isPackage` but had 0
|
||||
fail_compilation/traits.d(203): Error: expected 1 arguments for `isModule` but had 0
|
||||
---
|
||||
*/
|
||||
|
||||
#line 100
|
||||
enum A1 = __traits(getTargetInfo, "not_a_target_info");
|
||||
enum B1 = __traits(getTargetInfo, 100);
|
||||
enum C1 = __traits(getTargetInfo, "cppRuntimeLibrary", "bits");
|
||||
enum D1 = __traits(getTargetInfo);
|
||||
|
||||
#line 200
|
||||
enum A2 = __traits(isPackage, imports.nonexistent);
|
||||
enum B2 = __traits(isModule, imports.nonexistent);
|
||||
enum C2 = __traits(isPackage);
|
||||
enum D2 = __traits(isModule);
|
17
gcc/testsuite/gdc.test/fail_compilation/traits_child.d
Normal file
17
gcc/testsuite/gdc.test/fail_compilation/traits_child.d
Normal file
|
@ -0,0 +1,17 @@
|
|||
/************************************************************/
|
||||
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/traits_child.d(100): Error: expected 2 arguments for `child` but had 1
|
||||
fail_compilation/traits_child.d(101): Error: symbol or expression expected as first argument of __traits
|
||||
child` instead of `long`
|
||||
fail_compilation/traits_child.d(102): Error: symbol expected as second argument of __traits `child` inste
|
||||
d of `3`
|
||||
---
|
||||
*/
|
||||
|
||||
#line 100
|
||||
enum a = __traits(child, long);
|
||||
enum b = __traits(child, long, 3);
|
||||
enum c = __traits(child, "hi", 3);
|
14
gcc/testsuite/gdc.test/runnable/imports/test18322import.d
Normal file
14
gcc/testsuite/gdc.test/runnable/imports/test18322import.d
Normal file
|
@ -0,0 +1,14 @@
|
|||
module test18322import;
|
||||
void fun(string templateFileFullPath = __FILE_FULL_PATH__,
|
||||
string templateFile = __FILE__)(string expectedFilename, string fileFullPath = __FILE_FULL_PATH__)
|
||||
{
|
||||
// make sure it is an absolute path
|
||||
version(Windows)
|
||||
assert(fileFullPath[1..3] == ":\\");
|
||||
else
|
||||
assert(fileFullPath[0] == '/');
|
||||
|
||||
assert(templateFileFullPath == fileFullPath);
|
||||
assert(fileFullPath[$ - expectedFilename.length .. $] == expectedFilename);
|
||||
assert(fileFullPath[$ - templateFile.length .. $] == templateFile);
|
||||
}
|
20
gcc/testsuite/gdc.test/runnable/test17373.d
Normal file
20
gcc/testsuite/gdc.test/runnable/test17373.d
Normal file
|
@ -0,0 +1,20 @@
|
|||
interface Foo { void visit (int); }
|
||||
interface Bar { void visit(double); }
|
||||
interface FooBar : Foo, Bar {}
|
||||
static assert(__traits(getOverloads, FooBar, "visit").length == 2);
|
||||
|
||||
interface Fbar { void visit(char); void visit(double); }
|
||||
interface Triple : Foo, Bar, Fbar {}
|
||||
static assert(__traits(getOverloads, Triple, "visit").length == 3);
|
||||
|
||||
interface InheritanceMadness : FooBar, Triple {}
|
||||
static assert(__traits(getOverloads, Triple, "visit").length == 3);
|
||||
|
||||
interface Simple
|
||||
{
|
||||
int square(int);
|
||||
real square(real);
|
||||
}
|
||||
static assert(__traits(getOverloads, Simple, "square").length == 2);
|
||||
|
||||
void main() {}
|
19
gcc/testsuite/gdc.test/runnable/test17878.d
Normal file
19
gcc/testsuite/gdc.test/runnable/test17878.d
Normal file
|
@ -0,0 +1,19 @@
|
|||
@__future int foo()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bar()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
@__future int c;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
static assert(__traits(isFuture, foo));
|
||||
static assert(!__traits(isFuture, bar));
|
||||
static assert(__traits(isFuture, c));
|
||||
}
|
21
gcc/testsuite/gdc.test/runnable/test18322.d
Normal file
21
gcc/testsuite/gdc.test/runnable/test18322.d
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
REQUIRED_ARGS: -Irunnable/imports
|
||||
COMPILED_IMPORTS: imports/test18322import.d
|
||||
PERMUTE_ARGS:
|
||||
*/
|
||||
import test18322import;
|
||||
void main(){
|
||||
version(Windows)
|
||||
auto sep = "\\";
|
||||
else
|
||||
auto sep = "/";
|
||||
|
||||
auto filename = "runnable" ~ sep ~ "test18322.d";
|
||||
|
||||
fun(filename);
|
||||
mixin(`fun(filename ~ "-mixin-16");`);
|
||||
|
||||
#line 100 "poundlinefile.d"
|
||||
fun("poundlinefile.d");
|
||||
mixin(`fun("poundlinefile.d-mixin-101");`);
|
||||
}
|
|
@ -12,6 +12,7 @@ class AC2 { abstract void foo(); }
|
|||
class AC3 : AC2 { }
|
||||
final class FC { void foo() { } }
|
||||
enum E { EMEM }
|
||||
struct D1 { @disable void true_(); void false_(){} }
|
||||
|
||||
/********************************************************/
|
||||
|
||||
|
@ -623,7 +624,7 @@ struct Test24
|
|||
private void test24(int, int){}
|
||||
}
|
||||
|
||||
static assert(__traits(getProtection, __traits(getOverloads, Test24, "test24")[1]) == "private");
|
||||
static assert(__traits(getVisibility, __traits(getOverloads, Test24, "test24")[1]) == "private");
|
||||
|
||||
/********************************************************/
|
||||
// 1369
|
||||
|
@ -878,7 +879,7 @@ protected struct TestProt3 {}
|
|||
public struct TestProt4 {}
|
||||
export struct TestProt5 {}
|
||||
|
||||
void getProtection()
|
||||
void getVisibility()
|
||||
{
|
||||
class Test
|
||||
{
|
||||
|
@ -891,52 +892,52 @@ void getProtection()
|
|||
Test t;
|
||||
|
||||
// TOKvar and VarDeclaration
|
||||
static assert(__traits(getProtection, Test.va) == "private");
|
||||
static assert(__traits(getProtection, Test.vb) == "package");
|
||||
static assert(__traits(getProtection, Test.vc) == "protected");
|
||||
static assert(__traits(getProtection, Test.vd) == "public");
|
||||
static assert(__traits(getProtection, Test.ve) == "export");
|
||||
static assert(__traits(getVisibility, Test.va) == "private");
|
||||
static assert(__traits(getVisibility, Test.vb) == "package");
|
||||
static assert(__traits(getVisibility, Test.vc) == "protected");
|
||||
static assert(__traits(getVisibility, Test.vd) == "public");
|
||||
static assert(__traits(getVisibility, Test.ve) == "export");
|
||||
|
||||
// TOKdotvar and VarDeclaration
|
||||
static assert(__traits(getProtection, t.va) == "private");
|
||||
static assert(__traits(getProtection, t.vb) == "package");
|
||||
static assert(__traits(getProtection, t.vc) == "protected");
|
||||
static assert(__traits(getProtection, t.vd) == "public");
|
||||
static assert(__traits(getProtection, t.ve) == "export");
|
||||
static assert(__traits(getVisibility, t.va) == "private");
|
||||
static assert(__traits(getVisibility, t.vb) == "package");
|
||||
static assert(__traits(getVisibility, t.vc) == "protected");
|
||||
static assert(__traits(getVisibility, t.vd) == "public");
|
||||
static assert(__traits(getVisibility, t.ve) == "export");
|
||||
|
||||
// TOKvar and FuncDeclaration
|
||||
static assert(__traits(getProtection, Test.fa) == "private");
|
||||
static assert(__traits(getProtection, Test.fb) == "package");
|
||||
static assert(__traits(getProtection, Test.fc) == "protected");
|
||||
static assert(__traits(getProtection, Test.fd) == "public");
|
||||
static assert(__traits(getProtection, Test.fe) == "export");
|
||||
static assert(__traits(getVisibility, Test.fa) == "private");
|
||||
static assert(__traits(getVisibility, Test.fb) == "package");
|
||||
static assert(__traits(getVisibility, Test.fc) == "protected");
|
||||
static assert(__traits(getVisibility, Test.fd) == "public");
|
||||
static assert(__traits(getVisibility, Test.fe) == "export");
|
||||
|
||||
// TOKdotvar and FuncDeclaration
|
||||
static assert(__traits(getProtection, t.fa) == "private");
|
||||
static assert(__traits(getProtection, t.fb) == "package");
|
||||
static assert(__traits(getProtection, t.fc) == "protected");
|
||||
static assert(__traits(getProtection, t.fd) == "public");
|
||||
static assert(__traits(getProtection, t.fe) == "export");
|
||||
static assert(__traits(getVisibility, t.fa) == "private");
|
||||
static assert(__traits(getVisibility, t.fb) == "package");
|
||||
static assert(__traits(getVisibility, t.fc) == "protected");
|
||||
static assert(__traits(getVisibility, t.fd) == "public");
|
||||
static assert(__traits(getVisibility, t.fe) == "export");
|
||||
|
||||
// TOKtype
|
||||
static assert(__traits(getProtection, TestProt1) == "private");
|
||||
static assert(__traits(getProtection, TestProt2) == "package");
|
||||
static assert(__traits(getProtection, TestProt3) == "protected");
|
||||
static assert(__traits(getProtection, TestProt4) == "public");
|
||||
static assert(__traits(getProtection, TestProt5) == "export");
|
||||
static assert(__traits(getVisibility, TestProt1) == "private");
|
||||
static assert(__traits(getVisibility, TestProt2) == "package");
|
||||
static assert(__traits(getVisibility, TestProt3) == "protected");
|
||||
static assert(__traits(getVisibility, TestProt4) == "public");
|
||||
static assert(__traits(getVisibility, TestProt5) == "export");
|
||||
|
||||
// This specific pattern is important to ensure it always works
|
||||
// through reflection, however that becomes implemented
|
||||
static assert(__traits(getProtection, __traits(getMember, t, "va")) == "private");
|
||||
static assert(__traits(getProtection, __traits(getMember, t, "vb")) == "package");
|
||||
static assert(__traits(getProtection, __traits(getMember, t, "vc")) == "protected");
|
||||
static assert(__traits(getProtection, __traits(getMember, t, "vd")) == "public");
|
||||
static assert(__traits(getProtection, __traits(getMember, t, "ve")) == "export");
|
||||
static assert(__traits(getProtection, __traits(getMember, t, "fa")) == "private");
|
||||
static assert(__traits(getProtection, __traits(getMember, t, "fb")) == "package");
|
||||
static assert(__traits(getProtection, __traits(getMember, t, "fc")) == "protected");
|
||||
static assert(__traits(getProtection, __traits(getMember, t, "fd")) == "public");
|
||||
static assert(__traits(getProtection, __traits(getMember, t, "fe")) == "export");
|
||||
static assert(__traits(getVisibility, __traits(getMember, t, "va")) == "private");
|
||||
static assert(__traits(getVisibility, __traits(getMember, t, "vb")) == "package");
|
||||
static assert(__traits(getVisibility, __traits(getMember, t, "vc")) == "protected");
|
||||
static assert(__traits(getVisibility, __traits(getMember, t, "vd")) == "public");
|
||||
static assert(__traits(getVisibility, __traits(getMember, t, "ve")) == "export");
|
||||
static assert(__traits(getVisibility, __traits(getMember, t, "fa")) == "private");
|
||||
static assert(__traits(getVisibility, __traits(getMember, t, "fb")) == "package");
|
||||
static assert(__traits(getVisibility, __traits(getMember, t, "fc")) == "protected");
|
||||
static assert(__traits(getVisibility, __traits(getMember, t, "fd")) == "public");
|
||||
static assert(__traits(getVisibility, __traits(getMember, t, "fe")) == "export");
|
||||
}
|
||||
|
||||
/********************************************************/
|
||||
|
@ -947,47 +948,47 @@ void test9546()
|
|||
import imports.a9546 : S;
|
||||
|
||||
S s;
|
||||
static assert(__traits(getProtection, s.privA) == "private");
|
||||
static assert(__traits(getProtection, s.protA) == "protected");
|
||||
static assert(__traits(getProtection, s.packA) == "package");
|
||||
static assert(__traits(getProtection, S.privA) == "private");
|
||||
static assert(__traits(getProtection, S.protA) == "protected");
|
||||
static assert(__traits(getProtection, S.packA) == "package");
|
||||
static assert(__traits(getVisibility, s.privA) == "private");
|
||||
static assert(__traits(getVisibility, s.protA) == "protected");
|
||||
static assert(__traits(getVisibility, s.packA) == "package");
|
||||
static assert(__traits(getVisibility, S.privA) == "private");
|
||||
static assert(__traits(getVisibility, S.protA) == "protected");
|
||||
static assert(__traits(getVisibility, S.packA) == "package");
|
||||
|
||||
static assert(__traits(getProtection, mixin("s.privA")) == "private");
|
||||
static assert(__traits(getProtection, mixin("s.protA")) == "protected");
|
||||
static assert(__traits(getProtection, mixin("s.packA")) == "package");
|
||||
static assert(__traits(getProtection, mixin("S.privA")) == "private");
|
||||
static assert(__traits(getProtection, mixin("S.protA")) == "protected");
|
||||
static assert(__traits(getProtection, mixin("S.packA")) == "package");
|
||||
static assert(__traits(getVisibility, mixin("s.privA")) == "private");
|
||||
static assert(__traits(getVisibility, mixin("s.protA")) == "protected");
|
||||
static assert(__traits(getVisibility, mixin("s.packA")) == "package");
|
||||
static assert(__traits(getVisibility, mixin("S.privA")) == "private");
|
||||
static assert(__traits(getVisibility, mixin("S.protA")) == "protected");
|
||||
static assert(__traits(getVisibility, mixin("S.packA")) == "package");
|
||||
|
||||
static assert(__traits(getProtection, __traits(getMember, s, "privA")) == "private");
|
||||
static assert(__traits(getProtection, __traits(getMember, s, "protA")) == "protected");
|
||||
static assert(__traits(getProtection, __traits(getMember, s, "packA")) == "package");
|
||||
static assert(__traits(getProtection, __traits(getMember, S, "privA")) == "private");
|
||||
static assert(__traits(getProtection, __traits(getMember, S, "protA")) == "protected");
|
||||
static assert(__traits(getProtection, __traits(getMember, S, "packA")) == "package");
|
||||
static assert(__traits(getVisibility, __traits(getMember, s, "privA")) == "private");
|
||||
static assert(__traits(getVisibility, __traits(getMember, s, "protA")) == "protected");
|
||||
static assert(__traits(getVisibility, __traits(getMember, s, "packA")) == "package");
|
||||
static assert(__traits(getVisibility, __traits(getMember, S, "privA")) == "private");
|
||||
static assert(__traits(getVisibility, __traits(getMember, S, "protA")) == "protected");
|
||||
static assert(__traits(getVisibility, __traits(getMember, S, "packA")) == "package");
|
||||
|
||||
static assert(__traits(getProtection, s.privF) == "private");
|
||||
static assert(__traits(getProtection, s.protF) == "protected");
|
||||
static assert(__traits(getProtection, s.packF) == "package");
|
||||
static assert(__traits(getProtection, S.privF) == "private");
|
||||
static assert(__traits(getProtection, S.protF) == "protected");
|
||||
static assert(__traits(getProtection, S.packF) == "package");
|
||||
static assert(__traits(getVisibility, s.privF) == "private");
|
||||
static assert(__traits(getVisibility, s.protF) == "protected");
|
||||
static assert(__traits(getVisibility, s.packF) == "package");
|
||||
static assert(__traits(getVisibility, S.privF) == "private");
|
||||
static assert(__traits(getVisibility, S.protF) == "protected");
|
||||
static assert(__traits(getVisibility, S.packF) == "package");
|
||||
|
||||
static assert(__traits(getProtection, mixin("s.privF")) == "private");
|
||||
static assert(__traits(getProtection, mixin("s.protF")) == "protected");
|
||||
static assert(__traits(getProtection, mixin("s.packF")) == "package");
|
||||
static assert(__traits(getProtection, mixin("S.privF")) == "private");
|
||||
static assert(__traits(getProtection, mixin("S.protF")) == "protected");
|
||||
static assert(__traits(getProtection, mixin("S.packF")) == "package");
|
||||
static assert(__traits(getVisibility, mixin("s.privF")) == "private");
|
||||
static assert(__traits(getVisibility, mixin("s.protF")) == "protected");
|
||||
static assert(__traits(getVisibility, mixin("s.packF")) == "package");
|
||||
static assert(__traits(getVisibility, mixin("S.privF")) == "private");
|
||||
static assert(__traits(getVisibility, mixin("S.protF")) == "protected");
|
||||
static assert(__traits(getVisibility, mixin("S.packF")) == "package");
|
||||
|
||||
static assert(__traits(getProtection, __traits(getMember, s, "privF")) == "private");
|
||||
static assert(__traits(getProtection, __traits(getMember, s, "protF")) == "protected");
|
||||
static assert(__traits(getProtection, __traits(getMember, s, "packF")) == "package");
|
||||
static assert(__traits(getProtection, __traits(getMember, S, "privF")) == "private");
|
||||
static assert(__traits(getProtection, __traits(getMember, S, "protF")) == "protected");
|
||||
static assert(__traits(getProtection, __traits(getMember, S, "packF")) == "package");
|
||||
static assert(__traits(getVisibility, __traits(getMember, s, "privF")) == "private");
|
||||
static assert(__traits(getVisibility, __traits(getMember, s, "protF")) == "protected");
|
||||
static assert(__traits(getVisibility, __traits(getMember, s, "packF")) == "package");
|
||||
static assert(__traits(getVisibility, __traits(getMember, S, "privF")) == "private");
|
||||
static assert(__traits(getVisibility, __traits(getMember, S, "protF")) == "protected");
|
||||
static assert(__traits(getVisibility, __traits(getMember, S, "packF")) == "package");
|
||||
}
|
||||
|
||||
/********************************************************/
|
||||
|
@ -1547,6 +1548,19 @@ void async(ARGS...)(ARGS)
|
|||
|
||||
alias test17495 = async!(int, int);
|
||||
|
||||
/********************************************************/
|
||||
// 15094
|
||||
|
||||
void test15094()
|
||||
{
|
||||
static struct Foo { int i; }
|
||||
static struct Bar { Foo foo; }
|
||||
|
||||
Bar bar;
|
||||
auto n = __traits(getMember, bar.foo, "i");
|
||||
assert(n == bar.foo.i);
|
||||
}
|
||||
|
||||
/********************************************************/
|
||||
// https://issues.dlang.org/show_bug.cgi?id=10100
|
||||
|
||||
|
@ -1564,6 +1578,15 @@ static assert(
|
|||
|
||||
/********************************************************/
|
||||
|
||||
void testIsDisabled()
|
||||
{
|
||||
static assert(__traits(isDisabled, D1.true_));
|
||||
static assert(!__traits(isDisabled, D1.false_));
|
||||
static assert(!__traits(isDisabled, D1));
|
||||
}
|
||||
|
||||
/********************************************************/
|
||||
|
||||
int main()
|
||||
{
|
||||
test1();
|
||||
|
@ -1603,6 +1626,7 @@ int main()
|
|||
test_getFunctionAttributes();
|
||||
test_isOverrideFunction();
|
||||
test12237();
|
||||
test15094();
|
||||
|
||||
writeln("Success");
|
||||
return 0;
|
||||
|
|
122
gcc/testsuite/gdc.test/runnable/traits_child.d
Normal file
122
gcc/testsuite/gdc.test/runnable/traits_child.d
Normal file
|
@ -0,0 +1,122 @@
|
|||
struct A
|
||||
{
|
||||
ulong i;
|
||||
void foo(ulong a)
|
||||
{
|
||||
i = a;
|
||||
}
|
||||
|
||||
void foo(string s)
|
||||
{
|
||||
i = s.length;
|
||||
}
|
||||
|
||||
void bar(T)(T a)
|
||||
{
|
||||
i = a;
|
||||
}
|
||||
|
||||
void bar(T : string)(T s)
|
||||
{
|
||||
i = s.length;
|
||||
}
|
||||
}
|
||||
|
||||
alias ai = A.i;
|
||||
alias afoo = A.foo;
|
||||
alias abar = A.bar;
|
||||
alias abar_ulong = A.bar!ulong;
|
||||
alias abar_string = A.bar!string;
|
||||
|
||||
struct B
|
||||
{
|
||||
A a;
|
||||
}
|
||||
|
||||
alias ba = B.a;
|
||||
|
||||
template T(alias x)
|
||||
{
|
||||
void set(int n)
|
||||
{
|
||||
x = n;
|
||||
}
|
||||
}
|
||||
|
||||
mixin template M(alias x)
|
||||
{
|
||||
void set(int n)
|
||||
{
|
||||
x = n;
|
||||
}
|
||||
}
|
||||
|
||||
struct C
|
||||
{
|
||||
int i;
|
||||
alias t = T!i;
|
||||
mixin M!i m;
|
||||
}
|
||||
|
||||
alias ct = C.t;
|
||||
alias ctset = C.t.set;
|
||||
alias cm = C.m;
|
||||
alias cmset = C.m.set;
|
||||
|
||||
|
||||
// adapted from http://thecybershadow.net/d/dconf2017/#/21
|
||||
struct S { string a, b, c; }
|
||||
|
||||
static string printField(alias field)()
|
||||
{
|
||||
S s = { a: "aa", b: "bb", c: "cc" };
|
||||
return __traits(child, s, field);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
auto f = printField!(S.b)();
|
||||
assert(f == "bb");
|
||||
|
||||
A a;
|
||||
__traits(child, a, ai) = 3;
|
||||
assert(a.i == 3);
|
||||
assert(__traits(child, a, ai) == 3);
|
||||
__traits(child, a, afoo)(2);
|
||||
assert(a.i == 2);
|
||||
__traits(child, a, afoo)("hello");
|
||||
assert(a.i == 5);
|
||||
__traits(child, a, abar)(6);
|
||||
assert(a.i == 6);
|
||||
__traits(child, a, abar_ulong)(7);
|
||||
assert(a.i == 7);
|
||||
__traits(child, a, abar_string)("hi");
|
||||
assert(a.i == 2);
|
||||
|
||||
__traits(child, a, A.i) = 7;
|
||||
assert(a.i == 7);
|
||||
__traits(child, a, A.bar)(3);
|
||||
assert(a.i == 3);
|
||||
__traits(child, a, A.bar!ulong)(4);
|
||||
assert(a.i == 4);
|
||||
__traits(child, a, __traits(getMember, A, "i")) = 5;
|
||||
assert(a.i == 5);
|
||||
__traits(child, a, __traits(getOverloads, A, "bar", true)[1])("hi!");
|
||||
assert(a.i == 3);
|
||||
|
||||
B b;
|
||||
__traits(child, b.a, ai) = 2;
|
||||
assert(b.a.i == 2);
|
||||
__traits(child, __traits(child, b, ba), ai) = 3;
|
||||
assert(b.a.i == 3);
|
||||
|
||||
C c;
|
||||
__traits(child, c, ct).set(3);
|
||||
assert(c.i == 3);
|
||||
__traits(child, c, ctset)(4);
|
||||
assert(c.i == 4);
|
||||
__traits(child, c, cm).set(5);
|
||||
assert(c.i == 5);
|
||||
__traits(child, c, cmset)(6);
|
||||
assert(c.i == 6);
|
||||
}
|
Loading…
Add table
Reference in a new issue