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:
Iain Buclaw 2024-02-17 21:03:38 +01:00
parent a71d87431d
commit 5aff58e5ed
86 changed files with 1815 additions and 728 deletions

View file

@ -104,6 +104,7 @@ D_FRONTEND_OBJS = \
d/cppmangle.o \
d/ctfeexpr.o \
d/ctorflow.o \
d/cxxfrontend.o \
d/dcast.o \
d/dclass.o \
d/declaration.o \

View file

@ -320,14 +320,14 @@ build_attributes (Expressions *eattrs)
if (!eattrs)
return NULL_TREE;
expandTuples (eattrs);
dmd::expandTuples (eattrs);
tree attribs = NULL_TREE;
for (size_t i = 0; i < eattrs->length; i++)
{
Expression *attr = (*eattrs)[i];
Dsymbol *sym = toDsymbol (attr->type, NULL);
Dsymbol *sym = dmd::toDsymbol (attr->type, NULL);
if (!sym)
{
@ -354,7 +354,7 @@ build_attributes (Expressions *eattrs)
/* Get the result of the attribute if it hasn't already been folded. */
if (attr->op == EXP::call)
attr = ctfeInterpret (attr);
attr = dmd::ctfeInterpret (attr);
if (attr->op != EXP::structLiteral)
{

View file

@ -98,14 +98,14 @@ build_frontend_type (tree type)
/* Check for char * first. Needs to be done for chars/string. */
if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == char_type_node)
{
dtype = addMod (Type::tchar, dtype->mod);
return addMod (dtype->pointerTo (), mod);
dtype = dmd::addMod (Type::tchar, dtype->mod);
return dmd::addMod (dmd::pointerTo (dtype), mod);
}
if (dtype->ty == TY::Tfunction)
return addMod (TypePointer::create (dtype), mod);
return dmd::addMod (TypePointer::create (dtype), mod);
return addMod (dtype->pointerTo (), mod);
return dmd::addMod (dmd::pointerTo (dtype), mod);
}
break;
@ -116,7 +116,7 @@ build_frontend_type (tree type)
/* Want to assign ctype directly so that the REFERENCE_TYPE code
can be turned into as an `inout' argument. Can't use pointerTo(),
because the returned Type is shared. */
dtype = addMod (TypePointer::create (dtype), mod);
dtype = dmd::addMod (TypePointer::create (dtype), mod);
dtype->ctype = type;
builtin_converted_decls.safe_push (builtin_data (dtype, type));
return dtype;
@ -125,7 +125,7 @@ build_frontend_type (tree type)
case BOOLEAN_TYPE:
/* Should be no need for size checking. */
return addMod (Type::tbool, mod);
return dmd::addMod (Type::tbool, mod);
case INTEGER_TYPE:
{
@ -143,7 +143,7 @@ build_frontend_type (tree type)
|| size != dtype->size ())
continue;
return addMod (dtype, mod);
return dmd::addMod (dtype, mod);
}
break;
}
@ -160,7 +160,7 @@ build_frontend_type (tree type)
if (dtype->size () != size)
continue;
return addMod (dtype, mod);
return dmd::addMod (dtype, mod);
}
break;
}
@ -177,13 +177,13 @@ build_frontend_type (tree type)
if (dtype->size () != size)
continue;
return addMod (dtype, mod);
return dmd::addMod (dtype, mod);
}
break;
}
case VOID_TYPE:
return addMod (Type::tvoid, mod);
return dmd::addMod (Type::tvoid, mod);
case ARRAY_TYPE:
dtype = build_frontend_type (TREE_TYPE (type));
@ -197,7 +197,8 @@ build_frontend_type (tree type)
length = size_binop (PLUS_EXPR, size_one_node,
convert (sizetype, length));
dtype = addMod (dtype->sarrayOf (TREE_INT_CST_LOW (length)), mod);
dtype =
dmd::addMod (dtype->sarrayOf (TREE_INT_CST_LOW (length)), mod);
builtin_converted_decls.safe_push (builtin_data (dtype, type));
return dtype;
}
@ -213,11 +214,11 @@ build_frontend_type (tree type)
if (!dtype)
break;
dtype = addMod (dtype->sarrayOf (nunits), mod);
dtype = dmd::addMod (dtype->sarrayOf (nunits), mod);
if (target.isVectorTypeSupported (dtype->size (), dtype->nextOf ()))
break;
dtype = addMod (TypeVector::create (dtype), mod);
dtype = dmd::addMod (TypeVector::create (dtype), mod);
builtin_converted_decls.safe_push (builtin_data (dtype, type));
return dtype;
}
@ -241,9 +242,9 @@ build_frontend_type (tree type)
sdecl->alignsize = TYPE_ALIGN_UNIT (type);
sdecl->alignment.setDefault ();
sdecl->sizeok = Sizeok::done;
sdecl->type = addMod (TypeStruct::create (sdecl), mod);
sdecl->type = dmd::addMod (TypeStruct::create (sdecl), mod);
sdecl->type->ctype = type;
merge2 (sdecl->type);
dmd::merge2 (sdecl->type);
/* Add both named and anonymous fields as members of the struct.
Anonymous fields still need a name in D, so call them "__pad%u". */
@ -334,7 +335,7 @@ build_frontend_type (tree type)
if (args->length != 0 || varargs_p == VARARGnone)
{
dtype = TypeFunction::create (args, dtype, varargs_p, LINK::c);
return addMod (dtype, mod);
return dmd::addMod (dtype, mod);
}
}
break;
@ -690,10 +691,10 @@ strip_type_modifiers (Type *type)
if (type->ty == TY::Tpointer)
{
Type *tnext = strip_type_modifiers (type->nextOf ());
return tnext->pointerTo ();
return dmd::pointerTo (tnext);
}
return castMod (type, 0);
return dmd::castMod (type, 0);
}
/* Returns true if types T1 and T2 representing return types or types of
@ -727,7 +728,7 @@ static bool
covariant_with_builtin_type_p (Type *t1, Type *t2)
{
/* Check whether the declared function matches the built-in. */
if (same_type_p (t1, t2) || covariant (t1, t2) == Covariant::yes)
if (same_type_p (t1, t2) || dmd::covariant (t1, t2) == Covariant::yes)
return true;
/* May not be covariant because of D attributes applied on t1.

View file

@ -150,14 +150,14 @@ declaration_type (Declaration *decl)
TypeFunction *tf = TypeFunction::create (NULL, decl->type,
VARARGnone, LINK::d);
TypeDelegate *t = TypeDelegate::create (tf);
return build_ctype (merge2 (t));
return build_ctype (dmd::merge2 (t));
}
/* Static array va_list have array->pointer conversions applied. */
if (decl->isParameter () && valist_array_p (decl->type))
{
Type *valist = decl->type->nextOf ()->pointerTo ();
valist = castMod (valist, decl->type->mod);
Type *valist = dmd::pointerTo (decl->type->nextOf ());
valist = dmd::castMod (valist, decl->type->mod);
return build_ctype (valist);
}
@ -200,14 +200,14 @@ parameter_type (Parameter *arg)
TypeFunction *tf = TypeFunction::create (NULL, arg->type,
VARARGnone, LINK::d);
TypeDelegate *t = TypeDelegate::create (tf);
return build_ctype (merge2 (t));
return build_ctype (dmd::merge2 (t));
}
/* Static array va_list have array->pointer conversions applied. */
if (valist_array_p (arg->type))
{
Type *valist = arg->type->nextOf ()->pointerTo ();
valist = castMod (valist, arg->type->mod);
Type *valist = dmd::pointerTo (arg->type->nextOf ());
valist = dmd::castMod (valist, arg->type->mod);
return build_ctype (valist);
}
@ -1089,7 +1089,7 @@ build_array_struct_comparison (tree_code code, StructDeclaration *sd,
add_stmt (build_assign (INIT_EXPR, result, init));
/* Cast pointer-to-array to pointer-to-struct. */
tree ptrtype = build_ctype (sd->type->pointerTo ());
tree ptrtype = build_ctype (dmd::pointerTo (sd->type));
tree lentype = TREE_TYPE (length);
push_binding_level (level_block);
@ -1859,7 +1859,7 @@ void_okay_p (tree t)
if (VOID_TYPE_P (TREE_TYPE (type)))
{
tree totype = build_ctype (Type::tuns8->pointerTo ());
tree totype = build_ctype (dmd::pointerTo (Type::tuns8));
return fold_convert (totype, t);
}

View file

@ -470,7 +470,7 @@ convert_expr (tree exp, Type *etype, Type *totype)
dinteger_t esize = ebtype->nextOf ()->size ();
dinteger_t tsize = tbtype->nextOf ()->size ();
tree ptrtype = build_ctype (tbtype->nextOf ()->pointerTo ());
tree ptrtype = build_ctype (dmd::pointerTo (tbtype->nextOf ()));
if (esize != tsize)
{
@ -727,12 +727,12 @@ check_valist_conversion (Expression *expr, Type *totype, bool in_assignment)
if (VarExp *ve = expr->isVarExp ())
{
decl = ve->var;
type = ve->var->type->nextOf ()->pointerTo ();
type = dmd::pointerTo (ve->var->type->nextOf ());
}
else if (SymOffExp *se = expr->isSymOffExp ())
{
decl = se->var;
type = se->var->type->nextOf ()->pointerTo ()->pointerTo ();
type = dmd::pointerTo (dmd::pointerTo (se->var->type->nextOf ()));
}
/* Should not be called unless is_valist_parameter_type also matched. */

View file

@ -1029,8 +1029,8 @@ d_generate_ddoc_file (Module *m, OutBuffer &ddocbuf)
d_read_ddoc_files (global.params.ddoc.files, ddocbuf);
OutBuffer ddocbuf_out;
gendocfile (m, ddocbuf.peekChars (), ddocbuf.length (), global.datetime,
global.errorSink, ddocbuf_out);
dmd::gendocfile (m, ddocbuf.peekChars (), ddocbuf.length (), global.datetime,
global.errorSink, ddocbuf_out);
d_write_file (m->docfile.toChars (), ddocbuf_out.peekChars ());
}
@ -1205,7 +1205,7 @@ d_parse_file (void)
message ("import %s", m->toChars ());
OutBuffer buf;
genhdrfile (m, global.params.dihdr.fullOutput, buf);
dmd::genhdrfile (m, global.params.dihdr.fullOutput, buf);
d_write_file (m->hdrfile.toChars (), buf.peekChars ());
}
@ -1223,7 +1223,7 @@ d_parse_file (void)
if (global.params.v.verbose)
message ("importall %s", m->toChars ());
importAll (m, NULL);
dmd::importAll (m, NULL);
}
if (global.errors)
@ -1247,7 +1247,7 @@ d_parse_file (void)
if (global.params.v.verbose)
message ("semantic %s", m->toChars ());
dsymbolSemantic (m, NULL);
dmd::dsymbolSemantic (m, NULL);
}
/* Do deferred semantic analysis. */
@ -1278,7 +1278,7 @@ d_parse_file (void)
if (global.params.v.verbose)
message ("semantic2 %s", m->toChars ());
semantic2 (m, NULL);
dmd::semantic2 (m, NULL);
}
Module::runDeferredSemantic2 ();
@ -1294,7 +1294,7 @@ d_parse_file (void)
if (global.params.v.verbose)
message ("semantic3 %s", m->toChars ());
semantic3 (m, NULL);
dmd::semantic3 (m, NULL);
}
Module::runDeferredSemantic3 ();
@ -1318,7 +1318,7 @@ d_parse_file (void)
/* Declare the name of the root module as the first global name in order
to make the middle-end fully deterministic. */
OutBuffer buf;
mangleToBuffer (Module::rootModule, buf);
dmd::mangleToBuffer (Module::rootModule, buf);
first_global_object_name = buf.extractChars ();
}
@ -1341,15 +1341,15 @@ d_parse_file (void)
if (global.params.v.templates)
{
printTemplateStats (global.params.v.templatesListInstances,
global.errorSink);
dmd::printTemplateStats (global.params.v.templatesListInstances,
global.errorSink);
}
/* Generate JSON files. */
if (global.params.json.doOutput)
{
OutBuffer buf;
json_generate (modules, buf);
dmd::json_generate (modules, buf);
d_write_file (global.params.json.name.ptr, buf.peekChars ());
}
@ -1372,14 +1372,14 @@ d_parse_file (void)
OutBuffer buf;
buf.doindent = 1;
moduleToBuffer (buf, true, m);
dmd::moduleToBuffer (buf, true, m);
message ("%s", buf.peekChars ());
}
}
/* Generate C++ header files. */
if (global.params.cxxhdr.doOutput)
genCppHdrFiles (modules);
dmd::genCppHdrFiles (modules);
if (global.errors)
goto had_errors;

View file

