D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 3366 - Segfault(declaration.c) variadic template with unmatched constraint
Summary: Segfault(declaration.c) variadic template with unmatched constraint
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: Other Windows
: P2 normal
Assignee: No Owner
URL:
Keywords: ice-on-valid-code, patch
Depends on:
Blocks:
 
Reported: 2009-10-05 08:55 UTC by Haruki Shigemori
Modified: 2015-06-09 01:26 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Haruki Shigemori 2009-10-05 08:55:57 UTC
> type ice.d
class A
{
	void f(T...)() if (T.length != 1){}
}
void main()
{
	A a = new A;
	a.f!int();
}

> dmd main 2> error.txt
// dmd crash

>type error.txt
//ice.d(3): Error: template ice.A.f(T...) if (T.length != 1) declaration T is already defined
Comment 1 Don 2009-10-07 00:22:00 UTC
Reduced test case:

void f(T...)() if (T.length > 20){}
void main(){
    f!(int, int)();
}

If the tuple length isn't used in the constraint, there's no ICE, but you get the same silly error message about "T is already defined". It only happens if the function has no parameters, and when there is no match.

It thinks T is already defined, because in the code which is patched below, it's trying to pass an empty tuple for T. But it's already worked out what T must be (in this case (int, int)). So it gets horribly confused.

Root cause: deduceFunctionTemplateMatch() missed this case.

PATCH:
template.c, deduceFunctionTemplateMatch(), line 885.
----------------
    /* Check for match of function arguments with variadic template
     * parameter, such as:
     *
     * template Foo(T, A...) { void Foo(T t, A a); }
     * void main() { Foo(1,2,3); }
     */
    if (tp)				// if variadic
    {
-	if (nfparams == 0)		// if no function parameters
+	if (nfparams == 0 && nfargs!=0)		// if no function parameters
	{
	    Tuple *t = new Tuple();
	    //printf("t = %p\n", t);
	    dedargs->data[parameters->dim - 1] = (void *)t;
	    declareParameter(paramscope, tp, t);
	    goto L2;
	}
Comment 2 Walter Bright 2009-10-13 13:49:05 UTC
Fixed dmd 1.049 and 2.034