Skip to content

Commit 0ef6f63

Browse files
committed
UDAs for function arguments
1 parent bba56df commit 0ef6f63

27 files changed

Lines changed: 472 additions & 68 deletions
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
UDAs on function arguments are now supported
2+
3+
User-defined attributes on function arguments behave analogous to existing UDAs:
4+
5+
---
6+
void test(A)(@(22) A a)
7+
{
8+
static assert([__traits(getAttributes, a)] == [22]);
9+
}
10+
---

src/dmd/astbase.d

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1734,15 +1734,17 @@ struct ASTBase
17341734
Type type;
17351735
Identifier ident;
17361736
Expression defaultArg;
1737+
UserAttributeDeclaration userAttribDecl; // user defined attributes
17371738

17381739
extern (D) alias ForeachDg = int delegate(size_t idx, Parameter param);
17391740

1740-
final extern (D) this(StorageClass storageClass, Type type, Identifier ident, Expression defaultArg)
1741+
final extern (D) this(StorageClass storageClass, Type type, Identifier ident, Expression defaultArg, UserAttributeDeclaration userAttribDecl)
17411742
{
17421743
this.storageClass = storageClass;
17431744
this.type = type;
17441745
this.ident = ident;
17451746
this.defaultArg = defaultArg;
1747+
this.userAttribDecl = userAttribDecl;
17461748
}
17471749

17481750
static size_t dim(Parameters* parameters)
@@ -1809,7 +1811,7 @@ struct ASTBase
18091811

18101812
Parameter syntaxCopy()
18111813
{
1812-
return new Parameter(storageClass, type ? type.syntaxCopy() : null, ident, defaultArg ? defaultArg.syntaxCopy() : null);
1814+
return new Parameter(storageClass, type ? type.syntaxCopy() : null, ident, defaultArg ? defaultArg.syntaxCopy() : null, userAttribDecl ? cast(UserAttributeDeclaration) userAttribDecl.syntaxCopy(null) : null);
18131815
}
18141816

18151817
void accept(Visitor v)
@@ -3623,7 +3625,7 @@ struct ASTBase
36233625
Expression e = (*exps)[i];
36243626
if (e.type.ty == Ttuple)
36253627
e.error("cannot form tuple of tuples");
3626-
auto arg = new Parameter(STC.undefined_, e.type, null, null);
3628+
auto arg = new Parameter(STC.undefined_, e.type, null, null, null);
36273629
(*arguments)[i] = arg;
36283630
}
36293631
}

src/dmd/attrib.d

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,6 +1263,7 @@ extern (C++) final class CompileDeclaration : AttribDeclaration
12631263

12641264
/***********************************************************
12651265
* User defined attributes look like:
1266+
* @foo(args, ...)
12661267
* @(args, ...)
12671268
*/
12681269
extern (C++) final class UserAttributeDeclaration : AttribDeclaration

src/dmd/clone.d

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ extern (C++) FuncDeclaration buildOpAssign(StructDeclaration sd, Scope* sc)
255255
}
256256

