From b032e3d1f744005b24e0140286cbc56cf443585f Mon Sep 17 00:00:00 2001 From: Moritz Warning Date: Mon, 27 Sep 2010 00:05:13 +0200 Subject: [PATCH] fixes #428 :: apply DMDFE 1.061; thanks SiegeLord --- dmd/class.c | 4 +- dmd/declaration.c | 6 +- dmd/dsymbol.c | 56 +++++++++--- dmd/dsymbol.h | 5 ++ dmd/expression.c | 71 ++++++++------- dmd/func.c | 2 +- dmd/mars.c | 2 +- dmd/mars.h | 2 + dmd/optimize.c | 2 + dmd/scope.c | 14 ++- dmd/speller.c | 216 ++++++++++++++++++++++++++++++++-------------- dmd/struct.c | 4 + dmd/template.c | 4 + 13 files changed, 273 insertions(+), 115 deletions(-) diff --git a/dmd/class.c b/dmd/class.c index 55f2fbb8..4ecbee44 100644 --- a/dmd/class.c +++ b/dmd/class.c @@ -338,7 +338,7 @@ void ClassDeclaration::semantic(Scope *sc) } if (!tc->sym->symtab || tc->sym->sizeok == 0) { // Try to resolve forward reference - if (sc->mustsemantic && tc->sym->scope) + if (/*sc->mustsemantic &&*/ tc->sym->scope) tc->sym->semantic(NULL); } if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0) @@ -406,7 +406,7 @@ void ClassDeclaration::semantic(Scope *sc) if (!tc->sym->symtab) { // Try to resolve forward reference - if (sc->mustsemantic && tc->sym->scope) + if (/*sc->mustsemantic &&*/ tc->sym->scope) tc->sym->semantic(NULL); } diff --git a/dmd/declaration.c b/dmd/declaration.c index 6f200c64..7954e48d 100644 --- a/dmd/declaration.c +++ b/dmd/declaration.c @@ -523,7 +523,7 @@ void AliasDeclaration::semantic(Scope *sc) //printf("alias is a symbol %s %s\n", s->kind(), s->toChars()); type = NULL; VarDeclaration *v = s->isVarDeclaration(); - if (v && v->linkage == LINKdefault) + if (0 && v && v->linkage == LINKdefault) { error("forward reference of %s", v->toChars()); s = NULL; @@ -831,8 +831,8 @@ void VarDeclaration::semantic(Scope *sc) OutBuffer buf; buf.printf("_%s_field_%zu", ident->toChars(), i); buf.writeByte(0); - char *name = (char *)buf.extractData(); - Identifier *id = new Identifier(name, TOKidentifier); + const char *name = (const char *)buf.extractData(); + Identifier *id = Lexer::idPool(name); Expression *einit = ie; if (ie && ie->op == TOKtuple) diff --git a/dmd/dsymbol.c b/dmd/dsymbol.c index ac921fdb..e21943e1 100644 --- a/dmd/dsymbol.c +++ b/dmd/dsymbol.c @@ -14,6 +14,7 @@ #include "rmem.h" #include "speller.h" +#include "aav.h" #include "mars.h" #include "dsymbol.h" @@ -1197,60 +1198,89 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) DsymbolTable::DsymbolTable() { +#if STRINGTABLE tab = new StringTable; +#else + tab = NULL; +#endif } DsymbolTable::~DsymbolTable() { +#if STRINGTABLE delete tab; +#endif } Dsymbol *DsymbolTable::lookup(Identifier *ident) { +#if STRINGTABLE #ifdef DEBUG assert(ident); assert(tab); #endif + //printf("DsymbolTable::lookup(%s)\n", (char*)ident->string); StringValue *sv = tab->lookup((char*)ident->string, ident->len); return (Dsymbol *)(sv ? sv->ptrvalue : NULL); +#else + //printf("DsymbolTable::lookup(%s)\n", (char*)ident->string); + return (Dsymbol *)_aaGetRvalue(tab, ident); +#endif } Dsymbol *DsymbolTable::insert(Dsymbol *s) -{ StringValue *sv; - Identifier *ident; - +{ //printf("DsymbolTable::insert(this = %p, '%s')\n", this, s->ident->toChars()); - ident = s->ident; + Identifier *ident = s->ident; +#if STRINGTABLE #ifdef DEBUG assert(ident); assert(tab); #endif - sv = tab->insert(ident->toChars(), ident->len); + StringValue *sv = tab->insert(ident->toChars(), ident->len); if (!sv) return NULL; // already in table sv->ptrvalue = s; return s; +#else + Dsymbol **ps = (Dsymbol **)_aaGet(&tab, ident); + if (*ps) + return NULL; // already in table + *ps = s; + return s; +#endif } Dsymbol *DsymbolTable::insert(Identifier *ident, Dsymbol *s) -{ StringValue *sv; - +{ //printf("DsymbolTable::insert()\n"); - sv = tab->insert(ident->toChars(), ident->len); +#if STRINGTABLE + StringValue *sv = tab->insert(ident->toChars(), ident->len); if (!sv) return NULL; // already in table sv->ptrvalue = s; return s; +#else + Dsymbol **ps = (Dsymbol **)_aaGet(&tab, ident); + if (*ps) + return NULL; // already in table + *ps = s; + return s; +#endif } Dsymbol *DsymbolTable::update(Dsymbol *s) -{ StringValue *sv; - Identifier *ident; - - ident = s->ident; - sv = tab->update(ident->toChars(), ident->len); +{ + Identifier *ident = s->ident; +#if STRINGTABLE + StringValue *sv = tab->update(ident->toChars(), ident->len); sv->ptrvalue = s; return s; +#else + Dsymbol **ps = (Dsymbol **)_aaGet(&tab, ident); + *ps = s; + return s; +#endif } diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index c41f533f..9142ea5e 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -77,6 +77,7 @@ struct HdrGenState; struct TypeInfoDeclaration; struct ClassInfoDeclaration; struct OverloadSet; +struct AA; #if TARGET_NET struct PragmaScope; #endif @@ -355,7 +356,11 @@ struct OverloadSet : Dsymbol struct DsymbolTable : Object { +#if STRINGTABLE StringTable *tab; +#else + AA *tab; +#endif DsymbolTable(); ~DsymbolTable(); diff --git a/dmd/expression.c b/dmd/expression.c index 112faebe..64366fc9 100644 --- a/dmd/expression.c +++ b/dmd/expression.c @@ -2131,12 +2131,17 @@ Expression *IdentifierExp::semantic(Scope *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()); + const char *n = importHint(ident->toChars()); + if (n) + error("'%s' is not defined, perhaps you need to import %s; ?", ident->toChars(), n); else - error("undefined identifier %s", ident->toChars()); + { + 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()); + } return new ErrorExp(); } @@ -2251,7 +2256,9 @@ Lagain: { //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars()); if (!type) - { type = v->type; + { if (!v->type && v->scope) + v->semantic(v->scope); + type = v->type; if (!v->type) { error("forward reference of %s", v->toChars()); type = Type::terror; @@ -2299,6 +2306,9 @@ Lagain: f = s->isFuncDeclaration(); if (f) { //printf("'%s' is a function\n", f->toChars()); + + if (!f->originalType && f->scope) // semantic not yet run + f->semantic(f->scope); if (!f->type->deco) { error("forward reference to %s", toChars()); @@ -3510,33 +3520,36 @@ Expression *ScopeExp::semantic(Scope *sc) Lagain: ti = sds->isTemplateInstance(); if (ti && !global.errors) - { Dsymbol *s; + { if (!ti->semanticRun) ti->semantic(sc); - s = ti->inst->toAlias(); - sds2 = s->isScopeDsymbol(); - if (!sds2) - { Expression *e; - - //printf("s = %s, '%s'\n", s->kind(), s->toChars()); - if (ti->withsym) - { - // Same as wthis.s - e = new VarExp(loc, ti->withsym->withstate->wthis); - e = new DotVarExp(loc, e, s->isDeclaration()); - } - else - e = new DsymbolExp(loc, s); - e = e->semantic(sc); - //printf("-1ScopeExp::semantic()\n"); - return e; - } - if (sds2 != sds) + if (ti->inst) { - sds = sds2; - goto Lagain; + Dsymbol *s = ti->inst->toAlias(); + sds2 = s->isScopeDsymbol(); + if (!sds2) + { Expression *e; + + //printf("s = %s, '%s'\n", s->kind(), s->toChars()); + if (ti->withsym) + { + // Same as wthis.s + e = new VarExp(loc, ti->withsym->withstate->wthis); + e = new DotVarExp(loc, e, s->isDeclaration()); + } + else + e = new DsymbolExp(loc, s); + e = e->semantic(sc); + //printf("-1ScopeExp::semantic()\n"); + return e; + } + if (sds2 != sds) + { + sds = sds2; + goto Lagain; + } + //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); } - //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); } else { diff --git a/dmd/func.c b/dmd/func.c index de793343..826dad4b 100644 --- a/dmd/func.c +++ b/dmd/func.c @@ -168,7 +168,7 @@ void FuncDeclaration::semantic(Scope *sc) parent = sc->parent; Dsymbol *parent = toParent(); - if (semanticRun == PASSsemanticdone) + if (semanticRun >= PASSsemanticdone) { if (!parent->isClassDeclaration()) return; diff --git a/dmd/mars.c b/dmd/mars.c index 2fd589bf..24e82ff4 100644 --- a/dmd/mars.c +++ b/dmd/mars.c @@ -63,7 +63,7 @@ Global::Global() copyright = "Copyright (c) 1999-2010 by Digital Mars and Tomas Lindquist Olsen"; written = "written by Walter Bright and Tomas Lindquist Olsen"; - version = "v1.060"; + version = "v1.061"; ldc_version = LDC_REV; llvm_version = LLVM_REV_STR; global.structalign = 8; diff --git a/dmd/mars.h b/dmd/mars.h index 8500b378..a3184035 100644 --- a/dmd/mars.h +++ b/dmd/mars.h @@ -442,6 +442,8 @@ void err_nomem(); void inifile(char *argv0, const char *inifile); void halt(); +const char *importHint(const char *s); + /*** Where to send error messages ***/ #if IN_GCC || IN_LLVM #define stdmsg stderr diff --git a/dmd/optimize.c b/dmd/optimize.c index 86edce0b..3539ad8a 100644 --- a/dmd/optimize.c +++ b/dmd/optimize.c @@ -46,6 +46,8 @@ Expression *fromConstInitializer(Expression *e1) if (e1->op == TOKvar) { VarExp *ve = (VarExp *)e1; VarDeclaration *v = ve->var->isVarDeclaration(); + if (v && !v->originalType && v->scope) // semantic() not yet run + v->semantic (v->scope); if (v && v->isConst() && v->init) { Expression *ei = v->init->toExpression(); if (ei && ei->type) diff --git a/dmd/scope.c b/dmd/scope.c index b6414bde..1217f6d4 100644 --- a/dmd/scope.c +++ b/dmd/scope.c @@ -23,6 +23,7 @@ #include "aggregate.h" #include "module.h" #include "id.h" +#include "lexer.h" Scope *Scope::freelist = NULL; @@ -372,10 +373,19 @@ void Scope::setNoFree() void *scope_search_fp(void *arg, const char *seed) { //printf("scope_search_fp('%s')\n", seed); + + /* If not in the lexer's string table, it certainly isn't in the symbol table. + * Doing this first is a lot faster. + */ + StringValue *sv = Lexer::stringtable.lookup(seed, strlen(seed)); + if (!sv) + return NULL; + Identifier *id = (Identifier *)sv->ptrvalue; + assert(id); + Scope *sc = (Scope *)arg; - Identifier id(seed, 0); Module::clearCache(); - Dsymbol *s = sc->search(0, &id, NULL); + Dsymbol *s = sc->search(0, id, NULL); return s; } diff --git a/dmd/speller.c b/dmd/speller.c index bf3f72a4..5ea67db8 100644 --- a/dmd/speller.c +++ b/dmd/speller.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "speller.h" @@ -12,112 +13,188 @@ const char idchars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123 * Currently only looks a 'distance' of one from the seed[]. * This does an exhaustive search, so can potentially be very slow. * Input: - *seedwrongly spelled word - *fpsearch function - *fpargargument to search function - *charsetcharacter set + * seed wrongly spelled word + * fp search function + * fparg argument to search function + * charset character set * Returns: - *NULLno correct spellings found - *void*value returned by fp() for first possible correct spelling + * NULL no correct spellings found + * void* value returned by fp() for first possible correct spelling */ -void *spellerX(const char *seed, fp_speller_t fp, void *fparg, const char *charset, int flag) +void *spellerY(const char *seed, size_t seedlen, fp_speller_t fp, void *fparg, + const char *charset, size_t index) +{ + if (!seedlen) + return NULL; + assert(seed[seedlen] == 0); + + char tmp[30]; + char *buf; + if (seedlen <= sizeof(tmp) - 2) + buf = tmp; + else + { + buf = (char *)alloca(seedlen + 2); // leave space for extra char + if (!buf) + return NULL; // no matches + } + + memcpy(buf, seed, index); + + /* Delete at seed[index] */ + if (index < seedlen) + { + memcpy(buf + index, seed + index + 1, seedlen - index); + assert(buf[seedlen - 1] == 0); + void *p = (*fp)(fparg, buf); + if (p) + return p; + } + + if (charset && *charset) + { + /* Substitutions */ + if (index < seedlen) + { + memcpy(buf, seed, seedlen + 1); + for (const char *s = charset; *s; s++) + { + buf[index] = *s; + + //printf("sub buf = '%s'\n", buf); + void *p = (*fp)(fparg, buf); + if (p) + return p; + } + assert(buf[seedlen] == 0); + } + + /* Insertions */ + memcpy (buf + index + 1, seed + index, seedlen + 1 - index); + + for (const char *s = charset; *s; s++) + { + buf[index] = *s; + + //printf("ins buf = '%s'\n", buf); + void *p = (*fp)(fparg, buf); + if (p) + return p; + } + assert(buf[seedlen + 1] == 0); + } + + return NULL; // didn't find any corrections +} + +void *spellerX(const char *seed, size_t seedlen, fp_speller_t fp, void *fparg, + const char *charset, int flag) { - size_t seedlen = strlen(seed); if (!seedlen) return NULL; - char *buf = (char *)alloca(seedlen + 2);// leave space for extra char - if (!buf) - return NULL;// no matches + char tmp[30]; + char *buf; + if (seedlen <= sizeof(tmp) - 2) + buf = tmp; + else + { + buf = (char *)alloca(seedlen + 2); // leave space for extra char + if (!buf) + return NULL; // no matches + } /* Deletions */ memcpy(buf, seed + 1, seedlen); for (int i = 0; i < seedlen; i++) - { - //printf("del buf = '%s'\n", buf); + { + //printf("del buf = '%s'\n", buf); void *p; if (flag) - p = spellerX(buf, fp, fparg, charset, flag - 1); + p = spellerY(buf, seedlen - 1, fp, fparg, charset, i); else p = (*fp)(fparg, buf); - if (p) - return p; + if (p) + return p; - buf[i] = seed[i]; - } + buf[i] = seed[i]; + } /* Transpositions */ - memcpy(buf, seed, seedlen + 1); - for (int i = 0; i + 1 < seedlen; i++) + if (!flag) + { + memcpy(buf, seed, seedlen + 1); + for (int i = 0; i + 1 < seedlen; i++) { // swap [i] and [i + 1] buf[i] = seed[i + 1]; buf[i + 1] = seed[i]; //printf("tra buf = '%s'\n", buf); - void *p; - if (flag) - p = spellerX(buf, fp, fparg, charset, flag - 1); - else - p = (*fp)(fparg, buf); + void *p = (*fp)(fparg, buf); if (p) return p; buf[i] = seed[i]; } + } if (charset && *charset) + { + /* Substitutions */ + memcpy(buf, seed, seedlen + 1); + for (int i = 0; i < seedlen; i++) { - /* Substitutions */ - memcpy(buf, seed, seedlen + 1); - for (int i = 0; i < seedlen; i++) - { - for (const char *s = charset; *s; s++) - { - buf[i] = *s; + for (const char *s = charset; *s; s++) + { + buf[i] = *s; - //printf("sub buf = '%s'\n", buf); + //printf("sub buf = '%s'\n", buf); void *p; if (flag) - p = spellerX(buf, fp, fparg, charset, flag - 1); + p = spellerY(buf, seedlen, fp, fparg, charset, i + 1); else p = (*fp)(fparg, buf); - if (p) - return p; - } - buf[i] = seed[i]; - } - - /* Insertions */ - memcpy(buf + 1, seed, seedlen + 1); - for (int i = 0; i <= seedlen; i++)// yes, do seedlen+1 iterations - { - for (const char *s = charset; *s; s++) - { - buf[i] = *s; - - //printf("ins buf = '%s'\n", buf); - void *p; - if (flag) - p = spellerX(buf, fp, fparg, charset, flag - 1); - else - p = (*fp)(fparg, buf); - if (p) - return p; - } - buf[i] = seed[i];// going past end of seed[] is ok, as we hit the 0 - } + if (p) + return p; + } + buf[i] = seed[i]; } - return NULL;// didn't find any corrections + /* Insertions */ + memcpy(buf + 1, seed, seedlen + 1); + for (int i = 0; i <= seedlen; i++) // yes, do seedlen+1 iterations + { + for (const char *s = charset; *s; s++) + { + buf[i] = *s; + + //printf("ins buf = '%s'\n", buf); + void *p; + if (flag) + p = spellerY(buf, seedlen + 1, fp, fparg, charset, i + 1); + else + p = (*fp)(fparg, buf); + if (p) + return p; + } + buf[i] = seed[i]; // going past end of seed[] is ok, as we hit the 0 + } + } + + return NULL; // didn't find any corrections } + void *speller(const char *seed, fp_speller_t fp, void *fparg, const char *charset) { + size_t seedlen = strlen(seed); for (int distance = 0; distance < 2; distance++) - { void *p = spellerX(seed, fp, fparg, charset, distance); + { void *p = spellerX(seed, seedlen, fp, fparg, charset, distance); if (p) return p; +// if (seedlen > 10) +// break; } return NULL; // didn't find it } @@ -131,6 +208,7 @@ void *speller(const char *seed, fp_speller_t fp, void *fparg, const char *charse void *speller_test(void *fparg, const char *s) { + //printf("speller_test(%s, %s)\n", fparg, s); if (strcmp((char *)fparg, s) == 0) return fparg; return NULL; @@ -141,18 +219,28 @@ void unittest_speller() static const char *cases[][3] = { { "hello", "hell", "y" }, - { "hello", "abcd", "n" }, { "hello", "hel", "y" }, - { "ehllo", "helol", "y" }, + { "hello", "ello", "y" }, + { "hello", "llo", "y" }, + { "hello", "hellox", "y" }, + { "hello", "helloxy", "y" }, + { "hello", "xhello", "y" }, + { "hello", "xyhello", "y" }, + { "hello", "ehllo", "y" }, + { "hello", "helol", "y" }, + { "hello", "abcd", "n" }, + //{ "ehllo", "helol", "y" }, { "hello", "helxxlo", "y" }, { "hello", "ehlxxlo", "n" }, { "hello", "heaao", "y" }, + { "_123456789_123456789_123456789_123456789", "_123456789_123456789_123456789_12345678", "y" }, }; //printf("unittest_speller()\n"); - void *p = speller("hello", &speller_test, (void *)"hell", idchars); + const void *p = speller("hello", &speller_test, (void *)"hell", idchars); assert(p != NULL); for (int i = 0; i < sizeof(cases)/sizeof(cases[0]); i++) { + //printf("case [%d]\n", i); void *p = speller(cases[i][0], &speller_test, (void *)cases[i][1], idchars); if (p) assert(cases[i][2][0] == 'y'); diff --git a/dmd/struct.c b/dmd/struct.c index a71328cf..fcd5b675 100644 --- a/dmd/struct.c +++ b/dmd/struct.c @@ -122,6 +122,8 @@ unsigned AggregateDeclaration::size(Loc loc) //printf("AggregateDeclaration::size() = %d\n", structsize); if (!members) error(loc, "unknown size"); + if (sizeok != 1 && scope) + semantic(NULL); if (sizeok != 1) { error(loc, "no size yet for forward reference"); //*(char*)0=0; @@ -181,6 +183,8 @@ void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v) } #endif + if (ts->sym->sizeok != 1 && ts->sym->scope) + ts->sym->semantic(NULL); if (ts->sym->sizeok != 1) { sizeok = 2; // cannot finish; flag as forward referenced diff --git a/dmd/template.c b/dmd/template.c index aef93d8a..048ce23c 100644 --- a/dmd/template.c +++ b/dmd/template.c @@ -3544,7 +3544,11 @@ void TemplateInstance::semantic(Scope *sc) } errors = 1; if (global.gag) + { // Try to reset things so we can try again later to instantiate it tempdecl->instances.remove(tempdecl_instance_idx); + semanticRun = 0; + inst = NULL; + } } #if LOG