[cfe-dev] Comparison of pointers between Objc subclasses
Ted Kremenek
kremenek at apple.com
Tue Jul 1 20:54:23 PDT 2008
On Jul 1, 2008, at 7:44 PM, Eli Friedman wrote:
> On Tue, Jul 1, 2008 at 4:22 PM, Ted Kremenek <kremenek at apple.com>
> wrote:
>> Are pointer type compatibility checks for assignments and
>> conversions being
>> handled in the same way?
>
> Assignment (from C99 6.5.16.1):
> One of the following shall hold:
> <snip>
> both operands are pointers to qualified or unqualified versions of
> compatible types, and the type pointed to by the left has all the
> qualifiers of the type pointed to by the right;
> <snip>
>
> Comparison (from C99 6.5.9):
> One of the following shall hold:
> <snip>
> both operands are pointers to qualified or unqualified versions of
> compatible types;
> <snip>
>
> And currently, we (inconsistently) consider ObjC base types and
> derived types compatible in the C99 sense, which is implemented in
> ASTContext::typesAreCompatible.
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.
More information about the cfe-dev
mailing list