d: Merge upstream dmd 60bfa0ee7, druntime 94bd5bcb, phobos 3a1cd9a01.
D front-end changes: - Import dmd v2.100.0. - Add bit fields to D, enabled via the -fpreview=bitfields switch. - Removed the -ftransition=markdown and -frevert=markdown switches. - Added new trait `__traits(classInstanceAlignment)' to provide the required data alignment for classes. - The check for `pragma(crt_constructor)' and `pragma(crt_destructor)' linkage has been relaxed to allow all `void()' signatures. - ImportC parser now recognizes the `typeof(...)' operator. D runtime changes: - Import druntime v2.100.0. Phobos changes: - Import phobos v2.100.0. - To comply with dip1000, `std.socket.Socket` methods now accept only `scope' arrays. - The `fill', `alignSize', `align2', and `align4' methods of `std.outbuffer.OutBuffer' have been extended to allow specifying a custom value when pre-filling or padding the buffer. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 60bfa0ee7. * dmd/VERSION: Update version to v2.100.0. * d-builtins.cc (d_init_versions): Update for new front-end interface. * d-codegen.cc (d_decl_context): Use resolvedLinkage to get declaration linkage. (build_struct_literal): Track offset in bits. * d-gimplify.cc (d_gimplify_modify_expr): Check both operands for a bit-field reference. * d-lang.cc (d_handle_option): Handle -fpreview=bitfields, remove -frevert=markdown and -ftransition=vmarkdown. (d_post_options): Set flag_rtti and flag_exceptions if -fno-druntime was seen on command-line. (d_parse_file): Update for new front-end interface. (d_type_promotes_to): Use resolvedLinkage to get declaration linkage. * decl.cc (make_thunk): Likewise. * expr.cc (ExprVisitor::visit (CatAssignExp *)): Remove lowering for appending of an element or array to another array. * lang.opt (fpreview=bitfields): New option. (frevert=markdown): Remove. (ftransition=vmarkdown): Remove. * types.cc (layout_aggregate_members): Ignore anonymous fields in total count. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 94bd5bcb. * libdruntime/Makefile.am (ALL_DRUNTIME_INSTALL_DSOURCES): Add $(DRUNTIME_DSOURCES_ELF). (ALL_DRUNTIME_SOURCES): Likewise. (DRUNTIME_DSOURCES_ELF): New variable. * libdruntime/Makefile.in: Regenerate. * src/MERGE: Merge upstream phobos 3a1cd9a01. * testsuite/libphobos.init_fini/custom_gc.d: Update test.
This commit is contained in:
parent
682e587f10
commit
5eb9927aae
229 changed files with 6602 additions and 9383 deletions
|
@ -475,7 +475,7 @@ d_init_versions (void)
|
|||
if (flag_pie)
|
||||
VersionCondition::addPredefinedGlobalIdent ("D_PIE");
|
||||
|
||||
if (global.params.doDocComments)
|
||||
if (global.params.ddoc.doOutput)
|
||||
VersionCondition::addPredefinedGlobalIdent ("D_Ddoc");
|
||||
|
||||
if (global.params.useUnitTests)
|
||||
|
|
|
@ -76,7 +76,7 @@ d_decl_context (Dsymbol *dsym)
|
|||
but only for extern(D) symbols. */
|
||||
if (parent->isModule ())
|
||||
{
|
||||
if ((decl != NULL && decl->linkage != LINK::d)
|
||||
if ((decl != NULL && decl->resolvedLinkage () != LINK::d)
|
||||
|| (ad != NULL && ad->classKind != ClassKind::d))
|
||||
return NULL_TREE;
|
||||
|
||||
|
@ -1165,7 +1165,7 @@ build_struct_literal (tree type, vec <constructor_elt, va_gc> *init)
|
|||
}
|
||||
|
||||
vec <constructor_elt, va_gc> *ve = NULL;
|
||||
HOST_WIDE_INT offset = 0;
|
||||
HOST_WIDE_INT bitoffset = 0;
|
||||
bool constant_p = true;
|
||||
bool finished = false;
|
||||
|
||||
|
@ -1210,11 +1210,11 @@ build_struct_literal (tree type, vec <constructor_elt, va_gc> *init)
|
|||
|
||||
if (is_initialized)
|
||||
{
|
||||
HOST_WIDE_INT fieldpos = int_byte_position (field);
|
||||
HOST_WIDE_INT fieldpos = int_bit_position (field);
|
||||
gcc_assert (value != NULL_TREE);
|
||||
|
||||
/* Must not initialize fields that overlap. */
|
||||
if (fieldpos < offset)
|
||||
if (fieldpos < bitoffset)
|
||||
{
|
||||
/* Find the nearest user defined type and field. */
|
||||
tree vtype = type;
|
||||
|
@ -1243,12 +1243,9 @@ build_struct_literal (tree type, vec <constructor_elt, va_gc> *init)
|
|||
finished = true;
|
||||
}
|
||||
|
||||
/* Move offset to the next position in the struct. */
|
||||
if (TREE_CODE (type) == RECORD_TYPE)
|
||||
{
|
||||
offset = int_byte_position (field)
|
||||
+ int_size_in_bytes (TREE_TYPE (field));
|
||||
}
|
||||
/* Move bit offset to the next position in the struct. */
|
||||
if (TREE_CODE (type) == RECORD_TYPE && DECL_SIZE (field))
|
||||
bitoffset = int_bit_position (field) + tree_to_shwi (DECL_SIZE (field));
|
||||
|
||||
/* If all initializers have been assigned, there's nothing else to do. */
|
||||
if (vec_safe_is_empty (init))
|
||||
|
|
|
@ -109,7 +109,8 @@ d_gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
|
|||
}
|
||||
|
||||
/* Same as above, but for bit-field assignments. */
|
||||
if (bit_field_ref (op0) && TREE_TYPE (op0) != TREE_TYPE (op1))
|
||||
if ((bit_field_ref (op0) || bit_field_ref (op1))
|
||||
&& TREE_TYPE (op0) != TREE_TYPE (op1))
|
||||
{
|
||||
TREE_OPERAND (*expr_p, 1) = convert (TREE_TYPE (op0), op1);
|
||||
return GS_OK;
|
||||
|
|
104
gcc/d/d-lang.cc
104
gcc/d/d-lang.cc
|
@ -478,21 +478,21 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
|
|||
break;
|
||||
|
||||
case OPT_fdoc:
|
||||
global.params.doDocComments = value;
|
||||
global.params.ddoc.doOutput = value;
|
||||
break;
|
||||
|
||||
case OPT_fdoc_dir_:
|
||||
global.params.doDocComments = true;
|
||||
global.params.docdir = arg;
|
||||
global.params.ddoc.doOutput = true;
|
||||
global.params.ddoc.dir = arg;
|
||||
break;
|
||||
|
||||
case OPT_fdoc_file_:
|
||||
global.params.doDocComments = true;
|
||||
global.params.docname = arg;
|
||||
global.params.ddoc.doOutput = true;
|
||||
global.params.ddoc.name = arg;
|
||||
break;
|
||||
|
||||
case OPT_fdoc_inc_:
|
||||
global.params.ddocfiles.push (arg);
|
||||
global.params.ddoc.files.push (arg);
|
||||
break;
|
||||
|
||||
case OPT_fdruntime:
|
||||
|
@ -500,13 +500,12 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
|
|||
break;
|
||||
|
||||
case OPT_fdump_c___spec_:
|
||||
if (global.params.doCxxHdrGeneration == CxxHeaderMode::none)
|
||||
global.params.doCxxHdrGeneration = CxxHeaderMode::silent;
|
||||
global.params.cxxhdrname = arg;
|
||||
global.params.cxxhdr.doOutput = true;
|
||||
global.params.cxxhdr.name = arg;
|
||||
break;
|
||||
|
||||
case OPT_fdump_c___spec_verbose:
|
||||
global.params.doCxxHdrGeneration = CxxHeaderMode::verbose;
|
||||
global.params.cxxhdr.fullOutput = true;
|
||||
break;
|
||||
|
||||
case OPT_fdump_d_original:
|
||||
|
@ -572,18 +571,22 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
|
|||
global.params.useDIP25 = FeatureState::enabled;
|
||||
global.params.useDIP1000 = FeatureState::enabled;
|
||||
global.params.useDIP1021 = value;
|
||||
global.params.bitfields = value;
|
||||
global.params.dtorFields = FeatureState::enabled;
|
||||
global.params.fieldwise = value;
|
||||
global.params.fixAliasThis = value;
|
||||
global.params.previewIn = value;
|
||||
global.params.fix16997 = value;
|
||||
global.params.markdown = value;
|
||||
global.params.noSharedAccess = value;
|
||||
global.params.rvalueRefParam = FeatureState::enabled;
|
||||
global.params.inclusiveInContracts = value;
|
||||
global.params.shortenedMethods = value;
|
||||
break;
|
||||
|
||||
case OPT_fpreview_bitfields:
|
||||
global.params.bitfields = value;
|
||||
break;
|
||||
|
||||
case OPT_fpreview_dip1000:
|
||||
global.params.useDIP1000 = FeatureState::enabled;
|
||||
break;
|
||||
|
@ -641,7 +644,6 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
|
|||
global.params.useDIP25 = FeatureState::disabled;
|
||||
global.params.dtorFields = FeatureState::disabled;
|
||||
global.params.fix16997 = !value;
|
||||
global.params.markdown = !value;
|
||||
break;
|
||||
|
||||
case OPT_frevert_dip1000:
|
||||
|
@ -660,17 +662,14 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
|
|||
global.params.fix16997 = !value;
|
||||
break;
|
||||
|
||||
case OPT_frevert_markdown:
|
||||
global.params.markdown = !value;
|
||||
break;
|
||||
|
||||
case OPT_frtti:
|
||||
global.params.useTypeInfo = value;
|
||||
break;
|
||||
|
||||
case OPT_fsave_mixins_:
|
||||
global.params.mixinFile = arg;
|
||||
global.params.mixinOut = d_gc_malloc<OutBuffer> ();
|
||||
global.params.mixinOut.doOutput = true;
|
||||
global.params.mixinOut.name = arg;
|
||||
global.params.mixinOut.buffer = d_gc_malloc<OutBuffer> ();
|
||||
break;
|
||||
|
||||
case OPT_fswitch_errors:
|
||||
|
@ -681,7 +680,6 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
|
|||
global.params.vfield = value;
|
||||
global.params.vgc = value;
|
||||
global.params.vin = value;
|
||||
global.params.vmarkdown= value;
|
||||
global.params.vtls = value;
|
||||
break;
|
||||
|
||||
|
@ -697,10 +695,6 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
|
|||
global.params.vgc = value;
|
||||
break;
|
||||
|
||||
case OPT_ftransition_vmarkdown:
|
||||
global.params.vmarkdown = value;
|
||||
break;
|
||||
|
||||
case OPT_ftransition_templates:
|
||||
global.params.vtemplates = value;
|
||||
break;
|
||||
|
@ -736,17 +730,17 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
|
|||
break;
|
||||
|
||||
case OPT_H:
|
||||
global.params.doHdrGeneration = true;
|
||||
global.params.dihdr.doOutput = true;
|
||||
break;
|
||||
|
||||
case OPT_Hd:
|
||||
global.params.doHdrGeneration = true;
|
||||
global.params.hdrdir = arg;
|
||||
global.params.dihdr.doOutput = true;
|
||||
global.params.dihdr.dir = arg;
|
||||
break;
|
||||
|
||||
case OPT_Hf:
|
||||
global.params.doHdrGeneration = true;
|
||||
global.params.hdrname = arg;
|
||||
global.params.dihdr.doOutput = true;
|
||||
global.params.dihdr.name = arg;
|
||||
break;
|
||||
|
||||
case OPT_imultilib:
|
||||
|
@ -827,11 +821,11 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
|
|||
break;
|
||||
|
||||
case OPT_Xf:
|
||||
global.params.jsonfilename = arg;
|
||||
global.params.json.name = arg;
|
||||
/* Fall through. */
|
||||
|
||||
case OPT_X:
|
||||
global.params.doJsonGeneration = true;
|
||||
global.params.json.doOutput = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -904,16 +898,26 @@ d_post_options (const char ** fn)
|
|||
? CHECKENABLEoff : CHECKENABLEon;
|
||||
}
|
||||
|
||||
/* When not linking against D runtime, turn off all code generation that
|
||||
would otherwise reference it. */
|
||||
if (global.params.betterC)
|
||||
{
|
||||
if (!OPTION_SET_P (flag_moduleinfo))
|
||||
global.params.useModuleInfo = false;
|
||||
|
||||
/* Ensure that the front-end options are in sync with the `-frtti' and
|
||||
`-fexceptions' flags. */
|
||||
if (!OPTION_SET_P (flag_rtti))
|
||||
global.params.useTypeInfo = false;
|
||||
{
|
||||
global.params.useTypeInfo = false;
|
||||
flag_rtti = false;
|
||||
}
|
||||
|
||||
if (!OPTION_SET_P (flag_exceptions))
|
||||
global.params.useExceptions = false;
|
||||
{
|
||||
global.params.useExceptions = false;
|
||||
flag_exceptions = false;
|
||||
}
|
||||
|
||||
global.params.checkAction = CHECKACTION_C;
|
||||
}
|
||||
|
@ -947,19 +951,15 @@ d_post_options (const char ** fn)
|
|||
if (flag_excess_precision == EXCESS_PRECISION_DEFAULT)
|
||||
flag_excess_precision = EXCESS_PRECISION_STANDARD;
|
||||
|
||||
global.params.symdebug = write_symbols != NO_DEBUG;
|
||||
global.params.useInline = flag_inline_functions;
|
||||
global.params.showColumns = flag_show_column;
|
||||
global.params.printErrorContext = flag_diagnostics_show_caret;
|
||||
|
||||
if (global.params.useInline)
|
||||
global.params.hdrStripPlainFunctions = false;
|
||||
global.params.dihdr.fullOutput = true;
|
||||
|
||||
global.params.obj = !flag_syntax_only;
|
||||
|
||||
/* Has no effect yet. */
|
||||
global.params.pic = flag_pic != 0;
|
||||
|
||||
/* Add in versions given on the command line. */
|
||||
if (global.params.versionids)
|
||||
{
|
||||
|
@ -1068,8 +1068,8 @@ d_parse_file (void)
|
|||
/* Handling stdin, generate a unique name for the module. */
|
||||
Module *m = Module::create (in_fnames[i],
|
||||
Identifier::idPool ("__stdin"),
|
||||
global.params.doDocComments,
|
||||
global.params.doHdrGeneration);
|
||||
global.params.ddoc.doOutput,
|
||||
global.params.dihdr.doOutput);
|
||||
modules.push (m);
|
||||
|
||||
/* Overwrite the source file for the module, the one created by
|
||||
|
@ -1084,8 +1084,8 @@ d_parse_file (void)
|
|||
const char *name = FileName::removeExt (basename);
|
||||
|
||||
Module *m = Module::create (in_fnames[i], Identifier::idPool (name),
|
||||
global.params.doDocComments,
|
||||
global.params.doHdrGeneration);
|
||||
global.params.ddoc.doOutput,
|
||||
global.params.dihdr.doOutput);
|
||||
modules.push (m);
|
||||
FileName::free (name);
|
||||
}
|
||||
|
@ -1142,7 +1142,7 @@ d_parse_file (void)
|
|||
if (global.errors)
|
||||
goto had_errors;
|
||||
|
||||
if (global.params.doHdrGeneration)
|
||||
if (global.params.dihdr.doOutput)
|
||||
{
|
||||
/* Generate 'header' import files. Since 'header' import files must be
|
||||
independent of command line switches and what else is imported, they
|
||||
|
@ -1316,12 +1316,12 @@ d_parse_file (void)
|
|||
printTemplateStats ();
|
||||
|
||||
/* Generate JSON files. */
|
||||
if (global.params.doJsonGeneration)
|
||||
if (global.params.json.doOutput)
|
||||
{
|
||||
OutBuffer buf;
|
||||
json_generate (&buf, &modules);
|
||||
|
||||
const char *name = global.params.jsonfilename.ptr;
|
||||
const char *name = global.params.json.name.ptr;
|
||||
FILE *json_stream;
|
||||
|
||||
if (name && (name[0] != '-' || name[1] != '\0'))
|
||||
|
@ -1346,7 +1346,7 @@ d_parse_file (void)
|
|||
}
|
||||
|
||||
/* Generate Ddoc files. */
|
||||
if (global.params.doDocComments && !global.errors && !errorcount)
|
||||
if (global.params.ddoc.doOutput && !global.errors && !errorcount)
|
||||
{
|
||||
for (size_t i = 0; i < modules.length; i++)
|
||||
{
|
||||
|
@ -1370,7 +1370,7 @@ d_parse_file (void)
|
|||
}
|
||||
|
||||
/* Generate C++ header files. */
|
||||
if (global.params.doCxxHdrGeneration != CxxHeaderMode::none)
|
||||
if (global.params.cxxhdr.doOutput)
|
||||
genCppHdrFiles (modules);
|
||||
|
||||
if (global.errors)
|
||||
|
@ -1403,23 +1403,23 @@ d_parse_file (void)
|
|||
errorcount += (global.errors + global.warnings);
|
||||
|
||||
/* We want to write the mixin expansion file also on error. */
|
||||
if (global.params.mixinOut)
|
||||
if (global.params.mixinOut.doOutput)
|
||||
{
|
||||
FILE *mixin_stream = fopen (global.params.mixinFile, "w");
|
||||
FILE *mixin_stream = fopen (global.params.mixinOut.name.ptr, "w");
|
||||
|
||||
if (mixin_stream)
|
||||
{
|
||||
OutBuffer *buf = global.params.mixinOut;
|
||||
OutBuffer *buf = global.params.mixinOut.buffer;
|
||||
fprintf (mixin_stream, "%s", buf->peekChars ());
|
||||
|
||||
if (ferror (mixin_stream) || fclose (mixin_stream))
|
||||
fatal_error (input_location, "closing mixin file %s: %m",
|
||||
global.params.mixinFile);
|
||||
global.params.mixinOut.name.ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
fatal_error (input_location, "opening mixin file %s: %m",
|
||||
global.params.mixinFile);
|
||||
global.params.mixinOut.name.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1558,7 +1558,7 @@ d_type_promotes_to (tree type)
|
|||
/* Promotions are only applied on unnamed function arguments for declarations
|
||||
with `extern(C)' or `extern(C++)' linkage. */
|
||||
if (cfun && DECL_LANG_FRONTEND (cfun->decl)
|
||||
&& DECL_LANG_FRONTEND (cfun->decl)->linkage != LINK::d)
|
||||
&& DECL_LANG_FRONTEND (cfun->decl)->resolvedLinkage () != LINK::d)
|
||||
{
|
||||
/* In [type/integer-promotions], integer promotions are conversions of the
|
||||
following types:
|
||||
|
|
|
@ -1845,7 +1845,7 @@ make_thunk (FuncDeclaration *decl, int offset)
|
|||
forcing a D local thunk to be emitted. */
|
||||
const char *ident;
|
||||
|
||||
if (decl->linkage == LINK::cpp)
|
||||
if (decl->resolvedLinkage () == LINK::cpp)
|
||||
ident = target.cpp.thunkMangle (decl, offset);
|
||||
else
|
||||
{
|
||||
|
@ -1862,7 +1862,7 @@ make_thunk (FuncDeclaration *decl, int offset)
|
|||
|
||||
d_keep (thunk);
|
||||
|
||||
if (decl->linkage != LINK::cpp)
|
||||
if (decl->resolvedLinkage () != LINK::cpp)
|
||||
free (CONST_CAST (char *, ident));
|
||||
|
||||
if (!DECL_EXTERNAL (function))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
313d28b3db7523e67880ae3baf8ef28ce9abe9bd
|
||||
a6c5224b2d6b61fa3856aa8a3369581f7c949b68
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the dlang/dmd repository.
|
||||
|
|
|
@ -164,20 +164,21 @@ Note that these groups have no strict meaning, the category assignments are a bi
|
|||
|
||||
**Other**
|
||||
|
||||
| File | Purpose |
|
||||
|-------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|
|
||||
| [aliasthis.d](https://github.com/dlang/dmd/blob/master/src/dmd/aliasthis.d) | Resolve implicit conversions for `alias X this` |
|
||||
| [traits.d](https://github.com/dlang/dmd/blob/master/src/dmd/traits.d) | `__traits()` |
|
||||
| [lambdacomp.d](https://github.com/dlang/dmd/blob/master/src/dmd/lambdacomp.d) | `__traits(isSame, x => y, z => w)` |
|
||||
| [cond.d](https://github.com/dlang/dmd/blob/master/src/dmd/cond.d) | Evaluate `static if`, `version` `debug ` |
|
||||
| [staticcond.d](https://github.com/dlang/dmd/blob/master/src/dmd/staticcond.d) | Lazily evaluate static conditions for `static if`, `static assert` and template constraints |
|
||||
| [delegatize.d](https://github.com/dlang/dmd/blob/master/src/dmd/delegatize.d) | Converts expression to delegates for `lazy` parameters |
|
||||
| [eh.d](https://github.com/dlang/dmd/blob/master/src/dmd/eh.d) | Generate tables for exception handling |
|
||||
| [nspace.d](https://github.com/dlang/dmd/blob/master/src/dmd/nspace.d) | Namespace for `extern (C++, Module)` |
|
||||
| [intrange.d](https://github.com/dlang/dmd/blob/master/src/dmd/intrange.d) | [Value range propagation](https://digitalmars.com/articles/b62.html) |
|
||||
| [dimport.d](https://github.com/dlang/dmd/blob/master/src/dmd/dimport.d) | Renamed imports (`import aliasSymbol = pkg1.pkg2.symbol`) |
|
||||
| [arrayop.d](https://github.com/dlang/dmd/blob/master/src/dmd/arrayop.d) | Array operations (`a[] = b[] + c[]`) |
|
||||
| [typinf.d](https://github.com/dlang/dmd/blob/master/src/dmd/typinf.d) | Generate typeinfo for `typeid()` (as well as internals) |
|
||||
| File | Purpose |
|
||||
|--------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|
|
||||
| [aliasthis.d](https://github.com/dlang/dmd/blob/master/src/dmd/aliasthis.d) | Resolve implicit conversions for `alias X this` |
|
||||
| [traits.d](https://github.com/dlang/dmd/blob/master/src/dmd/traits.d) | `__traits()` |
|
||||
| [lambdacomp.d](https://github.com/dlang/dmd/blob/master/src/dmd/lambdacomp.d) | `__traits(isSame, x => y, z => w)` |
|
||||
| [cond.d](https://github.com/dlang/dmd/blob/master/src/dmd/cond.d) | Evaluate `static if`, `version` `debug ` |
|
||||
| [staticcond.d](https://github.com/dlang/dmd/blob/master/src/dmd/staticcond.d) | Lazily evaluate static conditions for `static if`, `static assert` and template constraints |
|
||||
| [delegatize.d](https://github.com/dlang/dmd/blob/master/src/dmd/delegatize.d) | Converts expression to delegates for `lazy` parameters |
|
||||
| [eh.d](https://github.com/dlang/dmd/blob/master/src/dmd/eh.d) | Generate tables for exception handling |
|
||||
| [nspace.d](https://github.com/dlang/dmd/blob/master/src/dmd/nspace.d) | Namespace for `extern (C++, Module)` |
|
||||
| [intrange.d](https://github.com/dlang/dmd/blob/master/src/dmd/intrange.d) | [Value range propagation](https://digitalmars.com/articles/b62.html) |
|
||||
| [dimport.d](https://github.com/dlang/dmd/blob/master/src/dmd/dimport.d) | Renamed imports (`import aliasSymbol = pkg1.pkg2.symbol`) |
|
||||
| [arrayop.d](https://github.com/dlang/dmd/blob/master/src/dmd/arrayop.d) | Array operations (`a[] = b[] + c[]`) |
|
||||
| [cpreprocess.d](https://github.com/dlang/dmd/blob/master/src/dmd/cpreprocess.d)| Run the C preprocessor on C source files |
|
||||
| [typinf.d](https://github.com/dlang/dmd/blob/master/src/dmd/typinf.d) | Generate typeinfo for `typeid()` (as well as internals) |
|
||||
|
||||
| File | Purpose |
|
||||
|-----------------------------------------------------------------------------|------------------------------------------------------------------------------------|
|
||||
|
|
|
@ -1 +1 @@
|
|||
v2.100.0-beta.1
|
||||
v2.100.0
|
||||
|
|
|
@ -563,9 +563,12 @@ FuncDeclaration buildXopEquals(StructDeclaration sd, Scope* sc)
|
|||
e = new DotIdExp(sd.loc, e, Id.object);
|
||||
e = new DotIdExp(sd.loc, e, id);
|
||||
e = e.expressionSemantic(sc);
|
||||
Dsymbol s = getDsymbol(e);
|
||||
assert(s);
|
||||
sd.xerreq = s.isFuncDeclaration();
|
||||
if (!e.isErrorExp())
|
||||
{
|
||||
Dsymbol s = getDsymbol(e);
|
||||
assert(s);
|
||||
sd.xerreq = s.isFuncDeclaration();
|
||||
}
|
||||
}
|
||||
Loc declLoc; // loc is unnecessary so __xopEquals is never called directly
|
||||
Loc loc; // loc is unnecessary so errors are gagged
|
||||
|
@ -684,9 +687,12 @@ FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc)
|
|||
e = new DotIdExp(sd.loc, e, Id.object);
|
||||
e = new DotIdExp(sd.loc, e, id);
|
||||
e = e.expressionSemantic(sc);
|
||||
Dsymbol s = getDsymbol(e);
|
||||
assert(s);
|
||||
sd.xerrcmp = s.isFuncDeclaration();
|
||||
if (!e.isErrorExp())
|
||||
{
|
||||
Dsymbol s = getDsymbol(e);
|
||||
assert(s);
|
||||
sd.xerrcmp = s.isFuncDeclaration();
|
||||
}
|
||||
}
|
||||
Loc declLoc; // loc is unnecessary so __xopCmp is never called directly
|
||||
Loc loc; // loc is unnecessary so errors are gagged
|
||||
|
@ -867,7 +873,7 @@ void buildDtors(AggregateDeclaration ad, Scope* sc)
|
|||
|
||||
// Build the field destructor (`ad.fieldDtor`), if needed.
|
||||
// If the user dtor is an extern(C++) prototype, then we expect it performs a full-destruction and skip building.
|
||||
const bool dtorIsCppPrototype = ad.userDtors.dim && ad.userDtors[0].linkage == LINK.cpp && !ad.userDtors[0].fbody;
|
||||
const bool dtorIsCppPrototype = ad.userDtors.dim && ad.userDtors[0]._linkage == LINK.cpp && !ad.userDtors[0].fbody;
|
||||
if (!dtorIsCppPrototype)
|
||||
{
|
||||
Expression e = null;
|
||||
|
@ -1019,7 +1025,7 @@ void buildDtors(AggregateDeclaration ad, Scope* sc)
|
|||
|
||||
// Set/build `ad.dtor`.
|
||||
// On Windows, the dtor in the vtable is a shim with different signature.
|
||||
ad.dtor = (ad.aggrDtor && ad.aggrDtor.linkage == LINK.cpp && !target.cpp.twoDtorInVtable)
|
||||
ad.dtor = (ad.aggrDtor && ad.aggrDtor._linkage == LINK.cpp && !target.cpp.twoDtorInVtable)
|
||||
? buildWindowsCppDtor(ad, ad.aggrDtor, sc)
|
||||
: ad.aggrDtor;
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ if (__traits(isUnsigned, T))
|
|||
enum mask = "(1 << "~i.stringof~")";
|
||||
result ~= "
|
||||
/// set or get the corresponding "~structName~" member
|
||||
bool "~mem~"() const { return !!(bitFields & "~mask~"); }
|
||||
bool "~mem~"() const scope { return !!(bitFields & "~mask~"); }
|
||||
/// ditto
|
||||
bool "~mem~"(bool v)
|
||||
{
|
||||
|
|
|
@ -309,23 +309,24 @@ struct OutBuffer
|
|||
writenl();
|
||||
}
|
||||
|
||||
// Zero-terminated
|
||||
void writeString(const(char)* s) pure nothrow @trusted
|
||||
/** Write string to buffer, ensure it is zero terminated
|
||||
*/
|
||||
void writeStringz(const(char)* s) pure nothrow @trusted
|
||||
{
|
||||
write(s[0 .. strlen(s)+1]);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
void writeString(const(char)[] s) pure nothrow
|
||||
void writeStringz(const(char)[] s) pure nothrow
|
||||
{
|
||||
write(s);
|
||||
writeByte(0);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
void writeString(string s) pure nothrow
|
||||
void writeStringz(string s) pure nothrow
|
||||
{
|
||||
writeString(cast(const(char)[])(s));
|
||||
writeStringz(cast(const(char)[])(s));
|
||||
}
|
||||
|
||||
extern (C++) void prependstring(const(char)* string) pure nothrow
|
||||
|
|
|
@ -370,7 +370,7 @@ extern (C++) final class StaticForeach : RootObject
|
|||
Type ety = new TypeTypeof(aloc, wrapAndCall(aloc, new CompoundStatement(aloc, s1)));
|
||||
auto aty = ety.arrayOf();
|
||||
auto idres = Identifier.generateId("__res");
|
||||
auto vard = new VarDeclaration(aloc, aty, idres, null);
|
||||
auto vard = new VarDeclaration(aloc, aty, idres, null, STC.temp);
|
||||
auto s2 = new Statements();
|
||||
|
||||
// Run 'typeof' gagged to avoid duplicate errors and if it fails just create
|
||||
|
@ -984,9 +984,9 @@ bool findCondition(Identifiers* ids, Identifier ident) @safe nothrow pure
|
|||
// Helper for printing dependency information
|
||||
private void printDepsConditional(Scope* sc, DVCondition condition, const(char)[] depType)
|
||||
{
|
||||
if (!global.params.moduleDeps || global.params.moduleDepsFile)
|
||||
if (!global.params.moduleDeps.buffer || global.params.moduleDeps.name)
|
||||
return;
|
||||
OutBuffer* ob = global.params.moduleDeps;
|
||||
OutBuffer* ob = global.params.moduleDeps.buffer;
|
||||
Module imod = sc ? sc._module : condition.mod;
|
||||
if (!imod)
|
||||
return;
|
||||
|
|
|
@ -1181,7 +1181,7 @@ UnionExp Cast(const ref Loc loc, Type type, Type to, Expression e1)
|
|||
{
|
||||
if (type != Type.terror)
|
||||
{
|
||||
// have to change to Internal Compiler Error
|
||||
// have to change to internal compiler error
|
||||
// all invalid casts should be handled already in Expression::castTo().
|
||||
error(loc, "cannot cast `%s` to `%s`", e1.type.toChars(), type.toChars());
|
||||
}
|
||||
|
|
|
@ -284,6 +284,7 @@ final class CParser(AST) : Parser!AST
|
|||
case TOK.struct_:
|
||||
case TOK.union_:
|
||||
case TOK.enum_:
|
||||
case TOK.typeof_:
|
||||
|
||||
// storage-class-specifiers
|
||||
case TOK.typedef_:
|
||||
|
@ -1662,6 +1663,14 @@ final class CParser(AST) : Parser!AST
|
|||
return;
|
||||
}
|
||||
|
||||
if (!tspec)
|
||||
{
|
||||
error("no type for declarator before `%s`", token.toChars());
|
||||
panic();
|
||||
nextToken();
|
||||
return;
|
||||
}
|
||||
|
||||
if (tspec && specifier.mod & MOD.xconst)
|
||||
{
|
||||
tspec = toConst(tspec);
|
||||
|
@ -2287,6 +2296,52 @@ final class CParser(AST) : Parser!AST
|
|||
break;
|
||||
}
|
||||
|
||||
case TOK.typeof_:
|
||||
{
|
||||
nextToken();
|
||||
check(TOK.leftParenthesis);
|
||||
|
||||
auto tk = &token;
|
||||
AST.Expression e;
|
||||
if (isTypeName(tk))
|
||||
e = new AST.TypeExp(loc, cparseTypeName());
|
||||
else
|
||||
e = cparseExpression();
|
||||
t = new AST.TypeTypeof(loc, e);
|
||||
|
||||
if(token.value == TOK.rightParenthesis)
|
||||
nextToken();
|
||||
else
|
||||
{
|
||||
t = AST.Type.terror;
|
||||
error("`typeof` operator expects an expression or type name in parentheses");
|
||||
|
||||
// skipParens et. al expect to be on the opening parenthesis
|
||||
int parens;
|
||||
loop: while(1)
|
||||
{
|
||||
switch(token.value)
|
||||
{
|
||||
case TOK.leftParenthesis:
|
||||
parens++;
|
||||
break;
|
||||
case TOK.rightParenthesis:
|
||||
parens--;
|
||||
if(parens < 0)
|
||||
goto case;
|
||||
break;
|
||||
case TOK.endOfFile:
|
||||
break loop;
|
||||
default:
|
||||
}
|
||||
nextToken();
|
||||
}
|
||||
}
|
||||
|
||||
tkwx = TKW.xtag;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break Lwhile;
|
||||
}
|
||||
|
@ -2498,7 +2553,7 @@ final class CParser(AST) : Parser!AST
|
|||
private AST.Type cparseDeclarator(DTR declarator, AST.Type t,
|
||||
out Identifier pident, ref Specifier specifier)
|
||||
{
|
||||
//printf("cparseDeclarator(%d)\n", declarator);
|
||||
//printf("cparseDeclarator(%d, %p)\n", declarator, t);
|
||||
AST.Types constTypes; // all the Types that will need `const` applied to them
|
||||
constTypes.setDim(0);
|
||||
|
||||
|
@ -4227,6 +4282,7 @@ final class CParser(AST) : Parser!AST
|
|||
|
||||
// atomic-type-specifier
|
||||
case TOK._Atomic:
|
||||
case TOK.typeof_:
|
||||
t = peek(t);
|
||||
if (t.value != TOK.leftParenthesis ||
|
||||
!skipParens(t, &t))
|
||||
|
|
|
@ -471,7 +471,7 @@ private final class CppMangleVisitor : Visitor
|
|||
}
|
||||
else
|
||||
{
|
||||
ti.error("Internal Compiler Error: C++ `%s` template value parameter is not supported", tv.valType.toChars());
|
||||
ti.error("internal compiler error: C++ `%s` template value parameter is not supported", tv.valType.toChars());
|
||||
fatal();
|
||||
}
|
||||
}
|
||||
|
@ -506,13 +506,13 @@ private final class CppMangleVisitor : Visitor
|
|||
}
|
||||
else
|
||||
{
|
||||
ti.error("Internal Compiler Error: C++ `%s` template alias parameter is not supported", o.toChars());
|
||||
ti.error("internal compiler error: C++ `%s` template alias parameter is not supported", o.toChars());
|
||||
fatal();
|
||||
}
|
||||
}
|
||||
else if (tp.isTemplateThisParameter())
|
||||
{
|
||||
ti.error("Internal Compiler Error: C++ `%s` template this parameter is not supported", o.toChars());
|
||||
ti.error("internal compiler error: C++ `%s` template this parameter is not supported", o.toChars());
|
||||
fatal();
|
||||
}
|
||||
else
|
||||
|
@ -995,7 +995,7 @@ private final class CppMangleVisitor : Visitor
|
|||
// fake mangling for fields to fix https://issues.dlang.org/show_bug.cgi?id=16525
|
||||
if (!(d.storage_class & (STC.extern_ | STC.field | STC.gshared)))
|
||||
{
|
||||
d.error("Internal Compiler Error: C++ static non-`__gshared` non-`extern` variables not supported");
|
||||
d.error("internal compiler error: C++ static non-`__gshared` non-`extern` variables not supported");
|
||||
fatal();
|
||||
}
|
||||
Dsymbol p = d.toParent();
|
||||
|
@ -1330,7 +1330,7 @@ private final class CppMangleVisitor : Visitor
|
|||
if (t.ty == Tsarray)
|
||||
{
|
||||
// Static arrays in D are passed by value; no counterpart in C++
|
||||
.error(loc, "Internal Compiler Error: unable to pass static array `%s` to extern(C++) function, use pointer instead",
|
||||
.error(loc, "internal compiler error: unable to pass static array `%s` to extern(C++) function, use pointer instead",
|
||||
t.toChars());
|
||||
fatal();
|
||||
}
|
||||
|
@ -1369,7 +1369,7 @@ private final class CppMangleVisitor : Visitor
|
|||
p = "`shared` ";
|
||||
else
|
||||
p = "";
|
||||
.error(loc, "Internal Compiler Error: %stype `%s` cannot be mapped to C++\n", p, t.toChars());
|
||||
.error(loc, "internal compiler error: %stype `%s` cannot be mapped to C++\n", p, t.toChars());
|
||||
fatal(); //Fatal, because this error should be handled in frontend
|
||||
}
|
||||
|
||||
|
|
|
@ -1695,14 +1695,6 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
|
|||
{
|
||||
// T[n] sa;
|
||||
// cast(U[])sa; // ==> cast(U[])sa[];
|
||||
if (global.params.useDIP1000 == FeatureState.enabled)
|
||||
{
|
||||
if (auto v = expToVariable(e))
|
||||
{
|
||||
if (e.type.hasPointers() && !checkAddressVar(sc, e, v))
|
||||
goto Lfail;
|
||||
}
|
||||
}
|
||||
const fsize = t1b.nextOf().size();
|
||||
const tsize = tob.nextOf().size();
|
||||
if (fsize == SIZE_INVALID || tsize == SIZE_INVALID)
|
||||
|
@ -2236,7 +2228,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
|
|||
ArrayLiteralExp ae = e;
|
||||
|
||||
Type tb = t.toBasetype();
|
||||
if (tb.ty == Tarray && global.params.useDIP1000 == FeatureState.enabled)
|
||||
if (tb.ty == Tarray)
|
||||
{
|
||||
if (checkArrayLiteralEscape(sc, ae, false))
|
||||
{
|
||||
|
@ -2782,9 +2774,8 @@ Expression scaleFactor(BinExp be, Scope* sc)
|
|||
if (eoff.op == EXP.int64 && eoff.toInteger() == 0)
|
||||
{
|
||||
}
|
||||
else if (sc.func.setUnsafe())
|
||||
else if (sc.func.setUnsafe(false, be.loc, "pointer arithmetic not allowed in @safe functions"))
|
||||
{
|
||||
be.error("pointer arithmetic not allowed in @safe functions");
|
||||
return ErrorExp.get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -984,7 +984,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
|
|||
auto var = new VarDeclaration(loc, vtype, Identifier.idPool("__vtbl"), null, STC.immutable_ | STC.static_);
|
||||
var.addMember(null, this);
|
||||
var.isdataseg = 1;
|
||||
var.linkage = LINK.d;
|
||||
var._linkage = LINK.d;
|
||||
var.semanticRun = PASS.semanticdone; // no more semantic wanted
|
||||
vtblsym = var;
|
||||
}
|
||||
|
|
|
@ -221,7 +221,7 @@ extern (C++) abstract class Declaration : Dsymbol
|
|||
Type originalType; // before semantic analysis
|
||||
StorageClass storage_class = STC.undefined_;
|
||||
Visibility visibility;
|
||||
LINK linkage = LINK.default_;
|
||||
LINK _linkage = LINK.default_; // may be `LINK.system`; use `resolvedLinkage()` to resolve it
|
||||
short inuse; // used to detect cycles
|
||||
|
||||
ubyte adFlags; // control re-assignment of AliasDeclaration (put here for packing reasons)
|
||||
|
@ -336,7 +336,7 @@ extern (C++) abstract class Declaration : Dsymbol
|
|||
{
|
||||
if (ctor.isCpCtor && ctor.isGenerated())
|
||||
{
|
||||
.error(loc, "Generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", parent.toPrettyChars());
|
||||
.error(loc, "generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", parent.toPrettyChars());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -420,6 +420,12 @@ extern (C++) abstract class Declaration : Dsymbol
|
|||
return (storage_class & STC.static_) != 0;
|
||||
}
|
||||
|
||||
/// Returns the linkage, resolving the target-specific `System` one.
|
||||
final LINK resolvedLinkage() const
|
||||
{
|
||||
return _linkage == LINK.system ? target.systemLinkage() : _linkage;
|
||||
}
|
||||
|
||||
bool isDelete()
|
||||
{
|
||||
return false;
|
||||
|
@ -1506,7 +1512,7 @@ extern (C++) class VarDeclaration : Declaration
|
|||
uint oldgag = global.gag;
|
||||
if (global.gag)
|
||||
{
|
||||
Dsymbol sym = toParent().isAggregateDeclaration();
|
||||
Dsymbol sym = isMember();
|
||||
if (sym && !sym.isSpeculative())
|
||||
global.gag = 0;
|
||||
}
|
||||
|
@ -1691,6 +1697,32 @@ extern (C++) class BitFieldDeclaration : VarDeclaration
|
|||
v.visit(this);
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Retrieve the .min or .max values.
|
||||
* Only valid after semantic analysis.
|
||||
* Params:
|
||||
* id = Id.min or Id.max
|
||||
* Returns:
|
||||
* the min or max value
|
||||
*/
|
||||
final ulong getMinMax(Identifier id)
|
||||
{
|
||||
const width = fieldWidth;
|
||||
const uns = type.isunsigned();
|
||||
const min = id == Id.min;
|
||||
ulong v;
|
||||
assert(width != 0); // should have been rejected in semantic pass
|
||||
if (width == ulong.sizeof * 8)
|
||||
v = uns ? (min ? ulong.min : ulong.max)
|
||||
: (min ? long.min : long.max);
|
||||
else
|
||||
v = uns ? (min ? 0
|
||||
: (1L << width) - 1)
|
||||
: (min ? -(1L << (width - 1))
|
||||
: (1L << (width - 1)) - 1);
|
||||
return v;
|
||||
}
|
||||
|
||||
override final void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
|
||||
{
|
||||
//printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars());
|
||||
|
@ -1919,7 +1951,7 @@ extern (C++) class TypeInfoDeclaration : VarDeclaration
|
|||
this.tinfo = tinfo;
|
||||
storage_class = STC.static_ | STC.gshared;
|
||||
visibility = Visibility(Visibility.Kind.public_);
|
||||
linkage = LINK.c;
|
||||
_linkage = LINK.c;
|
||||
alignment.set(target.ptrsize);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ struct Ensure
|
|||
class FuncDeclaration;
|
||||
class StructDeclaration;
|
||||
struct IntRange;
|
||||
struct AttributeViolation;
|
||||
|
||||
//enum STC : ulong from astenums.d:
|
||||
|
||||
|
@ -115,7 +116,7 @@ public:
|
|||
Type *originalType; // before semantic analysis
|
||||
StorageClass storage_class;
|
||||
Visibility visibility;
|
||||
LINK linkage;
|
||||
LINK _linkage; // may be `LINK::system`; use `resolvedLinkage()` to resolve it
|
||||
short inuse; // used to detect cycles
|
||||
uint8_t adFlags;
|
||||
Symbol* isym; // import version of csym
|
||||
|
@ -127,6 +128,7 @@ public:
|
|||
Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
|
||||
|
||||
bool isStatic() const { return (storage_class & STCstatic) != 0; }
|
||||
LINK resolvedLinkage() const; // returns the linkage, resolving the target-specific `System` one
|
||||
virtual bool isDelete();
|
||||
virtual bool isDataseg();
|
||||
virtual bool isThreadlocal();
|
||||
|
@ -612,6 +614,10 @@ public:
|
|||
|
||||
FuncDeclarations *inlinedNestedCallees;
|
||||
|
||||
private:
|
||||
AttributeViolation* safetyViolation;
|
||||
public:
|
||||
|
||||
unsigned flags; // FUNCFLAGxxxxx
|
||||
|
||||
// Data for a function declaration that is needed for the Objective-C
|
||||
|
@ -655,6 +661,7 @@ public:
|
|||
bool isNRVO() const;
|
||||
void isNRVO(bool v);
|
||||
bool isNaked() const;
|
||||
void isNaked(bool v);
|
||||
bool isGenerated() const;
|
||||
void isGenerated(bool v);
|
||||
bool isIntroducing() const;
|
||||
|
@ -664,7 +671,9 @@ public:
|
|||
bool hasDualContext() const;
|
||||
bool hasAlwaysInlines() const;
|
||||
bool isCrtCtor() const;
|
||||
void isCrtCtor(bool v);
|
||||
bool isCrtDtor() const;
|
||||
void isCrtDtor(bool v);
|
||||
|
||||
virtual bool isNested() const;
|
||||
AggregateDeclaration *isThis();
|
||||
|
|
|
@ -674,8 +674,20 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
|
|||
}
|
||||
}
|
||||
// If fell off the end of a void function, return void
|
||||
if (!e && tf.next.ty == Tvoid)
|
||||
e = CTFEExp.voidexp;
|
||||
if (!e)
|
||||
{
|
||||
if (tf.next.ty == Tvoid)
|
||||
e = CTFEExp.voidexp;
|
||||
else
|
||||
{
|
||||
/* missing a return statement can happen with C functions
|
||||
* https://issues.dlang.org/show_bug.cgi?id=23056
|
||||
*/
|
||||
fd.error("no return value from function");
|
||||
e = CTFEExp.cantexp;
|
||||
}
|
||||
}
|
||||
|
||||
if (tf.isref && e.op == EXP.variable && e.isVarExp().var == fd.vthis)
|
||||
e = thisarg;
|
||||
if (tf.isref && fd.hasDualContext() && e.op == EXP.index)
|
||||
|
@ -695,7 +707,6 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
|
|||
}
|
||||
}
|
||||
}
|
||||
assert(e !is null);
|
||||
|
||||
// Leave the function
|
||||
--ctfeGlobals.callDepth;
|
||||
|
@ -1038,6 +1049,21 @@ public:
|
|||
if (exceptionOrCant(e))
|
||||
return;
|
||||
|
||||
/**
|
||||
* Interpret `return a ~= b` (i.e. `return _d_arrayappendT{,Trace}(a, b)`) as:
|
||||
* a ~= b;
|
||||
* return a;
|
||||
* This is needed because `a ~= b` has to be interpreted as an lvalue, in order to avoid
|
||||
* assigning a larger array into a smaller one, such as:
|
||||
* `a = [1, 2], a ~= [3]` => `[1, 2] ~= [3]` => `[1, 2] = [1, 2, 3]`
|
||||
*/
|
||||
if (isRuntimeHook(s.exp, Id._d_arrayappendT) || isRuntimeHook(s.exp, Id._d_arrayappendTTrace))
|
||||
{
|
||||
auto rs = new ReturnStatement(s.loc, e);
|
||||
rs.accept(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// Disallow returning pointers to stack-allocated variables (bug 7876)
|
||||
if (!stopPointersEscaping(s.loc, e))
|
||||
{
|
||||
|
@ -4826,6 +4852,33 @@ public:
|
|||
result = interpret(ce, istate);
|
||||
return;
|
||||
}
|
||||
else if (fd.ident == Id._d_arrayappendT || fd.ident == Id._d_arrayappendTTrace)
|
||||
{
|
||||
// In expressionsem.d `ea ~= eb` was lowered to `_d_arrayappendT{,Trace}({file, line, funcname}, ea, eb);`.
|
||||
// The following code will rewrite it back to `ea ~= eb` and then interpret that expression.
|
||||
Expression lhs, rhs;
|
||||
|
||||
if (fd.ident == Id._d_arrayappendT)
|
||||
{
|
||||
assert(e.arguments.dim == 2);
|
||||
lhs = (*e.arguments)[0];
|
||||
rhs = (*e.arguments)[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(e.arguments.dim == 5);
|
||||
lhs = (*e.arguments)[3];
|
||||
rhs = (*e.arguments)[4];
|
||||
}
|
||||
|
||||
auto cae = new CatAssignExp(e.loc, lhs, rhs);
|
||||
cae.type = e.type;
|
||||
|
||||
result = interpretRegion(cae, istate, CTFEGoal.LValue);
|
||||
return;
|
||||
}
|
||||
else if (fd.ident == Id._d_arrayappendcTX)
|
||||
assert(0, "CTFE cannot interpret _d_arrayappendcTX!");
|
||||
}
|
||||
else if (auto soe = ecall.isSymOffExp())
|
||||
{
|
||||
|
@ -4947,6 +5000,25 @@ public:
|
|||
printf("%s CommaExp::interpret() %s\n", e.loc.toChars(), e.toChars());
|
||||
}
|
||||
|
||||
if (auto ce = isRuntimeHook(e.e1, Id._d_arrayappendcTX))
|
||||
{
|
||||
// In expressionsem.d `arr ~= elem` was lowered to
|
||||
// `_d_arrayappendcTX(arr, elem), arr[arr.length - 1] = elem, elem;`.
|
||||
// The following code will rewrite it back to `arr ~= elem`
|
||||
// and then interpret that expression.
|
||||
assert(ce.arguments.dim == 2);
|
||||
|
||||
auto arr = (*ce.arguments)[0];
|
||||
auto elem = e.e2.isConstructExp().e2;
|
||||
assert(elem);
|
||||
|
||||
auto cae = new CatAssignExp(e.loc, arr, elem);
|
||||
cae.type = arr.type;
|
||||
|
||||
result = interpret(cae, istate);
|
||||
return;
|
||||
}
|
||||
|
||||
// If it creates a variable, and there's no context for
|
||||
// the variable to be created in, we need to create one now.
|
||||
InterState istateComma;
|
||||
|
@ -6119,7 +6191,7 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
if (result.isStringExp())
|
||||
if (result.isStringExp() || result.isArrayLiteralExp())
|
||||
return;
|
||||
|
||||
if (result.op != EXP.address)
|
||||
|
@ -6268,7 +6340,7 @@ public:
|
|||
result = (*se.elements)[i];
|
||||
if (!result)
|
||||
{
|
||||
e.error("Internal Compiler Error: null field `%s`", v.toChars());
|
||||
e.error("internal compiler error: null field `%s`", v.toChars());
|
||||
result = CTFEExp.cantexp;
|
||||
return;
|
||||
}
|
||||
|
@ -6359,6 +6431,33 @@ public:
|
|||
{
|
||||
assert(0); // This should never be interpreted
|
||||
}
|
||||
|
||||
/*********************************************
|
||||
* Checks if the given expresion is a call to the runtime hook `id`.
|
||||
* Params:
|
||||
* e = the expression to check
|
||||
* id = the identifier of the runtime hook
|
||||
* Returns:
|
||||
* `e` cast to `CallExp` if it's the hook, `null` otherwise
|
||||
*/
|
||||
private CallExp isRuntimeHook(Expression e, Identifier id)
|
||||
{
|
||||
if (auto ce = e.isCallExp())
|
||||
{
|
||||
if (auto ve = ce.e1.isVarExp())
|
||||
{
|
||||
if (auto fd = ve.var.isFuncDeclaration())
|
||||
{
|
||||
// If `_d_HookTraceImpl` is found, resolve the underlying
|
||||
// hook and replace `e` and `fd` with it.
|
||||
removeHookTraceImpl(ce, fd);
|
||||
return fd.ident == id ? ce : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************
|
||||
|
|
|
@ -1335,15 +1335,19 @@ void realToMangleBuffer(OutBuffer* buf, real_t value)
|
|||
private
|
||||
extern (D) const(char)[] externallyMangledIdentifier(Declaration d)
|
||||
{
|
||||
assert(!d.mangleOverride, "mangle overrides should have been handled earlier");
|
||||
|
||||
const linkage = d.resolvedLinkage();
|
||||
const par = d.toParent(); //toParent() skips over mixin templates
|
||||
if (!par || par.isModule() || d.linkage == LINK.cpp ||
|
||||
(d.linkage == LINK.c && d.isCsymbol() && d.isFuncDeclaration()))
|
||||
if (!par || par.isModule() || linkage == LINK.cpp ||
|
||||
(linkage == LINK.c && d.isCsymbol() &&
|
||||
(d.isFuncDeclaration() ||
|
||||
(d.isVarDeclaration() && d.isDataseg() && d.storage_class & STC.extern_))))
|
||||
{
|
||||
if (d.linkage != LINK.d && d.localNum)
|
||||
if (linkage != LINK.d && d.localNum)
|
||||
d.error("the same declaration cannot be in multiple scopes with non-D linkage");
|
||||
|
||||
const l = d.linkage == LINK.system ? target.systemLinkage() : d.linkage;
|
||||
final switch (l)
|
||||
final switch (linkage)
|
||||
{
|
||||
case LINK.d:
|
||||
break;
|
||||
|
|
|
@ -71,7 +71,7 @@ void semantic3OnDependencies(Module m)
|
|||
*/
|
||||
void removeHdrFilesAndFail(ref Param params, ref Modules modules) nothrow
|
||||
{
|
||||
if (params.doHdrGeneration)
|
||||
if (params.dihdr.doOutput)
|
||||
{
|
||||
foreach (m; modules)
|
||||
{
|
||||
|
@ -472,7 +472,7 @@ extern (C++) final class Module : Package
|
|||
if (doDocComment)
|
||||
setDocfile();
|
||||
if (doHdrGen)
|
||||
hdrfile = setOutfilename(global.params.hdrname, global.params.hdrdir, arg, hdr_ext);
|
||||
hdrfile = setOutfilename(global.params.dihdr.name, global.params.dihdr.dir, arg, hdr_ext);
|
||||
}
|
||||
|
||||
extern (D) this(const(char)[] filename, Identifier ident, int doDocComment, int doHdrGen)
|
||||
|
@ -584,7 +584,7 @@ extern (C++) final class Module : Package
|
|||
|
||||
extern (D) void setDocfile()
|
||||
{
|
||||
docfile = setOutfilename(global.params.docname, global.params.docdir, arg, doc_ext);
|
||||
docfile = setOutfilename(global.params.ddoc.name, global.params.ddoc.dir, arg, doc_ext);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -662,11 +662,55 @@ extern (C++) final class Module : Package
|
|||
return true; // already read
|
||||
|
||||
//printf("Module::read('%s') file '%s'\n", toChars(), srcfile.toChars());
|
||||
if (auto result = global.fileManager.lookup(srcfile))
|
||||
|
||||
/* Preprocess the file if it's a .c file
|
||||
*/
|
||||
FileName filename = srcfile;
|
||||
bool ifile = false; // did we generate a .i file
|
||||
scope (exit)
|
||||
{
|
||||
if (ifile)
|
||||
File.remove(filename.toChars()); // remove generated file
|
||||
}
|
||||
|
||||
if (global.preprocess &&
|
||||
FileName.equalsExt(srcfile.toString(), c_ext) &&
|
||||
FileName.exists(srcfile.toString()))
|
||||
{
|
||||
/* Look for "importc.h" by searching along import path.
|
||||
* It should be in the same place as "object.d"
|
||||
*/
|
||||
const(char)* importc_h;
|
||||
|
||||
foreach (entry; (global.path ? (*global.path)[] : null))
|
||||
{
|
||||
auto f = FileName.combine(entry, "importc.h");
|
||||
if (FileName.exists(f) == 1)
|
||||
{
|
||||
importc_h = f;
|
||||
break;
|
||||
}
|
||||
FileName.free(f);
|
||||
}
|
||||
|
||||
if (importc_h)
|
||||
{
|
||||
if (global.params.verbose)
|
||||
message("include %s", importc_h);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("cannot find \"importc.h\" along import path");
|
||||
fatal();
|
||||
}
|
||||
filename = global.preprocess(srcfile, importc_h, global.params.cppswitches, ifile); // run C preprocessor
|
||||
}
|
||||
|
||||
if (auto result = global.fileManager.lookup(filename))
|
||||
{
|
||||
this.src = result;
|
||||
if (global.params.emitMakeDeps)
|
||||
global.params.makeDeps.push(srcfile.toChars());
|
||||
if (global.params.makeDeps.doOutput)
|
||||
global.params.makeDeps.files.push(srcfile.toChars());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -384,11 +384,11 @@ extern(C++) void gendocfile(Module m)
|
|||
// Override with DDOCFILE specified in the sc.ini file
|
||||
char* p = getenv("DDOCFILE");
|
||||
if (p)
|
||||
global.params.ddocfiles.shift(p);
|
||||
global.params.ddoc.files.shift(p);
|
||||
// Override with the ddoc macro files from the command line
|
||||
for (size_t i = 0; i < global.params.ddocfiles.dim; i++)
|
||||
for (size_t i = 0; i < global.params.ddoc.files.dim; i++)
|
||||
{
|
||||
auto buffer = readFile(m.loc, global.params.ddocfiles[i]);
|
||||
auto buffer = readFile(m.loc, global.params.ddoc.files[i]);
|
||||
// BUG: convert file contents to UTF-8 before use
|
||||
const data = buffer.data;
|
||||
//printf("file: '%.*s'\n", cast(int)data.length, data.ptr);
|
||||
|
@ -628,7 +628,7 @@ private void escapeStrayParenthesis(Loc loc, OutBuffer* buf, size_t start, bool
|
|||
break;
|
||||
case '\\':
|
||||
// replace backslash-escaped parens with their macros
|
||||
if (!inCode && respectBackslashEscapes && u+1 < buf.length && global.params.markdown)
|
||||
if (!inCode && respectBackslashEscapes && u+1 < buf.length)
|
||||
{
|
||||
if ((*buf)[u+1] == '(' || (*buf)[u+1] == ')')
|
||||
{
|
||||
|
@ -2317,8 +2317,6 @@ private void removeBlankLineMacro(ref OutBuffer buf, ref size_t iAt, ref size_t
|
|||
*/
|
||||
private bool replaceMarkdownThematicBreak(ref OutBuffer buf, ref size_t i, size_t iLineStart, const ref Loc loc)
|
||||
{
|
||||
if (!global.params.markdown)
|
||||
return false;
|
||||
|
||||
const slice = buf[];
|
||||
const c = buf[i];
|
||||
|
@ -2335,12 +2333,6 @@ private bool replaceMarkdownThematicBreak(ref OutBuffer buf, ref size_t i, size_
|
|||
{
|
||||
if (j >= buf.length || buf[j] == '\n' || buf[j] == '\r')
|
||||
{
|
||||
if (global.params.vmarkdown)
|
||||
{
|
||||
const s = buf[][i..j];
|
||||
message(loc, "Ddoc: converted '%.*s' to a thematic break", cast(int)s.length, s.ptr);
|
||||
}
|
||||
|
||||
buf.remove(iLineStart, j - iLineStart);
|
||||
i = buf.insert(iLineStart, "$(HR)") - 1;
|
||||
return true;
|
||||
|
@ -2361,9 +2353,6 @@ private bool replaceMarkdownThematicBreak(ref OutBuffer buf, ref size_t i, size_
|
|||
*/
|
||||
private int detectAtxHeadingLevel(ref OutBuffer buf, const size_t i)
|
||||
{
|
||||
if (!global.params.markdown)
|
||||
return 0;
|
||||
|
||||
const iHeadingStart = i;
|
||||
const iAfterHashes = skipChars(buf, i, "#");
|
||||
const headingLevel = cast(int) (iAfterHashes - iHeadingStart);
|
||||
|
@ -2433,14 +2422,6 @@ private void removeAnyAtxHeadingSuffix(ref OutBuffer buf, size_t i)
|
|||
*/
|
||||
private void endMarkdownHeading(ref OutBuffer buf, size_t iStart, ref size_t iEnd, const ref Loc loc, ref int headingLevel)
|
||||
{
|
||||
if (!global.params.markdown)
|
||||
return;
|
||||
if (global.params.vmarkdown)
|
||||
{
|
||||
const s = buf[][iStart..iEnd];
|
||||
message(loc, "Ddoc: added heading '%.*s'", cast(int)s.length, s.ptr);
|
||||
}
|
||||
|
||||
char[5] heading = "$(H0 ";
|
||||
heading[3] = cast(char) ('0' + headingLevel);
|
||||
buf.insert(iStart, heading);
|
||||
|
@ -2503,9 +2484,6 @@ private size_t endAllListsAndQuotes(ref OutBuffer buf, ref size_t i, ref Markdow
|
|||
*/
|
||||
private size_t replaceMarkdownEmphasis(ref OutBuffer buf, const ref Loc loc, ref MarkdownDelimiter[] inlineDelimiters, int downToLevel = 0)
|
||||
{
|
||||
if (!global.params.markdown)
|
||||
return 0;
|
||||
|
||||
size_t replaceEmphasisPair(ref MarkdownDelimiter start, ref MarkdownDelimiter end)
|
||||
{
|
||||
immutable count = start.count == 1 || end.count == 1 ? 1 : 2;
|
||||
|
@ -2521,12 +2499,6 @@ private size_t replaceMarkdownEmphasis(ref OutBuffer buf, const ref Loc loc, ref
|
|||
if (!end.count)
|
||||
end.type = 0;
|
||||
|
||||
if (global.params.vmarkdown)
|
||||
{
|
||||
const s = buf[][iStart + count..iEnd];
|
||||
message(loc, "Ddoc: emphasized text '%.*s'", cast(int)s.length, s.ptr);
|
||||
}
|
||||
|
||||
buf.remove(iStart, count);
|
||||
iEnd -= count;
|
||||
buf.remove(iEnd, count);
|
||||
|
@ -2857,9 +2829,6 @@ private struct MarkdownList
|
|||
*/
|
||||
static MarkdownList parseItem(ref OutBuffer buf, size_t iLineStart, size_t i)
|
||||
{
|
||||
if (!global.params.markdown)
|
||||
return MarkdownList();
|
||||
|
||||
if (buf[i] == '+' || buf[i] == '-' || buf[i] == '*')
|
||||
return parseUnorderedListItem(buf, iLineStart, i);
|
||||
else
|
||||
|
@ -2931,15 +2900,6 @@ private struct MarkdownList
|
|||
i = iStart - 1;
|
||||
iLineStart = i;
|
||||
|
||||
if (global.params.vmarkdown)
|
||||
{
|
||||
size_t iEnd = iStart;
|
||||
while (iEnd < buf.length && buf[iEnd] != '\r' && buf[iEnd] != '\n')
|
||||
++iEnd;
|
||||
const s = buf[][iStart..iEnd];
|
||||
message(loc, "Ddoc: starting list item '%.*s'", cast(int)s.length, s.ptr);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -3122,13 +3082,6 @@ private struct MarkdownLink
|
|||
immutable delta = replaceMarkdownEmphasis(buf, loc, inlineDelimiters, delimiterIndex);
|
||||
iEnd += delta;
|
||||
i += delta;
|
||||
|
||||
if (global.params.vmarkdown)
|
||||
{
|
||||
const s = buf[][delimiter.iStart..iEnd];
|
||||
message(loc, "Ddoc: linking '%.*s' to '%.*s'", cast(int)s.length, s.ptr, cast(int)link.href.length, link.href.ptr);
|
||||
}
|
||||
|
||||
link.replaceLink(buf, i, iEnd, delimiter);
|
||||
return true;
|
||||
}
|
||||
|
@ -3532,9 +3485,6 @@ private struct MarkdownLink
|
|||
*/
|
||||
private void storeAndReplaceDefinition(ref OutBuffer buf, ref size_t i, size_t iEnd, ref MarkdownLinkReferences linkReferences, const ref Loc loc)
|
||||
{
|
||||
if (global.params.vmarkdown)
|
||||
message(loc, "Ddoc: found link reference '%.*s' to '%.*s'", cast(int)label.length, label.ptr, cast(int)href.length, href.ptr);
|
||||
|
||||
// Remove the definition and trailing whitespace
|
||||
iEnd = skipChars(buf, iEnd, " \t\r\n");
|
||||
buf.remove(i, iEnd - i);
|
||||
|
@ -4050,12 +4000,6 @@ private bool replaceTableRow(ref OutBuffer buf, size_t iStart, size_t iEnd, cons
|
|||
if (headerRow && cellCount != columnAlignments.length)
|
||||
return false;
|
||||
|
||||
if (headerRow && global.params.vmarkdown)
|
||||
{
|
||||
const s = buf[][iStart..iEnd];
|
||||
message(loc, "Ddoc: formatting table '%.*s'", cast(int)s.length, s.ptr);
|
||||
}
|
||||
|
||||
void replaceTableCell(size_t iCellStart, size_t iCellEnd, int cellIndex, int di)
|
||||
{
|
||||
const eDelta = replaceMarkdownEmphasis(buf, loc, inlineDelimiters, di);
|
||||
|
@ -4378,17 +4322,8 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s
|
|||
|
||||
case '>':
|
||||
{
|
||||
if (leadingBlank && (!inCode || quoteLevel) && global.params.markdown)
|
||||
if (leadingBlank && (!inCode || quoteLevel))
|
||||
{
|
||||
if (!quoteLevel && global.params.vmarkdown)
|
||||
{
|
||||
size_t iEnd = i + 1;
|
||||
while (iEnd < buf.length && buf[iEnd] != '\n')
|
||||
++iEnd;
|
||||
const s = buf[][i .. iEnd];
|
||||
message(loc, "Ddoc: starting quote block with '%.*s'", cast(int)s.length, s.ptr);
|
||||
}
|
||||
|
||||
lineQuoted = true;
|
||||
int lineQuoteLevel = 1;
|
||||
size_t iAfterDelimiters = i + 1;
|
||||
|
@ -4488,7 +4423,7 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s
|
|||
}
|
||||
|
||||
// Perhaps we're starting or ending a Markdown code block
|
||||
if (leadingBlank && global.params.markdown && count >= 3)
|
||||
if (leadingBlank && count >= 3)
|
||||
{
|
||||
bool moreBackticks = false;
|
||||
for (size_t j = iAfterDelimiter; !moreBackticks && j < buf.length; ++j)
|
||||
|
@ -4548,7 +4483,7 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s
|
|||
|
||||
case '~':
|
||||
{
|
||||
if (leadingBlank && global.params.markdown)
|
||||
if (leadingBlank)
|
||||
{
|
||||
// Perhaps we're starting or ending a Markdown code block
|
||||
const iAfterDelimiter = skipChars(buf, i, "~");
|
||||
|
@ -4613,7 +4548,7 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s
|
|||
// BUG: handle UTF PS and LS too
|
||||
if (c != c0 || iInfoString)
|
||||
{
|
||||
if (global.params.markdown && !iInfoString && !inCode && i - istart >= 3)
|
||||
if (!iInfoString && !inCode && i - istart >= 3)
|
||||
{
|
||||
// Start a Markdown info string, like ```ruby
|
||||
codeFenceLength = i - istart;
|
||||
|
@ -4711,9 +4646,6 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s
|
|||
if (codeLanguage[j] == '\\' && ispunct(codeLanguage[j + 1]))
|
||||
codeLanguage = codeLanguage[0..j] ~ codeLanguage[j + 1..$];
|
||||
|
||||
if (global.params.vmarkdown)
|
||||
message(loc, "Ddoc: adding code block for language '%.*s'", cast(int)codeLanguage.length, codeLanguage.ptr);
|
||||
|
||||
i = buf.insert(i, "$(OTHER_CODE ");
|
||||
i = buf.insert(i, codeLanguage);
|
||||
i = buf.insert(i, ",");
|
||||
|
@ -4779,7 +4711,7 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s
|
|||
|
||||
case '*':
|
||||
{
|
||||
if (inCode || inBacktick || !global.params.markdown)
|
||||
if (inCode || inBacktick)
|
||||
{
|
||||
leadingBlank = false;
|
||||
break;
|
||||
|
@ -4829,7 +4761,7 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s
|
|||
{
|
||||
leadingBlank = false;
|
||||
|
||||
if (inCode || !global.params.markdown)
|
||||
if (inCode)
|
||||
break;
|
||||
|
||||
if (i < buf.length-1 && buf[i+1] == '[')
|
||||
|
@ -4842,7 +4774,7 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s
|
|||
}
|
||||
case '[':
|
||||
{
|
||||
if (inCode || !global.params.markdown)
|
||||
if (inCode)
|
||||
{
|
||||
leadingBlank = false;
|
||||
break;
|
||||
|
@ -4860,7 +4792,7 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s
|
|||
{
|
||||
leadingBlank = false;
|
||||
|
||||
if (inCode || !global.params.markdown)
|
||||
if (inCode)
|
||||
break;
|
||||
|
||||
for (int d = cast(int) inlineDelimiters.length - 1; d >= 0; --d)
|
||||
|
@ -4894,7 +4826,7 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s
|
|||
|
||||
case '|':
|
||||
{
|
||||
if (inCode || !global.params.markdown)
|
||||
if (inCode)
|
||||
{
|
||||
leadingBlank = false;
|
||||
break;
|
||||
|
@ -4909,16 +4841,13 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s
|
|||
case '\\':
|
||||
{
|
||||
leadingBlank = false;
|
||||
if (inCode || i+1 >= buf.length || !global.params.markdown)
|
||||
if (inCode || i+1 >= buf.length)
|
||||
break;
|
||||
|
||||
/* Escape Markdown special characters */
|
||||
char c1 = buf[i+1];
|
||||
if (ispunct(c1))
|
||||
{
|
||||
if (global.params.vmarkdown)
|
||||
message(loc, "Ddoc: backslash-escaped %c", c1);
|
||||
|
||||
buf.remove(i, 1);
|
||||
|
||||
auto se = sc._module.escapetable.escapeChar(c1);
|
||||
|
|
|
@ -63,7 +63,6 @@ enum SCOPE
|
|||
free = 0x8000, /// is on free list
|
||||
|
||||
fullinst = 0x10000, /// fully instantiate templates
|
||||
alias_ = 0x20000, /// inside alias declaration.
|
||||
|
||||
// The following are mutually exclusive
|
||||
printf = 0x4_0000, /// printf-style function
|
||||
|
|
|
@ -984,7 +984,7 @@ extern (C++) class Dsymbol : ASTNode
|
|||
*/
|
||||
uinteger_t size(const ref Loc loc)
|
||||
{
|
||||
error("Dsymbol `%s` has no size", toChars());
|
||||
error("symbol `%s` has no size", toChars());
|
||||
return SIZE_INVALID;
|
||||
}
|
||||
|
||||
|
@ -1641,6 +1641,32 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************
|
||||
* Returns: the symbols whose members have been imported, i.e. imported modules
|
||||
* and template mixins.
|
||||
*
|
||||
* See_Also: importScope
|
||||
*/
|
||||
extern (D) final Dsymbols* getImportedScopes() nothrow @nogc @safe pure
|
||||
{
|
||||
return importedScopes;
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
* Returns: the array of visibilities associated with each imported scope. The
|
||||
* length of the array matches the imported scopes array.
|
||||
*
|
||||
* See_Also: getImportedScopes
|
||||
*/
|
||||
extern (D) final Visibility.Kind[] getImportVisibilities() nothrow @nogc @safe pure
|
||||
{
|
||||
if (!importedScopes)
|
||||
return null;
|
||||
|
||||
return (() @trusted => visibilities[0 .. importedScopes.dim])();
|
||||
}
|
||||
|
||||
extern (D) final void addAccessiblePackage(Package p, Visibility visibility) nothrow
|
||||
{
|
||||
auto pary = visibility.kind == Visibility.Kind.private_ ? &privateAccessiblePackages : &accessiblePackages;
|
||||
|
|
|
@ -376,7 +376,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
// https://issues.dlang.org/show_bug.cgi?id=19482
|
||||
if ((dsym.storage_class & (STC.foreach_ | STC.local)) == (STC.foreach_ | STC.local))
|
||||
{
|
||||
dsym.linkage = LINK.d;
|
||||
dsym._linkage = LINK.d;
|
||||
dsym.visibility = Visibility(Visibility.Kind.public_);
|
||||
dsym.overlapped = false; // unset because it is modified early on this function
|
||||
dsym.userAttribDecl = null; // unset because it is set by Dsymbol.setScope()
|
||||
|
@ -389,7 +389,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
dsym.storage_class |= (sc.stc & ~(STC.synchronized_ | STC.override_ | STC.abstract_ | STC.final_));
|
||||
dsym.userAttribDecl = sc.userAttribDecl;
|
||||
dsym.cppnamespace = sc.namespace;
|
||||
dsym.linkage = sc.linkage;
|
||||
dsym._linkage = sc.linkage;
|
||||
dsym.visibility = sc.visibility;
|
||||
dsym.alignment = sc.alignment();
|
||||
}
|
||||
|
@ -472,8 +472,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
{
|
||||
if (dsym.storage_class & STC.gshared && !dsym.isMember())
|
||||
{
|
||||
if (sc.func.setUnsafe())
|
||||
dsym.error("__gshared not allowed in safe functions; use shared");
|
||||
sc.func.setUnsafe(false, dsym.loc, "__gshared not allowed in safe functions; use shared");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -863,20 +862,18 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
if (dsym._init && dsym._init.isVoidInitializer() &&
|
||||
(dsym.type.hasPointers() || dsym.type.hasInvariant())) // also computes type size
|
||||
{
|
||||
if (sc.func.setUnsafe())
|
||||
{
|
||||
if (dsym.type.hasPointers())
|
||||
dsym.error("`void` initializers for pointers not allowed in safe functions");
|
||||
else
|
||||
dsym.error("`void` initializers for structs with invariants are not allowed in safe functions");
|
||||
}
|
||||
if (dsym.type.hasPointers())
|
||||
sc.func.setUnsafe(false, dsym.loc,
|
||||
"`void` initializers for pointers not allowed in safe functions");
|
||||
else
|
||||
sc.func.setUnsafe(false, dsym.loc,
|
||||
"`void` initializers for structs with invariants are not allowed in safe functions");
|
||||
}
|
||||
else if (!dsym._init &&
|
||||
!(dsym.storage_class & (STC.static_ | STC.extern_ | STC.gshared | STC.manifest | STC.field | STC.parameter)) &&
|
||||
dsym.type.hasVoidInitPointers())
|
||||
{
|
||||
if (sc.func.setUnsafe())
|
||||
dsym.error("`void` initializers for pointers not allowed in safe functions");
|
||||
sc.func.setUnsafe(false, dsym.loc, "`void` initializers for pointers not allowed in safe functions");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -891,6 +888,15 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
else if (dsym.storage_class & STC.manifest)
|
||||
dsym.error("manifest constants must have initializers");
|
||||
|
||||
// Don't allow non-extern, non-__gshared variables to be interfaced with C++
|
||||
if (dsym._linkage == LINK.cpp && !(dsym.storage_class & (STC.ctfe | STC.extern_ | STC.gshared)) && dsym.isDataseg())
|
||||
{
|
||||
const char* p = (dsym.storage_class & STC.shared_) ? "shared" : "static";
|
||||
dsym.error("cannot have `extern(C++)` linkage because it is `%s`", p);
|
||||
errorSupplemental(dsym.loc, "perhaps declare it as `__gshared` instead");
|
||||
dsym.errors = true;
|
||||
}
|
||||
|
||||
bool isBlit = false;
|
||||
uinteger_t sz;
|
||||
if (sc.flags & SCOPE.Cfile && !dsym._init)
|
||||
|
@ -1191,7 +1197,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
|
||||
override void visit(TypeInfoDeclaration dsym)
|
||||
{
|
||||
assert(dsym.linkage == LINK.c);
|
||||
assert(dsym._linkage == LINK.c);
|
||||
}
|
||||
|
||||
override void visit(BitFieldDeclaration dsym)
|
||||
|
@ -1204,6 +1210,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
if (dsym.errors)
|
||||
return;
|
||||
|
||||
if (!dsym.parent.isStructDeclaration() && !dsym.parent.isClassDeclaration())
|
||||
{
|
||||
dsym.error("bit-field must be member of struct, union, or class");
|
||||
}
|
||||
|
||||
sc = sc.startCTFE();
|
||||
auto width = dsym.width.expressionSemantic(sc);
|
||||
sc = sc.endCTFE();
|
||||
|
@ -1239,7 +1250,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
|
||||
override void visit(Import imp)
|
||||
{
|
||||
//printf("Import::semantic('%s') %s\n", toPrettyChars(), id.toChars());
|
||||
static if (LOG)
|
||||
{
|
||||
printf("Import::semantic('%s') %s\n", toPrettyChars(), id.toChars());
|
||||
scope(exit)
|
||||
printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
|
||||
}
|
||||
if (imp.semanticRun > PASS.initial)
|
||||
return;
|
||||
|
||||
|
@ -1349,70 +1365,69 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
// don't list pseudo modules __entrypoint.d, __main.d
|
||||
// https://issues.dlang.org/show_bug.cgi?id=11117
|
||||
// https://issues.dlang.org/show_bug.cgi?id=11164
|
||||
if (global.params.moduleDeps !is null && !(imp.id == Id.object && sc._module.ident == Id.object) &&
|
||||
strcmp(sc._module.ident.toChars(), "__main") != 0)
|
||||
if (global.params.moduleDeps.buffer is null || (imp.id == Id.object && sc._module.ident == Id.object) ||
|
||||
strcmp(sc._module.ident.toChars(), "__main") == 0)
|
||||
return;
|
||||
|
||||
/* The grammar of the file is:
|
||||
* ImportDeclaration
|
||||
* ::= BasicImportDeclaration [ " : " ImportBindList ] [ " -> "
|
||||
* ModuleAliasIdentifier ] "\n"
|
||||
*
|
||||
* BasicImportDeclaration
|
||||
* ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection|"string"
|
||||
* " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
|
||||
*
|
||||
* FilePath
|
||||
* - any string with '(', ')' and '\' escaped with the '\' character
|
||||
*/
|
||||
OutBuffer* ob = global.params.moduleDeps.buffer;
|
||||
Module imod = sc._module;
|
||||
if (!global.params.moduleDeps.name)
|
||||
ob.writestring("depsImport ");
|
||||
ob.writestring(imod.toPrettyChars());
|
||||
ob.writestring(" (");
|
||||
escapePath(ob, imod.srcfile.toChars());
|
||||
ob.writestring(") : ");
|
||||
// use visibility instead of sc.visibility because it couldn't be
|
||||
// resolved yet, see the comment above
|
||||
visibilityToBuffer(ob, imp.visibility);
|
||||
ob.writeByte(' ');
|
||||
if (imp.isstatic)
|
||||
{
|
||||
/* The grammar of the file is:
|
||||
* ImportDeclaration
|
||||
* ::= BasicImportDeclaration [ " : " ImportBindList ] [ " -> "
|
||||
* ModuleAliasIdentifier ] "\n"
|
||||
*
|
||||
* BasicImportDeclaration
|
||||
* ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection|"string"
|
||||
* " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
|
||||
*
|
||||
* FilePath
|
||||
* - any string with '(', ')' and '\' escaped with the '\' character
|
||||
*/
|
||||
OutBuffer* ob = global.params.moduleDeps;
|
||||
Module imod = sc._module;
|
||||
if (!global.params.moduleDepsFile)
|
||||
ob.writestring("depsImport ");
|
||||
ob.writestring(imod.toPrettyChars());
|
||||
ob.writestring(" (");
|
||||
escapePath(ob, imod.srcfile.toChars());
|
||||
ob.writestring(") : ");
|
||||
// use visibility instead of sc.visibility because it couldn't be
|
||||
// resolved yet, see the comment above
|
||||
visibilityToBuffer(ob, imp.visibility);
|
||||
stcToBuffer(ob, STC.static_);
|
||||
ob.writeByte(' ');
|
||||
if (imp.isstatic)
|
||||
{
|
||||
stcToBuffer(ob, STC.static_);
|
||||
ob.writeByte(' ');
|
||||
}
|
||||
ob.writestring(": ");
|
||||
foreach (pid; imp.packages)
|
||||
{
|
||||
ob.printf("%s.", pid.toChars());
|
||||
}
|
||||
ob.writestring(imp.id.toString());
|
||||
ob.writestring(" (");
|
||||
if (imp.mod)
|
||||
escapePath(ob, imp.mod.srcfile.toChars());
|
||||
else
|
||||
ob.writestring("???");
|
||||
ob.writeByte(')');
|
||||
foreach (i, name; imp.names)
|
||||
{
|
||||
if (i == 0)
|
||||
ob.writeByte(':');
|
||||
else
|
||||
ob.writeByte(',');
|
||||
Identifier _alias = imp.aliases[i];
|
||||
if (!_alias)
|
||||
{
|
||||
ob.printf("%s", name.toChars());
|
||||
_alias = name;
|
||||
}
|
||||
else
|
||||
ob.printf("%s=%s", _alias.toChars(), name.toChars());
|
||||
}
|
||||
if (imp.aliasId)
|
||||
ob.printf(" -> %s", imp.aliasId.toChars());
|
||||
ob.writenl();
|
||||
}
|
||||
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
|
||||
ob.writestring(": ");
|
||||
foreach (pid; imp.packages)
|
||||
{
|
||||
ob.printf("%s.", pid.toChars());
|
||||
}
|
||||
ob.writestring(imp.id.toString());
|
||||
ob.writestring(" (");
|
||||
if (imp.mod)
|
||||
escapePath(ob, imp.mod.srcfile.toChars());
|
||||
else
|
||||
ob.writestring("???");
|
||||
ob.writeByte(')');
|
||||
foreach (i, name; imp.names)
|
||||
{
|
||||
if (i == 0)
|
||||
ob.writeByte(':');
|
||||
else
|
||||
ob.writeByte(',');
|
||||
Identifier _alias = imp.aliases[i];
|
||||
if (!_alias)
|
||||
{
|
||||
ob.printf("%s", name.toChars());
|
||||
_alias = name;
|
||||
}
|
||||
else
|
||||
ob.printf("%s=%s", _alias.toChars(), name.toChars());
|
||||
}
|
||||
if (imp.aliasId)
|
||||
ob.printf(" -> %s", imp.aliasId.toChars());
|
||||
ob.writenl();
|
||||
}
|
||||
|
||||
void attribSemantic(AttribDeclaration ad)
|
||||
|
@ -1457,24 +1472,24 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
return;
|
||||
}
|
||||
|
||||
if (scd.decl)
|
||||
if (!scd.decl)
|
||||
return;
|
||||
|
||||
sc = sc.push();
|
||||
sc.stc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.gshared);
|
||||
sc.inunion = scd.isunion ? scd : null;
|
||||
sc.flags = 0;
|
||||
for (size_t i = 0; i < scd.decl.dim; i++)
|
||||
{
|
||||
sc = sc.push();
|
||||
sc.stc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.gshared);
|
||||
sc.inunion = scd.isunion ? scd : null;
|
||||
sc.flags = 0;
|
||||
for (size_t i = 0; i < scd.decl.dim; i++)
|
||||
Dsymbol s = (*scd.decl)[i];
|
||||
if (auto var = s.isVarDeclaration)
|
||||
{
|
||||
Dsymbol s = (*scd.decl)[i];
|
||||
if (auto var = s.isVarDeclaration)
|
||||
{
|
||||
if (scd.isunion)
|
||||
var.overlapped = true;
|
||||
}
|
||||
s.dsymbolSemantic(sc);
|
||||
if (scd.isunion)
|
||||
var.overlapped = true;
|
||||
}
|
||||
sc = sc.pop();
|
||||
s.dsymbolSemantic(sc);
|
||||
}
|
||||
sc = sc.pop();
|
||||
}
|
||||
|
||||
override void visit(PragmaDeclaration pd)
|
||||
|
@ -1633,32 +1648,33 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
}
|
||||
if (pd.ident == Id.msg)
|
||||
{
|
||||
if (pd.args)
|
||||
if (!pd.args)
|
||||
return noDeclarations();
|
||||
|
||||
for (size_t i = 0; i < pd.args.dim; i++)
|
||||
{
|
||||
for (size_t i = 0; i < pd.args.dim; i++)
|
||||
Expression e = (*pd.args)[i];
|
||||
sc = sc.startCTFE();
|
||||
e = e.expressionSemantic(sc);
|
||||
e = resolveProperties(sc, e);
|
||||
sc = sc.endCTFE();
|
||||
e = ctfeInterpretForPragmaMsg(e);
|
||||
if (e.op == EXP.error)
|
||||
{
|
||||
Expression e = (*pd.args)[i];
|
||||
sc = sc.startCTFE();
|
||||
e = e.expressionSemantic(sc);
|
||||
e = resolveProperties(sc, e);
|
||||
sc = sc.endCTFE();
|
||||
e = ctfeInterpretForPragmaMsg(e);
|
||||
if (e.op == EXP.error)
|
||||
{
|
||||
errorSupplemental(pd.loc, "while evaluating `pragma(msg, %s)`", (*pd.args)[i].toChars());
|
||||
return;
|
||||
}
|
||||
StringExp se = e.toStringExp();
|
||||
if (se)
|
||||
{
|
||||
se = se.toUTF8(sc);
|
||||
fprintf(stderr, "%.*s", cast(int)se.len, se.peekString().ptr);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "%s", e.toChars());
|
||||
errorSupplemental(pd.loc, "while evaluating `pragma(msg, %s)`", (*pd.args)[i].toChars());
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
StringExp se = e.toStringExp();
|
||||
if (se)
|
||||
{
|
||||
se = se.toUTF8(sc);
|
||||
fprintf(stderr, "%.*s", cast(int)se.len, se.peekString().ptr);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "%s", e.toChars());
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
return noDeclarations();
|
||||
}
|
||||
else if (pd.ident == Id.lib)
|
||||
|
@ -1675,9 +1691,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
auto name = se.peekString().xarraydup;
|
||||
if (global.params.verbose)
|
||||
message("library %s", name.ptr);
|
||||
if (global.params.moduleDeps && !global.params.moduleDepsFile)
|
||||
if (global.params.moduleDeps.buffer && !global.params.moduleDeps.name)
|
||||
{
|
||||
OutBuffer* ob = global.params.moduleDeps;
|
||||
OutBuffer* ob = global.params.moduleDeps.buffer;
|
||||
Module imod = sc._module;
|
||||
ob.writestring("depsLib ");
|
||||
ob.writestring(imod.toPrettyChars());
|
||||
|
@ -1892,49 +1908,49 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
return Identifier.idPool(sident);
|
||||
}
|
||||
|
||||
if (ns.ident is null)
|
||||
if (ns.ident !is null)
|
||||
return attribSemantic(ns);
|
||||
|
||||
ns.cppnamespace = sc.namespace;
|
||||
sc = sc.startCTFE();
|
||||
ns.exp = ns.exp.expressionSemantic(sc);
|
||||
ns.exp = resolveProperties(sc, ns.exp);
|
||||
sc = sc.endCTFE();
|
||||
ns.exp = ns.exp.ctfeInterpret();
|
||||
// Can be either a tuple of strings or a string itself
|
||||
if (auto te = ns.exp.isTupleExp())
|
||||
{
|
||||
ns.cppnamespace = sc.namespace;
|
||||
sc = sc.startCTFE();
|
||||
ns.exp = ns.exp.expressionSemantic(sc);
|
||||
ns.exp = resolveProperties(sc, ns.exp);
|
||||
sc = sc.endCTFE();
|
||||
ns.exp = ns.exp.ctfeInterpret();
|
||||
// Can be either a tuple of strings or a string itself
|
||||
if (auto te = ns.exp.isTupleExp())
|
||||
expandTuples(te.exps);
|
||||
CPPNamespaceDeclaration current = ns.cppnamespace;
|
||||
for (size_t d = 0; d < te.exps.dim; ++d)
|
||||
{
|
||||
expandTuples(te.exps);
|
||||
CPPNamespaceDeclaration current = ns.cppnamespace;
|
||||
for (size_t d = 0; d < te.exps.dim; ++d)
|
||||
auto exp = (*te.exps)[d];
|
||||
auto prev = d ? current : ns.cppnamespace;
|
||||
current = (d + 1) != te.exps.dim
|
||||
? new CPPNamespaceDeclaration(ns.loc, exp, null)
|
||||
: ns;
|
||||
current.exp = exp;
|
||||
current.cppnamespace = prev;
|
||||
if (auto se = exp.toStringExp())
|
||||
{
|
||||
auto exp = (*te.exps)[d];
|
||||
auto prev = d ? current : ns.cppnamespace;
|
||||
current = (d + 1) != te.exps.dim
|
||||
? new CPPNamespaceDeclaration(ns.loc, exp, null)
|
||||
: ns;
|
||||
current.exp = exp;
|
||||
current.cppnamespace = prev;
|
||||
if (auto se = exp.toStringExp())
|
||||
{
|
||||
current.ident = identFromSE(se);
|
||||
if (current.ident is null)
|
||||
return; // An error happened in `identFromSE`
|
||||
}
|
||||
else
|
||||
ns.exp.error("`%s`: index %llu is not a string constant, it is a `%s`",
|
||||
ns.exp.toChars(), cast(ulong) d, ns.exp.type.toChars());
|
||||
current.ident = identFromSE(se);
|
||||
if (current.ident is null)
|
||||
return; // An error happened in `identFromSE`
|
||||
}
|
||||
else
|
||||
ns.exp.error("`%s`: index %llu is not a string constant, it is a `%s`",
|
||||
ns.exp.toChars(), cast(ulong) d, ns.exp.type.toChars());
|
||||
}
|
||||
else if (auto se = ns.exp.toStringExp())
|
||||
ns.ident = identFromSE(se);
|
||||
// Empty Tuple
|
||||
else if (ns.exp.isTypeExp() && ns.exp.isTypeExp().type.toBasetype().isTypeTuple())
|
||||
{
|
||||
}
|
||||
else
|
||||
ns.exp.error("compile time string constant (or tuple) expected, not `%s`",
|
||||
ns.exp.toChars());
|
||||
}
|
||||
else if (auto se = ns.exp.toStringExp())
|
||||
ns.ident = identFromSE(se);
|
||||
// Empty Tuple
|
||||
else if (ns.exp.isTypeExp() && ns.exp.isTypeExp().type.toBasetype().isTypeTuple())
|
||||
{
|
||||
}
|
||||
else
|
||||
ns.exp.error("compile time string constant (or tuple) expected, not `%s`",
|
||||
ns.exp.toChars());
|
||||
attribSemantic(ns);
|
||||
}
|
||||
|
||||
|
@ -2174,7 +2190,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
|
||||
em.semanticRun = PASS.semantic;
|
||||
em.type = Type.tint32;
|
||||
em.linkage = LINK.c;
|
||||
em._linkage = LINK.c;
|
||||
em.storage_class |= STC.manifest;
|
||||
if (em.value)
|
||||
{
|
||||
|
@ -2264,7 +2280,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
em.semanticRun = PASS.semantic;
|
||||
|
||||
em.visibility = em.ed.isAnonymous() ? em.ed.visibility : Visibility(Visibility.Kind.public_);
|
||||
em.linkage = LINK.d;
|
||||
em._linkage = LINK.d;
|
||||
em.storage_class |= STC.manifest;
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=9701
|
||||
|
@ -2538,7 +2554,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
Scope* paramscope = sc.push(paramsym);
|
||||
paramscope.stc = 0;
|
||||
|
||||
if (global.params.doDocComments)
|
||||
if (global.params.ddoc.doOutput)
|
||||
{
|
||||
tempdecl.origParameters = new TemplateParameters(tempdecl.parameters.dim);
|
||||
for (size_t i = 0; i < tempdecl.parameters.dim; i++)
|
||||
|
@ -2824,7 +2840,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
*/
|
||||
//if (!sc.func && Module.deferred.dim > deferred_dim) {}
|
||||
|
||||
AggregateDeclaration ad = tm.toParent().isAggregateDeclaration();
|
||||
AggregateDeclaration ad = tm.isMember();
|
||||
if (sc.func && !ad)
|
||||
{
|
||||
tm.semantic2(sc2);
|
||||
|
@ -2855,6 +2871,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
static if (LOG)
|
||||
{
|
||||
printf("+Nspace::semantic('%s')\n", ns.toChars());
|
||||
scope(exit) printf("-Nspace::semantic('%s')\n", ns.toChars());
|
||||
}
|
||||
if (ns._scope)
|
||||
{
|
||||
|
@ -2931,36 +2948,34 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
// Link does not matter here, if the UDA is present it will error
|
||||
UserAttributeDeclaration.checkGNUABITag(ns, LINK.cpp);
|
||||
|
||||
if (ns.members)
|
||||
if (!ns.members)
|
||||
{
|
||||
assert(sc);
|
||||
sc = sc.push(ns);
|
||||
sc.linkage = LINK.cpp; // note that namespaces imply C++ linkage
|
||||
sc.parent = ns;
|
||||
foreach (s; *ns.members)
|
||||
{
|
||||
if (repopulateMembers)
|
||||
{
|
||||
s.addMember(sc, sc.scopesym);
|
||||
s.setScope(sc);
|
||||
}
|
||||
s.importAll(sc);
|
||||
}
|
||||
foreach (s; *ns.members)
|
||||
{
|
||||
static if (LOG)
|
||||
{
|
||||
printf("\tmember '%s', kind = '%s'\n", s.toChars(), s.kind());
|
||||
}
|
||||
s.dsymbolSemantic(sc);
|
||||
}
|
||||
sc.pop();
|
||||
ns.semanticRun = PASS.semanticdone;
|
||||
return;
|
||||
}
|
||||
assert(sc);
|
||||
sc = sc.push(ns);
|
||||
sc.linkage = LINK.cpp; // note that namespaces imply C++ linkage
|
||||
sc.parent = ns;
|
||||
foreach (s; *ns.members)
|
||||
{
|
||||
if (repopulateMembers)
|
||||
{
|
||||
s.addMember(sc, sc.scopesym);
|
||||
s.setScope(sc);
|
||||
}
|
||||
s.importAll(sc);
|
||||
}
|
||||
foreach (s; *ns.members)
|
||||
{
|
||||
static if (LOG)
|
||||
{
|
||||
printf("\tmember '%s', kind = '%s'\n", s.toChars(), s.kind());
|
||||
}
|
||||
s.dsymbolSemantic(sc);
|
||||
}
|
||||
sc.pop();
|
||||
ns.semanticRun = PASS.semanticdone;
|
||||
static if (LOG)
|
||||
{
|
||||
printf("-Nspace::semantic('%s')\n", ns.toChars());
|
||||
}
|
||||
}
|
||||
|
||||
void funcDeclarationSemantic(FuncDeclaration funcdecl)
|
||||
|
@ -3024,7 +3039,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
if (sc.flags & SCOPE.compile)
|
||||
funcdecl.flags |= FUNCFLAG.compileTimeOnly; // don't emit code for this function
|
||||
|
||||
funcdecl.linkage = sc.linkage;
|
||||
funcdecl._linkage = sc.linkage;
|
||||
if (auto fld = funcdecl.isFuncLiteralDeclaration())
|
||||
{
|
||||
if (fld.treq)
|
||||
|
@ -3037,7 +3052,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
fld.tok = TOK.function_;
|
||||
else
|
||||
assert(0);
|
||||
funcdecl.linkage = treq.nextOf().toTypeFunction().linkage;
|
||||
funcdecl._linkage = treq.nextOf().toTypeFunction().linkage;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3045,19 +3060,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
if (auto pragmadecl = sc.inlining)
|
||||
funcdecl.inlining = pragmadecl.evalPragmaInline(sc);
|
||||
|
||||
// check pragma(crt_constructor)
|
||||
if (funcdecl.flags & (FUNCFLAG.CRTCtor | FUNCFLAG.CRTDtor))
|
||||
{
|
||||
if (funcdecl.linkage != LINK.c)
|
||||
{
|
||||
funcdecl.error("must be `extern(C)` for `pragma(%s)`",
|
||||
(funcdecl.flags & FUNCFLAG.CRTCtor) ? "crt_constructor".ptr : "crt_destructor".ptr);
|
||||
}
|
||||
}
|
||||
|
||||
funcdecl.visibility = sc.visibility;
|
||||
funcdecl.userAttribDecl = sc.userAttribDecl;
|
||||
UserAttributeDeclaration.checkGNUABITag(funcdecl, funcdecl.linkage);
|
||||
UserAttributeDeclaration.checkGNUABITag(funcdecl, funcdecl._linkage);
|
||||
checkMustUseReserved(funcdecl);
|
||||
|
||||
if (!funcdecl.originalType)
|
||||
|
@ -3193,7 +3198,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
tf.isScopeQual = false;
|
||||
}
|
||||
|
||||
sc.linkage = funcdecl.linkage;
|
||||
sc.linkage = funcdecl._linkage;
|
||||
|
||||
if (!tf.isNaked() && !(funcdecl.isThis() || funcdecl.isNested()))
|
||||
{
|
||||
|
@ -3243,6 +3248,16 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
funcdecl.storage_class &= ~(STC.TYPECTOR | STC.FUNCATTR);
|
||||
}
|
||||
|
||||
// check pragma(crt_constructor) signature
|
||||
if (funcdecl.flags & (FUNCFLAG.CRTCtor | FUNCFLAG.CRTDtor))
|
||||
{
|
||||
const idStr = (funcdecl.flags & FUNCFLAG.CRTCtor) ? "crt_constructor" : "crt_destructor";
|
||||
if (f.nextOf().ty != Tvoid)
|
||||
funcdecl.error("must return `void` for `pragma(%s)`", idStr.ptr);
|
||||
if (funcdecl._linkage != LINK.c && f.parameterList.length != 0)
|
||||
funcdecl.error("must be `extern(C)` for `pragma(%s)` when taking parameters", idStr.ptr);
|
||||
}
|
||||
|
||||
if (funcdecl.overnext && funcdecl.isCsymbol())
|
||||
{
|
||||
/* C does not allow function overloading, but it does allow
|
||||
|
@ -4027,67 +4042,67 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
*/
|
||||
if (ad && (!ctd.parent.isTemplateInstance() || ctd.parent.isTemplateMixin()))
|
||||
{
|
||||
if (sd)
|
||||
if (!sd)
|
||||
{
|
||||
if (dim == 0 && tf.parameterList.varargs == VarArg.none) // empty default ctor w/o any varargs
|
||||
{
|
||||
if (ctd.fbody || !(ctd.storage_class & STC.disable))
|
||||
{
|
||||
ctd.error("default constructor for structs only allowed " ~
|
||||
"with `@disable`, no body, and no parameters");
|
||||
ctd.storage_class |= STC.disable;
|
||||
ctd.fbody = null;
|
||||
}
|
||||
sd.noDefaultCtor = true;
|
||||
}
|
||||
else if (dim == 0 && tf.parameterList.varargs != VarArg.none) // allow varargs only ctor
|
||||
{
|
||||
}
|
||||
else if (dim && tf.parameterList[0].defaultArg)
|
||||
{
|
||||
// if the first parameter has a default argument, then the rest does as well
|
||||
if (ctd.storage_class & STC.disable)
|
||||
{
|
||||
ctd.error("is marked `@disable`, so it cannot have default "~
|
||||
"arguments for all parameters.");
|
||||
errorSupplemental(ctd.loc, "Use `@disable this();` if you want to disable default initialization.");
|
||||
}
|
||||
else
|
||||
ctd.error("all parameters have default arguments, "~
|
||||
"but structs cannot have default constructors.");
|
||||
}
|
||||
else if ((dim == 1 || (dim > 1 && tf.parameterList[1].defaultArg)))
|
||||
{
|
||||
//printf("tf: %s\n", tf.toChars());
|
||||
auto param = tf.parameterList[0];
|
||||
if (param.storageClass & STC.ref_ && param.type.mutableOf().unSharedOf() == sd.type.mutableOf().unSharedOf())
|
||||
{
|
||||
//printf("copy constructor\n");
|
||||
ctd.isCpCtor = true;
|
||||
}
|
||||
}
|
||||
if (dim == 0 && tf.parameterList.varargs == VarArg.none)
|
||||
ad.defaultCtor = ctd;
|
||||
return;
|
||||
}
|
||||
else if (dim == 0 && tf.parameterList.varargs == VarArg.none)
|
||||
|
||||
if (dim == 0 && tf.parameterList.varargs == VarArg.none) // empty default ctor w/o any varargs
|
||||
{
|
||||
ad.defaultCtor = ctd;
|
||||
if (ctd.fbody || !(ctd.storage_class & STC.disable))
|
||||
{
|
||||
ctd.error("default constructor for structs only allowed " ~
|
||||
"with `@disable`, no body, and no parameters");
|
||||
ctd.storage_class |= STC.disable;
|
||||
ctd.fbody = null;
|
||||
}
|
||||
sd.noDefaultCtor = true;
|
||||
}
|
||||
else if (dim == 0 && tf.parameterList.varargs != VarArg.none) // allow varargs only ctor
|
||||
{
|
||||
}
|
||||
else if (dim && tf.parameterList[0].defaultArg)
|
||||
{
|
||||
// if the first parameter has a default argument, then the rest does as well
|
||||
if (ctd.storage_class & STC.disable)
|
||||
{
|
||||
ctd.error("is marked `@disable`, so it cannot have default "~
|
||||
"arguments for all parameters.");
|
||||
errorSupplemental(ctd.loc, "Use `@disable this();` if you want to disable default initialization.");
|
||||
}
|
||||
else
|
||||
ctd.error("all parameters have default arguments, "~
|
||||
"but structs cannot have default constructors.");
|
||||
}
|
||||
else if ((dim == 1 || (dim > 1 && tf.parameterList[1].defaultArg)))
|
||||
{
|
||||
//printf("tf: %s\n", tf.toChars());
|
||||
auto param = tf.parameterList[0];
|
||||
if (param.storageClass & STC.ref_ && param.type.mutableOf().unSharedOf() == sd.type.mutableOf().unSharedOf())
|
||||
{
|
||||
//printf("copy constructor\n");
|
||||
ctd.isCpCtor = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// https://issues.dlang.org/show_bug.cgi?id=22593
|
||||
else if (auto ti = ctd.parent.isTemplateInstance())
|
||||
{
|
||||
if (sd && sd.hasCopyCtor && (dim == 1 || (dim > 1 && tf.parameterList[1].defaultArg)))
|
||||
{
|
||||
auto param = tf.parameterList[0];
|
||||
if (!sd || !sd.hasCopyCtor || !(dim == 1 || (dim > 1 && tf.parameterList[1].defaultArg)))
|
||||
return;
|
||||
|
||||
// if the template instance introduces an rvalue constructor
|
||||
// between the members of a struct declaration, we should check if a
|
||||
// copy constructor exists and issue an error in that case.
|
||||
if (!(param.storageClass & STC.ref_) && param.type.mutableOf().unSharedOf() == sd.type.mutableOf().unSharedOf())
|
||||
{
|
||||
.error(ctd.loc, "Cannot define both an rvalue constructor and a copy constructor for `struct %s`", sd.toChars);
|
||||
.errorSupplemental(ti.loc, "Template instance `%s` creates a rvalue constructor for `struct %s`",
|
||||
ti.toChars(), sd.toChars());
|
||||
}
|
||||
auto param = tf.parameterList[0];
|
||||
|
||||
// if the template instance introduces an rvalue constructor
|
||||
// between the members of a struct declaration, we should check if a
|
||||
// copy constructor exists and issue an error in that case.
|
||||
if (!(param.storageClass & STC.ref_) && param.type.mutableOf().unSharedOf() == sd.type.mutableOf().unSharedOf())
|
||||
{
|
||||
.error(ctd.loc, "cannot define both an rvalue constructor and a copy constructor for `struct %s`", sd.toChars);
|
||||
.errorSupplemental(ti.loc, "Template instance `%s` creates a rvalue constructor for `struct %s`",
|
||||
ti.toChars(), sd.toChars());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6417,13 +6432,8 @@ void aliasSemantic(AliasDeclaration ds, Scope* sc)
|
|||
ds.visibility = sc.visibility;
|
||||
ds.userAttribDecl = sc.userAttribDecl;
|
||||
|
||||
// TypeTraits needs to know if it's located in an AliasDeclaration
|
||||
const oldflags = sc.flags;
|
||||
sc.flags |= SCOPE.alias_;
|
||||
|
||||
void normalRet()
|
||||
{
|
||||
sc.flags = oldflags;
|
||||
ds.inuse = 0;
|
||||
ds.semanticRun = PASS.semanticdone;
|
||||
|
||||
|
|
|
@ -2777,7 +2777,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
|
|||
fd.storage_class == m.lastf.storage_class &&
|
||||
fd.parent == m.lastf.parent &&
|
||||
fd.visibility == m.lastf.visibility &&
|
||||
fd.linkage == m.lastf.linkage)
|
||||
fd._linkage == m.lastf._linkage)
|
||||
{
|
||||
if (fd.fbody && !m.lastf.fbody)
|
||||
goto LfIsBetter;
|
||||
|
|
|
@ -82,7 +82,7 @@ extern(C++) void genCppHdrFiles(ref Modules ms)
|
|||
foreach (m; ms)
|
||||
m.accept(v);
|
||||
|
||||
if (global.params.doCxxHdrGeneration == CxxHeaderMode.verbose)
|
||||
if (global.params.cxxhdr.fullOutput)
|
||||
buf.printf("// Automatically generated by %s Compiler v%d", global.vendor.ptr, global.versionNumber());
|
||||
else
|
||||
buf.printf("// Automatically generated by %s Compiler", global.vendor.ptr);
|
||||
|
@ -92,9 +92,9 @@ extern(C++) void genCppHdrFiles(ref Modules ms)
|
|||
buf.writestringln("#pragma once");
|
||||
buf.writenl();
|
||||
hashInclude(buf, "<assert.h>");
|
||||
hashInclude(buf, "<math.h>");
|
||||
hashInclude(buf, "<stddef.h>");
|
||||
hashInclude(buf, "<stdint.h>");
|
||||
hashInclude(buf, "<math.h>");
|
||||
// buf.writestring(buf, "#include <stdio.h>\n");
|
||||
// buf.writestring("#include <string.h>\n");
|
||||
|
||||
|
@ -189,7 +189,7 @@ struct _d_dynamicArray final
|
|||
buf.remove(buf.length - 1, 1);
|
||||
|
||||
|
||||
if (global.params.cxxhdrname is null)
|
||||
if (global.params.cxxhdr.name is null)
|
||||
{
|
||||
// Write to stdout; assume it succeeds
|
||||
size_t n = fwrite(buf[].ptr, 1, buf.length, stdout);
|
||||
|
@ -197,7 +197,7 @@ struct _d_dynamicArray final
|
|||
}
|
||||
else
|
||||
{
|
||||
const(char)[] name = FileName.combine(global.params.cxxhdrdir, global.params.cxxhdrname);
|
||||
const(char)[] name = FileName.combine(global.params.cxxhdr.dir, global.params.cxxhdr.name);
|
||||
writeFile(Loc.initial, name, buf[]);
|
||||
}
|
||||
}
|
||||
|
@ -297,7 +297,7 @@ public:
|
|||
this.fwdbuf = fwdbuf;
|
||||
this.donebuf = donebuf;
|
||||
this.buf = buf;
|
||||
this.printIgnored = global.params.doCxxHdrGeneration == CxxHeaderMode.verbose;
|
||||
this.printIgnored = global.params.cxxhdr.fullOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -966,12 +966,13 @@ public:
|
|||
if (vd.storage_class & (AST.STC.static_ | AST.STC.extern_ | AST.STC.gshared) ||
|
||||
vd.parent && vd.parent.isModule())
|
||||
{
|
||||
if (vd.linkage != LINK.c && vd.linkage != LINK.cpp && !(tdparent && (this.linkage == LINK.c || this.linkage == LINK.cpp)))
|
||||
const vdLinkage = vd.resolvedLinkage();
|
||||
if (vdLinkage != LINK.c && vdLinkage != LINK.cpp && !(tdparent && (this.linkage == LINK.c || this.linkage == LINK.cpp)))
|
||||
{
|
||||
ignored("variable %s because of linkage", vd.toPrettyChars());
|
||||
return;
|
||||
}
|
||||
if (vd.mangleOverride && vd.linkage != LINK.c)
|
||||
if (vd.mangleOverride && vdLinkage != LINK.c)
|
||||
{
|
||||
ignored("variable %s because C++ doesn't support explicit mangling", vd.toPrettyChars());
|
||||
return;
|
||||
|
@ -987,7 +988,7 @@ public:
|
|||
return;
|
||||
}
|
||||
writeProtection(vd.visibility.kind);
|
||||
if (vd.linkage == LINK.c)
|
||||
if (vdLinkage == LINK.c)
|
||||
buf.writestring("extern \"C\" ");
|
||||
else if (!adparent)
|
||||
buf.writestring("extern ");
|
||||
|
@ -2302,7 +2303,7 @@ public:
|
|||
this.forwarding = fwdStash;
|
||||
}
|
||||
|
||||
if (p.storageClass & AST.STC.ref_)
|
||||
if (p.storageClass & (AST.STC.ref_ | AST.STC.out_))
|
||||
buf.writeByte('&');
|
||||
buf.writeByte(' ');
|
||||
if (ident)
|
||||
|
@ -2805,7 +2806,10 @@ public:
|
|||
|
||||
// Check against the internal information which might be missing, e.g. inside of template declarations
|
||||
if (auto dec = sym.isDeclaration())
|
||||
return dec.linkage == LINK.cpp || dec.linkage == LINK.c;
|
||||
{
|
||||
const l = dec.resolvedLinkage();
|
||||
return l == LINK.cpp || l == LINK.c;
|
||||
}
|
||||
|
||||
if (auto ad = sym.isAggregateDeclaration())
|
||||
return ad.classKind == ClassKind.cpp;
|
||||
|
@ -2853,8 +2857,11 @@ public:
|
|||
if (!res)
|
||||
{
|
||||
// Check against the internal information which might be missing, e.g. inside of template declarations
|
||||
auto dec = sym.isDeclaration();
|
||||
res = dec && (dec.linkage == LINK.cpp || dec.linkage == LINK.c);
|
||||
if (auto dec = sym.isDeclaration())
|
||||
{
|
||||
const l = dec.resolvedLinkage();
|
||||
res = (l == LINK.cpp || l == LINK.c);
|
||||
}
|
||||
}
|
||||
|
||||
// Remember result for later calls
|
||||
|
|
1643
gcc/d/dmd/escape.d
1643
gcc/d/dmd/escape.d
File diff suppressed because it is too large
Load diff
|
@ -1370,10 +1370,9 @@ extern (C++) abstract class Expression : ASTNode
|
|||
*/
|
||||
if (v.storage_class & STC.gshared)
|
||||
{
|
||||
if (sc.func.setUnsafe())
|
||||
if (sc.func.setUnsafe(false, this.loc,
|
||||
"`@safe` function `%s` cannot access `__gshared` data `%s`", sc.func, v))
|
||||
{
|
||||
error("`@safe` %s `%s` cannot access `__gshared` data `%s`",
|
||||
sc.func.kind(), sc.func.toChars(), v.toChars());
|
||||
err = true;
|
||||
}
|
||||
}
|
||||
|
@ -1411,7 +1410,7 @@ extern (C++) abstract class Expression : ASTNode
|
|||
|
||||
if (!f.isSafe() && !f.isTrusted())
|
||||
{
|
||||
if (sc.flags & SCOPE.compile ? sc.func.isSafeBypassingInference() : sc.func.setUnsafe())
|
||||
if (sc.flags & SCOPE.compile ? sc.func.isSafeBypassingInference() : sc.func.setUnsafeCall(f))
|
||||
{
|
||||
if (!loc.isValid()) // e.g. implicitly generated dtor
|
||||
loc = sc.func.loc;
|
||||
|
@ -1420,6 +1419,7 @@ extern (C++) abstract class Expression : ASTNode
|
|||
error("`@safe` %s `%s` cannot call `@system` %s `%s`",
|
||||
sc.func.kind(), sc.func.toPrettyChars(), f.kind(),
|
||||
prettyChars);
|
||||
f.errorSupplementalInferredSafety(/*max depth*/ 10);
|
||||
.errorSupplemental(f.loc, "`%s` is declared here", prettyChars);
|
||||
|
||||
checkOverridenDtor(sc, f, dd => dd.type.toTypeFunction().trust > TRUST.system, "@system");
|
||||
|
@ -1456,7 +1456,8 @@ extern (C++) abstract class Expression : ASTNode
|
|||
|
||||
// Lowered non-@nogc'd hooks will print their own error message inside of nogc.d (NOGCVisitor.visit(CallExp e)),
|
||||
// so don't print anything to avoid double error messages.
|
||||
if (!(f.ident == Id._d_HookTraceImpl || f.ident == Id._d_arraysetlengthT))
|
||||
if (!(f.ident == Id._d_HookTraceImpl || f.ident == Id._d_arraysetlengthT
|
||||
|| f.ident == Id._d_arrayappendT || f.ident == Id._d_arrayappendcTX))
|
||||
error("`@nogc` %s `%s` cannot call non-@nogc %s `%s`",
|
||||
sc.func.kind(), sc.func.toPrettyChars(), f.kind(), f.toPrettyChars());
|
||||
|
||||
|
@ -5760,9 +5761,8 @@ extern (C++) final class DelegatePtrExp : UnaExp
|
|||
|
||||
override Expression modifiableLvalue(Scope* sc, Expression e)
|
||||
{
|
||||
if (sc.func.setUnsafe())
|
||||
if (sc.func.setUnsafe(false, this.loc, "cannot modify delegate pointer in `@safe` code `%s`", this))
|
||||
{
|
||||
error("cannot modify delegate pointer in `@safe` code `%s`", toChars());
|
||||
return ErrorExp.get();
|
||||
}
|
||||
return Expression.modifiableLvalue(sc, e);
|
||||
|
@ -5799,9 +5799,8 @@ extern (C++) final class DelegateFuncptrExp : UnaExp
|
|||
|
||||
override Expression modifiableLvalue(Scope* sc, Expression e)
|
||||
{
|
||||
if (sc.func.setUnsafe())
|
||||
if (sc.func.setUnsafe(false, this.loc, "cannot modify delegate function pointer in `@safe` code `%s`", this))
|
||||
{
|
||||
error("cannot modify delegate function pointer in `@safe` code `%s`", toChars());
|
||||
return ErrorExp.get();
|
||||
}
|
||||
return Expression.modifiableLvalue(sc, e);
|
||||
|
|
|
@ -1276,7 +1276,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
|
|||
// @@@DEPRECATED_2.105@@@
|
||||
// When turning into error, uncomment the return statement
|
||||
TypeFunction tf = fd.type.isTypeFunction();
|
||||
deprecation(loc, "Function `%s` of type `%s` is not accessible from module `%s`",
|
||||
deprecation(loc, "function `%s` of type `%s` is not accessible from module `%s`",
|
||||
fd.toPrettyChars(), tf.toChars, sc._module.toChars);
|
||||
//return ErrorExp.get();
|
||||
}
|
||||
|
@ -1298,7 +1298,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
|
|||
{
|
||||
// @@@DEPRECATED_2.105@@@
|
||||
// When turning into error, uncomment the return statement
|
||||
deprecation(loc, "Function `%s` of type `%s` is not accessible from module `%s`",
|
||||
deprecation(loc, "function `%s` of type `%s` is not accessible from module `%s`",
|
||||
fd.toPrettyChars(), tf.toChars, sc._module.toChars);
|
||||
//return ErrorExp.get();
|
||||
}
|
||||
|
@ -2035,20 +2035,26 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
|
|||
/* Argument value can be assigned to firstArg.
|
||||
* Check arg to see if it matters.
|
||||
*/
|
||||
if (global.params.useDIP1000 == FeatureState.enabled)
|
||||
err |= checkParamArgumentReturn(sc, firstArg, arg, p, false);
|
||||
err |= checkParamArgumentReturn(sc, firstArg, arg, p, false);
|
||||
}
|
||||
// Allow 'lazy' to imply 'scope' - lazy parameters can be passed along
|
||||
// as lazy parameters to the next function, but that isn't escaping.
|
||||
else if (!(pStc & (STC.scope_ | STC.lazy_)))
|
||||
else if (!(pStc & STC.lazy_))
|
||||
{
|
||||
/* Argument value can escape from the called function.
|
||||
* Check arg to see if it matters.
|
||||
*/
|
||||
if (global.params.useDIP1000 == FeatureState.enabled)
|
||||
err |= checkParamArgumentEscape(sc, fd, p, arg, false, false);
|
||||
err |= checkParamArgumentEscape(sc, fd, p, cast(STC) pStc, arg, false, false);
|
||||
}
|
||||
else if (!(pStc & STC.return_))
|
||||
|
||||
// Turning heap allocations into stack allocations is dangerous without dip1000, since `scope` inference
|
||||
// may be unreliable when scope violations only manifest as deprecation warnings.
|
||||
// However, existing `@nogc` code may rely on it, so still do it when the parameter is explicitly marked `scope`
|
||||
const explicitScope = (p.storageClass & STC.lazy_) ||
|
||||
((p.storageClass & STC.scope_) && !(p.storageClass & STC.scopeinferred));
|
||||
if ((pStc & (STC.scope_ | STC.lazy_)) &&
|
||||
((global.params.useDIP1000 == FeatureState.enabled) || explicitScope) &&
|
||||
!(pStc & STC.return_))
|
||||
{
|
||||
/* Argument value cannot escape from the called function.
|
||||
*/
|
||||
|
@ -2058,13 +2064,14 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
|
|||
|
||||
ArrayLiteralExp ale;
|
||||
if (p.type.toBasetype().ty == Tarray &&
|
||||
(ale = a.isArrayLiteralExp()) !is null)
|
||||
(ale = a.isArrayLiteralExp()) !is null && ale.elements && ale.elements.length > 0)
|
||||
{
|
||||
// allocate the array literal as temporary static array on the stack
|
||||
ale.type = ale.type.nextOf().sarrayOf(ale.elements ? ale.elements.length : 0);
|
||||
ale.type = ale.type.nextOf().sarrayOf(ale.elements.length);
|
||||
auto tmp = copyToTemp(0, "__arrayliteral_on_stack", ale);
|
||||
auto declareTmp = new DeclarationExp(ale.loc, tmp);
|
||||
auto castToSlice = new CastExp(ale.loc, new VarExp(ale.loc, tmp), p.type);
|
||||
auto castToSlice = new CastExp(ale.loc, new VarExp(ale.loc, tmp),
|
||||
p.type.substWildTo(MODFlags.mutable));
|
||||
arg = CommaExp.combine(declareTmp, castToSlice);
|
||||
arg = arg.expressionSemantic(sc);
|
||||
}
|
||||
|
@ -2473,7 +2480,7 @@ Package resolveIsPackage(Dsymbol sym)
|
|||
{
|
||||
if (imp.pkg is null)
|
||||
{
|
||||
.error(sym.loc, "Internal Compiler Error: unable to process forward-referenced import `%s`",
|
||||
.error(sym.loc, "internal compiler error: unable to process forward-referenced import `%s`",
|
||||
imp.toChars());
|
||||
assert(0);
|
||||
}
|
||||
|
@ -2995,7 +3002,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
buffer.write4(0);
|
||||
e.setData(buffer.extractData(), newlen, 4);
|
||||
if (sc && sc.flags & SCOPE.Cfile)
|
||||
e.type = Type.tuns32.pointerTo();
|
||||
e.type = Type.tuns32.sarrayOf(e.len + 1);
|
||||
else
|
||||
e.type = Type.tdchar.immutableOf().arrayOf();
|
||||
e.committed = 1;
|
||||
|
@ -3020,7 +3027,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
buffer.writeUTF16(0);
|
||||
e.setData(buffer.extractData(), newlen, 2);
|
||||
if (sc && sc.flags & SCOPE.Cfile)
|
||||
e.type = Type.tuns16.pointerTo();
|
||||
e.type = Type.tuns16.sarrayOf(e.len + 1);
|
||||
else
|
||||
e.type = Type.twchar.immutableOf().arrayOf();
|
||||
e.committed = 1;
|
||||
|
@ -3032,7 +3039,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
|
||||
default:
|
||||
if (sc && sc.flags & SCOPE.Cfile)
|
||||
e.type = Type.tchar.pointerTo();
|
||||
e.type = Type.tchar.sarrayOf(e.len + 1);
|
||||
else
|
||||
e.type = Type.tchar.immutableOf().arrayOf();
|
||||
break;
|
||||
|
@ -3170,11 +3177,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
|
||||
semanticTypeInfo(sc, e.type);
|
||||
|
||||
if (global.params.useDIP1000 == FeatureState.enabled)
|
||||
{
|
||||
if (checkAssocArrayLiteralEscape(sc, e, false))
|
||||
return setError();
|
||||
}
|
||||
if (checkAssocArrayLiteralEscape(sc, e, false))
|
||||
return setError();
|
||||
|
||||
result = e;
|
||||
}
|
||||
|
@ -3261,7 +3265,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
// to fix https://issues.dlang.org/show_bug.cgi?id=9490
|
||||
VarExp ve = e.isVarExp();
|
||||
if (ve && ve.var && exp.parens && !ve.var.isStatic() && !(sc.stc & STC.static_) &&
|
||||
sc.func && sc.func.needThis && ve.var.toParent2().isAggregateDeclaration())
|
||||
sc.func && sc.func.needThis && ve.var.isMember2())
|
||||
{
|
||||
// printf("apply fix for issue 9490: add `this.` to `%s`...\n", e.toChars());
|
||||
e = new DotVarExp(exp.loc, new ThisExp(exp.loc), ve.var, false);
|
||||
|
@ -3782,13 +3786,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
|
||||
/* Since a `new` allocation may escape, check each of the arguments for escaping
|
||||
*/
|
||||
if (global.params.useDIP1000 == FeatureState.enabled)
|
||||
foreach (arg; *exp.arguments)
|
||||
{
|
||||
foreach (arg; *exp.arguments)
|
||||
{
|
||||
if (arg && checkNewEscape(sc, arg, false))
|
||||
return setError();
|
||||
}
|
||||
if (arg && checkNewEscape(sc, arg, false))
|
||||
return setError();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4677,7 +4678,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
}
|
||||
if (exp.f.needThis())
|
||||
{
|
||||
AggregateDeclaration ad = exp.f.toParentLocal().isAggregateDeclaration();
|
||||
AggregateDeclaration ad = exp.f.isMemberLocal();
|
||||
ue.e1 = getRightThis(exp.loc, sc, ad, ue.e1, exp.f);
|
||||
if (ue.e1.op == EXP.error)
|
||||
{
|
||||
|
@ -4688,7 +4689,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
tthis = ue.e1.type;
|
||||
if (!(exp.f.type.ty == Tfunction && (cast(TypeFunction)exp.f.type).isScopeQual))
|
||||
{
|
||||
if (global.params.useDIP1000 == FeatureState.enabled && checkParamArgumentEscape(sc, exp.f, null, ethis, false, false))
|
||||
if (checkParamArgumentEscape(sc, exp.f, null, STC.undefined_, ethis, false, false))
|
||||
return setError();
|
||||
}
|
||||
}
|
||||
|
@ -5393,7 +5394,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
{
|
||||
if (tb.toDsymbol(sc).isClassDeclaration().classKind == ClassKind.cpp)
|
||||
{
|
||||
error(exp.loc, "Runtime type information is not supported for `extern(C++)` classes");
|
||||
error(exp.loc, "runtime type information is not supported for `extern(C++)` classes");
|
||||
e = ErrorExp.get();
|
||||
}
|
||||
else if (!Type.typeinfoclass)
|
||||
|
@ -6026,18 +6027,18 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
const slice = se.peekString();
|
||||
message("file %.*s\t(%s)", cast(int)slice.length, slice.ptr, name);
|
||||
}
|
||||
if (global.params.moduleDeps !is null)
|
||||
if (global.params.moduleDeps.buffer !is null)
|
||||
{
|
||||
OutBuffer* ob = global.params.moduleDeps;
|
||||
OutBuffer* ob = global.params.moduleDeps.buffer;
|
||||
Module imod = sc._module;
|
||||
|
||||
if (!global.params.moduleDepsFile)
|
||||
if (!global.params.moduleDeps.name)
|
||||
ob.writestring("depsFile ");
|
||||
ob.writestring(imod.toPrettyChars());
|
||||
ob.writestring(" (");
|
||||
escapePath(ob, imod.srcfile.toChars());
|
||||
ob.writestring(") : ");
|
||||
if (global.params.moduleDepsFile)
|
||||
if (global.params.moduleDeps.name)
|
||||
ob.writestring("string : ");
|
||||
ob.write(se.peekString());
|
||||
ob.writestring(" (");
|
||||
|
@ -6045,9 +6046,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
ob.writestring(")");
|
||||
ob.writenl();
|
||||
}
|
||||
if (global.params.emitMakeDeps)
|
||||
if (global.params.makeDeps.doOutput)
|
||||
{
|
||||
global.params.makeDeps.push(name);
|
||||
global.params.makeDeps.files.push(name);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -6349,7 +6350,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
exp.msg = resolveProperties(sc, exp.msg);
|
||||
exp.msg = exp.msg.implicitCastTo(sc, Type.tchar.constOf().arrayOf());
|
||||
exp.msg = exp.msg.optimize(WANTvalue);
|
||||
checkParamArgumentEscape(sc, null, null, exp.msg, true, false);
|
||||
checkParamArgumentEscape(sc, null, null, STC.undefined_, exp.msg, true, false);
|
||||
}
|
||||
|
||||
if (exp.msg && exp.msg.op == EXP.error)
|
||||
|
@ -6625,6 +6626,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
|
||||
exp.type = exp.type.addMod(t1.mod);
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=23109
|
||||
// Run semantic on the DotVarExp type
|
||||
if (auto handle = exp.type.isClassHandle())
|
||||
{
|
||||
if (handle.semanticRun < PASS.semanticdone && !handle.isBaseInfoComplete())
|
||||
handle.dsymbolSemantic(null);
|
||||
}
|
||||
|
||||
Dsymbol vparent = exp.var.toParent();
|
||||
AggregateDeclaration ad = vparent ? vparent.isAggregateDeclaration() : null;
|
||||
if (Expression e1x = getRightThis(exp.loc, sc, ad, exp.e1, exp.var, 1))
|
||||
|
@ -6705,24 +6714,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
e.type = e.type.typeSemantic(e.loc, sc);
|
||||
|
||||
FuncDeclaration f = e.func.toAliasFunc();
|
||||
AggregateDeclaration ad = f.toParentLocal().isAggregateDeclaration();
|
||||
AggregateDeclaration ad = f.isMemberLocal();
|
||||
if (f.needThis())
|
||||
e.e1 = getRightThis(e.loc, sc, ad, e.e1, f);
|
||||
if (e.e1.op == EXP.error)
|
||||
return setError();
|
||||
|
||||
/* A delegate takes the address of e.e1 in order to set the .ptr field
|
||||
* https://issues.dlang.org/show_bug.cgi?id=18575
|
||||
*/
|
||||
if (global.params.useDIP1000 == FeatureState.enabled && e.e1.type.toBasetype().ty == Tstruct)
|
||||
{
|
||||
if (auto v = expToVariable(e.e1))
|
||||
{
|
||||
if (!checkAddressVar(sc, e.e1, v))
|
||||
return setError();
|
||||
}
|
||||
}
|
||||
|
||||
if (f.type.ty == Tfunction)
|
||||
{
|
||||
TypeFunction tf = cast(TypeFunction)f.type;
|
||||
|
@ -6809,20 +6806,26 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
|
||||
if (sc.flags & SCOPE.Cfile)
|
||||
{
|
||||
/* Special handling for &"string"
|
||||
* since C regards a string literal as an lvalue
|
||||
/* Special handling for &"string"/&(T[]){0, 1}
|
||||
* since C regards string/array literals as lvalues
|
||||
*/
|
||||
if (auto se = exp.e1.isStringExp())
|
||||
auto e = exp.e1;
|
||||
if(e.isStringExp() || e.isArrayLiteralExp())
|
||||
{
|
||||
if (auto tp = se.type.toBasetype().isTypePointer())
|
||||
e.type = typeSemantic(e.type, Loc.initial, sc);
|
||||
// if type is already a pointer exp is an illegal expression of the form `&(&"")`
|
||||
if (!e.type.isTypePointer())
|
||||
{
|
||||
/* Switch from pointer-to-char to pointer-to-static-array-of-char
|
||||
*/
|
||||
auto ts = new TypeSArray(tp.nextOf(), new IntegerExp(Loc.initial, se.len + 1, Type.tsize_t));
|
||||
se.type = typeSemantic(ts, Loc.initial, sc).pointerTo();
|
||||
result = se;
|
||||
e.type = e.type.pointerTo();
|
||||
result = e;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// `toLvalue` call further below is upon exp.e1, omitting & from the error message
|
||||
exp.toLvalue(sc, null);
|
||||
return setError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6891,19 +6894,19 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
* because it might end up being a pointer to undefined
|
||||
* memory.
|
||||
*/
|
||||
if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
|
||||
if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_))
|
||||
{
|
||||
exp.error("cannot take address of lazy parameter `%s` in `@safe` function `%s`",
|
||||
ve.toChars(), sc.func.toChars());
|
||||
setError();
|
||||
}
|
||||
else
|
||||
{
|
||||
VarExp ve2 = callExp.e1.isVarExp();
|
||||
ve2.delegateWasExtracted = true;
|
||||
ve2.var.storage_class |= STC.scope_;
|
||||
result = ve2;
|
||||
if (sc.func.setUnsafe(false, exp.loc,
|
||||
"cannot take address of lazy parameter `%s` in `@safe` function `%s`", ve, sc.func))
|
||||
{
|
||||
setError();
|
||||
return;
|
||||
}
|
||||
}
|
||||
VarExp ve2 = callExp.e1.isVarExp();
|
||||
ve2.delegateWasExtracted = true;
|
||||
ve2.var.storage_class |= STC.scope_;
|
||||
result = ve2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -6987,15 +6990,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
// Look for misaligned pointer in @safe mode
|
||||
if (checkUnsafeAccess(sc, dve, !exp.type.isMutable(), true))
|
||||
return setError();
|
||||
|
||||
if (global.params.useDIP1000 == FeatureState.enabled)
|
||||
{
|
||||
if (VarDeclaration v = expToVariable(dve.e1))
|
||||
{
|
||||
if (!checkAddressVar(sc, exp.e1, v))
|
||||
return setError();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (exp.e1.op == EXP.variable)
|
||||
{
|
||||
|
@ -7049,29 +7043,15 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
result = e;
|
||||
return;
|
||||
}
|
||||
if (sc.func && !sc.intypeof)
|
||||
if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_))
|
||||
{
|
||||
if (!(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
|
||||
{
|
||||
exp.error("`this` reference necessary to take address of member `%s` in `@safe` function `%s`", f.toChars(), sc.func.toChars());
|
||||
}
|
||||
sc.func.setUnsafe(false, exp.loc,
|
||||
"`this` reference necessary to take address of member `%s` in `@safe` function `%s`",
|
||||
f, sc.func);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((exp.e1.op == EXP.this_ || exp.e1.op == EXP.super_) && global.params.useDIP1000 == FeatureState.enabled)
|
||||
{
|
||||
if (VarDeclaration v = expToVariable(exp.e1))
|
||||
{
|
||||
if (!checkAddressVar(sc, exp.e1, v))
|
||||
return setError();
|
||||
}
|
||||
}
|
||||
else if (auto ce = exp.e1.isCallExp())
|
||||
{
|
||||
if (!checkAddressCall(sc, ce, "take address of"))
|
||||
return setError();
|
||||
}
|
||||
else if (exp.e1.op == EXP.index)
|
||||
{
|
||||
/* For:
|
||||
|
@ -7081,9 +7061,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
*/
|
||||
if (VarDeclaration v = expToVariable(exp.e1))
|
||||
{
|
||||
if (global.params.useDIP1000 == FeatureState.enabled && !checkAddressVar(sc, exp.e1, v))
|
||||
return setError();
|
||||
|
||||
exp.e1.checkPurity(sc, v);
|
||||
}
|
||||
}
|
||||
|
@ -7839,10 +7816,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
|
||||
return setError();
|
||||
}
|
||||
if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
|
||||
if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_))
|
||||
{
|
||||
exp.error("pointer slicing not allowed in safe functions");
|
||||
return setError();
|
||||
if (sc.func.setUnsafe(false, exp.loc, "pointer slicing not allowed in safe functions"))
|
||||
return setError();
|
||||
}
|
||||
}
|
||||
else if (t1b.ty == Tarray)
|
||||
|
@ -7850,34 +7827,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
}
|
||||
else if (t1b.ty == Tsarray)
|
||||
{
|
||||
if (!exp.arrayop && global.params.useDIP1000 == FeatureState.enabled)
|
||||
{
|
||||
/* Slicing a static array is like taking the address of it.
|
||||
* Perform checks as if e[] was &e
|
||||
*/
|
||||
if (VarDeclaration v = expToVariable(exp.e1))
|
||||
{
|
||||
if (DotVarExp dve = exp.e1.isDotVarExp())
|
||||
{
|
||||
|
||||
if ((dve.e1.op == EXP.this_ || dve.e1.op == EXP.super_) &&
|
||||
!(v.storage_class & STC.ref_))
|
||||
{
|
||||
// because it's a class
|
||||
v = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (v && !checkAddressVar(sc, exp.e1, v))
|
||||
return setError();
|
||||
}
|
||||
// https://issues.dlang.org/show_bug.cgi?id=22539
|
||||
if (auto ce = exp.e1.isCallExp())
|
||||
{
|
||||
if (!checkAddressCall(sc, ce, "slice static array of"))
|
||||
return setError();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (t1b.ty == Ttuple)
|
||||
{
|
||||
|
@ -8202,7 +8151,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
discardValue(e.e1);
|
||||
}
|
||||
else if (!e.allowCommaExp && !e.isGenerated)
|
||||
e.error("Using the result of a comma expression is not allowed");
|
||||
e.error("using the result of a comma expression is not allowed");
|
||||
}
|
||||
|
||||
override void visit(IntervalExp e)
|
||||
|
@ -8379,10 +8328,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
if (exp.e2.op == EXP.int64 && exp.e2.toInteger() == 0)
|
||||
{
|
||||
}
|
||||
else if (sc.func && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
|
||||
else if (sc.func && !(sc.flags & SCOPE.debug_))
|
||||
{
|
||||
exp.error("safe function `%s` cannot index pointer `%s`", sc.func.toPrettyChars(), exp.e1.toChars());
|
||||
return setError();
|
||||
if (sc.func.setUnsafe(false, exp.loc,
|
||||
"`@safe` function `%s` cannot index pointer `%s`", sc.func, exp.e1))
|
||||
return setError();
|
||||
}
|
||||
exp.type = (cast(TypeNext)t1b).next;
|
||||
break;
|
||||
|
@ -8675,10 +8625,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
{
|
||||
static if (LOGSEMANTIC)
|
||||
{
|
||||
printf("AssignExp::semantic('%s')\n", exp.toChars());
|
||||
if (exp.op == EXP.blit) printf("BlitExp.toElem('%s')\n", exp.toChars());
|
||||
if (exp.op == EXP.assign) printf("AssignExp.toElem('%s')\n", exp.toChars());
|
||||
if (exp.op == EXP.construct) printf("ConstructExp.toElem('%s')\n", exp.toChars());
|
||||
}
|
||||
//printf("exp.e1.op = %d, '%s'\n", exp.e1.op, EXPtoString(exp.e1.op).ptr);
|
||||
//printf("exp.e2.op = %d, '%s'\n", exp.e2.op, EXPtoString(exp.e2.op).ptr);
|
||||
|
||||
void setResult(Expression e, int line = __LINE__)
|
||||
{
|
||||
|
@ -8696,7 +8646,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
if (auto e2comma = exp.e2.isCommaExp())
|
||||
{
|
||||
if (!e2comma.isGenerated && !(sc.flags & SCOPE.Cfile))
|
||||
exp.error("Using the result of a comma expression is not allowed");
|
||||
exp.error("using the result of a comma expression is not allowed");
|
||||
|
||||
/* Rewrite to get rid of the comma from rvalue
|
||||
* e1=(e0,e2) => e0,(e1=e2)
|
||||
|
@ -9425,6 +9375,23 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
Expression e1x = exp.e1;
|
||||
Expression e2x = exp.e2;
|
||||
|
||||
/* C strings come through as static arrays. May need to adjust the size of the
|
||||
* string to match the size of e1.
|
||||
*/
|
||||
Type t2 = e2x.type.toBasetype();
|
||||
if (sc.flags & SCOPE.Cfile && e2x.isStringExp() && t2.isTypeSArray())
|
||||
{
|
||||
uinteger_t dim1 = t1.isTypeSArray().dim.toInteger();
|
||||
uinteger_t dim2 = t2.isTypeSArray().dim.toInteger();
|
||||
if (dim1 + 1 == dim2 || dim2 < dim1)
|
||||
{
|
||||
auto tsa2 = t2.isTypeSArray();
|
||||
auto newt = tsa2.next.sarrayOf(dim1).immutableOf();
|
||||
e2x = castTo(e2x, sc, newt);
|
||||
exp.e2 = e2x;
|
||||
}
|
||||
}
|
||||
|
||||
if (e2x.implicitConvTo(e1x.type))
|
||||
{
|
||||
if (exp.op != EXP.blit && (e2x.op == EXP.slice && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op == EXP.cast_ && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op != EXP.slice && e2x.isLvalue()))
|
||||
|
@ -9686,13 +9653,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
tsa2 = cast(TypeSArray)toStaticArrayType(se);
|
||||
else
|
||||
tsa2 = t2.isTypeSArray();
|
||||
|
||||
if (tsa1 && tsa2)
|
||||
{
|
||||
uinteger_t dim1 = tsa1.dim.toInteger();
|
||||
uinteger_t dim2 = tsa2.dim.toInteger();
|
||||
if (dim1 != dim2)
|
||||
{
|
||||
exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
|
||||
exp.error("mismatched array lengths %d and %d for assignment `%s`", cast(int)dim1, cast(int)dim2, exp.toChars());
|
||||
return setError();
|
||||
}
|
||||
}
|
||||
|
@ -9761,10 +9729,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
}
|
||||
if (t1n.toBasetype.ty == Tvoid && t2n.toBasetype.ty == Tvoid)
|
||||
{
|
||||
if (!sc.intypeof && sc.func && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
|
||||
if (!sc.intypeof && sc.func && !(sc.flags & SCOPE.debug_))
|
||||
{
|
||||
exp.error("cannot copy `void[]` to `void[]` in `@safe` code");
|
||||
return setError();
|
||||
if (sc.func.setUnsafe(false, exp.loc, "cannot copy `void[]` to `void[]` in `@safe` code"))
|
||||
return setError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10190,10 +10158,135 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
|
||||
exp.type = exp.e1.type;
|
||||
auto res = exp.reorderSettingAAElem(sc);
|
||||
if ((exp.op == EXP.concatenateElemAssign || exp.op == EXP.concatenateDcharAssign) &&
|
||||
global.params.useDIP1000 == FeatureState.enabled)
|
||||
if (exp.op == EXP.concatenateElemAssign || exp.op == EXP.concatenateDcharAssign)
|
||||
checkAssignEscape(sc, res, false, false);
|
||||
result = res;
|
||||
|
||||
if ((exp.op == EXP.concatenateAssign || exp.op == EXP.concatenateElemAssign) &&
|
||||
!(sc.flags & (SCOPE.ctfe | SCOPE.compile)))
|
||||
{
|
||||
// if aa ordering is triggered, `res` will be a CommaExp
|
||||
// and `.e2` will be the rewritten original expression.
|
||||
|
||||
// `output` will point to the expression that the lowering will overwrite
|
||||
Expression* output;
|
||||
if (auto comma = res.isCommaExp())
|
||||
{
|
||||
output = &comma.e2;
|
||||
// manual cast because it could be either CatAssignExp or CatElemAssignExp
|
||||
exp = cast(CatAssignExp)comma.e2;
|
||||
}
|
||||
else
|
||||
{
|
||||
output = &result;
|
||||
exp = cast(CatAssignExp)result;
|
||||
}
|
||||
|
||||
if (exp.op == EXP.concatenateAssign)
|
||||
{
|
||||
Identifier hook = global.params.tracegc ? Id._d_arrayappendTTrace : Id._d_arrayappendT;
|
||||
|
||||
if (!verifyHookExist(exp.loc, *sc, hook, "appending array to arrays", Id.object))
|
||||
return setError();
|
||||
|
||||
// Lower to object._d_arrayappendT{,Trace}({file, line, funcname}, e1, e2)
|
||||
Expression id = new IdentifierExp(exp.loc, Id.empty);
|
||||
id = new DotIdExp(exp.loc, id, Id.object);
|
||||
id = new DotIdExp(exp.loc, id, hook);
|
||||
|
||||
auto arguments = new Expressions();
|
||||
arguments.reserve(5);
|
||||
if (global.params.tracegc)
|
||||
{
|
||||
auto funcname = (sc.callsc && sc.callsc.func) ? sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars();
|
||||
arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString()));
|
||||
arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32));
|
||||
arguments.push(new StringExp(exp.loc, funcname.toDString()));
|
||||
}
|
||||
|
||||
arguments.push(exp.e1);
|
||||
arguments.push(exp.e2);
|
||||
Expression ce = new CallExp(exp.loc, id, arguments);
|
||||
*output = ce.expressionSemantic(sc);
|
||||
}
|
||||
else if (exp.op == EXP.concatenateElemAssign)
|
||||
{
|
||||
/* Do not lower concats to the indices array returned by
|
||||
*`static foreach`, as this array is only used at compile-time.
|
||||
*/
|
||||
if (auto ve = exp.e1.isVarExp)
|
||||
{
|
||||
import core.stdc.ctype : isdigit;
|
||||
// The name of the indices array that static foreach loops uses.
|
||||
// See dmd.cond.lowerNonArrayAggregate
|
||||
enum varName = "__res";
|
||||
const(char)[] id = ve.var.ident.toString;
|
||||
if (ve.var.storage_class & STC.temp && id.length > varName.length &&
|
||||
id[0 .. varName.length] == varName && id[varName.length].isdigit)
|
||||
return;
|
||||
}
|
||||
|
||||
Identifier hook = global.params.tracegc ? Id._d_arrayappendcTXTrace : Id._d_arrayappendcTX;
|
||||
if (!verifyHookExist(exp.loc, *sc, Id._d_arrayappendcTXImpl, "appending element to arrays", Id.object))
|
||||
return setError();
|
||||
|
||||
// Lower to object._d_arrayappendcTXImpl!(typeof(e1))._d_arrayappendcTX{,Trace}(e1, 1), e1[$-1]=e2
|
||||
Expression id = new IdentifierExp(exp.loc, Id.empty);
|
||||
id = new DotIdExp(exp.loc, id, Id.object);
|
||||
auto tiargs = new Objects();
|
||||
tiargs.push(exp.e1.type);
|
||||
id = new DotTemplateInstanceExp(exp.loc, id, Id._d_arrayappendcTXImpl, tiargs);
|
||||
id = new DotIdExp(exp.loc, id, hook);
|
||||
|
||||
auto arguments = new Expressions();
|
||||
arguments.reserve(5);
|
||||
if (global.params.tracegc)
|
||||
{
|
||||
auto funcname = (sc.callsc && sc.callsc.func) ? sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars();
|
||||
arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString()));
|
||||
arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32));
|
||||
arguments.push(new StringExp(exp.loc, funcname.toDString()));
|
||||
}
|
||||
|
||||
Expression eValue1;
|
||||
Expression value1 = extractSideEffect(sc, "__appendtmp", eValue1, exp.e1);
|
||||
|
||||
arguments.push(value1);
|
||||
arguments.push(new IntegerExp(exp.loc, 1, Type.tsize_t));
|
||||
|
||||
Expression ce = new CallExp(exp.loc, id, arguments);
|
||||
|
||||
Expression eValue2;
|
||||
Expression value2 = exp.e2;
|
||||
if (!value2.isVarExp() && !value2.isConst())
|
||||
{
|
||||
/* Before the template hook, this check was performed in e2ir.d
|
||||
* for expressions like `a ~= a[$-1]`. Here, $ will be modified
|
||||
* by calling `_d_arrayappendcT`, so we need to save `a[$-1]` in
|
||||
* a temporary variable.
|
||||
*/
|
||||
value2 = extractSideEffect(sc, "__appendtmp", eValue2, value2, true);
|
||||
exp.e2 = value2;
|
||||
|
||||
// `__appendtmp*` will be destroyed together with the array `exp.e1`.
|
||||
auto vd = eValue2.isDeclarationExp().declaration.isVarDeclaration();
|
||||
vd.storage_class |= STC.nodtor;
|
||||
}
|
||||
|
||||
auto ale = new ArrayLengthExp(exp.loc, value1);
|
||||
auto elem = new IndexExp(exp.loc, value1, new MinExp(exp.loc, ale, IntegerExp.literal!1));
|
||||
auto ae = new ConstructExp(exp.loc, elem, value2);
|
||||
|
||||
auto e0 = Expression.combine(ce, ae).expressionSemantic(sc);
|
||||
e0 = Expression.combine(e0, value1);
|
||||
e0 = Expression.combine(eValue1, e0);
|
||||
|
||||
e0 = Expression.combine(eValue2, e0);
|
||||
|
||||
*output = e0.expressionSemantic(sc);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override void visit(AddExp exp)
|
||||
|
@ -11639,7 +11732,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
auto t1 = exp.e1.type;
|
||||
auto t2 = exp.e2.type;
|
||||
if (t1.ty == Tenum && t2.ty == Tenum && !t1.equivalent(t2))
|
||||
exp.error("Comparison between different enumeration types `%s` and `%s`; If this behavior is intended consider using `std.conv.asOriginalType`",
|
||||
exp.error("comparison between different enumeration types `%s` and `%s`; If this behavior is intended consider using `std.conv.asOriginalType`",
|
||||
t1.toChars(), t2.toChars());
|
||||
}
|
||||
|
||||
|
@ -11996,7 +12089,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
}
|
||||
// C11 6.5.1.1 Generic Selection
|
||||
|
||||
auto ec = exp.cntlExp.expressionSemantic(sc);
|
||||
auto ec = exp.cntlExp.expressionSemantic(sc).arrayFuncConv(sc);
|
||||
bool errors = ec.isErrorExp() !is null;
|
||||
auto tc = ec.type;
|
||||
|
||||
|
@ -12622,12 +12715,21 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
|
|||
Expression e = new IntegerExp(exp.loc, actualAlignment, Type.tsize_t);
|
||||
return e;
|
||||
}
|
||||
else if (cfile && exp.ident == Id.__sizeof && exp.e1.isStringExp())
|
||||
else if ((exp.ident == Id.max || exp.ident == Id.min) &&
|
||||
exp.e1.isVarExp() &&
|
||||
exp.e1.isVarExp().var.isBitFieldDeclaration())
|
||||
{
|
||||
// Sizeof string literal includes the terminating 0
|
||||
auto se = exp.e1.isStringExp();
|
||||
Expression e = new IntegerExp(exp.loc, (se.len + 1) * se.sz, Type.tsize_t);
|
||||
return e;
|
||||
// For `x.max` and `x.min` get the max/min of the bitfield, not the max/min of its type
|
||||
auto bf = exp.e1.isVarExp().var.isBitFieldDeclaration();
|
||||
return new IntegerExp(exp.loc, bf.getMinMax(exp.ident), bf.type);
|
||||
}
|
||||
else if ((exp.ident == Id.max || exp.ident == Id.min) &&
|
||||
exp.e1.isDotVarExp() &&
|
||||
exp.e1.isDotVarExp().var.isBitFieldDeclaration())
|
||||
{
|
||||
// For `x.max` and `x.min` get the max/min of the bitfield, not the max/min of its type
|
||||
auto bf = exp.e1.isDotVarExp().var.isBitFieldDeclaration();
|
||||
return new IntegerExp(exp.loc, bf.getMinMax(exp.ident), bf.type);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -12635,7 +12737,9 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
|
|||
flag = 0;
|
||||
Expression e = exp.e1.type.dotExp(sc, exp.e1, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
|
||||
if (e)
|
||||
{
|
||||
e = e.expressionSemantic(sc);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
@ -12982,22 +13086,12 @@ bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v)
|
|||
if (sc.func && !sc.intypeof && !v.isDataseg())
|
||||
{
|
||||
const(char)* p = v.isParameter() ? "parameter" : "local";
|
||||
if (global.params.useDIP1000 == FeatureState.enabled)
|
||||
{
|
||||
// Taking the address of v means it cannot be set to 'scope' later
|
||||
v.storage_class &= ~STC.maybescope;
|
||||
v.doNotInferScope = true;
|
||||
if (exp.type.hasPointers() && v.storage_class & STC.scope_ &&
|
||||
!(v.storage_class & STC.temp) &&
|
||||
!(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
|
||||
{
|
||||
exp.error("cannot take address of `scope` %s `%s` in `@safe` function `%s`", p, v.toChars(), sc.func.toChars());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!(sc.flags & SCOPE.debug_) &&
|
||||
!(v.storage_class & STC.temp) &&
|
||||
sc.func.setUnsafe())
|
||||
v.storage_class &= ~STC.maybescope;
|
||||
v.doNotInferScope = true;
|
||||
if (global.params.useDIP1000 != FeatureState.enabled &&
|
||||
!(sc.flags & SCOPE.debug_) &&
|
||||
!(v.storage_class & STC.temp) &&
|
||||
sc.func.setUnsafe())
|
||||
{
|
||||
exp.error("cannot take address of %s `%s` in `@safe` function `%s`", p, v.toChars(), sc.func.toChars());
|
||||
return false;
|
||||
|
@ -13007,37 +13101,6 @@ bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v)
|
|||
return true;
|
||||
}
|
||||
|
||||
/****************************************************
|
||||
* Determine if the address of a `ref return` value of
|
||||
* a function call with type `tf` can be taken safely.
|
||||
*
|
||||
* This is currently stricter than necessary: it can be safe to take the
|
||||
* address of a `ref` with pointer type when the pointer isn't `scope`, but
|
||||
* that involves inspecting the function arguments and parameter types, which
|
||||
* is left as a future enhancement.
|
||||
*
|
||||
* Params:
|
||||
* sc = context
|
||||
* ce = function call in question
|
||||
* action = for the error message, how the pointer is taken, e.g. "slice static array of"
|
||||
* Returns:
|
||||
* `true` if ok, `false` for error
|
||||
*/
|
||||
private bool checkAddressCall(Scope* sc, CallExp ce, const(char)* action)
|
||||
{
|
||||
if (auto tf = ce.e1.type.isTypeFunction())
|
||||
{
|
||||
if (tf.isref && sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_)
|
||||
&& tf.next.hasPointers() && sc.func.setUnsafe())
|
||||
{
|
||||
ce.error("cannot %s `ref return` of `%s()` in `@safe` function `%s`",
|
||||
action, ce.e1.toChars(), sc.func.toChars());
|
||||
ce.errorSupplemental("return type `%s` has pointers that may be `scope`", tf.next.toChars());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*******************************
|
||||
* Checks the attributes of a function.
|
||||
|
@ -13241,10 +13304,9 @@ private bool fit(StructDeclaration sd, const ref Loc loc, Scope* sc, Expressions
|
|||
{
|
||||
if ((!stype.alignment.isDefault() && stype.alignment.get() < target.ptrsize ||
|
||||
(v.offset & (target.ptrsize - 1))) &&
|
||||
(sc.func && sc.func.setUnsafe()))
|
||||
(sc.func && sc.func.setUnsafe(false, loc,
|
||||
"field `%s.%s` cannot assign to misaligned pointers in `@safe` code", sd, v)))
|
||||
{
|
||||
.error(loc, "field `%s.%s` cannot assign to misaligned pointers in `@safe` code",
|
||||
sd.toChars(), v.toChars());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
121
gcc/d/dmd/func.d
121
gcc/d/dmd/func.d
|
@ -344,6 +344,10 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
|
||||
FuncDeclarations *inlinedNestedCallees;
|
||||
|
||||
/// In case of failed `@safe` inference, store the error that made the function `@system` for
|
||||
/// better diagnostics
|
||||
private AttributeViolation* safetyViolation;
|
||||
|
||||
/// Function flags: A collection of boolean packed for memory efficiency
|
||||
/// See the `FUNCFLAG` enum
|
||||
uint flags = FUNCFLAG.NRVO;
|
||||
|
@ -1207,12 +1211,12 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
|
||||
final bool isMain() const
|
||||
{
|
||||
return ident == Id.main && linkage != LINK.c && !isMember() && !isNested();
|
||||
return ident == Id.main && resolvedLinkage() != LINK.c && !isMember() && !isNested();
|
||||
}
|
||||
|
||||
final bool isCMain() const
|
||||
{
|
||||
return ident == Id.main && linkage == LINK.c && !isMember() && !isNested();
|
||||
return ident == Id.main && resolvedLinkage() == LINK.c && !isMember() && !isNested();
|
||||
}
|
||||
|
||||
final bool isWinMain() const
|
||||
|
@ -1220,24 +1224,24 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
//printf("FuncDeclaration::isWinMain() %s\n", toChars());
|
||||
version (none)
|
||||
{
|
||||
bool x = ident == Id.WinMain && linkage != LINK.c && !isMember();
|
||||
bool x = ident == Id.WinMain && resolvedLinkage() != LINK.c && !isMember();
|
||||
printf("%s\n", x ? "yes" : "no");
|
||||
return x;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ident == Id.WinMain && linkage != LINK.c && !isMember();
|
||||
return ident == Id.WinMain && resolvedLinkage() != LINK.c && !isMember();
|
||||
}
|
||||
}
|
||||
|
||||
final bool isDllMain() const
|
||||
{
|
||||
return ident == Id.DllMain && linkage != LINK.c && !isMember();
|
||||
return ident == Id.DllMain && resolvedLinkage() != LINK.c && !isMember();
|
||||
}
|
||||
|
||||
final bool isRtInit() const
|
||||
{
|
||||
return ident == Id.rt_init && linkage == LINK.c && !isMember() && !isNested();
|
||||
return ident == Id.rt_init && resolvedLinkage() == LINK.c && !isMember() && !isNested();
|
||||
}
|
||||
|
||||
override final bool isExport() const
|
||||
|
@ -1349,8 +1353,7 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
flags |= FUNCFLAG.returnInprocess;
|
||||
|
||||
// Initialize for inferring STC.scope_
|
||||
if (global.params.useDIP1000 == FeatureState.enabled)
|
||||
flags |= FUNCFLAG.inferScope;
|
||||
flags |= FUNCFLAG.inferScope;
|
||||
}
|
||||
|
||||
final PURE isPure()
|
||||
|
@ -1427,24 +1430,51 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
}
|
||||
|
||||
/**************************************
|
||||
* The function is doing something unsafe,
|
||||
* so mark it as unsafe.
|
||||
* If there's a safe error, return true.
|
||||
* The function is doing something unsafe, so mark it as unsafe.
|
||||
*
|
||||
* Params:
|
||||
* gag = surpress error message (used in escape.d)
|
||||
* loc = location of error
|
||||
* fmt = printf-style format string
|
||||
* arg0 = (optional) argument for first %s format specifier
|
||||
* arg1 = (optional) argument for second %s format specifier
|
||||
* Returns: whether there's a safe error
|
||||
*/
|
||||
extern (D) final bool setUnsafe()
|
||||
extern (D) final bool setUnsafe(
|
||||
bool gag = false, Loc loc = Loc.init, const(char)* fmt = null, RootObject arg0 = null, RootObject arg1 = null)
|
||||
{
|
||||
if (flags & FUNCFLAG.safetyInprocess)
|
||||
{
|
||||
flags &= ~FUNCFLAG.safetyInprocess;
|
||||
type.toTypeFunction().trust = TRUST.system;
|
||||
if (!gag && !safetyViolation && (fmt || arg0))
|
||||
safetyViolation = new AttributeViolation(loc, fmt, arg0, arg1);
|
||||
|
||||
if (fes)
|
||||
fes.func.setUnsafe();
|
||||
}
|
||||
else if (isSafe())
|
||||
{
|
||||
if (!gag && fmt)
|
||||
.error(loc, fmt, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "");
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* The function is calling `@system` function `f`, so mark it as unsafe.
|
||||
*
|
||||
* Params:
|
||||
* f = function being called (needed for diagnostic of inferred functions)
|
||||
* Returns: whether there's a safe error
|
||||
*/
|
||||
extern (D) final bool setUnsafeCall(FuncDeclaration f)
|
||||
{
|
||||
return setUnsafe(false, f.loc, null, f, null);
|
||||
}
|
||||
|
||||
final bool isNogc()
|
||||
{
|
||||
//printf("isNogc() %s, inprocess: %d\n", toChars(), !!(flags & FUNCFLAG.nogcInprocess));
|
||||
|
@ -1474,6 +1504,12 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
return !!(this.flags & FUNCFLAG.naked);
|
||||
}
|
||||
|
||||
final void isNaked(bool v) @safe pure nothrow @nogc
|
||||
{
|
||||
if (v) this.flags |= FUNCFLAG.naked;
|
||||
else this.flags &= ~FUNCFLAG.naked;
|
||||
}
|
||||
|
||||
final bool isGenerated() const scope @safe pure nothrow @nogc
|
||||
{
|
||||
return !!(this.flags & FUNCFLAG.generated);
|
||||
|
@ -1520,11 +1556,23 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
return !!(this.flags & FUNCFLAG.CRTCtor);
|
||||
}
|
||||
|
||||
final void isCrtCtor(bool v) @safe pure nothrow @nogc
|
||||
{
|
||||
if (v) this.flags |= FUNCFLAG.CRTCtor;
|
||||
else this.flags &= ~FUNCFLAG.CRTCtor;
|
||||
}
|
||||
|
||||
final bool isCrtDtor() const scope @safe pure nothrow @nogc
|
||||
{
|
||||
return !!(this.flags & FUNCFLAG.CRTDtor);
|
||||
}
|
||||
|
||||
final void isCrtDtor(bool v) @safe pure nothrow @nogc
|
||||
{
|
||||
if (v) this.flags |= FUNCFLAG.CRTDtor;
|
||||
else this.flags &= ~FUNCFLAG.CRTDtor;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* The function is doing something that may allocate with the GC,
|
||||
* so mark it as not nogc (not no-how).
|
||||
|
@ -1758,7 +1806,7 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
auto f = toAliasFunc();
|
||||
//printf("\ttoParent2() = '%s'\n", f.toParent2().toChars());
|
||||
return ((f.storage_class & STC.static_) == 0) &&
|
||||
(f.linkage == LINK.d) &&
|
||||
(f._linkage == LINK.d) &&
|
||||
(f.toParent2().isFuncDeclaration() !is null ||
|
||||
f.toParent2() !is f.toParentLocal());
|
||||
}
|
||||
|
@ -2645,7 +2693,7 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
tf = new TypeFunction(ParameterList(fparams), treturn, LINK.c, stc);
|
||||
fd = new FuncDeclaration(Loc.initial, Loc.initial, id, STC.static_, tf);
|
||||
fd.visibility = Visibility(Visibility.Kind.public_);
|
||||
fd.linkage = LINK.c;
|
||||
fd._linkage = LINK.c;
|
||||
|
||||
st.insert(fd);
|
||||
}
|
||||
|
@ -2705,6 +2753,7 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
const nparams = tf.parameterList.length;
|
||||
bool argerr;
|
||||
|
||||
const linkage = resolvedLinkage();
|
||||
if (linkage == LINK.d)
|
||||
{
|
||||
if (nparams == 1)
|
||||
|
@ -4271,3 +4320,47 @@ extern (C++) final class NewDeclaration : FuncDeclaration
|
|||
v.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// Stores a reason why a function failed to infer a function attribute like `@safe` or `pure`
|
||||
///
|
||||
/// Has two modes:
|
||||
/// - a regular safety error, stored in (fmtStr, arg0, arg1)
|
||||
/// - a call to a function without the attribute, which is a special case, because in that case,
|
||||
/// that function might recursively also have a `AttributeViolation`. This way, in case
|
||||
/// of a big call stack, the error can go down all the way to the root cause.
|
||||
/// The `FunctionDeclaration` is then stored in `arg0` and `fmtStr` must be `null`.
|
||||
private struct AttributeViolation
|
||||
{
|
||||
/// location of error
|
||||
Loc loc = Loc.init;
|
||||
/// printf-style format string
|
||||
const(char)* fmtStr = null;
|
||||
/// Arguments for up to two `%s` format specifiers in format string
|
||||
RootObject arg0 = null;
|
||||
/// ditto
|
||||
RootObject arg1 = null;
|
||||
}
|
||||
|
||||
/// Print the reason why `fd` was inferred `@system` as a supplemental error
|
||||
/// Params:
|
||||
/// fd = function to check
|
||||
/// maxDepth = up to how many functions deep to report errors
|
||||
void errorSupplementalInferredSafety(FuncDeclaration fd, int maxDepth)
|
||||
{
|
||||
if (auto s = fd.safetyViolation)
|
||||
{
|
||||
if (s.fmtStr)
|
||||
{
|
||||
errorSupplemental(s.loc, "which was inferred `@system` because of:");
|
||||
errorSupplemental(s.loc, s.fmtStr, s.arg0 ? s.arg0.toChars() : "", s.arg1 ? s.arg1.toChars() : "");
|
||||
}
|
||||
else if (FuncDeclaration fd2 = cast(FuncDeclaration) s.arg0)
|
||||
{
|
||||
if (maxDepth > 0)
|
||||
{
|
||||
errorSupplemental(s.loc, "which calls `%s`", fd2.toPrettyChars());
|
||||
errorSupplementalInferredSafety(fd2, maxDepth - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,14 +51,6 @@ enum CHECKACTION : ubyte
|
|||
context, /// call D assert with the error context on failure
|
||||
}
|
||||
|
||||
/// Position Indepent Code setting
|
||||
enum PIC : ubyte
|
||||
{
|
||||
fixed, /// located at a specific address
|
||||
pic, /// Position Independent Code
|
||||
pie, /// Position Independent Executable
|
||||
}
|
||||
|
||||
/**
|
||||
Each flag represents a field that can be included in the JSON output.
|
||||
|
||||
|
@ -83,14 +75,6 @@ enum CppStdRevision : uint
|
|||
cpp20 = 2020_02,
|
||||
}
|
||||
|
||||
/// Configuration for the C++ header generator
|
||||
enum CxxHeaderMode : uint
|
||||
{
|
||||
none, /// Don't generate headers
|
||||
silent, /// Generate headers
|
||||
verbose /// Generate headers and add comments for hidden declarations
|
||||
}
|
||||
|
||||
/// Trivalent boolean to represent the state of a `revert`able change
|
||||
enum FeatureState : byte
|
||||
{
|
||||
|
@ -99,15 +83,24 @@ enum FeatureState : byte
|
|||
enabled = 1 /// Specified as `-preview=`
|
||||
}
|
||||
|
||||
extern(C++) struct Output
|
||||
{
|
||||
bool doOutput; // Output is enabled
|
||||
bool fullOutput; // Generate comments for hidden declarations (for -HC),
|
||||
// and don't strip the bodies of plain (non-template) functions (for -H)
|
||||
|
||||
const(char)[] dir; // write to directory 'dir'
|
||||
const(char)[] name; // write to file 'name'
|
||||
Array!(const(char)*) files; // Other files associated with this output,
|
||||
// e.g. macro include files for Ddoc, dependencies for makedeps
|
||||
OutBuffer* buffer; // if this output is buffered, this is the buffer
|
||||
int bufferLines; // number of lines written to the buffer
|
||||
}
|
||||
/// Put command line switches in here
|
||||
extern (C++) struct Param
|
||||
{
|
||||
bool obj = true; // write object file
|
||||
bool link = true; // perform link
|
||||
bool dll; // generate shared dynamic library
|
||||
bool lib; // write library file instead of object file(s)
|
||||
bool multiobj; // break one object file into multiple ones
|
||||
bool oneobj; // write one object file instead of multiple ones
|
||||
bool trace; // insert profiling hooks
|
||||
bool tracegc; // instrument calls to 'new'
|
||||
bool verbose; // verbose compile
|
||||
|
@ -120,11 +113,7 @@ extern (C++) struct Param
|
|||
bool vfield; // identify non-mutable field variables
|
||||
bool vcomplex = true; // identify complex/imaginary type usage
|
||||
bool vin; // identify 'in' parameters
|
||||
ubyte symdebug; // insert debug symbolic information
|
||||
bool symdebugref; // insert debug information for all referenced types, too
|
||||
bool optimize; // run optimizer
|
||||
DiagnosticReporting useDeprecated = DiagnosticReporting.inform; // how use of deprecated features are handled
|
||||
bool stackstomp; // add stack stomping code
|
||||
bool useUnitTests; // generate unittest code
|
||||
bool useInline = false; // inline expand functions
|
||||
FeatureState useDIP25; // implement https://wiki.dlang.org/DIP25
|
||||
|
@ -133,12 +122,10 @@ extern (C++) struct Param
|
|||
bool release; // build release version
|
||||
bool preservePaths; // true means don't strip path from source file
|
||||
DiagnosticReporting warnings = DiagnosticReporting.off; // how compiler warnings are handled
|
||||
PIC pic = PIC.fixed; // generate fixed, pic or pie code
|
||||
bool color; // use ANSI colors in console output
|
||||
bool cov; // generate code coverage data
|
||||
ubyte covPercent; // 0..100 code coverage percentage required
|
||||
bool ctfe_cov = false; // generate coverage data for ctfe
|
||||
bool nofloat; // code should not pull in floating point support
|
||||
bool ignoreUnsupportedPragmas; // rather than error on them
|
||||
bool useModuleInfo = true; // generate runtime module information
|
||||
bool useTypeInfo = true; // generate runtime type information
|
||||
|
@ -162,6 +149,7 @@ extern (C++) struct Param
|
|||
FeatureState dtorFields; // destruct fields of partially constructed objects
|
||||
// https://issues.dlang.org/show_bug.cgi?id=14246
|
||||
bool fieldwise; // do struct equality testing field-wise rather than by memcmp()
|
||||
bool bitfields; // support C style bit fields
|
||||
FeatureState rvalueRefParam; // allow rvalues to be arguments to ref parameters
|
||||
// https://dconf.org/2019/talks/alexandrescu.html
|
||||
// https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a
|
||||
|
@ -170,9 +158,6 @@ extern (C++) struct Param
|
|||
|
||||
CppStdRevision cplusplus = CppStdRevision.cpp11; // version of C++ standard to support
|
||||
|
||||
bool markdown = true; // enable Markdown replacements in Ddoc
|
||||
bool vmarkdown; // list instances of Markdown replacements in Ddoc
|
||||
|
||||
bool showGaggedErrors; // print gagged errors anyway
|
||||
bool printErrorContext; // print errors with the error context (the error line in the source file)
|
||||
bool manual; // open browser on compiler manual
|
||||
|
@ -207,27 +192,14 @@ extern (C++) struct Param
|
|||
const(char)[] objname; // .obj file output name
|
||||
const(char)[] libname; // .lib file output name
|
||||
|
||||
bool doDocComments; // process embedded documentation comments
|
||||
const(char)[] docdir; // write documentation file to docdir directory
|
||||
const(char)[] docname; // write documentation file to docname
|
||||
Array!(const(char)*) ddocfiles; // macro include files for Ddoc
|
||||
|
||||
bool doHdrGeneration; // process embedded documentation comments
|
||||
const(char)[] hdrdir; // write 'header' file to docdir directory
|
||||
const(char)[] hdrname; // write 'header' file to docname
|
||||
bool hdrStripPlainFunctions = true; // strip the bodies of plain (non-template) functions
|
||||
|
||||
CxxHeaderMode doCxxHdrGeneration; /// Generate 'Cxx header' file
|
||||
const(char)[] cxxhdrdir; // write 'header' file to docdir directory
|
||||
const(char)[] cxxhdrname; // write 'header' file to docname
|
||||
|
||||
bool doJsonGeneration; // write JSON file
|
||||
const(char)[] jsonfilename; // write JSON file to jsonfilename
|
||||
Output ddoc; // Generate embedded documentation comments
|
||||
Output dihdr; // Generate `.di` 'header' files
|
||||
Output cxxhdr; // Generate 'Cxx header' file
|
||||
Output json; // Generate JSON file
|
||||
JsonFieldFlags jsonFieldFlags; // JSON field flags to include
|
||||
|
||||
OutBuffer* mixinOut; // write expanded mixins for debugging
|
||||
const(char)* mixinFile; // .mixin file output name
|
||||
int mixinLines; // Number of lines in writeMixins
|
||||
Output makeDeps; // Generate make file dependencies
|
||||
Output mixinOut; // write expanded mixins for debugging
|
||||
Output moduleDeps; // Generate `.deps` module dependencies
|
||||
|
||||
uint debuglevel; // debug level
|
||||
Array!(const(char)*)* debugids; // debug identifiers
|
||||
|
@ -235,21 +207,12 @@ extern (C++) struct Param
|
|||
uint versionlevel; // version level
|
||||
Array!(const(char)*)* versionids; // version identifiers
|
||||
|
||||
const(char)[] defaultlibname; // default library for non-debug builds
|
||||
const(char)[] debuglibname; // default library for debug builds
|
||||
const(char)[] mscrtlib; // MS C runtime library
|
||||
|
||||
const(char)[] moduleDepsFile; // filename for deps output
|
||||
OutBuffer* moduleDeps; // contents to be written to deps file
|
||||
|
||||
bool emitMakeDeps; // whether to emit makedeps
|
||||
const(char)[] makeDepsFile; // filename for makedeps output
|
||||
Array!(const(char)*) makeDeps; // dependencies for makedeps
|
||||
|
||||
MessageStyle messageStyle = MessageStyle.digitalmars; // style of file/line annotations on messages
|
||||
|
||||
bool run; // run resulting executable
|
||||
Strings runargs; // arguments for executable
|
||||
Array!(const(char)*) cppswitches; // C preprocessor switches
|
||||
|
||||
// Linker stuff
|
||||
Array!(const(char)*) objfiles;
|
||||
|
@ -335,6 +298,8 @@ extern (C++) struct Global
|
|||
|
||||
enum recursionLimit = 500; /// number of recursive template expansions before abort
|
||||
|
||||
extern (C++) FileName function(FileName, const(char)* importc_h, ref Array!(const(char)*) cppswitches, out bool) preprocess;
|
||||
|
||||
nothrow:
|
||||
|
||||
/**
|
||||
|
@ -468,15 +433,6 @@ extern (C++) struct Global
|
|||
{
|
||||
return _version.ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns: the final defaultlibname based on the command-line parameters
|
||||
*/
|
||||
extern (D) const(char)[] finalDefaultlibname() const
|
||||
{
|
||||
return params.betterC ? null :
|
||||
params.symdebug ? params.debuglibname : params.defaultlibname;
|
||||
}
|
||||
}
|
||||
|
||||
// Because int64_t and friends may be any integral type of the
|
||||
|
|
|
@ -73,14 +73,6 @@ enum CppStdRevision
|
|||
CppStdRevisionCpp20 = 202002
|
||||
};
|
||||
|
||||
/// Configuration for the C++ header generator
|
||||
enum class CxxHeaderMode
|
||||
{
|
||||
none, /// Don't generate headers
|
||||
silent, /// Generate headers
|
||||
verbose /// Generate headers and add comments for hidden declarations
|
||||
};
|
||||
|
||||
/// Trivalent boolean to represent the state of a `revert`able change
|
||||
enum class FeatureState : signed char
|
||||
{
|
||||
|
@ -89,15 +81,25 @@ enum class FeatureState : signed char
|
|||
enabled = 1 /// Specified as `-preview=`
|
||||
};
|
||||
|
||||
struct Output
|
||||
{
|
||||
/// Configuration for the compiler generator
|
||||
bool doOutput; // Output is enabled
|
||||
bool fullOutput; // Generate comments for hidden declarations (for -HC),
|
||||
// and don't strip the bodies of plain (non-template) functions (for -H)
|
||||
DString dir; // write to directory 'dir'
|
||||
DString name; // write to file 'name'
|
||||
Array<const char*> files; // Other files associated with this output,
|
||||
// e.g. macro include files for Ddoc, dependencies for makedeps
|
||||
OutBuffer* buffer; // if this output is buffered, this is the buffer
|
||||
int bufferLines; // number of lines written to the buffer
|
||||
};
|
||||
|
||||
// Put command line switches in here
|
||||
struct Param
|
||||
{
|
||||
bool obj; // write object file
|
||||
bool link; // perform link
|
||||
bool dll; // generate shared dynamic library
|
||||
bool lib; // write library file instead of object file(s)
|
||||
bool multiobj; // break one object file into multiple ones
|
||||
bool oneobj; // write one object file instead of multiple ones
|
||||
bool trace; // insert profiling hooks
|
||||
bool tracegc; // instrument calls to 'new'
|
||||
bool verbose; // verbose compile
|
||||
|
@ -110,11 +112,7 @@ struct Param
|
|||
bool vfield; // identify non-mutable field variables
|
||||
bool vcomplex; // identify complex/imaginary type usage
|
||||
bool vin; // identify 'in' parameters
|
||||
unsigned char symdebug; // insert debug symbolic information
|
||||
bool symdebugref; // insert debug information for all referenced types, too
|
||||
bool optimize; // run optimizer
|
||||
Diagnostic useDeprecated;
|
||||
bool stackstomp; // add stack stomping code
|
||||
bool useUnitTests; // generate unittest code
|
||||
bool useInline; // inline expand functions
|
||||
FeatureState useDIP25; // implement https://wiki.dlang.org/DIP25
|
||||
|
@ -123,12 +121,10 @@ struct Param
|
|||
bool release; // build release version
|
||||
bool preservePaths; // true means don't strip path from source file
|
||||
Diagnostic warnings;
|
||||
unsigned char pic; // generate position-independent-code for shared libs
|
||||
bool color; // use ANSI colors in console output
|
||||
bool cov; // generate code coverage data
|
||||
unsigned char covPercent; // 0..100 code coverage percentage required
|
||||
bool ctfe_cov; // generate coverage data for ctfe
|
||||
bool nofloat; // code should not pull in floating point support
|
||||
bool ignoreUnsupportedPragmas; // rather than error on them
|
||||
bool useModuleInfo; // generate runtime module information
|
||||
bool useTypeInfo; // generate runtime type information
|
||||
|
@ -147,10 +143,9 @@ struct Param
|
|||
FeatureState dtorFields; // destruct fields of partially constructed objects
|
||||
// https://issues.dlang.org/show_bug.cgi?id=14246
|
||||
bool fieldwise; // do struct equality testing field-wise rather than by memcmp()
|
||||
bool bitfields; // support C style bit fields
|
||||
FeatureState rvalueRefParam; // allow rvalues to be arguments to ref parameters
|
||||
CppStdRevision cplusplus; // version of C++ name mangling to support
|
||||
bool markdown; // enable Markdown replacements in Ddoc
|
||||
bool vmarkdown; // list instances of Markdown replacements in Ddoc
|
||||
bool showGaggedErrors; // print gagged errors anyway
|
||||
bool printErrorContext; // print errors with the error context (the error line in the source file)
|
||||
bool manual; // open browser on compiler manual
|
||||
|
@ -185,27 +180,14 @@ struct Param
|
|||
DString objname; // .obj file output name
|
||||
DString libname; // .lib file output name
|
||||
|
||||
bool doDocComments; // process embedded documentation comments
|
||||
DString docdir; // write documentation file to docdir directory
|
||||
DString docname; // write documentation file to docname
|
||||
Array<const char *> ddocfiles; // macro include files for Ddoc
|
||||
|
||||
bool doHdrGeneration; // process embedded documentation comments
|
||||
DString hdrdir; // write 'header' file to docdir directory
|
||||
DString hdrname; // write 'header' file to docname
|
||||
bool hdrStripPlainFunctions; // strip the bodies of plain (non-template) functions
|
||||
|
||||
CxxHeaderMode doCxxHdrGeneration; // write 'Cxx header' file
|
||||
DString cxxhdrdir; // write 'header' file to docdir directory
|
||||
DString cxxhdrname; // write 'header' file to docname
|
||||
|
||||
bool doJsonGeneration; // write JSON file
|
||||
DString jsonfilename; // write JSON file to jsonfilename
|
||||
Output ddoc; // Generate embedded documentation comments
|
||||
Output dihdr; // Generate `.di` 'header' files
|
||||
Output cxxhdr; // Generate 'Cxx header' file
|
||||
Output json; // Generate JSON file
|
||||
unsigned jsonFieldFlags; // JSON field flags to include
|
||||
|
||||
OutBuffer *mixinOut; // write expanded mixins for debugging
|
||||
const char *mixinFile; // .mixin file output name
|
||||
int mixinLines; // Number of lines in writeMixins
|
||||
Output makeDeps; // Generate make file dependencies
|
||||
Output mixinOut; // write expanded mixins for debugging
|
||||
Output moduleDeps; // Generate `.deps` module dependencies
|
||||
|
||||
unsigned debuglevel; // debug level
|
||||
Array<const char *> *debugids; // debug identifiers
|
||||
|
@ -213,22 +195,14 @@ struct Param
|
|||
unsigned versionlevel; // version level
|
||||
Array<const char *> *versionids; // version identifiers
|
||||
|
||||
DString defaultlibname; // default library for non-debug builds
|
||||
DString debuglibname; // default library for debug builds
|
||||
DString mscrtlib; // MS C runtime library
|
||||
|
||||
DString moduleDepsFile; // filename for deps output
|
||||
OutBuffer *moduleDeps; // contents to be written to deps file
|
||||
|
||||
bool emitMakeDeps; // whether to emit makedeps
|
||||
DString makeDepsFile; // filename for makedeps output
|
||||
Array<const char *> makeDeps; // dependencies for makedeps
|
||||
|
||||
MessageStyle messageStyle; // style of file/line annotations on messages
|
||||
|
||||
bool run; // run resulting executable
|
||||
Strings runargs; // arguments for executable
|
||||
|
||||
Array<const char *> cppswitches; // preprocessor switches
|
||||
|
||||
// Linker stuff
|
||||
Array<const char *> objfiles;
|
||||
Array<const char *> linkswitches;
|
||||
|
@ -296,6 +270,8 @@ struct Global
|
|||
|
||||
FileManager* fileManager;
|
||||
|
||||
FileName (*preprocess)(FileName, const char*, Array<const char *>& cppswitches, bool&);
|
||||
|
||||
/* Start gagging. Return the current number of gagged errors
|
||||
*/
|
||||
unsigned startGagging();
|
||||
|
|
|
@ -1536,7 +1536,7 @@ public:
|
|||
bodyToBuffer(f);
|
||||
hgs.autoMember--;
|
||||
}
|
||||
else if (hgs.tpltMember == 0 && global.params.hdrStripPlainFunctions)
|
||||
else if (hgs.tpltMember == 0 && global.params.dihdr.fullOutput == false)
|
||||
{
|
||||
if (!f.fbody)
|
||||
{
|
||||
|
@ -1621,7 +1621,7 @@ public:
|
|||
|
||||
void bodyToBuffer(FuncDeclaration f)
|
||||
{
|
||||
if (!f.fbody || (hgs.hdrgen && global.params.hdrStripPlainFunctions && !hgs.autoMember && !hgs.tpltMember))
|
||||
if (!f.fbody || (hgs.hdrgen && global.params.dihdr.fullOutput == false && !hgs.autoMember && !hgs.tpltMember))
|
||||
{
|
||||
if (!f.fbody && (f.fensures || f.frequires))
|
||||
{
|
||||
|
|
|
@ -349,6 +349,11 @@ immutable Msgtable[] msgtable =
|
|||
{ "_d_arraysetlengthTImpl"},
|
||||
{ "_d_arraysetlengthT"},
|
||||
{ "_d_arraysetlengthTTrace"},
|
||||
{ "_d_arrayappendT" },
|
||||
{ "_d_arrayappendTTrace" },
|
||||
{ "_d_arrayappendcTXImpl" },
|
||||
{ "_d_arrayappendcTX" },
|
||||
{ "_d_arrayappendcTXTrace" },
|
||||
|
||||
// varargs implementation
|
||||
{ "stdc" },
|
||||
|
@ -454,6 +459,7 @@ immutable Msgtable[] msgtable =
|
|||
{ "getVirtualFunctions" },
|
||||
{ "getVirtualMethods" },
|
||||
{ "classInstanceSize" },
|
||||
{ "classInstanceAlignment" },
|
||||
{ "allMembers" },
|
||||
{ "derivedMembers" },
|
||||
{ "isSame" },
|
||||
|
|
|
@ -198,14 +198,16 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
|
|||
{
|
||||
if ((!t.alignment.isDefault() && t.alignment.get() < target.ptrsize ||
|
||||
(vd.offset & (target.ptrsize - 1))) &&
|
||||
sc.func && sc.func.setUnsafe())
|
||||
sc.func)
|
||||
{
|
||||
error(i.value[j].loc, "field `%s.%s` cannot assign to misaligned pointers in `@safe` code",
|
||||
sd.toChars(), vd.toChars());
|
||||
errors = true;
|
||||
elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
|
||||
++fieldi;
|
||||
continue;
|
||||
if (sc.func.setUnsafe(false, i.value[j].loc,
|
||||
"field `%s.%s` cannot assign to misaligned pointers in `@safe` code", sd, vd))
|
||||
{
|
||||
errors = true;
|
||||
elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
|
||||
++fieldi;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -502,6 +504,18 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
|
|||
i.exp = se.castTo(sc, t);
|
||||
goto L1;
|
||||
}
|
||||
|
||||
/* Lop off terminating 0 of initializer for:
|
||||
* static char s[5] = "hello";
|
||||
*/
|
||||
if (sc.flags & SCOPE.Cfile &&
|
||||
typeb.ty == Tsarray &&
|
||||
tynto.isSomeChar &&
|
||||
tb.isTypeSArray().dim.toInteger() + 1 == typeb.isTypeSArray().dim.toInteger())
|
||||
{
|
||||
i.exp = se.castTo(sc, t);
|
||||
goto L1;
|
||||
}
|
||||
}
|
||||
/* C11 6.7.9-14..15
|
||||
* Initialize an array of unknown size with a string.
|
||||
|
@ -573,7 +587,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
|
|||
}
|
||||
else if (sc.flags & SCOPE.Cfile && i.exp.isStringExp() &&
|
||||
tta && (tta.next.ty == Tint8 || tta.next.ty == Tuns8) &&
|
||||
ti.ty == Tpointer && ti.nextOf().ty == Tchar)
|
||||
ti.ty == Tsarray && ti.nextOf().ty == Tchar)
|
||||
{
|
||||
/* unsigned char bbb[1] = "";
|
||||
* signed char ccc[1] = "";
|
||||
|
|
|
@ -446,7 +446,7 @@ public:
|
|||
return;
|
||||
jsonProperties(cast(Dsymbol)d);
|
||||
propertyStorageClass("storageClass", d.storage_class);
|
||||
property("linkage", d.linkage);
|
||||
property("linkage", d._linkage);
|
||||
property("type", "deco", d.type);
|
||||
// Emit originalType if it differs from type
|
||||
if (d.type != d.originalType && d.originalType)
|
||||
|
@ -934,7 +934,7 @@ public:
|
|||
|
||||
propertyStart("ddocFiles");
|
||||
arrayStart();
|
||||
foreach (ddocFile; global.params.ddocfiles)
|
||||
foreach (ddocFile; global.params.ddoc.files)
|
||||
{
|
||||
item(ddocFile.toDString);
|
||||
}
|
||||
|
|
|
@ -4375,8 +4375,6 @@ extern (C++) final class TypeFunction : TypeNext
|
|||
{
|
||||
//printf("parameterStorageClass(p: %s)\n", p.toChars());
|
||||
auto stc = p.storageClass;
|
||||
if (global.params.useDIP1000 != FeatureState.enabled)
|
||||
return stc;
|
||||
|
||||
// When the preview switch is enable, `in` parameters are `scope`
|
||||
if (stc & STC.in_ && global.params.previewIn)
|
||||
|
@ -4441,7 +4439,9 @@ extern (C++) final class TypeFunction : TypeNext
|
|||
// Check escaping through return value
|
||||
Type tret = nextOf().toBasetype();
|
||||
if (isref || tret.hasPointers())
|
||||
{
|
||||
return stc | STC.scope_ | STC.return_ | STC.returnScope;
|
||||
}
|
||||
else
|
||||
return stc | STC.scope_;
|
||||
}
|
||||
|
@ -4764,12 +4764,31 @@ extern (C++) final class TypeFunction : TypeNext
|
|||
s ~= "@safe ";
|
||||
if (!f.isNogc && sc.func.setGC())
|
||||
s ~= "nogc ";
|
||||
s[$-1] = '\0';
|
||||
buf.printf("`%s` copy constructor cannot be called from a `%s` context", f.type.toChars(), s.ptr);
|
||||
|
||||
if (s)
|
||||
{
|
||||
s[$-1] = '\0';
|
||||
buf.printf("`%s` copy constructor cannot be called from a `%s` context", f.type.toChars(), s.ptr);
|
||||
}
|
||||
else if (f.isGenerated() && f.isDisabled())
|
||||
{
|
||||
/* https://issues.dlang.org/show_bug.cgi?id=23097
|
||||
* Compiler generated copy constructor failed.
|
||||
*/
|
||||
buf.printf("generating a copy constructor for `struct %s` failed, therefore instances of it are uncopyable",
|
||||
argStruct.toChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Although a copy constructor may exist, no suitable match was found.
|
||||
* i.e: `inout` constructor creates `const` object, not mutable.
|
||||
* Fallback to using the original generic error before bugzilla 22202.
|
||||
*/
|
||||
goto Lnocpctor;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Lnocpctor:
|
||||
buf.printf("`struct %s` does not define a copy constructor for `%s` to `%s` copies",
|
||||
argStruct.toChars(), targ.toChars(), tprm.toChars());
|
||||
}
|
||||
|
@ -5134,22 +5153,6 @@ extern (C++) final class TypeDelegate : TypeNext
|
|||
override Type addStorageClass(StorageClass stc)
|
||||
{
|
||||
TypeDelegate t = cast(TypeDelegate)Type.addStorageClass(stc);
|
||||
if (global.params.useDIP1000 != FeatureState.enabled)
|
||||
return t;
|
||||
|
||||
/* The rest is meant to add 'scope' to a delegate declaration if it is of the form:
|
||||
* alias dg_t = void* delegate();
|
||||
* scope dg_t dg = ...;
|
||||
*/
|
||||
if(stc & STC.scope_)
|
||||
{
|
||||
auto n = t.next.addStorageClass(STC.scope_ | STC.scopeinferred);
|
||||
if (n != t.next)
|
||||
{
|
||||
t.next = n;
|
||||
t.deco = t.merge().deco; // mangling supposed to not be changed due to STC.scope_inferrred
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -5218,8 +5221,8 @@ extern (C++) final class TypeTraits : Type
|
|||
Loc loc;
|
||||
/// The expression to resolve as type or symbol.
|
||||
TraitsExp exp;
|
||||
/// After `typeSemantic` the symbol when `exp` doesn't represent a type.
|
||||
Dsymbol sym;
|
||||
/// Cached type/symbol after semantic analysis.
|
||||
RootObject obj;
|
||||
|
||||
final extern (D) this(const ref Loc loc, TraitsExp exp)
|
||||
{
|
||||
|
|
|
@ -670,8 +670,8 @@ class TypeTraits : public Type
|
|||
Loc loc;
|
||||
/// The expression to resolve as type or symbol.
|
||||
TraitsExp *exp;
|
||||
/// The symbol when exp doesn't represent a type.
|
||||
Dsymbol *sym;
|
||||
/// Cached type/symbol after semantic analysis.
|
||||
RootObject *obj;
|
||||
|
||||
const char *kind();
|
||||
TypeTraits *syntaxCopy();
|
||||
|
|
|
@ -84,6 +84,17 @@ public:
|
|||
}
|
||||
f.printGCUsage(e.loc, "setting `length` may cause a GC allocation");
|
||||
}
|
||||
else if (fd.ident == Id._d_arrayappendT || fd.ident == Id._d_arrayappendcTX)
|
||||
{
|
||||
if (f.setGC())
|
||||
{
|
||||
e.error("cannot use operator `~=` in `@nogc` %s `%s`",
|
||||
f.kind(), f.toPrettyChars());
|
||||
err = true;
|
||||
return;
|
||||
}
|
||||
f.printGCUsage(e.loc, "operator `~=` may cause a GC allocation");
|
||||
}
|
||||
}
|
||||
|
||||
override void visit(ArrayLiteralExp e)
|
||||
|
@ -181,14 +192,15 @@ public:
|
|||
|
||||
override void visit(CatAssignExp e)
|
||||
{
|
||||
/* CatAssignExp will exist in `__traits(compiles, ...)` and in the `.e1` branch of a `__ctfe ? :` CondExp.
|
||||
* The other branch will be `_d_arrayappendcTX(e1, 1), e1[$-1]=e2` which will generate the warning about
|
||||
* GC usage. See visit(CallExp).
|
||||
*/
|
||||
if (f.setGC())
|
||||
{
|
||||
e.error("cannot use operator `~=` in `@nogc` %s `%s`",
|
||||
f.kind(), f.toPrettyChars());
|
||||
err = true;
|
||||
return;
|
||||
}
|
||||
f.printGCUsage(e.loc, "operator `~=` may cause a GC allocation");
|
||||
}
|
||||
|
||||
override void visit(CatExp e)
|
||||
|
|
|
@ -578,7 +578,7 @@ extern(C++) private final class Supported : Objc
|
|||
|
||||
override void checkLinkage(FuncDeclaration fd)
|
||||
{
|
||||
if (fd.linkage != LINK.objc && fd.objc.selector)
|
||||
if (fd._linkage != LINK.objc && fd.objc.selector)
|
||||
fd.error("must have Objective-C linkage to attach a selector");
|
||||
}
|
||||
|
||||
|
@ -640,11 +640,11 @@ extern(C++) private final class Supported : Objc
|
|||
if (!fd.objc.isOptional)
|
||||
return;
|
||||
|
||||
if (fd.linkage != LINK.objc)
|
||||
if (fd._linkage != LINK.objc)
|
||||
{
|
||||
fd.error("only functions with Objective-C linkage can be declared as optional");
|
||||
|
||||
const linkage = linkageToString(fd.linkage);
|
||||
const linkage = linkageToString(fd._linkage);
|
||||
|
||||
errorSupplemental(fd.loc, "function is declared with %.*s linkage",
|
||||
cast(uint) linkage.length, linkage.ptr);
|
||||
|
|
|
@ -558,6 +558,41 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
|
|||
}
|
||||
else if (auto ae = e.e1.isIndexExp())
|
||||
{
|
||||
if (ae.e2.isIntegerExp() && ae.e1.isIndexExp())
|
||||
{
|
||||
/* Rewrite `(a[i])[index]` to `(&a[i]) + index*size`
|
||||
*/
|
||||
sinteger_t index = ae.e2.toInteger();
|
||||
auto ae1 = ae.e1.isIndexExp(); // ae1 is a[i]
|
||||
if (auto ts = ae1.type.isTypeSArray())
|
||||
{
|
||||
sinteger_t dim = ts.dim.toInteger();
|
||||
|
||||
if (index < 0 || index > dim)
|
||||
{
|
||||
e.error("array index %lld is out of bounds `[0..%lld]`", index, dim);
|
||||
return error();
|
||||
}
|
||||
|
||||
import core.checkedint : mulu;
|
||||
bool overflow;
|
||||
const offset = mulu(index, ts.nextOf().size(e.loc), overflow); // offset = index*size
|
||||
if (overflow)
|
||||
{
|
||||
e.error("array offset overflow");
|
||||
return error();
|
||||
}
|
||||
|
||||
Expression ex = new AddrExp(ae1.loc, ae1); // &a[i]
|
||||
ex.type = ae1.type.pointerTo();
|
||||
|
||||
Expression add = new AddExp(ae.loc, ex, new IntegerExp(ae.loc, offset, e.type));
|
||||
add.type = e.type;
|
||||
ret = Expression_optimize(add, result, keepLvalue);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert &array[n] to &array+n
|
||||
if (ae.e2.isIntegerExp() && ae.e1.isVarExp())
|
||||
{
|
||||
|
|
|
@ -289,6 +289,15 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
return true;
|
||||
}
|
||||
|
||||
/************************************
|
||||
* Parse declarations and definitions
|
||||
* Params:
|
||||
* once = !=0 means parse exactly one decl or def
|
||||
* pLastDecl = set to last decl or def parsed
|
||||
* pAttrs = keep track of attributes
|
||||
* Returns:
|
||||
* array of declared symbols
|
||||
*/
|
||||
AST.Dsymbols* parseDeclDefs(int once, AST.Dsymbol* pLastDecl = null, PrefixAttributes!AST* pAttrs = null)
|
||||
{
|
||||
AST.Dsymbol lastDecl = null; // used to link unittest to its previous declaration
|
||||
|
@ -480,7 +489,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
* template instantiations in these unittests as candidates for
|
||||
* further codegen culling.
|
||||
*/
|
||||
if (mod.isRoot() && (global.params.useUnitTests || global.params.doDocComments || global.params.doHdrGeneration))
|
||||
if (mod.isRoot() && (global.params.useUnitTests || global.params.ddoc.doOutput || global.params.dihdr.doOutput))
|
||||
{
|
||||
s = parseUnitTest(pAttrs);
|
||||
if (*pLastDecl)
|
||||
|
@ -713,7 +722,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
// The deprecation period is longer than usual as `body`
|
||||
// was quite widely used.
|
||||
if (tk.value == TOK.identifier && tk.ident == Id._body)
|
||||
deprecation("Usage of the `body` keyword is deprecated. Use `do` instead.");
|
||||
deprecation("usage of the `body` keyword is deprecated. Use `do` instead.");
|
||||
|
||||
a = parseDeclarations(true, pAttrs, pAttrs.comment);
|
||||
if (a && a.dim)
|
||||
|
@ -2649,7 +2658,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
/** Extract unittest body as a string. Must be done eagerly since memory
|
||||
will be released by the lexer before doc gen. */
|
||||
char* docline = null;
|
||||
if (global.params.doDocComments && endPtr > begPtr)
|
||||
if (global.params.ddoc.doOutput && endPtr > begPtr)
|
||||
{
|
||||
/* Remove trailing whitespaces */
|
||||
for (const(char)* p = endPtr - 1; begPtr <= p && (*p == ' ' || *p == '\r' || *p == '\n' || *p == '\t'); --p)
|
||||
|
@ -4298,7 +4307,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
* These can be:
|
||||
* 1. declarations at global/class level
|
||||
* 2. declarations at statement level
|
||||
* Return array of Declaration *'s.
|
||||
* Returns:
|
||||
* array of Declarations.
|
||||
*/
|
||||
private AST.Dsymbols* parseDeclarations(bool autodecl, PrefixAttributes!AST* pAttrs, const(char)* comment)
|
||||
{
|
||||
|
@ -4422,7 +4432,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
// The deprecation period is longer than usual as `body`
|
||||
// was quite widely used.
|
||||
if (tk.value == TOK.identifier && tk.ident == Id._body)
|
||||
deprecation("Usage of the `body` keyword is deprecated. Use `do` instead.");
|
||||
deprecation("usage of the `body` keyword is deprecated. Use `do` instead.");
|
||||
|
||||
ts = null;
|
||||
}
|
||||
|
@ -4459,6 +4469,12 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
else if (t != tfirst)
|
||||
error("multiple declarations must have the same type, not `%s` and `%s`", tfirst.toChars(), t.toChars());
|
||||
|
||||
if (token.value == TOK.colon && !ident && t.ty != Tfunction)
|
||||
{
|
||||
// Unnamed bit field
|
||||
ident = Identifier.generateAnonymousId("BitField");
|
||||
}
|
||||
|
||||
bool isThis = (t.ty == Tident && (cast(AST.TypeIdentifier)t).ident == Id.This && token.value == TOK.assign);
|
||||
if (ident)
|
||||
checkCstyleTypeSyntax(loc, t, alt, ident);
|
||||
|
@ -4591,6 +4607,13 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
}
|
||||
else if (ident)
|
||||
{
|
||||
AST.Expression width;
|
||||
if (token.value == TOK.colon)
|
||||
{
|
||||
nextToken();
|
||||
width = parseCondExp();
|
||||
}
|
||||
|
||||
AST.Initializer _init = null;
|
||||
if (token.value == TOK.assign)
|
||||
{
|
||||
|
@ -4598,12 +4621,25 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
_init = parseInitializer();
|
||||
}
|
||||
|
||||
auto v = new AST.VarDeclaration(loc, t, ident, _init);
|
||||
v.storage_class = storage_class;
|
||||
if (pAttrs)
|
||||
pAttrs.storageClass = STC.undefined_;
|
||||
|
||||
AST.Dsymbol s = v;
|
||||
AST.Dsymbol s;
|
||||
if (width)
|
||||
{
|
||||
if (!global.params.bitfields)
|
||||
error("use -preview=bitfields for bitfield support");
|
||||
if (_init)
|
||||
error("initializer not allowed for bit-field declaration");
|
||||
if (storage_class)
|
||||
error("storage class not allowed for bit-field declaration");
|
||||
s = new AST.BitFieldDeclaration(width.loc, t, ident, width);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto v = new AST.VarDeclaration(loc, t, ident, _init);
|
||||
v.storage_class = storage_class;
|
||||
if (pAttrs)
|
||||
pAttrs.storageClass = STC.undefined_;
|
||||
s = v;
|
||||
}
|
||||
|
||||
if (tpl && _init)
|
||||
{
|
||||
|
@ -4616,7 +4652,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
{
|
||||
auto ax = new AST.Dsymbols();
|
||||
ax.push(s);
|
||||
s = new AST.AlignDeclaration(v.loc, ealign, ax);
|
||||
s = new AST.AlignDeclaration(s.loc, ealign, ax);
|
||||
}
|
||||
if (link != linkage)
|
||||
{
|
||||
|
@ -4646,12 +4682,12 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
default:
|
||||
if (loc.linnum != token.loc.linnum)
|
||||
{
|
||||
error("semicolon needed to end declaration of `%s`, instead of `%s`", v.toChars(), token.toChars());
|
||||
errorSupplemental(loc, "`%s` declared here", v.toChars());
|
||||
error("semicolon needed to end declaration of `%s`, instead of `%s`", s.toChars(), token.toChars());
|
||||
errorSupplemental(loc, "`%s` declared here", s.toChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
error("semicolon needed to end declaration of `%s` instead of `%s`", v.toChars(), token.toChars());
|
||||
error("semicolon needed to end declaration of `%s` instead of `%s`", s.toChars(), token.toChars());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -4826,7 +4862,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
if (udas !is null)
|
||||
{
|
||||
if (storage_class != 0)
|
||||
error("Cannot put a storage-class in an alias declaration.");
|
||||
error("cannot put a storage-class in an alias declaration.");
|
||||
// parseAttributes shouldn't have set these variables
|
||||
assert(link == linkage && !setAlignment && ealign is null);
|
||||
auto tpl_ = cast(AST.TemplateDeclaration) s;
|
||||
|
@ -5034,7 +5070,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
check(TOK.goesTo);
|
||||
if (token.value == TOK.leftCurly)
|
||||
{
|
||||
deprecation("Using `(args) => { ... }` to create a delegate that returns a delegate is error-prone.");
|
||||
deprecation("using `(args) => { ... }` to create a delegate that returns a delegate is error-prone.");
|
||||
deprecationSupplemental(token.loc, "Use `(args) { ... }` for a multi-statement function literal or use `(args) => () { }` if you intended for the lambda to return a delegate.");
|
||||
}
|
||||
const returnloc = token.loc;
|
||||
|
@ -5100,7 +5136,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
// Deprecated in 2.097 - Can be removed from 2.117
|
||||
// The deprecation period is longer than usual as `body`
|
||||
// was quite widely used.
|
||||
deprecation("Usage of the `body` keyword is deprecated. Use `do` instead.");
|
||||
deprecation("usage of the `body` keyword is deprecated. Use `do` instead.");
|
||||
goto case TOK.do_;
|
||||
}
|
||||
goto default;
|
||||
|
@ -7426,7 +7462,7 @@ LagainStc:
|
|||
// Deprecated in 2.097 - Can be removed from 2.117
|
||||
// The deprecation period is longer than usual as `body`
|
||||
// was quite widely used.
|
||||
deprecation("Usage of the `body` keyword is deprecated. Use `do` instead.");
|
||||
deprecation("usage of the `body` keyword is deprecated. Use `do` instead.");
|
||||
goto case TOK.do_;
|
||||
}
|
||||
goto default;
|
||||
|
@ -8026,7 +8062,7 @@ LagainStc:
|
|||
postfix = token.postfix;
|
||||
}
|
||||
|
||||
error("Implicit string concatenation is error-prone and disallowed in D");
|
||||
error("implicit string concatenation is error-prone and disallowed in D");
|
||||
errorSupplemental(token.loc, "Use the explicit syntax instead " ~
|
||||
"(concatenating literals is `@nogc`): %s ~ %s",
|
||||
prev.toChars(), token.toChars());
|
||||
|
@ -9580,18 +9616,18 @@ private StorageClass getStorageClass(AST)(PrefixAttributes!(AST)* pAttrs)
|
|||
*/
|
||||
private bool writeMixin(const(char)[] s, ref Loc loc)
|
||||
{
|
||||
if (!global.params.mixinOut)
|
||||
if (!global.params.mixinOut.doOutput)
|
||||
return false;
|
||||
|
||||
OutBuffer* ob = global.params.mixinOut;
|
||||
OutBuffer* ob = global.params.mixinOut.buffer;
|
||||
|
||||
ob.writestring("// expansion at ");
|
||||
ob.writestring(loc.toChars());
|
||||
ob.writenl();
|
||||
|
||||
global.params.mixinLines++;
|
||||
global.params.mixinOut.bufferLines++;
|
||||
|
||||
loc = Loc(global.params.mixinFile, global.params.mixinLines + 1, loc.charnum);
|
||||
loc = Loc(global.params.mixinOut.name.ptr, global.params.mixinOut.bufferLines + 1, loc.charnum);
|
||||
|
||||
// write by line to create consistent line endings
|
||||
size_t lastpos = 0;
|
||||
|
@ -9603,7 +9639,7 @@ private bool writeMixin(const(char)[] s, ref Loc loc)
|
|||
{
|
||||
ob.writestring(s[lastpos .. i]);
|
||||
ob.writenl();
|
||||
global.params.mixinLines++;
|
||||
global.params.mixinOut.bufferLines++;
|
||||
if (c == '\r')
|
||||
++i;
|
||||
lastpos = i + 1;
|
||||
|
@ -9616,10 +9652,10 @@ private bool writeMixin(const(char)[] s, ref Loc loc)
|
|||
if (s.length == 0 || s[$-1] != '\n')
|
||||
{
|
||||
ob.writenl(); // ensure empty line after expansion
|
||||
global.params.mixinLines++;
|
||||
global.params.mixinOut.bufferLines++;
|
||||
}
|
||||
ob.writenl();
|
||||
global.params.mixinLines++;
|
||||
global.params.mixinOut.bufferLines++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg)
|
|||
{
|
||||
if (sc.intypeof || !sc.func || !sc.func.isSafeBypassingInference())
|
||||
return false;
|
||||
auto ad = v.toParent2().isAggregateDeclaration();
|
||||
auto ad = v.isMember2();
|
||||
if (!ad)
|
||||
return false;
|
||||
|
||||
|
@ -64,23 +64,22 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg)
|
|||
const hasPointers = v.type.hasPointers();
|
||||
if (hasPointers)
|
||||
{
|
||||
if (v.overlapped && sc.func.setUnsafe())
|
||||
if (v.overlapped)
|
||||
{
|
||||
if (printmsg)
|
||||
e.error("field `%s.%s` cannot access pointers in `@safe` code that overlap other fields",
|
||||
ad.toChars(), v.toChars());
|
||||
return true;
|
||||
if (sc.func.setUnsafe(!printmsg, e.loc,
|
||||
"field `%s.%s` cannot access pointers in `@safe` code that overlap other fields", ad, v))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (v.type.hasInvariant())
|
||||
{
|
||||
if (v.overlapped && sc.func.setUnsafe())
|
||||
if (v.overlapped)
|
||||
{
|
||||
if (printmsg)
|
||||
e.error("field `%s.%s` cannot access structs with invariants in `@safe` code that overlap other fields",
|
||||
ad.toChars(), v.toChars());
|
||||
return true;
|
||||
if (sc.func.setUnsafe(!printmsg, e.loc,
|
||||
"field `%s.%s` cannot access structs with invariants in `@safe` code that overlap other fields",
|
||||
ad, v))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,22 +89,22 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg)
|
|||
if (hasPointers && v.type.toBasetype().ty != Tstruct)
|
||||
{
|
||||
if ((!ad.type.alignment.isDefault() && ad.type.alignment.get() < target.ptrsize ||
|
||||
(v.offset & (target.ptrsize - 1))) &&
|
||||
sc.func.setUnsafe())
|
||||
(v.offset & (target.ptrsize - 1))))
|
||||
{
|
||||
if (printmsg)
|
||||
e.error("field `%s.%s` cannot modify misaligned pointers in `@safe` code",
|
||||
ad.toChars(), v.toChars());
|
||||
return true;
|
||||
if (sc.func.setUnsafe(!printmsg, e.loc,
|
||||
"field `%s.%s` cannot modify misaligned pointers in `@safe` code", ad, v))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (v.overlapUnsafe && sc.func.setUnsafe())
|
||||
if (v.overlapUnsafe)
|
||||
{
|
||||
if (printmsg)
|
||||
e.error("field `%s.%s` cannot modify fields in `@safe` code that overlap fields with other storage classes",
|
||||
ad.toChars(), v.toChars());
|
||||
return true;
|
||||
if (sc.func.setUnsafe(!printmsg, e.loc,
|
||||
"field `%s.%s` cannot modify fields in `@safe` code that overlap fields with other storage classes",
|
||||
ad, v))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -215,14 +214,12 @@ bool checkUnsafeDotExp(Scope* sc, Expression e, Identifier id, int flag)
|
|||
if (!(flag & DotExpFlag.noDeref) && // this use is attempting a dereference
|
||||
sc.func && // inside a function
|
||||
!sc.intypeof && // allow unsafe code in typeof expressions
|
||||
!(sc.flags & SCOPE.debug_) && // allow unsafe code in debug statements
|
||||
sc.func.setUnsafe()) // infer this function to be unsafe
|
||||
!(sc.flags & SCOPE.debug_)) // allow unsafe code in debug statements
|
||||
{
|
||||
if (id == Id.ptr)
|
||||
e.error("`%s.ptr` cannot be used in `@safe` code, use `&%s[0]` instead", e.toChars(), e.toChars());
|
||||
return sc.func.setUnsafe(false, e.loc, "`%s.ptr` cannot be used in `@safe` code, use `&%s[0]` instead", e, e);
|
||||
else
|
||||
e.error("`%s.%s` cannot be used in `@safe` code", e.toChars(), id.toChars());
|
||||
return true;
|
||||
return sc.func.setUnsafe(false, e.loc, "`%s.%s` cannot be used in `@safe` code", e, id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -238,7 +238,7 @@ private extern(C++) final class Semantic2Visitor : Visitor
|
|||
return;
|
||||
}
|
||||
|
||||
UserAttributeDeclaration.checkGNUABITag(vd, vd.linkage);
|
||||
UserAttributeDeclaration.checkGNUABITag(vd, vd._linkage);
|
||||
|
||||
if (vd._init && !vd.toParent().isFuncDeclaration())
|
||||
{
|
||||
|
@ -379,6 +379,7 @@ private extern(C++) final class Semantic2Visitor : Visitor
|
|||
alias f1 = fd;
|
||||
auto tf1 = cast(TypeFunction) f1.type;
|
||||
auto parent1 = f1.toParent2();
|
||||
const linkage1 = f1.resolvedLinkage();
|
||||
|
||||
overloadApply(f1, (Dsymbol s)
|
||||
{
|
||||
|
@ -391,7 +392,7 @@ private extern(C++) final class Semantic2Visitor : Visitor
|
|||
return 0;
|
||||
|
||||
// Functions with different manglings can never conflict
|
||||
if (f1.linkage != f2.linkage)
|
||||
if (linkage1 != f2.resolvedLinkage())
|
||||
return 0;
|
||||
|
||||
// Functions with different names never conflict
|
||||
|
@ -428,12 +429,12 @@ private extern(C++) final class Semantic2Visitor : Visitor
|
|||
// @@@DEPRECATED_2.104@@@
|
||||
// Deprecated in 2020-08, make this an error in 2.104
|
||||
if (parent1.isModule() &&
|
||||
f1.linkage != LINK.d && f1.linkage != LINK.cpp &&
|
||||
linkage1 != LINK.d && linkage1 != LINK.cpp &&
|
||||
(!sameAttr || !sameParams)
|
||||
)
|
||||
{
|
||||
f2.deprecation("cannot overload `extern(%s)` function at %s",
|
||||
linkageToChars(f1.linkage),
|
||||
linkageToChars(f1._linkage),
|
||||
f1.loc.toChars());
|
||||
return 0;
|
||||
}
|
||||
|
@ -443,7 +444,7 @@ private extern(C++) final class Semantic2Visitor : Visitor
|
|||
return 0;
|
||||
|
||||
// Different attributes don't conflict in extern(D)
|
||||
if (!sameAttr && f1.linkage == LINK.d)
|
||||
if (!sameAttr && linkage1 == LINK.d)
|
||||
return 0;
|
||||
|
||||
error(f2.loc, "%s `%s%s` conflicts with previous declaration at %s",
|
||||
|
@ -460,7 +461,7 @@ private extern(C++) final class Semantic2Visitor : Visitor
|
|||
return;
|
||||
TypeFunction f = cast(TypeFunction) fd.type;
|
||||
|
||||
UserAttributeDeclaration.checkGNUABITag(fd, fd.linkage);
|
||||
UserAttributeDeclaration.checkGNUABITag(fd, fd._linkage);
|
||||
//semantic for parameters' UDAs
|
||||
foreach (i, param; f.parameterList)
|
||||
{
|
||||
|
@ -643,7 +644,7 @@ private extern(C++) final class Semantic2Visitor : Visitor
|
|||
{
|
||||
//printf(" found\n");
|
||||
// Check that calling conventions match
|
||||
if (fd.linkage != ifd.linkage)
|
||||
if (fd._linkage != ifd._linkage)
|
||||
fd.error("linkage doesn't match interface function");
|
||||
|
||||
// Check that it is current
|
||||
|
|
|
@ -327,7 +327,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
|||
sc2.scontinue = null;
|
||||
sc2.sw = null;
|
||||
sc2.fes = funcdecl.fes;
|
||||
sc2.linkage = LINK.d;
|
||||
sc2.linkage = funcdecl.isCsymbol() ? LINK.c : LINK.d;
|
||||
sc2.stc &= STC.flowThruFunction;
|
||||
sc2.visibility = Visibility(Visibility.Kind.public_);
|
||||
sc2.explicitVisibility = 0;
|
||||
|
@ -1053,7 +1053,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
|||
{
|
||||
if (!v._init)
|
||||
{
|
||||
v.error("Zero-length `out` parameters are not allowed.");
|
||||
v.error("zero-length `out` parameters are not allowed.");
|
||||
return;
|
||||
}
|
||||
ExpInitializer ie = v._init.isExpInitializer();
|
||||
|
@ -1277,70 +1277,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
|||
f.isnogc = true;
|
||||
}
|
||||
|
||||
if (funcdecl.flags & FUNCFLAG.returnInprocess)
|
||||
{
|
||||
funcdecl.flags &= ~FUNCFLAG.returnInprocess;
|
||||
if (funcdecl.storage_class & STC.return_)
|
||||
{
|
||||
if (funcdecl.type == f)
|
||||
f = cast(TypeFunction)f.copy();
|
||||
f.isreturn = true;
|
||||
f.isreturnscope = cast(bool) (funcdecl.storage_class & STC.returnScope);
|
||||
if (funcdecl.storage_class & STC.returninferred)
|
||||
f.isreturninferred = true;
|
||||
}
|
||||
}
|
||||
|
||||
funcdecl.flags &= ~FUNCFLAG.inferScope;
|
||||
|
||||
// Eliminate maybescope's
|
||||
{
|
||||
// Create and fill array[] with maybe candidates from the `this` and the parameters
|
||||
VarDeclaration[10] tmp = void;
|
||||
size_t dim = (funcdecl.vthis !is null) + (funcdecl.parameters ? funcdecl.parameters.dim : 0);
|
||||
|
||||
import dmd.common.string : SmallBuffer;
|
||||
auto sb = SmallBuffer!VarDeclaration(dim, tmp[]);
|
||||
VarDeclaration[] array = sb[];
|
||||
|
||||
size_t n = 0;
|
||||
if (funcdecl.vthis)
|
||||
array[n++] = funcdecl.vthis;
|
||||
if (funcdecl.parameters)
|
||||
{
|
||||
foreach (v; *funcdecl.parameters)
|
||||
{
|
||||
array[n++] = v;
|
||||
}
|
||||
}
|
||||
eliminateMaybeScopes(array[0 .. n]);
|
||||
}
|
||||
|
||||
// Infer STC.scope_
|
||||
if (funcdecl.parameters && !funcdecl.errors)
|
||||
{
|
||||
assert(f.parameterList.length == funcdecl.parameters.dim);
|
||||
foreach (u, p; f.parameterList)
|
||||
{
|
||||
auto v = (*funcdecl.parameters)[u];
|
||||
if (v.storage_class & STC.maybescope)
|
||||
{
|
||||
//printf("Inferring scope for %s\n", v.toChars());
|
||||
notMaybeScope(v);
|
||||
v.storage_class |= STC.scope_ | STC.scopeinferred;
|
||||
p.storageClass |= STC.scope_ | STC.scopeinferred;
|
||||
assert(!(p.storageClass & STC.maybescope));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (funcdecl.vthis && funcdecl.vthis.storage_class & STC.maybescope)
|
||||
{
|
||||
notMaybeScope(funcdecl.vthis);
|
||||
funcdecl.vthis.storage_class |= STC.scope_ | STC.scopeinferred;
|
||||
f.isScopeQual = true;
|
||||
f.isscopeinferred = true;
|
||||
}
|
||||
finishScopeParamInference(funcdecl, f);
|
||||
|
||||
// reset deco to apply inference result to mangled name
|
||||
if (f != funcdecl.type)
|
||||
|
@ -1353,11 +1290,77 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
|||
if (funcdecl.isCtorDeclaration()) // https://issues.dlang.org/show_bug.cgi?id=#15665
|
||||
f.isctor = true;
|
||||
sc.stc = 0;
|
||||
sc.linkage = funcdecl.linkage; // https://issues.dlang.org/show_bug.cgi?id=8496
|
||||
sc.linkage = funcdecl._linkage; // https://issues.dlang.org/show_bug.cgi?id=8496
|
||||
funcdecl.type = f.typeSemantic(funcdecl.loc, sc);
|
||||
sc = sc.pop();
|
||||
}
|
||||
|
||||
// Check `extern(C++)` functions for invalid the return/parameter types
|
||||
if (funcdecl._linkage == LINK.cpp)
|
||||
{
|
||||
static bool isCppNonMappableType(Type type, Parameter param = null, Type origType = null)
|
||||
{
|
||||
// Don't allow D `immutable` and `shared` types to be interfaced with C++
|
||||
if (type.isImmutable() || type.isShared())
|
||||
return true;
|
||||
else if (Type cpptype = target.cpp.parameterType(type))
|
||||
type = cpptype;
|
||||
|
||||
if (origType is null)
|
||||
origType = type;
|
||||
|
||||
// Permit types that are handled by toCppMangle. This list should be kept in sync with
|
||||
// each visit method in dmd.cppmangle and dmd.cppmanglewin.
|
||||
switch (type.ty)
|
||||
{
|
||||
case Tnull:
|
||||
case Tnoreturn:
|
||||
case Tvector:
|
||||
case Tpointer:
|
||||
case Treference:
|
||||
case Tfunction:
|
||||
case Tstruct:
|
||||
case Tenum:
|
||||
case Tclass:
|
||||
case Tident:
|
||||
case Tinstance:
|
||||
break;
|
||||
|
||||
case Tsarray:
|
||||
if (!origType.isTypePointer())
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!type.isTypeBasic())
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Descend to the enclosing type
|
||||
if (auto tnext = type.nextOf())
|
||||
return isCppNonMappableType(tnext, param, origType);
|
||||
|
||||
return false;
|
||||
}
|
||||
if (isCppNonMappableType(f.next.toBasetype()))
|
||||
{
|
||||
funcdecl.error("cannot return type `%s` because its linkage is `extern(C++)`", f.next.toChars());
|
||||
funcdecl.errors = true;
|
||||
}
|
||||
foreach (i, param; f.parameterList)
|
||||
{
|
||||
if (isCppNonMappableType(param.type.toBasetype(), param))
|
||||
{
|
||||
funcdecl.error("cannot have parameter of type `%s` because its linkage is `extern(C++)`", param.type.toChars());
|
||||
if (param.type.toBasetype().isTypeSArray())
|
||||
errorSupplemental(funcdecl.loc, "perhaps use a `%s*` type instead",
|
||||
param.type.nextOf().mutableOf().unSharedOf().toChars());
|
||||
funcdecl.errors = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do live analysis
|
||||
if (global.params.useDIP1021 && funcdecl.fbody && funcdecl.type.ty != Terror &&
|
||||
funcdecl.type.isTypeFunction().islive)
|
||||
|
@ -1535,9 +1538,11 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
|||
|
||||
sc2.pop();
|
||||
|
||||
// don't do it for unused deprecated types
|
||||
// or error ypes
|
||||
if (!ad.getRTInfo && Type.rtinfo && (!ad.isDeprecated() || global.params.useDeprecated != DiagnosticReporting.error) && (ad.type && ad.type.ty != Terror))
|
||||
// Instantiate RTInfo!S to provide a pointer bitmap for the GC
|
||||
// Don't do it in -betterC or on unused deprecated / error types
|
||||
if (!ad.getRTInfo && global.params.useTypeInfo && Type.rtinfo &&
|
||||
(!ad.isDeprecated() || global.params.useDeprecated != DiagnosticReporting.error) &&
|
||||
(ad.type && ad.type.ty != Terror))
|
||||
{
|
||||
// Evaluate: RTinfo!type
|
||||
auto tiargs = new Objects();
|
||||
|
|
|
@ -3554,13 +3554,13 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
|
|||
|
||||
if (!global.params.useExceptions)
|
||||
{
|
||||
tcs.error("Cannot use try-catch statements with -betterC");
|
||||
tcs.error("cannot use try-catch statements with -betterC");
|
||||
return setError();
|
||||
}
|
||||
|
||||
if (!ClassDeclaration.throwable)
|
||||
{
|
||||
tcs.error("Cannot use try-catch statements because `object.Throwable` was not declared");
|
||||
tcs.error("cannot use try-catch statements because `object.Throwable` was not declared");
|
||||
return setError();
|
||||
}
|
||||
|
||||
|
@ -3762,13 +3762,13 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
|
|||
{
|
||||
if (!global.params.useExceptions)
|
||||
{
|
||||
loc.error("Cannot use `throw` statements with -betterC");
|
||||
loc.error("cannot use `throw` statements with -betterC");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ClassDeclaration.throwable)
|
||||
{
|
||||
loc.error("Cannot use `throw` statements because `object.Throwable` was not declared");
|
||||
loc.error("cannot use `throw` statements because `object.Throwable` was not declared");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3927,8 +3927,10 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
|
|||
cas.error("`asm` statement is assumed to be impure - mark it with `pure` if it is not");
|
||||
if (!(cas.stc & STC.nogc) && sc.func.setGC())
|
||||
cas.error("`asm` statement is assumed to use the GC - mark it with `@nogc` if it does not");
|
||||
if (!(cas.stc & (STC.trusted | STC.safe)) && sc.func.setUnsafe())
|
||||
cas.error("`asm` statement is assumed to be `@system` - mark it with `@trusted` if it is not");
|
||||
if (!(cas.stc & (STC.trusted | STC.safe)))
|
||||
{
|
||||
sc.func.setUnsafe(false, cas.loc, "`asm` statement is assumed to be `@system` - mark it with `@trusted` if it is not");
|
||||
}
|
||||
|
||||
sc.pop();
|
||||
result = cas;
|
||||
|
@ -4032,10 +4034,10 @@ void catchSemantic(Catch c, Scope* sc)
|
|||
error(c.loc, "catching C++ class objects not supported for this target");
|
||||
c.errors = true;
|
||||
}
|
||||
if (sc.func && !sc.intypeof && !c.internalCatch && sc.func.setUnsafe())
|
||||
if (sc.func && !sc.intypeof && !c.internalCatch)
|
||||
{
|
||||
error(c.loc, "cannot catch C++ class objects in `@safe` code");
|
||||
c.errors = true;
|
||||
if (sc.func.setUnsafe(false, c.loc, "cannot catch C++ class objects in `@safe` code"))
|
||||
c.errors = true;
|
||||
}
|
||||
}
|
||||
else if (cd != ClassDeclaration.throwable && !ClassDeclaration.throwable.isBaseOf(cd, null))
|
||||
|
@ -4044,10 +4046,10 @@ void catchSemantic(Catch c, Scope* sc)
|
|||
c.errors = true;
|
||||
}
|
||||
else if (sc.func && !sc.intypeof && !c.internalCatch && ClassDeclaration.exception &&
|
||||
cd != ClassDeclaration.exception && !ClassDeclaration.exception.isBaseOf(cd, null) &&
|
||||
sc.func.setUnsafe())
|
||||
cd != ClassDeclaration.exception && !ClassDeclaration.exception.isBaseOf(cd, null) &&
|
||||
sc.func.setUnsafe(false, c.loc,
|
||||
"can only catch class objects derived from `Exception` in `@safe` code, not `%s`", c.type))
|
||||
{
|
||||
error(c.loc, "can only catch class objects derived from `Exception` in `@safe` code, not `%s`", c.type.toChars());
|
||||
c.errors = true;
|
||||
}
|
||||
else if (global.params.ehnogc)
|
||||
|
@ -4829,7 +4831,7 @@ private Statement toStatement(Dsymbol s)
|
|||
}
|
||||
else
|
||||
{
|
||||
.error(Loc.initial, "Internal Compiler Error: cannot mixin %s `%s`\n", s.kind(), s.toChars());
|
||||
.error(Loc.initial, "internal compiler error: cannot mixin %s `%s`\n", s.kind(), s.toChars());
|
||||
result = new ErrorStatement();
|
||||
}
|
||||
|
||||
|
|
|
@ -608,7 +608,7 @@ static immutable TOK[TOK.max + 1] Ckeywords =
|
|||
enum Ckwds = [ auto_, break_, case_, char_, const_, continue_, default_, do_, float64, else_,
|
||||
enum_, extern_, float32, for_, goto_, if_, inline, int32, int64, register,
|
||||
restrict, return_, int16, signed, sizeof_, static_, struct_, switch_, typedef_,
|
||||
union_, unsigned, void_, volatile, while_, asm_,
|
||||
union_, unsigned, void_, volatile, while_, asm_, typeof_,
|
||||
_Alignas, _Alignof, _Atomic, _Bool, _Complex, _Generic, _Imaginary, _Noreturn,
|
||||
_Static_assert, _Thread_local, _import, __cdecl, __declspec, __stdcall, __attribute__ ];
|
||||
|
||||
|
|
|
@ -132,6 +132,7 @@ shared static this()
|
|||
"getVirtualFunctions",
|
||||
"getVirtualMethods",
|
||||
"classInstanceSize",
|
||||
"classInstanceAlignment",
|
||||
"allMembers",
|
||||
"derivedMembers",
|
||||
"isSame",
|
||||
|
@ -1211,7 +1212,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
|
|||
else
|
||||
assert(0);
|
||||
}
|
||||
if (e.ident == Id.classInstanceSize)
|
||||
if (e.ident == Id.classInstanceSize || e.ident == Id.classInstanceAlignment)
|
||||
{
|
||||
if (dim != 1)
|
||||
return dimError(1);
|
||||
|
@ -1234,7 +1235,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
|
|||
return ErrorExp.get();
|
||||
}
|
||||
|
||||
return new IntegerExp(e.loc, cd.structsize, Type.tsize_t);
|
||||
return new IntegerExp(e.loc, e.ident == Id.classInstanceSize ? cd.structsize : cd.alignsize, Type.tsize_t);
|
||||
}
|
||||
if (e.ident == Id.getAliasThis)
|
||||
{
|
||||
|
@ -1381,7 +1382,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
|
|||
e.error("argument to `__traits(getFunctionVariadicStyle, %s)` is not a function", o.toChars());
|
||||
return ErrorExp.get();
|
||||
}
|
||||
link = fd.linkage;
|
||||
link = fd._linkage;
|
||||
varargs = fd.getParameterList().varargs;
|
||||
}
|
||||
string style;
|
||||
|
@ -1515,7 +1516,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
|
|||
|
||||
if (tf)
|
||||
{
|
||||
link = fd ? fd.linkage : tf.linkage;
|
||||
link = fd ? fd.toAliasFunc()._linkage : tf.linkage;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1529,7 +1530,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
|
|||
}
|
||||
|
||||
if (d !is null)
|
||||
link = d.linkage;
|
||||
link = d._linkage;
|
||||
else
|
||||
{
|
||||
// Resolves forward references
|
||||
|
@ -1574,7 +1575,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
|
|||
auto s = getDsymbol(o);
|
||||
if (!s)
|
||||
{
|
||||
e.error("In expression `%s` `%s` can't have members", e.toChars(), o.toChars());
|
||||
e.error("in expression `%s` `%s` can't have members", e.toChars(), o.toChars());
|
||||
e.errorSupplemental("`%s` must evaluate to either a module, a struct, an union, a class, an interface or a template instantiation", o.toChars());
|
||||
|
||||
return ErrorExp.get();
|
||||
|
@ -1595,7 +1596,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
|
|||
auto sds = s.isScopeDsymbol();
|
||||
if (!sds || sds.isTemplateDeclaration())
|
||||
{
|
||||
e.error("In expression `%s` %s `%s` has no members", e.toChars(), s.kind(), s.toChars());
|
||||
e.error("in expression `%s` %s `%s` has no members", e.toChars(), s.kind(), s.toChars());
|
||||
e.errorSupplemental("`%s` must evaluate to either a module, a struct, an union, a class, an interface or a template instantiation", s.toChars());
|
||||
return ErrorExp.get();
|
||||
}
|
||||
|
|
|
@ -1154,7 +1154,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
|
|||
//printf("already done\n");
|
||||
return mtype;
|
||||
}
|
||||
//printf("TypeFunction::semantic() this = %p\n", this);
|
||||
//printf("TypeFunction::semantic() this = %p\n", mtype);
|
||||
//printf("TypeFunction::semantic() %s, sc.stc = %llx\n", mtype.toChars(), sc.stc);
|
||||
|
||||
bool errors = false;
|
||||
|
@ -1788,111 +1788,18 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
|
|||
|
||||
Type visitTraits(TypeTraits mtype)
|
||||
{
|
||||
if (mtype.ty == Terror)
|
||||
return mtype;
|
||||
Expression e;
|
||||
Type t;
|
||||
Dsymbol s;
|
||||
mtype.resolve(loc, sc, e, t, s);
|
||||
|
||||
const inAlias = (sc.flags & SCOPE.alias_) != 0;
|
||||
if (mtype.exp.ident != Id.allMembers &&
|
||||
mtype.exp.ident != Id.derivedMembers &&
|
||||
mtype.exp.ident != Id.getMember &&
|
||||
mtype.exp.ident != Id.parent &&
|
||||
mtype.exp.ident != Id.parameters &&
|
||||
mtype.exp.ident != Id.child &&
|
||||
mtype.exp.ident != Id.toType &&
|
||||
mtype.exp.ident != Id.getOverloads &&
|
||||
mtype.exp.ident != Id.getVirtualFunctions &&
|
||||
mtype.exp.ident != Id.getVirtualMethods &&
|
||||
mtype.exp.ident != Id.getAttributes &&
|
||||
mtype.exp.ident != Id.getUnitTests &&
|
||||
mtype.exp.ident != Id.getAliasThis)
|
||||
{
|
||||
static immutable (const(char)*)[2] ctxt = ["as type", "in alias"];
|
||||
.error(mtype.loc, "trait `%s` is either invalid or not supported %s",
|
||||
mtype.exp.ident.toChars, ctxt[inAlias]);
|
||||
mtype.ty = Terror;
|
||||
return mtype;
|
||||
}
|
||||
|
||||
import dmd.traits : semanticTraits;
|
||||
Type result;
|
||||
|
||||
if (Expression e = semanticTraits(mtype.exp, sc))
|
||||
{
|
||||
switch (e.op)
|
||||
{
|
||||
case EXP.dotVariable:
|
||||
mtype.sym = e.isDotVarExp().var;
|
||||
break;
|
||||
case EXP.variable:
|
||||
mtype.sym = e.isVarExp().var;
|
||||
break;
|
||||
case EXP.function_:
|
||||
auto fe = e.isFuncExp();
|
||||
mtype.sym = fe.td ? fe.td : fe.fd;
|
||||
break;
|
||||
case EXP.dotTemplateDeclaration:
|
||||
mtype.sym = e.isDotTemplateExp().td;
|
||||
break;
|
||||
case EXP.dSymbol:
|
||||
mtype.sym = e.isDsymbolExp().s;
|
||||
break;
|
||||
case EXP.template_:
|
||||
mtype.sym = e.isTemplateExp().td;
|
||||
break;
|
||||
case EXP.scope_:
|
||||
mtype.sym = e.isScopeExp().sds;
|
||||
break;
|
||||
case EXP.tuple:
|
||||
TupleExp te = e.isTupleExp();
|
||||
Objects* elems = new Objects(te.exps.dim);
|
||||
foreach (i; 0 .. elems.dim)
|
||||
{
|
||||
auto src = (*te.exps)[i];
|
||||
switch (src.op)
|
||||
{
|
||||
case EXP.type:
|
||||
(*elems)[i] = src.isTypeExp().type;
|
||||
break;
|
||||
case EXP.dotType:
|
||||
(*elems)[i] = src.isDotTypeExp().sym.isType();
|
||||
break;
|
||||
case EXP.overloadSet:
|
||||
(*elems)[i] = src.isOverExp().type;
|
||||
break;
|
||||
default:
|
||||
if (auto sym = isDsymbol(src))
|
||||
(*elems)[i] = sym;
|
||||
else
|
||||
(*elems)[i] = src;
|
||||
}
|
||||
}
|
||||
TupleDeclaration td = new TupleDeclaration(e.loc, Identifier.generateId("__aliastup"), elems);
|
||||
mtype.sym = td;
|
||||
break;
|
||||
case EXP.dotType:
|
||||
result = e.isDotTypeExp().sym.isType();
|
||||
break;
|
||||
case EXP.type:
|
||||
result = e.isTypeExp().type;
|
||||
break;
|
||||
case EXP.overloadSet:
|
||||
result = e.isOverExp().type;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
result = result.addMod(mtype.mod);
|
||||
if (!inAlias && !result)
|
||||
if (!t)
|
||||
{
|
||||
if (!global.errors)
|
||||
.error(mtype.loc, "`%s` does not give a valid type", mtype.toChars);
|
||||
return error();
|
||||
}
|
||||
|
||||
return result;
|
||||
return t;
|
||||
}
|
||||
|
||||
Type visitReturn(TypeReturn mtype)
|
||||
|
@ -3132,7 +3039,8 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type
|
|||
if (mt.exp.op == EXP.type ||
|
||||
mt.exp.op == EXP.scope_)
|
||||
{
|
||||
if (mt.exp.checkType())
|
||||
if (!(sc.flags & SCOPE.Cfile) && // in (extended) C typeof may be used on types as with sizeof
|
||||
mt.exp.checkType())
|
||||
goto Lerr;
|
||||
|
||||
/* Today, 'typeof(func)' returns void if func is a
|
||||
|
@ -3326,14 +3234,99 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type
|
|||
mt.obj = pe ? pe : (pt ? pt : ps);
|
||||
}
|
||||
|
||||
void visitTraits(TypeTraits tt)
|
||||
void visitTraits(TypeTraits mt)
|
||||
{
|
||||
if (Type t = typeSemantic(tt, loc, sc))
|
||||
returnType(t);
|
||||
else if (tt.sym)
|
||||
returnSymbol(tt.sym);
|
||||
// if already resolved just return the cached object.
|
||||
if (mt.obj)
|
||||
{
|
||||
pt = mt.obj.isType();
|
||||
ps = mt.obj.isDsymbol();
|
||||
return;
|
||||
}
|
||||
|
||||
import dmd.traits : semanticTraits;
|
||||
|
||||
if (Expression e = semanticTraits(mt.exp, sc))
|
||||
{
|
||||
switch (e.op)
|
||||
{
|
||||
case EXP.dotVariable:
|
||||
mt.obj = e.isDotVarExp().var;
|
||||
break;
|
||||
case EXP.variable:
|
||||
mt.obj = e.isVarExp().var;
|
||||
break;
|
||||
case EXP.function_:
|
||||
auto fe = e.isFuncExp();
|
||||
mt.obj = fe.td ? fe.td : fe.fd;
|
||||
break;
|
||||
case EXP.dotTemplateDeclaration:
|
||||
mt.obj = e.isDotTemplateExp().td;
|
||||
break;
|
||||
case EXP.dSymbol:
|
||||
mt.obj = e.isDsymbolExp().s;
|
||||
break;
|
||||
case EXP.template_:
|
||||
mt.obj = e.isTemplateExp().td;
|
||||
break;
|
||||
case EXP.scope_:
|
||||
mt.obj = e.isScopeExp().sds;
|
||||
break;
|
||||
case EXP.tuple:
|
||||
TupleExp te = e.isTupleExp();
|
||||
Objects* elems = new Objects(te.exps.dim);
|
||||
foreach (i; 0 .. elems.dim)
|
||||
{
|
||||
auto src = (*te.exps)[i];
|
||||
switch (src.op)
|
||||
{
|
||||
case EXP.type:
|
||||
(*elems)[i] = src.isTypeExp().type;
|
||||
break;
|
||||
case EXP.dotType:
|
||||
(*elems)[i] = src.isDotTypeExp().sym.isType();
|
||||
break;
|
||||
case EXP.overloadSet:
|
||||
(*elems)[i] = src.isOverExp().type;
|
||||
break;
|
||||
default:
|
||||
if (auto sym = isDsymbol(src))
|
||||
(*elems)[i] = sym;
|
||||
else
|
||||
(*elems)[i] = src;
|
||||
}
|
||||
}
|
||||
TupleDeclaration td = new TupleDeclaration(e.loc, Identifier.generateId("__aliastup"), elems);
|
||||
mt.obj = td;
|
||||
break;
|
||||
case EXP.dotType:
|
||||
mt.obj = e.isDotTypeExp().sym.isType();
|
||||
break;
|
||||
case EXP.type:
|
||||
mt.obj = e.isTypeExp().type;
|
||||
break;
|
||||
case EXP.overloadSet:
|
||||
mt.obj = e.isOverExp().type;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mt.obj)
|
||||
{
|
||||
if (auto t = mt.obj.isType())
|
||||
returnType(t.addMod(mt.mod));
|
||||
else if (auto s = mt.obj.isDsymbol())
|
||||
returnSymbol(s);
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
mt.obj = Type.terror;
|
||||
return returnError();
|
||||
}
|
||||
}
|
||||
|
||||
switch (mt.ty)
|
||||
|
@ -3391,7 +3384,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
|
|||
v.dsymbolSemantic(null);
|
||||
if (v.isField())
|
||||
{
|
||||
auto ad = v.toParent().isAggregateDeclaration();
|
||||
auto ad = v.isMember();
|
||||
objc.checkOffsetof(e, ad);
|
||||
ad.size(e.loc);
|
||||
if (ad.sizeok != Sizeok.done)
|
||||
|
@ -3637,12 +3630,16 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
|
|||
}
|
||||
else
|
||||
{
|
||||
Expression e0;
|
||||
Expression ev = e;
|
||||
ev = extractSideEffect(sc, "__tup", e0, ev);
|
||||
|
||||
const length = cast(size_t)mt.dim.toUInteger();
|
||||
auto exps = new Expressions();
|
||||
exps.reserve(length);
|
||||
foreach (i; 0 .. length)
|
||||
exps.push(new IndexExp(e.loc, e, new IntegerExp(e.loc, i, Type.tsize_t)));
|
||||
e = new TupleExp(e.loc, exps);
|
||||
exps.push(new IndexExp(e.loc, ev, new IntegerExp(e.loc, i, Type.tsize_t)));
|
||||
e = new TupleExp(e.loc, e0, exps);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -84,7 +84,7 @@ extern (D) void writeFile(Loc loc, const(char)[] filename, const void[] data)
|
|||
ensurePathToNameExists(Loc.initial, filename);
|
||||
if (!File.update(filename, data))
|
||||
{
|
||||
error(loc, "Error writing file '%.*s'", cast(int) filename.length, filename.ptr);
|
||||
error(loc, "error writing file '%.*s'", cast(int) filename.length, filename.ptr);
|
||||
fatal();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -847,53 +847,10 @@ public:
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Appending an element or array to another array has already been
|
||||
handled by the front-end. */
|
||||
gcc_assert (tb1->ty == TY::Tarray || tb2->ty == TY::Tsarray);
|
||||
|
||||
if ((tb2->ty == TY::Tarray || tb2->ty == TY::Tsarray)
|
||||
&& same_type_p (etype, tb2->nextOf ()->toBasetype ()))
|
||||
{
|
||||
/* Append an array to another array:
|
||||
The assignment is handled by the D run-time library, so only
|
||||
need to call `_d_arrayappendT(ti, &e1, e2)' */
|
||||
result = build_libcall (LIBCALL_ARRAYAPPENDT, e->type, 3,
|
||||
build_typeinfo (e->loc, e->type),
|
||||
ptr, d_array_convert (e->e2));
|
||||
}
|
||||
else if (same_type_p (etype, tb2))
|
||||
{
|
||||
/* Append an element to an array:
|
||||
The assignment is generated inline, so need to handle temporaries
|
||||
here, and ensure that they are evaluated in the correct order.
|
||||
|
||||
The generated code should end up being equivalent to:
|
||||
_d_arrayappendcTX(ti, &e1, 1)[e1.length - 1] = e2
|
||||
*/
|
||||
tree callexp = build_libcall (LIBCALL_ARRAYAPPENDCTX, e->type, 3,
|
||||
build_typeinfo (e->loc, e->type),
|
||||
ptr, size_one_node);
|
||||
callexp = d_save_expr (callexp);
|
||||
|
||||
/* Assign e2 to last element. */
|
||||
tree offexp = d_array_length (callexp);
|
||||
offexp = build2 (MINUS_EXPR, TREE_TYPE (offexp),
|
||||
offexp, size_one_node);
|
||||
|
||||
tree ptrexp = d_array_ptr (callexp);
|
||||
ptrexp = void_okay_p (ptrexp);
|
||||
ptrexp = build_array_index (ptrexp, offexp);
|
||||
|
||||
/* Evaluate expression before appending. */
|
||||
tree rhs = build_expr (e->e2);
|
||||
tree rexpr = stabilize_expr (&rhs);
|
||||
|
||||
if (TREE_CODE (rhs) == CALL_EXPR)
|
||||
rhs = force_target_expr (rhs);
|
||||
|
||||
result = modify_expr (build_deref (ptrexp), rhs);
|
||||
result = compound_expr (rexpr, result);
|
||||
}
|
||||
else
|
||||
gcc_unreachable ();
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* Construct in order: ptr = &e1, _d_arrayappend(ptr, e2), *ptr; */
|
||||
|
|
|
@ -340,6 +340,10 @@ fpreview=all
|
|||
D RejectNegative
|
||||
Turn on all upcoming D language features.
|
||||
|
||||
fpreview=bitfields
|
||||
D RejectNegative
|
||||
Implement D bit-fields.
|
||||
|
||||
fpreview=dip1000
|
||||
D RejectNegative
|
||||
Implement DIP1000: Scoped pointers.
|
||||
|
@ -412,10 +416,6 @@ frevert=intpromote
|
|||
D RejectNegative
|
||||
Use C-style integral promotion for unary '+', '-' and '~'.
|
||||
|
||||
frevert=markdown
|
||||
D RejectNegative
|
||||
Disable Markdown replacements in Ddoc.
|
||||
|
||||
frtti
|
||||
D
|
||||
; Documented in C
|
||||
|
@ -452,10 +452,6 @@ ftransition=tls
|
|||
D RejectNegative
|
||||
List all variables going into thread local storage.
|
||||
|
||||
ftransition=vmarkdown
|
||||
D RejectNegative
|
||||
List instances of Markdown replacements in Ddoc.
|
||||
|
||||
funittest
|
||||
D
|
||||
Compile in unittest code.
|
||||
|
|
|
@ -375,7 +375,7 @@ fixup_anonymous_offset (tree fields, tree offset)
|
|||
|
||||
/* Iterate over all MEMBERS of an aggregate, and add them as fields to CONTEXT.
|
||||
If INHERITED_P is true, then the members derive from a base class.
|
||||
Returns the number of fields found. */
|
||||
Returns the number of named fields found. */
|
||||
|
||||
static size_t
|
||||
layout_aggregate_members (Dsymbols *members, tree context, bool inherited_p)
|
||||
|
@ -418,7 +418,8 @@ layout_aggregate_members (Dsymbols *members, tree context, bool inherited_p)
|
|||
/* Insert the field declaration at its given offset. */
|
||||
if (var->isField ())
|
||||
{
|
||||
const char *ident = var->ident ? var->ident->toChars () : NULL;
|
||||
const char *ident = (var->ident && !var->ident->isAnonymous ())
|
||||
? var->ident->toChars () : NULL;
|
||||
tree field = create_field_decl (declaration_type (var), ident,
|
||||
inherited_p, inherited_p);
|
||||
apply_user_attributes (var, field);
|
||||
|
@ -442,7 +443,10 @@ layout_aggregate_members (Dsymbols *members, tree context, bool inherited_p)
|
|||
var->csym = field;
|
||||
}
|
||||
|
||||
fields += 1;
|
||||
/* Only count the named fields in an aggregate. */
|
||||
if (ident != NULL)
|
||||
fields += 1;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,8 +24,8 @@ class C2 // overall alignment: max(vtbl.alignof, monitor.alignof, 1, 2)
|
|||
|
||||
enum payloadOffset = C2.bytes.offsetof;
|
||||
static assert(C2.int1.offsetof == payloadOffset + 8);
|
||||
static assert(C2.alignof == size_t.sizeof);
|
||||
static assert(__traits(classInstanceSize, C2) == payloadOffset + 12);
|
||||
static assert(__traits(classInstanceAlignment, C2) == size_t.sizeof);
|
||||
static assert(__traits(classInstanceSize, C2) == payloadOffset + 12); // no tail padding
|
||||
|
||||
align(8) struct PaddedStruct
|
||||
{
|
||||
|
@ -37,6 +37,15 @@ static assert(PaddedStruct.s1.offsetof == 2);
|
|||
static assert(PaddedStruct.alignof == 8);
|
||||
static assert(PaddedStruct.sizeof == 16);
|
||||
|
||||
class AlignedPayloadClass
|
||||
{
|
||||
align(64) int field;
|
||||
}
|
||||
|
||||
static assert(AlignedPayloadClass.field.offsetof == 64); // vtbl, monitor, alignment padding
|
||||
static assert(__traits(classInstanceAlignment, AlignedPayloadClass) == 64);
|
||||
static assert(__traits(classInstanceSize, AlignedPayloadClass) == 68);
|
||||
|
||||
align(1) struct UglyStruct
|
||||
{
|
||||
bool flag;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// EXTRA_FILES: imports/a12506.d
|
||||
/* TEST_OUTPUT:
|
||||
---
|
||||
compilable/compile1.d(229): Deprecation: use of complex type `cdouble` is deprecated, use `std.complex.Complex!(double)` instead
|
||||
compilable/compile1.d(230): Deprecation: use of complex type `cdouble` is deprecated, use `std.complex.Complex!(double)` instead
|
||||
---
|
||||
*/
|
||||
|
||||
|
|
|
@ -1327,3 +1327,8 @@ extern (C++)
|
|||
static assert(funccpp.mangleof == "?funccpp@@YAHP6AXXZ@Z");
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************/
|
||||
|
||||
extern(C++) enum _LIBNAME = "library";
|
||||
extern(C++) enum _DEBUG = _LIBNAME.length && 'd' == _LIBNAME[$-1];
|
||||
|
|
88
gcc/testsuite/gdc.test/compilable/dbitfield.d
Normal file
88
gcc/testsuite/gdc.test/compilable/dbitfield.d
Normal file
|
@ -0,0 +1,88 @@
|
|||
/* REQUIRED_ARGS: -preview=bitfields
|
||||
*/
|
||||
|
||||
/***************************************************/
|
||||
|
||||
class C
|
||||
{
|
||||
uint a:3;
|
||||
uint b:1;
|
||||
ulong c:64;
|
||||
|
||||
int d:3;
|
||||
int e:1;
|
||||
long f:64;
|
||||
|
||||
int i;
|
||||
}
|
||||
|
||||
static assert(C.a.min == 0);
|
||||
static assert(C.a.max == 7);
|
||||
|
||||
static assert(C.b.min == 0);
|
||||
static assert(C.b.max == 1);
|
||||
|
||||
static assert(C.c.min == 0);
|
||||
static assert(C.c.max == ulong.max);
|
||||
|
||||
static assert(C.d.min == -4);
|
||||
static assert(C.d.max == 3);
|
||||
|
||||
static assert(C.e.min == -1);
|
||||
static assert(C.e.max == 0);
|
||||
|
||||
static assert(C.f.min == long.min);
|
||||
static assert(C.f.max == long.max);
|
||||
|
||||
int testc()
|
||||
{
|
||||
scope c = new C();
|
||||
c.d = 9;
|
||||
return c.d;
|
||||
}
|
||||
|
||||
static assert(testc() == 1);
|
||||
|
||||
/***************************************************/
|
||||
|
||||
union U
|
||||
{
|
||||
uint a:3;
|
||||
uint b:1;
|
||||
ulong c:64;
|
||||
|
||||
int d:3;
|
||||
int e:1;
|
||||
long f:64;
|
||||
|
||||
int i;
|
||||
}
|
||||
|
||||
static assert(U.sizeof == 8);
|
||||
|
||||
static assert(U.a.min == 0);
|
||||
static assert(U.a.max == 7);
|
||||
|
||||
static assert(U.b.min == 0);
|
||||
static assert(U.b.max == 1);
|
||||
|
||||
static assert(U.c.min == 0);
|
||||
static assert(U.c.max == ulong.max);
|
||||
|
||||
static assert(U.d.min == -4);
|
||||
static assert(U.d.max == 3);
|
||||
|
||||
static assert(U.e.min == -1);
|
||||
static assert(U.e.max == 0);
|
||||
|
||||
static assert(U.f.min == long.min);
|
||||
static assert(U.f.max == long.max);
|
||||
|
||||
int testu()
|
||||
{
|
||||
U u;
|
||||
u.d = 9;
|
||||
return u.d;
|
||||
}
|
||||
|
||||
static assert(testu() == 1);
|
|
@ -1,13 +0,0 @@
|
|||
// PERMUTE_ARGS:
|
||||
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -wi -o- -transition=vmarkdown
|
||||
// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_breaks_verbose.html
|
||||
// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_breaks_verbose.html
|
||||
|
||||
/++
|
||||
Thematic Breaks
|
||||
|
||||
___
|
||||
- - -
|
||||
***
|
||||
+/
|
||||
module ddoc_markdown_breaks;
|
|
@ -1,13 +0,0 @@
|
|||
// PERMUTE_ARGS:
|
||||
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o- -transition=vmarkdown
|
||||
// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_code_verbose.html
|
||||
// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_code_verbose.html
|
||||
|
||||
/++
|
||||
Code:
|
||||
|
||||
``` ruby red
|
||||
RWBY
|
||||
```
|
||||
+/
|
||||
module test.compilable.ddoc_markdown_code_verbose;
|
|
@ -1,13 +0,0 @@
|
|||
// PERMUTE_ARGS:
|
||||
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -wi -o- -transition=vmarkdown
|
||||
// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_emphasis_verbose.html
|
||||
// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_emphasis_verbose.html
|
||||
|
||||
/++
|
||||
Markdown Emphasis:
|
||||
|
||||
*emphasized text*
|
||||
|
||||
**strongly emphasized text**
|
||||
+/
|
||||
module ddoc_markdown_emphasis;
|
|
@ -1,9 +0,0 @@
|
|||
// PERMUTE_ARGS:
|
||||
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o- -transition=vmarkdown
|
||||
// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_headings_verbose.html
|
||||
// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_headings_verbose.html
|
||||
|
||||
/++
|
||||
# Heading
|
||||
+/
|
||||
module ddoc_markdown_headings_verbose;
|
|
@ -1,17 +0,0 @@
|
|||
// PERMUTE_ARGS:
|
||||
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o- -transition=vmarkdown
|
||||
// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_links_verbose.html
|
||||
// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_links_verbose.html
|
||||
|
||||
/++
|
||||
Links:
|
||||
|
||||
A link to [Object].
|
||||
An inline link to [the D homepage](https://dlang.org).
|
||||
A simple link to [dub].
|
||||
A slightly less simple link to [dub][].
|
||||
An image: 
|
||||
|
||||
[dub]: https://code.dlang.org
|
||||
+/
|
||||
module test.compilable.ddoc_markdown_links_verbose;
|
|
@ -1,9 +0,0 @@
|
|||
// PERMUTE_ARGS:
|
||||
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o- -transition=vmarkdown
|
||||
// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_lists_verbose.html
|
||||
// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_lists_verbose.html
|
||||
|
||||
/++
|
||||
- list item
|
||||
+/
|
||||
module ddoc_markdown_lists_verbose;
|
|
@ -1,11 +0,0 @@
|
|||
// PERMUTE_ARGS:
|
||||
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o- -transition=vmarkdown
|
||||
// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_quote_verbose.html
|
||||
// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_quote_verbose.html
|
||||
|
||||
/++
|
||||
Quote Block:
|
||||
|
||||
> Great, just what I need.. another D in programming. -- Segfault
|
||||
+/
|
||||
module test.compilable.ddoc_markdown_code_verbose;
|
|
@ -1,13 +0,0 @@
|
|||
// PERMUTE_ARGS:
|
||||
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o- -transition=vmarkdown
|
||||
// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_tables_verbose.html
|
||||
// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_tables_verbose.html
|
||||
|
||||
/++
|
||||
Table:
|
||||
|
||||
| this | that |
|
||||
| ---- | ---- |
|
||||
| cell | cell |
|
||||
+/
|
||||
module test.compilable.ddoc_markdown_tables_verbose;
|
|
@ -8,9 +8,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -10,9 +10,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -7,9 +7,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -8,9 +8,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -8,9 +8,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -8,9 +8,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -8,9 +8,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -8,9 +8,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -8,9 +8,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -8,9 +8,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -10,9 +10,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -8,9 +8,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -8,9 +8,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -7,9 +7,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -9,9 +9,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -8,9 +8,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -8,9 +8,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
@ -79,6 +79,8 @@ extern size_t baz5(size_t x = 42);
|
|||
|
||||
extern size_t& bazRef(size_t& x);
|
||||
|
||||
extern size_t bazOut(size_t& x);
|
||||
|
||||
enum class E : int64_t
|
||||
{
|
||||
m = 1LL,
|
||||
|
@ -219,6 +221,11 @@ extern (C++) ref size_t bazRef(return ref size_t x)
|
|||
return x;
|
||||
}
|
||||
|
||||
extern (C++) size_t bazOut(out size_t x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
extern (C++):
|
||||
|
||||
enum E : long
|
||||
|
|
|
@ -8,9 +8,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -17,9 +17,9 @@ compilable/dtoh_invalid_identifiers.d(145): Warning: function `__attribute__` is
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -7,9 +7,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -8,9 +8,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -9,9 +9,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -7,9 +7,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -8,9 +8,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -8,9 +8,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -10,9 +10,9 @@ TEST_OUTPUT:
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef CUSTOM_D_ARRAY_TYPE
|
||||
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// REQUIRED_ARGS: -o-
|
||||
// REQUIRED_ARGS: -o- -preview=dip1000
|
||||
|
||||
void lazyfun(scope lazy int a) @nogc;
|
||||
|
||||
|
|
3
gcc/testsuite/gdc.test/compilable/test20427.d
Normal file
3
gcc/testsuite/gdc.test/compilable/test20427.d
Normal file
|
@ -0,0 +1,3 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=20427
|
||||
extern(C++) void test20427(T)(T) {}
|
||||
static assert(!__traits(compiles, { test20427([1, 2]); }));
|
13
gcc/testsuite/gdc.test/compilable/test23047.d
Normal file
13
gcc/testsuite/gdc.test/compilable/test23047.d
Normal file
|
@ -0,0 +1,13 @@
|
|||
/* REQUIRED_ARGS: -defaultlib= -c -O
|
||||
*/
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=23047
|
||||
version(D_SIMD):
|
||||
alias long2 = __vector(long[2]);
|
||||
|
||||
long2 _mm_srl_epi64 ()
|
||||
{
|
||||
long2 r = void;
|
||||
r[0] = 1;
|
||||
return r;
|
||||
}
|
9
gcc/testsuite/gdc.test/compilable/test23087.d
Normal file
9
gcc/testsuite/gdc.test/compilable/test23087.d
Normal file
|
@ -0,0 +1,9 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=23087
|
||||
struct S
|
||||
{
|
||||
this(bool) {}
|
||||
this(bool, int) {}
|
||||
}
|
||||
|
||||
static foreach (ctor; __traits(getOverloads, S, "__ctor"))
|
||||
static assert(__traits(getLinkage, ctor) == "D");
|
7
gcc/testsuite/gdc.test/compilable/test23089.d
Normal file
7
gcc/testsuite/gdc.test/compilable/test23089.d
Normal file
|
@ -0,0 +1,7 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=23089
|
||||
extern(System) int i23089;
|
||||
|
||||
extern(System):
|
||||
|
||||
alias F23089 = void function(int);
|
||||
F23089 f23089;
|
33
gcc/testsuite/gdc.test/compilable/test23097.d
Normal file
33
gcc/testsuite/gdc.test/compilable/test23097.d
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* https://issues.dlang.org/show_bug.cgi?id=23097
|
||||
REQUIRED_ARGS: -verrors=spec
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
(spec:2) compilable/test23097.d(14): Error: `inout` constructor `test23097.S23097.this` creates const object, not mutable
|
||||
(spec:2) compilable/test23097.d(14): Error: `inout` constructor `test23097.S23097.this` creates const object, not mutable
|
||||
(spec:1) compilable/test23097.d(14): Error: generated function `test23097.S23097.opAssign(S23097 p)` is not callable using argument types `(const(S23097))`
|
||||
(spec:2) compilable/test23097.d(14): Error: `inout` constructor `test23097.S23097.this` creates const object, not mutable
|
||||
(spec:1) compilable/test23097.d(14): `struct S23097` does not define a copy constructor for `const(S23097)` to `S23097` copies
|
||||
---
|
||||
*/
|
||||
void emplaceRef(UT, Args)(UT chunk, Args args)
|
||||
{
|
||||
static if (__traits(compiles, chunk = args))
|
||||
chunk = args;
|
||||
}
|
||||
|
||||
struct CpCtor23097(T)
|
||||
{
|
||||
T* payload;
|
||||
this(ref inout typeof(this)) { }
|
||||
ref opAssign(typeof(this)) { }
|
||||
}
|
||||
|
||||
struct S23097
|
||||
{
|
||||
CpCtor23097!int payload;
|
||||
}
|
||||
|
||||
void test23097(S23097 lhs, const S23097 rhs)
|
||||
{
|
||||
emplaceRef(lhs, rhs);
|
||||
}
|
6
gcc/testsuite/gdc.test/compilable/test23105.d
Normal file
6
gcc/testsuite/gdc.test/compilable/test23105.d
Normal file
|
@ -0,0 +1,6 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=23105
|
||||
|
||||
module test23105;
|
||||
|
||||
static assert(is(mixin(`__traits(getMember, test23105, "object")`) == module));
|
||||
static assert(is(__traits(getMember, test23105, "object") == module)); // Fixed
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue