diff --git a/src/dmd/dsymbolsem.d b/src/dmd/dsymbolsem.d index 3ade244db26f..481831df7e63 100644 --- a/src/dmd/dsymbolsem.d +++ b/src/dmd/dsymbolsem.d @@ -2719,6 +2719,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor { if (tempdecl.ident == Id.RTInfo) Type.rtinfo = tempdecl; + + if (tempdecl.ident == Id.RTTypeid) + Type.rttypeid = tempdecl; } /* Remember Scope for later instantiations, but make diff --git a/src/dmd/frontend.h b/src/dmd/frontend.h index 34b3c3fa0885..48414b14c7f0 100644 --- a/src/dmd/frontend.h +++ b/src/dmd/frontend.h @@ -1249,6 +1249,7 @@ class Type : public ASTNode static ClassDeclaration* typeinfoshared; static ClassDeclaration* typeinfowild; static TemplateDeclaration* rtinfo; + static TemplateDeclaration* rttypeid; static Type* basic[46LLU]; virtual const char* kind() const; Type* copy() const; @@ -7130,6 +7131,7 @@ struct Id static Identifier* outer; static Identifier* Exception; static Identifier* RTInfo; + static Identifier* RTTypeid; static Identifier* Throwable; static Identifier* Error; static Identifier* withSym; diff --git a/src/dmd/id.d b/src/dmd/id.d index 2e3be17228b4..a7f1dcc5acd6 100644 --- a/src/dmd/id.d +++ b/src/dmd/id.d @@ -107,6 +107,7 @@ immutable Msgtable[] msgtable = { "outer" }, { "Exception" }, { "RTInfo" }, + { "RTTypeid" }, { "Throwable" }, { "Error" }, { "withSym", "__withSym" }, diff --git a/src/dmd/mtype.d b/src/dmd/mtype.d index b83c804459fd..35dcd8b7a6cc 100644 --- a/src/dmd/mtype.d +++ b/src/dmd/mtype.d @@ -473,6 +473,7 @@ extern (C++) abstract class Type : ASTNode extern (C++) __gshared ClassDeclaration typeinfowild; extern (C++) __gshared TemplateDeclaration rtinfo; + extern (C++) __gshared TemplateDeclaration rttypeid; extern (C++) __gshared Type[TMAX] basic; diff --git a/src/dmd/typinf.d b/src/dmd/typinf.d index d1a254f8b51c..5673caf2724f 100644 --- a/src/dmd/typinf.d +++ b/src/dmd/typinf.d @@ -11,15 +11,21 @@ module dmd.typinf; +import dmd.arraytypes; import dmd.declaration; import dmd.dmodule; import dmd.dscope; import dmd.dclass; import dmd.dstruct; +import dmd.dsymbolsem; +import dmd.dtemplate; import dmd.errors; +import dmd.expressionsem; import dmd.globals; import dmd.gluelayer; import dmd.mtype; +import dmd.semantic2; +import dmd.semantic3; import dmd.visitor; import core.stdc.stdio; @@ -56,16 +62,47 @@ void genTypeInfo(Loc loc, Type torig, Scope* sc) Type t = torig.merge2(); // do this since not all Type's are merge'd if (!t.vtinfo) { - if (t.isShared()) // does both 'shared' and 'shared const' - t.vtinfo = TypeInfoSharedDeclaration.create(t); - else if (t.isConst()) - t.vtinfo = TypeInfoConstDeclaration.create(t); - else if (t.isImmutable()) - t.vtinfo = TypeInfoInvariantDeclaration.create(t); - else if (t.isWild()) - t.vtinfo = TypeInfoWildDeclaration.create(t); - else - t.vtinfo = getTypeInfoDeclaration(t); + if (Type.rttypeid) + { + // Evaluate: RTTypeid!t + auto tiargs = new Objects(); + tiargs.push(t); + auto ti = new TemplateInstance(loc, Type.rttypeid, tiargs); + + Scope* sc3 = ti.tempdecl._scope.startCTFE(); + sc3.tinst = sc.tinst; + sc3.minst = sc.minst; + ti.dsymbolSemantic(sc3); + ti.semantic2(sc3); + ti.semantic3(sc3); + auto e = symbolToExp(ti.toAlias(), Loc.initial, sc3, false); + + sc3.endCTFE(); + + e = e.ctfeInterpret(); + t.vtinfo = cast(TypeInfoDeclaration) e.isVarExp(); + /* Save this for when RTTypeid is fully operational + if (!t.vtinfo) + { + .error(loc, "`object.RTTypeid!T` did not return a TypeInfo variable"); + fatal(); + } + */ + } + + if (!t.vtinfo) + { + if (t.isShared()) // does both 'shared' and 'shared const' + t.vtinfo = TypeInfoSharedDeclaration.create(t); + else if (t.isConst()) + t.vtinfo = TypeInfoConstDeclaration.create(t); + else if (t.isImmutable()) + t.vtinfo = TypeInfoInvariantDeclaration.create(t); + else if (t.isWild()) + t.vtinfo = TypeInfoWildDeclaration.create(t); + else + t.vtinfo = getTypeInfoDeclaration(t); + } assert(t.vtinfo); /* If this has a custom implementation in std/typeinfo, then