diff options
-rw-r--r-- | CHANGES | 20 | ||||
-rw-r--r-- | cpp/src/Slice/PythonUtil.cpp | 43 | ||||
-rw-r--r-- | py/python/Ice.py | 7 |
3 files changed, 66 insertions, 4 deletions
@@ -109,6 +109,26 @@ C# Changes Python Changes ============== +- Fixed a bug in the constructors of user-defined types that have + structures as data members. Consider this example: + + // Slice + struct Point { + int x; + int y; + }; + struct Event { + Point location; + ... + }; + + The Event constructor supplied a default instance of the Point + member if the caller did not supply one. However, this default + instance was unintentionally shared by all Event objects that + omitted a value for the Point member during construction. The + generated code now ensures that each instance of Event assigns a + new instance of Point. + - Fixed bugs in getImplicitContext related to using it when an implicit context had not been set. diff --git a/cpp/src/Slice/PythonUtil.cpp b/cpp/src/Slice/PythonUtil.cpp index cb9e024717a..1917192ae29 100644 --- a/cpp/src/Slice/PythonUtil.cpp +++ b/cpp/src/Slice/PythonUtil.cpp @@ -153,6 +153,11 @@ private: }; typedef list<MemberInfo> MemberInfoList; + // + // Write a member assignment statement for a constructor. + // + void writeAssign(const MemberInfo&); + void collectClassMembers(const ClassDefPtr&, MemberInfoList&, bool); void collectExceptionMembers(const ExceptionPtr&, MemberInfoList&, bool); @@ -476,7 +481,7 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) { if(!q->inherited) { - _out << nl << "self." << q->fixedName << " = " << q->fixedName;; + writeAssign(*q); } } } @@ -982,7 +987,7 @@ Slice::Python::CodeVisitor::visitExceptionStart(const ExceptionPtr& p) { if(!q->inherited) { - _out << nl << "self." << q->fixedName << " = " << q->fixedName;; + writeAssign(*q); } } } @@ -1101,7 +1106,7 @@ Slice::Python::CodeVisitor::visitStructStart(const StructPtr& p) _out.inc(); for(r = memberList.begin(); r != memberList.end(); ++r) { - _out << nl << "self." << r->fixedName << " = " << r->fixedName; + writeAssign(*r); } _out.dec(); @@ -1629,7 +1634,13 @@ Slice::Python::CodeVisitor::writeDefaultValue(const TypePtr& p) StructPtr st = StructPtr::dynamicCast(p); if(st) { - _out << getSymbol(st) << "()"; + // + // We cannot emit a call to the struct's constructor here because Python + // only evaluates this expression once (see bug 3676). Instead, we emit + // a marker that allows us to determine whether the application has + // supplied a value. + // + _out << "Ice._struct_marker"; return; } @@ -1701,6 +1712,30 @@ Slice::Python::CodeVisitor::writeMetaData(const StringList& meta) _out << ')'; } +void +Slice::Python::CodeVisitor::writeAssign(const MemberInfo& info) +{ + // + // Structures are treated differently (see bug 3676). + // + StructPtr st = StructPtr::dynamicCast(info.type); + if(st) + { + _out << nl << "if " << info.fixedName << " is Ice._struct_marker:"; + _out.inc(); + _out << nl << "self." << info.fixedName << " = " << getSymbol(st) << "()"; + _out.dec(); + _out << nl << "else:"; + _out.inc(); + _out << nl << "self." << info.fixedName << " = " << info.fixedName; + _out.dec(); + } + else + { + _out << nl << "self." << info.fixedName << " = " << info.fixedName; + } +} + string Slice::Python::CodeVisitor::getOperationMode(Slice::Operation::Mode mode) { diff --git a/py/python/Ice.py b/py/python/Ice.py index 864315974f1..9689dbabc88 100644 --- a/py/python/Ice.py +++ b/py/python/Ice.py @@ -28,6 +28,13 @@ generateUUID = IcePy.generateUUID loadSlice = IcePy.loadSlice # +# This value is used as the default value for struct types in the constructors +# of user-defined types. It allows us to determine whether the application has +# supplied a value. (See bug 3676) +# +_struct_marker = object() + +# # Core Ice types. # class Object(object): |