Check array types with new isStaticOrDynamicArray function (#20795)

* Check array types with new `isStaticOrDynamicArray` function

* Make isStaticOrDynamicArray extern (D)
This commit is contained in:
Dennis 2025-01-28 19:45:36 +01:00 committed by GitHub
parent 84c7b040b0
commit acaa88abee
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 84 additions and 91 deletions

View file

@ -38,7 +38,7 @@ TypeTuple toArgTypes_aarch64(Type t)
return null;
Type tb = t.toBasetype();
const isAggregate = tb.ty == Tstruct || tb.ty == Tsarray || tb.ty == Tarray || tb.ty == Tdelegate || tb.isComplex();
const isAggregate = tb.ty == Tstruct || tb.isStaticOrDynamicArray() || tb.ty == Tdelegate || tb.isComplex();
if (!isAggregate)
return new TypeTuple(t);

View file

@ -44,12 +44,12 @@ bool isArrayOpValid(Expression e)
if (e.op == EXP.arrayLiteral)
{
Type t = e.type.toBasetype();
while (t.ty == Tarray || t.ty == Tsarray)
while (t.isStaticOrDynamicArray())
t = t.nextOf().toBasetype();
return (t.ty != Tvoid);
}
Type tb = e.type.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
if (tb.isStaticOrDynamicArray())
{
if (isUnaArrayOp(e.op))
{
@ -80,7 +80,7 @@ bool isNonAssignmentArrayOp(Expression e)
return isNonAssignmentArrayOp(e.isSliceExp().e1);
Type tb = e.type.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
if (tb.isStaticOrDynamicArray())
{
return (isUnaArrayOp(e.op) || isBinArrayOp(e.op));
}
@ -119,7 +119,7 @@ Expression arrayOp(BinExp e, Scope* sc)
{
//printf("BinExp.arrayOp() %s\n", e.toChars());
Type tb = e.type.toBasetype();
assert(tb.ty == Tarray || tb.ty == Tsarray);
assert(tb.isStaticOrDynamicArray());
Type tbn = tb.nextOf().toBasetype();
if (tbn.ty == Tvoid)
{
@ -346,7 +346,7 @@ bool isArrayOpOperand(Expression e)
if (e.op == EXP.arrayLiteral)
{
Type t = e.type.toBasetype();
while (t.ty == Tarray || t.ty == Tsarray)
while (t.isStaticOrDynamicArray())
t = t.nextOf().toBasetype();
return (t.ty != Tvoid);
}

View file

@ -2990,7 +2990,7 @@ final class CParser(AST) : Parser!AST
if (isStatic || mod)
error("static or type qualifier used outside of function prototype");
}
if (ts.isTypeSArray() || ts.isTypeDArray())
if (ts.isStaticOrDynamicArray())
{
/* C11 6.7.6.2-1: type qualifiers and 'static' shall only appear
* in the outermost array type derivation.

View file

@ -688,7 +688,7 @@ Expression getAggregateFromPointer(Expression e, dinteger_t* ofs)
if (auto ie = e.isIndexExp())
{
// Note that each AA element is part of its own memory block
if ((ie.e1.type.ty == Tarray || ie.e1.type.ty == Tsarray || ie.e1.op == EXP.string_ || ie.e1.op == EXP.arrayLiteral) && ie.e2.op == EXP.int64)
if ((ie.e1.type.isStaticOrDynamicArray() || ie.e1.op == EXP.string_ || ie.e1.op == EXP.arrayLiteral) && ie.e2.op == EXP.int64)
{
*ofs = ie.e2.toInteger();
return ie.e1;
@ -697,7 +697,7 @@ Expression getAggregateFromPointer(Expression e, dinteger_t* ofs)
if (auto se = e.isSliceExp())
{
if (se && e.type.toBasetype().ty == Tsarray &&
(se.e1.type.ty == Tarray || se.e1.type.ty == Tsarray || se.e1.op == EXP.string_ || se.e1.op == EXP.arrayLiteral) && se.lwr.op == EXP.int64)
(se.e1.type.isStaticOrDynamicArray() || se.e1.op == EXP.string_ || se.e1.op == EXP.arrayLiteral) && se.lwr.op == EXP.int64)
{
*ofs = se.lwr.toInteger();
return se.e1;
@ -1841,7 +1841,7 @@ bool isCtfeValueValid(Expression newval)
const SliceExp se = newval.isSliceExp();
assert(se.lwr && se.lwr.op == EXP.int64);
assert(se.upr && se.upr.op == EXP.int64);
return (tb.ty == Tarray || tb.ty == Tsarray) && (se.e1.op == EXP.string_ || se.e1.op == EXP.arrayLiteral);
return tb.isStaticOrDynamicArray() && (se.e1.op == EXP.string_ || se.e1.op == EXP.arrayLiteral);
}
case EXP.void_:

View file

@ -626,7 +626,7 @@ MATCH implicitConvTo(Expression e, Type t)
if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid)
return MATCH.nomatch;
if (!(e.type.ty == Tsarray || e.type.ty == Tarray || e.type.ty == Tpointer))
if (!(e.type.isStaticOrDynamicArray() || e.type.ty == Tpointer))
return visit(e);
TY tyn = e.type.nextOf().ty;
@ -758,8 +758,7 @@ MATCH implicitConvTo(Expression e, Type t)
Type typeb = e.type.toBasetype();
auto result = MATCH.nomatch;
if ((tb.ty == Tarray || tb.ty == Tsarray) &&
(typeb.ty == Tarray || typeb.ty == Tsarray))
if (tb.isStaticOrDynamicArray() && typeb.isStaticOrDynamicArray())
{
result = MATCH.exact;
Type typen = typeb.nextOf().toBasetype();
@ -802,7 +801,7 @@ MATCH implicitConvTo(Expression e, Type t)
return result;
}
else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray || typeb.ty == Tpointer))
else if (tb.ty == Tvector && (typeb.isStaticOrDynamicArray() || typeb.ty == Tpointer))
{ // Tpointer because ImportC eagerly converts Tsarray to Tpointer
result = MATCH.exact;
// Convert array literal to vector type
@ -2724,8 +2723,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
}
Type typeb = e.type.toBasetype();
if ((tb.ty == Tarray || tb.ty == Tsarray) &&
(typeb.ty == Tarray || typeb.ty == Tsarray))
if (tb.isStaticOrDynamicArray() && typeb.isStaticOrDynamicArray())
{
if (tb.nextOf().toBasetype().ty == Tvoid && typeb.nextOf().toBasetype().ty != Tvoid)
{
@ -2768,7 +2766,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
ae.type = tp;
}
}
else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray || typeb.ty == Tpointer))
else if (tb.ty == Tvector && (typeb.isStaticOrDynamicArray() || typeb.ty == Tpointer))
{
// Convert array literal to vector type
// The Tpointer case comes from C eagerly converting Tsarray to Tpointer
@ -3140,7 +3138,7 @@ Expression inferType(Expression e, Type t, int flag = 0)
Expression visitAle(ArrayLiteralExp ale)
{
Type tb = t.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
if (tb.isStaticOrDynamicArray())
{
Type tn = tb.nextOf();
if (ale.basis)
@ -3284,7 +3282,7 @@ private bool isVoidArrayLiteral(Expression e, Type other)
{
auto ale = e.isArrayLiteralExp();
e = ale[0];
if (other.ty == Tsarray || other.ty == Tarray)
if (other.isStaticOrDynamicArray())
other = other.nextOf();
else
return false;
@ -3550,7 +3548,7 @@ Lagain:
return null;
}
if ((t1.ty == Tsarray || t1.ty == Tarray) && (e2.op == EXP.null_ && t2.ty == Tpointer && t2.nextOf().ty == Tvoid || e2.op == EXP.arrayLiteral && t2.ty == Tsarray && t2.nextOf().ty == Tvoid && t2.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e2, t1)))
if (t1.isStaticOrDynamicArray() && (e2.op == EXP.null_ && t2.ty == Tpointer && t2.nextOf().ty == Tvoid || e2.op == EXP.arrayLiteral && t2.ty == Tsarray && t2.nextOf().ty == Tvoid && t2.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e2, t1)))
{
/* (T[n] op void*) => T[]
* (T[] op void*) => T[]
@ -3562,7 +3560,9 @@ Lagain:
return coerce(t1.nextOf().arrayOf());
}
if ((t2.ty == Tsarray || t2.ty == Tarray) && (e1.op == EXP.null_ && t1.ty == Tpointer && t1.nextOf().ty == Tvoid || e1.op == EXP.arrayLiteral && t1.ty == Tsarray && t1.nextOf().ty == Tvoid && t1.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e1, t2)))
if (t2.isStaticOrDynamicArray() &&
(e1.op == EXP.null_ && t1.ty == Tpointer && t1.nextOf().ty == Tvoid || e1.op == EXP.arrayLiteral
&& t1.ty == Tsarray && t1.nextOf().ty == Tvoid && t1.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e1, t2)))
{
/* (void* op T[n]) => T[]
* (void* op T[]) => T[]
@ -3574,7 +3574,7 @@ Lagain:
return coerce(t2.nextOf().arrayOf());
}
if ((t1.ty == Tsarray || t1.ty == Tarray) && (m = t1.implicitConvTo(t2)) != MATCH.nomatch)
if (t1.isStaticOrDynamicArray() && (m = t1.implicitConvTo(t2)) != MATCH.nomatch)
{
// https://issues.dlang.org/show_bug.cgi?id=7285
// Tsarray op [x, y, ...] should to be Tsarray
@ -3590,7 +3590,7 @@ Lagain:
return convert(e1, t2);
}
if ((t2.ty == Tsarray || t2.ty == Tarray) && t2.implicitConvTo(t1))
if (t2.isStaticOrDynamicArray() && t2.implicitConvTo(t1))
{
// https://issues.dlang.org/show_bug.cgi?id=7285
// https://issues.dlang.org/show_bug.cgi?id=14737
@ -3599,7 +3599,8 @@ Lagain:
return convert(e2, t1);
}
if ((t1.ty == Tsarray || t1.ty == Tarray || t1.ty == Tpointer) && (t2.ty == Tsarray || t2.ty == Tarray || t2.ty == Tpointer) && t1.nextOf().mod != t2.nextOf().mod)
if ((t1.isStaticOrDynamicArray() || t1.ty == Tpointer) && (t2.isStaticOrDynamicArray() || t2.ty == Tpointer)
&& t1.nextOf().mod != t2.nextOf().mod)
{
/* If one is mutable and the other immutable, then retry
* with both of them as const
@ -4240,7 +4241,7 @@ extern (D) bool arrayTypeCompatibleWithoutCasting(Type t1, Type t2)
t1 = t1.toBasetype();
t2 = t2.toBasetype();
if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && t2.ty == t1.ty)
if ((t1.isStaticOrDynamicArray() || t1.ty == Tpointer) && t2.ty == t1.ty)
{
if (t1.nextOf().implicitConvTo(t2.nextOf()) >= MATCH.constant || t2.nextOf().implicitConvTo(t1.nextOf()) >= MATCH.constant)
return true;

View file

@ -1885,7 +1885,7 @@ public:
// Check for taking an address of a shared variable.
// If the shared variable is an array, the offset might not be zero.
Type fromType = null;
if (e.var.type.ty == Tarray || e.var.type.ty == Tsarray)
if (e.var.type.isStaticOrDynamicArray())
{
fromType = (cast(TypeArray)e.var.type).next;
}
@ -1900,7 +1900,7 @@ public:
Expression val = getVarExp(e.loc, istate, e.var, goal);
if (exceptionOrCant(val))
return;
if (val.type.ty == Tarray || val.type.ty == Tsarray)
if (val.type.isStaticOrDynamicArray())
{
// Check for unsupported type painting operations
Type elemtype = (cast(TypeArray)val.type).next;
@ -3354,7 +3354,7 @@ public:
// a[] = e can have const e. So we compare the naked types.
Type tdst = e1.type.toBasetype();
Type tsrc = e.e2.type.toBasetype();
while (tdst.ty == Tsarray || tdst.ty == Tarray)
while (tdst.isStaticOrDynamicArray())
{
tdst = (cast(TypeArray)tdst).next.toBasetype();
if (tsrc.equivalent(tdst))
@ -4302,7 +4302,7 @@ public:
Expression assignTo(ArrayLiteralExp ae, size_t lwr, size_t upr)
{
Expressions* w = ae.elements;
assert(ae.type.ty == Tsarray || ae.type.ty == Tarray || ae.type.ty == Tpointer);
assert(ae.type.isStaticOrDynamicArray() || ae.type.ty == Tpointer);
bool directblk = (cast(TypeNext)ae.type).next.equivalent(newval.type);
for (size_t k = lwr; k < upr; k++)
{
@ -5804,8 +5804,7 @@ public:
auto expTb = exp.type.toBasetype();
if (exp.type.implicitConvTo(tbNext) >= MATCH.convert &&
(tb.ty == Tarray || tb.ty == Tsarray) &&
(expTb.ty == Tarray || expTb.ty == Tsarray))
tb.isStaticOrDynamicArray() && expTb.isStaticOrDynamicArray())
return new ArrayLiteralExp(exp.loc, e.type, exp);
return exp;
}
@ -5921,7 +5920,7 @@ public:
bool castToSarrayPointer = false;
bool castBackFromVoid = false;
if (e1.type.ty == Tarray || e1.type.ty == Tsarray || e1.type.ty == Tpointer)
if (e1.type.isStaticOrDynamicArray() || e1.type.ty == Tpointer)
{
// Check for unsupported type painting operations
// For slices, we need the type being sliced,
@ -6101,7 +6100,7 @@ public:
// Disallow array type painting, except for conversions between built-in
// types of identical size.
if ((e.to.ty == Tsarray || e.to.ty == Tarray) && (e1.type.ty == Tsarray || e1.type.ty == Tarray) && !isSafePointerCast(e1.type.nextOf(), e.to.nextOf()))
if (e.to.isStaticOrDynamicArray() && e1.type.isStaticOrDynamicArray() && !isSafePointerCast(e1.type.nextOf(), e.to.nextOf()))
{
auto se = e1.isStringExp();
// Allow casting a hex string literal to short[], int[] or long[]

View file

@ -1625,8 +1625,7 @@ elem* toElem(Expression e, ref IRState irs)
Type tb1 = be.e1.type.toBasetype();
Type tb2 = be.e2.type.toBasetype();
assert(!((tb1.ty == Tarray || tb1.ty == Tsarray ||
tb2.ty == Tarray || tb2.ty == Tsarray) &&
assert(!((tb1.isStaticOrDynamicArray() || tb2.isStaticOrDynamicArray()) &&
tb2.ty != Tvoid &&
op != OPeq && op != OPandand && op != OPoror));
@ -1648,8 +1647,7 @@ elem* toElem(Expression e, ref IRState irs)
Type tb1 = be.e1.type.toBasetype();
Type tb2 = be.e2.type.toBasetype();
assert(!((tb1.ty == Tarray || tb1.ty == Tsarray ||
tb2.ty == Tarray || tb2.ty == Tsarray) &&
assert(!((tb1.isStaticOrDynamicArray() || tb2.isStaticOrDynamicArray()) &&
tb2.ty != Tvoid &&
op != OPeq && op != OPandand && op != OPoror));
@ -1822,9 +1820,7 @@ elem* toElem(Expression e, ref IRState irs)
// Should have already been lowered
assert(0);
}
else if (cast(int)eop > 1 &&
(t1.ty == Tarray || t1.ty == Tsarray) &&
(t2.ty == Tarray || t2.ty == Tsarray))
else if (cast(int)eop > 1 && t1.isStaticOrDynamicArray() && t2.isStaticOrDynamicArray())
{
// This codepath was replaced by lowering during semantic
// to object.__cmp in druntime.
@ -1975,8 +1971,7 @@ elem* toElem(Expression e, ref IRState irs)
// Rewritten to IdentityExp or memberwise-compare
assert(0);
}
else if ((t1.ty == Tarray || t1.ty == Tsarray) &&
(t2.ty == Tarray || t2.ty == Tsarray))
else if (t1.isStaticOrDynamicArray() && t2.isStaticOrDynamicArray())
{
Type telement = t1.nextOf().toBasetype();
Type telement2 = t2.nextOf().toBasetype();
@ -2142,8 +2137,7 @@ elem* toElem(Expression e, ref IRState irs)
e = el_bin(eop, TYint, e, el_long(TYint, 0));
elem_setLoc(e, ie.loc);
}
else if ((t1.ty == Tarray || t1.ty == Tsarray) &&
(t2.ty == Tarray || t2.ty == Tsarray))
else if (t1.isStaticOrDynamicArray() && t2.isStaticOrDynamicArray())
{
elem *ea1 = toElem(ie.e1, irs);
@ -3765,7 +3759,7 @@ elem* toElem(Expression e, ref IRState irs)
{
//printf("SliceExp.toElem() se = %s %s\n", se.type.toChars(), se.toChars());
Type tb = se.type.toBasetype();
assert(tb.ty == Tarray || tb.ty == Tsarray);
assert(tb.isStaticOrDynamicArray());
Type t1 = se.e1.type.toBasetype();
elem *e = toElem(se.e1, irs);
if (se.lwr)

View file

@ -1607,7 +1607,7 @@ void escapeExp(Expression e, ref scope EscapeByResults er, int deref)
void visitArrayLiteral(ArrayLiteralExp e)
{
Type tb = e.type.toBasetype();
if (tb.isTypeSArray() || tb.isTypeDArray())
if (tb.isStaticOrDynamicArray())
{
if (e.basis)
escapeExp(e.basis, er, deref);
@ -2245,7 +2245,7 @@ private bool isTypesafeVariadicArray(VarDeclaration v)
if (v.storage_class & STC.variadic)
{
Type tb = v.type.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
if (tb.isStaticOrDynamicArray())
return true;
}
return false;

View file

@ -1207,7 +1207,7 @@ private Expression resolveUFCS(Scope* sc, CallExp ce)
eleft = die.e1;
Type t = eleft.type.toBasetype();
if (t.ty == Tarray || t.ty == Tsarray || t.ty == Tnull || (t.isTypeBasic() && t.ty != Tvoid))
if (t.isStaticOrDynamicArray() || t.ty == Tnull || (t.isTypeBasic() && t.ty != Tvoid))
{
/* Built-in types and arrays have no callable properties, so do shortcut.
* It is necessary in: e.init()
@ -7554,7 +7554,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = e;
return;
}
if (exp.e1.op == EXP.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
if (exp.e1.op == EXP.slice || exp.e1.type.isStaticOrDynamicArray())
{
if (checkNonAssignmentArrayOp(exp.e1))
return setError();
@ -8846,7 +8846,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
fix16997(sc, exp);
exp.type = exp.e1.type;
Type tb = exp.type.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
if (tb.isStaticOrDynamicArray())
{
if (!isArrayOpValid(exp.e1))
{
@ -8911,7 +8911,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
fix16997(sc, exp);
exp.type = exp.e1.type;
Type tb = exp.type.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
if (tb.isStaticOrDynamicArray())
{
if (!isArrayOpValid(exp.e1))
{
@ -9193,7 +9193,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
}
if (!t1b.equals(tob) && (t1b.ty == Tarray || t1b.ty == Tsarray))
if (!t1b.equals(tob) && t1b.isStaticOrDynamicArray())
{
if (checkNonAssignmentArrayOp(exp.e1))
return setError();
@ -9513,7 +9513,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* Run semantic on lwr and upr.
*/
Scope* scx = sc;
if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
if (t1b.isStaticOrDynamicArray() || t1b.ty == Ttuple)
{
// Create scope for 'length' variable
ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp);
@ -9620,7 +9620,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
IntRange lwrRange = getIntRange(exp.lwr);
IntRange uprRange = getIntRange(exp.upr);
if (t1b.ty == Tsarray || t1b.ty == Tarray)
if (t1b.isStaticOrDynamicArray())
{
Expression el = new ArrayLengthExp(exp.loc, exp.e1);
el = el.expressionSemantic(sc);
@ -9941,7 +9941,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
t1b = t1b.castMod(tv1.mod);
exp.e1 = exp.e1.castTo(sc, t1b);
}
if (t1b.ty == Tsarray || t1b.ty == Tarray)
if (t1b.isStaticOrDynamicArray())
{
if (!checkAddressable(exp, sc))
return setError();
@ -9950,7 +9950,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* Run semantic on e2
*/
Scope* scx = sc;
if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
if (t1b.isStaticOrDynamicArray() || t1b.ty == Ttuple)
{
// Create scope for 'length' variable
ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp);
@ -10086,7 +10086,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// We might know $ now
setLengthVarIfKnown(exp.lengthVar, t1b);
if (t1b.ty == Tsarray || t1b.ty == Tarray)
if (t1b.isStaticOrDynamicArray())
{
Expression el = new ArrayLengthExp(exp.loc, exp.e1);
el = el.expressionSemantic(sc);
@ -11352,7 +11352,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
}
else if (exp.e1.op == EXP.slice &&
(t2.ty == Tarray || t2.ty == Tsarray) &&
t2.isStaticOrDynamicArray() &&
t2.nextOf().implicitConvTo(t1.nextOf()))
{
// Check element-wise assignment.
@ -11461,7 +11461,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
if (exp.e1.op == EXP.slice &&
(t1.ty == Tarray || t1.ty == Tsarray) &&
t1.isStaticOrDynamicArray() &&
t1.nextOf().toBasetype().ty == Tvoid)
{
if (t2.nextOf().implicitConvTo(t1.nextOf()))
@ -11496,7 +11496,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* Look for array operations
*/
if ((t2.ty == Tarray || t2.ty == Tsarray) && isArrayOpValid(exp.e2))
if (t2.isStaticOrDynamicArray() && isArrayOpValid(exp.e2))
{
// Look for valid array operations
if (exp.memset != MemorySet.blockAssign &&
@ -11673,7 +11673,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return ae;
const isArrayAssign = (ae.e1.isSliceExp() || ae.e1.type.ty == Tsarray) &&
(ae.e2.type.ty == Tsarray || ae.e2.type.ty == Tarray) &&
(ae.e2.type.isStaticOrDynamicArray()) &&
(ae.e1.type.nextOf() && ae.e2.type.nextOf() && ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf()));
const isArraySetAssign = (ae.e1.isSliceExp() || ae.e1.type.ty == Tsarray) &&
@ -11749,7 +11749,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
assert(exp.e1.type && exp.e2.type);
if (exp.e1.op == EXP.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
if (exp.e1.op == EXP.slice || exp.e1.type.isStaticOrDynamicArray())
{
if (checkNonAssignmentArrayOp(exp.e1))
return setError();
@ -11769,7 +11769,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// Check element types are arithmetic
Type tb1 = exp.e1.type.nextOf().toBasetype();
Type tb2 = exp.e2.type.toBasetype();
if (tb2.ty == Tarray || tb2.ty == Tsarray)
if (tb2.isStaticOrDynamicArray())
tb2 = tb2.nextOf().toBasetype();
if ((tb1.isIntegral() || tb1.isFloating()) && (tb2.isIntegral() || tb2.isFloating()))
{
@ -11858,7 +11858,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
* EXP.concatenateDcharAssign: appending dchar to T[]
*/
if ((tb1.ty == Tarray) &&
(tb2.ty == Tarray || tb2.ty == Tsarray) &&
tb2.isStaticOrDynamicArray() &&
(exp.e2.implicitConvTo(exp.e1.type) ||
(tb2.nextOf().implicitConvTo(tb1next) &&
// Do not strip const(void)[]
@ -12116,7 +12116,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
Type tb = exp.type.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
if (tb.isStaticOrDynamicArray())
{
if (!isArrayOpValid(exp))
{
@ -12269,7 +12269,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
Type tb = exp.type.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
if (tb.isStaticOrDynamicArray())
{
if (!isArrayOpValid(exp))
{
@ -12451,7 +12451,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
// Check for: array ~ element
if ((tb1.ty == Tsarray || tb1.ty == Tarray) && tb2.ty != Tvoid)
if (tb1.isStaticOrDynamicArray() && tb2.ty != Tvoid)
{
if (exp.e1.op == EXP.arrayLiteral)
{
@ -12490,7 +12490,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
}
// Check for: element ~ array
if ((tb2.ty == Tsarray || tb2.ty == Tarray) && tb1.ty != Tvoid)
if (tb2.isStaticOrDynamicArray() && tb1.ty != Tvoid)
{
if (exp.e2.op == EXP.arrayLiteral)
{
@ -12525,7 +12525,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
Lpeer:
if ((tb1.ty == Tsarray || tb1.ty == Tarray) && (tb2.ty == Tsarray || tb2.ty == Tarray) && (tb1next.mod || tb2next.mod) && (tb1next.mod != tb2next.mod))
if (tb1.isStaticOrDynamicArray() && tb2.isStaticOrDynamicArray() &&
(tb1next.mod || tb2next.mod) && (tb1next.mod != tb2next.mod))
{
Type t1 = tb1next.mutableOf().constOf().arrayOf();
Type t2 = tb2next.mutableOf().constOf().arrayOf();
@ -12564,8 +12565,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Type t1 = exp.e1.type.toBasetype();
Type t2 = exp.e2.type.toBasetype();
Expression e;
if ((t1.ty == Tarray || t1.ty == Tsarray) &&
(t2.ty == Tarray || t2.ty == Tsarray))
if (t1.isStaticOrDynamicArray() && t2.isStaticOrDynamicArray())
{
// Normalize to ArrayLiteralExp or StringExp as far as possible
e = exp.optimize(WANTvalue);
@ -12596,7 +12596,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
Type tb = exp.type.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
if (tb.isStaticOrDynamicArray())
{
if (!isArrayOpValid(exp))
{
@ -12876,7 +12876,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
Type tb = exp.type.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
if (tb.isStaticOrDynamicArray())
{
if (!isArrayOpValid(exp))
{
@ -13038,7 +13038,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Expression arrayLowering = null;
t1 = exp.e1.type.toBasetype();
t2 = exp.e2.type.toBasetype();
if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && (t2.ty == Tarray || t2.ty == Tsarray || t2.ty == Tpointer))
if ((t1.isStaticOrDynamicArray() || t1.ty == Tpointer) && (t2.isStaticOrDynamicArray() || t2.ty == Tpointer))
{
Type t1next = t1.nextOf();
Type t2next = t2.nextOf();
@ -13048,8 +13048,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
}
if ((t1.ty == Tarray || t1.ty == Tsarray) &&
(t2.ty == Tarray || t2.ty == Tsarray))
if (t1.isStaticOrDynamicArray() && t2.isStaticOrDynamicArray())
{
if (!verifyHookExist(exp.loc, *sc, Id.__cmp, "comparing arrays"))
return setError();
@ -13288,8 +13287,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
const isArrayComparison = (t1.ty == Tarray || t1.ty == Tsarray) &&
(t2.ty == Tarray || t2.ty == Tsarray);
const isArrayComparison = t1.isStaticOrDynamicArray() && t2.isStaticOrDynamicArray();
const needsArrayLowering = isArrayComparison && needsDirectEq(t1, t2, sc);
if (!needsArrayLowering)
@ -14401,7 +14399,7 @@ Expression dotTemplateSemanticProp(DotTemplateInstanceExp exp, Scope* sc, bool g
{
exp.e1 = die.e1; // take back
Type t1b = exp.e1.type.toBasetype();
if (t1b.ty == Tarray || t1b.ty == Tsarray || t1b.ty == Taarray || t1b.ty == Tnull || (t1b.isTypeBasic() && t1b.ty != Tvoid))
if (t1b.isStaticOrDynamicArray() || t1b.ty == Taarray || t1b.ty == Tnull || (t1b.isTypeBasic() && t1b.ty != Tvoid))
{
/* No built-in type has templatized properties, so do shortcut.
* It is necessary in: 1024.max!"a < b"
@ -16281,7 +16279,7 @@ private bool fit(StructDeclaration sd, const ref Loc loc, Scope* sc, Expressions
Type typeb = se.type.toBasetype();
TY tynto = tb.nextOf().ty;
if (!se.committed &&
(typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
typeb.isStaticOrDynamicArray() && tynto.isSomeChar &&
se.numberOfCodeUnits(tynto) < (cast(TypeSArray)tb).dim.toInteger())
{
e = se.castTo(sc, t);

View file

@ -166,7 +166,7 @@ Expression carraySemantic(ArrayExp ae, Scope* sc)
* So, rewrite as an IndexExp if we can.
*/
auto t1 = e1.type.toBasetype();
if (t1.isTypeDArray() || t1.isTypeSArray())
if (t1.isStaticOrDynamicArray())
{
e2 = e2.expressionSemantic(sc).arrayFuncConv(sc);
// C doesn't do array bounds checking, so `true` turns it off
@ -176,7 +176,7 @@ Expression carraySemantic(ArrayExp ae, Scope* sc)
e1 = e1.arrayFuncConv(sc); // e1 might still be a function call
e2 = e2.expressionSemantic(sc);
auto t2 = e2.type.toBasetype();
if (t2.isTypeDArray() || t2.isTypeSArray())
if (t2.isStaticOrDynamicArray())
{
return new IndexExp(ae.loc, e2, e1, true).expressionSemantic(sc); // swap operands
}

View file

@ -439,7 +439,7 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
Type typeb = se.type.toBasetype();
TY tynto = tb.nextOf().ty;
if (!se.committed &&
(typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
typeb.isStaticOrDynamicArray() && tynto.isSomeChar &&
se.numberOfCodeUnits(tynto) < tb.isTypeSArray().dim.toInteger())
{
i.exp = se.castTo(sc, t);

View file

@ -822,7 +822,7 @@ public:
visit(cast(BinExp)e);
Type t1 = e.e1.type.toBasetype();
if (t1.ty == Tarray || t1.ty == Tsarray)
if (t1.isStaticOrDynamicArray())
{
Type t = t1.nextOf().toBasetype();
while (t.toBasetype().nextOf())

View file

@ -1521,6 +1521,8 @@ extern (C++) abstract class Type : ASTNode
inout(TypeTraits) isTypeTraits() { return ty == Ttraits ? cast(typeof(return))this : null; }
inout(TypeNoreturn) isTypeNoreturn() { return ty == Tnoreturn ? cast(typeof(return))this : null; }
inout(TypeTag) isTypeTag() { return ty == Ttag ? cast(typeof(return))this : null; }
extern (D) bool isStaticOrDynamicArray() const { return ty == Tarray || ty == Tsarray; }
}
override void accept(Visitor v)
@ -3947,7 +3949,7 @@ extern (C++) final class Parameter : ASTNode
Type isLazyArray()
{
Type tb = type.toBasetype();
if (tb.ty == Tsarray || tb.ty == Tarray)
if (tb.isStaticOrDynamicArray())
{
Type tel = (cast(TypeArray)tb).next.toBasetype();
if (auto td = tel.isTypeDelegate())
@ -4334,7 +4336,7 @@ AggregateDeclaration isAggregate(Type t)
bool isIndexableNonAggregate(Type t)
{
t = t.toBasetype();
return (t.ty == Tpointer || t.ty == Tsarray || t.ty == Tarray || t.ty == Taarray ||
return (t.ty == Tpointer || t.isStaticOrDynamicArray() || t.ty == Taarray ||
t.ty == Ttuple || t.ty == Tvector);
}

View file

@ -1683,7 +1683,7 @@ void genKill(ref ObState obstate, ObNode* ob)
override void visit(ArrayLiteralExp e)
{
Type tb = e.type.toBasetype();
if (tb.ty == Tsarray || tb.ty == Tarray)
if (tb.isStaticOrDynamicArray())
{
if (e.basis)
e.basis.accept(this);
@ -2424,7 +2424,7 @@ void checkObErrors(ref ObState obstate)
override void visit(ArrayLiteralExp e)
{
Type tb = e.type.toBasetype();
if (tb.ty == Tsarray || tb.ty == Tarray)
if (tb.isStaticOrDynamicArray())
{
if (e.basis)
e.basis.accept(this);

View file

@ -658,8 +658,7 @@ Expression opOverloadEqual(EqualExp e, Scope* sc, Type[2] aliasThisStop)
* lowering to object.__equals(), which takes care of overloaded
* operators for the element types.
*/
if ((t1.isTypeDArray() || t1.isTypeSArray()) &&
(t2.isTypeDArray() || t2.isTypeSArray()))
if (t1.isStaticOrDynamicArray() && t2.isStaticOrDynamicArray())
{
return null;
}

View file

@ -1080,7 +1080,7 @@ private void toDtElem(TypeSArray tsa, ref DtBuilder dtb, Expression e, bool isCt
Type tnext = tsa.next;
Type tbn = tnext.toBasetype();
Type ten = e ? e.type : null;
if (ten && (ten.ty == Tsarray || ten.ty == Tarray))
if (ten && ten.isStaticOrDynamicArray())
ten = ten.nextOf();
while (tbn.ty == Tsarray && (!e || !tbn.equivalent(ten)))
{