summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES20
-rw-r--r--cpp/src/Slice/PythonUtil.cpp43
-rw-r--r--py/python/Ice.py7
3 files changed, 66 insertions, 4 deletions
diff --git a/CHANGES b/CHANGES
index aa512f1be3d..3f6821bc812 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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):