On Wednesday, March 13, 2002, at 04:01 PM, Markus Hitter wrote:
Am Dienstag den, 12. März 2002, um 22:36, schrieb Richard
Frith-Macdonald:
On Tuesday, March 12, 2002, at 08:59 PM, Markus Hitter wrote:
As you probably know, constant strings are declared/defined in code,
but are known to the compiler, too. With Apple's gcc, the compiler
explicitely requires a declaration like:
@interface NXConstantString : NSString /* or NSObject */ {
char *cString;
unsigned int len;
...
}
But GNUstep declares:
@interface NXConstantString : NSString {
union {
unichar *u;
unsigned char *c;
} _contents;
unsigned int _count;
}
which isn't compatible. You notice the additional unicode variable?
It's perfectly compatible, there is no additional variable,
what you are looking at (_contents) is a union ... a single variable.
Here's an excerpt from gcc 3.1's gcc/objc/objc-act.c:
...
/* APPLE LOCAL begin Objective-C++ */
/* Ensure that the ivar list for NSConstantString/NXConstantString
begins with the following three fields:
struct STRING_OBJECT_CLASS_NAME
{
Object isa;
char *cString;
unsigned int length;
}; */
static int
check_string_class_template ()
{
tree field_decl = TYPE_FIELDS (constant_string_type);
#define IS_FIELD_OF_TYPE(F, T) \
(F && TREE_CODE (F) == FIELD_DECL && TREE_CODE (TREE_TYPE (F)) == T)
if (!IS_FIELD_OF_TYPE (field_decl, POINTER_TYPE))
return 0;
field_decl = TREE_CHAIN (field_decl);
if (!IS_FIELD_OF_TYPE (field_decl, POINTER_TYPE))
return 0;
field_decl = TREE_CHAIN (field_decl);
return IS_FIELD_OF_TYPE (field_decl, INTEGER_TYPE);
#undef IS_FIELD_OF_TYPE
}
/* APPLE LOCAL end Objective-C++ */
... and later:
if (!check_string_class_template ())
{
error ("interface `%s' lacks required ivars",
IDENTIFIER_POINTER (constant_string_id));
return error_mark_node;
}
...
It's the code which checks for some specific ivar layout and it
doesn't see a pointer inside a union as a valid pointer. The later is
the type of incompatibility I'm speaking of.
Ok ... so parhaps apple have broken the compiler somewhat ... could
report it as a bug.
However, the above code looks correct to me ... ie it would appear to
be checking to
see that the declared ivars are a pointer, a pointer, and an
integer ... which is what
they were and are. So given that the compiler seems to be checking for
the ivar types
which were in fact present, I still wonder if there was not some sort
of header file
confusion going on. However, I don't know gcc internals to say whether
the
IS_FIELD_OF_TYPE() macro is doing the right thing.
Actually the unicode representation is used for the standard unicode
concrete
subclass of the NSString class. The declaration of NXConstantString
is the
same as that of the private subclasses because the ivar layout of the
two *must*
be the same - and declaring them identically (as well as putting
comments in the
source) is the clearest way of showing that.
While I can understand you quite well, one could consider it as a
cosmetic issue as well. So there are three choices:
1) Get used to live with the cosmetic issue and declare
NXConstantString like:
@interface NXConstantString : NSString
{
/* These (first) two declarations must be byte-compatible with
@interface GSString : NSString _and_ with the ivar layout required
by the ObjC++ compiler. */
unsigned char *_contents;
unsigned int _count;
}
@end
I already got rid of the broken change to NSString.h,
declaring a dummy interface for NXConstantString much like the above,
and
simply not using that dummy interface anywhere.
This will work around the compiler bug (if present).
(already tested, requires about five lines to change in GSString.h)
2) Disable the check for the ivar layout in gcc at the risk of buggier
code.
Hardly any risk at all. Only two places use this - the objc runtime,
and foundation
libraries, and if either got it wrong the effects could hardly pass
unnoticed.
3) Improve the check for the ivar layout at the cost of a more complex
compiler.
I think that if the check is worth adding, it's worth adding properly -
and the
additional complexity of checking properly is surely rather less than
the additional
complexity to add the check was in the first place.