diff --git a/src/class.c b/src/class.c index f1425c46f4fa..1c46c8441087 100644 --- a/src/class.c +++ b/src/class.c @@ -905,7 +905,12 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags) if (scope && !symtab) { Scope *sc = scope; sc->mustsemantic++; + // If speculatively gagged, ungag now. + unsigned oldgag = global.gag; + if (global.isSpeculativeGagging()) + global.gag = 0; semantic(sc); + global.gag = oldgag; sc->mustsemantic--; } diff --git a/src/declaration.c b/src/declaration.c index 222e46cb7740..ef1fc99932c5 100644 --- a/src/declaration.c +++ b/src/declaration.c @@ -503,7 +503,7 @@ void AliasDeclaration::semantic(Scope *sc) ScopeDsymbol::multiplyDefined(0, this, overnext); this->inSemantic = 0; - if (errors != global.errors) + if (global.gag && errors != global.errors) type = savedtype; return; @@ -539,7 +539,7 @@ void AliasDeclaration::semantic(Scope *sc) assert(global.errors); s = NULL; } - if (errors != global.errors) + if (global.gag && errors != global.errors) { type = savedtype; overnext = savedovernext; diff --git a/src/dsymbol.c b/src/dsymbol.c index 505baf0c98bf..a6d22186457e 100644 --- a/src/dsymbol.c +++ b/src/dsymbol.c @@ -277,6 +277,23 @@ TemplateInstance *Dsymbol::inTemplateInstance() return NULL; } +// Check if this function is a member of a template which has only been +// instantiated speculatively, eg from inside is(typeof()). +// Return the speculative template instance it is part of, +// or NULL if not speculative. +TemplateInstance *Dsymbol::isSpeculative() +{ + Dsymbol * par = parent; + while (par) + { + TemplateInstance *ti = par->isTemplateInstance(); + if (ti && ti->speculative) + return ti; + par = par->toParent(); + } + return NULL; +} + int Dsymbol::isAnonymous() { return ident ? 0 : 1; diff --git a/src/dsymbol.h b/src/dsymbol.h index 346bd9b50f63..f76d04bb76d3 100644 --- a/src/dsymbol.h +++ b/src/dsymbol.h @@ -137,6 +137,7 @@ struct Dsymbol : Object Dsymbol *toParent(); Dsymbol *toParent2(); TemplateInstance *inTemplateInstance(); + TemplateInstance *isSpeculative(); int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol() diff --git a/src/expression.c b/src/expression.c index 6fabea9da5c1..8cf777890c9b 100644 --- a/src/expression.c +++ b/src/expression.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -670,23 +670,6 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e, int noscope) } #endif -// Check if this function is a member of a template which has only been -// instantiated speculatively, eg from inside is(typeof()). -// Return the speculative template instance it is part of, -// or NULL if not speculative. -TemplateInstance *isSpeculativeFunction(FuncDeclaration *fd) -{ - Dsymbol * par = fd->parent; - while (par) - { - TemplateInstance *ti = par->isTemplateInstance(); - if (ti && ti->speculative) - return ti; - par = par->toParent(); - } - return NULL; -} - /**************************************** * Now that we know the exact type of the function we're calling, * the arguments[] need to be adjusted: @@ -716,7 +699,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, // If inferring return type, and semantic3() needs to be run if not already run if (!tf->next && fd->inferRetType) { - TemplateInstance *spec = isSpeculativeFunction(fd); + TemplateInstance *spec = fd->isSpeculative(); int olderrs = global.errors; fd->semantic3(fd->scope); // Update the template instantiation with the number @@ -2737,12 +2720,18 @@ Expression *DsymbolExp::semantic(Scope *sc) { //printf("'%s' is a function\n", f->toChars()); if (!f->originalType && f->scope) // semantic not yet run + { + unsigned oldgag = global.gag; + if (global.isSpeculativeGagging() && !f->isSpeculative()) + global.gag = 0; f->semantic(f->scope); + global.gag = oldgag; + } // if inferring return type, sematic3 needs to be run if (f->inferRetType && f->scope && f->type && !f->type->nextOf()) { - TemplateInstance *spec = isSpeculativeFunction(f); + TemplateInstance *spec = f->isSpeculative(); int olderrs = global.errors; f->semantic3(f->scope); // Update the template instantiation with the number @@ -9572,10 +9561,11 @@ Expression *PostExp::semantic(Scope *sc) return new ErrorExp(); } - e1 = e1->modifiableLvalue(sc, e1); + if (e1->op != TOKarraylength) + e1 = e1->modifiableLvalue(sc, e1); Type *t1 = e1->type->toBasetype(); - if (t1->ty == Tclass || t1->ty == Tstruct) + if (t1->ty == Tclass || t1->ty == Tstruct || e1->op == TOKarraylength) { /* Check for operator overloading, * but rewrite in terms of ++e instead of e++ */ @@ -9583,7 +9573,7 @@ Expression *PostExp::semantic(Scope *sc) /* If e1 is not trivial, take a reference to it */ Expression *de = NULL; - if (e1->op != TOKvar) + if (e1->op != TOKvar && e1->op != TOKarraylength) { // ref v = e1; Identifier *id = Lexer::uniqueId("__postref"); diff --git a/src/interpret.c b/src/interpret.c index fffd868d78a7..6ab1a97bcd8e 100644 --- a/src/interpret.c +++ b/src/interpret.c @@ -27,7 +27,6 @@ #include "attrib.h" // for AttribDeclaration #include "template.h" -TemplateInstance *isSpeculativeFunction(FuncDeclaration *fd); #define LOG 0 @@ -480,7 +479,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument */ int olderrors = global.errors; int oldgag = global.gag; - TemplateInstance *spec = isSpeculativeFunction(this); + TemplateInstance *spec = isSpeculative(); if (global.gag && !spec) global.gag = 0; semantic3(scope); diff --git a/src/mars.c b/src/mars.c index c30d5f95197a..6a6dc183eb3a 100644 --- a/src/mars.c +++ b/src/mars.c @@ -117,6 +117,11 @@ bool Global::endGagging(unsigned oldGagged) return anyErrs; } +bool Global::isSpeculativeGagging() +{ + return gag && gag == speculativeGag; +} + char *Loc::toChars() { diff --git a/src/mars.h b/src/mars.h index 24cd00b25267..9a35b3260189 100644 --- a/src/mars.h +++ b/src/mars.h @@ -262,6 +262,12 @@ struct Global unsigned gag; // !=0 means gag reporting of errors & warnings unsigned gaggedErrors; // number of errors reported while gagged + /* Gagging can either be speculative (is(typeof()), etc) + * or because of forward references + */ + unsigned speculativeGag; // == gag means gagging is for is(typeof); + bool isSpeculativeGagging(); + // Start gagging. Return the current number of gagged errors unsigned startGagging(); diff --git a/src/mtype.c b/src/mtype.c index 694650351c43..e8f1b69cf227 100644 --- a/src/mtype.c +++ b/src/mtype.c @@ -6730,7 +6730,12 @@ Type *TypeTypeof::semantic(Loc loc, Scope *sc) Scope *sc2 = sc->push(); sc2->intypeof++; sc2->flags |= sc->flags & SCOPEstaticif; + unsigned oldspecgag = global.speculativeGag; + if (global.gag) + global.speculativeGag = global.gag; exp = exp->semantic(sc2); + global.speculativeGag = oldspecgag; + #if DMDV2 if (exp->type && exp->type->ty == Tfunction && ((TypeFunction *)exp->type)->isproperty) diff --git a/src/struct.c b/src/struct.c index e13f3a9b82f3..0edec4de4ac1 100644 --- a/src/struct.c +++ b/src/struct.c @@ -473,7 +473,12 @@ void StructDeclaration::semantic(Scope *sc) if (sizeok == 0 && s->isAliasDeclaration()) finalizeSize(); } + // Ungag errors when not speculative + unsigned oldgag = global.gag; + if (global.isSpeculativeGagging() && !isSpeculative()) + global.gag = 0; s->semantic(sc2); + global.gag = oldgag; } if (sizeok == 2) diff --git a/src/traits.c b/src/traits.c index ad676004fa13..707de874a098 100644 --- a/src/traits.c +++ b/src/traits.c @@ -451,6 +451,8 @@ Expression *TraitsExp::semantic(Scope *sc) Expression *e; unsigned errors = global.startGagging(); + unsigned oldspec = global.speculativeGag; + global.speculativeGag = global.gag; Type *t = isType(o); if (t) @@ -471,6 +473,7 @@ Expression *TraitsExp::semantic(Scope *sc) } } + global.speculativeGag = oldspec; if (global.endGagging(errors)) { goto Lfalse; diff --git a/test/fail_compilation/gag4269a.d b/test/fail_compilation/gag4269a.d new file mode 100644 index 000000000000..23044710096e --- /dev/null +++ b/test/fail_compilation/gag4269a.d @@ -0,0 +1,11 @@ +// REQUIRED_ARGS: -c -o- + +static if(is(typeof(A4269.sizeof))) {} + +class A4269 +{ + void foo(B b); +} + + + \ No newline at end of file diff --git a/test/fail_compilation/gag4269b.d b/test/fail_compilation/gag4269b.d new file mode 100644 index 000000000000..d8aad6365411 --- /dev/null +++ b/test/fail_compilation/gag4269b.d @@ -0,0 +1,6 @@ +// REQUIRED_ARGS: -c -o- + +static if(is(typeof(X2.init))) {} +struct X2 { Y y; } + + \ No newline at end of file diff --git a/test/fail_compilation/gag4269c.d b/test/fail_compilation/gag4269c.d new file mode 100644 index 000000000000..fe1e4fa05109 --- /dev/null +++ b/test/fail_compilation/gag4269c.d @@ -0,0 +1,5 @@ +// REQUIRED_ARGS: -c -o- + +static if(is(typeof(X3.init))) {} +void X3(T3) { } + \ No newline at end of file diff --git a/test/fail_compilation/gag4269d.d b/test/fail_compilation/gag4269d.d new file mode 100644 index 000000000000..bba69ba391bb --- /dev/null +++ b/test/fail_compilation/gag4269d.d @@ -0,0 +1,5 @@ +// REQUIRED_ARGS: -c -o- + +static if(is(typeof(X4.init))) {} +Y4 X4() { return typeof(return).init; } + \ No newline at end of file diff --git a/test/fail_compilation/gag4269e.d b/test/fail_compilation/gag4269e.d new file mode 100644 index 000000000000..72f53a981437 --- /dev/null +++ b/test/fail_compilation/gag4269e.d @@ -0,0 +1,4 @@ +// REQUIRED_ARGS: -c -o- + +static if(is(typeof(X8.init))) {} +class X8 : Y8 {} \ No newline at end of file diff --git a/test/fail_compilation/gag4269f.d b/test/fail_compilation/gag4269f.d new file mode 100644 index 000000000000..857cdd18f88f --- /dev/null +++ b/test/fail_compilation/gag4269f.d @@ -0,0 +1,4 @@ +// REQUIRED_ARGS: -c -o- + +static if(is(typeof(X9.init))) {} +interface X9 { Y9 y; } \ No newline at end of file diff --git a/test/runnable/xtest46.d b/test/runnable/xtest46.d index 3522f95af813..e524b0578245 100644 --- a/test/runnable/xtest46.d +++ b/test/runnable/xtest46.d @@ -1120,6 +1120,17 @@ void test62() /***************************************************/ +void test3927() +{ + int[] array; + assert(array.length++ == 0); + assert(array.length == 1); + assert(array.length-- == 1); + assert(array.length == 0); +} + +/***************************************************/ + void test63() { int[3] b; @@ -4771,7 +4782,7 @@ int main() test103(); test104(); test105(); - + test3927(); test107(); test109();