]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
d: Merge dmd, druntime 9471b25db9, phobos 547886846.
authorIain Buclaw <ibuclaw@gdcproject.org>
Sat, 17 Feb 2024 20:03:38 +0000 (21:03 +0100)
committerIain Buclaw <ibuclaw@gdcproject.org>
Sat, 17 Feb 2024 20:28:58 +0000 (21:28 +0100)
D front-end changes:

- Import dmd v2.107.1-rc.1.

D runtime changes:

- Import druntime v2.107.1-rc.1.

Phobos changes:

- Import phobos v2.107.1-rc.1.

gcc/d/ChangeLog:

* dmd/MERGE: Merge upstream dmd 9471b25db9.
* dmd/VERSION: Bump version to v2.107.1-rc.1.
* Make-lang.in (D_FRONTEND_OBJS): Add d/cxxfrontend.o.
* d-attribs.cc (build_attributes): Update for new front-end interface.
* d-builtins.cc (build_frontend_type): Likewise.
(strip_type_modifiers): Likewise.
(covariant_with_builtin_type_p): Likewise.
* d-codegen.cc (declaration_type): Likewise.
(parameter_type): Likewise.
(build_array_struct_comparison): Likewise.
(void_okay_p): Likewise.
* d-convert.cc (convert_expr): Likewise.
(check_valist_conversion): Likewise.
* d-lang.cc (d_generate_ddoc_file): Likewise.
(d_parse_file): Likewise.
* d-target.cc (TargetCPP::toMangle): Likewise.
(TargetCPP::typeInfoMangle): Likewise.
(TargetCPP::thunkMangle): Likewise.
(TargetCPP::parameterType): Likewise.
* decl.cc (d_mangle_decl): Likewise.
(DeclVisitor::visit): Likewise.
(DeclVisitor::visit (CAsmDeclaration *)): New method.
(get_symbol_decl): Update for new front-end interface.
(layout_class_initializer): Likewise.
* expr.cc (ExprVisitor::visit): Likewise.
* intrinsics.cc (maybe_set_intrinsic): Likewise.
(expand_intrinsic_rotate): Likewise.
* modules.cc (layout_moduleinfo_fields): Likewise.
(layout_moduleinfo): Likewise.
* runtime.cc (get_libcall_type): Likewise.
* typeinfo.cc (make_frontend_typeinfo): Likewise.
(TypeInfoVisitor::visit): Likewise.
(create_typeinfo): Likewise.
* types.cc (same_type_p): Likewise.
(build_ctype): Likewise.

libphobos/ChangeLog:

* libdruntime/MERGE: Merge upstream druntime 9471b25db9.
* src/MERGE: Merge upstream phobos 547886846.

86 files changed:
gcc/d/Make-lang.in
gcc/d/d-attribs.cc
gcc/d/d-builtins.cc
gcc/d/d-codegen.cc
gcc/d/d-convert.cc
gcc/d/d-lang.cc
gcc/d/d-target.cc
gcc/d/decl.cc
gcc/d/dmd/MERGE
gcc/d/dmd/VERSION
gcc/d/dmd/aggregate.h
gcc/d/dmd/cparse.d
gcc/d/dmd/cppmangle.d
gcc/d/dmd/cxxfrontend.d [new file with mode: 0644]
gcc/d/dmd/declaration.h
gcc/d/dmd/dinterpret.d
gcc/d/dmd/dmangle.d
gcc/d/dmd/dmodule.d
gcc/d/dmd/doc.d
gcc/d/dmd/doc.h
gcc/d/dmd/dscope.d
gcc/d/dmd/dstruct.d
gcc/d/dmd/dsymbol.d
gcc/d/dmd/dsymbol.h
gcc/d/dmd/dsymbolsem.d
gcc/d/dmd/dtemplate.d
gcc/d/dmd/dtoh.d
gcc/d/dmd/expression.d
gcc/d/dmd/expression.h
gcc/d/dmd/expressionsem.d
gcc/d/dmd/funcsem.d
gcc/d/dmd/gluelayer.d
gcc/d/dmd/hdrgen.d
gcc/d/dmd/hdrgen.h
gcc/d/dmd/iasm.d
gcc/d/dmd/iasmgcc.d
gcc/d/dmd/importc.d
gcc/d/dmd/init.h
gcc/d/dmd/initsem.d
gcc/d/dmd/json.d
gcc/d/dmd/json.h
gcc/d/dmd/mangle.h
gcc/d/dmd/module.h
gcc/d/dmd/mtype.d
gcc/d/dmd/mtype.h
gcc/d/dmd/optimize.d
gcc/d/dmd/parse.d
gcc/d/dmd/parsetimevisitor.d
gcc/d/dmd/semantic2.d
gcc/d/dmd/semantic3.d
gcc/d/dmd/statement.h
gcc/d/dmd/statementsem.d
gcc/d/dmd/target.d
gcc/d/dmd/template.h
gcc/d/dmd/templateparamsem.d
gcc/d/dmd/typesem.d
gcc/d/dmd/typinf.d
gcc/d/dmd/typinf.h
gcc/d/dmd/visitor.h
gcc/d/expr.cc
gcc/d/intrinsics.cc
gcc/d/modules.cc
gcc/d/runtime.cc
gcc/d/typeinfo.cc
gcc/d/types.cc
gcc/testsuite/gdc.test/compilable/imports/test24390a.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/imports/test24390b.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/interpret3.d
gcc/testsuite/gdc.test/compilable/test24390.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/traits.d
gcc/testsuite/gdc.test/fail_compilation/imports/issue21685.d
gcc/testsuite/gdc.test/fail_compilation/issue21685_main.d
gcc/testsuite/gdc.test/fail_compilation/test23786.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/link15021.d
gcc/testsuite/gdc.test/runnable/mars1.d
gcc/testsuite/gdc.test/runnable/staticaa.d
gcc/testsuite/gdc.test/runnable_cxx/test7925.d
libphobos/libdruntime/MERGE
libphobos/libdruntime/core/interpolation.d
libphobos/libdruntime/core/thread/fiber.d
libphobos/libdruntime/core/thread/osthread.d
libphobos/libdruntime/core/thread/threadbase.d
libphobos/src/MERGE
libphobos/src/std/algorithm/iteration.d
libphobos/src/std/algorithm/mutation.d
libphobos/src/std/range/package.d

index d379ef14f8060703dd52236a7ea2c8c7e80ffdad..eaea6e039cf70bac2e5f1248adc7cbc881ce38ad 100644 (file)
@@ -104,6 +104,7 @@ D_FRONTEND_OBJS = \
        d/cppmangle.o \
        d/ctfeexpr.o \
        d/ctorflow.o \
+       d/cxxfrontend.o \
        d/dcast.o \
        d/dclass.o \
        d/declaration.o \
index 36a139b4ec4e8e650386c25f1bf270f2e3fbac61..0f7ca10e0175ee1dedf2fa7477c6681636af7b2f 100644 (file)
@@ -320,14 +320,14 @@ build_attributes (Expressions *eattrs)
   if (!eattrs)
     return NULL_TREE;
 
-  expandTuples (eattrs);
+  dmd::expandTuples (eattrs);
 
   tree attribs = NULL_TREE;
 
   for (size_t i = 0; i < eattrs->length; i++)
     {
       Expression *attr = (*eattrs)[i];
-      Dsymbol *sym = toDsymbol (attr->type, NULL);
+      Dsymbol *sym = dmd::toDsymbol (attr->type, NULL);
 
       if (!sym)
        {
@@ -354,7 +354,7 @@ build_attributes (Expressions *eattrs)
 
       /* Get the result of the attribute if it hasn't already been folded.  */
       if (attr->op == EXP::call)
-       attr = ctfeInterpret (attr);
+       attr = dmd::ctfeInterpret (attr);
 
       if (attr->op != EXP::structLiteral)
        {
index 24ac456e23d9dc6833491c7b3b1c5c14f3db3ca7..dc50df4252c43cef024821b83fc87b765d067b11 100644 (file)
@@ -98,14 +98,14 @@ build_frontend_type (tree type)
          /* Check for char * first.  Needs to be done for chars/string.  */
          if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == char_type_node)
            {
-             dtype = addMod (Type::tchar, dtype->mod);
-             return addMod (dtype->pointerTo (), mod);
+             dtype = dmd::addMod (Type::tchar, dtype->mod);
+             return dmd::addMod (dmd::pointerTo (dtype), mod);
            }
 
          if (dtype->ty == TY::Tfunction)
-           return addMod (TypePointer::create (dtype), mod);
+           return dmd::addMod (TypePointer::create (dtype), mod);
 
-         return addMod (dtype->pointerTo (), mod);
+         return dmd::addMod (dmd::pointerTo (dtype), mod);
        }
       break;
 
@@ -116,7 +116,7 @@ build_frontend_type (tree type)
          /* Want to assign ctype directly so that the REFERENCE_TYPE code
             can be turned into as an `inout' argument.  Can't use pointerTo(),
             because the returned Type is shared.  */
-         dtype = addMod (TypePointer::create (dtype), mod);
+         dtype = dmd::addMod (TypePointer::create (dtype), mod);
          dtype->ctype = type;
          builtin_converted_decls.safe_push (builtin_data (dtype, type));
          return dtype;
@@ -125,7 +125,7 @@ build_frontend_type (tree type)
 
     case BOOLEAN_TYPE:
       /* Should be no need for size checking.  */
-      return addMod (Type::tbool, mod);
+      return dmd::addMod (Type::tbool, mod);
 
     case INTEGER_TYPE:
     {
@@ -143,7 +143,7 @@ build_frontend_type (tree type)
              || size != dtype->size ())
            continue;
 
-         return addMod (dtype, mod);
+         return dmd::addMod (dtype, mod);
        }
       break;
     }
@@ -160,7 +160,7 @@ build_frontend_type (tree type)
          if (dtype->size () != size)
            continue;
 
-         return addMod (dtype, mod);
+         return dmd::addMod (dtype, mod);
        }
       break;
     }
@@ -177,13 +177,13 @@ build_frontend_type (tree type)
          if (dtype->size () != size)
            continue;
 
-         return addMod (dtype, mod);
+         return dmd::addMod (dtype, mod);
        }
       break;
     }
 
     case VOID_TYPE:
-      return addMod (Type::tvoid, mod);
+      return dmd::addMod (Type::tvoid, mod);
 
     case ARRAY_TYPE:
       dtype = build_frontend_type (TREE_TYPE (type));
@@ -197,7 +197,8 @@ build_frontend_type (tree type)
          length = size_binop (PLUS_EXPR, size_one_node,
                               convert (sizetype, length));
 
-         dtype = addMod (dtype->sarrayOf (TREE_INT_CST_LOW (length)), mod);
+         dtype =
+           dmd::addMod (dtype->sarrayOf (TREE_INT_CST_LOW (length)), mod);
          builtin_converted_decls.safe_push (builtin_data (dtype, type));
          return dtype;
        }
@@ -213,11 +214,11 @@ build_frontend_type (tree type)
       if (!dtype)
        break;
 
-      dtype = addMod (dtype->sarrayOf (nunits), mod);
+      dtype = dmd::addMod (dtype->sarrayOf (nunits), mod);
       if (target.isVectorTypeSupported (dtype->size (), dtype->nextOf ()))
        break;
 
-      dtype = addMod (TypeVector::create (dtype), mod);
+      dtype = dmd::addMod (TypeVector::create (dtype), mod);
       builtin_converted_decls.safe_push (builtin_data (dtype, type));
       return dtype;
     }
@@ -241,9 +242,9 @@ build_frontend_type (tree type)
       sdecl->alignsize = TYPE_ALIGN_UNIT (type);
       sdecl->alignment.setDefault ();
       sdecl->sizeok = Sizeok::done;
-      sdecl->type = addMod (TypeStruct::create (sdecl), mod);
+      sdecl->type = dmd::addMod (TypeStruct::create (sdecl), mod);
       sdecl->type->ctype = type;
-      merge2 (sdecl->type);
+      dmd::merge2 (sdecl->type);
 
       /* Add both named and anonymous fields as members of the struct.
         Anonymous fields still need a name in D, so call them "__pad%u".  */
@@ -334,7 +335,7 @@ build_frontend_type (tree type)
          if (args->length != 0 || varargs_p == VARARGnone)
            {
              dtype = TypeFunction::create (args, dtype, varargs_p, LINK::c);
-             return addMod (dtype, mod);
+             return dmd::addMod (dtype, mod);
            }
        }
       break;
@@ -690,10 +691,10 @@ strip_type_modifiers (Type *type)
   if (type->ty == TY::Tpointer)
     {
       Type *tnext = strip_type_modifiers (type->nextOf ());
-      return tnext->pointerTo ();
+      return dmd::pointerTo (tnext);
     }
 
-  return castMod (type, 0);
+  return dmd::castMod (type, 0);
 }
 
 /* Returns true if types T1 and T2 representing return types or types of
@@ -727,7 +728,7 @@ static bool
 covariant_with_builtin_type_p (Type *t1, Type *t2)
 {
   /* Check whether the declared function matches the built-in.  */
-  if (same_type_p (t1, t2) || covariant (t1, t2) == Covariant::yes)
+  if (same_type_p (t1, t2) || dmd::covariant (t1, t2) == Covariant::yes)
     return true;
 
   /* May not be covariant because of D attributes applied on t1.
index dc528164aaffd6e001eb2268a7c252a3193cb61c..5bc233928aa86723f6ee4f582a3f3ca3206d9de6 100644 (file)
@@ -150,14 +150,14 @@ declaration_type (Declaration *decl)
       TypeFunction *tf = TypeFunction::create (NULL, decl->type,
                                               VARARGnone, LINK::d);
       TypeDelegate *t = TypeDelegate::create (tf);
-      return build_ctype (merge2 (t));
+      return build_ctype (dmd::merge2 (t));
     }
 
   /* Static array va_list have array->pointer conversions applied.  */
   if (decl->isParameter () && valist_array_p (decl->type))
     {
-      Type *valist = decl->type->nextOf ()->pointerTo ();
-      valist = castMod (valist, decl->type->mod);
+      Type *valist = dmd::pointerTo (decl->type->nextOf ());
+      valist = dmd::castMod (valist, decl->type->mod);
       return build_ctype (valist);
     }
 
@@ -200,14 +200,14 @@ parameter_type (Parameter *arg)
       TypeFunction *tf = TypeFunction::create (NULL, arg->type,
                                               VARARGnone, LINK::d);
       TypeDelegate *t = TypeDelegate::create (tf);
-      return build_ctype (merge2 (t));
+      return build_ctype (dmd::merge2 (t));
     }
 
   /* Static array va_list have array->pointer conversions applied.  */
   if (valist_array_p (arg->type))
     {
-      Type *valist = arg->type->nextOf ()->pointerTo ();
-      valist = castMod (valist, arg->type->mod);
+      Type *valist = dmd::pointerTo (arg->type->nextOf ());
+      valist = dmd::castMod (valist, arg->type->mod);
       return build_ctype (valist);
     }
 
@@ -1089,7 +1089,7 @@ build_array_struct_comparison (tree_code code, StructDeclaration *sd,
   add_stmt (build_assign (INIT_EXPR, result, init));
 
   /* Cast pointer-to-array to pointer-to-struct.  */
-  tree ptrtype = build_ctype (sd->type->pointerTo ());
+  tree ptrtype = build_ctype (dmd::pointerTo (sd->type));
   tree lentype = TREE_TYPE (length);
 
   push_binding_level (level_block);
@@ -1859,7 +1859,7 @@ void_okay_p (tree t)
 
   if (VOID_TYPE_P (TREE_TYPE (type)))
     {
-      tree totype = build_ctype (Type::tuns8->pointerTo ());
+      tree totype = build_ctype (dmd::pointerTo (Type::tuns8));
       return fold_convert (totype, t);
     }
 
index 011b22ec28cf154857b629c4a43fe3e7903e1480..4ccbf0908b5caa88ab98bab15c4ffeb1bd285fda 100644 (file)
@@ -470,7 +470,7 @@ convert_expr (tree exp, Type *etype, Type *totype)
          dinteger_t esize = ebtype->nextOf ()->size ();
          dinteger_t tsize = tbtype->nextOf ()->size ();
 
-         tree ptrtype = build_ctype (tbtype->nextOf ()->pointerTo ());
+         tree ptrtype = build_ctype (dmd::pointerTo (tbtype->nextOf ()));
 
          if (esize != tsize)
            {
@@ -727,12 +727,12 @@ check_valist_conversion (Expression *expr, Type *totype, bool in_assignment)
   if (VarExp *ve = expr->isVarExp ())
     {
       decl = ve->var;
-      type = ve->var->type->nextOf ()->pointerTo ();
+      type = dmd::pointerTo (ve->var->type->nextOf ());
     }
   else if (SymOffExp *se = expr->isSymOffExp ())
     {
       decl = se->var;
-      type = se->var->type->nextOf ()->pointerTo ()->pointerTo ();
+      type = dmd::pointerTo (dmd::pointerTo (se->var->type->nextOf ()));
     }
 
   /* Should not be called unless is_valist_parameter_type also matched.  */
index 138a7f9d0f98c59b782055ba2a8fd21db4cfc939..89ffa7e61ea1ece9d241a14ae0e132e5f7a76017 100644 (file)
@@ -1029,8 +1029,8 @@ d_generate_ddoc_file (Module *m, OutBuffer &ddocbuf)
   d_read_ddoc_files (global.params.ddoc.files, ddocbuf);
 
   OutBuffer ddocbuf_out;
-  gendocfile (m, ddocbuf.peekChars (), ddocbuf.length (), global.datetime,
-             global.errorSink, ddocbuf_out);
+  dmd::gendocfile (m, ddocbuf.peekChars (), ddocbuf.length (), global.datetime,
+                  global.errorSink, ddocbuf_out);
 
   d_write_file (m->docfile.toChars (), ddocbuf_out.peekChars ());
 }
@@ -1205,7 +1205,7 @@ d_parse_file (void)
            message ("import    %s", m->toChars ());
 
          OutBuffer buf;
-         genhdrfile (m, global.params.dihdr.fullOutput, buf);
+         dmd::genhdrfile (m, global.params.dihdr.fullOutput, buf);
          d_write_file (m->hdrfile.toChars (), buf.peekChars ());
        }
 
@@ -1223,7 +1223,7 @@ d_parse_file (void)
       if (global.params.v.verbose)
        message ("importall %s", m->toChars ());
 
-      importAll (m, NULL);
+      dmd::importAll (m, NULL);
     }
 
   if (global.errors)
@@ -1247,7 +1247,7 @@ d_parse_file (void)
       if (global.params.v.verbose)
        message ("semantic  %s", m->toChars ());
 
-      dsymbolSemantic (m, NULL);
+      dmd::dsymbolSemantic (m, NULL);
     }
 
   /* Do deferred semantic analysis.  */
@@ -1278,7 +1278,7 @@ d_parse_file (void)
       if (global.params.v.verbose)
        message ("semantic2 %s", m->toChars ());
 
-      semantic2 (m, NULL);
+      dmd::semantic2 (m, NULL);
     }
 
   Module::runDeferredSemantic2 ();
@@ -1294,7 +1294,7 @@ d_parse_file (void)
       if (global.params.v.verbose)
        message ("semantic3 %s", m->toChars ());
 
-      semantic3 (m, NULL);
+      dmd::semantic3 (m, NULL);
     }
 
   Module::runDeferredSemantic3 ();
@@ -1318,7 +1318,7 @@ d_parse_file (void)
       /* Declare the name of the root module as the first global name in order
         to make the middle-end fully deterministic.  */
       OutBuffer buf;
-      mangleToBuffer (Module::rootModule, buf);
+      dmd::mangleToBuffer (Module::rootModule, buf);
       first_global_object_name = buf.extractChars ();
     }
 
@@ -1341,15 +1341,15 @@ d_parse_file (void)
 
   if (global.params.v.templates)
     {
-      printTemplateStats (global.params.v.templatesListInstances,
-                         global.errorSink);
+      dmd::printTemplateStats (global.params.v.templatesListInstances,
+                              global.errorSink);
     }
 
   /* Generate JSON files.  */
   if (global.params.json.doOutput)
     {
       OutBuffer buf;
-      json_generate (modules, buf);
+      dmd::json_generate (modules, buf);
       d_write_file (global.params.json.name.ptr, buf.peekChars ());
     }
 
@@ -1372,14 +1372,14 @@ d_parse_file (void)
          OutBuffer buf;
          buf.doindent = 1;
 
-         moduleToBuffer (buf, true, m);
+         dmd::moduleToBuffer (buf, true, m);
          message ("%s", buf.peekChars ());
        }
     }
 
   /* Generate C++ header files.  */
   if (global.params.cxxhdr.doOutput)
-    genCppHdrFiles (modules);
+    dmd::genCppHdrFiles (modules);
 
   if (global.errors)
     goto had_errors;
index ff3489c6cf4e81a23f5ce4b1fb28f7b6cab13513..b9d124422b7a35c9161d27865a4d3a838015ea56 100644 (file)
@@ -335,7 +335,7 @@ Target::isVectorOpSupported (Type *type, EXP op, Type *)
 const char *
 TargetCPP::toMangle (Dsymbol *s)
 {
-  return toCppMangleItanium (s);
+  return dmd::toCppMangleItanium (s);
 }
 
 /* Return the symbol mangling of CD for C++ linkage.  */
