d: Merge dmd, druntime 9471b25db9, phobos 547886846.
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.
This commit is contained in:
parent
a71d87431d
commit
5aff58e5ed
86 changed files with 1815 additions and 728 deletions
|
@ -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 \
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ());
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1 +1 @@
|
|||
v2.107.0
|
||||
v2.107.1-rc.1
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
623
gcc/d/dmd/cxxfrontend.d
Normal file
623
gcc/d/dmd/cxxfrontend.d
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
/**
|
||||
* ImportC global `asm` definition.
|
||||
*/
|
||||
Dsymbol handleTagSymbols(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
|
||||
extern (C++) final class CAsmDeclaration : Dsymbol
|
||||
{
|
||||
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)
|
||||
Expression code;
|
||||
extern (D) this(Expression e) nothrow @safe
|
||||
{
|
||||
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());
|
||||
super();
|
||||
this.code = e;
|
||||
}
|
||||
|
||||
if (!sd2)
|
||||
override inout(CAsmDeclaration) isCAsmDeclaration() inout nothrow
|
||||
{
|
||||
/* 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
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
if (sd && sd2) // `s` is a tag, `sd2` is the same tag
|
||||
override void accept(Visitor v)
|
||||
{
|
||||
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
|
||||
v.visit(this);
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
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);
|
||||
// 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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) ||
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -317,14 +317,17 @@ public:
|
|||
void accept(Visitor *v) override { v->visit(this); }
|
||||
};
|
||||
|
||||
// in templateparamsem.d
|
||||
bool tpsemantic(TemplateParameter *tp, Scope *sc, TemplateParameters *parameters);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
2
gcc/testsuite/gdc.test/compilable/imports/test24390a.d
Normal file
2
gcc/testsuite/gdc.test/compilable/imports/test24390a.d
Normal file
|
@ -0,0 +1,2 @@
|
|||
module imports.test24390a;
|
||||
public import imports.test24390b;
|
9
gcc/testsuite/gdc.test/compilable/imports/test24390b.d
Normal file
9
gcc/testsuite/gdc.test/compilable/imports/test24390b.d
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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()))));
|
||||
|
||||
|
|
26
gcc/testsuite/gdc.test/compilable/test24390.d
Normal file
26
gcc/testsuite/gdc.test/compilable/test24390.d
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -3,4 +3,5 @@ module issue21685;
|
|||
class E
|
||||
{
|
||||
private this() {}
|
||||
public this(int) {}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
39
gcc/testsuite/gdc.test/fail_compilation/test23786.d
Normal file
39
gcc/testsuite/gdc.test/fail_compilation/test23786.d
Normal file
|
@ -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) {}
|
|
@ -13,7 +13,7 @@ class AliasDecl {}
|
|||
|
||||
void aliasDecl(AliasDecl ad)
|
||||
{
|
||||
AliasDecl* zis;
|
||||
AliasDecl* zis = &ad;
|
||||
|
||||
static if (is(typeof(to!string(*zis))))
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -91,6 +91,14 @@
|
|||
+/
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ...)
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue