d: Merge dmd, druntime 11240a9663

D front-end changes:

	- Import latest fixes from dmd v2.107.0.

D runtime changes:

	- Import latest fixes from druntime v2.107.0.

Included in the merge are the fix for PR113772, and new testsuite
directives to enable fixing PR104739.

	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.
This commit is contained in:
Iain Buclaw 2024-02-12 16:46:33 +01:00
parent 3c57b1c12a
commit 2dde675ff4
42 changed files with 491 additions and 296 deletions

View File

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

View File

@ -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.

View File

@ -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;
/**

View File

@ -42,6 +42,7 @@ enum class Baseok : uint8_t
};
FuncDeclaration *search_toString(StructDeclaration *sd);
void semanticTypeInfoMembers(StructDeclaration *sd);
enum class ClassKind : uint8_t
{

View File

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

View File

@ -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_ |

View File

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

View File

@ -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();

View File

@ -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:

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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)
{

View File

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

View File

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

View File

@ -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()

View File

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

View File

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

View File

@ -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
{

View File

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

View File

@ -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:

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 && tb1->equivalent (tb2))
if (tb1->ty == tb2->ty && equivalent (tb1, tb2))
return true;
return false;

View File

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

View File

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

View File

@ -1,6 +1,7 @@
// PERMUTE_ARGS:
// EXTRA_SOURCES: imports/mangle10077.d
// EXTRA_FILES: imports/testmangle.d
// UNICODE_NAMES:
/*
TEST_OUTPUT:
---

View File

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

View File

@ -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()

View File

@ -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.

View File

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

View File

@ -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)

View File

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

View File

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

View File

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

View File

@ -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.");
}

View File

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

View File

@ -437,6 +437,7 @@ unittest
string[412] names;
ubyte[1024] moredata;
}
version (OnlyLowMemUnittests) {} else
test!(Large, Large);
}

View File

@ -2247,6 +2247,7 @@ unittest
assert(GC.getAttr(p) == BlkAttr.NO_SCAN);
}
test(16);
version (OnlyLowMemUnittests) {} else
test(1024 * 1024);
}