diff options
Diffstat (limited to 'Cython/Compiler/ExprNodes.py')
-rw-r--r-- | Cython/Compiler/ExprNodes.py | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 56e490490..98a41f9b0 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -2288,6 +2288,8 @@ class NameNode(AtomicExprNode): entry = self.entry if not entry: return "<error>" # There was an error earlier + if self.entry.is_cpp_optional and not self.is_target: + return "(*%s)" % entry.cname return entry.cname def generate_result_code(self, code): @@ -2897,6 +2899,7 @@ class CppIteratorNode(ExprNode): # Created at the analyse_types stage by IteratorNode cpp_sequence_cname = None cpp_attribute_op = "." + extra_dereference = "" is_temp = True subexprs = ['sequence'] @@ -2921,6 +2924,8 @@ class CppIteratorNode(ExprNode): return self iter_type = begin.type.return_type if iter_type.is_cpp_class: + if env.directives['cpp_locals']: + self.extra_dereference = "*" if env.lookup_operator_for_types( self.pos, "!=", @@ -2965,7 +2970,7 @@ class CppIteratorNode(ExprNode): # make the temp a pointer so we are not sensitive to users reassigning # the pointer than it came from temp_type = PyrexTypes.CPtrType(sequence_type.ref_base_type) - if temp_type.is_ptr: + if temp_type.is_ptr or code.globalstate.directives['cpp_locals']: self.cpp_attribute_op = "->" # 3) (otherwise) sequence comes from a function call or similar, so we must # create a temp to store it in @@ -2979,14 +2984,16 @@ class CppIteratorNode(ExprNode): def generate_iter_next_result_code(self, result_name, code): # end call isn't cached to support containers that allow adding while iterating # (much as this is usually a bad idea) - code.putln("if (!(%s != %s%send())) break;" % ( + code.putln("if (!(%s%s != %s%send())) break;" % ( + self.extra_dereference, self.result(), self.cpp_sequence_cname or self.sequence.result(), self.cpp_attribute_op)) - code.putln("%s = *%s;" % ( + code.putln("%s = *%s%s;" % ( result_name, + self.extra_dereference, self.result())) - code.putln("++%s;" % self.result()) + code.putln("++%s%s;" % (self.extra_dereference, self.result())) def free_temps(self, code): if self.cpp_sequence_cname: @@ -7162,9 +7169,6 @@ class AttributeNode(ExprNode): self.op = "->" elif obj_type.is_reference and obj_type.is_fake_reference: self.op = "->" - elif (obj_type.is_cpp_class and (self.obj.is_name or self.obj.is_attribute) and - self.obj.entry and self.obj.entry.is_cpp_optional): - self.op = "->" else: self.op = "." if obj_type.has_attributes: @@ -7297,9 +7301,14 @@ class AttributeNode(ExprNode): return NameNode.is_ephemeral(self) def calculate_result_code(self): - #print "AttributeNode.calculate_result_code:", self.member ### - #print "...obj node =", self.obj, "code", self.obj.result() ### - #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ### + result = self.calculate_access_code() + if self.entry and self.entry.is_cpp_optional and not self.is_target: + result = "(*%s)" % result + return result + + def calculate_access_code(self): + # Does the job of calculate_result_code but doesn't dereference cpp_optionals + # Therefore allowing access to the holder variable obj = self.obj obj_code = obj.result_as(obj.type) #print "...obj_code =", obj_code ### @@ -7374,7 +7383,12 @@ class AttributeNode(ExprNode): '%s' '}' % (self.result(), code.error_goto(self.pos))) elif self.entry.is_cpp_optional and self.initialized_check: - unbound_check_code = self.type.cpp_optional_check_for_null_code(self.result()) + if self.is_target: + undereferenced_result = self.result() + else: + assert not self.is_temp # calculate_access_code() only makes sense for non-temps + undereferenced_result = self.calculate_access_code() + unbound_check_code = self.type.cpp_optional_check_for_null_code(undereferenced_result) code.put_error_if_unbound(self.pos, self.entry, unbound_check_code=unbound_check_code) else: # result_code contains what is needed, but we may need to insert |