Mercurial > projects > ldc
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"; }