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
-a5c86f5b92c4cd3afde910c89881ccaea11de554
+9038e64c5b67a10763d32893f53bb6c610df3595
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
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),
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);
}
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);
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);
}
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);
/* 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);
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;
/* 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);
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;
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);
{
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];
{
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;
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);
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;
}
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);
}
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;
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)
{
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);
+ }
}
/****************************************************
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);
parameters->push(v);
localsymtab->insert(v);
v->parent = this;
+ if (fparam->userAttribDecl)
+ v->userAttribDecl = fparam->userAttribDecl;
}
}
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 ");
{
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)
{
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);
}
}
}
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;
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;
}
(*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);
}
{ 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;
}
}
: 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()
/***************************** 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()
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)
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()
// 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;
}
StorageClass storageClass = 0;
StorageClass stc;
Expression *ae;
+ Expressions *udas = NULL;
for (;1; nextToken())
{
+ L3:
switch (token.value)
{
case TOKrparen:
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;
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 ...
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;
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 ||
// 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);
*/
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)
{
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);
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();
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();
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);
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]);
}
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)
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));
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);
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
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
{
}
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)
{
- e->error("first argument is not a symbol");
- return new ErrorExp();
+ udad = po->userAttribDecl;
}
- if (Import *imp = s->isImport())
+ else if (s)
{
- s = imp->mod;
+ 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();
}
- //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);
@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){}
}
void main() {}
+
+void foo(@(1) int bar, @UDA(2) string bebe);
/*
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;
/************************************************/
+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();
test11();
test12();
test9178();
+ test13();
+ test14();
+ test16();
+ test17();
+ test18();
+ test19();
+ test20();
printf("Success\n");
return 0;