Skip to content

Commit

Permalink
Check array types with new isStaticOrDynamicArray function (#20795)
Browse files Browse the repository at this point in the history
* Check array types with new `isStaticOrDynamicArray` function

* Make isStaticOrDynamicArray extern (D)
  • Loading branch information
dkorpel authored Jan 28, 2025
1 parent 84c7b04 commit acaa88a
Show file tree
Hide file tree
Showing 16 changed files with 84 additions and 91 deletions.
2 changes: 1 addition & 1 deletion compiler/src/dmd/argtypes_aarch64.d
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
10 changes: 5 additions & 5 deletions compiler/src/dmd/arrayop.d
Original file line number Diff line number Diff line change
Expand Up @@ -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))
{
Expand Down Expand Up @@ -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));
}
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dmd/cparse.d
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dmd/ctfeexpr.d
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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_:
Expand Down
31 changes: 16 additions & 15 deletions compiler/src/dmd/dcast.d
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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[]
Expand All @@ -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[]
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down
15 changes: 7 additions & 8 deletions compiler/src/dmd/dinterpret.d
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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++)
{
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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[]
Expand Down
18 changes: 6 additions & 12 deletions compiler/src/dmd/e2ir.d
Original file line number Diff line number Diff line change
Expand Up @@ -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));

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

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dmd/escape.d
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
Loading

0 comments on commit acaa88a

Please sign in to comment.