257257
auto fparams = new Parameters();
258-
fparams.push(new Parameter(STC.nodtor, sd.type, Id.p, null));
258+
fparams.push(new Parameter(STC.nodtor, sd.type, Id.p, null, null));
259259
auto tf = new TypeFunction(fparams, sd.handleType(), 0, LINK.d, stc | STC.ref_);
260260
auto fop = new FuncDeclaration(declLoc, Loc.initial, Id.assign, stc, tf);
261261
fop.storage_class |= STC.inference;
@@ -504,7 +504,7 @@ extern (C++) FuncDeclaration buildXopEquals(StructDeclaration sd, Scope* sc)
504504
/* const bool opEquals(ref const S s);
505505
*/
506506
auto parameters = new Parameters();
507-
parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, null, null));
507+
parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, null, null, null));
508508
tfeqptr = new TypeFunction(parameters, Type.tbool, 0, LINK.d);
509509
tfeqptr.mod = MODFlags.const_;
510510
tfeqptr = cast(TypeFunction)tfeqptr.typeSemantic(Loc.initial, &scx);
@@ -529,8 +529,8 @@ extern (C++) FuncDeclaration buildXopEquals(StructDeclaration sd, Scope* sc)
529529
Loc declLoc; // loc is unnecessary so __xopEquals is never called directly
530530
Loc loc; // loc is unnecessary so errors are gagged
531531
auto parameters = new Parameters();
532-
parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.p, null));
533-
parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.q, null));
532+
parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.p, null, null));
533+
parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.q, null, null));
534534
auto tf = new TypeFunction(parameters, Type.tbool, 0, LINK.d);
535535
Identifier id = Id.xopEquals;
536536
auto fop = new FuncDeclaration(declLoc, Loc.initial, id, STC.static_, tf);
@@ -574,7 +574,7 @@ extern (C++) FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc)
574574
/* const int opCmp(ref const S s);
575575
*/
576576
auto parameters = new Parameters();
577-
parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, null, null));
577+
parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, null, null, null));
578578
tfcmpptr = new TypeFunction(parameters, Type.tint32, 0, LINK.d);
579579
tfcmpptr.mod = MODFlags.const_;
580580
tfcmpptr = cast(TypeFunction)tfcmpptr.typeSemantic(Loc.initial, &scx);
@@ -649,8 +649,8 @@ extern (C++) FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc)
649649
Loc declLoc; // loc is unnecessary so __xopCmp is never called directly
650650
Loc loc; // loc is unnecessary so errors are gagged
651651
auto parameters = new Parameters();
652-
parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.p, null));
653-
parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.q, null));
652+
parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.p, null, null));
653+
parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.q, null, null));
654654
auto tf = new TypeFunction(parameters, Type.tint32, 0, LINK.d);
655655
Identifier id = Id.xopCmp;
656656
auto fop = new FuncDeclaration(declLoc, Loc.initial, id, STC.static_, tf);
@@ -757,7 +757,7 @@ extern (C++) FuncDeclaration buildXtoHash(StructDeclaration sd, Scope* sc)
757757
Loc declLoc; // loc is unnecessary so __xtoHash is never called directly
758758
Loc loc; // internal code should have no loc to prevent coverage
759759
auto parameters = new Parameters();
760-
parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.p, null));
760+
parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.p, null, null));
761761
auto tf = new TypeFunction(parameters, Type.thash_t, 0, LINK.d, STC.nothrow_ | STC.trusted);
762762
Identifier id = Id.xtoHash;
763763
auto fop = new FuncDeclaration(declLoc, Loc.initial, id, STC.static_, tf);
@@ -1009,7 +1009,7 @@ private DtorDeclaration buildWindowsCppDtor(AggregateDeclaration ad, DtorDeclara
10091009
// // TODO: if (del) delete (char*)this;
10101010
// return (void*) this;
10111011
// }
1012-
Parameter delparam = new Parameter(STC.undefined_, Type.tuns32, Identifier.idPool("del"), new IntegerExp(dtor.loc, 0, Type.tuns32));
1012+
Parameter delparam = new Parameter(STC.undefined_, Type.tuns32, Identifier.idPool("del"), new IntegerExp(dtor.loc, 0, Type.tuns32), null);
10131013
Parameters* params = new Parameters;
10141014
params.push(delparam);
10151015
auto ftype = new TypeFunction(params, Type.tvoidptr, false, LINK.cpp, dtor.storage_class);

src/dmd/cond.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ extern (C++) final class StaticForeach : RootObject
291291
foreach (params; pparams)
292292
{
293293
auto p = aggrfe ? (*aggrfe.parameters)[i] : rangefe.prm;
294-
params.push(new Parameter(p.storageClass, p.type, p.ident, null));
294+
params.push(new Parameter(p.storageClass, p.type, p.ident, null, null));
295295
}
296296
}
297297
Expression[2] res;

src/dmd/declaration.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ extern (C++) final class TupleDeclaration : Declaration
621621
}
622622
else
623623
{
624-
auto arg = new Parameter(0, t, null, null);
624+
auto arg = new Parameter(0, t, null, null, null);
625625
}
626626
(*args)[i] = arg;
627627
if (!t.deco)

src/dmd/dsymbolsem.d

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3581,6 +3581,14 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
35813581
genCmain(sc);
35823582

35833583
assert(funcdecl.type.ty != Terror || funcdecl.errors);
3584+
3585+
// semantic for parameters' UDAs
3586+
foreach (i; 0 .. Parameter.dim(f.parameters))
3587+
{
3588+
Parameter param = Parameter.getNth(f.parameters, i);
3589+
if (param && param.userAttribDecl)
3590+
param.userAttribDecl.dsymbolSemantic(sc);
3591+
}
35843592
}
35853593

35863594
/// Do the semantic analysis on the external interface to the function.

src/dmd/dtemplate.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6684,7 +6684,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
66846684
for (size_t i = 0; i < dim; i++)
66856685
{
66866686
Parameter arg = (*tt.arguments)[i];
6687-
if (flags & 2 && arg.ident)
6687+
if (flags & 2 && (arg.ident || arg.userAttribDecl))
66886688
tiargs.insert(j + i, arg);
66896689
else
66906690
tiargs.insert(j + i, arg.type);

src/dmd/expressionsem.d

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,7 +1106,7 @@ private bool functionParameters(Loc loc, Scope* sc, TypeFunction tf, Type tthis,
11061106
args.setDim(arguments.dim - nparams);
11071107
for (size_t i = 0; i < arguments.dim - nparams; i++)
11081108
{
1109-
auto arg = new Parameter(STC.in_, (*arguments)[nparams + i].type, null, null);
1109+
auto arg = new Parameter(STC.in_, (*arguments)[nparams + i].type, null, null, null);
11101110
(*args)[i] = arg;
11111111
}
11121112
auto tup = new TypeTuple(args);
@@ -3934,7 +3934,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
39343934
for (size_t i = 0; i < cd.baseclasses.dim; i++)
39353935
{
39363936
BaseClass* b = (*cd.baseclasses)[i];
3937-
args.push(new Parameter(STC.in_, b.type, null, null));
3937+
args.push(new Parameter(STC.in_, b.type, null, null, null));
39383938
}
39393939
tded = new TypeTuple(args);
39403940
}
@@ -3981,7 +3981,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
39813981
*/
39823982
if (e.tok2 == TOK.parameters && arg.defaultArg && arg.defaultArg.op == TOK.error)
39833983
return setError();
3984-
args.push(new Parameter(arg.storageClass, arg.type, (e.tok2 == TOK.parameters) ? arg.ident : null, (e.tok2 == TOK.parameters) ? arg.defaultArg : null));
3984+
args.push(new Parameter(arg.storageClass, arg.type, (e.tok2 == TOK.parameters) ? arg.ident : null, (e.tok2 == TOK.parameters) ? arg.defaultArg : null, arg.userAttribDecl));
39853985
}
39863986
tded = new TypeTuple(args);
39873987
break;

src/dmd/func.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2170,7 +2170,7 @@ extern (C++) class FuncDeclaration : Declaration
21702170
Parameter p = null;
21712171
if (canBuildResultVar())
21722172
{
2173-
p = new Parameter(STC.ref_ | STC.const_, f.nextOf(), Id.result, null);
2173+
p = new Parameter(STC.ref_ | STC.const_, f.nextOf(), Id.result, null, null);
21742174
fparams.push(p);
21752175
}
21762176
auto tf = new TypeFunction(fparams, Type.tvoid, 0, LINK.d);

0 commit comments

Comments
 (0)