@@ -343,7 +343,7 @@ TargetCPP::toMangle (Dsymbol *s)
 const char *
 TargetCPP::typeInfoMangle (ClassDeclaration *cd)
 {
-  return cppTypeInfoMangleItanium (cd);
+  return dmd::cppTypeInfoMangleItanium (cd);
 }
 
 /* Get mangle name of a this-adjusting thunk to the function declaration FD
@@ -352,7 +352,7 @@ TargetCPP::typeInfoMangle (ClassDeclaration *cd)
 const char *
 TargetCPP::thunkMangle (FuncDeclaration *fd, int offset)
 {
-  return cppThunkMangleItanium (fd, offset);
+  return dmd::cppThunkMangleItanium (fd, offset);
 }
 
 /* For a vendor-specific type, return a string containing the C++ mangling.
@@ -381,11 +381,11 @@ TargetCPP::parameterType (Type *type)
   Type *tvalist = target.va_listType (Loc (), NULL);
   if (type->ty == TY::Tsarray && tvalist->ty == TY::Tsarray)
     {
-      Type *tb = mutableOf (type->toBasetype ());
+      Type *tb = dmd::mutableOf (type->toBasetype ());
       if (tb == tvalist)
        {
-         tb = type->nextOf ()->pointerTo ();
-         type = castMod (tb, type->mod);
+         tb = dmd::pointerTo (type->nextOf ());
+         type = dmd::castMod (tb, type->mod);
        }
     }
 
index 827495b3e3036e39cb0572a576087384bb8d17d6..25398a323818a34e35f8739b732b126c6c3bd84d 100644 (file)
@@ -69,11 +69,11 @@ const char *
 d_mangle_decl (Dsymbol *decl)
 {
   if (decl->isFuncDeclaration ())
-    return mangleExact ((FuncDeclaration *) decl);
+    return dmd::mangleExact ((FuncDeclaration *) decl);
   else
     {
       OutBuffer buf;
-      mangleToBuffer (decl, buf);
+      dmd::mangleToBuffer (decl, buf);
       return buf.extractChars ();
     }
 }
@@ -332,6 +332,14 @@ public:
     d->semanticRun = PASS::obj;
   }
 
+  /* Finish a top-level `asm` definition.  */
+
+  void visit (CAsmDeclaration *d) final override
+  {
+    tree asm_str = build_expr (d->code);
+    symtab->finalize_toplevel_asm (asm_str);
+  }
+
   /* Expand any local variables found in tuples.  */
 
   void visit (TupleDeclaration *d) final override
@@ -402,7 +410,7 @@ public:
 
   void visit (Nspace *d) final override
   {
-    if (isError (d) || !d->members)
+    if (dmd::isError (d) || !d->members)
       return;
 
     for (size_t i = 0; i < d->members->length; i++)
@@ -447,7 +455,7 @@ public:
 
   void visit (TemplateInstance *d) final override
   {
-    if (isError (d)|| !d->members)
+    if (dmd::isError (d)|| !d->members)
       return;
 
     if (!d->needsCodegen ())
@@ -461,7 +469,7 @@ public:
 
   void visit (TemplateMixin *d) final override
   {
-    if (isError (d)|| !d->members)
+    if (dmd::isError (d)|| !d->members)
       return;
 
     for (size_t i = 0; i < d->members->length; i++)
@@ -539,7 +547,7 @@ public:
          continue;
 
        /* Ensure function has a return value.  */
-       if (!functionSemantic (fd))
+       if (!dmd::functionSemantic (fd))
          has_errors = true;
 
        /* No name hiding to check for.  */
@@ -765,7 +773,7 @@ public:
            && d->_init && !d->_init->isVoidInitializer ())
          {
            /* Evaluate RHS for side effects first.  */
-           Expression *ie = initializerToExpression (d->_init);
+           Expression *ie = dmd::initializerToExpression (d->_init);
            add_stmt (build_expr (ie));
 
            Expression *e = d->type->defaultInitLiteral (d->loc);
@@ -785,7 +793,7 @@ public:
       {
        /* Do not store variables we cannot take the address of,
           but keep the values for purposes of debugging.  */
-       if (d->type->isscalar () && !hasPointers (d->type))
+       if (d->type->isscalar () && !dmd::hasPointers (d->type))
          {
            tree decl = get_symbol_decl (d);
            d_pushdecl (decl);
@@ -820,7 +828,8 @@ public:
            /* Use the explicit initializer, this includes `void`.  */
            if (!d->_init->isVoidInitializer ())
              {
-               Expression *e = initializerToExpression (d->_init, d->type);
+               Expression *e =
+                 dmd::initializerToExpression (d->_init, d->type);
                DECL_INITIAL (decl) = build_expr (e, true);
              }
          }
@@ -857,7 +866,7 @@ public:
            tree decl = get_symbol_decl (d);
 
            ExpInitializer *vinit = d->_init->isExpInitializer ();
-           Expression *ie = initializerToExpression (vinit);
+           Expression *ie = dmd::initializerToExpression (vinit);
            tree exp = build_expr (ie);
 
            /* Maybe put variable on list of things needing destruction.  */
@@ -964,7 +973,7 @@ public:
        gcc_assert (!doing_semantic_analysis_p);
 
        doing_semantic_analysis_p = true;
-       functionSemantic3 (d);
+       dmd::functionSemantic3 (d);
        Module::runDeferredSemantic3 ();
        doing_semantic_analysis_p = false;
       }
@@ -1241,7 +1250,7 @@ get_symbol_decl (Declaration *decl)
       if (!vd->canTakeAddressOf () && !vd->type->isscalar ())
        {
          gcc_assert (vd->_init && !vd->_init->isVoidInitializer ());
-         Expression *ie = initializerToExpression (vd->_init);
+         Expression *ie = dmd::initializerToExpression (vd->_init);
          decl->csym = build_expr (ie, false);
          return decl->csym;
        }
@@ -1252,7 +1261,7 @@ get_symbol_decl (Declaration *decl)
   if (fd)
     {
       /* Run full semantic on functions we need to know about.  */
-      if (!functionSemantic (fd))
+      if (!dmd::functionSemantic (fd))
        {
          decl->csym = error_mark_node;
          return decl->csym;
@@ -1301,7 +1310,7 @@ get_symbol_decl (Declaration *decl)
          /* Non-scalar manifest constants have already been dealt with.  */
          gcc_assert (vd->type->isscalar ());
 
-         Expression *ie = initializerToExpression (vd->_init);
+         Expression *ie = dmd::initializerToExpression (vd->_init);
          DECL_INITIAL (decl->csym) = build_expr (ie, true);
        }
 
@@ -2398,7 +2407,7 @@ layout_class_initializer (ClassDeclaration *cd)
   NewExp *ne = NewExp::create (cd->loc, NULL, cd->type, NULL);
   ne->type = cd->type;
 
-  Expression *e = ctfeInterpret (ne);
+  Expression *e = dmd::ctfeInterpret (ne);
   gcc_assert (e->op == EXP::classReference);
 
   return build_class_instance (e->isClassReferenceExp ());
index 74c194508f7da3a91bc6c1233a66d5bdb2d0a3c3..021149aabc7c2da4d7c25583fab900492ada8bea 100644 (file)
@@ -1,4 +1,4 @@
-11240a96635074b2f79d908b9348e9c0fbc3c7dc
+9471b25db9ed44d71e0e27956430c0c6a09c16db
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
index 8463aee451ce4976ad63d6dbd02b34d000558178..1880c9808c5584ca730fd962c14a3a149e9d60e7 100644 (file)
@@ -1 +1 @@
-v2.107.0
+v2.107.1-rc.1
index 6a864002e088242bcb669d43bba65ffa3e342945..c972f0a6631ffba505e089e7b377fb07ed042ee4 100644 (file)
@@ -41,8 +41,11 @@ enum class Baseok : uint8_t
     semanticdone  // all base classes semantic done
 };
 
-FuncDeclaration *search_toString(StructDeclaration *sd);
-void semanticTypeInfoMembers(StructDeclaration *sd);
+namespace dmd
+{
+    FuncDeclaration *search_toString(StructDeclaration *sd);
+    void semanticTypeInfoMembers(StructDeclaration *sd);
+}
 
 enum class ClassKind : uint8_t
 {
index d462350581632987548ac64f403e0abe6198ae58..536a212536dab65e56649ddf093ca3ae3c2604b2 100644 (file)
@@ -136,6 +136,23 @@ final class CParser(AST) : Parser!AST
                 return wrap;
             }
 
+            /* GNU Extensions
+             * external-declaration:
+             *    simple-asm-expr ;
+             */
+            if (token.value == TOK.asm_)
+            {
+                nextToken();     // move past asm
+                check(TOK.leftParenthesis);
+                if (token.value != TOK.string_)
+                    error("string literal expected for Asm Definition, not `%s`", token.toChars());
+                auto code = cparsePrimaryExp();
+                check(TOK.rightParenthesis);
+                symbols.push(new AST.CAsmDeclaration(code));
+                check(TOK.semicolon);
+                continue;
+            }
+
             cparseDeclaration(LVL.global);
         }
     }
index 90b6295ab2fd77673b2e8bedda7006d0fe9fb847..0116aa35c8c05fcaab3d298b1c0cb9af5e438d64 100644 (file)
@@ -65,7 +65,7 @@ package CppOperator isCppOperator(Identifier id)
 }
 
 ///
-extern(C++) const(char)* toCppMangleItanium(Dsymbol s)
+const(char)* toCppMangleItanium(Dsymbol s)
 {
     //printf("toCppMangleItanium(%s)\n", s.toChars());
     OutBuffer buf;
@@ -75,7 +75,7 @@ extern(C++) const(char)* toCppMangleItanium(Dsymbol s)
 }
 
 ///
-extern(C++) const(char)* cppTypeInfoMangleItanium(Dsymbol s)
+const(char)* cppTypeInfoMangleItanium(Dsymbol s)
 {
     //printf("cppTypeInfoMangle(%s)\n", s.toChars());
     OutBuffer buf;
@@ -86,7 +86,7 @@ extern(C++) const(char)* cppTypeInfoMangleItanium(Dsymbol s)
 }
 
 ///
-extern(C++) const(char)* cppThunkMangleItanium(FuncDeclaration fd, int offset)
+const(char)* cppThunkMangleItanium(FuncDeclaration fd, int offset)
 {
     //printf("cppThunkMangleItanium(%s)\n", fd.toChars());
     OutBuffer buf;
diff --git a/gcc/d/dmd/cxxfrontend.d b/gcc/d/dmd/cxxfrontend.d
new file mode 100644 (file)
index 0000000..1b94a69
--- /dev/null
@@ -0,0 +1,623 @@
+/**
+ * Contains C++ interfaces for interacting with DMD as a library.
+ *
+ * Copyright:   Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved
+ * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
+ * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cxxfrontend.d, _cxxfrontend.d)
+ * Documentation:  https://dlang.org/phobos/dmd_cxxfrontend.html
+ * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/cxxfrontend.d
+ */
+module dmd.cxxfrontend;
+
+import dmd.aggregate : AggregateDeclaration;
+import dmd.arraytypes;
+import dmd.astenums;
+import dmd.common.outbuffer : OutBuffer;
+import dmd.dmodule /*: Module*/;
+import dmd.dscope : Scope;
+import dmd.dstruct /*: StructDeclaration*/;
+import dmd.dsymbol : Dsymbol, ScopeDsymbol, CAsmDeclaration, SearchOpt, SearchOptFlags;
+import dmd.dtemplate /*: TemplateInstance, TemplateParameter, Tuple*/;
+import dmd.errorsink : ErrorSink;
+import dmd.expression /*: Expression*/;
+import dmd.func : FuncDeclaration;
+import dmd.globals;
+import dmd.identifier : Identifier;
+import dmd.init : Initializer, NeedInterpret;
+import dmd.location : Loc;
+import dmd.mtype /*: Covariant, Type, Parameter, ParameterList*/;
+import dmd.rootobject : RootObject;
+import dmd.statement : Statement, AsmStatement, GccAsmStatement;
+
+// NB: At some point in the future, we can switch to shortened function syntax.
+extern (C++, "dmd"):
+
+/***********************************************************
+ * cppmangle.d
+ */
+const(char)* toCppMangleItanium(Dsymbol s)
+{
+    import dmd.cppmangle;
+    return dmd.cppmangle.toCppMangleItanium(s);
+}
+
+const(char)* cppTypeInfoMangleItanium(Dsymbol s)
+{
+    import dmd.cppmangle;
+    return dmd.cppmangle.cppTypeInfoMangleItanium(s);
+}
+
+const(char)* cppThunkMangleItanium(FuncDeclaration fd, int offset)
+{
+    import dmd.cppmangle;
+    return dmd.cppmangle.cppThunkMangleItanium(fd, offset);
+}
+
+/***********************************************************
+ * dinterpret.d
+ */
+Expression ctfeInterpret(Expression e)
+{
+    import dmd.dinterpret;
+    return dmd.dinterpret.ctfeInterpret(e);
+}
+
+/***********************************************************
+ * dmangle.d
+ */
+const(char)* mangleExact(FuncDeclaration fd)
+{
+    import dmd.dmangle;
+    return dmd.dmangle.mangleExact(fd);
+}
+
+void mangleToBuffer(Type t, ref OutBuffer buf)
+{
+    import dmd.dmangle;
+    return dmd.dmangle.mangleToBuffer(t, buf);
+}
+
+void mangleToBuffer(Expression e, ref OutBuffer buf)
+{
+    import dmd.dmangle;
+    return dmd.dmangle.mangleToBuffer(e, buf);
+}
+
+void mangleToBuffer(Dsymbol s, ref OutBuffer buf)
+{
+    import dmd.dmangle;
+    return dmd.dmangle.mangleToBuffer(s, buf);
+}
+
+void mangleToBuffer(TemplateInstance ti, ref OutBuffer buf)
+{
+    import dmd.dmangle;
+    return dmd.dmangle.mangleToBuffer(ti, buf);
+}
+
+/***********************************************************
+ * dmodule.d
+ */
+void getLocalClasses(Module mod, ref ClassDeclarations aclasses)
+{
+    return dmd.dmodule.getLocalClasses(mod, aclasses);
+}
+
+FuncDeclaration findGetMembers(ScopeDsymbol dsym)
+{
+    return dmd.dmodule.findGetMembers(dsym);
+}
+
+/***********************************************************
+ * doc.d
+ */
+void gendocfile(Module m, const char* ddoctext_ptr, size_t ddoctext_length,
+                const char* datetime, ErrorSink eSink, ref OutBuffer outbuf)
+{
+    import dmd.doc;
+    return dmd.doc.gendocfile(m, ddoctext_ptr, ddoctext_length, datetime, eSink, outbuf);
+}
+
+/***********************************************************
+ * dstruct.d
+ */
+FuncDeclaration search_toString(StructDeclaration sd)
+{
+    return dmd.dstruct.search_toString(sd);
+}
+
+/***********************************************************
+ * dsymbolsem.d
+ */
+void dsymbolSemantic(Dsymbol dsym, Scope* sc)
+{
+    import dmd.dsymbolsem;
+    return dmd.dsymbolsem.dsymbolSemantic(dsym, sc);
+}
+
+void addMember(Dsymbol dsym, Scope* sc, ScopeDsymbol sds)
+{
+    import dmd.dsymbolsem;
+    return dmd.dsymbolsem.addMember(dsym, sc, sds);
+}
+
+Dsymbol search(Dsymbol d, const ref Loc loc, Identifier ident, SearchOptFlags
+               flags = SearchOpt.all)
+{
+    import dmd.dsymbolsem;
+    return dmd.dsymbolsem.search(d, loc, ident, flags);
+}
+
+void setScope(Dsymbol d, Scope* sc)
+{
+    import dmd.dsymbolsem;
+    return dmd.dsymbolsem.setScope(d, sc);
+}
+
+void importAll(Dsymbol d, Scope* sc)
+{
+    import dmd.dsymbolsem;
+    return dmd.dsymbolsem.importAll(d, sc);
+}
+
+/***********************************************************
+ * dtemplate.d
+ */
+inout(Expression) isExpression(inout RootObject o)
+{
+    return dmd.dtemplate.isExpression(o);
+}
+
+inout(Dsymbol) isDsymbol(inout RootObject o)
+{
+    return dmd.dtemplate.isDsymbol(o);
+}
+
+inout(Type) isType(inout RootObject o)
+{
+    return dmd.dtemplate.isType(o);
+}
+
+inout(Tuple) isTuple(inout RootObject o)
+{
+    return dmd.dtemplate.isTuple(o);
+}
+
+inout(Parameter) isParameter(inout RootObject o)
+{
+    return dmd.dtemplate.isParameter(o);
+}
+
+inout(TemplateParameter) isTemplateParameter(inout RootObject o)
+{
+    return dmd.dtemplate.isTemplateParameter(o);
+}
+
+bool isError(const RootObject o)
+{
+    return dmd.dtemplate.isError(o);
+}
+
+void printTemplateStats(bool listInstances, ErrorSink eSink)
+{
+    return dmd.dtemplate.printTemplateStats(listInstances, eSink);
+}
+
+/***********************************************************
+ * dtoh.d
+ */
+void genCppHdrFiles(ref Modules ms)
+{
+    import dmd.dtoh;
+    return dmd.dtoh.genCppHdrFiles(ms);
+}
+
+/***********************************************************
+ * expression.d
+ */
+void expandTuples(Expressions* exps, Identifiers* names = null)
+{
+    return dmd.expression.expandTuples(exps, names);
+}
+
+/***********************************************************
+ * expressionsem.d
+ */
+Expression expressionSemantic(Expression e, Scope* sc)
+{
+    import dmd.expressionsem;
+    return dmd.expressionsem.expressionSemantic(e, sc);
+}
+
+/***********************************************************
+ * funcsem.d
+ */
+bool functionSemantic(FuncDeclaration fd)
+{
+    import dmd.funcsem;
+    return dmd.funcsem.functionSemantic(fd);
+}
+
+bool functionSemantic3(FuncDeclaration fd)
+{
+    import dmd.funcsem;
+    return dmd.funcsem.functionSemantic3(fd);
+}
+
+/***********************************************************
+ * hdrgen.d
+ */
+void genhdrfile(Module m, bool doFuncBodies, ref OutBuffer buf)
+{
+    import dmd.hdrgen;
+    return dmd.hdrgen.genhdrfile(m, doFuncBodies, buf);
+}
+
+const(char)* toChars(const Statement s)
+{
+    import dmd.hdrgen;
+    return dmd.hdrgen.toChars(s);
+}
+
+const(char)* toChars(const Expression e)
+{
+    import dmd.hdrgen;
+    return dmd.hdrgen.toChars(e);
+}
+
+const(char)* toChars(const Initializer i)
+{
+    import dmd.hdrgen;
+    return dmd.hdrgen.toChars(i);
+}
+
+const(char)* toChars(const Type t)
+{
+    import dmd.hdrgen;
+    return dmd.hdrgen.toChars(t);
+}
+
+void moduleToBuffer(ref OutBuffer buf, bool vcg_ast, Module m)
+{
+    import dmd.hdrgen;
+    return dmd.hdrgen.moduleToBuffer(buf, vcg_ast, m);
+}
+
+const(char)* parametersTypeToChars(ParameterList pl)
+{
+    import dmd.hdrgen;
+    return dmd.hdrgen.parametersTypeToChars(pl);
+}
+
+/***********************************************************
+ * iasm.d
+ */
+Statement asmSemantic(AsmStatement s, Scope *sc)
+{
+    import dmd.iasm;
+    return dmd.iasm.asmSemantic(s, sc);
+}
+
+void asmSemantic(CAsmDeclaration d, Scope *sc)
+{
+    import dmd.iasm;
+    return dmd.iasm.asmSemantic(d, sc);
+}
+
+/***********************************************************
+ * iasmgcc.d
+ */
+Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
+{
+    import dmd.iasmgcc;
+    return dmd.iasmgcc.gccAsmSemantic(s, sc);
+}
+
+void gccAsmSemantic(CAsmDeclaration d, Scope *sc)
+{
+    import dmd.iasmgcc;
+    return dmd.iasmgcc.gccAsmSemantic(d, sc);
+}
+
+/***********************************************************
+ * initsem.d
+ */
+Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx,
+                                NeedInterpret needInterpret)
+{
+    import dmd.initsem;
+    return dmd.initsem.initializerSemantic(init, sc, tx, needInterpret);
+}
+
+Expression initializerToExpression(Initializer init, Type itype = null, const
+                                   bool isCfile = false)
+{
+    import dmd.initsem;
+    return dmd.initsem.initializerToExpression(init, itype, isCfile);
+}
+
+/***********************************************************
+ * json.d
+ */
+void json_generate(ref Modules modules, ref OutBuffer buf)
+{
+    import dmd.json;
+    return dmd.json.json_generate(modules, buf);
+}
+
+JsonFieldFlags tryParseJsonField(const(char)* fieldName)
+{
+    import dmd.json;
+    return dmd.json.tryParseJsonField(fieldName);
+}
+
+/***********************************************************
+ * mtype.d
+ */
+AggregateDeclaration isAggregate(Type t)
+{
+    return dmd.mtype.isAggregate(t);
+}
+
+/***********************************************************
+ * optimize.d
+ */
+Expression optimize(Expression e, int result, bool keepLvalue = false)
+{
+    import dmd.optimize;
+    return dmd.optimize.optimize(e, result, keepLvalue);
+}
+
+/***********************************************************
+ * semantic2.d
+ */
+void semantic2(Dsymbol dsym, Scope* sc)
+{
+    import dmd.semantic2;
+    return dmd.semantic2.semantic2(dsym, sc);
+}
+
+/***********************************************************
+ * semantic3.d
+ */
+void semantic3(Dsymbol dsym, Scope* sc)
+{
+    import dmd.semantic3;
+    return dmd.semantic3.semantic3(dsym, sc);
+}
+
+void semanticTypeInfoMembers(StructDeclaration sd)
+{
+    import dmd.semantic3;
+    return dmd.semantic3.semanticTypeInfoMembers(sd);
+}
+
+/***********************************************************
+ * statementsem.d
+ */
+Statement statementSemantic(Statement s, Scope* sc)
+{
+    import dmd.statementsem;
+    return dmd.statementsem.statementSemantic(s, sc);
+}
+
+/***********************************************************
+ * templateparamsem.d
+ */
+bool tpsemantic(TemplateParameter tp, Scope* sc, TemplateParameters* parameters)
+{
+    import dmd.templateparamsem;
+    return dmd.templateparamsem.tpsemantic(tp, sc, parameters);
+}
+
+/***********************************************************
+ * typesem.d
+ */
+bool hasPointers(Type t)
+{
+    import dmd.typesem;
+    return dmd.typesem.hasPointers(t);
+}
+
+Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
+{
+    import dmd.typesem;
+    return dmd.typesem.typeSemantic(type, loc, sc);
+}
+
+Type trySemantic(Type type, const ref Loc loc, Scope* sc)
+{
+    import dmd.typesem;
+    return dmd.typesem.trySemantic(type, loc, sc);
+}
+
+Type merge(Type type)
+{
+    import dmd.typesem;
+    return dmd.typesem.merge(type);
+}
+
+Type merge2(Type type)
+{
+    import dmd.typesem;
+    return dmd.typesem.merge2(type);
+}
+
+Expression defaultInit(Type mt, const ref Loc loc, const bool isCfile = false)
+{
+    import dmd.typesem;
+    return dmd.typesem.defaultInit(mt, loc, isCfile);
+}
+
+Dsymbol toDsymbol(Type type, Scope* sc)
+{
+    import dmd.typesem;
+    return dmd.typesem.toDsymbol(type, sc);
+}
+
+Covariant covariant(Type src, Type t, StorageClass* pstc = null, bool
+                    cppCovariant = false)
+{
+    import dmd.typesem;
+    return dmd.typesem.covariant(src, t, pstc, cppCovariant);
+}
+
+bool isBaseOf(Type tthis, Type t, int* poffset)
+{
+    import dmd.typesem;
+    return dmd.typesem.isBaseOf(tthis, t, poffset);
+}
+
+bool equivalent(Type src, Type t)
+{
+    import dmd.typesem;
+    return dmd.typesem.equivalent(src, t);
+}
+
+Type constOf(Type type)
+{
+    import dmd.typesem;
+    return dmd.typesem.constOf(type);
+}
+
+Type immutableOf(Type type)
+{
+    import dmd.typesem;
+    return dmd.typesem.immutableOf(type);
+}
+
+Type mutableOf(Type type)
+{
+    import dmd.typesem;
+    return dmd.typesem.mutableOf(type);
+}
+
+Type sharedOf(Type type)
+{
+    import dmd.typesem;
+    return dmd.typesem.sharedOf(type);
+}
+
+Type sharedConstOf(Type type)
+{
+    import dmd.typesem;
+    return dmd.typesem.sharedConstOf(type);
+}
+
+Type unSharedOf(Type type)
+{
+    import dmd.typesem;
+    return dmd.typesem.unSharedOf(type);
+}
+
+Type wildOf(Type type)
+{
+    import dmd.typesem;
+    return dmd.typesem.wildOf(type);
+}
+
+Type wildConstOf(Type type)
+{
+    import dmd.typesem;
+    return dmd.typesem.wildConstOf(type);
+}
+
+Type sharedWildOf(Type type)
+{
+    import dmd.typesem;
+    return dmd.typesem.sharedWildOf(type);
+}
+
+Type sharedWildConstOf(Type type)
+{
+    import dmd.typesem;
+    return dmd.typesem.sharedWildConstOf(type);
+}
+
+Type castMod(Type type, MOD mod)
+{
+    import dmd.typesem;
+    return dmd.typesem.castMod(type, mod);
+}
+
+Type addMod(Type type, MOD mod)
+{
+    import dmd.typesem;
+    return dmd.typesem.addMod(type, mod);
+}
+
+Type addStorageClass(Type type, StorageClass stc)
+{
+    import dmd.typesem;
+    return dmd.typesem.addStorageClass(type, stc);
+}
+
+Type pointerTo(Type type)
+{
+    import dmd.typesem;
+    return dmd.typesem.pointerTo(type);
+}
+
+Type referenceTo(Type type)
+{
+    import dmd.typesem;
+    return dmd.typesem.referenceTo(type);
+}
+
+/***********************************************************
+ * typinf.d
+ */
+bool genTypeInfo(Expression e, const ref Loc loc, Type torig, Scope* sc)
+{
+    import dmd.typinf;
+    return dmd.typinf.genTypeInfo(e, loc, torig, sc);
+}
+
+bool isSpeculativeType(Type t)
+{
+    import dmd.typinf;
+    return dmd.typinf.isSpeculativeType(t);
+}
+
+bool builtinTypeInfo(Type t)
+{
+    import dmd.typinf;
+    return dmd.typinf.builtinTypeInfo(t);
+}
+
+version (IN_LLVM)
+{
+    /***********************************************************
+     * argtypes_aarch64.d
+     */
+    TypeTuple toArgTypes_aarch64(Type t)
+    {
+        import dmd.argtypes_aarch64;
+        return dmd.argtypes_aarch64.toArgTypes_aarch64(t);
+    }
+
+    bool isHFVA(Type t, int maxNumElements = 4, Type* rewriteType = null)
+    {
+        import dmd.argtypes_aarch64;
+        return dmd.argtypes_aarch64.isHFVA(t, maxNumElements, rewriteType);
+    }
+
+    /***********************************************************
+     * argtypes_sysv_x64.d
+     */
+    TypeTuple toArgTypes_sysv_x64(Type t)
+    {
+        import dmd.argtypes_sysv_x64;
+        return dmd.argtypes_sysv_x64.toArgTypes_sysv_x64(t);
+    }
+
+    /***********************************************************
+     * argtypes_x86.d
+     */
+    TypeTuple toArgTypes_x86(Type t)
+    {
+        import dmd.argtypes_x86;
+        return dmd.argtypes_x86.toArgTypes_x86(t);
+    }
+}
index a393da80c097ae793ffe46c44f266a7044473727..998beba97dde88fd77605b8fdda6f28506799eea 100644 (file)
@@ -30,8 +30,11 @@ class StructDeclaration;
 struct IntRange;
 struct AttributeViolation;
 
