mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-16 04:43:14 +01:00
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Both DMD revisions are for fixing bugzilla 2029 (Typesafe variadic functions don't work in CTFE). The DMD r314 commit message is: bugzilla 2029 (Typesafe variadic functions don't work in CTFE The DMD r315 commit message is: bugzilla 2029 - try again --- dmd/constfold.c | 11 ++++- dmd/declaration.c | 21 +++++++++- dmd/declaration.h | 10 ++++- dmd/expression.c | 1 + dmd/interpret.c | 111 +++++++++++++++++++++++++++++++++++++++++++++-------- dmd/mars.h | 2 +- dmd/mtype.c | 2 +- 7 files changed, 135 insertions(+), 23 deletions(-)
This commit is contained in:
@@ -863,7 +863,7 @@ Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2)
|
||||
}
|
||||
|
||||
Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2)
|
||||
{ Expression *e;
|
||||
{
|
||||
Loc loc = e1->loc;
|
||||
int cmp;
|
||||
|
||||
@@ -1055,12 +1055,12 @@ Expression *Cast(Type *type, Type *to, Expression *e1)
|
||||
return e1;
|
||||
|
||||
Type *tb = to->toBasetype();
|
||||
Type *typeb = type->toBasetype();
|
||||
|
||||
/* Allow casting from one string type to another
|
||||
*/
|
||||
if (e1->op == TOKstring)
|
||||
{
|
||||
Type *typeb = type->toBasetype();
|
||||
if (tb->ty == Tarray && typeb->ty == Tarray &&
|
||||
tb->nextOf()->size() == typeb->nextOf()->size())
|
||||
{
|
||||
@@ -1068,8 +1068,15 @@ Expression *Cast(Type *type, Type *to, Expression *e1)
|
||||
}
|
||||
}
|
||||
|
||||
if (e1->op == TOKarrayliteral && typeb == tb)
|
||||
{
|
||||
return e1;
|
||||
}
|
||||
|
||||
if (e1->isConst() != 1)
|
||||
{
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
|
||||
if (tb->ty == Tbool)
|
||||
e = new IntegerExp(loc, e1->toInteger() != 0, type);
|
||||
|
||||
@@ -309,6 +309,9 @@ void TypedefDeclaration::semantic(Scope *sc)
|
||||
{ sem = 1;
|
||||
basetype = basetype->semantic(loc, sc);
|
||||
sem = 2;
|
||||
#if DMDV2
|
||||
type = type->addStorageClass(storage_class);
|
||||
#endif
|
||||
type = type->semantic(loc, sc);
|
||||
if (sc->parent->isFuncDeclaration() && init)
|
||||
semantic2(sc);
|
||||
@@ -441,8 +444,10 @@ void AliasDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
this->inSemantic = 1;
|
||||
|
||||
#if DMDV1 // don't really know why this is here
|
||||
if (storage_class & STCconst)
|
||||
error("cannot be const");
|
||||
#endif
|
||||
|
||||
storage_class |= sc->stc & STCdeprecated;
|
||||
|
||||
@@ -473,11 +478,12 @@ void AliasDeclaration::semantic(Scope *sc)
|
||||
goto L2; // it's a symbolic alias
|
||||
|
||||
#if DMDV2
|
||||
type = type->addStorageClass(storage_class);
|
||||
if (storage_class & (STCref | STCnothrow | STCpure))
|
||||
{ // For 'ref' to be attached to function types, and picked
|
||||
// up by Type::resolve(), it has to go into sc.
|
||||
sc = sc->push();
|
||||
sc->stc |= storage_class & (STCref | STCnothrow | STCpure);
|
||||
sc->stc |= storage_class & (STCref | STCnothrow | STCpure | STCshared);
|
||||
type->resolve(loc, sc, &e, &t, &s);
|
||||
sc = sc->pop();
|
||||
}
|
||||
@@ -1341,7 +1347,7 @@ int VarDeclaration::isDataseg()
|
||||
{
|
||||
#if 0
|
||||
printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
|
||||
printf("%x, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance());
|
||||
printf("%llx, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance());
|
||||
printf("parent = '%s'\n", parent->toChars());
|
||||
#endif
|
||||
Dsymbol *parent = this->toParent();
|
||||
@@ -1364,6 +1370,17 @@ int VarDeclaration::isThreadlocal()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* Can variable be read and written by CTFE?
|
||||
*/
|
||||
|
||||
int VarDeclaration::isCTFE()
|
||||
{
|
||||
//printf("VarDeclaration::isCTFE(%p, '%s')\n", this, toChars());
|
||||
//printf("%llx\n", storage_class);
|
||||
return (storage_class & STCctfe) || !isDataseg();
|
||||
}
|
||||
|
||||
int VarDeclaration::hasPointers()
|
||||
{
|
||||
//printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type->ty);
|
||||
|
||||
@@ -79,9 +79,16 @@ enum STC
|
||||
STCshared = 0x20000000, // accessible from multiple threads
|
||||
STCgshared = 0x40000000, // accessible from multiple threads
|
||||
// but not typed as "shared"
|
||||
STC_TYPECTOR = (STCconst | STCimmutable | STCshared),
|
||||
STCwild = 0x80000000, // for "wild" type constructor
|
||||
STC_TYPECTOR = (STCconst | STCimmutable | STCshared | STCwild),
|
||||
};
|
||||
|
||||
#define STCproperty 0x100000000LL
|
||||
#define STCsafe 0x200000000LL
|
||||
#define STCtrusted 0x400000000LL
|
||||
#define STCsystem 0x800000000LL
|
||||
#define STCctfe 0x1000000000LL // can be used in CTFE, even if it is static
|
||||
|
||||
struct Match
|
||||
{
|
||||
int count; // number of matches found
|
||||
@@ -290,6 +297,7 @@ struct VarDeclaration : Declaration
|
||||
int isImportedSymbol();
|
||||
int isDataseg();
|
||||
int isThreadlocal();
|
||||
int isCTFE();
|
||||
int hasPointers();
|
||||
#if DMDV2
|
||||
int canTakeAddressOf();
|
||||
|
||||
@@ -711,6 +711,7 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
|
||||
Type *t = new TypeSArray(((TypeArray *)tb)->next, new IntegerExp(nargs - i));
|
||||
t = t->semantic(loc, sc);
|
||||
VarDeclaration *v = new VarDeclaration(loc, t, id, new VoidInitializer(loc));
|
||||
v->storage_class |= STCctfe;
|
||||
v->semantic(sc);
|
||||
v->parent = sc->parent;
|
||||
//sc->insert(v);
|
||||
|
||||
111
dmd/interpret.c
111
dmd/interpret.c
@@ -48,6 +48,10 @@ Expression *interpret_aaLen(InterState *istate, Expressions *arguments);
|
||||
Expression *interpret_aaKeys(InterState *istate, Expressions *arguments);
|
||||
Expression *interpret_aaValues(InterState *istate, Expressions *arguments);
|
||||
|
||||
Expression *interpret_length(InterState *istate, Expression *earg);
|
||||
Expression *interpret_keys(InterState *istate, Expression *earg, FuncDeclaration *fd);
|
||||
Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclaration *fd);
|
||||
|
||||
/*************************************
|
||||
* Attempt to interpret a function given the arguments.
|
||||
* Input:
|
||||
@@ -66,12 +70,27 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
||||
#endif
|
||||
if (global.errors)
|
||||
return NULL;
|
||||
|
||||
#if DMDV1
|
||||
if (ident == Id::aaLen)
|
||||
return interpret_aaLen(istate, arguments);
|
||||
else if (ident == Id::aaKeys)
|
||||
return interpret_aaKeys(istate, arguments);
|
||||
else if (ident == Id::aaValues)
|
||||
return interpret_aaValues(istate, arguments);
|
||||
#endif
|
||||
#if DMDV2
|
||||
if (thisarg &&
|
||||
(!arguments || arguments->dim == 0))
|
||||
{
|
||||
if (ident == Id::length)
|
||||
return interpret_length(istate, thisarg);
|
||||
else if (ident == Id::keys)
|
||||
return interpret_keys(istate, thisarg, this);
|
||||
else if (ident == Id::values)
|
||||
return interpret_values(istate, thisarg, this);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cantInterpret || semanticRun == 3)
|
||||
return NULL;
|
||||
@@ -94,9 +113,9 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
||||
assert(tb->ty == Tfunction);
|
||||
TypeFunction *tf = (TypeFunction *)tb;
|
||||
Type *tret = tf->next->toBasetype();
|
||||
if (tf->varargs)
|
||||
if (tf->varargs && arguments && parameters && arguments->dim != parameters->dim)
|
||||
{ cantInterpret = 1;
|
||||
error("Variadic functions are not yet implemented in CTFE");
|
||||
error("C-style variadic functions are not yet implemented in CTFE");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1004,7 +1023,7 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d)
|
||||
}
|
||||
else
|
||||
{ e = v->value;
|
||||
if (v->isDataseg())
|
||||
if (!v->isCTFE())
|
||||
{ error(loc, "static variable %s cannot be read at compile time", v->toChars());
|
||||
e = EXP_CANT_INTERPRET;
|
||||
}
|
||||
@@ -1136,9 +1155,7 @@ Expression *ArrayLiteralExp::interpret(InterState *istate)
|
||||
|
||||
ex = e->interpret(istate);
|
||||
if (ex == EXP_CANT_INTERPRET)
|
||||
{ delete expsx;
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
goto Lerror;
|
||||
|
||||
/* If any changes, do Copy On Write
|
||||
*/
|
||||
@@ -1160,14 +1177,18 @@ Expression *ArrayLiteralExp::interpret(InterState *istate)
|
||||
{
|
||||
expandTuples(expsx);
|
||||
if (expsx->dim != elements->dim)
|
||||
{ delete expsx;
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
goto Lerror;
|
||||
ArrayLiteralExp *ae = new ArrayLiteralExp(loc, expsx);
|
||||
ae->type = type;
|
||||
return ae;
|
||||
}
|
||||
return this;
|
||||
|
||||
Lerror:
|
||||
if (expsx)
|
||||
delete expsx;
|
||||
error("cannot interpret array literal");
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
|
||||
Expression *AssocArrayLiteralExp::interpret(InterState *istate)
|
||||
@@ -1594,12 +1615,12 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
|
||||
VarExp *ve = (VarExp *)e1;
|
||||
VarDeclaration *v = ve->var->isVarDeclaration();
|
||||
assert(v);
|
||||
if (v && v->isDataseg())
|
||||
if (v && !v->isCTFE())
|
||||
{ // Can't modify global or static data
|
||||
error("%s cannot be modified at compile time", v->toChars());
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
if (v && !v->isDataseg())
|
||||
if (v && v->isCTFE())
|
||||
{
|
||||
Expression *ev = v->value;
|
||||
if (fp && !ev)
|
||||
@@ -1635,7 +1656,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
|
||||
else if (e1->op == TOKdotvar && aggregate->op == TOKvar)
|
||||
{ VarDeclaration *v = ((VarExp *)aggregate)->var->isVarDeclaration();
|
||||
|
||||
if (v->isDataseg())
|
||||
if (!v->isCTFE())
|
||||
{ // Can't modify global or static data
|
||||
error("%s cannot be modified at compile time", v->toChars());
|
||||
return EXP_CANT_INTERPRET;
|
||||
@@ -1707,7 +1728,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
|
||||
{ SymOffExp *soe = (SymOffExp *)((PtrExp *)e1)->e1;
|
||||
VarDeclaration *v = soe->var->isVarDeclaration();
|
||||
|
||||
if (v->isDataseg())
|
||||
if (!v->isCTFE())
|
||||
{
|
||||
error("%s cannot be modified at compile time", v->toChars());
|
||||
return EXP_CANT_INTERPRET;
|
||||
@@ -1753,7 +1774,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
|
||||
{ IndexExp *ie = (IndexExp *)e1;
|
||||
VarExp *ve = (VarExp *)ie->e1;
|
||||
VarDeclaration *v = ve->var->isVarDeclaration();
|
||||
if (!v || v->isDataseg())
|
||||
if (!v || !v->isCTFE())
|
||||
{
|
||||
error("%s cannot be modified at compile time", v ? v->toChars(): "void");
|
||||
return EXP_CANT_INTERPRET;
|
||||
@@ -1916,7 +1937,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
|
||||
IndexExp * ie = (IndexExp *)aggregate;
|
||||
VarExp *ve = (VarExp *)(ie->e1);
|
||||
VarDeclaration *v = ve->var->isVarDeclaration();
|
||||
if (!v || v->isDataseg())
|
||||
if (!v || !v->isCTFE())
|
||||
{
|
||||
error("%s cannot be modified at compile time", v ? v->toChars(): "void");
|
||||
return EXP_CANT_INTERPRET;
|
||||
@@ -2008,7 +2029,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
|
||||
SliceExp * sexp = (SliceExp *)e1;
|
||||
VarExp *ve = (VarExp *)(sexp->e1);
|
||||
VarDeclaration *v = ve->var->isVarDeclaration();
|
||||
if (!v || v->isDataseg())
|
||||
if (!v || !v->isCTFE())
|
||||
{
|
||||
error("%s cannot be modified at compile time", v->toChars());
|
||||
return EXP_CANT_INTERPRET;
|
||||
@@ -2636,6 +2657,8 @@ Expression *DotVarExp::interpret(InterState *istate)
|
||||
|
||||
/******************************* Special Functions ***************************/
|
||||
|
||||
#if DMDV1
|
||||
|
||||
Expression *interpret_aaLen(InterState *istate, Expressions *arguments)
|
||||
{
|
||||
if (!arguments || arguments->dim != 1)
|
||||
@@ -2690,3 +2713,59 @@ Expression *interpret_aaValues(InterState *istate, Expressions *arguments)
|
||||
return e;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if DMDV2
|
||||
|
||||
Expression *interpret_length(InterState *istate, Expression *earg)
|
||||
{
|
||||
//printf("interpret_length()\n");
|
||||
earg = earg->interpret(istate);
|
||||
if (earg == EXP_CANT_INTERPRET)
|
||||
return NULL;
|
||||
if (earg->op != TOKassocarrayliteral)
|
||||
return NULL;
|
||||
AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg;
|
||||
Expression *e = new IntegerExp(aae->loc, aae->keys->dim, Type::tsize_t);
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *interpret_keys(InterState *istate, Expression *earg, FuncDeclaration *fd)
|
||||
{
|
||||
#if LOG
|
||||
printf("interpret_keys()\n");
|
||||
#endif
|
||||
earg = earg->interpret(istate);
|
||||
if (earg == EXP_CANT_INTERPRET)
|
||||
return NULL;
|
||||
if (earg->op != TOKassocarrayliteral)
|
||||
return NULL;
|
||||
AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg;
|
||||
Expression *e = new ArrayLiteralExp(aae->loc, aae->keys);
|
||||
assert(fd->type->ty == Tfunction);
|
||||
assert(fd->type->nextOf()->ty == Tarray);
|
||||
Type *elemType = ((TypeFunction *)fd->type)->nextOf()->nextOf();
|
||||
e->type = new TypeSArray(elemType, new IntegerExp(aae->keys->dim));
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclaration *fd)
|
||||
{
|
||||
//printf("interpret_values()\n");
|
||||
earg = earg->interpret(istate);
|
||||
if (earg == EXP_CANT_INTERPRET)
|
||||
return NULL;
|
||||
if (earg->op != TOKassocarrayliteral)
|
||||
return NULL;
|
||||
AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg;
|
||||
Expression *e = new ArrayLiteralExp(aae->loc, aae->values);
|
||||
assert(fd->type->ty == Tfunction);
|
||||
assert(fd->type->nextOf()->ty == Tarray);
|
||||
Type *elemType = ((TypeFunction *)fd->type)->nextOf()->nextOf();
|
||||
e->type = new TypeSArray(elemType, new IntegerExp(aae->values->dim));
|
||||
//printf("result is %s\n", e->toChars());
|
||||
return e;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -417,7 +417,7 @@ enum MATCH
|
||||
MATCHexact // exact match
|
||||
};
|
||||
|
||||
typedef unsigned StorageClass;
|
||||
typedef uint64_t StorageClass;
|
||||
|
||||
|
||||
void warning(Loc loc, const char *format, ...) IS_PRINTF(2);
|
||||
|
||||
@@ -5466,7 +5466,7 @@ void TypeSlice::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
|
||||
|
||||
/***************************** Parameter *****************************/
|
||||
|
||||
Parameter::Parameter(unsigned storageClass, Type *type, Identifier *ident, Expression *defaultArg)
|
||||
Parameter::Parameter(StorageClass storageClass, Type *type, Identifier *ident, Expression *defaultArg)
|
||||
{
|
||||
this->type = type;
|
||||
this->ident = ident;
|
||||
|
||||
Reference in New Issue
Block a user