aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2022-05-16 18:30:46 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2022-05-16 19:07:45 +0200
commit5eb9927aae076200bb7ba3f22c33b0a7c97c5643 (patch)
treef80210439a5d8995ebf189bce7f2e141fcb1caec /gcc
parent682e587f1021241758f7dfe0b22651008622a312 (diff)
downloadgcc-5eb9927aae076200bb7ba3f22c33b0a7c97c5643.zip
gcc-5eb9927aae076200bb7ba3f22c33b0a7c97c5643.tar.gz
gcc-5eb9927aae076200bb7ba3f22c33b0a7c97c5643.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/d/d-builtins.cc2
-rw-r--r--gcc/d/d-codegen.cc17
-rw-r--r--gcc/d/d-gimplify.cc3
-rw-r--r--gcc/d/d-lang.cc104
-rw-r--r--gcc/d/decl.cc4
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/README.md29
-rw-r--r--gcc/d/dmd/VERSION2
-rw-r--r--gcc/d/dmd/clone.d22
-rw-r--r--gcc/d/dmd/common/bitfields.d2
-rw-r--r--gcc/d/dmd/common/outbuffer.d11
-rw-r--r--gcc/d/dmd/cond.d6
-rw-r--r--gcc/d/dmd/constfold.d2
-rw-r--r--gcc/d/dmd/cparse.d58
-rw-r--r--gcc/d/dmd/cppmangle.d12
-rw-r--r--gcc/d/dmd/dcast.d13
-rw-r--r--gcc/d/dmd/dclass.d2
-rw-r--r--gcc/d/dmd/declaration.d40
-rw-r--r--gcc/d/dmd/declaration.h11
-rw-r--r--gcc/d/dmd/dinterpret.d109
-rw-r--r--gcc/d/dmd/dmangle.d14
-rw-r--r--gcc/d/dmd/dmodule.d56
-rw-r--r--gcc/d/dmd/doc.d99
-rw-r--r--gcc/d/dmd/dscope.d1
-rw-r--r--gcc/d/dmd/dsymbol.d28
-rw-r--r--gcc/d/dmd/dsymbolsem.d500
-rw-r--r--gcc/d/dmd/dtemplate.d2
-rw-r--r--gcc/d/dmd/dtoh.d31
-rw-r--r--gcc/d/dmd/escape.d1429
-rw-r--r--gcc/d/dmd/expression.d17
-rw-r--r--gcc/d/dmd/expressionsem.d466
-rw-r--r--gcc/d/dmd/func.d121
-rw-r--r--gcc/d/dmd/globals.d92
-rw-r--r--gcc/d/dmd/globals.h76
-rw-r--r--gcc/d/dmd/hdrgen.d4
-rw-r--r--gcc/d/dmd/id.d6
-rw-r--r--gcc/d/dmd/initsem.d30
-rw-r--r--gcc/d/dmd/json.d4
-rw-r--r--gcc/d/dmd/mtype.d49
-rw-r--r--gcc/d/dmd/mtype.h4
-rw-r--r--gcc/d/dmd/nogc.d18
-rw-r--r--gcc/d/dmd/objc.d6
-rw-r--r--gcc/d/dmd/optimize.d35
-rw-r--r--gcc/d/dmd/parse.d90
-rw-r--r--gcc/d/dmd/safe.d51
-rw-r--r--gcc/d/dmd/semantic2.d15
-rw-r--r--gcc/d/dmd/semantic3.d145
-rw-r--r--gcc/d/dmd/statementsem.d28
-rw-r--r--gcc/d/dmd/tokens.d2
-rw-r--r--gcc/d/dmd/traits.d15
-rw-r--r--gcc/d/dmd/typesem.d215
-rw-r--r--gcc/d/dmd/utils.d2
-rw-r--r--gcc/d/expr.cc49
-rw-r--r--gcc/d/lang.opt12
-rw-r--r--gcc/d/types.cc10
-rw-r--r--gcc/testsuite/gdc.test/compilable/aggr_alignment.d13
-rw-r--r--gcc/testsuite/gdc.test/compilable/compile1.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/cppmangle.d5
-rw-r--r--gcc/testsuite/gdc.test/compilable/dbitfield.d88
-rw-r--r--gcc/testsuite/gdc.test/compilable/ddoc_markdown_breaks_verbose.d13
-rw-r--r--gcc/testsuite/gdc.test/compilable/ddoc_markdown_code_verbose.d13
-rw-r--r--gcc/testsuite/gdc.test/compilable/ddoc_markdown_emphasis_verbose.d13
-rw-r--r--gcc/testsuite/gdc.test/compilable/ddoc_markdown_headings_verbose.d9
-rw-r--r--gcc/testsuite/gdc.test/compilable/ddoc_markdown_links_verbose.d17
-rw-r--r--gcc/testsuite/gdc.test/compilable/ddoc_markdown_lists_verbose.d9
-rw-r--r--gcc/testsuite/gdc.test/compilable/ddoc_markdown_quote_verbose.d11
-rw-r--r--gcc/testsuite/gdc.test/compilable/ddoc_markdown_tables_verbose.d13
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_21217.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_AliasDeclaration.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_AliasDeclaration_98.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_AnonDeclaration.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_CPPNamespaceDeclaration.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_ClassDeclaration.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_StructDeclaration.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_TemplateDeclaration.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_UnionDeclaration.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_VarDeclaration.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_cpp98_compat.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_enum.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_enum_cpp98.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_expressions.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_extern_type.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_forwarding.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_functions.d9
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_ignored.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_invalid_identifiers.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_mangling.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_names.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_protection.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_required_symbols.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_special_enum.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_unittest_block.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dtoh_verbose.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/test17590.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/test20427.d3
-rw-r--r--gcc/testsuite/gdc.test/compilable/test23047.d13
-rw-r--r--gcc/testsuite/gdc.test/compilable/test23087.d9
-rw-r--r--gcc/testsuite/gdc.test/compilable/test23089.d7
-rw-r--r--gcc/testsuite/gdc.test/compilable/test23097.d33
-rw-r--r--gcc/testsuite/gdc.test/compilable/test23105.d6
-rw-r--r--gcc/testsuite/gdc.test/compilable/test3004.d4
-rw-r--r--gcc/testsuite/gdc.test/compilable/vcg-ast.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/attributediagnostic.d23
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/b6227.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/betterc.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/biterrors.d15
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/biterrors2.d17
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/biterrors3.d18
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/biterrors4.d19
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/commaexp.d20
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/cppvar.d22
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/dbitfields.d32
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag10805.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag10862.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/dip25.d6
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/dtor_attributes.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/dtorfields_attributes.d1
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/e7804_1.d11
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/extra-files/test23109/object.d17
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail109.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail12604.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail13902.d10
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail16001.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail16575.d65
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail16772.d7
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail196.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19759.d8
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19881.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail20691.d9
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail21092.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail21206.d13
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail21275.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail21314.d11
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail21868b.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail23108a.d16
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail23108b.d18
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail23109.d12
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail3703.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail_scope.d53
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice10949.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice14844.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice22377.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice23097.d28
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice9254a.d10
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice9254b.d10
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice9254c.d10
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/imports/test23109a.d10
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/imports/test23109b.d10
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/imports/test23109c.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/issue3827.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/no_Throwable.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/retscope.d20
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/retscope2.d6
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/retscope6.d12
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/safe_gshared.d15
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/safe_pointer_index.d12
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test13536.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test14496.d10
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test15191.d31
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test15373.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test16188.d10
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test16365.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test17284.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test17423.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test17868b.d14
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test18130.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test18282.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test18484.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test20245.d14
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test20569.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test21198.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test21204.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test21665.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test22145.d1
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test22593.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test9150.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/traits.d8
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/udaparams.d4
-rw-r--r--gcc/testsuite/gdc.test/runnable/bit.d106
-rw-r--r--gcc/testsuite/gdc.test/runnable/dbitfields.d189
-rw-r--r--gcc/testsuite/gdc.test/runnable/interpret.d16
-rw-r--r--gcc/testsuite/gdc.test/runnable/test17868b.d4
-rw-r--r--gcc/testsuite/gdc.test/runnable/test20734.d28
-rw-r--r--gcc/testsuite/gdc.test/runnable/test21416.d9
-rw-r--r--gcc/testsuite/gdc.test/runnable/test23083.d16
-rw-r--r--gcc/testsuite/gdc.test/runnable/testcontracts.d26
186 files changed, 3516 insertions, 2145 deletions
diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc
index 7e7fb75..cd9748c 100644
--- a/gcc/d/d-builtins.cc
+++ b/gcc/d/d-builtins.cc
@@ -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)
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index bb96b2f..22090a8 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -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))
diff --git a/gcc/d/d-gimplify.cc b/gcc/d/d-gimplify.cc
index a98089b7..36b76da 100644
--- a/gcc/d/d-gimplify.cc
+++ b/gcc/d/d-gimplify.cc
@@ -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;
diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index 9adcabd..d1f4959 100644
--- a/gcc/d/d-lang.cc
+++ b/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:
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 86ea176..f5c2107 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -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))
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index d181191..b4d42ec 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -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.
diff --git a/gcc/d/dmd/README.md b/gcc/d/dmd/README.md
index b143103..50c5ac3 100644
--- a/gcc/d/dmd/README.md
+++ b/gcc/d/dmd/README.md
@@ -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 |
|-----------------------------------------------------------------------------|------------------------------------------------------------------------------------|
diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION
index 2450fd5..5ea2ba0 100644
--- a/gcc/d/dmd/VERSION
+++ b/gcc/d/dmd/VERSION
@@ -1 +1 @@
-v2.100.0-beta.1
+v2.100.0
diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d
index 9c8c1c3..75a16bd 100644
--- a/gcc/d/dmd/clone.d
+++ b/gcc/d/dmd/clone.d
@@ -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;
diff --git a/gcc/d/dmd/common/bitfields.d b/gcc/d/dmd/common/bitfields.d
index d17983d..cccaabd 100644
--- a/gcc/d/dmd/common/bitfields.d
+++ b/gcc/d/dmd/common/bitfields.d
@@ -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)
{
diff --git a/gcc/d/dmd/common/outbuffer.d b/gcc/d/dmd/common/outbuffer.d
index 7e46d29..9a5bd82 100644
--- a/gcc/d/dmd/common/outbuffer.d
+++ b/gcc/d/dmd/common/outbuffer.d
@@ -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
diff --git a/gcc/d/dmd/cond.d b/gcc/d/dmd/cond.d
index dee0a17..65085f5 100644
--- a/gcc/d/dmd/cond.d
+++ b/gcc/d/dmd/cond.d
@@ -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;
diff --git a/gcc/d/dmd/constfold.d b/gcc/d/dmd/constfold.d
index bf66408..d90542f 100644
--- a/gcc/d/dmd/constfold.d
+++ b/gcc/d/dmd/constfold.d
@@ -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());
}
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index 2b2046f..fde0648 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -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))
diff --git a/gcc/d/dmd/cppmangle.d b/gcc/d/dmd/cppmangle.d
index 13ef34c..6235342a 100644
--- a/gcc/d/dmd/cppmangle.d
+++ b/gcc/d/dmd/cppmangle.d
@@ -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
}
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 8397839..c0a86f5 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -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();
}
}
diff --git a/gcc/d/dmd/dclass.d b/gcc/d/dmd/dclass.d
index 15ac8d9..a4a2abf 100644
--- a/gcc/d/dmd/dclass.d
+++ b/gcc/d/dmd/dclass.d
@@ -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;
}
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index a533d30..bb0feb6 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -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);
}
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 441a966..0bde33d 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -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();
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index 3cfc07a..5e7527d 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -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;
+ }
}
/********************************************
diff --git a/gcc/d/dmd/dmangle.d b/gcc/d/dmd/dmangle.d
index 1f895e0..7604296 100644
--- a/gcc/d/dmd/dmangle.d
+++ b/gcc/d/dmd/dmangle.d
@@ -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;
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index 2d9f651..26a0ff0 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -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;
}
diff --git a/gcc/d/dmd/doc.d b/gcc/d/dmd/doc.d
index d05060d..6eb433e 100644
--- a/gcc/d/dmd/doc.d
+++ b/gcc/d/dmd/doc.d
@@ -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);
diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d
index 6339a9e..b546e37 100644
--- a/gcc/d/dmd/dscope.d
+++ b/gcc/d/dmd/dscope.d
@@ -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
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index 74eaa1d..b006940 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -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;
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index 5415401..5d88056 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -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)
- {
- /* 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);
+ 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)
+ {
+ 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());
+ }
+ 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.writestring("???");
- ob.writeByte(')');
- foreach (i, name; imp.names)
+ ob.writeByte(',');
+ Identifier _alias = imp.aliases[i];
+ if (!_alias)
{
- 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());
+ ob.printf("%s", name.toChars());
+ _alias = name;
}
- if (imp.aliasId)
- ob.printf(" -> %s", imp.aliasId.toChars());
- ob.writenl();
+ else
+ ob.printf("%s=%s", _alias.toChars(), name.toChars());
}
- //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
+ 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)
- {
- 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)
+ 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())
+ {
+ 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)
+ {
+ 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)
{
- 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)
{
- if (repopulateMembers)
- {
- s.addMember(sc, sc.scopesym);
- s.setScope(sc);
- }
- s.importAll(sc);
+ s.addMember(sc, sc.scopesym);
+ s.setScope(sc);
}
- foreach (s; *ns.members)
+ s.importAll(sc);
+ }
+ foreach (s; *ns.members)
+ {
+ static if (LOG)
{
- static if (LOG)
- {
- printf("\tmember '%s', kind = '%s'\n", s.toChars(), s.kind());
- }
- s.dsymbolSemantic(sc);
+ printf("\tmember '%s', kind = '%s'\n", s.toChars(), s.kind());
}
- sc.pop();
+ 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 (dim == 0 && tf.parameterList.varargs == VarArg.none)
+ ad.defaultCtor = ctd;
+ return;
+ }
+
+ if (dim == 0 && tf.parameterList.varargs == VarArg.none) // empty default ctor w/o any varargs
+ {
+ if (ctd.fbody || !(ctd.storage_class & STC.disable))
{
- // 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.");
+ ctd.error("default constructor for structs only allowed " ~
+ "with `@disable`, no body, and no parameters");
+ ctd.storage_class |= STC.disable;
+ ctd.fbody = null;
}
- else if ((dim == 1 || (dim > 1 && tf.parameterList[1].defaultArg)))
+ 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)
{
- //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;
- }
+ 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 == 0 && tf.parameterList.varargs == VarArg.none)
+ else if ((dim == 1 || (dim > 1 && tf.parameterList[1].defaultArg)))
{
- ad.defaultCtor = ctd;
+ //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;
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index fb41e2b..ed0126e 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -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;
diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d
index 41fb82b..55f7c72 100644
--- a/gcc/d/dmd/dtoh.d
+++ b/gcc/d/dmd/dtoh.d
@@ -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
diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d
index 44c3757..3f41c29 100644
--- a/gcc/d/dmd/escape.d
+++ b/gcc/d/dmd/escape.d
@@ -280,13 +280,14 @@ bool checkAssocArrayLiteralEscape(Scope *sc, AssocArrayLiteralExp ae, bool gag)
* sc = used to determine current function and module
* fdc = function being called, `null` if called indirectly
* par = function parameter (`this` if null)
+ * parStc = storage classes of function parameter (may have added `scope` from `pure`)
* arg = initializer for param
* assertmsg = true if the parameter is the msg argument to assert(bool, msg).
* gag = do not print error messages
* Returns:
* `true` if pointers to the stack can escape via assignment
*/
-bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, Expression arg, bool assertmsg, bool gag)
+bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, STC parStc, Expression arg, bool assertmsg, bool gag)
{
enum log = false;
if (log) printf("checkParamArgumentEscape(arg: %s par: %s)\n",
@@ -301,42 +302,38 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, Exp
escapeByValue(arg, &er);
+ if (parStc & STC.scope_)
+ {
+ // These errors only apply to non-scope parameters
+ // When the paraneter is `scope`, only `checkScopeVarAddr` on `er.byref` is needed
+ er.byfunc.setDim(0);
+ er.byvalue.setDim(0);
+ er.byexp.setDim(0);
+ }
+
if (!er.byref.dim && !er.byvalue.dim && !er.byfunc.dim && !er.byexp.dim)
return false;
bool result = false;
- ScopeRef psr;
- if (par && fdc && fdc.type.isTypeFunction())
- psr = buildScopeRef(par.storageClass);
- else
- psr = ScopeRef.None;
-
/* 'v' is assigned unsafely to 'par'
*/
- void unsafeAssign(VarDeclaration v, const char* desc)
+ void unsafeAssign(string desc)(VarDeclaration v)
{
- if (setUnsafeDIP1000(sc.func))
+ if (assertmsg)
{
- if (!gag)
- {
- if (assertmsg)
- {
- previewErrorFunc(sc.isDeprecated(), global.params.useDIP1000)
- (arg.loc, "%s `%s` assigned to non-scope parameter calling `assert()`",
- desc, v.toChars());
- }
- else
- {
- previewErrorFunc(sc.isDeprecated(), global.params.useDIP1000)
- (arg.loc, "%s `%s` assigned to non-scope parameter `%s` calling %s",
- desc, v.toChars(),
- par ? par.toChars() : "this",
- fdc ? fdc.toPrettyChars() : "indirectly");
- }
- }
- if (global.params.useDIP1000 == FeatureState.enabled)
- result = true;
+ result |= sc.setUnsafeDIP1000(gag, arg.loc,
+ desc ~ " `%s` assigned to non-scope parameter calling `assert()`", v);
+ }
+ else if (par)
+ {
+ result |= sc.setUnsafeDIP1000(gag, arg.loc,
+ desc ~ " `%s` assigned to non-scope parameter `%s`", v, par);
+ }
+ else
+ {
+ result |= sc.setUnsafeDIP1000(gag, arg.loc,
+ desc ~ " `%s` assigned to non-scope parameter `this`", v);
}
}
@@ -352,14 +349,14 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, Exp
if (v.isScope())
{
- unsafeAssign(v, "scope variable");
+ unsafeAssign!"scope variable"(v);
}
else if (v.storage_class & STC.variadic && p == sc.func)
{
Type tb = v.type.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
{
- unsafeAssign(v, "variadic variable");
+ unsafeAssign!"variadic variable"(v);
}
}
else
@@ -382,17 +379,15 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, Exp
Dsymbol p = v.toParent2();
notMaybeScope(v);
-
- if (p == sc.func)
+ if (checkScopeVarAddr(v, arg, sc, gag))
{
- if (psr == ScopeRef.Scope ||
- psr == ScopeRef.RefScope ||
- psr == ScopeRef.ReturnRef_Scope)
- {
- continue;
- }
+ result = true;
+ continue;
+ }
- unsafeAssign(v, "reference to local variable");
+ if (p == sc.func && !(parStc & STC.scope_))
+ {
+ unsafeAssign!"reference to local variable"(v);
continue;
}
}
@@ -414,21 +409,26 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, Exp
if ((v.isReference() || v.isScope()) && p == sc.func)
{
- unsafeAssign(v, "reference to local");
+ unsafeAssign!"reference to local"(v);
continue;
}
}
}
+ if (!sc.func)
+ return result;
+
foreach (Expression ee; er.byexp)
{
- if (sc.func && sc.func.setUnsafe())
+ if (!par)
{
- if (!gag)
- error(ee.loc, "reference to stack allocated value returned by `%s` assigned to non-scope parameter `%s`",
- ee.toChars(),
- par ? par.toChars() : "this");
- result = true;
+ result |= sc.setUnsafeDIP1000(gag, ee.loc,
+ "reference to stack allocated value returned by `%s` assigned to non-scope parameter `this`", ee);
+ }
+ else
+ {
+ result |= sc.setUnsafeDIP1000(gag, ee.loc,
+ "reference to stack allocated value returned by `%s` assigned to non-scope parameter `%s`", ee, par);
}
}
@@ -688,25 +688,25 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
}
}
- if (va && va.isScope() && va.storage_class & STC.return_ && !(v.storage_class & STC.return_) &&
- fd.setUnsafe())
+ if (va && va.isScope() && va.storage_class & STC.return_ && !(v.storage_class & STC.return_))
{
// va may return its value, but v does not allow that, so this is an error
- if (!gag)
- error(ae.loc, "scope variable `%s` assigned to return scope `%s`", v.toChars(), va.toChars());
- result = true;
- continue;
+ if (sc.setUnsafeDIP1000(gag, ae.loc, "scope variable `%s` assigned to return scope `%s`", v, va))
+ {
+ result = true;
+ continue;
+ }
}
// If va's lifetime encloses v's, then error
if (va && !va.isDataseg() &&
- ((va.enclosesLifetimeOf(v) && !(v.storage_class & STC.temp)) || vaIsRef) &&
- fd.setUnsafe())
+ ((va.enclosesLifetimeOf(v) && !(v.storage_class & STC.temp)) || vaIsRef))
{
- if (!gag)
- error(ae.loc, "scope variable `%s` assigned to `%s` with longer lifetime", v.toChars(), va.toChars());
- result = true;
- continue;
+ if (sc.setUnsafeDIP1000(gag, ae.loc, "scope variable `%s` assigned to `%s` with longer lifetime", v, va))
+ {
+ result = true;
+ continue;
+ }
}
if (va && !va.isDataseg() && !va.doNotInferScope)
@@ -733,12 +733,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
}
continue;
}
- if (fd.setUnsafe())
- {
- if (!gag)
- error(ae.loc, "scope variable `%s` assigned to non-scope `%s`", v.toChars(), e1.toChars());
- result = true;
- }
+ result |= sc.setUnsafeDIP1000(gag, ae.loc, "scope variable `%s` assigned to non-scope `%s`", v, e1);
}
else if (v.storage_class & STC.variadic && p == fd)
{
@@ -753,12 +748,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
}
continue;
}
- if (fd.setUnsafe())
- {
- if (!gag)
- error(ae.loc, "variadic variable `%s` assigned to non-scope `%s`", v.toChars(), e1.toChars());
- result = true;
- }
+ result |= sc.setUnsafeDIP1000(gag, ae.loc, "variadic variable `%s` assigned to non-scope `%s`", v, e1);
}
}
else
@@ -777,27 +767,22 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
if (v.isDataseg())
continue;
- if (global.params.useDIP1000 != FeatureState.disabled)
+ if (checkScopeVarAddr(v, ae, sc, gag))
{
- if (va && va.isScope() && !v.isReference())
- {
- if (!(va.storage_class & STC.return_))
- {
- va.doNotInferReturn = true;
- }
- else if (setUnsafeDIP1000(fd))
- {
- if (!gag)
- previewErrorFunc(sc.isDeprecated(), global.params.useDIP1000)
- (ae.loc, "address of local variable `%s` assigned to return scope `%s`", v.toChars(), va.toChars());
-
+ result = true;
+ continue;
+ }
- if (global.params.useDIP1000 == FeatureState.enabled)
- {
- result = true;
- continue;
- }
- }
+ if (va && va.isScope() && !v.isReference())
+ {
+ if (!(va.storage_class & STC.return_))
+ {
+ va.doNotInferReturn = true;
+ }
+ else
+ {
+ result |= sc.setUnsafeDIP1000(gag, ae.loc,
+ "address of local variable `%s` assigned to return scope `%s`", v, va);
}
}
@@ -815,19 +800,19 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
// If va's lifetime encloses v's, then error
if (va &&
!(vaIsFirstRef && (v.storage_class & STC.return_)) &&
- (va.enclosesLifetimeOf(v) || (va.isReference() && !(va.storage_class & STC.temp)) || va.isDataseg()) &&
- fd.setUnsafe())
+ (va.enclosesLifetimeOf(v) || (va.isReference() && !(va.storage_class & STC.temp)) || va.isDataseg()))
{
- if (!gag)
- error(ae.loc, "address of variable `%s` assigned to `%s` with longer lifetime", v.toChars(), va.toChars());
- result = true;
- continue;
+ if (sc.setUnsafeDIP1000(gag, ae.loc, "address of variable `%s` assigned to `%s` with longer lifetime", v, va))
+ {
+ result = true;
+ continue;
+ }
}
if (!(va && va.isScope()))
notMaybeScope(v);
- if ((global.params.useDIP1000 != FeatureState.enabled && v.isReference()) || p != sc.func)
+ if (p != sc.func)
continue;
if (va && !va.isDataseg() && !va.doNotInferScope)
@@ -842,12 +827,8 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
}
if (e1.op == EXP.structLiteral)
continue;
- if (fd.setUnsafe())
- {
- if (!gag)
- error(ae.loc, "reference to local variable `%s` assigned to non-scope `%s`", v.toChars(), e1.toChars());
- result = true;
- }
+
+ result |= sc.setUnsafeDIP1000(gag, ae.loc, "reference to local variable `%s` assigned to non-scope `%s`", v, e1);
}
foreach (FuncDeclaration func; er.byfunc)
@@ -886,12 +867,8 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
//va.storage_class |= STC.scope_ | STC.scopeinferred;
continue;
}
- if (fd.setUnsafe())
- {
- if (!gag)
- error(ae.loc, "reference to local `%s` assigned to non-scope `%s` in @safe code", v.toChars(), e1.toChars());
- result = true;
- }
+ result |= sc.setUnsafeDIP1000(gag, ae.loc,
+ "reference to local `%s` assigned to non-scope `%s` in @safe code", v, e1);
}
}
@@ -912,25 +889,23 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
}
if (ee.op == EXP.call && ee.type.toBasetype().isTypeStruct() &&
- (!va || !(va.storage_class & STC.temp)) &&
- fd.setUnsafe())
+ (!va || !(va.storage_class & STC.temp)))
{
- if (!gag)
- error(ee.loc, "address of struct temporary returned by `%s` assigned to longer lived variable `%s`",
- ee.toChars(), e1.toChars());
- result = true;
- continue;
+ if (sc.setUnsafeDIP1000(gag, ee.loc, "address of struct temporary returned by `%s` assigned to longer lived variable `%s`", ee, e1))
+ {
+ result = true;
+ continue;
+ }
}
if (ee.op == EXP.structLiteral &&
- (!va || !(va.storage_class & STC.temp)) &&
- fd.setUnsafe())
+ (!va || !(va.storage_class & STC.temp)))
{
- if (!gag)
- error(ee.loc, "address of struct literal `%s` assigned to longer lived variable `%s`",
- ee.toChars(), e1.toChars());
- result = true;
- continue;
+ if (sc.setUnsafeDIP1000(gag, ee.loc, "address of struct literal `%s` assigned to longer lived variable `%s`", ee, e1))
+ {
+ result = true;
+ continue;
+ }
}
if (va && !va.isDataseg() && !va.doNotInferScope)
@@ -942,13 +917,8 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
continue;
}
- if (fd.setUnsafe())
- {
- if (!gag)
- error(ee.loc, "reference to stack allocated value returned by `%s` assigned to non-scope `%s`",
- ee.toChars(), e1.toChars());
- result = true;
- }
+ result |= sc.setUnsafeDIP1000(gag, ee.loc,
+ "reference to stack allocated value returned by `%s` assigned to non-scope `%s`", ee, e1);
}
return result;
@@ -985,11 +955,8 @@ bool checkThrowEscape(Scope* sc, Expression e, bool gag)
if (v.isScope() && !v.iscatchvar) // special case: allow catch var to be rethrown
// despite being `scope`
{
- if (!gag)
- previewErrorFunc(sc.isDeprecated(), global.params.useDIP1000)
- (e.loc, "scope variable `%s` may not be thrown", v.toChars());
- if (global.params.useDIP1000 == FeatureState.enabled) // https://issues.dlang.org/show_bug.cgi?id=17029
- result = true;
+ // https://issues.dlang.org/show_bug.cgi?id=17029
+ result |= sc.setUnsafeDIP1000(gag, e.loc, "scope variable `%s` may not be thrown", v);
continue;
}
else
@@ -1050,16 +1017,8 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
*/
!(p.parent == sc.func))
{
- if (setUnsafeDIP1000(sc.func)) // https://issues.dlang.org/show_bug.cgi?id=20868
- {
- // Only look for errors if in module listed on command line
- if (!gag)
- previewErrorFunc(sc.isDeprecated(), global.params.useDIP1000)
- (e.loc, "scope variable `%s` may not be copied into allocated memory", v.toChars());
- if (global.params.useDIP1000 == FeatureState.enabled)
- result = true;
- }
-
+ // https://issues.dlang.org/show_bug.cgi?id=20868
+ result |= sc.setUnsafeDIP1000(gag, e.loc, "scope variable `%s` may not be copied into allocated memory", v);
continue;
}
}
@@ -1068,9 +1027,8 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
Type tb = v.type.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
{
- if (!gag)
- error(e.loc, "copying `%s` into allocated memory escapes a reference to variadic parameter `%s`", e.toChars(), v.toChars());
- result = false;
+ result |= sc.setUnsafeDIP1000(gag, e.loc,
+ "copying `%s` into allocated memory escapes a reference to variadic parameter `%s`", e, v);
}
}
else
@@ -1085,16 +1043,13 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
if (log) printf("byref `%s`\n", v.toChars());
// 'featureState' tells us whether to emit an error or a deprecation,
- // depending on the flag passed to the CLI for DIP25
- void escapingRef(VarDeclaration v, FeatureState featureState = FeatureState.enabled)
+ // depending on the flag passed to the CLI for DIP25 / DIP1000
+ bool escapingRef(VarDeclaration v, FeatureState fs)
{
- if (!gag)
- {
- const(char)* kind = (v.storage_class & STC.parameter) ? "parameter" : "local";
- const(char)* msg = "copying `%s` into allocated memory escapes a reference to %s variable `%s`";
- previewErrorFunc(sc.isDeprecated(), featureState)(e.loc, msg, e.toChars(), kind, v.toChars());
- }
- result |= (featureState == FeatureState.enabled);
+ const(char)* msg = v.isParameter() ?
+ "copying `%s` into allocated memory escapes a reference to parameter `%s`" :
+ "copying `%s` into allocated memory escapes a reference to local variable `%s`";
+ return sc.setUnsafePreview(fs, gag, e.loc, msg, e, v);
}
if (v.isDataseg())
@@ -1106,7 +1061,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
{
if (p == sc.func)
{
- escapingRef(v);
+ result |= escapingRef(v, global.params.useDIP1000);
continue;
}
}
@@ -1122,7 +1077,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
{
//printf("escaping reference to local ref variable %s\n", v.toChars());
//printf("storage class = x%llx\n", v.storage_class);
- escapingRef(v, global.params.useDIP25);
+ result |= escapingRef(v, global.params.useDIP25);
continue;
}
// Don't need to be concerned if v's parent does not return a ref
@@ -1269,14 +1224,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
)
{
// https://issues.dlang.org/show_bug.cgi?id=17029
- if (setUnsafeDIP1000(sc.func))
- {
- if (!gag)
- previewErrorFunc(sc.isDeprecated(), global.params.useDIP1000)
- (e.loc, "scope variable `%s` may not be returned", v.toChars());
- if (global.params.useDIP1000 == FeatureState.enabled)
- result = true;
- }
+ result |= sc.setUnsafeDIP1000(gag, e.loc, "scope variable `%s` may not be returned", v);
continue;
}
}
@@ -1306,16 +1254,18 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
// 'featureState' tells us whether to emit an error or a deprecation,
// depending on the flag passed to the CLI for DIP25
- void escapingRef(VarDeclaration v, ScopeRef vsr, FeatureState featureState = FeatureState.enabled)
+ void escapingRef(VarDeclaration v, FeatureState featureState)
{
- if (!gag)
- {
- const(char)* varKind = v.isParameter() ? "parameter" : "local variable";
- previewErrorFunc(sc.isDeprecated(), featureState)(e.loc,
- "returning `%s` escapes a reference to %s `%s`", e.toChars(), varKind, v.toChars());
+ const(char)* msg = v.isParameter() ?
+ "returning `%s` escapes a reference to parameter `%s`" :
+ "returning `%s` escapes a reference to local variable `%s`";
- if (v.isParameter() && v.isReference())
+ if (v.isParameter() && v.isReference())
+ {
+ if (sc.setUnsafePreview(featureState, gag, e.loc, msg, e, v) ||
+ sc.func.isSafeBypassingInference())
{
+ result = true;
if (v.storage_class & STC.returnScope)
{
previewSupplementalFunc(sc.isDeprecated(), featureState)(v.loc,
@@ -1329,7 +1279,12 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
}
}
}
- result = true;
+ else
+ {
+ if (!gag)
+ previewErrorFunc(sc.isDeprecated(), featureState)(e.loc, msg, e.toChars(), v.toChars());
+ result = true;
+ }
}
if (v.isDataseg())
@@ -1340,14 +1295,23 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
Dsymbol p = v.toParent2();
// https://issues.dlang.org/show_bug.cgi?id=19965
- if (!refs && sc.func.vthis == v)
- notMaybeScope(v);
+ if (!refs)
+ {
+ if (sc.func.vthis == v)
+ notMaybeScope(v);
+
+ if (checkScopeVarAddr(v, e, sc, gag))
+ {
+ result = true;
+ continue;
+ }
+ }
if (!v.isReference())
{
if (p == sc.func)
{
- escapingRef(v, vsr, FeatureState.enabled);
+ escapingRef(v, FeatureState.enabled);
continue;
}
FuncDeclaration fd = p.isFuncDeclaration();
@@ -1388,7 +1352,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
{
//printf("escaping reference to local ref variable %s\n", v.toChars());
//printf("storage class = x%llx\n", v.storage_class);
- escapingRef(v, vsr, global.params.useDIP25);
+ escapingRef(v, global.params.useDIP25);
continue;
}
// Don't need to be concerned if v's parent does not return a ref
@@ -1489,370 +1453,385 @@ private void inferReturn(FuncDeclaration fd, VarDeclaration v, bool returnScope)
void escapeByValue(Expression e, EscapeByResults* er, bool live = false)
{
//printf("[%s] escapeByValue, e: %s\n", e.loc.toChars(), e.toChars());
- extern (C++) final class EscapeVisitor : Visitor
- {
- alias visit = Visitor.visit;
- public:
- EscapeByResults* er;
- bool live;
-
- extern (D) this(EscapeByResults* er, bool live)
- {
- this.er = er;
- this.live = live;
- }
- override void visit(Expression e)
- {
- }
+ void visit(Expression e)
+ {
+ }
- override void visit(AddrExp e)
- {
- /* Taking the address of struct literal is normally not
- * allowed, but CTFE can generate one out of a new expression,
- * but it'll be placed in static data so no need to check it.
- */
- if (e.e1.op != EXP.structLiteral)
- escapeByRef(e.e1, er, live);
- }
+ void visitAddr(AddrExp e)
+ {
+ /* Taking the address of struct literal is normally not
+ * allowed, but CTFE can generate one out of a new expression,
+ * but it'll be placed in static data so no need to check it.
+ */
+ if (e.e1.op != EXP.structLiteral)
+ escapeByRef(e.e1, er, live);
+ }
- override void visit(SymOffExp e)
- {
- VarDeclaration v = e.var.isVarDeclaration();
- if (v)
- er.byref.push(v);
- }
+ void visitSymOff(SymOffExp e)
+ {
+ VarDeclaration v = e.var.isVarDeclaration();
+ if (v)
+ er.byref.push(v);
+ }
- override void visit(VarExp e)
+ void visitVar(VarExp e)
+ {
+ if (auto v = e.var.isVarDeclaration())
{
- if (auto v = e.var.isVarDeclaration())
- {
- if (v.type.hasPointers() || // not tracking non-pointers
- v.storage_class & STC.lazy_) // lazy variables are actually pointers
- er.byvalue.push(v);
- }
+ if (v.type.hasPointers() || // not tracking non-pointers
+ v.storage_class & STC.lazy_) // lazy variables are actually pointers
+ er.byvalue.push(v);
}
+ }
- override void visit(ThisExp e)
- {
- if (e.var)
- er.byvalue.push(e.var);
- }
+ void visitThis(ThisExp e)
+ {
+ if (e.var)
+ er.byvalue.push(e.var);
+ }
- override void visit(PtrExp e)
- {
- if (live && e.type.hasPointers())
- e.e1.accept(this);
- }
+ void visitPtr(PtrExp e)
+ {
+ if (live && e.type.hasPointers())
+ escapeByValue(e.e1, er, live);
+ }
- override void visit(DotVarExp e)
+ void visitDotVar(DotVarExp e)
+ {
+ auto t = e.e1.type.toBasetype();
+ if (e.type.hasPointers() && (live || t.ty == Tstruct))
{
- auto t = e.e1.type.toBasetype();
- if (e.type.hasPointers() && (live || t.ty == Tstruct))
- {
- e.e1.accept(this);
- }
+ escapeByValue(e.e1, er, live);
}
+ }
- override void visit(DelegateExp e)
- {
- Type t = e.e1.type.toBasetype();
- if (t.ty == Tclass || t.ty == Tpointer)
- escapeByValue(e.e1, er, live);
- else
- escapeByRef(e.e1, er, live);
- er.byfunc.push(e.func);
- }
+ void visitDelegate(DelegateExp e)
+ {
+ Type t = e.e1.type.toBasetype();
+ if (t.ty == Tclass || t.ty == Tpointer)
+ escapeByValue(e.e1, er, live);
+ else
+ escapeByRef(e.e1, er, live);
+ er.byfunc.push(e.func);
+ }
- override void visit(FuncExp e)
- {
- if (e.fd.tok == TOK.delegate_)
- er.byfunc.push(e.fd);
- }
+ void visitFunc(FuncExp e)
+ {
+ if (e.fd.tok == TOK.delegate_)
+ er.byfunc.push(e.fd);
+ }
- override void visit(TupleExp e)
- {
- assert(0); // should have been lowered by now
- }
+ void visitTuple(TupleExp e)
+ {
+ assert(0); // should have been lowered by now
+ }
- override void visit(ArrayLiteralExp e)
+ void visitArrayLiteral(ArrayLiteralExp e)
+ {
+ Type tb = e.type.toBasetype();
+ if (tb.ty == Tsarray || tb.ty == Tarray)
{
- Type tb = e.type.toBasetype();
- if (tb.ty == Tsarray || tb.ty == Tarray)
+ if (e.basis)
+ escapeByValue(e.basis, er, live);
+ foreach (el; *e.elements)
{
- if (e.basis)
- e.basis.accept(this);
- foreach (el; *e.elements)
- {
- if (el)
- el.accept(this);
- }
+ if (el)
+ escapeByValue(el, er, live);
}
}
+ }
- override void visit(StructLiteralExp e)
+ void visitStructLiteral(StructLiteralExp e)
+ {
+ if (e.elements)
{
- if (e.elements)
+ foreach (ex; *e.elements)
{
- foreach (ex; *e.elements)
- {
- if (ex)
- ex.accept(this);
- }
+ if (ex)
+ escapeByValue(ex, er, live);
}
}
+ }
- override void visit(NewExp e)
+ void visitNew(NewExp e)
+ {
+ Type tb = e.newtype.toBasetype();
+ if (tb.ty == Tstruct && !e.member && e.arguments)
{
- Type tb = e.newtype.toBasetype();
- if (tb.ty == Tstruct && !e.member && e.arguments)
+ foreach (ex; *e.arguments)
{
- foreach (ex; *e.arguments)
- {
- if (ex)
- ex.accept(this);
- }
+ if (ex)
+ escapeByValue(ex, er, live);
}
}
+ }
- override void visit(CastExp e)
+ void visitCast(CastExp e)
+ {
+ if (!e.type.hasPointers())
+ return;
+ Type tb = e.type.toBasetype();
+ if (tb.ty == Tarray && e.e1.type.toBasetype().ty == Tsarray)
{
- if (!e.type.hasPointers())
- return;
- Type tb = e.type.toBasetype();
- if (tb.ty == Tarray && e.e1.type.toBasetype().ty == Tsarray)
- {
- escapeByRef(e.e1, er, live);
- }
- else
- e.e1.accept(this);
+ escapeByRef(e.e1, er, live);
}
+ else
+ escapeByValue(e.e1, er, live);
+ }
- override void visit(SliceExp e)
+ void visitSlice(SliceExp e)
+ {
+ if (auto ve = e.e1.isVarExp())
{
- if (auto ve = e.e1.isVarExp())
+ VarDeclaration v = ve.var.isVarDeclaration();
+ Type tb = e.type.toBasetype();
+ if (v)
{
- VarDeclaration v = ve.var.isVarDeclaration();
- Type tb = e.type.toBasetype();
- if (v)
+ if (tb.ty == Tsarray)
+ return;
+ if (v.storage_class & STC.variadic)
{
- if (tb.ty == Tsarray)
- return;
- if (v.storage_class & STC.variadic)
- {
- er.byvalue.push(v);
- return;
- }
+ er.byvalue.push(v);
+ return;
}
}
- Type t1b = e.e1.type.toBasetype();
- if (t1b.ty == Tsarray)
- {
- Type tb = e.type.toBasetype();
- if (tb.ty != Tsarray)
- escapeByRef(e.e1, er, live);
- }
- else
- e.e1.accept(this);
}
-
- override void visit(IndexExp e)
- {
- if (e.e1.type.toBasetype().ty == Tsarray ||
- live && e.type.hasPointers())
- {
- e.e1.accept(this);
- }
- }
-
- override void visit(BinExp e)
+ Type t1b = e.e1.type.toBasetype();
+ if (t1b.ty == Tsarray)
{
Type tb = e.type.toBasetype();
- if (tb.ty == Tpointer)
- {
- e.e1.accept(this);
- e.e2.accept(this);
- }
+ if (tb.ty != Tsarray)
+ escapeByRef(e.e1, er, live);
}
+ else
+ escapeByValue(e.e1, er, live);
+ }
- override void visit(BinAssignExp e)
+ void visitIndex(IndexExp e)
+ {
+ if (e.e1.type.toBasetype().ty == Tsarray ||
+ live && e.type.hasPointers())
{
- e.e1.accept(this);
+ escapeByValue(e.e1, er, live);
}
+ }
- override void visit(AssignExp e)
+ void visitBin(BinExp e)
+ {
+ Type tb = e.type.toBasetype();
+ if (tb.ty == Tpointer)
{
- e.e1.accept(this);
+ escapeByValue(e.e1, er, live);
+ escapeByValue(e.e2, er, live);
}
+ }
- override void visit(CommaExp e)
- {
- e.e2.accept(this);
- }
+ void visitBinAssign(BinAssignExp e)
+ {
+ escapeByValue(e.e1, er, live);
+ }
+
+ void visitAssign(AssignExp e)
+ {
+ escapeByValue(e.e1, er, live);
+ }
- override void visit(CondExp e)
+ void visitComma(CommaExp e)
+ {
+ escapeByValue(e.e2, er, live);
+ }
+
+ void visitCond(CondExp e)
+ {
+ escapeByValue(e.e1, er, live);
+ escapeByValue(e.e2, er, live);
+ }
+
+ void visitCall(CallExp e)
+ {
+ //printf("CallExp(): %s\n", e.toChars());
+ /* Check each argument that is
+ * passed as 'return scope'.
+ */
+ Type t1 = e.e1.type.toBasetype();
+ TypeFunction tf;
+ TypeDelegate dg;
+ if (t1.ty == Tdelegate)
{
- e.e1.accept(this);
- e.e2.accept(this);
+ dg = t1.isTypeDelegate();
+ tf = dg.next.isTypeFunction();
}
+ else if (t1.ty == Tfunction)
+ tf = t1.isTypeFunction();
+ else
+ return;
+
+ if (!e.type.hasPointers())
+ return;
- override void visit(CallExp e)
+ if (e.arguments && e.arguments.dim)
{
- //printf("CallExp(): %s\n", e.toChars());
- /* Check each argument that is
- * passed as 'return scope'.
+ /* j=1 if _arguments[] is first argument,
+ * skip it because it is not passed by ref
*/
- Type t1 = e.e1.type.toBasetype();
- TypeFunction tf;
- TypeDelegate dg;
- if (t1.ty == Tdelegate)
+ int j = tf.isDstyleVariadic();
+ for (size_t i = j; i < e.arguments.dim; ++i)
{
- dg = t1.isTypeDelegate();
- tf = dg.next.isTypeFunction();
- }
- else if (t1.ty == Tfunction)
- tf = t1.isTypeFunction();
- else
- return;
-
- if (!e.type.hasPointers())
- return;
-
- if (e.arguments && e.arguments.dim)
- {
- /* j=1 if _arguments[] is first argument,
- * skip it because it is not passed by ref
- */
- int j = tf.isDstyleVariadic();
- for (size_t i = j; i < e.arguments.dim; ++i)
+ Expression arg = (*e.arguments)[i];
+ size_t nparams = tf.parameterList.length;
+ if (i - j < nparams && i >= j)
{
- Expression arg = (*e.arguments)[i];
- size_t nparams = tf.parameterList.length;
- if (i - j < nparams && i >= j)
+ Parameter p = tf.parameterList[i - j];
+ const stc = tf.parameterStorageClass(null, p);
+ ScopeRef psr = buildScopeRef(stc);
+ if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
+ escapeByValue(arg, er, live);
+ else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
{
- Parameter p = tf.parameterList[i - j];
- const stc = tf.parameterStorageClass(null, p);
- ScopeRef psr = buildScopeRef(stc);
- if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
- arg.accept(this);
- else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
+ if (tf.isref)
{
- if (tf.isref)
- {
- /* Treat:
- * ref P foo(return ref P p)
- * as:
- * p;
- */
- arg.accept(this);
- }
- else
- escapeByRef(arg, er, live);
+ /* Treat:
+ * ref P foo(return ref P p)
+ * as:
+ * p;
+ */
+ escapeByValue(arg, er, live);
}
+ else
+ escapeByRef(arg, er, live);
}
}
}
- // If 'this' is returned, check it too
- if (e.e1.op == EXP.dotVariable && t1.ty == Tfunction)
+ }
+ // If 'this' is returned, check it too
+ if (e.e1.op == EXP.dotVariable && t1.ty == Tfunction)
+ {
+ DotVarExp dve = e.e1.isDotVarExp();
+ FuncDeclaration fd = dve.var.isFuncDeclaration();
+ if (global.params.useDIP1000 == FeatureState.enabled)
{
- DotVarExp dve = e.e1.isDotVarExp();
- FuncDeclaration fd = dve.var.isFuncDeclaration();
- if (global.params.useDIP1000 == FeatureState.enabled)
+ if (fd && fd.isThis())
{
- if (fd && fd.isThis())
- {
- /* Calling a non-static member function dve.var, which is returning `this`, and with dve.e1 representing `this`
- */
-
- /*****************************
- * Concoct storage class for member function's implicit `this` parameter.
- * Params:
- * fd = member function
- * Returns:
- * storage class for fd's `this`
- */
- StorageClass getThisStorageClass(FuncDeclaration fd)
- {
- StorageClass stc;
- auto tf = fd.type.toBasetype().isTypeFunction();
- if (tf.isreturn)
- stc |= STC.return_;
- if (tf.isreturnscope)
- stc |= STC.returnScope;
- auto ad = fd.isThis();
- if (ad.isClassDeclaration() || tf.isScopeQual)
- stc |= STC.scope_;
- if (ad.isStructDeclaration())
- stc |= STC.ref_; // `this` for a struct member function is passed by `ref`
- return stc;
- }
+ /* Calling a non-static member function dve.var, which is returning `this`, and with dve.e1 representing `this`
+ */
- const psr = buildScopeRef(getThisStorageClass(fd));
- if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
- dve.e1.accept(this);
- else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
- {
- if (tf.isref)
- {
- /* Treat calling:
- * struct S { ref S foo() return; }
- * as:
- * this;
- */
- dve.e1.accept(this);
- }
- else
- escapeByRef(dve.e1, er, live);
- }
+ /*****************************
+ * Concoct storage class for member function's implicit `this` parameter.
+ * Params:
+ * fd = member function
+ * Returns:
+ * storage class for fd's `this`
+ */
+ StorageClass getThisStorageClass(FuncDeclaration fd)
+ {
+ StorageClass stc;
+ auto tf = fd.type.toBasetype().isTypeFunction();
+ if (tf.isreturn)
+ stc |= STC.return_;
+ if (tf.isreturnscope)
+ stc |= STC.returnScope;
+ auto ad = fd.isThis();
+ if (ad.isClassDeclaration() || tf.isScopeQual)
+ stc |= STC.scope_;
+ if (ad.isStructDeclaration())
+ stc |= STC.ref_; // `this` for a struct member function is passed by `ref`
+ return stc;
}
- }
- else
- {
- // Calling member function before dip1000
- StorageClass stc = dve.var.storage_class & (STC.return_ | STC.scope_ | STC.ref_);
- if (tf.isreturn)
- stc |= STC.return_;
- const psr = buildScopeRef(stc);
+ const psr = buildScopeRef(getThisStorageClass(fd));
if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
- dve.e1.accept(this);
+ escapeByValue(dve.e1, er, live);
else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
- escapeByRef(dve.e1, er, live);
+ {
+ if (tf.isref)
+ {
+ /* Treat calling:
+ * struct S { ref S foo() return; }
+ * as:
+ * this;
+ */
+ escapeByValue(dve.e1, er, live);
+ }
+ else
+ escapeByRef(dve.e1, er, live);
+ }
}
+ }
+ else
+ {
+ // Calling member function before dip1000
+ StorageClass stc = dve.var.storage_class & (STC.return_ | STC.scope_ | STC.ref_);
+ if (tf.isreturn)
+ stc |= STC.return_;
- // If it's also a nested function that is 'return scope'
- if (fd && fd.isNested())
- {
- if (tf.isreturn && tf.isScopeQual)
- er.byexp.push(e);
- }
+ const psr = buildScopeRef(stc);
+ if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
+ escapeByValue(dve.e1, er, live);
+ else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
+ escapeByRef(dve.e1, er, live);
}
- /* If returning the result of a delegate call, the .ptr
- * field of the delegate must be checked.
- */
- if (dg)
+ // If it's also a nested function that is 'return scope'
+ if (fd && fd.isNested())
{
- if (tf.isreturn)
- e.e1.accept(this);
+ if (tf.isreturn && tf.isScopeQual)
+ er.byexp.push(e);
}
+ }
- /* If it's a nested function that is 'return scope'
- */
- if (auto ve = e.e1.isVarExp())
+ /* If returning the result of a delegate call, the .ptr
+ * field of the delegate must be checked.
+ */
+ if (dg)
+ {
+ if (tf.isreturn)
+ escapeByValue(e.e1, er, live);
+ }
+
+ /* If it's a nested function that is 'return scope'
+ */
+ if (auto ve = e.e1.isVarExp())
+ {
+ FuncDeclaration fd = ve.var.isFuncDeclaration();
+ if (fd && fd.isNested())
{
- FuncDeclaration fd = ve.var.isFuncDeclaration();
- if (fd && fd.isNested())
- {
- if (tf.isreturn && tf.isScopeQual)
- er.byexp.push(e);
- }
+ if (tf.isreturn && tf.isScopeQual)
+ er.byexp.push(e);
}
}
}
- scope EscapeVisitor v = new EscapeVisitor(er, live);
- e.accept(v);
+ switch (e.op)
+ {
+ case EXP.address: return visitAddr(e.isAddrExp());
+ case EXP.symbolOffset: return visitSymOff(e.isSymOffExp());
+ case EXP.variable: return visitVar(e.isVarExp());
+ case EXP.this_: return visitThis(e.isThisExp());
+ case EXP.star: return visitPtr(e.isPtrExp());
+ case EXP.dotVariable: return visitDotVar(e.isDotVarExp());
+ case EXP.delegate_: return visitDelegate(e.isDelegateExp());
+ case EXP.function_: return visitFunc(e.isFuncExp());
+ case EXP.tuple: return visitTuple(e.isTupleExp());
+ case EXP.arrayLiteral: return visitArrayLiteral(e.isArrayLiteralExp());
+ case EXP.structLiteral: return visitStructLiteral(e.isStructLiteralExp());
+ case EXP.new_: return visitNew(e.isNewExp());
+ case EXP.cast_: return visitCast(e.isCastExp());
+ case EXP.slice: return visitSlice(e.isSliceExp());
+ case EXP.index: return visitIndex(e.isIndexExp());
+ case EXP.blit: return visitAssign(e.isBlitExp());
+ case EXP.construct: return visitAssign(e.isConstructExp());
+ case EXP.assign: return visitAssign(e.isAssignExp());
+ case EXP.comma: return visitComma(e.isCommaExp());
+ case EXP.question: return visitCond(e.isCondExp());
+ case EXP.call: return visitCall(e.isCallExp());
+ default:
+ if (auto b = e.isBinExp())
+ return visitBin(b);
+ if (auto ba = e.isBinAssignExp())
+ return visitBinAssign(ba);
+ return visit(e);
+ }
}
@@ -1877,236 +1856,239 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false)
void escapeByRef(Expression e, EscapeByResults* er, bool live = false)
{
//printf("[%s] escapeByRef, e: %s\n", e.loc.toChars(), e.toChars());
- extern (C++) final class EscapeRefVisitor : Visitor
+ void visit(Expression e)
{
- alias visit = Visitor.visit;
- public:
- EscapeByResults* er;
- bool live;
-
- extern (D) this(EscapeByResults* er, bool live)
- {
- this.er = er;
- this.live = live;
- }
-
- override void visit(Expression e)
- {
- }
+ }
- override void visit(VarExp e)
+ void visitVar(VarExp e)
+ {
+ auto v = e.var.isVarDeclaration();
+ if (v)
{
- auto v = e.var.isVarDeclaration();
- if (v)
+ if (v.storage_class & STC.ref_ && v.storage_class & (STC.foreach_ | STC.temp) && v._init)
{
- if (v.storage_class & STC.ref_ && v.storage_class & (STC.foreach_ | STC.temp) && v._init)
+ /* If compiler generated ref temporary
+ * (ref v = ex; ex)
+ * look at the initializer instead
+ */
+ if (ExpInitializer ez = v._init.isExpInitializer())
{
- /* If compiler generated ref temporary
- * (ref v = ex; ex)
- * look at the initializer instead
- */
- if (ExpInitializer ez = v._init.isExpInitializer())
- {
- if (auto ce = ez.exp.isConstructExp())
- ce.e2.accept(this);
- else
- ez.exp.accept(this);
- }
+ if (auto ce = ez.exp.isConstructExp())
+ escapeByRef(ce.e2, er, live);
+ else
+ escapeByRef(ez.exp, er, live);
}
- else
- er.byref.push(v);
}
+ else
+ er.byref.push(v);
}
+ }
- override void visit(ThisExp e)
- {
- if (e.var && e.var.toParent2().isFuncDeclaration().hasDualContext())
- escapeByValue(e, er, live);
- else if (e.var)
- er.byref.push(e.var);
- }
+ void visitThis(ThisExp e)
+ {
+ if (e.var && e.var.toParent2().isFuncDeclaration().hasDualContext())
+ escapeByValue(e, er, live);
+ else if (e.var)
+ er.byref.push(e.var);
+ }
- override void visit(PtrExp e)
- {
- escapeByValue(e.e1, er, live);
- }
+ void visitPtr(PtrExp e)
+ {
+ escapeByValue(e.e1, er, live);
+ }
- override void visit(IndexExp e)
+ void visitIndex(IndexExp e)
+ {
+ Type tb = e.e1.type.toBasetype();
+ if (auto ve = e.e1.isVarExp())
{
- Type tb = e.e1.type.toBasetype();
- if (auto ve = e.e1.isVarExp())
+ VarDeclaration v = ve.var.isVarDeclaration();
+ if (tb.ty == Tarray || tb.ty == Tsarray)
{
- VarDeclaration v = ve.var.isVarDeclaration();
- if (tb.ty == Tarray || tb.ty == Tsarray)
+ if (v && v.storage_class & STC.variadic)
{
- if (v && v.storage_class & STC.variadic)
- {
- er.byref.push(v);
- return;
- }
+ er.byref.push(v);
+ return;
}
}
- if (tb.ty == Tsarray)
- {
- e.e1.accept(this);
- }
- else if (tb.ty == Tarray)
- {
- escapeByValue(e.e1, er, live);
- }
}
-
- override void visit(StructLiteralExp e)
+ if (tb.ty == Tsarray)
{
- if (e.elements)
- {
- foreach (ex; *e.elements)
- {
- if (ex)
- ex.accept(this);
- }
- }
- er.byexp.push(e);
+ escapeByRef(e.e1, er, live);
}
-
- override void visit(DotVarExp e)
+ else if (tb.ty == Tarray)
{
- Type t1b = e.e1.type.toBasetype();
- if (t1b.ty == Tclass)
- escapeByValue(e.e1, er, live);
- else
- e.e1.accept(this);
+ escapeByValue(e.e1, er, live);
}
+ }
- override void visit(BinAssignExp e)
+ void visitStructLiteral(StructLiteralExp e)
+ {
+ if (e.elements)
{
- e.e1.accept(this);
+ foreach (ex; *e.elements)
+ {
+ if (ex)
+ escapeByRef(ex, er, live);
+ }
}
+ er.byexp.push(e);
+ }
- override void visit(AssignExp e)
- {
- e.e1.accept(this);
- }
+ void visitDotVar(DotVarExp e)
+ {
+ Type t1b = e.e1.type.toBasetype();
+ if (t1b.ty == Tclass)
+ escapeByValue(e.e1, er, live);
+ else
+ escapeByRef(e.e1, er, live);
+ }
- override void visit(CommaExp e)
- {
- e.e2.accept(this);
- }
+ void visitBinAssign(BinAssignExp e)
+ {
+ escapeByRef(e.e1, er, live);
+ }
- override void visit(CondExp e)
- {
- e.e1.accept(this);
- e.e2.accept(this);
- }
+ void visitAssign(AssignExp e)
+ {
+ escapeByRef(e.e1, er, live);
+ }
- override void visit(CallExp e)
+ void visitComma(CommaExp e)
+ {
+ escapeByRef(e.e2, er, live);
+ }
+
+ void visitCond(CondExp e)
+ {
+ escapeByRef(e.e1, er, live);
+ escapeByRef(e.e2, er, live);
+ }
+
+ void visitCall(CallExp e)
+ {
+ //printf("escapeByRef.CallExp(): %s\n", e.toChars());
+ /* If the function returns by ref, check each argument that is
+ * passed as 'return ref'.
+ */
+ Type t1 = e.e1.type.toBasetype();
+ TypeFunction tf;
+ if (t1.ty == Tdelegate)
+ tf = t1.isTypeDelegate().next.isTypeFunction();
+ else if (t1.ty == Tfunction)
+ tf = t1.isTypeFunction();
+ else
+ return;
+ if (tf.isref)
{
- //printf("escapeByRef.CallExp(): %s\n", e.toChars());
- /* If the function returns by ref, check each argument that is
- * passed as 'return ref'.
- */
- Type t1 = e.e1.type.toBasetype();
- TypeFunction tf;
- if (t1.ty == Tdelegate)
- tf = t1.isTypeDelegate().next.isTypeFunction();
- else if (t1.ty == Tfunction)
- tf = t1.isTypeFunction();
- else
- return;
- if (tf.isref)
+ if (e.arguments && e.arguments.dim)
{
- if (e.arguments && e.arguments.dim)
+ /* j=1 if _arguments[] is first argument,
+ * skip it because it is not passed by ref
+ */
+ int j = tf.isDstyleVariadic();
+ for (size_t i = j; i < e.arguments.dim; ++i)
{
- /* j=1 if _arguments[] is first argument,
- * skip it because it is not passed by ref
- */
- int j = tf.isDstyleVariadic();
- for (size_t i = j; i < e.arguments.dim; ++i)
+ Expression arg = (*e.arguments)[i];
+ size_t nparams = tf.parameterList.length;
+ if (i - j < nparams && i >= j)
{
- Expression arg = (*e.arguments)[i];
- size_t nparams = tf.parameterList.length;
- if (i - j < nparams && i >= j)
+ Parameter p = tf.parameterList[i - j];
+ const stc = tf.parameterStorageClass(null, p);
+ ScopeRef psr = buildScopeRef(stc);
+ if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
+ escapeByRef(arg, er, live);
+ else if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
{
- Parameter p = tf.parameterList[i - j];
- const stc = tf.parameterStorageClass(null, p);
- ScopeRef psr = buildScopeRef(stc);
- if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
- arg.accept(this);
- else if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
+ if (auto de = arg.isDelegateExp())
{
- if (auto de = arg.isDelegateExp())
- {
- if (de.func.isNested())
- er.byexp.push(de);
- }
- else
- escapeByValue(arg, er, live);
+ if (de.func.isNested())
+ er.byexp.push(de);
}
+ else
+ escapeByValue(arg, er, live);
}
}
}
- // If 'this' is returned by ref, check it too
- if (e.e1.op == EXP.dotVariable && t1.ty == Tfunction)
+ }
+ // If 'this' is returned by ref, check it too
+ if (e.e1.op == EXP.dotVariable && t1.ty == Tfunction)
+ {
+ DotVarExp dve = e.e1.isDotVarExp();
+
+ // https://issues.dlang.org/show_bug.cgi?id=20149#c10
+ if (dve.var.isCtorDeclaration())
{
- DotVarExp dve = e.e1.isDotVarExp();
+ er.byexp.push(e);
+ return;
+ }
- // https://issues.dlang.org/show_bug.cgi?id=20149#c10
- if (dve.var.isCtorDeclaration())
- {
- er.byexp.push(e);
- return;
- }
+ StorageClass stc = dve.var.storage_class & (STC.return_ | STC.scope_ | STC.ref_);
+ if (tf.isreturn)
+ stc |= STC.return_;
+ if (tf.isref)
+ stc |= STC.ref_;
+ if (tf.isScopeQual)
+ stc |= STC.scope_;
+ if (tf.isreturnscope)
+ stc |= STC.returnScope;
+
+ const psr = buildScopeRef(stc);
+ if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
+ escapeByRef(dve.e1, er, live);
+ else if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
+ escapeByValue(dve.e1, er, live);
- StorageClass stc = dve.var.storage_class & (STC.return_ | STC.scope_ | STC.ref_);
- if (tf.isreturn)
- stc |= STC.return_;
- if (tf.isref)
- stc |= STC.ref_;
- if (tf.isScopeQual)
- stc |= STC.scope_;
- if (tf.isreturnscope)
- stc |= STC.returnScope;
-
- const psr = buildScopeRef(stc);
- if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
- dve.e1.accept(this);
- else if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
- escapeByValue(dve.e1, er, live);
-
- // If it's also a nested function that is 'return ref'
- if (FuncDeclaration fd = dve.var.isFuncDeclaration())
+ // If it's also a nested function that is 'return ref'
+ if (FuncDeclaration fd = dve.var.isFuncDeclaration())
+ {
+ if (fd.isNested() && tf.isreturn)
{
- if (fd.isNested() && tf.isreturn)
- {
- er.byexp.push(e);
- }
+ er.byexp.push(e);
}
}
- // If it's a delegate, check it too
- if (e.e1.op == EXP.variable && t1.ty == Tdelegate)
- {
- escapeByValue(e.e1, er, live);
- }
+ }
+ // If it's a delegate, check it too
+ if (e.e1.op == EXP.variable && t1.ty == Tdelegate)
+ {
+ escapeByValue(e.e1, er, live);
+ }
- /* If it's a nested function that is 'return ref'
- */
- if (auto ve = e.e1.isVarExp())
+ /* If it's a nested function that is 'return ref'
+ */
+ if (auto ve = e.e1.isVarExp())
+ {
+ FuncDeclaration fd = ve.var.isFuncDeclaration();
+ if (fd && fd.isNested())
{
- FuncDeclaration fd = ve.var.isFuncDeclaration();
- if (fd && fd.isNested())
- {
- if (tf.isreturn)
- er.byexp.push(e);
- }
+ if (tf.isreturn)
+ er.byexp.push(e);
}
}
- else
- er.byexp.push(e);
}
+ else
+ er.byexp.push(e);
}
- scope EscapeRefVisitor v = new EscapeRefVisitor(er, live);
- e.accept(v);
+ switch (e.op)
+ {
+ case EXP.variable: return visitVar(e.isVarExp());
+ case EXP.this_: return visitThis(e.isThisExp());
+ case EXP.star: return visitPtr(e.isPtrExp());
+ case EXP.structLiteral: return visitStructLiteral(e.isStructLiteralExp());
+ case EXP.dotVariable: return visitDotVar(e.isDotVarExp());
+ case EXP.index: return visitIndex(e.isIndexExp());
+ case EXP.blit: return visitAssign(e.isBlitExp());
+ case EXP.construct: return visitAssign(e.isConstructExp());
+ case EXP.assign: return visitAssign(e.isAssignExp());
+ case EXP.comma: return visitComma(e.isCommaExp());
+ case EXP.question: return visitCond(e.isCondExp());
+ case EXP.call: return visitCall(e.isCallExp());
+ default:
+ if (auto ba = e.isBinAssignExp())
+ return visitBinAssign(ba);
+ return visit(e);
+ }
}
@@ -2170,7 +2152,7 @@ public void findAllOuterAccessedVariables(FuncDeclaration fd, VarDeclarations* v
*/
version (none)
{
- public void notMaybeScope(string file = __FILE__, int line = __LINE__)(VarDeclaration v)
+ private void notMaybeScope(string file = __FILE__, int line = __LINE__)(VarDeclaration v)
{
printf("%.*s(%d): notMaybeScope('%s')\n", cast(int)file.length, file.ptr, line, v.toChars());
v.storage_class &= ~STC.maybescope;
@@ -2178,12 +2160,88 @@ version (none)
}
else
{
- public void notMaybeScope(VarDeclaration v)
+ private void notMaybeScope(VarDeclaration v)
{
v.storage_class &= ~STC.maybescope;
}
}
+/***********************************
+ * After semantic analysis of the function body,
+ * try to infer `scope` / `return` on the parameters
+ *
+ * Params:
+ * funcdecl = function declaration that was analyzed
+ * f = final function type. `funcdecl.type` started as the 'premature type' before attribute
+ * inference, then its inferred attributes are copied over to final type `f`
+ */
+void finishScopeParamInference(FuncDeclaration funcdecl, ref TypeFunction f)
+{
+ 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;
+ }
+}
/**********************************************
* Have some variables that are maybescopes that were
@@ -2207,7 +2265,7 @@ else
* Params:
* array = array of variables that were assigned to from maybescope variables
*/
-public void eliminateMaybeScopes(VarDeclaration[] array)
+private void eliminateMaybeScopes(VarDeclaration[] array)
{
enum log = false;
if (log) printf("eliminateMaybeScopes()\n");
@@ -2355,10 +2413,89 @@ private void addMaybe(VarDeclaration va, VarDeclaration v)
va.maybes.push(v);
}
+/***************************************
+ * Like `FuncDeclaration.setUnsafe`, but modified for dip25 / dip1000 by default transitions
+ *
+ * With `-preview=dip1000` it actually sets the function as unsafe / prints an error, while
+ * without it, it only prints a deprecation in a `@safe` function.
+ * With `-revert=preview=dip1000`, it doesn't do anything.
+ *
+ * Params:
+ * sc = used for checking whether we are in a deprecated scope
+ * fs = command line setting of dip1000 / dip25
+ * gag = surpress error message
+ * 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 an actual safe error (not deprecation) occured
+ */
+private bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)* msg, RootObject arg0 = null, RootObject arg1 = null)
+{
+ if (fs == FeatureState.disabled)
+ {
+ return false;
+ }
+ else if (fs == FeatureState.enabled)
+ {
+ return sc.func.setUnsafe(gag, loc, msg, arg0, arg1);
+ }
+ else
+ {
+ if (sc.func.isSafeBypassingInference())
+ {
+ if (!gag)
+ previewErrorFunc(sc.isDeprecated(), fs)(
+ loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : ""
+ );
+ }
+ return false;
+ }
+}
+
+// `setUnsafePreview` partially evaluated for dip1000
+private bool setUnsafeDIP1000(Scope* sc, bool gag, Loc loc, const(char)* msg, RootObject arg0 = null, RootObject arg1 = null)
+{
+ return setUnsafePreview(sc, global.params.useDIP1000, gag, loc, msg, arg0, arg1);
+}
-private bool setUnsafeDIP1000(FuncDeclaration f)
+/***************************************
+ * Check that taking the address of `v` is `@safe`
+ *
+ * It's not possible to take the address of a scope variable, because `scope` only applies
+ * to the top level indirection.
+ *
+ * Params:
+ * v = variable that a reference is created
+ * e = expression that takes the referene
+ * sc = used to obtain function / deprecated status
+ * gag = don't print errors
+ * Returns:
+ * true if taking the address of `v` is problematic because of the lack of transitive `scope`
+ */
+private bool checkScopeVarAddr(VarDeclaration v, Expression e, Scope* sc, bool gag)
{
- return global.params.useDIP1000 == FeatureState.enabled
- ? f.setUnsafe()
- : f.isSafeBypassingInference();
+ if (v.storage_class & STC.temp)
+ return false;
+
+ if (!v.isScope())
+ {
+ v.storage_class &= ~STC.maybescope;
+ v.doNotInferScope = true;
+ return false;
+ }
+
+ if (!e.type)
+ return false;
+
+ // When the type after dereferencing has no pointers, it's okay.
+ // Comes up when escaping `&someStruct.intMember` of a `scope` struct:
+ // scope does not apply to the `int`
+ Type t = e.type.baseElemOf();
+ if ((t.ty == Tarray || t.ty == Tpointer) && !t.nextOf().toBasetype().hasPointers())
+ return false;
+
+ // take address of `scope` variable not allowed, requires transitive scope
+ return sc.setUnsafeDIP1000(gag, e.loc,
+ "cannot take address of `scope` variable `%s` since `scope` applies to first indirection only", v);
}
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 107e85b..0872356 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -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);
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index d4e96bb..b65b0ed 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -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;
}
}
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index 8d83951..e53a540 100644
--- a/gcc/d/dmd/func.d
+++ b/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);
+ }
+ }
+ }
+}
diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d
index 6b6655c..ba4ccbe 100644
--- a/gcc/d/dmd/globals.d
+++ b/gcc/d/dmd/globals.d
@@ -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
diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h
index 2a33692..5c164fd 100644
--- a/gcc/d/dmd/globals.h
+++ b/gcc/d/dmd/globals.h
@@ -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();
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index 69fdf27..fd35e1c 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -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))
{
diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index 11455af..ab9528a 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/dmd/id.d
@@ -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" },
diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d
index c84a9f6..2cddd28 100644
--- a/gcc/d/dmd/initsem.d
+++ b/gcc/d/dmd/initsem.d
@@ -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] = "";
diff --git a/gcc/d/dmd/json.d b/gcc/d/dmd/json.d
index fc27039..a22c664 100644
--- a/gcc/d/dmd/json.d
+++ b/gcc/d/dmd/json.d
@@ -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);
}
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index 13df0d7..be17ab3 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -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)
{
diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h
index 6ba47df..d2b1364 100644
--- a/gcc/d/dmd/mtype.h
+++ b/gcc/d/dmd/mtype.h
@@ -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();
diff --git a/gcc/d/dmd/nogc.d b/gcc/d/dmd/nogc.d
index 2957b3a..8cf3585 100644
--- a/gcc/d/dmd/nogc.d
+++ b/gcc/d/dmd/nogc.d
@@ -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)
diff --git a/gcc/d/dmd/objc.d b/gcc/d/dmd/objc.d
index 9e92212..9afedc1 100644
--- a/gcc/d/dmd/objc.d
+++ b/gcc/d/dmd/objc.d
@@ -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);
diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d
index 3cc36b4..2b7b9ac 100644
--- a/gcc/d/dmd/optimize.d
+++ b/gcc/d/dmd/optimize.d
@@ -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())
{
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index 4b9c0f2..15b7658 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -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;
}
diff --git a/gcc/d/dmd/safe.d b/gcc/d/dmd/safe.d
index bad071e..1c5275b 100644
--- a/gcc/d/dmd/safe.d
+++ b/gcc/d/dmd/safe.d
@@ -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;
}
diff --git a/gcc/d/dmd/semantic2.d b/gcc/d/dmd/semantic2.d
index cd65920..73dcaa6 100644
--- a/gcc/d/dmd/semantic2.d
+++ b/gcc/d/dmd/semantic2.d
@@ -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
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index 5119576..a056c99 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -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();
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index 2916bbc..a7ad84f 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -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();
}
diff --git a/gcc/d/dmd/tokens.d b/gcc/d/dmd/tokens.d
index 03e8024..170a534 100644
--- a/gcc/d/dmd/tokens.d
+++ b/gcc/d/dmd/tokens.d
@@ -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__ ];
diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d
index 04e1c47..be95432 100644
--- a/gcc/d/dmd/traits.d
+++ b/gcc/d/dmd/traits.d
@@ -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();
}
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index f63b177..ac4c23b 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -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;
-
- 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;
- }
- }
+ Expression e;
+ Type t;
+ Dsymbol s;
+ mtype.resolve(loc, sc, e, t, s);
- 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
diff --git a/gcc/d/dmd/utils.d b/gcc/d/dmd/utils.d
index 7f3fb64..5be4a19 100644
--- a/gcc/d/dmd/utils.d
+++ b/gcc/d/dmd/utils.d
@@ -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();
}
}
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index c683d9d..7f5e683 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -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; */
diff --git a/gcc/d/lang.opt b/gcc/d/lang.opt
index b4b8152..c263582 100644
--- a/gcc/d/lang.opt
+++ b/gcc/d/lang.opt
@@ -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.
diff --git a/gcc/d/types.cc b/gcc/d/types.cc
index d897ec4..c54049d 100644
--- a/gcc/d/types.cc
+++ b/gcc/d/types.cc
@@ -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;
}
}
diff --git a/gcc/testsuite/gdc.test/compilable/aggr_alignment.d b/gcc/testsuite/gdc.test/compilable/aggr_alignment.d
index 0c727e2..7db9531 100644
--- a/gcc/testsuite/gdc.test/compilable/aggr_alignment.d
+++ b/gcc/testsuite/gdc.test/compilable/aggr_alignment.d
@@ -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;
diff --git a/gcc/testsuite/gdc.test/compilable/compile1.d b/gcc/testsuite/gdc.test/compilable/compile1.d
index 40fba48..4678eb5 100644
--- a/gcc/testsuite/gdc.test/compilable/compile1.d
+++ b/gcc/testsuite/gdc.test/compilable/compile1.d
@@ -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
---
*/
diff --git a/gcc/testsuite/gdc.test/compilable/cppmangle.d b/gcc/testsuite/gdc.test/compilable/cppmangle.d
index 8c112d1..fc74c94 100644
--- a/gcc/testsuite/gdc.test/compilable/cppmangle.d
+++ b/gcc/testsuite/gdc.test/compilable/cppmangle.d
@@ -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];
diff --git a/gcc/testsuite/gdc.test/compilable/dbitfield.d b/gcc/testsuite/gdc.test/compilable/dbitfield.d
new file mode 100644
index 0000000..e2883fd
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/dbitfield.d
@@ -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);
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_breaks_verbose.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_breaks_verbose.d
deleted file mode 100644
index 1ff26b0..0000000
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_breaks_verbose.d
+++ /dev/null
@@ -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;
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_code_verbose.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_code_verbose.d
deleted file mode 100644
index eb64c04..0000000
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_code_verbose.d
+++ /dev/null
@@ -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;
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_emphasis_verbose.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_emphasis_verbose.d
deleted file mode 100644
index 07904c1..0000000
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_emphasis_verbose.d
+++ /dev/null
@@ -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;
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_headings_verbose.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_headings_verbose.d
deleted file mode 100644
index 6448463..0000000
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_headings_verbose.d
+++ /dev/null
@@ -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;
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_links_verbose.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_links_verbose.d
deleted file mode 100644
index 435b426..0000000
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_links_verbose.d
+++ /dev/null
@@ -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: ![D-Man](https://dlang.org/images/d3.png)
-
-[dub]: https://code.dlang.org
-+/
-module test.compilable.ddoc_markdown_links_verbose;
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_lists_verbose.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_lists_verbose.d
deleted file mode 100644
index 4fd1a80..0000000
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_lists_verbose.d
+++ /dev/null
@@ -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;
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_quote_verbose.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_quote_verbose.d
deleted file mode 100644
index f16e539..0000000
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_quote_verbose.d
+++ /dev/null
@@ -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;
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_tables_verbose.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_tables_verbose.d
deleted file mode 100644
index d1aac1c..0000000
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_tables_verbose.d
+++ /dev/null
@@ -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;
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_21217.d b/gcc/testsuite/gdc.test/compilable/dtoh_21217.d
index 8836ad1..3e535d2 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_21217.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_21217.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_AliasDeclaration.d b/gcc/testsuite/gdc.test/compilable/dtoh_AliasDeclaration.d
index 10f5807..64198f9 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_AliasDeclaration.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_AliasDeclaration.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_AliasDeclaration_98.d b/gcc/testsuite/gdc.test/compilable/dtoh_AliasDeclaration_98.d
index 1499d04..12edbd2 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_AliasDeclaration_98.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_AliasDeclaration_98.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_AnonDeclaration.d b/gcc/testsuite/gdc.test/compilable/dtoh_AnonDeclaration.d
index 9d68631..20134f5 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_AnonDeclaration.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_AnonDeclaration.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_CPPNamespaceDeclaration.d b/gcc/testsuite/gdc.test/compilable/dtoh_CPPNamespaceDeclaration.d
index 6995a67..870387c 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_CPPNamespaceDeclaration.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_CPPNamespaceDeclaration.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_ClassDeclaration.d b/gcc/testsuite/gdc.test/compilable/dtoh_ClassDeclaration.d
index 4f13d2b..de4c7ba 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_ClassDeclaration.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_ClassDeclaration.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_StructDeclaration.d b/gcc/testsuite/gdc.test/compilable/dtoh_StructDeclaration.d
index 4d56c7c..8c7ba9b 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_StructDeclaration.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_StructDeclaration.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_TemplateDeclaration.d b/gcc/testsuite/gdc.test/compilable/dtoh_TemplateDeclaration.d
index e9e57da..35c4ed7 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_TemplateDeclaration.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_TemplateDeclaration.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_UnionDeclaration.d b/gcc/testsuite/gdc.test/compilable/dtoh_UnionDeclaration.d
index b609cc2..48fcf72 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_UnionDeclaration.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_UnionDeclaration.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_VarDeclaration.d b/gcc/testsuite/gdc.test/compilable/dtoh_VarDeclaration.d
index 7356ba3..1faa51e 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_VarDeclaration.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_VarDeclaration.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_cpp98_compat.d b/gcc/testsuite/gdc.test/compilable/dtoh_cpp98_compat.d
index b291cf6..cf1ae48 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_cpp98_compat.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_cpp98_compat.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_enum.d b/gcc/testsuite/gdc.test/compilable/dtoh_enum.d
index 6a0dfd9..8b3e5aa 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_enum.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_enum.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_enum_cpp98.d b/gcc/testsuite/gdc.test/compilable/dtoh_enum_cpp98.d
index 2330d76..6a266d9 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_enum_cpp98.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_enum_cpp98.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_expressions.d b/gcc/testsuite/gdc.test/compilable/dtoh_expressions.d
index 7919c67..b93c47e 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_expressions.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_expressions.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_extern_type.d b/gcc/testsuite/gdc.test/compilable/dtoh_extern_type.d
index 0426a5e..83ac67d 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_extern_type.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_extern_type.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_forwarding.d b/gcc/testsuite/gdc.test/compilable/dtoh_forwarding.d
index 2f5b7df..c9d5bbc 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_forwarding.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_forwarding.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_functions.d b/gcc/testsuite/gdc.test/compilable/dtoh_functions.d
index 1ee6ce6..1feff40 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_functions.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_functions.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_ignored.d b/gcc/testsuite/gdc.test/compilable/dtoh_ignored.d
index d687673..d162a32 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_ignored.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_ignored.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_invalid_identifiers.d b/gcc/testsuite/gdc.test/compilable/dtoh_invalid_identifiers.d
index c7d4c14..b8e8d05 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_invalid_identifiers.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_invalid_identifiers.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_mangling.d b/gcc/testsuite/gdc.test/compilable/dtoh_mangling.d
index 44d0dd5..10967c8 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_mangling.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_mangling.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_names.d b/gcc/testsuite/gdc.test/compilable/dtoh_names.d
index 8a7eb7f..a4b055e 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_names.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_names.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_protection.d b/gcc/testsuite/gdc.test/compilable/dtoh_protection.d
index 2180c41..3fd54c7 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_protection.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_protection.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_required_symbols.d b/gcc/testsuite/gdc.test/compilable/dtoh_required_symbols.d
index d41cb1b..ab53764 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_required_symbols.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_required_symbols.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_special_enum.d b/gcc/testsuite/gdc.test/compilable/dtoh_special_enum.d
index a7c0a0d..37b4507 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_special_enum.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_special_enum.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_unittest_block.d b/gcc/testsuite/gdc.test/compilable/dtoh_unittest_block.d
index ac58d0e..7b2943c 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_unittest_block.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_unittest_block.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_verbose.d b/gcc/testsuite/gdc.test/compilable/dtoh_verbose.d
index 505ffdc..891ff0e 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_verbose.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_verbose.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/test17590.d b/gcc/testsuite/gdc.test/compilable/test17590.d
index 6eec76f..3e00e9f 100644
--- a/gcc/testsuite/gdc.test/compilable/test17590.d
+++ b/gcc/testsuite/gdc.test/compilable/test17590.d
@@ -1,4 +1,4 @@
-// REQUIRED_ARGS: -o-
+// REQUIRED_ARGS: -o- -preview=dip1000
void lazyfun(scope lazy int a) @nogc;
diff --git a/gcc/testsuite/gdc.test/compilable/test20427.d b/gcc/testsuite/gdc.test/compilable/test20427.d
new file mode 100644
index 0000000..074ed12
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test20427.d
@@ -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]); }));
diff --git a/gcc/testsuite/gdc.test/compilable/test23047.d b/gcc/testsuite/gdc.test/compilable/test23047.d
new file mode 100644
index 0000000..e1ac3e7
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23047.d
@@ -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;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23087.d b/gcc/testsuite/gdc.test/compilable/test23087.d
new file mode 100644
index 0000000..6927ddf
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23087.d
@@ -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");
diff --git a/gcc/testsuite/gdc.test/compilable/test23089.d b/gcc/testsuite/gdc.test/compilable/test23089.d
new file mode 100644
index 0000000..1bc2913
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23089.d
@@ -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;
diff --git a/gcc/testsuite/gdc.test/compilable/test23097.d b/gcc/testsuite/gdc.test/compilable/test23097.d
new file mode 100644
index 0000000..092bd77
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23097.d
@@ -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);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23105.d b/gcc/testsuite/gdc.test/compilable/test23105.d
new file mode 100644
index 0000000..8595e37
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23105.d
@@ -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
diff --git a/gcc/testsuite/gdc.test/compilable/test3004.d b/gcc/testsuite/gdc.test/compilable/test3004.d
index baa0cd7..9912b88 100644
--- a/gcc/testsuite/gdc.test/compilable/test3004.d
+++ b/gcc/testsuite/gdc.test/compilable/test3004.d
@@ -1,13 +1,15 @@
// https://issues.dlang.org/show_bug.cgi?id=3004
/*
REQUIRED_ARGS: -ignore -v
-TRANSFORM_OUTPUT: remove_lines("^(predefs|binary|version|config|DFLAG|parse|import|semantic|entry|function object|\s*$)")
+TRANSFORM_OUTPUT: remove_lines("^(predefs|binary|version|config|DFLAG|parse|import|semantic|entry|library|function object|\s*$)")
TEST_OUTPUT:
---
pragma GNU_attribute (__error)
pragma GNU_attribute (__error)
code test3004
function test3004.test
+function core.internal.array.appending._d_arrayappendcTXImpl!(char[], char)._d_arrayappendcTX
+function core.internal.array.utils._d_HookTraceImpl!(char[], _d_arrayappendcTX, "Cannot append to array if compiling without support for runtime type information!")._d_HookTraceImpl
---
*/
diff --git a/gcc/testsuite/gdc.test/compilable/vcg-ast.d b/gcc/testsuite/gdc.test/compilable/vcg-ast.d
index 4673677..cbb150c 100644
--- a/gcc/testsuite/gdc.test/compilable/vcg-ast.d
+++ b/gcc/testsuite/gdc.test/compilable/vcg-ast.d
@@ -52,8 +52,7 @@ alias wchar_t = __c_wchar_t;
T[] values(T)()
{
- T[] values;
- values ~= T();
+ T[] values = [T()];
return values;
}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic.d b/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic.d
new file mode 100644
index 0000000..1fdf5a5
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic.d
@@ -0,0 +1,23 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/attributediagnostic.d(16): Error: `@safe` function `attributediagnostic.layer2` cannot call `@system` function `attributediagnostic.layer1`
+fail_compilation/attributediagnostic.d(18): which calls `attributediagnostic.layer0`
+fail_compilation/attributediagnostic.d(20): which calls `attributediagnostic.system`
+fail_compilation/attributediagnostic.d(22): which was inferred `@system` because of:
+fail_compilation/attributediagnostic.d(22): `asm` statement is assumed to be `@system` - mark it with `@trusted` if it is not
+fail_compilation/attributediagnostic.d(17): `attributediagnostic.layer1` is declared here
+---
+*/
+
+// Issue 17374 - Improve inferred attribute error message
+// https://issues.dlang.org/show_bug.cgi?id=17374
+
+auto layer2() @safe { layer1(); }
+auto layer1() { layer0(); }
+auto layer0() { system(); }
+
+auto system()
+{
+ asm {}
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/b6227.d b/gcc/testsuite/gdc.test/fail_compilation/b6227.d
index a9b2a50..c975a43 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/b6227.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/b6227.d
@@ -1,8 +1,8 @@
/* TEST_OUTPUT:
---
-fail_compilation/b6227.d(16): Error: Comparison between different enumeration types `X` and `Y`; If this behavior is intended consider using `std.conv.asOriginalType`
+fail_compilation/b6227.d(16): Error: comparison between different enumeration types `X` and `Y`; If this behavior is intended consider using `std.conv.asOriginalType`
fail_compilation/b6227.d(16): while evaluating: `static assert(!(X.O != Y.U))`
-fail_compilation/b6227.d(17): Error: Comparison between different enumeration types `X` and `Y`; If this behavior is intended consider using `std.conv.asOriginalType`
+fail_compilation/b6227.d(17): Error: comparison between different enumeration types `X` and `Y`; If this behavior is intended consider using `std.conv.asOriginalType`
fail_compilation/b6227.d(17): while evaluating: `static assert(X.O == Y.U)`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/betterc.d b/gcc/testsuite/gdc.test/fail_compilation/betterc.d
index e1cc4cf..6f4fb03 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/betterc.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/betterc.d
@@ -1,8 +1,8 @@
/* REQUIRED_ARGS: -betterC
* TEST_OUTPUT:
---
-fail_compilation/betterc.d(12): Error: Cannot use `throw` statements with -betterC
-fail_compilation/betterc.d(17): Error: Cannot use try-catch statements with -betterC
+fail_compilation/betterc.d(12): Error: cannot use `throw` statements with -betterC
+fail_compilation/betterc.d(17): Error: cannot use try-catch statements with -betterC
fail_compilation/betterc.d(29): Error: `TypeInfo` cannot be used with -betterC
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/biterrors.d b/gcc/testsuite/gdc.test/fail_compilation/biterrors.d
new file mode 100644
index 0000000..a8f0faa
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/biterrors.d
@@ -0,0 +1,15 @@
+/* REQUIRED_ARGS: -preview=bitfields
+ * TEST_OUTPUT:
+---
+fail_compilation/biterrors.d(103): Error: initializer not allowed for bit-field declaration
+fail_compilation/biterrors.d(104): Error: storage class not allowed for bit-field declaration
+---
+ */
+
+#line 100
+
+struct S
+{
+ int i : 3 = 7;
+ static int j : 3;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/biterrors2.d b/gcc/testsuite/gdc.test/fail_compilation/biterrors2.d
new file mode 100644
index 0000000..c8390ba
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/biterrors2.d
@@ -0,0 +1,17 @@
+/* REQUIRED_ARGS: -preview=bitfields
+ * TEST_OUTPUT:
+---
+fail_compilation/biterrors2.d(100): Error: variable `biterrors2.a` bit-field must be member of struct, union, or class
+fail_compilation/biterrors2.d(104): Error: bit-field `b` has zero width
+fail_compilation/biterrors2.d(105): Error: bit-field type `float` is not an integer type
+---
+*/
+
+#line 100
+int a : 2;
+
+struct S
+{
+ int b:0;
+ float c:3;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/biterrors3.d b/gcc/testsuite/gdc.test/fail_compilation/biterrors3.d
new file mode 100644
index 0000000..f9e1df2
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/biterrors3.d
@@ -0,0 +1,18 @@
+/* REQUIRED_ARGS: -preview=bitfields
+ * TEST_OUTPUT:
+---
+fail_compilation/biterrors3.d(103): Error: storage class not allowed for bit-field declaration
+fail_compilation/biterrors3.d(106): Error: `d` is not a valid attribute for enum members
+fail_compilation/biterrors3.d(106): Error: `:` is not a valid attribute for enum members
+fail_compilation/biterrors3.d(106): Error: `3` is not a valid attribute for enum members
+---
+*/
+
+#line 100
+
+struct S
+{
+ static int : 3;
+}
+
+enum E { d : 3 }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/biterrors4.d b/gcc/testsuite/gdc.test/fail_compilation/biterrors4.d
new file mode 100644
index 0000000..0f2ca2d
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/biterrors4.d
@@ -0,0 +1,19 @@
+/* REQUIRED_ARGS: -preview=bitfields
+ * TEST_OUTPUT:
+---
+fail_compilation/biterrors4.d(109): Error: cannot take address of bit-field `a`
+---
+*/
+
+#line 100
+
+struct S
+{
+ int a:3;
+}
+
+void test()
+{
+ S s;
+ int* p = &s.a;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/commaexp.d b/gcc/testsuite/gdc.test/fail_compilation/commaexp.d
index 7d50223..3874fb1 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/commaexp.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/commaexp.d
@@ -1,16 +1,16 @@
/* REQUIRED_ARGS: -o-
TEST_OUTPUT:
---
-fail_compilation/commaexp.d(27): Error: Using the result of a comma expression is not allowed
-fail_compilation/commaexp.d(39): Error: Using the result of a comma expression is not allowed
-fail_compilation/commaexp.d(40): Error: Using the result of a comma expression is not allowed
-fail_compilation/commaexp.d(41): Error: Using the result of a comma expression is not allowed
-fail_compilation/commaexp.d(42): Error: Using the result of a comma expression is not allowed
-fail_compilation/commaexp.d(44): Error: Using the result of a comma expression is not allowed
-fail_compilation/commaexp.d(45): Error: Using the result of a comma expression is not allowed
-fail_compilation/commaexp.d(56): Error: Using the result of a comma expression is not allowed
-fail_compilation/commaexp.d(69): Error: Using the result of a comma expression is not allowed
-fail_compilation/commaexp.d(81): Error: Using the result of a comma expression is not allowed
+fail_compilation/commaexp.d(27): Error: using the result of a comma expression is not allowed
+fail_compilation/commaexp.d(39): Error: using the result of a comma expression is not allowed
+fail_compilation/commaexp.d(40): Error: using the result of a comma expression is not allowed
+fail_compilation/commaexp.d(41): Error: using the result of a comma expression is not allowed
+fail_compilation/commaexp.d(42): Error: using the result of a comma expression is not allowed
+fail_compilation/commaexp.d(44): Error: using the result of a comma expression is not allowed
+fail_compilation/commaexp.d(45): Error: using the result of a comma expression is not allowed
+fail_compilation/commaexp.d(56): Error: using the result of a comma expression is not allowed
+fail_compilation/commaexp.d(69): Error: using the result of a comma expression is not allowed
+fail_compilation/commaexp.d(81): Error: using the result of a comma expression is not allowed
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/cppvar.d b/gcc/testsuite/gdc.test/fail_compilation/cppvar.d
new file mode 100644
index 0000000..885a555
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/cppvar.d
@@ -0,0 +1,22 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/cppvar.d(10): Error: variable `cppvar.funcLiteral` cannot have `extern(C++)` linkage because it is `static`
+fail_compilation/cppvar.d(10): perhaps declare it as `__gshared` instead
+fail_compilation/cppvar.d(20): Error: variable `cppvar.threadLocalVar` cannot have `extern(C++)` linkage because it is `static`
+fail_compilation/cppvar.d(20): perhaps declare it as `__gshared` instead
+fail_compilation/cppvar.d(21): Error: variable `cppvar.staticVar` cannot have `extern(C++)` linkage because it is `static`
+fail_compilation/cppvar.d(21): perhaps declare it as `__gshared` instead
+fail_compilation/cppvar.d(22): Error: variable `cppvar.sharedVar` cannot have `extern(C++)` linkage because it is `shared`
+fail_compilation/cppvar.d(22): perhaps declare it as `__gshared` instead
+fail_compilation/cppvar.d(30): Error: delegate `cppvar.__lambda7` cannot return type `bool[3]` because its linkage is `extern(C++)`
+---
+*/
+#line 10
+extern(C++) bool[3] funcLiteral = () { bool[3] a; return a; };
+#line 20
+extern(C++) int threadLocalVar;
+extern(C++) static int staticVar;
+extern(C++) shared int sharedVar;
+#line 30
+extern(C++) __gshared bool[3] gfuncLiteral = () { bool[3] a; return a; };
diff --git a/gcc/testsuite/gdc.test/fail_compilation/dbitfields.d b/gcc/testsuite/gdc.test/fail_compilation/dbitfields.d
new file mode 100644
index 0000000..0dd1a0b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/dbitfields.d
@@ -0,0 +1,32 @@
+/* REQUIRED_ARGS: -preview=bitfields
+ * TEST_OUTPUT:
+---
+fail_compilation/dbitfields.d(118): Error: reinterpretation through overlapped field `e` is not allowed in CTFE
+fail_compilation/dbitfields.d(121): called from here: `testu()`
+fail_compilation/dbitfields.d(121): while evaluating: `static assert(testu() == 1)`
+---
+ */
+
+#line 100
+
+union U
+{
+ uint a:3;
+ uint b:1;
+ ulong c:64;
+
+ int d:3;
+ int e:1;
+ long f:64;
+
+ int i;
+}
+
+int testu()
+{
+ U u;
+ u.d = 9;
+ return u.e;
+}
+
+static assert(testu() == 1);
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10805.d b/gcc/testsuite/gdc.test/fail_compilation/diag10805.d
index ed38167..932aa5c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag10805.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag10805.d
@@ -3,7 +3,7 @@ TEST_OUTPUT:
---
fail_compilation/diag10805.d(12): Error: delimited string must end in `FOO"`
fail_compilation/diag10805.d(14): Error: unterminated string constant starting at fail_compilation/diag10805.d(14)
-fail_compilation/diag10805.d(14): Error: Implicit string concatenation is error-prone and disallowed in D
+fail_compilation/diag10805.d(14): Error: implicit string concatenation is error-prone and disallowed in D
fail_compilation/diag10805.d(14): Use the explicit syntax instead (concatenating literals is `@nogc`): "" ~ ""
fail_compilation/diag10805.d(15): Error: semicolon expected following auto declaration, not `End of File`
---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10862.d b/gcc/testsuite/gdc.test/fail_compilation/diag10862.d
index 00949f1..3e15497 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag10862.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag10862.d
@@ -24,7 +24,7 @@ fail_compilation/diag10862.d(74): Error: assignment cannot be used as a conditio
fail_compilation/diag10862.d-mixin-77(77): Error: assignment cannot be used as a condition, perhaps `==` was meant?
fail_compilation/diag10862.d-mixin-78(78): Error: assignment cannot be used as a condition, perhaps `==` was meant?
fail_compilation/diag10862.d-mixin-79(79): Error: assignment cannot be used as a condition, perhaps `==` was meant?
-fail_compilation/diag10862.d-mixin-80(80): Error: Using the result of a comma expression is not allowed
+fail_compilation/diag10862.d-mixin-80(80): Error: using the result of a comma expression is not allowed
fail_compilation/diag10862.d-mixin-80(80): Error: assignment cannot be used as a condition, perhaps `==` was meant?
fail_compilation/diag10862.d-mixin-83(83): Error: `a + b` is not an lvalue and cannot be modified
fail_compilation/diag10862.d-mixin-84(84): Error: undefined identifier `c`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/dip25.d b/gcc/testsuite/gdc.test/fail_compilation/dip25.d
index 4f8ea23..41bfe49 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/dip25.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/dip25.d
@@ -12,15 +12,15 @@ fail_compilation/dip25.d(23): perhaps annotate the parameter with `return
struct Data
{
char[256] buffer;
- @property const(char)[] filename() const pure nothrow
+ @property const(char)[] filename() const pure nothrow @safe
{
return buffer[];
}
}
-ref int identity(return ref int x) { return x; }
+ref int identity(return ref int x) @safe { return x; }
ref int fun(return int x) { return identity(x); }
-ref int fun2(ref int x) { return identity(x); }
+ref int fun2(ref int x) @safe { return identity(x); }
void main()
{
diff --git a/gcc/testsuite/gdc.test/fail_compilation/dtor_attributes.d b/gcc/testsuite/gdc.test/fail_compilation/dtor_attributes.d
index 21a12ed..ce81d6b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/dtor_attributes.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/dtor_attributes.d
@@ -8,6 +8,8 @@ fail_compilation/dtor_attributes.d(113): generated `Strict.~this` is impu
fail_compilation/dtor_attributes.d(111): - HasDtor member
fail_compilation/dtor_attributes.d(103): impure `HasDtor.~this` is declared here
fail_compilation/dtor_attributes.d(118): Error: `@safe` function `dtor_attributes.test1` cannot call `@system` destructor `dtor_attributes.Strict.~this`
+fail_compilation/dtor_attributes.d(113): which calls `dtor_attributes.Strict.~this`
+fail_compilation/dtor_attributes.d(103): which calls `dtor_attributes.HasDtor.~this`
fail_compilation/dtor_attributes.d(113): `dtor_attributes.Strict.~this` is declared here
fail_compilation/dtor_attributes.d(113): generated `Strict.~this` is @system because of the following field's destructors:
fail_compilation/dtor_attributes.d(111): - HasDtor member
diff --git a/gcc/testsuite/gdc.test/fail_compilation/dtorfields_attributes.d b/gcc/testsuite/gdc.test/fail_compilation/dtorfields_attributes.d
index f6cab89..45b23ce 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/dtorfields_attributes.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/dtorfields_attributes.d
@@ -9,6 +9,7 @@ fail_compilation/dtorfields_attributes.d(119): generated `Strict.~this` i
fail_compilation/dtorfields_attributes.d(115): - HasDtor member
fail_compilation/dtorfields_attributes.d(103): impure `HasDtor.~this` is declared here
fail_compilation/dtorfields_attributes.d(117): Error: `@safe` constructor `dtorfields_attributes.Strict.this` cannot call `@system` destructor `dtorfields_attributes.Strict.~this`
+fail_compilation/dtorfields_attributes.d(103): which calls `dtorfields_attributes.HasDtor.~this`
fail_compilation/dtorfields_attributes.d(119): `dtorfields_attributes.Strict.~this` is declared here
fail_compilation/dtorfields_attributes.d(119): generated `Strict.~this` is @system because of the following field's destructors:
fail_compilation/dtorfields_attributes.d(115): - HasDtor member
diff --git a/gcc/testsuite/gdc.test/fail_compilation/e7804_1.d b/gcc/testsuite/gdc.test/fail_compilation/e7804_1.d
index 38c25fb..1dfcf44 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/e7804_1.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/e7804_1.d
@@ -1,11 +1,18 @@
/*
TEST_OUTPUT:
---
-fail_compilation/e7804_1.d(10): Error: trait `farfelu` is either invalid or not supported as type
-fail_compilation/e7804_1.d(11): Error: trait `farfelu` is either invalid or not supported in alias
+fail_compilation/e7804_1.d(14): Error: undefined identifier `Aggr`
+fail_compilation/e7804_1.d(15): Error: unrecognized trait `farfelu`
+fail_compilation/e7804_1.d(17): Error: undefined identifier `Aggr`
+fail_compilation/e7804_1.d(18): Error: unrecognized trait `farfelu`
---
*/
module e7804_1;
+struct S {}
+
__traits(farfelu, Aggr, "member") a;
+__traits(farfelu, S, "member") a2;
+
alias foo = __traits(farfelu, Aggr, "member");
+alias foo2 = __traits(farfelu, S, "member");
diff --git a/gcc/testsuite/gdc.test/fail_compilation/extra-files/test23109/object.d b/gcc/testsuite/gdc.test/fail_compilation/extra-files/test23109/object.d
new file mode 100644
index 0000000..747b6e9
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/extra-files/test23109/object.d
@@ -0,0 +1,17 @@
+module object;
+
+alias size_t = typeof(int.sizeof);
+class Object {}
+auto opEquals(Object ) { return true; }
+class TypeInfo {}
+class TypeInfo_Const {}
+bool _xopEquals() { return true; }
+
+bool __equals(T1, T2)(T1[] lhs, T2[] rhs)
+{
+ static at(R)(R[] r, size_t i) { return r.ptr[i]; }
+ foreach (u; 0 .. lhs.length)
+ if (at(lhs, u) != at(rhs, u))
+ return false;
+ return true;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail109.d b/gcc/testsuite/gdc.test/fail_compilation/fail109.d
index 3419079..7caae59 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail109.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail109.d
@@ -34,7 +34,7 @@ enum E1 : short
/* https://issues.dlang.org/show_bug.cgi?id=14950
TEST_OUTPUT:
---
-fail_compilation/fail109.d(50): Error: Comparison between different enumeration types `B` and `C`; If this behavior is intended consider using `std.conv.asOriginalType`
+fail_compilation/fail109.d(50): Error: comparison between different enumeration types `B` and `C`; If this behavior is intended consider using `std.conv.asOriginalType`
fail_compilation/fail109.d(50): Error: enum member `fail109.B.end` initialization with `B.start+1` causes overflow for type `C`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail12604.d b/gcc/testsuite/gdc.test/fail_compilation/fail12604.d
index 2ed8ebf..bed8735 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail12604.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail12604.d
@@ -66,8 +66,8 @@ void test12606b() // ExpInitializer::semantic
/*
TEST_OUTPUT:
---
-fail_compilation/fail12604.d(77): Error: mismatched array lengths, 4 and 3
-fail_compilation/fail12604.d(78): Error: mismatched array lengths, 4 and 3
+fail_compilation/fail12604.d(77): Error: mismatched array lengths 4 and 3 for assignment `sa1[0..4] = [1, 2, 3]`
+fail_compilation/fail12604.d(78): Error: mismatched array lengths 4 and 3 for assignment `sa1[0..4] = sa2`
---
*/
void testc()
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail13902.d b/gcc/testsuite/gdc.test/fail_compilation/fail13902.d
index 12a6b6e..47cb65c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail13902.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail13902.d
@@ -8,11 +8,11 @@ class C { int v; }
/*
TEST_OUTPUT:
---
-fail_compilation/fail13902.d(45): Error: Using the result of a comma expression is not allowed
+fail_compilation/fail13902.d(45): Error: using the result of a comma expression is not allowed
fail_compilation/fail13902.d(32): Error: returning `& x` escapes a reference to local variable `x`
fail_compilation/fail13902.d(33): Error: returning `&s1.v` escapes a reference to local variable `s1`
fail_compilation/fail13902.d(38): Error: returning `& sa1` escapes a reference to local variable `sa1`
-fail_compilation/fail13902.d(39): Error: returning `&sa2[0][0]` escapes a reference to local variable `sa2`
+fail_compilation/fail13902.d(39): Error: returning `& sa2` escapes a reference to local variable `sa2`
fail_compilation/fail13902.d(40): Error: returning `& x` escapes a reference to local variable `x`
fail_compilation/fail13902.d(41): Error: returning `(& x+4)` escapes a reference to local variable `x`
fail_compilation/fail13902.d(42): Error: returning `& x + cast(long)x * 4L` escapes a reference to local variable `x`
@@ -53,11 +53,11 @@ int* testEscape1()
/*
TEST_OUTPUT:
---
-fail_compilation/fail13902.d(88): Error: Using the result of a comma expression is not allowed
+fail_compilation/fail13902.d(88): Error: using the result of a comma expression is not allowed
fail_compilation/fail13902.d(75): Error: returning `& x` escapes a reference to parameter `x`
fail_compilation/fail13902.d(76): Error: returning `&s1.v` escapes a reference to parameter `s1`
fail_compilation/fail13902.d(81): Error: returning `& sa1` escapes a reference to parameter `sa1`
-fail_compilation/fail13902.d(82): Error: returning `&sa2[0][0]` escapes a reference to parameter `sa2`
+fail_compilation/fail13902.d(82): Error: returning `& sa2` escapes a reference to parameter `sa2`
fail_compilation/fail13902.d(83): Error: returning `& x` escapes a reference to parameter `x`
fail_compilation/fail13902.d(84): Error: returning `(& x+4)` escapes a reference to parameter `x`
fail_compilation/fail13902.d(85): Error: returning `& x + cast(long)x * 4L` escapes a reference to parameter `x`
@@ -98,7 +98,7 @@ int* testEscape2(
/*
TEST_OUTPUT:
---
-fail_compilation/fail13902.d(123): Error: Using the result of a comma expression is not allowed
+fail_compilation/fail13902.d(123): Error: using the result of a comma expression is not allowed
---
*/
int* testEscape3(
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail16001.d b/gcc/testsuite/gdc.test/fail_compilation/fail16001.d
index dc480cf..9d0b96f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail16001.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail16001.d
@@ -2,7 +2,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail16001.d(10): Deprecation: Using `(args) => { ... }` to create a delegate that returns a delegate is error-prone.
+fail_compilation/fail16001.d(10): Deprecation: using `(args) => { ... }` to create a delegate that returns a delegate is error-prone.
fail_compilation/fail16001.d(10): Use `(args) { ... }` for a multi-statement function literal or use `(args) => () { }` if you intended for the lambda to return a delegate.
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail16575.d b/gcc/testsuite/gdc.test/fail_compilation/fail16575.d
new file mode 100644
index 0000000..7f66724
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail16575.d
@@ -0,0 +1,65 @@
+// https://issues.dlang.org/show_bug.cgi?id=16575
+/*
+REQUIRED_ARGS: -m64
+TEST_OUTPUT:
+---
+fail_compilation/fail16575.d(10): Error: function `fail16575.immNull` cannot have parameter of type `immutable(typeof(null))*` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(11): Error: function `fail16575.shaNull` cannot have parameter of type `shared(typeof(null))*` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(20): Error: function `fail16575.immNoReturn` cannot have parameter of type `immutable(noreturn)*` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(21): Error: function `fail16575.shaNoReturn` cannot have parameter of type `shared(noreturn)*` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(30): Error: function `fail16575.immBasic` cannot have parameter of type `immutable(int)*` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(31): Error: function `fail16575.shaBasic` cannot have parameter of type `shared(int)*` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(40): Error: function `fail16575.immVector` cannot have parameter of type `immutable(__vector(long[2]))*` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(41): Error: function `fail16575.shaVector` cannot have parameter of type `shared(__vector(long[2]))*` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(50): Error: function `fail16575.immSArray` cannot have parameter of type `immutable(long[2])` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(50): perhaps use a `long*` type instead
+fail_compilation/fail16575.d(51): Error: function `fail16575.shaSArray` cannot have parameter of type `shared(long[2])` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(51): perhaps use a `long*` type instead
+fail_compilation/fail16575.d(60): Error: function `fail16575.immPointer` cannot have parameter of type `immutable(int*)` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(61): Error: function `fail16575.shaPointer` cannot have parameter of type `shared(int*)` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(71): Error: function `fail16575.immStruct` cannot have parameter of type `immutable(SPP)*` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(72): Error: function `fail16575.shaStruct` cannot have parameter of type `shared(SPP)*` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(81): Error: function `fail16575.immClass` cannot have parameter of type `immutable(CPP)` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(82): Error: function `fail16575.shaClass` cannot have parameter of type `shared(CPP)` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(91): Error: function `fail16575.immEnum` cannot have parameter of type `immutable(EPP)*` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(92): Error: function `fail16575.shaEnum` cannot have parameter of type `shared(EPP)*` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(100): Error: function `fail16575.typeDArray` cannot have parameter of type `int[]` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(101): Error: function `fail16575.typeAArray` cannot have parameter of type `int[int]` because its linkage is `extern(C++)`
+fail_compilation/fail16575.d(102): Error: function `fail16575.typeDelegate` cannot have parameter of type `extern (C++) int delegate()` because its linkage is `extern(C++)`
+---
+*/
+
+#line 10
+extern(C++) void immNull(immutable(typeof(null))* a) {}
+extern(C++) void shaNull(shared(typeof(null))* a) {}
+#line 20
+extern(C++) void immNoReturn(immutable(typeof(*null))* a) {}
+extern(C++) void shaNoReturn(shared(typeof(*null))* a) {}
+#line 30
+extern(C++) void immBasic(immutable(int)* a) {}
+extern(C++) void shaBasic(shared(int)* a) {}
+#line 40
+extern(C++) void immVector(immutable(__vector(long[2]))* a) {}
+extern(C++) void shaVector(shared(__vector(long[2]))* a) {}
+#line 50
+extern(C++) void immSArray(immutable(long[2]) a) {}
+extern(C++) void shaSArray(shared(long[2]) a) {}
+#line 60
+extern(C++) void immPointer(immutable(int*) a) {}
+extern(C++) void shaPointer(shared(int*) a) {}
+#line 70
+extern(C++) struct SPP {}
+extern(C++) void immStruct(immutable(SPP)* a) {}
+extern(C++) void shaStruct(shared(SPP)* a) {}
+#line 80
+extern(C++) class CPP {}
+extern(C++) void immClass(immutable CPP a) {}
+extern(C++) void shaClass(shared CPP a) {}
+#line 90
+extern(C++) enum EPP {a}
+extern(C++) void immEnum(immutable(EPP)* a) {}
+extern(C++) void shaEnum(shared(EPP)* a) {}
+# line 100
+extern(C++) void typeDArray(int[] a) {}
+extern(C++) void typeAArray(int[int] a) {}
+extern(C++) void typeDelegate(int delegate() a) {}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail16772.d b/gcc/testsuite/gdc.test/fail_compilation/fail16772.d
new file mode 100644
index 0000000..e77951d3
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail16772.d
@@ -0,0 +1,7 @@
+// https://issues.dlang.org/show_bug.cgi?id=16772
+/* TEST_OUTPUT:
+---
+fail_compilation/fail16772.d(7): Error: function `fail16772.ice16772` cannot return type `ubyte[]` because its linkage is `extern(C++)`
+---
+*/
+extern(C++) ubyte[] ice16772() { return []; }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail196.d b/gcc/testsuite/gdc.test/fail_compilation/fail196.d
index 55c3bd8..2c7d93f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail196.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail196.d
@@ -2,7 +2,7 @@
TEST_OUTPUT:
---
fail_compilation/fail196.d(27): Error: delimited string must end in `)"`
-fail_compilation/fail196.d(27): Error: Implicit string concatenation is error-prone and disallowed in D
+fail_compilation/fail196.d(27): Error: implicit string concatenation is error-prone and disallowed in D
fail_compilation/fail196.d(27): Use the explicit syntax instead (concatenating literals is `@nogc`): "foo(xxx)" ~ ";\n assert(s == "
fail_compilation/fail196.d(28): Error: semicolon needed to end declaration of `s`, instead of `foo`
fail_compilation/fail196.d(27): `s` declared here
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19759.d b/gcc/testsuite/gdc.test/fail_compilation/fail19759.d
new file mode 100644
index 0000000..cdb65ae
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19759.d
@@ -0,0 +1,8 @@
+// https://issues.dlang.org/show_bug.cgi?id=19759
+/* TEST_OUTPUT:
+---
+fail_compilation/fail19759.d(8): Error: function `fail19759.fail19759` cannot have parameter of type `float[4]` because its linkage is `extern(C++)`
+fail_compilation/fail19759.d(8): perhaps use a `float*` type instead
+---
+*/
+extern(C++) bool fail19759(float[4] col);
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19881.d b/gcc/testsuite/gdc.test/fail_compilation/fail19881.d
index f4a4d76..62f3dc4 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail19881.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19881.d
@@ -1,7 +1,8 @@
/* REQUIRED_ARGS: -preview=dip1000
* TEST_OUTPUT:
---
-fail_compilation/fail19881.d(12): Error: address of local variable `local` assigned to return scope `input`
+fail_compilation/fail19881.d(13): Error: address of local variable `local` assigned to return scope `input`
+fail_compilation/fail19881.d(13): Error: address of variable `local` assigned to `input` with longer lifetime
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail20691.d b/gcc/testsuite/gdc.test/fail_compilation/fail20691.d
index 7a43232..54e36fc 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail20691.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail20691.d
@@ -1,12 +1,9 @@
/* REQUIRED_ARGS: -preview=dip1000
TEST_OUTPUT:
---
-fail_compilation/fail20691.d(106): Error: cannot take address of `scope` local `sa` in `@safe` function `bar`
-fail_compilation/fail20691.d(106): Error: cannot cast expression `sa` of type `char[][2]` to `char[][]`
-fail_compilation/fail20691.d(107): Error: cannot take address of `scope` local `sa` in `@safe` function `bar`
-fail_compilation/fail20691.d(107): Error: cannot cast expression `sa` of type `char[][2]` to `char[][]`
-fail_compilation/fail20691.d(108): Error: cannot take address of `scope` local `sa` in `@safe` function `bar`
-fail_compilation/fail20691.d(108): Error: cannot cast expression `sa` of type `char[][2]` to `char[][]`
+fail_compilation/fail20691.d(106): Error: cannot take address of `scope` variable `sa` since `scope` applies to first indirection only
+fail_compilation/fail20691.d(107): Error: cannot take address of `scope` variable `sa` since `scope` applies to first indirection only
+fail_compilation/fail20691.d(108): Error: cannot take address of `scope` variable `sa` since `scope` applies to first indirection only
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21092.d b/gcc/testsuite/gdc.test/fail_compilation/fail21092.d
index 2ca826e..d12b387 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail21092.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail21092.d
@@ -3,10 +3,10 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail21092.d(19): Error: Using the result of a comma expression is not allowed
+fail_compilation/fail21092.d(19): Error: using the result of a comma expression is not allowed
fail_compilation/fail21092.d(19): Error: using `*` on an array is no longer supported; use `*(T , U).ptr` instead
fail_compilation/fail21092.d(19): Error: `*(T , cast(real*)U)` has no effect
-fail_compilation/fail21092.d(26): Error: Using the result of a comma expression is not allowed
+fail_compilation/fail21092.d(26): Error: using the result of a comma expression is not allowed
fail_compilation/fail21092.d(26): Error: using `*` on an array is no longer supported; use `*(w , SmallStirlingCoeffs).ptr` instead
fail_compilation/fail21092.d(26): Error: `*(w , cast(real*)SmallStirlingCoeffs)` has no effect
---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21206.d b/gcc/testsuite/gdc.test/fail_compilation/fail21206.d
new file mode 100644
index 0000000..c3d648e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail21206.d
@@ -0,0 +1,13 @@
+// https://issues.dlang.org/show_bug.cgi?id=21206
+/* TEST_OUTPUT:
+---
+fail_compilation/fail21206.d(9): Error: function `fail21206.Obj.toString` cannot return type `string` because its linkage is `extern(C++)`
+---
+*/
+extern(C++) struct Obj
+{
+ string toString()
+ {
+ return "ret";
+ }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21275.d b/gcc/testsuite/gdc.test/fail_compilation/fail21275.d
index dbdedb3..69cdf1a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail21275.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail21275.d
@@ -5,8 +5,8 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail21275.d(18): Deprecation: Function `imports.fail21275a.Foo.x` of type `ref int() return` is not accessible from module `fail21275`
-fail_compilation/fail21275.d(21): Deprecation: Function `imports.fail21275a.Bar.x` of type `int(int)` is not accessible from module `fail21275`
+fail_compilation/fail21275.d(18): Deprecation: function `imports.fail21275a.Foo.x` of type `ref int() return` is not accessible from module `fail21275`
+fail_compilation/fail21275.d(21): Deprecation: function `imports.fail21275a.Bar.x` of type `int(int)` is not accessible from module `fail21275`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21314.d b/gcc/testsuite/gdc.test/fail_compilation/fail21314.d
new file mode 100644
index 0000000..78e52ce
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail21314.d
@@ -0,0 +1,11 @@
+// https://issues.dlang.org/show_bug.cgi?id=21314
+/* TEST_OUTPUT:
+---
+fail_compilation/fail21314.d(10): Error: variable `fail21314.C21314.c21314` cannot have `extern(C++)` linkage because it is `static`
+fail_compilation/fail21314.d(10): perhaps declare it as `__gshared` instead
+---
+*/
+extern(C++) class C21314
+{
+ static C21314[] c21314;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21868b.d b/gcc/testsuite/gdc.test/fail_compilation/fail21868b.d
index 687a727..0df31d7 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail21868b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail21868b.d
@@ -14,7 +14,7 @@ struct S
int* y;
}
-int* test(ref return scope S s)
+int* test(ref return scope S s) @safe
{
return &s.x;
}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail23108a.d b/gcc/testsuite/gdc.test/fail_compilation/fail23108a.d
new file mode 100644
index 0000000..a974871
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail23108a.d
@@ -0,0 +1,16 @@
+// https://issues.dlang.org/show_bug.cgi?id=23108
+/* TEST_OUTPUT:
+---
+fail_compilation/fail23108a.d(9): Error: undefined identifier `_xopEquals` in module `object`
+---
+*/
+module object;
+
+struct Interface
+{
+ void[] vtbl;
+}
+
+class TypeInfo
+{
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail23108b.d b/gcc/testsuite/gdc.test/fail_compilation/fail23108b.d
new file mode 100644
index 0000000..10eae37
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail23108b.d
@@ -0,0 +1,18 @@
+// https://issues.dlang.org/show_bug.cgi?id=23108
+/* TEST_OUTPUT:
+---
+fail_compilation/fail23108b.d(10): Error: undefined identifier `_xopEquals` in module `object`
+fail_compilation/fail23108b.d(10): Error: undefined identifier `_xopCmp` in module `object`
+---
+*/
+module object;
+
+struct Interface
+{
+ void[] vtbl;
+ int opCmp() { return 0; }
+}
+
+class TypeInfo
+{
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail23109.d b/gcc/testsuite/gdc.test/fail_compilation/fail23109.d
new file mode 100644
index 0000000..91b4e79
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail23109.d
@@ -0,0 +1,12 @@
+// https://issues.dlang.org/show_bug.cgi?id=23109
+/*
+EXTRA_FILES: imports/test23109a.d imports/test23109b.d imports/test23109c.d
+EXTRA_SOURCES: extra-files/test23109/object.d
+TEST_OUTPUT:
+---
+Error: no property `getHash` for type `object.TypeInfo_Const`
+Error: no property `getHash` for type `object.TypeInfo_Const`
+fail_compilation/imports/test23109a.d(10): Error: template instance `imports.test23109a.Array!(Ensure)` error instantiating
+---
+*/
+import imports.test23109a;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail3703.d b/gcc/testsuite/gdc.test/fail_compilation/fail3703.d
index 6b4edd5..d2d277f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail3703.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail3703.d
@@ -3,8 +3,8 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail3703.d(18): Error: mismatched array lengths, 2 and 1
-fail_compilation/fail3703.d(20): Error: mismatched array lengths, 2 and 1
+fail_compilation/fail3703.d(18): Error: mismatched array lengths 2 and 1 for assignment `b[] = a`
+fail_compilation/fail3703.d(20): Error: mismatched array lengths 2 and 1 for assignment `b[] = a`
fail_compilation/fail3703.d(22): Error: mismatched array lengths, 3 and 2
fail_compilation/fail3703.d(23): Error: mismatched array lengths, 2 and 3
fail_compilation/fail3703.d(25): Error: mismatched array lengths, 3 and 2
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d b/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d
index 07c3766..153e90b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d
@@ -2,39 +2,40 @@
REQUIRED_ARGS:
TEST_OUTPUT:
---
-fail_compilation/fail_scope.d(29): Deprecation: scope variable `da` may not be returned
-fail_compilation/fail_scope.d(31): Deprecation: scope variable `o` may not be returned
-fail_compilation/fail_scope.d(32): Deprecation: scope variable `dg` may not be returned
-fail_compilation/fail_scope.d(34): Deprecation: scope variable `da` may not be returned
-fail_compilation/fail_scope.d(36): Deprecation: scope variable `o` may not be returned
-fail_compilation/fail_scope.d(37): Deprecation: scope variable `dg` may not be returned
-fail_compilation/fail_scope.d(39): Deprecation: scope variable `p` may not be returned
-fail_compilation/fail_scope.d(44): Error: returning `cast(char[])string` escapes a reference to local variable `string`
-fail_compilation/fail_scope.d(62): Error: returning `s.bar()` escapes a reference to local variable `s`
-fail_compilation/fail_scope.d(73): Error: `fail_scope.foo8` called with argument types `(int)` matches both:
-fail_compilation/fail_scope.d(67): `fail_scope.foo8(ref int x)`
+fail_compilation/fail_scope.d(40): Deprecation: scope variable `p` may not be returned
+fail_compilation/fail_scope.d(45): Error: returning `cast(char[])string` escapes a reference to local variable `string`
+fail_compilation/fail_scope.d(63): Error: returning `s.bar()` escapes a reference to local variable `s`
+fail_compilation/fail_scope.d(74): Error: `fail_scope.foo8` called with argument types `(int)` matches both:
+fail_compilation/fail_scope.d(68): `fail_scope.foo8(ref int x)`
and:
-fail_compilation/fail_scope.d(68): `fail_scope.foo8(return ref int x)`
-fail_compilation/fail_scope.d(81): Error: returning `& string` escapes a reference to local variable `string`
-fail_compilation/fail_scope.d(91): Error: returning `cast(int[])a` escapes a reference to local variable `a`
-fail_compilation/fail_scope.d(99): Error: returning `cast(int[])a` escapes a reference to local variable `a`
-fail_compilation/fail_scope.d(107): Deprecation: escaping reference to outer local variable `x`
-fail_compilation/fail_scope.d(126): Error: returning `s.bar()` escapes a reference to local variable `s`
-fail_compilation/fail_scope.d(136): Error: returning `foo16226(i)` escapes a reference to local variable `i`
+fail_compilation/fail_scope.d(69): `fail_scope.foo8(return ref int x)`
+fail_compilation/fail_scope.d(82): Error: returning `& string` escapes a reference to local variable `string`
+fail_compilation/fail_scope.d(92): Error: returning `cast(int[])a` escapes a reference to local variable `a`
+fail_compilation/fail_scope.d(100): Error: returning `cast(int[])a` escapes a reference to local variable `a`
+fail_compilation/fail_scope.d(108): Deprecation: escaping reference to outer local variable `x`
+fail_compilation/fail_scope.d(127): Error: returning `s.bar()` escapes a reference to local variable `s`
+fail_compilation/fail_scope.d(137): Error: returning `foo16226(i)` escapes a reference to local variable `i`
---
+//fail_compilation/fail_scope.d(30): Error: scope variable `da` may not be returned
+//fail_compilation/fail_scope.d(32): Error: scope variable `o` may not be returned
+//fail_compilation/fail_scope.d(33): Error: scope variable `dg` may not be returned
+//fail_compilation/fail_scope.d(35): Error: scope variable `da` may not be returned
+//fail_compilation/fail_scope.d(37): Error: scope variable `o` may not be returned
+//fail_compilation/fail_scope.d(38): Error: scope variable `dg` may not be returned
+//fail_compilation/fail_scope.d(40): Error: scope variable `p` may not be returned
*/
alias int delegate() dg_t;
-int[] checkEscapeScope1(scope int[] da) @safe { return da; }
-int[3] checkEscapeScope2(scope int[3] sa) @safe { return sa; }
-Object checkEscapeScope3(scope Object o) @safe { return o; }
-dg_t checkEscapeScope4(scope dg_t dg) @safe { return dg; }
+int[] checkEscapeScope1(scope int[] da) { return da; }
+int[3] checkEscapeScope2(scope int[3] sa) { return sa; }
+Object checkEscapeScope3(scope Object o) { return o; }
+dg_t checkEscapeScope4(scope dg_t dg) { return dg; }
-int[] checkEscapeScope1() @safe { scope int[] da = []; return da; }
-int[3] checkEscapeScope2() @safe { scope int[3] sa = [1,2,3]; return sa; }
-Object checkEscapeScope3() @safe { scope Object o = new Object; return o; } // same with fail7294.d
-dg_t checkEscapeScope4() @safe { scope dg_t dg = () => 1; return dg; }
+int[] checkEscapeScope1() { scope int[] da = []; return da; }
+int[3] checkEscapeScope2() { scope int[3] sa = [1,2,3]; return sa; }
+Object checkEscapeScope3() { scope Object o = new Object; return o; } // same with fail7294.d
+dg_t checkEscapeScope4() { scope dg_t dg = () => 1; return dg; }
int* test(scope int* p) @safe { return p; }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice10949.d b/gcc/testsuite/gdc.test/fail_compilation/ice10949.d
index 45b18e0..b39548d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice10949.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice10949.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/ice10949.d(12): Error: Using the result of a comma expression is not allowed
+fail_compilation/ice10949.d(12): Error: using the result of a comma expression is not allowed
fail_compilation/ice10949.d(12): Error: array index 3 is out of bounds `[5, 5][0 .. 2]`
fail_compilation/ice10949.d(12): Error: array index 17 is out of bounds `[2, 3][0 .. 2]`
fail_compilation/ice10949.d(12): while evaluating: `static assert((((([5, 5][3] + global - global) * global / global % global >> global & global | global) ^ global) == 9 , [2, 3][17]) || [3, 3, 3][9] is 4 && [[1, 2, 3]][4].length)`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice14844.d b/gcc/testsuite/gdc.test/fail_compilation/ice14844.d
index 9f602a5..d466a30 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice14844.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice14844.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/ice14844.d(21): Error: In expression `__traits(allMembers, opDispatch)` template `opDispatch(string name)` has no members
+fail_compilation/ice14844.d(21): Error: in expression `__traits(allMembers, opDispatch)` template `opDispatch(string name)` has no members
fail_compilation/ice14844.d(21): `opDispatch(string name)` must evaluate to either a module, a struct, an union, a class, an interface or a template instantiation
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice22377.d b/gcc/testsuite/gdc.test/fail_compilation/ice22377.d
index 4616f99..686e700 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice22377.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice22377.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/ice22377.d(8): Error: Internal Compiler Error: type `string` cannot be mapped to C++
+fail_compilation/ice22377.d(8): Error: function `ice22377.foo` cannot have parameter of type `string` because its linkage is `extern(C++)`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice23097.d b/gcc/testsuite/gdc.test/fail_compilation/ice23097.d
new file mode 100644
index 0000000..4fd1f61
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice23097.d
@@ -0,0 +1,28 @@
+/* https://issues.dlang.org/show_bug.cgi?id=23097
+TEST_OUTPUT:
+---
+fail_compilation/ice23097.d(12): Error: undefined identifier `ICE`
+fail_compilation/ice23097.d(27): Error: template instance `ice23097.ice23097!(S23097)` error instantiating
+fail_compilation/ice23097.d(27): Error: function `ice23097.ice23097!(S23097).ice23097(S23097 _param_0)` is not callable using argument types `(S23097)`
+fail_compilation/ice23097.d(27): generating a copy constructor for `struct S23097` failed, therefore instances of it are uncopyable
+---
+*/
+auto ice23097(I)(I)
+{
+ ICE;
+}
+
+struct Cpctor23097
+{
+ this(ref typeof(this)) { }
+}
+
+struct S23097
+{
+ Cpctor23097 cpctor;
+}
+
+auto fail23097(S23097 s)
+{
+ s.ice23097;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice9254a.d b/gcc/testsuite/gdc.test/fail_compilation/ice9254a.d
index d7086b4..8ba1cbf 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice9254a.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice9254a.d
@@ -1,11 +1,11 @@
/*
TEST_OUTPUT:
---
-fail_compilation/ice9254a.d(15): Error: Using the result of a comma expression is not allowed
-fail_compilation/ice9254a.d(15): Error: Using the result of a comma expression is not allowed
-fail_compilation/ice9254a.d(15): Error: Using the result of a comma expression is not allowed
-fail_compilation/ice9254a.d(15): Error: Using the result of a comma expression is not allowed
-fail_compilation/ice9254a.d(15): Error: Using the result of a comma expression is not allowed
+fail_compilation/ice9254a.d(15): Error: using the result of a comma expression is not allowed
+fail_compilation/ice9254a.d(15): Error: using the result of a comma expression is not allowed
+fail_compilation/ice9254a.d(15): Error: using the result of a comma expression is not allowed
+fail_compilation/ice9254a.d(15): Error: using the result of a comma expression is not allowed
+fail_compilation/ice9254a.d(15): Error: using the result of a comma expression is not allowed
fail_compilation/ice9254a.d(15): Error: invalid `foreach` aggregate `false` of type `bool`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice9254b.d b/gcc/testsuite/gdc.test/fail_compilation/ice9254b.d
index 5484abd..04f28fd 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice9254b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice9254b.d
@@ -1,11 +1,11 @@
/*
TEST_OUTPUT:
---
-fail_compilation/ice9254b.d(17): Error: Using the result of a comma expression is not allowed
-fail_compilation/ice9254b.d(17): Error: Using the result of a comma expression is not allowed
-fail_compilation/ice9254b.d(17): Error: Using the result of a comma expression is not allowed
-fail_compilation/ice9254b.d(17): Error: Using the result of a comma expression is not allowed
-fail_compilation/ice9254b.d(17): Error: Using the result of a comma expression is not allowed
+fail_compilation/ice9254b.d(17): Error: using the result of a comma expression is not allowed
+fail_compilation/ice9254b.d(17): Error: using the result of a comma expression is not allowed
+fail_compilation/ice9254b.d(17): Error: using the result of a comma expression is not allowed
+fail_compilation/ice9254b.d(17): Error: using the result of a comma expression is not allowed
+fail_compilation/ice9254b.d(17): Error: using the result of a comma expression is not allowed
fail_compilation/ice9254b.d(17): Error: invalid `foreach` aggregate `false` of type `bool`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice9254c.d b/gcc/testsuite/gdc.test/fail_compilation/ice9254c.d
index 23eeecc..acecc8d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice9254c.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice9254c.d
@@ -1,11 +1,11 @@
/*
TEST_OUTPUT:
---
-fail_compilation/ice9254c.d(15): Error: Using the result of a comma expression is not allowed
-fail_compilation/ice9254c.d(15): Error: Using the result of a comma expression is not allowed
-fail_compilation/ice9254c.d(15): Error: Using the result of a comma expression is not allowed
-fail_compilation/ice9254c.d(15): Error: Using the result of a comma expression is not allowed
-fail_compilation/ice9254c.d(15): Error: Using the result of a comma expression is not allowed
+fail_compilation/ice9254c.d(15): Error: using the result of a comma expression is not allowed
+fail_compilation/ice9254c.d(15): Error: using the result of a comma expression is not allowed
+fail_compilation/ice9254c.d(15): Error: using the result of a comma expression is not allowed
+fail_compilation/ice9254c.d(15): Error: using the result of a comma expression is not allowed
+fail_compilation/ice9254c.d(15): Error: using the result of a comma expression is not allowed
fail_compilation/ice9254c.d(15): Error: invalid `foreach` aggregate `false` of type `bool`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/test23109a.d b/gcc/testsuite/gdc.test/fail_compilation/imports/test23109a.d
new file mode 100644
index 0000000..5a11d91
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/test23109a.d
@@ -0,0 +1,10 @@
+module imports.test23109a;
+import imports.test23109c;
+import imports.test23109b;
+struct Array(T)
+{
+ T[] data;
+ enum SMALLARRAYCAP = 1;
+ T[SMALLARRAYCAP] smallarray;
+}
+alias Ensures = Array!Ensure;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/test23109b.d b/gcc/testsuite/gdc.test/fail_compilation/imports/test23109b.d
new file mode 100644
index 0000000..38680d3
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/test23109b.d
@@ -0,0 +1,10 @@
+module imports.test23109b;
+import imports.test23109a;
+import imports.test23109c;
+struct Ensure
+{
+ Statement ensure;
+ Ensures* arraySyntaxCopy()
+ {
+ }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/test23109c.d b/gcc/testsuite/gdc.test/fail_compilation/imports/test23109c.d
new file mode 100644
index 0000000..c6faf5c
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/test23109c.d
@@ -0,0 +1,3 @@
+module imports.test23109c;
+import imports.test23109b;
+class Statement {}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/issue3827.d b/gcc/testsuite/gdc.test/fail_compilation/issue3827.d
index d17cee8..12ae60b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/issue3827.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/issue3827.d
@@ -2,9 +2,9 @@
/*
TEST_OUTPUT:
---
-fail_compilation/issue3827.d(14): Error: Implicit string concatenation is error-prone and disallowed in D
+fail_compilation/issue3827.d(14): Error: implicit string concatenation is error-prone and disallowed in D
fail_compilation/issue3827.d(14): Use the explicit syntax instead (concatenating literals is `@nogc`): "Hello" ~ "World"
-fail_compilation/issue3827.d(15): Error: Implicit string concatenation is error-prone and disallowed in D
+fail_compilation/issue3827.d(15): Error: implicit string concatenation is error-prone and disallowed in D
fail_compilation/issue3827.d(15): Use the explicit syntax instead (concatenating literals is `@nogc`): "A" ~ "B"
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/no_Throwable.d b/gcc/testsuite/gdc.test/fail_compilation/no_Throwable.d
index 5a8af97..eb385cb 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/no_Throwable.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/no_Throwable.d
@@ -4,8 +4,8 @@ REQUIRED_ARGS: -c
EXTRA_SOURCES: extra-files/minimal/object.d
TEST_OUTPUT:
---
-fail_compilation/no_Throwable.d(14): Error: Cannot use `throw` statements because `object.Throwable` was not declared
-fail_compilation/no_Throwable.d(19): Error: Cannot use try-catch statements because `object.Throwable` was not declared
+fail_compilation/no_Throwable.d(14): Error: cannot use `throw` statements because `object.Throwable` was not declared
+fail_compilation/no_Throwable.d(19): Error: cannot use try-catch statements because `object.Throwable` was not declared
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope.d b/gcc/testsuite/gdc.test/fail_compilation/retscope.d
index 64db4c8..27d5663 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/retscope.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/retscope.d
@@ -85,7 +85,7 @@ struct HTTP
/*
TEST_OUTPUT:
---
-fail_compilation/retscope.d(96): Error: reference to local variable `sa` assigned to non-scope parameter `a` calling retscope.bar8
+fail_compilation/retscope.d(96): Error: reference to local variable `sa` assigned to non-scope parameter `a`
---
*/
// https://issues.dlang.org/show_bug.cgi?id=8838
@@ -234,16 +234,16 @@ void* funretscope(scope dg_t ptr) @safe
/*
TEST_OUTPUT:
---
-fail_compilation/retscope.d(248): Error: cannot implicitly convert expression `__lambda2` of type `void* delegate() pure nothrow @nogc @safe` to `void* delegate() @safe`
-fail_compilation/retscope.d(248): Error: cannot implicitly convert expression `__lambda2` of type `void* delegate() pure nothrow @nogc @safe` to `void* delegate() @safe`
-fail_compilation/retscope.d(249): Error: cannot implicitly convert expression `__lambda4` of type `void* delegate() pure nothrow @nogc @safe` to `void* delegate() @safe`
-fail_compilation/retscope.d(249): Error: cannot implicitly convert expression `__lambda4` of type `void* delegate() pure nothrow @nogc @safe` to `void* delegate() @safe`
+fail_compilation/retscope.d(248): Error: cannot implicitly convert expression `__lambda2` of type `void* delegate() pure nothrow @nogc @safe` to `void* delegate() scope @safe`
+fail_compilation/retscope.d(248): Error: cannot implicitly convert expression `__lambda2` of type `void* delegate() pure nothrow @nogc @safe` to `void* delegate() scope @safe`
+fail_compilation/retscope.d(249): Error: cannot implicitly convert expression `__lambda4` of type `void* delegate() pure nothrow @nogc @safe` to `void* delegate() scope @safe`
+fail_compilation/retscope.d(249): Error: cannot implicitly convert expression `__lambda4` of type `void* delegate() pure nothrow @nogc @safe` to `void* delegate() scope @safe`
---
*/
void escape4() @safe
{
- alias FunDG = void* delegate () @safe;
+ alias FunDG = void* delegate () scope @safe;
int x = 42;
scope FunDG f = () return { return &x; };
scope FunDG g = () { return &x; };
@@ -254,7 +254,7 @@ void escape4() @safe
/*
TEST_OUTPUT:
---
-fail_compilation/retscope.d(266): Error: cannot take address of `scope` local `p` in `@safe` function `escape5`
+fail_compilation/retscope.d(266): Error: cannot take address of `scope` variable `p` since `scope` applies to first indirection only
---
*/
@@ -331,7 +331,7 @@ int* bar10( scope int** ptr ) @safe
/*
TEST_OUTPUT:
---
-fail_compilation/retscope.d(342): Error: cannot take address of `scope` local `aa` in `@safe` function `escape11`
+fail_compilation/retscope.d(342): Error: cannot take address of `scope` variable `aa` since `scope` applies to first indirection only
---
*/
@@ -403,7 +403,7 @@ class Foo13
/*
TEST_OUTPUT:
---
-fail_compilation/retscope.d(1205): Error: scope variable `f14` assigned to non-scope parameter `this` calling retscope.Foo14.foo
+fail_compilation/retscope.d(1205): Error: scope variable `f14` assigned to non-scope parameter `this`
---
*/
@@ -454,7 +454,7 @@ fail_compilation/retscope.d(1311): Error: scope variable `u2` assigned to `ek` w
/*
TEST_OUTPUT:
---
-fail_compilation/retscope.d(1405): Error: reference to local variable `buf` assigned to non-scope parameter `__anonymous_param` calling retscope.myprintf
+fail_compilation/retscope.d(1405): Error: reference to local variable `buf` assigned to non-scope parameter `__anonymous_param`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope2.d b/gcc/testsuite/gdc.test/fail_compilation/retscope2.d
index 4f1e324..17d2182 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/retscope2.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/retscope2.d
@@ -86,8 +86,8 @@ fail_compilation/retscope2.d(504): Error: scope variable `c` may not be returned
/*
TEST_OUTPUT:
---
-fail_compilation/retscope2.d(604): Error: scope variable `_param_0` assigned to non-scope parameter `__anonymous_param` calling retscope2.foo600
-fail_compilation/retscope2.d(604): Error: scope variable `_param_1` assigned to non-scope parameter `__anonymous_param` calling retscope2.foo600
+fail_compilation/retscope2.d(604): Error: scope variable `_param_0` assigned to non-scope parameter `__anonymous_param`
+fail_compilation/retscope2.d(604): Error: scope variable `_param_1` assigned to non-scope parameter `__anonymous_param`
fail_compilation/retscope2.d(614): Error: template instance `retscope2.test600!(int*, int*)` error instantiating
---
*/
@@ -156,7 +156,7 @@ fail_compilation/retscope2.d(804): Error: scope variable `e` may not be thrown
#line 800
-void foo800()
+void foo800() @safe
{
scope Exception e;
throw e;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope6.d b/gcc/testsuite/gdc.test/fail_compilation/retscope6.d
index 6d5807b..b9a85ae 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/retscope6.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/retscope6.d
@@ -76,9 +76,9 @@ void foo() @safe
/* TEST_OUTPUT:
---
fail_compilation/retscope6.d(8016): Error: address of variable `i` assigned to `p` with longer lifetime
-fail_compilation/retscope6.d(8031): Error: reference to local variable `i` assigned to non-scope parameter `p` calling retscope6.betty!().betty
-fail_compilation/retscope6.d(8031): Error: reference to local variable `j` assigned to non-scope parameter `q` calling retscope6.betty!().betty
-fail_compilation/retscope6.d(8048): Error: reference to local variable `j` assigned to non-scope parameter `q` calling retscope6.archie!().archie
+fail_compilation/retscope6.d(8031): Error: reference to local variable `i` assigned to non-scope parameter `p`
+fail_compilation/retscope6.d(8031): Error: reference to local variable `j` assigned to non-scope parameter `q`
+fail_compilation/retscope6.d(8048): Error: reference to local variable `j` assigned to non-scope parameter `q`
---
*/
@@ -172,7 +172,7 @@ T9 testfred()
/* TEST_OUTPUT:
---
-fail_compilation/retscope6.d(10003): Error: scope variable `values` assigned to non-scope parameter `values` calling retscope6.escape
+fail_compilation/retscope6.d(10003): Error: scope variable `values` assigned to non-scope parameter `values`
---
*/
@@ -234,7 +234,7 @@ const(int)* f_c_20150() @safe nothrow
/* TEST_OUTPUT:
---
-fail_compilation/retscope6.d(13010): Error: reference to local variable `str` assigned to non-scope parameter `x` calling retscope6.f_throw
+fail_compilation/retscope6.d(13010): Error: reference to local variable `str` assigned to non-scope parameter `x`
---
*/
@@ -254,7 +254,7 @@ void escape_throw_20150() @safe
/* TEST_OUTPUT:
---
-fail_compilation/retscope6.d(14019): Error: scope variable `scopePtr` assigned to non-scope parameter `x` calling retscope6.noInfer23021
+fail_compilation/retscope6.d(14019): Error: scope variable `scopePtr` assigned to non-scope parameter `x`
fail_compilation/retscope6.d(14022): Error: scope variable `scopePtr` may not be returned
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/safe_gshared.d b/gcc/testsuite/gdc.test/fail_compilation/safe_gshared.d
new file mode 100644
index 0000000..ea0775c
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/safe_gshared.d
@@ -0,0 +1,15 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/safe_gshared.d(13): Error: `@safe` function `f` cannot access `__gshared` data `x`
+fail_compilation/safe_gshared.d(14): Error: `@safe` function `f` cannot access `__gshared` data `x`
+---
+*/
+
+__gshared int x;
+
+@safe int f()
+{
+ x++;
+ return x;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/safe_pointer_index.d b/gcc/testsuite/gdc.test/fail_compilation/safe_pointer_index.d
new file mode 100644
index 0000000..4b107db
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/safe_pointer_index.d
@@ -0,0 +1,12 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/safe_pointer_index.d(11): Error: `@safe` function `f` cannot index pointer `x`
+---
+*/
+
+@safe void f(int* x)
+{
+ int y = x[0]; // allowed, same as *x
+ int z = x[1];
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test13536.d b/gcc/testsuite/gdc.test/fail_compilation/test13536.d
index c45d76a..f4e2cac 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test13536.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test13536.d
@@ -2,7 +2,7 @@
TEST_OUTPUT:
---
fail_compilation/test13536.d(23): Error: field `U.sysDg` cannot access pointers in `@safe` code that overlap other fields
-fail_compilation/test13536.d(23): Error: address of variable `s` assigned to `u` with longer lifetime
+fail_compilation/test13536.d(23): Deprecation: address of variable `s` assigned to `u` with longer lifetime
fail_compilation/test13536.d(24): Error: field `U.safeDg` cannot access pointers in `@safe` code that overlap other fields
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test14496.d b/gcc/testsuite/gdc.test/fail_compilation/test14496.d
index 92dd3cf..9f628ca 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test14496.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test14496.d
@@ -1,11 +1,11 @@
/*
TEST_OUTPUT:
---
-fail_compilation/test14496.d(21): Error: variable `test14496.foo.f` `void` initializers for pointers not allowed in safe functions
-fail_compilation/test14496.d(24): Error: variable `test14496.foo.Bar.foo` `void` initializers for pointers not allowed in safe functions
-fail_compilation/test14496.d(28): Error: variable `test14496.foo.Baz.x` `void` initializers for pointers not allowed in safe functions
-fail_compilation/test14496.d(48): Error: variable `test14496.sinister.bar` `void` initializers for pointers not allowed in safe functions
-fail_compilation/test14496.d(49): Error: variable `test14496.sinister.baz` `void` initializers for pointers not allowed in safe functions
+fail_compilation/test14496.d(21): Error: `void` initializers for pointers not allowed in safe functions
+fail_compilation/test14496.d(24): Error: `void` initializers for pointers not allowed in safe functions
+fail_compilation/test14496.d(28): Error: `void` initializers for pointers not allowed in safe functions
+fail_compilation/test14496.d(48): Error: `void` initializers for pointers not allowed in safe functions
+fail_compilation/test14496.d(49): Error: `void` initializers for pointers not allowed in safe functions
---
*/
// https://issues.dlang.org/show_bug.cgi?id=14496
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test15191.d b/gcc/testsuite/gdc.test/fail_compilation/test15191.d
index f2a117c..fbbc1c0 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test15191.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test15191.d
@@ -1,12 +1,11 @@
/* TEST_OUTPUT:
REQUIRED_ARGS: -preview=dip1000
---
-fail_compilation/test15191.d(35): Error: returning `&identity(x)` escapes a reference to local variable `x`
-fail_compilation/test15191.d(41): Error: returning `&identityPtr(x)` escapes a reference to local variable `x`
-fail_compilation/test15191.d(47): Error: cannot take address of `ref return` of `identityPtr()` in `@safe` function `addrOfRefTransitive`
-fail_compilation/test15191.d(47): return type `int*` has pointers that may be `scope`
-fail_compilation/test15191.d(68): Error: cannot slice static array of `ref return` of `identityArr()` in `@safe` function `sliceOfRefEscape`
-fail_compilation/test15191.d(68): return type `int*[1]` has pointers that may be `scope`
+fail_compilation/test15191.d(34): Error: returning `&identity(x)` escapes a reference to local variable `x`
+fail_compilation/test15191.d(40): Error: returning `&identityPtr(x)` escapes a reference to local variable `x`
+fail_compilation/test15191.d(46): Error: returning `&identityPtr(x)` escapes a reference to local variable `x`
+fail_compilation/test15191.d(67): Error: cannot take address of `scope` variable `x` since `scope` applies to first indirection only
+fail_compilation/test15191.d(69): Error: cannot take address of `scope` variable `x` since `scope` applies to first indirection only
---
*/
@@ -61,10 +60,24 @@ ref int*[1] identityArr(return ref scope int*[1] x)
return x;
}
-int* sliceOfRefEscape()
+int*[] sliceOfRefEscape()
{
int stackVar = 0xFF;
scope int*[1] x = [&stackVar];
- int*[] y = identityArr(x)[];
- return y[0];
+ auto y = identityArr(x)[]; // check transitive scope in assignment
+ cast(void) y;
+ return identityArr(x)[]; // check transitive scope in return statement
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=23079
+int** p;
+
+ref int* get() @safe
+{
+ return *p;
+}
+
+int** g1() @safe
+{
+ return &get();
}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test15373.d b/gcc/testsuite/gdc.test/fail_compilation/test15373.d
index 1b3cecd..02a1b32 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test15373.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test15373.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/test15373.d(21): Error: Runtime type information is not supported for `extern(C++)` classes
+fail_compilation/test15373.d(21): Error: runtime type information is not supported for `extern(C++)` classes
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16188.d b/gcc/testsuite/gdc.test/fail_compilation/test16188.d
index c8ab825..c4a0fa6 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test16188.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test16188.d
@@ -1,8 +1,8 @@
-TEST_OUTPUT:
+/* REQUIRED_ARGS: -preview=bitfields
+ * TEST_OUTPUT:
---
-fail_compilation/test16188.d(1): Error: no identifier for declarator `TEST_OUTPUT`
-fail_compilation/test16188.d(1): Error: declaration expected, not `:`
-fail_compilation/test16188.d(18): Error: unmatched closing brace
+fail_compilation/test16188.d(101): Error: no property `name` for type `test16188.Where`
+fail_compilation/test16188.d(101): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
---
*/
@@ -15,6 +15,8 @@ fail_compilation/test16188.d(18): Error: unmatched closing brace
* I don't understand why.
*/
+#line 100
+
void where() { Where().name; }
struct Where
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16365.d b/gcc/testsuite/gdc.test/fail_compilation/test16365.d
index a11807f..c987969 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test16365.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test16365.d
@@ -3,7 +3,7 @@ TEST_OUTPUT:
---
fail_compilation/test16365.d(21): Error: `this` reference necessary to take address of member `f1` in `@safe` function `main`
fail_compilation/test16365.d(23): Error: cannot implicitly convert expression `&f2` of type `void delegate() pure nothrow @nogc @safe` to `void function() @safe`
-fail_compilation/test16365.d(27): Error: address of variable `s` assigned to `dg` with longer lifetime
+fail_compilation/test16365.d(27): Deprecation: address of variable `s` assigned to `dg` with longer lifetime
fail_compilation/test16365.d(28): Error: `dg.funcptr` cannot be used in `@safe` code
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17284.d b/gcc/testsuite/gdc.test/fail_compilation/test17284.d
index 5bb3c2c..b7fd979 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test17284.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test17284.d
@@ -1,9 +1,10 @@
/*
TEST_OUTPUT:
---
-fail_compilation/test17284.d(16): Error: field `U.c` cannot access pointers in `@safe` code that overlap other fields
+fail_compilation/test17284.d(17): Error: field `U.c` cannot access pointers in `@safe` code that overlap other fields
pure nothrow @safe void(U t)
---
+REQUIRED_ARGS: -preview=bitfields
*/
// https://issues.dlang.org/show_bug.cgi?id=17284
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17423.d b/gcc/testsuite/gdc.test/fail_compilation/test17423.d
index 66a81c3..ec86646 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test17423.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test17423.d
@@ -1,7 +1,7 @@
/* REQUIRED_ARGS: -preview=dip1000
TEST_OUTPUT:
---
-fail_compilation/test17423.d(26): Error: reference to local `this` assigned to non-scope parameter `dlg` calling test17423.Bar.opApply
+fail_compilation/test17423.d(26): Error: reference to local `this` assigned to non-scope parameter `dlg`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17868b.d b/gcc/testsuite/gdc.test/fail_compilation/test17868b.d
index 7833b61..18f1844 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test17868b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test17868b.d
@@ -2,8 +2,8 @@
TEST_OUTPUT:
----
fail_compilation/test17868b.d(9): Error: pragma `crt_constructor` can only apply to a single declaration
-fail_compilation/test17868b.d(10): Error: function `test17868b.foo` must be `extern(C)` for `pragma(crt_constructor)`
-fail_compilation/test17868b.d(14): Error: function `test17868b.bar` must be `extern(C)` for `pragma(crt_constructor)`
+fail_compilation/test17868b.d(14): Error: function `test17868b.bar` must return `void` for `pragma(crt_constructor)`
+fail_compilation/test17868b.d(18): Error: function `test17868b.baz` must be `extern(C)` for `pragma(crt_constructor)` when taking parameters
----
*/
pragma(crt_constructor):
@@ -11,6 +11,14 @@ void foo()
{
}
-void bar()
+extern(C) int bar()
+{
+}
+
+void baz(int argc, char** argv)
+{
+}
+
+extern(C) void bazC(int, char**)
{
}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test18130.d b/gcc/testsuite/gdc.test/fail_compilation/test18130.d
index 4309a6b..be296f8 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test18130.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test18130.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/test18130.d(8): Error: variable `test18130.foo.v` Zero-length `out` parameters are not allowed.
+fail_compilation/test18130.d(8): Error: variable `test18130.foo.v` zero-length `out` parameters are not allowed.
---
*/
// https://issues.dlang.org/show_bug.cgi?id=18130
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test18282.d b/gcc/testsuite/gdc.test/fail_compilation/test18282.d
index cf26878..580fe1b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test18282.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test18282.d
@@ -60,7 +60,7 @@ TEST_OUTPUT:
fail_compilation/test18282.d(1007): Error: copying `& foo` into allocated memory escapes a reference to local variable `foo`
fail_compilation/test18282.d(1008): Error: copying `& foo` into allocated memory escapes a reference to local variable `foo`
fail_compilation/test18282.d(1009): Error: copying `& foo` into allocated memory escapes a reference to local variable `foo`
-fail_compilation/test18282.d(1016): Error: copying `&this` into allocated memory escapes a reference to parameter variable `this`
+fail_compilation/test18282.d(1016): Error: copying `&this` into allocated memory escapes a reference to parameter `this`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test18484.d b/gcc/testsuite/gdc.test/fail_compilation/test18484.d
index 55d0ff1..d604f38 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test18484.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test18484.d
@@ -10,11 +10,11 @@ fail_compilation/test18484.d(24): Error: escaping reference to stack allocated v
struct S
{
- int* bar() return;
+ int* bar() @safe return;
int i;
}
-int* test1()
+int* test1() @safe
{
auto x = S(); return x.bar(); // error
}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20245.d b/gcc/testsuite/gdc.test/fail_compilation/test20245.d
index 74c5384..daa0697 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test20245.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test20245.d
@@ -2,15 +2,15 @@
REQUIRED_ARGS: -preview=dip1000
TEST_OUTPUT:
---
-fail_compilation/test20245.d(20): Error: reference to local variable `x` assigned to non-scope parameter `ptr` calling test20245.escape
-fail_compilation/test20245.d(21): Error: copying `&x` into allocated memory escapes a reference to parameter variable `x`
+fail_compilation/test20245.d(20): Error: reference to local variable `x` assigned to non-scope parameter `ptr`
+fail_compilation/test20245.d(21): Error: copying `&x` into allocated memory escapes a reference to parameter `x`
fail_compilation/test20245.d(22): Error: scope variable `a` may not be returned
-fail_compilation/test20245.d(26): Error: cannot take address of `scope` parameter `x` in `@safe` function `foo`
-fail_compilation/test20245.d(32): Error: reference to local variable `x` assigned to non-scope parameter `ptr` calling test20245.escape
-fail_compilation/test20245.d(33): Error: copying `&x` into allocated memory escapes a reference to parameter variable `x`
+fail_compilation/test20245.d(26): Error: cannot take address of `scope` variable `x` since `scope` applies to first indirection only
+fail_compilation/test20245.d(32): Error: reference to local variable `x` assigned to non-scope parameter `ptr`
+fail_compilation/test20245.d(33): Error: copying `&x` into allocated memory escapes a reference to parameter `x`
fail_compilation/test20245.d(49): Error: reference to local variable `price` assigned to non-scope `this.minPrice`
-fail_compilation/test20245.d(68): Error: reference to local variable `this` assigned to non-scope parameter `msg` calling object.Exception.this
-fail_compilation/test20245.d(88): Error: reference to local variable `this` assigned to non-scope parameter `content` calling test20245.listUp
+fail_compilation/test20245.d(68): Error: reference to local variable `this` assigned to non-scope parameter `msg`
+fail_compilation/test20245.d(88): Error: reference to local variable `this` assigned to non-scope parameter `content`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20569.d b/gcc/testsuite/gdc.test/fail_compilation/test20569.d
index a5ac98b..7ad50dc 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test20569.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test20569.d
@@ -1,8 +1,8 @@
/* REQUIRED_ARGS: -preview=dip1000
TEST_OUTPUT:
---
-fail_compilation/test20569.d(19): Error: cannot take address of `scope` local `s1` in `@safe` function `main`
-fail_compilation/test20569.d(23): Error: cannot take address of `scope` local `s2` in `@safe` function `main`
+fail_compilation/test20569.d(19): Error: cannot take address of `scope` variable `s1` since `scope` applies to first indirection only
+fail_compilation/test20569.d(23): Error: cannot take address of `scope` variable `s2` since `scope` applies to first indirection only
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21198.d b/gcc/testsuite/gdc.test/fail_compilation/test21198.d
index cab6fc8..04c3bcf 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test21198.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21198.d
@@ -3,7 +3,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/test21198.d(23): Error: Generating an `inout` copy constructor for `struct test21198.U` failed, therefore instances of it are uncopyable
+fail_compilation/test21198.d(23): Error: generating an `inout` copy constructor for `struct test21198.U` failed, therefore instances of it are uncopyable
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21204.d b/gcc/testsuite/gdc.test/fail_compilation/test21204.d
index 8732cc0..45bb6d7 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test21204.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21204.d
@@ -2,7 +2,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/test21204.d(22): Error: Generating an `inout` copy constructor for `struct test21204.B` failed, therefore instances of it are uncopyable
+fail_compilation/test21204.d(22): Error: generating an `inout` copy constructor for `struct test21204.B` failed, therefore instances of it are uncopyable
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21665.d b/gcc/testsuite/gdc.test/fail_compilation/test21665.d
index a3a348d..b4c2811 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test21665.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21665.d
@@ -1,6 +1,6 @@
/* TEST_OUTPUT:
---
-fail_compilation/test21665.d(18): Error: variable `test21665.test1.s` `void` initializers for structs with invariants are not allowed in safe functions
+fail_compilation/test21665.d(18): Error: `void` initializers for structs with invariants are not allowed in safe functions
fail_compilation/test21665.d(30): Error: field `U.s` cannot access structs with invariants in `@safe` code that overlap other fields
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22145.d b/gcc/testsuite/gdc.test/fail_compilation/test22145.d
index 084083c..394116d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test22145.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test22145.d
@@ -1,4 +1,5 @@
/* TEST_OUTPUT:
+REQUIRED_ARGS: -preview=dip1000
---
fail_compilation/test22145.d(115): Error: scope variable `x` assigned to non-scope `global`
---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22593.d b/gcc/testsuite/gdc.test/fail_compilation/test22593.d
index f90287e..a47c0fe 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test22593.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test22593.d
@@ -3,7 +3,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/test22593.d(14): Error: Cannot define both an rvalue constructor and a copy constructor for `struct Foo`
+fail_compilation/test22593.d(14): Error: cannot define both an rvalue constructor and a copy constructor for `struct Foo`
fail_compilation/test22593.d(22): Template instance `__ctor!(immutable(Foo!int), immutable(Foo!int))` creates a rvalue constructor for `struct Foo`
fail_compilation/test22593.d(22): Error: template instance `test22593.Foo!int.Foo.__ctor!(immutable(Foo!int), immutable(Foo!int))` error instantiating
---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test9150.d b/gcc/testsuite/gdc.test/fail_compilation/test9150.d
index e65afec..5f66b36 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test9150.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test9150.d
@@ -3,7 +3,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/test9150.d(14): Error: mismatched array lengths, 5 and 3
+fail_compilation/test9150.d(14): Error: mismatched array lengths 5 and 3 for assignment `row[] = __r2[__key3]`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/traits.d b/gcc/testsuite/gdc.test/fail_compilation/traits.d
index 5b9daaa..8c16afe 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/traits.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/traits.d
@@ -11,13 +11,13 @@ fail_compilation/traits.d(200): Error: undefined identifier `imports.nonexistent
fail_compilation/traits.d(201): Error: undefined identifier `imports.nonexistent`
fail_compilation/traits.d(202): Error: expected 1 arguments for `isPackage` but had 0
fail_compilation/traits.d(203): Error: expected 1 arguments for `isModule` but had 0
-fail_compilation/traits.d(300): Error: In expression `__traits(allMembers, float)` `float` can't have members
+fail_compilation/traits.d(300): Error: in expression `__traits(allMembers, float)` `float` can't have members
fail_compilation/traits.d(300): `float` must evaluate to either a module, a struct, an union, a class, an interface or a template instantiation
-fail_compilation/traits.d(306): Error: In expression `__traits(allMembers, TemplatedStruct)` struct `TemplatedStruct(T)` has no members
+fail_compilation/traits.d(306): Error: in expression `__traits(allMembers, TemplatedStruct)` struct `TemplatedStruct(T)` has no members
fail_compilation/traits.d(306): `TemplatedStruct(T)` must evaluate to either a module, a struct, an union, a class, an interface or a template instantiation
-fail_compilation/traits.d(309): Error: In expression `__traits(derivedMembers, float)` `float` can't have members
+fail_compilation/traits.d(309): Error: in expression `__traits(derivedMembers, float)` `float` can't have members
fail_compilation/traits.d(309): `float` must evaluate to either a module, a struct, an union, a class, an interface or a template instantiation
-fail_compilation/traits.d(316): Error: In expression `__traits(derivedMembers, TemplatedStruct)` struct `TemplatedStruct(T)` has no members
+fail_compilation/traits.d(316): Error: in expression `__traits(derivedMembers, TemplatedStruct)` struct `TemplatedStruct(T)` has no members
fail_compilation/traits.d(316): `TemplatedStruct(T)` must evaluate to either a module, a struct, an union, a class, an interface or a template instantiation
fail_compilation/traits.d(404): Error: function `traits.func1` circular reference in `__traits(GetCppNamespaces,...)`
fail_compilation/traits.d(413): Error: function `traits.foo1.func1` circular reference in `__traits(GetCppNamespaces,...)`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/udaparams.d b/gcc/testsuite/gdc.test/fail_compilation/udaparams.d
index ec760bd..5d0390f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/udaparams.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/udaparams.d
@@ -12,8 +12,8 @@ fail_compilation/udaparams.d(40): Error: `@safe` attribute for function paramete
fail_compilation/udaparams.d(43): Error: `@system` attribute for function parameter is not supported
fail_compilation/udaparams.d(44): Error: `@trusted` attribute for function parameter is not supported
fail_compilation/udaparams.d(45): Error: `@nogc` attribute for function parameter is not supported
-fail_compilation/udaparams.d(51): Error: Cannot put a storage-class in an alias declaration.
-fail_compilation/udaparams.d(52): Error: Cannot put a storage-class in an alias declaration.
+fail_compilation/udaparams.d(51): Error: cannot put a storage-class in an alias declaration.
+fail_compilation/udaparams.d(52): Error: cannot put a storage-class in an alias declaration.
fail_compilation/udaparams.d(53): Error: semicolon expected to close `alias` declaration
fail_compilation/udaparams.d(53): Error: declaration expected, not `=>`
fail_compilation/udaparams.d(54): Error: semicolon expected to close `alias` declaration
diff --git a/gcc/testsuite/gdc.test/runnable/bit.d b/gcc/testsuite/gdc.test/runnable/bit.d
new file mode 100644
index 0000000..289e1bc
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/bit.d
@@ -0,0 +1,106 @@
+/* REQUIRED_ARGS: -preview=bitfields
+ */
+
+struct T
+{
+ uint x : 2, y : 3, :0;
+ int :0;
+}
+
+uint foo(T s)
+{
+ return s.x + s.y;
+}
+
+void test1()
+{
+ T s;
+ s.x = 2;
+ s.y = 4;
+ uint u = foo(s);
+ assert(u == 6);
+}
+
+/********************************************/
+
+struct S
+{
+ uint a:3;
+ uint b:1;
+ ulong c:64;
+
+ int d:3;
+ int e:1;
+ long f:64;
+
+ int i;
+ alias f this;
+}
+
+static assert(S.a.min == 0);
+static assert(S.a.max == 7);
+
+static assert(S.b.min == 0);
+static assert(S.b.max == 1);
+
+static assert(S.c.min == 0);
+static assert(S.c.max == ulong.max);
+
+static assert(S.d.min == -4);
+static assert(S.d.max == 3);
+
+static assert(S.e.min == -1);
+static assert(S.e.max == 0);
+
+static assert(S.f.min == long.min);
+static assert(S.f.max == long.max);
+static assert(S.max == S.f.max);
+
+void test2()
+{
+ int x;
+ S effect()
+ {
+ ++x;
+ return S();
+ }
+ assert(effect().a.max == 7);
+ assert(effect().i.max == int.max);
+ assert(x == 0); // ensure effect() was not executed
+}
+
+/********************************************/
+
+struct U
+{
+ int a;
+ int b:3, c:4;
+ this(this)
+ {
+ b = 2;
+ }
+}
+
+static assert(U.b.offsetof == 4);
+static assert(U.b.sizeof == 4);
+
+void test3()
+{
+ U u;
+ u.c = 4;
+ U v = u;
+ assert(v.c == 4);
+ u = v;
+ assert(u.b == 2);
+ assert(__traits(getMember, u, "b") == 2);
+}
+
+/********************************************/
+
+int main()
+{
+ test1();
+ test2();
+ test3();
+ return 0;
+}
diff --git a/gcc/testsuite/gdc.test/runnable/dbitfields.d b/gcc/testsuite/gdc.test/runnable/dbitfields.d
new file mode 100644
index 0000000..0d1877a
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/dbitfields.d
@@ -0,0 +1,189 @@
+/* REQUIRED_ARGS: -preview=bitfields
+ */
+
+struct S
+{
+ int a:2, b:4;
+}
+
+static assert(S.sizeof == 4);
+
+void test1()
+{
+ S s;
+ s.a = 3;
+ assert(s.a == -1);
+
+ s.b = 4;
+ assert(s.b == 4);
+}
+
+/******************************************/
+
+struct S2
+{
+ uint a:2, b:4;
+}
+
+S2 foo()
+{
+ S2 s = { 7, 8 }; // test struct literal expressions
+ return s;
+}
+
+void test2()
+{
+ S2 s = foo();
+
+ assert(s.a == 3);
+ assert(s.b == 8);
+}
+
+/******************************************/
+
+struct S3
+{
+ int i1;
+ uint a:2, b:4, c:6;
+ int i2;
+}
+
+static assert(S3.sizeof == 12);
+
+S3 s3 = { 63, 7, 8 };
+
+void test3()
+{
+ assert(s3.i1 == 63);
+ assert(s3.a == 3);
+ assert(s3.b == 8);
+ assert(s3.c == 0);
+ assert(s3.i2 == 0);
+}
+
+/******************************************/
+
+struct S4
+{
+ int i1;
+ uint a:2, b:31;
+}
+
+static assert(S4.sizeof == 12);
+
+S4 s4 = { 63, 7, 8 };
+
+void test4()
+{
+ assert(s4.i1 == 63);
+ assert(s4.a == 3);
+ assert(s4.b == 8);
+}
+
+/******************************************/
+
+struct S5
+{
+ int i1;
+ uint a:2, :0, b:5;
+}
+
+static assert(S5.sizeof == 12);
+
+S5 s5 = { 63, 7, 8 };
+
+void test5()
+{
+ assert(s5.i1 == 63);
+ assert(s5.a == 3);
+ assert(s5.b == 8);
+}
+
+/******************************************/
+
+// https://issues.dlang.org/show_bug.cgi?id=22710
+
+struct S6
+{
+ uint a:2, b:2;
+}
+
+int boo6()
+{
+ S s;
+ s.a = 3;
+ s.b = 1;
+ s.a += 2;
+ return s.a;
+}
+
+void test6()
+{
+ //printf("res: %d\n", test());
+ assert(boo6() == 1);
+}
+
+/******************************************/
+
+// https://issues.dlang.org/show_bug.cgi?id=22710
+
+struct S7
+{
+ uint a:2, b:2;
+ int c:2, d:2;
+}
+
+int test7u()
+{
+ S7 s;
+ s.a = 7;
+ s.b = 1;
+ s.a += 2;
+ return s.a;
+}
+
+int test7s()
+{
+ S7 s;
+ s.c = 7;
+ s.d = 1;
+ s.c += 4;
+ return s.c;
+}
+
+int test7s2()
+{
+ S7 s;
+ s.c = 7;
+ s.d = 2;
+ s.c += 4;
+ return s.d;
+}
+
+void test7()
+{
+ //printf("uns: %d\n", test7u());
+ assert(test7u() == 1);
+ //printf("sig: %d\n", test7s());
+ assert(test7s() == -1);
+ assert(test7s2() == -2);
+}
+
+static assert(test7u() == 1);
+static assert(test7s() == -1);
+static assert(test7s2() == -2);
+
+/******************************************/
+
+int main()
+{
+ test1();
+ test2();
+ test3();
+ test4();
+ test5();
+ test6();
+ test7();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gdc.test/runnable/interpret.d b/gcc/testsuite/gdc.test/runnable/interpret.d
index 6b1e89b..16d4c55 100644
--- a/gcc/testsuite/gdc.test/runnable/interpret.d
+++ b/gcc/testsuite/gdc.test/runnable/interpret.d
@@ -3454,6 +3454,21 @@ void test113()
}
/************************************************/
+
+bool test114()
+{
+ string fizzBuzz()
+ {
+ string result = "fizz ";
+ return result ~= "buzz";
+ }
+
+ assert(fizzBuzz() == "fizz buzz");
+ return true;
+}
+static assert(test114());
+
+/************************************************/
// https://issues.dlang.org/show_bug.cgi?id=14140
struct S14140
@@ -3852,6 +3867,7 @@ int main()
test109();
test112();
test113();
+ test114();
test6439();
test6504();
test8818();
diff --git a/gcc/testsuite/gdc.test/runnable/test17868b.d b/gcc/testsuite/gdc.test/runnable/test17868b.d
index d28cae2..44d6951 100644
--- a/gcc/testsuite/gdc.test/runnable/test17868b.d
+++ b/gcc/testsuite/gdc.test/runnable/test17868b.d
@@ -12,8 +12,6 @@ fini
import core.stdc.stdio;
-extern(C):
-
pragma(crt_constructor)
pragma(crt_destructor)
void ctor_dtor_1()
@@ -45,7 +43,7 @@ template fini()
alias instantiate = fini!();
-int main()
+extern(C) int main()
{
puts("main");
return 0;
diff --git a/gcc/testsuite/gdc.test/runnable/test20734.d b/gcc/testsuite/gdc.test/runnable/test20734.d
new file mode 100644
index 0000000..264602b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/test20734.d
@@ -0,0 +1,28 @@
+/*
+REQUIRED_ARGS: -betterC -preview=dip1000
+*/
+
+__gshared int numDtor;
+
+struct S
+{
+ int a;
+ ~this() nothrow @nogc @trusted { ++numDtor; }
+}
+
+void takeScopeSlice(const scope S[] slice) nothrow @nogc @safe {}
+
+extern(C) int main() nothrow @nogc @safe
+{
+ takeScopeSlice([ S(1), S(2) ]); // @nogc => no GC allocation
+ (() @trusted { assert(numDtor == 2); })(); // stack-allocated array literal properly destructed
+ return 0;
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=23098
+void f23098(scope inout(int)[] d) @safe {}
+
+void test23098() @safe
+{
+ f23098([10, 20]);
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test21416.d b/gcc/testsuite/gdc.test/runnable/test21416.d
new file mode 100644
index 0000000..88eebd8
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/test21416.d
@@ -0,0 +1,9 @@
+// https://issues.dlang.org/show_bug.cgi?id=21416
+
+// REQUIRED_ARGS: -betterC
+
+extern(C) void main() {}
+
+extern(C++) interface IEntry {}
+
+extern(C++) class MyEntryInfo : IEntry {}
diff --git a/gcc/testsuite/gdc.test/runnable/test23083.d b/gcc/testsuite/gdc.test/runnable/test23083.d
new file mode 100644
index 0000000..41c881f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/test23083.d
@@ -0,0 +1,16 @@
+// https://issues.dlang.org/show_bug.cgi?id=23083
+int calls = 0;
+
+int[2] f()
+{
+ calls++;
+ return [123, 456];
+}
+
+void g(int a, int b) {}
+
+void main()
+{
+ g(f().tupleof);
+ assert(calls == 1);
+}
diff --git a/gcc/testsuite/gdc.test/runnable/testcontracts.d b/gcc/testsuite/gdc.test/runnable/testcontracts.d
index ba0dc69..e79c6a0 100644
--- a/gcc/testsuite/gdc.test/runnable/testcontracts.d
+++ b/gcc/testsuite/gdc.test/runnable/testcontracts.d
@@ -1,19 +1,19 @@
/* PERMUTE_ARGS: -inline -g -O
TEST_OUTPUT:
---
-runnable/testcontracts.d(323): Deprecation: Usage of the `body` keyword is deprecated. Use `do` instead.
-runnable/testcontracts.d(324): Deprecation: Usage of the `body` keyword is deprecated. Use `do` instead.
-runnable/testcontracts.d(325): Deprecation: Usage of the `body` keyword is deprecated. Use `do` instead.
-runnable/testcontracts.d(326): Deprecation: Usage of the `body` keyword is deprecated. Use `do` instead.
-runnable/testcontracts.d(328): Deprecation: Usage of the `body` keyword is deprecated. Use `do` instead.
-runnable/testcontracts.d(329): Deprecation: Usage of the `body` keyword is deprecated. Use `do` instead.
-runnable/testcontracts.d(330): Deprecation: Usage of the `body` keyword is deprecated. Use `do` instead.
-runnable/testcontracts.d(331): Deprecation: Usage of the `body` keyword is deprecated. Use `do` instead.
-runnable/testcontracts.d(502): Deprecation: Usage of the `body` keyword is deprecated. Use `do` instead.
-runnable/testcontracts.d(503): Deprecation: Usage of the `body` keyword is deprecated. Use `do` instead.
-runnable/testcontracts.d(504): Deprecation: Usage of the `body` keyword is deprecated. Use `do` instead.
-runnable/testcontracts.d(505): Deprecation: Usage of the `body` keyword is deprecated. Use `do` instead.
-runnable/testcontracts.d(505): Deprecation: Usage of the `body` keyword is deprecated. Use `do` instead.
+runnable/testcontracts.d(323): Deprecation: usage of the `body` keyword is deprecated. Use `do` instead.
+runnable/testcontracts.d(324): Deprecation: usage of the `body` keyword is deprecated. Use `do` instead.
+runnable/testcontracts.d(325): Deprecation: usage of the `body` keyword is deprecated. Use `do` instead.
+runnable/testcontracts.d(326): Deprecation: usage of the `body` keyword is deprecated. Use `do` instead.
+runnable/testcontracts.d(328): Deprecation: usage of the `body` keyword is deprecated. Use `do` instead.
+runnable/testcontracts.d(329): Deprecation: usage of the `body` keyword is deprecated. Use `do` instead.
+runnable/testcontracts.d(330): Deprecation: usage of the `body` keyword is deprecated. Use `do` instead.
+runnable/testcontracts.d(331): Deprecation: usage of the `body` keyword is deprecated. Use `do` instead.
+runnable/testcontracts.d(502): Deprecation: usage of the `body` keyword is deprecated. Use `do` instead.
+runnable/testcontracts.d(503): Deprecation: usage of the `body` keyword is deprecated. Use `do` instead.
+runnable/testcontracts.d(504): Deprecation: usage of the `body` keyword is deprecated. Use `do` instead.
+runnable/testcontracts.d(505): Deprecation: usage of the `body` keyword is deprecated. Use `do` instead.
+runnable/testcontracts.d(505): Deprecation: usage of the `body` keyword is deprecated. Use `do` instead.
---
*/
extern(C) int printf(const char*, ...);