@@ -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;
@@ -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.
@@ -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;
/**
@@ -42,6 +42,7 @@ enum class Baseok : uint8_t
};
FuncDeclaration *search_toString(StructDeclaration *sd);
+void semanticTypeInfoMembers(StructDeclaration *sd);
enum class ClassKind : uint8_t
{
@@ -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;
@@ -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_ |
@@ -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);
}
@@ -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();
@@ -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:
@@ -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);
}
@@ -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
@@ -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;
@@ -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);
@@ -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);
@@ -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
@@ -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;
@@ -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);
}
@@ -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)
{
@@ -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);
@@ -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);
@@ -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()
@@ -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);
@@ -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);
@@ -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
{
@@ -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);
@@ -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:
@@ -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;
@@ -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) ));
new file mode 100644
@@ -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;
+}
@@ -1,6 +1,7 @@
// PERMUTE_ARGS:
// EXTRA_SOURCES: imports/mangle10077.d
// EXTRA_FILES: imports/testmangle.d
+// UNICODE_NAMES:
/*
TEST_OUTPUT:
---
@@ -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;
}
@@ -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()
@@ -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.
@@ -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;
@@ -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)
@@ -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);
+ }
}
}
}
@@ -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]);
}
}
@@ -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
@@ -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.");
}
@@ -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;
@@ -437,6 +437,7 @@ unittest
string[412] names;
ubyte[1024] moredata;
}
+ version (OnlyLowMemUnittests) {} else
test!(Large, Large);
}
@@ -2247,6 +2247,7 @@ unittest
assert(GC.getAttr(p) == BlkAttr.NO_SCAN);
}
test(16);
+ version (OnlyLowMemUnittests) {} else
test(1024 * 1024);
}