diff dmd/func.c @ 336:aaade6ded589 trunk

[svn r357] Merged DMD 1.033
author lindquist
date Sat, 12 Jul 2008 19:38:31 +0200
parents f7190d9eb70c
children d8234836b40f
line wrap: on
line diff
--- a/dmd/func.c	Sat Jul 12 17:04:36 2008 +0200
+++ b/dmd/func.c	Sat Jul 12 19:38:31 2008 +0200
@@ -103,6 +103,7 @@
     StructDeclaration *sd;
     ClassDeclaration *cd;
     InterfaceDeclaration *id;
+    Dsymbol *pd;
 
 #if 0
     printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc->linkage);
@@ -208,6 +209,18 @@
 	    error("function body is not abstract in interface %s", id->toChars());
     }
 
+    /* Template member functions aren't virtual:
+     *   interface TestInterface { void tpl(T)(); }
+     * and so won't work in interfaces
+     */
+    if ((pd = toParent()) != NULL &&
+	pd->isTemplateInstance() &&
+	(pd = toParent2()) != NULL &&
+	(id = pd->isInterfaceDeclaration()) != NULL)
+    {
+	error("template member function not allowed in interface %s", id->toChars());
+    }
+
     cd = parent->isClassDeclaration();
     if (cd)
     {	int vi;
@@ -306,7 +319,7 @@
 		if (fdv->isFinal())
 		    error("cannot override final function %s", fdv->toPrettyChars());
 
-#if V2
+#if DMDV2
 		if (!isOverride() && global.params.warnings)
 		    warning("%s: overrides base class function %s, but is not marked with 'override'", locToChars() fdv->toPrettyChars());
 #endif
@@ -322,7 +335,7 @@
 #if !BREAKABI
 			&& !isDtorDeclaration()
 #endif
-#if V2
+#if DMDV2
 			&& !isPostBlitDeclaration()
 #endif
 			)
@@ -978,7 +991,8 @@
 		f = (TypeFunction *)type;
 	    }
 
-	    int offend = fbody ? fbody->fallOffEnd() : TRUE;
+	    int offend = fbody ? fbody->blockExit() & BEfallthru : TRUE;
+	    //int offend = fbody ? fbody->fallOffEnd() : TRUE;
 
 	    if (isStaticCtorDeclaration())
 	    {	/* It's a static constructor. Ensure that all
@@ -1471,7 +1485,7 @@
 	return 1;
     }
 
-#if V2
+#if DMDV2
     /* Allow covariant matches, if it's just a const conversion
      * of the return type
      */
@@ -1777,6 +1791,7 @@
     }
     return (LabelDsymbol *)s;
 }
+
 /****************************************
  * If non-static member function that has a 'this' pointer,
  * return the aggregate it is a member of.
@@ -2031,17 +2046,18 @@
     return fd;
 }
 
-char *FuncDeclaration::kind()
+const char *FuncDeclaration::kind()
 {
     return "function";
 }
+
 /*******************************
  * Look at all the variables in this function that are referenced
  * by nested functions, and determine if a closure needs to be
  * created for them.
  */
 
-#if V2
+#if DMDV2
 int FuncDeclaration::needsClosure()
 {
     /* Need a closure for all the closureVars[] if any of the
@@ -2051,7 +2067,11 @@
      * 1) is a virtual function
      * 2) has its address taken
      * 3) has a parent that escapes
-     * escapes.
+     *
+     * Note that since a non-virtual function can be called by
+     * a virtual one, if that non-virtual function accesses a closure
+     * var, the closure still has to be taken. Hence, we check for isThis()
+     * instead of isVirtual(). (thanks to David Friedman)
      */
 
     //printf("FuncDeclaration::needsClosure() %s\n", toChars());
@@ -2065,14 +2085,14 @@
 	    assert(f != this);
 
 	    //printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf);
-	    if (f->isVirtual() || f->tookAddressOf)
+	    if (f->isThis() || f->tookAddressOf)
 		goto Lyes;	// assume f escapes this function's scope
 
 	    // Look to see if any parents of f that are below this escape
 	    for (Dsymbol *s = f->parent; s != this; s = s->parent)
 	    {
 		f = s->isFuncDeclaration();
-		if (f && (f->isVirtual() || f->tookAddressOf))
+		if (f && (f->isThis() || f->tookAddressOf))
 		    goto Lyes;
 	    }
 	}
@@ -2097,7 +2117,7 @@
     this->funcalias = funcalias;
 }
 
