Mercurial > projects > ddmd
diff dmd/TemplateInstance.d @ 135:af1bebfd96a4 dmd2037
dmd 2.038
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Mon, 13 Sep 2010 22:19:42 +0100 |
parents | 206db751bd4c |
children | e7769d53e750 |
line wrap: on
line diff
--- a/dmd/TemplateInstance.d Sat Sep 11 13:03:39 2010 +0100 +++ b/dmd/TemplateInstance.d Mon Sep 13 22:19:42 2010 +0100 @@ -40,6 +40,7 @@ import dmd.TypeFunction; import dmd.TemplateTupleParameter; import dmd.FuncDeclaration; +import dmd.OverloadSet; import dmd.templates.Util; import dmd.backend.glue; @@ -263,6 +264,11 @@ override void semantic(Scope sc) { + semantic(sc, null); + } + + void semantic(Scope sc, Expressions fargs) + { if (global.errors) { if (!global.gag) @@ -364,6 +370,34 @@ if (!match(o1, o2, tempdecl, sc)) { goto L1; + } + } + + /* Template functions may have different instantiations based on + * "auto ref" parameters. + */ + if (fargs) + { + FuncDeclaration fd = ti.toAlias().isFuncDeclaration(); + if (fd) + { + auto fparameters = fd.getParameters(null); + size_t nfparams = Parameter.dim(fparameters); // Num function parameters + for (int i = 0; i < nfparams && i < fargs.dim; i++) + { auto fparam = Parameter.getNth(fparameters, i); + auto farg = fargs[i]; + if (fparam.storageClass & STCauto) // if "auto ref" + { + if (farg.isLvalue()) + { if (!(fparam.storageClass & STC.STCref)) + goto L1; // auto ref's don't match + } + else + { if (fparam.storageClass & STC.STCref) + goto L1; // auto ref's don't match + } + } + } } } @@ -514,6 +548,22 @@ } } } + + /* If function template declaration + */ + if (fargs && aliasdecl) + { + FuncDeclaration fd = aliasdecl.toAlias().isFuncDeclaration(); + if (fd) + { + /* Transmit fargs to type so that TypeFunction::semantic() can + * resolve any "auto ref" storage classes. + */ + auto tf = cast(TypeFunction)fd.type; + if (tf && tf.ty == TY.Tfunction) + tf.fargs = fargs; + } + } // Do semantic() analysis on template instance members version (LOG) { @@ -610,10 +660,9 @@ if (global.errors != errorsave) { error("error instantiating"); - if (tinst && !global.gag) + if (tinst) { tinst.printInstantiationTrace(); - fatal(); } errors = 1; if (global.gag) @@ -832,10 +881,82 @@ return id; } + /************************************** + * Given an error instantiating the TemplateInstance, + * give the nested TemplateInstance instantiations that got + * us here. Those are a list threaded into the nested scopes. + */ void printInstantiationTrace() { if (global.gag) - return; + return; +/+ + const int max_shown = 6; + const string format = "%s: instantiated from here: %s\n"; + + // determine instantiation depth and number of recursive instantiations + int n_instantiations = 1; + int n_totalrecursions = 0; + for (TemplateInstance cur = this; cur; cur = cur.tinst) + { + ++n_instantiations; + // If two instantiations use the same declaration, they are recursive. + // (this works even if they are instantiated from different places in the + // same template). + // In principle, we could also check for multiple-template recursion, but it's + // probably not worthwhile. + if (cur.tinst && cur.tempdecl && cur.tinst.tempdecl + && cur.tempdecl.loc.equals(cur.tinst.tempdecl.loc)) + ++n_totalrecursions; + } + + // show full trace only if it's short or verbose is on + if (n_instantiations <= max_shown || global.params.verbose) + { + for (TemplateInstance cur = this; cur; cur = cur.tinst) + { + fprintf(stdmsg, format, cur.loc.toChars(), cur.toChars()); + } + } + else if (n_instantiations - n_totalrecursions <= max_shown) + { + // By collapsing recursive instantiations into a single line, + // we can stay under the limit. + int recursionDepth=0; + for (TemplateInstance cur = this; cur; cur = cur.tinst) + { + if (cur.tinst && cur.tempdecl && cur.tinst.tempdecl + && cur.tempdecl.loc.equals(cur.tinst.tempdecl.loc)) + { + ++recursionDepth; + } + else + { + if (recursionDepth) + fprintf(stdmsg, "%s: %d recursive instantiations from here: %s\n", cur.loc.toChars(), recursionDepth+2, cur.toChars()); + else + fprintf(stdmsg,format, cur.loc.toChars(), cur.toChars()); + recursionDepth = 0; + } + } + } + else + { + // Even after collapsing the recursions, the depth is too deep. + // Just display the first few and last few instantiations. + size_t i = 0; + for (TemplateInstance cur = this; cur; cur = cur.tinst) + { + if (i == max_shown / 2) + fprintf(stdmsg," ... (%d instantiations, -v to show) ...\n", n_instantiations - max_shown); + + if (i < max_shown / 2 || + i >= n_instantiations - max_shown + max_shown / 2) + fprintf(stdmsg, format, cur.loc.toChars(), cur.toChars()); + ++i; + } + } ++/ } override void toObjFile(int multiobj) // compile to .obj file @@ -1024,9 +1145,32 @@ s = sc.search(loc, id, &scopesym); if (!s) { - error("identifier '%s' is not defined", id.toChars()); + error("template '%s' is not defined", id.toChars()); return null; } + + /* If an OverloadSet, look for a unique member that is a template declaration + */ + OverloadSet os = s.isOverloadSet(); + if (os) + { + s = null; + foreach (s2; os.a) + { + if (s2.isTemplateDeclaration()) + { + if (s) + error("ambiguous template declaration %s and %s", s.toPrettyChars(), s2.toPrettyChars()); + s = s2; + } + } + if (!s) + { + error("template '%s' is not defined", id.toChars()); + return null; + } + } + version (LOG) { printf("It's an instance of '%s' kind '%s'\n", s.toChars(), s.kind()); if (s.parent)