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:
Iain Buclaw 2021-01-07 18:03:33 +01:00
parent d54029179c
commit dddea6d4d8
20 changed files with 432 additions and 74 deletions

View File

@ -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

View File

@ -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.

View File

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

View File

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

View File

@ -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];

View File

@ -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;

View File

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

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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 ");

View File

@ -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)

View File

@ -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()

View File

@ -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();

View File

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

View File

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

View File

@ -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){}

View File

@ -11,3 +11,5 @@ struct UDA
}
void main() {}
void foo(@(1) int bar, @UDA(2) string bebe);

View File

@ -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;

View File

@ -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;