Thanks Eli.
C99 obviously doesn't stipulate the compatibility of pointers to Objective-C classes, which gets back to the original issue. In this regards, C99 6.5.9 might not even apply when comparing Objective-C types ("compatibility" is defined by an extended type system that is well beyond the scope of C99). This of course was the original issue. Because there is a subclassing relationship here between NSArray and NSMutableArray (which is a subtyping relationship from a PL theory standpoint), it makes sense to me that the pointer types are compatible, but I'm not an Objective-C lawyer.
Incidentally, comparing a pointer to a derived type is with a pointer to a base type is okay in C++ (at least as far as C++ classes and g++ -pedantic is concerned; I'm not certain what the standard says):
$ cat t.cpp
class A {};
class B : public A {};
bool f(A* a, B* b) { return a == b; }
$ g++ -pedantic -fsyntax-only t.cpp
$
This example appears to be essentially the same as the one Thomas presented in his original email, except that we are dealing with C++ classes, not Objective-C classes. Incidentally, the following Objective-C example also passes with gcc -pedantic:
$ cat t.m
@interface A { int x; } @end
@interface B : A { int y; } @end
int f(A* a, B* b) {
return a == b;
}
$ gcc -pedantic -fsytnax-only t.m
$
If we remove the subtyping relationship between B and A, however, gcc issues a warning:
$ cat t2.m
@interface A { int x; } @end
@interface B { int y; } @end
int f(A* a, B* b) {
return a == b;
}
$ gcc -fsyntax-only -pedantic t2.m
t2.m: In function ‘f’:
t2.m:5: warning: comparison of distinct Objective-C types lacks a cast
$
Now lets look at assignments (t3.m is the same as t.m except the comparison is now an assignment). Notice that B subclasses A:
$ cat t3.m
@interface A { int x; } @end
@interface B : A { int y; } @end
A* f(A* a, B* b) {
return a = b;
}
$ gcc -pedantic -fsyntax-only t3.m
$
What happens if we assign a to b (where B still subclasses A)?
$ cat t4.m
@interface A { int x; } @end
@interface B : A { int y; } @end
A* f(A* a, B* b) {
return b = a;
}
$ gcc -pedantic -fsyntax-only t4.m
t4.m: In function ‘f’:
t4.m:5: warning: assignment from distinct Objective-C type
GCC's diagnostics are horrible, but I think this experiment illustrates that two Objective-C pointer types can be compared if one pointee subclasses the other (a subtyping relationship), and in an assignment two types are compatible if the type of the right expression subtypes the left expression. This makes sense because B* can be treated as an A*, but an A* cannot always be treated as a B* (since B is more specialized, and that A* might actually be a C*, where C subclasses A, but is neither a parent or subclass of B).
So, I think the answers we are looking for are outside the letter of C99 standard. The Objective-C and C++ object type systems are a completely different animal.