[qfcc] Copy self param when copying methods

Copying methods is done when adding protocols to classes (the current
use for adding regular methods is an incorrect solution to a different
problem). However, when a method is added to a class, the type of its
self parameter is set to be a pointer to the class. Thus, not only does
the method need to be copied, the self parameter does too, otherwise
the self parameter of methods added via protocols will have their type
set to be a pointer to the last class seen adding the protocol.

That is, if, while compiling the implementation for class A, but the
interface for class B is comes after the interface for class A, and both
A and B add protocol P, then all methods in protocol P will have self
pointing to B rather than A.

@protocol P
-method;
@end

@interface A <P>
@end

@interface B <P>
@end

@implementation A
-method	{} // self is B, not A!
@end
This commit is contained in:
Bill Currie 2020-03-02 23:38:04 +09:00
parent 8a4de6fea6
commit f025bd96d4

View file

@ -208,11 +208,21 @@ new_methodlist (void)
void
copy_methods (methodlist_t *dst, methodlist_t *src)
{
method_t *s, *d;
method_t *s, *d;
param_t *self;
for (s = src->head; s; s = s->next) {
d = malloc (sizeof (method_t));
*d = *s;
// The above is only a shallow copy and thus even though the methods
// are not shared between the source and destination lists, the
// parameters are. Thus, duplicate the self (first) parameter so
// changing its type to match the class into which it is inserted does
// not affect the source list. The rest of the parameters do not need
// to be copied as they will not be altered.
self = malloc (sizeof (param_t));
*self = *d->params;
d->params = self;
d->next = 0;
add_method (dst, d);
}