From 425d025b91f5924f307a544f2dc0c4239ef97b8e Mon Sep 17 00:00:00 2001 From: k-hara Date: Fri, 14 Feb 2014 23:59:07 +0900 Subject: [PATCH 1/3] [Refactoring] Separate `Type::genTypeInfo` from `Type::getTypeInfo` Reduce redundant Expression generation in glue layer --- src/mtype.h | 1 + src/toobj.c | 10 +++++----- src/typinf.c | 43 ++++++++++++++++++++++++------------------- 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/mtype.h b/src/mtype.h index c60edb976083..84deabb201e2 100644 --- a/src/mtype.h +++ b/src/mtype.h @@ -326,6 +326,7 @@ class Type : public RootObject virtual void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false); Expression *getInternalTypeInfo(Scope *sc); Expression *getTypeInfo(Scope *sc); + void genTypeInfo(Scope *sc); virtual TypeInfoDeclaration *getTypeInfoDeclaration(); virtual int builtinTypeInfo(); virtual Type *reliesOnTident(TemplateParameters *tparams = NULL); diff --git a/src/toobj.c b/src/toobj.c index 08c8ed1b8cfe..d3f713a95869 100644 --- a/src/toobj.c +++ b/src/toobj.c @@ -252,7 +252,7 @@ void ClassDeclaration::toObjFile(int multiobj) ////////////////////////////////////////////// // Put out the TypeInfo - type->getTypeInfo(NULL); + type->genTypeInfo(NULL); //type->vtinfo->toObjFile(multiobj); ////////////////////////////////////////////// @@ -661,7 +661,7 @@ void InterfaceDeclaration::toObjFile(int multiobj) ////////////////////////////////////////////// // Put out the TypeInfo - type->getTypeInfo(NULL); + type->genTypeInfo(NULL); type->vtinfo->toObjFile(multiobj); ////////////////////////////////////////////// @@ -821,7 +821,7 @@ void StructDeclaration::toObjFile(int multiobj) if (global.params.symdebug) toDebug(); - type->getTypeInfo(NULL); // generate TypeInfo + type->genTypeInfo(NULL); if (1) { @@ -990,7 +990,7 @@ void TypedefDeclaration::toObjFile(int multiobj) if (global.params.symdebug) toDebug(); - type->getTypeInfo(NULL); // generate TypeInfo + type->genTypeInfo(NULL); TypeTypedef *tc = (TypeTypedef *)type; if (type->isZeroInit() || !tc->sym->init) @@ -1030,7 +1030,7 @@ void EnumDeclaration::toObjFile(int multiobj) if (global.params.symdebug) toDebug(); - type->getTypeInfo(NULL); // generate TypeInfo + type->genTypeInfo(NULL); TypeEnum *tc = (TypeEnum *)type; if (!tc->sym->members || type->isZeroInit()) diff --git a/src/typinf.c b/src/typinf.c index ca10a97d0994..1a796d8cbf7f 100644 --- a/src/typinf.c +++ b/src/typinf.c @@ -98,9 +98,9 @@ FuncDeclaration *search_toString(StructDeclaration *sd); * Get the exact TypeInfo. */ -Expression *Type::getTypeInfo(Scope *sc) +void Type::genTypeInfo(Scope *sc) { - //printf("Type::getTypeInfo() %p, %s\n", this, toChars()); + //printf("Type::genTypeInfo() %p, %s\n", this, toChars()); if (!Type::dtypeinfo) { error(Loc(), "TypeInfo not found. object.d may be incorrectly installed or corrupt, compile with -v switch"); @@ -121,7 +121,6 @@ Expression *Type::getTypeInfo(Scope *sc) else t->vtinfo = t->getTypeInfoDeclaration(); assert(t->vtinfo); - vtinfo = t->vtinfo; /* If this has a custom implementation in std/typeinfo, then * do not generate a COMDAT for it. @@ -160,7 +159,13 @@ Expression *Type::getTypeInfo(Scope *sc) } if (!vtinfo) vtinfo = t->vtinfo; // Types aren't merged, but we can share the vtinfo's - Expression *e = VarExp::create(Loc(), t->vtinfo); + assert(vtinfo); +} + +Expression *Type::getTypeInfo(Scope *sc) +{ + genTypeInfo(sc); + Expression *e = VarExp::create(Loc(), vtinfo); e = e->addressOf(sc); e->type = t->vtinfo->type; // do this so we don't get redundant dereference return e; @@ -283,7 +288,7 @@ class TypeInfoDtVisitor : public Visitor dtsize_t(pdt, 0); // monitor Type *tm = d->tinfo->mutableOf(); tm = tm->merge(); - tm->getTypeInfo(NULL); + tm->genTypeInfo(NULL); dtxoff(pdt, tm->vtinfo->toSymbol(), 0); } @@ -296,7 +301,7 @@ class TypeInfoDtVisitor : public Visitor dtsize_t(pdt, 0); // monitor Type *tm = d->tinfo->mutableOf(); tm = tm->merge(); - tm->getTypeInfo(NULL); + tm->genTypeInfo(NULL); dtxoff(pdt, tm->vtinfo->toSymbol(), 0); } @@ -309,7 +314,7 @@ class TypeInfoDtVisitor : public Visitor dtsize_t(pdt, 0); // monitor Type *tm = d->tinfo->unSharedOf(); tm = tm->merge(); - tm->getTypeInfo(NULL); + tm->genTypeInfo(NULL); dtxoff(pdt, tm->vtinfo->toSymbol(), 0); } @@ -322,7 +327,7 @@ class TypeInfoDtVisitor : public Visitor dtsize_t(pdt, 0); // monitor Type *tm = d->tinfo->mutableOf(); tm = tm->merge(); - tm->getTypeInfo(NULL); + tm->genTypeInfo(NULL); dtxoff(pdt, tm->vtinfo->toSymbol(), 0); } @@ -347,7 +352,7 @@ class TypeInfoDtVisitor : public Visitor */ sd->basetype = sd->basetype->merge(); - sd->basetype->getTypeInfo(NULL); // generate vtinfo + sd->basetype->genTypeInfo(NULL); // generate vtinfo assert(sd->basetype->vtinfo); dtxoff(pdt, sd->basetype->vtinfo->toSymbol(), 0); // TypeInfo for basetype @@ -391,7 +396,7 @@ class TypeInfoDtVisitor : public Visitor if (sd->memtype) { - sd->memtype->getTypeInfo(NULL); + sd->memtype->genTypeInfo(NULL); dtxoff(pdt, sd->memtype->vtinfo->toSymbol(), 0); // TypeInfo for enum members } else @@ -428,7 +433,7 @@ class TypeInfoDtVisitor : public Visitor TypePointer *tc = (TypePointer *)d->tinfo; - tc->next->getTypeInfo(NULL); + tc->next->genTypeInfo(NULL); dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0); // TypeInfo for type being pointed to } @@ -444,7 +449,7 @@ class TypeInfoDtVisitor : public Visitor TypeDArray *tc = (TypeDArray *)d->tinfo; - tc->next->getTypeInfo(NULL); + tc->next->genTypeInfo(NULL); dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0); // TypeInfo for array of type } @@ -460,7 +465,7 @@ class TypeInfoDtVisitor : public Visitor TypeSArray *tc = (TypeSArray *)d->tinfo; - tc->next->getTypeInfo(NULL); + tc->next->genTypeInfo(NULL); dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0); // TypeInfo for array of type dtsize_t(pdt, tc->dim->toInteger()); // length @@ -478,7 +483,7 @@ class TypeInfoDtVisitor : public Visitor TypeVector *tc = (TypeVector *)d->tinfo; - tc->basetype->getTypeInfo(NULL); + tc->basetype->genTypeInfo(NULL); dtxoff(pdt, tc->basetype->vtinfo->toSymbol(), 0); // TypeInfo for equivalent static array } @@ -494,10 +499,10 @@ class TypeInfoDtVisitor : public Visitor TypeAArray *tc = (TypeAArray *)d->tinfo; - tc->next->getTypeInfo(NULL); + tc->next->genTypeInfo(NULL); dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0); // TypeInfo for array of type - tc->index->getTypeInfo(NULL); + tc->index->genTypeInfo(NULL); dtxoff(pdt, tc->index->vtinfo->toSymbol(), 0); // TypeInfo for array of type } @@ -513,7 +518,7 @@ class TypeInfoDtVisitor : public Visitor TypeFunction *tc = (TypeFunction *)d->tinfo; - tc->next->getTypeInfo(NULL); + tc->next->genTypeInfo(NULL); dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0); // TypeInfo for function return value const char *name = d->tinfo->deco; @@ -535,7 +540,7 @@ class TypeInfoDtVisitor : public Visitor TypeDelegate *tc = (TypeDelegate *)d->tinfo; - tc->next->nextOf()->getTypeInfo(NULL); + tc->next->nextOf()->genTypeInfo(NULL); dtxoff(pdt, tc->next->nextOf()->vtinfo->toSymbol(), 0); // TypeInfo for delegate return value const char *name = d->tinfo->deco; @@ -666,7 +671,7 @@ class TypeInfoDtVisitor : public Visitor // m_argi if (t) { - t->getTypeInfo(NULL); + t->genTypeInfo(NULL); dtxoff(pdt, t->vtinfo->toSymbol(), 0); } else From c3e326c04284a961dc3d4a870c8f792aaa4dc45c Mon Sep 17 00:00:00 2001 From: k-hara Date: Sat, 15 Feb 2014 00:09:12 +0900 Subject: [PATCH 2/3] Add semanticTypeInfo --- src/expression.c | 3 +- src/mtype.h | 2 ++ src/struct.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++- src/typinf.c | 19 ++---------- 4 files changed, 79 insertions(+), 20 deletions(-) diff --git a/src/expression.c b/src/expression.c index e208a5867a25..1a2adcc76825 100644 --- a/src/expression.c +++ b/src/expression.c @@ -1281,8 +1281,7 @@ bool Expression::checkPostblit(Scope *sc, Type *t) if (t->ty == Tstruct) { // Bugzilla 11395: Require TypeInfo generation for array concatenation - if (!t->vtinfo) - t->getTypeInfo(sc); + semanticTypeInfo(sc, t); StructDeclaration *sd = ((TypeStruct *)t)->sym; if (sd->postblit) diff --git a/src/mtype.h b/src/mtype.h index 84deabb201e2..d729640db2b2 100644 --- a/src/mtype.h +++ b/src/mtype.h @@ -50,6 +50,8 @@ typedef struct TYPE type; struct Symbol; class TypeTuple; +void semanticTypeInfo(Scope *sc, Type *t); + enum ENUMTY { Tarray, // slice array, aka T[] diff --git a/src/struct.c b/src/struct.c index d89af333da16..d4b52fd3f963 100644 --- a/src/struct.c +++ b/src/struct.c @@ -72,6 +72,79 @@ FuncDeclaration *search_toString(StructDeclaration *sd) return fd; } +/*************************************** + * Request additonal semantic analysis for TypeInfo generation. + */ +void semanticTypeInfo(Scope *sc, Type *t) +{ + class FullTypeInfoVisitor : public Visitor + { + public: + Scope *sc; + + void visit(Type *t) + { + Type *tb = t->toBasetype(); + if (tb != t) + tb->accept(this); + } + void visit(TypeNext *t) + { + if (t->next) + t->next->accept(this); + } + void visit(TypeBasic *t) { } + void visit(TypeVector *t) + { + t->basetype->accept(this); + } + void visit(TypeAArray *t) + { + t->index->accept(this); + visit((TypeNext *)t); + } + void visit(TypeFunction *t) + { + visit((TypeNext *)t); + // Currently TypeInfo_Function doesn't store parameter types. + } + void visit(TypeStruct *t) + { + Dsymbol *s; + StructDeclaration *sd = t->sym; + if (sd->members && + (sd->xeq && sd->xeq != sd->xerreq || + sd->xcmp && sd->xcmp != sd->xerrcmp || + (sd->postblit && !(sd->postblit->storage_class & STCdisable)) || + sd->dtor || + search_toHash(sd) || + search_toString(sd) + ) && + sd->inNonRoot()) + { + //printf("deferred sem3 for TypeInfo - sd = %s, inNonRoot = %d\n", sd->toChars(), sd->inNonRoot()); + Module::addDeferredSemantic3(sd); + } + } + void visit(TypeClass *t) { } + void visit(TypeTuple *t) + { + if (t->arguments) + { + for (size_t i = 0; i < t->arguments->dim; i++) + { + Type *tprm = (*t->arguments)[i]->type; + if (tprm) + tprm->accept(this); + } + } + } + }; + FullTypeInfoVisitor v; + v.sc = sc; + t->accept(&v); +} + /********************************* AggregateDeclaration ****************************/ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id) @@ -741,7 +814,7 @@ void StructDeclaration::semantic(Scope *sc) //if ((xeq && xeq != xerreq || xcmp && xcmp != xerrcmp) && isImportedSym(this)) // Module::addDeferredSemantic3(this); /* Defer requesting semantic3 until TypeInfo generation is actually invoked. - * See Type::getTypeInfo(). + * See semanticTypeInfo(). */ inv = buildInv(sc2); diff --git a/src/typinf.c b/src/typinf.c index 1a796d8cbf7f..62e0e1c3ac4e 100644 --- a/src/typinf.c +++ b/src/typinf.c @@ -134,22 +134,7 @@ void Type::genTypeInfo(Scope *sc) Module *m = sc->module->importedFrom; m->members->push(t->vtinfo); - if (ty == Tstruct) - { - Dsymbol *s; - StructDeclaration *sd = ((TypeStruct *)this)->sym; - if ((sd->xeq && sd->xeq != sd->xerreq || - sd->xcmp && sd->xcmp != sd->xerrcmp || - (sd->postblit && !(sd->postblit->storage_class & STCdisable)) || - sd->dtor || - search_toHash(sd) || - search_toString(sd) - ) && sd->inNonRoot()) - { - //printf("deferred sem3 for TypeInfo - sd = %s, inNonRoot = %d\n", sd->toChars(), sd->inNonRoot()); - Module::addDeferredSemantic3(sd); - } - } + semanticTypeInfo(sc, t); } else // if in obj generation pass { @@ -167,7 +152,7 @@ Expression *Type::getTypeInfo(Scope *sc) genTypeInfo(sc); Expression *e = VarExp::create(Loc(), vtinfo); e = e->addressOf(sc); - e->type = t->vtinfo->type; // do this so we don't get redundant dereference + e->type = vtinfo->type; // do this so we don't get redundant dereference return e; } From 0cf5608cd9a0041e3c47290dd52f737b40fceabd Mon Sep 17 00:00:00 2001 From: k-hara Date: Fri, 14 Feb 2014 01:01:15 +0900 Subject: [PATCH 3/3] fix Issue 12144 - Unresolved xopEquals when referenced by dynamic array constructor --- src/cast.c | 9 ++++++ src/expression.c | 47 +++++++++++++++++++++--------- test/runnable/imports/link12144a.d | 47 ++++++++++++++++++++++++++++++ test/runnable/link12144.d | 20 +++++++++++++ 4 files changed, 109 insertions(+), 14 deletions(-) create mode 100644 test/runnable/imports/link12144a.d create mode 100644 test/runnable/link12144.d diff --git a/src/cast.c b/src/cast.c index f9293263d0ed..a39ff77b0840 100644 --- a/src/cast.c +++ b/src/cast.c @@ -119,6 +119,15 @@ Expression *implicitCastTo(Expression *e, Scope *sc, Type *t) //printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", e->type, e->type ? e->type->toChars() : NULL, t->toChars()); visit((Expression *)e->inferType(t)); } + + void visit(ArrayLiteralExp *e) + { + visit((Expression *)e); + + Type *tb = result->type->toBasetype(); + if (tb->ty == Tarray) + semanticTypeInfo(sc, ((TypeDArray *)tb)->next); + } }; ImplicitCastTo v(sc, t); diff --git a/src/expression.c b/src/expression.c index 1a2adcc76825..4e758e8538d2 100644 --- a/src/expression.c +++ b/src/expression.c @@ -3979,6 +3979,8 @@ Expression *ArrayLiteralExp::semantic(Scope *sc) return new ErrorExp(); } + semanticTypeInfo(sc, t0); + return this; } @@ -4116,6 +4118,9 @@ Expression *AssocArrayLiteralExp::semantic(Scope *sc) type = new TypeAArray(tvalue, tkey); type = type->semantic(loc, sc); + + semanticTypeInfo(sc, type); + return this; } @@ -4995,8 +5000,9 @@ Expression *NewExp::semantic(Scope *sc) goto Lerr; } -//printf("NewExp: '%s'\n", toChars()); -//printf("NewExp:type '%s'\n", type->toChars()); + //printf("NewExp: '%s'\n", toChars()); + //printf("NewExp:type '%s'\n", type->toChars()); + semanticTypeInfo(sc, type); return this; @@ -5805,13 +5811,15 @@ Expression *TypeidExp::semantic(Scope *sc) } if (ea && ta->toBasetype()->ty == Tclass) - { /* Get the dynamic type, which is .classinfo + { + /* Get the dynamic type, which is .classinfo */ e = new DotIdExp(ea->loc, ea, Id::classinfo); e = e->semantic(sc); } else - { /* Get the static type + { + /* Get the static type */ e = ta->getTypeInfo(sc); if (e->loc.linnum == 0) @@ -8988,8 +8996,6 @@ DeleteExp::DeleteExp(Loc loc, Expression *e) Expression *DeleteExp::semantic(Scope *sc) { - Type *tb; - UnaExp::semantic(sc); e1 = resolveProperties(sc, e1); e1 = e1->modifiableLvalue(sc, NULL); @@ -8997,7 +9003,7 @@ Expression *DeleteExp::semantic(Scope *sc) return e1; type = Type::tvoid; - tb = e1->type->toBasetype(); + Type *tb = e1->type->toBasetype(); switch (tb->ty) { case Tclass: { TypeClass *tc = (TypeClass *)tb; @@ -9064,10 +9070,17 @@ Expression *DeleteExp::semantic(Scope *sc) break; case Tarray: - /* BUG: look for deleting arrays of structs with dtors. - */ + { + Type *tv = tb->nextOf()->baseElemOf(); + if (tv->ty == Tstruct) + { + TypeStruct *ts = (TypeStruct *)tv; + StructDeclaration *sd = ts->sym; + if (sd->dtor) + semanticTypeInfo(sc, ts); + } break; - + } default: if (e1->op == TOKindex) { @@ -10923,7 +10936,9 @@ Expression *AssignExp::semantic(Scope *sc) if (ale->e1->op == TOKerror) return ale->e1; - checkDefCtor(ale->loc, ale->e1->type->toBasetype()->nextOf()); + Type *tn = ale->e1->type->toBasetype()->nextOf(); + checkDefCtor(ale->loc, tn); + semanticTypeInfo(sc, tn); } else if (e1->op == TOKslice) { @@ -12604,7 +12619,7 @@ EqualExp::EqualExp(TOK op, Loc loc, Expression *e1, Expression *e2) assert(op == TOKequal || op == TOKnotequal); } -int needDirectEq(Type *t1, Type *t2) +int needDirectEq(Scope *sc, Type *t1, Type *t2) { assert(t1->ty == Tarray || t1->ty == Tsarray); assert(t2->ty == Tarray || t2->ty == Tsarray); @@ -12628,6 +12643,7 @@ int needDirectEq(Type *t1, Type *t2) if (t->ty != Tstruct) return false; + semanticTypeInfo(sc, t); return ((TypeStruct *)t)->sym->hasIdentityEquals; } @@ -12679,8 +12695,9 @@ Expression *EqualExp::semantic(Scope *sc) if ((t1->ty == Tarray || t1->ty == Tsarray) && (t2->ty == Tarray || t2->ty == Tsarray)) { - if (needDirectEq(t1, t2)) - { /* Rewrite as: + if (needDirectEq(sc, t1, t2)) + { + /* Rewrite as: * _ArrayEq(e1, e2) */ Expression *eq = new IdentifierExp(loc, Id::_ArrayEq); @@ -12795,6 +12812,8 @@ Expression *EqualExp::semantic(Scope *sc) e2 = e2->castTo(sc, Type::tcomplex80); } } + if (e1->type->toBasetype()->ty == Taarray) + semanticTypeInfo(sc, e1->type->toBasetype()); if (e1->type->toBasetype()->ty == Tvector) return incompatibleTypes(); diff --git a/test/runnable/imports/link12144a.d b/test/runnable/imports/link12144a.d new file mode 100644 index 000000000000..51e2989fba5c --- /dev/null +++ b/test/runnable/imports/link12144a.d @@ -0,0 +1,47 @@ +struct S1 { bool opEquals(T : typeof(this))(T) { return false; } } +struct S2 { bool opEquals(T : typeof(this))(T) { return false; } } +struct S3 { bool opEquals(T : typeof(this))(T) { return false; } } +struct S4 { bool opEquals(T : typeof(this))(T) { return false; } } +struct S5 { bool opEquals(T : typeof(this))(T) { return false; } } +struct S6 { bool opEquals(T : typeof(this))(T) { return false; } ~this(){} } +struct S7 { bool opEquals(T : typeof(this))(T) { return false; } } +struct S8 { bool opEquals(T : typeof(this))(T) { return false; } } +struct S9 { bool opEquals(T : typeof(this))(T) { return false; } } + +struct S10 { bool opEquals(T : typeof(this))(T) { return false; } } +struct S11 { int opCmp(T : typeof(this))(T) { return 0; } } +struct S12 { bool opEquals(T : typeof(this))(T) { return false; } } +struct S13 { bool opEquals(T : typeof(this))(T) { return false; } } +struct S14 { bool opEquals(T : typeof(this))(T) { return false; } } +struct S15 { bool opEquals(T : typeof(this))(T) { return false; } } +struct S16 { bool opEquals(T : typeof(this))(T) { return false; } } +struct S17 { bool opEquals(T : typeof(this))(T) { return false; } } +struct S18 { bool opEquals(T : typeof(this))(T) { return false; } } + +void fun()() +{ + { auto a = new S1[1]; } + { auto p = new S2(); } + { alias P = S3*; auto p = new P; } + { S4[int] aa; auto b = (aa == aa); } + { S5[] a; a.length = 10; } + { S6[] a; delete a; } + { S7[] a = []; } + { S8[] a = [S8.init]; } + { S9[int] aa = [1:S9.init]; } + + { auto ti = typeid(S10[int]); } + { auto ti = typeid(int[S11]); } + { auto ti = typeid(S12[]); } + { auto ti = typeid(S13*); } + { auto ti = typeid(S14[3]); } + { auto ti = typeid(S15 function()); } + { auto ti = typeid(S16 delegate()); } + { auto ti = typeid(void function(S17)); } // TypeInfo_Function doesn't have parameter types + { auto ti = typeid(void delegate(S18)); } // ditto +} + +struct B12146 +{ + bool opCmp(ubyte val) { return false; } +} diff --git a/test/runnable/link12144.d b/test/runnable/link12144.d new file mode 100644 index 000000000000..90925563e152 --- /dev/null +++ b/test/runnable/link12144.d @@ -0,0 +1,20 @@ +// COMPILE_SEPARATELY: -g +// EXTRA_SOURCES: imports/link12144a.d + +import imports.link12144a; + +void main() +{ + fun(); +} + +struct A12146 +{ + B12146[] tokens; + // implicitly generated + // bool opEquals(const ref Appender rhs) const + // will make + // tokens == rhs.tokens + // references TypeInfo of B12146 + // and it references __xopCmp +}