@ -335,7 +335,7 @@ Target::isVectorOpSupported (Type *type, EXP op, Type *)
const char *
TargetCPP::toMangle (Dsymbol *s)
{
return toCppMangleItanium (s);
return dmd::toCppMangleItanium (s);
}
/* Return the symbol mangling of CD for C++ linkage. */
@ -343,7 +343,7 @@ TargetCPP::toMangle (Dsymbol *s)
const char *
TargetCPP::typeInfoMangle (ClassDeclaration *cd)
{
return cppTypeInfoMangleItanium (cd);
return dmd::cppTypeInfoMangleItanium (cd);
}
/* Get mangle name of a this-adjusting thunk to the function declaration FD
@ -352,7 +352,7 @@ TargetCPP::typeInfoMangle (ClassDeclaration *cd)
const char *
TargetCPP::thunkMangle (FuncDeclaration *fd, int offset)
{
return cppThunkMangleItanium (fd, offset);
return dmd::cppThunkMangleItanium (fd, offset);
}
/* For a vendor-specific type, return a string containing the C++ mangling.
@ -381,11 +381,11 @@ TargetCPP::parameterType (Type *type)
Type *tvalist = target.va_listType (Loc (), NULL);
if (type->ty == TY::Tsarray && tvalist->ty == TY::Tsarray)
{
Type *tb = mutableOf (type->toBasetype ());
Type *tb = dmd::mutableOf (type->toBasetype ());
if (tb == tvalist)
{
tb = type->nextOf ()->pointerTo ();
type = castMod (tb, type->mod);
tb = dmd::pointerTo (type->nextOf ());
type = dmd::castMod (tb, type->mod);
}
}

View file

@ -69,11 +69,11 @@ const char *
d_mangle_decl (Dsymbol *decl)
{
if (decl->isFuncDeclaration ())
return mangleExact ((FuncDeclaration *) decl);
return dmd::mangleExact ((FuncDeclaration *) decl);
else
{
OutBuffer buf;
mangleToBuffer (decl, buf);
dmd::mangleToBuffer (decl, buf);
return buf.extractChars ();
}
}
@ -332,6 +332,14 @@ public:
d->semanticRun = PASS::obj;
}
/* Finish a top-level `asm` definition. */
void visit (CAsmDeclaration *d) final override
{
tree asm_str = build_expr (d->code);
symtab->finalize_toplevel_asm (asm_str);
}
/* Expand any local variables found in tuples. */
void visit (TupleDeclaration *d) final override
@ -402,7 +410,7 @@ public:
void visit (Nspace *d) final override
{
if (isError (d) || !d->members)
if (dmd::isError (d) || !d->members)
return;
for (size_t i = 0; i < d->members->length; i++)
@ -447,7 +455,7 @@ public:
void visit (TemplateInstance *d) final override
{
if (isError (d)|| !d->members)
if (dmd::isError (d)|| !d->members)
return;
if (!d->needsCodegen ())
@ -461,7 +469,7 @@ public:
void visit (TemplateMixin *d) final override
{
if (isError (d)|| !d->members)
if (dmd::isError (d)|| !d->members)
return;
for (size_t i = 0; i < d->members->length; i++)
@ -539,7 +547,7 @@ public:
continue;
/* Ensure function has a return value. */
if (!functionSemantic (fd))
if (!dmd::functionSemantic (fd))
has_errors = true;
/* No name hiding to check for. */
@ -765,7 +773,7 @@ public:
&& d->_init && !d->_init->isVoidInitializer ())
{
/* Evaluate RHS for side effects first. */
Expression *ie = initializerToExpression (d->_init);
Expression *ie = dmd::initializerToExpression (d->_init);
add_stmt (build_expr (ie));
Expression *e = d->type->defaultInitLiteral (d->loc);
@ -785,7 +793,7 @@ public:
{
/* Do not store variables we cannot take the address of,
but keep the values for purposes of debugging. */
if (d->type->isscalar () && !hasPointers (d->type))
if (d->type->isscalar () && !dmd::hasPointers (d->type))
{
tree decl = get_symbol_decl (d);
d_pushdecl (decl);
@ -820,7 +828,8 @@ public:
/* Use the explicit initializer, this includes `void`. */
if (!d->_init->isVoidInitializer ())
{
Expression *e = initializerToExpression (d->_init, d->type);
Expression *e =
dmd::initializerToExpression (d->_init, d->type);
DECL_INITIAL (decl) = build_expr (e, true);
}
}
@ -857,7 +866,7 @@ public:
tree decl = get_symbol_decl (d);
ExpInitializer *vinit = d->_init->isExpInitializer ();
Expression *ie = initializerToExpression (vinit);
Expression *ie = dmd::initializerToExpression (vinit);
tree exp = build_expr (ie);
/* Maybe put variable on list of things needing destruction. */
@ -964,7 +973,7 @@ public:
gcc_assert (!doing_semantic_analysis_p);
doing_semantic_analysis_p = true;
functionSemantic3 (d);
dmd::functionSemantic3 (d);
Module::runDeferredSemantic3 ();
doing_semantic_analysis_p = false;
}
@ -1241,7 +1250,7 @@ get_symbol_decl (Declaration *decl)
if (!vd->canTakeAddressOf () && !vd->type->isscalar ())
{
gcc_assert (vd->_init && !vd->_init->isVoidInitializer ());
Expression *ie = initializerToExpression (vd->_init);
Expression *ie = dmd::initializerToExpression (vd->_init);
decl->csym = build_expr (ie, false);
return decl->csym;
}
@ -1252,7 +1261,7 @@ get_symbol_decl (Declaration *decl)
if (fd)
{
/* Run full semantic on functions we need to know about. */
if (!functionSemantic (fd))
if (!dmd::functionSemantic (fd))
{
decl->csym = error_mark_node;
return decl->csym;
@ -1301,7 +1310,7 @@ get_symbol_decl (Declaration *decl)
/* Non-scalar manifest constants have already been dealt with. */
gcc_assert (vd->type->isscalar ());
Expression *ie = initializerToExpression (vd->_init);
Expression *ie = dmd::initializerToExpression (vd->_init);
DECL_INITIAL (decl->csym) = build_expr (ie, true);
}
@ -2398,7 +2407,7 @@ layout_class_initializer (ClassDeclaration *cd)
NewExp *ne = NewExp::create (cd->loc, NULL, cd->type, NULL);
ne->type = cd->type;
Expression *e = ctfeInterpret (ne);
Expression *e = dmd::ctfeInterpret (ne);
gcc_assert (e->op == EXP::classReference);
return build_class_instance (e->isClassReferenceExp ());

View file

@ -1,4 +1,4 @@
11240a96635074b2f79d908b9348e9c0fbc3c7dc
9471b25db9ed44d71e0e27956430c0c6a09c16db
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.

View file

@ -1 +1 @@
v2.107.0
v2.107.1-rc.1

View file

@ -41,8 +41,11 @@ enum class Baseok : uint8_t
semanticdone // all base classes semantic done
};
FuncDeclaration *search_toString(StructDeclaration *sd);
void semanticTypeInfoMembers(StructDeclaration *sd);
namespace dmd
{
FuncDeclaration *search_toString(StructDeclaration *sd);
void semanticTypeInfoMembers(StructDeclaration *sd);
}
enum class ClassKind : uint8_t
{

View file

@ -136,6 +136,23 @@ final class CParser(AST) : Parser!AST
return wrap;
}
/* GNU Extensions
* external-declaration:
* simple-asm-expr ;
*/
if (token.value == TOK.asm_)
{
nextToken(); // move past asm
check(TOK.leftParenthesis);
if (token.value != TOK.string_)
error("string literal expected for Asm Definition, not `%s`", token.toChars());
auto code = cparsePrimaryExp();
check(TOK.rightParenthesis);
symbols.push(new AST.CAsmDeclaration(code));
check(TOK.semicolon);
continue;
}
cparseDeclaration(LVL.global);
}
}

View file

@ -65,7 +65,7 @@ package CppOperator isCppOperator(Identifier id)
}
///
extern(C++) const(char)* toCppMangleItanium(Dsymbol s)
const(char)* toCppMangleItanium(Dsymbol s)
{
//printf("toCppMangleItanium(%s)\n", s.toChars());
OutBuffer buf;
@ -75,7 +75,7 @@ extern(C++) const(char)* toCppMangleItanium(Dsymbol s)
}
///
extern(C++) const(char)* cppTypeInfoMangleItanium(Dsymbol s)
const(char)* cppTypeInfoMangleItanium(Dsymbol s)
{
//printf("cppTypeInfoMangle(%s)\n", s.toChars());
OutBuffer buf;
@ -86,7 +86,7 @@ extern(C++) const(char)* cppTypeInfoMangleItanium(Dsymbol s)
}
///
extern(C++) const(char)* cppThunkMangleItanium(FuncDeclaration fd, int offset)
const(char)* cppThunkMangleItanium(FuncDeclaration fd, int offset)
{
//printf("cppThunkMangleItanium(%s)\n", fd.toChars());
OutBuffer buf;

623
gcc/d/dmd/cxxfrontend.d Normal file
View 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);
}
}

View file

@ -30,8 +30,11 @@ class StructDeclaration;
struct IntRange;
struct AttributeViolation;
bool functionSemantic(FuncDeclaration* fd);
bool functionSemantic3(FuncDeclaration* fd);
namespace dmd
{
bool functionSemantic(FuncDeclaration* fd);
bool functionSemantic3(FuncDeclaration* fd);
}
//enum STC : ulong from astenums.d:

View file

