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)