# HG changeset patch # User Tomas Lindquist Olsen # Date 1229170531 -3600 # Node ID bc982f1ad106cfc7bddd5b6e2c5583b7e0097ca7 # Parent d128381e086e419450f0e69c29ef7ba6ec481f41 Merged DMD 1.037 frontend diff -r d128381e086e -r bc982f1ad106 dmd/attrib.c --- a/dmd/attrib.c Sat Dec 13 06:48:00 2008 +0100 +++ b/dmd/attrib.c Sat Dec 13 13:15:31 2008 +0100 @@ -615,6 +615,7 @@ sc->flags = 0; aad.structalign = sc->structalign; aad.parent = ad; + for (unsigned i = 0; i < decl->dim; i++) { Dsymbol *s = (Dsymbol *)decl->data[i]; diff -r d128381e086e -r bc982f1ad106 dmd/cast.c --- a/dmd/cast.c Sat Dec 13 06:48:00 2008 +0100 +++ b/dmd/cast.c Sat Dec 13 13:15:31 2008 +0100 @@ -33,9 +33,10 @@ { //printf("implicitCastTo(%s) => %s\n", type->toChars(), t->toChars()); if (implicitConvTo(t)) - { + { TY tyfrom = type->toBasetype()->ty; + TY tyto = t->toBasetype()->ty; if (global.params.warnings && - Type::impcnvWarn[type->toBasetype()->ty][t->toBasetype()->ty] && + Type::impcnvWarn[tyfrom][tyto] && op != TOKint64) { Expression *e = optimize(WANTflags | WANTvalue); @@ -43,8 +44,24 @@ if (e->op == TOKint64) return e->implicitCastTo(sc, t); - warning("%s: implicit conversion of expression (%s) of type %s to %s can cause loss of data", - loc.toChars(), toChars(), type->toChars(), t->toChars()); + if (tyfrom == Tint32 && + (op == TOKadd || op == TOKmin || + op == TOKand || op == TOKor || op == TOKxor) + ) + { + /* This is really only a semi-kludge fix, + * we really should look at the operands of op + * and see if they are narrower types. + * For example, b=b|b and b=b|7 and s=b+b should be allowed, + * but b=b|i should be an error. + */ + ; + } + else + { + warning("%s: implicit conversion of expression (%s) of type %s to %s can cause loss of data", + loc.toChars(), toChars(), type->toChars(), t->toChars()); + } } #if DMDV2 if (match == MATCHconst && t == type->constOf()) diff -r d128381e086e -r bc982f1ad106 dmd/declaration.h --- a/dmd/declaration.h Sat Dec 13 06:48:00 2008 +0100 +++ b/dmd/declaration.h Sat Dec 13 13:15:31 2008 +0100 @@ -623,6 +623,7 @@ virtual int isNested(); int needThis(); virtual int isVirtual(); + virtual int isFinal(); virtual int addPreInvariant(); virtual int addPostInvariant(); Expression *interpret(InterState *istate, Expressions *arguments); diff -r d128381e086e -r bc982f1ad106 dmd/expression.c --- a/dmd/expression.c Sat Dec 13 06:48:00 2008 +0100 +++ b/dmd/expression.c Sat Dec 13 13:15:31 2008 +0100 @@ -5067,10 +5067,14 @@ if (eright->op == TOKimport) // also used for template alias's { - Dsymbol *s; ScopeExp *ie = (ScopeExp *)eright; - s = ie->sds->search(loc, ident, 0); + /* Disable access to another module's private imports. + * The check for 'is sds our current module' is because + * the current module should have access to its own imports. + */ + Dsymbol *s = ie->sds->search(loc, ident, + (ie->sds->isModule() && ie->sds != sc->module) ? 1 : 0); if (s) { s = s->toAlias(); diff -r d128381e086e -r bc982f1ad106 dmd/func.c --- a/dmd/func.c Sat Dec 13 06:48:00 2008 +0100 +++ b/dmd/func.c Sat Dec 13 13:15:31 2008 +0100 @@ -1965,6 +1965,23 @@ toParent()->isClassDeclaration(); } +int FuncDeclaration::isFinal() +{ + ClassDeclaration *cd; +#if 0 + printf("FuncDeclaration::isFinal(%s)\n", toChars()); + printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd); + printf("result is %d\n", + isMember() && + !(isStatic() || protection == PROTprivate || protection == PROTpackage) && + (cd = toParent()->isClassDeclaration()) != NULL && + cd->storage_class & STCfinal); +#endif + return isMember() && + (Declaration::isFinal() || + ((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal)); +} + int FuncDeclaration::isAbstract() { return storage_class & STCabstract; @@ -2708,10 +2725,11 @@ { if (global.params.useUnitTests) { - Type *tret; - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); - FuncDeclaration::semantic(sc); + Scope *sc2 = sc->push(); + sc2->linkage = LINKd; + FuncDeclaration::semantic(sc2); + sc2->pop(); } // We're going to need ModuleInfo even if the unit tests are not diff -r d128381e086e -r bc982f1ad106 dmd/import.c --- a/dmd/import.c Sat Dec 13 06:48:00 2008 +0100 +++ b/dmd/import.c Sat Dec 13 13:15:31 2008 +0100 @@ -1,275 +1,262 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include - -#include "root.h" -#include "dsymbol.h" -#include "import.h" -#include "identifier.h" -#include "module.h" -#include "scope.h" -#include "hdrgen.h" -#include "mtype.h" -#include "declaration.h" -#include "id.h" - -/********************************* Import ****************************/ - -Import::Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId, - int isstatic) - : Dsymbol(id) -{ - this->loc = loc; - this->packages = packages; - this->id = id; - this->aliasId = aliasId; - this->isstatic = isstatic; - protection = PROTundefined; - pkg = NULL; - mod = NULL; - - if (aliasId) - this->ident = aliasId; - // Kludge to change Import identifier to first package - else if (packages && packages->dim) - this->ident = (Identifier *)packages->data[0]; -} - -void Import::addAlias(Identifier *name, Identifier *alias) -{ - if (isstatic) - error("cannot have an import bind list"); - - if (!aliasId) - this->ident = NULL; // make it an anonymous import - - names.push(name); - aliases.push(alias); -} - -const char *Import::kind() -{ - return isstatic ? (char *)"static import" : (char *)"import"; -} - -enum PROT Import::prot() -{ - return protection; -} - -Dsymbol *Import::syntaxCopy(Dsymbol *s) -{ - assert(!s); - - Import *si; - - si = new Import(loc, packages, id, aliasId, isstatic); - - for (size_t i = 0; i < names.dim; i++) - { - si->addAlias((Identifier *)names.data[i], (Identifier *)aliases.data[i]); - } - - return si; -} - -void Import::load(Scope *sc) -{ - DsymbolTable *dst; - Dsymbol *s; - - //printf("Import::load('%s')\n", toChars()); - - // See if existing module - dst = Package::resolve(packages, NULL, &pkg); - - s = dst->lookup(id); - if (s) - { - if (s->isModule()) - mod = (Module *)s; - else - error("package and module have the same name"); - } - - if (!mod) - { - // Load module - mod = Module::load(loc, packages, id); - dst->insert(id, mod); // id may be different from mod->ident, - // if so then insert alias - if (!mod->importedFrom) - mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule; - } - if (!pkg) - pkg = mod; - mod->semantic(); - - //printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg); -} - - -void Import::semantic(Scope *sc) -{ - //printf("Import::semantic('%s')\n", toChars()); - - load(sc); - - if (mod) - { -#if 0 - if (mod->loc.linnum != 0) - { /* If the line number is not 0, then this is not - * a 'root' module, i.e. it was not specified on the command line. - */ - mod->importedFrom = sc->module->importedFrom; - assert(mod->importedFrom); - } -#endif - - /* Default to private importing - */ - protection = sc->protection; - if (!sc->explicitProtection) - protection = PROTprivate; - - if (!isstatic && !aliasId && !names.dim) - { - sc->scopesym->importScope(mod, protection); - } - - // Modules need a list of each imported module - sc->module->aimports.push(mod); - - if (mod->needmoduleinfo) - sc->module->needmoduleinfo = 1; - - sc = sc->push(mod); - for (size_t i = 0; i < aliasdecls.dim; i++) - { AliasDeclaration *ad = (AliasDeclaration *)aliasdecls.data[i]; - - //printf("\tImport alias semantic('%s')\n", s->toChars()); - if (!mod->search(loc, (Identifier *)names.data[i], 0)) - error("%s not found", ((Identifier *)names.data[i])->toChars()); - - ad->semantic(sc); - ad->protection = protection; - } - sc = sc->pop(); - } - //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg); -} - -void Import::semantic2(Scope *sc) -{ - //printf("Import::semantic2('%s')\n", toChars()); - mod->semantic2(); - if (mod->needmoduleinfo) - sc->module->needmoduleinfo = 1; -} - -Dsymbol *Import::toAlias() -{ - if (aliasId) - return mod; - return this; -} - -int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) -{ - int result = 0; - - if (names.dim == 0) - return Dsymbol::addMember(sc, sd, memnum); - - if (aliasId) - result = Dsymbol::addMember(sc, sd, memnum); - - for (size_t i = 0; i < names.dim; i++) - { - Identifier *name = (Identifier *)names.data[i]; - Identifier *alias = (Identifier *)aliases.data[i]; - - if (!alias) - alias = name; - -#if 1 - TypeIdentifier *tname = new TypeIdentifier(loc, name); -#else - TypeIdentifier *tname = new TypeIdentifier(loc, NULL); - if (packages) - { - for (size_t j = 0; j < packages->dim; j++) - { Identifier *pid = (Identifier *)packages->data[j]; - - if (!tname->ident) - tname->ident = pid; - else - tname->addIdent(pid); - } - } - if (!tname->ident) - tname->ident = id; - else - tname->addIdent(id); - tname->addIdent(name); -#endif - AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname); - result |= ad->addMember(sc, sd, memnum); - - aliasdecls.push(ad); - } - - return result; -} - -Dsymbol *Import::search(Loc loc, Identifier *ident, int flags) -{ - //printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags); - - if (!pkg) - load(NULL); - - // Forward it to the package/module - return pkg->search(loc, ident, flags); -} - -int Import::overloadInsert(Dsymbol *s) -{ - // Allow multiple imports of the same name - return s->isImport() != NULL; -} - -void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ - if (hgs->hdrgen && id == Id::object) - return; // object is imported by default - - if (isstatic) - buf->writestring("static "); - buf->writestring("import "); - if (aliasId) - { - buf->printf("%s = ", aliasId->toChars()); - } - if (packages && packages->dim) - { - for (size_t i = 0; i < packages->dim; i++) - { Identifier *pid = (Identifier *)packages->data[i]; - - buf->printf("%s.", pid->toChars()); - } - } - buf->printf("%s;", id->toChars()); - buf->writenl(); -} - + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2006 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// http://www.digitalmars.com +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. + +#include +#include + +#include "root.h" +#include "dsymbol.h" +#include "import.h" +#include "identifier.h" +#include "module.h" +#include "scope.h" +#include "hdrgen.h" +#include "mtype.h" +#include "declaration.h" +#include "id.h" + +/********************************* Import ****************************/ + +Import::Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId, + int isstatic) + : Dsymbol(id) +{ + this->loc = loc; + this->packages = packages; + this->id = id; + this->aliasId = aliasId; + this->isstatic = isstatic; + protection = PROTundefined; + pkg = NULL; + mod = NULL; + + if (aliasId) + this->ident = aliasId; + // Kludge to change Import identifier to first package + else if (packages && packages->dim) + this->ident = (Identifier *)packages->data[0]; +} + +void Import::addAlias(Identifier *name, Identifier *alias) +{ + if (isstatic) + error("cannot have an import bind list"); + + if (!aliasId) + this->ident = NULL; // make it an anonymous import + + names.push(name); + aliases.push(alias); +} + +const char *Import::kind() +{ + return isstatic ? (char *)"static import" : (char *)"import"; +} + +enum PROT Import::prot() +{ + return protection; +} + +Dsymbol *Import::syntaxCopy(Dsymbol *s) +{ + assert(!s); + + Import *si; + + si = new Import(loc, packages, id, aliasId, isstatic); + + for (size_t i = 0; i < names.dim; i++) + { + si->addAlias((Identifier *)names.data[i], (Identifier *)aliases.data[i]); + } + + return si; +} + +void Import::load(Scope *sc) +{ + DsymbolTable *dst; + Dsymbol *s; + + //printf("Import::load('%s')\n", toChars()); + + // See if existing module + dst = Package::resolve(packages, NULL, &pkg); + + s = dst->lookup(id); + if (s) + { + if (s->isModule()) + mod = (Module *)s; + else + error("package and module have the same name"); + } + + if (!mod) + { + // Load module + mod = Module::load(loc, packages, id); + dst->insert(id, mod); // id may be different from mod->ident, + // if so then insert alias + if (!mod->importedFrom) + mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule; + } + if (!pkg) + pkg = mod; + mod->semantic(); + + //printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg); +} + + +void Import::semantic(Scope *sc) +{ + //printf("Import::semantic('%s')\n", toChars()); + + load(sc); + + if (mod) + { +#if 0 + if (mod->loc.linnum != 0) + { /* If the line number is not 0, then this is not + * a 'root' module, i.e. it was not specified on the command line. + */ + mod->importedFrom = sc->module->importedFrom; + assert(mod->importedFrom); + } +#endif + + /* Default to private importing + */ + protection = sc->protection; + if (!sc->explicitProtection) + protection = PROTprivate; + + if (!isstatic && !aliasId && !names.dim) + { + sc->scopesym->importScope(mod, protection); + } + + // Modules need a list of each imported module + sc->module->aimports.push(mod); + + if (mod->needmoduleinfo) + sc->module->needmoduleinfo = 1; + + sc = sc->push(mod); + for (size_t i = 0; i < aliasdecls.dim; i++) + { AliasDeclaration *ad = (AliasDeclaration *)aliasdecls.data[i]; + + //printf("\tImport alias semantic('%s')\n", s->toChars()); + if (!mod->search(loc, (Identifier *)names.data[i], 0)) + error("%s not found", ((Identifier *)names.data[i])->toChars()); + + ad->semantic(sc); + ad->protection = protection; + } + sc = sc->pop(); + } + //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg); +} + +void Import::semantic2(Scope *sc) +{ + //printf("Import::semantic2('%s')\n", toChars()); + mod->semantic2(); + if (mod->needmoduleinfo) + sc->module->needmoduleinfo = 1; +} + +Dsymbol *Import::toAlias() +{ + if (aliasId) + return mod; + return this; +} + +/***************************** + * Add import to sd's symbol table. + */ + +int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) +{ + int result = 0; + + if (names.dim == 0) + return Dsymbol::addMember(sc, sd, memnum); + + if (aliasId) + result = Dsymbol::addMember(sc, sd, memnum); + + /* Instead of adding the import to sd's symbol table, + * add each of the alias=name pairs + */ + for (size_t i = 0; i < names.dim; i++) + { + Identifier *name = (Identifier *)names.data[i]; + Identifier *alias = (Identifier *)aliases.data[i]; + + if (!alias) + alias = name; + + TypeIdentifier *tname = new TypeIdentifier(loc, name); + AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname); + result |= ad->addMember(sc, sd, memnum); + + aliasdecls.push(ad); + } + + return result; +} + +Dsymbol *Import::search(Loc loc, Identifier *ident, int flags) +{ + //printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags); + + if (!pkg) + load(NULL); + + // Forward it to the package/module + return pkg->search(loc, ident, flags); +} + +int Import::overloadInsert(Dsymbol *s) +{ + // Allow multiple imports of the same name + return s->isImport() != NULL; +} + +void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + if (hgs->hdrgen && id == Id::object) + return; // object is imported by default + + if (isstatic) + buf->writestring("static "); + buf->writestring("import "); + if (aliasId) + { + buf->printf("%s = ", aliasId->toChars()); + } + if (packages && packages->dim) + { + for (size_t i = 0; i < packages->dim; i++) + { Identifier *pid = (Identifier *)packages->data[i]; + + buf->printf("%s.", pid->toChars()); + } + } + buf->printf("%s;", id->toChars()); + buf->writenl(); +} + diff -r d128381e086e -r bc982f1ad106 dmd/lexer.c --- a/dmd/lexer.c Sat Dec 13 06:48:00 2008 +0100 +++ b/dmd/lexer.c Sat Dec 13 13:15:31 2008 +0100 @@ -2656,10 +2656,13 @@ void Lexer::getDocComment(Token *t, unsigned lineComment) { - OutBuffer buf; + /* ct tells us which kind of comment it is: '/', '*', or '+' + */ unsigned char ct = t->ptr[2]; + + /* Start of comment text skips over / * *, / + +, or / / / + */ unsigned char *q = t->ptr + 3; // start of comment text - int linestart = 0; unsigned char *qend = p; if (ct == '*' || ct == '+') @@ -2684,6 +2687,12 @@ } } + /* Comment is now [q .. qend]. + * Canonicalize it into buf[]. + */ + OutBuffer buf; + int linestart = 0; + for (; q < qend; q++) { unsigned char c = *q; @@ -2760,11 +2769,14 @@ } /******************************************** - * Combine two document comments into one. + * Combine two document comments into one, + * separated by a newline. */ unsigned char *Lexer::combineComments(unsigned char *c1, unsigned char *c2) { + //printf("Lexer::combineComments('%s', '%s')\n", c1, c2); + unsigned char *c = c2; if (c1) @@ -2775,9 +2787,12 @@ c = (unsigned char *)mem.malloc(len1 + 1 + len2 + 1); memcpy(c, c1, len1); - c[len1] = '\n'; - memcpy(c + len1 + 1, c2, len2); - c[len1 + 1 + len2] = 0; + if (len1 && c1[len1 - 1] != '\n') + { c[len1] = '\n'; + len1++; + } + memcpy(c + len1, c2, len2); + c[len1 + len2] = 0; } } return c; @@ -2951,6 +2966,7 @@ { "__FILE__", TOKfile }, { "__LINE__", TOKline }, { "shared", TOKshared }, + { "immutable", TOKimmutable }, #endif }; diff -r d128381e086e -r bc982f1ad106 dmd/mars.c --- a/dmd/mars.c Sat Dec 13 06:48:00 2008 +0100 +++ b/dmd/mars.c Sat Dec 13 13:15:31 2008 +0100 @@ -64,7 +64,7 @@ copyright = "Copyright (c) 1999-2008 by Digital Mars and Tomas Lindquist Olsen"; written = "written by Walter Bright and Tomas Lindquist Olsen"; - version = "v1.036"; + version = "v1.037"; ldc_version = "0.1"; global.structalign = 8; diff -r d128381e086e -r bc982f1ad106 dmd/mtype.c --- a/dmd/mtype.c Sat Dec 13 06:48:00 2008 +0100 +++ b/dmd/mtype.c Sat Dec 13 13:15:31 2008 +0100 @@ -2485,7 +2485,7 @@ int TypeAArray::isZeroInit() { - return 1; + return TRUE; } int TypeAArray::checkBoolean() @@ -3994,6 +3994,12 @@ goto Lfwd; e = defaultInit(loc); } + else if (ident == Id::stringof) + { char *s = toChars(); + e = new StringExp(loc, s, strlen(s), 'c'); + Scope sc; + e = e->semantic(&sc); + } else { if (!sym->memtype) diff -r d128381e086e -r bc982f1ad106 dmd/parse.c --- a/dmd/parse.c Sat Dec 13 06:48:00 2008 +0100 +++ b/dmd/parse.c Sat Dec 13 13:15:31 2008 +0100 @@ -386,7 +386,7 @@ } ident = token.ident; nextToken(); - if (token.value == TOKcomma) + if (token.value == TOKcomma && peekNext() != TOKrparen) args = parseArguments(); // pragma(identifier, args...) else check(TOKrparen); // pragma(identifier) @@ -3068,7 +3068,7 @@ } ident = token.ident; nextToken(); - if (token.value == TOKcomma) + if (token.value == TOKcomma && peekNext() != TOKrparen) args = parseArguments(); // pragma(identifier, args...); else check(TOKrparen); // pragma(identifier); diff -r d128381e086e -r bc982f1ad106 dmd/root.c --- a/dmd/root.c Sat Dec 13 06:48:00 2008 +0100 +++ b/dmd/root.c Sat Dec 13 13:15:31 2008 +0100 @@ -16,6 +16,7 @@ #if _MSC_VER ||__MINGW32__ #include +#include #endif #if _WIN32 @@ -47,6 +48,7 @@ } #endif + /************************************* * Convert wchar string to ascii string. */ @@ -1606,6 +1608,36 @@ fill0(nbytes); } + +//////////////////////////////////////////////////////////////// +// The compiler shipped with Visual Studio 2005 (and possible +// other versions) does not support C99 printf format specfiers +// such as %z and %j +#if _MSC_VER +using std::string; +using std::wstring; + +template +inline void +search_and_replace(S& str, const S& what, const S& replacement) +{ + assert(!what.empty()); + size_t pos = str.find(what); + while (pos != S::npos) + { + str.replace(pos, what.size(), replacement); + pos = str.find(what, pos + replacement.size()); + } +} +#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \ + S tmp = f; \ + search_and_replace(fmt, S("%z"), S("%l")); \ + search_and_replace(fmt, S("%j"), S("%i")); \ + f = tmp.c_str(); +#else +#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) +#endif + void OutBuffer::vprintf(const char *format, va_list args) { char buffer[128]; @@ -1613,10 +1645,7 @@ unsigned psize; int count; - // On some platforms (i.e. x86_64) va_list is an array and thus passed by - // reference. Copy the input list so we can copy it back before retrying. - va_list orig_args; - va_copy(orig_args, args); + WORKAROUND_C99_SPECIFIERS_BUG(string, fmt, format); p = buffer; psize = sizeof(buffer); @@ -1628,7 +1657,19 @@ break; psize *= 2; #elif POSIX - count = vsnprintf(p,psize,format,args); + va_list va; + va_copy(va, args); +/* + The functions vprintf(), vfprintf(), vsprintf(), vsnprintf() + are equivalent to the functions printf(), fprintf(), sprintf(), + snprintf(), respectively, except that they are called with a + va_list instead of a variable number of arguments. These + functions do not call the va_end macro. Consequently, the value + of ap is undefined after the call. The application should call + va_end(ap) itself afterwards. + */ + count = vsnprintf(p,psize,format,va); + va_end(va); if (count == -1) psize *= 2; else if (count >= psize) @@ -1636,7 +1677,6 @@ else break; #endif - va_copy(args, orig_args); p = (char *) alloca(psize); // buffer too small, try again with larger size } write(p,count); @@ -1650,6 +1690,8 @@ unsigned psize; int count; + WORKAROUND_C99_SPECIFIERS_BUG(wstring, fmt, format); + p = buffer; psize = sizeof(buffer) / sizeof(buffer[0]); for (;;) @@ -1661,7 +1703,11 @@ psize *= 2; #endif #if POSIX - count = vsnwprintf(p,psize,format,args); + va_list va; + va_copy(va, args); + count = vsnwprintf(p,psize,format,va); + va_end(va); + if (count == -1) psize *= 2; else if (count >= psize) diff -r d128381e086e -r bc982f1ad106 dmd/statement.c --- a/dmd/statement.c Sat Dec 13 06:48:00 2008 +0100 +++ b/dmd/statement.c Sat Dec 13 13:15:31 2008 +0100 @@ -26,6 +26,7 @@ #include "id.h" #include "hdrgen.h" #include "parse.h" +#include "template.h" /******************************** Statement ***************************/ @@ -451,10 +452,7 @@ body = new CompoundStatement(0, a); body = new ScopeStatement(0, body); - static int num; - char name[3 + sizeof(num) * 3 + 1]; - sprintf(name, "__o%d", ++num); - Identifier *id = Lexer::idPool(name); + Identifier *id = Lexer::uniqueId("__o"); Statement *handler = new ThrowStatement(0, new IdentifierExp(0, id)); handler = new CompoundStatement(0, sexception, handler); @@ -1107,12 +1105,17 @@ // Use a default value condition = new IntegerExp(loc, 1, Type::tboolean); sc->noctor++; - condition = condition->semantic(sc); - condition = resolveProperties(sc, condition); - condition = condition->optimize(WANTvalue); - condition = condition->checkToBoolean(); + if (condition) + { + condition = condition->semantic(sc); + condition = resolveProperties(sc, condition); + condition = condition->optimize(WANTvalue); + condition = condition->checkToBoolean(); + } if (increment) - increment = increment->semantic(sc); + { increment = increment->semantic(sc); + increment = resolveProperties(sc, increment); + } sc->sbreak = this; sc->scontinue = this; @@ -1257,8 +1260,7 @@ //printf("ForeachStatement::semantic() %p\n", this); ScopeDsymbol *sym; Statement *s = this; - int dim = arguments->dim; - int i; + size_t dim = arguments->dim; TypeAArray *taa = NULL; Type *tn = NULL; @@ -1272,6 +1274,7 @@ aggr = aggr->semantic(sc); aggr = resolveProperties(sc, aggr); + aggr = aggr->optimize(WANTvalue); if (!aggr->type) { error("invalid foreach aggregate %s", aggr->toChars()); @@ -1387,7 +1390,7 @@ return s; } - for (i = 0; i < dim; i++) + for (size_t i = 0; i < dim; i++) { Argument *arg = (Argument *)arguments->data[i]; if (!arg->type) { @@ -1419,7 +1422,7 @@ if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar) { Argument *arg; - i = (dim == 1) ? 0 : 1; // index of value + int i = (dim == 1) ? 0 : 1; // index of value arg = (Argument *)arguments->data[i]; arg->type = arg->type->semantic(loc, sc); tnv = arg->type->toBasetype(); @@ -1437,7 +1440,7 @@ } } - for (i = 0; i < dim; i++) + for (size_t i = 0; i < dim; i++) { // Declare args Argument *arg = (Argument *)arguments->data[i]; VarDeclaration *var; @@ -1468,7 +1471,8 @@ if (aggr->op == TOKstring) aggr = aggr->implicitCastTo(sc, value->type->arrayOf()); else - error("foreach: %s is not an array of %s", tab->toChars(), value->type->toChars()); + error("foreach: %s is not an array of %s", + tab->toChars(), value->type->toChars()); } if (key) @@ -1505,6 +1509,72 @@ case Tclass: case Tstruct: +#if DMDV2 + { /* Look for range iteration, i.e. the properties + * .empty, .next, .retreat, .head and .rear + * foreach (e; range) { ... } + * translates to: + * for (auto __r = range; !__r.empty; __r.next) + * { auto e = __r.head; + * ... + * } + */ + if (dim != 1) // only one argument allowed with ranges + goto Lapply; + AggregateDeclaration *ad = (tab->ty == Tclass) + ? (AggregateDeclaration *)((TypeClass *)tab)->sym + : (AggregateDeclaration *)((TypeStruct *)tab)->sym; + Identifier *idhead; + Identifier *idnext; + if (op == TOKforeach) + { idhead = Id::Fhead; + idnext = Id::Fnext; + } + else + { idhead = Id::Frear; + idnext = Id::Fretreat; + } + Dsymbol *shead = search_function(ad, idhead); + if (!shead) + goto Lapply; + + /* Generate a temporary __r and initialize it with the aggregate. + */ + Identifier *id = Identifier::generateId("__r"); + VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, aggr)); + r->semantic(sc); + Statement *init = new DeclarationStatement(loc, r); + + // !__r.empty + Expression *e = new VarExp(loc, r); + e = new DotIdExp(loc, e, Id::Fempty); + Expression *condition = new NotExp(loc, e); + + // __r.next + e = new VarExp(loc, r); + Expression *increment = new DotIdExp(loc, e, idnext); + + /* Declaration statement for e: + * auto e = __r.idhead; + */ + e = new VarExp(loc, r); + Expression *einit = new DotIdExp(loc, e, idhead); + einit = einit->semantic(sc); + Argument *arg = (Argument *)arguments->data[0]; + VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit)); + ve->storage_class |= STCforeach; + ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCconst | STCinvariant); + + DeclarationExp *de = new DeclarationExp(loc, ve); + + Statement *body = new CompoundStatement(loc, + new DeclarationStatement(loc, de), this->body); + + s = new ForStatement(loc, init, condition, increment, body); + s = s->semantic(sc); + break; + } +#endif case Tdelegate: Lapply: { FuncDeclaration *fdapply; @@ -1540,7 +1610,7 @@ * int delegate(ref T arg) { body } */ args = new Arguments(); - for (i = 0; i < dim; i++) + for (size_t i = 0; i < dim; i++) { Argument *arg = (Argument *)arguments->data[i]; arg->type = arg->type->semantic(loc, sc); @@ -1551,10 +1621,8 @@ // a reference. VarDeclaration *v; Initializer *ie; - char applyArg[10 + sizeof(i)*3 + 1]; - - sprintf(applyArg, "__applyArg%d", i); - id = Lexer::idPool(applyArg); + + id = Lexer::uniqueId("__applyArg", i); ie = new ExpInitializer(0, new IdentifierExp(0, id)); v = new VarDeclaration(0, arg->type, arg->ident, ie); @@ -2145,6 +2213,11 @@ } else if (ident == Id::lib) { +#if 1 + /* Should this be allowed? + */ + error("pragma(lib) not allowed as statement"); +#else if (!args || args->dim != 1) error("string expected for library name"); else @@ -2166,6 +2239,7 @@ mem.free(name); } } +#endif } else error("unrecognized pragma(%s)", ident->toChars()); @@ -2454,8 +2528,7 @@ //printf("CaseStatement::semantic() %s\n", toChars()); exp = exp->semantic(sc); if (sw) - { int i; - + { exp = exp->implicitCastTo(sc, sw->condition->type); exp = exp->optimize(WANTvalue | WANTinterpret); if (exp->op != TOKstring && exp->op != TOKint64) @@ -2464,7 +2537,7 @@ exp = new IntegerExp(0); } - for (i = 0; i < sw->cases->dim; i++) + for (int i = 0; i < sw->cases->dim; i++) { CaseStatement *cs = (CaseStatement *)sw->cases->data[i]; @@ -2478,7 +2551,7 @@ sw->cases->push(this); // Resolve any goto case's with no exp to this case statement - for (i = 0; i < sw->gotoCases.dim; i++) + for (size_t i = 0; i < sw->gotoCases.dim; i++) { GotoCaseStatement *gcs = (GotoCaseStatement *)sw->gotoCases.data[i]; @@ -2875,32 +2948,25 @@ exp->op == TOKstring) { sc->fes->cases.push(this); + // Construct: return cases.dim+1; s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); } else if (fd->type->nextOf()->toBasetype() == Type::tvoid) { - Statement *s1; - Statement *s2; - s = new ReturnStatement(0, NULL); sc->fes->cases.push(s); // Construct: { exp; return cases.dim + 1; } - s1 = new ExpStatement(loc, exp); - s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); + Statement *s1 = new ExpStatement(loc, exp); + Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); s = new CompoundStatement(loc, s1, s2); } else { - VarExp *v; - Statement *s1; - Statement *s2; - // Construct: return vresult; if (!fd->vresult) - { VarDeclaration *v; - - v = new VarDeclaration(loc, tret, Id::result, NULL); + { // Declare vresult + VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL); v->noauto = 1; v->semantic(scx); if (!scx->insert(v)) @@ -2909,16 +2975,14 @@ fd->vresult = v; } - v = new VarExp(0, fd->vresult); - s = new ReturnStatement(0, v); + s = new ReturnStatement(0, new VarExp(0, fd->vresult)); sc->fes->cases.push(s); // Construct: { vresult = exp; return cases.dim + 1; } - v = new VarExp(0, fd->vresult); - exp = new AssignExp(loc, v, exp); + exp = new AssignExp(loc, new VarExp(0, fd->vresult), exp); exp = exp->semantic(sc); - s1 = new ExpStatement(loc, exp); - s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); + Statement *s1 = new ExpStatement(loc, exp); + Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); s = new CompoundStatement(loc, s1, s2); } return s; @@ -2959,9 +3023,10 @@ gs->label = fd->returnLabel; if (exp) - { Statement *s; - - s = new ExpStatement(0, exp); + { /* Replace: return exp; + * with: exp; goto returnLabel; + */ + Statement *s = new ExpStatement(0, exp); return new CompoundStatement(loc, s, gs); } return gs; @@ -3739,10 +3804,7 @@ * sexception: x = 1; * sfinally: if (!x) statement; */ - static int num; - char name[5 + sizeof(num) * 3 + 1]; - sprintf(name, "__osf%d", ++num); - Identifier *id = Lexer::idPool(name); + Identifier *id = Lexer::uniqueId("__os"); ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(0)); VarDeclaration *v = new VarDeclaration(loc, Type::tint32, id, ie);