@@ -139,7 +139,7 @@ build_frontend_type (tree type)
dtype = Type::basic[i];
/* Search for type matching size and signedness. */
- if (unsignedp != dtype->isunsigned ()
+ if (unsignedp != dtype->isUnsigned ()
|| size != dmd::size (dtype))
continue;
@@ -572,8 +572,8 @@ d_build_builtins_module (Module *m)
tf->trust = !DECL_ASSEMBLER_NAME_SET_P (decl) ? TRUST::safe
: TREE_NOTHROW (decl) ? TRUST::trusted
: TRUST::system;
- tf->isnothrow (true);
- tf->isnogc (true);
+ tf->isNothrow (true);
+ tf->isNogc (true);
FuncDeclaration *func
= FuncDeclaration::create (Loc (), Loc (),
@@ -715,7 +715,7 @@ matches_builtin_type (Type *t1, Type *t2)
&& dmd::implicitConvTo (tb1, tb2) != MATCH::nomatch)
return true;
- if (tb1->isintegral () == tb2->isintegral ()
+ if (tb1->isIntegral () == tb2->isIntegral ()
&& dmd::size (tb1) == dmd::size (tb2))
return true;
@@ -739,7 +739,7 @@ covariant_with_builtin_type_p (Type *t1, Type *t2)
/* Check for obvious reasons why types may be distinct. */
if (tf1 == NULL || tf2 == NULL
- || tf1->isref () != tf2->isref ()
+ || tf1->isRef () != tf2->isRef ()
|| tf1->parameterList.varargs != tf2->parameterList.varargs
|| tf1->parameterList.length () != tf2->parameterList.length ())
return false;
@@ -972,15 +972,15 @@ lower_struct_comparison (tree_code code, StructDeclaration *sd,
/* Compare inner data structures. */
tcmp = lower_struct_comparison (code, ts->sym, t1ref, t2ref);
}
- else if (type->ty != TY::Tvector && type->isintegral ())
+ else if (type->ty != TY::Tvector && type->isIntegral ())
{
/* Integer comparison, no special handling required. */
tcmp = build_boolop (code, t1ref, t2ref);
}
- else if (type->ty != TY::Tvector && type->isfloating ())
+ else if (type->ty != TY::Tvector && type->isFloating ())
{
/* Floating-point comparison, don't compare padding in type. */
- if (!type->iscomplex ())
+ if (!type->isComplex ())
tcmp = build_float_identity (code, t1ref, t2ref);
else
{
@@ -2119,7 +2119,7 @@ call_side_effect_free_p (FuncDeclaration *func, Type *type)
/* Must be a `nothrow' function. */
TypeFunction *tf = func->type->toTypeFunction ();
- if (!tf->isnothrow ())
+ if (!tf->isNothrow ())
return false;
/* Return type can't be `void' or `noreturn', as that implies all work is
@@ -2137,7 +2137,7 @@ call_side_effect_free_p (FuncDeclaration *func, Type *type)
TypeFunction *tf = get_function_type (type);
/* Must be a `nothrow` function type. */
- if (tf == NULL || !tf->isnothrow ())
+ if (tf == NULL || !tf->isNothrow ())
return false;
/* Return type can't be `void' or `noreturn', as that implies all work is
@@ -46,9 +46,9 @@ Compiler::paintAsType (UnionExp *, Expression *expr, Type *type)
Type *tb = type->toBasetype ();
- if (expr->type->isintegral ())
+ if (expr->type->isIntegral ())
cst = build_integer_cst (expr->toInteger (), build_ctype (expr->type));
- else if (expr->type->isfloating ())
+ else if (expr->type->isFloating ())
cst = build_float_cst (expr->toReal (), expr->type);
else if (expr->op == EXP::arrayLiteral)
{
@@ -60,13 +60,13 @@ Compiler::paintAsType (UnionExp *, Expression *expr, Type *type)
for (size_t i = 0; i < elements->length; i++)
{
Expression *e = (*elements)[i];
- if (e->type->isintegral ())
+ if (e->type->isIntegral ())
{
tree value = build_integer_cst (e->toInteger (),
build_ctype (e->type));
CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value);
}
- else if (e->type->isfloating ())
+ else if (e->type->isFloating ())
{
tree value = build_float_cst (e->toReal (), e->type);
CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value);
@@ -603,8 +603,8 @@ convert_expr (tree exp, Type *etype, Type *totype)
default:
/* All casts between imaginary and non-imaginary result in 0.0,
except for casts between complex and imaginary types. */
- if (!ebtype->iscomplex () && !tbtype->iscomplex ()
- && (ebtype->isimaginary () != tbtype->isimaginary ()))
+ if (!ebtype->isComplex () && !tbtype->isComplex ()
+ && (ebtype->isImaginary () != tbtype->isImaginary ()))
{
warning (OPT_Wcast_result,
"cast from %qs to %qs will produce zero result",
@@ -814,7 +814,7 @@ convert_for_assignment (Expression *expr, Type *totype, bool literalp)
/* D Front end uses IntegerExp(0) to mean zero-init an array or structure. */
if ((tbtype->ty == TY::Tsarray || tbtype->ty == TY::Tstruct)
- && ebtype->isintegral ())
+ && ebtype->isIntegral ())
{
tree ret = build_expr (expr, false, literalp);
gcc_assert (integer_zerop (ret));
@@ -274,7 +274,7 @@ Target::isVectorTypeSupported (int sz, Type *type)
type = Type::tuns8;
/* No support for non-trivial types, complex types, or booleans. */
- if (!type->isTypeBasic () || type->iscomplex () || type->ty == TY::Tbool)
+ if (!type->isTypeBasic () || type->isComplex () || type->ty == TY::Tbool)
return 2;
/* In [simd/vector extensions], which vector types are supported depends on
@@ -300,7 +300,7 @@ Target::isVectorOpSupported (Type *type, EXP op, Type *)
return true;
/* Don't support if type is non-scalar, such as __vector(void[]). */
- if (!type->isscalar ())
+ if (!type->isScalar ())
return false;
/* Don't support if expression cannot be represented. */
@@ -314,7 +314,7 @@ Target::isVectorOpSupported (Type *type, EXP op, Type *)
case EXP::mod:
case EXP::modAssign:
/* fmod() is lowered as a function call. */
- if (type->isfloating ())
+ if (type->isFloating ())
return false;
break;
@@ -449,7 +449,7 @@ Target::isReturnOnStack (TypeFunction *tf, bool)
/* Need the back-end type to determine this, but this is called from the
frontend before semantic processing is finished. An accurate value
is not currently needed anyway. */
- if (tf->isref ())
+ if (tf->isRef ())
return false;
Type *tn = tf->next->toBasetype ();
@@ -781,7 +781,7 @@ public:
{
/* Do not store variables we cannot take the address of,
but keep the values for purposes of debugging. */
- if (d->type->isscalar () && !dmd::hasPointers (d->type))
+ if (d->type->isScalar () && !dmd::hasPointers (d->type))
{
tree decl = get_symbol_decl (d);
d_pushdecl (decl);
@@ -1245,7 +1245,7 @@ get_symbol_decl (Declaration *decl)
/* CONST_DECL was initially intended for enumerals and may be used for
scalars in general, but not for aggregates. Here a non-constant
value is generated anyway so as its value can be used. */
- if (!vd->canTakeAddressOf () && !vd->type->isscalar ())
+ if (!vd->canTakeAddressOf () && !vd->type->isScalar ())
{
gcc_assert (vd->_init && !vd->_init->isVoidInitializer ());
Expression *ie = dmd::initializerToExpression (vd->_init);
@@ -1306,7 +1306,7 @@ get_symbol_decl (Declaration *decl)
/* Cannot make an expression out of a void initializer. */
gcc_assert (vd->_init && !vd->_init->isVoidInitializer ());
/* Non-scalar manifest constants have already been dealt with. */
- gcc_assert (vd->type->isscalar ());
+ gcc_assert (vd->type->isScalar ());
Expression *ie = dmd::initializerToExpression (vd->_init);
DECL_INITIAL (decl->csym) = build_expr (ie, true);
@@ -1,4 +1,4 @@
-34875cd6e1faa42e84ae953c0485ef524fe67e38
+6884b433d21d9b6356e5c83ffc6eb06a62a5cad1
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
@@ -140,13 +140,8 @@ int blockExit(Statement s, FuncDeclaration func, ErrorSink eSink)
else if (func.getModule().filetype != FileType.c)
{
const(char)* gototype = s.isCaseStatement() ? "case" : "default";
- // @@@DEPRECATED_2.110@@@ https://issues.dlang.org/show_bug.cgi?id=22999
- // Deprecated in 2.100
- // Make an error in 2.110
- if (sl && sl.isCaseStatement())
- global.errorSink.deprecation(s.loc, "switch case fallthrough - use 'goto %s;' if intended", gototype);
- else
- global.errorSink.error(s.loc, "switch case fallthrough - use 'goto %s;' if intended", gototype);
+ // https://issues.dlang.org/show_bug.cgi?id=22999
+ global.errorSink.error(s.loc, "switch case fallthrough - use 'goto %s;' if intended", gototype);
}
}
}
@@ -72,7 +72,7 @@ CT canThrow(Expression e, FuncDeclaration func, ErrorSink eSink)
void checkFuncThrows(Expression e, FuncDeclaration f)
{
auto tf = f.type.toBasetype().isTypeFunction();
- if (tf && !tf.isnothrow)
+ if (tf && !tf.isNothrow)
{
if (eSink)
{
@@ -81,7 +81,7 @@ CT canThrow(Expression e, FuncDeclaration func, ErrorSink eSink)
errorSupplementalInferredAttr(f, 10, false, STC.nothrow_);
import dmd.expressionsem : checkOverriddenDtor;
- f.checkOverriddenDtor(null, e.loc, dd => dd.type.toTypeFunction().isnothrow, "not nothrow");
+ f.checkOverriddenDtor(null, e.loc, dd => dd.type.toTypeFunction().isNothrow, "not nothrow");
}
else if (func)
{
@@ -133,7 +133,7 @@ CT canThrow(Expression e, FuncDeclaration func, ErrorSink eSink)
if (ce.f && ce.f == func)
return;
const tf = ce.calledFunctionType();
- if (tf && tf.isnothrow)
+ if (tf && tf.isNothrow)
return;
if (ce.f)
@@ -174,13 +174,13 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
case Format.lu: // unsigned long int
case Format.ld: // long int
- if (!(t.isintegral() && t.size() == c_longsize))
+ if (!(t.isIntegral() && t.size() == c_longsize))
{
if (fmt == Format.lu)
errorMsg(null, e, (c_longsize == 4 ? "uint" : "ulong"), t);
else
errorMsg(null, e, (c_longsize == 4 ? "int" : "long"), t);
- if (t.isintegral() && t.size() != c_longsize)
+ if (t.isIntegral() && t.size() != c_longsize)
eSink.errorSupplemental(e.loc, "C `long` is %d bytes on your system", c_longsize);
}
break;
@@ -203,12 +203,12 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
break;
case Format.zd: // size_t
- if (!(t.isintegral() && t.size() == ptrsize))
+ if (!(t.isIntegral() && t.size() == ptrsize))
errorMsg(null, e, "size_t", t);
break;
case Format.td: // ptrdiff_t
- if (!(t.isintegral() && t.size() == ptrsize))
+ if (!(t.isIntegral() && t.size() == ptrsize))
errorMsg(null, e, "ptrdiff_t", t);
break;
@@ -234,7 +234,7 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
break;
case Format.ln: // pointer to long int
- if (!(t.ty == Tpointer && tnext.isintegral() && tnext.size() == c_longsize))
+ if (!(t.ty == Tpointer && tnext.isIntegral() && tnext.size() == c_longsize))
errorMsg(null, e, (c_longsize == 4 ? "int*" : "long*"), t);
break;
@@ -259,12 +259,12 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
break;
case Format.zn: // pointer to size_t
- if (!(t.ty == Tpointer && tnext.isintegral() && tnext.isunsigned() && tnext.size() == ptrsize))
+ if (!(t.ty == Tpointer && tnext.isIntegral() && tnext.isUnsigned() && tnext.size() == ptrsize))
errorMsg(null, e, "size_t*", t);
break;
case Format.tn: // pointer to ptrdiff_t
- if (!(t.ty == Tpointer && tnext.isintegral() && !tnext.isunsigned() && tnext.size() == ptrsize))
+ if (!(t.ty == Tpointer && tnext.isIntegral() && !tnext.isUnsigned() && tnext.size() == ptrsize))
errorMsg(null, e, "ptrdiff_t*", t);
break;
@@ -414,7 +414,7 @@ bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres
case Format.ln:
case Format.ld: // pointer to long int
- if (!(t.ty == Tpointer && tnext.isintegral() && !tnext.isunsigned() && tnext.size() == c_longsize))
+ if (!(t.ty == Tpointer && tnext.isIntegral() && !tnext.isUnsigned() && tnext.size() == c_longsize))
errorMsg(null, e, (c_longsize == 4 ? "int*" : "long*"), t);
break;
@@ -432,13 +432,13 @@ bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres
case Format.zn:
case Format.zd: // pointer to size_t
- if (!(t.ty == Tpointer && tnext.isintegral() && tnext.isunsigned() && tnext.size() == ptrsize))
+ if (!(t.ty == Tpointer && tnext.isIntegral() && tnext.isUnsigned() && tnext.size() == ptrsize))
errorMsg(null, e, "size_t*", t);
break;
case Format.tn:
case Format.td: // pointer to ptrdiff_t
- if (!(t.ty == Tpointer && tnext.isintegral() && !tnext.isunsigned() && tnext.size() == ptrsize))
+ if (!(t.ty == Tpointer && tnext.isIntegral() && !tnext.isUnsigned() && tnext.size() == ptrsize))
errorMsg(null, e, "ptrdiff_t*", t);
break;
@@ -458,7 +458,7 @@ bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres
break;
case Format.lu: // pointer to unsigned long int
- if (!(t.ty == Tpointer && tnext.isintegral() && tnext.isunsigned() && tnext.size() == c_longsize))
+ if (!(t.ty == Tpointer && tnext.isIntegral() && tnext.isUnsigned() && tnext.size() == c_longsize))
errorMsg(null, e, (c_longsize == 4 ? "uint*" : "ulong*"), t);
break;
@@ -67,9 +67,9 @@ StorageClass mergeFuncAttrs(StorageClass s1, const FuncDeclaration f) pure
if (tf.purity != PURE.impure)
s2 |= STC.pure_;
- if (tf.isnothrow)
+ if (tf.isNothrow)
s2 |= STC.nothrow_;
- if (tf.isnogc)
+ if (tf.isNogc)
s2 |= STC.nogc;
const sa = s1 & s2;
@@ -377,7 +377,7 @@ FuncDeclaration buildOpAssign(StructDeclaration sd, Scope* sc)
auto er = new ThisExp(loc);
Statement s2 = new ReturnStatement(loc, er);
fop.fbody = new CompoundStatement(loc, s1, s2);
- tf.isreturn = true;
+ tf.isReturn = true;
}
sd.members.push(fop);
fop.addMember(sc, sd);
@@ -440,7 +440,7 @@ bool needOpEquals(StructDeclaration sd)
if (needOpEquals(ts.sym))
goto Lneed;
}
- if (tvbase.isfloating())
+ if (tvbase.isFloating())
{
// This is necessray for:
// 1. comparison of +0.0 and -0.0 should be true.
@@ -767,7 +767,7 @@ private bool needToHash(StructDeclaration sd)
if (needToHash(ts.sym))
goto Lneed;
}
- if (tvbase.isfloating())
+ if (tvbase.isFloating())
{
/* This is necessary because comparison of +0.0 and -0.0 should be true,
* i.e. not a bit compare.
@@ -1274,7 +1274,7 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
// block to destroy any prior successfully postblitted fields should
// this field's postblit fail.
// Don't generate it for betterC code since it cannot throw exceptions.
- if (fieldsToDestroy.length > 0 && !(cast(TypeFunction)sdv.postblit.type).isnothrow && global.params.useExceptions)
+ if (fieldsToDestroy.length > 0 && !(cast(TypeFunction)sdv.postblit.type).isNothrow && global.params.useExceptions)
{
// create a list of destructors that need to be called
Expression[] dtorCalls;
@@ -398,7 +398,7 @@ extern (C++) final class StaticForeach : RootObject
Expression aggr = void;
Type indexty = void;
- if (rangefe && (indexty = ety).isintegral())
+ if (rangefe && (indexty = ety).isIntegral())
{
rangefe.lwr.type = indexty;
rangefe.upr.type = indexty;
@@ -744,6 +744,7 @@ extern (C++) final class VersionCondition : DVCondition
case "Win32":
case "Win64":
case "Windows":
+ case "Xtensa":
case "X86":
case "X86_64":
return true;
@@ -69,15 +69,15 @@ UnionExp Neg(Type type, Expression e1)
{
UnionExp ue = void;
Loc loc = e1.loc;
- if (e1.type.isreal())
+ if (e1.type.isReal())
{
emplaceExp!(RealExp)(&ue, loc, -e1.toReal(), type);
}
- else if (e1.type.isimaginary())
+ else if (e1.type.isImaginary())
{
emplaceExp!(RealExp)(&ue, loc, -e1.toImaginary(), type);
}
- else if (e1.type.iscomplex())
+ else if (e1.type.isComplex())
{
emplaceExp!(ComplexExp)(&ue, loc, -e1.toComplex(), type);
}
@@ -114,15 +114,15 @@ UnionExp Add(const ref Loc loc, Type type, Expression e1, Expression e2)
{
printf("Add(e1 = %s, e2 = %s)\n", e1.toChars(), e2.toChars());
}
- if (type.isreal())
+ if (type.isReal())
{
emplaceExp!(RealExp)(&ue, loc, e1.toReal() + e2.toReal(), type);
}
- else if (type.isimaginary())
+ else if (type.isImaginary())
{
emplaceExp!(RealExp)(&ue, loc, e1.toImaginary() + e2.toImaginary(), type);
}
- else if (type.iscomplex())
+ else if (type.isComplex())
{
// This rigamarole is necessary so that -0.0 doesn't get
// converted to +0.0 by doing an extraneous add with +0.0
@@ -134,12 +134,12 @@ UnionExp Add(const ref Loc loc, Type type, Expression e1, Expression e2)
real_t i2 = CTFloat.zero;
auto v = complex_t(CTFloat.zero);
int x;
- if (e1.type.isreal())
+ if (e1.type.isReal())
{
r1 = e1.toReal();
x = 0;
}
- else if (e1.type.isimaginary())
+ else if (e1.type.isImaginary())
{
i1 = e1.toImaginary();
x = 3;
@@ -149,11 +149,11 @@ UnionExp Add(const ref Loc loc, Type type, Expression e1, Expression e2)
c1 = e1.toComplex();
x = 6;
}
- if (e2.type.isreal())
+ if (e2.type.isReal())
{
r2 = e2.toReal();
}
- else if (e2.type.isimaginary())
+ else if (e2.type.isImaginary())
{
i2 = e2.toImaginary();
x += 1;
@@ -223,29 +223,29 @@ UnionExp Min(const ref Loc loc, Type type, Expression e1, Expression e2)
UnionExp Mul(const ref Loc loc, Type type, Expression e1, Expression e2)
{
UnionExp ue = void;
- if (type.isfloating())
+ if (type.isFloating())
{
auto c = complex_t(CTFloat.zero);
real_t r = CTFloat.zero;
- if (e1.type.isreal())
+ if (e1.type.isReal())
{
r = e1.toReal();
c = e2.toComplex();
c = complex_t(r * creall(c), r * cimagl(c));
}
- else if (e1.type.isimaginary())
+ else if (e1.type.isImaginary())
{
r = e1.toImaginary();
c = e2.toComplex();
c = complex_t(-r * cimagl(c), r * creall(c));
}
- else if (e2.type.isreal())
+ else if (e2.type.isReal())
{
r = e2.toReal();
c = e1.toComplex();
c = complex_t(r * creall(c), r * cimagl(c));
}
- else if (e2.type.isimaginary())
+ else if (e2.type.isImaginary())
{
r = e2.toImaginary();
c = e1.toComplex();
@@ -253,11 +253,11 @@ UnionExp Mul(const ref Loc loc, Type type, Expression e1, Expression e2)
}
else
c = e1.toComplex() * e2.toComplex();
- if (type.isreal())
+ if (type.isReal())
emplaceExp!(RealExp)(&ue, loc, creall(c), type);
- else if (type.isimaginary())
+ else if (type.isImaginary())
emplaceExp!(RealExp)(&ue, loc, cimagl(c), type);
- else if (type.iscomplex())
+ else if (type.isComplex())
emplaceExp!(ComplexExp)(&ue, loc, c, type);
else
assert(0);
@@ -272,12 +272,12 @@ UnionExp Mul(const ref Loc loc, Type type, Expression e1, Expression e2)
UnionExp Div(const ref Loc loc, Type type, Expression e1, Expression e2)
{
UnionExp ue = void;
- if (type.isfloating())
+ if (type.isFloating())
{
auto c = complex_t(CTFloat.zero);
- if (e2.type.isreal())
+ if (e2.type.isReal())
{
- if (e1.type.isreal())
+ if (e1.type.isReal())
{
emplaceExp!(RealExp)(&ue, loc, e1.toReal() / e2.toReal(), type);
return ue;
@@ -286,7 +286,7 @@ UnionExp Div(const ref Loc loc, Type type, Expression e1, Expression e2)
c = e1.toComplex();
c = complex_t(creall(c) / r, cimagl(c) / r);
}
- else if (e2.type.isimaginary())
+ else if (e2.type.isImaginary())
{
const r = e2.toImaginary();
c = e1.toComplex();
@@ -297,11 +297,11 @@ UnionExp Div(const ref Loc loc, Type type, Expression e1, Expression e2)
c = e1.toComplex() / e2.toComplex();
}
- if (type.isreal())
+ if (type.isReal())
emplaceExp!(RealExp)(&ue, loc, creall(c), type);
- else if (type.isimaginary())
+ else if (type.isImaginary())
emplaceExp!(RealExp)(&ue, loc, cimagl(c), type);
- else if (type.iscomplex())
+ else if (type.isComplex())
emplaceExp!(ComplexExp)(&ue, loc, c, type);
else
assert(0);
@@ -319,7 +319,7 @@ UnionExp Div(const ref Loc loc, Type type, Expression e1, Expression e2)
emplaceExp!(ErrorExp)(&ue);
return ue;
}
- if (n2 == -1 && !type.isunsigned())
+ if (n2 == -1 && !type.isUnsigned())
{
// Check for int.min / -1
if (n1 == 0xFFFFFFFF80000000UL && type.toBasetype().ty != Tint64)
@@ -335,7 +335,7 @@ UnionExp Div(const ref Loc loc, Type type, Expression e1, Expression e2)
return ue;
}
}
- if (e1.type.isunsigned() || e2.type.isunsigned())
+ if (e1.type.isUnsigned() || e2.type.isUnsigned())
n = (cast(dinteger_t)n1) / (cast(dinteger_t)n2);
else
n = n1 / n2;
@@ -347,26 +347,26 @@ UnionExp Div(const ref Loc loc, Type type, Expression e1, Expression e2)
UnionExp Mod(const ref Loc loc, Type type, Expression e1, Expression e2)
{
UnionExp ue = void;
- if (type.isfloating())
+ if (type.isFloating())
{
auto c = complex_t(CTFloat.zero);
- if (e2.type.isreal())
+ if (e2.type.isReal())
{
const r2 = e2.toReal();
c = complex_t(e1.toReal() % r2, e1.toImaginary() % r2);
}
- else if (e2.type.isimaginary())
+ else if (e2.type.isImaginary())
{
const i2 = e2.toImaginary();
c = complex_t(e1.toReal() % i2, e1.toImaginary() % i2);
}
else
assert(0);
- if (type.isreal())
+ if (type.isReal())
emplaceExp!(RealExp)(&ue, loc, creall(c), type);
- else if (type.isimaginary())
+ else if (type.isImaginary())
emplaceExp!(RealExp)(&ue, loc, cimagl(c), type);
- else if (type.iscomplex())
+ else if (type.isComplex())
emplaceExp!(ComplexExp)(&ue, loc, c, type);
else
assert(0);
@@ -384,7 +384,7 @@ UnionExp Mod(const ref Loc loc, Type type, Expression e1, Expression e2)
emplaceExp!(ErrorExp)(&ue);
return ue;
}
- if (n2 == -1 && !type.isunsigned())
+ if (n2 == -1 && !type.isUnsigned())
{
// Check for int.min % -1
if (n1 == 0xFFFFFFFF80000000UL && type.toBasetype().ty != Tint64)
@@ -400,7 +400,7 @@ UnionExp Mod(const ref Loc loc, Type type, Expression e1, Expression e2)
return ue;
}
}
- if (e1.type.isunsigned() || e2.type.isunsigned())
+ if (e1.type.isUnsigned() || e2.type.isUnsigned())
n = (cast(dinteger_t)n1) % (cast(dinteger_t)n2);
else
n = n1 % n2;
@@ -414,13 +414,13 @@ UnionExp Pow(const ref Loc loc, Type type, Expression e1, Expression e2)
//printf("Pow()\n");
UnionExp ue;
// Handle integer power operations.
- if (e2.type.isintegral())
+ if (e2.type.isIntegral())
{
dinteger_t n = e2.toInteger();
bool neg;
- if (!e2.type.isunsigned() && cast(sinteger_t)n < 0)
+ if (!e2.type.isUnsigned() && cast(sinteger_t)n < 0)
{
- if (e1.type.isintegral())
+ if (e1.type.isIntegral())
{
cantExp(ue);
return ue;
@@ -432,12 +432,12 @@ UnionExp Pow(const ref Loc loc, Type type, Expression e1, Expression e2)
else
neg = false;
UnionExp ur, uv;
- if (e1.type.iscomplex())
+ if (e1.type.isComplex())
{
emplaceExp!(ComplexExp)(&ur, loc, e1.toComplex(), e1.type);
emplaceExp!(ComplexExp)(&uv, loc, complex_t(CTFloat.one), e1.type);
}
- else if (e1.type.isfloating())
+ else if (e1.type.isFloating())
{
emplaceExp!(RealExp)(&ur, loc, e1.toReal(), e1.type);
emplaceExp!(RealExp)(&uv, loc, CTFloat.one, e1.type);
@@ -467,14 +467,14 @@ UnionExp Pow(const ref Loc loc, Type type, Expression e1, Expression e2)
emplaceExp!(RealExp)(&one, loc, CTFloat.one, v.type);
uv = Div(loc, v.type, one.exp(), v);
}
- if (type.iscomplex())
+ if (type.isComplex())
emplaceExp!(ComplexExp)(&ue, loc, v.toComplex(), type);
- else if (type.isintegral())
+ else if (type.isIntegral())
emplaceExp!(IntegerExp)(&ue, loc, v.toInteger(), type);
else
emplaceExp!(RealExp)(&ue, loc, v.toReal(), type);
}
- else if (e2.type.isfloating())
+ else if (e2.type.isFloating())
{
// x ^^ y for x < 0 and y not an integer is not defined; so set result as NaN
if (e1.toReal() < CTFloat.zero)
@@ -765,13 +765,13 @@ UnionExp Equal(EXP op, const ref Loc loc, Type type, Expression e1, Expression e
cantExp(ue);
return ue;
}
- else if (e1.type.isreal())
+ else if (e1.type.isReal())
{
r1 = e1.toReal();
r2 = e2.toReal();
goto L1;
}
- else if (e1.type.isimaginary())
+ else if (e1.type.isImaginary())
{
r1 = e1.toImaginary();
r2 = e2.toImaginary();
@@ -785,11 +785,11 @@ UnionExp Equal(EXP op, const ref Loc loc, Type type, Expression e1, Expression e
cmp = (r1 == r2);
}
}
- else if (e1.type.iscomplex())
+ else if (e1.type.isComplex())
{
cmp = e1.toComplex() == e2.toComplex();
}
- else if (e1.type.isintegral() || e1.type.toBasetype().ty == Tpointer)
+ else if (e1.type.isIntegral() || e1.type.toBasetype().ty == Tpointer)
{
cmp = (e1.toInteger() == e2.toInteger());
}
@@ -824,7 +824,7 @@ UnionExp Identity(EXP op, const ref Loc loc, Type type, Expression e1, Expressio
}
else
{
- if (e1.type.isfloating())
+ if (e1.type.isFloating())
cmp = e1.isIdentical(e2);
else
{
@@ -866,20 +866,20 @@ UnionExp Cmp(EXP op, const ref Loc loc, Type type, Expression e1, Expression e2)
cantExp(ue);
return ue;
}
- else if (e1.type.isreal())
+ else if (e1.type.isReal())
{
r1 = e1.toReal();
r2 = e2.toReal();
goto L1;
}
- else if (e1.type.isimaginary())
+ else if (e1.type.isImaginary())
{
r1 = e1.toImaginary();
r2 = e2.toImaginary();
L1:
n = realCmp(op, r1, r2);
}
- else if (e1.type.iscomplex())
+ else if (e1.type.isComplex())
{
assert(0);
}
@@ -889,7 +889,7 @@ UnionExp Cmp(EXP op, const ref Loc loc, Type type, Expression e1, Expression e2)
sinteger_t n2;
n1 = e1.toInteger();
n2 = e2.toInteger();
- if (e1.type.isunsigned() || e2.type.isunsigned())
+ if (e1.type.isUnsigned() || e2.type.isUnsigned())
n = intUnsignedCmp(op, n1, n2);
else
n = intSignedCmp(op, n1, n2);
@@ -968,9 +968,9 @@ UnionExp Cast(const ref Loc loc, Type type, Type to, Expression e1)
emplaceExp!(IntegerExp)(&ue, loc, opt.get(), type);
}
- else if (type.isintegral())
+ else if (type.isIntegral())
{
- if (e1.type.isfloating())
+ if (e1.type.isFloating())
{
dinteger_t result;
real_t r = e1.toReal();
@@ -1008,27 +1008,27 @@ UnionExp Cast(const ref Loc loc, Type type, Type to, Expression e1)
}
emplaceExp!(IntegerExp)(&ue, loc, result, type);
}
- else if (type.isunsigned())
+ else if (type.isUnsigned())
emplaceExp!(IntegerExp)(&ue, loc, e1.toUInteger(), type);
else
emplaceExp!(IntegerExp)(&ue, loc, e1.toInteger(), type);
}
- else if (tb.isreal())
+ else if (tb.isReal())
{
real_t value = e1.toReal();
emplaceExp!(RealExp)(&ue, loc, value, type);
}
- else if (tb.isimaginary())
+ else if (tb.isImaginary())
{
real_t value = e1.toImaginary();
emplaceExp!(RealExp)(&ue, loc, value, type);
}
- else if (tb.iscomplex())
+ else if (tb.isComplex())
{
complex_t value = e1.toComplex();
emplaceExp!(ComplexExp)(&ue, loc, value, type);
}
- else if (tb.isscalar())
+ else if (tb.isScalar())
{
emplaceExp!(IntegerExp)(&ue, loc, e1.toInteger(), type);
}
@@ -1494,7 +1494,7 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
assert(ue.exp().type);
return ue;
}
- else if (e2.op == EXP.string_ && e1.op == EXP.arrayLiteral && t1.nextOf().isintegral())
+ else if (e2.op == EXP.string_ && e1.op == EXP.arrayLiteral && t1.nextOf().isIntegral())
{
// [chars] ~ string --> [chars]
StringExp es = e2.isStringExp();
@@ -1511,7 +1511,7 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
assert(ue.exp().type);
return ue;
}
- else if (e1.op == EXP.string_ && e2.op == EXP.arrayLiteral && t2.nextOf().isintegral())
+ else if (e1.op == EXP.string_ && e2.op == EXP.arrayLiteral && t2.nextOf().isIntegral())
{
// string ~ [chars] --> [chars]
StringExp es = e1.isStringExp();
@@ -1120,75 +1120,74 @@ final class CParser(AST) : Parser!AST
*/
private AST.Expression cparseCastExp()
{
- if (token.value == TOK.leftParenthesis)
+ if (token.value != TOK.leftParenthesis)
+ return cparseUnaryExp();
+
+ //printf("cparseCastExp()\n");
+ auto tk = peek(&token);
+ bool iscast;
+ bool isexp;
+ if (tk.value == TOK.identifier)
{
- //printf("cparseCastExp()\n");
- auto tk = peek(&token);
- bool iscast;
- bool isexp;
- if (tk.value == TOK.identifier)
- {
- iscast = isTypedef(tk.ident);
- isexp = !iscast;
- }
- if (isexp)
- {
- // ( identifier ) is an expression
- return cparseUnaryExp();
- }
+ iscast = isTypedef(tk.ident);
+ isexp = !iscast;
+ }
+ if (isexp)
+ {
+ // ( identifier ) is an expression
+ return cparseUnaryExp();
+ }
- // If ( type-name )
- auto pt = &token;
+ // If ( type-name )
+ auto pt = &token;
- if (isCastExpression(pt))
- {
- // Expression may be either a cast or a compound literal, which
- // requires checking whether the next token is leftCurly
- const loc = token.loc;
- nextToken();
- auto t = cparseTypeName();
- check(TOK.rightParenthesis);
- pt = &token;
+ if (!isCastExpression(pt))
+ return cparseUnaryExp();
- if (token.value == TOK.leftCurly)
- {
- // C11 6.5.2.5 ( type-name ) { initializer-list }
- auto ci = cparseInitializer();
- auto ce = new AST.CompoundLiteralExp(loc, t, ci);
- return cparsePostfixOperators(ce);
- }
+ // Expression may be either a cast or a compound literal, which
+ // requires checking whether the next token is leftCurly
+ const loc = token.loc;
+ nextToken();
+ auto t = cparseTypeName();
+ check(TOK.rightParenthesis);
+ pt = &token;
- if (iscast)
- {
- // ( type-name ) cast-expression
- auto ce = cparseCastExp();
- return new AST.CastExp(loc, ce, t);
- }
+ if (token.value == TOK.leftCurly)
+ {
+ // C11 6.5.2.5 ( type-name ) { initializer-list }
+ auto ci = cparseInitializer();
+ auto ce = new AST.CompoundLiteralExp(loc, t, ci);
+ return cparsePostfixOperators(ce);
+ }
- if (t.isTypeIdentifier() &&
- isexp &&
- token.value == TOK.leftParenthesis &&
- !isCastExpression(pt))
- {
- /* (t)(...)... might be a cast expression or a function call,
- * with different grammars: a cast would be cparseCastExp(),
- * a function call would be cparsePostfixExp(CallExp(cparseArguments())).
- * We can't know until t is known. So, parse it as a function call
- * and let semantic() rewrite the AST as a CastExp if it turns out
- * to be a type.
- */
- auto ie = new AST.IdentifierExp(loc, t.isTypeIdentifier().ident);
- ie.parens = true; // let semantic know it might be a CastExp
- AST.Expression e = new AST.CallExp(loc, ie, cparseArguments());
- return cparsePostfixOperators(e);
- }
+ if (iscast)
+ {
+ // ( type-name ) cast-expression
+ auto ce = cparseCastExp();
+ return new AST.CastExp(loc, ce, t);
+ }
- // ( type-name ) cast-expression
- auto ce = cparseCastExp();
- return new AST.CastExp(loc, ce, t);
- }
+ if (t.isTypeIdentifier() &&
+ isexp &&
+ token.value == TOK.leftParenthesis &&
+ !isCastExpression(pt))
+ {
+ /* (t)(...)... might be a cast expression or a function call,
+ * with different grammars: a cast would be cparseCastExp(),
+ * a function call would be cparsePostfixExp(CallExp(cparseArguments())).
+ * We can't know until t is known. So, parse it as a function call
+ * and let semantic() rewrite the AST as a CastExp if it turns out
+ * to be a type.
+ */
+ auto ie = new AST.IdentifierExp(loc, t.isTypeIdentifier().ident);
+ ie.parens = true; // let semantic know it might be a CastExp
+ AST.Expression e = new AST.CallExp(loc, ie, cparseArguments());
+ return cparsePostfixOperators(e);
}
- return cparseUnaryExp();
+
+ // ( type-name ) cast-expression
+ auto ce = cparseCastExp();
+ return new AST.CastExp(loc, ce, t);
}
/**************
@@ -5814,7 +5813,7 @@ final class CParser(AST) : Parser!AST
if (len == 1) // stack is now empty
packalign.setDefault();
else
- packalign = (*this.packs)[len - 1];
+ packalign = (*this.packs)[len - 2];
return closingParen();
}
while (n.value == TOK.comma) // #pragma pack ( pop ,
@@ -5956,6 +5955,30 @@ final class CParser(AST) : Parser!AST
AST.Type t;
+ bool hasMinus;
+ if (token.value == TOK.min)
+ {
+ nextToken();
+ // Only allow integer and float literals after minus.
+ switch (token.value)
+ {
+ case TOK.int32Literal:
+ case TOK.uns32Literal:
+ case TOK.int64Literal:
+ case TOK.uns64Literal:
+ case TOK.float32Literal:
+ case TOK.float64Literal:
+ case TOK.float80Literal:
+ case TOK.imaginary32Literal:
+ case TOK.imaginary64Literal:
+ case TOK.imaginary80Literal:
+ hasMinus = true;
+ break;
+ default:
+ continue;
+ }
+ }
+
Lswitch:
switch (token.value)
{
@@ -5980,6 +6003,8 @@ final class CParser(AST) : Parser!AST
* enum id = intvalue;
*/
AST.Expression e = new AST.IntegerExp(scanloc, intvalue, t);
+ if (hasMinus)
+ e = new AST.NegExp(scanloc, e);
auto v = new AST.VarDeclaration(scanloc, t, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
addSym(v);
++p;
@@ -6003,6 +6028,8 @@ final class CParser(AST) : Parser!AST
* enum id = floatvalue;
*/
AST.Expression e = new AST.RealExp(scanloc, floatvalue, t);
+ if (hasMinus)
+ e = new AST.NegExp(scanloc, e);
auto v = new AST.VarDeclaration(scanloc, t, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
addSym(v);
++p;
@@ -234,7 +234,7 @@ private final class CppMangleVisitor : Visitor
// if so, just pick up the type from the instance
if (!rt)
rt = tf.nextOf();
- if (tf.isref)
+ if (tf.isRef)
rt = rt.referenceTo();
auto prev = this.context.push(tf.nextOf());
scope (exit) this.context.pop(prev);
@@ -441,7 +441,7 @@ private final class CppMangleVisitor : Visitor
else if (t.ty == Tnull && global.params.cplusplus >= CppStdRevision.cpp11)
return true;
else
- return t.isTypeBasic() && (t.isintegral() || t.isreal());
+ return t.isTypeBasic() && (t.isIntegral() || t.isReal());
}
/******************************
@@ -484,14 +484,14 @@ private final class CppMangleVisitor : Visitor
else if (TemplateValueParameter tv = tp.isTemplateValueParameter())
{
// <expr-primary> ::= L <type> <value number> E # integer literal
- if (tv.valType.isintegral())
+ if (tv.valType.isIntegral())
{
Expression e = isExpression(o);
assert(e);
buf.writeByte('L');
tv.valType.accept(this);
auto val = e.toUInteger();
- if (!tv.valType.isunsigned() && cast(sinteger_t)val < 0)
+ if (!tv.valType.isUnsigned() && cast(sinteger_t)val < 0)
{
val = -val;
buf.writeByte('n');
@@ -1749,7 +1749,7 @@ extern(C++):
* Ds char16_t
* u <source-name> # vendor extended type
*/
- if (t.isimaginary() || t.iscomplex())
+ if (t.isImaginary() || t.isComplex())
{
// https://issues.dlang.org/show_bug.cgi?id=22806
// Complex and imaginary types are represented in the same way as
@@ -1760,7 +1760,7 @@ extern(C++):
append(t);
CV_qualifiers(t);
- if (t.isimaginary())
+ if (t.isImaginary())
buf.writeByte('G'); // 'G' means imaginary
else
buf.writeByte('C'); // 'C' means complex
@@ -1915,7 +1915,7 @@ extern(C++):
if (t.linkage == LINK.c)
buf.writeByte('Y');
Type tn = t.next;
- if (t.isref)
+ if (t.isRef)
tn = tn.referenceTo();
tn.accept(this);
mangleFunctionParameters(t.parameterList);
@@ -661,7 +661,7 @@ bool isSafePointerCast(Type srcPointee, Type destPointee)
srcPointee = srcPointee.baseElemOf();
destPointee = destPointee.baseElemOf();
}
- return srcPointee.isintegral() && destPointee.isintegral() && srcPointee.size() == destPointee.size();
+ return srcPointee.isIntegral() && destPointee.isIntegral() && srcPointee.size() == destPointee.size();
}
Expression getAggregateFromPointer(Expression e, dinteger_t* ofs)
@@ -951,7 +951,7 @@ int comparePointers(EXP op, Expression agg1, dinteger_t ofs1, Expression agg2, d
// floating point -> integer or integer -> floating point
bool isFloatIntPaint(Type to, Type from)
{
- return from.size() == to.size() && (from.isintegral() && to.isfloating() || from.isfloating() && to.isintegral());
+ return from.size() == to.size() && (from.isIntegral() && to.isFloating() || from.isFloating() && to.isIntegral());
}
// Reinterpret float/int value 'fromVal' as a float/integer of type 'to'.
@@ -1088,7 +1088,7 @@ private int ctfeCmpArrays(const ref Loc loc, Expression e1, Expression e2, uinte
// Comparing two array literals. This case is potentially recursive.
// If they aren't strings, we just need an equality check rather than
// a full cmp.
- const bool needCmp = ae1.type.nextOf().isintegral();
+ const bool needCmp = ae1.type.nextOf().isIntegral();
foreach (size_t i; 0 .. cast(size_t)len)
{
Expression ee1 = (*ae1.elements)[cast(size_t)(lo1 + i)];
@@ -1213,16 +1213,16 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide
}
return cast(int)(len1 - len2);
}
- if (e1.type.isintegral())
+ if (e1.type.isIntegral())
{
return e1.toInteger() != e2.toInteger();
}
- if (identity && e1.type.isfloating())
+ if (identity && e1.type.isFloating())
return !e1.isIdentical(e2);
- if (e1.type.isreal() || e1.type.isimaginary())
+ if (e1.type.isReal() || e1.type.isImaginary())
{
- real_t r1 = e1.type.isreal() ? e1.toReal() : e1.toImaginary();
- real_t r2 = e1.type.isreal() ? e2.toReal() : e2.toImaginary();
+ real_t r1 = e1.type.isReal() ? e1.toReal() : e1.toImaginary();
+ real_t r2 = e1.type.isReal() ? e2.toReal() : e2.toImaginary();
if (CTFloat.isNaN(r1) || CTFloat.isNaN(r2)) // if unordered
{
return 1; // they are not equal
@@ -1232,7 +1232,7 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide
return (r1 != r2);
}
}
- else if (e1.type.iscomplex())
+ else if (e1.type.isComplex())
{
return e1.toComplex() != e2.toComplex();
}
@@ -1343,7 +1343,7 @@ bool ctfeIdentity(const ref Loc loc, EXP op, Expression e1, Expression e2)
SymOffExp es2 = e2.isSymOffExp();
cmp = (es1.var == es2.var && es1.offset == es2.offset);
}
- else if (e1.type.isfloating())
+ else if (e1.type.isFloating())
cmp = e1.isIdentical(e2);
else
{
@@ -1362,11 +1362,11 @@ bool ctfeCmp(const ref Loc loc, EXP op, Expression e1, Expression e2)
if (t1.isString() && t2.isString())
return specificCmp(op, ctfeRawCmp(loc, e1, e2));
- else if (t1.isreal())
+ else if (t1.isReal())
return realCmp(op, e1.toReal(), e2.toReal());
- else if (t1.isimaginary())
+ else if (t1.isImaginary())
return realCmp(op, e1.toImaginary(), e2.toImaginary());
- else if (t1.isunsigned() || t2.isunsigned())
+ else if (t1.isUnsigned() || t2.isUnsigned())
return intUnsignedCmp(op, e1.toInteger(), e2.toInteger());
else
return intSignedCmp(op, e1.toInteger(), e2.toInteger());
@@ -1377,7 +1377,7 @@ UnionExp ctfeCat(const ref Loc loc, Type type, Expression e1, Expression e2)
Type t1 = e1.type.toBasetype();
Type t2 = e2.type.toBasetype();
UnionExp ue;
- if (e2.op == EXP.string_ && e1.op == EXP.arrayLiteral && t1.nextOf().isintegral())
+ if (e2.op == EXP.string_ && e1.op == EXP.arrayLiteral && t1.nextOf().isIntegral())
{
// [chars] ~ string => string (only valid for CTFE)
StringExp es1 = e2.isStringExp();
@@ -1406,7 +1406,7 @@ UnionExp ctfeCat(const ref Loc loc, Type type, Expression e1, Expression e2)
es.type = type;
return ue;
}
- if (e1.op == EXP.string_ && e2.op == EXP.arrayLiteral && t2.nextOf().isintegral())
+ if (e1.op == EXP.string_ && e2.op == EXP.arrayLiteral && t2.nextOf().isIntegral())
{
// string ~ [chars] => string (only valid for CTFE)
// Concatenate the strings
@@ -1775,7 +1775,7 @@ bool isCtfeValueValid(Expression newval)
case EXP.int64:
case EXP.float64:
case EXP.complex80:
- return tb.isscalar();
+ return tb.isScalar();
case EXP.null_:
return tb.ty == Tnull ||
@@ -272,7 +272,7 @@ MATCH implicitConvTo(Expression e, Type t)
/* See if we can do integral narrowing conversions
*/
- if (e.type.isintegral() && t.isintegral() && e.type.isTypeBasic() && t.isTypeBasic())
+ if (e.type.isIntegral() && t.isIntegral() && e.type.isTypeBasic() && t.isTypeBasic())
{
IntRange src = getIntRange(e);
IntRange target = IntRange.fromType(t);
@@ -321,14 +321,14 @@ MATCH implicitConvTo(Expression e, Type t)
Type t1b = e.e1.type.toBasetype();
Type t2b = e.e2.type.toBasetype();
- if (t1b.ty == Tpointer && t2b.isintegral() && t1b.equivalent(tb))
+ if (t1b.ty == Tpointer && t2b.isIntegral() && t1b.equivalent(tb))
{
// ptr + offset
// ptr - offset
MATCH m = e.e1.implicitConvTo(t);
return (m > MATCH.constant) ? MATCH.constant : m;
}
- if (t2b.ty == Tpointer && t1b.isintegral() && t2b.equivalent(tb))
+ if (t2b.ty == Tpointer && t1b.isIntegral() && t2b.equivalent(tb))
{
// offset + ptr
MATCH m = e.e2.implicitConvTo(t);
@@ -453,7 +453,7 @@ MATCH implicitConvTo(Expression e, Type t)
bool isLosslesslyConvertibleToFP(T)()
{
- if (e.type.isunsigned())
+ if (e.type.isUnsigned())
{
const f = cast(T) value;
return cast(dinteger_t) f == value;
@@ -704,7 +704,7 @@ MATCH implicitConvTo(Expression e, Type t)
return MATCH.nomatch;
m = MATCH.constant;
}
- if (e.hexString && tn.isintegral && (tn.size == e.sz || (!e.committed && (e.len % tn.size) == 0)))
+ if (e.hexString && tn.isIntegral && (tn.size == e.sz || (!e.committed && (e.len % tn.size) == 0)))
{
m = MATCH.convert;
return m;
@@ -931,7 +931,7 @@ MATCH implicitConvTo(Expression e, Type t)
*/
Type tb = t.toBasetype();
MOD mod = tb.mod;
- if (tf.isref)
+ if (tf.isRef)
{
}
else
@@ -1163,7 +1163,7 @@ MATCH implicitConvTo(Expression e, Type t)
if (result != MATCH.nomatch)
return result;
- if (t.isintegral() && e.e1.type.isintegral() && e.e1.implicitConvTo(t) != MATCH.nomatch)
+ if (t.isIntegral() && e.e1.type.isIntegral() && e.e1.implicitConvTo(t) != MATCH.nomatch)
result = MATCH.convert;
else
result = visit(e);
@@ -1947,12 +1947,12 @@ MATCH cimplicitConvTo(Expression e, Type t)
if (tb.isTypeVector() || typeb.isTypeVector())
return implicitConvTo(e, t); // permissive checking doesn't apply to vectors
- if ((typeb.isintegral() || typeb.isfloating()) &&
- (tb.isintegral() || tb.isfloating()))
+ if ((typeb.isIntegral() || typeb.isFloating()) &&
+ (tb.isIntegral() || tb.isFloating()))
return MATCH.convert;
- if (tb.ty == Tpointer && typeb.isintegral()) // C11 6.3.2.3-5
+ if (tb.ty == Tpointer && typeb.isIntegral()) // C11 6.3.2.3-5
return MATCH.convert;
- if (tb.isintegral() && typeb.ty == Tpointer) // C11 6.3.2.3-6
+ if (tb.isIntegral() && typeb.ty == Tpointer) // C11 6.3.2.3-6
return MATCH.convert;
if (tb.ty == Tpointer && typeb.ty == Tpointer) // C11 6.3.2.3-7
return MATCH.convert;
@@ -2053,8 +2053,8 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
const(bool) t1b_isR = (t1b_isFR || t1b.ty == Tpointer || t1b.ty == Taarray || t1b.ty == Tclass);
// Arithmetic types (== valueable basic types)
- const(bool) tob_isA = ((tob.isintegral() || tob.isfloating()) && tob.ty != Tvector);
- const(bool) t1b_isA = ((t1b.isintegral() || t1b.isfloating()) && t1b.ty != Tvector);
+ const(bool) tob_isA = ((tob.isIntegral() || tob.isFloating()) && tob.ty != Tvector);
+ const(bool) t1b_isA = ((t1b.isIntegral() || t1b.isFloating()) && t1b.ty != Tvector);
// Try casting the alias this member.
// Return the expression if it succeeds, null otherwise.
@@ -2257,7 +2257,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
{
if (!e.type.equals(t))
{
- if ((e.type.isreal() && t.isreal()) || (e.type.isimaginary() && t.isimaginary()))
+ if ((e.type.isReal() && t.isReal()) || (e.type.isImaginary() && t.isImaginary()))
{
auto result = e.copy();
result.type = t;
@@ -2273,7 +2273,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
{
if (!e.type.equals(t))
{
- if (e.type.iscomplex() && t.iscomplex())
+ if (e.type.isComplex() && t.isComplex())
{
auto result = e.copy();
result.type = t;
@@ -3219,7 +3219,7 @@ Expression scaleFactor(BinExp be, Scope* sc)
Type t2b = be.e2.type.toBasetype();
Expression eoff;
- if (t1b.ty == Tpointer && t2b.isintegral())
+ if (t1b.ty == Tpointer && t2b.isIntegral())
{
// Need to adjust operator by the stride
// Replace (ptr + int) with (ptr + (int * stride))
@@ -3233,7 +3233,7 @@ Expression scaleFactor(BinExp be, Scope* sc)
be.e2.type = t;
be.type = be.e1.type;
}
- else if (t2b.ty == Tpointer && t1b.isintegral())
+ else if (t2b.ty == Tpointer && t1b.isIntegral())
{
// Need to adjust operator by the stride
// Replace (int + ptr) with (ptr + (int * stride))
@@ -3361,11 +3361,11 @@ Type typeMerge(Scope* sc, EXP op, ref Expression pe1, ref Expression pe2)
// Integral types can be implicitly converted to pointers
if ((t1b.ty == Tpointer) != (t2b.ty == Tpointer))
{
- if (t1b.isintegral())
+ if (t1b.isIntegral())
{
return convert(e1, t2b);
}
- else if (t2b.isintegral())
+ else if (t2b.isIntegral())
{
return convert(e2, t1b);
}
@@ -3487,8 +3487,8 @@ Lagain:
d.purity = PURE.impure;
assert(d.purity != PURE.fwdref);
- d.isnothrow = (tf1.isnothrow && tf2.isnothrow);
- d.isnogc = (tf1.isnogc && tf2.isnogc);
+ d.isNothrow = (tf1.isNothrow && tf2.isNothrow);
+ d.isNogc = (tf1.isNogc && tf2.isNogc);
if (tf1.trust == tf2.trust)
d.trust = tf1.trust;
@@ -3878,7 +3878,7 @@ LmergeClassTypes:
goto Lagain;
}
- if (t1.isintegral() && t2.isintegral())
+ if (t1.isIntegral() && t2.isIntegral())
{
if (t1.ty != t2.ty)
{
@@ -1716,7 +1716,7 @@ extern (C++) class BitFieldDeclaration : VarDeclaration
final ulong getMinMax(Identifier id)
{
const width = fieldWidth;
- const uns = type.isunsigned();
+ const uns = type.isUnsigned();
const min = id == Id.min;
ulong v;
assert(width != 0); // should have been rejected in semantic pass
@@ -720,9 +720,9 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
}
}
- if (tf.isref && e.op == EXP.variable && e.isVarExp().var == fd.vthis)
+ if (tf.isRef && e.op == EXP.variable && e.isVarExp().var == fd.vthis)
e = thisarg;
- if (tf.isref && fd.hasDualContext() && e.op == EXP.index)
+ if (tf.isRef && fd.hasDualContext() && e.op == EXP.index)
{
auto ie = e.isIndexExp();
auto pe = ie.e1.isPtrExp();
@@ -999,7 +999,7 @@ Expression interpretStatement(UnionExp* pue, Statement s, InterState* istate)
/* If the function returns a ref AND it's been called from an assignment,
* we need to return an lvalue. Otherwise, just do an (rvalue) interpret.
*/
- if (tf.isref)
+ if (tf.isRef)
{
result = interpret(pue, s.exp, istate, CTFEGoal.LValue);
return;
@@ -2928,7 +2928,7 @@ public:
result = eref;
return;
}
- if (e.newtype.toBasetype().isscalar())
+ if (e.newtype.toBasetype().isScalar())
{
Expression newval;
if (e.arguments && e.arguments.length)
@@ -3027,7 +3027,7 @@ public:
result = pointerDifference(pue, e.loc, e.type, e1, e2);
return;
}
- if (e.e1.type.ty == Tpointer && e.e2.type.isintegral())
+ if (e.e1.type.ty == Tpointer && e.e2.type.isIntegral())
{
UnionExp ue1 = void;
Expression e1 = interpret(&ue1, e.e1, istate);
@@ -3040,7 +3040,7 @@ public:
result = pointerArithmetic(pue, e.loc, e.op, e.type, e1, e2);
return;
}
- if (e.e2.type.ty == Tpointer && e.e1.type.isintegral() && e.op == EXP.add)
+ if (e.e2.type.ty == Tpointer && e.e1.type.isIntegral() && e.op == EXP.add)
{
UnionExp ue1 = void;
Expression e1 = interpret(&ue1, e.e1, istate);
@@ -3636,7 +3636,7 @@ public:
newval = (*fp)(e.loc, e.type, oldval, newval).copy();
}
- else if (e.e2.type.isintegral() &&
+ else if (e.e2.type.isIntegral() &&
(e.op == EXP.addAssign ||
e.op == EXP.minAssign ||
e.op == EXP.plusPlus ||
@@ -3869,7 +3869,7 @@ public:
if (auto bf = v.isBitFieldDeclaration())
{
sinteger_t value = ival.toInteger();
- if (bf.type.isunsigned())
+ if (bf.type.isUnsigned())
value &= (1L << bf.fieldWidth) - 1; // zero extra bits
else
{ // sign extend extra bits
@@ -6169,9 +6169,9 @@ public:
}
else if (tobt.isTypeBasic() && e1.op == EXP.null_)
{
- if (tobt.isintegral())
+ if (tobt.isIntegral())
emplaceExp!(IntegerExp)(pue, e.loc, 0, e.to);
- else if (tobt.isreal())
+ else if (tobt.isReal())
emplaceExp!(RealExp)(pue, e.loc, CTFloat.zero, e.to);
result = pue.exp();
return;
@@ -358,31 +358,31 @@ void mangleFuncType(TypeFunction t, TypeFunction ta, ubyte modMask, Type tret, r
if (ta.purity)
buf.writestring("Na");
- if (ta.isnothrow)
+ if (ta.isNothrow)
buf.writestring("Nb");
- if (ta.isref)
+ if (ta.isRef)
buf.writestring("Nc");
- if (ta.isproperty)
+ if (ta.isProperty)
buf.writestring("Nd");
- if (ta.isnogc)
+ if (ta.isNogc)
buf.writestring("Ni");
// `return scope` must be in that order
- if (ta.isreturnscope && !ta.isreturninferred)
+ if (ta.isReturnScope && !ta.isReturnInferred)
{
buf.writestring("NjNl");
}
else
{
// when return ref, the order is `scope return`
- if (ta.isScopeQual && !ta.isscopeinferred)
+ if (ta.isScopeQual && !ta.isScopeInferred)
buf.writestring("Nl");
- if (ta.isreturn && !ta.isreturninferred)
+ if (ta.isReturn && !ta.isReturnInferred)
buf.writestring("Nj");
}
- if (ta.islive)
+ if (ta.isLive)
buf.writestring("Nm");
switch (ta.trust)
@@ -133,7 +133,7 @@ AlignDeclaration getAlignment(AlignDeclaration ad, Scope* sc)
if (sc.inCfile && n == 0) // C11 6.7.5-6 allows 0 for alignment
continue;
- if (n < 1 || n & (n - 1) || ushort.max < n || !e.type.isintegral())
+ if (n < 1 || n & (n - 1) || ushort.max < n || !e.type.isIntegral())
{
error(ad.loc, "alignment must be an integer positive power of 2, not 0x%llx", cast(ulong)n);
errors = true;
@@ -615,6 +615,15 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (ad)
dsym.storage_class |= ad.storage_class & STC.TYPECTOR;
+ if ((dsym.storage_class & STC.auto_) && (dsym.storage_class & STC.ref_))
+ {
+ if (!(dsym.storage_class & STC.autoref))
+ {
+ .error(dsym.loc, "%s `%s` - `auto ref` variable must have `auto` and `ref` adjacent", dsym.kind, dsym.toChars());
+ dsym.storage_class |= STC.autoref;
+ }
+ }
+
/* If auto type inference, do the inference
*/
int inferred = 0;
@@ -732,7 +741,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
dsym.type = Type.terror;
}
}
- if ((dsym.storage_class & STC.auto_) && !inferred)
+ if ((dsym.storage_class & STC.auto_) && !inferred && !(dsym.storage_class & STC.autoref))
.error(dsym.loc, "%s `%s` - storage class `auto` has no effect if type is not inferred, did you mean `scope`?", dsym.kind, dsym.toPrettyChars);
if (auto tt = tb.isTypeTuple())
@@ -1069,7 +1078,19 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (dsymIsRef)
{
if (!dsym._init && dsym.ident != Id.This)
- .error(dsym.loc, "%s `%s` - initializer is required for `ref` variable", dsym.kind, dsym.toPrettyChars);
+ {
+ if (dsym.storage_class & STC.autoref)
+ {
+ dsymIsRef = false;
+ dsym.storage_class &= ~STC.ref_;
+ }
+ else
+ .error(dsym.loc, "%s `%s` - initializer is required for `ref` variable", dsym.kind, dsym.toPrettyChars);
+ }
+ else if (dsym._init.isVoidInitializer())
+ {
+ .error(dsym.loc, "%s `%s` - void initializer not allowed for `ref` variable", dsym.kind, dsym.toPrettyChars);
+ }
}
FuncDeclaration fd = parent.isFuncDeclaration();
@@ -1303,6 +1324,18 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
Expression exp = ei.exp;
Expression e1 = new VarExp(dsym.loc, dsym);
+
+ void constructInit(bool isBlit)
+ {
+ if (isBlit)
+ exp = new BlitExp(dsym.loc, e1, exp);
+ else
+ exp = new ConstructExp(dsym.loc, e1, exp);
+ dsym.canassign++;
+ exp = exp.expressionSemantic(sc);
+ dsym.canassign--;
+ }
+
if (dsymIsRef) // follow logic similar to typesem.argumentMatchParameter() and statementsem.visitForeach()
{
dsym.storage_class |= STC.nodtor;
@@ -1311,31 +1344,38 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
Type ta = exp.type;
if (!exp.isLvalue())
{
- .error(dsym.loc, "rvalue `%s` cannot be assigned to `ref %s`", exp.toChars(), dsym.toChars());
- exp = ErrorExp.get();
+ if (dsym.storage_class & STC.autoref)
+ {
+ dsym.storage_class &= ~STC.ref_;
+ constructInit(isBlit);
+ }
+ else
+ {
+ .error(dsym.loc, "rvalue `%s` cannot be assigned to `ref %s`", exp.toChars(), dsym.toChars());
+ exp = ErrorExp.get();
+ }
}
else if (!ta.constConv(tp))
{
- .error(dsym.loc, "type `%s` cannot be assigned to `ref %s %s`", ta.toChars(), tp.toChars(), dsym.toChars());
- exp = ErrorExp.get();
+ if (dsym.storage_class & STC.autoref)
+ {
+ dsym.storage_class &= ~STC.ref_;
+ constructInit(false);
+ }
+ else
+ {
+ .error(dsym.loc, "type `%s` cannot be assigned to `ref %s %s`", ta.toChars(), tp.toChars(), dsym.toChars());
+ exp = ErrorExp.get();
+ }
}
else
{
- exp = new ConstructExp(dsym.loc, e1, exp);
- dsym.canassign++;
- exp = exp.expressionSemantic(sc);
- dsym.canassign--;
+ constructInit(false);
}
}
else
{
- if (isBlit)
- exp = new BlitExp(dsym.loc, e1, exp);
- else
- exp = new ConstructExp(dsym.loc, e1, exp);
- dsym.canassign++;
- exp = exp.expressionSemantic(sc);
- dsym.canassign--;
+ constructInit(isBlit);
}
if (exp.op == EXP.error)
@@ -1530,7 +1570,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
auto width = dsym.width.expressionSemantic(sc);
sc = sc.endCTFE();
width = width.ctfeInterpret();
- if (!dsym.type.isintegral())
+ if (!dsym.type.isIntegral())
{
// C11 6.7.2.1-5
error(width.loc, "bit-field type `%s` is not an integer type", dsym.type.toChars());
@@ -5318,9 +5358,11 @@ void aliasSemantic(AliasDeclaration ds, Scope* sc)
mt.ident != Id.This && mt.ident != Id._super)
{
s = tident.toDsymbol(sc);
- if (s && s.isVarDeclaration()) {
- error(mt.loc, "cannot alias member of variable `%s`", mt.ident.toChars());
- errorSupplemental(mt.loc, "Use `typeof(%s)` instead to preserve behaviour",
+ // don't error for `var1.static_symbol`
+ if (s && s.needThis()) {
+ error(ds.loc, "cannot alias %s member `%s` of variable `%s`",
+ s.kind(), s.toChars(), mt.ident.toChars());
+ errorSupplemental(ds.loc, "Use `typeof(%s)` instead to preserve behaviour",
mt.ident.toChars());
}
}
@@ -1839,7 +1839,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, ref TemplateParameters pa
Parameter a = t.parameterList[i];
- if (!a.isCovariant(t.isref, ap) ||
+ if (!a.isCovariant(t.isRef, ap) ||
!deduceType(a.type, sc, ap.type, parameters, dedtypes))
{
result = MATCH.nomatch;
@@ -2324,7 +2324,7 @@ public:
assert(tf.next, fd.loc.toChars().toDString());
tf.next == AST.Type.tsize_t ? originalType.next.accept(this) : tf.next.accept(this);
- if (tf.isref)
+ if (tf.isRef)
buf.writeByte('&');
buf.writeByte(' ');
@@ -699,7 +699,7 @@ void enumMemberSemantic(Scope* sc, EnumMember em)
if (e.op == EXP.error)
return errorReturn();
- if (e.type.isfloating())
+ if (e.type.isFloating())
{
// Check that e != eprev (not always true for floats)
Expression etest = new EqualExp(EXP.equal, em.loc, e, eprev);
@@ -179,7 +179,7 @@ bool checkMutableArguments(ref Scope sc, FuncDeclaration fd, TypeFunction tf,
if (!(eb.isMutable || eb2.isMutable))
return;
- if (!tf.islive && !(sc.useDIP1000 == FeatureState.enabled && sc.func && sc.func.setUnsafe()))
+ if (!tf.isLive && !(sc.useDIP1000 == FeatureState.enabled && sc.func && sc.func.setUnsafe()))
return;
if (!gag)
@@ -567,7 +567,7 @@ public
ReturnParamDest returnParamDest(TypeFunction tf, Type tthis)
{
assert(tf);
- if (tf.isctor)
+ if (tf.isCtor)
return ReturnParamDest.this_;
if (!tf.nextOf() || (tf.nextOf().ty != Tvoid))
@@ -612,17 +612,6 @@ bool checkAssignEscape(ref Scope sc, Expression e, bool gag, bool byRef)
if (!e1.type.hasPointers())
return false;
- if (e1.isSliceExp())
- {
- if (VarDeclaration va = expToVariable(e1))
- {
- if (!va.type.toBasetype().isTypeSArray() || // treat static array slice same as a variable
- !va.type.hasPointers())
- return false;
- }
- else
- return false;
- }
/* The struct literal case can arise from the S(e2) constructor call:
* return S(e2);
@@ -633,7 +622,24 @@ bool checkAssignEscape(ref Scope sc, Expression e, bool gag, bool byRef)
if (e1.isStructLiteralExp())
return false;
- VarDeclaration va = expToVariable(e1);
+ int deref;
+ VarDeclaration va = expToVariable(e1, deref);
+ // transitive scope not implemented, so can't assign scope pointers to a dereferenced variable
+ if (deref > 0)
+ va = null;
+
+ if (e1.isSliceExp())
+ {
+ // slice-copy is not assigning a pointer, but copying array content
+ if (va)
+ {
+ if (!va.type.toBasetype().isTypeSArray() || // treat static array slice same as a variable
+ !va.type.hasPointers())
+ return false;
+ }
+ else
+ return false;
+ }
if (va && e.op == EXP.concatenateElemAssign)
{
@@ -647,18 +653,6 @@ bool checkAssignEscape(ref Scope sc, Expression e, bool gag, bool byRef)
va = null;
}
- if (va && e1.isDotVarExp() && va.type.toBasetype().isTypeClass())
- {
- /* https://issues.dlang.org/show_bug.cgi?id=17949
- * Draw an equivalence between:
- * *q = p;
- * and:
- * va.field = e2;
- * since we are not assigning to va, but are assigning indirectly through class reference va.
- */
- va = null;
- }
-
if (e.op == EXP.construct && va && (va.storage_class & STC.temp) && va._init)
{
// Initializing a temporary is safe, `escapeExp` will forward such vars
@@ -734,8 +728,6 @@ bool checkAssignEscape(ref Scope sc, Expression e, bool gag, bool byRef)
msg = "scope variable `%s` assigned to return scope `%s`";
break;
case EnclosedBy.longerScope:
- if (v.storage_class & STC.temp)
- return;
msg = "scope variable `%s` assigned to `%s` with longer lifetime";
break;
case EnclosedBy.refVar:
@@ -1052,7 +1044,7 @@ bool checkNewEscape(ref Scope sc, Expression e, bool gag)
return;
if (auto tf = func.type.isTypeFunction())
{
- if (!tf.isref)
+ if (!tf.isRef)
return;
const(char)* msg = "storing reference to outer local variable `%s` into allocated memory causes it to escape";
@@ -1339,7 +1331,7 @@ private bool checkReturnEscapeImpl(ref Scope sc, Expression e, bool refs, bool g
if (fd && fd.type && fd.type.ty == Tfunction)
{
TypeFunction tf = fd.type.isTypeFunction();
- if (tf.isref)
+ if (tf.isRef)
{
const(char)* msg = "escaping reference to outer local variable `%s`";
if (!gag)
@@ -1443,9 +1435,9 @@ private bool inferReturn(FuncDeclaration fd, VarDeclaration v, bool returnScope)
if (auto tf = fd.type.isTypeFunction())
{
//printf("'this' too %p %s\n", tf, sc.func.toChars());
- tf.isreturnscope = returnScope;
- tf.isreturn = true;
- tf.isreturninferred = true;
+ tf.isReturnScope = returnScope;
+ tf.isReturn = true;
+ tf.isReturnInferred = true;
}
}
else
@@ -1729,7 +1721,7 @@ void escapeExp(Expression e, ref scope EscapeByResults er, int deref)
if (!tf)
return;
- if (deref < 0 && !tf.isref)
+ if (deref < 0 && !tf.isRef)
{
er.byExp(e, er.inRetRefTransition > 0);
return;
@@ -1764,12 +1756,12 @@ void escapeExp(Expression e, ref scope EscapeByResults er, int deref)
const stc = tf.parameterStorageClass(null, p);
ScopeRef psr = buildScopeRef(stc);
- // For struct constructors, `tf.isref` is true, but for escape analysis,
+ // For struct constructors, `tf.isRef` is true, but for escape analysis,
// it's as if they return `void` and escape through the first (`this`) parameter:
// void assign(ref S this, return scope constructorArgs...)
// If you then return the constructed result by value, it doesn't count
// as dereferencing the scope arguments, they're still escaped.
- const isRef = tf.isref && !(tf.isctor && paramDeref(psr) == 0);
+ const isRef = tf.isRef && !(tf.isCtor && paramDeref(psr) == 0);
const maybeInaccurate = deref == 0 && paramDeref(psr) == 0;
er.inRetRefTransition += maybeInaccurate;
if (paramDeref(psr) <= 0)
@@ -1799,15 +1791,15 @@ void escapeExp(Expression e, ref scope EscapeByResults er, int deref)
const psr = buildScopeRef(getThisStorageClass(fd));
er.inRetRefTransition += (psr == ScopeRef.ReturnRef_Scope);
if (paramDeref(psr) <= 0)
- escapeExp(dve.e1, er, deref + paramDeref(psr) + (tf.isref && !tf.isctor));
+ escapeExp(dve.e1, er, deref + paramDeref(psr) + (tf.isRef && !tf.isCtor));
er.inRetRefTransition -= (psr == ScopeRef.ReturnRef_Scope);
}
// The return value of a delegate call with return (scope) may point to a closure variable,
// so escape the delegate in case it's `scope` / stack allocated.
- if (t1.isTypeDelegate() && tf.isreturn)
+ if (t1.isTypeDelegate() && tf.isReturn)
{
- escapeExp(e.e1, er, deref + tf.isref);
+ escapeExp(e.e1, er, deref + tf.isRef);
}
// If `fd` is a nested function that's return ref / return scope, check that
@@ -1816,7 +1808,7 @@ void escapeExp(Expression e, ref scope EscapeByResults er, int deref)
{
if (FuncDeclaration fd = ve.var.isFuncDeclaration())
{
- if (fd.isNested() && tf.isreturn)
+ if (fd.isNested() && tf.isReturn)
{
er.byFunc(fd, true);
}
@@ -1873,9 +1865,9 @@ StorageClass getThisStorageClass(FuncDeclaration fd)
{
StorageClass stc;
auto tf = fd.type.toBasetype().isTypeFunction();
- if (tf.isreturn)
+ if (tf.isReturn)
stc |= STC.return_;
- if (tf.isreturnscope)
+ if (tf.isReturnScope)
stc |= STC.returnScope | STC.scope_;
auto ad = fd.isThis();
if ((ad && ad.isClassDeclaration()) || tf.isScopeQual)
@@ -2037,10 +2029,10 @@ void finishScopeParamInference(FuncDeclaration funcdecl, ref TypeFunction f)
{
if (funcdecl.type == f)
f = cast(TypeFunction)f.copy();
- f.isreturn = true;
- f.isreturnscope = cast(bool) (funcdecl.storage_class & STC.returnScope);
+ f.isReturn = true;
+ f.isReturnScope = cast(bool) (funcdecl.storage_class & STC.returnScope);
if (funcdecl.storage_class & STC.returninferred)
- f.isreturninferred = true;
+ f.isReturnInferred = true;
}
@@ -2063,7 +2055,7 @@ void finishScopeParamInference(FuncDeclaration funcdecl, ref TypeFunction f)
{
inferScope(funcdecl.vthis);
f.isScopeQual = funcdecl.vthis.isScope();
- f.isscopeinferred = !!(funcdecl.vthis.storage_class & STC.scopeinferred);
+ f.isScopeInferred = !!(funcdecl.vthis.storage_class & STC.scopeinferred);
}
}
@@ -2218,9 +2210,6 @@ bool setUnsafeDIP1000(ref Scope sc, bool gag, Loc loc, const(char)* msg,
*/
private bool checkScopeVarAddr(VarDeclaration v, Expression e, ref Scope sc, bool gag)
{
- if (v.storage_class & STC.temp)
- return false;
-
if (!v.isScope())
{
doNotInferScope(v, e);
@@ -237,45 +237,49 @@ DotIdExp typeDotIdExp(const ref Loc loc, Type type, Identifier ident) @safe
* For example, `a[index]` is really `a`, and `s.f` is really `s`.
* Params:
* e = Expression to look at
+ * deref = number of dereferences encountered
* Returns:
* variable if there is one, null if not
*/
-VarDeclaration expToVariable(Expression e)
+VarDeclaration expToVariable(Expression e, out int deref)
{
+ deref = 0;
while (1)
{
switch (e.op)
{
case EXP.variable:
- return (cast(VarExp)e).var.isVarDeclaration();
+ return e.isVarExp().var.isVarDeclaration();
case EXP.dotVariable:
- e = (cast(DotVarExp)e).e1;
+ e = e.isDotVarExp().e1;
+ if (e.type.toBasetype().isTypeClass())
+ deref++;
+
continue;
case EXP.index:
{
- IndexExp ei = cast(IndexExp)e;
- e = ei.e1;
- Type ti = e.type.toBasetype();
- if (ti.ty == Tsarray)
- continue;
- return null;
+ e = e.isIndexExp().e1;
+ if (!e.type.toBasetype().isTypeSArray())
+ deref++;
+
+ continue;
}
case EXP.slice:
{
- SliceExp ei = cast(SliceExp)e;
- e = ei.e1;
- Type ti = e.type.toBasetype();
- if (ti.ty == Tsarray)
- continue;
- return null;
+ e = e.isSliceExp().e1;
+ if (!e.type.toBasetype().isTypeSArray())
+ deref++;
+
+ continue;
}
- case EXP.this_:
case EXP.super_:
- return (cast(ThisExp)e).var.isVarDeclaration();
+ return e.isSuperExp().var.isVarDeclaration();
+ case EXP.this_:
+ return e.isThisExp().var.isVarDeclaration();
// Temporaries for rvalues that need destruction
// are of form: (T s = rvalue, s). For these cases
@@ -554,7 +558,7 @@ extern (C++) abstract class Expression : ASTNode
return true;
if (type.toBasetype().ty == Terror)
return true;
- if (!type.isscalar())
+ if (!type.isScalar())
{
error(loc, "`%s` is not a scalar, it is a `%s`", toChars(), type.toChars());
return true;
@@ -582,7 +586,7 @@ extern (C++) abstract class Expression : ASTNode
return true;
if (type.toBasetype().ty == Terror)
return true;
- if (!type.isintegral())
+ if (!type.isIntegral())
{
error(loc, "`%s` is not of integral type, it is a `%s`", toChars(), type.toChars());
return true;
@@ -596,7 +600,7 @@ extern (C++) abstract class Expression : ASTNode
return true;
if (type.toBasetype().ty == Terror)
return true;
- if (!type.isintegral() && !type.isfloating())
+ if (!type.isIntegral() && !type.isFloating())
{
// unary aggregate ops error here
const char* msg = type.isAggregate() ?
@@ -875,7 +879,7 @@ extern (C++) final class IntegerExp : Expression
super(loc, EXP.int64);
//printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type.toChars() : "");
assert(type);
- if (!type.isscalar())
+ if (!type.isScalar())
{
//printf("%s, loc = %d\n", toChars(), loc.linnum);
if (type.ty != Terror)
@@ -1195,12 +1199,12 @@ extern (C++) final class RealExp : Expression
override real_t toReal()
{
- return type.isreal() ? value : CTFloat.zero;
+ return type.isReal() ? value : CTFloat.zero;
}
override real_t toImaginary()
{
- return type.isreal() ? CTFloat.zero : value;
+ return type.isReal() ? CTFloat.zero : value;
}
override complex_t toComplex()
@@ -3606,7 +3610,7 @@ extern (C++) final class CallExp : UnaExp
if (tb.ty == Tdelegate || tb.ty == Tpointer)
tb = tb.nextOf();
auto tf = tb.isTypeFunction();
- if (tf && tf.isref)
+ if (tf && tf.isRef)
{
if (auto dve = e1.isDotVarExp())
if (dve.var.isCtorDeclaration())
@@ -402,12 +402,12 @@ private Expression checkOpAssignTypes(BinExp binExp, Scope* sc)
// T opAssign floating yields a floating. Prevent truncating conversions (float to int).
// See https://issues.dlang.org/show_bug.cgi?id=3841.
- // Should we also prevent double to float (type.isfloating() && type.size() < t2.size()) ?
+ // Should we also prevent double to float (type.isFloating() && type.size() < t2.size()) ?
if (op == EXP.addAssign || op == EXP.minAssign ||
op == EXP.mulAssign || op == EXP.divAssign || op == EXP.modAssign ||
op == EXP.powAssign)
{
- if ((type.isintegral() && t2.isfloating()))
+ if ((type.isIntegral() && t2.isFloating()))
{
warning(loc, "`%s %s %s` is performing truncating conversion", type.toChars(), EXPtoString(op).ptr, t2.toChars());
}
@@ -419,17 +419,17 @@ private Expression checkOpAssignTypes(BinExp binExp, Scope* sc)
// Any multiplication by an imaginary or complex number yields a complex result.
// r *= c, i*=c, r*=i, i*=i are all forbidden operations.
const(char)* opstr = EXPtoString(op).ptr;
- if (t1.isreal() && t2.iscomplex())
+ if (t1.isReal() && t2.isComplex())
{
error(loc, "`%s %s %s` is undefined. Did you mean `%s %s %s.re`?", t1.toChars(), opstr, t2.toChars(), t1.toChars(), opstr, t2.toChars());
return ErrorExp.get();
}
- else if (t1.isimaginary() && t2.iscomplex())
+ else if (t1.isImaginary() && t2.isComplex())
{
error(loc, "`%s %s %s` is undefined. Did you mean `%s %s %s.im`?", t1.toChars(), opstr, t2.toChars(), t1.toChars(), opstr, t2.toChars());
return ErrorExp.get();
}
- else if ((t1.isreal() || t1.isimaginary()) && t2.isimaginary())
+ else if ((t1.isReal() || t1.isImaginary()) && t2.isImaginary())
{
error(loc, "`%s %s %s` is an undefined operation", t1.toChars(), opstr, t2.toChars());
return ErrorExp.get();
@@ -441,31 +441,31 @@ private Expression checkOpAssignTypes(BinExp binExp, Scope* sc)
{
// Addition or subtraction of a real and an imaginary is a complex result.
// Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations.
- if ((t1.isreal() && (t2.isimaginary() || t2.iscomplex())) || (t1.isimaginary() && (t2.isreal() || t2.iscomplex())))
+ if ((t1.isReal() && (t2.isImaginary() || t2.isComplex())) || (t1.isImaginary() && (t2.isReal() || t2.isComplex())))
{
error(loc, "`%s %s %s` is undefined (result is complex)", t1.toChars(), EXPtoString(op).ptr, t2.toChars());
return ErrorExp.get();
}
- if (type.isreal() || type.isimaginary())
+ if (type.isReal() || type.isImaginary())
{
- assert(global.errors || t2.isfloating());
+ assert(global.errors || t2.isFloating());
e2 = e2.castTo(sc, t1);
}
}
if (op == EXP.mulAssign)
{
- if (t2.isfloating())
+ if (t2.isFloating())
{
- if (t1.isreal())
+ if (t1.isReal())
{
- if (t2.isimaginary() || t2.iscomplex())
+ if (t2.isImaginary() || t2.isComplex())
{
e2 = e2.castTo(sc, t1);
}
}
- else if (t1.isimaginary())
+ else if (t1.isImaginary())
{
- if (t2.isimaginary() || t2.iscomplex())
+ if (t2.isImaginary() || t2.isComplex())
{
switch (t1.ty)
{
@@ -491,9 +491,9 @@ private Expression checkOpAssignTypes(BinExp binExp, Scope* sc)
}
else if (op == EXP.divAssign)
{
- if (t2.isimaginary())
+ if (t2.isImaginary())
{
- if (t1.isreal())
+ if (t1.isReal())
{
// x/iv = i(-x/v)
// Therefore, the result is 0
@@ -503,7 +503,7 @@ private Expression checkOpAssignTypes(BinExp binExp, Scope* sc)
e.type = t1;
return e;
}
- else if (t1.isimaginary())
+ else if (t1.isImaginary())
{
Type t3;
switch (t1.ty)
@@ -532,7 +532,7 @@ private Expression checkOpAssignTypes(BinExp binExp, Scope* sc)
}
else if (op == EXP.modAssign)
{
- if (t2.iscomplex())
+ if (t2.isComplex())
{
error(loc, "cannot perform modulo complex arithmetic");
return ErrorExp.get();
@@ -1375,12 +1375,12 @@ Expression resolvePropertiesOnly(Scope* sc, Expression e1)
auto td = s.isTemplateDeclaration();
if (fd)
{
- if (fd.type.isTypeFunction().isproperty)
+ if (fd.type.isTypeFunction().isProperty)
return resolveProperties(sc, e1);
}
else if (td && td.onemember && (fd = td.onemember.isFuncDeclaration()) !is null)
{
- if (fd.type.isTypeFunction().isproperty ||
+ if (fd.type.isTypeFunction().isProperty ||
(fd.storage_class2 & STC.property) ||
(td._scope.stc & STC.property))
return resolveProperties(sc, e1);
@@ -1396,7 +1396,7 @@ Expression resolvePropertiesOnly(Scope* sc, Expression e1)
{
if (auto fd = td.onemember.isFuncDeclaration())
{
- if (fd.type.isTypeFunction().isproperty ||
+ if (fd.type.isTypeFunction().isProperty ||
(fd.storage_class2 & STC.property) ||
(td._scope.stc & STC.property))
return resolveProperties(sc, e1);
@@ -1408,7 +1408,7 @@ Expression resolvePropertiesOnly(Scope* sc, Expression e1)
Expression handleFuncDecl(FuncDeclaration fd)
{
assert(fd);
- if (fd.type.isTypeFunction().isproperty)
+ if (fd.type.isTypeFunction().isProperty)
return resolveProperties(sc, e1);
return e1;
}
@@ -2208,7 +2208,7 @@ private bool checkNogc(FuncDeclaration f, ref Loc loc, Scope* sc)
f.errorSupplementalInferredAttr(/*max depth*/ 10, /*deprecation*/ false, STC.nogc);
}
- f.checkOverriddenDtor(sc, loc, dd => dd.type.toTypeFunction().isnogc, "non-@nogc");
+ f.checkOverriddenDtor(sc, loc, dd => dd.type.toTypeFunction().isNogc, "non-@nogc");
return true;
}
@@ -2314,7 +2314,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
fd = f;
assert(fd.type.ty == Tfunction);
auto tf = fd.type.isTypeFunction();
- if (!tf.isref && e2)
+ if (!tf.isRef && e2)
{
error(loc, "%s is not an lvalue", e1.toChars());
return ErrorExp.get();
@@ -2429,7 +2429,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
if (fd.errors)
return ErrorExp.get();
TypeFunction tf = fd.type.isTypeFunction();
- if (!e2 || tf.isref)
+ if (!e2 || tf.isRef)
{
Expression e = new CallExp(loc, e1);
if (e2)
@@ -3049,7 +3049,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
}
if ((wildmatch == MODFlags.mutable || wildmatch == MODFlags.immutable_) &&
tf.next && tf.next.hasWild() &&
- (tf.isref || !tf.next.implicitConvTo(tf.next.immutableOf())))
+ (tf.isRef || !tf.next.implicitConvTo(tf.next.immutableOf())))
{
bool errorInout(MOD wildmatch)
{
@@ -3574,7 +3574,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
/* Test compliance with DIP1021 Argument Ownership and Function Calls
*/
if (global.params.useDIP1021 && (tf.trust == TRUST.safe || tf.trust == TRUST.default_) ||
- tf.islive)
+ tf.isLive)
err |= checkMutableArguments(*sc, fd, tf, ethis, arguments, false);
// If D linkage and variadic, add _arguments[] as first argument
@@ -3724,7 +3724,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
if (!e.type)
e.type = Type.tfloat64;
- else if (e.type.isimaginary && sc.inCfile)
+ else if (e.type.isImaginary && sc.inCfile)
{
/* Convert to core.stdc.config.complex
*/
@@ -5362,7 +5362,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.lowering = lowering.expressionSemantic(sc);
}
}
- else if (tb.isscalar())
+ else if (tb.isScalar())
{
if (!nargs)
{
@@ -6178,7 +6178,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = e;
return;
}
- else if (exp.e1.op == EXP.type && t1.isscalar())
+ else if (exp.e1.op == EXP.type && t1.isScalar())
{
Expression e;
@@ -6630,7 +6630,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
err = true;
}
- if (!tf.isnogc && sc.func.setGC(exp.loc, "`@nogc` %s `%s` cannot call non-@nogc `%s`", exp.e1))
+ if (!tf.isNogc && sc.func.setGC(exp.loc, "`@nogc` %s `%s` cannot call non-@nogc `%s`", exp.e1))
{
error(exp.loc, "`@nogc` %s `%s` cannot call non-@nogc %s `%s`",
sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
@@ -7561,7 +7561,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
else if (exp.checkNoBool())
return setError();
- if ((exp.op == EXP.addAssign || exp.op == EXP.minAssign) && exp.e1.type.toBasetype().ty == Tpointer && exp.e2.type.toBasetype().isintegral())
+ if ((exp.op == EXP.addAssign || exp.op == EXP.minAssign) && exp.e1.type.toBasetype().ty == Tpointer && exp.e2.type.toBasetype().isIntegral())
{
result = scaleFactor(exp, sc);
return;
@@ -8737,7 +8737,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
* &a[i]
* check 'a' the same as for a regular variable
*/
- if (VarDeclaration v = expToVariable(exp.e1))
+ int deref;
+ if (VarDeclaration v = expToVariable(exp.e1, deref))
{
v.checkPurity(exp.e1.loc, sc);
}
@@ -9116,6 +9117,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
+ // https://issues.dlang.org/show_bug.cgi?id=24701
+ auto r = checkNoreturnVarAccess(exp.e1);
+ if (r != exp.e1 && exp.to && !exp.to.isTypeNoreturn())
+ {
+ result = r;
+ return;
+ }
+
if (exp.to && !exp.to.isTypeSArray() && !exp.to.isTypeFunction())
exp.e1 = exp.e1.arrayFuncConv(sc);
@@ -9823,13 +9832,16 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (sc.inCfile)
return;
- if (e.type is Type.tvoid)
+ if (!e.isGenerated)
{
- checkMustUse(e.e1, sc);
- discardValue(e.e1);
+ if (e.allowCommaExp)
+ {
+ checkMustUse(e.e1, sc);
+ discardValue(e.e1);
+ }
+ else
+ error(e.loc, "using the result of a comma expression is not allowed");
}
- else if (!e.allowCommaExp && !e.isGenerated)
- error(e.loc, "using the result of a comma expression is not allowed");
}
override void visit(IntervalExp e)
@@ -11756,7 +11768,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Type tb2 = exp.e2.type.toBasetype();
if (tb2.ty == Tarray || tb2.ty == Tsarray)
tb2 = tb2.nextOf().toBasetype();
- if ((tb1.isintegral() || tb1.isfloating()) && (tb2.isintegral() || tb2.isfloating()))
+ if ((tb1.isIntegral() || tb1.isFloating()) && (tb2.isIntegral() || tb2.isFloating()))
{
exp.type = exp.e1.type;
result = arrayOp(exp, sc);
@@ -11768,7 +11780,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.e1 = exp.e1.modifiableLvalue(sc);
}
- if ((exp.e1.type.isintegral() || exp.e1.type.isfloating()) && (exp.e2.type.isintegral() || exp.e2.type.isfloating()))
+ if ((exp.e1.type.isIntegral() || exp.e1.type.isFloating()) && (exp.e2.type.isIntegral() || exp.e2.type.isFloating()))
{
Expression e0 = null;
e = exp.reorderSettingAAElem(sc);
@@ -12135,7 +12147,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (err)
return setError();
- if (tb1.ty == Tpointer && exp.e2.type.isintegral() || tb2.ty == Tpointer && exp.e1.type.isintegral())
+ if (tb1.ty == Tpointer && exp.e2.type.isIntegral() || tb2.ty == Tpointer && exp.e1.type.isIntegral())
{
result = scaleFactor(exp, sc);
return;
@@ -12171,7 +12183,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = exp.incompatibleTypes();
return;
}
- if ((tb1.isreal() && exp.e2.type.isimaginary()) || (tb1.isimaginary() && exp.e2.type.isreal()))
+ if ((tb1.isReal() && exp.e2.type.isImaginary()) || (tb1.isImaginary() && exp.e2.type.isReal()))
{
switch (exp.type.toBasetype().ty)
{
@@ -12287,7 +12299,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
e.type = Type.tptrdiff_t;
}
}
- else if (t2.isintegral())
+ else if (t2.isIntegral())
e = scaleFactor(exp, sc);
else
{
@@ -12329,7 +12341,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = exp.incompatibleTypes();
return;
}
- if ((t1.isreal() && t2.isimaginary()) || (t1.isimaginary() && t2.isreal()))
+ if ((t1.isReal() && t2.isImaginary()) || (t1.isImaginary() && t2.isReal()))
{
switch (exp.type.ty)
{
@@ -12676,22 +12688,22 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
return setError();
- if (exp.type.isfloating())
+ if (exp.type.isFloating())
{
Type t1 = exp.e1.type;
Type t2 = exp.e2.type;
- if (t1.isreal())
+ if (t1.isReal())
{
exp.type = t2;
}
- else if (t2.isreal())
+ else if (t2.isReal())
{
exp.type = t1;
}
- else if (t1.isimaginary())
+ else if (t1.isImaginary())
{
- if (t2.isimaginary())
+ if (t2.isImaginary())
{
switch (t1.toBasetype().ty)
{
@@ -12722,7 +12734,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
else
exp.type = t2; // t2 is complex
}
- else if (t2.isimaginary())
+ else if (t2.isImaginary())
{
exp.type = t1; // t1 is complex
}
@@ -12776,15 +12788,15 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
return setError();
- if (exp.type.isfloating())
+ if (exp.type.isFloating())
{
Type t1 = exp.e1.type;
Type t2 = exp.e2.type;
- if (t1.isreal())
+ if (t1.isReal())
{
exp.type = t2;
- if (t2.isimaginary())
+ if (t2.isImaginary())
{
// x/iv = i(-x/v)
exp.e2.type = t1;
@@ -12794,13 +12806,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
}
- else if (t2.isreal())
+ else if (t2.isReal())
{
exp.type = t1;
}
- else if (t1.isimaginary())
+ else if (t1.isImaginary())
{
- if (t2.isimaginary())
+ if (t2.isImaginary())
{
switch (t1.toBasetype().ty)
{
@@ -12823,7 +12835,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
else
exp.type = t2; // t2 is complex
}
- else if (t2.isimaginary())
+ else if (t2.isImaginary())
{
exp.type = t1; // t1 is complex
}
@@ -12882,10 +12894,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
return setError();
- if (exp.type.isfloating())
+ if (exp.type.isFloating())
{
exp.type = exp.e1.type;
- if (exp.e2.type.iscomplex())
+ if (exp.e2.type.isComplex())
{
error(exp.loc, "cannot perform modulo complex arithmetic");
return setError();
@@ -13366,7 +13378,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
EXP cmpop = exp.op;
if (auto e = exp.op_overload(sc, &cmpop))
{
- if (!e.type.isscalar() && e.type.equals(exp.e1.type))
+ if (!e.type.isScalar() && e.type.equals(exp.e1.type))
{
error(exp.loc, "recursive `opCmp` expansion");
return setError();
@@ -13470,7 +13482,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
error(exp.loc, "need member function `opCmp()` for %s `%s` to compare", t1.toDsymbol(sc).kind(), t1.toChars());
return setError();
}
- else if (t1.iscomplex() || t2.iscomplex())
+ else if (t1.isComplex() || t2.isComplex())
{
error(exp.loc, "compare not defined for complex operands");
return setError();
@@ -13723,7 +13735,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (!isArrayComparison)
{
- if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating())
+ if (exp.e1.type != exp.e2.type && exp.e1.type.isFloating() && exp.e2.type.isFloating())
{
// Cast both to complex
exp.e1 = exp.e1.castTo(sc, Type.tcomplex80);
@@ -13836,7 +13848,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.type = Type.tbool;
- if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating())
+ if (exp.e1.type != exp.e2.type && exp.e1.type.isFloating() && exp.e2.type.isFloating())
{
// Cast both to complex
exp.e1 = exp.e1.castTo(sc, Type.tcomplex80);
@@ -15028,11 +15040,11 @@ MATCH matchType(FuncExp funcExp, Type to, Scope* sc, FuncExp* presult, ErrorSink
tfx.linkage, STC.undefined_);
tfy.mod = tfx.mod;
tfy.trust = tfx.trust;
- tfy.isnothrow = tfx.isnothrow;
- tfy.isnogc = tfx.isnogc;
+ tfy.isNothrow = tfx.isNothrow;
+ tfy.isNogc = tfx.isNogc;
tfy.purity = tfx.purity;
- tfy.isproperty = tfx.isproperty;
- tfy.isref = tfx.isref;
+ tfy.isProperty = tfx.isProperty;
+ tfy.isRef = tfx.isRef;
tfy.isInOutParam = tfx.isInOutParam;
tfy.isInOutQual = tfx.isInOutQual;
tfy.deco = tfy.merge().deco;
@@ -15154,10 +15166,8 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
{
if (e.var.isThisDeclaration())
return false;
- else
- return sharedError(e);
}
- else if (!allowRef && e.var.type.isShared())
+ if (!allowRef && e.var.type.isShared())
return sharedError(e);
return false;
@@ -15559,7 +15569,7 @@ Expression addDtorHook(Expression e, Scope* sc)
if (auto tf = e1.type.isTypeFunction())
{
- if (tf.isref)
+ if (tf.isRef)
return exp;
}
@@ -164,15 +164,12 @@ extern (C++) struct Ensure
*/
static Ensures* arraySyntaxCopy(Ensures* a)
{
- Ensures* b = null;
- if (a)
- {
- b = a.copy();
- foreach (i, e; *a)
- {
- (*b)[i] = e.syntaxCopy();
- }
- }
+ if (!a)
+ return null;
+
+ Ensures* b = a.copy();
+ foreach (i, e; *a)
+ (*b)[i] = e.syntaxCopy();
return b;
}
@@ -386,40 +383,38 @@ extern (C++) class FuncDeclaration : Declaration
if (this == o)
return true;
- if (auto s = isDsymbol(o))
- {
- auto fd1 = this;
- auto fd2 = s.isFuncDeclaration();
- if (!fd2)
- return false;
+ auto s = isDsymbol(o);
+ if (!s)
+ return false;
- auto fa1 = fd1.isFuncAliasDeclaration();
- auto faf1 = fa1 ? fa1.toAliasFunc() : fd1;
+ auto fd1 = this;
+ auto fd2 = s.isFuncDeclaration();
+ if (!fd2)
+ return false;
- auto fa2 = fd2.isFuncAliasDeclaration();
- auto faf2 = fa2 ? fa2.toAliasFunc() : fd2;
+ auto fa1 = fd1.isFuncAliasDeclaration();
+ auto faf1 = fa1 ? fa1.toAliasFunc() : fd1;
- if (fa1 && fa2)
- {
- return faf1.equals(faf2) && fa1.hasOverloads == fa2.hasOverloads;
- }
+ auto fa2 = fd2.isFuncAliasDeclaration();
+ auto faf2 = fa2 ? fa2.toAliasFunc() : fd2;
- bool b1 = fa1 !is null;
- if (b1 && faf1.isUnique() && !fa1.hasOverloads)
- b1 = false;
+ if (fa1 && fa2)
+ return faf1.equals(faf2) && fa1.hasOverloads == fa2.hasOverloads;
- bool b2 = fa2 !is null;
- if (b2 && faf2.isUnique() && !fa2.hasOverloads)
- b2 = false;
+ bool b1 = fa1 !is null;
+ if (b1 && faf1.isUnique() && !fa1.hasOverloads)
+ b1 = false;
- if (b1 != b2)
- return false;
+ bool b2 = fa2 !is null;
+ if (b2 && faf2.isUnique() && !fa2.hasOverloads)
+ b2 = false;
- return faf1.toParent().equals(faf2.toParent()) &&
- faf1.ident.equals(faf2.ident) &&
- faf1.type.equals(faf2.type);
- }
- return false;
+ if (b1 != b2)
+ return false;
+
+ return faf1.toParent().equals(faf2.toParent()) &&
+ faf1.ident.equals(faf2.ident) &&
+ faf1.type.equals(faf2.type);
}
/****************************************************
@@ -715,10 +710,10 @@ extern (C++) class FuncDeclaration : Declaration
if (tf.trust == TRUST.default_)
safetyInprocess = true;
- if (!tf.isnothrow)
+ if (!tf.isNothrow)
nothrowInprocess = true;
- if (!tf.isnogc)
+ if (!tf.isNogc)
nogcInprocess = true;
// Initialize for inferring STC.scope_
@@ -808,7 +803,7 @@ extern (C++) class FuncDeclaration : Declaration
//printf("isNogc() %s, inprocess: %d\n", toChars(), !!(flags & FUNCFLAG.nogcInprocess));
if (nogcInprocess)
setGC(loc, null);
- return type.toTypeFunction().isnogc;
+ return type.toTypeFunction().isNogc;
}
extern (D) final bool isNogcBypassingInference()
@@ -845,7 +840,7 @@ extern (C++) class FuncDeclaration : Declaration
else if (arg0)
nogcViolation = new AttributeViolation(loc, fmt, arg0); // call to non-@nogc function
- type.toTypeFunction().isnogc = false;
+ type.toTypeFunction().isNogc = false;
if (fes)
fes.func.setGC(Loc.init, null, null);
}
@@ -2295,33 +2290,33 @@ void errorSupplementalInferredAttr(FuncDeclaration fd, int maxDepth, bool deprec
attr = "@nogc";
}
- if (s)
+ if (!s)
+ return;
+
+ if (s.fmtStr)
{
- if (s.fmtStr)
+ errorFunc(s.loc, deprecation ?
+ "which wouldn't be `%s` because of:" :
+ "which wasn't inferred `%s` because of:", attr);
+ if (stc == STC.nogc || stc == STC.pure_)
{
- errorFunc(s.loc, deprecation ?
- "which wouldn't be `%s` because of:" :
- "which wasn't inferred `%s` because of:", attr);
- if (stc == STC.nogc || stc == STC.pure_)
- {
- auto f = (cast(Dsymbol) s.arg0).isFuncDeclaration();
- errorFunc(s.loc, s.fmtStr, f.kind(), f.toPrettyChars(), s.arg1 ? s.arg1.toChars() : "");
- }
- else
- {
- errorFunc(s.loc, s.fmtStr,
- s.arg0 ? s.arg0.toChars() : "", s.arg1 ? s.arg1.toChars() : "", s.arg2 ? s.arg2.toChars() : "");
- }
+ auto f = (cast(Dsymbol) s.arg0).isFuncDeclaration();
+ errorFunc(s.loc, s.fmtStr, f.kind(), f.toPrettyChars(), s.arg1 ? s.arg1.toChars() : "");
}
- else if (auto sa = s.arg0.isDsymbol())
+ else
{
- if (FuncDeclaration fd2 = sa.isFuncDeclaration())
+ errorFunc(s.loc, s.fmtStr,
+ s.arg0 ? s.arg0.toChars() : "", s.arg1 ? s.arg1.toChars() : "", s.arg2 ? s.arg2.toChars() : "");
+ }
+ }
+ else if (auto sa = s.arg0.isDsymbol())
+ {
+ if (FuncDeclaration fd2 = sa.isFuncDeclaration())
+ {
+ if (maxDepth > 0)
{
- if (maxDepth > 0)
- {
- errorFunc(s.loc, "which calls `%s`", fd2.toPrettyChars());
- errorSupplementalInferredAttr(fd2, maxDepth - 1, deprecation, stc);
- }
+ errorFunc(s.loc, "which calls `%s`", fd2.toPrettyChars());
+ errorSupplementalInferredAttr(fd2, maxDepth - 1, deprecation, stc);
}
}
}
@@ -332,15 +332,15 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl)
}
}
- if (tf.isref)
+ if (tf.isRef)
sc.stc |= STC.ref_;
if (tf.isScopeQual)
sc.stc |= STC.scope_;
- if (tf.isnothrow)
+ if (tf.isNothrow)
sc.stc |= STC.nothrow_;
- if (tf.isnogc)
+ if (tf.isNogc)
sc.stc |= STC.nogc;
- if (tf.isproperty)
+ if (tf.isProperty)
sc.stc |= STC.property;
if (tf.purity == PURE.fwdref)
sc.stc |= STC.pure_;
@@ -358,7 +358,7 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl)
if (funcdecl.isCtorDeclaration())
{
- tf.isctor = true;
+ tf.isCtor = true;
Type tret = ad.handleType();
assert(tret);
tret = tret.addStorageClass(funcdecl.storage_class | sc.stc);
@@ -369,7 +369,7 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl)
}
// 'return' on a non-static class member function implies 'scope' as well
- if (ad && ad.isClassDeclaration() && (tf.isreturn || sc.stc & STC.return_) && !(sc.stc & STC.static_))
+ if (ad && ad.isClassDeclaration() && (tf.isReturn || sc.stc & STC.return_) && !(sc.stc & STC.static_))
sc.stc |= STC.scope_;
// If 'this' has no pointers, remove 'scope' as it has no meaning
@@ -380,11 +380,11 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl)
{
sc.stc &= ~STC.scope_;
tf.isScopeQual = false;
- if (tf.isreturnscope)
+ if (tf.isReturnScope)
{
sc.stc &= ~(STC.return_ | STC.returnScope);
- tf.isreturn = false;
- tf.isreturnscope = false;
+ tf.isReturn = false;
+ tf.isReturnScope = false;
}
}
@@ -430,12 +430,12 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl)
TypeFunction tfo = funcdecl.originalType.toTypeFunction();
tfo.mod = f.mod;
tfo.isScopeQual = f.isScopeQual;
- tfo.isreturninferred = f.isreturninferred;
- tfo.isscopeinferred = f.isscopeinferred;
- tfo.isref = f.isref;
- tfo.isnothrow = f.isnothrow;
- tfo.isnogc = f.isnogc;
- tfo.isproperty = f.isproperty;
+ tfo.isReturnInferred = f.isReturnInferred;
+ tfo.isScopeInferred = f.isScopeInferred;
+ tfo.isRef = f.isRef;
+ tfo.isNothrow = f.isNothrow;
+ tfo.isNogc = f.isNogc;
+ tfo.isProperty = f.isProperty;
tfo.purity = f.purity;
tfo.trust = f.trust;
@@ -472,10 +472,10 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl)
funcdecl.overnext = null; // don't overload the redeclarations
}
- if ((funcdecl.storage_class & STC.auto_) && !f.isref && !funcdecl.inferRetType)
+ if ((funcdecl.storage_class & STC.auto_) && !f.isRef && !funcdecl.inferRetType)
.error(funcdecl.loc, "%s `%s` storage class `auto` has no effect if return type is not inferred", funcdecl.kind, funcdecl.toPrettyChars);
- if (f.isreturn && !funcdecl.needThis() && !funcdecl.isNested())
+ if (f.isReturn && !funcdecl.needThis() && !funcdecl.isNested())
{
/* Non-static nested functions have a hidden 'this' pointer to which
* the 'return' applies
@@ -1268,11 +1268,11 @@ extern (D) void declareThis(FuncDeclaration fd, Scope* sc)
if (auto tf = fd.type.isTypeFunction())
{
- if (tf.isreturn)
+ if (tf.isReturn)
fd.vthis.storage_class |= STC.return_;
if (tf.isScopeQual)
fd.vthis.storage_class |= STC.scope_;
- if (tf.isreturnscope)
+ if (tf.isReturnScope)
fd.vthis.storage_class |= STC.returnScope;
}
@@ -1331,54 +1331,54 @@ int findVtblIndex(FuncDeclaration fd, Dsymbol[] vtbl)
for (int vi = 0; vi < cast(int)vtbl.length; vi++)
{
FuncDeclaration fdv = vtbl[vi].isFuncDeclaration();
- if (fdv && fdv.ident == fd.ident)
+ if (!fdv || fdv.ident != fd.ident)
+ continue;
+
+ if (fd.type.equals(fdv.type)) // if exact match
{
- if (fd.type.equals(fdv.type)) // if exact match
+ if (fdv.parent.isClassDeclaration())
{
- if (fdv.parent.isClassDeclaration())
- {
- if (fdv.isFuture())
- {
- bestvi = vi;
- continue; // keep looking
- }
- return vi; // no need to look further
- }
-
- if (exactvi >= 0)
+ if (fdv.isFuture())
{
- .error(fd.loc, "%s `%s` cannot determine overridden function", fd.kind, fd.toPrettyChars);
- return exactvi;
+ bestvi = vi;
+ continue; // keep looking
}
- exactvi = vi;
- bestvi = vi;
- continue;
+ return vi; // no need to look further
}
- StorageClass stc = 0;
- const cov = fd.type.covariant(fdv.type, &stc);
- //printf("\tbaseclass cov = %d\n", cov);
- final switch (cov)
+ if (exactvi >= 0)
{
- case Covariant.distinct:
- // types are distinct
- break;
+ .error(fd.loc, "%s `%s` cannot determine overridden function", fd.kind, fd.toPrettyChars);
+ return exactvi;
+ }
+ exactvi = vi;
+ bestvi = vi;
+ continue;
+ }
- case Covariant.yes:
- bestvi = vi; // covariant, but not identical
- break;
- // keep looking for an exact match
+ StorageClass stc = 0;
+ const cov = fd.type.covariant(fdv.type, &stc);
+ //printf("\tbaseclass cov = %d\n", cov);
+ final switch (cov)
+ {
+ case Covariant.distinct:
+ // types are distinct
+ break;
- case Covariant.no:
- mismatchvi = vi;
- mismatchstc = stc;
- mismatch = fdv; // overrides, but is not covariant
- break;
- // keep looking for an exact match
+ case Covariant.yes:
+ bestvi = vi; // covariant, but not identical
+ break;
+ // keep looking for an exact match
- case Covariant.fwdref:
- return -2; // forward references
- }
+ case Covariant.no:
+ mismatchvi = vi;
+ mismatchstc = stc;
+ mismatch = fdv; // overrides, but is not covariant
+ break;
+ // keep looking for an exact match
+
+ case Covariant.fwdref:
+ return -2; // forward references
}
}
if (fd._linkage == LINK.cpp && bestvi != -1)
@@ -1700,39 +1700,40 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
fd.kind(), fd.toPrettyChars(), parametersTypeToChars(tf.parameterList),
tf.modToChars(), fargsBuf.peekChars());
+ if (global.gag && !global.params.v.showGaggedErrors)
+ return null;
+
// re-resolve to check for supplemental message
- if (!global.gag || global.params.v.showGaggedErrors)
+ if (tthis)
{
- if (tthis)
+ if (auto classType = tthis.isTypeClass())
{
- if (auto classType = tthis.isTypeClass())
+ if (auto baseClass = classType.sym.baseClass)
{
- if (auto baseClass = classType.sym.baseClass)
+ if (auto baseFunction = baseClass.search(baseClass.loc, fd.ident))
{
- if (auto baseFunction = baseClass.search(baseClass.loc, fd.ident))
+ MatchAccumulator mErr;
+ functionResolve(mErr, baseFunction, loc, sc, tiargs, baseClass.type, argumentList);
+ if (mErr.last > MATCH.nomatch && mErr.lastf)
{
- MatchAccumulator mErr;
- functionResolve(mErr, baseFunction, loc, sc, tiargs, baseClass.type, argumentList);
- if (mErr.last > MATCH.nomatch && mErr.lastf)
- {
- errorSupplemental(loc, "%s `%s` hides base class function `%s`",
- fd.kind, fd.toPrettyChars(), mErr.lastf.toPrettyChars());
- errorSupplemental(loc, "add `alias %s = %s` to `%s`'s body to merge the overload sets",
- fd.toChars(), mErr.lastf.toPrettyChars(), tthis.toChars());
- return null;
- }
+ errorSupplemental(loc, "%s `%s` hides base class function `%s`",
+ fd.kind, fd.toPrettyChars(), mErr.lastf.toPrettyChars());
+ errorSupplemental(loc, "add `alias %s = %s` to `%s`'s body to merge the overload sets",
+ fd.toChars(), mErr.lastf.toPrettyChars(), tthis.toChars());
+ return null;
}
}
}
}
+ }
- void errorHelper2(const(char)* failMessage) scope
- {
- errorSupplemental(loc, failMessage);
- }
-
- functionResolve(m, orig_s, loc, sc, tiargs, tthis, argumentList, &errorHelper2);
+ void errorHelper2(const(char)* failMessage) scope
+ {
+ errorSupplemental(loc, failMessage);
}
+
+ functionResolve(m, orig_s, loc, sc, tiargs, tthis, argumentList, &errorHelper2);
+
return null;
}
@@ -1888,32 +1889,32 @@ Expression addInvariant(AggregateDeclaration ad, VarDeclaration vthis)
break;
inv = cd.inv;
}
- if (inv)
+ if (!inv)
+ return e;
+
+ version (all)
{
- version (all)
- {
- // Workaround for https://issues.dlang.org/show_bug.cgi?id=13394
- // For the correct mangling,
- // run attribute inference on inv if needed.
- functionSemantic(inv);
- }
+ // Workaround for https://issues.dlang.org/show_bug.cgi?id=13394
+ // For the correct mangling,
+ // run attribute inference on inv if needed.
+ functionSemantic(inv);
+ }
- //e = new DsymbolExp(Loc.initial, inv);
- //e = new CallExp(Loc.initial, e);
- //e = e.semantic(sc2);
+ //e = new DsymbolExp(Loc.initial, inv);
+ //e = new CallExp(Loc.initial, e);
+ //e = e.semantic(sc2);
- /* https://issues.dlang.org/show_bug.cgi?id=13113
- * Currently virtual invariant calls completely
- * bypass attribute enforcement.
- * Change the behavior of pre-invariant call by following it.
- */
- e = new ThisExp(Loc.initial);
- e.type = ad.type.addMod(vthis.type.mod);
- e = new DotVarExp(Loc.initial, e, inv, false);
- e.type = inv.type;
- e = new CallExp(Loc.initial, e);
- e.type = Type.tvoid;
- }
+ /* https://issues.dlang.org/show_bug.cgi?id=13113
+ * Currently virtual invariant calls completely
+ * bypass attribute enforcement.
+ * Change the behavior of pre-invariant call by following it.
+ */
+ e = new ThisExp(Loc.initial);
+ e.type = ad.type.addMod(vthis.type.mod);
+ e = new DotVarExp(Loc.initial, e, inv, false);
+ e.type = inv.type;
+ e = new CallExp(Loc.initial, e);
+ e.type = Type.tvoid;
return e;
}
@@ -1960,19 +1961,19 @@ FuncDeclaration overloadExactMatch(FuncDeclaration thisfd, Type t)
*/
int overrides(FuncDeclaration fd1, FuncDeclaration fd2)
{
- int result = 0;
- if (fd1.ident == fd2.ident)
- {
- const cov = fd1.type.covariant(fd2.type);
- if (cov != Covariant.distinct)
- {
- ClassDeclaration cd1 = fd1.toParent().isClassDeclaration();
- ClassDeclaration cd2 = fd2.toParent().isClassDeclaration();
- if (cd1 && cd2 && cd2.isBaseOf(cd1, null))
- result = 1;
- }
- }
- return result;
+ if (fd1.ident != fd2.ident)
+ return 0;
+
+ const cov = fd1.type.covariant(fd2.type);
+ if (cov == Covariant.distinct)
+ return 0;
+
+ ClassDeclaration cd1 = fd1.toParent().isClassDeclaration();
+ ClassDeclaration cd2 = fd2.toParent().isClassDeclaration();
+
+ if (cd1 && cd2 && cd2.isBaseOf(cd1, null))
+ return 1;
+ return 0;
}
/*************************************
@@ -2090,6 +2091,26 @@ FuncDeclaration overloadModMatch(FuncDeclaration thisfd, const ref Loc loc, Type
auto tf = f.type.toTypeFunction();
//printf("tf = %s\n", tf.toChars());
MATCH match;
+ int lastIsBetter()
+ {
+ //printf("\tlastbetter\n");
+ m.count++; // count up
+ return 0;
+ }
+ int currIsBetter()
+ {
+ //printf("\tisbetter\n");
+ if (m.last <= MATCH.convert)
+ {
+ // clear last secondary matching
+ m.nextf = null;
+ m.count = 0;
+ }
+ m.last = match;
+ m.lastf = f;
+ m.count++; // count up
+ return 0;
+ }
if (tthis) // non-static functions are preferred than static ones
{
if (f.needThis())
@@ -2106,31 +2127,15 @@ FuncDeclaration overloadModMatch(FuncDeclaration thisfd, const ref Loc loc, Type
}
if (match == MATCH.nomatch)
return 0;
- if (match > m.last) goto LcurrIsBetter;
- if (match < m.last) goto LlastIsBetter;
+ if (match > m.last) return currIsBetter();
+ if (match < m.last) return lastIsBetter();
// See if one of the matches overrides the other.
- if (m.lastf.overrides(f)) goto LlastIsBetter;
- if (f.overrides(m.lastf)) goto LcurrIsBetter;
+ if (m.lastf.overrides(f)) return lastIsBetter();
+ if (f.overrides(m.lastf)) return currIsBetter();
//printf("\tambiguous\n");
m.nextf = f;
m.count++;
return 0;
- LlastIsBetter:
- //printf("\tlastbetter\n");
- m.count++; // count up
- return 0;
- LcurrIsBetter:
- //printf("\tisbetter\n");
- if (m.last <= MATCH.convert)
- {
- // clear last secondary matching
- m.nextf = null;
- m.count = 0;
- }
- m.last = match;
- m.lastf = f;
- m.count++; // count up
- return 0;
});
if (m.count == 1) // exact match
{
@@ -2266,51 +2271,51 @@ bool checkNestedReference(FuncDeclaration fd, Scope* sc, const ref Loc loc)
ensureStaticLinkTo(fdthis, p);
if (p != p2)
ensureStaticLinkTo(fdthis, p2);
- if (fd.isNested())
+ if (!fd.isNested())
+ return false;
+
+ // The function that this function is in
+ bool checkEnclosing(FuncDeclaration fdv)
{
- // The function that this function is in
- bool checkEnclosing(FuncDeclaration fdv)
- {
- if (!fdv)
- return false;
- if (fdv == fdthis)
- return false;
- //printf("this = %s in [%s]\n", this.toChars(), this.loc.toChars());
- //printf("fdv = %s in [%s]\n", fdv .toChars(), fdv .loc.toChars());
- //printf("fdthis = %s in [%s]\n", fdthis.toChars(), fdthis.loc.toChars());
- // Add this function to the list of those which called us
- if (fdthis != fd)
+ if (!fdv)
+ return false;
+ if (fdv == fdthis)
+ return false;
+ //printf("this = %s in [%s]\n", this.toChars(), this.loc.toChars());
+ //printf("fdv = %s in [%s]\n", fdv .toChars(), fdv .loc.toChars());
+ //printf("fdthis = %s in [%s]\n", fdthis.toChars(), fdthis.loc.toChars());
+ // Add this function to the list of those which called us
+ if (fdthis != fd)
+ {
+ bool found = false;
+ for (size_t i = 0; i < fd.siblingCallers.length; ++i)
{
- bool found = false;
- for (size_t i = 0; i < fd.siblingCallers.length; ++i)
- {
- if (fd.siblingCallers[i] == fdthis)
- found = true;
- }
- if (!found)
+ if (fd.siblingCallers[i] == fdthis)
+ found = true;
+ }
+ if (!found)
+ {
+ //printf("\tadding sibling %s to %s\n", fdthis.toPrettyChars(), toPrettyChars());
+ if (!sc.intypeof && !sc.traitsCompiles)
{
- //printf("\tadding sibling %s to %s\n", fdthis.toPrettyChars(), toPrettyChars());
- if (!sc.intypeof && !sc.traitsCompiles)
- {
- fd.siblingCallers.push(fdthis);
- fd.computedEscapingSiblings = false;
- }
+ fd.siblingCallers.push(fdthis);
+ fd.computedEscapingSiblings = false;
}
}
- const lv = fdthis.getLevelAndCheck(loc, sc, fdv, fd);
- if (lv == fd.LevelError)
- return true; // error
- if (lv == -1)
- return false; // downlevel call
- if (lv == 0)
- return false; // same level call
- return false; // Uplevel call
- }
- if (checkEnclosing(p.isFuncDeclaration()))
- return true;
- if (checkEnclosing(p == p2 ? null : p2.isFuncDeclaration()))
- return true;
+ }
+ const lv = fdthis.getLevelAndCheck(loc, sc, fdv, fd);
+ if (lv == fd.LevelError)
+ return true; // error
+ if (lv == -1)
+ return false; // downlevel call
+ if (lv == 0)
+ return false; // same level call
+ return false; // Uplevel call
}
+ if (checkEnclosing(p.isFuncDeclaration()))
+ return true;
+ if (checkEnclosing(p == p2 ? null : p2.isFuncDeclaration()))
+ return true;
return false;
}
@@ -2349,7 +2354,7 @@ void buildResultVar(FuncDeclaration fd, Scope* sc, Type tret)
if (sc && fd.vresult.semanticRun == PASS.initial)
{
TypeFunction tf = fd.type.toTypeFunction();
- if (tf.isref)
+ if (tf.isRef)
fd.vresult.storage_class |= STC.ref_;
fd.vresult.type = tret;
fd.vresult.dsymbolSemantic(sc);
@@ -2449,33 +2454,31 @@ Statement mergeFrequireInclusivePreview(FuncDeclaration fd, Statement sf, Expres
sc.pop();
}
sf = fdv.mergeFrequireInclusivePreview(sf, params);
- if (sf && fdv.fdrequire)
- {
- const loc = fd.fdrequire.loc;
- //printf("fdv.frequire: %s\n", fdv.frequire.toChars());
- /* Make the call:
- * try { frequire; }
- * catch (Throwable thr) { __require(params); assert(false, "Logic error: " ~ thr.msg); }
- */
- Identifier id = Identifier.generateId("thr");
- params = Expression.arraySyntaxCopy(params);
- Expression e = new CallExp(loc, new VarExp(loc, fdv.fdrequire, false), params);
- Statement s2 = new ExpStatement(loc, e);
- // assert(false, ...)
- // TODO make this a runtime helper to allow:
- // - chaining the original expression
- // - nogc concatenation
- Expression msg = new StringExp(loc, "Logic error: in-contract was tighter than parent in-contract");
- Statement fail = new ExpStatement(loc, new AssertExp(loc, IntegerExp.literal!0, msg));
- Statement s3 = new CompoundStatement(loc, s2, fail);
- auto c = new Catch(loc, getThrowable(), id, s3);
- c.internalCatch = true;
- auto catches = new Catches();
- catches.push(c);
- sf = new TryCatchStatement(loc, sf, catches);
- }
- else
+ if (!sf || !fdv.fdrequire)
return null;
+
+ const loc = fd.fdrequire.loc;
+ //printf("fdv.frequire: %s\n", fdv.frequire.toChars());
+ /* Make the call:
+ * try { frequire; }
+ * catch (Throwable thr) { __require(params); assert(false, "Logic error: " ~ thr.msg); }
+ */
+ Identifier id = Identifier.generateId("thr");
+ params = Expression.arraySyntaxCopy(params);
+ Expression e = new CallExp(loc, new VarExp(loc, fdv.fdrequire, false), params);
+ Statement s2 = new ExpStatement(loc, e);
+ // assert(false, ...)
+ // TODO make this a runtime helper to allow:
+ // - chaining the original expression
+ // - nogc concatenation
+ Expression msg = new StringExp(loc, "Logic error: in-contract was tighter than parent in-contract");
+ Statement fail = new ExpStatement(loc, new AssertExp(loc, IntegerExp.literal!0, msg));
+ Statement s3 = new CompoundStatement(loc, s2, fail);
+ auto c = new Catch(loc, getThrowable(), id, s3);
+ c.internalCatch = true;
+ auto catches = new Catches();
+ catches.push(c);
+ sf = new TryCatchStatement(loc, sf, catches);
}
return sf;
}
@@ -2570,8 +2573,8 @@ void buildEnsureRequire(FuncDeclaration thisfd)
auto fo = cast(TypeFunction)(thisfd.originalType ? thisfd.originalType : f);
auto fparams = toRefCopy(fo.parameterList);
auto tf = new TypeFunction(ParameterList(fparams), Type.tvoid, LINK.d);
- tf.isnothrow = f.isnothrow;
- tf.isnogc = f.isnogc;
+ tf.isNothrow = f.isNothrow;
+ tf.isNogc = f.isNogc;
tf.purity = f.purity;
tf.trust = f.trust;
auto fd = new FuncDeclaration(loc, loc, Id.require, STC.undefined_, tf);
@@ -2611,8 +2614,8 @@ void buildEnsureRequire(FuncDeclaration thisfd)
auto fo = cast(TypeFunction)(thisfd.originalType ? thisfd.originalType : f);
fparams.pushSlice((*toRefCopy(fo.parameterList))[]);
auto tf = new TypeFunction(ParameterList(fparams), Type.tvoid, LINK.d);
- tf.isnothrow = f.isnothrow;
- tf.isnogc = f.isnogc;
+ tf.isNothrow = f.isNothrow;
+ tf.isNogc = f.isNogc;
tf.purity = f.purity;
tf.trust = f.trust;
auto fd = new FuncDeclaration(loc, loc, Id.ensure, STC.undefined_, tf);
@@ -2677,40 +2680,40 @@ Statement mergeFensure(FuncDeclaration fd, Statement sf, Identifier oid, Express
sc.pop();
}
sf = fdv.mergeFensure(sf, oid, params);
- if (fdv.fdensure)
+ if (!fdv.fdensure)
+ continue;
+
+ //printf("fdv.fensure: %s\n", fdv.fensure.toChars());
+ // Make the call: __ensure(result, params)
+ params = Expression.arraySyntaxCopy(params);
+ if (fd.canBuildResultVar())
{
- //printf("fdv.fensure: %s\n", fdv.fensure.toChars());
- // Make the call: __ensure(result, params)
- params = Expression.arraySyntaxCopy(params);
- if (fd.canBuildResultVar())
- {
- Type t1 = fdv.type.nextOf().toBasetype();
- Type t2 = fd.type.nextOf().toBasetype();
- if (t1.isBaseOf(t2, null))
- {
- /* Making temporary reference variable is necessary
- * in covariant return.
- * https://issues.dlang.org/show_bug.cgi?id=5204
- * https://issues.dlang.org/show_bug.cgi?id=10479
- */
- Expression* eresult = &(*params)[0];
- auto ei = new ExpInitializer(Loc.initial, *eresult);
- auto v = new VarDeclaration(Loc.initial, t1, Identifier.generateId("__covres"), ei);
- v.storage_class |= STC.temp;
- auto de = new DeclarationExp(Loc.initial, v);
- auto ve = new VarExp(Loc.initial, v);
- *eresult = new CommaExp(Loc.initial, de, ve);
- }
- }
- Expression e = new CallExp(fd.loc, new VarExp(fd.loc, fdv.fdensure, false), params);
- Statement s2 = new ExpStatement(fd.loc, e);
- if (sf)
+ Type t1 = fdv.type.nextOf().toBasetype();
+ Type t2 = fd.type.nextOf().toBasetype();
+ if (t1.isBaseOf(t2, null))
{
- sf = new CompoundStatement(sf.loc, s2, sf);
+ /* Making temporary reference variable is necessary
+ * in covariant return.
+ * https://issues.dlang.org/show_bug.cgi?id=5204
+ * https://issues.dlang.org/show_bug.cgi?id=10479
+ */
+ Expression* eresult = &(*params)[0];
+ auto ei = new ExpInitializer(Loc.initial, *eresult);
+ auto v = new VarDeclaration(Loc.initial, t1, Identifier.generateId("__covres"), ei);
+ v.storage_class |= STC.temp;
+ auto de = new DeclarationExp(Loc.initial, v);
+ auto ve = new VarExp(Loc.initial, v);
+ *eresult = new CommaExp(Loc.initial, de, ve);
}
- else
- sf = s2;
}
+ Expression e = new CallExp(fd.loc, new VarExp(fd.loc, fdv.fdensure, false), params);
+ Statement s2 = new ExpStatement(fd.loc, e);
+ if (sf)
+ {
+ sf = new CompoundStatement(sf.loc, s2, sf);
+ }
+ else
+ sf = s2;
}
return sf;
}
@@ -3023,7 +3026,7 @@ extern (D) bool checkNRVO(FuncDeclaration fd)
return false;
auto tf = fd.type.toTypeFunction();
- if (tf.isref)
+ if (tf.isRef)
return false;
foreach (rs; *fd.returns)
@@ -3342,7 +3345,7 @@ extern (D) bool isReturnIsolated(FuncDeclaration fd)
assert(tf.next);
Type treti = tf.next;
- if (tf.isref)
+ if (tf.isRef)
return fd.isTypeIsolatedIndirect(treti); // check influence from parameters
return fd.isTypeIsolated(treti);
@@ -2609,9 +2609,9 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
// the `sideeffect.copyToTemp` function.
auto ve = e.e2.isVarExp();
- // not a CommaExp introduced for temporaries, go on
- // the old path
- if (!ve || !(ve.var.storage_class & STC.temp))
+ // Not a CommaExp introduced for temporaries, or -vcg-ast,
+ // print the full comma
+ if (!ve || !(ve.var.storage_class & STC.temp) || hgs.vcg_ast)
{
visitBin(cast(BinExp)e);
return;
@@ -3016,7 +3016,7 @@ void floatToBuffer(Type type, const real_t value, ref OutBuffer buf, const bool
default:
break;
}
- if (t.isimaginary())
+ if (t.isImaginary())
buf.writeByte('i');
}
}
@@ -3190,6 +3190,12 @@ bool stcToBuffer(ref OutBuffer buf, StorageClass stc) @safe
stc &= ~(STC.return_ | STC.returninferred);
}
+ // ensure `auto ref` keywords are (almost) adjacent
+ if (stc & STC.auto_)
+ {
+ buf.writestring("auto ");
+ stc &= ~STC.auto_;
+ }
/* Put scope ref return into a standard order
*/
string rrs;
@@ -3199,12 +3205,12 @@ bool stcToBuffer(ref OutBuffer buf, StorageClass stc) @safe
{
case ScopeRef.None:
case ScopeRef.Scope:
- case ScopeRef.Ref:
case ScopeRef.Return:
break;
case ScopeRef.ReturnScope: rrs = "return scope"; goto L1;
case ScopeRef.ReturnRef: rrs = isout ? "return out" : "return ref"; goto L1;
+ case ScopeRef.Ref: rrs = isout ? "out" : "ref"; goto L1;
case ScopeRef.RefScope: rrs = isout ? "out scope" : "ref scope"; goto L1;
case ScopeRef.ReturnRef_Scope: rrs = isout ? "return out scope" : "return ref scope"; goto L1;
case ScopeRef.Ref_ReturnScope: rrs = isout ? "out return scope" : "ref return scope"; goto L1;
@@ -3980,15 +3986,15 @@ private void visitFuncIdentWithPrefix(TypeFunction t, const Identifier ident, Te
buf.writeByte(' ');
MODtoBuffer(buf, t.mod);
}
- if (t.isreturnscope && !t.isreturninferred)
+ if (t.isReturnScope && !t.isReturnInferred)
{
buf.writestring(" return scope");
}
- else if (t.isScopeQual && !t.isscopeinferred)
+ else if (t.isScopeQual && !t.isScopeInferred)
{
buf.writestring(" scope");
}
- if (t.isreturn && !t.isreturnscope && !t.isreturninferred)
+ if (t.isReturn && !t.isReturnScope && !t.isReturnInferred)
{
buf.writestring(" return");
}
@@ -4178,7 +4184,7 @@ private void typeToBufferx(Type t, ref OutBuffer buf, ref HdrGenState hgs)
void visitFunction(TypeFunction t)
{
- //printf("TypeFunction::toCBuffer2() t = %p, ref = %d\n", t, t.isref);
+ //printf("TypeFunction::toCBuffer2() t = %p, ref = %d\n", t, t.isRef);
visitFuncIdentWithPostfix(t, null, buf, hgs, false);
}
@@ -711,7 +711,7 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
if (tnsa && ix.isExpInitializer())
{
ExpInitializer ei = ix.isExpInitializer();
- if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
+ if (ei.exp.isStringExp() && tnsa.nextOf().isIntegral())
{
si.addInit(field.ident, ei);
++index;
@@ -774,7 +774,7 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
else if (tnsa && di.initializer.isExpInitializer())
{
ExpInitializer ei = di.initializer.isExpInitializer();
- if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
+ if (ei.exp.isStringExp() && tnsa.nextOf().isIntegral())
{
ai.addInit(null, ei);
++index;
@@ -917,7 +917,7 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
if (tnsa && ix.isExpInitializer())
{
ExpInitializer ei = ix.isExpInitializer();
- if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
+ if (ei.exp.isStringExp() && tnsa.nextOf().isIntegral())
{
si.addInit(field.ident, ei);
++index;
@@ -954,7 +954,7 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
/* If it's an array of integral being initialized by `{ string }`
* replace with `string`
*/
- if (tn.isintegral())
+ if (tn.isIntegral())
{
if (ExpInitializer ei = isBraceExpression())
{
@@ -1017,7 +1017,7 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
else if (tnsa && di.initializer.isExpInitializer())
{
ExpInitializer ei = di.initializer.isExpInitializer();
- if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
+ if (ei.exp.isStringExp() && tnsa.nextOf().isIntegral())
{
ai.addInit(null, ei);
++index;
@@ -317,12 +317,12 @@ struct IntRange
static IntRange fromType(Type type)
{
- return fromType(type, type.isunsigned());
+ return fromType(type, type.isUnsigned());
}
static IntRange fromType(Type type, bool isUnsigned)
{
- if (!type.isintegral() || type.toBasetype().ty == Tvector)
+ if (!type.isIntegral() || type.toBasetype().ty == Tvector)
return widest();
uinteger_t mask = type.sizemask();
@@ -444,9 +444,9 @@ struct IntRange
IntRange _cast(Type type)
{
- if (!type.isintegral() || type.toBasetype().ty == Tvector)
+ if (!type.isIntegral() || type.toBasetype().ty == Tvector)
return this;
- else if (!type.isunsigned())
+ else if (!type.isUnsigned())
return castSigned(type.sizemask());
else if (type.toBasetype().ty == Tdchar)
return castDchar();
@@ -456,7 +456,7 @@ struct IntRange
IntRange castUnsigned(Type type)
{
- if (!type.isintegral() || type.toBasetype().ty == Tvector)
+ if (!type.isIntegral() || type.toBasetype().ty == Tvector)
return castUnsigned(ulong.max);
else if (type.toBasetype().ty == Tdchar)
return castDchar();
@@ -641,38 +641,38 @@ extern (C++) abstract class Type : ASTNode
return buf.extractChars();
}
- bool isintegral()
+ bool isIntegral()
{
return false;
}
// real, imaginary, or complex
- bool isfloating()
+ bool isFloating()
{
return false;
}
- bool isreal()
+ bool isReal()
{
return false;
}
- bool isimaginary()
+ bool isImaginary()
{
return false;
}
- bool iscomplex()
+ bool isComplex()
{
return false;
}
- bool isscalar()
+ bool isScalar()
{
return false;
}
- bool isunsigned()
+ bool isUnsigned()
{
return false;
}
@@ -705,7 +705,7 @@ extern (C++) abstract class Type : ASTNode
*/
bool isBoolean()
{
- return isscalar();
+ return isScalar();
}
final bool isConst() const nothrow pure @nogc @safe
@@ -2031,38 +2031,38 @@ extern (C++) final class TypeBasic : Type
return target.alignsize(this);
}
- override bool isintegral()
+ override bool isIntegral()
{
- //printf("TypeBasic::isintegral('%s') x%x\n", toChars(), flags);
+ //printf("TypeBasic::isIntegral('%s') x%x\n", toChars(), flags);
return (flags & TFlags.integral) != 0;
}
- override bool isfloating()
+ override bool isFloating()
{
return (flags & TFlags.floating) != 0;
}
- override bool isreal()
+ override bool isReal()
{
return (flags & TFlags.real_) != 0;
}
- override bool isimaginary()
+ override bool isImaginary()
{
return (flags & TFlags.imaginary) != 0;
}
- override bool iscomplex()
+ override bool isComplex()
{
return (flags & TFlags.complex) != 0;
}
- override bool isscalar()
+ override bool isScalar()
{
return (flags & (TFlags.integral | TFlags.floating)) != 0;
}
- override bool isunsigned()
+ override bool isUnsigned()
{
return (flags & TFlags.unsigned) != 0;
}
@@ -2120,25 +2120,25 @@ extern (C++) final class TypeVector : Type
return cast(uint)basetype.size();
}
- override bool isintegral()
+ override bool isIntegral()
{
- //printf("TypeVector::isintegral('%s') x%x\n", toChars(), flags);
- return basetype.nextOf().isintegral();
+ //printf("TypeVector::isIntegral('%s') x%x\n", toChars(), flags);
+ return basetype.nextOf().isIntegral();
}
- override bool isfloating()
+ override bool isFloating()
{
- return basetype.nextOf().isfloating();
+ return basetype.nextOf().isFloating();
}
- override bool isscalar()
+ override bool isScalar()
{
- return basetype.nextOf().isscalar();
+ return basetype.nextOf().isScalar();
}
- override bool isunsigned()
+ override bool isUnsigned()
{
- return basetype.nextOf().isunsigned();
+ return basetype.nextOf().isUnsigned();
}
override bool isBoolean()
@@ -2432,7 +2432,7 @@ extern (C++) final class TypePointer : TypeNext
return result;
}
- override bool isscalar()
+ override bool isScalar()
{
return true;
}
@@ -2502,20 +2502,20 @@ extern (C++) final class TypeFunction : TypeNext
// getters and setters are generated for them
private extern (D) static struct BitFields
{
- bool isnothrow; /// nothrow
- bool isnogc; /// is @nogc
- bool isproperty; /// can be called without parentheses
- bool isref; /// returns a reference
- bool isreturn; /// 'this' is returned by ref
+ bool isNothrow; /// nothrow
+ bool isNogc; /// is @nogc
+ bool isProperty; /// can be called without parentheses
+ bool isRef; /// returns a reference
+ bool isReturn; /// 'this' is returned by ref
bool isScopeQual; /// 'this' is scope
- bool isreturninferred; /// 'this' is return from inference
- bool isscopeinferred; /// 'this' is scope from inference
- bool islive; /// is @live
+ bool isReturnInferred; /// 'this' is return from inference
+ bool isScopeInferred; /// 'this' is scope from inference
+ bool isLive; /// is @live
bool incomplete; /// return type or default arguments removed
bool isInOutParam; /// inout on the parameters
bool isInOutQual; /// inout on the qualifier
- bool isctor; /// the function is a constructor
- bool isreturnscope; /// `this` is returned by value
+ bool isCtor; /// the function is a constructor
+ bool isReturnScope; /// `this` is returned by value
}
import dmd.common.bitfields : generateBitFields;
@@ -2539,26 +2539,26 @@ extern (C++) final class TypeFunction : TypeNext
if (stc & STC.pure_)
this.purity = PURE.fwdref;
if (stc & STC.nothrow_)
- this.isnothrow = true;
+ this.isNothrow = true;
if (stc & STC.nogc)
- this.isnogc = true;
+ this.isNogc = true;
if (stc & STC.property)
- this.isproperty = true;
+ this.isProperty = true;
if (stc & STC.live)
- this.islive = true;
+ this.isLive = true;
if (stc & STC.ref_)
- this.isref = true;
+ this.isRef = true;
if (stc & STC.return_)
- this.isreturn = true;
+ this.isReturn = true;
if (stc & STC.returnScope)
- this.isreturnscope = true;
+ this.isReturnScope = true;
if (stc & STC.returninferred)
- this.isreturninferred = true;
+ this.isReturnInferred = true;
if (stc & STC.scope_)
this.isScopeQual = true;
if (stc & STC.scopeinferred)
- this.isscopeinferred = true;
+ this.isScopeInferred = true;
this.trust = TRUST.default_;
if (stc & STC.safe)
@@ -2584,22 +2584,22 @@ extern (C++) final class TypeFunction : TypeNext
Type treturn = next ? next.syntaxCopy() : null;
auto t = new TypeFunction(parameterList.syntaxCopy(), treturn, linkage);
t.mod = mod;
- t.isnothrow = isnothrow;
- t.isnogc = isnogc;
- t.islive = islive;
+ t.isNothrow = isNothrow;
+ t.isNogc = isNogc;
+ t.isLive = isLive;
t.purity = purity;
- t.isproperty = isproperty;
- t.isref = isref;
- t.isreturn = isreturn;
- t.isreturnscope = isreturnscope;
+ t.isProperty = isProperty;
+ t.isRef = isRef;
+ t.isReturn = isReturn;
+ t.isReturnScope = isReturnScope;
t.isScopeQual = isScopeQual;
- t.isreturninferred = isreturninferred;
- t.isscopeinferred = isscopeinferred;
+ t.isReturnInferred = isReturnInferred;
+ t.isScopeInferred = isScopeInferred;
t.isInOutParam = isInOutParam;
t.isInOutQual = isInOutQual;
t.trust = trust;
t.inferenceArguments = inferenceArguments;
- t.isctor = isctor;
+ t.isCtor = isCtor;
return t;
}
@@ -2737,7 +2737,7 @@ extern (C++) final class TypeFunction : TypeNext
error(loc, "functions cannot return a sequence (use `std.typecons.Tuple`)");
next = Type.terror;
}
- if (!isref && (tb.ty == Tstruct || tb.ty == Tsarray))
+ if (!isRef && (tb.ty == Tstruct || tb.ty == Tsarray))
{
if (auto ts = tb.baseElemOf().isTypeStruct())
{
@@ -2774,9 +2774,9 @@ extern (C++) final class TypeFunction : TypeNext
return (this.trust == other.trust ||
(trustSystemEqualsDefault && this.trust <= TRUST.system && other.trust <= TRUST.system)) &&
this.purity == other.purity &&
- this.isnothrow == other.isnothrow &&
- this.isnogc == other.isnogc &&
- this.islive == other.islive;
+ this.isNothrow == other.isNothrow &&
+ this.isNogc == other.isNogc &&
+ this.isLive == other.isLive;
}
override void accept(Visitor v)
@@ -3388,39 +3388,39 @@ extern (C++) final class TypeEnum : Type
return t.alignsize();
}
- override bool isintegral()
+ override bool isIntegral()
{
- return memType().isintegral();
+ return memType().isIntegral();
}
- override bool isfloating()
+ override bool isFloating()
{
- return memType().isfloating();
+ return memType().isFloating();
}
- override bool isreal()
+ override bool isReal()
{
- return memType().isreal();
+ return memType().isReal();
}
- override bool isimaginary()
+ override bool isImaginary()
{
- return memType().isimaginary();
+ return memType().isImaginary();
}
- override bool iscomplex()
+ override bool isComplex()
{
- return memType().iscomplex();
+ return memType().isComplex();
}
- override bool isscalar()
+ override bool isScalar()
{
- return memType().isscalar();
+ return memType().isScalar();
}
- override bool isunsigned()
+ override bool isUnsigned()
{
- return memType().isunsigned();
+ return memType().isUnsigned();
}
override bool isBoolean()
@@ -4333,19 +4333,19 @@ void attributesApply(const TypeFunction tf, void delegate(string) dg, TRUSTforma
{
if (tf.purity)
dg("pure");
- if (tf.isnothrow)
+ if (tf.isNothrow)
dg("nothrow");
- if (tf.isnogc)
+ if (tf.isNogc)
dg("@nogc");
- if (tf.isproperty)
+ if (tf.isProperty)
dg("@property");
- if (tf.isref)
+ if (tf.isRef)
dg("ref");
- if (tf.isreturn && !tf.isreturninferred)
+ if (tf.isReturn && !tf.isReturnInferred)
dg("return");
- if (tf.isScopeQual && !tf.isscopeinferred)
+ if (tf.isScopeQual && !tf.isScopeInferred)
dg("scope");
- if (tf.islive)
+ if (tf.isLive)
dg("@live");
TRUST trustAttrib = tf.trust;
@@ -232,13 +232,13 @@ public:
void modToBuffer(OutBuffer& buf) const;
char *modToChars() const;
- virtual bool isintegral();
- virtual bool isfloating(); // real, imaginary, or complex
- virtual bool isreal();
- virtual bool isimaginary();
- virtual bool iscomplex();
- virtual bool isscalar();
- virtual bool isunsigned();
+ virtual bool isIntegral();
+ virtual bool isFloating(); // real, imaginary, or complex
+ virtual bool isReal();
+ virtual bool isImaginary();
+ virtual bool isComplex();
+ virtual bool isScalar();
+ virtual bool isUnsigned();
virtual bool isScopeClass();
virtual bool isString();
virtual bool isAssignable();
@@ -352,13 +352,13 @@ public:
const char *kind() override;
TypeBasic *syntaxCopy() override;
unsigned alignsize() override;
- bool isintegral() override;
- bool isfloating() override;
- bool isreal() override;
- bool isimaginary() override;
- bool iscomplex() override;
- bool isscalar() override;
- bool isunsigned() override;
+ bool isIntegral() override;
+ bool isFloating() override;
+ bool isReal() override;
+ bool isImaginary() override;
+ bool isComplex() override;
+ bool isScalar() override;
+ bool isUnsigned() override;
// For eliminating dynamic_cast
TypeBasic *isTypeBasic() override;
@@ -374,10 +374,10 @@ public:
const char *kind() override;
TypeVector *syntaxCopy() override;
unsigned alignsize() override;
- bool isintegral() override;
- bool isfloating() override;
- bool isscalar() override;
- bool isunsigned() override;
+ bool isIntegral() override;
+ bool isFloating() override;
+ bool isScalar() override;
+ bool isUnsigned() override;
bool isBoolean() override;
Expression *defaultInitLiteral(const Loc &loc) override;
TypeBasic *elementType();
@@ -447,7 +447,7 @@ public:
static TypePointer *create(Type *t);
const char *kind() override;
TypePointer *syntaxCopy() override;
- bool isscalar() override;
+ bool isScalar() override;
void accept(Visitor *v) override { v->visit(this); }
};
@@ -545,26 +545,26 @@ public:
bool isDstyleVariadic() const;
- bool isnothrow() const;
- void isnothrow(bool v);
- bool isnogc() const;
- void isnogc(bool v);
- bool isproperty() const;
- void isproperty(bool v);
- bool isref() const;
- void isref(bool v);
- bool isreturn() const;
- void isreturn(bool v);
- bool isreturnscope() const;
- void isreturnscope(bool v);
+ bool isNothrow() const;
+ void isNothrow(bool v);
+ bool isNogc() const;
+ void isNogc(bool v);
+ bool isProperty() const;
+ void isProperty(bool v);
+ bool isRef() const;
+ void isRef(bool v);
+ bool isReturn() const;
+ void isReturn(bool v);
+ bool isReturnScope() const;
+ void isReturnScope(bool v);
bool isScopeQual() const;
void isScopeQual(bool v);
- bool isreturninferred() const;
- void isreturninferred(bool v);
- bool isscopeinferred() const;
- void isscopeinferred(bool v);
- bool islive() const;
- void islive(bool v);
+ bool isReturnInferred() const;
+ void isReturnInferred(bool v);
+ bool isScopeInferred() const;
+ void isScopeInferred(bool v);
+ bool isLive() const;
+ void isLive(bool v);
bool incomplete() const;
void incomplete(bool v);
bool isInOutParam() const;
@@ -716,13 +716,13 @@ public:
TypeEnum *syntaxCopy() override;
unsigned alignsize() override;
Type *memType(const Loc &loc);
- bool isintegral() override;
- bool isfloating() override;
- bool isreal() override;
- bool isimaginary() override;
- bool iscomplex() override;
- bool isscalar() override;
- bool isunsigned() override;
+ bool isIntegral() override;
+ bool isFloating() override;
+ bool isReal() override;
+ bool isImaginary() override;
+ bool isComplex() override;
+ bool isScalar() override;
+ bool isUnsigned() override;
bool isBoolean() override;
bool isString() override;
bool isAssignable() override;
@@ -213,7 +213,7 @@ Expression checkGC(Scope* sc, Expression e)
if (e && e.op != EXP.error && f && sc.intypeof != 1 &&
(!sc.ctfe || betterC) &&
(f.type.ty == Tfunction &&
- (cast(TypeFunction)f.type).isnogc || f.nogcInprocess || global.params.v.gc) &&
+ (cast(TypeFunction)f.type).isNogc || f.nogcInprocess || global.params.v.gc) &&
!sc.debug_)
{
scope NOGCVisitor gcv = new NOGCVisitor(f);
@@ -100,7 +100,7 @@ struct ObjcSelector
const id = fdecl.ident.toString();
const nparams = ftype.parameterList.length;
// Special case: property setter
- if (ftype.isproperty && nparams == 1)
+ if (ftype.isProperty && nparams == 1)
{
// rewrite "identifier" as "setIdentifier"
char firstChar = id[0];
@@ -84,7 +84,7 @@ Expression expandVar(int result, VarDeclaration v)
{
Type tb = v.type.toBasetype();
if (v.storage_class & STC.manifest ||
- tb.isscalar() ||
+ tb.isScalar() ||
((result & WANTexpand) && (tb.ty != Tsarray && tb.ty != Tstruct)))
{
if (v._init)
@@ -1071,7 +1071,7 @@ Expression optimize(Expression e, int result, bool keepLvalue = false)
if (binOptimize(e, result))
return;
// All negative integral powers are illegal.
- if (e.e1.type.isintegral() && (e.e2.op == EXP.int64) && cast(sinteger_t)e.e2.toInteger() < 0)
+ if (e.e1.type.isIntegral() && (e.e2.op == EXP.int64) && cast(sinteger_t)e.e2.toInteger() < 0)
{
error(e.loc, "cannot raise `%s` to a negative integer power. Did you mean `(cast(real)%s)^^%s` ?", e.e1.type.toBasetype().toChars(), e.e1.toChars(), e.e2.toChars());
return errorReturn();
@@ -1080,7 +1080,7 @@ Expression optimize(Expression e, int result, bool keepLvalue = false)
if (e.e2.op == EXP.float64 && e.e2.toReal() == real_t(cast(sinteger_t)e.e2.toReal()))
{
// This only applies to floating point, or positive integral powers.
- if (e.e1.type.isfloating() || cast(sinteger_t)e.e2.toInteger() >= 0)
+ if (e.e1.type.isFloating() || cast(sinteger_t)e.e2.toInteger() >= 0)
e.e2 = new IntegerExp(e.loc, e.e2.toInteger(), Type.tint64);
}
if (e.e1.isConst() == 1 && e.e2.isConst() == 1)
@@ -651,6 +651,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.auto_:
stc = STC.auto_;
+ if (peekNext() == TOK.ref_)
+ stc |= STC.autoref;
goto Lstc;
case TOK.scope_:
@@ -1705,19 +1707,28 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
* mixin Foo;
* mixin Foo!(args);
* mixin a.b.c!(args).Foo!(args);
- * mixin Foo!(args) identifier;
* mixin typeof(expr).identifier!(args);
+ * mixin Foo!(args) identifier;
+ * mixin identifier = Foo!(args);
*/
private AST.Dsymbol parseMixin()
{
AST.TemplateMixin tm;
- Identifier id;
+ Identifier id, name;
AST.Objects* tiargs;
//printf("parseMixin()\n");
const locMixin = token.loc;
nextToken(); // skip 'mixin'
+ // mixin Identifier = MixinTemplateName TemplateArguments;
+ if (token.value == TOK.identifier && peekNext() == TOK.assign)
+ {
+ name = token.ident;
+ nextToken();
+ nextToken();
+ }
+
auto loc = token.loc;
AST.TypeQualified tqual = null;
if (token.value == TOK.dot)
@@ -1780,14 +1791,14 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
nextToken();
}
- id = null;
- if (token.value == TOK.identifier)
+ // mixin MixinTemplateName TemplateArguments Identifier;
+ if (!name && token.value == TOK.identifier)
{
- id = token.ident;
+ name = token.ident;
nextToken();
}
- tm = new AST.TemplateMixin(locMixin, id, tqual, tiargs);
+ tm = new AST.TemplateMixin(locMixin, name, tqual, tiargs);
if (token.value != TOK.semicolon)
error("`;` expected after `mixin`");
nextToken();
@@ -2935,6 +2946,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.auto_:
stc = STC.auto_;
+ if (peekNext() == TOK.ref_)
+ stc |= STC.autoref;
goto L2;
case TOK.return_:
@@ -2952,8 +2965,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
// if stcx is not a power of 2
if (stcx & (stcx - 1) && !(stcx == (STC.in_ | STC.ref_)))
error("incompatible parameter storage classes");
- //if ((storageClass & STC.scope_) && (storageClass & (STC.ref_ | STC.out_)))
- //error("scope cannot be ref or out");
+
+ // Deprecated in 2.111
+ if ((storageClass & STC.auto_) && (storageClass & STC.ref_) && !(storageClass & STC.autoref))
+ deprecation("`auto` and `ref` storage classes should be adjacent");
const tv = peekNext();
Loc loc;
@@ -4259,6 +4274,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.auto_:
stc = STC.auto_;
+ if (peekNext() == TOK.ref_)
+ stc |= STC.autoref;
goto L1;
case TOK.scope_:
@@ -5079,7 +5096,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
{
// function auto ref (parameters) { statements... }
// delegate auto ref (parameters) { statements... }
- stc = STC.auto_ | STC.ref_;
+ stc = STC.auto_ | STC.ref_ | STC.autoref;
nextToken();
}
else
@@ -5121,7 +5138,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
{
// auto ref (parameters) => expression
// auto ref (parameters) { statements... }
- stc = STC.auto_ | STC.ref_;
+ stc = STC.auto_ | STC.ref_ | STC.autoref;
nextToken();
}
else
@@ -5678,6 +5695,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.auto_:
stc = STC.auto_;
+ if (peekNext() == TOK.ref_)
+ stc |= STC.autoref;
break;
case TOK.const_:
@@ -610,7 +610,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
}
}
- bool inferRef = (f.isref && (funcdecl.storage_class & STC.auto_));
+ bool inferRef = (f.isRef && (funcdecl.storage_class & STC.auto_));
funcdecl.fbody = funcdecl.fbody.statementSemantic(sc2);
if (!funcdecl.fbody)
@@ -654,12 +654,12 @@ private extern(C++) final class Semantic3Visitor : Visitor
funcdecl.returns.remove(i);
continue;
}
- if (inferRef && f.isref && !exp.type.constConv(f.next)) // https://issues.dlang.org/show_bug.cgi?id=13336
- f.isref = false;
+ if (inferRef && f.isRef && !exp.type.constConv(f.next)) // https://issues.dlang.org/show_bug.cgi?id=13336
+ f.isRef = false;
i++;
}
}
- if (f.isref) // Function returns a reference
+ if (f.isRef) // Function returns a reference
{
if (funcdecl.storage_class & STC.auto_)
funcdecl.storage_class &= ~STC.auto_;
@@ -766,8 +766,8 @@ private extern(C++) final class Semantic3Visitor : Visitor
funcdecl.buildEnsureRequire();
// Check for errors related to 'nothrow'.
- const blockexit = funcdecl.fbody.blockExit(funcdecl, f.isnothrow ? global.errorSink : null);
- if (f.isnothrow && blockexit & BE.throw_)
+ const blockexit = funcdecl.fbody.blockExit(funcdecl, f.isNothrow ? global.errorSink : null);
+ if (f.isNothrow && blockexit & BE.throw_)
error(funcdecl.loc, "%s `%s` may throw but is marked as `nothrow`", funcdecl.kind(), funcdecl.toPrettyChars());
if (!(blockexit & (BE.throw_ | BE.halt) || funcdecl.hasCatches))
@@ -782,7 +782,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
{
if (funcdecl.type == f)
f = cast(TypeFunction)f.copy();
- f.isnothrow = !(blockexit & BE.throw_);
+ f.isNothrow = !(blockexit & BE.throw_);
}
if (funcdecl.fbody.isErrorStatement())
@@ -916,7 +916,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
}
// Function returns a reference
- if (f.isref)
+ if (f.isRef)
{
if (!MODimplicitConv(exp.type.mod, tret.mod) && !tret.isTypeSArray())
error(exp.loc, "expression `%s` of type `%s` is not implicitly convertible to return type `ref %s`",
@@ -993,7 +993,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
/* Do the semantic analysis on the [in] preconditions and
* [out] postconditions.
*/
- immutable bool isnothrow = f.isnothrow && !funcdecl.nothrowInprocess;
+ immutable bool isNothrow = f.isNothrow && !funcdecl.nothrowInprocess;
if (freq)
{
/* frequire is composed of the [in] contracts
@@ -1009,17 +1009,14 @@ private extern(C++) final class Semantic3Visitor : Visitor
// BUG: verify that all in and ref parameters are read
freq = freq.statementSemantic(sc2);
- // @@@DEPRECATED_2.111@@@ - pass `isnothrow` instead of `false` to print a more detailed error msg`
const blockExit = freq.blockExit(funcdecl, null);
if (blockExit & BE.throw_)
{
- if (isnothrow)
- // @@@DEPRECATED_2.111@@@
- // Deprecated in 2.101, can be made an error in 2.111
- deprecation(funcdecl.loc, "`%s`: `in` contract may throw but function is marked as `nothrow`",
+ if (isNothrow)
+ error(funcdecl.loc, "`%s`: `in` contract may throw but function is marked as `nothrow`",
funcdecl.toPrettyChars());
else if (funcdecl.nothrowInprocess)
- f.isnothrow = false;
+ f.isNothrow = false;
}
funcdecl.hasNoEH = false;
@@ -1056,17 +1053,14 @@ private extern(C++) final class Semantic3Visitor : Visitor
fens = fens.statementSemantic(sc2);
- // @@@DEPRECATED_2.111@@@ - pass `isnothrow` instead of `false` to print a more detailed error msg`
const blockExit = fens.blockExit(funcdecl, null);
if (blockExit & BE.throw_)
{
- if (isnothrow)
- // @@@DEPRECATED_2.111@@@
- // Deprecated in 2.101, can be made an error in 2.111
- deprecation(funcdecl.loc, "`%s`: `out` contract may throw but function is marked as `nothrow`",
+ if (isNothrow)
+ error(funcdecl.loc, "`%s`: `out` contract may throw but function is marked as `nothrow`",
funcdecl.toPrettyChars());
else if (funcdecl.nothrowInprocess)
- f.isnothrow = false;
+ f.isNothrow = false;
}
funcdecl.hasNoEH = false;
@@ -1194,17 +1188,17 @@ private extern(C++) final class Semantic3Visitor : Visitor
s = s.statementSemantic(sc2);
- const blockexit = s.blockExit(funcdecl, isnothrow ? global.errorSink : null);
+ const blockexit = s.blockExit(funcdecl, isNothrow ? global.errorSink : null);
if (blockexit & BE.throw_)
{
funcdecl.hasNoEH = false;
- if (isnothrow)
+ if (isNothrow)
error(funcdecl.loc, "%s `%s` may throw but is marked as `nothrow`", funcdecl.kind(), funcdecl.toPrettyChars());
else if (funcdecl.nothrowInprocess)
- f.isnothrow = false;
+ f.isNothrow = false;
}
- if (sbody.blockExit(funcdecl, f.isnothrow ? global.errorSink : null) == BE.fallthru)
+ if (sbody.blockExit(funcdecl, f.isNothrow ? global.errorSink : null) == BE.fallthru)
sbody = new CompoundStatement(Loc.initial, sbody, s);
else
sbody = new TryFinallyStatement(Loc.initial, sbody, s);
@@ -1311,7 +1305,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
funcdecl.nogcInprocess = false;
if (funcdecl.type == f)
f = cast(TypeFunction)f.copy();
- f.isnogc = true;
+ f.isNogc = true;
}
finishScopeParamInference(funcdecl, f);
@@ -1325,7 +1319,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
{
sc = sc.push();
if (funcdecl.isCtorDeclaration()) // https://issues.dlang.org/show_bug.cgi?id=#15665
- f.isctor = true;
+ f.isCtor = true;
sc.stc = 0;
sc.linkage = funcdecl._linkage; // https://issues.dlang.org/show_bug.cgi?id=8496
funcdecl.type = f.typeSemantic(funcdecl.loc, sc);
@@ -1402,7 +1396,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
// Do live analysis
if (global.params.useDIP1021 && funcdecl.fbody && funcdecl.type.ty != Terror &&
- funcdecl.type.isTypeFunction().islive)
+ funcdecl.type.isTypeFunction().isLive)
{
oblive(funcdecl);
}
@@ -1439,7 +1433,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
*/
AggregateDeclaration ad = ctor.isMemberDecl();
if (!ctor.fbody || !ad || !ad.fieldDtor ||
- global.params.dtorFields == FeatureState.disabled || !global.params.useExceptions || ctor.type.toTypeFunction.isnothrow)
+ global.params.dtorFields == FeatureState.disabled || !global.params.useExceptions || ctor.type.toTypeFunction.isNothrow)
return visit(cast(FuncDeclaration)ctor);
/* Generate:
@@ -1452,16 +1446,12 @@ private extern(C++) final class Semantic3Visitor : Visitor
auto sexp = new ExpStatement(ctor.loc, ce);
auto ss = new ScopeStatement(ctor.loc, sexp, ctor.loc);
- // @@@DEPRECATED_2.106@@@
- // Allow negligible attribute violations to allow for a smooth
- // transition. Remove this after the usual deprecation period
- // after 2.106.
if (global.params.dtorFields == FeatureState.default_)
{
auto ctf = cast(TypeFunction) ctor.type;
auto dtf = cast(TypeFunction) ad.fieldDtor.type;
- const ngErr = ctf.isnogc && !dtf.isnogc;
+ const ngErr = ctf.isNogc && !dtf.isNogc;
const puErr = ctf.purity && !dtf.purity;
const saErr = ctf.trust == TRUST.safe && dtf.trust <= TRUST.system;
@@ -1474,9 +1464,9 @@ private extern(C++) final class Semantic3Visitor : Visitor
(puErr ? STC.pure_ : 0) |
(saErr ? STC.system : 0)
);
- ctor.loc.deprecation("`%s` has stricter attributes than its destructor (`%s`)", ctor.toPrettyChars(), ob.peekChars());
- ctor.loc.deprecationSupplemental("The destructor will be called if an exception is thrown");
- ctor.loc.deprecationSupplemental("Either make the constructor `nothrow` or adjust the field destructors");
+ ctor.loc.error("`%s` has stricter attributes than its destructor (`%s`)", ctor.toPrettyChars(), ob.peekChars());
+ ctor.loc.errorSupplemental("The destructor will be called if an exception is thrown");
+ ctor.loc.errorSupplemental("Either make the constructor `nothrow` or adjust the field destructors");
ce.ignoreAttributes = true;
}
@@ -113,7 +113,7 @@ int callSideEffectLevel(FuncDeclaration f)
return 0;
assert(f.type.ty == Tfunction);
TypeFunction tf = cast(TypeFunction)f.type;
- if (!tf.isnothrow)
+ if (!tf.isNothrow)
return 0;
final switch (f.isPure())
{
@@ -123,7 +123,7 @@ int callSideEffectLevel(FuncDeclaration f)
return 0;
case PURE.const_:
- return mutabilityOfType(tf.isref, tf.next) == 2 ? 2 : 1;
+ return mutabilityOfType(tf.isRef, tf.next) == 2 ? 2 : 1;
}
}
@@ -138,7 +138,7 @@ int callSideEffectLevel(Type t)
assert(t.ty == Tfunction);
tf = cast(TypeFunction)t;
}
- if (!tf.isnothrow) // function can throw
+ if (!tf.isNothrow) // function can throw
return 0;
tf.purityLevel();
@@ -152,7 +152,7 @@ int callSideEffectLevel(Type t)
}
if (purity == PURE.const_)
- return mutabilityOfType(tf.isref, tf.next) == 2 ? 2 : 1;
+ return mutabilityOfType(tf.isRef, tf.next) == 2 ? 2 : 1;
return 0;
}
@@ -975,7 +975,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
if (dim == 2)
{
Type tindex = (*fs.parameters)[0].type;
- if (!tindex.isintegral())
+ if (!tindex.isIntegral())
{
error(fs.loc, "foreach: key cannot be of non-integral type `%s`", tindex.toChars());
return retError();
@@ -1309,7 +1309,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
if (auto ftt = tfront.toBasetype().isTypeFunction())
{
tfront = tfront.toBasetype().nextOf();
- if (!ftt.isref)
+ if (!ftt.isRef)
{
// .front() does not return a ref. We ignore ref on foreach arg.
// see https://issues.dlang.org/show_bug.cgi?id=11934
@@ -1539,7 +1539,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
if (fs.op == TOK.foreach_reverse_)
{
cond = new PostExp(EXP.minusMinus, loc, new VarExp(loc, fs.key));
- if (fs.prm.type.isscalar())
+ if (fs.prm.type.isScalar())
{
// key-- > tmp
cond = new CmpExp(EXP.greaterThan, loc, cond, new VarExp(loc, tmp));
@@ -1552,7 +1552,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
}
else
{
- if (fs.prm.type.isscalar())
+ if (fs.prm.type.isScalar())
{
// key < tmp
cond = new CmpExp(EXP.lessThan, loc, new VarExp(loc, fs.key), new VarExp(loc, tmp));
@@ -1837,7 +1837,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
break;
}
ss.condition = integralPromotions(ss.condition, sc);
- if (!ss.condition.isErrorExp() && ss.condition.type.isintegral())
+ if (!ss.condition.isErrorExp() && ss.condition.type.isIntegral())
break;
auto ad = isAggregate(ss.condition.type);
@@ -2145,7 +2145,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
{
VarDeclaration v = ve.var.isVarDeclaration();
Type t = cs.exp.type.toBasetype();
- if (v && (t.isintegral() || t.ty == Tclass))
+ if (v && (t.isIntegral() || t.ty == Tclass))
{
/* Flag that we need to do special code generation
* for this, i.e. generate a sequence of if-then-else
@@ -2298,7 +2298,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
uinteger_t fval = crs.first.toInteger();
uinteger_t lval = crs.last.toInteger();
- if ((crs.first.type.isunsigned() && fval > lval) || (!crs.first.type.isunsigned() && cast(sinteger_t)fval > cast(sinteger_t)lval))
+ if ((crs.first.type.isUnsigned() && fval > lval) || (!crs.first.type.isUnsigned() && cast(sinteger_t)fval > cast(sinteger_t)lval))
{
error(crs.loc, "first `case %s` is greater than last `case %s`", crs.first.toChars(), crs.last.toChars());
errors = true;
@@ -2469,7 +2469,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
Type tret = tf.next;
Type tbret = tret ? tret.toBasetype() : null;
- bool inferRef = (tf.isref && (fd.storage_class & STC.auto_));
+ bool inferRef = (tf.isRef && (fd.storage_class & STC.auto_));
Expression e0 = null;
bool errors = false;
@@ -2525,7 +2525,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
rs.exp = rs.exp.expressionSemantic(sc);
rs.exp = rs.exp.arrayFuncConv(sc);
// If we're returning by ref, allow the expression to be `shared`
- const returnSharedRef = (tf.isref && (fd.inferRetType || tret.isShared()));
+ const returnSharedRef = (tf.isRef && (fd.inferRetType || tret.isShared()));
rs.exp.checkSharedAccess(sc, returnSharedRef);
// for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
@@ -2643,8 +2643,8 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
void turnOffRef(scope void delegate() supplemental)
{
- tf.isref = false; // return by value
- tf.isreturn = false; // ignore 'return' attribute, whether explicit or inferred
+ tf.isRef = false; // return by value
+ tf.isReturn = false; // ignore 'return' attribute, whether explicit or inferred
fd.storage_class &= ~STC.return_;
// If we previously assumed the function could be ref when
@@ -2716,7 +2716,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
// https://issues.dlang.org/show_bug.cgi?id=23914
if (inferRef && !resType.isTypeNoreturn()) // deduce 'auto ref'
- tf.isref = false;
+ tf.isRef = false;
if (tbret.ty != Tvoid && !resType.isTypeNoreturn()) // if non-void return
{
@@ -4382,7 +4382,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState
}
p.type = p.type.typeSemantic(loc, sc);
- if (!p.type.isintegral())
+ if (!p.type.isIntegral())
{
error(fs.loc, "foreach: key cannot be of non-integral type `%s`",
p.type.toChars());
@@ -1729,7 +1729,7 @@ FuncDeclaration doHeaderInstantiation(TemplateDeclaration td, TemplateInstance t
{
// For constructors, emitting return type is necessary for
// isReturnIsolated() in functionResolve.
- tf.isctor = true;
+ tf.isCtor = true;
Dsymbol parent = td.toParentDecl();
Type tret;
@@ -1747,7 +1747,7 @@ FuncDeclaration doHeaderInstantiation(TemplateDeclaration td, TemplateInstance t
}
tf.next = tret;
if (ad && ad.isStructDeclaration())
- tf.isref = 1;
+ tf.isRef = 1;
//printf("tf = %s\n", tf.toChars());
}
else
@@ -1940,7 +1940,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
//printf("fd = %s %s, fargs = %s\n", fd.toChars(), fd.type.toChars(), fargs.toChars());
auto tf = fd.type.isTypeFunction();
- int prop = tf.isproperty ? 1 : 2;
+ int prop = tf.isProperty ? 1 : 2;
if (property == 0)
property = prop;
else if (property != prop)
@@ -444,23 +444,23 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
if (e.ident == Id.isArithmetic)
{
- return isTypeX(t => t.isintegral() || t.isfloating());
+ return isTypeX(t => t.isIntegral() || t.isFloating());
}
if (e.ident == Id.isFloating)
{
- return isTypeX(t => t.isfloating());
+ return isTypeX(t => t.isFloating());
}
if (e.ident == Id.isIntegral)
{
- return isTypeX(t => t.isintegral());
+ return isTypeX(t => t.isIntegral());
}
if (e.ident == Id.isScalar)
{
- return isTypeX(t => t.isscalar());
+ return isTypeX(t => t.isScalar());
}
if (e.ident == Id.isUnsigned)
{
- return isTypeX(t => t.isunsigned());
+ return isTypeX(t => t.isUnsigned());
}
if (e.ident == Id.isAssociativeArray)
{
@@ -468,7 +468,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
}
if (e.ident == Id.isDeprecated)
{
- if (isTypeX(t => t.iscomplex() || t.isimaginary()).toBool().hasValue(true))
+ if (isTypeX(t => t.isComplex() || t.isImaginary()).toBool().hasValue(true))
return True();
return isDsymX(t => t.isDeprecated());
}
@@ -482,13 +482,19 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
}
if (e.ident == Id.isAbstractClass)
{
- return isTypeX(t => t.toBasetype().isTypeClass() &&
- t.toBasetype().isTypeClass().sym.isAbstract());
+ return isTypeX((t)
+ {
+ auto c = t.toBasetype().isTypeClass();
+ return c && c.sym.isAbstract();
+ });
}
if (e.ident == Id.isFinalClass)
{
- return isTypeX(t => t.toBasetype().isTypeClass() &&
- (t.toBasetype().isTypeClass().sym.storage_class & STC.final_) != 0);
+ return isTypeX((t)
+ {
+ const c = t.toBasetype().isTypeClass();
+ return c && (c.sym.storage_class & STC.final_) != 0;
+ });
}
if (e.ident == Id.isTemplate)
{
@@ -1773,7 +1779,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
if (sc2.func && sc2.func.type.isTypeFunction())
{
const tf = sc2.func.type.isTypeFunction();
- err |= tf.isnothrow && canThrow(ex, sc2.func, null);
+ err |= tf.isNothrow && canThrow(ex, sc2.func, null);
}
ex = checkGC(sc2, ex);
if (ex.op == EXP.error)
@@ -473,12 +473,12 @@ bool isCopyable(Type t)
* Otherwise, when the type has const/inout indirections, returns 1.
*
* Params:
- * isref = if true, check `ref t`; otherwise, check just `t`
+ * isRef = if true, check `ref t`; otherwise, check just `t`
* t = the type that is being checked
*/
-int mutabilityOfType(bool isref, Type t)
+int mutabilityOfType(bool isRef, Type t)
{
- if (isref)
+ if (isRef)
{
if (t.mod & MODFlags.immutable_)
return 2;
@@ -631,7 +631,7 @@ extern (D) bool checkComplexTransition(Type type, const ref Loc loc, Scope* sc)
if (t.ty == Tenum && !(cast(TypeEnum)t).sym.memtype)
return false;
- if (t.isimaginary() || t.iscomplex())
+ if (t.isImaginary() || t.isComplex())
{
if (sc.inCfile)
return true; // complex/imaginary not deprecated in C code
@@ -660,7 +660,7 @@ extern (D) bool checkComplexTransition(Type type, const ref Loc loc, Scope* sc)
// Deprecated in 2.097 - Can be made an error from 2.117.
// The deprecation period is longer than usual as `cfloat`,
// `cdouble`, and `creal` were quite widely used.
- if (t.iscomplex())
+ if (t.isComplex())
{
deprecation(loc, "use of complex type `%s` is deprecated, use `std.complex.Complex!(%s)` instead",
type.toChars(), rt.toChars());
@@ -2150,23 +2150,23 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
if (sc.stc & STC.pure_)
tf.purity = PURE.fwdref;
if (sc.stc & STC.nothrow_)
- tf.isnothrow = true;
+ tf.isNothrow = true;
if (sc.stc & STC.nogc)
- tf.isnogc = true;
+ tf.isNogc = true;
if (sc.stc & STC.ref_)
- tf.isref = true;
+ tf.isRef = true;
if (sc.stc & STC.return_)
- tf.isreturn = true;
+ tf.isReturn = true;
if (sc.stc & STC.returnScope)
- tf.isreturnscope = true;
+ tf.isReturnScope = true;
if (sc.stc & STC.returninferred)
- tf.isreturninferred = true;
+ tf.isReturnInferred = true;
if (sc.stc & STC.scope_)
tf.isScopeQual = true;
if (sc.stc & STC.scopeinferred)
- tf.isscopeinferred = true;
+ tf.isScopeInferred = true;
-// if (tf.isreturn && !tf.isref)
+// if (tf.isReturn && !tf.isRef)
// tf.isScopeQual = true; // return by itself means 'return scope'
if (tf.trust == TRUST.default_)
@@ -2180,9 +2180,9 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
}
if (sc.stc & STC.property)
- tf.isproperty = true;
+ tf.isProperty = true;
if (sc.stc & STC.live)
- tf.islive = true;
+ tf.isLive = true;
tf.linkage = sc.linkage;
if (tf.linkage == LINK.system)
@@ -2216,7 +2216,7 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
tf.next = tf.next.typeSemantic(loc, sc);
sc = sc.pop();
errors |= tf.checkRetType(loc);
- if (tf.next.isScopeClass() && !tf.isctor)
+ if (tf.next.isScopeClass() && !tf.isCtor)
{
.error(loc, "functions cannot return `scope %s`", tf.next.toChars());
errors = true;
@@ -2224,9 +2224,9 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
if (tf.next.hasWild())
wildreturn = true;
- if (tf.isreturn && !tf.isref && !tf.next.hasPointers())
+ if (tf.isReturn && !tf.isRef && !tf.next.hasPointers())
{
- tf.isreturn = false;
+ tf.isReturn = false;
}
}
@@ -2449,7 +2449,7 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
{
if (!(fparam.storageClass & STC.scope_))
fparam.storageClass |= STC.scope_ | STC.scopeinferred; // 'return' implies 'scope'
- if (tf.isref)
+ if (tf.isRef)
{
}
else if (tf.next && !tf.next.hasPointers() && tf.next.toBasetype().ty != Tvoid)
@@ -2607,7 +2607,7 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
tf.isInOutParam = (wildparams & 1) != 0;
tf.isInOutQual = (wildparams & 2) != 0;
- if (tf.isproperty && (tf.parameterList.varargs != VarArg.none || tf.parameterList.length > 2))
+ if (tf.isProperty && (tf.parameterList.varargs != VarArg.none || tf.parameterList.length > 2))
{
.error(loc, "properties can only have zero, one, or two parameter");
errors = true;
@@ -3429,7 +3429,7 @@ Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden
Expression floatValue(real_t r)
{
- if (mt.isreal() || mt.isimaginary())
+ if (mt.isReal() || mt.isImaginary())
return new RealExp(loc, r, mt);
else
{
@@ -4769,8 +4769,8 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag
fd_aaLen = FuncDeclaration.genCfunc(fparams, Type.tsize_t, Id.aaLen);
TypeFunction tf = fd_aaLen.type.toTypeFunction();
tf.purity = PURE.const_;
- tf.isnothrow = true;
- tf.isnogc = false;
+ tf.isNothrow = true;
+ tf.isNogc = false;
}
Expression ev = new VarExp(e.loc, fd_aaLen, false);
e = new CallExp(e.loc, ev, e);
@@ -6107,8 +6107,8 @@ Type addStorageClass(Type type, StorageClass stc)
//printf("addStorageClass(%llx) %d\n", stc, (stc & STC.scope_) != 0);
TypeFunction t = visitType(tf_src).toTypeFunction();
if ((stc & STC.pure_ && !t.purity) ||
- (stc & STC.nothrow_ && !t.isnothrow) ||
- (stc & STC.nogc && !t.isnogc) ||
+ (stc & STC.nothrow_ && !t.isNothrow) ||
+ (stc & STC.nogc && !t.isNogc) ||
(stc & STC.scope_ && !t.isScopeQual) ||
(stc & STC.safe && t.trust < TRUST.trusted))
{
@@ -6117,33 +6117,33 @@ Type addStorageClass(Type type, StorageClass stc)
tf.mod = t.mod;
tf.inferenceArguments = tf_src.inferenceArguments;
tf.purity = t.purity;
- tf.isnothrow = t.isnothrow;
- tf.isnogc = t.isnogc;
- tf.isproperty = t.isproperty;
- tf.isref = t.isref;
- tf.isreturn = t.isreturn;
- tf.isreturnscope = t.isreturnscope;
+ tf.isNothrow = t.isNothrow;
+ tf.isNogc = t.isNogc;
+ tf.isProperty = t.isProperty;
+ tf.isRef = t.isRef;
+ tf.isReturn = t.isReturn;
+ tf.isReturnScope = t.isReturnScope;
tf.isScopeQual = t.isScopeQual;
- tf.isreturninferred = t.isreturninferred;
- tf.isscopeinferred = t.isscopeinferred;
+ tf.isReturnInferred = t.isReturnInferred;
+ tf.isScopeInferred = t.isScopeInferred;
tf.trust = t.trust;
tf.isInOutParam = t.isInOutParam;
tf.isInOutQual = t.isInOutQual;
- tf.isctor = t.isctor;
+ tf.isCtor = t.isCtor;
if (stc & STC.pure_)
tf.purity = PURE.fwdref;
if (stc & STC.nothrow_)
- tf.isnothrow = true;
+ tf.isNothrow = true;
if (stc & STC.nogc)
- tf.isnogc = true;
+ tf.isNogc = true;
if (stc & STC.safe)
tf.trust = TRUST.safe;
if (stc & STC.scope_)
{
tf.isScopeQual = true;
if (stc & STC.scopeinferred)
- tf.isscopeinferred = true;
+ tf.isScopeInferred = true;
}
tf.deco = tf.merge().deco;
@@ -6315,7 +6315,7 @@ Covariant covariant(Type src, Type t, StorageClass* pstc = null, bool cppCovaria
goto Ldistinct;
}
Lcov:
- notcovariant |= !fparam1.isCovariant(t1.isref, fparam2);
+ notcovariant |= !fparam1.isCovariant(t1.isRef, fparam2);
/* https://issues.dlang.org/show_bug.cgi?id=23135
* extern(C++) mutable parameters are not covariant with const.
@@ -6375,7 +6375,7 @@ Covariant covariant(Type src, Type t, StorageClass* pstc = null, bool cppCovaria
}
else if (t1n.ty == t2n.ty && t1n.implicitConvTo(t2n))
{
- if (t1.isref && t2.isref)
+ if (t1.isRef && t2.isRef)
{
// Treat like pointers to t1n and t2n
if (t1n.constConv(t2n) < MATCH.constant)
@@ -6400,31 +6400,31 @@ Covariant covariant(Type src, Type t, StorageClass* pstc = null, bool cppCovaria
goto Lnotcovariant;
Lcovariant:
- if (t1.isref != t2.isref)
+ if (t1.isRef != t2.isRef)
goto Lnotcovariant;
- if (!t1.isref && (t1.isScopeQual || t2.isScopeQual))
+ if (!t1.isRef && (t1.isScopeQual || t2.isScopeQual))
{
StorageClass stc1 = t1.isScopeQual ? STC.scope_ : 0;
StorageClass stc2 = t2.isScopeQual ? STC.scope_ : 0;
- if (t1.isreturn)
+ if (t1.isReturn)
{
stc1 |= STC.return_;
if (!t1.isScopeQual)
stc1 |= STC.ref_;
}
- if (t2.isreturn)
+ if (t2.isReturn)
{
stc2 |= STC.return_;
if (!t2.isScopeQual)
stc2 |= STC.ref_;
}
- if (!Parameter.isCovariantScope(t1.isref, stc1, stc2))
+ if (!Parameter.isCovariantScope(t1.isRef, stc1, stc2))
goto Lnotcovariant;
}
// We can subtract 'return ref' from 'this', but cannot add it
- else if (t1.isreturn && !t2.isreturn)
+ else if (t1.isReturn && !t2.isReturn)
goto Lnotcovariant;
/* https://issues.dlang.org/show_bug.cgi?id=23135
@@ -6457,10 +6457,10 @@ Lcovariant:
if (!t1.purity && t2.purity)
stc |= STC.pure_;
- if (!t1.isnothrow && t2.isnothrow)
+ if (!t1.isNothrow && t2.isNothrow)
stc |= STC.nothrow_;
- if (!t1.isnogc && t2.isnogc)
+ if (!t1.isNogc && t2.isNogc)
stc |= STC.nogc;
/* Can convert safe/trusted to system
@@ -6519,7 +6519,7 @@ StorageClass parameterStorageClass(TypeFunction tf, Type tthis, Parameter p, Var
/* If haven't inferred the return type yet, can't infer storage classes
*/
- if (!tf.nextOf() || !tf.isnothrow())
+ if (!tf.nextOf() || !tf.isNothrow())
return stc;
tf.purityLevel();
@@ -6599,7 +6599,7 @@ StorageClass parameterStorageClass(TypeFunction tf, Type tthis, Parameter p, Var
// Check escaping through return value
Type tret = tf.nextOf().toBasetype();
- if (tf.isref || tret.hasPointers())
+ if (tf.isRef || tret.hasPointers())
{
return stc | STC.scope_ | STC.return_ | STC.returnScope;
}
@@ -7196,21 +7196,21 @@ Type substWildTo(Type type, uint mod)
// Similar to TypeFunction.syntaxCopy;
auto t = new TypeFunction(ParameterList(params, tf.parameterList.varargs), tret, tf.linkage);
t.mod = ((tf.mod & MODFlags.wild) ? (tf.mod & ~MODFlags.wild) | MODFlags.const_ : tf.mod);
- t.isnothrow = tf.isnothrow;
- t.isnogc = tf.isnogc;
+ t.isNothrow = tf.isNothrow;
+ t.isNogc = tf.isNogc;
t.purity = tf.purity;
- t.isproperty = tf.isproperty;
- t.isref = tf.isref;
- t.isreturn = tf.isreturn;
- t.isreturnscope = tf.isreturnscope;
+ t.isProperty = tf.isProperty;
+ t.isRef = tf.isRef;
+ t.isReturn = tf.isReturn;
+ t.isReturnScope = tf.isReturnScope;
t.isScopeQual = tf.isScopeQual;
- t.isreturninferred = tf.isreturninferred;
- t.isscopeinferred = tf.isscopeinferred;
+ t.isReturnInferred = tf.isReturnInferred;
+ t.isScopeInferred = tf.isScopeInferred;
t.isInOutParam = false;
t.isInOutQual = false;
t.trust = tf.trust;
t.inferenceArguments = tf.inferenceArguments;
- t.isctor = tf.isctor;
+ t.isCtor = tf.isCtor;
return t.merge();
}
@@ -7713,7 +7713,7 @@ Expression getMaxMinValue(EnumDeclaration ed, const ref Loc loc, Identifier id)
.error(loc, "%s `%s` is opaque and has no `.%s`", ed.kind, ed.toPrettyChars, id.toChars(), id.toChars());
return errorReturn();
}
- if (!(ed.memtype && ed.memtype.isintegral()))
+ if (!(ed.memtype && ed.memtype.isIntegral()))
{
.error(loc, "%s `%s` has no `.%s` property because base type `%s` is not an integral type", ed.kind, ed.toPrettyChars, id.toChars(),
id.toChars(), ed.memtype ? ed.memtype.toChars() : "");
@@ -295,14 +295,14 @@ public:
this->result_ = d_convert (build_ctype (e->type),
build_boolop (code, t1, t2));
}
- else if (tb1->isfloating () && tb1->ty != TY::Tvector)
+ else if (tb1->isFloating () && tb1->ty != TY::Tvector)
{
/* For floating-point values, identity is defined as the bits in the
operands being identical. */
tree t1 = d_save_expr (build_expr (e->e1));
tree t2 = d_save_expr (build_expr (e->e2));
- if (!tb1->iscomplex ())
+ if (!tb1->isComplex ())
this->result_ = build_float_identity (code, t1, t2);
else
{
@@ -388,7 +388,7 @@ public:
e1.length == e2.length && memcmp(e1.ptr, e2.ptr, size) == 0;
Or when generating a NE expression:
e1.length != e2.length || memcmp(e1.ptr, e2.ptr, size) != 0; */
- if ((t1elem->isintegral () || t1elem->ty == TY::Tvoid
+ if ((t1elem->isIntegral () || t1elem->ty == TY::Tvoid
|| (t1elem->ty == TY::Tstruct
&& !t1elem->isTypeStruct ()->sym->xeq))
&& t1elem->ty == t2elem->ty)
@@ -621,8 +621,8 @@ public:
{
case EXP::add:
case EXP::min:
- if ((e->e1->type->isreal () && e->e2->type->isimaginary ())
- || (e->e1->type->isimaginary () && e->e2->type->isreal ()))
+ if ((e->e1->type->isReal () && e->e2->type->isImaginary ())
+ || (e->e1->type->isImaginary () && e->e2->type->isReal ()))
{
/* If the result is complex, then we can shortcut binary_op.
Frontend should have already validated types and sizes. */
@@ -632,7 +632,7 @@ public:
if (e->op == EXP::min)
t2 = build1 (NEGATE_EXPR, TREE_TYPE (t2), t2);
- if (e->e1->type->isreal ())
+ if (e->e1->type->isReal ())
this->result_ = complex_expr (build_ctype (e->type), t1, t2);
else
this->result_ = complex_expr (build_ctype (e->type), t2, t1);
@@ -662,12 +662,12 @@ public:
}
}
- code = e->e1->type->isintegral ()
+ code = e->e1->type->isIntegral ()
? TRUNC_DIV_EXPR : RDIV_EXPR;
break;
case EXP::mod:
- code = e->e1->type->isfloating ()
+ code = e->e1->type->isFloating ()
? FLOAT_MOD_EXPR : TRUNC_MOD_EXPR;
break;
@@ -751,12 +751,12 @@ public:
break;
case EXP::divAssign:
- code = e->e1->type->isintegral ()
+ code = e->e1->type->isIntegral ()
? TRUNC_DIV_EXPR : RDIV_EXPR;
break;
case EXP::modAssign:
- code = e->e1->type->isfloating ()
+ code = e->e1->type->isFloating ()
? FLOAT_MOD_EXPR : TRUNC_MOD_EXPR;
break;
@@ -1506,7 +1506,7 @@ public:
{
AddExp *ae = e->e1->isAddExp ();
if (ae->e1->op == EXP::address
- && ae->e2->isConst () && ae->e2->type->isintegral ())
+ && ae->e2->isConst () && ae->e2->type->isIntegral ())
{
Expression *ex = ae->e1->isAddrExp ()->e1;
tnext = ex->type->toBasetype ();
@@ -1754,7 +1754,7 @@ public:
if (returnvalue != NULL_TREE)
exp = compound_expr (exp, returnvalue);
- if (tf->isref ())
+ if (tf->isRef ())
exp = build_deref (exp);
/* Some library calls are defined to return a generic type.
@@ -3062,7 +3062,7 @@ build_return_dtor (Expression *e, Type *type, TypeFunction *tf)
tree result = build_expr (e);
/* Convert for initializing the DECL_RESULT. */
- if (tf->isref ())
+ if (tf->isRef ())
{
/* If we are returning a reference, take the address. */
result = convert_expr (result, e->type, type);
@@ -130,7 +130,7 @@ public:
void visit (VarDeclaration *d) final override
{
/* Not all kinds of manifest constants create a CONST_DECL. */
- if (!d->canTakeAddressOf () && !d->type->isscalar ())
+ if (!d->canTakeAddressOf () && !d->type->isScalar ())
return;
visit ((Declaration *) d);
@@ -831,7 +831,7 @@ public:
/* A switch statement on a string gets turned into a library call.
It is not lowered during codegen. */
- if (!condtype->isscalar ())
+ if (!condtype->isScalar ())
{
error ("cannot handle switch condition of type %s",
condtype->toChars ());
@@ -920,7 +920,7 @@ public:
else
{
tree casevalue;
- if (s->exp->type->isscalar ())
+ if (s->exp->type->isScalar ())
casevalue = build_expr (s->exp);
else
casevalue = build_integer_cst (s->index, build_ctype (Type::tint32));
@@ -1008,7 +1008,7 @@ public:
/* Returning by hidden reference, store the result into the retval decl.
The result returned then becomes the retval reference itself. */
tree decl = DECL_RESULT (get_symbol_decl (this->func_));
- gcc_assert (!tf->isref ());
+ gcc_assert (!tf->isRef ());
/* If returning via NRVO, just refer to the DECL_RESULT; this differs
from using NULL_TREE in that it indicates that we care about the
@@ -892,7 +892,7 @@ public:
void visit (TypeSArray *t) final override
{
- if (t->dim->isConst () && t->dim->type->isintegral ())
+ if (t->dim->isConst () && t->dim->type->isIntegral ())
{
uinteger_t size = t->dim->toUInteger ();
t->ctype = make_array_type (t->next, size);
@@ -975,7 +975,7 @@ public:
if (t->next != NULL)
{
fntype = build_ctype (t->next);
- if (t->isref ())
+ if (t->isRef ())
fntype = build_reference_type (fntype);
}
else
deleted file mode 100644
@@ -1,49 +0,0 @@
-/**
-Checks that code still compiles when -preview=dtorfields is enabled by default
-but issues an appropriate deprecation message.
-
-Remove this test when the deprecations period ends, see visit(CtorDeclaration)
-in semantic3.d
-
-TEST_OUTPUT:
----
-compilable/dtorfields_deprecation.d(30): Deprecation: `dtorfields_deprecation.Pure.this` has stricter attributes than its destructor (`pure`)
-compilable/dtorfields_deprecation.d(30): The destructor will be called if an exception is thrown
-compilable/dtorfields_deprecation.d(30): Either make the constructor `nothrow` or adjust the field destructors
-compilable/dtorfields_deprecation.d(42): Deprecation: `dtorfields_deprecation.NoGC.this` has stricter attributes than its destructor (`@nogc`)
-compilable/dtorfields_deprecation.d(42): The destructor will be called if an exception is thrown
-compilable/dtorfields_deprecation.d(42): Either make the constructor `nothrow` or adjust the field destructors
-compilable/dtorfields_deprecation.d(48): Deprecation: `dtorfields_deprecation.Safe.this` has stricter attributes than its destructor (`@system`)
-compilable/dtorfields_deprecation.d(48): The destructor will be called if an exception is thrown
-compilable/dtorfields_deprecation.d(48): Either make the constructor `nothrow` or adjust the field destructors
----
-**/
-
-struct HasDtor
-{
- ~this() {}
-}
-
-struct Pure
-{
- HasDtor member;
- this(int) pure {}
-}
-
-struct Nothrow
-{
- HasDtor member;
- this(int) nothrow {}
-}
-
-struct NoGC
-{
- HasDtor member;
- this(int) @nogc {}
-}
-
-struct Safe
-{
- HasDtor member;
- this(int) @safe {}
-}
@@ -55,3 +55,11 @@ int pr16199c()
{
return 8;
}
+
+// https://issues.dlang.org/show_bug.cgi?id=24639
+#define NEGATIVE_I32 -1
+#define NEGATIVE_U32 -2U
+#define NEGATIVE_I64 -3LL
+#define NEGATIVE_U64 -4LLU
+#define NEGATIVE_F32 -5.0f
+#define NEGATIVE_F64 -6.0
@@ -20,4 +20,11 @@ class Oops
// this shouldn't compile `k` is a field of class `Oops`
static assert (!__traits(compiles, k = 2));
}
+
+ // https://issues.dlang.org/show_bug.cgi?id=24705
+ synchronized void foo(int n)
+ {
+ // Error: direct access to shared `n` is not allowed, see `core.atomic`
+ int a = n;
+ }
}
@@ -25,3 +25,17 @@ static assert(pr16199_ice == 3);
static assert(pr16199d() == 7);
static assert(pr16199c() == 8);
+
+// https://issues.dlang.org/show_bug.cgi?id=24639
+static assert(NEGATIVE_I32 == -1);
+static assert(NEGATIVE_U32 == cast(uint)-2);
+static assert(NEGATIVE_I64 == -3);
+static assert(NEGATIVE_U64 == cast(ulong)-4L);
+static assert(NEGATIVE_F32 == -5f);
+static assert(NEGATIVE_F64 == -6);
+static assert(is(typeof(NEGATIVE_I32) == int));
+static assert(is(typeof(NEGATIVE_U32) == uint));
+static assert(is(typeof(NEGATIVE_I64) == long));
+static assert(is(typeof(NEGATIVE_U64) == ulong));
+static assert(is(typeof(NEGATIVE_F32) == float));
+static assert(is(typeof(NEGATIVE_F64) == double));
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/alias_instance_member.d(18): Error: cannot alias member of variable `that`
+fail_compilation/alias_instance_member.d(18): Error: cannot alias variable member `v` of variable `that`
fail_compilation/alias_instance_member.d(18): Use `typeof(that)` instead to preserve behaviour
---
*/
@@ -17,6 +17,7 @@ struct Foo
alias a = this.v; // OK
alias b = that.v;
assert(&a is &b);
+ alias b2 = typeof(that).v; // OK
}
}
@@ -1,8 +1,10 @@
/*
TEST_OUTPUT:
---
-fail_compilation/alias_instance_member2.d(20): Error: cannot alias member of variable `f`
-fail_compilation/alias_instance_member2.d(20): Use `typeof(f)` instead to preserve behaviour
+fail_compilation/alias_instance_member2.d(26): Error: cannot alias variable member `v` of variable `f`
+fail_compilation/alias_instance_member2.d(26): Use `typeof(f)` instead to preserve behaviour
+fail_compilation/alias_instance_member2.d(30): Error: cannot alias function member `fun` of variable `f`
+fail_compilation/alias_instance_member2.d(30): Use `typeof(f)` instead to preserve behaviour
---
*/
@@ -12,10 +14,19 @@ module aim;
struct Foo
{
int v;
+ static int w;
+ enum x = 5;
+ void fun() {}
+ static void gun() {}
}
struct Bar
{
Foo f;
alias v = f.v;
+ alias v2 = typeof(f).v; // OK
+ alias w = f.w; // OK
+ alias x = f.x; // OK
+ alias fun = f.fun;
+ alias gun = f.gun; // OK
}
new file mode 100644
@@ -0,0 +1,12 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/auto_ref_inout.d(12): Error: template `f` is not callable using argument types `!()(int)`
+fail_compilation/auto_ref_inout.d(10): Candidate is: `f(T)(auto ref inout T a, auto ref inout T b)`
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=24707
+auto ref inout(T) f(T)(auto ref inout T a, auto ref inout T b);
+
+enum e = f(5);
@@ -1,6 +1,8 @@
/* REQUIRED_ARGS: -verrors=0
TEST_OUTPUT:
---
+fail_compilation/diag9679.d(93): Deprecation: `auto` and `ref` storage classes should be adjacent
+fail_compilation/diag9679.d(93): Deprecation: `auto` and `ref` storage classes should be adjacent
fail_compilation/diag9679.d(15): Error: rvalue `1` cannot be assigned to `ref n`
fail_compilation/diag9679.d(16): Error: variable `diag9679.main.n` - storage class `auto` has no effect if type is not inferred, did you mean `scope`?
fail_compilation/diag9679.d(17): Error: variable `diag9679.main.S.a` - field declarations cannot be `ref`
@@ -8,8 +10,6 @@ fail_compilation/diag9679.d(24): Error: returning `r` escapes a reference to loc
---
*/
-
-
void main()
{
if (ref n = 1) {}
@@ -48,13 +48,19 @@ void test4()
/* TEST_OUTPUT:
---
-fail_compilation/diag9679.d(60): Error: variable `diag9679.test5.r5` - initializer is required for `ref` variable
-fail_compilation/diag9679.d(60): Error: rvalue `0` cannot be assigned to `ref r5`
-fail_compilation/diag9679.d(65): Error: rvalue `4` cannot be assigned to `ref x`
-fail_compilation/diag9679.d(66): Error: returning `x` escapes a reference to local variable `x`
-fail_compilation/diag9679.d(71): Error: type `immutable(int)` cannot be assigned to `ref int x`
+fail_compilation/diag9679.d(66): Error: variable `diag9679.test5.r5` - initializer is required for `ref` variable
+fail_compilation/diag9679.d(66): Error: rvalue `0` cannot be assigned to `ref r5`
+fail_compilation/diag9679.d(71): Error: rvalue `4` cannot be assigned to `ref x`
+fail_compilation/diag9679.d(72): Error: returning `x` escapes a reference to local variable `x`
+fail_compilation/diag9679.d(77): Error: type `immutable(int)` cannot be assigned to `ref int x`
+fail_compilation/diag9679.d(84): Error: returning `x` escapes a reference to local variable `x`
+fail_compilation/diag9679.d(89): Error: variable `diag9679.test9.x` - void initializer not allowed for `ref` variable
+fail_compilation/diag9679.d(90): Error: variable `diag9679.test9.y` - void initializer not allowed for `ref` variable
+fail_compilation/diag9679.d(96): Error: variable `x` - `auto ref` variable must have `auto` and `ref` adjacent
---
*/
+
+
void test5()
{
ref int r5;
@@ -71,3 +77,21 @@ void test7(immutable int y)
ref int x = y;
x = 5;
}
+
+ref int test8()
+{
+ auto ref int x = 3;
+ return x;
+}
+
+void test9()
+{
+ ref int x = void;
+ auto ref int y = void;
+}
+
+void testKeywordOrder()(ref auto int x, auto const ref float y) {}
+void testKeywordOrder()
+{
+ ref auto int x = 3;
+}
@@ -1,9 +1,8 @@
-// REQUIRED_ARGS: -de
/*
TEST_OUTPUT:
---
-fail_compilation/fail13123.d(10): Deprecation: `fail13123.test`: `in` contract may throw but function is marked as `nothrow`
-fail_compilation/fail13123.d(10): Deprecation: `fail13123.test`: `out` contract may throw but function is marked as `nothrow`
+fail_compilation/fail13123.d(9): Error: `fail13123.test`: `in` contract may throw but function is marked as `nothrow`
+fail_compilation/fail13123.d(9): Error: `fail13123.test`: `out` contract may throw but function is marked as `nothrow`
---
*/
@@ -4,7 +4,7 @@ TEST_OUTPUT:
---
(spec:1) fail_compilation/fail20730b.d-mixin-43(43): Error: C style cast illegal, use `cast(int)mod`
fail_compilation/fail20730b.d(26): Error: template `atomicOp` is not callable using argument types `!("+=")(shared(uint), int)`
-fail_compilation/fail20730b.d(41): Candidate is: `atomicOp(string op, T, V1)(shared ref T val, V1 mod)`
+fail_compilation/fail20730b.d(41): Candidate is: `atomicOp(string op, T, V1)(ref shared T val, V1 mod)`
with `op = "+=",
T = uint,
V1 = int`
@@ -1,13 +1,14 @@
/*
TEST_OUTPUT:
---
-fail_compilation/misc1.d(108): Error: `5` has no effect
-fail_compilation/misc1.d(109): Error: `1 + 2` has no effect
-fail_compilation/misc1.d(115): Deprecation: `1 * 1` has no effect
-fail_compilation/misc1.d(116): Deprecation: `__lambda3` has no effect
-fail_compilation/misc1.d(122): Deprecation: `false` has no effect
-fail_compilation/misc1.d(125): Deprecation: `*sp++` has no effect
-fail_compilation/misc1.d(126): Deprecation: `j` has no effect
+fail_compilation/misc1.d(109): Error: `5` has no effect
+fail_compilation/misc1.d(110): Error: `1 + 2` has no effect
+fail_compilation/misc1.d(111): Error: `x` has no effect
+fail_compilation/misc1.d(117): Deprecation: `1 * 1` has no effect
+fail_compilation/misc1.d(118): Deprecation: `__lambda3` has no effect
+fail_compilation/misc1.d(124): Deprecation: `false` has no effect
+fail_compilation/misc1.d(127): Deprecation: `*sp++` has no effect
+fail_compilation/misc1.d(128): Deprecation: `j` has no effect
---
*/
@@ -20,8 +21,10 @@ void hasSideEffect12490(){}
void issue12490()
{
+ int x;
5, hasSideEffect12490();
1 + 2, hasSideEffect12490();
+ x, x++;
}
void issue23480()
@@ -1,16 +1,19 @@
/+
TEST_OUTPUT:
---
-fail_compilation/must_use.d(15): Error: ignored value of `@mustuse` type `must_use.S`; prepend a `cast(void)` if intentional
+fail_compilation/must_use.d(17): Error: ignored value of `@mustuse` type `must_use.S`; prepend a `cast(void)` if intentional
+fail_compilation/must_use.d(18): Error: ignored value of `@mustuse` type `must_use.S`; prepend a `cast(void)` if intentional
---
+/
import core.attribute;
@mustuse struct S {}
-S fun() { return S(); }
+S fun();
void test()
{
+ int x;
fun();
+ fun(), x++;
}
@@ -80,49 +80,50 @@ fail_compilation/reserved_version.d(179): Error: version identifier `LoongArch32
fail_compilation/reserved_version.d(180): Error: version identifier `LoongArch64` is reserved and cannot be set
fail_compilation/reserved_version.d(181): Error: version identifier `LoongArch_HardFloat` is reserved and cannot be set
fail_compilation/reserved_version.d(182): Error: version identifier `LoongArch_SoftFloat` is reserved and cannot be set
-fail_compilation/reserved_version.d(183): Error: version identifier `LittleEndian` is reserved and cannot be set
-fail_compilation/reserved_version.d(184): Error: version identifier `BigEndian` is reserved and cannot be set
-fail_compilation/reserved_version.d(185): Error: version identifier `ELFv1` is reserved and cannot be set
-fail_compilation/reserved_version.d(186): Error: version identifier `ELFv2` is reserved and cannot be set
-fail_compilation/reserved_version.d(187): Error: version identifier `CRuntime_Bionic` is reserved and cannot be set
-fail_compilation/reserved_version.d(188): Error: version identifier `CRuntime_DigitalMars` is reserved and cannot be set
-fail_compilation/reserved_version.d(189): Error: version identifier `CRuntime_Glibc` is reserved and cannot be set
-fail_compilation/reserved_version.d(190): Error: version identifier `CRuntime_Microsoft` is reserved and cannot be set
-fail_compilation/reserved_version.d(191): Error: version identifier `CRuntime_Musl` is reserved and cannot be set
-fail_compilation/reserved_version.d(192): Error: version identifier `CRuntime_Newlib` is reserved and cannot be set
-fail_compilation/reserved_version.d(193): Error: version identifier `CRuntime_UClibc` is reserved and cannot be set
-fail_compilation/reserved_version.d(194): Error: version identifier `CRuntime_WASI` is reserved and cannot be set
-fail_compilation/reserved_version.d(195): Error: version identifier `D_Coverage` is reserved and cannot be set
-fail_compilation/reserved_version.d(196): Error: version identifier `D_Ddoc` is reserved and cannot be set
-fail_compilation/reserved_version.d(197): Error: version identifier `D_InlineAsm_X86` is reserved and cannot be set
-fail_compilation/reserved_version.d(198): Error: version identifier `D_InlineAsm_X86_64` is reserved and cannot be set
-fail_compilation/reserved_version.d(199): Error: version identifier `D_LP64` is reserved and cannot be set
-fail_compilation/reserved_version.d(200): Error: version identifier `D_X32` is reserved and cannot be set
-fail_compilation/reserved_version.d(201): Error: version identifier `D_HardFloat` is reserved and cannot be set
-fail_compilation/reserved_version.d(202): Error: version identifier `D_SoftFloat` is reserved and cannot be set
-fail_compilation/reserved_version.d(203): Error: version identifier `D_PIC` is reserved and cannot be set
-fail_compilation/reserved_version.d(204): Error: version identifier `D_SIMD` is reserved and cannot be set
-fail_compilation/reserved_version.d(205): Error: version identifier `D_Version2` is reserved and cannot be set
-fail_compilation/reserved_version.d(206): Error: version identifier `D_NoBoundsChecks` is reserved and cannot be set
-fail_compilation/reserved_version.d(209): Error: version identifier `all` is reserved and cannot be set
-fail_compilation/reserved_version.d(210): Error: version identifier `none` is reserved and cannot be set
-fail_compilation/reserved_version.d(211): Error: version identifier `AsmJS` is reserved and cannot be set
-fail_compilation/reserved_version.d(212): Error: version identifier `Emscripten` is reserved and cannot be set
-fail_compilation/reserved_version.d(213): Error: version identifier `WebAssembly` is reserved and cannot be set
-fail_compilation/reserved_version.d(214): Error: version identifier `WASI` is reserved and cannot be set
-fail_compilation/reserved_version.d(215): Error: version identifier `CppRuntime_LLVM` is reserved and cannot be set
-fail_compilation/reserved_version.d(216): Error: version identifier `CppRuntime_DigitalMars` is reserved and cannot be set
-fail_compilation/reserved_version.d(217): Error: version identifier `CppRuntime_GNU` is reserved and cannot be set
-fail_compilation/reserved_version.d(218): Error: version identifier `CppRuntime_Microsoft` is reserved and cannot be set
-fail_compilation/reserved_version.d(219): Error: version identifier `CppRuntime_Sun` is reserved and cannot be set
-fail_compilation/reserved_version.d(220): Error: version identifier `D_PIE` is reserved and cannot be set
-fail_compilation/reserved_version.d(221): Error: version identifier `AVR` is reserved and cannot be set
-fail_compilation/reserved_version.d(222): Error: version identifier `D_PreConditions` is reserved and cannot be set
-fail_compilation/reserved_version.d(223): Error: version identifier `D_PostConditions` is reserved and cannot be set
-fail_compilation/reserved_version.d(224): Error: version identifier `D_ProfileGC` is reserved and cannot be set
-fail_compilation/reserved_version.d(225): Error: version identifier `D_Invariants` is reserved and cannot be set
-fail_compilation/reserved_version.d(226): Error: version identifier `D_Optimized` is reserved and cannot be set
-fail_compilation/reserved_version.d(227): Error: version identifier `VisionOS` is reserved and cannot be set
+fail_compilation/reserved_version.d(183): Error: version identifier `Xtensa` is reserved and cannot be set
+fail_compilation/reserved_version.d(184): Error: version identifier `LittleEndian` is reserved and cannot be set
+fail_compilation/reserved_version.d(185): Error: version identifier `BigEndian` is reserved and cannot be set
+fail_compilation/reserved_version.d(186): Error: version identifier `ELFv1` is reserved and cannot be set
+fail_compilation/reserved_version.d(187): Error: version identifier `ELFv2` is reserved and cannot be set
+fail_compilation/reserved_version.d(188): Error: version identifier `CRuntime_Bionic` is reserved and cannot be set
+fail_compilation/reserved_version.d(189): Error: version identifier `CRuntime_DigitalMars` is reserved and cannot be set
+fail_compilation/reserved_version.d(190): Error: version identifier `CRuntime_Glibc` is reserved and cannot be set
+fail_compilation/reserved_version.d(191): Error: version identifier `CRuntime_Microsoft` is reserved and cannot be set
+fail_compilation/reserved_version.d(192): Error: version identifier `CRuntime_Musl` is reserved and cannot be set
+fail_compilation/reserved_version.d(193): Error: version identifier `CRuntime_Newlib` is reserved and cannot be set
+fail_compilation/reserved_version.d(194): Error: version identifier `CRuntime_UClibc` is reserved and cannot be set
+fail_compilation/reserved_version.d(195): Error: version identifier `CRuntime_WASI` is reserved and cannot be set
+fail_compilation/reserved_version.d(196): Error: version identifier `D_Coverage` is reserved and cannot be set
+fail_compilation/reserved_version.d(197): Error: version identifier `D_Ddoc` is reserved and cannot be set
+fail_compilation/reserved_version.d(198): Error: version identifier `D_InlineAsm_X86` is reserved and cannot be set
+fail_compilation/reserved_version.d(199): Error: version identifier `D_InlineAsm_X86_64` is reserved and cannot be set
+fail_compilation/reserved_version.d(200): Error: version identifier `D_LP64` is reserved and cannot be set
+fail_compilation/reserved_version.d(201): Error: version identifier `D_X32` is reserved and cannot be set
+fail_compilation/reserved_version.d(202): Error: version identifier `D_HardFloat` is reserved and cannot be set
+fail_compilation/reserved_version.d(203): Error: version identifier `D_SoftFloat` is reserved and cannot be set
+fail_compilation/reserved_version.d(204): Error: version identifier `D_PIC` is reserved and cannot be set
+fail_compilation/reserved_version.d(205): Error: version identifier `D_SIMD` is reserved and cannot be set
+fail_compilation/reserved_version.d(206): Error: version identifier `D_Version2` is reserved and cannot be set
+fail_compilation/reserved_version.d(207): Error: version identifier `D_NoBoundsChecks` is reserved and cannot be set
+fail_compilation/reserved_version.d(210): Error: version identifier `all` is reserved and cannot be set
+fail_compilation/reserved_version.d(211): Error: version identifier `none` is reserved and cannot be set
+fail_compilation/reserved_version.d(212): Error: version identifier `AsmJS` is reserved and cannot be set
+fail_compilation/reserved_version.d(213): Error: version identifier `Emscripten` is reserved and cannot be set
+fail_compilation/reserved_version.d(214): Error: version identifier `WebAssembly` is reserved and cannot be set
+fail_compilation/reserved_version.d(215): Error: version identifier `WASI` is reserved and cannot be set
+fail_compilation/reserved_version.d(216): Error: version identifier `CppRuntime_LLVM` is reserved and cannot be set
+fail_compilation/reserved_version.d(217): Error: version identifier `CppRuntime_DigitalMars` is reserved and cannot be set
+fail_compilation/reserved_version.d(218): Error: version identifier `CppRuntime_GNU` is reserved and cannot be set
+fail_compilation/reserved_version.d(219): Error: version identifier `CppRuntime_Microsoft` is reserved and cannot be set
+fail_compilation/reserved_version.d(220): Error: version identifier `CppRuntime_Sun` is reserved and cannot be set
+fail_compilation/reserved_version.d(221): Error: version identifier `D_PIE` is reserved and cannot be set
+fail_compilation/reserved_version.d(222): Error: version identifier `AVR` is reserved and cannot be set
+fail_compilation/reserved_version.d(223): Error: version identifier `D_PreConditions` is reserved and cannot be set
+fail_compilation/reserved_version.d(224): Error: version identifier `D_PostConditions` is reserved and cannot be set
+fail_compilation/reserved_version.d(225): Error: version identifier `D_ProfileGC` is reserved and cannot be set
+fail_compilation/reserved_version.d(226): Error: version identifier `D_Invariants` is reserved and cannot be set
+fail_compilation/reserved_version.d(227): Error: version identifier `D_Optimized` is reserved and cannot be set
+fail_compilation/reserved_version.d(228): Error: version identifier `VisionOS` is reserved and cannot be set
---
*/
@@ -207,6 +208,7 @@ version = LoongArch32;
version = LoongArch64;
version = LoongArch_HardFloat;
version = LoongArch_SoftFloat;
+version = Xtensa;
version = LittleEndian;
version = BigEndian;
version = ELFv1;
@@ -327,6 +329,7 @@ debug = LoongArch32;
debug = LoongArch64;
debug = LoongArch_HardFloat;
debug = LoongArch_SoftFloat;
+debug = Xtensa;
debug = LittleEndian;
debug = BigEndian;
debug = ELFv1;
@@ -74,6 +74,7 @@
// REQUIRED_ARGS: -version=LoongArch64
// REQUIRED_ARGS: -version=LoongArch_HardFloat
// REQUIRED_ARGS: -version=LoongArch_SoftFloat
+// REQUIRED_ARGS: -version=Xtensa
// REQUIRED_ARGS: -version=LittleEndian
// REQUIRED_ARGS: -version=BigEndian
// REQUIRED_ARGS: -version=ELFv1
@@ -183,6 +184,7 @@
// REQUIRED_ARGS: -debug=LoongArch64
// REQUIRED_ARGS: -debug=LoongArch_HardFloat
// REQUIRED_ARGS: -debug=LoongArch_SoftFloat
+// REQUIRED_ARGS: -debug=Xtensa
// REQUIRED_ARGS: -debug=LittleEndian
// REQUIRED_ARGS: -debug=BigEndian
// REQUIRED_ARGS: -debug=ELFv1
@@ -298,6 +300,7 @@ Error: version identifier `LoongArch32` is reserved and cannot be set
Error: version identifier `LoongArch64` is reserved and cannot be set
Error: version identifier `LoongArch_HardFloat` is reserved and cannot be set
Error: version identifier `LoongArch_SoftFloat` is reserved and cannot be set
+Error: version identifier `Xtensa` is reserved and cannot be set
Error: version identifier `LittleEndian` is reserved and cannot be set
Error: version identifier `BigEndian` is reserved and cannot be set
Error: version identifier `ELFv1` is reserved and cannot be set
@@ -1,9 +1,8 @@
/*
-REQUIRED_ARGS: -de
TEST_OUTPUT:
---
-fail_compilation/test22999.d(18): Deprecation: switch case fallthrough - use 'goto default;' if intended
-fail_compilation/test22999.d(25): Deprecation: switch case fallthrough - use 'goto case;' if intended
+fail_compilation/test22999.d(17): Error: switch case fallthrough - use 'goto default;' if intended
+fail_compilation/test22999.d(24): Error: switch case fallthrough - use 'goto case;' if intended
---
*/
new file mode 100644
@@ -0,0 +1,27 @@
+/**
+REQUIRED_ARGS: -preview=dip1000
+TEST_OUTPUT:
+---
+fail_compilation/test24694.d(25): Error: reference to local variable `x` assigned to non-scope `b.c.p`
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=24694
+
+class C
+{
+ int* p;
+}
+
+struct S
+{
+ C c;
+}
+
+int* escape() @safe
+{
+ int x = 0;
+ S b = S(new C());
+ b.c.p = &x;
+ return b.c.p;
+}
@@ -1,6 +1,7 @@
/* TEST_OUTPUT:
---
-fail_compilation/varargsstc.d(102): Error: variadic parameter cannot have attributes `out ref`
+fail_compilation/varargsstc.d(102): Error: variadic parameter cannot have attributes `out`
+fail_compilation/varargsstc.d(103): Error: variadic parameter cannot have attributes `ref`
---
*/
@@ -8,3 +9,4 @@ fail_compilation/varargsstc.d(102): Error: variadic parameter cannot have attrib
int printf(const(char)*, const scope shared return ...);
int printf(const(char)*, ref out scope immutable shared return ...);
+int printf(const(char)*, ref scope immutable shared return ...);
@@ -433,6 +433,38 @@ void testglobalref()
/***************************************************/
+void testAutoRef()
+{
+ auto ref int x = 4;
+ auto ref int y = x;
+ auto ref z = x + 0;
+ auto ref char w;
+ auto ref float v = x; // type conversion
+
+ static assert(!__traits(isRef, x));
+ static assert( __traits(isRef, y));
+ static assert(!__traits(isRef, z));
+ static assert(!__traits(isRef, w));
+ static assert(!__traits(isRef, v));
+
+ assert(&y == &x);
+ assert(&z != &x);
+ assert(w == char.init);
+ assert(v == 4.0);
+
+ if (auto ref int a = 3)
+ static assert(!__traits(isRef, a));
+
+ while (auto ref a = x)
+ {
+ static assert(is(typeof(a) == int));
+ static assert(__traits(isRef, a));
+ break;
+ }
+}
+
+/***************************************************/
+
int main()
{
test6475();
@@ -448,6 +480,7 @@ int main()
test13950();
testlocalref();
testglobalref();
+ testAutoRef();
printf("Success\n");
return 0;
@@ -100,6 +100,7 @@ template Foo2(T)
mixin Foo2!(uint) B2;
mixin Foo2!(long) C2;
+mixin D2 = Foo2!(wchar);
mixin Foo2!(int);
void test2()
@@ -107,6 +108,7 @@ void test2()
B2.x2 = 3;
assert(B2.x2 == 3);
assert(C2.x2 == long.sizeof);
+ assert(D2.x2 == 2);
// assert(x2 == int.sizeof);
}
@@ -284,6 +286,9 @@ void test11()
int y = 8;
mixin Foo11!(y) B;
assert(B.abc() == 8);
+
+ mixin C = Foo11!2;
+ assert(C.abc() == 2);
}
/*******************************************/
@@ -68,12 +68,37 @@ void test12936() @nogc
/***********************/
+version(none) // Pending future enhancements:
+void testIndexedArrayLiteral() @nogc
+{
+ int i = 2;
+ int x = [10, 20, 30, 40][i];
+ assert(x == 30);
+
+ enum arr = [100, 200, 300, 400][1 .. $];
+ assert(arr[i] == 400);
+}
+
+void testArrayLiteralLvalue()
+{
+ // https://github.com/dlang/dmd/pull/16784
+ // Test that this array literal is *not* put on the stack because
+ // it gets its address taken
+ static int* getPtr(int i) => &[1, 2, 3][i];
+ int* x = getPtr(1);
+ int* y = getPtr(1);
+ assert(x != y);
+}
+
+/***********************/
+
int main()
{
test1();
test3032();
test12642();
test12936();
+ testArrayLiteralLvalue();
printf("Success\n");
return 0;
@@ -211,10 +211,26 @@ void testFuncCall()
assert(WithDtor.destroyed == 1);
}
+// https://issues.dlang.org/show_bug.cgi?id=24701
+void testCast()
+{
+ noreturn foo;
+ try
+ auto a = cast(int)foo;
+ catch (Throwable e)
+ {
+ assert(e.msg == "Accessed expression of type `noreturn`");
+ return;
+ }
+
+ assert(0);
+}
+
int main()
{
testDtors();
testAccess();
testFuncCall();
+ testCast();
return 0;
}
@@ -1,4 +1,4 @@
-34875cd6e1faa42e84ae953c0485ef524fe67e38
+6884b433d21d9b6356e5c83ffc6eb06a62a5cad1
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
@@ -13,6 +13,9 @@
* Makes an Objective-C interface method optional.)
* $(TROW $(LREF selector), Objective-C,
* Attaches an Objective-C selector to a method.)
+ * $(TROW $(LREF standalone),,
+ * Marks a shared module constructor as not depending on any
+ * other module constructor being run first.)
* $(TROW $(LREF weak),,
* Specifies that a global symbol should be emitted with weak linkage.)
* )
@@ -1699,7 +1699,7 @@ template forward(args...)
{
x_ = forward!x;
}
- this()(auto const ref X x)
+ this()(auto ref const X x)
{
x_ = forward!x;
}
@@ -299,9 +299,10 @@ version (CppRuntime_Microsoft)
{
enum size_t _Big_allocation_threshold = 4096;
enum size_t _Big_allocation_alignment = 32;
+ enum isPowerOf2(size_t v) = v && !(v & (v - 1));
static assert(2 * (void*).sizeof <= _Big_allocation_alignment, "Big allocation alignment should at least match vector register alignment");
- static assert((v => v != 0 && (v & (v - 1)) == 0)(_Big_allocation_alignment), "Big allocation alignment must be a power of two");
+ static assert(isPowerOf2!_Big_allocation_alignment, "Big allocation alignment must be a power of two");
static assert(size_t.sizeof == (void*).sizeof, "uintptr_t is not the same size as size_t");
// NOTE: this must track `_DEBUG` macro used in C++...
@@ -17,3 +17,5 @@ extern(C):
nothrow:
int getosreldate() pure @trusted;
+
+void closefrom(int);
@@ -5,6 +5,7 @@ public import core.sys.posix.unistd;
version (linux):
extern(C):
nothrow:
+@nogc:
// Additional seek constants for sparse file handling
// from Linux's unistd.h, stdio.h, and linux/fs.h
@@ -21,3 +22,6 @@ char* getpass(const(char)* prompt);
// Exit all threads in a process
void exit_group(int status);
+
+/// Close all open file descriptors greater or equal to `lowfd`
+void closefrom(int lowfd);
@@ -19,3 +19,5 @@ int getthrname(pid_t, char*, size_t);
int pledge(const scope char*, const scope char*);
int setthrname(pid_t, const scope char*);
int unveil(const scope char*, const scope char*);
+
+int closefrom(int);
@@ -1,4 +1,4 @@
-ebd24da8add9243c52e5cb346dcdf7acf3e6cbac
+48d581a1f509a7a302ea893e28939edb5b130622
The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository.
@@ -3586,11 +3586,14 @@ if (isDynamicArray!A)
return _data ? _data.capacity : 0;
}
+ /// Returns: The number of elements appended.
+ @property size_t length() const => _data ? _data.arr.length : 0;
+
/**
* Use opSlice() from now on.
* Returns: The managed array.
*/
- @property inout(T)[] data() inout @trusted
+ @property inout(T)[] data() inout
{
return this[];
}
@@ -3921,6 +3924,7 @@ if (isDynamicArray!A)
int[] a = [ 1, 2 ];
auto app2 = appender(a);
app2.put(3);
+ assert(app2.length == 3);
app2.put([ 4, 5, 6 ]);
assert(app2[] == [ 1, 2, 3, 4, 5, 6 ]);
}
@@ -4134,6 +4138,9 @@ if (isDynamicArray!A)
return impl.capacity;
}
+ /// Returns: The number of elements appended.
+ @property size_t length() const => impl.length;
+
/* Use opSlice() instead.
* Returns: the managed array.
*/
@@ -4160,6 +4167,7 @@ unittest
assert(app2[] == [1, 2]);
assert(a == [1, 2]);
app2 ~= 3;
+ assert(app2.length == 3);
app2 ~= [4, 5, 6];
assert(app2[] == [1, 2, 3, 4, 5, 6]);
assert(a == [1, 2, 3, 4, 5, 6]);
@@ -3161,10 +3161,10 @@ public:
auto str = strip(isoString);
- enforce(str.length >= 15, new DateTimeException(format("Invalid ISO String: %s", isoString)));
+ enforce!DateTimeException(str.length >= 15, format("Invalid format for DateTime.fromISOString %s", isoString));
auto t = str.byCodeUnit.countUntil('T');
- enforce(t != -1, new DateTimeException(format("Invalid ISO String: %s", isoString)));
+ enforce!DateTimeException(t != -1, format("Invalid format for DateTime.fromISOString: %s", isoString));
immutable date = Date.fromISOString(str[0 .. t]);
immutable tod = TimeOfDay.fromISOString(str[t+1 .. $]);
@@ -3262,10 +3262,11 @@ public:
auto str = strip(isoExtString);
- enforce(str.length >= 15, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
+ enforce!DateTimeException(str.length >= 15,
+ format("Invalid format for DateTime.fromISOExtString: %s", isoExtString));
auto t = str.byCodeUnit.countUntil('T');
- enforce(t != -1, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
+ enforce!DateTimeException(t != -1, format("Invalid format for DateTime.fromISOExtString: %s", isoExtString));
immutable date = Date.fromISOExtString(str[0 .. t]);
immutable tod = TimeOfDay.fromISOExtString(str[t+1 .. $]);
@@ -3362,10 +3363,11 @@ public:
auto str = strip(simpleString);
- enforce(str.length >= 15, new DateTimeException(format("Invalid string format: %s", simpleString)));
+ enforce!DateTimeException(str.length >= 15,
+ format("Invalid format for DateTime.fromSimpleString: %s", simpleString));
auto t = str.byCodeUnit.countUntil(' ');
- enforce(t != -1, new DateTimeException(format("Invalid string format: %s", simpleString)));
+ enforce!DateTimeException(t != -1, format("Invalid format for DateTime.fromSimpleString: %s", simpleString));
immutable date = Date.fromSimpleString(str[0 .. t]);
immutable tod = TimeOfDay.fromISOExtString(str[t+1 .. $]);
@@ -7628,7 +7630,7 @@ public:
auto str = isoString.strip;
- enforce!DateTimeException(str.length >= 8, text("Invalid ISO String: ", isoString));
+ enforce!DateTimeException(str.length >= 8, text("Invalid format for Date.fromISOString: ", isoString));
int day, month, year;
auto yearStr = str[0 .. $ - 4];
@@ -7643,7 +7645,7 @@ public:
if (yearStr.length > 4)
{
enforce!DateTimeException(yearStr.startsWith('-', '+'),
- text("Invalid ISO String: ", isoString));
+ text("Invalid format for Date.fromISOString: ", isoString));
year = to!int(yearStr);
}
else
@@ -7653,7 +7655,7 @@ public:
}
catch (ConvException)
{
- throw new DateTimeException(text("Invalid ISO String: ", isoString));
+ throw new DateTimeException(text("Invalid format for Date.fromISOString: ", isoString));
}
return Date(year, month, day);
@@ -7774,13 +7776,13 @@ public:
ubyte month, day;
if (str.length < 10 || str[$-3] != '-' || str[$-6] != '-')
- throw new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString));
+ throw new DateTimeException(format("Invalid format for Date.fromISOExtString: %s", isoExtString));
auto yearStr = str[0 .. $-6];
auto signAtBegining = cast(bool) yearStr.startsWith('-', '+');
if ((yearStr.length > 4) != signAtBegining)
{
- throw new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString));
+ throw new DateTimeException(format("Invalid format for Date.fromISOExtString: %s", isoExtString));
}
try
@@ -7791,7 +7793,7 @@ public:
}
catch (ConvException)
{
- throw new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString));
+ throw new DateTimeException(format("Invalid format for Date.fromISOExtString: %s", isoExtString));
}
return Date(year, month, day);
@@ -7910,7 +7912,7 @@ public:
auto str = strip(simpleString);
if (str.length < 11 || str[$-3] != '-' || str[$-7] != '-')
- throw new DateTimeException(format!"Invalid string format: %s"(simpleString));
+ throw new DateTimeException(format!"Invalid format for Date.fromSimpleString: %s"(simpleString));
int year;
uint day;
@@ -7919,7 +7921,7 @@ public:
auto signAtBegining = cast(bool) yearStr.startsWith('-', '+');
if ((yearStr.length > 4) != signAtBegining)
{
- throw new DateTimeException(format!"Invalid string format: %s"(simpleString));
+ throw new DateTimeException(format!"Invalid format for Date.fromSimpleString: %s"(simpleString));
}
try
@@ -7929,7 +7931,7 @@ public:
}
catch (ConvException)
{
- throw new DateTimeException(format!"Invalid string format: %s"(simpleString));
+ throw new DateTimeException(format!"Invalid format for Date.fromSimpleString: %s"(simpleString));
}
return Date(year, month, day);
@@ -9208,7 +9210,7 @@ public:
int hours, minutes, seconds;
auto str = strip(isoString);
- enforce!DateTimeException(str.length == 6, text("Invalid ISO String: ", isoString));
+ enforce!DateTimeException(str.length == 6, text("Invalid format for TimeOfDay.fromISOString: ", isoString));
try
{
@@ -9220,7 +9222,7 @@ public:
}
catch (ConvException)
{
- throw new DateTimeException(text("Invalid ISO String: ", isoString));
+ throw new DateTimeException(text("Invalid format for TimeOfDay.fromISOString: ", isoString));
}
return TimeOfDay(hours, minutes, seconds);
@@ -9333,7 +9335,7 @@ public:
int hours, minutes, seconds;
if (str.length != 8 || str[2] != ':' || str[5] != ':')
- throw new DateTimeException(text("Invalid ISO Extended String: ", isoExtString));
+ throw new DateTimeException(text("Invalid format for TimeOfDay.fromISOExtString: ", isoExtString));
try
{
@@ -9345,7 +9347,7 @@ public:
}
catch (ConvException)
{
- throw new DateTimeException(text("Invalid ISO Extended String: ", isoExtString));
+ throw new DateTimeException(text("Invalid format for TimeOfDay.fromISOExtString: ", isoExtString));
}
return TimeOfDay(hours, minutes, seconds);
@@ -8879,7 +8879,7 @@ public:
return retval;
}
catch (DateTimeException dte)
- throw new DateTimeException(format("Invalid ISO String: %s", isoString));
+ throw new DateTimeException(format("Invalid format for SysTime.fromISOString: %s", isoString));
}
///
@@ -9109,7 +9109,8 @@ public:
auto str = strip(isoExtString);
auto tIndex = str.indexOf('T');
- enforce(tIndex != -1, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
+ enforce!DateTimeException(tIndex != -1,
+ format("Invalid format for SysTime.fromISOExtString: %s", isoExtString));
auto found = str[tIndex + 1 .. $].find('.', 'Z', '+', '-');
auto dateTimeStr = str[0 .. $ - found[0].length];
@@ -9157,7 +9158,7 @@ public:
return retval;
}
catch (DateTimeException dte)
- throw new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString));
+ throw new DateTimeException(format("Invalid format for SysTime.fromISOExtString: %s", isoExtString));
}
///
@@ -9359,7 +9360,8 @@ public:
auto str = strip(simpleString);
auto spaceIndex = str.indexOf(' ');
- enforce(spaceIndex != -1, new DateTimeException(format("Invalid Simple String: %s", simpleString)));
+ enforce!DateTimeException(spaceIndex != -1,
+ format("Invalid format for SysTime.fromSimpleString: %s", simpleString));
auto found = str[spaceIndex + 1 .. $].find('.', 'Z', '+', '-');
auto dateTimeStr = str[0 .. $ - found[0].length];
@@ -9407,7 +9409,7 @@ public:
return retval;
}
catch (DateTimeException dte)
- throw new DateTimeException(format("Invalid Simple String: %s", simpleString));
+ throw new DateTimeException(format("Invalid format for SysTime.fromSimpleString: %s", simpleString));
}
///
@@ -11170,6 +11172,7 @@ if (isSomeString!S)
import std.algorithm.searching : all;
import std.ascii : isDigit;
import std.conv : to;
+ import std.format : format;
import std.string : representation;
if (isoString.empty)
@@ -11177,10 +11180,11 @@ if (isSomeString!S)
auto str = isoString.representation;
- enforce(str[0] == '.', new DateTimeException("Invalid ISO String"));
+ enforce!DateTimeException(str[0] == '.', format("Invalid format for fracSecsFromISOString: %s", isoString));
str.popFront();
- enforce(!str.empty && all!isDigit(str), new DateTimeException("Invalid ISO String"));
+ enforce!DateTimeException(!str.empty && all!isDigit(str),
+ format("Invalid format for fracSecsFromISOString: %s", isoString));
dchar[7] fullISOString = void;
foreach (i, ref dchar c; fullISOString)
@@ -25,7 +25,6 @@ package(std.format):
void skipData(Range, Char)(ref Range input, scope const ref FormatSpec!Char spec)
{
import std.ascii : isDigit;
- import std.conv : text;
import std.range.primitives : empty, front, popFront;
switch (spec.spec)
@@ -38,8 +37,7 @@ void skipData(Range, Char)(ref Range input, scope const ref FormatSpec!Char spec
while (!input.empty && isDigit(input.front)) input.popFront();
break;
default:
- assert(false,
- text("Format specifier not understood: %", spec.spec));
+ assert(0, "Format specifier not understood: %" ~ spec.spec);
}
}
@@ -880,6 +880,7 @@ version (Posix) private enum InternalError : ubyte
doubleFork,
malloc,
preExec,
+ closefds_dup2,
}
/*
@@ -1008,7 +1009,7 @@ private Pid spawnProcessPosix(scope const(char[])[] args,
if (config.flags & Config.Flags.detached)
close(pidPipe[0]);
close(forkPipe[0]);
- immutable forkPipeOut = forkPipe[1];
+ auto forkPipeOut = forkPipe[1];
immutable pidPipeOut = pidPipe[1];
// Set the working directory.
@@ -1042,56 +1043,106 @@ private Pid spawnProcessPosix(scope const(char[])[] args,
if (!(config.flags & Config.Flags.inheritFDs))
{
- // NOTE: malloc() and getrlimit() are not on the POSIX async
- // signal safe functions list, but practically this should
- // not be a problem. Java VM and CPython also use malloc()
- // in its own implementation via opendir().
- import core.stdc.stdlib : malloc;
- import core.sys.posix.poll : pollfd, poll, POLLNVAL;
- import core.sys.posix.sys.resource : rlimit, getrlimit, RLIMIT_NOFILE;
-
- // Get the maximum number of file descriptors that could be open.
- rlimit r;
- if (getrlimit(RLIMIT_NOFILE, &r) != 0)
- {
- abortOnError(forkPipeOut, InternalError.getrlimit, .errno);
- }
- immutable maxDescriptors = cast(int) r.rlim_cur;
-
- // The above, less stdin, stdout, and stderr
- immutable maxToClose = maxDescriptors - 3;
+ version (FreeBSD)
+ import core.sys.freebsd.unistd : closefrom;
+ else version (OpenBSD)
+ import core.sys.openbsd.unistd : closefrom;
- // Call poll() to see which ones are actually open:
- auto pfds = cast(pollfd*) malloc(pollfd.sizeof * maxToClose);
- if (pfds is null)
- {
- abortOnError(forkPipeOut, InternalError.malloc, .errno);
- }
- foreach (i; 0 .. maxToClose)
+ static if (!__traits(compiles, closefrom))
{
- pfds[i].fd = i + 3;
- pfds[i].events = 0;
- pfds[i].revents = 0;
- }
- if (poll(pfds, maxToClose, 0) >= 0)
- {
- foreach (i; 0 .. maxToClose)
- {
- // don't close pipe write end
- if (pfds[i].fd == forkPipeOut) continue;
- // POLLNVAL will be set if the file descriptor is invalid.
- if (!(pfds[i].revents & POLLNVAL)) close(pfds[i].fd);
- }
- }
- else
- {
- // Fall back to closing everything.
- foreach (i; 3 .. maxDescriptors)
- {
- if (i == forkPipeOut) continue;
- close(i);
+ // FIXME: This implementation crashes the system when RLIMIT_NOFILE
+ // has a big value. For a possible solution see:
+ // https://github.com/dlang/phobos/pull/8990
+ void fallback (int lowfd) {
+ // NOTE: malloc() and getrlimit() are not on the POSIX async
+ // signal safe functions list, but practically this should
+ // not be a problem. Java VM and CPython also use malloc()
+ // in its own implementation via opendir().
+ import core.stdc.stdlib : malloc;
+ import core.sys.posix.poll : pollfd, poll, POLLNVAL;
+ import core.sys.posix.sys.resource : rlimit, getrlimit, RLIMIT_NOFILE;
+
+ // Get the maximum number of file descriptors that could be open.
+ rlimit r;
+ if (getrlimit(RLIMIT_NOFILE, &r) != 0)
+ {
+ abortOnError(forkPipeOut, InternalError.getrlimit, .errno);
+ }
+ immutable maxDescriptors = cast(int) r.rlim_cur;
+
+ immutable maxToClose = maxDescriptors - lowfd;
+
+ // Call poll() to see which ones are actually open:
+ auto pfds = cast(pollfd*) malloc(pollfd.sizeof * maxToClose);
+ if (pfds is null)
+ {
+ abortOnError(forkPipeOut, InternalError.malloc, .errno);
+ }
+ foreach (i; 0 .. maxToClose)
+ {
+ pfds[i].fd = i + lowfd;
+ pfds[i].events = 0;
+ pfds[i].revents = 0;
+ }
+ if (poll(pfds, maxToClose, 0) >= 0)
+ {
+ foreach (i; 0 .. maxToClose)
+ {
+ // POLLNVAL will be set if the file descriptor is invalid.
+ if (!(pfds[i].revents & POLLNVAL)) close(pfds[i].fd);
+ }
+ }
+ else
+ {
+ // Fall back to closing everything.
+ foreach (i; lowfd .. maxDescriptors)
+ {
+ close(i);
+ }
+ }
}
+
+ // closefrom may not be available on the version of glibc we build against.
+ // Until we find a way to perform this check we will try to use dlsym to
+ // check for the function. See: https://github.com/dlang/phobos/pull/9048
+ version (CRuntime_Glibc)
+ void closefrom (int lowfd) {
+ static bool tryGlibcClosefrom (int lowfd) {
+ import core.sys.posix.dlfcn : dlopen, dlclose, dlsym, dlerror, RTLD_LAZY;
+
+ void *handle = dlopen("libc.so.6", RTLD_LAZY);
+ if (!handle)
+ return false;
+ scope(exit) dlclose(handle);
+
+ // Clear errors
+ dlerror();
+ alias closefromT = extern(C) void function(int) @nogc @system nothrow;
+ auto closefrom = cast(closefromT) dlsym(handle, "closefrom");
+ if (dlerror())
+ return false;
+
+ closefrom(lowfd);
+ return true;
+ }
+
+ if (!tryGlibcClosefrom(lowfd))
+ fallback(lowfd);
+ }
+ else
+ alias closefrom = fallback;
}
+
+ // We need to close all open file descriptors excluding std{in,out,err}
+ // and forkPipeOut because we still need it.
+ // Since the various libc's provide us with `closefrom` move forkPipeOut
+ // to position 3, right after STDERR_FILENO, and close all FDs following that.
+ if (dup2(forkPipeOut, 3) == -1)
+ abortOnError(forkPipeOut, InternalError.closefds_dup2, .errno);
+ forkPipeOut = 3;
+ // forkPipeOut needs to be closed after we call `exec`.
+ setCLOEXEC(forkPipeOut, true);
+ closefrom(forkPipeOut + 1);
}
else // This is already done if we don't inherit descriptors.
{
@@ -1205,6 +1256,10 @@ private Pid spawnProcessPosix(scope const(char[])[] args,
case InternalError.preExec:
errorMsg = "Failed to execute preExecFunction or preExecDelegate";
break;
+ case InternalError.closefds_dup2:
+ assert(!(config.flags & Config.Flags.inheritFDs));
+ errorMsg = "Failed to close inherited file descriptors";
+ break;
case InternalError.noerror:
assert(false);
}
@@ -3349,7 +3349,7 @@ struct CowArray(SP=GcPolicy)
data[$-val.length-1 .. $-1] = val[];
}
- bool opEquals()(auto const ref CowArray rhs)const
+ bool opEquals()(auto ref const CowArray rhs) const
{
if (empty ^ rhs.empty)
return false; // one is empty and the other isn't