Skip to content

Commit eb972a4

Browse files
authored
Fix #issue22881 by adding early guards (#22886)
1 parent f3ad3d0 commit eb972a4

2 files changed

Lines changed: 95 additions & 38 deletions

File tree

compiler/src/dmd/dsymbolsem.d

Lines changed: 86 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2259,6 +2259,55 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
22592259
else
22602260
autoDollarDims = null;
22612261
}
2262+
static bool hasDollarDimension(TypeSArray tsa)
2263+
{
2264+
auto d = tsa.dim;
2265+
if (!d)
2266+
return false;
2267+
auto ide = d.isIdentifierExp();
2268+
if (!ide)
2269+
return false;
2270+
return ide.ident == Id.dollar;
2271+
}
2272+
static bool hasUnresolvedDollar(Type t)
2273+
{
2274+
if (!t)
2275+
return false;
2276+
t = t.toBasetype();
2277+
2278+
auto tsa = t.isTypeSArray();
2279+
if (!tsa)
2280+
{
2281+
// catch int[$]*
2282+
auto next = t.nextOf();
2283+
return next ? hasUnresolvedDollar(next) : false;
2284+
}
2285+
if (hasDollarDimension(tsa))
2286+
return true;
2287+
return hasUnresolvedDollar(tsa.next);
2288+
}
2289+
static void resolveDollarToZero(Type t, Loc loc)
2290+
{
2291+
if (!t)
2292+
return;
2293+
t = t.toBasetype();
2294+
2295+
auto tsa = t.isTypeSArray();
2296+
if (tsa && hasDollarDimension(tsa))
2297+
{
2298+
tsa.dim = new IntegerExp(loc, 0, Type.tsize_t);
2299+
}
2300+
2301+
if (tsa)
2302+
resolveDollarToZero(tsa.next, loc);
2303+
else
2304+
{
2305+
// handle int[$]*
2306+
auto next = t.nextOf();
2307+
if (next)
2308+
resolveDollarToZero(next, loc);
2309+
}
2310+
}
22622311
if (!dsym.type)
22632312
{
22642313
dsym.inuse++;
@@ -2271,6 +2320,14 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
22712320
sc.condition = true;
22722321
sc = sc.startCTFE();
22732322
}
2323+
if (autoDollarDims.length && !dsym._init)
2324+
{
2325+
.error(dsym.loc, "cannot infer static array length from `$`, provide an initializer");
2326+
dsym.type = Type.terror;
2327+
dsym.errors = true;
2328+
dsym.semanticRun = PASS.semanticdone;
2329+
return;
2330+
}
22742331
//printf("inferring type for %s with init %s\n", dsym.toChars(), dsym._init.toChars());
22752332
dsym._init = dsym._init.inferType(sc);
22762333
dsym.type = dsym._init.initializerToExpression(null, sc.inCfile).type;
@@ -2285,7 +2342,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
22852342
auto elem = t.nextOf();
22862343
if (!elem)
22872344
{
2288-
.error(dsym.loc, "cannot infer static array element type for `auto[$]`, provide an array initializer");
2345+
.error(dsym.loc,
2346+
"cannot infer static array element type for `auto[$]`, " ~
2347+
"provide an array initializer");
22892348
t = Type.terror;
22902349
break;
22912350
}
@@ -2317,6 +2376,19 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
23172376
if (!dsym.originalType)
23182377
dsym.originalType = dsym.type.syntaxCopy();
23192378

