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:
Leandro Lucarella
2010-01-06 15:18:22 -03:00
parent 3fc72b7ec3
commit b9896b9034
7 changed files with 135 additions and 23 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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