From 918636ff03e4744828da49cf5d82731b7e16c1d8 Mon Sep 17 00:00:00 2001 From: Bruno da Silva de Oliveira Date: Sun, 10 Aug 2003 23:21:25 +0000 Subject: [PATCH] - Fixed a bug where in some classes the virtual methods were being definied incorrectly [SVN r19525] --- pyste/NEWS | 3 +++ pyste/src/Pyste/ClassExporter.py | 41 +++++++++++++++++++++----------- pyste/src/Pyste/CppParser.py | 1 - pyste/src/Pyste/declarations.py | 10 +++++++- pyste/src/Pyste/pyste.py | 2 +- pyste/tests/inherit2.h | 3 +++ pyste/tests/inherit2.pyste | 5 ++-- pyste/tests/inherit2UT.py | 2 ++ pyste/tests/inherit3.h | 3 ++- pyste/tests/inherit3UT.py | 20 +++++++++------- 10 files changed, 61 insertions(+), 29 deletions(-) diff --git a/pyste/NEWS b/pyste/NEWS index 5ba48563..1f0b358b 100644 --- a/pyste/NEWS +++ b/pyste/NEWS @@ -7,6 +7,9 @@ solution. Automatically convert \ to / in Windows systems before passing the paths to gccxml. +Fixed a bug reported by Prabhu Ramachandran, where in some classes the virtual +methods were being definied incorrectly. Thanks a lot Prabhu! + 7 July 2003 Applied 2 patches by Prabhu Ramachandran: a fix in the new --multiple method, and two new functions "hold_with_shared_ptr" and its counterpart for auto_ptr. diff --git a/pyste/src/Pyste/ClassExporter.py b/pyste/src/Pyste/ClassExporter.py index 6b8f389c..93073b9a 100644 --- a/pyste/src/Pyste/ClassExporter.py +++ b/pyste/src/Pyste/ClassExporter.py @@ -113,6 +113,9 @@ class ClassExporter(Exporter): valid_members = (Method, ClassVariable, NestedClass, ClassEnumeration) # these don't work INVESTIGATE!: (ClassOperator, ConverterOperator) fullnames = [x.FullName() for x in self.class_] + pointers = [x.PointerDeclaration(True) for x in self.class_ if isinstance(x, Method)] + fullnames = dict([(x, None) for x in fullnames]) + pointers = dict([(x, None) for x in pointers]) for level in self.class_.hierarchy: level_exported = False for base in level: @@ -122,7 +125,12 @@ class ClassExporter(Exporter): if type(member) in valid_members: member_copy = copy.deepcopy(member) member_copy.class_ = self.class_.FullName() - if member_copy.FullName() not in fullnames: + if isinstance(member_copy, Method): + pointer = member_copy.PointerDeclaration(True) + if pointer not in pointers: + self.class_.AddMember(member) + pointers[pointer] = None + elif member_copy.FullName() not in fullnames: self.class_.AddMember(member) else: level_exported = True @@ -646,7 +654,7 @@ class _VirtualWrapperGenerator(object): 'Generates code to export the virtual methods of the given class' def __init__(self, class_, bases, info): - self.class_ = class_ + self.class_ = copy.deepcopy(class_) self.bases = bases[:] self.info = info self.wrapper_name = makeid(class_.FullName()) + '_Wrapper' @@ -703,7 +711,7 @@ class _VirtualWrapperGenerator(object): if not wrapper: # return the default implementation of the class if method.abstract: - s = indent2 + 'PyErr_SetString(PyExc_RuntimeError, "abstract function called");\n' +\ + s = indent2 + 'PyErr_SetString(PyExc_RuntimeError, "pure virtual function called");\n' +\ indent2 + 'throw_error_already_set();\n' if method.result.FullName() != 'void': s += indent2 + 'return %s();\n' % method.result.FullName() @@ -789,14 +797,7 @@ class _VirtualWrapperGenerator(object): return type(m) is Method and \ m.virtual and \ m.visibility != Scope.private - - all_methods = [x for x in self.class_ if IsVirtual(x)] - for base in self.bases: - base_methods = [copy.deepcopy(x) for x in base if IsVirtual(x)] - for base_method in base_methods: - base_method.class_ = self.class_.FullName() - all_methods.append(base_method) - + # extract the virtual methods, avoiding duplications. The duplication # must take in account the full signature without the class name, so # that inherited members are correctly excluded if the subclass overrides @@ -811,10 +812,22 @@ class _VirtualWrapperGenerator(object): else: result = '' params = ', '.join([x.FullName() for x in method.parameters]) - return '%s %s(%s) %s' % (result, method.name, params, const) - - self.virtual_methods = [] + return '%s %s(%s) %s' % (result, method.name, params, const) + already_added = {} + self.virtual_methods = [] + for member in self.class_: + if IsVirtual(member): + already_added[MethodSig(member)] = None + self.virtual_methods.append(member) + + for base in self.bases: + base_methods = [copy.deepcopy(x) for x in base if IsVirtual(x)] + for base_method in base_methods: + self.class_.AddMember(base_method) + + all_methods = [x for x in self.class_ if IsVirtual(x)] + for member in all_methods: sig = MethodSig(member) if IsVirtual(member) and not sig in already_added: diff --git a/pyste/src/Pyste/CppParser.py b/pyste/src/Pyste/CppParser.py index e2ca0758..def0dfc4 100644 --- a/pyste/src/Pyste/CppParser.py +++ b/pyste/src/Pyste/CppParser.py @@ -152,7 +152,6 @@ class CppParser: cache_file = os.path.splitext(interface_name)[0] + '.pystec' cache_file = os.path.join(self.cache_dir, cache_file) return cache_file - def GetCache(self, header, interface, tail): diff --git a/pyste/src/Pyste/declarations.py b/pyste/src/Pyste/declarations.py index 64cf59bf..6111f6f5 100644 --- a/pyste/src/Pyste/declarations.py +++ b/pyste/src/Pyste/declarations.py @@ -123,7 +123,7 @@ class Class(Declaration): m.is_unique = False else: member.is_unique = True - self.__member_names[member.name] = 1 + self.__member_names[member.name] = 1 self.__members.append(member) if isinstance(member, ClassOperator): self.operator[member.name] = member @@ -329,6 +329,10 @@ class Constructor(Method): return param_reference and class_as_param and param.const and is_public + def PointerDeclaration(self, force=False): + return '' + + #============================================================================== # Destructor #============================================================================== @@ -342,6 +346,10 @@ class Destructor(Method): return self.class_ + '::~' + self.name + def PointerDeclaration(self, force=False): + return '' + + #============================================================================== # ClassOperator diff --git a/pyste/src/Pyste/pyste.py b/pyste/src/Pyste/pyste.py index e6ce18c6..87a16151 100644 --- a/pyste/src/Pyste/pyste.py +++ b/pyste/src/Pyste/pyste.py @@ -43,7 +43,7 @@ from CppParser import CppParser, CppParserError import time from declarations import Typedef -__VERSION__ = '0.9.11' +__VERSION__ = '0.9.12' def RecursiveIncludes(include): 'Return a list containg the include dir and all its subdirectories' diff --git a/pyste/tests/inherit2.h b/pyste/tests/inherit2.h index 40aed2f2..f1a7195a 100644 --- a/pyste/tests/inherit2.h +++ b/pyste/tests/inherit2.h @@ -4,12 +4,15 @@ struct A { int x; int getx() { return x; } + int foo() { return 0; } + int foo(int x) { return x; } }; struct B : A { int y; int gety() { return y; } + int foo() { return 1; } }; struct C : B diff --git a/pyste/tests/inherit2.pyste b/pyste/tests/inherit2.pyste index df7d7454..38082139 100644 --- a/pyste/tests/inherit2.pyste +++ b/pyste/tests/inherit2.pyste @@ -1,3 +1,2 @@ -header = AllFromHeader('inherit2.h') -exclude(header.A) -exclude(header.C) +Class('inherit2::B', 'inherit2.h') +Class('inherit2::D', 'inherit2.h') diff --git a/pyste/tests/inherit2UT.py b/pyste/tests/inherit2UT.py index 1ca08705..22985b1c 100644 --- a/pyste/tests/inherit2UT.py +++ b/pyste/tests/inherit2UT.py @@ -16,6 +16,8 @@ class InheritExampleTest(unittest.TestCase): self.assertEqual(d.gety(), 15) self.assertEqual(d.getz(), 10) self.assertEqual(d.getw(), 5) + self.assertEqual(b.foo(), 1) + self.assertEqual(b.foo(3), 3) def wrong(): return b.getw() diff --git a/pyste/tests/inherit3.h b/pyste/tests/inherit3.h index d296b5cf..8385fe50 100644 --- a/pyste/tests/inherit3.h +++ b/pyste/tests/inherit3.h @@ -5,7 +5,8 @@ struct A { struct X { int y; }; int x; - int foo() { return 1; } + virtual int foo() { return 0; } + virtual int foo(int x) { return x; } A operator+(A o) const { A r; diff --git a/pyste/tests/inherit3UT.py b/pyste/tests/inherit3UT.py index 53b9a947..78cd7c3f 100644 --- a/pyste/tests/inherit3UT.py +++ b/pyste/tests/inherit3UT.py @@ -4,16 +4,20 @@ from _inherit3 import * class testInherit3(unittest.TestCase): def testIt(self): - def testClass(class_): - c = class_() + def testInst(c): self.assertEqual(c.x, 0) - self.assertEqual(c.foo(), 1) - x = class_.X() + self.assertEqual(c.foo(3), 3) + x = c.X() self.assertEqual(x.y, 0) - self.assertEqual(class_.E.i, 0) - self.assertEqual(class_.E.j, 1) - testClass(B) - testClass(C) + self.assertEqual(c.E.i, 0) + self.assertEqual(c.E.j, 1) + b = B() + c = C() + testInst(b) + testInst(c) + self.assertEqual(b.foo(), 1) + self.assertEqual(c.foo(), 0) + if __name__ == '__main__': unittest.main()