Commit 81e51c9d authored by Robert Bradshaw's avatar Robert Bradshaw

More nullary C++ class constructor checks.

parent b640de61
......@@ -2048,6 +2048,8 @@ class CFuncDefNode(FuncDefNode):
if self.return_type.is_array and self.visibility != 'extern':
error(self.pos,
"Function cannot return an array")
if self.return_type.is_cpp_class:
self.return_type.check_nullary_constructor(self.pos, "used as a return value")
if self.overridable and not env.is_module_scope:
if len(self.args) < 1 or not self.args[0].type.is_pyobject:
......
......@@ -3205,6 +3205,11 @@ class CppClassType(CType):
func_type = func_type.base_type
return func_type.return_type
def check_nullary_constructor(self, pos, msg="stack allocated"):
constructor = self.scope.lookup(u'<init>')
if constructor is not None and best_match([], constructor.all_alternatives()) is None:
error(pos, "C++ class must have a nullary constructor to be %s" % msg)
class TemplatePlaceholderType(CType):
......
......@@ -569,9 +569,7 @@ class Scope(object):
else:
cname = self.mangle(Naming.var_prefix, name)
if type.is_cpp_class and visibility != 'extern':
constructor = type.scope.lookup(u'<init>')
if constructor is not None and PyrexTypes.best_match([], constructor.all_alternatives()) is None:
error(pos, "C++ class must have a no-arg constructor to be stack allocated")
type.check_nullary_constructor(pos)
entry = self.declare(name, cname, type, pos, visibility)
entry.is_variable = 1
if in_pxd and visibility != 'extern':
......@@ -1782,10 +1780,7 @@ class CClassScope(ClassScope):
if visibility == 'private':
cname = c_safe_identifier(cname)
if type.is_cpp_class and visibility != 'extern':
constructor = type.scope.lookup(u'<init>')
if constructor is not None and \
PyrexTypes.best_match([], constructor.all_alternatives()) is None:
error(pos, "C++ class must have a no-arg constructor to be a member of an extension type; use a pointer instead")
type.check_nullary_constructor(pos)
self.use_utility_code(Code.UtilityCode("#include <new>"))
entry = self.declare(name, cname, type, pos, visibility)
entry.is_variable = 1
......
......@@ -390,7 +390,7 @@ class SimpleAssignmentTypeInferer(object):
types = [assmt.rhs.infer_type(scope)
for assmt in entry.cf_assignments]
if types and Utils.all(types):
entry.type = spanning_type(types, entry.might_overflow)
entry.type = spanning_type(types, entry.might_overflow, entry.pos)
else:
# FIXME: raise a warning?
# print "No assignments", entry.pos, entry
......@@ -405,10 +405,10 @@ class SimpleAssignmentTypeInferer(object):
for assmt in entry.cf_assignments
if assmt.type_dependencies(scope) == ()]
if types:
entry.type = spanning_type(types, entry.might_overflow)
entry.type = spanning_type(types, entry.might_overflow, entry.pos)
types = [assmt.infer_type(scope)
for assmt in entry.cf_assignments]
entry.type = spanning_type(types, entry.might_overflow) # might be wider...
entry.type = spanning_type(types, entry.might_overflow, entry.pos) # might be wider...
resolve_dependancy(entry)
del dependancies_by_entry[entry]
if ready_to_infer:
......@@ -438,16 +438,20 @@ def find_spanning_type(type1, type2):
return PyrexTypes.c_double_type
return result_type
def aggressive_spanning_type(types, might_overflow):
def aggressive_spanning_type(types, might_overflow, pos):
result_type = reduce(find_spanning_type, types)
if result_type.is_reference:
result_type = result_type.ref_base_type
if result_type.is_cpp_class:
result_type.check_nullary_constructor(pos)
return result_type
def safe_spanning_type(types, might_overflow):
def safe_spanning_type(types, might_overflow, pos):
result_type = reduce(find_spanning_type, types)
if result_type.is_reference:
result_type = result_type.ref_base_type
if result_type.is_cpp_class:
result_type.check_nullary_constructor(pos)
if result_type.is_pyobject:
# In theory, any specific Python type is always safe to
# infer. However, inferring str can cause some existing code
......
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