Hi Richard, all,
While updating QuartzCore under GNUstep, I ran into an obscure issue caused
by Richard's July 20th commit, revision 35304 with log message:
"Use GSSelectorTypesMatch() for types comparison where we are interested in
types but not qualifiers and stack layout information."
Primarily I'm having trouble with changes to NSValue.m around what's line
197 in revision 35403 (the revision of -base that I currently use). Here
are the changes to + (Class) valueClassWithObjCType: (const char *)type.
35304 rfm /* Try for equivalent types match.
35304 rfm */
35304 rfm else if (GSSelectorTypesMatch(@encode(id), type))
35304 rfm theClass = nonretainedObjectValueClass;
35304 rfm else if (GSSelectorTypesMatch(@encode(NSPoint), type))
35304 rfm theClass = pointValueClass;
35304 rfm else if (GSSelectorTypesMatch(@encode(void *), type))
35304 rfm theClass = pointerValueClass;
35304 rfm else if (GSSelectorTypesMatch(@encode(NSRange), type))
35304 rfm theClass = rangeValueClass;
35304 rfm else if (GSSelectorTypesMatch(@encode(NSRect), type))
35304 rfm theClass = rectValueClass;
35304 rfm else if (GSSelectorTypesMatch(@encode(NSSize), type))
35304 rfm theClass = sizeValueClass;
35304 rfm
I'm currently considering this a bug, since the above behavior differs from
Cocoa's. Under Cocoa, if I request to store a CGPoint inside a NSValue
using @encode(CGPoint), that's exactly what I get out. However, with
GNUstep, if I store a CGPoint into a NSValue, I get a NSPoint out of it,
wreaking havoc with my current code that handles case when these structs
don't have equal members.
While this would ordinarily be a very welcome change and I'd love it if
Cocoa did the same, unfortunately it doesn't. Here's a part of my code that
breaks (for further context, see -calculatedAnimationValueAtTime:onLayer:
in libs/quartzcore/trunk/CAAnimation.m):
/*
NSValue * from = ....;
*/
if (!strcmp([from objCType], @encode(NSPoint)))
{
CGPoint fromPt = CGPointMake([from pointValue].x, [from
pointValue].y);
from = [NSValue valueWithBytes: &fromPt objCType:
@encode(CGPoint)];
}
if (!strcmp([from objCType], @encode(CGPoint)))
{
// ... actual handling of both NSPoint and CGPoint here
return;
}
if (...
This code takes care of possibility that CGPoint, the native point type
that I work with, has different data types than NSPoint. Under GNUstep, it
trips up in case the data types are the same.
I'll modify the CGPoint section of my code to accept both NSPoint and
CGPoint; since the 'from' and 'to' values that happened to be NSPoints were
already replaced with a CGPoint, and -base erroneously decided to consider
the value a NSPoint just because all struct members are of equal type, it's
safe to extract values and put them in a CGPoint (they're surely that
already). However, it's still just a workaround; who knows what other
problems might this change trigger in third-party code.
I'll have QuartzCore print out a warning if it detects this bug in -base.