d: Merge upstream dmd 9038e64c5.
Adds support for using user-defined attributes on function arguments and single-parameter alias declarations. These attributes behave analogous to existing UDAs. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 9038e64c5. * d-builtins.cc (build_frontend_type): Update call to Parameter::create.
This commit is contained in:
parent
d54029179c
commit
dddea6d4d8
@ -311,7 +311,7 @@ build_frontend_type (tree type)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
args->push (Parameter::create (sc, targ, NULL, NULL));
|
||||
args->push (Parameter::create (sc, targ, NULL, NULL, NULL));
|
||||
}
|
||||
|
||||
/* GCC generic and placeholder built-ins are marked as variadic, yet
|
||||
|
@ -1,4 +1,4 @@
|
||||
a5c86f5b92c4cd3afde910c89881ccaea11de554
|
||||
9038e64c5b67a10763d32893f53bb6c610df3595
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the dlang/dmd repository.
|
||||
|
@ -51,7 +51,7 @@ FuncDeclaration *buildArrayOp(Identifier *ident, BinExp *exp, Scope *sc)
|
||||
Parameter *p = (*fparams)[0];
|
||||
// foreach (i; 0 .. p.length)
|
||||
Statement *s1 = new ForeachRangeStatement(Loc(), TOKforeach,
|
||||
new Parameter(0, NULL, Id::p, NULL),
|
||||
new Parameter(0, NULL, Id::p, NULL, NULL),
|
||||
new IntegerExp(Loc(), 0, Type::tsize_t),
|
||||
new ArrayLengthExp(Loc(), new IdentifierExp(Loc(), p->ident)),
|
||||
new ExpStatement(Loc(), loopbody),
|
||||
@ -422,7 +422,7 @@ Expression *buildArrayLoop(Expression *e, Parameters *fparams)
|
||||
void visit(Expression *e)
|
||||
{
|
||||
Identifier *id = Identifier::generateId("c", fparams->length);
|
||||
Parameter *param = new Parameter(0, e->type, id, NULL);
|
||||
Parameter *param = new Parameter(0, e->type, id, NULL, NULL);
|
||||
fparams->shift(param);
|
||||
result = new IdentifierExp(Loc(), id);
|
||||
}
|
||||
@ -441,7 +441,7 @@ Expression *buildArrayLoop(Expression *e, Parameters *fparams)
|
||||
void visit(ArrayLiteralExp *e)
|
||||
{
|
||||
Identifier *id = Identifier::generateId("p", fparams->length);
|
||||
Parameter *param = new Parameter(STCconst, e->type, id, NULL);
|
||||
Parameter *param = new Parameter(STCconst, e->type, id, NULL, NULL);
|
||||
fparams->shift(param);
|
||||
Expression *ie = new IdentifierExp(Loc(), id);
|
||||
Expression *index = new IdentifierExp(Loc(), Id::p);
|
||||
@ -451,7 +451,7 @@ Expression *buildArrayLoop(Expression *e, Parameters *fparams)
|
||||
void visit(SliceExp *e)
|
||||
{
|
||||
Identifier *id = Identifier::generateId("p", fparams->length);
|
||||
Parameter *param = new Parameter(STCconst, e->type, id, NULL);
|
||||
Parameter *param = new Parameter(STCconst, e->type, id, NULL, NULL);
|
||||
fparams->shift(param);
|
||||
Expression *ie = new IdentifierExp(Loc(), id);
|
||||
Expression *index = new IdentifierExp(Loc(), Id::p);
|
||||
|
@ -244,7 +244,7 @@ FuncDeclaration *buildOpAssign(StructDeclaration *sd, Scope *sc)
|
||||
}
|
||||
|
||||
Parameters *fparams = new Parameters;
|
||||
fparams->push(new Parameter(STCnodtor, sd->type, Id::p, NULL));
|
||||
fparams->push(new Parameter(STCnodtor, sd->type, Id::p, NULL, NULL));
|
||||
TypeFunction *tf = new TypeFunction(ParameterList(fparams), sd->handleType(), LINKd, stc | STCref);
|
||||
|
||||
FuncDeclaration *fop = new FuncDeclaration(declLoc, Loc(), Id::assign, stc, tf);
|
||||
@ -503,7 +503,7 @@ FuncDeclaration *buildXopEquals(StructDeclaration *sd, Scope *sc)
|
||||
/* const bool opEquals(ref const S s);
|
||||
*/
|
||||
Parameters *parameters = new Parameters;
|
||||
parameters->push(new Parameter(STCref | STCconst, sd->type, NULL, NULL));
|
||||
parameters->push(new Parameter(STCref | STCconst, sd->type, NULL, NULL, NULL));
|
||||
tfeqptr = new TypeFunction(ParameterList(parameters), Type::tbool, LINKd);
|
||||
tfeqptr->mod = MODconst;
|
||||
tfeqptr = (TypeFunction *)tfeqptr->semantic(Loc(), &scx);
|
||||
@ -531,8 +531,8 @@ FuncDeclaration *buildXopEquals(StructDeclaration *sd, Scope *sc)
|
||||
Loc loc = Loc(); // loc is unnecessary so errors are gagged
|
||||
|
||||
Parameters *parameters = new Parameters;
|
||||
parameters->push(new Parameter(STCref | STCconst, sd->type, Id::p, NULL));
|
||||
parameters->push(new Parameter(STCref | STCconst, sd->type, Id::q, NULL));
|
||||
parameters->push(new Parameter(STCref | STCconst, sd->type, Id::p, NULL, NULL));
|
||||
parameters->push(new Parameter(STCref | STCconst, sd->type, Id::q, NULL, NULL));
|
||||
TypeFunction *tf = new TypeFunction(ParameterList(parameters), Type::tbool, LINKd);
|
||||
|
||||
Identifier *id = Id::xopEquals;
|
||||
@ -583,7 +583,7 @@ FuncDeclaration *buildXopCmp(StructDeclaration *sd, Scope *sc)
|
||||
/* const int opCmp(ref const S s);
|
||||
*/
|
||||
Parameters *parameters = new Parameters;
|
||||
parameters->push(new Parameter(STCref | STCconst, sd->type, NULL, NULL));
|
||||
parameters->push(new Parameter(STCref | STCconst, sd->type, NULL, NULL, NULL));
|
||||
tfcmpptr = new TypeFunction(ParameterList(parameters), Type::tint32, LINKd);
|
||||
tfcmpptr->mod = MODconst;
|
||||
tfcmpptr = (TypeFunction *)tfcmpptr->semantic(Loc(), &scx);
|
||||
@ -616,8 +616,8 @@ FuncDeclaration *buildXopCmp(StructDeclaration *sd, Scope *sc)
|
||||
Loc loc = Loc(); // loc is unnecessary so errors are gagged
|
||||
|
||||
Parameters *parameters = new Parameters;
|
||||
parameters->push(new Parameter(STCref | STCconst, sd->type, Id::p, NULL));
|
||||
parameters->push(new Parameter(STCref | STCconst, sd->type, Id::q, NULL));
|
||||
parameters->push(new Parameter(STCref | STCconst, sd->type, Id::p, NULL, NULL));
|
||||
parameters->push(new Parameter(STCref | STCconst, sd->type, Id::q, NULL, NULL));
|
||||
TypeFunction *tf = new TypeFunction(ParameterList(parameters), Type::tint32, LINKd);
|
||||
|
||||
Identifier *id = Id::xopCmp;
|
||||
@ -738,7 +738,7 @@ FuncDeclaration *buildXtoHash(StructDeclaration *sd, Scope *sc)
|
||||
Loc loc = Loc(); // internal code should have no loc to prevent coverage
|
||||
|
||||
Parameters *parameters = new Parameters();
|
||||
parameters->push(new Parameter(STCref | STCconst, sd->type, Id::p, NULL));
|
||||
parameters->push(new Parameter(STCref | STCconst, sd->type, Id::p, NULL, NULL));
|
||||
TypeFunction *tf = new TypeFunction(ParameterList(parameters), Type::thash_t,
|
||||
LINKd, STCnothrow | STCtrusted);
|
||||
|
||||
|
@ -257,7 +257,7 @@ static void lowerNonArrayAggregate(StaticForeach *sfe, Scope *sc)
|
||||
{
|
||||
Parameters *params = pparams[j];
|
||||
Parameter *p = sfe->aggrfe ? (*sfe->aggrfe->parameters)[i] : sfe->rangefe->prm;
|
||||
params->push(new Parameter(p->storageClass, p->type, p->ident, NULL));
|
||||
params->push(new Parameter(p->storageClass, p->type, p->ident, NULL, NULL));
|
||||
}
|
||||
}
|
||||
Expression *res[2];
|
||||
|
@ -224,7 +224,7 @@ Type *TupleDeclaration::getType()
|
||||
{
|
||||
Type *t = (*types)[i];
|
||||
//printf("type = %s\n", t->toChars());
|
||||
Parameter *arg = new Parameter(0, t, NULL, NULL);
|
||||
Parameter *arg = new Parameter(0, t, NULL, NULL, NULL);
|
||||
(*args)[i] = arg;
|
||||
if (!t->deco)
|
||||
hasdeco = 0;
|
||||
|
@ -6805,7 +6805,7 @@ bool TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
{
|
||||
Parameter *arg = (*tt->arguments)[i];
|
||||
if (flags & 2 && arg->ident)
|
||||
if (flags & 2 && (arg->ident || arg->userAttribDecl))
|
||||
tiargs->insert(j + i, arg);
|
||||
else
|
||||
tiargs->insert(j + i, arg->type);
|
||||
|
@ -1953,7 +1953,7 @@ bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
|
||||
args->setDim(arguments->length - nparams);
|
||||
for (size_t i = 0; i < arguments->length - nparams; i++)
|
||||
{
|
||||
Parameter *arg = new Parameter(STCin, (*arguments)[nparams + i]->type, NULL, NULL);
|
||||
Parameter *arg = new Parameter(STCin, (*arguments)[nparams + i]->type, NULL, NULL, NULL);
|
||||
(*args)[i] = arg;
|
||||
}
|
||||
|
||||
|
@ -2051,7 +2051,7 @@ public:
|
||||
for (size_t i = 0; i < cd->baseclasses->length; i++)
|
||||
{
|
||||
BaseClass *b = (*cd->baseclasses)[i];
|
||||
args->push(new Parameter(STCin, b->type, NULL, NULL));
|
||||
args->push(new Parameter(STCin, b->type, NULL, NULL, NULL));
|
||||
}
|
||||
tded = new TypeTuple(args);
|
||||
}
|
||||
@ -2100,7 +2100,8 @@ public:
|
||||
return setError();
|
||||
args->push(new Parameter(arg->storageClass, arg->type,
|
||||
(e->tok2 == TOKparameters) ? arg->ident : NULL,
|
||||
(e->tok2 == TOKparameters) ? arg->defaultArg : NULL));
|
||||
(e->tok2 == TOKparameters) ? arg->defaultArg : NULL,
|
||||
arg->userAttribDecl));
|
||||
}
|
||||
tded = new TypeTuple(args);
|
||||
break;
|
||||
|
@ -1221,6 +1221,15 @@ Ldone:
|
||||
Compiler::genCmain(sc);
|
||||
|
||||
assert(type->ty != Terror || errors);
|
||||
|
||||
// semantic for parameters' UDAs
|
||||
const size_t nparams = f->parameterList.length();
|
||||
for (size_t i = 0; i < nparams; i++)
|
||||
{
|
||||
Parameter *param = f->parameterList[i];
|
||||
if (param && param->userAttribDecl)
|
||||
param->userAttribDecl->semantic(sc);
|
||||
}
|
||||
}
|
||||
|
||||
void FuncDeclaration::semantic2(Scope *sc)
|
||||
@ -1237,6 +1246,17 @@ void FuncDeclaration::semantic2(Scope *sc)
|
||||
{
|
||||
objc()->checkLinkage(this);
|
||||
}
|
||||
if (!type || type->ty != Tfunction)
|
||||
return;
|
||||
TypeFunction *f = type->toTypeFunction();
|
||||
const size_t nparams = f->parameterList.length();
|
||||
// semantic for parameters' UDAs
|
||||
for (size_t i = 0; i < nparams; i++)
|
||||
{
|
||||
Parameter *param = f->parameterList[i];
|
||||
if (param && param->userAttribDecl)
|
||||
param->userAttribDecl->semantic2(sc);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************
|
||||
@ -1317,7 +1337,7 @@ static void buildEnsureRequire(FuncDeclaration *fdx)
|
||||
Parameter *p = NULL;
|
||||
if (fdx->outId)
|
||||
{
|
||||
p = new Parameter(STCref | STCconst, f->nextOf(), fdx->outId, NULL);
|
||||
p = new Parameter(STCref | STCconst, f->nextOf(), fdx->outId, NULL, NULL);
|
||||
fparams->push(p);
|
||||
}
|
||||
TypeFunction *tf = new TypeFunction(ParameterList(fparams), Type::tvoid, LINKd);
|
||||
@ -1603,6 +1623,8 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
parameters->push(v);
|
||||
localsymtab->insert(v);
|
||||
v->parent = this;
|
||||
if (fparam->userAttribDecl)
|
||||
v->userAttribDecl = fparam->userAttribDecl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3097,6 +3097,18 @@ public:
|
||||
|
||||
void visit(Parameter *p)
|
||||
{
|
||||
if (p->userAttribDecl)
|
||||
{
|
||||
buf->writestring("@");
|
||||
bool isAnonymous = p->userAttribDecl->atts->length > 0
|
||||
&& (*p->userAttribDecl->atts)[0]->op != TOKcall;
|
||||
if (isAnonymous)
|
||||
buf->writestring("(");
|
||||
argsToBuffer(p->userAttribDecl->atts);
|
||||
if (isAnonymous)
|
||||
buf->writestring(")");
|
||||
buf->writestring(" ");
|
||||
}
|
||||
if (p->storageClass & STCauto)
|
||||
buf->writestring("auto ");
|
||||
|
||||
|
@ -1543,7 +1543,7 @@ Type *stripDefaultArgs(Type *t)
|
||||
{
|
||||
Parameter *p = (*params)[i];
|
||||
Type *ta = stripDefaultArgs(p->type);
|
||||
if (ta != p->type || p->defaultArg || p->ident)
|
||||
if (ta != p->type || p->defaultArg || p->ident || p->userAttribDecl)
|
||||
{
|
||||
if (params == parameters)
|
||||
{
|
||||
@ -1552,7 +1552,7 @@ Type *stripDefaultArgs(Type *t)
|
||||
for (size_t j = 0; j < params->length; j++)
|
||||
(*params)[j] = (*parameters)[j];
|
||||
}
|
||||
(*params)[i] = new Parameter(p->storageClass, ta, NULL, NULL);
|
||||
(*params)[i] = new Parameter(p->storageClass, ta, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1996,7 +1996,7 @@ Type *TypeFunction::substWildTo(unsigned)
|
||||
continue;
|
||||
if (params == parameterList.parameters)
|
||||
params = parameterList.parameters->copy();
|
||||
(*params)[i] = new Parameter(p->storageClass, t, NULL, NULL);
|
||||
(*params)[i] = new Parameter(p->storageClass, t, NULL, NULL, NULL);
|
||||
}
|
||||
if (next == tret && params == parameterList.parameters)
|
||||
return this;
|
||||
@ -4914,7 +4914,7 @@ Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int
|
||||
if (fd_aaLen == NULL)
|
||||
{
|
||||
Parameters *fparams = new Parameters();
|
||||
fparams->push(new Parameter(STCin, this, NULL, NULL));
|
||||
fparams->push(new Parameter(STCin, this, NULL, NULL, NULL));
|
||||
fd_aaLen = FuncDeclaration::genCfunc(fparams, Type::tsize_t, Id::aaLen);
|
||||
TypeFunction *tf = fd_aaLen->type->toTypeFunction();
|
||||
tf->purity = PUREconst;
|
||||
@ -5821,7 +5821,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
|
||||
}
|
||||
|
||||
(*newparams)[j] = new Parameter(
|
||||
stc, narg->type, narg->ident, narg->defaultArg);
|
||||
stc, narg->type, narg->ident, narg->defaultArg, narg->userAttribDecl);
|
||||
}
|
||||
fparam->type = new TypeTuple(newparams);
|
||||
}
|
||||
@ -9098,7 +9098,7 @@ TypeTuple::TypeTuple(Expressions *exps)
|
||||
{ Expression *e = (*exps)[i];
|
||||
if (e->type->ty == Ttuple)
|
||||
e->error("cannot form tuple of tuples");
|
||||
Parameter *arg = new Parameter(STCundefined, e->type, NULL, NULL);
|
||||
Parameter *arg = new Parameter(STCundefined, e->type, NULL, NULL, NULL);
|
||||
(*arguments)[i] = arg;
|
||||
}
|
||||
}
|
||||
@ -9124,15 +9124,15 @@ TypeTuple::TypeTuple(Type *t1)
|
||||
: Type(Ttuple)
|
||||
{
|
||||
arguments = new Parameters();
|
||||
arguments->push(new Parameter(0, t1, NULL, NULL));
|
||||
arguments->push(new Parameter(0, t1, NULL, NULL, NULL));
|
||||
}
|
||||
|
||||
TypeTuple::TypeTuple(Type *t1, Type *t2)
|
||||
: Type(Ttuple)
|
||||
{
|
||||
arguments = new Parameters();
|
||||
arguments->push(new Parameter(0, t1, NULL, NULL));
|
||||
arguments->push(new Parameter(0, t2, NULL, NULL));
|
||||
arguments->push(new Parameter(0, t1, NULL, NULL, NULL));
|
||||
arguments->push(new Parameter(0, t2, NULL, NULL, NULL));
|
||||
}
|
||||
|
||||
const char *TypeTuple::kind()
|
||||
@ -9436,17 +9436,20 @@ size_t ParameterList::length()
|
||||
|
||||
/***************************** Parameter *****************************/
|
||||
|
||||
Parameter::Parameter(StorageClass storageClass, Type *type, Identifier *ident, Expression *defaultArg)
|
||||
Parameter::Parameter(StorageClass storageClass, Type *type, Identifier *ident,
|
||||
Expression *defaultArg, UserAttributeDeclaration *userAttribDecl)
|
||||
{
|
||||
this->type = type;
|
||||
this->ident = ident;
|
||||
this->storageClass = storageClass;
|
||||
this->defaultArg = defaultArg;
|
||||
this->userAttribDecl = userAttribDecl;
|
||||
}
|
||||
|
||||
Parameter *Parameter::create(StorageClass storageClass, Type *type, Identifier *ident, Expression *defaultArg)
|
||||
Parameter *Parameter::create(StorageClass storageClass, Type *type, Identifier *ident,
|
||||
Expression *defaultArg, UserAttributeDeclaration *userAttribDecl)
|
||||
{
|
||||
return new Parameter(storageClass, type, ident, defaultArg);
|
||||
return new Parameter(storageClass, type, ident, defaultArg, userAttribDecl);
|
||||
}
|
||||
|
||||
Parameter *Parameter::syntaxCopy()
|
||||
@ -9454,7 +9457,8 @@ Parameter *Parameter::syntaxCopy()
|
||||
return new Parameter(storageClass,
|
||||
type ? type->syntaxCopy() : NULL,
|
||||
ident,
|
||||
defaultArg ? defaultArg->syntaxCopy() : NULL);
|
||||
defaultArg ? defaultArg->syntaxCopy() : NULL,
|
||||
userAttribDecl ? (UserAttributeDeclaration *) userAttribDecl->syntaxCopy(NULL) : NULL);
|
||||
}
|
||||
|
||||
Parameters *Parameter::arraySyntaxCopy(Parameters *parameters)
|
||||
|
@ -623,9 +623,12 @@ public:
|
||||
Type *type;
|
||||
Identifier *ident;
|
||||
Expression *defaultArg;
|
||||
UserAttributeDeclaration *userAttribDecl; // user defined attributes
|
||||
|
||||
Parameter(StorageClass storageClass, Type *type, Identifier *ident, Expression *defaultArg);
|
||||
static Parameter *create(StorageClass storageClass, Type *type, Identifier *ident, Expression *defaultArg);
|
||||
Parameter(StorageClass storageClass, Type *type, Identifier *ident,
|
||||
Expression *defaultArg, UserAttributeDeclaration *userAttribDecl);
|
||||
static Parameter *create(StorageClass storageClass, Type *type, Identifier *ident,
|
||||
Expression *defaultArg, UserAttributeDeclaration *userAttribDecl);
|
||||
Parameter *syntaxCopy();
|
||||
Type *isLazyArray();
|
||||
// kludge for template.isType()
|
||||
|
@ -1110,7 +1110,7 @@ StorageClass Parser::parsePostfix(StorageClass storageClass, Expressions **pudas
|
||||
// Disallow:
|
||||
// void function() @uda fp;
|
||||
// () @uda { return 1; }
|
||||
error("user defined attributes cannot appear as postfixes");
|
||||
error("user-defined attributes cannot appear as postfixes");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -1979,9 +1979,11 @@ Parameters *Parser::parseParameters(VarArg *pvarargs, TemplateParameters **tpl)
|
||||
StorageClass storageClass = 0;
|
||||
StorageClass stc;
|
||||
Expression *ae;
|
||||
Expressions *udas = NULL;
|
||||
|
||||
for (;1; nextToken())
|
||||
{
|
||||
L3:
|
||||
switch (token.value)
|
||||
{
|
||||
case TOKrparen:
|
||||
@ -2016,6 +2018,28 @@ Parameters *Parser::parseParameters(VarArg *pvarargs, TemplateParameters **tpl)
|
||||
stc = STCwild;
|
||||
goto L2;
|
||||
|
||||
case TOKat:
|
||||
{
|
||||
Expressions *exps = NULL;
|
||||
StorageClass stc2 = parseAttribute(&exps);
|
||||
if (stc2 == STCproperty || stc2 == STCnogc ||
|
||||
stc2 == STCdisable || stc2 == STCsafe ||
|
||||
stc2 == STCtrusted || stc2 == STCsystem)
|
||||
{
|
||||
error("`@%s` attribute for function parameter is not supported", token.toChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
udas = UserAttributeDeclaration::concat(udas, exps);
|
||||
}
|
||||
if (token.value == TOKdotdotdot)
|
||||
error("variadic parameter cannot have user-defined attributes");
|
||||
if (stc2)
|
||||
nextToken();
|
||||
goto L3;
|
||||
// Don't call nextToken again.
|
||||
}
|
||||
|
||||
case TOKin: stc = STCin; goto L2;
|
||||
case TOKout: stc = STCout; goto L2;
|
||||
case TOKref: stc = STCref; goto L2;
|
||||
@ -2068,6 +2092,30 @@ Parameters *Parser::parseParameters(VarArg *pvarargs, TemplateParameters **tpl)
|
||||
error("default argument expected for %s",
|
||||
ai ? ai->toChars() : at->toChars());
|
||||
}
|
||||
Parameter *param = new Parameter(storageClass, at, ai, ae, NULL);
|
||||
if (udas)
|
||||
{
|
||||
Dsymbols *a = new Dsymbols();
|
||||
UserAttributeDeclaration *udad = new UserAttributeDeclaration(udas, a);
|
||||
param->userAttribDecl = udad;
|
||||
}
|
||||
if (token.value == TOKat)
|
||||
{
|
||||
Expressions *exps = NULL;
|
||||
StorageClass stc2 = parseAttribute(&exps);
|
||||
if (stc2 == STCproperty || stc2 == STCnogc ||
|
||||
stc2 == STCdisable || stc2 == STCsafe ||
|
||||
stc2 == STCtrusted || stc2 == STCsystem)
|
||||
{
|
||||
error("`@%s` attribute for function parameter is not supported", token.toChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
error("user-defined attributes cannot appear as postfixes", token.toChars());
|
||||
}
|
||||
if (stc2)
|
||||
nextToken();
|
||||
}
|
||||
if (token.value == TOKdotdotdot)
|
||||
{ /* This is:
|
||||
* at ai ...
|
||||
@ -2076,11 +2124,11 @@ Parameters *Parser::parseParameters(VarArg *pvarargs, TemplateParameters **tpl)
|
||||
if (storageClass & (STCout | STCref))
|
||||
error("variadic argument cannot be out or ref");
|
||||
varargs = VARARGtypesafe;
|
||||
parameters->push(new Parameter(storageClass, at, ai, ae));
|
||||
parameters->push(param);
|
||||
nextToken();
|
||||
break;
|
||||
}
|
||||
parameters->push(new Parameter(storageClass, at, ai, ae));
|
||||
parameters->push(param);
|
||||
if (token.value == TOKcomma)
|
||||
{ nextToken();
|
||||
goto L1;
|
||||
@ -3779,6 +3827,21 @@ Dsymbols *Parser::parseDeclarations(bool autodecl, PrefixAttributes *pAttrs, con
|
||||
tpl = parseTemplateParameterList();
|
||||
check(TOKassign);
|
||||
|
||||
bool hasParsedAttributes = false;
|
||||
if (token.value == TOKat)
|
||||
{
|
||||
if (!hasParsedAttributes)
|
||||
{
|
||||
hasParsedAttributes = true;
|
||||
storage_class = STCundefined;
|
||||
link = linkage;
|
||||
setAlignment = false;
|
||||
ealign = NULL;
|
||||
udas = NULL;
|
||||
parseStorageClasses(storage_class, link, setAlignment, ealign, udas);
|
||||
}
|
||||
}
|
||||
|
||||
Declaration *v;
|
||||
if (token.value == TOKfunction ||
|
||||
token.value == TOKdelegate ||
|
||||
@ -3796,21 +3859,39 @@ Dsymbols *Parser::parseDeclarations(bool autodecl, PrefixAttributes *pAttrs, con
|
||||
// identifier => expression
|
||||
|
||||
Dsymbol *s = parseFunctionLiteral();
|
||||
|
||||
if (udas != NULL)
|
||||
{
|
||||
if (storage_class != 0)
|
||||
error("Cannot put a storage-class in an alias declaration.");
|
||||
// shouldn't have set these variables
|
||||
assert(link == linkage && !setAlignment && ealign == NULL);
|
||||
TemplateDeclaration *tpl_ = (TemplateDeclaration *) s;
|
||||
assert(tpl_ != NULL && tpl_->members->length == 1);
|
||||
FuncLiteralDeclaration *fd = (FuncLiteralDeclaration *) (*tpl_->members)[0];
|
||||
TypeFunction *tf = (TypeFunction *) fd->type;
|
||||
assert(tf->parameterList.length() > 0);
|
||||
Dsymbols *as = new Dsymbols();
|
||||
(*tf->parameterList.parameters)[0]->userAttribDecl = new UserAttributeDeclaration(udas, as);
|
||||
}
|
||||
v = new AliasDeclaration(loc, ident, s);
|
||||
}
|
||||
else
|
||||
{
|
||||
// StorageClasses type
|
||||
|
||||
storage_class = STCundefined;
|
||||
link = linkage;
|
||||
setAlignment = false;
|
||||
ealign = NULL;
|
||||
udas = NULL;
|
||||
parseStorageClasses(storage_class, link, setAlignment, ealign, udas);
|
||||
if (!hasParsedAttributes)
|
||||
{
|
||||
hasParsedAttributes = true;
|
||||
storage_class = STCundefined;
|
||||
link = linkage;
|
||||
setAlignment = false;
|
||||
ealign = NULL;
|
||||
udas = NULL;
|
||||
parseStorageClasses(storage_class, link, setAlignment, ealign, udas);
|
||||
}
|
||||
|
||||
if (udas)
|
||||
error("user defined attributes not allowed for %s declarations", Token::toChars(tok));
|
||||
error("user-defined attributes not allowed for %s declarations", Token::toChars(tok));
|
||||
|
||||
t = parseType();
|
||||
v = new AliasDeclaration(loc, ident, t);
|
||||
@ -3991,7 +4072,7 @@ L2:
|
||||
*/
|
||||
|
||||
if (udas)
|
||||
error("user defined attributes not allowed for %s declarations", Token::toChars(tok));
|
||||
error("user-defined attributes not allowed for %s declarations", Token::toChars(tok));
|
||||
|
||||
if (token.value == TOKassign)
|
||||
{
|
||||
@ -4221,7 +4302,7 @@ Dsymbol *Parser::parseFunctionLiteral()
|
||||
parameters = new Parameters();
|
||||
Identifier *id = Identifier::generateId("__T");
|
||||
Type *t = new TypeIdentifier(loc, id);
|
||||
parameters->push(new Parameter(0, t, token.ident, NULL));
|
||||
parameters->push(new Parameter(0, t, token.ident, NULL, NULL));
|
||||
|
||||
tpl = new TemplateParameters();
|
||||
TemplateParameter *tp = new TemplateTypeParameter(loc, id, NULL, NULL);
|
||||
@ -4811,7 +4892,7 @@ Statement *Parser::parseForeach(Loc loc, bool *isRange, bool isDecl)
|
||||
if (!ai)
|
||||
error("no identifier for declarator %s", at->toChars());
|
||||
Larg:
|
||||
Parameter *p = new Parameter(storageClass, at, ai, NULL);
|
||||
Parameter *p = new Parameter(storageClass, at, ai, NULL, NULL);
|
||||
parameters->push(p);
|
||||
if (token.value == TOKcomma)
|
||||
{ nextToken();
|
||||
@ -5335,14 +5416,14 @@ Statement *Parser::parseStatement(int flags, const utf8_t** endPtr, Loc *pEndloc
|
||||
Type *at = NULL; // infer parameter type
|
||||
nextToken();
|
||||
check(TOKassign);
|
||||
param = new Parameter(storageClass, at, ai, NULL);
|
||||
param = new Parameter(storageClass, at, ai, NULL, NULL);
|
||||
}
|
||||
else if (isDeclaration(&token, 2, TOKassign, NULL))
|
||||
{
|
||||
Identifier *ai;
|
||||
Type *at = parseType(&ai);
|
||||
check(TOKassign);
|
||||
param = new Parameter(storageClass, at, ai, NULL);
|
||||
param = new Parameter(storageClass, at, ai, NULL, NULL);
|
||||
}
|
||||
|
||||
condition = parseExpression();
|
||||
|
@ -1494,7 +1494,7 @@ public:
|
||||
s = new ExpStatement(Loc(), v);
|
||||
fs->_body = new CompoundStatement(loc, s, fs->_body);
|
||||
}
|
||||
params->push(new Parameter(stc, p->type, id, NULL));
|
||||
params->push(new Parameter(stc, p->type, id, NULL, NULL));
|
||||
}
|
||||
// Bugzilla 13840: Throwable nested function inside nothrow function is acceptable.
|
||||
StorageClass stc = mergeFuncAttrs(STCsafe | STCpure | STCnogc, fs->func);
|
||||
@ -1570,15 +1570,15 @@ public:
|
||||
if (!fdapply[i])
|
||||
{
|
||||
params = new Parameters();
|
||||
params->push(new Parameter(0, Type::tvoid->pointerTo(), NULL, NULL));
|
||||
params->push(new Parameter(STCin, Type::tsize_t, NULL, NULL));
|
||||
params->push(new Parameter(0, Type::tvoid->pointerTo(), NULL, NULL, NULL));
|
||||
params->push(new Parameter(STCin, Type::tsize_t, NULL, NULL, NULL));
|
||||
Parameters* dgparams = new Parameters;
|
||||
dgparams->push(new Parameter(0, Type::tvoidptr, NULL, NULL));
|
||||
dgparams->push(new Parameter(0, Type::tvoidptr, NULL, NULL, NULL));
|
||||
if (dim == 2)
|
||||
dgparams->push(new Parameter(0, Type::tvoidptr, NULL, NULL));
|
||||
dgparams->push(new Parameter(0, Type::tvoidptr, NULL, NULL, NULL));
|
||||
fldeTy[i] = new TypeDelegate(new TypeFunction(ParameterList(dgparams),
|
||||
Type::tint32, LINKd));
|
||||
params->push(new Parameter(0, fldeTy[i], NULL, NULL));
|
||||
params->push(new Parameter(0, fldeTy[i], NULL, NULL, NULL));
|
||||
fdapply[i] = FuncDeclaration::genCfunc(params, Type::tint32, name[i]);
|
||||
}
|
||||
|
||||
@ -1637,14 +1637,14 @@ public:
|
||||
FuncDeclaration *fdapply;
|
||||
TypeDelegate *dgty;
|
||||
params = new Parameters();
|
||||
params->push(new Parameter(STCin, tn->arrayOf(), NULL, NULL));
|
||||
params->push(new Parameter(STCin, tn->arrayOf(), NULL, NULL, NULL));
|
||||
Parameters* dgparams = new Parameters;
|
||||
dgparams->push(new Parameter(0, Type::tvoidptr, NULL, NULL));
|
||||
dgparams->push(new Parameter(0, Type::tvoidptr, NULL, NULL, NULL));
|
||||
if (dim == 2)
|
||||
dgparams->push(new Parameter(0, Type::tvoidptr, NULL, NULL));
|
||||
dgparams->push(new Parameter(0, Type::tvoidptr, NULL, NULL, NULL));
|
||||
dgty = new TypeDelegate(new TypeFunction(ParameterList(dgparams),
|
||||
Type::tint32, LINKd));
|
||||
params->push(new Parameter(0, dgty, NULL, NULL));
|
||||
params->push(new Parameter(0, dgty, NULL, NULL, NULL));
|
||||
fdapply = FuncDeclaration::genCfunc(params, Type::tint32, fdname);
|
||||
|
||||
if (tab->ty == Tsarray)
|
||||
@ -3192,7 +3192,7 @@ public:
|
||||
cs->push(new ExpStatement(ss->loc, tmp));
|
||||
|
||||
Parameters* args = new Parameters;
|
||||
args->push(new Parameter(0, ClassDeclaration::object->type, NULL, NULL));
|
||||
args->push(new Parameter(0, ClassDeclaration::object->type, NULL, NULL, NULL));
|
||||
|
||||
FuncDeclaration *fdenter = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorenter);
|
||||
Expression *e = new CallExp(ss->loc, new VarExp(ss->loc, fdenter, false), new VarExp(ss->loc, tmp));
|
||||
@ -3234,7 +3234,7 @@ public:
|
||||
cs->push(new ExpStatement(ss->loc, v));
|
||||
|
||||
Parameters* args = new Parameters;
|
||||
args->push(new Parameter(0, t->pointerTo(), NULL, NULL));
|
||||
args->push(new Parameter(0, t->pointerTo(), NULL, NULL, NULL));
|
||||
|
||||
FuncDeclaration *fdenter = FuncDeclaration::genCfunc(args, Type::tvoid, Id::criticalenter, STCnothrow);
|
||||
Expression *e = new AddrExp(ss->loc, tmpExp);
|
||||
|
@ -658,7 +658,8 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
|
||||
if (e->ident != Id::compiles &&
|
||||
e->ident != Id::isSame &&
|
||||
e->ident != Id::identifier &&
|
||||
e->ident != Id::getProtection && e->ident != Id::getVisibility)
|
||||
e->ident != Id::getProtection && e->ident != Id::getVisibility &&
|
||||
e->ident != Id::getAttributes)
|
||||
{
|
||||
// Pretend we're in a deprecated scope so that deprecation messages
|
||||
// aren't triggered when checking if a symbol is deprecated
|
||||
@ -905,8 +906,12 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
|
||||
Identifier *id = NULL;
|
||||
if (Parameter *po = isParameter(o))
|
||||
{
|
||||
if (!po->ident)
|
||||
{
|
||||
e->error("argument `%s` has no identifier", po->type->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
id = po->ident;
|
||||
assert(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1245,23 +1250,39 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
|
||||
}
|
||||
else if (e->ident == Id::getAttributes)
|
||||
{
|
||||
/* Specify 0 for bit 0 of the flags argument to semanticTiargs() so that
|
||||
* a symbol should not be folded to a constant.
|
||||
* Bit 1 means don't convert Parameter to Type if Parameter has an identifier
|
||||
*/
|
||||
if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 3))
|
||||
return new ErrorExp();
|
||||
|
||||
if (dim != 1)
|
||||
return dimError(e, 1, dim);
|
||||
|
||||
RootObject *o = (*e->args)[0];
|
||||
Parameter *po = isParameter(o);
|
||||
Dsymbol *s = getDsymbolWithoutExpCtx(o);
|
||||
if (!s)
|
||||
UserAttributeDeclaration *udad = NULL;
|
||||
if (po)
|
||||
{
|
||||
udad = po->userAttribDecl;
|
||||
}
|
||||
else if (s)
|
||||
{
|
||||
if (Import *imp = s->isImport())
|
||||
{
|
||||
s = imp->mod;
|
||||
}
|
||||
//printf("getAttributes %s, attrs = %p, scope = %p\n", s->toChars(), s->userAttribDecl, s->_scope);
|
||||
udad = s->userAttribDecl;
|
||||
}
|
||||
else
|
||||
{
|
||||
e->error("first argument is not a symbol");
|
||||
return new ErrorExp();
|
||||
}
|
||||
if (Import *imp = s->isImport())
|
||||
{
|
||||
s = imp->mod;
|
||||
}
|
||||
|
||||
//printf("getAttributes %s, attrs = %p, scope = %p\n", s->toChars(), s->userAttribDecl, s->_scope);
|
||||
UserAttributeDeclaration *udad = s->userAttribDecl;
|
||||
Expressions *exps = udad ? udad->getAttributes() : new Expressions();
|
||||
TupleExp *tup = new TupleExp(e->loc, exps);
|
||||
return semantic(tup, sc);
|
||||
|
@ -519,3 +519,21 @@ struct Foo3A(T)
|
||||
@disable this(this);
|
||||
@disable this();
|
||||
}
|
||||
|
||||
void test13x(@(10) int a, @(20) int, @(30) @(40) int[] arr...) {}
|
||||
|
||||
enum Test14UDA1;
|
||||
struct Test14UDA2
|
||||
{
|
||||
string str;
|
||||
}
|
||||
|
||||
Test14UDA2 test14uda3(string name)
|
||||
{
|
||||
return Test14UDA2(name);
|
||||
}
|
||||
struct Test14UDA4(string v){}
|
||||
|
||||
void test14x(@Test14UDA1 int, @Test14UDA2("1") int, @test14uda3("2") int, @Test14UDA4!"3" int) {}
|
||||
|
||||
void test15x(@(20) void delegate(int) @safe dg){}
|
||||
|
@ -11,3 +11,5 @@ struct UDA
|
||||
}
|
||||
|
||||
void main() {}
|
||||
|
||||
void foo(@(1) int bar, @UDA(2) string bebe);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/fail10207.d(7): Error: user defined attributes not allowed for `alias` declarations
|
||||
fail_compilation/fail10207.d(7): Error: user-defined attributes not allowed for `alias` declarations
|
||||
---
|
||||
*/
|
||||
alias @Safe int __externC;
|
||||
|
@ -467,6 +467,193 @@ static assert(__traits(getAttributes, FileData11844.member)[0](new FileData11844
|
||||
|
||||
/************************************************/
|
||||
|
||||
template AliasSeq(T...)
|
||||
{
|
||||
alias AliasSeq = T;
|
||||
}
|
||||
|
||||
template ParameterUDA(size_t p_num, func...)
|
||||
if (func.length == 1 && is(typeof(func[0]) PT == __parameters) && PT.length > p_num)
|
||||
{
|
||||
static if (is(typeof(func[0]) PT == __parameters))
|
||||
{
|
||||
template Get(size_t i)
|
||||
{
|
||||
static if (//!isFunctionPointer!func && !isDelegate!func
|
||||
// Parameters without UDA may yield CT error.
|
||||
/*&&*/ is(typeof(__traits(getAttributes, PT[i..i+1]))x))
|
||||
{
|
||||
alias Get = AliasSeq!(__traits(getAttributes, PT[i..i+1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
alias Get = AliasSeq!();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(0, func[0].stringof ~ "is not a function");
|
||||
|
||||
// Define dummy entities to avoid pointless errors
|
||||
template Get(size_t i) { alias Get = AliasSeq!(); }
|
||||
alias PT = AliasSeq!();
|
||||
}
|
||||
|
||||
alias ParameterUDA = Get!p_num;
|
||||
}
|
||||
|
||||
void test13x(@(10) int a, @(20) int, @(30) @(40) int[] arr...) {}
|
||||
|
||||
void test13()
|
||||
{
|
||||
static assert([ParameterUDA!(0, test13x)] == [10]);
|
||||
static assert([ParameterUDA!(1, test13x)] == [20]);
|
||||
static assert([ParameterUDA!(2, test13x)] == [30, 40]);
|
||||
}
|
||||
|
||||
template Test13t(F)
|
||||
{
|
||||
static assert(!__traits(compiles, ParameterUDA!(0, F)));
|
||||
static assert(!__traits(compiles, ParameterUDA!(1, F)));
|
||||
static assert(!__traits(compiles, ParameterUDA!(2, F)));
|
||||
enum Test13t = true;
|
||||
}
|
||||
|
||||
alias test13t = Test13t!(typeof(test13x));
|
||||
|
||||
enum Test14UDA1;
|
||||
|
||||
struct Test14UDA2
|
||||
{
|
||||
string str;
|
||||
}
|
||||
|
||||
Test14UDA2 test14uda3(string name)
|
||||
{
|
||||
return Test14UDA2(name);
|
||||
}
|
||||
|
||||
struct Test14UDA4(string v)
|
||||
{
|
||||
}
|
||||
|
||||
void test14x(@Test14UDA1 int, @Test14UDA2("1") int, @test14uda3("2") int, @Test14UDA4!"3" int) {}
|
||||
void test14()
|
||||
{
|
||||
static assert(is(ParameterUDA!(0, test14x)[0] == Test14UDA1));
|
||||
static assert(ParameterUDA!(1, test14x)[0] == Test14UDA2("1"));
|
||||
static assert(ParameterUDA!(2, test14x)[0] == test14uda3("2"));
|
||||
static assert(is(ParameterUDA!(3, test14x)[0] == Test14UDA4!"3"));
|
||||
}
|
||||
|
||||
void test15x(@(20) void delegate(int) @safe dg)
|
||||
{
|
||||
static assert([__traits(getAttributes, dg)] == [20]);
|
||||
static assert(is(typeof(dg) == void delegate(int) @safe));
|
||||
}
|
||||
|
||||
template MinimalFunctionTypeOf(func...)
|
||||
if (func.length == 1)
|
||||
{
|
||||
static if (is(func[0] T) || is(typeof(func[0]) T) && is(T Fdlg == delegate))
|
||||
alias MinimalFunctionTypeOf = Fdlg; // HIT: delegate
|
||||
else
|
||||
static assert(0);
|
||||
}
|
||||
|
||||
template Parameters(func...)
|
||||
if (func.length == 1)
|
||||
{
|
||||
static if (is(MinimalFunctionTypeOf!func P == function))
|
||||
alias Parameters = P;
|
||||
else
|
||||
static assert(0, "argument has no parameters");
|
||||
}
|
||||
|
||||
void test15y(@(20) void delegate(@Test14UDA2("2") @("test15yUDA") int) @safe dg)
|
||||
{
|
||||
static assert([__traits(getAttributes, dg)] == [20]);
|
||||
static assert(is(typeof(dg) == void delegate(int) @safe));
|
||||
auto foo = (@("myUDA") int x){
|
||||
static assert([__traits(getAttributes, x)] == ["myUDA"]);
|
||||
};
|
||||
static assert(__traits(getAttributes, Parameters!dg)[0] == Test14UDA2("2"));
|
||||
static assert(__traits(getAttributes, Parameters!dg)[1] == "test15yUDA");
|
||||
}
|
||||
|
||||
void test15z()
|
||||
{
|
||||
test15y((@(15) @(16) int x){
|
||||
static assert([__traits(getAttributes, x)] == [15, 16]);
|
||||
});
|
||||
}
|
||||
|
||||
void test16x(A)(@(22) A a)
|
||||
{
|
||||
static assert([__traits(getAttributes, a)] == [22]);
|
||||
}
|
||||
|
||||
void test16()
|
||||
{
|
||||
static assert([ParameterUDA!(0, test16x!int)] == [22]);
|
||||
}
|
||||
|
||||
void test17()
|
||||
{
|
||||
void test17x(A)(@(23) A a)
|
||||
{
|
||||
static assert([__traits(getAttributes, a)] == [23]);
|
||||
}
|
||||
static assert([ParameterUDA!(0, test17x!int)] == [23]);
|
||||
}
|
||||
|
||||
void test18()
|
||||
{
|
||||
void test18a(@(Tuple!(18, "a")) int a)
|
||||
{
|
||||
static assert(__traits(getAttributes, a) == Tuple!(18, "a"));
|
||||
}
|
||||
void test18b(@Tuple!(18, "b") int a)
|
||||
{
|
||||
static assert(__traits(getAttributes, a) == Tuple!(18, "b"));
|
||||
}
|
||||
|
||||
static assert(ParameterUDA!(0, test18a) == Tuple!(18, "a"));
|
||||
static assert(ParameterUDA!(0, test18b) == Tuple!(18, "b"));
|
||||
}
|
||||
|
||||
// Lambdas with parentheses:
|
||||
void test19()
|
||||
{
|
||||
// lambdas without parentheses
|
||||
alias test19a = @(3) b => 1 + 2;
|
||||
alias test19b = @(3) @(4) b => 1 + 2;
|
||||
|
||||
alias test19c = (@(3) c, @(5) d) => 1 + 2;
|
||||
alias test19d = (@(3) @(4) c, @(5) d) => 1 + 2;
|
||||
auto test19e = (@(3) int c, @(5) int d) => 1 + 2;
|
||||
|
||||
// still allow alias function declarations
|
||||
alias FuncType = @safe void function();
|
||||
alias FuncType2 = @safe nothrow void function();
|
||||
alias FuncType3 = nothrow void function();
|
||||
alias FuncType4 = nothrow @safe void function();
|
||||
}
|
||||
|
||||
void test20()
|
||||
{
|
||||
// Using a delegate with inferred parameter type
|
||||
void test20a(int delegate(int) t){ t(1); }
|
||||
test20a((@(19) a) {
|
||||
static assert([__traits(getAttributes, a)] == [19]);
|
||||
return a + 2;
|
||||
});
|
||||
}
|
||||
|
||||
/************************************************/
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
test1();
|
||||
@ -482,6 +669,13 @@ int main()
|
||||
test11();
|
||||
test12();
|
||||
test9178();
|
||||
test13();
|
||||
test14();
|
||||
test16();
|
||||
test17();
|
||||
test18();
|
||||
test19();
|
||||
test20();
|
||||
|
||||
printf("Success\n");
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user