Skip to content

Commit c235355

Browse files
committed
refactoring
1 parent 543c4eb commit c235355

File tree

2 files changed

+82
-20
lines changed

2 files changed

+82
-20
lines changed

compiler/src/dmd/attribsem.d

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,55 +33,66 @@ import dmd.expressionsem;
3333
import dmd.location;
3434
import dmd.root.array; // for each
3535

36-
36+
/**
37+
* Retrieves the attributes associated with a UserAttributeDeclaration.
38+
* Returns:
39+
* A pointer to Expressions containing the attributes, or null if none exist.
40+
*/
3741
Expressions* getAttributes(UserAttributeDeclaration a)
3842
{
43+
if (!a.userAttribDecl && (!a.atts || !a.atts.length))
44+
return null;
45+
3946
if (auto sc = a._scope)
4047
{
4148
a._scope = null;
42-
arrayExpressionSemantic(a.atts.peekSlice(), sc);
49+
if (a.atts)
50+
arrayExpressionSemantic(a.atts.peekSlice(), sc);
4351
}
52+
4453
auto exps = new Expressions();
54+
4555
if (a.userAttribDecl && a.userAttribDecl !is a)
46-
exps.push(new TupleExp(Loc.initial, a.userAttribDecl.getAttributes()));
56+
{
57+
if (auto parentAtts = a.userAttribDecl.getAttributes())
58+
exps.push(new TupleExp(Loc.initial, parentAtts));
59+
}
60+
4761
if (a.atts && a.atts.length)
4862
exps.push(new TupleExp(Loc.initial, a.atts));
63+
4964
return exps;
5065
}
5166

5267
/**
5368
* Iterates the UDAs attached to the given symbol.
5469
*
5570
* Params:
56-
* sym = the symbol to get the UDAs from
57-
* sc = scope to use for semantic analysis of UDAs
58-
* dg = called once for each UDA
71+
* sym = the symbol to get the UDAs from
72+
* sc = scope to use for semantic analysis of UDAs
73+
* dg = called once for each UDA
5974
*
6075
* Returns:
61-
* If `dg` returns `!= 0`, stops the iteration and returns that value.
62-
* Otherwise, returns 0.
76+
* If `dg` returns `!= 0`, stops the iteration and returns that value.
77+
* Otherwise, returns 0.
6378
*/
6479
int foreachUda(Dsymbol sym, Scope* sc, int delegate(Expression) dg)
6580
{
6681
if (!sym.userAttribDecl)
6782
return 0;
6883

6984
auto udas = sym.userAttribDecl.getAttributes();
85+
if (!udas)
86+
return 0;
87+
7088
arrayExpressionSemantic(udas.peekSlice(), sc, true);
7189

7290
return udas.each!((uda) {
73-
if (!uda.isTupleExp())
74-
return 0;
75-
76-
auto exps = uda.isTupleExp().exps;
77-
78-
return exps.each!((e) {
79-
assert(e);
80-
81-
if (auto result = dg(e))
82-
return result;
91+
if (!uda) return 0;
8392

84-
return 0;
85-
});
93+
if (auto te = uda.isTupleExp())
94+
return te.exps.each!((e) => dg(e));
95+
else
96+
return dg(uda);
8697
});
8798
}

compiler/test/runnable/test22287.d

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
TEST_OUTPUT:
3+
---
4+
---
5+
*/
6+
7+
/**
8+
* Regression test for UDA handling refactoring.
9+
* Covers single attributes, tuple attributes, and recursive collection.
10+
* https://github.com/dlang/dmd/pull/22287
11+
*/
12+
module test22287;
13+
14+
struct MyUda {}
15+
struct AnotherUda { int x; }
16+
17+
// 1. Single attribute (tests the new 'else' branch in foreachUda)
18+
@MyUda void testSingle() {}
19+
20+
// 2. Multiple attributes in a tuple (tests TupleExp handling)
21+
@(MyUda, AnotherUda(42)) void testMultiple() {}
22+
23+
// 3. Nested attributes (tests recursive collection in getAttributes)
24+
@MyUda
25+
{
26+
@AnotherUda(100) int testNested;
27+
}
28+
29+
void main()
30+
{
31+
// Check single attribute
32+
alias attrs1 = __traits(getAttributes, testSingle);
33+
static assert(attrs1.length == 1);
34+
static assert(is(attrs1[0] == MyUda));
35+
36+
// Check multiple attributes
37+
alias attrs2 = __traits(getAttributes, testMultiple);
38+
static assert(attrs2.length == 2);
39+
static assert(is(attrs2[0] == MyUda));
40+
static assert(attrs2[1].x == 42);
41+
42+
// Check nested attributes collection
43+
alias attrs3 = __traits(getAttributes, testNested);
44+
static assert(attrs3.length == 2);
45+
static assert(is(attrs3[0] == MyUda));
46+
static assert(attrs3[1].x == 100);
47+
48+
// Verify main itself (standalone check)
49+
alias attrsMain = __traits(getAttributes, main);
50+
static assert(attrsMain.length == 0);
51+
}

0 commit comments

Comments
 (0)