2379+
// `$` inference outside top-level static-array declarations is invalid.
2380+
if (hasUnresolvedDollar(dsym.type) && !dsym.type.toBasetype().isTypeSArray())
2381+
{
2382+
.error(dsym.loc,
2383+
"cannot infer static array length from `$` in this type position; " ~
2384+
"only direct static array declarations can infer `$` from an initializer");
2385+
resolveDollarToZero(dsym.type, dsym.loc);
2386+
dsym.type = Type.terror;
2387+
dsym.errors = true;
2388+
dsym.semanticRun = PASS.semanticdone;
2389+
return;
2390+
}
2391+
23202392
/* Prefix function attributes of variable declaration can affect
23212393
* its type:
23222394
* pure nothrow void function() fp;
@@ -2329,37 +2401,6 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
23292401
dsym.inuse--;
23302402
sc2.pop();
23312403
}
2332-
static bool hasDollarDimension(TypeSArray tsa)
2333-
{
2334-
auto d = tsa.dim;
2335-
if (!d)
2336-
return false;
2337-
auto ide = d.isIdentifierExp();
2338-
if (!ide)
2339-
return false;
2340-
return ide.ident == Id.dollar;
2341-
}
2342-
static bool hasUnresolvedDollar(Type t)
2343-
{
2344-
auto tsa = t.isTypeSArray();
2345-
if (!tsa)
2346-
return false;
2347-
if (hasDollarDimension(tsa))
2348-
return true;
2349-
return hasUnresolvedDollar(tsa.next);
2350-
}
2351-
2352-
static void resolveDollarToZero(Type t, Loc loc)
2353-
{
2354-
auto tsa = t.isTypeSArray();
2355-
if (!tsa)
2356-
return;
2357-
if (hasDollarDimension(tsa)) {
2358-
tsa.dim = new IntegerExp(loc, 0, Type.tsize_t);
2359-
}
2360-
resolveDollarToZero(tsa.next, loc);
2361-
}
2362-
23632404
static bool inferExprLength(Expression e, out dinteger_t len)
23642405
{
23652406
if (!e)
@@ -2498,10 +2539,20 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
24982539
}
24992540
}
25002541
}
2501-
if (tsa && hasUnresolvedDollar(tsa.next))
2542+
if (hasUnresolvedDollar(dsym.type))
25022543
{
2503-
.error(dsym.loc, "cannot infer static array length from `$`, provide an initializer");
2504-
resolveDollarToZero(tsa.next, dsym.loc);
2544+
if (dsym.type.toBasetype().isTypeSArray())
2545+
.error(dsym.loc, "cannot infer static array length from `$`, provide an initializer");
2546+
else
2547+
{
2548+
.error(dsym.loc,
2549+
"cannot infer static array length from `$` in this type position; " ~
2550+
"only direct static array declarations can infer `$` from an initializer");
2551+
}
2552+
resolveDollarToZero(dsym.type, dsym.loc);
2553+
dsym.type = Type.terror;
2554+
dsym.errors = true;
2555+
dsym.semanticRun = PASS.semanticdone;
25052556
return;
25062557
}
25072558

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
/*
22
TEST_OUTPUT:
33
---
4-
fail_compilation/staticarray.d(10): Error: cannot infer static array length from `$`, provide an initializer
5-
fail_compilation/staticarray.d(11): Error: cannot infer static array length from `$`, provide an initializer
6-
fail_compilation/staticarray.d(12): Error: cannot infer static array length from `$`, provide an initializer
4+
fail_compilation/staticarray.d(13): Error: cannot infer static array length from `$`, provide an initializer
5+
fail_compilation/staticarray.d(14): Error: cannot infer static array length from `$`, provide an initializer
6+
fail_compilation/staticarray.d(15): Error: cannot infer static array length from `$`, provide an initializer
7+
fail_compilation/staticarray.d(16): Error: cannot infer static array length from `$` in this type position; only direct static array declarations can infer `$` from an initializer
8+
fail_compilation/staticarray.d(17): Error: cannot infer static array length from `$` in this type position; only direct static array declarations can infer `$` from an initializer
9+
fail_compilation/staticarray.d(18): Error: cannot infer static array length from `$`, provide an initializer
710
---
811
*/
912

1013
int[$] arr1;
1114
int[$] arr2 = void;
1215
int[$][1] arr3 = 1;
16+
int[$]* arr4 = [1, 2];
17+
auto[$]* arr5 = [1, 2];
18+
auto[$] arr6;

0 commit comments

Comments
 (0)