Mercurial > projects > ldc
changeset 1640:9bf06e02070b
Merge DMD 1.057.
author | Christian Kamm <kamm incasoftware de> |
---|---|
date | Mon, 08 Mar 2010 21:39:20 +0100 |
parents | 41145d30acb8 |
children | 00cd99bedf06 |
files | dmd/dsymbol.c dmd/dsymbol.h dmd/expression.c dmd/func.c dmd/inline.c dmd/interpret.c dmd/mars.c dmd/mars.h dmd/module.c dmd/module.h dmd/mtype.c dmd/root/root.c dmd/root/root.h dmd/scope.c dmd/scope.h dmd/statement.c dmd/template.c |
diffstat | 17 files changed, 349 insertions(+), 82 deletions(-) [+] |
line wrap: on
line diff
--- a/dmd/dsymbol.c Mon Mar 08 20:09:18 2010 +0100 +++ b/dmd/dsymbol.c Mon Mar 08 21:39:20 2010 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -13,6 +13,7 @@ #include <assert.h> #include "rmem.h" +#include "speller.h" #include "mars.h" #include "dsymbol.h" @@ -347,6 +348,27 @@ return NULL; } +/*************************************************** + * Search for symbol with correct spelling. + */ + +void *symbol_search_fp(void *arg, const char *seed) +{ + Dsymbol *s = (Dsymbol *)arg; + Identifier id(seed, 0); + Module::clearCache(); + s = s->search(0, &id, 4|2); + return s; +} + +Dsymbol *Dsymbol::search_correct(Identifier *ident) +{ + if (global.gag) + return NULL; // don't do it for speculative compiles; too time consuming + + return (Dsymbol *)speller(ident->toChars(), &symbol_search_fp, this, idchars); +} + /*************************************** * Search for identifier id as a member of 'this'. * id may be a template instance.
--- a/dmd/dsymbol.h Mon Mar 08 20:09:18 2010 +0100 +++ b/dmd/dsymbol.h Mon Mar 08 21:39:20 2010 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -167,6 +167,7 @@ virtual void semantic3(Scope *sc); virtual void inlineScan(); virtual Dsymbol *search(Loc loc, Identifier *ident, int flags); + Dsymbol *search_correct(Identifier *id); Dsymbol *searchX(Loc loc, Scope *sc, Identifier *id); virtual int overloadInsert(Dsymbol *s); #ifdef _DH
--- a/dmd/expression.c Mon Mar 08 20:09:18 2010 +0100 +++ b/dmd/expression.c Mon Mar 08 21:39:20 2010 +0100 @@ -55,6 +55,7 @@ #include "hdrgen.h" #include "parse.h" + Expression *expandVar(int result, VarDeclaration *v); #define LOGSEMANTIC 0 @@ -1059,13 +1060,10 @@ void Expression::warning(const char *format, ...) { - if (global.params.warnings && !global.gag) - { - va_list ap; - va_start(ap, format); - ::vwarning(loc, format, ap); - va_end( ap ); - } + va_list ap; + va_start(ap, format); + ::vwarning(loc, format, ap); + va_end( ap ); } void Expression::rvalue() @@ -1076,7 +1074,7 @@ dump(0); halt(); #endif - type = Type::tint32; + type = Type::terror; } } @@ -1138,6 +1136,9 @@ void Expression::toMangleBuffer(OutBuffer *buf) { error("expression %s is not a valid template value argument", toChars()); +#ifdef DEBUG +dump(0); +#endif } /*************************************** @@ -1666,7 +1667,18 @@ if ((sinteger_t)value < 0) buf->printf("N%jd", -value); else + { + /* This is an awful hack to maintain backwards compatibility. + * There really always should be an 'i' before a number, but + * there wasn't in earlier implementations, so to maintain + * backwards compatibility it is only done if necessary to disambiguate. + * See bugzilla 3029 + */ + if (buf->offset > 0 && isdigit(buf->data[buf->offset - 1])) + buf->writeByte('i'); + buf->printf("%jd", value); + } } /******************************** ErrorExp **************************/ @@ -2103,7 +2115,21 @@ } return e->semantic(sc); } - error("undefined identifier %s", ident->toChars()); +#if DMDV2 + if (ident == Id::ctfe) + { // Create the magic __ctfe bool variable + VarDeclaration *vd = new VarDeclaration(loc, Type::tbool, Id::ctfe, NULL); + Expression *e = new VarExp(loc, vd); + e = e->semantic(sc); + return e; + } +#endif + + s = sc->search_correct(ident); + if (s) + error("undefined identifier %s, did you mean %s %s?", ident->toChars(), s->kind(), s->toChars()); + else + error("undefined identifier %s", ident->toChars()); type = Type::terror; return this; } @@ -5275,14 +5301,14 @@ goto Lerror; } - if (name != FileName::name(name)) - { error("use -Jpath switch to provide path for filename %s", name); - goto Lerror; - } - - name = FileName::searchPath(global.filePath, name, 0); + /* Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory + * ('Path Traversal') attacks. + * http://cwe.mitre.org/data/definitions/22.html + */ + + name = FileName::safeSearchPath(global.filePath, name); if (!name) - { error("file %s cannot be found, check -Jpath", se->toChars()); + { error("file %s cannot be found or not in a path specified with -J", se->toChars()); goto Lerror; } @@ -5820,6 +5846,14 @@ e = e->semantic(sc); return e; } + if (v->init) + { Expression *e = v->init->toExpression(); + if (e) + { e = e->copy(); + e = e->semantic(sc); + return e; + } + } } } } @@ -5941,11 +5975,15 @@ e = e->semantic(sc); if (e->op == TOKdottd) { + if (global.errors) + return new ErrorExp(); // TemplateInstance::semantic() will fail anyway DotTemplateExp *dte = (DotTemplateExp *)e; TemplateDeclaration *td = dte->td; eleft = dte->e1; ti->tempdecl = td; ti->semantic(sc); + if (!ti->inst) // if template failed to expand + return new ErrorExp(); Dsymbol *s = ti->inst->toAlias(); Declaration *v = s->isDeclaration(); if (v) @@ -7377,6 +7415,12 @@ } } } + + if (!e1->type) + { error("cannot cast %s", e1->toChars()); + return new ErrorExp(); + } + e = e1->castTo(sc, to); return e; }
--- a/dmd/func.c Mon Mar 08 20:09:18 2010 +0100 +++ b/dmd/func.c Mon Mar 08 21:39:20 2010 +0100 @@ -640,15 +640,15 @@ fdrequire = fd; } + if (!outId && f->nextOf()->toBasetype()->ty != Tvoid) + outId = Id::result; // provide a default + if (fensure) { /* out (result) { ... } * becomes: * tret __ensure(ref tret result) { ... } * __ensure(result); */ - if (!outId && f->nextOf()->toBasetype()->ty != Tvoid) - outId = Id::result; // provide a default - Loc loc = fensure->loc; Parameters *arguments = new Parameters(); Parameter *a = NULL; @@ -772,14 +772,14 @@ if (ad) { VarDeclaration *v; - if (isFuncLiteralDeclaration() && isNested()) + if (isFuncLiteralDeclaration() && isNested() && !sc->intypeof) { - error("literals cannot be class members"); + error("function literals cannot be class members"); return; } else { - assert(!isNested()); // can't be both member and nested + assert(!isNested() || sc->intypeof); // can't be both member and nested assert(ad->handle); v = new ThisDeclaration(loc, ad->handle); v->storage_class |= STCparameter | STCin; @@ -2628,15 +2628,9 @@ void FuncLiteralDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { - static Identifier *idfunc; - static Identifier *iddel; - - if (!idfunc) - idfunc = new Identifier("function", 0); - if (!iddel) - iddel = new Identifier("delegate", 0); - - type->toCBuffer(buf, ((tok == TOKdelegate) ? iddel : idfunc), hgs); + buf->writestring(kind()); + buf->writeByte(' '); + type->toCBuffer(buf, NULL, hgs); bodyToCBuffer(buf, hgs); }
--- a/dmd/inline.c Mon Mar 08 20:09:18 2010 +0100 +++ b/dmd/inline.c Mon Mar 08 21:39:20 2010 +0100 @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -292,6 +292,11 @@ int CallExp::inlineCost(InlineCostState *ics) { + // Bugzilla 3500: super.func() calls must be devirtualized, and the inliner + // can't handle that at present. + if (e1->op == TOKdotvar && ((DotVarExp *)e1)->e1->op == TOKsuper) + return COST_MAX; + return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments); }
--- a/dmd/interpret.c Mon Mar 08 20:09:18 2010 +0100 +++ b/dmd/interpret.c Mon Mar 08 21:39:20 2010 +0100 @@ -115,7 +115,8 @@ assert(tb->ty == Tfunction); TypeFunction *tf = (TypeFunction *)tb; Type *tret = tf->next->toBasetype(); - if (tf->varargs && arguments && parameters && arguments->dim != parameters->dim) + if (tf->varargs && arguments && + ((parameters && arguments->dim != parameters->dim) || (!parameters && arguments->dim))) { cantInterpret = 1; error("C-style variadic functions are not yet implemented in CTFE"); return NULL;
--- a/dmd/mars.c Mon Mar 08 20:09:18 2010 +0100 +++ b/dmd/mars.c Mon Mar 08 21:39:20 2010 +0100 @@ -61,9 +61,9 @@ obj_ext_alt = "obj"; #endif - copyright = "Copyright (c) 1999-2009 by Digital Mars and Tomas Lindquist Olsen"; + copyright = "Copyright (c) 1999-2010 by Digital Mars and Tomas Lindquist Olsen"; written = "written by Walter Bright and Tomas Lindquist Olsen"; - version = "v1.056"; + version = "v1.057"; ldc_version = LDC_REV; llvm_version = LLVM_REV_STR; global.structalign = 8; @@ -116,13 +116,10 @@ void warning(Loc loc, const char *format, ...) { - if (global.params.warnings && !global.gag) - { - va_list ap; - va_start(ap, format); - vwarning(loc, format, ap); - va_end( ap ); - } + va_list ap; + va_start(ap, format); + vwarning(loc, format, ap); + va_end( ap ); } void verror(Loc loc, const char *format, va_list ap) @@ -147,16 +144,26 @@ { if (global.params.warnings && !global.gag) { - char *p = loc.toChars(); + char *p = loc.toChars(); + + if (*p) + fprintf(stdmsg, "%s: ", p); + mem.free(p); - if (*p) - fprintf(stdmsg, "%s: ", p); - mem.free(p); - - fprintf(stdmsg, "Warning: "); - vfprintf(stdmsg, format, ap); - fprintf(stdmsg, "\n"); - fflush(stdmsg); + fprintf(stdmsg, "Warning: "); +#if _MSC_VER + // MS doesn't recognize %zu format + OutBuffer tmp; + tmp.vprintf(format, ap); + fprintf(stdmsg, "%s", tmp.toChars()); +#else + vfprintf(stdmsg, format, ap); +#endif + fprintf(stdmsg, "\n"); + fflush(stdmsg); +//halt(); + if (global.params.warnings == 1) + global.warnings++; // warnings don't count if gagged } } @@ -184,6 +191,7 @@ #endif } + /*********************************** * Parse and append contents of environment variable envvar * to argc and argv[].
--- a/dmd/mars.h Mon Mar 08 20:09:18 2010 +0100 +++ b/dmd/mars.h Mon Mar 08 21:39:20 2010 +0100 @@ -94,6 +94,7 @@ #define STRUCTTHISREF DMDV2 // if 'this' for struct is a reference, not a pointer #define SNAN_DEFAULT_INIT DMDV2 // if floats are default initialized to signalling NaN #define SARRAYVALUE DMDV2 // static arrays are value types +#define MODULEINFO_IS_STRUCT DMDV2 // if ModuleInfo is a struct rather than a class // Set if C++ mangling is done by the front end #define CPP_MANGLE (DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS)) @@ -182,6 +183,8 @@ bool useInline; // inline expand functions bool warnings; // enable warnings ubyte Dversion; // D version number + // 1: warnings as errors + // 2: informational warnings (no errors) char safe; // enforce safe memory model char *argv0; // program name @@ -283,7 +286,8 @@ Param params; unsigned errors; // number of errors reported so far - unsigned gag; // !=0 means gag reporting of errors + unsigned warnings; // number of warnings reported so far + unsigned gag; // !=0 means gag reporting of errors & warnings Global(); }; @@ -426,10 +430,9 @@ void warning(Loc loc, const char *format, ...) IS_PRINTF(2); -void vwarning(Loc loc, const char *format, va_list); void error(Loc loc, const char *format, ...) IS_PRINTF(2); void verror(Loc loc, const char *format, va_list); - +void vwarning(Loc loc, const char *format, va_list); #ifdef __GNUC__ __attribute__((noreturn)) #endif
--- a/dmd/module.c Mon Mar 08 20:09:18 2010 +0100 +++ b/dmd/module.c Mon Mar 08 21:39:20 2010 +0100 @@ -905,6 +905,7 @@ int Module::needModuleInfo() { + //printf("needModuleInfo() %s, %d, %d\n", toChars(), needmoduleinfo, global.params.cov); return needmoduleinfo; } @@ -943,6 +944,13 @@ return Package::symtabInsert(s); } +void Module::clearCache() +{ + for (int i = 0; i < amodules.dim; i++) + { Module *m = (Module *)amodules.data[i]; + m->searchCacheIdent = NULL; + } +} /******************************************* * Can't run semantic on s now, try again later.
--- a/dmd/module.h Mon Mar 08 20:09:18 2010 +0100 +++ b/dmd/module.h Mon Mar 08 21:39:20 2010 +0100 @@ -154,6 +154,7 @@ void deleteObjFile(); void addDeferredSemantic(Dsymbol *s); static void runDeferredSemantic(); + static void clearCache(); int imports(Module *m); // Back end
--- a/dmd/mtype.c Mon Mar 08 20:09:18 2010 +0100 +++ b/dmd/mtype.c Mon Mar 08 21:39:20 2010 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -135,6 +135,10 @@ #if DMDV2 this->cto = NULL; this->ito = NULL; + this->sto = NULL; + this->scto = NULL; + this->wto = NULL; + this->swto = NULL; #endif this->pto = NULL; this->rto = NULL; @@ -641,7 +645,7 @@ else if (ident == Id::size) { error(loc, ".size property should be replaced with .sizeof"); - e = new IntegerExp(loc, size(loc), Type::tsize_t); + e = new ErrorExp(); } else if (ident == Id::alignof) { @@ -679,8 +683,16 @@ } else { - error(loc, "no property '%s' for type '%s'", ident->toChars(), toChars()); - e = new IntegerExp(loc, 1, Type::tint32); + Dsymbol *s = NULL; + if (ty == Tstruct || ty == Tclass || ty == Tenum || ty == Ttypedef) + s = toDsymbol(NULL); + if (s) + s = s->search_correct(ident); + if (s) + error(loc, "no property '%s' for type '%s', did you mean '%s'?", ident->toChars(), toChars(), s->toChars()); + else + error(loc, "no property '%s' for type '%s'", ident->toChars(), toChars()); + e = new ErrorExp(); } return e; } @@ -785,13 +797,10 @@ void Type::warning(Loc loc, const char *format, ...) { - if (global.params.warnings && !global.gag) - { - va_list ap; - va_start(ap, format); - ::vwarning(loc, format, ap); - va_end( ap ); - } + va_list ap; + va_start(ap, format); + ::vwarning(loc, format, ap); + va_end( ap ); } Identifier *Type::getTypeInfoIdent(int internal) @@ -4630,7 +4639,11 @@ TemplateInstance *ti = s->isTemplateInstance(); if (ti) { if (!ti->semanticRun) + { + if (global.errors) + return new ErrorExp(); // TemplateInstance::semantic() will fail anyway ti->semantic(sc); + } s = ti->inst->toAlias(); if (!s->isTemplateInstance()) goto L1; @@ -5071,7 +5084,11 @@ TemplateInstance *ti = s->isTemplateInstance(); if (ti) { if (!ti->semanticRun) + { + if (global.errors) + return new ErrorExp(); // TemplateInstance::semantic() will fail anyway ti->semantic(sc); + } s = ti->inst->toAlias(); if (!s->isTemplateInstance()) goto L1;
--- a/dmd/root/root.c Mon Mar 08 20:09:18 2010 +0100 +++ b/dmd/root/root.c Mon Mar 08 21:39:20 2010 +0100 @@ -1,8 +1,8 @@ -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// 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. @@ -14,6 +14,7 @@ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> +#include <limits.h> #include <string.h> #include <stdint.h> #include <assert.h> @@ -819,6 +820,91 @@ return NULL; } + +/************************************* + * Search Path for file in a safe manner. + * + * Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory + * ('Path Traversal') attacks. + * http://cwe.mitre.org/data/definitions/22.html + * More info: + * https://www.securecoding.cert.org/confluence/display/seccode/FIO02-C.+Canonicalize+path+names+originating+from+untrusted+sources + * Returns: + * NULL file not found + * !=NULL mem.malloc'd file name + */ + +char *FileName::safeSearchPath(Array *path, const char *name) +{ +#if _WIN32 + /* Disallow % / \ : and .. in name characters + */ + for (const char *p = name; *p; p++) + { + char c = *p; + if (c == '\\' || c == '/' || c == ':' || c == '%' || + (c == '.' && p[1] == '.')) + { + return NULL; + } + } + + return FileName::searchPath(path, name, 0); +#elif POSIX + /* Even with realpath(), we must check for // and disallow it + */ + for (const char *p = name; *p; p++) + { + char c = *p; + if (c == '/' && p[1] == '/') + { + return NULL; + } + } + + if (path) + { unsigned i; + + /* Each path is converted to a cannonical name and then a check is done to see + * that the searched name is really a child one of the the paths searched. + */ + for (i = 0; i < path->dim; i++) + { + char *cname = NULL; + char *cpath = canonicalName((char *)path->data[i]); + //printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n", + // name, (char *)path->data[i], cpath); + if (cpath == NULL) + goto cont; + cname = canonicalName(combine(cpath, name)); + //printf("FileName::safeSearchPath(): cname=%s\n", cname); + if (cname == NULL) + goto cont; + //printf("FileName::safeSearchPath(): exists=%i " + // "strncmp(cpath, cname, %i)=%i\n", exists(cname), + // strlen(cpath), strncmp(cpath, cname, strlen(cpath))); + // exists and name is *really* a "child" of path + if (exists(cname) && strncmp(cpath, cname, strlen(cpath)) == 0) + { + free(cpath); + char *p = mem.strdup(cname); + free(cname); + return p; + } +cont: + if (cpath) + free(cpath); + if (cname) + free(cname); + } + } + return NULL; +#else + assert(0); +#endif +} + + int FileName::exists(const char *name) { #if POSIX @@ -886,6 +972,52 @@ } } + +/****************************************** + * Return canonical version of name in a malloc'd buffer. + * This code is high risk. + */ +char *FileName::canonicalName(const char *name) +{ +#if linux + // Lovely glibc extension to do it for us + return canonicalize_file_name(name); +#elif POSIX + #if _POSIX_VERSION >= 200809L || defined (linux) + // NULL destination buffer is allowed and preferred + return realpath(name, NULL); + #else + char *cname = NULL; + #if PATH_MAX + /* PATH_MAX must be defined as a constant in <limits.h>, + * otherwise using it is unsafe due to TOCTOU + */ + size_t path_max = (size_t)PATH_MAX; + if (path_max > 0) + { + /* Need to add one to PATH_MAX because of realpath() buffer overflow bug: + * http://isec.pl/vulnerabilities/isec-0011-wu-ftpd.txt + */ + cname = (char *)malloc(path_max + 1); + if (cname == NULL) + return NULL; + } + #endif + return realpath(name, cname); + #endif +#elif _WIN32 + /* Apparently, there is no good way to do this on Windows. + * GetFullPathName isn't it. + */ + assert(0); + return NULL; +#else + assert(0); + return NULL; +#endif +} + + /****************************** File ********************************/ File::File(FileName *n)
--- a/dmd/root/root.h Mon Mar 08 20:09:18 2010 +0100 +++ b/dmd/root/root.h Mon Mar 08 21:39:20 2010 +0100 @@ -1,9 +1,9 @@ -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// 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. @@ -156,8 +156,10 @@ void CopyTo(FileName *to); static char *searchPath(Array *path, const char *name, int cwd); + static char *safeSearchPath(Array *path, const char *name); static int exists(const char *name); static void ensurePathExists(const char *path); + static char *canonicalName(const char *name); }; struct File : Object
--- a/dmd/scope.c Mon Mar 08 20:09:18 2010 +0100 +++ b/dmd/scope.c Mon Mar 08 21:39:20 2010 +0100 @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2005 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -11,6 +11,7 @@ #include <assert.h> #include "root.h" +#include "speller.h" #include "mars.h" #include "init.h" @@ -361,3 +362,27 @@ //assert(0); } } + + +/************************************************ + * Given the failed search attempt, try to find + * one with a close spelling. + */ + +void *scope_search_fp(void *arg, const char *seed) +{ + //printf("scope_search_fp('%s')\n", seed); + Scope *sc = (Scope *)arg; + Identifier id(seed, 0); + Module::clearCache(); + Dsymbol *s = sc->search(0, &id, NULL); + return s; +} + +Dsymbol *Scope::search_correct(Identifier *ident) +{ + if (global.gag) + return NULL; // don't do it for speculative compiles; too time consuming + + return (Dsymbol *)speller(ident->toChars(), &scope_search_fp, this, idchars); +}
--- a/dmd/scope.h Mon Mar 08 20:09:18 2010 +0100 +++ b/dmd/scope.h Mon Mar 08 21:39:20 2010 +0100 @@ -116,6 +116,7 @@ void mergeCallSuper(Loc loc, unsigned cs); Dsymbol *search(Loc loc, Identifier *ident, Dsymbol **pscopesym); + Dsymbol *search_correct(Identifier *ident); Dsymbol *insert(Dsymbol *s); ClassDeclaration *getClassScope();
--- a/dmd/statement.c Mon Mar 08 20:09:18 2010 +0100 +++ b/dmd/statement.c Mon Mar 08 21:39:20 2010 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -101,13 +101,10 @@ void Statement::warning(const char *format, ...) { - if (global.params.warnings && !global.gag) - { - va_list ap; - va_start(ap, format); - ::vwarning(loc, format, ap); - va_end( ap ); - } + va_list ap; + va_start(ap, format); + ::vwarning(loc, format, ap); + va_end( ap ); } int Statement::hasBreak() @@ -737,6 +734,7 @@ Statement *s = (Statement *) statements->data[i]; if (s) { + //printf("[%d]: %s\n", i, s->toChars()); s = s->semantic(scd); statements->data[i] = s; } @@ -798,6 +796,7 @@ return result; } + int UnrolledLoopStatement::comeFrom() { int comefrom = FALSE; @@ -3466,7 +3465,6 @@ Statement *s = new ExpStatement(loc, exp); exp = NULL; s = s->semantic(sc); - loc = 0; return new CompoundStatement(loc, s, this); }
--- a/dmd/template.c Mon Mar 08 20:09:18 2010 +0100 +++ b/dmd/template.c Mon Mar 08 21:39:20 2010 +0100 @@ -3701,7 +3701,12 @@ id = name; s = sc->search(loc, id, &scopesym); if (!s) - { error("template '%s' is not defined", id->toChars()); + { + s = sc->search_correct(id); + if (s) + error("template '%s' is not defined, did you mean %s?", id->toChars(), s->toChars()); + else + error("template '%s' is not defined", id->toChars()); return NULL; } #if LOG