From eadd5fb6452798bdf900891aae67b7933b02ca6c Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Sun, 22 Apr 2012 09:41:54 +0400 Subject: [PATCH] Squashed 'dmd2/' changes from fc63fd3..82e6a91 82e6a91 Resolve rvalue reference on template function arguments 3708457 Implement rvalue reference for struct literal & construction 530a59f Revert "struct literals are lvalues again" f199933 struct literals are lvalues again 5f181da better error message for Issue 7815 - Mixin template forward reference (?) regression e5452d5 fix Issue 7888 - derivedMembers forward reference error with nested imports b77ae4f merge with D1 5fed58d fix Issue 7886 - derivedMembers infinite recursion 0cf5ecd Merge pull request #872 from 9rnsr/fix7873 744f102 fix Issue 7695 - Regression(2.058): ICE(mtype.c) on associative array with keys of struct type with const members 80fc228 fix Issue 7873 - IFTI with inout does not properly match template parameter if called from inout function for pointers 4a5d365 fix CTFE bugs reported in beta df22942 add kind() d36a3b4 Merge pull request #871 from 9rnsr/fix7871 66d1302 fix Issue 7871 - RangeViolation with findSplitBefore 020ab91 fix Issue 7811 - "not a property" error instead of real error on UFCS array template property c349458 fix Issue 7862 - Accepts-invalid template forward reference bug related to derivedMembers 00d8ec8 fix Issue 7861 - Segfault during __error propagation with self-referencing module 4c9652d fix fwd ref bug 477c357 fix Issue 7859 - Crash on invalid alias template parameter type c35f67a fix Issue 7858 - __traits(getOverloads) returns incorrect symbol bc840e8 fix Issue 7815 - Mixin template forward reference (?) regression 18a1485 fix auto test break ceef368 fix Issue 7826 - [D2 Beta] Cannot use getHash in toHash without a warning d747fd6 fix Issue 7820 - regression(DMD 2.059head) Wrong error on forward reference to 'front' with -property switch 1094601 fix Issue 7823 - Can't use a struct initializer to initialize a nested enum used as a default function argument initializer git-subtree-dir: dmd2 git-subtree-split: 82e6a91f234843be7f660b242f8b8819c1eae20c --- attrib.c | 18 +++++-- attrib.h | 1 + cond.c | 29 +++++++--- cond.h | 3 +- declaration.c | 11 +++- expression.c | 143 +++++++++++++++++++++++++++++++++++++++----------- expression.h | 3 +- func.c | 56 ++++++++++++++++++++ init.c | 28 ++++++++-- interpret.c | 3 +- module.c | 2 + mtype.c | 23 +++++++- struct.c | 4 +- template.c | 20 ++++++- traits.c | 5 ++ typinf.c | 4 +- 16 files changed, 297 insertions(+), 56 deletions(-) diff --git a/attrib.c b/attrib.c index 326d9452..dfa19cac 100644 --- a/attrib.c +++ b/attrib.c @@ -49,7 +49,7 @@ Dsymbols *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd) int AttribDeclaration::apply(Dsymbol_apply_ft_t fp, void *param) { - Dsymbols *d = include(NULL, NULL); + Dsymbols *d = include(scope, NULL); if (d) { @@ -1237,9 +1237,9 @@ void ConditionalDeclaration::emitComment(Scope *sc) Dsymbols *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sd) { - //printf("ConditionalDeclaration::include()\n"); + //printf("ConditionalDeclaration::include(sc = %p) scope = %p\n", sc, scope); assert(condition); - return condition->include(sc, sd) ? decl : elsedecl; + return condition->include(scope ? scope : sc, sd) ? decl : elsedecl; } void ConditionalDeclaration::setScope(Scope *sc) @@ -1399,6 +1399,9 @@ void StaticIfDeclaration::importAll(Scope *sc) void StaticIfDeclaration::setScope(Scope *sc) { // do not evaluate condition before semantic pass + + // But do set the scope, in case we need it for forward referencing + Dsymbol::setScope(sc); } void StaticIfDeclaration::semantic(Scope *sc) @@ -1430,6 +1433,8 @@ const char *StaticIfDeclaration::kind() /***************************** CompileDeclaration *****************************/ +// These are mixin declarations, like mixin("int x"); + CompileDeclaration::CompileDeclaration(Loc loc, Expression *exp) : AttribDeclaration(NULL) { @@ -1503,3 +1508,10 @@ void CompileDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring(");"); buf->writenl(); } + +const char *CompileDeclaration::kind() +{ + return "mixin"; +} + + diff --git a/attrib.h b/attrib.h index 7806517f..da738c28 100644 --- a/attrib.h +++ b/attrib.h @@ -187,6 +187,7 @@ struct CompileDeclaration : AttribDeclaration void compileIt(Scope *sc); void semantic(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + const char *kind(); }; #endif /* DMD_ATTRIB_H */ diff --git a/cond.c b/cond.c index 3ee03889..386a1f91 100644 --- a/cond.c +++ b/cond.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 @@ -22,6 +22,7 @@ #include "lexer.h" #include "mtype.h" #include "scope.h" +#include "arraytypes.h" int findCondition(Strings *ids, Identifier *ident) { @@ -29,7 +30,7 @@ int findCondition(Strings *ids, Identifier *ident) { for (size_t i = 0; i < ids->dim; i++) { - const char *id = ids->tdata()[i]; + const char *id = (*ids)[i]; if (strcmp(id, ident->toChars()) == 0) return TRUE; @@ -218,6 +219,7 @@ StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp) : Condition(loc) { this->exp = exp; + this->nest = 0; } Condition *StaticIfCondition::syntaxCopy() @@ -228,7 +230,7 @@ Condition *StaticIfCondition::syntaxCopy() int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s) { #if 0 - printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc, s); + printf("StaticIfCondition::include(sc = %p, s = %p) this=%p inc = %d\n", sc, s, this, inc); if (s) { printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind()); @@ -236,6 +238,15 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s) #endif if (inc == 0) { + if (exp->op == TOKerror || nest > 100) + { + error(loc, (nest > 1000) ? "unresolvable circular static if expression" + : "error evaluating static if expression"); + if (!global.gag) + inc = 2; // so we don't see the error message again + return 0; + } + if (!sc) { error(loc, "static if conditional cannot be at global scope"); @@ -243,13 +254,19 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s) return 0; } + ++nest; sc = sc->push(sc->scopesym); sc->sd = s; // s gets any addMember() sc->flags |= SCOPEstaticif; Expression *e = exp->semantic(sc); sc->pop(); e = e->optimize(WANTvalue | WANTinterpret); - if (e->isBool(TRUE)) + --nest; + if (e->op == TOKerror) + { exp = e; + inc = 0; + } + else if (e->isBool(TRUE)) inc = 1; else if (e->isBool(FALSE)) inc = 2; @@ -321,7 +338,7 @@ int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd) TemplateParameters parameters; parameters.setDim(1); - parameters.tdata()[0] = &tp; + parameters[0] = &tp; Objects dedtypes; dedtypes.setDim(1); @@ -333,7 +350,7 @@ int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd) else { inc = 1; - Type *tded = (Type *)dedtypes.tdata()[0]; + Type *tded = (Type *)dedtypes[0]; if (!tded) tded = targ; Dsymbol *s = new AliasDeclaration(loc, id, tded); diff --git a/cond.h b/cond.h index 789503a4..71400314 100644 --- a/cond.h +++ b/cond.h @@ -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 @@ -79,6 +79,7 @@ struct VersionCondition : DVCondition struct StaticIfCondition : Condition { Expression *exp; + int nest; // limit circular dependencies StaticIfCondition(Loc loc, Expression *exp); Condition *syntaxCopy(); diff --git a/declaration.c b/declaration.c index bcb063be..d0409bc7 100644 --- a/declaration.c +++ b/declaration.c @@ -760,6 +760,7 @@ void VarDeclaration::semantic(Scope *sc) if (!type) { inuse++; + //printf("inferring type for %s with init %s\n", toChars(), init->toChars()); ArrayInitializer *ai = init->isArrayInitializer(); if (ai) { Expression *e; @@ -780,7 +781,6 @@ void VarDeclaration::semantic(Scope *sc) else type = init->inferType(sc); -//printf("test2: %s, %s, %s\n", toChars(), type->toChars(), type->deco); // type = type->semantic(loc, sc); inuse--; @@ -847,7 +847,14 @@ void VarDeclaration::semantic(Scope *sc) Type *tb = type->toBasetype(); if (tb->ty == Tvoid && !(storage_class & STClazy)) - { error("voids have no value"); + { + if (inferred) + { + error("type %s is inferred from initializer %s, and variables cannot be of type void", + type->toChars(), init->toChars()); + } + else + error("variables cannot be of type void"); type = Type::terror; tb = type; } diff --git a/expression.c b/expression.c index 5831d39c..d9d2aa25 100644 --- a/expression.c +++ b/expression.c @@ -314,7 +314,15 @@ void checkPropertyCall(Expression *e, Expression *emsg) { CallExp *ce = (CallExp *)e; TypeFunction *tf; if (ce->f) + { tf = (TypeFunction *)ce->f->type; + /* If a forward reference to ce->f, try to resolve it + */ + if (!tf->deco && ce->f->scope) + { ce->f->semantic(ce->f->scope); + tf = (TypeFunction *)ce->f->type; + } + } else if (ce->e1->type->ty == Tfunction) tf = (TypeFunction *)ce->e1->type; else if (ce->e1->type->ty == Tdelegate) @@ -366,46 +374,54 @@ Expression *resolveUFCSProperties(Scope *sc, Expression *e1, Expression *e2 = NU else e = new DotIdExp(loc, e, ident); - Expressions *arguments = new Expressions(); - /* .f(e1, e2) - */ if (e2) { - arguments->setDim(2); - (*arguments)[0] = eleft; - (*arguments)[1] = e2; - + /* .f(e1) = e2 + */ Expression *ex = e->syntaxCopy(); - e = new CallExp(loc, e, arguments); - e = e->trySemantic(sc); - if (e) - { checkPropertyCall(e, e1); - return e->semantic(sc); - } - e = ex; - } + Expressions *a1 = new Expressions(); + a1->setDim(1); + (*a1)[0] = eleft; + ex = new CallExp(loc, ex, a1); + ex = ex->trySemantic(sc); - /* .f(e1) - * .f(e1) = e2 - */ + /* .f(e1, e2) + */ + Expressions *a2 = new Expressions(); + a2->setDim(2); + (*a2)[0] = eleft; + (*a2)[1] = e2; + e = new CallExp(loc, e, a2); + if (ex) + { // if fallback setter exists, gag errors + e = e->trySemantic(sc); + if (!e) + { checkPropertyCall(ex, e1); + ex = new AssignExp(loc, ex, e2); + return ex->semantic(sc); + } + } + else + { // strict setter prints errors if fails + e = e->semantic(sc); + } + checkPropertyCall(e, e1); + return e; + } + else { + /* .f(e1) + */ + Expressions *arguments = new Expressions(); arguments->setDim(1); (*arguments)[0] = eleft; e = new CallExp(loc, e, arguments); - e = e->trySemantic(sc); - if (!e) - goto Leprop; + e = e->semantic(sc); checkPropertyCall(e, e1); - if (e2) - e = new AssignExp(loc, e, e2); return e->semantic(sc); } } return e; - -Leprop: - e1->error("not a property %s", e1->toChars()); - return new ErrorExp(); } /****************************** @@ -1021,7 +1037,37 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, } if (p->storageClass & STCref) { - arg = arg->toLvalue(sc, arg); + if (arg->op == TOKstructliteral) + { + Identifier *idtmp = Lexer::uniqueId("__tmpsl"); + VarDeclaration *tmp = new VarDeclaration(loc, arg->type, idtmp, new ExpInitializer(0, arg)); + tmp->storage_class |= STCctfe; + Expression *ae = new DeclarationExp(loc, tmp); + Expression *e = new CommaExp(loc, ae, new VarExp(loc, tmp)); + e = e->semantic(sc); + + arg = e; + } + else if (arg->op == TOKcall) + { + CallExp *ce = (CallExp *)arg; + if (ce->e1->op == TOKdotvar && + ((DotVarExp *)ce->e1)->var->isCtorDeclaration()) + { + DotVarExp *dve = (DotVarExp *)ce->e1; + assert(dve->e1->op == TOKcomma); + assert(((CommaExp *)dve->e1)->e2->op == TOKvar); + VarExp *ve = (VarExp *)((CommaExp *)dve->e1)->e2; + VarDeclaration *tmp = ve->var->isVarDeclaration(); + + arg = new CommaExp(arg->loc, arg, new VarExp(loc, tmp)); + arg = arg->semantic(sc); + } + else + arg = arg->toLvalue(sc, arg); + } + else + arg = arg->toLvalue(sc, arg); } else if (p->storageClass & STCout) { @@ -6674,9 +6720,29 @@ Expression *DotIdExp::semantic(Scope *sc, int flag) { goto L2; } - unsigned errors = global.startGagging(); + /* This would be much better if we added a "hasProperty" method to types, + * i.e. the gagging is a bad way. + */ + + if (t1b->ty == Taarray) + { + TypeAArray *taa = (TypeAArray *)t1b; + if (!taa->impl && + ident != Id::__sizeof && + ident != Id::__xalignof && + ident != Id::init && + ident != Id::mangleof && + ident != Id::stringof && + ident != Id::offsetof) + { + // Find out about these errors when not gagged + taa->getImpl(); + } + } + Type *t1 = e1->type; - e = e1->type->dotExp(sc, e1, ident); + unsigned errors = global.startGagging(); + e = t1->dotExp(sc, e1, ident); if (global.endGagging(errors)) // if failed to find the property { e1->type = t1; // kludge to restore type @@ -8716,6 +8782,8 @@ Expression *CastExp::semantic(Scope *sc) } else to = to->semantic(loc, sc); + if (to == Type::terror) + return new ErrorExp(); if (!to->equals(e1->type)) { @@ -8952,7 +9020,9 @@ Expression *SliceExp::syntaxCopy() if (this->upr) upr = this->upr->syntaxCopy(); - return new SliceExp(loc, e1->syntaxCopy(), lwr, upr); + SliceExp *se = new SliceExp(loc, e1->syntaxCopy(), lwr, upr); + se->lengthVar = this->lengthVar; // bug7871 + return se; } Expression *SliceExp::semantic(Scope *sc) @@ -9297,7 +9367,9 @@ ArrayExp::ArrayExp(Loc loc, Expression *e1, Expressions *args) Expression *ArrayExp::syntaxCopy() { - return new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments)); + ArrayExp *ae = new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments)); + ae->lengthVar = this->lengthVar; // bug7871 + return ae; } Expression *ArrayExp::semantic(Scope *sc) @@ -9464,6 +9536,13 @@ IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2) modifiable = 0; // assume it is an rvalue } +Expression *IndexExp::syntaxCopy() +{ + IndexExp *ie = new IndexExp(loc, e1->syntaxCopy(), e2->syntaxCopy()); + ie->lengthVar = this->lengthVar; // bug7871 + return ie; +} + Expression *IndexExp::semantic(Scope *sc) { Expression *e; Type *t1; diff --git a/expression.h b/expression.h index 7c91273d..412566cd 100644 --- a/expression.h +++ b/expression.h @@ -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 @@ -1196,6 +1196,7 @@ struct IndexExp : BinExp int modifiable; IndexExp(Loc loc, Expression *e1, Expression *e2); + Expression *syntaxCopy(); Expression *semantic(Scope *sc); int isLvalue(); Expression *toLvalue(Scope *sc, Expression *e); diff --git a/func.c b/func.c index 94ed87fe..5364f08d 100644 --- a/func.c +++ b/func.c @@ -156,6 +156,11 @@ void FuncDeclaration::semantic(Scope *sc) semanticRun = PASSsemantic; } + if (scope) + { sc = scope; + scope = NULL; + } + unsigned dprogress_save = Module::dprogress; foverrides.setDim(0); // reset in case semantic() is being retried for this function @@ -2743,6 +2748,9 @@ int FuncDeclaration::isImportedSymbol() int FuncDeclaration::isVirtual() { + if (toAliasFunc() != this) + return toAliasFunc()->isVirtual(); + Dsymbol *p = toParent(); #if 0 printf("FuncDeclaration::isVirtual(%s)\n", toChars()); @@ -2763,6 +2771,9 @@ int FuncDeclaration::isVirtual() int FuncDeclaration::isVirtualMethod() { + if (toAliasFunc() != this) + return toAliasFunc()->isVirtualMethod(); + //printf("FuncDeclaration::isVirtualMethod() %s\n", toChars()); if (!isVirtual()) return 0; @@ -2776,6 +2787,9 @@ int FuncDeclaration::isVirtualMethod() int FuncDeclaration::isFinal() { + if (toAliasFunc() != this) + return toAliasFunc()->isFinal(); + ClassDeclaration *cd; #if 0 printf("FuncDeclaration::isFinal(%s), %x\n", toChars(), Declaration::isFinal()); @@ -3285,6 +3299,11 @@ void CtorDeclaration::semantic(Scope *sc) TypeFunction *tf = (TypeFunction *)type; assert(tf && tf->ty == Tfunction); + if (scope) + { sc = scope; + scope = NULL; + } + sc = sc->push(); sc->stc &= ~STCstatic; // not a static constructor sc->flags |= SCOPEctor; @@ -3403,6 +3422,10 @@ void PostBlitDeclaration::semantic(Scope *sc) //printf("PostBlitDeclaration::semantic() %s\n", toChars()); //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor); //printf("stc = x%llx\n", sc->stc); + if (scope) + { sc = scope; + scope = NULL; + } parent = sc->parent; Dsymbol *parent = toParent(); StructDeclaration *ad = parent->isStructDeclaration(); @@ -3476,6 +3499,10 @@ void DtorDeclaration::semantic(Scope *sc) { //printf("DtorDeclaration::semantic() %s\n", toChars()); //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor); + if (scope) + { sc = scope; + scope = NULL; + } parent = sc->parent; Dsymbol *parent = toParent(); AggregateDeclaration *ad = parent->isAggregateDeclaration(); @@ -3567,6 +3594,11 @@ void StaticCtorDeclaration::semantic(Scope *sc) { //printf("StaticCtorDeclaration::semantic()\n"); + if (scope) + { sc = scope; + scope = NULL; + } + if (!type) type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); @@ -3695,6 +3727,11 @@ Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s) void StaticDtorDeclaration::semantic(Scope *sc) { + if (scope) + { sc = scope; + scope = NULL; + } + ClassDeclaration *cd = sc->scopesym->isClassDeclaration(); if (!type) @@ -3822,6 +3859,10 @@ Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s) void InvariantDeclaration::semantic(Scope *sc) { + if (scope) + { sc = scope; + scope = NULL; + } parent = sc->parent; Dsymbol *parent = toParent(); AggregateDeclaration *ad = parent->isAggregateDeclaration(); @@ -3902,6 +3943,11 @@ Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s) void UnitTestDeclaration::semantic(Scope *sc) { + if (scope) + { sc = scope; + scope = NULL; + } + if (global.params.useUnitTests) { if (!type) @@ -3985,6 +4031,11 @@ void NewDeclaration::semantic(Scope *sc) { //printf("NewDeclaration::semantic()\n"); + if (scope) + { sc = scope; + scope = NULL; + } + parent = sc->parent; Dsymbol *parent = toParent(); ClassDeclaration *cd = parent->isClassDeclaration(); @@ -4069,6 +4120,11 @@ void DeleteDeclaration::semantic(Scope *sc) { //printf("DeleteDeclaration::semantic()\n"); + if (scope) + { sc = scope; + scope = NULL; + } + parent = sc->parent; Dsymbol *parent = toParent(); ClassDeclaration *cd = parent->isClassDeclaration(); diff --git a/init.c b/init.c index 768c6137..74fd7447 100644 --- a/init.c +++ b/init.c @@ -21,6 +21,7 @@ #include "scope.h" #include "mtype.h" #include "hdrgen.h" +#include "template.h" /********************************** Initializer *******************************/ @@ -157,8 +158,18 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) if (ad->ctor) error(loc, "%s %s has constructors, cannot use { initializers }, use %s( initializers ) instead", ad->kind(), ad->toChars(), ad->toChars()); - size_t nfields = ad->fields.dim; - if (((StructDeclaration *)ad)->isnested) nfields--; + StructDeclaration *sd = ad->isStructDeclaration(); + assert(sd); + sd->size(loc); + if (sd->sizeok != SIZEOKdone) + { + error(loc, "struct %s is forward referenced", sd->toChars()); + errors = 1; + goto Lerror; + } + size_t nfields = sd->fields.dim; + if (sd->isnested) + nfields--; for (size_t i = 0; i < field.dim; i++) { Identifier *id = field[i]; @@ -241,6 +252,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) error(loc, "a struct is not a valid initializer for a %s", t->toChars()); errors = 1; } +Lerror: if (errors) { field.setDim(0); @@ -261,12 +273,11 @@ Expression *StructInitializer::toExpression() //printf("StructInitializer::toExpression() %s\n", toChars()); if (!ad) // if fwd referenced - { return NULL; - } StructDeclaration *sd = ad->isStructDeclaration(); if (!sd) return NULL; + Expressions *elements = new Expressions(); size_t nfields = ad->fields.dim; #if DMDV2 @@ -856,6 +867,15 @@ Type *ExpInitializer::inferType(Scope *sc) //printf("ExpInitializer::inferType() %s\n", toChars()); exp = exp->semantic(sc); exp = resolveProperties(sc, exp); + if (exp->op == TOKimport) + { ScopeExp *se = (ScopeExp *)exp; + TemplateInstance *ti = se->sds->isTemplateInstance(); + if (ti && ti->semanticRun == PASSsemantic && !ti->aliasdecl) + se->error("cannot infer type from %s %s, possible circular dependency", se->sds->kind(), se->toChars()); + else + se->error("cannot infer type from %s %s", se->sds->kind(), se->toChars()); + return Type::terror; + } // Give error for overloaded function addresses if (exp->op == TOKsymoff) diff --git a/interpret.c b/interpret.c index 56436990..d64883a0 100644 --- a/interpret.c +++ b/interpret.c @@ -6696,7 +6696,8 @@ Expression *TypeStruct::voidInitLiteral(VarDeclaration *var) exps->setDim(sym->fields.dim); for (size_t i = 0; i < sym->fields.dim; i++) { - (*exps)[i] = new VoidInitExp(var, sym->fields[i]->type); + //(*exps)[i] = new VoidInitExp(var, sym->fields[i]->type); + (*exps)[i] = sym->fields[i]->type->voidInitLiteral(var); } StructLiteralExp *se = new StructLiteralExp(var->loc, sym, exps); se->type = this; diff --git a/module.c b/module.c index a09e22fd..c4432250 100644 --- a/module.c +++ b/module.c @@ -828,6 +828,8 @@ void Module::semantic2() return; } //printf("Module::semantic2('%s'): parent = %p\n", toChars(), parent); + if (semanticRun == 0) // semantic() not completed yet - could be recursive call + return; if (semanticstarted >= 2) return; assert(semanticstarted == 1); diff --git a/mtype.c b/mtype.c index 6c53c2e4..c90d21cf 100644 --- a/mtype.c +++ b/mtype.c @@ -5827,6 +5827,19 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag) new IntegerExp(0, ((StringExp *)arg)->len, Type::tindex)); } + else if (arg->op == TOKstructliteral) + match = MATCHconvert; + else if (arg->op == TOKcall) + { + CallExp *ce = (CallExp *)arg; + if (ce->e1->op == TOKdotvar && + ((DotVarExp *)ce->e1)->var->isCtorDeclaration()) + { + match = MATCHconvert; + } + else + goto Nomatch; + } else goto Nomatch; } @@ -7691,7 +7704,15 @@ Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident) L1: if (!s) { - return noMember(sc, e, ident); + if (sym->scope) // it's a fwd ref, maybe we can resolve it + { + sym->semantic(NULL); + s = sym->search(e->loc, ident, 0); + if (!s) + return noMember(sc, e, ident); + } + else + return noMember(sc, e, ident); } if (!s->isFuncDeclaration()) // because of overloading s->checkDeprecated(e->loc, sc); diff --git a/struct.c b/struct.c index 6c71f583..dd976284 100644 --- a/struct.c +++ b/struct.c @@ -444,7 +444,7 @@ void StructDeclaration::semantic(Scope *sc) */ //if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident)) { - //printf("setScope %s %s\n", s->kind(), s->toChars()); + //printf("struct: setScope %s %s\n", s->kind(), s->toChars()); s->setScope(sc2); } } @@ -466,7 +466,9 @@ void StructDeclaration::semantic(Scope *sc) // Ungag errors when not speculative unsigned oldgag = global.gag; if (global.isSpeculativeGagging() && !isSpeculative()) + { global.gag = 0; + } s->semantic(sc2); global.gag = oldgag; } diff --git a/template.c b/template.c index bf63e6e8..8b7e2f18 100644 --- a/template.c +++ b/template.c @@ -1504,7 +1504,23 @@ Lretry: if (m && (fparam->storageClass & (STCref | STCauto)) == STCref) { if (!farg->isLvalue()) - goto Lnomatch; + { + if (farg->op == TOKstructliteral) + m = MATCHconvert; + else if (farg->op == TOKcall) + { + CallExp *ce = (CallExp *)farg; + if (ce->e1->op == TOKdotvar && + ((DotVarExp *)ce->e1)->var->isCtorDeclaration()) + { + m = MATCHconvert; + } + else + goto Lnomatch; + } + else + goto Lnomatch; + } } if (m && (fparam->storageClass & STCout)) { if (!farg->isLvalue()) @@ -2319,7 +2335,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, *wildmatch |= MODmutable; else *wildmatch |= (mod & ~MODshared); - tt = mutableOf(); + tt = mutableOf()->substWildTo(MODmutable); dedtypes->tdata()[i] = tt; goto Lconst; } diff --git a/traits.c b/traits.c index 3ead0b45..01a1cc8c 100644 --- a/traits.c +++ b/traits.c @@ -528,6 +528,11 @@ Expression *TraitsExp::semantic(Scope *sc) s1 = s1->toAlias(); s2 = s2->toAlias(); + if (s1->isFuncAliasDeclaration()) + s1 = ((FuncAliasDeclaration *)s1)->toAliasFunc(); + if (s2->isFuncAliasDeclaration()) + s2 = ((FuncAliasDeclaration *)s2)->toAliasFunc(); + if (s1 == s2) goto Ltrue; else diff --git a/typinf.c b/typinf.c index 167a5b1d..c40a6cdb 100644 --- a/typinf.c +++ b/typinf.c @@ -594,8 +594,8 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt) * function with the name "toHash". * So I'm leaving this here as an experiment for the moment. */ - if (!tf->isnothrow || tf->trust == TRUSTsystem || tf->purity == PUREimpure) - { warning(fd->loc, "toHash() must be declared as extern (D) uint toHash() const pure nothrow @safe, not %s", tf->toChars()); + if (!tf->isnothrow || tf->trust == TRUSTsystem /*|| tf->purity == PUREimpure*/) + { warning(fd->loc, "toHash() must be declared as extern (D) uint toHash() const nothrow @safe, not %s", tf->toChars()); if (global.params.warnings == 1) global.errors++; }