Hi all,
I would like to have a go at hacking a little on Clang when a get a bit of spare time, and have found that adding support for override would be useful little exercise. I’ve seen another post referring to Clang’s support for attribute((override)), and seems like I could use this as a starting point.
Big Nerd Ranch would like to see an @override keyword, as follows:
@override
- (NSInteger)numberOfSectionsInTableview:(UITableView *)tv
{ ... }
This would seem the most natural, but I feel it would involve mucking with the parser, the AST and therefore fairly complicated. Given Clang already parses attribute, I could take the following approach instead:
- (NSInteger)numberOfSectionsInTableview:(UITableView *)tv __attribute__((override))
{ ... }
Can I implement this as a Clang plugin or must I modify Clang source?
One other question is I couldn’t get Clang 2.8 to recognize __has_attribute(override) for a .cpp file:
#ifndef __has_attribute
#define __has_attribute(x) 0
#warning no __has_attribute support
#endif
#if __has_attribute(override)
#define OVERRIDE attribute((override))
#else
#warning No override attribute
#endif
Would always output the two warnings.
Cheers,
Stu
Stuart Carnie, CTO
manomio | in retro we trust!
attribute is preferred but, first you need to implement it for .cpp (as it is intended for), and then see if it makes sense to do same for
an objc method. I don’t know its c++ semantics so I cannot make any comment on its usefulness for objc methods.
Hi Stuart,
Is your goal here to allow overloading of ObjC methods? If so, the parsing isn’t the hard part, you’d need to mangle selectors somehow, and enhance the runtime to support this. This isn’t something we want in ObjC, because want to keep it simple.
-Chris
The benefit of an @Override annotation (for e.g. as implemented in Java) is for the compiler to warn you if you’re not actually overriding something when you think you are. Which could happen if the superclass changed since the time you wrote the code or if you made a typo in the method name/signature.
This is completely orthogonal to overloading. (Though I don’t know Stuart’s actual intention.)
-Alexei
This falls into the “namespace for selectors” discussion on a previous thread about a month ago.
One needs either @override(s) and @implements (or just an overrides attribute annotation) to signal that the intention is to redeclare a method that one intends to redefine.
I have a big issue if the runtime can’t enforce distinct selectors for the same name when a superclass introduces a method already introduced and used in a subclass. Clearly this is part of the API contract. Just adding the annotation would allow the compiler to say, hey, you thought you were introducing a new method, but you weren’t, and that would be good, but the principle advantage is to give runtime protection for those binaries that get hosed when in fact a superclass does introduce a method already in use in a later rev.
Adding partial support in the compiler and not the runtime would create source compatibility issues if/when the runtime ever did implement this feature, and might in fact indefinitely delay such an implementation. I think this requires a combined runtime/compiler approach.
Blaine
Not at all, I am only looking to add compile-time verification of the developer’s intent that they wish to override a particular method.
In the example below, the fictitious developer has derived from UIViewController, and intended to override / implement the numberOfSectionsInTableView method from the UITableViewDataSource protocol. The subtle issue is they have misspelled the method as numberOfSectionsInTableview, however as the method is marked @optional, the compiler issues no warning. By adding support for “override”, we would force the compiler to walk the inheritance and protocol hierarchy and issue a warning if the method marked as override was not found. It is not changing the behavior of Obj-C or the runtime in anyway.
Cheers,
Stu
Stuart Carnie, CTO
manomio | in retro we trust!
This is exactly what I am going for, simply to enhance compile-time and static analysis, when the developer has identified they wished to override a particular method.
I am definitely not looking to introduce method overloading or scoping as that is far too intrusive.
Cheers,
Stu
Stuart Carnie, CTO
manomio | in retro we trust!
If you are only looking at this for a compile time warning (as opposed
to new runtime hooks and altered code generation) then I don't think
it is semantically similiar to the existing override attribute, and
that would be a bad jumping off point. Also, if you want something
purely for static analysis I don't think a whole extension to the
language syntax is really appropriate. If I were proposing this, I
would just add a new attribute, lets call it "implementsObjCProtocol"
. You could then annotate declarations like this:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
__attribute__((implementsObjCProtocol(UITableViewDataSource)));
or even hide it behind a macro
#define LG_IMPLEMENTS_PROTOCOL(x) __attribute__((implementsObjCProtocol(x)))
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
LG_IMPLEMENTS_PROTOCOL(UITableViewDataSource);
You could then just store the attribute data hanging off the AST node,
and in the static analyzer you could write a simple analysis pass that
checks for all nodes that have the attribute and make sure the method
part of the protocol they declare. This is basically how the current
annotations in Foundation, like NS_REQUIRES_NIL_TERMINATION (though
that is used during compilation for warning analysis not static
analysis, but the concept is the same).
Louis
I agree, I think attribute is the most appropriate way, as it can be made compatible with other compilers using macros, and is not changing the syntax of Objective-C.
Perhaps I was premature in calling the feature “override”, as I want the attribute to serve as an indicator that somewhere in the class hierarchy there should be a selector with the same signature, regardless of whether it is an optional from a protocol or from a superclass.
That is:
@interface MyBase
- (void)someMethodWithInt:(NSInteger)value;
@end
@protocol MyProtocol
@optional
- (void)optionalMethod;
@end
@interface MyDerived : MyBase
@end
@implementation MyDerived
@end
I want the compiler to issue a warning for both methods, because they do not match an existing selector in the class hierarchy. It could even provide possible matches, similar to how Clang does searches for unknown types.
I assume that adding a new attribute requires changing Clang, as I couldn’t see how this could be added via a plugin.
Thats much for all the discussion.
Cheers,
Stu
Stuart Carnie, CTO
manomio | in retro we trust!