Commit 40f879db authored by root's avatar root

Added reference tracking to template arguments. Not fully tested, complete solution to ticket #838.

parent 5284bb23
# Can be enabled at the command line with --debug-xxx. # Can be enabled at the command line with --debug-xxx.
debug_disposal_code = 0 debug_disposal_code = 0
debug_temp_alloc = 0 debug_temp_alloc = 1
debug_coercion = 0 debug_coercion = 0
# Write comments into the C code that show where temporary variables # Write comments into the C code that show where temporary variables
......
...@@ -1110,7 +1110,7 @@ class TemplatedTypeNode(CBaseTypeNode): ...@@ -1110,7 +1110,7 @@ class TemplatedTypeNode(CBaseTypeNode):
error(template_node.pos, "unknown type in template argument") error(template_node.pos, "unknown type in template argument")
return error_type return error_type
template_types.append(type) template_types.append(type)
self.type = base_type.specialize_here(self.pos, template_types) self.type = base_type.specialize_here(self.pos, template_types, is_reference=self.is_reference)
elif base_type.is_pyobject: elif base_type.is_pyobject:
# Buffer # Buffer
...@@ -2821,7 +2821,6 @@ class DefNode(FuncDefNode): ...@@ -2821,7 +2821,6 @@ class DefNode(FuncDefNode):
error(arg.pos, "Only Python type arguments can have 'not None'") error(arg.pos, "Only Python type arguments can have 'not None'")
if arg.or_none: if arg.or_none:
error(arg.pos, "Only Python type arguments can have 'or None'") error(arg.pos, "Only Python type arguments can have 'or None'")
env.fused_to_specific = f2s env.fused_to_specific = f2s
def analyse_signature(self, env): def analyse_signature(self, env):
......
...@@ -2168,7 +2168,8 @@ def p_buffer_or_template(s, base_type_node, templates): ...@@ -2168,7 +2168,8 @@ def p_buffer_or_template(s, base_type_node, templates):
result = Nodes.TemplatedTypeNode(pos, result = Nodes.TemplatedTypeNode(pos,
positional_args = positional_args, positional_args = positional_args,
keyword_args = keyword_dict, keyword_args = keyword_dict,
base_type_node = base_type_node) base_type_node = base_type_node,
is_reference = (s.sy == '&'))
return result return result
def p_bracketed_base_type(s, base_type_node, nonempty, empty): def p_bracketed_base_type(s, base_type_node, nonempty, empty):
...@@ -2392,7 +2393,7 @@ def p_c_array_declarator(s, base): ...@@ -2392,7 +2393,7 @@ def p_c_array_declarator(s, base):
s.expect(']') s.expect(']')
return Nodes.CArrayDeclaratorNode(pos, base = base, dimension = dim) return Nodes.CArrayDeclaratorNode(pos, base = base, dimension = dim)
def p_c_func_declarator(s, pos, ctx, base, cmethod_flag): def p_c_func_declarator(s, pos, ctx, base, cmethod_flag):
# Opening paren has already been skipped # Opening paren has already been skipped
args = p_c_arg_list(s, ctx, cmethod_flag = cmethod_flag, args = p_c_arg_list(s, ctx, cmethod_flag = cmethod_flag,
nonempty_declarators = 0) nonempty_declarators = 0)
......
...@@ -12,7 +12,7 @@ from .Code import UtilityCode, LazyUtilityCode, TempitaUtilityCode ...@@ -12,7 +12,7 @@ from .Code import UtilityCode, LazyUtilityCode, TempitaUtilityCode
from . import StringEncoding from . import StringEncoding
from . import Naming from . import Naming
from .Errors import error from .Errors import error, warning
class BaseType(object): class BaseType(object):
...@@ -3217,7 +3217,7 @@ class CppClassType(CType): ...@@ -3217,7 +3217,7 @@ class CppClassType(CType):
subtypes = ['templates'] subtypes = ['templates']
def __init__(self, name, scope, cname, base_classes, templates = None, template_type = None): def __init__(self, name, scope, cname, base_classes, templates = None, template_type = None, is_reference = False):
self.name = name self.name = name
self.cname = cname self.cname = cname
self.scope = scope self.scope = scope
...@@ -3227,6 +3227,7 @@ class CppClassType(CType): ...@@ -3227,6 +3227,7 @@ class CppClassType(CType):
self.template_type = template_type self.template_type = template_type
self.specializations = {} self.specializations = {}
self.is_cpp_string = cname in cpp_string_conversions self.is_cpp_string = cname in cpp_string_conversions
self.is_reference = is_reference
def use_conversion_utility(self, from_or_to): def use_conversion_utility(self, from_or_to):
pass pass
...@@ -3286,6 +3287,10 @@ class CppClassType(CType): ...@@ -3286,6 +3287,10 @@ class CppClassType(CType):
tags = type_identifier(self), tags = type_identifier(self),
else: else:
cls = self.cname[5:] cls = self.cname[5:]
if self.is_reference:
warning("dwqkokw", -1)
print "warned"
cname = '__pyx_convert_%s_from_py_%s' % (cls, '__and_'.join(tags)) cname = '__pyx_convert_%s_from_py_%s' % (cls, '__and_'.join(tags))
context = { context = {
'template_type_declarations': '\n'.join(declarations), 'template_type_declarations': '\n'.join(declarations),
...@@ -3350,7 +3355,7 @@ class CppClassType(CType): ...@@ -3350,7 +3355,7 @@ class CppClassType(CType):
T.get_fused_types(result, seen) T.get_fused_types(result, seen)
return result return result
def specialize_here(self, pos, template_values = None): def specialize_here(self, pos, template_values = None, is_reference = False):
if not self.is_template_type(): if not self.is_template_type():
error(pos, "'%s' type is not a template" % self) error(pos, "'%s' type is not a template" % self)
return error_type return error_type
...@@ -3366,19 +3371,19 @@ class CppClassType(CType): ...@@ -3366,19 +3371,19 @@ class CppClassType(CType):
"Python object type '%s' cannot be used as a template argument" % value) "Python object type '%s' cannot be used as a template argument" % value)
if has_object_template_param: if has_object_template_param:
return error_type return error_type
return self.specialize(dict(zip(self.templates, template_values))) return self.specialize(dict(zip(self.templates, template_values)), is_reference)
def specialize(self, values): def specialize(self, values, is_reference = False):
if not self.templates and not self.namespace: if not self.templates and not self.namespace:
return self return self
if self.templates is None: if self.templates is None:
self.templates = [] self.templates = []
key = tuple(values.items()) key = tuple(values.items() + [is_reference]) # Python 3?
if key in self.specializations: if key in self.specializations:
return self.specializations[key] return self.specializations[key]
template_values = [t.specialize(values) for t in self.templates] template_values = [t.specialize(values) for t in self.templates]
specialized = self.specializations[key] = \ specialized = self.specializations[key] = \
CppClassType(self.name, None, self.cname, [], template_values, template_type=self) CppClassType(self.name, None, self.cname, [], template_values, template_type=self, is_reference=is_reference)
# Need to do these *after* self.specializations[key] is set # Need to do these *after* self.specializations[key] is set
# to avoid infinite recursion on circular references. # to avoid infinite recursion on circular references.
specialized.base_classes = [b.specialize(values) for b in self.base_classes] specialized.base_classes = [b.specialize(values) for b in self.base_classes]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment