summaryrefslogtreecommitdiffstats
path: root/generic/tclOODefineCmds.c
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2018-10-19 15:53:14 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2018-10-19 15:53:14 (GMT)
commite87ceb89576dc37f5f988edd8b27e2be84ecc918 (patch)
treeb618a526471d0d0959cd61fb4f2f6710ea3ee4bf /generic/tclOODefineCmds.c
parent251aca8829d76cd4994afdf3bcbc966523809053 (diff)
parentcb061edef8250a8cd969eb0eb291f4c44d65d74e (diff)
downloadtcl-e87ceb89576dc37f5f988edd8b27e2be84ecc918.zip
tcl-e87ceb89576dc37f5f988edd8b27e2be84ecc918.tar.gz
tcl-e87ceb89576dc37f5f988edd8b27e2be84ecc918.tar.bz2
Merge 8.7
Diffstat (limited to 'generic/tclOODefineCmds.c')
-rw-r--r--generic/tclOODefineCmds.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/generic/tclOODefineCmds.c b/generic/tclOODefineCmds.c
index 4ead43f..9d23f8f 100644
--- a/generic/tclOODefineCmds.c
+++ b/generic/tclOODefineCmds.c
@@ -1375,6 +1375,8 @@ TclOODefineClassObjCmd(
{
Object *oPtr;
Class *clsPtr;
+ Foundation *fPtr = TclOOGetFoundation(interp);
+ int wasClass, willBeClass;
/*
* Parse the context to get the object to operate on.
@@ -1410,12 +1412,20 @@ TclOODefineClassObjCmd(
if (clsPtr == NULL) {
return TCL_ERROR;
}
-
+ if (oPtr == clsPtr->thisPtr) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "may not change classes into an instance of themselves", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
+ return TCL_ERROR;
+ }
/*
* Set the object's class.
*/
+ wasClass = (oPtr->classPtr != NULL);
+ willBeClass = (TclOOIsReachable(fPtr->classCls, clsPtr));
+
if (oPtr->selfCls != clsPtr) {
TclOORemoveFromInstances(oPtr, oPtr->selfCls);
TclOODecrRefCount(oPtr->selfCls->thisPtr);
@@ -1423,6 +1433,26 @@ TclOODefineClassObjCmd(
AddRef(oPtr->selfCls->thisPtr);
TclOOAddToInstances(oPtr, oPtr->selfCls);
+ /*
+ * Create or delete the class guts if necessary.
+ */
+
+ if (wasClass && !willBeClass) {
+ /*
+ * This is the most global of all epochs. Bump it! No cache can be
+ * trusted!
+ */
+
+ TclOORemoveFromMixins(oPtr->classPtr, oPtr);
+ oPtr->fPtr->epoch++;
+ oPtr->flags |= DONT_DELETE;
+ TclOODeleteDescendants(interp, oPtr);
+ oPtr->flags &= ~DONT_DELETE;
+ TclOOReleaseClassContents(interp, oPtr);
+ } else if (!wasClass && willBeClass) {
+ TclOOAllocClass(interp, oPtr);
+ }
+
if (oPtr->classPtr != NULL) {
BumpGlobalEpoch(interp, oPtr->classPtr);
} else {