Bug creation and email sending has been disabled, file new bugs at gcc.gnu.org/bugzilla
Bug 36 - Templates declared in functions have wrong scope
Summary: Templates declared in functions have wrong scope
Status: RESOLVED FIXED
Alias: None
Product: GDC
Classification: Unclassified
Component: gdc (show other bugs)
Version: development
Hardware: x86_64 Linux
: --- major
Assignee: Iain Buclaw
URL:
Depends on:
Blocks:
 
Reported: 2013-01-19 12:23 CET by Johannes Pfau
Modified: 2013-03-01 17:20 CET (History)
1 user (show)

See Also:


Attachments
Proposed partial patch (1.41 KB, patch)
2013-01-19 12:23 CET, Johannes Pfau
Details | Diff
test case 1 (232 bytes, text/x-dsrc)
2013-01-19 12:23 CET, Johannes Pfau
Details
test case 2 (554 bytes, text/x-dsrc)
2013-01-19 12:24 CET, Johannes Pfau
Details
test case 2 (264 bytes, text/x-dsrc)
2013-01-19 12:25 CET, Johannes Pfau
Details
test 3a (242 bytes, text/x-dsrc)
2013-01-19 12:25 CET, Johannes Pfau
Details
test 3b (68 bytes, text/x-dsrc)
2013-01-19 12:26 CET, Johannes Pfau
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Johannes Pfau 2013-01-19 12:23:34 CET
Created attachment 27 [details]
Proposed partial patch

Template instances of templates declared in functions must have their scope set to that function. (Template instances with nested args have even more strict requirements, their scope should be the scope where they are instantiated).

Here's a pseudo-example:
-------------------
void func()
{
    void nested(){}
    void nestedTemplate()()
    {nested();}

    void nested2()
    {nestedTemplate()} //<--creates instance. scope should be func,
    //currently is module scope
}
-------------------

There are two reasons for this problem:
TemplateInstances created in functions are added to the Module->members array by the frontend.
TemplateInstances created in structs/classes/interfaces are added to the struct/class/interface members array and work fine.

The other reason is the way gdc sets the scope of functions/classes/etc: The scope is set by FuncDeclaration::toObjFile which calls irs->startScope(); then emits it's member functions, then calls irs->endScope();

So the simplest solution would be to add code to toObjFile which emits templates instantiated in that function. This is what the attached patch does (it also makes sure that the TemplateInstace->toObjFile method is not called from the modules genobjfile first) and I'll probably file a pull request for it.

But this solution is incomplete. It fixes test case 1&2 which is already good. But it can't fix test case 3: There's a fundamental problem:

We require the S!(int) instance to be output from parseJSON(test3a) to set the scope correctly. This means we have to call S!(int)->toObjFile from parseJSON->toObjFile.
But when the S!int instance is actually created in module test3b, parseJSON->toObjFile has already been called when compiling test3a and we can't call parseJSON->toObjFile in module test3b! So with the current way of pushing scopes there's no way to implement this correctly!

BTW: DMD does not push any scopes in it's FuncDeclaration::toObjFile and therefore avoids this problem.
Comment 1 Johannes Pfau 2013-01-19 12:23:57 CET
Created attachment 28 [details]
test case 1
Comment 2 Johannes Pfau 2013-01-19 12:24:17 CET
Created attachment 29 [details]
test case 2
Comment 3 Johannes Pfau 2013-01-19 12:25:15 CET
Created attachment 30 [details]
test case 2
Comment 4 Johannes Pfau 2013-01-19 12:25:56 CET
Created attachment 31 [details]
test 3a
Comment 5 Johannes Pfau 2013-01-19 12:26:17 CET
Created attachment 32 [details]
test 3b