changeset 1621:fb2e6707ad17

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(-)
author Leandro Lucarella <llucax@gmail.com>
date Wed, 06 Jan 2010 15:18:22 -0300
parents 0333945a915e
children a542ef277a84
files dmd/constfold.c dmd/declaration.c dmd/declaration.h dmd/expression.c dmd/interpret.c dmd/mars.h dmd/mtype.c
diffstat 7 files changed, 135 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/constfold.c	Wed Jan 06 15:18:22 2010 -0300
+++ b/dmd/constfold.c	Wed Jan 06 15:18:22 2010 -0300
@@ -863,7 +863,7 @@
 }
 
 Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2)
-{   Expression *e;
+{
     Loc loc = e1->loc;
     int cmp;
 
@@ -1055,12 +1055,12 @@
 	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 @@
 	}
     }
 
+    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);
--- a/dmd/declaration.c	Wed Jan 06 15:18:22 2010 -0300
+++ b/dmd/declaration.c	Wed Jan 06 15:18:22 2010 -0300
@@ -309,6 +309,9 @@
     {	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 @@
     }
     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 @@
 	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 @@
 {
 #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 @@
     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);
--- a/dmd/declaration.h	Wed Jan 06 15:18:22 2010 -0300
+++ b/dmd/declaration.h	Wed Jan 06 15:18:22 2010 -0300
@@ -79,9 +79,16 @@
     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 @@
     int isImportedSymbol();
     int isDataseg();
     int isThreadlocal();
+    int isCTFE();
     int hasPointers();
 #if DMDV2
     int canTakeAddressOf();
--- a/dmd/expression.c	Wed Jan 06 15:18:22 2010 -0300
+++ b/dmd/expression.c	Wed Jan 06 15:18:22 2010 -0300
@@ -711,6 +711,7 @@
 			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);
--- a/dmd/interpret.c	Wed Jan 06 15:18:22 2010 -0300
+++ b/dmd/interpret.c	Wed Jan 06 15:18:22 2010 -0300
@@ -48,6 +48,10 @@
 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 @@
 #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 @@
     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 @@
 	}
 	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 @@
 
 	    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 @@
     {
 	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 @@
 	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 @@
     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 @@
     {	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 @@
     {	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 @@
         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 @@
         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 @@
 
 /******************************* Special Functions ***************************/
 
+#if DMDV1
+
 Expression *interpret_aaLen(InterState *istate, Expressions *arguments)
 {
     if (!arguments || arguments->dim != 1)
@@ -2690,3 +2713,59 @@
     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
+
--- a/dmd/mars.h	Wed Jan 06 15:18:22 2010 -0300
+++ b/dmd/mars.h	Wed Jan 06 15:18:22 2010 -0300
@@ -417,7 +417,7 @@
     MATCHexact		// exact match
 };
 
-typedef unsigned StorageClass;
+typedef uint64_t StorageClass;
 
 
 void warning(Loc loc, const char *format, ...) IS_PRINTF(2);
--- a/dmd/mtype.c	Wed Jan 06 15:18:22 2010 -0300
+++ b/dmd/mtype.c	Wed Jan 06 15:18:22 2010 -0300
@@ -5466,7 +5466,7 @@
 
 /***************************** 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;