fix vtable type casting in Py3 to support strict aliasing
authorStefan Behnel <scoder@users.berlios.de>
Sat, 28 Feb 2009 07:43:22 +0000 (08:43 +0100)
committerStefan Behnel <scoder@users.berlios.de>
Sat, 28 Feb 2009 07:43:22 +0000 (08:43 +0100)
Cython/Compiler/ModuleNode.py
Cython/Compiler/PyrexTypes.py

index fa1695eb74e286e20c103f61cbc41e56ca781567..bee9a4242f1b3bfd712841992dc70b780110c1ee 100644 (file)
@@ -1967,13 +1967,27 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                         type.vtable_cname,
                         Naming.obj_base_cname,
                         type.base_type.vtabptr_cname))
-            for meth_entry in type.scope.cfunc_entries:
-                if meth_entry.func_cname:
-                    code.putln(
-                        "*(void(**)(void))&%s.%s = (void(*)(void))%s;" % (
-                            type.vtable_cname,
-                            meth_entry.cname,
-                            meth_entry.func_cname))
+
+            c_method_entries = [
+                entry for entry in type.scope.cfunc_entries
+                if entry.func_cname ]
+            code.putln('#if PY_MAJOR_VERSION >= 3')
+            for meth_entry in c_method_entries:
+                cast = meth_entry.type.signature_cast_string()
+                code.putln(
+                    "%s.%s = %s%s;" % (
+                        type.vtable_cname,
+                        meth_entry.cname,
+                        cast,
+                        meth_entry.func_cname))
+            code.putln('#else')
+            for meth_entry in c_method_entries:
+                code.putln(
+                    "*(void(**)(void))&%s.%s = (void(*)(void))%s;" % (
+                        type.vtable_cname,
+                        meth_entry.cname,
+                        meth_entry.func_cname))
+            code.putln('#endif')
     
     def generate_typeptr_assignment_code(self, entry, code):
         # Generate code to initialise the typeptr of an extension
index fe8b14e115a6d469b49c035cba914640de400289..aeea3c506ca27ef4bea996acd3d09217f8e4bed0 100644 (file)
@@ -874,7 +874,8 @@ class CFuncType(CType):
             and not (self.nogil and not other_type.nogil)
     
     def declaration_code(self, entity_code, 
-            for_display = 0, dll_linkage = None, pyrex = 0):
+                         for_display = 0, dll_linkage = None, pyrex = 0,
+                         with_calling_convention = 1):
         arg_decl_list = []
         for arg in self.args[:len(self.args)-self.optional_arg_count]:
             arg_decl_list.append(
@@ -900,10 +901,13 @@ class CFuncType(CType):
                 " except *" # ignored
             if self.nogil:
                 trailer += " nogil"
-        cc = self.calling_convention_prefix()
-        if (not entity_code and cc) or entity_code.startswith("*"):
-            entity_code = "(%s%s)" % (cc, entity_code)
-            cc = ""
+        if not with_calling_convention:
+            cc = ''
+        else:
+            cc = self.calling_convention_prefix()
+            if (not entity_code and cc) or entity_code.startswith("*"):
+                entity_code = "(%s%s)" % (cc, entity_code)
+                cc = ""
         return self.return_type.declaration_code(
             "%s%s(%s)%s" % (cc, entity_code, arg_decl_code, trailer),
             for_display, dll_linkage, pyrex)
@@ -916,6 +920,10 @@ class CFuncType(CType):
         s = self.declaration_code("")
         return s
 
+    def signature_cast_string(self):
+        s = self.declaration_code("(*)", with_calling_convention=False)
+        return '(%s)' % s
+
 
 class CFuncTypeArg:
     #  name       string