-char *FuncAliasDeclaration::kind()
+const char *FuncAliasDeclaration::kind()
 {
     return "function alias";
 }
@@ -2142,7 +2162,12 @@
     return (tok == TOKdelegate);
 }
 
-char *FuncLiteralDeclaration::kind()
+int FuncLiteralDeclaration::isVirtual()
+{
+    return FALSE;
+}
+
+const char *FuncLiteralDeclaration::kind()
 {
     // GCC requires the (char*) casts
     return (tok == TOKdelegate) ? (char*)"delegate" : (char*)"function";
@@ -2214,6 +2239,8 @@
     else
 	tret = cd->type; //->referenceTo();
     type = new TypeFunction(arguments, tret, varargs, LINKd);
+    if (!originalType)
+	originalType = type;
 
     sc->flags |= SCOPEctor;
     type = type->semantic(loc, sc);
@@ -2240,7 +2267,7 @@
 	cd->defaultCtor = this;
 }
 
-char *CtorDeclaration::kind()
+const char *CtorDeclaration::kind()
 {
     return "constructor";
 }
@@ -2377,6 +2404,34 @@
 
     type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
 
+    /* If the static ctor appears within a template instantiation,
+     * it could get called multiple times by the module constructors
+     * for different modules. Thus, protect it with a gate.
+     */
+    if (inTemplateInstance())
+    {
+	/* Add this prefix to the function:
+	 *	static int gate;
+	 *	if (++gate != 1) return;
+	 * Note that this is not thread safe; should not have threads
+	 * during static construction.
+	 */
+	Identifier *id = Lexer::idPool("__gate");
+	VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
+	v->storage_class = STCstatic;
+	Statements *sa = new Statements();
+	Statement *s = new DeclarationStatement(0, v);
+	sa->push(s);
+	Expression *e = new IdentifierExp(0, id);
+	e = new AddAssignExp(0, e, new IntegerExp(1));
+	e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(1));
+	s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL);
+	sa->push(s);
+	if (fbody)
+	    sa->push(fbody);
+	fbody = new CompoundStatement(0, sa);
+    }
+
     FuncDeclaration::semantic(sc);
 
     // We're going to need ModuleInfo
@@ -2432,6 +2487,7 @@
     : FuncDeclaration(loc, endloc,
       Identifier::generateId("_staticDtor"), STCstatic, NULL)
 {
+    vgate = NULL;
 }
 
 Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s)
@@ -2455,6 +2511,36 @@
     }
     type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
 
+    /* If the static ctor appears within a template instantiation,
+     * it could get called multiple times by the module constructors
+     * for different modules. Thus, protect it with a gate.
+     */
+    if (inTemplateInstance())
+    {
+	/* Add this prefix to the function:
+	 *	static int gate;
+	 *	if (--gate != 0) return;
+	 * Increment gate during constructor execution.
+	 * Note that this is not thread safe; should not have threads
+	 * during static destruction.
+	 */
+	Identifier *id = Lexer::idPool("__gate");
+	VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
+	v->storage_class = STCstatic;
+	Statements *sa = new Statements();
+	Statement *s = new DeclarationStatement(0, v);
+	sa->push(s);
+	Expression *e = new IdentifierExp(0, id);
+	e = new AddAssignExp(0, e, new IntegerExp(-1));
+	e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(1));
+	s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL);
+	sa->push(s);
+	if (fbody)
+	    sa->push(fbody);
+	fbody = new CompoundStatement(0, sa);
+	vgate = v;
+    }
+
     FuncDeclaration::semantic(sc);
 
     // We're going to need ModuleInfo
@@ -2583,12 +2669,7 @@
 
 static Identifier *unitTestId()
 {
-    static int n;
-    char buffer[10 + sizeof(n)*3 + 1];
-
-    sprintf(buffer,"__unittest%d", n);
-    n++;
-    return Lexer::idPool(buffer);
+    return Lexer::uniqueId("__unittest");
 }
 
 UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc)
@@ -2713,7 +2794,7 @@
     FuncDeclaration::semantic(sc);
 }
 
-char *NewDeclaration::kind()
+const char *NewDeclaration::kind()
 {
     return "allocator";
 }
@@ -2797,7 +2878,7 @@
     FuncDeclaration::semantic(sc);
 }
 
-char *DeleteDeclaration::kind()
+const char *DeleteDeclaration::kind()
 {
     return "deallocator";
 }