Tcl Source Code

Check-in [8e643395a4]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:[9d61624b3d]: Stop crashes when emptying the superclass slot.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 8e643395a421eaa27282d522866245ddb0d7ab79
User & Date: dkf 2013-08-02 14:58:58
Context
2013-08-02
20:19
Deal with the elaborate rip-apart-a-metaclass case as well. check-in: 04e4971bde user: dkf tags: trunk
17:30
merge trunk check-in: 0d355bac3f user: dgp tags: dgp-refactor
14:58
[9d61624b3d]: Stop crashes when emptying the superclass slot. check-in: 8e643395a4 user: dkf tags: trunk
2013-08-01
19:18
[1905562] [8d2c0da36d] Raise the recursion limits on regexps to allow existing regexps "in the wild"... check-in: b7100ded1f user: dgp tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclOODefineCmds.c.

2202
2203
2204
2205
2206
2207
2208



2209
2210





2211
2212
2213
2214
2215
2216
2217
2218
2219
2220

2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231

2232
2233
2234
2235
2236
2237
2238
     * Allocate some working space.
     */

    superclasses = (Class **) ckalloc(sizeof(Class *) * superc);

    /*
     * Parse the arguments to get the class to use as superclasses.



     */






    for (i=0 ; i<superc ; i++) {
	superclasses[i] = GetClassInOuterContext(interp, superv[i],
		"only a class can be a superclass");
	if (superclasses[i] == NULL) {
	    goto failedAfterAlloc;
	}
	for (j=0 ; j<i ; j++) {
	    if (superclasses[j] == superclasses[i]) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"class should only be a direct superclass once", -1));

		Tcl_SetErrorCode(interp, "TCL", "OO", "REPETITIOUS", NULL);
		goto failedAfterAlloc;
	    }
	}
	if (TclOOIsReachable(oPtr->classPtr, superclasses[i])) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "attempt to form circular dependency graph", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "CIRCULARITY", NULL);
	failedAfterAlloc:
	    ckfree((char *) superclasses);
	    return TCL_ERROR;

	}
    }

    /*
     * Install the list of superclasses into the class. Note that this also
     * involves splicing the class out of the superclasses' subclass list that
     * it used to be a member of and splicing it into the new superclasses'







>
>
>


>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
>







2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
     * Allocate some working space.
     */

    superclasses = (Class **) ckalloc(sizeof(Class *) * superc);

    /*
     * Parse the arguments to get the class to use as superclasses.
     *
     * Note that zero classes is special, as it is equivalent to just the
     * class of objects. [Bug 9d61624b3d]
     */

    if (superc == 0) {
	superclasses = ckrealloc(superclasses, sizeof(Class *));
	superclasses[0] = oPtr->fPtr->objectCls;
	superc = 1;
    } else {
	for (i=0 ; i<superc ; i++) {
	    superclasses[i] = GetClassInOuterContext(interp, superv[i],
		    "only a class can be a superclass");
	    if (superclasses[i] == NULL) {
		goto failedAfterAlloc;
	    }
	    for (j=0 ; j<i ; j++) {
		if (superclasses[j] == superclasses[i]) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "class should only be a direct superclass once",
			    -1));
		    Tcl_SetErrorCode(interp, "TCL", "OO", "REPETITIOUS",NULL);
		    goto failedAfterAlloc;
		}
	    }
	    if (TclOOIsReachable(oPtr->classPtr, superclasses[i])) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"attempt to form circular dependency graph", -1));
		Tcl_SetErrorCode(interp, "TCL", "OO", "CIRCULARITY", NULL);
	    failedAfterAlloc:
		ckfree((char *) superclasses);
		return TCL_ERROR;
	    }
	}
    }

    /*
     * Install the list of superclasses into the class. Note that this also
     * involves splicing the class out of the superclasses' subclass list that
     * it used to be a member of and splicing it into the new superclasses'

Changes to tests/oo.test.

3370
3371
3372
3373
3374
3375
3376

















3377
3378
3379
3380
3381
3382
3383
} {{-append -clear -set} {Get Set}}
test oo-34.8 {TIP 380: slots - presence} {
    getMethods oo::objdefine::mixin
} {{-append -clear -set} {--default-operation Get Set}}
test oo-34.9 {TIP 380: slots - presence} {
    getMethods oo::objdefine::variable
} {{-append -clear -set} {Get Set}}


















cleanupTests
return

# Local Variables:
# mode: tcl
# End:







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
} {{-append -clear -set} {Get Set}}
test oo-34.8 {TIP 380: slots - presence} {
    getMethods oo::objdefine::mixin
} {{-append -clear -set} {--default-operation Get Set}}
test oo-34.9 {TIP 380: slots - presence} {
    getMethods oo::objdefine::variable
} {{-append -clear -set} {Get Set}}

test oo-35.1 {Bug 9d61624b3d: Empty superclass must not cause crash} -setup {
    oo::class create fruit {
	method eat {} {}
    }
    set result {}
} -body {
    lappend result [fruit create ::apple] [info class superclasses fruit]
    oo::define fruit superclass
    lappend result [info class superclasses fruit] \
	[info object class apple oo::object] \
	[info class call fruit destroy] \
	[catch { apple }]
} -cleanup {
    unset -nocomplain result
    fruit destroy
} -result {::apple ::oo::object ::oo::object 1 {{method destroy ::oo::object {core method: "destroy"}}} 1}

cleanupTests
return

# Local Variables:
# mode: tcl
# End: