discuss-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: This NSConstantString thing


From: Richard Frith-Macdonald
Subject: Re: This NSConstantString thing
Date: Wed, 13 Mar 2002 16:30:02 +0000

On Wednesday, March 13, 2002, at 04:27 PM, Richard Frith-Macdonald wrote:


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.

I think that if/when we get the ObjC++ changes merged into the main gcc, we can get
the compiler fixed if necessary.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]