-bool functionSemantic(FuncDeclaration* fd);
-bool functionSemantic3(FuncDeclaration* fd);
+namespace dmd
+{
+    bool functionSemantic(FuncDeclaration* fd);
+    bool functionSemantic3(FuncDeclaration* fd);
+}
 
 //enum STC : ulong from astenums.d:
 
index c3395a584e20bce60eb5ca7aa48da9f570e0fbb6..467e29f3c3cd1e66e7eaa53466d646a21d45355e 100644 (file)
@@ -50,7 +50,7 @@ import dmd.rootobject;
 import dmd.root.utf;
 import dmd.statement;
 import dmd.tokens;
-import dmd.typesem : mutableOf, equivalent;
+import dmd.typesem : mutableOf, equivalent, pointerTo;
 import dmd.utils : arrayCastBigEndian;
 import dmd.visitor;
 
@@ -63,7 +63,7 @@ import dmd.visitor;
  * functions and may invoke a function that contains `ErrorStatement` in its body.
  * If that, the "CTFE failed because of previous errors" error is raised.
  */
-extern(C++) public Expression ctfeInterpret(Expression e)
+public Expression ctfeInterpret(Expression e)
 {
     switch (e.op)
     {
index 1d016479e1d9c009fd52129f8aa21c4e03b74f68..33428ded2d1db7504a5062c2afbcc4eb6e7d9d55 100644 (file)
@@ -18,7 +18,7 @@ module dmd.dmangle;
 /******************************************************************************
  * Returns exact mangled name of function.
  */
-extern (C++) const(char)* mangleExact(FuncDeclaration fd)
+const(char)* mangleExact(FuncDeclaration fd)
 {
     //printf("mangleExact()\n");
     if (!fd.mangleString)
@@ -32,7 +32,7 @@ extern (C++) const(char)* mangleExact(FuncDeclaration fd)
     return fd.mangleString;
 }
 
-extern (C++) void mangleToBuffer(Type t, ref OutBuffer buf)
+void mangleToBuffer(Type t, ref OutBuffer buf)
 {
     //printf("mangleToBuffer t()\n");
     if (t.deco)
@@ -45,7 +45,7 @@ extern (C++) void mangleToBuffer(Type t, ref OutBuffer buf)
     }
 }
 
-extern (C++) void mangleToBuffer(Expression e, ref OutBuffer buf)
+void mangleToBuffer(Expression e, ref OutBuffer buf)
 {
     //printf("mangleToBuffer e()\n");
     auto backref = Backref(null);
@@ -53,7 +53,7 @@ extern (C++) void mangleToBuffer(Expression e, ref OutBuffer buf)
     e.accept(v);
 }
 
-extern (C++) void mangleToBuffer(Dsymbol s, ref OutBuffer buf)
+void mangleToBuffer(Dsymbol s, ref OutBuffer buf)
 {
     //printf("mangleToBuffer s(%s)\n", s.toChars());
     auto backref = Backref(null);
@@ -61,7 +61,7 @@ extern (C++) void mangleToBuffer(Dsymbol s, ref OutBuffer buf)
     s.accept(v);
 }
 
-extern (C++) void mangleToBuffer(TemplateInstance ti, ref OutBuffer buf)
+void mangleToBuffer(TemplateInstance ti, ref OutBuffer buf)
 {
     //printf("mangleToBuffer ti()\n");
     auto backref = Backref(null);
index 6167e2a748668b9a8ddce58153570f3eab500dc1..07d5077ee49c63ba1c2d11a938f7b3f4d08a6e10 100644 (file)
@@ -1300,7 +1300,7 @@ extern (C++) struct ModuleDeclaration
  *      aclasses = array to fill in
  * Returns: array of local classes
  */
-extern (C++) void getLocalClasses(Module mod, ref ClassDeclarations aclasses)
+void getLocalClasses(Module mod, ref ClassDeclarations aclasses)
 {
     //printf("members.length = %d\n", mod.members.length);
     int pushAddClassDg(size_t n, Dsymbol sm)
@@ -1565,7 +1565,7 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod)
  *      const(MemberInfo)[] getMembers(string);
  * Returns NULL if not found
  */
-extern(C++) FuncDeclaration findGetMembers(ScopeDsymbol dsym)
+FuncDeclaration findGetMembers(ScopeDsymbol dsym)
 {
     import dmd.opover : search_function;
     Dsymbol s = search_function(dsym, Id.getmembers);
index bcf358cb5e9dbec3dced2a41861f2f74425471b3..c00c1cc8f40d8555f83066dbba3d6de62433a782 100644 (file)
@@ -382,7 +382,7 @@ immutable ddoc_decl_dd_e = ")\n";
  *      outbuf = append the Ddoc text to this
  */
 public
-extern(C++) void gendocfile(Module m, const char* ddoctext_ptr, size_t ddoctext_length, const char* datetime, ErrorSink eSink, ref OutBuffer outbuf)
+void gendocfile(Module m, const char* ddoctext_ptr, size_t ddoctext_length, const char* datetime, ErrorSink eSink, ref OutBuffer outbuf)
 {
     gendocfile(m, ddoctext_ptr[0 .. ddoctext_length], datetime, eSink, outbuf);
 }
index 71a66b90cb8ef4e5483ef70009f8f2df302efc30..1775e354e00c24b5debe36aafb2dbf77bd1314ec 100644 (file)
@@ -15,5 +15,8 @@
 class Module;
 class ErrorSink;
 
-void gendocfile(Module *m, const char *ddoctext_ptr, d_size_t ddoctext_length,
-                const char *datetime, ErrorSink *eSink, OutBuffer &outbuf);
+namespace dmd
+{
+    void gendocfile(Module *m, const char *ddoctext_ptr, d_size_t ddoctext_length,
+                    const char *datetime, ErrorSink *eSink, OutBuffer &outbuf);
+}
index e02ba9a873bacc6ea012ed6b1832fad4c5339368..76a26a245fb48573cb1fc016843acfe2eb954a36 100644 (file)
@@ -34,6 +34,7 @@ import dmd.func;
 import dmd.globals;
 import dmd.id;
 import dmd.identifier;
+import dmd.importc;
 import dmd.location;
 import dmd.common.outbuffer;
 import dmd.root.rmem;
index 7546fb6146b421799003cbb17ce134eb5bb4caa8..df4d07a81d997f331df317f5b1bcc3665b9f603f 100644 (file)
@@ -48,7 +48,7 @@ import dmd.visitor;
  * Returns:
  *   FuncDeclaration of `toString()` if found, `null` if not
  */
-extern (C++) FuncDeclaration search_toString(StructDeclaration sd)
+FuncDeclaration search_toString(StructDeclaration sd)
 {
     Dsymbol s = search_function(sd, Id.tostring);
     FuncDeclaration fd = s ? s.isFuncDeclaration() : null;
index 5e7922ea11dac1a852ea66cde69b241a5d2a581a..b831c32c28bdc808748afe1eaecfc65f2028ccc9 100644 (file)
@@ -1105,6 +1105,7 @@ extern (C++) class Dsymbol : ASTNode
     inout(MixinDeclaration)            isMixinDeclaration()            inout { return null; }
     inout(StaticAssert)                isStaticAssert()                inout { return null; }
     inout(StaticIfDeclaration)         isStaticIfDeclaration()         inout { return null; }
+    inout(CAsmDeclaration)             isCAsmDeclaration()             inout { return null; }
 }
 
 /***********************************************************
@@ -1700,275 +1701,25 @@ extern (C++) final class DsymbolTable : RootObject
     }
 }
 
-/**********************************************
- * ImportC tag symbols sit in a parallel symbol table,
- * so that this C code works:
- * ---
- * struct S { a; };
- * int S;
- * struct S s;
- * ---
- * But there are relatively few such tag symbols, so that would be
- * a waste of memory and complexity. An additional problem is we'd like the D side
- * to find the tag symbols with ordinary lookup, not lookup in both
- * tables, if the tag symbol is not conflicting with an ordinary symbol.
- * The solution is to put the tag symbols that conflict into an associative
- * array, indexed by the address of the ordinary symbol that conflicts with it.
- * C has no modules, so this associative array is tagSymTab[] in ModuleDeclaration.
- * A side effect of our approach is that D code cannot access a tag symbol that is
- * hidden by an ordinary symbol. This is more of a theoretical problem, as nobody
- * has mentioned it when importing C headers. If someone wants to do it,
- * too bad so sad. Change the C code.
- * This function fixes up the symbol table when faced with adding a new symbol
- * `s` when there is an existing symbol `s2` with the same name.
- * C also allows forward and prototype declarations of tag symbols,
- * this function merges those.
- * Params:
- *      sc = context
- *      s = symbol to add to symbol table
- *      s2 = existing declaration
- *      sds = symbol table
- * Returns:
- *      if s and s2 are successfully put in symbol table then return the merged symbol,
- *      null if they conflict
- */
-Dsymbol handleTagSymbols(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
-{
-    enum log = false;
-    if (log) printf("handleTagSymbols('%s') add %p existing %p\n", s.toChars(), s, s2);
-    if (log) printf("  add %s %s, existing %s %s\n", s.kind(), s.toChars(), s2.kind(), s2.toChars());
-    auto sd = s.isScopeDsymbol(); // new declaration
-    auto sd2 = s2.isScopeDsymbol(); // existing declaration
-
-    static if (log) void print(EnumDeclaration sd)
-    {
-        printf("members: %p\n", sd.members);
-        printf("symtab: %p\n", sd.symtab);
-        printf("endlinnum: %d\n", sd.endlinnum);
-        printf("type: %s\n", sd.type.toChars());
-        printf("memtype: %s\n", sd.memtype.toChars());
-    }
-
-    if (!sd2)
-    {
-        /* Look in tag table
-         */
-        if (log) printf(" look in tag table\n");
-        if (auto p = cast(void*)s2 in sc._module.tagSymTab)
-        {
-            Dsymbol s2tag = *p;
-            sd2 = s2tag.isScopeDsymbol();
-            assert(sd2);        // only tags allowed in tag symbol table
-        }
-    }
-
-    if (sd && sd2) // `s` is a tag, `sd2` is the same tag
-    {
-        if (log) printf(" tag is already defined\n");
-
-        if (sd.kind() != sd2.kind())  // being enum/struct/union must match
-            return null;              // conflict
-
-        /* Not a redeclaration if one is a forward declaration.
-         * Move members to the first declared type, which is sd2.
-         */
-        if (sd2.members)
-        {
-            if (!sd.members)
-                return sd2;  // ignore the sd redeclaration
-        }
-        else if (sd.members)
-        {
-            sd2.members = sd.members; // transfer definition to sd2
-            sd.members = null;
-            if (auto ed2 = sd2.isEnumDeclaration())
-            {
-                auto ed = sd.isEnumDeclaration();
-                if (ed.memtype != ed2.memtype)
-                    return null;        // conflict
-
-                // transfer ed's members to sd2
-                ed2.members.foreachDsymbol( (s)
-                {
-                    if (auto em = s.isEnumMember())
-                        em.ed = ed2;
-                });
-
-                ed2.type = ed.type;
-                ed2.memtype = ed.memtype;
-                ed2.added = false;
-            }
-            return sd2;
-        }
-        else
-            return sd2; // ignore redeclaration
-    }
-    else if (sd) // `s` is a tag, `s2` is not
-    {
-        if (log) printf(" s is tag, s2 is not\n");
-        /* add `s` as tag indexed by s2
-         */
-        sc._module.tagSymTab[cast(void*)s2] = s;
-        return s;
-    }
-    else if (s2 is sd2) // `s2` is a tag, `s` is not
-    {
-        if (log) printf(" s2 is tag, s is not\n");
-        /* replace `s2` in symbol table with `s`,
-         * then add `s2` as tag indexed by `s`
-         */
-        sds.symtab.update(s);
-        sc._module.tagSymTab[cast(void*)s] = s2;
-        return s;
-    }
-    // neither s2 nor s is a tag
-    if (log) printf(" collision\n");
-    return null;
-}
-
-
-/**********************************************
- * ImportC allows redeclarations of C variables, functions and typedefs.
- *    extern int x;
- *    int x = 3;
- * and:
- *    extern void f();
- *    void f() { }
- * Attempt to merge them.
- * Params:
- *      sc = context
- *      s = symbol to add to symbol table
- *      s2 = existing declaration
- *      sds = symbol table
- * Returns:
- *      if s and s2 are successfully put in symbol table then return the merged symbol,
- *      null if they conflict
+/**
+ * ImportC global `asm` definition.
  */
-Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
+extern (C++) final class CAsmDeclaration : Dsymbol
 {
-    enum log = false;
-    if (log) printf("handleSymbolRedeclarations('%s')\n", s.toChars());
-    if (log) printf("  add %s %s, existing %s %s\n", s.kind(), s.toChars(), s2.kind(), s2.toChars());
-
-    static Dsymbol collision()
+    Expression code;
+    extern (D) this(Expression e) nothrow @safe
     {
-        if (log) printf(" collision\n");
-        return null;
-    }
-    /*
-    Handle merging declarations with asm("foo") and their definitions
-    */
-    static void mangleWrangle(Declaration oldDecl, Declaration newDecl)
-    {
-        if (oldDecl && newDecl)
-        {
-            newDecl.mangleOverride = oldDecl.mangleOverride ? oldDecl.mangleOverride : null;
-        }
+        super();
+        this.code = e;
     }
 
-    auto vd = s.isVarDeclaration(); // new declaration
-    auto vd2 = s2.isVarDeclaration(); // existing declaration
-
-    if (vd && vd.isCmacro())
-        return vd2;
-
-    assert(!(vd2 && vd2.isCmacro()));
-
-    if (vd && vd2)
+    override inout(CAsmDeclaration) isCAsmDeclaration() inout nothrow
     {
-        /* if one is `static` and the other isn't, the result is undefined
-         * behavior, C11 6.2.2.7
-         */
-        if ((vd.storage_class ^ vd2.storage_class) & STC.static_)
-            return collision();
-
-        const i1 =  vd._init && ! vd._init.isVoidInitializer();
-        const i2 = vd2._init && !vd2._init.isVoidInitializer();
-
-        if (i1 && i2)
-            return collision();         // can't both have initializers
-
-        mangleWrangle(vd2, vd);
-
-        if (i1)                         // vd is the definition
-        {
-            vd2.storage_class |= STC.extern_;  // so toObjFile() won't emit it
-            sds.symtab.update(vd);      // replace vd2 with the definition
-            return vd;
-        }
-
-        /* BUG: the types should match, which needs semantic() to be run on it
-         *    extern int x;
-         *    int x;  // match
-         *    typedef int INT;
-         *    INT x;  // match
-         *    long x; // collision
-         * We incorrectly ignore these collisions
-         */
-        return vd2;
-    }
-
-    auto fd = s.isFuncDeclaration(); // new declaration
-    auto fd2 = s2.isFuncDeclaration(); // existing declaration
-    if (fd && fd2)
-    {
-        /* if one is `static` and the other isn't, the result is undefined
-         * behavior, C11 6.2.2.7
-         * However, match what gcc allows:
-         *    static int sun1(); int sun1() { return 0; }
-         * and:
-         *    static int sun2() { return 0; } int sun2();
-         * Both produce a static function.
-         *
-         * Both of these should fail:
-         *    int sun3(); static int sun3() { return 0; }
-         * and:
-         *    int sun4() { return 0; } static int sun4();
-         */
-        // if adding `static`
-        if (   fd.storage_class & STC.static_ &&
-            !(fd2.storage_class & STC.static_))
-        {
-            return collision();
-        }
-
-        if (fd.fbody && fd2.fbody)
-            return collision();         // can't both have bodies
-
-        mangleWrangle(fd2, fd);
-
-        if (fd.fbody)                   // fd is the definition
-        {
-            if (log) printf(" replace existing with new\n");
-            sds.symtab.update(fd);      // replace fd2 in symbol table with fd
-            fd.overnext = fd2;
-
-            /* If fd2 is covering a tag symbol, then fd has to cover the same one
-             */
-            auto ps = cast(void*)fd2 in sc._module.tagSymTab;
-            if (ps)
-                sc._module.tagSymTab[cast(void*)fd] = *ps;
-
-            return fd;
-        }
-
-        /* Just like with VarDeclaration, the types should match, which needs semantic() to be run on it.
-         * FuncDeclaration::semantic() detects this, but it relies on .overnext being set.
-         */
-        fd2.overloadInsert(fd);
-
-        return fd2;
+        return this;
     }
 
-    auto td  = s.isAliasDeclaration();  // new declaration
-    auto td2 = s2.isAliasDeclaration(); // existing declaration
-    if (td && td2)
+    override void accept(Visitor v)
     {
-        /* BUG: just like with variables and functions, the types should match, which needs semantic() to be run on it.
-         * FuncDeclaration::semantic2() can detect this, but it relies overnext being set.
-         */
-        return td2;
+        v.visit(this);
     }
-
-    return collision();
 }
index db236275570d48ec5dc0ee7b70273aa8de4f318f..f8454354fed536cfd29c7ad05e0926ccb3c4f3a4 100644 (file)
@@ -73,6 +73,7 @@ class AliasAssign;
 class OverloadSet;
 class StaticAssert;
 class StaticIfDeclaration;
+class CAsmDeclaration;
 struct AA;
 #ifdef IN_GCC
 typedef union tree_node Symbol;
@@ -95,9 +96,16 @@ enum class ThreeState : uint8_t
     yes,          // value is true
 };
 
-void dsymbolSemantic(Dsymbol *dsym, Scope *sc);
-void semantic2(Dsymbol *dsym, Scope *sc);
-void semantic3(Dsymbol *dsym, Scope* sc);
+namespace dmd
+{
+    void dsymbolSemantic(Dsymbol *dsym, Scope *sc);
+    void semantic2(Dsymbol *dsym, Scope *sc);
+    void semantic3(Dsymbol *dsym, Scope* sc);
+    // in iasm.d
+    void asmSemantic(CAsmDeclaration *ad, Scope *sc);
+    // in iasmgcc.d
+    void gccAsmSemantic(CAsmDeclaration *ad, Scope *sc);
+}
 
 struct Visibility
 {
@@ -315,6 +323,7 @@ public:
     virtual MixinDeclaration *isMixinDeclaration() { return NULL; }
     virtual StaticAssert *isStaticAssert() { return NULL; }
     virtual StaticIfDeclaration *isStaticIfDeclaration() { return NULL; }
+    virtual CAsmDeclaration *isCAsmDeclaration() { return NULL; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -404,6 +413,15 @@ public:
     ExpressionDsymbol *isExpressionDsymbol() override { return this; }
 };
 
+class CAsmDeclaration final : public Dsymbol
+{
+public:
+    Expression *code;   // string expression
+
+    CAsmDeclaration *isCAsmDeclaration() override { return this; }
+    void accept(Visitor *v) override { v->visit(this); }
+};
+
 // Table of Dsymbol's
 
 class DsymbolTable final : public RootObject
@@ -425,7 +443,10 @@ public:
     size_t length() const;
 };
 
-void addMember(Dsymbol *dsym, Scope *sc, ScopeDsymbol *sds);
-Dsymbol *search(Dsymbol *d, const Loc &loc, Identifier *ident, SearchOptFlags flags = (SearchOptFlags)SearchOpt::localsOnly);
-void setScope(Dsymbol *d, Scope *sc);
-void importAll(Dsymbol *d, Scope *sc);
+namespace dmd
+{
+    void addMember(Dsymbol *dsym, Scope *sc, ScopeDsymbol *sds);
+    Dsymbol *search(Dsymbol *d, const Loc &loc, Identifier *ident, SearchOptFlags flags = (SearchOptFlags)SearchOpt::localsOnly);
+    void setScope(Dsymbol *d, Scope *sc);
+    void importAll(Dsymbol *d, Scope *sc);
+}
index 4a4d82ff5c063f40cf6eb21c2bce3d4b8738d3ee..c15d925ce0a96f410a7100f8ddb240ab428a9ea7 100644 (file)
@@ -85,7 +85,7 @@ enum LOG = false;
 /*************************************
  * Does semantic analysis on the public face of declarations.
  */
-extern(C++) void dsymbolSemantic(Dsymbol dsym, Scope* sc)
+void dsymbolSemantic(Dsymbol dsym, Scope* sc)
 {
     scope v = new DsymbolSemanticVisitor(sc);
     dsym.accept(v);
@@ -1440,6 +1440,15 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         assert(dsym._linkage == LINK.c);
     }
 
+    override void visit(CAsmDeclaration dsym)
+    {
+        if (dsym.semanticRun >= PASS.semanticdone)
+            return;
+        import dmd.iasm : asmSemantic;
+        asmSemantic(dsym, sc);
+        dsym.semanticRun = PASS.semanticdone;
+    }
+
     override void visit(BitFieldDeclaration dsym)
     {
         //printf("BitField::semantic('%s')\n", dsym.toChars());
@@ -4059,7 +4068,7 @@ Params:
     sc = scope where the dsymbol is declared
     sds = ScopeDsymbol where dsym is inserted
 */
-extern(C++) void addMember(Dsymbol dsym, Scope* sc, ScopeDsymbol sds)
+void addMember(Dsymbol dsym, Scope* sc, ScopeDsymbol sds)
 {
     auto addMemberVisitor = new AddMemberVisitor(sc, sds);
     dsym.accept(addMemberVisitor);
@@ -5979,7 +5988,7 @@ void checkPrintfScanfSignature(FuncDeclaration funcdecl, TypeFunction f, Scope*
  * Returns:
  *  null if not found
  */
-extern(C++) Dsymbol search(Dsymbol d, const ref Loc loc, Identifier ident, SearchOptFlags flags = SearchOpt.all)
+Dsymbol search(Dsymbol d, const ref Loc loc, Identifier ident, SearchOptFlags flags = SearchOpt.all)
 {
     scope v = new SearchVisitor(loc, ident, flags);
     d.accept(v);
@@ -6621,7 +6630,7 @@ private extern(C++) class SearchVisitor : Visitor
  *   d = dsymbol for which the scope is set
  *   sc = scope that is used to set the value
  */
-extern(C++) void setScope(Dsymbol d, Scope* sc)
+void setScope(Dsymbol d, Scope* sc)
 {
     scope setScopeVisitor = new SetScopeVisitor(sc);
     d.accept(setScopeVisitor);
@@ -6764,7 +6773,7 @@ private extern(C++) class SetScopeVisitor : Visitor
     }
 }
 
-extern(C++) void importAll(Dsymbol d, Scope* sc)
+void importAll(Dsymbol d, Scope* sc)
 {
     scope iav = new ImportAllVisitor(sc);
     d.accept(iav);
index 4a195e3e7c2528dbcdcffd424c0a72677fa2b631..165a010059f943da4179352c17875720858c10b3 100644 (file)
@@ -96,7 +96,7 @@ pure nothrow @nogc @safe
  * These functions substitute for dynamic_cast. dynamic_cast does not work
  * on earlier versions of gcc.
  */
-extern (C++) inout(Expression) isExpression(inout RootObject o)
+inout(Expression) isExpression(inout RootObject o)
 {
     //return dynamic_cast<Expression *>(o);
     if (!o || o.dyncast() != DYNCAST.expression)
@@ -104,7 +104,7 @@ extern (C++) inout(Expression) isExpression(inout RootObject o)
     return cast(inout(Expression))o;
 }
 
-extern (C++) inout(Dsymbol) isDsymbol(inout RootObject o)
+inout(Dsymbol) isDsymbol(inout RootObject o)
 {
     //return dynamic_cast<Dsymbol *>(o);
     if (!o || o.dyncast() != DYNCAST.dsymbol)
@@ -112,7 +112,7 @@ extern (C++) inout(Dsymbol) isDsymbol(inout RootObject o)
     return cast(inout(Dsymbol))o;
 }
 
-extern (C++) inout(Type) isType(inout RootObject o)
+inout(Type) isType(inout RootObject o)
 {
     //return dynamic_cast<Type *>(o);
     if (!o || o.dyncast() != DYNCAST.type)
@@ -120,7 +120,7 @@ extern (C++) inout(Type) isType(inout RootObject o)
     return cast(inout(Type))o;
 }
 
-extern (C++) inout(Tuple) isTuple(inout RootObject o)
+inout(Tuple) isTuple(inout RootObject o)
 {
     //return dynamic_cast<Tuple *>(o);
     if (!o || o.dyncast() != DYNCAST.tuple)
@@ -128,7 +128,7 @@ extern (C++) inout(Tuple) isTuple(inout RootObject o)
     return cast(inout(Tuple))o;
 }
 
-extern (C++) inout(Parameter) isParameter(inout RootObject o)
+inout(Parameter) isParameter(inout RootObject o)
 {
     //return dynamic_cast<Parameter *>(o);
     if (!o || o.dyncast() != DYNCAST.parameter)
@@ -136,7 +136,7 @@ extern (C++) inout(Parameter) isParameter(inout RootObject o)
     return cast(inout(Parameter))o;
 }
 
-extern (C++) inout(TemplateParameter) isTemplateParameter(inout RootObject o)
+inout(TemplateParameter) isTemplateParameter(inout RootObject o)
 {
     if (!o || o.dyncast() != DYNCAST.templateparameter)
         return null;
@@ -146,7 +146,7 @@ extern (C++) inout(TemplateParameter) isTemplateParameter(inout RootObject o)
 /**************************************
  * Is this Object an error?
  */
-extern (C++) bool isError(const RootObject o)
+bool isError(const RootObject o)
 {
     if (const t = isType(o))
         return (t.ty == Terror);
@@ -6311,7 +6311,7 @@ struct TemplateStats
  *      listInstances = list instances of templates
  *      eSink = where the print is sent
  */
-extern (C++) void printTemplateStats(bool listInstances, ErrorSink eSink)
+void printTemplateStats(bool listInstances, ErrorSink eSink)
 {
     static struct TemplateDeclarationStats
     {
index 4a1ff055157ae871a88406d082c2d47311efd4d3..2e2ced4b0d1b94072cccd64ada43d7b8b5d3e0d2 100644 (file)
@@ -54,7 +54,7 @@ import dmd.utils;
  *  - ignored declarations are mentioned in a comment if `global.params.doCxxHdrGeneration`
  *    is set to `CxxHeaderMode.verbose`
  */
-extern(C++) void genCppHdrFiles(ref Modules ms)
+void genCppHdrFiles(ref Modules ms)
 {
     initialize();
 
index 82de837ef750c6ef9d7412f6b029f79373f9705c..bc907cfd2f4e0ff1d314fe4f3c650ade8df3d570 100644 (file)
@@ -108,7 +108,7 @@ inout(Expression) lastComma(inout Expression e)
  *     exps  = array of Expressions
  *     names = optional array of names corresponding to Expressions
  */
-extern (C++) void expandTuples(Expressions* exps, Identifiers* names = null)
+void expandTuples(Expressions* exps, Identifiers* names = null)
 {
     //printf("expandTuples()\n");
     if (exps is null)
index 8dbb4a63c7e0cf2202d31fc04fd64c558edd10e3..3bd8ca7568ef52554010c1b4d1d4792a466d517a 100644 (file)
@@ -46,16 +46,19 @@ typedef union tree_node Symbol;
 struct Symbol;          // back end symbol
 #endif
 
-// in expressionsem.d
-Expression *expressionSemantic(Expression *e, Scope *sc);
-// in typesem.d
-Expression *defaultInit(Type *mt, const Loc &loc, const bool isCfile = false);
-
-// Entry point for CTFE.
-// A compile-time result is required. Give an error if not possible
-Expression *ctfeInterpret(Expression *e);
-void expandTuples(Expressions *exps, Identifiers *names = nullptr);
-Expression *optimize(Expression *exp, int result, bool keepLvalue = false);
+namespace dmd
+{
+    // in expressionsem.d
+    Expression *expressionSemantic(Expression *e, Scope *sc);
+    // in typesem.d
+    Expression *defaultInit(Type *mt, const Loc &loc, const bool isCfile = false);
+
+    // Entry point for CTFE.
+    // A compile-time result is required. Give an error if not possible
+    Expression *ctfeInterpret(Expression *e);
+    void expandTuples(Expressions *exps, Identifiers *names = nullptr);
+    Expression *optimize(Expression *exp, int result, bool keepLvalue = false);
+}
 
 typedef unsigned char OwnedBy;
 enum
index 9028ba1b191d32642b2498d927caac1975c799a3..cc589b991d1e1e72eb089acf8e4bba77edd9f679 100644 (file)
@@ -5023,7 +5023,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     return setError();
 
                 checkFunctionAttributes(exp, sc, f);
-                checkAccess(cd, exp.loc, sc, f);
+                if (!checkSymbolAccess(sc, f))
+                {
+                    error(exp.loc, "%s `%s` is not accessible from module `%s`",
+                        f.kind(), f.toPrettyChars(), sc._module.toChars);
+                    return setError();
+                }
 
                 TypeFunction tf = f.type.isTypeFunction();
                 if (!exp.arguments)
@@ -6463,7 +6468,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 return setError();
 
             checkFunctionAttributes(exp, sc, exp.f);
-            checkAccess(exp.loc, sc, null, exp.f);
+            if (!checkSymbolAccess(sc, exp.f))
+            {
+                error(exp.loc, "%s `%s` is not accessible from module `%s`",
+                    exp.f.kind(), exp.f.toPrettyChars(), sc._module.toChars);
+                return setError();
+            }
 
             exp.e1 = new DotVarExp(exp.e1.loc, exp.e1, exp.f, false);
             exp.e1 = exp.e1.expressionSemantic(sc);
@@ -6649,7 +6659,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             assert(exp.f);
             tiargs = null;
 
-            if (exp.f.overnext)
+            if (ve.hasOverloads && exp.f.overnext)
                 exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.argumentList, FuncResolveFlag.overloadOnly);
             else
             {
@@ -14193,7 +14203,7 @@ Expression binSemanticProp(BinExp e, Scope* sc)
 }
 
 // entrypoint for semantic ExpressionSemanticVisitor
-extern (C++) Expression expressionSemantic(Expression e, Scope* sc)
+Expression expressionSemantic(Expression e, Scope* sc)
 {
     scope v = new ExpressionSemanticVisitor(sc);
     e.accept(v);
@@ -14211,8 +14221,10 @@ private Expression dotIdSemanticPropX(DotIdExp exp, Scope* sc)
         // symbol.mangleof
 
         // return mangleof as an Expression
-        static Expression dotMangleof(const ref Loc loc, Scope* sc, Dsymbol ds)
+        static Expression dotMangleof(const ref Loc loc, Scope* sc, Dsymbol ds, bool hasOverloads)
         {
+            Expression e;
+
             assert(ds);
             if (auto f = ds.isFuncDeclaration())
             {
@@ -14224,24 +14236,40 @@ private Expression dotIdSemanticPropX(DotIdExp exp, Scope* sc)
                     error(loc, "%s `%s` cannot retrieve its `.mangleof` while inferring attributes", f.kind, f.toPrettyChars);
                     return ErrorExp.get();
                 }
+
+                if (!hasOverloads)
+                    e = StringExp.create(loc, mangleExact(f));
             }
-            OutBuffer buf;
-            mangleToBuffer(ds, buf);
-            Expression e = new StringExp(loc, buf.extractSlice());
+
+            if (!e)
+            {
+                OutBuffer buf;
+                mangleToBuffer(ds, buf);
+                e = new StringExp(loc, buf.extractSlice());
+            }
+
             return e.expressionSemantic(sc);
         }
 
         Dsymbol ds;
         switch (exp.e1.op)
         {
-            case EXP.scope_:      return dotMangleof(exp.loc, sc, exp.e1.isScopeExp().sds);
-            case EXP.variable:    return dotMangleof(exp.loc, sc, exp.e1.isVarExp().var);
-            case EXP.dotVariable: return dotMangleof(exp.loc, sc, exp.e1.isDotVarExp().var);
-            case EXP.overloadSet: return dotMangleof(exp.loc, sc, exp.e1.isOverExp().vars);
+            case EXP.scope_:      return dotMangleof(exp.loc, sc, exp.e1.isScopeExp().sds, false);
+            case EXP.overloadSet: return dotMangleof(exp.loc, sc, exp.e1.isOverExp().vars, false);
+            case EXP.variable:
+            {
+                VarExp ve = exp.e1.isVarExp();
+                return dotMangleof(exp.loc, sc, ve.var, ve.hasOverloads);
+            }
+            case EXP.dotVariable:
+            {
+                DotVarExp dve = exp.e1.isDotVarExp();
+                return dotMangleof(exp.loc, sc, dve.var, dve.hasOverloads);
+            }
             case EXP.template_:
             {
                 TemplateExp te = exp.e1.isTemplateExp();
-                return dotMangleof(exp.loc, sc, ds = te.fd ? te.fd.isDsymbol() : te.td);
+                return dotMangleof(exp.loc, sc, ds = te.fd ? te.fd.isDsymbol() : te.td, false);
             }
 
             default:
index 9e706ee80d9d17b455683f1137c3656d64eaa658..49da6b201367578460f2b2919de9b60a13dc2c62 100644 (file)
@@ -1042,7 +1042,6 @@ Ldone:
  *  false if any errors exist in the signature.
  */
 public
-extern (C++)
 bool functionSemantic(FuncDeclaration fd)
 {
     //printf("functionSemantic() %p %s\n", this, toChars());
@@ -1101,7 +1100,6 @@ bool functionSemantic(FuncDeclaration fd)
  * Returns false if any errors exist in the body.
  */
 public
-extern (C++)
 bool functionSemantic3(FuncDeclaration fd)
 {
     if (fd.semanticRun < PASS.semantic3 && fd._scope)
index b3980eb79306024b5aa1c7e5348a8fb85175d1a8..a3a3bd01f135fc62da56dc9979e032eb16640349 100644 (file)
@@ -30,19 +30,9 @@ version (NoBackend)
     struct TYPE;
     alias type = TYPE;
 
-    extern (C++)
+    extern(C++) abstract class ObjcGlue
     {
-        // iasm
-        Statement asmSemantic(AsmStatement s, Scope* sc)
-        {
-            sc.func.hasReturnExp = 8;
-            return null;
-        }
-
-        extern(C++) abstract class ObjcGlue
-        {
-            static void initialize() {}
-        }
+        static void initialize() {}
     }
 }
 else version (IN_GCC)
@@ -53,11 +43,6 @@ else version (IN_GCC)
     alias code = tree_node;
     alias type = tree_node;
 
-    extern (C++)
-    {
-        Statement asmSemantic(AsmStatement s, Scope* sc);
-    }
-
     // stubs
     extern(C++) abstract class ObjcGlue
     {
@@ -70,6 +55,5 @@ else
     public import dmd.backend.type : type;
     public import dmd.backend.el : elem;
     public import dmd.backend.code_x86 : code;
-    public import dmd.iasm : asmSemantic;
     public import dmd.objc_glue : ObjcGlue;
 }
index e4cbcc5f0b9a2d208e57ef4581f9f10d0b18f61d..8eef7992e2aee33c79c792b7c866dc9dae3c6b05 100644 (file)
@@ -83,7 +83,7 @@ enum TEST_EMIT_ALL = 0;
  *      doFuncBodies = generate function definitions rather than just declarations
  *      buf = buffer to write the data to
  */
-extern (C++) void genhdrfile(Module m, bool doFuncBodies, ref OutBuffer buf)
+void genhdrfile(Module m, bool doFuncBodies, ref OutBuffer buf)
 {
     buf.doindent = 1;
     buf.printf("// D import file generated from '%s'", m.srcfile.toChars());
@@ -103,7 +103,7 @@ extern (C++) void genhdrfile(Module m, bool doFuncBodies, ref OutBuffer buf)
  * Returns:
  *      0-terminated string
  */
-public extern (C++) const(char)* toChars(const Statement s)
+public const(char)* toChars(const Statement s)
 {
     HdrGenState hgs;
     OutBuffer buf;
@@ -112,7 +112,7 @@ public extern (C++) const(char)* toChars(const Statement s)
     return buf.extractSlice().ptr;
 }
 
-public extern (C++) const(char)* toChars(const Expression e)
+public const(char)* toChars(const Expression e)
 {
     HdrGenState hgs;
     OutBuffer buf;
@@ -120,7 +120,7 @@ public extern (C++) const(char)* toChars(const Expression e)
     return buf.extractChars();
 }
 
-public extern (C++) const(char)* toChars(const Initializer i)
+public const(char)* toChars(const Initializer i)
 {
     OutBuffer buf;
     HdrGenState hgs;
@@ -128,7 +128,7 @@ public extern (C++) const(char)* toChars(const Initializer i)
     return buf.extractChars();
 }
 
-public extern (C++) const(char)* toChars(const Type t)
+public const(char)* toChars(const Type t)
 {
     OutBuffer buf;
     buf.reserve(16);
@@ -154,7 +154,7 @@ public const(char)[] toString(const Initializer i)
  *   vcg_ast = write out codegen ast
  *   m = module to visit all members of.
  */
-extern (C++) void moduleToBuffer(ref OutBuffer buf, bool vcg_ast, Module m)
+void moduleToBuffer(ref OutBuffer buf, bool vcg_ast, Module m)
 {
     HdrGenState hgs;
     hgs.fullDump = true;
@@ -3418,7 +3418,7 @@ void arrayObjectsToBuffer(ref OutBuffer buf, Objects* objects)
  *  pl = parameter list to print
  * Returns: Null-terminated string representing parameters.
  */
-extern (C++) const(char)* parametersTypeToChars(ParameterList pl)
+const(char)* parametersTypeToChars(ParameterList pl)
 {
     OutBuffer buf;
     HdrGenState hgs;
index e0a20461d4558536906cd14d81904dc9db8d7be5..14793ad23a8a7def8e76ae16efc536bc9ac61010 100644 (file)
@@ -18,12 +18,15 @@ class Initializer;
 class Module;
 class Statement;
 
-void genhdrfile(Module *m, bool doFuncBodies, OutBuffer &buf);
-void genCppHdrFiles(Modules &ms);
-void moduleToBuffer(OutBuffer& buf, bool vcg_ast, Module *m);
-const char *parametersTypeToChars(ParameterList pl);
+namespace dmd
+{
+    void genhdrfile(Module *m, bool doFuncBodies, OutBuffer &buf);
+    void genCppHdrFiles(Modules &ms);
+    void moduleToBuffer(OutBuffer& buf, bool vcg_ast, Module *m);
+    const char *parametersTypeToChars(ParameterList pl);
 
-const char* toChars(const Expression* const e);
-const char* toChars(const Initializer* const i);
-const char* toChars(const Statement* const s);
-const char* toChars(const Type* const t);
+    const char* toChars(const Expression* const e);
+    const char* toChars(const Initializer* const i);
+    const char* toChars(const Statement* const s);
+    const char* toChars(const Type* const t);
+}
index 24a45136cd5b6f2685f26d7fb5df519166e901e8..1399ac27fae2b9b3719b3d56bfbdc652af803b83 100644 (file)
@@ -16,6 +16,7 @@ module dmd.iasm;
 import core.stdc.stdio;
 
 import dmd.dscope;
+import dmd.dsymbol;
 import dmd.expression;
 import dmd.func;
 import dmd.mtype;
@@ -23,7 +24,10 @@ import dmd.tokens;
 import dmd.statement;
 import dmd.statementsem;
 
-version (IN_GCC)
+version (NoBackend)
+{
+}
+else version (IN_GCC)
 {
     import dmd.iasmgcc;
 }
@@ -35,7 +39,7 @@ else
 
 /************************ AsmStatement ***************************************/
 
-extern(C++) Statement asmSemantic(AsmStatement s, Scope *sc)
+Statement asmSemantic(AsmStatement s, Scope *sc)
 {
     //printf("AsmStatement.semantic()\n");
 
@@ -48,7 +52,11 @@ extern(C++) Statement asmSemantic(AsmStatement s, Scope *sc)
     // Assume assembler code takes care of setting the return value
     sc.func.hasReturnExp |= 8;
 
-    version (MARS)
+    version (NoBackend)
+    {
+        return null;
+    }
+    else version (MARS)
     {
         /* If it starts with a string literal, it's gcc inline asm
          */
@@ -78,3 +86,21 @@ extern(C++) Statement asmSemantic(AsmStatement s, Scope *sc)
         return new ErrorStatement();
     }
 }
+
+/************************ CAsmDeclaration ************************************/
+
+void asmSemantic(CAsmDeclaration ad, Scope *sc)
+{
+    version (NoBackend)
+    {
+    }
+    else version (IN_GCC)
+    {
+        return gccAsmSemantic(ad, sc);
+    }
+    else
+    {
+        import dmd.errors : error;
+        error(ad.code.loc, "Gnu Asm not supported - compile this file with gcc or clang");
+    }
+}
index db51e7341552b68c4473b98a069106a2a3d78772..4b1b2e78c69e9f399ad04cc5fafdf7b0f5afef3e 100644 (file)
@@ -16,6 +16,7 @@ import core.stdc.string;
 import dmd.arraytypes;
 import dmd.astcodegen;
 import dmd.dscope;
+import dmd.dsymbol;
 import dmd.errors;
 import dmd.errorsink;
 import dmd.expression;
@@ -299,7 +300,7 @@ Ldone:
  * Returns:
  *      the completed gcc asm statement, or null if errors occurred
  */
-extern (C++) public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
+public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
 {
     //printf("GccAsmStatement.semantic()\n");
     const bool doUnittests = global.params.parsingUnittestsRequired();
@@ -382,6 +383,26 @@ extern (C++) public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
     return s;
 }
 
+/***********************************
+ * Run semantic analysis on an CAsmDeclaration.
+ * Params:
+ *      ad  = asm declaration
+ *      sc = the scope where the asm declaration is located
+ */
+public void gccAsmSemantic(CAsmDeclaration ad, Scope *sc)
+{
+    import dmd.typesem : pointerTo;
+    ad.code = semanticString(sc, ad.code, "asm definition");
+    ad.code.type = ad.code.type.nextOf().pointerTo();
+
+    // Asm definition always needs emitting into the root module.
+    import dmd.dmodule : Module;
+    if (sc._module && sc._module.isRoot())
+        return;
+    if (Module m = Module.rootModule)
+        m.members.push(ad);
+}
+
 unittest
 {
     import dmd.mtype : TypeBasic;
index 69a85ceec9397f610f1f58b84c1ede37f942b245..e4d5aa2cae1d466e38c64aaf6cffa3eafd13b9a3 100644 (file)
@@ -366,3 +366,276 @@ bool cTypeEquivalence(Type t1, Type t2)
 
     return false;
 }
+
+/**********************************************
+ * ImportC tag symbols sit in a parallel symbol table,
+ * so that this C code works:
+ * ---
+ * struct S { a; };
+ * int S;
+ * struct S s;
+ * ---
+ * But there are relatively few such tag symbols, so that would be
+ * a waste of memory and complexity. An additional problem is we'd like the D side
+ * to find the tag symbols with ordinary lookup, not lookup in both
+ * tables, if the tag symbol is not conflicting with an ordinary symbol.
+ * The solution is to put the tag symbols that conflict into an associative
+ * array, indexed by the address of the ordinary symbol that conflicts with it.
+ * C has no modules, so this associative array is tagSymTab[] in ModuleDeclaration.
+ * A side effect of our approach is that D code cannot access a tag symbol that is
+ * hidden by an ordinary symbol. This is more of a theoretical problem, as nobody
+ * has mentioned it when importing C headers. If someone wants to do it,
+ * too bad so sad. Change the C code.
+ * This function fixes up the symbol table when faced with adding a new symbol
+ * `s` when there is an existing symbol `s2` with the same name.
+ * C also allows forward and prototype declarations of tag symbols,
+ * this function merges those.
+ * Params:
+ *      sc = context
+ *      s = symbol to add to symbol table
+ *      s2 = existing declaration
+ *      sds = symbol table
+ * Returns:
+ *      if s and s2 are successfully put in symbol table then return the merged symbol,
+ *      null if they conflict
+ */
+Dsymbol handleTagSymbols(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
+{
+    enum log = false;
+    if (log) printf("handleTagSymbols('%s') add %p existing %p\n", s.toChars(), s, s2);
+    if (log) printf("  add %s %s, existing %s %s\n", s.kind(), s.toChars(), s2.kind(), s2.toChars());
+    auto sd = s.isScopeDsymbol(); // new declaration
+    auto sd2 = s2.isScopeDsymbol(); // existing declaration
+
+    static if (log) void print(EnumDeclaration sd)
+    {
+        printf("members: %p\n", sd.members);
+        printf("symtab: %p\n", sd.symtab);
+        printf("endlinnum: %d\n", sd.endlinnum);
+        printf("type: %s\n", sd.type.toChars());
+        printf("memtype: %s\n", sd.memtype.toChars());
+    }
+
+    if (!sd2)
+    {
+        /* Look in tag table
+         */
+        if (log) printf(" look in tag table\n");
+        if (auto p = cast(void*)s2 in sc._module.tagSymTab)
+        {
+            Dsymbol s2tag = *p;
+            sd2 = s2tag.isScopeDsymbol();
+            assert(sd2);        // only tags allowed in tag symbol table
+        }
+    }
+
+    if (sd && sd2) // `s` is a tag, `sd2` is the same tag
+    {
+        if (log) printf(" tag is already defined\n");
+
+        if (sd.kind() != sd2.kind())  // being enum/struct/union must match
+            return null;              // conflict
+
+        /* Not a redeclaration if one is a forward declaration.
+         * Move members to the first declared type, which is sd2.
+         */
+        if (sd2.members)
+        {
+            if (!sd.members)
+                return sd2;  // ignore the sd redeclaration
+        }
+        else if (sd.members)
+        {
+            sd2.members = sd.members; // transfer definition to sd2
+            sd.members = null;
+            if (auto ed2 = sd2.isEnumDeclaration())
+            {
+                auto ed = sd.isEnumDeclaration();
+                if (ed.memtype != ed2.memtype)
+                    return null;        // conflict
+
+                // transfer ed's members to sd2
+                ed2.members.foreachDsymbol( (s)
+                {
+                    if (auto em = s.isEnumMember())
+                        em.ed = ed2;
+                });
+
+                ed2.type = ed.type;
+                ed2.memtype = ed.memtype;
+                ed2.added = false;
+            }
+            return sd2;
+        }
+        else
+            return sd2; // ignore redeclaration
+    }
+    else if (sd) // `s` is a tag, `s2` is not
+    {
+        if (log) printf(" s is tag, s2 is not\n");
+        /* add `s` as tag indexed by s2
+         */
+        sc._module.tagSymTab[cast(void*)s2] = s;
+        return s;
+    }
+    else if (s2 is sd2) // `s2` is a tag, `s` is not
+    {
+        if (log) printf(" s2 is tag, s is not\n");
+        /* replace `s2` in symbol table with `s`,
+         * then add `s2` as tag indexed by `s`
+         */
+        sds.symtab.update(s);
+        sc._module.tagSymTab[cast(void*)s] = s2;
+        return s;
+    }
+    // neither s2 nor s is a tag
+    if (log) printf(" collision\n");
+    return null;
+}
+
+
+/**********************************************
+ * ImportC allows redeclarations of C variables, functions and typedefs.
+ *    extern int x;
+ *    int x = 3;
+ * and:
+ *    extern void f();
+ *    void f() { }
+ * Attempt to merge them.
+ * Params:
+ *      sc = context
+ *      s = symbol to add to symbol table
+ *      s2 = existing declaration
+ *      sds = symbol table
+ * Returns:
+ *      if s and s2 are successfully put in symbol table then return the merged symbol,
+ *      null if they conflict
+ */
+Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
+{
+    enum log = false;
+    if (log) printf("handleSymbolRedeclarations('%s')\n", s.toChars());
+    if (log) printf("  add %s %s, existing %s %s\n", s.kind(), s.toChars(), s2.kind(), s2.toChars());
+
+    static Dsymbol collision()
+    {
+        if (log) printf(" collision\n");
+        return null;
+    }
+    /*
+    Handle merging declarations with asm("foo") and their definitions
+    */
+    static void mangleWrangle(Declaration oldDecl, Declaration newDecl)
+    {
+        if (oldDecl && newDecl)
+        {
+            newDecl.mangleOverride = oldDecl.mangleOverride ? oldDecl.mangleOverride : null;
+        }
+    }
+
+    auto vd = s.isVarDeclaration(); // new declaration
+    auto vd2 = s2.isVarDeclaration(); // existing declaration
+
+    if (vd && vd.isCmacro())
+        return vd2;
+
+    assert(!(vd2 && vd2.isCmacro()));
+
+    if (vd && vd2)
+    {
+        /* if one is `static` and the other isn't, the result is undefined
+         * behavior, C11 6.2.2.7
+         */
+        if ((vd.storage_class ^ vd2.storage_class) & STC.static_)
+            return collision();
+
+        const i1 =  vd._init && ! vd._init.isVoidInitializer();
+        const i2 = vd2._init && !vd2._init.isVoidInitializer();
+
+        if (i1 && i2)
+            return collision();         // can't both have initializers
+
+        mangleWrangle(vd2, vd);
+
+        if (i1)                         // vd is the definition
+        {
+            vd2.storage_class |= STC.extern_;  // so toObjFile() won't emit it
+            sds.symtab.update(vd);      // replace vd2 with the definition
+            return vd;
+        }
+
+        /* BUG: the types should match, which needs semantic() to be run on it
+         *    extern int x;
+         *    int x;  // match
+         *    typedef int INT;
+         *    INT x;  // match
+         *    long x; // collision
+         * We incorrectly ignore these collisions
+         */
+        return vd2;
+    }
+
+    auto fd = s.isFuncDeclaration(); // new declaration
+    auto fd2 = s2.isFuncDeclaration(); // existing declaration
+    if (fd && fd2)
+    {
+        /* if one is `static` and the other isn't, the result is undefined
+         * behavior, C11 6.2.2.7
+         * However, match what gcc allows:
+         *    static int sun1(); int sun1() { return 0; }
+         * and:
+         *    static int sun2() { return 0; } int sun2();
+         * Both produce a static function.
+         *
+         * Both of these should fail:
+         *    int sun3(); static int sun3() { return 0; }
+         * and:
+         *    int sun4() { return 0; } static int sun4();
+         */
+        // if adding `static`
+        if (   fd.storage_class & STC.static_ &&
+            !(fd2.storage_class & STC.static_))
+        {
+            return collision();
+        }
+
+        if (fd.fbody && fd2.fbody)
+            return collision();         // can't both have bodies
+
+        mangleWrangle(fd2, fd);
+
+        if (fd.fbody)                   // fd is the definition
+        {
+            if (log) printf(" replace existing with new\n");
+            sds.symtab.update(fd);      // replace fd2 in symbol table with fd
+            fd.overnext = fd2;
+
+            /* If fd2 is covering a tag symbol, then fd has to cover the same one
+             */
+            auto ps = cast(void*)fd2 in sc._module.tagSymTab;
+            if (ps)
+                sc._module.tagSymTab[cast(void*)fd] = *ps;
+
+            return fd;
+        }
+
+        /* Just like with VarDeclaration, the types should match, which needs semantic() to be run on it.
+         * FuncDeclaration::semantic() detects this, but it relies on .overnext being set.
+         */
+        fd2.overloadInsert(fd);
+
+        return fd2;
+    }
+
+    auto td  = s.isAliasDeclaration();  // new declaration
+    auto td2 = s2.isAliasDeclaration(); // existing declaration
+    if (td && td2)
+    {
+        /* BUG: just like with variables and functions, the types should match, which needs semantic() to be run on it.
+         * FuncDeclaration::semantic2() can detect this, but it relies overnext being set.
+         */
+        return td2;
+    }
+
+    return collision();
+}
index cccd3c97f2cccc69ec92b9e4256be93f18960700..2485d78bb59e08f43e9105fa9f486ccbad3739c3 100644 (file)
@@ -124,5 +124,8 @@ public:
     void accept(Visitor *v) override { v->visit(this); }
 };
 
-Expression *initializerToExpression(Initializer *init, Type *t = NULL, const bool isCfile = false);
-Initializer *initializerSemantic(Initializer *init, Scope *sc, Type *&tx, NeedInterpret needInterpret);
+namespace dmd
+{
+    Expression *initializerToExpression(Initializer *init, Type *t = NULL, const bool isCfile = false);
+    Initializer *initializerSemantic(Initializer *init, Scope *sc, Type *&tx, NeedInterpret needInterpret);
+}
index 79d7902fc9b4723e9e63a3a8ca3b590b0cd22589..b07699e19fe27d9ec97e4a9c0bdde80fbc3c4c84 100644 (file)
@@ -103,7 +103,7 @@ Expression toAssocArrayLiteral(ArrayInitializer ai)
  *      `Initializer` with completed semantic analysis, `ErrorInitializer` if errors
  *      were encountered
  */
-extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedInterpret needInterpret)
+Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedInterpret needInterpret)
 {
     //printf("initializerSemantic() tx: %p %s\n", tx, tx.toChars());
     Type t = tx;
@@ -1224,7 +1224,7 @@ Initializer inferType(Initializer init, Scope* sc)
  * Returns:
  *      `Expression` created, `null` if cannot, `ErrorExp` for other errors
  */
-extern (C++) Expression initializerToExpression(Initializer init, Type itype = null, const bool isCfile = false)
+Expression initializerToExpression(Initializer init, Type itype = null, const bool isCfile = false)
 {
     //printf("initializerToExpression() isCfile: %d\n", isCfile);
 
index 7c6506712fc521af2039b31b0eed77dc7e16ae4d..f20b3d4b38a3cec36a33e5061b3c2520b79d5df9 100644 (file)
@@ -978,7 +978,7 @@ public:
  *      modules = array of Modules
  *      buf = write json output to buf
  */
-extern (C++) void json_generate(ref Modules modules, ref OutBuffer buf)
+void json_generate(ref Modules modules, ref OutBuffer buf)
 {
     scope ToJsonVisitor json = new ToJsonVisitor(&buf);
     // write trailing newline
@@ -1047,7 +1047,7 @@ Params:
 Returns: JsonFieldFlags.none on error, otherwise the JsonFieldFlags value
          corresponding to the given fieldName.
 */
-extern (C++) JsonFieldFlags tryParseJsonField(const(char)* fieldName)
+JsonFieldFlags tryParseJsonField(const(char)* fieldName)
 {
     auto fieldNameString = fieldName.toDString();
     foreach (idx, enumName; __traits(allMembers, JsonFieldFlags))
index 8a949114feb1ce51175a7c4a1efcc1d8aa7c7c16..b119c9ede4ec180cc0019919528444c2b99a59a5 100644 (file)
@@ -15,5 +15,8 @@
 
 struct OutBuffer;
 
-void json_generate(Modules &, OutBuffer &);
-JsonFieldFlags tryParseJsonField(const char *fieldName);
+namespace dmd
+{
+    void json_generate(Modules &, OutBuffer &);
+    JsonFieldFlags tryParseJsonField(const char *fieldName);
+}
index 68064a9210a948077eae32793e8277b283cd1602..de6fa55f7770b12dda10bfdb4e27ce3aee603704 100644 (file)
@@ -17,18 +17,21 @@ class TemplateInstance;
 class Type;
 struct OutBuffer;
 
-// In cppmangle.d
-const char *toCppMangleItanium(Dsymbol *s);
-const char *cppTypeInfoMangleItanium(Dsymbol *s);
-const char *cppThunkMangleItanium(FuncDeclaration *fd, int offset);
+namespace dmd
+{
+    // In cppmangle.d
+    const char *toCppMangleItanium(Dsymbol *s);
+    const char *cppTypeInfoMangleItanium(Dsymbol *s);
+    const char *cppThunkMangleItanium(FuncDeclaration *fd, int offset);
 
-// In cppmanglewin.d
-const char *toCppMangleMSVC(Dsymbol *s);
-const char *cppTypeInfoMangleMSVC(Dsymbol *s);
+    // In cppmanglewin.d
+    const char *toCppMangleMSVC(Dsymbol *s);
+    const char *cppTypeInfoMangleMSVC(Dsymbol *s);
 
-// In dmangle.d
-const char *mangleExact(FuncDeclaration *fd);
-void mangleToBuffer(Type *s, OutBuffer& buf);
-void mangleToBuffer(Expression *s, OutBuffer& buf);
-void mangleToBuffer(Dsymbol *s, OutBuffer& buf);
-void mangleToBuffer(TemplateInstance *s, OutBuffer& buf);
+    // In dmangle.d
+    const char *mangleExact(FuncDeclaration *fd);
+    void mangleToBuffer(Type *s, OutBuffer& buf);
+    void mangleToBuffer(Expression *s, OutBuffer& buf);
+    void mangleToBuffer(Dsymbol *s, OutBuffer& buf);
+    void mangleToBuffer(TemplateInstance *s, OutBuffer& buf);
+}
index d09e873c49542f64fd1c455cd376a0c954d97e0d..379e8e6973aa31c1114450b319d2aee38465a887 100644 (file)
@@ -167,5 +167,8 @@ struct ModuleDeclaration
     const char *toChars() const;
 };
 
-extern void getLocalClasses(Module* mod, Array<ClassDeclaration* >& aclasses);
-FuncDeclaration *findGetMembers(ScopeDsymbol *dsym);
+namespace dmd
+{
+    void getLocalClasses(Module* mod, Array<ClassDeclaration* >& aclasses);
+    FuncDeclaration *findGetMembers(ScopeDsymbol *dsym);
+}
index 4f8ed7594c7d60a1c62e4b6cf3d4b5d27419804b..09ed630fe8ba9e0665772270cb2b8d8105586224 100644 (file)
@@ -1186,58 +1186,6 @@ extern (C++) abstract class Type : ASTNode
         return t;
     }
 
-    /************************************
-     * Add storage class modifiers to type.
-     */
-    Type addStorageClass(StorageClass stc)
-    {
-        /* Just translate to MOD bits and let addMod() do the work
-         */
-        MOD mod = 0;
-        if (stc & STC.immutable_)
-            mod = MODFlags.immutable_;
-        else
-        {
-            if (stc & (STC.const_ | STC.in_))
-                mod |= MODFlags.const_;
-            if (stc & STC.wild)
-                mod |= MODFlags.wild;
-            if (stc & STC.shared_)
-                mod |= MODFlags.shared_;
-        }
-        return this.addMod(mod);
-    }
-
-    final Type pointerTo()
-    {
-        if (ty == Terror)
-            return this;
-        if (!pto)
-        {
-            Type t = new TypePointer(this);
-            if (ty == Tfunction)
-            {
-                t.deco = t.merge().deco;
-                pto = t;
-            }
-            else
-                pto = t.merge();
-        }
-        return pto;
-    }
-
-    final Type referenceTo()
-    {
-        if (ty == Terror)
-            return this;
-        if (!rto)
-        {
-            Type t = new TypeReference(this);
-            rto = t.merge();
-        }
-        return rto;
-    }
-
     final Type arrayOf()
     {
         if (ty == Terror)
@@ -3449,56 +3397,6 @@ extern (C++) final class TypeFunction : TypeNext
         return linkage == LINK.d && parameterList.varargs == VarArg.variadic;
     }
 
-    override Type addStorageClass(StorageClass stc)
-    {
-        //printf("addStorageClass(%llx) %d\n", stc, (stc & STC.scope_) != 0);
-        TypeFunction t = Type.addStorageClass(stc).toTypeFunction();
-        if ((stc & STC.pure_ && !t.purity) ||
-            (stc & STC.nothrow_ && !t.isnothrow) ||
-            (stc & STC.nogc && !t.isnogc) ||
-            (stc & STC.scope_ && !t.isScopeQual) ||
-            (stc & STC.safe && t.trust < TRUST.trusted))
-        {
-            // Klunky to change these
-            auto tf = new TypeFunction(t.parameterList, t.next, t.linkage, 0);
-            tf.mod = t.mod;
-            tf.fargs = fargs;
-            tf.purity = t.purity;
-            tf.isnothrow = t.isnothrow;
-            tf.isnogc = t.isnogc;
-            tf.isproperty = t.isproperty;
-            tf.isref = t.isref;
-            tf.isreturn = t.isreturn;
-            tf.isreturnscope = t.isreturnscope;
-            tf.isScopeQual = t.isScopeQual;
-            tf.isreturninferred = t.isreturninferred;
-            tf.isscopeinferred = t.isscopeinferred;
-            tf.trust = t.trust;
-            tf.isInOutParam = t.isInOutParam;
-            tf.isInOutQual = t.isInOutQual;
-            tf.isctor = t.isctor;
-
-            if (stc & STC.pure_)
-                tf.purity = PURE.fwdref;
-            if (stc & STC.nothrow_)
-                tf.isnothrow = true;
-            if (stc & STC.nogc)
-                tf.isnogc = true;
-            if (stc & STC.safe)
-                tf.trust = TRUST.safe;
-            if (stc & STC.scope_)
-            {
-                tf.isScopeQual = true;
-                if (stc & STC.scopeinferred)
-                    tf.isscopeinferred = true;
-            }
-
-            tf.deco = tf.merge().deco;
-            t = tf;
-        }
-        return t;
-    }
-
     override Type substWildTo(uint)
     {
         if (!iswild && !(mod & MODFlags.wild))
@@ -3800,12 +3698,6 @@ extern (C++) final class TypeDelegate : TypeNext
         return result;
     }
 
-    override Type addStorageClass(StorageClass stc)
-    {
-        TypeDelegate t = cast(TypeDelegate)Type.addStorageClass(stc);
-        return t;
-    }
-
     override uinteger_t size(const ref Loc loc)
     {
         return target.ptrsize * 2;
@@ -5673,7 +5565,7 @@ void attributesApply(const TypeFunction tf, void delegate(string) dg, TRUSTforma
  * If the type is a class or struct, returns the symbol for it,
  * else null.
  */
-extern (C++) AggregateDeclaration isAggregate(Type t)
+AggregateDeclaration isAggregate(Type t)
 {
     t = t.toBasetype();
     if (t.ty == Tclass)
index df8cc4dd6b6f84bac858af8dd8e6539cc0949581..57f4ec6e0d2552e66521380b468ca06c208680c7 100644 (file)
@@ -39,8 +39,11 @@ typedef union tree_node type;
 typedef struct TYPE type;
 #endif
 
-Type *typeSemantic(Type *t, const Loc &loc, Scope *sc);
-Type *merge(Type *type);
+namespace dmd
+{
+    Type *typeSemantic(Type *t, const Loc &loc, Scope *sc);
+    Type *merge(Type *type);
+}
 
 enum class TY : uint8_t
 {
@@ -251,9 +254,6 @@ public:
     bool isSharedWild() const  { return (mod & (MODshared | MODwild)) == (MODshared | MODwild); }
     bool isNaked() const       { return mod == 0; }
     Type *nullAttributes() const;
-    virtual Type *addStorageClass(StorageClass stc);
-    Type *pointerTo();
-    Type *referenceTo();
     Type *arrayOf();
     Type *sarrayOf(dinteger_t dim);
     bool hasDeprecatedAliasThis();
@@ -579,7 +579,6 @@ public:
     TypeFunction *syntaxCopy() override;
     bool hasLazyParameters();
     bool isDstyleVariadic() const;
-    Type *addStorageClass(StorageClass stc) override;
 
     Type *substWildTo(unsigned mod) override;
     MATCH constConv(Type *to) override;
@@ -623,7 +622,6 @@ public:
     static TypeDelegate *create(TypeFunction *t);
     const char *kind() override;
     TypeDelegate *syntaxCopy() override;
-    Type *addStorageClass(StorageClass stc) override;
     uinteger_t size(const Loc &loc) override;
     unsigned alignsize() override;
     MATCH implicitConvTo(Type *to) override;
@@ -880,26 +878,31 @@ public:
 
 /**************************************************************/
 
-
-// If the type is a class or struct, returns the symbol for it, else null.
-AggregateDeclaration *isAggregate(Type *t);
-bool hasPointers(Type *t);
-// return the symbol to which type t resolves
-Dsymbol *toDsymbol(Type *t, Scope *sc);
-bool equivalent(Type *src, Type *t);
-Covariant covariant(Type *, Type *, StorageClass * = NULL, bool = false);
-bool isBaseOf(Type *tthis, Type *t, int *poffset);
-Type *trySemantic(Type *type, const Loc &loc, Scope *sc);
-Type *merge2(Type *type);
-Type *constOf(Type *type);
-Type *immutableOf(Type *type);
-Type *mutableOf(Type *type);
-Type *sharedOf(Type *type);
-Type *sharedConstOf(Type *type);
-Type *unSharedOf(Type *type);
-Type *wildOf(Type *type);
-Type *wildConstOf(Type *type);
-Type *sharedWildOf(Type *type);
-Type *sharedWildConstOf(Type *type);
-Type *castMod(Type *type, MOD mod);
-Type *addMod(Type *type, MOD mod);
+namespace dmd
+{
+    // If the type is a class or struct, returns the symbol for it, else null.
+    AggregateDeclaration *isAggregate(Type *t);
+    bool hasPointers(Type *t);
+    // return the symbol to which type t resolves
+    Dsymbol *toDsymbol(Type *t, Scope *sc);
+    bool equivalent(Type *src, Type *t);
+    Covariant covariant(Type *, Type *, StorageClass * = NULL, bool = false);
+    bool isBaseOf(Type *tthis, Type *t, int *poffset);
+    Type *trySemantic(Type *type, const Loc &loc, Scope *sc);
+    Type *pointerTo(Type *type);
+    Type *referenceTo(Type *type);
+    Type *merge2(Type *type);
+    Type *constOf(Type *type);
+    Type *immutableOf(Type *type);
+    Type *mutableOf(Type *type);
+    Type *sharedOf(Type *type);
+    Type *sharedConstOf(Type *type);
+    Type *unSharedOf(Type *type);
+    Type *wildOf(Type *type);
+    Type *wildConstOf(Type *type);
+    Type *sharedWildOf(Type *type);
+    Type *sharedWildConstOf(Type *type);
+    Type *castMod(Type *type, MOD mod);
+    Type *addMod(Type *type, MOD mod);
+    Type *addStorageClass(Type *type, StorageClass stc);
+}
index 5c0ef67787c44d2260bc2ae41b9b88a075d12492..dd6b117e0acafab1c59f2c61faa2ad5b71fbe368 100644 (file)
@@ -273,7 +273,7 @@ package void setLengthVarIfKnown(VarDeclaration lengthVar, Type type)
  * Returns:
  *      Constant folded version of `e`
  */
-extern (C++) Expression optimize(Expression e, int result, bool keepLvalue = false)
+Expression optimize(Expression e, int result, bool keepLvalue = false)
 {
     //printf("optimize() e: %s result: %d keepLvalue %d\n", e.toChars(), result, keepLvalue);
     Expression ret = e;
index 2d2e6fde32311e09bf8e99db20f03ce11f348fbd..9c446eb1bf3169016e1c876a86ee07f427320eb2 100644 (file)
@@ -7180,6 +7180,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         }
         if (!isDeclarator(&t, &haveId, &haveTpl, endtok, needId != NeedDeclaratorId.mustIfDstyle))
             goto Lisnot;
+        // needed for `__traits(compiles, arr[0] = 0)`
+        if (!haveId && t.value == TOK.assign)
+            goto Lisnot;
         if ((needId == NeedDeclaratorId.no && !haveId) ||
             (needId == NeedDeclaratorId.opt) ||
             (needId == NeedDeclaratorId.must && haveId) ||
index 422c1c8c0ec5d20a8bd0368acd787eae8cf09141..c03f78d4de9ac7206d1a2d5844de1c2c6e9bc056 100644 (file)
@@ -36,6 +36,7 @@ public:
     void visit(AST.DebugSymbol s) { visit(cast(AST.Dsymbol)s); }
     void visit(AST.VersionSymbol s) { visit(cast(AST.Dsymbol)s); }
     void visit(AST.AliasAssign s) { visit(cast(AST.Dsymbol)s); }
+    void visit(AST.CAsmDeclaration s) { visit(cast(AST.Dsymbol)s); }
 
     // ScopeDsymbols
     void visit(AST.Package s) { visit(cast(AST.ScopeDsymbol)s); }
index b4f91ac7cf04621b60c018c1af8dc7caa3a56d06..f5ce0c0ada63df3dca58549cc07537446c252ec3 100644 (file)
@@ -73,7 +73,7 @@ enum LOG = false;
 /*************************************
  * Does semantic analysis on initializers and members of aggregates.
  */
-extern(C++) void semantic2(Dsymbol dsym, Scope* sc)
+void semantic2(Dsymbol dsym, Scope* sc)
 {
     scope v = new Semantic2Visitor(sc);
     dsym.accept(v);
@@ -876,7 +876,7 @@ private extern(C++) final class StaticAAVisitor : SemanticTimeTransitiveVisitor
         hookFunc = new DotIdExp(aaExp.loc, hookFunc, Id.object);
         hookFunc = new DotIdExp(aaExp.loc, hookFunc, Id._aaAsStruct);
         auto arguments = new Expressions();
-        arguments.push(aaExp.syntaxCopy());
+        arguments.push(aaExp);
         Expression loweredExp = new CallExp(aaExp.loc, hookFunc, arguments);
 
         sc = sc.startCTFE();
index 125a39d179fc45a193a8ff3fa7716234170dd024..882d1a9a35529c86bed7b937e250c4b1dfa7afc6 100644 (file)
@@ -79,7 +79,7 @@ enum LOG = false;
 /*************************************
  * Does semantic analysis on function bodies.
  */
-extern(C++) void semantic3(Dsymbol dsym, Scope* sc)
+void semantic3(Dsymbol dsym, Scope* sc)
 {
     scope v = new Semantic3Visitor(sc);
     dsym.accept(v);
@@ -1636,7 +1636,7 @@ private struct FuncDeclSem3
     }
 }
 
-extern (C++) void semanticTypeInfoMembers(StructDeclaration sd)
+void semanticTypeInfoMembers(StructDeclaration sd)
 {
     if (sd.xeq &&
         sd.xeq._scope &&
index 8a6bf3d0d1cc51f353b758b712141a6247c51340..ea80e510c52a19efe34c093b29699c9de1ac2b88 100644 (file)
@@ -701,12 +701,15 @@ public:
     void accept(Visitor *v) override { v->visit(this); }
 };
 
-// in statementsem.d
-Statement* statementSemantic(Statement *s, Scope *sc);
-// in iasm.d
-Statement* asmSemantic(AsmStatement *s, Scope *sc);
-// in iasmgcc.d
-Statement *gccAsmSemantic(GccAsmStatement *s, Scope *sc);
+namespace dmd
+{
+    // in statementsem.d
+    Statement* statementSemantic(Statement *s, Scope *sc);
+    // in iasm.d
+    Statement* asmSemantic(AsmStatement *s, Scope *sc);
+    // in iasmgcc.d
+    Statement *gccAsmSemantic(GccAsmStatement *s, Scope *sc);
+}
 
 class AsmStatement : public Statement
 {
index a431d5c0922a0acd79ea0c5a88c489aec86f0b1f..5013c569933b631ba9a494762a03f4001dbf1e8e 100644 (file)
@@ -41,8 +41,8 @@ import dmd.expressionsem;
 import dmd.func;
 import dmd.funcsem;
 import dmd.globals;
-import dmd.gluelayer;
 import dmd.hdrgen;
+import dmd.iasm;
 import dmd.id;
 import dmd.identifier;
 import dmd.importc;
@@ -135,7 +135,7 @@ private Expression checkAssignmentAsCondition(Expression e, Scope* sc)
 }
 
 // Performs semantic analysis in Statement AST nodes
-extern(C++) Statement statementSemantic(Statement s, Scope* sc)
+Statement statementSemantic(Statement s, Scope* sc)
 {
     import dmd.compiler;
 
index e63bf17a5f7cbf88b6f6ad73365a52c947a3c3f5..cff1d2e9bec1df103c925ff6fcc2b44919536768 100644 (file)
@@ -110,7 +110,7 @@ extern (C++) struct Target
 
     /// Architecture name
     const(char)[] architectureName;
-    CPU cpu = CPU.baseline; // CPU instruction set to target
+    CPU cpu;                // CPU instruction set to target
     bool isX86_64;          // generate 64 bit code for x86_64; true by default for 64 bit dmd
     bool isLP64;            // pointers are 64 bits
 
@@ -119,7 +119,7 @@ extern (C++) struct Target
     const(char)[] lib_ext;    /// extension for static library files
     const(char)[] dll_ext;    /// extension for dynamic library files
     bool run_noext;           /// allow -run sources without extensions
-    bool omfobj = false;      // for Win32: write OMF object files instead of MsCoff
+    bool omfobj;              // for Win32: write OMF object files instead of MsCoff
     /**
      * Values representing all properties for floating point types
      */
index c80f28bf80798d2ff3f4d6d916ee34da96284da1..6f12ac3eb1f29471106285a5e7d83a8269763a23 100644 (file)
@@ -317,14 +317,17 @@ public:
     void accept(Visitor *v) override { v->visit(this); }
 };
 
-// in templateparamsem.d
-bool tpsemantic(TemplateParameter *tp, Scope *sc, TemplateParameters *parameters);
-
-Expression *isExpression(RootObject *o);
-Dsymbol *isDsymbol(RootObject *o);
-Type *isType(RootObject *o);
-Tuple *isTuple(RootObject *o);
-Parameter *isParameter(RootObject *o);
-TemplateParameter *isTemplateParameter(RootObject *o);
-bool isError(const RootObject *const o);
-void printTemplateStats(bool listInstances, ErrorSink* eSink);
+namespace dmd
+{
+    // in templateparamsem.d
+    bool tpsemantic(TemplateParameter *tp, Scope *sc, TemplateParameters *parameters);
+
+    Expression *isExpression(RootObject *o);
+    Dsymbol *isDsymbol(RootObject *o);
+    Type *isType(RootObject *o);
+    Tuple *isTuple(RootObject *o);
+    Parameter *isParameter(RootObject *o);
+    TemplateParameter *isTemplateParameter(RootObject *o);
+    bool isError(const RootObject *const o);
+    void printTemplateStats(bool listInstances, ErrorSink* eSink);
+}
index 89749d6b7f3213af534bcf967fd70f135eff66c7..f2dc50ebb7021979a1f6bd98314e1bebc36233ef 100644 (file)
@@ -35,7 +35,7 @@ import dmd.visitor;
  * Returns:
  *      `true` if no errors
  */
-extern(C++) bool tpsemantic(TemplateParameter tp, Scope* sc, TemplateParameters* parameters)
+bool tpsemantic(TemplateParameter tp, Scope* sc, TemplateParameters* parameters)
 {
     scope v = new TemplateParameterSemanticVisitor(sc, parameters);
     tp.accept(v);
index 19c6912eeaf5204922bae3c64a508519cd4c2c1b..61272ea344c827ebfa168243044ca44457d83514 100644 (file)
@@ -1222,7 +1222,7 @@ private extern(D) MATCH matchTypeSafeVarArgs(TypeFunction tf, Parameter p,
  * Return !=0 if type has pointers that need to
  * be scanned by the GC during a collection cycle.
  */
-extern(C++) bool hasPointers(Type t)
+bool hasPointers(Type t)
 {
     bool visitType(Type _)              { return false; }
     bool visitDArray(TypeDArray _)      { return true; }
@@ -1292,7 +1292,7 @@ extern(C++) bool hasPointers(Type t)
  *      `Type` with completed semantic analysis, `Terror` if errors
  *      were encountered
  */
-extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
+Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
 {
     static Type error()
     {
@@ -2821,7 +2821,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
     }
 }
 
-extern(C++) Type trySemantic(Type type, const ref Loc loc, Scope* sc)
+Type trySemantic(Type type, const ref Loc loc, Scope* sc)
 {
     //printf("+trySemantic(%s) %d\n", toChars(), global.errors);
 
@@ -2855,7 +2855,7 @@ extern(C++) Type trySemantic(Type type, const ref Loc loc, Scope* sc)
  * Returns:
  *      the type that was merged
  */
-extern (C++) Type merge(Type type)
+Type merge(Type type)
 {
     switch (type.ty)
     {
@@ -2925,7 +2925,7 @@ extern (C++) Type merge(Type type)
  * This version does a merge even if the deco is already computed.
  * Necessary for types that have a deco, but are not merged.
  */
-extern(C++) Type merge2(Type type)
+Type merge2(Type type)
 {
     //printf("merge2(%s)\n", toChars());
     Type t = type;
@@ -5365,7 +5365,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag
  * Returns:
  *  The initialization expression for the type.
  */
-extern (C++) Expression defaultInit(Type mt, const ref Loc loc, const bool isCfile = false)
+Expression defaultInit(Type mt, const ref Loc loc, const bool isCfile = false)
 {
     Expression visitBasic(TypeBasic mt)
     {
@@ -5545,7 +5545,7 @@ Returns:
   if the type does resolve to any symbol (for example,
   in the case of basic types).
 */
-extern(C++) Dsymbol toDsymbol(Type type, Scope* sc)
+Dsymbol toDsymbol(Type type, Scope* sc)
 {
     Dsymbol visitType(Type _)            { return null; }
     Dsymbol visitStruct(TypeStruct type) { return type.sym; }
@@ -5644,6 +5644,94 @@ extern(C++) Dsymbol toDsymbol(Type type, Scope* sc)
     }
 }
 
+/************************************
+ * Add storage class modifiers to type.
+ */
+Type addStorageClass(Type type, StorageClass stc)
+{
+    Type visitType(Type t)
+    {
+        /* Just translate to MOD bits and let addMod() do the work
+         */
+        MOD mod = 0;
+        if (stc & STC.immutable_)
+            mod = MODFlags.immutable_;
+        else
+        {
+            if (stc & (STC.const_ | STC.in_))
+                mod |= MODFlags.const_;
+            if (stc & STC.wild)
+                mod |= MODFlags.wild;
+            if (stc & STC.shared_)
+                mod |= MODFlags.shared_;
+        }
+        return t.addMod(mod);
+    }
+
+    Type visitFunction(TypeFunction tf_src)
+    {
+        //printf("addStorageClass(%llx) %d\n", stc, (stc & STC.scope_) != 0);
+        TypeFunction t = visitType(tf_src).toTypeFunction();
+        if ((stc & STC.pure_ && !t.purity) ||
+            (stc & STC.nothrow_ && !t.isnothrow) ||
+            (stc & STC.nogc && !t.isnogc) ||
+            (stc & STC.scope_ && !t.isScopeQual) ||
+            (stc & STC.safe && t.trust < TRUST.trusted))
+        {
+            // Klunky to change these
+            auto tf = new TypeFunction(t.parameterList, t.next, t.linkage, 0);
+            tf.mod = t.mod;
+            tf.fargs = tf_src.fargs;
+            tf.purity = t.purity;
+            tf.isnothrow = t.isnothrow;
+            tf.isnogc = t.isnogc;
+            tf.isproperty = t.isproperty;
+            tf.isref = t.isref;
+            tf.isreturn = t.isreturn;
+            tf.isreturnscope = t.isreturnscope;
+            tf.isScopeQual = t.isScopeQual;
+            tf.isreturninferred = t.isreturninferred;
+            tf.isscopeinferred = t.isscopeinferred;
+            tf.trust = t.trust;
+            tf.isInOutParam = t.isInOutParam;
+            tf.isInOutQual = t.isInOutQual;
+            tf.isctor = t.isctor;
+
+            if (stc & STC.pure_)
+                tf.purity = PURE.fwdref;
+            if (stc & STC.nothrow_)
+                tf.isnothrow = true;
+            if (stc & STC.nogc)
+                tf.isnogc = true;
+            if (stc & STC.safe)
+                tf.trust = TRUST.safe;
+            if (stc & STC.scope_)
+            {
+                tf.isScopeQual = true;
+                if (stc & STC.scopeinferred)
+                    tf.isscopeinferred = true;
+            }
+
+            tf.deco = tf.merge().deco;
+            t = tf;
+        }
+        return t;
+    }
+
+    Type visitDelegate(TypeDelegate tdg)
+    {
+        TypeDelegate t = visitType(tdg).isTypeDelegate();
+        return t;
+    }
+
+    switch(type.ty)
+    {
+        default:            return visitType(type);
+        case Tfunction:     return visitFunction(type.isTypeFunction());
+        case Tdelegate:     return visitDelegate(type.isTypeDelegate());
+    }
+}
+
 /**********************************************
  * Extract complex type from core.stdc.config
  * Params:
@@ -5722,7 +5810,7 @@ Type getComplexLibraryType(const ref Loc loc, Scope* sc, TY ty)
  * Returns:
  *     An enum value of either `Covariant.yes` or a reason it's not covariant.
  */
-extern(C++) Covariant covariant(Type src, Type t, StorageClass* pstc = null, bool cppCovariant = false)
+Covariant covariant(Type src, Type t, StorageClass* pstc = null, bool cppCovariant = false)
 {
     version (none)
     {
@@ -6085,7 +6173,7 @@ StorageClass parameterStorageClass(TypeFunction tf, Type tthis, Parameter p, Var
         return stc | STC.scope_;
 }
 
-extern(C++) bool isBaseOf(Type tthis, Type t, int* poffset)
+bool isBaseOf(Type tthis, Type t, int* poffset)
 {
     auto tc = tthis.isTypeClass();
     if (!tc)
@@ -6106,15 +6194,45 @@ extern(C++) bool isBaseOf(Type tthis, Type t, int* poffset)
     return false;
 }
 
-extern(C++) bool equivalent(Type src, Type t)
+bool equivalent(Type src, Type t)
 {
     return immutableOf(src).equals(t.immutableOf());
 }
 
+Type pointerTo(Type type)
+{
+    if (type.ty == Terror)
+        return type;
+    if (!type.pto)
+    {
+        Type t = new TypePointer(type);
+        if (type.ty == Tfunction)
+        {
+            t.deco = t.merge().deco;
+            type.pto = t;
+        }
+        else
+            type.pto = t.merge();
+    }
+    return type.pto;
+}
+
+Type referenceTo(Type type)
+{
+    if (type.ty == Terror)
+        return type;
+    if (!type.rto)
+    {
+        Type t = new TypeReference(type);
+        type.rto = t.merge();
+    }
+    return type.rto;
+}
+
 /********************************
  * Convert to 'const'.
  */
-extern(C++) Type constOf(Type type)
+Type constOf(Type type)
 {
     //printf("Type::constOf() %p %s\n", type, type.toChars());
     if (type.mod == MODFlags.const_)
@@ -6134,7 +6252,7 @@ extern(C++) Type constOf(Type type)
 /********************************
  * Convert to 'immutable'.
  */
-extern(C++) Type immutableOf(Type type)
+Type immutableOf(Type type)
 {
     //printf("Type::immutableOf() %p %s\n", this, toChars());
     if (type.isImmutable())
@@ -6154,7 +6272,7 @@ extern(C++) Type immutableOf(Type type)
 /********************************
  * Make type mutable.
  */
-extern(C++) Type mutableOf(Type type)
+Type mutableOf(Type type)
 {
     //printf("Type::mutableOf() %p, %s\n", type, type.toChars());
     Type t = type;
@@ -6204,7 +6322,7 @@ extern(C++) Type mutableOf(Type type)
     return t;
 }
 
-extern(C++) Type sharedOf(Type type)
+Type sharedOf(Type type)
 {
     //printf("Type::sharedOf() %p, %s\n", type, type.toChars());
     if (type.mod == MODFlags.shared_)
@@ -6221,7 +6339,7 @@ extern(C++) Type sharedOf(Type type)
     return t;
 }
 
-extern(C++) Type sharedConstOf(Type type)
+Type sharedConstOf(Type type)
 {
     //printf("Type::sharedConstOf() %p, %s\n", type, type.toChars());
     if (type.mod == (MODFlags.shared_ | MODFlags.const_))
@@ -6250,7 +6368,7 @@ extern(C++) Type sharedConstOf(Type type)
  *      shared wild  => wild
  *      shared wild const => wild const
  */
-extern(C++) Type unSharedOf(Type type)
+Type unSharedOf(Type type)
 {
     //printf("Type::unSharedOf() %p, %s\n", type, type.toChars());
     Type t = type;
@@ -6292,7 +6410,7 @@ extern(C++) Type unSharedOf(Type type)
 /********************************
  * Convert to 'wild'.
  */
-extern(C++) Type wildOf(Type type)
+Type wildOf(Type type)
 {
     //printf("Type::wildOf() %p %s\n", type, type.toChars());
     if (type.mod == MODFlags.wild)
@@ -6309,7 +6427,7 @@ extern(C++) Type wildOf(Type type)
     return t;
 }
 
-extern(C++) Type wildConstOf(Type type)
+Type wildConstOf(Type type)
 {
     //printf("Type::wildConstOf() %p %s\n", type, type.toChars());
     if (type.mod == MODFlags.wildconst)
@@ -6326,7 +6444,7 @@ extern(C++) Type wildConstOf(Type type)
     return t;
 }
 
-extern(C++) Type sharedWildOf(Type type)
+Type sharedWildOf(Type type)
 {
     //printf("Type::sharedWildOf() %p, %s\n", type, type.toChars());
     if (type.mod == (MODFlags.shared_ | MODFlags.wild))
@@ -6343,7 +6461,7 @@ extern(C++) Type sharedWildOf(Type type)
     return t;
 }
 
-extern(C++) Type sharedWildConstOf(Type type)
+Type sharedWildConstOf(Type type)
 {
     //printf("Type::sharedWildConstOf() %p, %s\n", type, type.toChars());
     if (type.mod == (MODFlags.shared_ | MODFlags.wildconst))
@@ -6363,7 +6481,7 @@ extern(C++) Type sharedWildConstOf(Type type)
 /************************************
  * Apply MODxxxx bits to existing type.
  */
-extern(C++) Type castMod(Type type, MOD mod)
+Type castMod(Type type, MOD mod)
 {
     Type t;
     switch (mod)
@@ -6415,7 +6533,7 @@ extern(C++) Type castMod(Type type, MOD mod)
  * We're adding, not replacing, so adding const to
  * a shared type => "shared const"
  */
-extern(C++) Type addMod(Type type, MOD mod)
+Type addMod(Type type, MOD mod)
 {
     /* Add anything to immutable, and it remains immutable
      */
index 6ae6df0e9b5a9bb54ec98718e07118435564e4d2..a3198327fb2eeac414d871906db739497ce94751 100644 (file)
@@ -35,7 +35,7 @@ import core.stdc.stdio;
  * Returns:
  *      true if `TypeInfo` was generated and needs compiling to object file
  */
-extern (C++) bool genTypeInfo(Expression e, const ref Loc loc, Type torig, Scope* sc)
+bool genTypeInfo(Expression e, const ref Loc loc, Type torig, Scope* sc)
 {
     // printf("genTypeInfo() %s\n", torig.toChars());
 
@@ -147,7 +147,7 @@ private TypeInfoDeclaration getTypeInfoDeclaration(Type t)
  *      true if any part of type t is speculative.
  *      if t is null, returns false.
  */
-extern (C++) bool isSpeculativeType(Type t)
+bool isSpeculativeType(Type t)
 {
     static bool visitVector(TypeVector t)
     {
@@ -244,7 +244,7 @@ extern (C++) bool isSpeculativeType(Type t)
 /* Indicates whether druntime already contains an appropriate TypeInfo instance
  * for the specified type (in module rt.util.typeinfo).
  */
-extern (C++) bool builtinTypeInfo(Type t)
+bool builtinTypeInfo(Type t)
 {
     if (!t.mod) // unqualified types only
     {
index fe80b94b4e1420c7b02575bb666ebf09efbac086..dd9572aab42f0afca8bf10a8d350e93157d42e78 100644 (file)
@@ -16,7 +16,10 @@ class Expression;
 class Type;
 struct Scope;
 
-bool genTypeInfo(Expression *e, const Loc &loc, Type *torig, Scope *sc);
+namespace dmd
+{
+    bool genTypeInfo(Expression *e, const Loc &loc, Type *torig, Scope *sc);
+    bool isSpeculativeType(Type *t);
+    bool builtinTypeInfo(Type *t);
+}
 Type *getTypeInfoType(const Loc &loc, Type *t, Scope *sc, bool genObjCode = true);
-bool isSpeculativeType(Type *t);
-bool builtinTypeInfo(Type *t);
index 6e3d31518888e0e610cc4cc77fe4085a562368c7..ab5cba6f7d0a1c8db2e4b563cd5a320fba1ebcc5 100644 (file)
@@ -126,6 +126,7 @@ class WithScopeSymbol;
 class ArrayScopeSymbol;
 class Nspace;
 class AliasAssign;
+class CAsmDeclaration;
 
 class AggregateDeclaration;
 class StructDeclaration;
@@ -339,6 +340,7 @@ public:
     virtual void visit(DebugSymbol *s) { visit((Dsymbol *)s); }
     virtual void visit(VersionSymbol *s) { visit((Dsymbol *)s); }
     virtual void visit(AliasAssign *s) { visit((Dsymbol *)s); }
+    virtual void visit(CAsmDeclaration *s) { visit((Dsymbol *)s); }
 
     // ScopeDsymbols
     virtual void visit(Package *s) { visit((ScopeDsymbol *)s); }
index a05058834afa96fb7b945180c20d69018f2dab94..7fbabbe185f062374f1c2554fa5a907b38ad885a 100644 (file)
@@ -1178,7 +1178,7 @@ public:
          {
            libcall = LIBCALL_AAGETY;
            ptr = build_address (build_expr (e->e1));
-           tinfo = build_typeinfo (e, mutableOf (unSharedOf (tb1)));
+           tinfo = build_typeinfo (e, dmd::mutableOf (dmd::unSharedOf (tb1)));
          }
        else
          {
@@ -1188,7 +1188,7 @@ public:
          }
 
        /* Index the associative array.  */
-       tree result = build_libcall (libcall, e->type->pointerTo (), 4,
+       tree result = build_libcall (libcall, dmd::pointerTo (e->type), 4,
                                     ptr, tinfo,
                                     size_int (tb1->nextOf ()->size ()),
                                     build_address (key));
@@ -1253,7 +1253,8 @@ public:
        else
          {
            /* Generate `array.ptr[index]'.  */
-           tree ptr = convert_expr (array, tb1, tb1->nextOf ()->pointerTo ());
+           tree ptr = convert_expr (array, tb1,
+                                    dmd::pointerTo (tb1->nextOf ()));
            ptr = void_okay_p (ptr);
            this->result_ = indirect_ref (TREE_TYPE (TREE_TYPE (ptr)),
                                          build_pointer_index (ptr, index));
@@ -1328,7 +1329,7 @@ public:
 
     /* Get the data pointer and length for static and dynamic arrays.  */
     tree array = d_save_expr (build_expr (e->e1));
-    tree ptr = convert_expr (array, tb1, tb1->nextOf ()->pointerTo ());
+    tree ptr = convert_expr (array, tb1, dmd::pointerTo (tb1->nextOf ()));
     tree length = NULL_TREE;
 
     /* Our array is already a SAVE_EXPR if necessary, so we don't make length
@@ -1994,7 +1995,7 @@ public:
 
   void visit (TypeidExp *e) final override
   {
-    if (Type *tid = isType (e->obj))
+    if (Type *tid = dmd::isType (e->obj))
       {
        tree ti = build_typeinfo (e, tid);
 
@@ -2004,7 +2005,7 @@ public:
 
        this->result_ = build_nop (build_ctype (e->type), ti);
       }
-    else if (Expression *tid = isExpression (e->obj))
+    else if (Expression *tid = dmd::isExpression (e->obj))
       {
        Type *type = tid->type->toBasetype ();
        assert (type->ty == TY::Tclass);
@@ -2136,7 +2137,8 @@ public:
            else
              {
                var->inuse++;
-               init = build_expr (initializerToExpression (var->_init), true);
+               Expression *vinit = dmd::initializerToExpression (var->_init);
+               init = build_expr (vinit, true);
                var->inuse--;
              }
          }
@@ -2170,7 +2172,7 @@ public:
              {
                /* Generate a slice for non-zero initialized aggregates,
                   otherwise create an empty array.  */
-               gcc_assert (e->type == constOf (Type::tvoid->arrayOf ()));
+               gcc_assert (e->type == dmd::constOf (Type::tvoid->arrayOf ()));
 
                tree type = build_ctype (e->type);
                tree length = size_int (sd->dsym->structsize);
@@ -2682,7 +2684,7 @@ public:
       {
        /* Allocate space on the memory managed heap.  */
        tree mem = build_libcall (LIBCALL_ARRAYLITERALTX,
-                                 etype->pointerTo (), 2,
+                                 dmd::pointerTo (etype), 2,
                                  build_typeinfo (e, etype->arrayOf ()),
                                  size_int (e->elements->length));
        mem = d_save_expr (mem);
@@ -2718,7 +2720,7 @@ public:
       }
 
     /* Want the mutable type for typeinfo reference.  */
-    Type *tb = mutableOf (e->type->toBasetype ());
+    Type *tb = dmd::mutableOf (e->type->toBasetype ());
 
     /* Handle empty assoc array literals.  */
     TypeAArray *ta = tb->isTypeAArray ();
index 8adbbeede7003f9cb4947e670ddb3f640895ca9e..8bbcdc164ee2336bd5c1170912f7a22064c51fa7 100644 (file)
@@ -126,7 +126,7 @@ maybe_set_intrinsic (FuncDeclaration *decl)
            return;
 
          OutBuffer buf;
-         mangleToBuffer (fd->type, buf);
+         dmd::mangleToBuffer (fd->type, buf);
          tdeco = buf.extractChars ();
        }
 
@@ -719,7 +719,7 @@ expand_intrinsic_rotate (intrinsic_code intrinsic, tree callexp)
       TemplateInstance *ti = DECL_LANG_FRONTEND (callee)->isInstantiated ();
       gcc_assert (ti && ti->tiargs && ti->tiargs->length == 2);
 
-      Expression *e = isExpression ((*ti->tiargs)[0]);
+      Expression *e = dmd::isExpression ((*ti->tiargs)[0]);
       gcc_assert (e && e->op == EXP::int64);
       count = build_expr (e, true);
     }
index 58b15beba34582853a36818a3b4f5d4d3b157e86..b111ee90cea00831f78dc3ad1d89615afaa56370 100644 (file)
@@ -504,7 +504,7 @@ layout_moduleinfo_fields (Module *decl, tree type)
   if (decl->sshareddtor)
     layout_moduleinfo_field (ptr_type_node, type, offset);
 
-  if (findGetMembers (decl))
+  if (dmd::findGetMembers (decl))
     layout_moduleinfo_field (ptr_type_node, type, offset);
 
   if (decl->sictor)
@@ -532,7 +532,7 @@ layout_moduleinfo_fields (Module *decl, tree type)
 
   /* Array of local ClassInfo decls are laid out in the same way.  */
   ClassDeclarations aclasses;
-  getLocalClasses (decl, aclasses);
+  dmd::getLocalClasses (decl, aclasses);
 
   if (aclasses.length)
     {
@@ -562,7 +562,7 @@ layout_moduleinfo (Module *decl)
   ClassDeclarations aclasses;
   FuncDeclaration *sgetmembers;
 
-  getLocalClasses (decl, aclasses);
+  dmd::getLocalClasses (decl, aclasses);
 
   size_t aimports_dim = decl->aimports.length;
   for (size_t i = 0; i < decl->aimports.length; i++)
@@ -572,7 +572,7 @@ layout_moduleinfo (Module *decl)
        aimports_dim--;
     }
 
-  sgetmembers = findGetMembers (decl);
+  sgetmembers = dmd::findGetMembers (decl);
 
   size_t flags = 0;
   if (decl->sctor)
index 9d11e7e132a20f8d2ee507e87827e9a3f4b667f5..e5988c721caf033c98601706148a9df56fddeb51 100644 (file)
@@ -150,11 +150,11 @@ get_libcall_type (d_libcall_type type)
       break;
 
     case LCT_CONST_TYPEINFO:
-      libcall_types[type] = constOf (Type::dtypeinfo->type);
+      libcall_types[type] = dmd::constOf (Type::dtypeinfo->type);
       break;
 
     case LCT_CONST_CLASSINFO:
-      libcall_types[type] = constOf (Type::typeinfoclass->type);
+      libcall_types[type] = dmd::constOf (Type::typeinfoclass->type);
       break;
 
     case LCT_ARRAY_VOID:
@@ -186,7 +186,7 @@ get_libcall_type (d_libcall_type type)
       break;
 
     case LCT_POINTER_ASSOCARRAY:
-      libcall_types[type] = get_libcall_type (LCT_ASSOCARRAY)->pointerTo ();
+      libcall_types[type] = dmd::pointerTo (get_libcall_type (LCT_ASSOCARRAY));
       break;
 
     case LCT_POINTER_VOIDPTR:
@@ -194,15 +194,15 @@ get_libcall_type (d_libcall_type type)
       break;
 
     case LCT_ARRAYPTR_VOID:
-      libcall_types[type] = Type::tvoid->arrayOf ()->pointerTo ();
+      libcall_types[type] = dmd::pointerTo (Type::tvoid->arrayOf ());
       break;
 
     case LCT_ARRAYPTR_BYTE:
-      libcall_types[type] = Type::tint8->arrayOf ()->pointerTo ();
+      libcall_types[type] = dmd::pointerTo (Type::tint8->arrayOf ());
       break;
 
     case LCT_IMMUTABLE_CHARPTR:
-      libcall_types[type] = immutableOf (Type::tchar->pointerTo ());
+      libcall_types[type] = dmd::immutableOf (dmd::pointerTo (Type::tchar));
       break;
 
     default:
index 3dbda55ad2b1838f956c383431b9bccc21d879db..794737b3b0b33385e2592374e10ca081484b66d5 100644 (file)
@@ -206,7 +206,7 @@ make_frontend_typeinfo (Identifier *ident, ClassDeclaration *base = NULL)
 
   /* Create object module in order to complete the semantic.  */
   if (!object_module->_scope)
-    importAll (object_module, NULL);
+    dmd::importAll (object_module, NULL);
 
   /* Object class doesn't exist, create a stub one that will cause an error if
      used.  */
@@ -232,7 +232,7 @@ make_frontend_typeinfo (Identifier *ident, ClassDeclaration *base = NULL)
                                                      true);
   tinfo->parent = object_module;
   tinfo->members = d_gc_malloc<Dsymbols> ();
-  dsymbolSemantic (tinfo, object_module->_scope);
+  dmd::dsymbolSemantic (tinfo, object_module->_scope);
   tinfo->baseClass = base;
   /* This is a compiler generated class, and shouldn't be mistaken for being
      the type declared in the runtime library.  */
@@ -577,8 +577,8 @@ public:
 
   void visit (TypeInfoConstDeclaration *d) final override
   {
-    Type *tm = mutableOf (d->tinfo);
-    tm = merge2 (tm);
+    Type *tm = dmd::mutableOf (d->tinfo);
+    tm = dmd::merge2 (tm);
 
     /* The vtable for TypeInfo_Const.  */
     this->layout_base (Type::typeinfoconst);
@@ -594,8 +594,8 @@ public:
 
   void visit (TypeInfoInvariantDeclaration *d) final override
   {
-    Type *tm = mutableOf (d->tinfo);
-    tm = merge2 (tm);
+    Type *tm = dmd::mutableOf (d->tinfo);
+    tm = dmd::merge2 (tm);
 
     /* The vtable for TypeInfo_Invariant.  */
     this->layout_base (Type::typeinfoinvariant);
@@ -611,8 +611,8 @@ public:
 
   void visit (TypeInfoSharedDeclaration *d) final override
   {
-    Type *tm = unSharedOf (d->tinfo);
-    tm = merge2 (tm);
+    Type *tm = dmd::unSharedOf (d->tinfo);
+    tm = dmd::merge2 (tm);
 
     /* The vtable for TypeInfo_Shared.  */
     this->layout_base (Type::typeinfoshared);
@@ -628,8 +628,8 @@ public:
 
   void visit (TypeInfoWildDeclaration *d) final override
   {
-    Type *tm = mutableOf (d->tinfo);
-    tm = merge2 (tm);
+    Type *tm = dmd::mutableOf (d->tinfo);
+    tm = dmd::merge2 (tm);
 
     /* The vtable for TypeInfo_Inout.  */
     this->layout_base (Type::typeinfowild);
@@ -1091,7 +1091,7 @@ public:
     this->layout_field (xcmp);
 
     /* string function(const(void)*) xtoString;  */
-    FuncDeclaration *fdx = search_toString (sd);
+    FuncDeclaration *fdx = dmd::search_toString (sd);
     if (fdx)
       this->layout_field (build_address (get_symbol_decl (fdx)));
     else
@@ -1099,7 +1099,7 @@ public:
 
     /* StructFlags m_flags;  */
     int m_flags = StructFlags::none;
-    if (hasPointers (ti))
+    if (dmd::hasPointers (ti))
       m_flags |= StructFlags::hasPointers;
     this->layout_field (build_integer_cst (m_flags, d_uint_type));
 
@@ -1551,7 +1551,7 @@ create_typeinfo (Type *type, Module *mod, bool generate)
     create_frontend_tinfo_types ();
 
   /* Do this since not all Type's are merged.  */
-  Type *t = merge2 (type);
+  Type *t = dmd::merge2 (type);
   Identifier *ident;
 
   if (!t->vtinfo)
index ed97aa39cc541cc188aac62ab4b7659cd45efdc7..9fa2f888cb22551cc8b82c2984e6965c2b2d2010 100644 (file)
@@ -144,7 +144,7 @@ same_type_p (Type *t1, Type *t2)
     return true;
 
   /* Types are mutably the same type.  */
-  if (tb1->ty == tb2->ty && equivalent (tb1, tb2))
+  if (tb1->ty == tb2->ty && dmd::equivalent (tb1, tb2))
     return true;
 
   return false;
@@ -1334,7 +1334,7 @@ build_ctype (Type *t)
        t->accept (&v);
       else
        {
-         Type *tb = castMod (t, 0);
+         Type *tb = dmd::castMod (t, 0);
          if (!tb->ctype)
            tb->accept (&v);
          t->ctype = insert_type_modifiers (tb->ctype, t->mod);
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test24390a.d b/gcc/testsuite/gdc.test/compilable/imports/test24390a.d
new file mode 100644 (file)
index 0000000..0792c67
--- /dev/null
@@ -0,0 +1,2 @@
+module imports.test24390a;
+public import imports.test24390b;
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test24390b.d b/gcc/testsuite/gdc.test/compilable/imports/test24390b.d
new file mode 100644 (file)
index 0000000..914553e
--- /dev/null
@@ -0,0 +1,9 @@
+module imports.test24390b;
+static if (__traits(compiles, __vector(int[4])) && __traits(compiles, __vector(byte[16])))
+{
+    __vector(int[4]) _mm_set1_epi8 (byte a)
+    {
+        __vector(byte[16]) b = a;
+        return cast(__vector(int[4]))b;
+    }
+}
index 14142630454fe9f8bcc560dbe360137d025a9198..69f65b1cbdf8b589fd8bf9bafe9caa2946d56386 100644 (file)
@@ -2326,7 +2326,7 @@ struct Bug10840
     Data10840* _data;
 }
 
-bool bug10840(int n)
+enum bug10840 = (int n)
 {
     Bug10840 stack;
     if (n == 1)
@@ -2336,7 +2336,7 @@ bool bug10840(int n)
     }
     // Wrong-code for ?:
     return stack._data ? false : true;
-}
+};
 
 static assert(bug10840(0));
 static assert(!is(typeof(Compileable!(bug10840(1)))));
@@ -5910,13 +5910,13 @@ struct Bug7527
     char[] data;
 }
 
-int bug7527()
+enum bug7527 = ()
 {
     auto app = Bug7527();
 
     app.data.ptr[0 .. 1] = "x";
     return 1;
-}
+};
 
 static assert(!is(typeof(compiles!(bug7527()))));
 
diff --git a/gcc/testsuite/gdc.test/compilable/test24390.d b/gcc/testsuite/gdc.test/compilable/test24390.d
new file mode 100644 (file)
index 0000000..f02054d
--- /dev/null
@@ -0,0 +1,26 @@
+// PERMUTE_ARGS: -O -inline
+// EXTRA_SOURCES: imports/test24390a.d imports/test24390b.d
+static if (__traits(compiles, __vector(int[4])) && __traits(compiles, __vector(byte[16])))
+{
+    import imports.test24390a;
+
+    void main()
+    {
+        __vector(int[4]) mmA ;
+        __vector(int[4]) mmB ;
+        auto mask = _mm_cmpestrm(mmA, mmB);
+    }
+
+    __vector(int[4]) _mm_cmpestrm(__vector(int[4]) mmA, __vector(int[4]) mmB)
+    {
+        __vector(int[4]) R;
+        for (int pos ; pos < 16; ++pos)
+        {
+            byte charK = (cast(__vector(byte[16]))mmA).array[pos];
+            __vector(int[4]) eqMask = _mm_set1_epi8(charK);
+            R = R & eqMask;
+
+        }
+        return R;
+    }
+}
index 3c65dac09328d75591428d608b328b71e433e5ec..d5e2cb0f2201051058b4413988c2a6f226ae4153 100644 (file)
@@ -316,3 +316,7 @@ extern(C++, `inst`)
 mixin GetNamespaceTestTemplatedMixin!() GNTT;
 
 static assert (__traits(getCppNamespaces, GNTT.foo) == Seq!(`inst`,/*`decl`,*/ `f`));
+
+int[1] arr;
+// test that index assignment parses as an expression, not a type
+enum _ = __traits(compiles, arr[0] = 0);
index eef95bf9ade295777fcfaaecca695c65247c0b51..cfc39dee37884851161c83a775ede8de9b5e5d50 100644 (file)
@@ -3,4 +3,5 @@ module issue21685;
 class E
 {
     private this() {}
+    public this(int) {}
 }
index c6e29c3eb175474a3d1950e09709798b88c2981b..5b95d9be76414869a005af170df964c84026465d 100644 (file)
@@ -1,7 +1,8 @@
 /* REQUIRED_ARGS: -preview=dip1000 -Ifail_compilation/imports
 TEST_OUTPUT:
 ---
-fail_compilation/issue21685_main.d(11): Error: class `issue21685.E` constructor `this` is not accessible
+fail_compilation/issue21685_main.d(12): Error: constructor `issue21685.E.this` is not accessible from module `issue21685_main`
+fail_compilation/issue21685_main.d(19): Error: constructor `issue21685.E.this` is not accessible from module `issue21685_main`
 ---
 */
 import issue21685;
@@ -10,3 +11,11 @@ void main()
 {
     new E;
 }
+
+class F : E
+{
+    this()
+    {
+        super();
+    }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test23786.d b/gcc/testsuite/gdc.test/fail_compilation/test23786.d
new file mode 100644 (file)
index 0000000..11fe5d4
--- /dev/null
@@ -0,0 +1,39 @@
+/* TEST_OUTPUT:
+---
+fail_compilation/test23786.d(22): Error: function `foo` is not callable using argument types `(double)`
+fail_compilation/test23786.d(22):        cannot pass argument `1.0` of type `double` to parameter `int i`
+fail_compilation/test23786.d(19):        `test23786.foo(int i)` declared here
+fail_compilation/test23786.d(29): Error: function `bar` is not callable using argument types `(int*)`
+fail_compilation/test23786.d(29):        cannot pass argument `& i` of type `int*` to parameter `int i`
+fail_compilation/test23786.d(26):        `test23786.bar(int i)` declared here
+fail_compilation/test23786.d(37): Error: function `baz` is not callable using argument types `(int*)`
+fail_compilation/test23786.d(37):        cannot pass argument `& i` of type `int*` to parameter `int i`
+fail_compilation/test23786.d(34):        `test23786.baz(int i)` declared here
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=23786
+
+module test23786;
+
+void foo(int i)
+{
+    static assert(__traits(parent, {}).mangleof == "_D9test237863fooFiZv");
+    __traits(parent, {})(1.0);
+}
+void foo(int* p) {}
+
+void bar(int i)
+{
+    static assert(__traits(parent, {}).mangleof == "_D9test237863barFiZv");
+    __traits(parent, {})(&i);
+}
+void bar(int* p) {}
+
+void baz(int* p) {}
+void baz(int i)
+{
+    static assert(__traits(parent, {}).mangleof == "_D9test237863bazFiZv");
+    __traits(parent, {})(&i);
+}
+void baz(float* p) {}
index 2e82610148db5edcbe70c169eb29b9a8b23e7830..1c136fcffc2e81e9838a7d41a724cc459ad423e9 100644 (file)
@@ -13,7 +13,7 @@ class AliasDecl {}
 
 void aliasDecl(AliasDecl ad)
 {
-    AliasDecl* zis;
+    AliasDecl* zis = &ad;
 
     static if (is(typeof(to!string(*zis))))
     {
index b24eced9f7f4d014c2b5d1cb7d76e31bf7b847f2..f493eac181de7e40774488a40192ce9fe0a40c81 100644 (file)
@@ -2478,6 +2478,19 @@ void test21835()
     if (arr[0].r != 0.0) assert(0);
 }
 
+////////////////////////////////////////////////////////////////////////
+// https://github.com/dlang/dmd/pull/16187#issuecomment-1946534649
+
+void testDoWhileContinue()
+{
+    int i = 10;
+    do
+    {
+        continue;
+    }
+    while(--i > 0);
+}
+
 ////////////////////////////////////////////////////////////////////////
 
 int main()
@@ -2578,6 +2591,7 @@ int main()
     test21256();
     test21816();
     test21835();
+    testDoWhileContinue();
 
     printf("Success\n");
     return 0;
index e5b25d1f66aa9f74f4653506f5e360498b5a0aaf..089144c4fb5c336084d8e74f5d6ceea4249c5e1f 100644 (file)
@@ -165,6 +165,22 @@ void testEnumInit()
 
 /////////////////////////////////////////////
 
+// https://issues.dlang.org/show_bug.cgi?id=24370
+immutable uint[3][string] test = [
+       "oneTwoThree": [1,2,3],
+       "fourFiveSix": [4,5,6],
+       "sevenEightNine": [7,8,9],
+];
+
+void testStaticArray()
+{
+       assert(test["oneTwoThree"] == [1, 2, 3]);
+       assert(test["fourFiveSix"] == [4, 5, 6]);
+       assert(test["sevenEightNine"] == [7, 8, 9]);
+}
+
+/////////////////////////////////////////////
+
 void main()
 {
     testSimple();
@@ -175,4 +191,5 @@ void main()
     testImmutable();
     testLocalStatic();
     testEnumInit();
+    testStaticArray();
 }
index 2f52826bc4f1721a3b20082b06eb1ffd624ae9af..f05aac916e2993f767b4701b188c027072709b92 100644 (file)
@@ -1,10 +1,10 @@
 // EXTRA_CPP_SOURCES: cpp7925.cpp
 
 /*
-Exclude -O due to a codegen bug on OSX:
+Exclude -O/-inline due to a codegen bug on OSX:
 https://issues.dlang.org/show_bug.cgi?id=22556
 
-PERMUTE_ARGS(osx): -inline -release -g
+PERMUTE_ARGS(osx): -release -g
 */
 
 import core.vararg;
index 74c194508f7da3a91bc6c1233a66d5bdb2d0a3c3..021149aabc7c2da4d7c25583fab900492ada8bea 100644 (file)
@@ -1,4 +1,4 @@
-11240a96635074b2f79d908b9348e9c0fbc3c7dc
+9471b25db9ed44d71e0e27956430c0c6a09c16db
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
index 0d45fe79088e0174a34d3e69832c0f6b4a9e5819..530602580f1ed6909c8addfd549d270180cd5fdf 100644 (file)
 +/
 module core.interpolation;
 
+/++
+    Common implementation for returning an empty string, to avoid storing
+    multiple versions of the same function based on templated types below.
++/
+public string __getEmptyString() @nogc pure nothrow @safe {
+    return "";
+}
+
 /++
     Sentinel values to indicate the beginning and end of an
     interpolated expression sequence.
@@ -104,9 +112,7 @@ struct InterpolationHeader {
         Returns `null` for easy compatibility with existing functions
         like `std.stdio.writeln` and `std.conv.text`.
     +/
-    string toString() const @nogc pure nothrow @safe {
-        return null;
-    }
+    alias toString = __getEmptyString;
 }
 
 /// ditto
@@ -115,9 +121,7 @@ struct InterpolationFooter {
         Returns `null` for easy compatibility with existing functions
         like `std.stdio.writeln` and `std.conv.text`.
     +/
-    string toString() const @nogc pure nothrow @safe {
-        return null;
-    }
+    alias toString = __getEmptyString;
 }
 
 /++
@@ -130,7 +134,7 @@ struct InterpolatedLiteral(string text) {
         segment of the tuple, for easy access and compatibility with
         existing functions like `std.stdio.writeln` and `std.conv.text`.
     +/
-    string toString() const @nogc pure nothrow @safe {
+    static string toString() @nogc pure nothrow @safe {
         return text;
     }
 }
@@ -150,7 +154,5 @@ struct InterpolatedExpression(string text) {
         Returns `null` for easy compatibility with existing functions
         like `std.stdio.writeln` and `std.conv.text`.
     +/
-    string toString() const @nogc pure nothrow @safe {
-        return null;
-    }
+    alias toString = __getEmptyString;
 }
index 50253b09512893d8b23fdbbf57ba7ca01814082b..dd2462fbca14625fe3136f4e08b7f741765d2160 100644 (file)
@@ -14,7 +14,7 @@
  */
 module core.thread.fiber;
 
-import core.thread.osthread;
+import core.thread.threadbase;
 import core.thread.threadgroup;
 import core.thread.types;
 import core.thread.context;
@@ -220,8 +220,8 @@ private
         Fiber   obj = Fiber.getThis();
         assert( obj );
 
-        assert( Thread.getThis().m_curr is obj.m_ctxt );
-        atomicStore!(MemoryOrder.raw)(*cast(shared)&Thread.getThis().m_lock, false);
+        assert( ThreadBase.getThis().m_curr is obj.m_ctxt );
+        atomicStore!(MemoryOrder.raw)(*cast(shared)&ThreadBase.getThis().m_lock, false);
         obj.m_ctxt.tstack = obj.m_ctxt.bstack;
         obj.m_state = Fiber.State.EXEC;
 
@@ -1106,7 +1106,7 @@ private:
             }
         }
 
-        Thread.add( m_ctxt );
+        ThreadBase.add( m_ctxt );
     }
 
 
@@ -1119,9 +1119,9 @@ private:
     {
         // NOTE: m_ctxt is guaranteed to be alive because it is held in the
         //       global context list.
-        Thread.slock.lock_nothrow();
-        scope(exit) Thread.slock.unlock_nothrow();
-        Thread.remove( m_ctxt );
+        ThreadBase.slock.lock_nothrow();
+        scope(exit) ThreadBase.slock.unlock_nothrow();
+        ThreadBase.remove( m_ctxt );
 
         version (Windows)
         {
@@ -1623,7 +1623,7 @@ private:
     //
     final void switchIn() nothrow @nogc
     {
-        Thread  tobj = Thread.getThis();
+        ThreadBase  tobj = ThreadBase.getThis();
         void**  oldp = &tobj.m_curr.tstack;
         void*   newp = m_ctxt.tstack;
 
@@ -1657,7 +1657,7 @@ private:
     //
     final void switchOut() nothrow @nogc
     {
-        Thread  tobj = Thread.getThis();
+        ThreadBase  tobj = ThreadBase.getThis();
         void**  oldp = &m_ctxt.tstack;
         void*   newp = tobj.m_curr.within.tstack;
 
@@ -1682,7 +1682,7 @@ private:
         // NOTE: If use of this fiber is multiplexed across threads, the thread
         //       executing here may be different from the one above, so get the
         //       current thread handle before unlocking, etc.
-        tobj = Thread.getThis();
+        tobj = ThreadBase.getThis();
         atomicStore!(MemoryOrder.raw)(*cast(shared)&tobj.m_lock, false);
         tobj.m_curr.tstack = tobj.m_curr.bstack;
     }
@@ -2027,6 +2027,7 @@ unittest
 unittest
 {
     import core.memory;
+    import core.thread.osthread : Thread;
     import core.time : dur;
 
     static void unreferencedThreadObject()
index 295ca52e350391b113351eccf9b690a1e794e559..a9fcf96254bcf41a43bd2ec4afea5aa4b353167c 100644 (file)
@@ -1625,7 +1625,7 @@ extern (C) @nogc nothrow
 }
 
 
-package extern(D) void* getStackTop() nothrow @nogc
+private extern(D) void* getStackTop() nothrow @nogc
 {
     version (D_InlineAsm_X86)
         asm pure nothrow @nogc { naked; mov EAX, ESP; ret; }
@@ -1638,7 +1638,7 @@ package extern(D) void* getStackTop() nothrow @nogc
 }
 
 
-package extern(D) void* getStackBottom() nothrow @nogc
+private extern(D) void* getStackBottom() nothrow @nogc
 {
     version (Windows)
     {
index 84f9203f23b8ac89baf38e3e2b110f63d93e59ef..f593387c755a00e93f78c567f16a662f1c4346a9 100644 (file)
@@ -84,7 +84,10 @@ private
     enum mutexClassInstanceSize = __traits(classInstanceSize, Mutex);
 
     alias swapContext = externDFunc!("core.thread.osthread.swapContext", void* function(void*) nothrow @nogc);
+}
 
+package
+{
     alias getStackBottom = externDFunc!("core.thread.osthread.getStackBottom", void* function() nothrow @nogc);
     alias getStackTop = externDFunc!("core.thread.osthread.getStackTop", void* function() nothrow @nogc);
 }
index ff182d9da420619b07a5d100d28dcd596e523a2c..4125fd717f4b0745073749448dc6008c197891e9 100644 (file)
@@ -1,4 +1,4 @@
-37796e783ba438a0bedfb435dbbcc7aeaf06ce2a
+5478868465ae1ad743ff76ac5bb92691463ffec5
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/phobos repository.
index ef1170600b3348251a0bad1b5ca914908be2eef2..1453d2b64b948fcb7832fe6acba0516ae85aa868 100644 (file)
@@ -2027,7 +2027,7 @@ private struct ChunkByGroup(alias eq, Range, bool eqEquivalenceAssured)
     }
 
     // Cannot be a copy constructor due to https://issues.dlang.org/show_bug.cgi?id=22239
-    this(this) @trusted
+    this(this) scope @trusted
     {
         import core.lifetime : emplace;
         // since mothership has to be in a union, we have to manually trigger
@@ -2129,7 +2129,7 @@ if (isForwardRange!Range)
     }
 
     // Cannot be a copy constructor due to https://issues.dlang.org/show_bug.cgi?id=22239
-    this(this) @trusted
+    this(this) scope @trusted
     {
         import core.lifetime : emplace;
         // since _impl has to be in a union, we have to manually trigger
index 61b6a5e4eff34f3db341ab826f34de963c205dd1..fbef28e5d563afe6535461d1e505023b4c4abc98 100644 (file)
@@ -1813,22 +1813,28 @@ range.
 
 For example, here is how to remove a single element from an array:
 
+$(RUNNABLE_EXAMPLE
 ----
+import std.algorithm.mutation;
 string[] a = [ "a", "b", "c", "d" ];
 a = a.remove(1); // remove element at offset 1
 assert(a == [ "a", "c", "d"]);
 ----
+)
 
 Note that `remove` does not change the length of the original range directly;
 instead, it returns the shortened range. If its return value is not assigned to
 the original range, the original range will retain its original length, though
 its contents will have changed:
 
+$(RUNNABLE_EXAMPLE
 ----
+import std.algorithm.mutation;
 int[] a = [ 3, 5, 7, 8 ];
 assert(remove(a, 1) == [ 3, 7, 8 ]);
 assert(a == [ 3, 7, 8, 8 ]);
 ----
+)
 
 The element at offset `1` has been removed and the rest of the elements have
 shifted up to fill its place, however, the original array remains of the same
@@ -1838,25 +1844,34 @@ invoked to rearrange elements, and on integers `move` simply copies the source
 to the destination.  To replace `a` with the effect of the removal, simply
 assign the slice returned by `remove` to it, as shown in the first example.
 
+$(H3 $(LNAME2 remove-multiple, Removing multiple elements))
+
 Multiple indices can be passed into `remove`. In that case,
 elements at the respective indices are all removed. The indices must
 be passed in increasing order, otherwise an exception occurs.
 
+$(RUNNABLE_EXAMPLE
 ----
+import std.algorithm.mutation;
 int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
 assert(remove(a, 1, 3, 5) ==
     [ 0, 2, 4, 6, 7, 8, 9, 10 ]);
 ----
+)
 
-(Note that all indices refer to slots in the $(I original) array, not
-in the array as it is being progressively shortened.)
+Note that all indices refer to slots in the $(I original) array, not
+in the array as it is being progressively shortened.
 
-Tuples of two integral offsets can be used to remove an indices range:
+Tuples of two integral offsets can be supplied to remove a range of indices:
 
+$(RUNNABLE_EXAMPLE
 ----
+import std.algorithm.mutation, std.typecons;
 int[] a = [ 3, 4, 5, 6, 7];
-assert(remove(a, 1, tuple(1, 3), 9) == [ 3, 6, 7 ]);
+// remove elements at indices 1 and 2
+assert(remove(a, tuple(1, 3)) == [ 3, 6, 7 ]);
 ----
+)
 
 The tuple passes in a range closed to the left and open to
 the right (consistent with built-in slices), e.g. `tuple(1, 3)`
@@ -1865,22 +1880,31 @@ means indices `1` and `2` but not `3`.
 Finally, any combination of integral offsets and tuples composed of two integral
 offsets can be passed in:
 
+$(RUNNABLE_EXAMPLE
 ----
+import std.algorithm.mutation, std.typecons;
 int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
-assert(remove(a, 1, tuple(3, 5), 9) == [ 0, 2, 5, 6, 7, 8, 10 ]);
+a = remove(a, 1, tuple(3, 5), 9);
+assert(a == [ 0, 2, 5, 6, 7, 8, 10 ]);
 ----
+)
 
 In this case, the slots at positions 1, 3, 4, and 9 are removed from
 the array.
 
+$(H3 $(LNAME2 remove-moving, Moving strategy))
+
 If the need is to remove some elements in the range but the order of
 the remaining elements does not have to be preserved, you may want to
 pass `SwapStrategy.unstable` to `remove`.
 
+$(RUNNABLE_EXAMPLE
 ----
+import std.algorithm.mutation;
 int[] a = [ 0, 1, 2, 3 ];
 assert(remove!(SwapStrategy.unstable)(a, 1) == [ 0, 3, 2 ]);
 ----
+)
 
 In the case above, the element at slot `1` is removed, but replaced
 with the last element of the range. Taking advantage of the relaxation
@@ -1888,7 +1912,7 @@ of the stability requirement, `remove` moved elements from the end
 of the array over the slots to be removed. This way there is less data
 movement to be done which improves the execution time of the function.
 
-The function `remove` works on bidirectional ranges that have assignable
+`remove` works on bidirectional ranges that have assignable
 lvalue elements. The moving strategy is (listed from fastest to slowest):
 
 $(UL
@@ -1914,7 +1938,7 @@ Params:
     offset = which element(s) to remove
 
 Returns:
-    A range containing all of the elements of range with offset removed.
+    A range containing elements of `range` with 1 or more elements removed.
 */
 Range remove
 (SwapStrategy s = SwapStrategy.stable, Range, Offset ...)
index c985015a7af4506a6b8fc6f3c019107d0e0efa53..30f6ffb9f44e3547b4ff5607477d388c6c4d267e 100644 (file)
@@ -2427,7 +2427,14 @@ if (Rs.length > 1 && allSatisfy!(isInputRange, staticMap!(Unqual, Rs)))
         }
     }
 
-    return Result(rs, 0);
+    size_t firstNonEmpty = size_t.max;
+    static foreach (i; 0 .. Rs.length)
+    {
+        if (firstNonEmpty == size_t.max && !rs[i].empty)
+            firstNonEmpty = i;
+    }
+
+    return Result(rs, firstNonEmpty);
 }
 
 ///
@@ -2489,6 +2496,14 @@ pure @safe nothrow unittest
     assert(equal(r, [ S(1), S(10), S(2), S(20) ]));
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=24384
+@safe unittest
+{
+    auto r = roundRobin("", "a");
+    assert(!r.empty);
+    auto e = r.front;
+}
+
 /**
 Iterates a random-access range starting from a given point and
 progressively extending left and right from that point. If no initial
@@ -10167,10 +10182,18 @@ public:
 private struct OnlyResult(Values...)
 if (Values.length > 1)
 {
+    import std.meta : ApplyRight;
+    import std.traits : isAssignable;
+
     private enum arity = Values.length;
 
     private alias UnqualValues = staticMap!(Unqual, Values);
 
+    private enum canAssignElements = allSatisfy!(
+        ApplyRight!(isAssignable, CommonType!Values),
+        Values
+    );
+
     private this(return scope ref Values values)
     {
         ref @trusted unqual(T)(ref T x){return cast() x;}
@@ -10195,6 +10218,15 @@ if (Values.length > 1)
         return this[0];
     }
 
+    static if (canAssignElements)
+    {
+        void front(CommonType!Values value) @property
+        {
+            assert(!empty, "Attempting to assign the front of an empty Only range");
+            this[0] = value;
+        }
+    }
+
     void popFront()
     {
         assert(!empty, "Attempting to popFront an empty Only range");
@@ -10207,6 +10239,15 @@ if (Values.length > 1)
         return this[$ - 1];
     }
 
+    static if (canAssignElements)
+    {
+        void back(CommonType!Values value) @property
+        {
+            assert(!empty, "Attempting to assign the back of an empty Only range");
+            this[$ - 1] = value;
+        }
+    }
+
     void popBack()
     {
         assert(!empty, "Attempting to popBack an empty Only range");
@@ -10236,6 +10277,18 @@ if (Values.length > 1)
                 return cast(T) values[i];
     }
 
+    static if (canAssignElements)
+    {
+        void opIndexAssign(CommonType!Values value, size_t idx)
+        {
+            assert(idx < length, "Attempting to assign to an out of bounds index of an Only range");
+            final switch (frontIndex + idx)
+                static foreach (i; 0 .. Values.length)
+                case i:
+                    values[i] = value;
+        }
+    }
+
     OnlyResult opSlice()
     {
         return this;
@@ -10279,16 +10332,34 @@ if (Values.length > 1)
 // Specialize for single-element results
 private struct OnlyResult(T)
 {
+    import std.traits : isAssignable;
+
     @property T front()
     {
         assert(!empty, "Attempting to fetch the front of an empty Only range");
         return fetchFront();
     }
+    static if (isAssignable!T)
+    {
+        @property void front(T value)
+        {
+            assert(!empty, "Attempting to assign the front of an empty Only range");
+            assignFront(value);
+        }
+    }
     @property T back()
     {
         assert(!empty, "Attempting to fetch the back of an empty Only range");
         return fetchFront();
     }
+    static if (isAssignable!T)
+    {
+        @property void back(T value)
+        {
+            assert(!empty, "Attempting to assign the front of an empty Only range");
+            assignFront(value);
+        }
+    }
     @property bool empty() const { return _empty; }
     @property size_t length() const { return !_empty; }
     @property auto save() { return this; }
@@ -10319,6 +10390,15 @@ private struct OnlyResult(T)
         return fetchFront();
     }
 
+    static if (isAssignable!T)
+    {
+        void opIndexAssign(T value, size_t i)
+        {
+            assert(!_empty && i == 0, "Attempting to assign an out of bounds index of an Only range");
+            assignFront(value);
+        }
+    }
+
     OnlyResult opSlice()
     {
         return this;
@@ -10348,6 +10428,13 @@ private struct OnlyResult(T)
     {
         return *cast(T*)&_value;
     }
+    static if (isAssignable!T)
+    {
+        private @trusted void assignFront(T newValue)
+        {
+            *cast(T*) &_value = newValue;
+        }
+    }
 }
 
 /**
@@ -10368,6 +10455,9 @@ Params:
 Returns:
     A `RandomAccessRange` of the assembled values.
 
+    The returned range can be sliced. Its elements can be assigned to if every
+    type in `Values` supports assignment from the range's element type.
+
 See_Also: $(LREF chain) to chain ranges
  */
 auto only(Values...)(return scope Values values)
@@ -10629,6 +10719,32 @@ auto only()()
     auto r1 = arr.chain(x.only, only(x, x));
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=24382
+@safe unittest
+{
+    auto r1 = only(123);
+    r1.front = 456;
+    r1.back = 456;
+    r1[0] = 456;
+
+    auto r2 = only(123, 456);
+    r2.front = 789;
+    r2.back = 789;
+    r2[0] = 789;
+
+    auto r3 = only(1.23, 456);
+    // Can't assign double to int
+    static assert(!__traits(compiles, r3.front = 7.89));
+    static assert(!__traits(compiles, r3.back = 7.89));
+    // Workaround https://issues.dlang.org/show_bug.cgi?id=24383
+    static assert(!__traits(compiles, () { r3[0] = 7.89; }));
+    // Can't assign type other than element type (even if compatible)
+    static assert(!__traits(compiles, r3.front = 789));
+    static assert(!__traits(compiles, r3.back = 789));
+    // Workaround https://issues.dlang.org/show_bug.cgi?id=24383
+    static assert(!__traits(compiles, () { r3[0] = 789; }));
+}
+
 /**
 Iterate over `range` with an attached index variable.