diff --git a/CHANGELOG.md b/CHANGELOG.md index 406b415215c..5aa179ef660 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # LDC master #### Big news -- Frontend, druntime and Phobos are at version [2.106.0](https://dlang.org/changelog/2.106.0.html). (#4522) +- Frontend, druntime and Phobos are at version [2.106.0](https://dlang.org/changelog/2.106.0.html). (#4522, #4539) - New command-line options `-fno-{exceptions,moduleinfo,rtti}` to selectively enable some `-betterC` effects. (#4522) - New command-line option `-fprofile-sample-use` for using sample-based profile data for optimization. Functionality and usage is identical to Clang's option with same name. (#4531) - New `ldc-profgen` tool for sample-based PGO, a copy of LLVM's [llvm-profgen](https://llvm.org/docs/CommandGuide/llvm-profgen.html). (#4536) diff --git a/dmd/dcast.d b/dmd/dcast.d index f769473f591..8ab71fb8582 100644 --- a/dmd/dcast.d +++ b/dmd/dcast.d @@ -1630,6 +1630,13 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null) } else if (tob.ty == Tvector && t1b.ty != Tvector) { + if (t1b.ty == Tsarray) + { + // Casting static array to vector with same size, e.g. `cast(int4) int[4]` + if (t1b.size(e.loc) != tob.size(e.loc)) + goto Lfail; + return new VectorExp(e.loc, e, tob).expressionSemantic(sc); + } //printf("test1 e = %s, e.type = %s, tob = %s\n", e.toChars(), e.type.toChars(), tob.toChars()); TypeVector tv = tob.isTypeVector(); Expression result = new CastExp(e.loc, e, tv.elementType()); diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 95546d53606..c5dd7382e44 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -5981,7 +5981,7 @@ private bool isDRuntimeHook(Identifier id) id == Id._d_arraysetlengthTImpl || id == Id._d_arraysetlengthT || id == Id._d_arraysetlengthTTrace || id == Id._d_arrayappendT || id == Id._d_arrayappendTTrace || - id == Id._d_arrayappendcTXImpl; + id == Id._d_arrayappendcTX; } void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList argumentList) diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 3aa67e02770..439d424e95a 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -7549,7 +7549,12 @@ version (IN_LLVM) } //printf("\t-. mi = %s\n", mi.toPrettyChars()); - assert(!memberOf || (!memberOf.isRoot() && mi.isRoot()), "can only re-append from non-root to root module"); + if (memberOf) // already appended to some module + { + assert(mi.isRoot(), "can only re-append to a root module"); + if (memberOf.isRoot()) + return null; // no need to move to another root module + } Dsymbols* a = mi.members; a.push(this); diff --git a/dmd/expression.d b/dmd/expression.d index 02f03928cfc..033094707a6 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -5666,7 +5666,9 @@ extern (C++) final class UshrAssignExp : BinAssignExp */ extern (C++) class CatAssignExp : BinAssignExp { - extern (D) this(const ref Loc loc, Expression e1, Expression e2) @safe + Expression lowering; // lowered druntime hook `_d_arrayappend{cTX,T}` + + extern (D) this(const ref Loc loc, Expression e1, Expression e2) { super(loc, EXP.concatenateAssign, e1, e2); } diff --git a/dmd/expression.h b/dmd/expression.h index 208c4b8c619..ffabf0d08ba 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -1204,6 +1204,8 @@ class UshrAssignExp final : public BinAssignExp class CatAssignExp : public BinAssignExp { public: + Expression *lowering; // lowered druntime hook `_d_arrayappend{cTX,T}` + void accept(Visitor *v) override { v->visit(this); } }; diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index f037d4ecbde..2c6d588b802 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -8505,14 +8505,6 @@ version (IN_LLVM) return setError(); } - // Look for casting to a vector type - if (tob.ty == Tvector && t1b.ty != Tvector) - { - result = new VectorExp(exp.loc, exp.e1, exp.to); - result = result.expressionSemantic(sc); - return; - } - Expression ex = exp.e1.castTo(sc, exp.to); if (ex.op == EXP.error) { @@ -11215,8 +11207,7 @@ version (IN_LLVM) result = res; - if ((exp.op == EXP.concatenateAssign || exp.op == EXP.concatenateElemAssign) && - sc.needsCodegen()) + if ((exp.op == EXP.concatenateAssign || exp.op == EXP.concatenateElemAssign) && sc.needsCodegen()) { // if aa ordering is triggered, `res` will be a CommaExp // and `.e2` will be the rewritten original expression. @@ -11260,7 +11251,9 @@ version (IN_LLVM) arguments.push(exp.e1); arguments.push(exp.e2); Expression ce = new CallExp(exp.loc, id, arguments); - *output = ce.expressionSemantic(sc); + + exp.lowering = ce.expressionSemantic(sc); + *output = exp; } else if (exp.op == EXP.concatenateElemAssign) { @@ -11280,15 +11273,12 @@ version (IN_LLVM) } Identifier hook = global.params.tracegc ? Id._d_arrayappendcTXTrace : Id._d_arrayappendcTX; - if (!verifyHookExist(exp.loc, *sc, Id._d_arrayappendcTXImpl, "appending element to arrays", Id.object)) + if (!verifyHookExist(exp.loc, *sc, hook, "appending element to arrays", Id.object)) return setError(); - // Lower to object._d_arrayappendcTXImpl!(typeof(e1))._d_arrayappendcTX{,Trace}(e1, 1), e1[$-1]=e2 + // Lower to object._d_arrayappendcTX{,Trace}(e1, 1), e1[$-1]=e2 Expression id = new IdentifierExp(exp.loc, Id.empty); id = new DotIdExp(exp.loc, id, Id.object); - auto tiargs = new Objects(); - tiargs.push(exp.e1.type); - id = new DotTemplateInstanceExp(exp.loc, id, Id._d_arrayappendcTXImpl, tiargs); id = new DotIdExp(exp.loc, id, hook); auto arguments = new Expressions(); @@ -11315,11 +11305,10 @@ version (IN_LLVM) { /* Before the template hook, this check was performed in e2ir.d * for expressions like `a ~= a[$-1]`. Here, $ will be modified - * by calling `_d_arrayappendcT`, so we need to save `a[$-1]` in + * by calling `_d_arrayappendcTX`, so we need to save `a[$-1]` in * a temporary variable. */ value2 = extractSideEffect(sc, "__appendtmp", eValue2, value2, true); - exp.e2 = value2; // `__appendtmp*` will be destroyed together with the array `exp.e1`. auto vd = eValue2.isDeclarationExp().declaration.isVarDeclaration(); @@ -11335,13 +11324,12 @@ version (IN_LLVM) auto e0 = Expression.combine(ce, ae).expressionSemantic(sc); e0 = Expression.combine(e0, value1); e0 = Expression.combine(eValue1, e0); - e0 = Expression.combine(eValue2, e0); - *output = e0.expressionSemantic(sc); + exp.lowering = e0.expressionSemantic(sc); + *output = exp; } } - } override void visit(AddExp exp) diff --git a/dmd/frontend.h b/dmd/frontend.h index 1ce33a7abdd..d4090e7d36e 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -6539,6 +6539,7 @@ struct Scope final void* anchorCounts; Identifier* prevAnchor; AliasDeclaration* aliasAsg; + Dsymbol* search(const Loc& loc, Identifier* ident, Dsymbol** pscopesym, int32_t flags = 0); Scope() : enclosing(), _module(), @@ -7830,6 +7831,7 @@ class UshrAssignExp final : public BinAssignExp class CatAssignExp : public BinAssignExp { public: + Expression* lowering; void accept(Visitor* v) override; }; @@ -8713,7 +8715,6 @@ struct Id final static Identifier* _d_arraysetlengthTTrace; static Identifier* _d_arrayappendT; static Identifier* _d_arrayappendTTrace; - static Identifier* _d_arrayappendcTXImpl; static Identifier* _d_arrayappendcTX; static Identifier* _d_arrayappendcTXTrace; static Identifier* _d_arraycatnTX; diff --git a/dmd/id.d b/dmd/id.d index bfdfa152a35..24a82cc5dea 100644 --- a/dmd/id.d +++ b/dmd/id.d @@ -366,7 +366,6 @@ immutable Msgtable[] msgtable = { "_d_arraysetlengthTTrace"}, { "_d_arrayappendT" }, { "_d_arrayappendTTrace" }, - { "_d_arrayappendcTXImpl" }, { "_d_arrayappendcTX" }, { "_d_arrayappendcTXTrace" }, { "_d_arraycatnTX" }, diff --git a/dmd/inline.d b/dmd/inline.d index 47fb8e40772..4017a65784a 100644 --- a/dmd/inline.d +++ b/dmd/inline.d @@ -776,6 +776,21 @@ version (IN_LLVM) {} else result = ce; } + override void visit(CatAssignExp e) + { + auto cae = cast(CatAssignExp) e.copy(); + + if (auto lowering = cae.lowering) + cae.lowering = doInlineAs!Expression(cae.lowering, ids); + else + { + cae.e1 = doInlineAs!Expression(e.e1, ids); + cae.e2 = doInlineAs!Expression(e.e2, ids); + } + + result = cae; + } + override void visit(BinExp e) { auto be = cast(BinExp)e.copy(); @@ -1288,6 +1303,14 @@ public: inlineScan(e.e2); } + override void visit(CatAssignExp e) + { + if (auto lowering = e.lowering) + inlineScan(lowering); + else + visit(cast(BinExp) e); + } + override void visit(BinExp e) { inlineScan(e.e1); diff --git a/dmd/nogc.d b/dmd/nogc.d index 59bf1d5d1d5..e59b01019f4 100644 --- a/dmd/nogc.d +++ b/dmd/nogc.d @@ -108,12 +108,6 @@ public: return; f.printGCUsage(e.loc, "setting `length` may cause a GC allocation"); } - else if (fd.ident == Id._d_arrayappendT || fd.ident == Id._d_arrayappendcTX) - { - if (setGC(e, "cannot use operator `~=` in `@nogc` %s `%s`")) - return; - f.printGCUsage(e.loc, "operator `~=` may cause a GC allocation"); - } } override void visit(ArrayLiteralExp e) @@ -187,20 +181,14 @@ public: override void visit(CatAssignExp e) { - /* CatAssignExp will exist in `__traits(compiles, ...)` and in the `.e1` branch of a `__ctfe ? :` CondExp. - * The other branch will be `_d_arrayappendcTX(e1, 1), e1[$-1]=e2` which will generate the warning about - * GC usage. See visit(CallExp). - */ if (checkOnly) { err = true; return; } - if (f.setGC(e.loc, null)) - { - err = true; + if (setGC(e, "cannot use operator `~=` in `@nogc` %s `%s`")) return; - } + f.printGCUsage(e.loc, "operator `~=` may cause a GC allocation"); } override void visit(CatExp e) diff --git a/dmd/optimize.d b/dmd/optimize.d index 0065b016f83..4a9fbe360b5 100644 --- a/dmd/optimize.d +++ b/dmd/optimize.d @@ -928,6 +928,14 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue) } } + void visitCatAssign(CatAssignExp e) + { + if (auto lowering = e.lowering) + Expression_optimize(lowering, result, keepLvalue); + else + visitBinAssign(e); + } + void visitBin(BinExp e) { //printf("BinExp::optimize(result = %d) %s\n", result, e.toChars()); @@ -1392,9 +1400,9 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue) case EXP.leftShiftAssign: case EXP.rightShiftAssign: case EXP.unsignedRightShiftAssign: + case EXP.concatenateDcharAssign: visitBinAssign(ex.isBinAssignExp()); break; case EXP.concatenateElemAssign: - case EXP.concatenateDcharAssign: - case EXP.concatenateAssign: visitBinAssign(ex.isBinAssignExp()); break; + case EXP.concatenateAssign: visitCatAssign(cast(CatAssignExp) ex); break; case EXP.minusMinus: case EXP.plusPlus: diff --git a/gen/toir.cpp b/gen/toir.cpp index 24813640b49..13704bccfa2 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2161,7 +2161,6 @@ class ToElemVisitor : public Visitor { e->type->toChars()); LOG_SCOPE; - // TODO: still required? if (!global.params.useGC) { error( e->loc, @@ -2188,6 +2187,22 @@ class ToElemVisitor : public Visitor { e->type->toChars()); LOG_SCOPE; + if (!global.params.useGC) { + error(e->loc, + "appending to array in `%s` requires the GC which is not available " + "with -betterC", + e->toChars()); + result = + new DSliceValue(e->type, llvm::UndefValue::get(DtoType(e->type))); + return; + } + + if (e->lowering) { + assert(e->op != EXP::concatenateDcharAssign); + result = toElem(e->lowering); + return; + } + result = toElem(e->e1); Type *e1type = e->e1->type->toBasetype(); @@ -2197,6 +2212,7 @@ class ToElemVisitor : public Visitor { if (e1type->ty == TY::Tarray && e2type->ty == TY::Tdchar && (elemtype->ty == TY::Tchar || elemtype->ty == TY::Twchar)) { + assert(e->op == EXP::concatenateDcharAssign); if (elemtype->ty == TY::Tchar) { // append dchar to char[] DtoAppendDCharToString(e->loc, result, e->e2); diff --git a/packaging/dlang-tools_version b/packaging/dlang-tools_version index b8cc4b915ac..95ea209b264 100644 --- a/packaging/dlang-tools_version +++ b/packaging/dlang-tools_version @@ -1 +1 @@ -v2.105.3 \ No newline at end of file +v2.106.0 \ No newline at end of file diff --git a/packaging/dub_version b/packaging/dub_version index 3d29685a1e2..5971cf8a25f 100644 --- a/packaging/dub_version +++ b/packaging/dub_version @@ -1 +1 @@ -v1.34.0 \ No newline at end of file +v1.35.0 \ No newline at end of file diff --git a/runtime/druntime/src/core/cpuid.d b/runtime/druntime/src/core/cpuid.d index b79bd1df9c4..62edbac34f3 100644 --- a/runtime/druntime/src/core/cpuid.d +++ b/runtime/druntime/src/core/cpuid.d @@ -628,16 +628,17 @@ void getAMDcacheinfo() if (max_extended_cpuid >= 0x8000_0006) { // AMD K6-III or K6-2+ or later. - ubyte numcores = 1; + uint numcores = 1; if (max_extended_cpuid >= 0x8000_0008) { + // read the number of physical cores (minus 1) from the 8 lowest ECX bits version (GNU_OR_LDC) asm pure nothrow @nogc { "cpuid" : "=a" (dummy), "=c" (numcores) : "a" (0x8000_0008) : "ebx", "edx"; } else asm pure nothrow @nogc { mov EAX, 0x8000_0008; cpuid; - mov numcores, CL; + mov numcores, ECX; } - ++numcores; + numcores = (numcores & 0xFF) + 1; if (numcores>cpuFeatures.maxCores) cpuFeatures.maxCores = numcores; } @@ -666,10 +667,12 @@ void getAMDcacheinfo() // to determine number of processors. void getCpuInfo0B() { - int level=0; int threadsPerCore; uint a, b, c, d; - do { + // I'm not sure about this. The docs state that there + // are 2 hyperthreads per core if HT is factory enabled. + for (int level = 0; level < 2; level++) + { version (GNU_OR_LDC) asm pure nothrow @nogc { "cpuid" : "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (0x0B), "c" (level); } else asm pure nothrow @nogc { @@ -681,19 +684,20 @@ void getCpuInfo0B() mov c, ECX; mov d, EDX; } - if (b!=0) { - // I'm not sure about this. The docs state that there - // are 2 hyperthreads per core if HT is factory enabled. - if (level==0) + if (b != 0) + { + if (level == 0) threadsPerCore = b & 0xFFFF; - else if (level==1) { + else if (level == 1) + { cpuFeatures.maxThreads = b & 0xFFFF; cpuFeatures.maxCores = cpuFeatures.maxThreads / threadsPerCore; } - } - ++level; - } while (a!=0 || b!=0); + // Got "invalid domain" returned from cpuid + if (a == 0 && b == 0) + break; + } } void cpuidX86() diff --git a/runtime/druntime/src/core/internal/array/appending.d b/runtime/druntime/src/core/internal/array/appending.d index bb24813ae9e..ba34727a305 100644 --- a/runtime/druntime/src/core/internal/array/appending.d +++ b/runtime/druntime/src/core/internal/array/appending.d @@ -14,56 +14,55 @@ private extern (C) byte[] _d_arrayappendcTX(const TypeInfo ti, ref return scope private enum isCopyingNothrow(T) = __traits(compiles, (ref T rhs) nothrow { T lhs = rhs; }); -/// Implementation of `_d_arrayappendcTX` and `_d_arrayappendcTXTrace` -template _d_arrayappendcTXImpl(Tarr : T[], T) +/** + * Extend an array `px` by `n` elements. + * Caller must initialize those elements. + * Params: + * px = the array that will be extended, taken as a reference + * n = how many new elements to extend it with + * Returns: + * The new value of `px` + * Bugs: + * This function template was ported from a much older runtime hook that bypassed safety, + * purity, and throwabilty checks. To prevent breaking existing code, this function template + * is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations. + */ +ref Tarr _d_arrayappendcTX(Tarr : T[], T)(return ref scope Tarr px, size_t n) @trusted { - private enum errorMessage = "Cannot append to array if compiling without support for runtime type information!"; + // needed for CTFE: https://github.com/dlang/druntime/pull/3870#issuecomment-1178800718 + version (DigitalMars) pragma(inline, false); + version (D_TypeInfo) + { + auto ti = typeid(Tarr); + + // _d_arrayappendcTX takes the `px` as a ref byte[], but its length + // should still be the original length + auto pxx = (cast(byte*)px.ptr)[0 .. px.length]; + ._d_arrayappendcTX(ti, pxx, n); + px = (cast(T*)pxx.ptr)[0 .. pxx.length]; + + return px; + } + else + assert(0, "Cannot append to array if compiling without support for runtime type information!"); +} +version (D_ProfileGC) +{ /** - * Extend an array `px` by `n` elements. - * Caller must initialize those elements. - * Params: - * px = the array that will be extended, taken as a reference - * n = how many new elements to extend it with - * Returns: - * The new value of `px` - * Bugs: - * This function template was ported from a much older runtime hook that bypassed safety, - * purity, and throwabilty checks. To prevent breaking existing code, this function template - * is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations. + * TraceGC wrapper around $(REF _d_arrayappendT, core,internal,array,appending). */ - ref Tarr _d_arrayappendcTX(return ref scope Tarr px, size_t n) @trusted pure nothrow + ref Tarr _d_arrayappendcTXTrace(Tarr : T[], T)(string file, int line, string funcname, return ref scope Tarr px, size_t n) @trusted { - // needed for CTFE: https://github.com/dlang/druntime/pull/3870#issuecomment-1178800718 - version (DigitalMars) pragma(inline, false); version (D_TypeInfo) { - auto ti = typeid(Tarr); - - // _d_arrayappendcTX takes the `px` as a ref byte[], but its length - // should still be the original length - auto pxx = (cast(byte*)px.ptr)[0 .. px.length]; - ._d_arrayappendcTX(ti, pxx, n); - px = (cast(T*)pxx.ptr)[0 .. pxx.length]; + import core.internal.array.utils: TraceHook, gcStatsPure, accumulatePure; + mixin(TraceHook!(Tarr.stringof, "_d_arrayappendcTX")); - return px; + return _d_arrayappendcTX(px, n); } else - assert(0, errorMessage); - } - - version (D_ProfileGC) - { - import core.internal.array.utils : _d_HookTraceImpl; - - /** - * TraceGC wrapper around $(REF _d_arrayappendcTX, rt,array,appending,_d_arrayappendcTXImpl). - * Bugs: - * This function template was ported from a much older runtime hook that bypassed safety, - * purity, and throwabilty checks. To prevent breaking existing code, this function template - * is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations. - */ - alias _d_arrayappendcTXTrace = _d_HookTraceImpl!(Tarr, _d_arrayappendcTX, errorMessage); + static assert(0, "Cannot append to array if compiling without support for runtime type information!"); } } @@ -78,7 +77,7 @@ ref Tarr _d_arrayappendT(Tarr : T[], T)(return ref scope Tarr x, scope Tarr y) @ enum hasPostblit = __traits(hasPostblit, T); auto length = x.length; - _d_arrayappendcTXImpl!Tarr._d_arrayappendcTX(x, y.length); + _d_arrayappendcTX(x, y.length); // Only call `copyEmplace` if `T` has a copy ctor and no postblit. static if (hasElaborateCopyConstructor!T && !hasPostblit) @@ -126,7 +125,7 @@ version (D_ProfileGC) return _d_arrayappendT(x, y); } else - assert(0, "Cannot append to array if compiling without support for runtime type information!"); + static assert(0, "Cannot append to array if compiling without support for runtime type information!"); } } diff --git a/runtime/druntime/src/object.d b/runtime/druntime/src/object.d index 46798fd21c6..5c4eaf6d4ac 100644 --- a/runtime/druntime/src/object.d +++ b/runtime/druntime/src/object.d @@ -4726,11 +4726,12 @@ public import core.internal.array.appending : _d_arrayappendT; version (D_ProfileGC) { public import core.internal.array.appending : _d_arrayappendTTrace; + public import core.internal.array.appending : _d_arrayappendcTXTrace; public import core.internal.array.concatenation : _d_arraycatnTXTrace; public import core.lifetime : _d_newitemTTrace; public import core.internal.array.construction : _d_newarrayTTrace; } -public import core.internal.array.appending : _d_arrayappendcTXImpl; +public import core.internal.array.appending : _d_arrayappendcTX; public import core.internal.array.comparison : __cmp; public import core.internal.array.equality : __equals; public import core.internal.array.casting: __ArrayCast; diff --git a/runtime/phobos b/runtime/phobos index d904981723d..5ed76293b98 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit d904981723d04704eb64332db2365b73f72ba9b2 +Subproject commit 5ed76293b98b9bd72eb971d8e792e2ab9b859bcf diff --git a/tests/codegen/vector_init.d b/tests/codegen/vector_init.d index 398dbaa2b06..8a73c02a2c2 100644 --- a/tests/codegen/vector_init.d +++ b/tests/codegen/vector_init.d @@ -40,7 +40,7 @@ void foo() // https://github.com/ldc-developers/ldc/issues/3418 // CHECK: define {{.*}}_D11vector_init3bar -void bar(const ref float[4] floats, const(int)[] ints) +void bar(const ref float[4] floats, const ref int[4] ints) { alias float4 = __vector(float[4]); alias int4 = __vector(int[4]); diff --git a/tests/dmd/compilable/nogc.d b/tests/dmd/compilable/nogc.d index 88cf1229d4d..959adc499cc 100644 --- a/tests/dmd/compilable/nogc.d +++ b/tests/dmd/compilable/nogc.d @@ -119,3 +119,12 @@ void f(bool cond, string s) @nogc { alias Unused2 = typeof(&inner); // (Does not) INFERS GC (anymore) enum Unused3 = __traits(compiles , &inner); } + +// https://issues.dlang.org/show_bug.cgi?id=24072 + +version (D_SIMD) void f24072() @nogc +{ + alias int4 = __vector(int[4]); + int4 b = cast(int4)[1, 2, 3, 4]; + int4 c = cast(int4)[1, 2]; +} diff --git a/tests/dmd/fail_compilation/test24159.d b/tests/dmd/fail_compilation/test24159.d new file mode 100644 index 00000000000..35c7f364168 --- /dev/null +++ b/tests/dmd/fail_compilation/test24159.d @@ -0,0 +1,14 @@ +// https://issues.dlang.org/show_bug.cgi?id=24159 +// REQUIRED_ARGS: -betterC +/* +TEST_OUTPUT: +--- +fail_compilation/test24159.d(13): Error: appending to array in `x ~= 3` requires the GC which is not available with -betterC +--- +*/ + +extern(C) void main() +{ + int[] x = null; + x ~= 3; +} diff --git a/tests/dmd/fail_compilation/vector_cast.d b/tests/dmd/fail_compilation/vector_cast.d new file mode 100644 index 00000000000..e8a8d48c790 --- /dev/null +++ b/tests/dmd/fail_compilation/vector_cast.d @@ -0,0 +1,13 @@ +/** +REQUIRED_ARGS: -m64 +TEST_OUTPUT: +--- +fail_compilation/vector_cast.d(11): Error: cannot cast expression `a` of type `int[3]` to `__vector(int[4])` +fail_compilation/vector_cast.d(13): Error: cannot cast expression `a` of type `int[5]` to `__vector(int[4])` +--- +*/ + +alias int4 = __vector(int[4]); +int4 convtest3(int[3] a) { return cast(int4) a; } +int4 convtest4(int[4] a) { return cast(int4) a; } +int4 convtest5(int[5] a) { return cast(int4) a; } diff --git a/tests/dmd/runnable/bitfields.c b/tests/dmd/runnable/bitfields.c index 8946c832571..20ff397a90f 100644 --- a/tests/dmd/runnable/bitfields.c +++ b/tests/dmd/runnable/bitfields.c @@ -254,6 +254,34 @@ _Static_assert(test7s2() == -2, "3"); /******************************************/ +// https://issues.dlang.org/show_bug.cgi?id=24257 + +#include + +struct Entry +{ + unsigned id : 15; + _Bool done : 1; +}; + +struct State +{ + struct Entry e; +}; + +void test24257() +{ + int i = 72; + struct State s = (struct State){i}; + if (s.e.id != 72) + { + printf("error %d\n", __LINE__); + exit(1); + } +} + +/******************************************/ + int main() { test1(); @@ -263,6 +291,7 @@ int main() test5(); test6(); test7(); + test24257(); return 0; } diff --git a/tests/dmd/runnable/dbitfields.d b/tests/dmd/runnable/dbitfields.d index 0d1877a7bfd..aa154c7bbb2 100644 --- a/tests/dmd/runnable/dbitfields.d +++ b/tests/dmd/runnable/dbitfields.d @@ -173,6 +173,39 @@ static assert(test7u() == 1); static assert(test7s() == -1); static assert(test7s2() == -2); +/******************************************/ +// https://issues.dlang.org/show_bug.cgi?id=24257 + +struct S24257 +{ + uint : 15; + bool done : 1; +} + +bool advance() +{ + S24257 n; + n.done = false; + n.done = true; + return n.done; +} + +bool retard() +{ + S24257 n; + n.done = true; + n.done = false; + return n.done; +} + +static assert(advance() == true); + +void test24257() +{ + assert(advance() == true); + assert(retard() == false); +} + /******************************************/ int main() @@ -184,6 +217,7 @@ int main() test5(); test6(); test7(); + test24257(); return 0; } diff --git a/tests/dmd/runnable/test24184.d b/tests/dmd/runnable/test24184.d new file mode 100644 index 00000000000..736824fce86 --- /dev/null +++ b/tests/dmd/runnable/test24184.d @@ -0,0 +1,30 @@ +// https://issues.dlang.org/show_bug.cgi?id=24184 + +void stage3(alias abc)(ubyte[]) +{ + bool skipSpaces() + { + abc(); + return false; + } + skipSpaces; +} +ubyte[] singleThreadJsonImpl(alias xxx)(ubyte[] table) +{ + align(64) ubyte[] vector; + + ubyte[] abc() { return vector; } + + stage3!(abc)(table); + + return table; +} +ubyte[] singleThreadJsonText() +{ + bool xxx() { return true; } + + return singleThreadJsonImpl!(xxx)([]); +} +void deserializeJson() { singleThreadJsonText(); } + +void main() { deserializeJson(); } diff --git a/tests/semantic/dcompute.d b/tests/semantic/dcompute.d index 2baca067d82..f2317319374 100644 --- a/tests/semantic/dcompute.d +++ b/tests/semantic/dcompute.d @@ -31,7 +31,7 @@ void func() int[] quux; //CHECK: dcompute.d([[@LINE+1]]): Error: setting `length` in `@compute` code not allowed quux.length = 1; - //CHECK: dcompute.d([[@LINE+1]]): Error: can only call functions from other `@compute` modules in `@compute` code + //CHECK: dcompute.d([[@LINE+1]]): Error: cannot use operator `~=` in `@compute` code quux ~= 42; //CHECK: dcompute.d([[@LINE+1]]): Error: cannot use operator `~` in `@compute` code cast(void) (quux ~ 1);