diff options
author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2018-10-19 15:53:14 (GMT) |
---|---|---|
committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2018-10-19 15:53:14 (GMT) |
commit | e87ceb89576dc37f5f988edd8b27e2be84ecc918 (patch) | |
tree | b618a526471d0d0959cd61fb4f2f6710ea3ee4bf /generic/tclOODefineCmds.c | |
parent | 251aca8829d76cd4994afdf3bcbc966523809053 (diff) | |
parent | cb061edef8250a8cd969eb0eb291f4c44d65d74e (diff) | |
download | tcl-e87ceb89576dc37f5f988edd8b27e2be84ecc918.zip tcl-e87ceb89576dc37f5f988edd8b27e2be84ecc918.tar.gz tcl-e87ceb89576dc37f5f988edd8b27e2be84ecc918.tar.bz2 |
Merge 8.7
Diffstat (limited to 'generic/tclOODefineCmds.c')
-rw-r--r-- | generic/tclOODefineCmds.c | 32 |
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 { |