From patchwork Mon Feb 12 16:10:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 1897793 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gdcproject.org header.i=@gdcproject.org header.a=rsa-sha256 header.s=MBO0001 header.b=hJXtd5sD; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4TYTwn3Lvzz23hw for ; Tue, 13 Feb 2024 03:11:37 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5EC453858C39 for ; Mon, 12 Feb 2024 16:11:35 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mout-p-202.mailbox.org (mout-p-202.mailbox.org [IPv6:2001:67c:2050:0:465::202]) by sourceware.org (Postfix) with ESMTPS id 193863858D38 for ; Mon, 12 Feb 2024 16:11:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 193863858D38 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=gdcproject.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gdcproject.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 193863858D38 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2001:67c:2050:0:465::202 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1707754270; cv=none; b=f9uu4+JqoJE4A1uyAECrudHYLy1/QJpC6DCGybBruYVZoqFvppexclhlumHSTcuHAPdN5Q70YIg3jP22SWwMNCXn46Mbfx0Cz3MjhYpDm/Cq13yBoMC0ZHFoqh9BvF+JnPzN30m8Mf+9lu0krPSxeQlaFEWqwi2lnat+GCyQ36w= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1707754270; c=relaxed/simple; bh=rQ9yICcijavRdtNNrfxDlees6ftLh4Ht/1G265Npbe0=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=sTpNZ97iYs7gGgQkfS5wxVo7E0ZeH4k/WMADxPsXRP1YF6EkV/Ss5g5Yddk2elKq23ZlPDf5T6jZhe8UBn95gKASSlZ0nmHAzaBlasJTyN3+njsl7occ9iVN0y07Geb7E11USUUm+d+yU29TzQm4dvISNnwj/olgWjQP3HieYhc= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smtp2.mailbox.org (smtp2.mailbox.org [10.196.197.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-202.mailbox.org (Postfix) with ESMTPS id 4TYTw44ftPz9stY; Mon, 12 Feb 2024 17:11:00 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gdcproject.org; s=MBO0001; t=1707754260; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=D7lcIJP6QMXrwAiEZY+w9LI9wVc0z+1SmyDuypWqjfc=; b=hJXtd5sD+YMCnwQ+o76TJDICB4za3zR4XZLmDS/kJcL2Mx/RDtm+X3p3V/oRoDFeghMFIz LKlVWgeMuW7aN5Eyv/3TJf3USq27HanyrENI60I24Gm3wtxixeLfpomLwA8Gc1L6lgYTkh /mrkMf8buHA5OhHedAya+xvFDFqM/TUd6PEv4WTXVnUvSevNLyDSwzioHd9HJczpF7l2sZ 8aIl408AXyJzIt10FYNEOQl0Gz+xNPAPxiBfvTHhytI7pogFtdIPphpueUYMChHuEQI8dV Ti0wVpAmWMXh/FI23J5dF21J127B/dFoTNSD2N/ki37Shpjnexd2ACMPWwo4kA== From: Iain Buclaw To: gcc-patches@gcc.gnu.org Cc: Iain Buclaw Subject: [committed] d: Merge dmd, druntime 11240a9663 Date: Mon, 12 Feb 2024 17:10:56 +0100 Message-Id: <20240212161056.1199560-1-ibuclaw@gdcproject.org> MIME-Version: 1.0 X-Spam-Status: No, score=-13.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_NUMSUBJECT, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Hi, This patch merges the D front-end and core runtime library with upstream dmd 11240a9663. Included in the merge are the fix for PR113772, and new testsuite directives to enable fixing PR104739. D front-end changes: - Import latest fixes from dmd v2.107.0. D runtime changes: - Import latest fixes from druntime v2.107.0. Bootstrapped and regression tested on x86_64-linux-gnu/-m32, committed to mainline. Regards, Iain. --- PR d/113772 gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 11240a9663. * d-builtins.cc (build_frontend_type): Update for new front-end interface. * types.cc (same_type_p): Likewise. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 11240a9663. --- gcc/d/d-builtins.cc | 31 ++-- gcc/d/dmd/MERGE | 2 +- gcc/d/dmd/aggregate.d | 2 +- gcc/d/dmd/aggregate.h | 1 + gcc/d/dmd/astcodegen.d | 1 + gcc/d/dmd/astenums.d | 2 +- gcc/d/dmd/clone.d | 17 +- gcc/d/dmd/constfold.d | 2 +- gcc/d/dmd/dcast.d | 87 +++++++++- gcc/d/dmd/declaration.d | 4 +- gcc/d/dmd/declaration.h | 2 - gcc/d/dmd/dinterpret.d | 2 +- gcc/d/dmd/dsymbol.h | 2 - gcc/d/dmd/dsymbolsem.d | 2 +- gcc/d/dmd/errors.h | 2 - gcc/d/dmd/expression.h | 10 +- gcc/d/dmd/expressionsem.d | 34 ++-- gcc/d/dmd/func.d | 11 +- gcc/d/dmd/hdrgen.h | 8 + gcc/d/dmd/init.h | 1 + gcc/d/dmd/mtype.d | 112 +----------- gcc/d/dmd/mtype.h | 6 +- gcc/d/dmd/parse.d | 2 +- gcc/d/dmd/statement.h | 5 + gcc/d/dmd/template.h | 3 + gcc/d/dmd/typesem.d | 112 +++++++++++- gcc/d/types.cc | 2 +- .../gdc.test/compilable/commontype.d | 20 +-- gcc/testsuite/gdc.test/compilable/test3543.d | 80 +++++++++ gcc/testsuite/gdc.test/runnable/mangle.d | 1 + gcc/testsuite/gdc.test/runnable/testmodule.d | 2 + gcc/testsuite/gdc.test/runnable/ufcs.d | 2 + libphobos/libdruntime/MERGE | 2 +- libphobos/libdruntime/core/demangle.d | 160 +++++++++--------- libphobos/libdruntime/core/internal/atomic.d | 2 +- .../core/internal/gc/impl/conservative/gc.d | 39 +++-- libphobos/libdruntime/core/internal/qsort.d | 5 +- libphobos/libdruntime/core/memory.d | 1 + libphobos/libdruntime/core/thread/osthread.d | 2 + libphobos/libdruntime/core/time.d | 4 + libphobos/libdruntime/rt/aaA.d | 1 + libphobos/libdruntime/rt/lifetime.d | 1 + 42 files changed, 491 insertions(+), 296 deletions(-) create mode 100644 gcc/testsuite/gdc.test/compilable/test3543.d diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc index 4ed8751079b..24ac456e23d 100644 --- a/gcc/d/d-builtins.cc +++ b/gcc/d/d-builtins.cc @@ -97,12 +97,15 @@ 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) - return Type::tchar->addMod (dtype->mod)->pointerTo ()->addMod (mod); + { + dtype = addMod (Type::tchar, dtype->mod); + return addMod (dtype->pointerTo (), mod); + } if (dtype->ty == TY::Tfunction) - return (TypePointer::create (dtype))->addMod (mod); + return addMod (TypePointer::create (dtype), mod); - return dtype->pointerTo ()->addMod (mod); + return addMod (dtype->pointerTo (), mod); } break; @@ -113,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 = (TypePointer::create (dtype))->addMod (mod); + dtype = addMod (TypePointer::create (dtype), mod); dtype->ctype = type; builtin_converted_decls.safe_push (builtin_data (dtype, type)); return dtype; @@ -122,7 +125,7 @@ build_frontend_type (tree type) case BOOLEAN_TYPE: /* Should be no need for size checking. */ - return Type::tbool->addMod (mod); + return addMod (Type::tbool, mod); case INTEGER_TYPE: { @@ -140,7 +143,7 @@ build_frontend_type (tree type) || size != dtype->size ()) continue; - return dtype->addMod (mod); + return addMod (dtype, mod); } break; } @@ -157,7 +160,7 @@ build_frontend_type (tree type) if (dtype->size () != size) continue; - return dtype->addMod (mod); + return addMod (dtype, mod); } break; } @@ -174,13 +177,13 @@ build_frontend_type (tree type) if (dtype->size () != size) continue; - return dtype->addMod (mod); + return addMod (dtype, mod); } break; } case VOID_TYPE: - return Type::tvoid->addMod (mod); + return addMod (Type::tvoid, mod); case ARRAY_TYPE: dtype = build_frontend_type (TREE_TYPE (type)); @@ -194,7 +197,7 @@ build_frontend_type (tree type) length = size_binop (PLUS_EXPR, size_one_node, convert (sizetype, length)); - dtype = dtype->sarrayOf (TREE_INT_CST_LOW (length))->addMod (mod); + dtype = addMod (dtype->sarrayOf (TREE_INT_CST_LOW (length)), mod); builtin_converted_decls.safe_push (builtin_data (dtype, type)); return dtype; } @@ -210,11 +213,11 @@ build_frontend_type (tree type) if (!dtype) break; - dtype = dtype->sarrayOf (nunits)->addMod (mod); + dtype = addMod (dtype->sarrayOf (nunits), mod); if (target.isVectorTypeSupported (dtype->size (), dtype->nextOf ())) break; - dtype = (TypeVector::create (dtype))->addMod (mod); + dtype = addMod (TypeVector::create (dtype), mod); builtin_converted_decls.safe_push (builtin_data (dtype, type)); return dtype; } @@ -238,7 +241,7 @@ build_frontend_type (tree type) sdecl->alignsize = TYPE_ALIGN_UNIT (type); sdecl->alignment.setDefault (); sdecl->sizeok = Sizeok::done; - sdecl->type = (TypeStruct::create (sdecl))->addMod (mod); + sdecl->type = addMod (TypeStruct::create (sdecl), mod); sdecl->type->ctype = type; merge2 (sdecl->type); @@ -331,7 +334,7 @@ build_frontend_type (tree type) if (args->length != 0 || varargs_p == VARARGnone) { dtype = TypeFunction::create (args, dtype, varargs_p, LINK::c); - return dtype->addMod (mod); + return addMod (dtype, mod); } } break; diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index 57ac2dc69e7..74c194508f7 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -a6f10836997d0b5526c8c363d781b4029c77f09f +11240a96635074b2f79d908b9348e9c0fbc3c7dc The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/gcc/d/dmd/aggregate.d b/gcc/d/dmd/aggregate.d index 2d320426c23..2c7622a9aa0 100644 --- a/gcc/d/dmd/aggregate.d +++ b/gcc/d/dmd/aggregate.d @@ -37,7 +37,7 @@ import dmd.identifier; import dmd.location; import dmd.mtype; import dmd.tokens; -import dmd.typesem : defaultInit; +import dmd.typesem : defaultInit, addMod; import dmd.visitor; /** diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h index f466ba61740..6a864002e08 100644 --- a/gcc/d/dmd/aggregate.h +++ b/gcc/d/dmd/aggregate.h @@ -42,6 +42,7 @@ enum class Baseok : uint8_t }; FuncDeclaration *search_toString(StructDeclaration *sd); +void semanticTypeInfoMembers(StructDeclaration *sd); enum class ClassKind : uint8_t { diff --git a/gcc/d/dmd/astcodegen.d b/gcc/d/dmd/astcodegen.d index f17907719a7..fd8387adb22 100644 --- a/gcc/d/dmd/astcodegen.d +++ b/gcc/d/dmd/astcodegen.d @@ -82,6 +82,7 @@ struct ASTCodegen alias Tcomplex64 = dmd.mtype.Tcomplex64; alias Tcomplex80 = dmd.mtype.Tcomplex80; + alias ModToStc = dmd.mtype.ModToStc; alias ParameterList = dmd.mtype.ParameterList; alias VarArg = dmd.mtype.VarArg; alias STC = dmd.declaration.STC; diff --git a/gcc/d/dmd/astenums.d b/gcc/d/dmd/astenums.d index 77940b80248..4fc15141c39 100644 --- a/gcc/d/dmd/astenums.d +++ b/gcc/d/dmd/astenums.d @@ -152,7 +152,7 @@ bool isRefReturnScope(const ulong stc) /* This is different from the one in declaration.d, make that fix a separate PR */ static if (0) -extern (C++) __gshared const(StorageClass) STCStorageClass = +__gshared const(StorageClass) STCStorageClass = (STC.auto_ | STC.scope_ | STC.static_ | STC.extern_ | STC.const_ | STC.final_ | STC.abstract_ | STC.synchronized_ | STC.deprecated_ | STC.override_ | STC.lazy_ | STC.alias_ | STC.out_ | STC.in_ | STC.manifest | STC.immutable_ | STC.shared_ | diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d index 46470ee9e37..2e4833e8fdd 100644 --- a/gcc/d/dmd/clone.d +++ b/gcc/d/dmd/clone.d @@ -327,10 +327,19 @@ FuncDeclaration buildOpAssign(StructDeclaration sd, Scope* sc) auto e2 = new BlitExp(loc, new VarExp(loc, swap), new ThisExp(loc)); auto e3 = new BlitExp(loc, new ThisExp(loc), new IdentifierExp(loc, Id.p)); - /* Instead of running the destructor on s, run it - * on swap. This avoids needing to copy swap back in to s. - */ - auto e4 = new CallExp(loc, new DotVarExp(loc, new VarExp(loc, swap), sd.dtor, false)); + Expression e4; + if (target.isCalleeDestroyingArgs(tf)) + { /* callee destroys s + * Instead of running the destructor on s, run it + * on swap. + */ + e4 = new CallExp(loc, new DotVarExp(loc, new VarExp(loc, swap), sd.dtor, false)); + } + else + { /* caller destroys s, so copy contents of swap back into s + */ + e4 = new BlitExp(loc, new IdentifierExp(loc, Id.p), new VarExp(loc, swap)); + } e = Expression.combine(e1, e2, e3, e4); } diff --git a/gcc/d/dmd/constfold.d b/gcc/d/dmd/constfold.d index f5d2b60f45b..0686e1b0825 100644 --- a/gcc/d/dmd/constfold.d +++ b/gcc/d/dmd/constfold.d @@ -36,6 +36,7 @@ import dmd.root.utf; import dmd.sideeffect; import dmd.target; import dmd.tokens; +import dmd.typesem : toDsymbol, equivalent; private enum LOG = false; @@ -1038,7 +1039,6 @@ UnionExp Cast(const ref Loc loc, Type type, Type to, Expression e1) else if (tb.ty == Tstruct && e1.op == EXP.int64) { // Struct = 0; - import dmd.typesem : toDsymbol; StructDeclaration sd = tb.toDsymbol(null).isStructDeclaration(); assert(sd); auto elements = new Expressions(); diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d index 9ee8e8c4864..a49bd575f4b 100644 --- a/gcc/d/dmd/dcast.d +++ b/gcc/d/dmd/dcast.d @@ -235,7 +235,7 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t) * Returns: * The `MATCH` level between `e.type` and `t`. */ -extern(C++) MATCH implicitConvTo(Expression e, Type t) +MATCH implicitConvTo(Expression e, Type t) { MATCH visit(Expression e) { @@ -2848,7 +2848,7 @@ private bool isVoidArrayLiteral(Expression e, Type other) */ Type typeMerge(Scope* sc, EXP op, ref Expression pe1, ref Expression pe2) { - //printf("typeMerge() %s op %s\n", e1.toChars(), e2.toChars()); + //printf("typeMerge() %s op %s\n", pe1.toChars(), pe2.toChars()); Expression e1 = pe1; Expression e2 = pe2; @@ -3165,6 +3165,9 @@ Lagain: goto Lagain; } +LmergeClassTypes: + /* Merge different type modifiers on classes + */ if (t1.ty == Tclass && t2.ty == Tclass) { if (t1.mod != t2.mod) @@ -3233,9 +3236,23 @@ Lagain: if (t1.ty == Tclass && t2.ty == Tclass) { + /* t1 cannot be converted to t2, and vice versa + */ TypeClass tc1 = t1.isTypeClass(); TypeClass tc2 = t2.isTypeClass(); + //if (tc1.sym.interfaces.length || tc2.sym.interfaces.length) + if (tc1.sym.isInterfaceDeclaration() || + tc2.sym.isInterfaceDeclaration()) + { + ClassDeclaration cd = findClassCommonRoot(tc1.sym, tc2.sym); + if (!cd) + return null; // no common root + t1 = cd.type.castMod(t1.mod); + t2 = cd.type.castMod(t2.mod); + goto LmergeClassTypes; // deal with mod differences + } + /* Pick 'tightest' type */ ClassDeclaration cd1 = tc1.sym.baseClass; @@ -3251,6 +3268,7 @@ Lagain: t2 = cd2.type; else return null; + goto LmergeClassTypes; } else if (t1.ty == Tstruct && t1.isTypeStruct().sym.aliasthis) { @@ -3582,6 +3600,71 @@ LmodCompare: return null; } +/********************************** + * Find common root that both cd1 and cd2 can be implicitly converted to. + * Params: + * cd1 = first class + * cd2 = second class + * Returns: + * common base that both can implicitly convert to, null if none or + * multiple matches + */ +private +ClassDeclaration findClassCommonRoot(ClassDeclaration cd1, ClassDeclaration cd2) +{ + enum log = false; + if (log) printf("findClassCommonRoot(%s, %s)\n", cd1.toChars(), cd2.toChars()); + /* accumulate results in this */ + static struct Root + { + ClassDeclaration cd; + bool error; + + /* merge cd into results */ + void accumulate(ClassDeclaration cd) + { + if (log) printf(" accumulate(r.cd: %s r.error: %d cd: %s)\n", this.cd ? this.cd.toChars() : "null", error, cd ? cd.toChars() : null); + if (this.cd is cd) + { + } + else if (!this.cd) + this.cd = cd; + else + error = true; + } + } + + /* Find common root of cd1 and cd2. Accumulate results in r. depth is nesting level */ + void findCommonRoot(ClassDeclaration cd1, ClassDeclaration cd2, ref Root r) + { + if (log) printf("findCommonRoot(cd1: %s cd2: %s)\n", cd1.toChars(), cd2.toChars()); + /* Warning: quadratic time function + */ + if (cd1 is cd2) + { + r.accumulate(cd1); + return; + } + + foreach (b1; (*cd1.baseclasses)[]) + { + if (b1.sym != r.cd) + findCommonRoot(cd2, b1.sym, r); + } + foreach (b2; (*cd2.baseclasses)[]) + { + if (b2.sym != r.cd) + findCommonRoot(cd1, b2.sym, r); + } + } + + Root r; + findCommonRoot(cd1, cd2, r); + if (!r.cd || r.error) + return null; // no common root + return r.cd; +} + /************************************ * Bring leaves to common type. * Returns: diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d index 93ef63f7aa3..3f9769d7155 100644 --- a/gcc/d/dmd/declaration.d +++ b/gcc/d/dmd/declaration.d @@ -213,7 +213,7 @@ bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1) /****************************************** */ -extern (C++) void ObjectNotFound(Identifier id) +void ObjectNotFound(Identifier id) { error(Loc.initial, "`%s` not found. object.d may be incorrectly installed or corrupt.", id.toChars()); fatal(); @@ -1380,7 +1380,7 @@ extern (C++) class VarDeclaration : Declaration */ final bool needsScopeDtor() { - //printf("VarDeclaration::needsScopeDtor() %s\n", toChars()); + //printf("VarDeclaration::needsScopeDtor() %s %d\n", toChars(), edtor && !(storage_class & STC.nodtor)); return edtor && !(storage_class & STC.nodtor); } diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h index afbb9975cc9..a393da80c09 100644 --- a/gcc/d/dmd/declaration.h +++ b/gcc/d/dmd/declaration.h @@ -107,8 +107,6 @@ bool functionSemantic3(FuncDeclaration* fd); #define STC_TYPECTOR (STCconst | STCimmutable | STCshared | STCwild) #define STC_FUNCATTR (STCref | STCnothrow | STCnogc | STCpure | STCproperty | STCsafe | STCtrusted | STCsystem) -void ObjectNotFound(Identifier *id); - /**************************************************************/ class Declaration : public Dsymbol diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d index b0785424f3c..c3395a584e2 100644 --- a/gcc/d/dmd/dinterpret.d +++ b/gcc/d/dmd/dinterpret.d @@ -50,7 +50,7 @@ import dmd.rootobject; import dmd.root.utf; import dmd.statement; import dmd.tokens; -import dmd.typesem : mutableOf; +import dmd.typesem : mutableOf, equivalent; import dmd.utils : arrayCastBigEndian; import dmd.visitor; diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h index e463d3d9005..db236275570 100644 --- a/gcc/d/dmd/dsymbol.h +++ b/gcc/d/dmd/dsymbol.h @@ -427,7 +427,5 @@ public: void addMember(Dsymbol *dsym, Scope *sc, ScopeDsymbol *sds); Dsymbol *search(Dsymbol *d, const Loc &loc, Identifier *ident, SearchOptFlags flags = (SearchOptFlags)SearchOpt::localsOnly); -bool checkDeprecated(Dsymbol *d, const Loc &loc, Scope *sc); void setScope(Dsymbol *d, Scope *sc); void importAll(Dsymbol *d, Scope *sc); -void setFieldOffset(Dsymbol *d, AggregateDeclaration *ad, FieldState& fieldState, bool isunion); diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index 33a397a87b0..4a4d82ff5c0 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -6907,7 +6907,7 @@ extern(C++) class ImportAllVisitor : Visitor override void visit(StaticForeachDeclaration _) {} } -extern(C++) void setFieldOffset(Dsymbol d, AggregateDeclaration ad, FieldState* fieldState, bool isunion) +void setFieldOffset(Dsymbol d, AggregateDeclaration ad, FieldState* fieldState, bool isunion) { scope v = new SetFieldOffsetVisitor(ad, fieldState, isunion); d.accept(v); diff --git a/gcc/d/dmd/errors.h b/gcc/d/dmd/errors.h index 308e81e30ba..a47b5aada56 100644 --- a/gcc/d/dmd/errors.h +++ b/gcc/d/dmd/errors.h @@ -24,8 +24,6 @@ enum class ErrorKind message = 4, }; -bool isConsoleColorSupported(); - #if defined(__GNUC__) #define D_ATTRIBUTE_FORMAT(m, n) __attribute__((format(printf, m, n))) __attribute__((nonnull (m))) #else diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h index f713d25a739..8dbb4a63c7e 100644 --- a/gcc/d/dmd/expression.h +++ b/gcc/d/dmd/expression.h @@ -46,15 +46,15 @@ typedef union tree_node Symbol; struct Symbol; // back end symbol #endif +// in expressionsem.d +Expression *expressionSemantic(Expression *e, Scope *sc); +// in typesem.d +Expression *defaultInit(Type *mt, const Loc &loc, const bool isCfile = false); + // Entry point for CTFE. // A compile-time result is required. Give an error if not possible Expression *ctfeInterpret(Expression *e); void expandTuples(Expressions *exps, Identifiers *names = nullptr); -StringExp *toUTF8(StringExp *se, Scope *sc); -Expression *resolveLoc(Expression *exp, const Loc &loc, Scope *sc); -MATCH implicitConvTo(Expression *e, Type *t); -Expression *toLvalue(Expression *_this, Scope *sc, const char* action); -Expression *modifiableLvalue(Expression* exp, Scope *sc); Expression *optimize(Expression *exp, int result, bool keepLvalue = false); typedef unsigned char OwnedBy; diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index d7377dbdea8..9028ba1b191 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -2523,7 +2523,7 @@ private bool checkRightThis(Expression e, Scope* sc) return false; } -extern (C++) Expression resolveProperties(Scope* sc, Expression e) +Expression resolveProperties(Scope* sc, Expression e) { //printf("resolveProperties(%s)\n", e.toChars()); e = resolvePropertiesX(sc, e); @@ -3464,12 +3464,12 @@ private bool functionParameters(const ref Loc loc, Scope* sc, eprefix = ae.expressionSemantic(sc); } - for (ptrdiff_t i = 0; i != nargs; i++) + foreach (ptrdiff_t i; 0 .. nargs) { Expression arg = (*arguments)[i]; //printf("arg[%d]: %s\n", cast(int)i, arg.toChars()); - Parameter parameter = (i >= nparams ? null : tf.parameterList[i]); + Parameter parameter = i < nparams ? tf.parameterList[i] : null; const bool isRef = parameter && parameter.isReference(); const bool isLazy = parameter && parameter.isLazy(); @@ -3485,7 +3485,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, * 'eprefix' will therefore finally contain all args up to and including 'lastPrefix', * excluding all lazy parameters. */ - if (needsPrefix && (lastPrefix - i) >= 0) + if (needsPrefix && i <= lastPrefix) { const bool needsDtor = !isRef && arg.type.needsDestruction() && // Problem 3: last throwing arg doesn't require dtor patching @@ -3494,9 +3494,9 @@ private bool functionParameters(const ref Loc loc, Scope* sc, /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor) */ auto tmp = copyToTemp( - (parameter ? parameter.storageClass : tf.parameterList.stc) & (STC.scope_), + (parameter ? parameter.storageClass : tf.parameterList.stc) & (STC.return_ | STC.scope_), needsDtor ? "__pfx" : "__pfy", - !isRef ? arg : arg.addressOf()); + isRef ? arg.addressOf() : arg); tmp.dsymbolSemantic(sc); if (callerDestroysArgs) @@ -3511,15 +3511,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, /* Problem 2: Modify the destructor so it only runs if gate==false, * i.e., only if there was a throw while constructing the args */ - if (!needsDtor) - { - if (tmp.edtor) - { - assert(i == lastPrefix); - tmp.edtor = null; - } - } - else + if (needsDtor) { // edtor => (__gate || edtor) assert(tmp.edtor); @@ -3528,6 +3520,14 @@ private bool functionParameters(const ref Loc loc, Scope* sc, tmp.edtor = e.expressionSemantic(sc); //printf("edtor: %s\n", tmp.edtor.toChars()); } + else + { + if (tmp.edtor) + { + assert(i == lastPrefix); + tmp.edtor = null; + } + } } // eprefix => (eprefix, auto __pfx/y = arg) @@ -15534,7 +15534,7 @@ Expression addDtorHook(Expression e, Scope* sc) * action = for error messages, what the lvalue is needed for (e.g. take address of for `&x`, modify for `x++`) * Returns: converted expression, or `ErrorExp` on error */ -extern(C++) Expression toLvalue(Expression _this, Scope* sc, const(char)* action) +Expression toLvalue(Expression _this, Scope* sc, const(char)* action) { return toLvalueImpl(_this, sc, action, _this); } @@ -15955,7 +15955,7 @@ Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag = ModifyF * sc = scope * Returns: `_this` converted to an lvalue, or an `ErrorExp` */ -extern(C++) Expression modifiableLvalue(Expression _this, Scope* sc) +Expression modifiableLvalue(Expression _this, Scope* sc) { return modifiableLvalueImpl(_this, sc, _this); } diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d index ddf21a2079f..4881ad6c020 100644 --- a/gcc/d/dmd/func.d +++ b/gcc/d/dmd/func.d @@ -60,6 +60,7 @@ import dmd.statement; import dmd.statementsem; import dmd.templatesem; import dmd.tokens; +import dmd.typesem; import dmd.visitor; version (IN_GCC) {} @@ -518,7 +519,6 @@ extern (C++) class FuncDeclaration : Declaration int result = 0; if (fd.ident == ident) { - import dmd.typesem : covariant; const cov = type.covariant(fd.type); if (cov != Covariant.distinct) { @@ -625,7 +625,6 @@ extern (C++) class FuncDeclaration : Declaration */ if (t.ty == Tfunction) { - import dmd.typesem : covariant; auto tf = cast(TypeFunction)f.type; if (tf.covariant(t) == Covariant.yes && tf.nextOf().implicitConvTo(t.nextOf()) >= MATCH.constant) @@ -840,7 +839,6 @@ extern (C++) class FuncDeclaration : Declaration args.push(e); } - import dmd.typesem : callMatch; MATCH m = tg.callMatch(null, ArgumentList(&args, names), 1); if (m > MATCH.nomatch) { @@ -1151,7 +1149,6 @@ extern (C++) class FuncDeclaration : Declaration { //printf("FuncDeclaration::isPure() '%s'\n", toChars()); - import dmd.typesem : purityLevel; TypeFunction tf = type.toTypeFunction(); if (purityInprocess) @@ -1464,7 +1461,6 @@ extern (C++) class FuncDeclaration : Declaration case Tstruct: /* Drill down and check the struct's fields */ - import dmd.typesem : toDsymbol; auto sym = t.toDsymbol(null).isStructDeclaration(); const tName = t.toChars.toDString; const entry = parentTypes.insert(tName, t); @@ -1546,7 +1542,6 @@ extern (C++) class FuncDeclaration : Declaration case Tstruct: /* Drill down and check the struct's fields */ - import dmd.typesem : toDsymbol; auto sym = tp.toDsymbol(null).isStructDeclaration(); foreach (v; sym.fields) { @@ -2411,7 +2406,6 @@ extern (C++) class FuncDeclaration : Declaration { Type t1 = fdv.type.nextOf().toBasetype(); Type t2 = this.type.nextOf().toBasetype(); - import dmd.typesem : isBaseOf; if (t1.isBaseOf(t2, null)) { /* Making temporary reference variable is necessary @@ -3325,7 +3319,6 @@ if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration)) */ Type getIndirection(Type t) { - import dmd.typesem : hasPointers; t = t.baseElemOf(); if (t.ty == Tarray || t.ty == Tpointer) return t.nextOf().toBasetype(); @@ -3372,7 +3365,6 @@ private bool traverseIndirections(Type ta, Type tb) static bool traverse(Type ta, Type tb, ref scope AssocArray!(const(char)*, bool) table, bool reversePass) { - import dmd.typesem : hasPointers; //printf("traverse(%s, %s)\n", ta.toChars(), tb.toChars()); ta = ta.baseElemOf(); tb = tb.baseElemOf(); @@ -3409,7 +3401,6 @@ private bool traverseIndirections(Type ta, Type tb) else *found = true; - import dmd.typesem : toDsymbol; AggregateDeclaration sym = tb.toDsymbol(null).isAggregateDeclaration(); foreach (v; sym.fields) { diff --git a/gcc/d/dmd/hdrgen.h b/gcc/d/dmd/hdrgen.h index e38ca569354..e0a20461d45 100644 --- a/gcc/d/dmd/hdrgen.h +++ b/gcc/d/dmd/hdrgen.h @@ -13,9 +13,17 @@ #include "globals.h" #include "mtype.h" +class Expression; +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); + +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); diff --git a/gcc/d/dmd/init.h b/gcc/d/dmd/init.h index b4e15e3fa98..cccd3c97f2c 100644 --- a/gcc/d/dmd/init.h +++ b/gcc/d/dmd/init.h @@ -125,3 +125,4 @@ public: }; Expression *initializerToExpression(Initializer *init, Type *t = NULL, const bool isCfile = false); +Initializer *initializerSemantic(Initializer *init, Scope *sc, Type *&tx, NeedInterpret needInterpret); diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d index c46f5600c80..4f8ed7594c7 100644 --- a/gcc/d/dmd/mtype.d +++ b/gcc/d/dmd/mtype.d @@ -444,11 +444,6 @@ extern (C++) abstract class Type : ASTNode return false; } - final bool equivalent(Type t) - { - return immutableOf(this).equals(t.immutableOf()); - } - // kludge for template.isType() override final DYNCAST dyncast() const { @@ -1191,111 +1186,6 @@ extern (C++) abstract class Type : ASTNode return t; } - /************************************ - * Add MODxxxx bits to existing type. - * We're adding, not replacing, so adding const to - * a shared type => "shared const" - */ - final Type addMod(MOD mod) - { - /* Add anything to immutable, and it remains immutable - */ - Type t = this; - if (!t.isImmutable()) - { - //printf("addMod(%x) %s\n", mod, toChars()); - switch (mod) - { - case 0: - break; - - case MODFlags.const_: - if (isShared()) - { - if (isWild()) - t = this.sharedWildConstOf(); - else - t = this.sharedConstOf(); - } - else - { - if (this.isWild()) - t = this.wildConstOf(); - else - t = t.constOf(); - } - break; - - case MODFlags.wild: - if (isShared()) - { - if (isConst()) - t = this.sharedWildConstOf(); - else - t = this.sharedWildOf(); - } - else - { - if (isConst()) - t = this.wildConstOf(); - else - t = this.wildOf(); - } - break; - - case MODFlags.wildconst: - if (isShared()) - t = this.sharedWildConstOf(); - else - t = this.wildConstOf(); - break; - - case MODFlags.shared_: - if (isWild()) - { - if (isConst()) - t = this.sharedWildConstOf(); - else - t = this.sharedWildOf(); - } - else - { - if (isConst()) - t = this.sharedConstOf(); - else - t = this.sharedOf(); - } - break; - - case MODFlags.shared_ | MODFlags.const_: - if (isWild()) - t = this.sharedWildConstOf(); - else - t = this.sharedConstOf(); - break; - - case MODFlags.shared_ | MODFlags.wild: - if (isConst()) - t = this.sharedWildConstOf(); - else - t = this.sharedWildOf(); - break; - - case MODFlags.shared_ | MODFlags.wildconst: - t = this.sharedWildConstOf(); - break; - - case MODFlags.immutable_: - t = this.immutableOf(); - break; - - default: - assert(0); - } - } - return t; - } - /************************************ * Add storage class modifiers to type. */ @@ -1315,7 +1205,7 @@ extern (C++) abstract class Type : ASTNode if (stc & STC.shared_) mod |= MODFlags.shared_; } - return addMod(mod); + return this.addMod(mod); } final Type pointerTo() diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h index a7a41c64042..df8cc4dd6b6 100644 --- a/gcc/d/dmd/mtype.h +++ b/gcc/d/dmd/mtype.h @@ -39,7 +39,6 @@ typedef union tree_node type; typedef struct TYPE type; #endif -extern const char* toChars(const Type* const t); Type *typeSemantic(Type *t, const Loc &loc, Scope *sc); Type *merge(Type *type); @@ -218,7 +217,6 @@ public: Type *copy() const; virtual Type *syntaxCopy(); bool equals(const RootObject * const o) const override; - bool equivalent(Type *t); // kludge for template.isType() DYNCAST dyncast() const override final { return DYNCAST_TYPE; } size_t getUniqueID() const; @@ -253,7 +251,6 @@ public: bool isSharedWild() const { return (mod & (MODshared | MODwild)) == (MODshared | MODwild); } bool isNaked() const { return mod == 0; } Type *nullAttributes() const; - Type *addMod(MOD mod); virtual Type *addStorageClass(StorageClass stc); Type *pointerTo(); Type *referenceTo(); @@ -889,10 +886,10 @@ 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); -void purityLevel(TypeFunction *type); Type *merge2(Type *type); Type *constOf(Type *type); Type *immutableOf(Type *type); @@ -905,3 +902,4 @@ Type *wildConstOf(Type *type); Type *sharedWildOf(Type *type); Type *sharedWildConstOf(Type *type); Type *castMod(Type *type, MOD mod); +Type *addMod(Type *type, MOD mod); diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d index 0dc54ffe762..2d2e6fde323 100644 --- a/gcc/d/dmd/parse.d +++ b/gcc/d/dmd/parse.d @@ -8730,7 +8730,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer else { AST.Type t = parseType(); // cast( type ) - t = t.addMod(m); // cast( const type ) + t = t.addSTC(AST.ModToStc(m)); // cast( const type ) check(TOK.rightParenthesis); e = parseUnaryExp(); e = new AST.CastExp(loc, e, t); diff --git a/gcc/d/dmd/statement.h b/gcc/d/dmd/statement.h index ee03d49eb4a..8a6bf3d0d1c 100644 --- a/gcc/d/dmd/statement.h +++ b/gcc/d/dmd/statement.h @@ -701,7 +701,12 @@ 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); class AsmStatement : public Statement { diff --git a/gcc/d/dmd/template.h b/gcc/d/dmd/template.h index 153eb4eb68b..c80f28bf807 100644 --- a/gcc/d/dmd/template.h +++ b/gcc/d/dmd/template.h @@ -317,6 +317,9 @@ public: void accept(Visitor *v) override { v->visit(this); } }; +// in templateparamsem.d +bool tpsemantic(TemplateParameter *tp, Scope *sc, TemplateParameters *parameters); + Expression *isExpression(RootObject *o); Dsymbol *isDsymbol(RootObject *o); Type *isType(RootObject *o); diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d index b1ca92da4cb..19c6912eeaf 100644 --- a/gcc/d/dmd/typesem.d +++ b/gcc/d/dmd/typesem.d @@ -520,7 +520,7 @@ int mutabilityOfType(bool isref, Type t) * Set 'purity' field of 'typeFunction'. * Do this lazily, as the parameter types might be forward referenced. */ -extern(C++) void purityLevel(TypeFunction typeFunction) +void purityLevel(TypeFunction typeFunction) { TypeFunction tf = typeFunction; if (tf.purity != PURE.fwdref) @@ -6106,6 +6106,11 @@ extern(C++) bool isBaseOf(Type tthis, Type t, int* poffset) return false; } +extern(C++) bool equivalent(Type src, Type t) +{ + return immutableOf(src).equals(t.immutableOf()); +} + /******************************** * Convert to 'const'. */ @@ -6405,6 +6410,111 @@ extern(C++) Type castMod(Type type, MOD mod) return t; } +/************************************ + * Add MODxxxx bits to existing type. + * We're adding, not replacing, so adding const to + * a shared type => "shared const" + */ +extern(C++) Type addMod(Type type, MOD mod) +{ + /* Add anything to immutable, and it remains immutable + */ + Type t = type; + if (!t.isImmutable()) + { + //printf("addMod(%x) %s\n", mod, toChars()); + switch (mod) + { + case 0: + break; + + case MODFlags.const_: + if (type.isShared()) + { + if (type.isWild()) + t = type.sharedWildConstOf(); + else + t = type.sharedConstOf(); + } + else + { + if (type.isWild()) + t = type.wildConstOf(); + else + t = t.constOf(); + } + break; + + case MODFlags.wild: + if (type.isShared()) + { + if (type.isConst()) + t = type.sharedWildConstOf(); + else + t = type.sharedWildOf(); + } + else + { + if (type.isConst()) + t = type.wildConstOf(); + else + t = type.wildOf(); + } + break; + + case MODFlags.wildconst: + if (type.isShared()) + t = type.sharedWildConstOf(); + else + t = type.wildConstOf(); + break; + + case MODFlags.shared_: + if (type.isWild()) + { + if (type.isConst()) + t = type.sharedWildConstOf(); + else + t = type.sharedWildOf(); + } + else + { + if (type.isConst()) + t = type.sharedConstOf(); + else + t = type.sharedOf(); + } + break; + + case MODFlags.shared_ | MODFlags.const_: + if (type.isWild()) + t = type.sharedWildConstOf(); + else + t = type.sharedConstOf(); + break; + + case MODFlags.shared_ | MODFlags.wild: + if (type.isConst()) + t = type.sharedWildConstOf(); + else + t = type.sharedWildOf(); + break; + + case MODFlags.shared_ | MODFlags.wildconst: + t = type.sharedWildConstOf(); + break; + + case MODFlags.immutable_: + t = type.immutableOf(); + break; + + default: + assert(0); + } + } + return t; +} + /******************************* Private *****************************************/ private: diff --git a/gcc/d/types.cc b/gcc/d/types.cc index 4e14b158bea..af9aad8a412 100644 --- a/gcc/d/types.cc +++ b/gcc/d/types.cc @@ -144,7 +144,7 @@ same_type_p (Type *t1, Type *t2) return true; /* Types are mutably the same type. */ - if (tb1->ty == tb2->ty && tb1->equivalent (tb2)) + if (tb1->ty == tb2->ty && equivalent (tb1, tb2)) return true; return false; diff --git a/gcc/testsuite/gdc.test/compilable/commontype.d b/gcc/testsuite/gdc.test/compilable/commontype.d index a980ace2177..c12506f2939 100644 --- a/gcc/testsuite/gdc.test/compilable/commontype.d +++ b/gcc/testsuite/gdc.test/compilable/commontype.d @@ -413,12 +413,12 @@ static assert(is( X!( C, immutable(B) ) == const(B) )); static assert(is( X!( C, immutable(D) ) == const(B) )); static assert(is( X!( C, immutable(K) ) == const(Object) )); -static assert(Error!( C, immutable(SC) )); // should work -static assert(Error!( C, immutable(SI) )); // should work -static assert(Error!( immutable(SI), C )); // should work -static assert(Error!( C, immutable(SB) )); // should work -static assert(Error!( C, immutable(SD) )); // should work -static assert(Error!( C, immutable(SK) )); // should work +static assert(is( X!( C, immutable(SC)) == const(B) )); +static assert(is( X!( C, immutable(SI) ) == const(I) )); +static assert(is( X!( immutable(SI), C ) == const(I) )); +static assert(is( X!( C, immutable(SB) ) == const(Object) )); +static assert(is( X!( C, immutable(SD) ) == const(B) )); +static assert(is( X!( C, immutable(SK) ) == const(Object) )); static assert(is( X!( const(C), C ) == const(C) )); static assert(is( X!( const(C), I ) == const(I) )); @@ -427,11 +427,11 @@ static assert(is( X!( const(C), D ) == const(B) )); static assert(is( X!( const(C), K ) == const(Object) )); static assert(is( X!( const(C), SC ) == const(C))); -static assert(Error!( const(C), SI )); // should work -static assert(is( X!( const(SI), const(C) ) == const(I) )); // should work -static assert(is( X!( const(C), SB ) == const(B))); +static assert(is( X!( const(C), SI ) == const(I))); +static assert(is( X!( const(SI), const(C) ) == const(I) )); +static assert(is( X!( const(C), SB ) == const(Object))); static assert(is( X!( const(C), SD ) == const(B))); -static assert(is( X!( const(C), SK ) == Object)); // `const` +static assert(is( X!( const(C), SK ) == const(Object))); static assert(is( X!( SiC, SC ) == const(C) )); diff --git a/gcc/testsuite/gdc.test/compilable/test3543.d b/gcc/testsuite/gdc.test/compilable/test3543.d new file mode 100644 index 00000000000..9a72ca9dda5 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test3543.d @@ -0,0 +1,80 @@ + +// https://issues.dlang.org/show_bug.cgi?id=3543 + +// merge with commontype.d? + +void testi(bool bla) +{ + interface Root { } + interface A : Root { } + interface B : Root { } + A a; + B b; + Root r = bla ? a : b; + static assert(is(typeof(r) == Root)); + Root[] t = [a, b]; + static assert(is(typeof(t[0]) == Root)); +} + +void testc(bool bla) +{ + class Root { } + class A : Root { } + class B : Root { } + A a; + B b; + Root r = bla ? a : b; + static assert(is(typeof(r) == Root)); + Root[] t = [a, b]; + static assert(is(typeof(t[0]) == Root)); +} + +void teste(bool bla) +{ + interface Root { } + interface Othe { } + interface A : Root, Othe { } + interface B : Root, Othe { } + A a; + B b; + static assert(!__traits(compiles, bla ? a : b)); +} + +void testf(bool bla) +{ + interface Othe { } + interface Root : Othe { } + interface A : Root { } + interface B : Othe { } + A a; + B b; + Othe r = bla ? a : b; +} + +void testg() +{ + interface A{} + interface B{} + + interface C:A{} + interface D:B,C{} + + interface E:B{} + interface F:A,E{} + + D d; + F f; + static assert(!__traits(compiles, true ? d : f)); + static assert(!__traits(compiles, true ? f : d)); +} + +void testh() +{ + interface I {} + class B {} + class C : B, I {} + class D : B {} + C c; + D d; + auto b = true ? c : d; +} diff --git a/gcc/testsuite/gdc.test/runnable/mangle.d b/gcc/testsuite/gdc.test/runnable/mangle.d index 6e8f2b28987..53d76480997 100644 --- a/gcc/testsuite/gdc.test/runnable/mangle.d +++ b/gcc/testsuite/gdc.test/runnable/mangle.d @@ -1,6 +1,7 @@ // PERMUTE_ARGS: // EXTRA_SOURCES: imports/mangle10077.d // EXTRA_FILES: imports/testmangle.d +// UNICODE_NAMES: /* TEST_OUTPUT: --- diff --git a/gcc/testsuite/gdc.test/runnable/testmodule.d b/gcc/testsuite/gdc.test/runnable/testmodule.d index 45da7d1659d..4e1068c8938 100644 --- a/gcc/testsuite/gdc.test/runnable/testmodule.d +++ b/gcc/testsuite/gdc.test/runnable/testmodule.d @@ -1,4 +1,5 @@ // PERMUTE_ARGS: +// UNICODE_NAMES: // $HeadURL$ // $Date$ @@ -11,6 +12,7 @@ module run.unicode_06_哪里; +//UTF-8 chars int 哪里(int ö){ return ö+2; } diff --git a/gcc/testsuite/gdc.test/runnable/ufcs.d b/gcc/testsuite/gdc.test/runnable/ufcs.d index 8fd7bb2fba2..6328a5b380c 100644 --- a/gcc/testsuite/gdc.test/runnable/ufcs.d +++ b/gcc/testsuite/gdc.test/runnable/ufcs.d @@ -1,4 +1,5 @@ // EXTRA_SOURCES: imports/ufcs5a.d imports/ufcs5b.d imports/ufcs5c.d imports/ufcs5d.d imports/ufcs5e.d +// UNICODE_NAMES: module ufcs; @@ -677,6 +678,7 @@ void test8453() /*******************************************/ // https://issues.dlang.org/show_bug.cgi?id=8503 +//UTF-8 chars void α8503(int i) {} void test8503() diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE index 57ac2dc69e7..74c194508f7 100644 --- a/libphobos/libdruntime/MERGE +++ b/libphobos/libdruntime/MERGE @@ -1,4 +1,4 @@ -a6f10836997d0b5526c8c363d781b4029c77f09f +11240a96635074b2f79d908b9348e9c0fbc3c7dc The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/libphobos/libdruntime/core/demangle.d b/libphobos/libdruntime/core/demangle.d index 5a6ad6f5cf5..272ee1e1ba4 100644 --- a/libphobos/libdruntime/core/demangle.d +++ b/libphobos/libdruntime/core/demangle.d @@ -79,17 +79,6 @@ pure @safe: AddType addType = AddType.yes; bool mute = false; Hooks hooks; - bool hasErrors = false; - - /// Called when encountering an error / unrecognized mangle. - /// - /// Currently, errors simply make `demangle` return - /// the input string, but the `msg` string can be used for debugging. - /// As a future enhancement, error handlers can be supplied through `Hooks` - void error(string msg = "error") - { - hasErrors = true; - } ////////////////////////////////////////////////////////////////////////// // Type Testing and Conversion @@ -733,7 +722,7 @@ pure @safe: TypeTuple: B Number Arguments */ - BufSlice parseType() return scope nothrow + BufSlice parseType(out bool errStatus) return scope nothrow { static immutable string[23] primitives = [ "char", // a @@ -763,8 +752,8 @@ pure @safe: static if (__traits(hasMember, Hooks, "parseType")) { - auto n = hooks.parseType(this, null); - if (this.hasErrors) + auto n = hooks.parseType(errStatus, this, null); + if (errStatus) return dst.bslice_empty; else if (n !is null) @@ -776,11 +765,11 @@ pure @safe: auto beg = dst.length; auto t = front; - BufSlice parseBackrefType(scope BufSlice delegate() pure @safe nothrow parseDg) pure @safe nothrow + BufSlice parseBackrefType(out string errStatus, scope BufSlice delegate(bool err_flag) pure @safe nothrow parseDg) pure @safe nothrow { if (pos == brp) { - this.error("recursive back reference"); + errStatus = "recursive back reference"; return dst.bslice_empty; } @@ -789,7 +778,7 @@ pure @safe: auto n = decodeBackref(); if (n == 0 || n > pos) { - this.error("invalid back reference"); + errStatus = "invalid back reference"; return dst.bslice_empty; } @@ -801,31 +790,44 @@ pure @safe: pos = refPos - n; brp = refPos; - auto ret = parseDg(); + bool err_flag; + auto ret = parseDg(err_flag); + if (err_flag) + { + errStatus = "parseDg error"; + return dst.bslice_empty; + } + return ret; } + // call parseType() and return error if occured + enum parseTypeOrF = "parseType(errStatus); if (errStatus) return dst.bslice_empty;"; + switch ( t ) { case 'Q': // Type back reference - auto r = parseBackrefType(() => parseType()); + string errMsg; + auto r = parseBackrefType(errMsg, (e_flag) => parseType(e_flag)); + if (errMsg !is null) + return dst.bslice_empty; return r; case 'O': // Shared (O Type) popFront(); put( "shared(" ); - parseType(); + mixin(parseTypeOrF); put( ')' ); return dst[beg .. $]; case 'x': // Const (x Type) popFront(); put( "const(" ); - parseType(); + mixin(parseTypeOrF); put( ')' ); return dst[beg .. $]; case 'y': // Immutable (y Type) popFront(); put( "immutable(" ); - parseType(); + mixin(parseTypeOrF); put( ')' ); return dst[beg .. $]; case 'N': @@ -840,28 +842,28 @@ pure @safe: popFront(); // TODO: Anything needed here? put( "inout(" ); - parseType(); + mixin(parseTypeOrF); put( ')' ); return dst[beg .. $]; case 'h': // TypeVector (Nh Type) popFront(); put( "__vector(" ); - parseType(); + mixin(parseTypeOrF); put( ')' ); return dst[beg .. $]; default: - error(); + errStatus = true; return dst.bslice_empty; } case 'A': // TypeArray (A Type) popFront(); - parseType(); + mixin(parseTypeOrF); put( "[]" ); return dst[beg .. $]; case 'G': // TypeStaticArray (G Number Type) popFront(); auto num = sliceNumber(); - parseType(); + mixin(parseTypeOrF); put( '[' ); put( num ); put( ']' ); @@ -869,34 +871,29 @@ pure @safe: case 'H': // TypeAssocArray (H Type Type) popFront(); // skip t1 - auto tx = parseType(); - if (this.hasErrors) + auto tx = parseType(errStatus); + if (errStatus) return dst.bslice_empty; - parseType(); + mixin(parseTypeOrF); put( '[' ); shift(tx); put( ']' ); return dst[beg .. $]; case 'P': // TypePointer (P Type) popFront(); - parseType(); + mixin(parseTypeOrF); put( '*' ); return dst[beg .. $]; case 'F': case 'U': case 'W': case 'V': case 'R': // TypeFunction - bool errStatus; auto r = parseTypeFunction(errStatus); if (errStatus) - { - error(); return dst.bslice_empty; - } return r; case 'C': // TypeClass (C LName) case 'S': // TypeStruct (S LName) case 'E': // TypeEnum (E LName) case 'T': // TypeTypedef (T LName) popFront(); - bool errStatus; parseQualifiedName(errStatus); if (errStatus) return dst.bslice_empty; @@ -906,20 +903,16 @@ pure @safe: auto modifiers = parseModifier(); if ( front == 'Q' ) { - bool errStatus; - auto r = parseBackrefType(() => parseTypeFunction(errStatus, IsDelegate.yes)); - if (errStatus) - { - error(); + string errMsg; + auto r = parseBackrefType(errMsg, (e_flag) => parseTypeFunction(e_flag, IsDelegate.yes)); + if (errMsg !is null) return dst.bslice_empty; - } return r; } else { - bool errStatus; parseTypeFunction(errStatus, IsDelegate.yes); - if (this.hasErrors || errStatus) + if (errStatus) return dst.bslice_empty; } @@ -972,11 +965,11 @@ pure @safe: put( "ucent" ); return dst[beg .. $]; default: - error("unknown type"); + errStatus = true; return dst.bslice_empty; } } - error("unknown type"); + errStatus = true; return dst.bslice_empty; } } @@ -1289,6 +1282,9 @@ pure @safe: pos--; } + // call parseType() and return error if occured + enum parseTypeOrF = "parseType(errStatus); if (errStatus) return;"; + switch ( front ) { case 'I': // in (I Type) @@ -1296,25 +1292,25 @@ pure @safe: put("in "); if (front == 'K') goto case; - parseType(); + mixin(parseTypeOrF); continue; case 'K': // ref (K Type) popFront(); put( "ref " ); - parseType(); + mixin(parseTypeOrF); continue; case 'J': // out (J Type) popFront(); put( "out " ); - parseType(); + mixin(parseTypeOrF); continue; case 'L': // lazy (L Type) popFront(); put( "lazy " ); - parseType(); + mixin(parseTypeOrF); continue; default: - parseType(); + mixin(parseTypeOrF); } } } @@ -1361,8 +1357,8 @@ pure @safe: // e.g. `delegate(int) @safedouble ' => 'double delegate(int) @safe' { auto retbeg = dst.length; - parseType(); - if (this.hasErrors) + parseType(errStatus); + if (errStatus) return dst.bslice_empty; put(' '); shift(dst[argbeg .. retbeg]); @@ -1576,9 +1572,7 @@ pure @safe: // f MangledName // A function literal symbol popFront(); - parseMangledName(false, 1); - if (this.hasErrors) - errStatus = true; + parseMangledName(errStatus, false, 1); return; default: errStatus = true; @@ -1716,12 +1710,9 @@ pure @safe: case 'T': popFront(); putComma(n); - parseType(); - if (this.hasErrors) - { - errStatus = true; + parseType(errStatus); + if (errStatus) return; - } continue; case 'V': popFront(); @@ -1742,7 +1733,7 @@ pure @safe: } } BufSlice name = dst.bslice_empty; - silent( errStatus, delegate void(out bool e_flg) nothrow { name = parseType(); } ); + silent( errStatus, delegate void(out bool e_flg) nothrow { name = parseType(e_flg); } ); if (errStatus) return; parseValue( errStatus, name, t ); @@ -1857,20 +1848,20 @@ pure @safe: debug(trace) printf( "parseMangledNameArg+\n" ); debug(trace) scope(success) printf( "parseMangledNameArg-\n" ); + bool errStatus; + size_t n = 0; if ( isDigit( front ) ) { - bool errStatus; n = decodeNumber(errStatus); + if (errStatus) - { - error(); return false; - } } - parseMangledName(false, n); - return !this.hasErrors; + parseMangledName(errStatus, false, n ); + + return !errStatus; } /* @@ -2091,7 +2082,7 @@ pure @safe: _D QualifiedName Type _D QualifiedName M Type */ - void parseMangledName(bool displayType, size_t n = 0 ) scope nothrow + void parseMangledName( out bool errStatus, bool displayType, size_t n = 0 ) scope nothrow { debug(trace) printf( "parseMangledName+\n" ); debug(trace) scope(success) printf( "parseMangledName-\n" ); @@ -2100,8 +2091,9 @@ pure @safe: auto end = pos + n; eat( '_' ); - if (!match('D')) - return error(); + errStatus = !match( 'D' ); + if (errStatus) + return; do { @@ -2117,17 +2109,16 @@ pure @safe: if (beg != dst.length) put( '.' ); - bool errStatus; parseSymbolName(errStatus); if (errStatus) - return error(); + return; nameEnd = dst.length; attr = parseFunctionTypeNoReturn( displayType ); is_sym_name_front = isSymbolNameFront(errStatus); if (errStatus) - return error(); + return; } while (is_sym_name_front); if ( displayType ) @@ -2142,8 +2133,8 @@ pure @safe: popFront(); // has 'this' pointer auto lastlen = dst.length; - auto type = parseType(); - if (this.hasErrors) + auto type = parseType(errStatus); + if (errStatus) return; if ( displayType ) @@ -2176,9 +2167,9 @@ pure @safe: } while ( true ); } - void parseMangledName() nothrow + void parseMangledName(out bool errStatus) nothrow { - parseMangledName(AddType.yes == addType); + parseMangledName(errStatus, AddType.yes == addType); } char[] doDemangle(alias FUNC)() return scope nothrow @@ -2187,8 +2178,9 @@ pure @safe: { debug(info) printf( "demangle(%.*s)\n", cast(int) buf.length, buf.ptr ); - FUNC(); - if (!this.hasErrors) + bool errStatus; + FUNC(errStatus); + if (!errStatus) { return dst[0 .. $].getSlice; } @@ -2387,9 +2379,8 @@ char[] reencodeMangled(return scope const(char)[] mangled) nothrow pure @safe return true; } - char[] parseType(ref Remangle d, char[] name) return scope nothrow + char[] parseType( out bool errStatus, ref Remangle d, char[] name ) return scope nothrow { - bool errStatus; if (d.front != 'Q') return null; @@ -2400,7 +2391,8 @@ char[] reencodeMangled(return scope const(char)[] mangled) nothrow pure @safe auto n = d.decodeBackref(); if (n == 0 || n > refPos) { - d.error("invalid back reference"); + // invalid back reference + errStatus = true; return null; } @@ -2436,7 +2428,7 @@ char[] reencodeMangled(return scope const(char)[] mangled) nothrow pure @safe bool errStatus; d.parseMangledName(errStatus); - if (d.hasErrors) + if (errStatus) { // error cannot occur return mangled.dup; diff --git a/libphobos/libdruntime/core/internal/atomic.d b/libphobos/libdruntime/core/internal/atomic.d index 03d1c017c07..6242d76ba30 100644 --- a/libphobos/libdruntime/core/internal/atomic.d +++ b/libphobos/libdruntime/core/internal/atomic.d @@ -609,7 +609,7 @@ else version (GNU) import gcc.builtins; import gcc.config; - enum IsAtomicLockFree(T) = __atomic_is_lock_free(T.sizeof, null); + enum IsAtomicLockFree(T) = __traits(compiles, { enum E = __atomic_is_lock_free(T.sizeof, null); }); inout(T) atomicLoad(MemoryOrder order = MemoryOrder.seq, T)(inout(T)* src) pure nothrow @nogc @trusted if (CanCAS!T) diff --git a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d index 73fe087861a..56433b49302 100644 --- a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d +++ b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d @@ -4941,6 +4941,7 @@ unittest // improve predictability of coverage of code that is eventually not hit by other tests debug (SENTINEL) {} else // cannot extend with SENTINEL debug (MARK_PRINTF) {} else // takes forever +version (OnlyLowMemUnittests) {} else unittest { import core.memory; @@ -4988,24 +4989,34 @@ version (D_LP64) unittest { // only run if the system has enough physical memory size_t sz = 2L^^32; - //import core.stdc.stdio; - //printf("availphys = %lld", os_physical_mem(true)); - if (os_physical_mem(true) > sz) + size_t phys_mem = os_physical_mem(true); + if (phys_mem > sz) { import core.memory; + import core.exception; GC.collect(); GC.minimize(); - auto stats = GC.stats(); - auto ptr = GC.malloc(sz, BlkAttr.NO_SCAN); - auto info = GC.query(ptr); - //printf("info.size = %lld", info.size); - assert(info.size >= sz); - GC.free(ptr); - GC.minimize(); - auto nstats = GC.stats(); - assert(nstats.usedSize == stats.usedSize); - assert(nstats.freeSize == stats.freeSize); - assert(nstats.allocatedInCurrentThread - sz == stats.allocatedInCurrentThread); + try + { + auto stats = GC.stats(); + auto ptr = GC.malloc(sz, BlkAttr.NO_SCAN); + auto info = GC.query(ptr); + //printf("info.size = %lld", info.size); + assert(info.size >= sz); + GC.free(ptr); + GC.minimize(); + auto nstats = GC.stats(); + assert(nstats.usedSize == stats.usedSize); + assert(nstats.freeSize == stats.freeSize); + assert(nstats.allocatedInCurrentThread - sz == stats.allocatedInCurrentThread); + } + catch (OutOfMemoryError) + { + // ignore if the system still doesn't have enough virtual memory + import core.stdc.stdio; + printf("%s(%d): out-of-memory execption ignored, phys_mem = %zd", + __FILE__.ptr, __LINE__, phys_mem); + } } } } diff --git a/libphobos/libdruntime/core/internal/qsort.d b/libphobos/libdruntime/core/internal/qsort.d index ad8307a2523..ada914c9ef4 100644 --- a/libphobos/libdruntime/core/internal/qsort.d +++ b/libphobos/libdruntime/core/internal/qsort.d @@ -132,6 +132,7 @@ else unittest { + debug(qsort) import core.stdc.stdio; debug(qsort) printf("array.sort.unittest()\n"); int[] a = new int[10]; @@ -151,8 +152,8 @@ unittest for (int i = 0; i < a.length - 1; i++) { - //printf("i = %d", i); - //printf(" %d %d\n", a[i], a[i + 1]); + debug(qsort) printf("i = %d", i); + debug(qsort) printf(" %d %d\n", a[i], a[i + 1]); assert(a[i] <= a[i + 1]); } } diff --git a/libphobos/libdruntime/core/memory.d b/libphobos/libdruntime/core/memory.d index f2a48f9a3ae..239d23ff01d 100644 --- a/libphobos/libdruntime/core/memory.d +++ b/libphobos/libdruntime/core/memory.d @@ -575,6 +575,7 @@ extern(C): // https://issues.dlang.org/show_bug.cgi?id=13111 /// + version (OnlyLowMemUnittests) {} else // Test needs a lot of RAM unittest { enum size1 = 1 << 11 + 1; // page in large object pool diff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d index 93902439fbf..295ca52e350 100644 --- a/libphobos/libdruntime/core/thread/osthread.d +++ b/libphobos/libdruntime/core/thread/osthread.d @@ -2103,6 +2103,8 @@ private extern (D) void resume(ThreadBase _t) nothrow @nogc t.m_curr.tstack = t.m_curr.bstack; } } + else + static assert(false, "Platform not supported."); } diff --git a/libphobos/libdruntime/core/time.d b/libphobos/libdruntime/core/time.d index be941e2abcd..c3192fc39f9 100644 --- a/libphobos/libdruntime/core/time.d +++ b/libphobos/libdruntime/core/time.d @@ -2584,6 +2584,8 @@ extern(C) void _d_initMonoTime() @nogc nothrow } } } + else + static assert(0, "Unsupported platform"); } @@ -2883,6 +2885,8 @@ deprecated: else ticksPerSec = 1_000_000; } + else + static assert(0, "Unsupported platform"); if (ticksPerSec != 0) appOrigin = TickDuration.currSystemTick; diff --git a/libphobos/libdruntime/rt/aaA.d b/libphobos/libdruntime/rt/aaA.d index 36f25554db3..5903d9cd754 100644 --- a/libphobos/libdruntime/rt/aaA.d +++ b/libphobos/libdruntime/rt/aaA.d @@ -437,6 +437,7 @@ unittest string[412] names; ubyte[1024] moredata; } + version (OnlyLowMemUnittests) {} else test!(Large, Large); } diff --git a/libphobos/libdruntime/rt/lifetime.d b/libphobos/libdruntime/rt/lifetime.d index 8ce2d564bd6..4a071f3d81b 100644 --- a/libphobos/libdruntime/rt/lifetime.d +++ b/libphobos/libdruntime/rt/lifetime.d @@ -2247,6 +2247,7 @@ unittest assert(GC.getAttr(p) == BlkAttr.NO_SCAN); } test(16); + version (OnlyLowMemUnittests) {} else test(1024 * 1024); }