@ -50,7 +50,7 @@ import dmd.rootobject;
import dmd.root.utf;
import dmd.statement;
import dmd.tokens;
import dmd.typesem : mutableOf, equivalent;
import dmd.typesem : mutableOf, equivalent, pointerTo;
import dmd.utils : arrayCastBigEndian;
import dmd.visitor;
@ -63,7 +63,7 @@ import dmd.visitor;
* functions and may invoke a function that contains `ErrorStatement` in its body.
* If that, the "CTFE failed because of previous errors" error is raised.
*/
extern(C++) public Expression ctfeInterpret(Expression e)
public Expression ctfeInterpret(Expression e)
{
switch (e.op)
{

View file

@ -18,7 +18,7 @@ module dmd.dmangle;
/******************************************************************************
* Returns exact mangled name of function.
*/
extern (C++) const(char)* mangleExact(FuncDeclaration fd)
const(char)* mangleExact(FuncDeclaration fd)
{
//printf("mangleExact()\n");
if (!fd.mangleString)
@ -32,7 +32,7 @@ extern (C++) const(char)* mangleExact(FuncDeclaration fd)
return fd.mangleString;
}
extern (C++) void mangleToBuffer(Type t, ref OutBuffer buf)
void mangleToBuffer(Type t, ref OutBuffer buf)
{
//printf("mangleToBuffer t()\n");
if (t.deco)
@ -45,7 +45,7 @@ extern (C++) void mangleToBuffer(Type t, ref OutBuffer buf)
}
}
extern (C++) void mangleToBuffer(Expression e, ref OutBuffer buf)
void mangleToBuffer(Expression e, ref OutBuffer buf)
{
//printf("mangleToBuffer e()\n");
auto backref = Backref(null);
@ -53,7 +53,7 @@ extern (C++) void mangleToBuffer(Expression e, ref OutBuffer buf)
e.accept(v);
}
extern (C++) void mangleToBuffer(Dsymbol s, ref OutBuffer buf)
void mangleToBuffer(Dsymbol s, ref OutBuffer buf)
{
//printf("mangleToBuffer s(%s)\n", s.toChars());
auto backref = Backref(null);
@ -61,7 +61,7 @@ extern (C++) void mangleToBuffer(Dsymbol s, ref OutBuffer buf)
s.accept(v);
}
extern (C++) void mangleToBuffer(TemplateInstance ti, ref OutBuffer buf)
void mangleToBuffer(TemplateInstance ti, ref OutBuffer buf)
{
//printf("mangleToBuffer ti()\n");
auto backref = Backref(null);

View file

@ -1300,7 +1300,7 @@ extern (C++) struct ModuleDeclaration
* aclasses = array to fill in
* Returns: array of local classes
*/
extern (C++) void getLocalClasses(Module mod, ref ClassDeclarations aclasses)
void getLocalClasses(Module mod, ref ClassDeclarations aclasses)
{
//printf("members.length = %d\n", mod.members.length);
int pushAddClassDg(size_t n, Dsymbol sm)
@ -1565,7 +1565,7 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod)
* const(MemberInfo)[] getMembers(string);
* Returns NULL if not found
*/
extern(C++) FuncDeclaration findGetMembers(ScopeDsymbol dsym)
FuncDeclaration findGetMembers(ScopeDsymbol dsym)
{
import dmd.opover : search_function;
Dsymbol s = search_function(dsym, Id.getmembers);

View file

@ -382,7 +382,7 @@ immutable ddoc_decl_dd_e = ")\n";
* outbuf = append the Ddoc text to this
*/
public
extern(C++) void gendocfile(Module m, const char* ddoctext_ptr, size_t ddoctext_length, const char* datetime, ErrorSink eSink, ref OutBuffer outbuf)
void gendocfile(Module m, const char* ddoctext_ptr, size_t ddoctext_length, const char* datetime, ErrorSink eSink, ref OutBuffer outbuf)
{
gendocfile(m, ddoctext_ptr[0 .. ddoctext_length], datetime, eSink, outbuf);
}

View file

@ -15,5 +15,8 @@
class Module;
class ErrorSink;
void gendocfile(Module *m, const char *ddoctext_ptr, d_size_t ddoctext_length,
const char *datetime, ErrorSink *eSink, OutBuffer &outbuf);
namespace dmd
{
void gendocfile(Module *m, const char *ddoctext_ptr, d_size_t ddoctext_length,
const char *datetime, ErrorSink *eSink, OutBuffer &outbuf);
}

View file

@ -34,6 +34,7 @@ import dmd.func;
import dmd.globals;
import dmd.id;
import dmd.identifier;
import dmd.importc;
import dmd.location;
import dmd.common.outbuffer;
import dmd.root.rmem;

View file

@ -48,7 +48,7 @@ import dmd.visitor;
* Returns:
* FuncDeclaration of `toString()` if found, `null` if not
*/
extern (C++) FuncDeclaration search_toString(StructDeclaration sd)
FuncDeclaration search_toString(StructDeclaration sd)
{
Dsymbol s = search_function(sd, Id.tostring);
FuncDeclaration fd = s ? s.isFuncDeclaration() : null;

View file

@ -1105,6 +1105,7 @@ extern (C++) class Dsymbol : ASTNode
inout(MixinDeclaration) isMixinDeclaration() inout { return null; }
inout(StaticAssert) isStaticAssert() inout { return null; }
inout(StaticIfDeclaration) isStaticIfDeclaration() inout { return null; }
inout(CAsmDeclaration) isCAsmDeclaration() inout { return null; }
}
/***********************************************************
@ -1700,275 +1701,25 @@ extern (C++) final class DsymbolTable : RootObject
}
}
/**********************************************
* ImportC tag symbols sit in a parallel symbol table,
* so that this C code works:
* ---
* struct S { a; };
* int S;
* struct S s;
* ---
* But there are relatively few such tag symbols, so that would be
* a waste of memory and complexity. An additional problem is we'd like the D side
* to find the tag symbols with ordinary lookup, not lookup in both
* tables, if the tag symbol is not conflicting with an ordinary symbol.
* The solution is to put the tag symbols that conflict into an associative
* array, indexed by the address of the ordinary symbol that conflicts with it.
* C has no modules, so this associative array is tagSymTab[] in ModuleDeclaration.
* A side effect of our approach is that D code cannot access a tag symbol that is
* hidden by an ordinary symbol. This is more of a theoretical problem, as nobody
* has mentioned it when importing C headers. If someone wants to do it,
* too bad so sad. Change the C code.
* This function fixes up the symbol table when faced with adding a new symbol
* `s` when there is an existing symbol `s2` with the same name.
* C also allows forward and prototype declarations of tag symbols,
* this function merges those.
* Params:
* sc = context
* s = symbol to add to symbol table
* s2 = existing declaration
* sds = symbol table
* Returns:
* if s and s2 are successfully put in symbol table then return the merged symbol,
* null if they conflict
/**
* 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();
}

View file

@ -73,6 +73,7 @@ class AliasAssign;
class OverloadSet;
class StaticAssert;
class StaticIfDeclaration;
class CAsmDeclaration;
struct AA;
#ifdef IN_GCC
typedef union tree_node Symbol;
@ -95,9 +96,16 @@ enum class ThreeState : uint8_t
yes, // value is true
};
void dsymbolSemantic(Dsymbol *dsym, Scope *sc);
void semantic2(Dsymbol *dsym, Scope *sc);
void semantic3(Dsymbol *dsym, Scope* sc);
namespace dmd
{
void dsymbolSemantic(Dsymbol *dsym, Scope *sc);
void semantic2(Dsymbol *dsym, Scope *sc);
void semantic3(Dsymbol *dsym, Scope* sc);
// in iasm.d
void asmSemantic(CAsmDeclaration *ad, Scope *sc);
// in iasmgcc.d
void gccAsmSemantic(CAsmDeclaration *ad, Scope *sc);
}
struct Visibility
{
@ -315,6 +323,7 @@ public:
virtual MixinDeclaration *isMixinDeclaration() { return NULL; }
virtual StaticAssert *isStaticAssert() { return NULL; }
virtual StaticIfDeclaration *isStaticIfDeclaration() { return NULL; }
virtual CAsmDeclaration *isCAsmDeclaration() { return NULL; }
void accept(Visitor *v) override { v->visit(this); }
};
@ -404,6 +413,15 @@ public:
ExpressionDsymbol *isExpressionDsymbol() override { return this; }
};
class CAsmDeclaration final : public Dsymbol
{
public:
Expression *code; // string expression
CAsmDeclaration *isCAsmDeclaration() override { return this; }
void accept(Visitor *v) override { v->visit(this); }
};
// Table of Dsymbol's
class DsymbolTable final : public RootObject
@ -425,7 +443,10 @@ public:
size_t length() const;
};
void addMember(Dsymbol *dsym, Scope *sc, ScopeDsymbol *sds);
Dsymbol *search(Dsymbol *d, const Loc &loc, Identifier *ident, SearchOptFlags flags = (SearchOptFlags)SearchOpt::localsOnly);
void setScope(Dsymbol *d, Scope *sc);
void importAll(Dsymbol *d, Scope *sc);
namespace dmd
{
void addMember(Dsymbol *dsym, Scope *sc, ScopeDsymbol *sds);
Dsymbol *search(Dsymbol *d, const Loc &loc, Identifier *ident, SearchOptFlags flags = (SearchOptFlags)SearchOpt::localsOnly);
void setScope(Dsymbol *d, Scope *sc);
void importAll(Dsymbol *d, Scope *sc);
}

View file

@ -85,7 +85,7 @@ enum LOG = false;
/*************************************
* Does semantic analysis on the public face of declarations.
*/
extern(C++) void dsymbolSemantic(Dsymbol dsym, Scope* sc)
void dsymbolSemantic(Dsymbol dsym, Scope* sc)
{
scope v = new DsymbolSemanticVisitor(sc);
dsym.accept(v);
@ -1440,6 +1440,15 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
assert(dsym._linkage == LINK.c);
}
override void visit(CAsmDeclaration dsym)
{
if (dsym.semanticRun >= PASS.semanticdone)
return;
import dmd.iasm : asmSemantic;
asmSemantic(dsym, sc);
dsym.semanticRun = PASS.semanticdone;
}
override void visit(BitFieldDeclaration dsym)
{
//printf("BitField::semantic('%s')\n", dsym.toChars());
@ -4059,7 +4068,7 @@ Params:
sc = scope where the dsymbol is declared
sds = ScopeDsymbol where dsym is inserted
*/
extern(C++) void addMember(Dsymbol dsym, Scope* sc, ScopeDsymbol sds)
void addMember(Dsymbol dsym, Scope* sc, ScopeDsymbol sds)
{
auto addMemberVisitor = new AddMemberVisitor(sc, sds);
dsym.accept(addMemberVisitor);
@ -5979,7 +5988,7 @@ void checkPrintfScanfSignature(FuncDeclaration funcdecl, TypeFunction f, Scope*
* Returns:
* null if not found
*/
extern(C++) Dsymbol search(Dsymbol d, const ref Loc loc, Identifier ident, SearchOptFlags flags = SearchOpt.all)
Dsymbol search(Dsymbol d, const ref Loc loc, Identifier ident, SearchOptFlags flags = SearchOpt.all)
{
scope v = new SearchVisitor(loc, ident, flags);
d.accept(v);
@ -6621,7 +6630,7 @@ private extern(C++) class SearchVisitor : Visitor
* d = dsymbol for which the scope is set
* sc = scope that is used to set the value
*/
extern(C++) void setScope(Dsymbol d, Scope* sc)
void setScope(Dsymbol d, Scope* sc)
{
scope setScopeVisitor = new SetScopeVisitor(sc);
d.accept(setScopeVisitor);
@ -6764,7 +6773,7 @@ private extern(C++) class SetScopeVisitor : Visitor
}
}
extern(C++) void importAll(Dsymbol d, Scope* sc)
void importAll(Dsymbol d, Scope* sc)
{
scope iav = new ImportAllVisitor(sc);
d.accept(iav);

View file

@ -96,7 +96,7 @@ pure nothrow @nogc @safe
* These functions substitute for dynamic_cast. dynamic_cast does not work
* on earlier versions of gcc.
*/
extern (C++) inout(Expression) isExpression(inout RootObject o)
inout(Expression) isExpression(inout RootObject o)
{
//return dynamic_cast<Expression *>(o);
if (!o || o.dyncast() != DYNCAST.expression)
@ -104,7 +104,7 @@ extern (C++) inout(Expression) isExpression(inout RootObject o)
return cast(inout(Expression))o;
}
extern (C++) inout(Dsymbol) isDsymbol(inout RootObject o)
inout(Dsymbol) isDsymbol(inout RootObject o)
{
//return dynamic_cast<Dsymbol *>(o);
if (!o || o.dyncast() != DYNCAST.dsymbol)
@ -112,7 +112,7 @@ extern (C++) inout(Dsymbol) isDsymbol(inout RootObject o)
return cast(inout(Dsymbol))o;
}
extern (C++) inout(Type) isType(inout RootObject o)
inout(Type) isType(inout RootObject o)
{
//return dynamic_cast<Type *>(o);
if (!o || o.dyncast() != DYNCAST.type)
@ -120,7 +120,7 @@ extern (C++) inout(Type) isType(inout RootObject o)
return cast(inout(Type))o;
}
extern (C++) inout(Tuple) isTuple(inout RootObject o)
inout(Tuple) isTuple(inout RootObject o)
{
//return dynamic_cast<Tuple *>(o);
if (!o || o.dyncast() != DYNCAST.tuple)
@ -128,7 +128,7 @@ extern (C++) inout(Tuple) isTuple(inout RootObject o)
return cast(inout(Tuple))o;
}
extern (C++) inout(Parameter) isParameter(inout RootObject o)
inout(Parameter) isParameter(inout RootObject o)
{
//return dynamic_cast<Parameter *>(o);
if (!o || o.dyncast() != DYNCAST.parameter)
@ -136,7 +136,7 @@ extern (C++) inout(Parameter) isParameter(inout RootObject o)
return cast(inout(Parameter))o;
}
extern (C++) inout(TemplateParameter) isTemplateParameter(inout RootObject o)
inout(TemplateParameter) isTemplateParameter(inout RootObject o)
{
if (!o || o.dyncast() != DYNCAST.templateparameter)
return null;
@ -146,7 +146,7 @@ extern (C++) inout(TemplateParameter) isTemplateParameter(inout RootObject o)
/**************************************
* Is this Object an error?
*/
extern (C++) bool isError(const RootObject o)
bool isError(const RootObject o)
{
if (const t = isType(o))
return (t.ty == Terror);
@ -6311,7 +6311,7 @@ struct TemplateStats
* listInstances = list instances of templates
* eSink = where the print is sent
*/
extern (C++) void printTemplateStats(bool listInstances, ErrorSink eSink)
void printTemplateStats(bool listInstances, ErrorSink eSink)
{
static struct TemplateDeclarationStats
{

View file

@ -54,7 +54,7 @@ import dmd.utils;
* - ignored declarations are mentioned in a comment if `global.params.doCxxHdrGeneration`
* is set to `CxxHeaderMode.verbose`
*/
extern(C++) void genCppHdrFiles(ref Modules ms)
void genCppHdrFiles(ref Modules ms)
{
initialize();

View file

@ -108,7 +108,7 @@ inout(Expression) lastComma(inout Expression e)
* exps = array of Expressions
* names = optional array of names corresponding to Expressions
*/
extern (C++) void expandTuples(Expressions* exps, Identifiers* names = null)
void expandTuples(Expressions* exps, Identifiers* names = null)
{
//printf("expandTuples()\n");
if (exps is null)

View file

@ -46,16 +46,19 @@ typedef union tree_node Symbol;
struct Symbol; // back end symbol
#endif
// in expressionsem.d
Expression *expressionSemantic(Expression *e, Scope *sc);
// in typesem.d
Expression *defaultInit(Type *mt, const Loc &loc, const bool isCfile = false);
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

View file

@ -5023,7 +5023,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
checkFunctionAttributes(exp, sc, f);
checkAccess(cd, exp.loc, sc, f);
if (!checkSymbolAccess(sc, f))
{
error(exp.loc, "%s `%s` is not accessible from module `%s`",
f.kind(), f.toPrettyChars(), sc._module.toChars);
return setError();
}
TypeFunction tf = f.type.isTypeFunction();
if (!exp.arguments)
@ -6463,7 +6468,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
checkFunctionAttributes(exp, sc, exp.f);
checkAccess(exp.loc, sc, null, exp.f);
if (!checkSymbolAccess(sc, exp.f))
{
error(exp.loc, "%s `%s` is not accessible from module `%s`",
exp.f.kind(), exp.f.toPrettyChars(), sc._module.toChars);
return setError();
}
exp.e1 = new DotVarExp(exp.e1.loc, exp.e1, exp.f, false);
exp.e1 = exp.e1.expressionSemantic(sc);
@ -6649,7 +6659,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
assert(exp.f);
tiargs = null;
if (exp.f.overnext)
if (ve.hasOverloads && exp.f.overnext)
exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.argumentList, FuncResolveFlag.overloadOnly);
else
{
@ -14193,7 +14203,7 @@ Expression binSemanticProp(BinExp e, Scope* sc)
}
// entrypoint for semantic ExpressionSemanticVisitor
extern (C++) Expression expressionSemantic(Expression e, Scope* sc)
Expression expressionSemantic(Expression e, Scope* sc)
{
scope v = new ExpressionSemanticVisitor(sc);
e.accept(v);
@ -14211,8 +14221,10 @@ private Expression dotIdSemanticPropX(DotIdExp exp, Scope* sc)
// symbol.mangleof
// return mangleof as an Expression
static Expression dotMangleof(const ref Loc loc, Scope* sc, Dsymbol ds)
static Expression dotMangleof(const ref Loc loc, Scope* sc, Dsymbol ds, bool hasOverloads)
{
Expression e;
assert(ds);
if (auto f = ds.isFuncDeclaration())
{
@ -14224,24 +14236,40 @@ private Expression dotIdSemanticPropX(DotIdExp exp, Scope* sc)
error(loc, "%s `%s` cannot retrieve its `.mangleof` while inferring attributes", f.kind, f.toPrettyChars);
return ErrorExp.get();
}
if (!hasOverloads)
e = StringExp.create(loc, mangleExact(f));
}
OutBuffer buf;
mangleToBuffer(ds, buf);
Expression e = new StringExp(loc, buf.extractSlice());
if (!e)
{
OutBuffer buf;
mangleToBuffer(ds, buf);
e = new StringExp(loc, buf.extractSlice());
}
return e.expressionSemantic(sc);
}
Dsymbol ds;
switch (exp.e1.op)
{
case EXP.scope_: return dotMangleof(exp.loc, sc, exp.e1.isScopeExp().sds);
case EXP.variable: return dotMangleof(exp.loc, sc, exp.e1.isVarExp().var);
case EXP.dotVariable: return dotMangleof(exp.loc, sc, exp.e1.isDotVarExp().var);
case EXP.overloadSet: return dotMangleof(exp.loc, sc, exp.e1.isOverExp().vars);
case EXP.scope_: return dotMangleof(exp.loc, sc, exp.e1.isScopeExp().sds, false);
case EXP.overloadSet: return dotMangleof(exp.loc, sc, exp.e1.isOverExp().vars, false);
case EXP.variable:
{
VarExp ve = exp.e1.isVarExp();
return dotMangleof(exp.loc, sc, ve.var, ve.hasOverloads);
}
case EXP.dotVariable:
{
DotVarExp dve = exp.e1.isDotVarExp();
return dotMangleof(exp.loc, sc, dve.var, dve.hasOverloads);
}
case EXP.template_:
{
TemplateExp te = exp.e1.isTemplateExp();
return dotMangleof(exp.loc, sc, ds = te.fd ? te.fd.isDsymbol() : te.td);
return dotMangleof(exp.loc, sc, ds = te.fd ? te.fd.isDsymbol() : te.td, false);
}
default:

View file

@ -1042,7 +1042,6 @@ Ldone:
* false if any errors exist in the signature.
*/
public
extern (C++)
bool functionSemantic(FuncDeclaration fd)
{
//printf("functionSemantic() %p %s\n", this, toChars());
@ -1101,7 +1100,6 @@ bool functionSemantic(FuncDeclaration fd)
* Returns false if any errors exist in the body.
*/
public
extern (C++)
bool functionSemantic3(FuncDeclaration fd)
{
if (fd.semanticRun < PASS.semantic3 && fd._scope)

View file

@ -30,19 +30,9 @@ version (NoBackend)
struct TYPE;
alias type = TYPE;
extern (C++)
extern(C++) abstract class ObjcGlue
{
// iasm
Statement asmSemantic(AsmStatement s, Scope* sc)
{
sc.func.hasReturnExp = 8;
return null;
}
extern(C++) abstract class ObjcGlue
{
static void initialize() {}
}
static void initialize() {}
}
}
else version (IN_GCC)
@ -53,11 +43,6 @@ else version (IN_GCC)
alias code = tree_node;
alias type = tree_node;
extern (C++)
{
Statement asmSemantic(AsmStatement s, Scope* sc);
}
// stubs
extern(C++) abstract class ObjcGlue
{
@ -70,6 +55,5 @@ else
public import dmd.backend.type : type;
public import dmd.backend.el : elem;
public import dmd.backend.code_x86 : code;
public import dmd.iasm : asmSemantic;
public import dmd.objc_glue : ObjcGlue;
}

View file

@ -83,7 +83,7 @@ enum TEST_EMIT_ALL = 0;
* doFuncBodies = generate function definitions rather than just declarations
* buf = buffer to write the data to
*/
extern (C++) void genhdrfile(Module m, bool doFuncBodies, ref OutBuffer buf)
void genhdrfile(Module m, bool doFuncBodies, ref OutBuffer buf)
{
buf.doindent = 1;
buf.printf("// D import file generated from '%s'", m.srcfile.toChars());
@ -103,7 +103,7 @@ extern (C++) void genhdrfile(Module m, bool doFuncBodies, ref OutBuffer buf)
* Returns:
* 0-terminated string
*/
public extern (C++) const(char)* toChars(const Statement s)
public const(char)* toChars(const Statement s)
{
HdrGenState hgs;
OutBuffer buf;
@ -112,7 +112,7 @@ public extern (C++) const(char)* toChars(const Statement s)
return buf.extractSlice().ptr;
}
public extern (C++) const(char)* toChars(const Expression e)
public const(char)* toChars(const Expression e)
{
HdrGenState hgs;
OutBuffer buf;
@ -120,7 +120,7 @@ public extern (C++) const(char)* toChars(const Expression e)
return buf.extractChars();
}
public extern (C++) const(char)* toChars(const Initializer i)
public const(char)* toChars(const Initializer i)
{
OutBuffer buf;
HdrGenState hgs;
@ -128,7 +128,7 @@ public extern (C++) const(char)* toChars(const Initializer i)
return buf.extractChars();
}
public extern (C++) const(char)* toChars(const Type t)
public const(char)* toChars(const Type t)
{
OutBuffer buf;
buf.reserve(16);
@ -154,7 +154,7 @@ public const(char)[] toString(const Initializer i)
* vcg_ast = write out codegen ast
* m = module to visit all members of.
*/
extern (C++) void moduleToBuffer(ref OutBuffer buf, bool vcg_ast, Module m)
void moduleToBuffer(ref OutBuffer buf, bool vcg_ast, Module m)
{
HdrGenState hgs;
hgs.fullDump = true;
@ -3418,7 +3418,7 @@ void arrayObjectsToBuffer(ref OutBuffer buf, Objects* objects)
* pl = parameter list to print
* Returns: Null-terminated string representing parameters.
*/
extern (C++) const(char)* parametersTypeToChars(ParameterList pl)
const(char)* parametersTypeToChars(ParameterList pl)
{
OutBuffer buf;
HdrGenState hgs;

View file

@ -18,12 +18,15 @@ class Initializer;
class Module;
class Statement;
void genhdrfile(Module *m, bool doFuncBodies, OutBuffer &buf);
void genCppHdrFiles(Modules &ms);
void moduleToBuffer(OutBuffer& buf, bool vcg_ast, Module *m);
const char *parametersTypeToChars(ParameterList pl);
namespace dmd
{
void genhdrfile(Module *m, bool doFuncBodies, OutBuffer &buf);
void genCppHdrFiles(Modules &ms);
void moduleToBuffer(OutBuffer& buf, bool vcg_ast, Module *m);
const char *parametersTypeToChars(ParameterList pl);
const char* toChars(const Expression* const e);
const char* toChars(const Initializer* const i);
const char* toChars(const Statement* const s);
const char* toChars(const Type* const t);
const char* toChars(const Expression* const e);
const char* toChars(const Initializer* const i);
const char* toChars(const Statement* const s);
const char* toChars(const Type* const t);
}

View file

@ -16,6 +16,7 @@ module dmd.iasm;
import core.stdc.stdio;
import dmd.dscope;
import dmd.dsymbol;
import dmd.expression;
import dmd.func;
import dmd.mtype;
@ -23,7 +24,10 @@ import dmd.tokens;
import dmd.statement;
import dmd.statementsem;
version (IN_GCC)
version (NoBackend)
{
}
else version (IN_GCC)
{
import dmd.iasmgcc;
}
@ -35,7 +39,7 @@ else
/************************ AsmStatement ***************************************/
extern(C++) Statement asmSemantic(AsmStatement s, Scope *sc)
Statement asmSemantic(AsmStatement s, Scope *sc)
{
//printf("AsmStatement.semantic()\n");
@ -48,7 +52,11 @@ extern(C++) Statement asmSemantic(AsmStatement s, Scope *sc)
// Assume assembler code takes care of setting the return value
sc.func.hasReturnExp |= 8;
version (MARS)
version (NoBackend)
{
return null;
}
else version (MARS)
{
/* If it starts with a string literal, it's gcc inline asm
*/
@ -78,3 +86,21 @@ extern(C++) Statement asmSemantic(AsmStatement s, Scope *sc)
return new ErrorStatement();
}
}
/************************ CAsmDeclaration ************************************/
void asmSemantic(CAsmDeclaration ad, Scope *sc)
{
version (NoBackend)
{
}
else version (IN_GCC)
{
return gccAsmSemantic(ad, sc);
}
else
{
import dmd.errors : error;
error(ad.code.loc, "Gnu Asm not supported - compile this file with gcc or clang");
}
}

View file

@ -16,6 +16,7 @@ import core.stdc.string;
import dmd.arraytypes;
import dmd.astcodegen;
import dmd.dscope;
import dmd.dsymbol;
import dmd.errors;
import dmd.errorsink;
import dmd.expression;
@ -299,7 +300,7 @@ Ldone:
* Returns:
* the completed gcc asm statement, or null if errors occurred
*/
extern (C++) public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
{
//printf("GccAsmStatement.semantic()\n");
const bool doUnittests = global.params.parsingUnittestsRequired();
@ -382,6 +383,26 @@ extern (C++) public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
return s;
}
/***********************************
* Run semantic analysis on an CAsmDeclaration.
* Params:
* ad = asm declaration
* sc = the scope where the asm declaration is located
*/
public void gccAsmSemantic(CAsmDeclaration ad, Scope *sc)
{
import dmd.typesem : pointerTo;
ad.code = semanticString(sc, ad.code, "asm definition");
ad.code.type = ad.code.type.nextOf().pointerTo();
// Asm definition always needs emitting into the root module.
import dmd.dmodule : Module;
if (sc._module && sc._module.isRoot())
return;
if (Module m = Module.rootModule)
m.members.push(ad);
}
unittest
{
import dmd.mtype : TypeBasic;

View file

@ -366,3 +366,276 @@ bool cTypeEquivalence(Type t1, Type t2)
return false;
}
/**********************************************
* ImportC tag symbols sit in a parallel symbol table,
* so that this C code works:
* ---
* struct S { a; };
* int S;
* struct S s;
* ---
* But there are relatively few such tag symbols, so that would be
* a waste of memory and complexity. An additional problem is we'd like the D side
* to find the tag symbols with ordinary lookup, not lookup in both
* tables, if the tag symbol is not conflicting with an ordinary symbol.
* The solution is to put the tag symbols that conflict into an associative
* array, indexed by the address of the ordinary symbol that conflicts with it.
* C has no modules, so this associative array is tagSymTab[] in ModuleDeclaration.
* A side effect of our approach is that D code cannot access a tag symbol that is
* hidden by an ordinary symbol. This is more of a theoretical problem, as nobody
* has mentioned it when importing C headers. If someone wants to do it,
* too bad so sad. Change the C code.
* This function fixes up the symbol table when faced with adding a new symbol
* `s` when there is an existing symbol `s2` with the same name.
* C also allows forward and prototype declarations of tag symbols,
* this function merges those.
* Params:
* sc = context
* s = symbol to add to symbol table
* s2 = existing declaration
* sds = symbol table
* Returns:
* if s and s2 are successfully put in symbol table then return the merged symbol,
* null if they conflict
*/
Dsymbol handleTagSymbols(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
{
enum log = false;
if (log) printf("handleTagSymbols('%s') add %p existing %p\n", s.toChars(), s, s2);
if (log) printf(" add %s %s, existing %s %s\n", s.kind(), s.toChars(), s2.kind(), s2.toChars());
auto sd = s.isScopeDsymbol(); // new declaration
auto sd2 = s2.isScopeDsymbol(); // existing declaration
static if (log) void print(EnumDeclaration sd)
{
printf("members: %p\n", sd.members);
printf("symtab: %p\n", sd.symtab);
printf("endlinnum: %d\n", sd.endlinnum);
printf("type: %s\n", sd.type.toChars());
printf("memtype: %s\n", sd.memtype.toChars());
}
if (!sd2)
{
/* Look in tag table
*/
if (log) printf(" look in tag table\n");
if (auto p = cast(void*)s2 in sc._module.tagSymTab)
{
Dsymbol s2tag = *p;
sd2 = s2tag.isScopeDsymbol();
assert(sd2); // only tags allowed in tag symbol table
}
}
if (sd && sd2) // `s` is a tag, `sd2` is the same tag
{
if (log) printf(" tag is already defined\n");
if (sd.kind() != sd2.kind()) // being enum/struct/union must match
return null; // conflict
/* Not a redeclaration if one is a forward declaration.
* Move members to the first declared type, which is sd2.
*/
if (sd2.members)
{
if (!sd.members)
return sd2; // ignore the sd redeclaration
}
else if (sd.members)
{
sd2.members = sd.members; // transfer definition to sd2
sd.members = null;
if (auto ed2 = sd2.isEnumDeclaration())
{
auto ed = sd.isEnumDeclaration();
if (ed.memtype != ed2.memtype)
return null; // conflict
// transfer ed's members to sd2
ed2.members.foreachDsymbol( (s)
{
if (auto em = s.isEnumMember())
em.ed = ed2;
});
ed2.type = ed.type;
ed2.memtype = ed.memtype;
ed2.added = false;
}
return sd2;
}
else
return sd2; // ignore redeclaration
}
else if (sd) // `s` is a tag, `s2` is not
{
if (log) printf(" s is tag, s2 is not\n");
/* add `s` as tag indexed by s2
*/
sc._module.tagSymTab[cast(void*)s2] = s;
return s;
}
else if (s2 is sd2) // `s2` is a tag, `s` is not
{
if (log) printf(" s2 is tag, s is not\n");
/* replace `s2` in symbol table with `s`,
* then add `s2` as tag indexed by `s`
*/
sds.symtab.update(s);
sc._module.tagSymTab[cast(void*)s] = s2;
return s;
}
// neither s2 nor s is a tag
if (log) printf(" collision\n");
return null;
}
/**********************************************
* ImportC allows redeclarations of C variables, functions and typedefs.
* extern int x;
* int x = 3;
* and:
* extern void f();
* void f() { }
* Attempt to merge them.
* Params:
* sc = context
* s = symbol to add to symbol table
* s2 = existing declaration
* sds = symbol table
* Returns:
* if s and s2 are successfully put in symbol table then return the merged symbol,
* null if they conflict
*/
Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
{
enum log = false;
if (log) printf("handleSymbolRedeclarations('%s')\n", s.toChars());
if (log) printf(" add %s %s, existing %s %s\n", s.kind(), s.toChars(), s2.kind(), s2.toChars());
static Dsymbol collision()
{
if (log) printf(" collision\n");
return null;
}
/*
Handle merging declarations with asm("foo") and their definitions
*/
static void mangleWrangle(Declaration oldDecl, Declaration newDecl)
{
if (oldDecl && newDecl)
{
newDecl.mangleOverride = oldDecl.mangleOverride ? oldDecl.mangleOverride : null;
}
}
auto vd = s.isVarDeclaration(); // new declaration
auto vd2 = s2.isVarDeclaration(); // existing declaration
if (vd && vd.isCmacro())
return vd2;
assert(!(vd2 && vd2.isCmacro()));
if (vd && vd2)
{
/* if one is `static` and the other isn't, the result is undefined
* behavior, C11 6.2.2.7
*/
if ((vd.storage_class ^ vd2.storage_class) & STC.static_)
return collision();
const i1 = vd._init && ! vd._init.isVoidInitializer();
const i2 = vd2._init && !vd2._init.isVoidInitializer();
if (i1 && i2)
return collision(); // can't both have initializers
mangleWrangle(vd2, vd);
if (i1) // vd is the definition
{
vd2.storage_class |= STC.extern_; // so toObjFile() won't emit it
sds.symtab.update(vd); // replace vd2 with the definition
return vd;
}
/* BUG: the types should match, which needs semantic() to be run on it
* extern int x;
* int x; // match
* typedef int INT;
* INT x; // match
* long x; // collision
* We incorrectly ignore these collisions
*/
return vd2;
}
auto fd = s.isFuncDeclaration(); // new declaration
auto fd2 = s2.isFuncDeclaration(); // existing declaration
if (fd && fd2)
{
/* if one is `static` and the other isn't, the result is undefined
* behavior, C11 6.2.2.7
* However, match what gcc allows:
* static int sun1(); int sun1() { return 0; }
* and:
* static int sun2() { return 0; } int sun2();
* Both produce a static function.
*
* Both of these should fail:
* int sun3(); static int sun3() { return 0; }
* and:
* int sun4() { return 0; } static int sun4();
*/
// if adding `static`
if ( fd.storage_class & STC.static_ &&
!(fd2.storage_class & STC.static_))
{
return collision();
}
if (fd.fbody && fd2.fbody)
return collision(); // can't both have bodies
mangleWrangle(fd2, fd);
if (fd.fbody) // fd is the definition
{
if (log) printf(" replace existing with new\n");
sds.symtab.update(fd); // replace fd2 in symbol table with fd
fd.overnext = fd2;
/* If fd2 is covering a tag symbol, then fd has to cover the same one
*/
auto ps = cast(void*)fd2 in sc._module.tagSymTab;
if (ps)
sc._module.tagSymTab[cast(void*)fd] = *ps;
return fd;
}
/* Just like with VarDeclaration, the types should match, which needs semantic() to be run on it.
* FuncDeclaration::semantic() detects this, but it relies on .overnext being set.
*/
fd2.overloadInsert(fd);
return fd2;
}
auto td = s.isAliasDeclaration(); // new declaration
auto td2 = s2.isAliasDeclaration(); // existing declaration
if (td && td2)
{
/* BUG: just like with variables and functions, the types should match, which needs semantic() to be run on it.
* FuncDeclaration::semantic2() can detect this, but it relies overnext being set.
*/
return td2;
}
return collision();
}

View file

@ -124,5 +124,8 @@ public:
void accept(Visitor *v) override { v->visit(this); }
};
Expression *initializerToExpression(Initializer *init, Type *t = NULL, const bool isCfile = false);
Initializer *initializerSemantic(Initializer *init, Scope *sc, Type *&tx, NeedInterpret needInterpret);
namespace dmd
{
Expression *initializerToExpression(Initializer *init, Type *t = NULL, const bool isCfile = false);
Initializer *initializerSemantic(Initializer *init, Scope *sc, Type *&tx, NeedInterpret needInterpret);
}

View file

@ -103,7 +103,7 @@ Expression toAssocArrayLiteral(ArrayInitializer ai)
* `Initializer` with completed semantic analysis, `ErrorInitializer` if errors
* were encountered
*/
extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedInterpret needInterpret)
Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedInterpret needInterpret)
{
//printf("initializerSemantic() tx: %p %s\n", tx, tx.toChars());
Type t = tx;
@ -1224,7 +1224,7 @@ Initializer inferType(Initializer init, Scope* sc)
* Returns:
* `Expression` created, `null` if cannot, `ErrorExp` for other errors
*/
extern (C++) Expression initializerToExpression(Initializer init, Type itype = null, const bool isCfile = false)
Expression initializerToExpression(Initializer init, Type itype = null, const bool isCfile = false)
{
//printf("initializerToExpression() isCfile: %d\n", isCfile);

View file

@ -978,7 +978,7 @@ public:
* modules = array of Modules
* buf = write json output to buf
*/
extern (C++) void json_generate(ref Modules modules, ref OutBuffer buf)
void json_generate(ref Modules modules, ref OutBuffer buf)
{
scope ToJsonVisitor json = new ToJsonVisitor(&buf);
// write trailing newline
@ -1047,7 +1047,7 @@ Params:
Returns: JsonFieldFlags.none on error, otherwise the JsonFieldFlags value
corresponding to the given fieldName.
*/
extern (C++) JsonFieldFlags tryParseJsonField(const(char)* fieldName)
JsonFieldFlags tryParseJsonField(const(char)* fieldName)
{
auto fieldNameString = fieldName.toDString();
foreach (idx, enumName; __traits(allMembers, JsonFieldFlags))

View file

@ -15,5 +15,8 @@
struct OutBuffer;
void json_generate(Modules &, OutBuffer &);
JsonFieldFlags tryParseJsonField(const char *fieldName);
namespace dmd
{
void json_generate(Modules &, OutBuffer &);
JsonFieldFlags tryParseJsonField(const char *fieldName);
}

View file

@ -17,18 +17,21 @@ class TemplateInstance;
class Type;
struct OutBuffer;
// In cppmangle.d
const char *toCppMangleItanium(Dsymbol *s);
const char *cppTypeInfoMangleItanium(Dsymbol *s);
const char *cppThunkMangleItanium(FuncDeclaration *fd, int offset);
namespace dmd
{
// In cppmangle.d
const char *toCppMangleItanium(Dsymbol *s);
const char *cppTypeInfoMangleItanium(Dsymbol *s);
const char *cppThunkMangleItanium(FuncDeclaration *fd, int offset);
// In cppmanglewin.d
const char *toCppMangleMSVC(Dsymbol *s);
const char *cppTypeInfoMangleMSVC(Dsymbol *s);
// In cppmanglewin.d
const char *toCppMangleMSVC(Dsymbol *s);
const char *cppTypeInfoMangleMSVC(Dsymbol *s);
// In dmangle.d
const char *mangleExact(FuncDeclaration *fd);
void mangleToBuffer(Type *s, OutBuffer& buf);
void mangleToBuffer(Expression *s, OutBuffer& buf);
void mangleToBuffer(Dsymbol *s, OutBuffer& buf);
void mangleToBuffer(TemplateInstance *s, OutBuffer& buf);
// In dmangle.d
const char *mangleExact(FuncDeclaration *fd);
void mangleToBuffer(Type *s, OutBuffer& buf);
void mangleToBuffer(Expression *s, OutBuffer& buf);
void mangleToBuffer(Dsymbol *s, OutBuffer& buf);
void mangleToBuffer(TemplateInstance *s, OutBuffer& buf);
}

View file

@ -167,5 +167,8 @@ struct ModuleDeclaration
const char *toChars() const;
};
extern void getLocalClasses(Module* mod, Array<ClassDeclaration* >& aclasses);
FuncDeclaration *findGetMembers(ScopeDsymbol *dsym);
namespace dmd
{
void getLocalClasses(Module* mod, Array<ClassDeclaration* >& aclasses);
FuncDeclaration *findGetMembers(ScopeDsymbol *dsym);
}

View file

@ -1186,58 +1186,6 @@ extern (C++) abstract class Type : ASTNode
return t;
}
/************************************
* Add storage class modifiers to type.
*/
Type addStorageClass(StorageClass stc)
{
/* Just translate to MOD bits and let addMod() do the work
*/
MOD mod = 0;
if (stc & STC.immutable_)
mod = MODFlags.immutable_;
else
{
if (stc & (STC.const_ | STC.in_))
mod |= MODFlags.const_;
if (stc & STC.wild)
mod |= MODFlags.wild;
if (stc & STC.shared_)
mod |= MODFlags.shared_;
}
return this.addMod(mod);
}
final Type pointerTo()
{
if (ty == Terror)
return this;
if (!pto)
{
Type t = new TypePointer(this);
if (ty == Tfunction)
{
t.deco = t.merge().deco;
pto = t;
}
else
pto = t.merge();
}
return pto;
}
final Type referenceTo()
{
if (ty == Terror)
return this;
if (!rto)
{
Type t = new TypeReference(this);
rto = t.merge();
}
return rto;
}
final Type arrayOf()
{
if (ty == Terror)
@ -3449,56 +3397,6 @@ extern (C++) final class TypeFunction : TypeNext
return linkage == LINK.d && parameterList.varargs == VarArg.variadic;
}
override Type addStorageClass(StorageClass stc)
{
//printf("addStorageClass(%llx) %d\n", stc, (stc & STC.scope_) != 0);
TypeFunction t = Type.addStorageClass(stc).toTypeFunction();
if ((stc & STC.pure_ && !t.purity) ||
(stc & STC.nothrow_ && !t.isnothrow) ||
(stc & STC.nogc && !t.isnogc) ||
(stc & STC.scope_ && !t.isScopeQual) ||
(stc & STC.safe && t.trust < TRUST.trusted))
{
// Klunky to change these
auto tf = new TypeFunction(t.parameterList, t.next, t.linkage, 0);
tf.mod = t.mod;
tf.fargs = fargs;
tf.purity = t.purity;
tf.isnothrow = t.isnothrow;
tf.isnogc = t.isnogc;
tf.isproperty = t.isproperty;
tf.isref = t.isref;
tf.isreturn = t.isreturn;
tf.isreturnscope = t.isreturnscope;
tf.isScopeQual = t.isScopeQual;
tf.isreturninferred = t.isreturninferred;
tf.isscopeinferred = t.isscopeinferred;
tf.trust = t.trust;
tf.isInOutParam = t.isInOutParam;
tf.isInOutQual = t.isInOutQual;
tf.isctor = t.isctor;
if (stc & STC.pure_)
tf.purity = PURE.fwdref;
if (stc & STC.nothrow_)
tf.isnothrow = true;
if (stc & STC.nogc)
tf.isnogc = true;
if (stc & STC.safe)
tf.trust = TRUST.safe;
if (stc & STC.scope_)
{
tf.isScopeQual = true;
if (stc & STC.scopeinferred)
tf.isscopeinferred = true;
}
tf.deco = tf.merge().deco;
t = tf;
}
return t;
}
override Type substWildTo(uint)
{
if (!iswild && !(mod & MODFlags.wild))
@ -3800,12 +3698,6 @@ extern (C++) final class TypeDelegate : TypeNext
return result;
}
override Type addStorageClass(StorageClass stc)
{
TypeDelegate t = cast(TypeDelegate)Type.addStorageClass(stc);
return t;
}
override uinteger_t size(const ref Loc loc)
{
return target.ptrsize * 2;
@ -5673,7 +5565,7 @@ void attributesApply(const TypeFunction tf, void delegate(string) dg, TRUSTforma
* If the type is a class or struct, returns the symbol for it,
* else null.
*/
extern (C++) AggregateDeclaration isAggregate(Type t)
AggregateDeclaration isAggregate(Type t)
{
t = t.toBasetype();
if (t.ty == Tclass)

View file

@ -39,8 +39,11 @@ typedef union tree_node type;
typedef struct TYPE type;
#endif
Type *typeSemantic(Type *t, const Loc &loc, Scope *sc);
Type *merge(Type *type);
namespace dmd
{
Type *typeSemantic(Type *t, const Loc &loc, Scope *sc);
Type *merge(Type *type);
}
enum class TY : uint8_t
{
@ -251,9 +254,6 @@ public:
bool isSharedWild() const { return (mod & (MODshared | MODwild)) == (MODshared | MODwild); }
bool isNaked() const { return mod == 0; }
Type *nullAttributes() const;
virtual Type *addStorageClass(StorageClass stc);
Type *pointerTo();
Type *referenceTo();
Type *arrayOf();
Type *sarrayOf(dinteger_t dim);
bool hasDeprecatedAliasThis();
@ -579,7 +579,6 @@ public:
TypeFunction *syntaxCopy() override;
bool hasLazyParameters();
bool isDstyleVariadic() const;
Type *addStorageClass(StorageClass stc) override;
Type *substWildTo(unsigned mod) override;
MATCH constConv(Type *to) override;
@ -623,7 +622,6 @@ public:
static TypeDelegate *create(TypeFunction *t);
const char *kind() override;
TypeDelegate *syntaxCopy() override;
Type *addStorageClass(StorageClass stc) override;
uinteger_t size(const Loc &loc) override;
unsigned alignsize() override;
MATCH implicitConvTo(Type *to) override;
@ -880,26 +878,31 @@ public:
/**************************************************************/
// If the type is a class or struct, returns the symbol for it, else null.
AggregateDeclaration *isAggregate(Type *t);
bool hasPointers(Type *t);
// return the symbol to which type t resolves
Dsymbol *toDsymbol(Type *t, Scope *sc);
bool equivalent(Type *src, Type *t);
Covariant covariant(Type *, Type *, StorageClass * = NULL, bool = false);
bool isBaseOf(Type *tthis, Type *t, int *poffset);
Type *trySemantic(Type *type, const Loc &loc, Scope *sc);
Type *merge2(Type *type);
Type *constOf(Type *type);
Type *immutableOf(Type *type);
Type *mutableOf(Type *type);
Type *sharedOf(Type *type);
Type *sharedConstOf(Type *type);
Type *unSharedOf(Type *type);
Type *wildOf(Type *type);
Type *wildConstOf(Type *type);
Type *sharedWildOf(Type *type);
Type *sharedWildConstOf(Type *type);
Type *castMod(Type *type, MOD mod);
Type *addMod(Type *type, MOD mod);
namespace dmd
{
// If the type is a class or struct, returns the symbol for it, else null.
AggregateDeclaration *isAggregate(Type *t);
bool hasPointers(Type *t);
// return the symbol to which type t resolves
Dsymbol *toDsymbol(Type *t, Scope *sc);
bool equivalent(Type *src, Type *t);
Covariant covariant(Type *, Type *, StorageClass * = NULL, bool = false);
bool isBaseOf(Type *tthis, Type *t, int *poffset);
Type *trySemantic(Type *type, const Loc &loc, Scope *sc);
Type *pointerTo(Type *type);
Type *referenceTo(Type *type);
Type *merge2(Type *type);
Type *constOf(Type *type);
Type *immutableOf(Type *type);
Type *mutableOf(Type *type);
Type *sharedOf(Type *type);
Type *sharedConstOf(Type *type);
Type *unSharedOf(Type *type);
Type *wildOf(Type *type);
Type *wildConstOf(Type *type);
Type *sharedWildOf(Type *type);
Type *sharedWildConstOf(Type *type);
Type *castMod(Type *type, MOD mod);
Type *addMod(Type *type, MOD mod);
Type *addStorageClass(Type *type, StorageClass stc);
}

View file

@ -273,7 +273,7 @@ package void setLengthVarIfKnown(VarDeclaration lengthVar, Type type)
* Returns:
* Constant folded version of `e`
*/
extern (C++) Expression optimize(Expression e, int result, bool keepLvalue = false)
Expression optimize(Expression e, int result, bool keepLvalue = false)
{
//printf("optimize() e: %s result: %d keepLvalue %d\n", e.toChars(), result, keepLvalue);
Expression ret = e;

View file

@ -7180,6 +7180,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
}
if (!isDeclarator(&t, &haveId, &haveTpl, endtok, needId != NeedDeclaratorId.mustIfDstyle))
goto Lisnot;
// needed for `__traits(compiles, arr[0] = 0)`
if (!haveId && t.value == TOK.assign)
goto Lisnot;
if ((needId == NeedDeclaratorId.no && !haveId) ||
(needId == NeedDeclaratorId.opt) ||
(needId == NeedDeclaratorId.must && haveId) ||

View file

@ -36,6 +36,7 @@ public:
void visit(AST.DebugSymbol s) { visit(cast(AST.Dsymbol)s); }
void visit(AST.VersionSymbol s) { visit(cast(AST.Dsymbol)s); }
void visit(AST.AliasAssign s) { visit(cast(AST.Dsymbol)s); }
void visit(AST.CAsmDeclaration s) { visit(cast(AST.Dsymbol)s); }
// ScopeDsymbols
void visit(AST.Package s) { visit(cast(AST.ScopeDsymbol)s); }

View file

@ -73,7 +73,7 @@ enum LOG = false;
/*************************************
* Does semantic analysis on initializers and members of aggregates.
*/
extern(C++) void semantic2(Dsymbol dsym, Scope* sc)
void semantic2(Dsymbol dsym, Scope* sc)
{
scope v = new Semantic2Visitor(sc);
dsym.accept(v);
@ -876,7 +876,7 @@ private extern(C++) final class StaticAAVisitor : SemanticTimeTransitiveVisitor
hookFunc = new DotIdExp(aaExp.loc, hookFunc, Id.object);
hookFunc = new DotIdExp(aaExp.loc, hookFunc, Id._aaAsStruct);
auto arguments = new Expressions();
arguments.push(aaExp.syntaxCopy());
arguments.push(aaExp);
Expression loweredExp = new CallExp(aaExp.loc, hookFunc, arguments);
sc = sc.startCTFE();

View file

@ -79,7 +79,7 @@ enum LOG = false;
/*************************************
* Does semantic analysis on function bodies.
*/
extern(C++) void semantic3(Dsymbol dsym, Scope* sc)
void semantic3(Dsymbol dsym, Scope* sc)
{
scope v = new Semantic3Visitor(sc);
dsym.accept(v);
@ -1636,7 +1636,7 @@ private struct FuncDeclSem3
}
}
extern (C++) void semanticTypeInfoMembers(StructDeclaration sd)
void semanticTypeInfoMembers(StructDeclaration sd)
{
if (sd.xeq &&
sd.xeq._scope &&

View file

@ -701,12 +701,15 @@ public:
void accept(Visitor *v) override { v->visit(this); }
};
// in statementsem.d
Statement* statementSemantic(Statement *s, Scope *sc);
// in iasm.d
Statement* asmSemantic(AsmStatement *s, Scope *sc);
// in iasmgcc.d
Statement *gccAsmSemantic(GccAsmStatement *s, Scope *sc);
namespace dmd
{
// in statementsem.d
Statement* statementSemantic(Statement *s, Scope *sc);
// in iasm.d
Statement* asmSemantic(AsmStatement *s, Scope *sc);
// in iasmgcc.d
Statement *gccAsmSemantic(GccAsmStatement *s, Scope *sc);
}
class AsmStatement : public Statement
{

View file

@ -41,8 +41,8 @@ import dmd.expressionsem;
import dmd.func;
import dmd.funcsem;
import dmd.globals;
import dmd.gluelayer;
import dmd.hdrgen;
import dmd.iasm;
import dmd.id;
import dmd.identifier;
import dmd.importc;
@ -135,7 +135,7 @@ private Expression checkAssignmentAsCondition(Expression e, Scope* sc)
}
// Performs semantic analysis in Statement AST nodes
extern(C++) Statement statementSemantic(Statement s, Scope* sc)
Statement statementSemantic(Statement s, Scope* sc)
{
import dmd.compiler;

View file

@ -110,7 +110,7 @@ extern (C++) struct Target
/// Architecture name
const(char)[] architectureName;
CPU cpu = CPU.baseline; // CPU instruction set to target
CPU cpu; // CPU instruction set to target
bool isX86_64; // generate 64 bit code for x86_64; true by default for 64 bit dmd
bool isLP64; // pointers are 64 bits
@ -119,7 +119,7 @@ extern (C++) struct Target
const(char)[] lib_ext; /// extension for static library files
const(char)[] dll_ext; /// extension for dynamic library files
bool run_noext; /// allow -run sources without extensions
bool omfobj = false; // for Win32: write OMF object files instead of MsCoff
bool omfobj; // for Win32: write OMF object files instead of MsCoff
/**
* Values representing all properties for floating point types
*/

View file

@ -317,14 +317,17 @@ public:
void accept(Visitor *v) override { v->visit(this); }
};
// in templateparamsem.d
bool tpsemantic(TemplateParameter *tp, Scope *sc, TemplateParameters *parameters);
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);
}

View file

@ -35,7 +35,7 @@ import dmd.visitor;
* Returns:
* `true` if no errors
*/
extern(C++) bool tpsemantic(TemplateParameter tp, Scope* sc, TemplateParameters* parameters)
bool tpsemantic(TemplateParameter tp, Scope* sc, TemplateParameters* parameters)
{
scope v = new TemplateParameterSemanticVisitor(sc, parameters);
tp.accept(v);

View file

@ -1222,7 +1222,7 @@ private extern(D) MATCH matchTypeSafeVarArgs(TypeFunction tf, Parameter p,
* Return !=0 if type has pointers that need to
* be scanned by the GC during a collection cycle.
*/
extern(C++) bool hasPointers(Type t)
bool hasPointers(Type t)
{
bool visitType(Type _) { return false; }
bool visitDArray(TypeDArray _) { return true; }
@ -1292,7 +1292,7 @@ extern(C++) bool hasPointers(Type t)
* `Type` with completed semantic analysis, `Terror` if errors
* were encountered
*/
extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
{
static Type error()
{
@ -2821,7 +2821,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
}
}
extern(C++) Type trySemantic(Type type, const ref Loc loc, Scope* sc)
Type trySemantic(Type type, const ref Loc loc, Scope* sc)
{
//printf("+trySemantic(%s) %d\n", toChars(), global.errors);
@ -2855,7 +2855,7 @@ extern(C++) Type trySemantic(Type type, const ref Loc loc, Scope* sc)
* Returns:
* the type that was merged
*/
extern (C++) Type merge(Type type)
Type merge(Type type)
{
switch (type.ty)
{
@ -2925,7 +2925,7 @@ extern (C++) Type merge(Type type)
* This version does a merge even if the deco is already computed.
* Necessary for types that have a deco, but are not merged.
*/
extern(C++) Type merge2(Type type)
Type merge2(Type type)
{
//printf("merge2(%s)\n", toChars());
Type t = type;
@ -5365,7 +5365,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag
* Returns:
* The initialization expression for the type.
*/
extern (C++) Expression defaultInit(Type mt, const ref Loc loc, const bool isCfile = false)
Expression defaultInit(Type mt, const ref Loc loc, const bool isCfile = false)
{
Expression visitBasic(TypeBasic mt)
{
@ -5545,7 +5545,7 @@ Returns:
if the type does resolve to any symbol (for example,
in the case of basic types).
*/
extern(C++) Dsymbol toDsymbol(Type type, Scope* sc)
Dsymbol toDsymbol(Type type, Scope* sc)
{
Dsymbol visitType(Type _) { return null; }
Dsymbol visitStruct(TypeStruct type) { return type.sym; }
@ -5644,6 +5644,94 @@ extern(C++) Dsymbol toDsymbol(Type type, Scope* sc)
}
}
/************************************
* Add storage class modifiers to type.
*/
Type addStorageClass(Type type, StorageClass stc)
{
Type visitType(Type t)
{
/* Just translate to MOD bits and let addMod() do the work
*/
MOD mod = 0;
if (stc & STC.immutable_)
mod = MODFlags.immutable_;
else
{
if (stc & (STC.const_ | STC.in_))
mod |= MODFlags.const_;
if (stc & STC.wild)
mod |= MODFlags.wild;
if (stc & STC.shared_)
mod |= MODFlags.shared_;
}
return t.addMod(mod);
}
Type visitFunction(TypeFunction tf_src)
{
//printf("addStorageClass(%llx) %d\n", stc, (stc & STC.scope_) != 0);
TypeFunction t = visitType(tf_src).toTypeFunction();
if ((stc & STC.pure_ && !t.purity) ||
(stc & STC.nothrow_ && !t.isnothrow) ||
(stc & STC.nogc && !t.isnogc) ||
(stc & STC.scope_ && !t.isScopeQual) ||
(stc & STC.safe && t.trust < TRUST.trusted))
{
// Klunky to change these
auto tf = new TypeFunction(t.parameterList, t.next, t.linkage, 0);
tf.mod = t.mod;
tf.fargs = tf_src.fargs;
tf.purity = t.purity;
tf.isnothrow = t.isnothrow;
tf.isnogc = t.isnogc;
tf.isproperty = t.isproperty;
tf.isref = t.isref;
tf.isreturn = t.isreturn;
tf.isreturnscope = t.isreturnscope;
tf.isScopeQual = t.isScopeQual;
tf.isreturninferred = t.isreturninferred;
tf.isscopeinferred = t.isscopeinferred;
tf.trust = t.trust;
tf.isInOutParam = t.isInOutParam;
tf.isInOutQual = t.isInOutQual;
tf.isctor = t.isctor;
if (stc & STC.pure_)
tf.purity = PURE.fwdref;
if (stc & STC.nothrow_)
tf.isnothrow = true;
if (stc & STC.nogc)
tf.isnogc = true;
if (stc & STC.safe)
tf.trust = TRUST.safe;
if (stc & STC.scope_)
{
tf.isScopeQual = true;
if (stc & STC.scopeinferred)
tf.isscopeinferred = true;
}
tf.deco = tf.merge().deco;
t = tf;
}
return t;
}
Type visitDelegate(TypeDelegate tdg)
{
TypeDelegate t = visitType(tdg).isTypeDelegate();
return t;
}
switch(type.ty)
{
default: return visitType(type);
case Tfunction: return visitFunction(type.isTypeFunction());
case Tdelegate: return visitDelegate(type.isTypeDelegate());
}
}
/**********************************************
* Extract complex type from core.stdc.config
* Params:
@ -5722,7 +5810,7 @@ Type getComplexLibraryType(const ref Loc loc, Scope* sc, TY ty)
* Returns:
* An enum value of either `Covariant.yes` or a reason it's not covariant.
*/
extern(C++) Covariant covariant(Type src, Type t, StorageClass* pstc = null, bool cppCovariant = false)
Covariant covariant(Type src, Type t, StorageClass* pstc = null, bool cppCovariant = false)
{
version (none)
{
@ -6085,7 +6173,7 @@ StorageClass parameterStorageClass(TypeFunction tf, Type tthis, Parameter p, Var
return stc | STC.scope_;
}
extern(C++) bool isBaseOf(Type tthis, Type t, int* poffset)
bool isBaseOf(Type tthis, Type t, int* poffset)
{
auto tc = tthis.isTypeClass();
if (!tc)
@ -6106,15 +6194,45 @@ extern(C++) bool isBaseOf(Type tthis, Type t, int* poffset)
return false;
}
extern(C++) bool equivalent(Type src, Type t)
bool equivalent(Type src, Type t)
{
return immutableOf(src).equals(t.immutableOf());
}
Type pointerTo(Type type)
{
if (type.ty == Terror)
return type;
if (!type.pto)
{
Type t = new TypePointer(type);
if (type.ty == Tfunction)
{
t.deco = t.merge().deco;
type.pto = t;
}
else
type.pto = t.merge();
}
return type.pto;
}
Type referenceTo(Type type)
{
if (type.ty == Terror)
return type;
if (!type.rto)
{
Type t = new TypeReference(type);
type.rto = t.merge();
}
return type.rto;
}
/********************************
* Convert to 'const'.
*/
extern(C++) Type constOf(Type type)
Type constOf(Type type)
{
//printf("Type::constOf() %p %s\n", type, type.toChars());
if (type.mod == MODFlags.const_)
@ -6134,7 +6252,7 @@ extern(C++) Type constOf(Type type)
/********************************
* Convert to 'immutable'.
*/
extern(C++) Type immutableOf(Type type)
Type immutableOf(Type type)
{
//printf("Type::immutableOf() %p %s\n", this, toChars());
if (type.isImmutable())
@ -6154,7 +6272,7 @@ extern(C++) Type immutableOf(Type type)
/********************************
* Make type mutable.
*/
extern(C++) Type mutableOf(Type type)
Type mutableOf(Type type)
{
//printf("Type::mutableOf() %p, %s\n", type, type.toChars());
Type t = type;
@ -6204,7 +6322,7 @@ extern(C++) Type mutableOf(Type type)
return t;
}
extern(C++) Type sharedOf(Type type)
Type sharedOf(Type type)
{
//printf("Type::sharedOf() %p, %s\n", type, type.toChars());
if (type.mod == MODFlags.shared_)
@ -6221,7 +6339,7 @@ extern(C++) Type sharedOf(Type type)
return t;
}
extern(C++) Type sharedConstOf(Type type)
Type sharedConstOf(Type type)
{
//printf("Type::sharedConstOf() %p, %s\n", type, type.toChars());
if (type.mod == (MODFlags.shared_ | MODFlags.const_))
@ -6250,7 +6368,7 @@ extern(C++) Type sharedConstOf(Type type)
* shared wild => wild
* shared wild const => wild const
*/
extern(C++) Type unSharedOf(Type type)
Type unSharedOf(Type type)
{
//printf("Type::unSharedOf() %p, %s\n", type, type.toChars());
Type t = type;
@ -6292,7 +6410,7 @@ extern(C++) Type unSharedOf(Type type)
/********************************
* Convert to 'wild'.
*/
extern(C++) Type wildOf(Type type)
Type wildOf(Type type)
{
//printf("Type::wildOf() %p %s\n", type, type.toChars());
if (type.mod == MODFlags.wild)
@ -6309,7 +6427,7 @@ extern(C++) Type wildOf(Type type)
return t;
}
extern(C++) Type wildConstOf(Type type)
Type wildConstOf(Type type)
{
//printf("Type::wildConstOf() %p %s\n", type, type.toChars());
if (type.mod == MODFlags.wildconst)
@ -6326,7 +6444,7 @@ extern(C++) Type wildConstOf(Type type)
return t;
}
extern(C++) Type sharedWildOf(Type type)
Type sharedWildOf(Type type)
{
//printf("Type::sharedWildOf() %p, %s\n", type, type.toChars());
if (type.mod == (MODFlags.shared_ | MODFlags.wild))
@ -6343,7 +6461,7 @@ extern(C++) Type sharedWildOf(Type type)
return t;
}
extern(C++) Type sharedWildConstOf(Type type)
Type sharedWildConstOf(Type type)
{
//printf("Type::sharedWildConstOf() %p, %s\n", type, type.toChars());
if (type.mod == (MODFlags.shared_ | MODFlags.wildconst))
@ -6363,7 +6481,7 @@ extern(C++) Type sharedWildConstOf(Type type)
/************************************
* Apply MODxxxx bits to existing type.
*/
extern(C++) Type castMod(Type type, MOD mod)
Type castMod(Type type, MOD mod)
{
Type t;
switch (mod)
@ -6415,7 +6533,7 @@ extern(C++) Type castMod(Type type, MOD mod)
* We're adding, not replacing, so adding const to
* a shared type => "shared const"
*/
extern(C++) Type addMod(Type type, MOD mod)
Type addMod(Type type, MOD mod)
{
/* Add anything to immutable, and it remains immutable
*/

View file

@ -35,7 +35,7 @@ import core.stdc.stdio;
* Returns:
* true if `TypeInfo` was generated and needs compiling to object file
*/
extern (C++) bool genTypeInfo(Expression e, const ref Loc loc, Type torig, Scope* sc)
bool genTypeInfo(Expression e, const ref Loc loc, Type torig, Scope* sc)
{
// printf("genTypeInfo() %s\n", torig.toChars());
@ -147,7 +147,7 @@ private TypeInfoDeclaration getTypeInfoDeclaration(Type t)
* true if any part of type t is speculative.
* if t is null, returns false.
*/
extern (C++) bool isSpeculativeType(Type t)
bool isSpeculativeType(Type t)
{
static bool visitVector(TypeVector t)
{
@ -244,7 +244,7 @@ extern (C++) bool isSpeculativeType(Type t)
/* Indicates whether druntime already contains an appropriate TypeInfo instance
* for the specified type (in module rt.util.typeinfo).
*/
extern (C++) bool builtinTypeInfo(Type t)
bool builtinTypeInfo(Type t)
{
if (!t.mod) // unqualified types only
{

View file

@ -16,7 +16,10 @@ class Expression;
class Type;
struct Scope;
bool genTypeInfo(Expression *e, const Loc &loc, Type *torig, Scope *sc);
namespace dmd
{
bool genTypeInfo(Expression *e, const Loc &loc, Type *torig, Scope *sc);
bool isSpeculativeType(Type *t);
bool builtinTypeInfo(Type *t);
}
Type *getTypeInfoType(const Loc &loc, Type *t, Scope *sc, bool genObjCode = true);
bool isSpeculativeType(Type *t);
bool builtinTypeInfo(Type *t);

View file

@ -126,6 +126,7 @@ class WithScopeSymbol;
class ArrayScopeSymbol;
class Nspace;
class AliasAssign;
class CAsmDeclaration;
class AggregateDeclaration;
class StructDeclaration;
@ -339,6 +340,7 @@ public:
virtual void visit(DebugSymbol *s) { visit((Dsymbol *)s); }
virtual void visit(VersionSymbol *s) { visit((Dsymbol *)s); }
virtual void visit(AliasAssign *s) { visit((Dsymbol *)s); }
virtual void visit(CAsmDeclaration *s) { visit((Dsymbol *)s); }
// ScopeDsymbols
virtual void visit(Package *s) { visit((ScopeDsymbol *)s); }

View file

@ -1178,7 +1178,7 @@ public:
{
libcall = LIBCALL_AAGETY;
ptr = build_address (build_expr (e->e1));
tinfo = build_typeinfo (e, mutableOf (unSharedOf (tb1)));
tinfo = build_typeinfo (e, dmd::mutableOf (dmd::unSharedOf (tb1)));
}
else
{
@ -1188,7 +1188,7 @@ public:
}
/* Index the associative array. */
tree result = build_libcall (libcall, e->type->pointerTo (), 4,
tree result = build_libcall (libcall, dmd::pointerTo (e->type), 4,
ptr, tinfo,
size_int (tb1->nextOf ()->size ()),
build_address (key));
@ -1253,7 +1253,8 @@ public:
else
{
/* Generate `array.ptr[index]'. */
tree ptr = convert_expr (array, tb1, tb1->nextOf ()->pointerTo ());
tree ptr = convert_expr (array, tb1,
dmd::pointerTo (tb1->nextOf ()));
ptr = void_okay_p (ptr);
this->result_ = indirect_ref (TREE_TYPE (TREE_TYPE (ptr)),
build_pointer_index (ptr, index));
@ -1328,7 +1329,7 @@ public:
/* Get the data pointer and length for static and dynamic arrays. */
tree array = d_save_expr (build_expr (e->e1));
tree ptr = convert_expr (array, tb1, tb1->nextOf ()->pointerTo ());
tree ptr = convert_expr (array, tb1, dmd::pointerTo (tb1->nextOf ()));
tree length = NULL_TREE;
/* Our array is already a SAVE_EXPR if necessary, so we don't make length
@ -1994,7 +1995,7 @@ public:
void visit (TypeidExp *e) final override
{
if (Type *tid = isType (e->obj))
if (Type *tid = dmd::isType (e->obj))
{
tree ti = build_typeinfo (e, tid);
@ -2004,7 +2005,7 @@ public:
this->result_ = build_nop (build_ctype (e->type), ti);
}
else if (Expression *tid = isExpression (e->obj))
else if (Expression *tid = dmd::isExpression (e->obj))
{
Type *type = tid->type->toBasetype ();
assert (type->ty == TY::Tclass);
@ -2136,7 +2137,8 @@ public:
else
{
var->inuse++;
init = build_expr (initializerToExpression (var->_init), true);
Expression *vinit = dmd::initializerToExpression (var->_init);
init = build_expr (vinit, true);
var->inuse--;
}
}
@ -2170,7 +2172,7 @@ public:
{
/* Generate a slice for non-zero initialized aggregates,
otherwise create an empty array. */
gcc_assert (e->type == constOf (Type::tvoid->arrayOf ()));
gcc_assert (e->type == dmd::constOf (Type::tvoid->arrayOf ()));
tree type = build_ctype (e->type);
tree length = size_int (sd->dsym->structsize);
@ -2682,7 +2684,7 @@ public:
{
/* Allocate space on the memory managed heap. */
tree mem = build_libcall (LIBCALL_ARRAYLITERALTX,
etype->pointerTo (), 2,
dmd::pointerTo (etype), 2,
build_typeinfo (e, etype->arrayOf ()),
size_int (e->elements->length));
mem = d_save_expr (mem);
@ -2718,7 +2720,7 @@ public:
}
/* Want the mutable type for typeinfo reference. */
Type *tb = mutableOf (e->type->toBasetype ());
Type *tb = dmd::mutableOf (e->type->toBasetype ());
/* Handle empty assoc array literals. */
TypeAArray *ta = tb->isTypeAArray ();

View file

@ -126,7 +126,7 @@ maybe_set_intrinsic (FuncDeclaration *decl)
return;
OutBuffer buf;
mangleToBuffer (fd->type, buf);
dmd::mangleToBuffer (fd->type, buf);
tdeco = buf.extractChars ();
}
@ -719,7 +719,7 @@ expand_intrinsic_rotate (intrinsic_code intrinsic, tree callexp)
TemplateInstance *ti = DECL_LANG_FRONTEND (callee)->isInstantiated ();
gcc_assert (ti && ti->tiargs && ti->tiargs->length == 2);
Expression *e = isExpression ((*ti->tiargs)[0]);
Expression *e = dmd::isExpression ((*ti->tiargs)[0]);
gcc_assert (e && e->op == EXP::int64);
count = build_expr (e, true);
}

View file

@ -504,7 +504,7 @@ layout_moduleinfo_fields (Module *decl, tree type)
if (decl->sshareddtor)
layout_moduleinfo_field (ptr_type_node, type, offset);
if (findGetMembers (decl))
if (dmd::findGetMembers (decl))
layout_moduleinfo_field (ptr_type_node, type, offset);
if (decl->sictor)
@ -532,7 +532,7 @@ layout_moduleinfo_fields (Module *decl, tree type)
/* Array of local ClassInfo decls are laid out in the same way. */
ClassDeclarations aclasses;
getLocalClasses (decl, aclasses);
dmd::getLocalClasses (decl, aclasses);
if (aclasses.length)
{
@ -562,7 +562,7 @@ layout_moduleinfo (Module *decl)
ClassDeclarations aclasses;
FuncDeclaration *sgetmembers;
getLocalClasses (decl, aclasses);
dmd::getLocalClasses (decl, aclasses);
size_t aimports_dim = decl->aimports.length;
for (size_t i = 0; i < decl->aimports.length; i++)
@ -572,7 +572,7 @@ layout_moduleinfo (Module *decl)
aimports_dim--;
}
sgetmembers = findGetMembers (decl);
sgetmembers = dmd::findGetMembers (decl);
size_t flags = 0;
if (decl->sctor)

View file

@ -150,11 +150,11 @@ get_libcall_type (d_libcall_type type)
break;
case LCT_CONST_TYPEINFO:
libcall_types[type] = constOf (Type::dtypeinfo->type);
libcall_types[type] = dmd::constOf (Type::dtypeinfo->type);
break;
case LCT_CONST_CLASSINFO:
libcall_types[type] = constOf (Type::typeinfoclass->type);
libcall_types[type] = dmd::constOf (Type::typeinfoclass->type);
break;
case LCT_ARRAY_VOID:
@ -186,7 +186,7 @@ get_libcall_type (d_libcall_type type)
break;
case LCT_POINTER_ASSOCARRAY:
libcall_types[type] = get_libcall_type (LCT_ASSOCARRAY)->pointerTo ();
libcall_types[type] = dmd::pointerTo (get_libcall_type (LCT_ASSOCARRAY));
break;
case LCT_POINTER_VOIDPTR:
@ -194,15 +194,15 @@ get_libcall_type (d_libcall_type type)
break;
case LCT_ARRAYPTR_VOID:
libcall_types[type] = Type::tvoid->arrayOf ()->pointerTo ();
libcall_types[type] = dmd::pointerTo (Type::tvoid->arrayOf ());
break;
case LCT_ARRAYPTR_BYTE:
libcall_types[type] = Type::tint8->arrayOf ()->pointerTo ();
libcall_types[type] = dmd::pointerTo (Type::tint8->arrayOf ());
break;
case LCT_IMMUTABLE_CHARPTR:
libcall_types[type] = immutableOf (Type::tchar->pointerTo ());
libcall_types[type] = dmd::immutableOf (dmd::pointerTo (Type::tchar));
break;
default:

View file

@ -206,7 +206,7 @@ make_frontend_typeinfo (Identifier *ident, ClassDeclaration *base = NULL)
/* Create object module in order to complete the semantic. */
if (!object_module->_scope)
importAll (object_module, NULL);
dmd::importAll (object_module, NULL);
/* Object class doesn't exist, create a stub one that will cause an error if
used. */
@ -232,7 +232,7 @@ make_frontend_typeinfo (Identifier *ident, ClassDeclaration *base = NULL)
true);
tinfo->parent = object_module;
tinfo->members = d_gc_malloc<Dsymbols> ();
dsymbolSemantic (tinfo, object_module->_scope);
dmd::dsymbolSemantic (tinfo, object_module->_scope);
tinfo->baseClass = base;
/* This is a compiler generated class, and shouldn't be mistaken for being
the type declared in the runtime library. */
@ -577,8 +577,8 @@ public:
void visit (TypeInfoConstDeclaration *d) final override
{
Type *tm = mutableOf (d->tinfo);
tm = merge2 (tm);
Type *tm = dmd::mutableOf (d->tinfo);
tm = dmd::merge2 (tm);
/* The vtable for TypeInfo_Const. */
this->layout_base (Type::typeinfoconst);
@ -594,8 +594,8 @@ public:
void visit (TypeInfoInvariantDeclaration *d) final override
{
Type *tm = mutableOf (d->tinfo);
tm = merge2 (tm);
Type *tm = dmd::mutableOf (d->tinfo);
tm = dmd::merge2 (tm);
/* The vtable for TypeInfo_Invariant. */
this->layout_base (Type::typeinfoinvariant);
@ -611,8 +611,8 @@ public:
void visit (TypeInfoSharedDeclaration *d) final override
{
Type *tm = unSharedOf (d->tinfo);
tm = merge2 (tm);
Type *tm = dmd::unSharedOf (d->tinfo);
tm = dmd::merge2 (tm);
/* The vtable for TypeInfo_Shared. */
this->layout_base (Type::typeinfoshared);
@ -628,8 +628,8 @@ public:
void visit (TypeInfoWildDeclaration *d) final override
{
Type *tm = mutableOf (d->tinfo);
tm = merge2 (tm);
Type *tm = dmd::mutableOf (d->tinfo);
tm = dmd::merge2 (tm);
/* The vtable for TypeInfo_Inout. */
this->layout_base (Type::typeinfowild);
@ -1091,7 +1091,7 @@ public:
this->layout_field (xcmp);
/* string function(const(void)*) xtoString; */
FuncDeclaration *fdx = search_toString (sd);
FuncDeclaration *fdx = dmd::search_toString (sd);
if (fdx)
this->layout_field (build_address (get_symbol_decl (fdx)));
else
@ -1099,7 +1099,7 @@ public:
/* StructFlags m_flags; */
int m_flags = StructFlags::none;
if (hasPointers (ti))
if (dmd::hasPointers (ti))
m_flags |= StructFlags::hasPointers;
this->layout_field (build_integer_cst (m_flags, d_uint_type));
@ -1551,7 +1551,7 @@ create_typeinfo (Type *type, Module *mod, bool generate)
create_frontend_tinfo_types ();
/* Do this since not all Type's are merged. */
Type *t = merge2 (type);
Type *t = dmd::merge2 (type);
Identifier *ident;
if (!t->vtinfo)

View file

@ -144,7 +144,7 @@ same_type_p (Type *t1, Type *t2)
return true;
/* Types are mutably the same type. */
if (tb1->ty == tb2->ty && equivalent (tb1, tb2))
if (tb1->ty == tb2->ty && dmd::equivalent (tb1, tb2))
return true;
return false;
@ -1334,7 +1334,7 @@ build_ctype (Type *t)
t->accept (&v);
else
{
Type *tb = castMod (t, 0);
Type *tb = dmd::castMod (t, 0);
if (!tb->ctype)
tb->accept (&v);
t->ctype = insert_type_modifiers (tb->ctype, t->mod);

View file

@ -0,0 +1,2 @@
module imports.test24390a;
public import imports.test24390b;

View 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;
}
}

View file

@ -2326,7 +2326,7 @@ struct Bug10840
Data10840* _data;
}
bool bug10840(int n)
enum bug10840 = (int n)
{
Bug10840 stack;
if (n == 1)
@ -2336,7 +2336,7 @@ bool bug10840(int n)
}
// Wrong-code for ?:
return stack._data ? false : true;
}
};
static assert(bug10840(0));
static assert(!is(typeof(Compileable!(bug10840(1)))));
@ -5910,13 +5910,13 @@ struct Bug7527
char[] data;
}
int bug7527()
enum bug7527 = ()
{
auto app = Bug7527();
app.data.ptr[0 .. 1] = "x";
return 1;
}
};
static assert(!is(typeof(compiles!(bug7527()))));

View 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;
}
}

View file

@ -316,3 +316,7 @@ extern(C++, `inst`)
mixin GetNamespaceTestTemplatedMixin!() GNTT;
static assert (__traits(getCppNamespaces, GNTT.foo) == Seq!(`inst`,/*`decl`,*/ `f`));
int[1] arr;
// test that index assignment parses as an expression, not a type
enum _ = __traits(compiles, arr[0] = 0);

View file

@ -3,4 +3,5 @@ module issue21685;
class E
{
private this() {}
public this(int) {}
}

View file

@ -1,7 +1,8 @@
/* REQUIRED_ARGS: -preview=dip1000 -Ifail_compilation/imports
TEST_OUTPUT:
---
fail_compilation/issue21685_main.d(11): Error: class `issue21685.E` constructor `this` is not accessible
fail_compilation/issue21685_main.d(12): Error: constructor `issue21685.E.this` is not accessible from module `issue21685_main`
fail_compilation/issue21685_main.d(19): Error: constructor `issue21685.E.this` is not accessible from module `issue21685_main`
---
*/
import issue21685;
@ -10,3 +11,11 @@ void main()
{
new E;
}
class F : E
{
this()
{
super();
}
}

View 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) {}

View file

@ -13,7 +13,7 @@ class AliasDecl {}
void aliasDecl(AliasDecl ad)
{
AliasDecl* zis;
AliasDecl* zis = &ad;
static if (is(typeof(to!string(*zis))))
{

View file

@ -2478,6 +2478,19 @@ void test21835()
if (arr[0].r != 0.0) assert(0);
}
////////////////////////////////////////////////////////////////////////
// https://github.com/dlang/dmd/pull/16187#issuecomment-1946534649
void testDoWhileContinue()
{
int i = 10;
do
{
continue;
}
while(--i > 0);
}
////////////////////////////////////////////////////////////////////////
int main()
@ -2578,6 +2591,7 @@ int main()
test21256();
test21816();
test21835();
testDoWhileContinue();
printf("Success\n");
return 0;

View file

@ -165,6 +165,22 @@ void testEnumInit()
/////////////////////////////////////////////
// https://issues.dlang.org/show_bug.cgi?id=24370
immutable uint[3][string] test = [
"oneTwoThree": [1,2,3],
"fourFiveSix": [4,5,6],
"sevenEightNine": [7,8,9],
];
void testStaticArray()
{
assert(test["oneTwoThree"] == [1, 2, 3]);
assert(test["fourFiveSix"] == [4, 5, 6]);
assert(test["sevenEightNine"] == [7, 8, 9]);
}
/////////////////////////////////////////////
void main()
{
testSimple();
@ -175,4 +191,5 @@ void main()
testImmutable();
testLocalStatic();
testEnumInit();
testStaticArray();
}

View file

@ -1,10 +1,10 @@
// EXTRA_CPP_SOURCES: cpp7925.cpp
/*
Exclude -O due to a codegen bug on OSX:
Exclude -O/-inline due to a codegen bug on OSX:
https://issues.dlang.org/show_bug.cgi?id=22556
PERMUTE_ARGS(osx): -inline -release -g
PERMUTE_ARGS(osx): -release -g
*/
import core.vararg;

View file

@ -1,4 +1,4 @@
11240a96635074b2f79d908b9348e9c0fbc3c7dc
9471b25db9ed44d71e0e27956430c0c6a09c16db
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.

View file

@ -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;
}

View file

@ -14,7 +14,7 @@
*/
module core.thread.fiber;
import core.thread.osthread;
import core.thread.threadbase;
import core.thread.threadgroup;
import core.thread.types;
import core.thread.context;
@ -220,8 +220,8 @@ private
Fiber obj = Fiber.getThis();
assert( obj );
assert( Thread.getThis().m_curr is obj.m_ctxt );
atomicStore!(MemoryOrder.raw)(*cast(shared)&Thread.getThis().m_lock, false);
assert( ThreadBase.getThis().m_curr is obj.m_ctxt );
atomicStore!(MemoryOrder.raw)(*cast(shared)&ThreadBase.getThis().m_lock, false);
obj.m_ctxt.tstack = obj.m_ctxt.bstack;
obj.m_state = Fiber.State.EXEC;
@ -1106,7 +1106,7 @@ private:
}
}
Thread.add( m_ctxt );
ThreadBase.add( m_ctxt );
}
@ -1119,9 +1119,9 @@ private:
{
// NOTE: m_ctxt is guaranteed to be alive because it is held in the
// global context list.
Thread.slock.lock_nothrow();
scope(exit) Thread.slock.unlock_nothrow();
Thread.remove( m_ctxt );
ThreadBase.slock.lock_nothrow();
scope(exit) ThreadBase.slock.unlock_nothrow();
ThreadBase.remove( m_ctxt );
version (Windows)
{
@ -1623,7 +1623,7 @@ private:
//
final void switchIn() nothrow @nogc
{
Thread tobj = Thread.getThis();
ThreadBase tobj = ThreadBase.getThis();
void** oldp = &tobj.m_curr.tstack;
void* newp = m_ctxt.tstack;
@ -1657,7 +1657,7 @@ private:
//
final void switchOut() nothrow @nogc
{
Thread tobj = Thread.getThis();
ThreadBase tobj = ThreadBase.getThis();
void** oldp = &m_ctxt.tstack;
void* newp = tobj.m_curr.within.tstack;
@ -1682,7 +1682,7 @@ private:
// NOTE: If use of this fiber is multiplexed across threads, the thread
// executing here may be different from the one above, so get the
// current thread handle before unlocking, etc.
tobj = Thread.getThis();
tobj = ThreadBase.getThis();
atomicStore!(MemoryOrder.raw)(*cast(shared)&tobj.m_lock, false);
tobj.m_curr.tstack = tobj.m_curr.bstack;
}
@ -2027,6 +2027,7 @@ unittest
unittest
{
import core.memory;
import core.thread.osthread : Thread;
import core.time : dur;
static void unreferencedThreadObject()

View file

@ -1625,7 +1625,7 @@ extern (C) @nogc nothrow
}
package extern(D) void* getStackTop() nothrow @nogc
private extern(D) void* getStackTop() nothrow @nogc
{
version (D_InlineAsm_X86)
asm pure nothrow @nogc { naked; mov EAX, ESP; ret; }
@ -1638,7 +1638,7 @@ package extern(D) void* getStackTop() nothrow @nogc
}
package extern(D) void* getStackBottom() nothrow @nogc
private extern(D) void* getStackBottom() nothrow @nogc
{
version (Windows)
{

View file

@ -84,7 +84,10 @@ private
enum mutexClassInstanceSize = __traits(classInstanceSize, Mutex);
alias swapContext = externDFunc!("core.thread.osthread.swapContext", void* function(void*) nothrow @nogc);
}
package
{
alias getStackBottom = externDFunc!("core.thread.osthread.getStackBottom", void* function() nothrow @nogc);
alias getStackTop = externDFunc!("core.thread.osthread.getStackTop", void* function() nothrow @nogc);
}

View file

@ -1,4 +1,4 @@
37796e783ba438a0bedfb435dbbcc7aeaf06ce2a
5478868465ae1ad743ff76ac5bb92691463ffec5
The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository.

View file

@ -2027,7 +2027,7 @@ private struct ChunkByGroup(alias eq, Range, bool eqEquivalenceAssured)
}
// Cannot be a copy constructor due to https://issues.dlang.org/show_bug.cgi?id=22239
this(this) @trusted
this(this) scope @trusted
{
import core.lifetime : emplace;
// since mothership has to be in a union, we have to manually trigger
@ -2129,7 +2129,7 @@ if (isForwardRange!Range)
}
// Cannot be a copy constructor due to https://issues.dlang.org/show_bug.cgi?id=22239
this(this) @trusted
this(this) scope @trusted
{
import core.lifetime : emplace;
// since _impl has to be in a union, we have to manually trigger

View file

@ -1813,22 +1813,28 @@ range.
For example, here is how to remove a single element from an array:
$(RUNNABLE_EXAMPLE
----
import std.algorithm.mutation;
string[] a = [ "a", "b", "c", "d" ];
a = a.remove(1); // remove element at offset 1
assert(a == [ "a", "c", "d"]);
----
)
Note that `remove` does not change the length of the original range directly;
instead, it returns the shortened range. If its return value is not assigned to
the original range, the original range will retain its original length, though
its contents will have changed:
$(RUNNABLE_EXAMPLE
----
import std.algorithm.mutation;
int[] a = [ 3, 5, 7, 8 ];
assert(remove(a, 1) == [ 3, 7, 8 ]);
assert(a == [ 3, 7, 8, 8 ]);
----
)
The element at offset `1` has been removed and the rest of the elements have
shifted up to fill its place, however, the original array remains of the same
@ -1838,25 +1844,34 @@ invoked to rearrange elements, and on integers `move` simply copies the source
to the destination. To replace `a` with the effect of the removal, simply
assign the slice returned by `remove` to it, as shown in the first example.
$(H3 $(LNAME2 remove-multiple, Removing multiple elements))
Multiple indices can be passed into `remove`. In that case,
elements at the respective indices are all removed. The indices must
be passed in increasing order, otherwise an exception occurs.
$(RUNNABLE_EXAMPLE
----
import std.algorithm.mutation;
int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
assert(remove(a, 1, 3, 5) ==
[ 0, 2, 4, 6, 7, 8, 9, 10 ]);
----
)
(Note that all indices refer to slots in the $(I original) array, not
in the array as it is being progressively shortened.)
Note that all indices refer to slots in the $(I original) array, not
in the array as it is being progressively shortened.
Tuples of two integral offsets can be used to remove an indices range:
Tuples of two integral offsets can be supplied to remove a range of indices:
$(RUNNABLE_EXAMPLE
----
import std.algorithm.mutation, std.typecons;
int[] a = [ 3, 4, 5, 6, 7];
assert(remove(a, 1, tuple(1, 3), 9) == [ 3, 6, 7 ]);
// remove elements at indices 1 and 2
assert(remove(a, tuple(1, 3)) == [ 3, 6, 7 ]);
----
)
The tuple passes in a range closed to the left and open to
the right (consistent with built-in slices), e.g. `tuple(1, 3)`
@ -1865,22 +1880,31 @@ means indices `1` and `2` but not `3`.
Finally, any combination of integral offsets and tuples composed of two integral
offsets can be passed in:
$(RUNNABLE_EXAMPLE
----
import std.algorithm.mutation, std.typecons;
int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
assert(remove(a, 1, tuple(3, 5), 9) == [ 0, 2, 5, 6, 7, 8, 10 ]);
a = remove(a, 1, tuple(3, 5), 9);
assert(a == [ 0, 2, 5, 6, 7, 8, 10 ]);
----
)
In this case, the slots at positions 1, 3, 4, and 9 are removed from
the array.
$(H3 $(LNAME2 remove-moving, Moving strategy))
If the need is to remove some elements in the range but the order of
the remaining elements does not have to be preserved, you may want to
pass `SwapStrategy.unstable` to `remove`.
$(RUNNABLE_EXAMPLE
----
import std.algorithm.mutation;
int[] a = [ 0, 1, 2, 3 ];
assert(remove!(SwapStrategy.unstable)(a, 1) == [ 0, 3, 2 ]);
----
)
In the case above, the element at slot `1` is removed, but replaced
with the last element of the range. Taking advantage of the relaxation
@ -1888,7 +1912,7 @@ of the stability requirement, `remove` moved elements from the end
of the array over the slots to be removed. This way there is less data
movement to be done which improves the execution time of the function.
The function `remove` works on bidirectional ranges that have assignable
`remove` works on bidirectional ranges that have assignable
lvalue elements. The moving strategy is (listed from fastest to slowest):
$(UL
@ -1914,7 +1938,7 @@ Params:
offset = which element(s) to remove
Returns:
A range containing all of the elements of range with offset removed.
A range containing elements of `range` with 1 or more elements removed.
*/
Range remove
(SwapStrategy s = SwapStrategy.stable, Range, Offset ...)

View file

@ -2427,7 +2427,14 @@ if (Rs.length > 1 && allSatisfy!(isInputRange, staticMap!(Unqual, Rs)))
}
}
return Result(rs, 0);
size_t firstNonEmpty = size_t.max;
static foreach (i; 0 .. Rs.length)
{
if (firstNonEmpty == size_t.max && !rs[i].empty)
firstNonEmpty = i;
}
return Result(rs, firstNonEmpty);
}
///
@ -2489,6 +2496,14 @@ pure @safe nothrow unittest
assert(equal(r, [ S(1), S(10), S(2), S(20) ]));
}
// https://issues.dlang.org/show_bug.cgi?id=24384
@safe unittest
{
auto r = roundRobin("", "a");
assert(!r.empty);
auto e = r.front;
}
/**
Iterates a random-access range starting from a given point and
progressively extending left and right from that point. If no initial
@ -10167,10 +10182,18 @@ public:
private struct OnlyResult(Values...)
if (Values.length > 1)
{
import std.meta : ApplyRight;
import std.traits : isAssignable;
private enum arity = Values.length;
private alias UnqualValues = staticMap!(Unqual, Values);
private enum canAssignElements = allSatisfy!(
ApplyRight!(isAssignable, CommonType!Values),
Values
);
private this(return scope ref Values values)
{
ref @trusted unqual(T)(ref T x){return cast() x;}
@ -10195,6 +10218,15 @@ if (Values.length > 1)
return this[0];
}
static if (canAssignElements)
{
void front(CommonType!Values value) @property
{
assert(!empty, "Attempting to assign the front of an empty Only range");
this[0] = value;
}
}
void popFront()
{
assert(!empty, "Attempting to popFront an empty Only range");
@ -10207,6 +10239,15 @@ if (Values.length > 1)
return this[$ - 1];
}
static if (canAssignElements)
{
void back(CommonType!Values value) @property
{
assert(!empty, "Attempting to assign the back of an empty Only range");
this[$ - 1] = value;
}
}
void popBack()
{
assert(!empty, "Attempting to popBack an empty Only range");
@ -10236,6 +10277,18 @@ if (Values.length > 1)
return cast(T) values[i];
}
static if (canAssignElements)
{
void opIndexAssign(CommonType!Values value, size_t idx)
{
assert(idx < length, "Attempting to assign to an out of bounds index of an Only range");
final switch (frontIndex + idx)
static foreach (i; 0 .. Values.length)
case i:
values[i] = value;
}
}
OnlyResult opSlice()
{
return this;
@ -10279,16 +10332,34 @@ if (Values.length > 1)
// Specialize for single-element results
private struct OnlyResult(T)
{
import std.traits : isAssignable;
@property T front()
{
assert(!empty, "Attempting to fetch the front of an empty Only range");
return fetchFront();
}
static if (isAssignable!T)
{
@property void front(T value)
{
assert(!empty, "Attempting to assign the front of an empty Only range");
assignFront(value);
}
}
@property T back()
{
assert(!empty, "Attempting to fetch the back of an empty Only range");
return fetchFront();
}
static if (isAssignable!T)
{
@property void back(T value)
{
assert(!empty, "Attempting to assign the front of an empty Only range");
assignFront(value);
}
}
@property bool empty() const { return _empty; }
@property size_t length() const { return !_empty; }
@property auto save() { return this; }
@ -10319,6 +10390,15 @@ private struct OnlyResult(T)
return fetchFront();
}
static if (isAssignable!T)
{
void opIndexAssign(T value, size_t i)
{
assert(!_empty && i == 0, "Attempting to assign an out of bounds index of an Only range");
assignFront(value);
}
}
OnlyResult opSlice()
{
return this;
@ -10348,6 +10428,13 @@ private struct OnlyResult(T)
{
return *cast(T*)&_value;
}
static if (isAssignable!T)
{
private @trusted void assignFront(T newValue)
{
*cast(T*) &_value = newValue;
}
}
}
/**
@ -10368,6 +10455,9 @@ Params:
Returns:
A `RandomAccessRange` of the assembled values.
The returned range can be sliced. Its elements can be assigned to if every
type in `Values` supports assignment from the range's element type.
See_Also: $(LREF chain) to chain ranges
*/
auto only(Values...)(return scope Values values)
@ -10629,6 +10719,32 @@ auto only()()
auto r1 = arr.chain(x.only, only(x, x));
}
// https://issues.dlang.org/show_bug.cgi?id=24382
@safe unittest
{
auto r1 = only(123);
r1.front = 456;
r1.back = 456;
r1[0] = 456;
auto r2 = only(123, 456);
r2.front = 789;
r2.back = 789;
r2[0] = 789;
auto r3 = only(1.23, 456);
// Can't assign double to int
static assert(!__traits(compiles, r3.front = 7.89));
static assert(!__traits(compiles, r3.back = 7.89));
// Workaround https://issues.dlang.org/show_bug.cgi?id=24383
static assert(!__traits(compiles, () { r3[0] = 7.89; }));
// Can't assign type other than element type (even if compatible)
static assert(!__traits(compiles, r3.front = 789));
static assert(!__traits(compiles, r3.back = 789));
// Workaround https://issues.dlang.org/show_bug.cgi?id=24383
static assert(!__traits(compiles, () { r3[0] = 789; }));
}
/**
Iterate over `range` with an attached index variable.