<div dir="ltr">Hi Erik,<div><br></div><div>this sounds very useful, thanks for working on it. One think Ted had suggested on the review for r232750 (that I failed to follow up on :-/) was to also have a #pragma to mark whole regions as e.g. 10.10+. From <a href="https://www.mail-archive.com/cfe-commits@cs.uiuc.edu/msg117130.html">https://www.mail-archive.com/cfe-commits@cs.uiuc.edu/msg117130.html</a>: </div><div><br></div><div><div>  #pragma clang assume_availability(macosx, 10.8) begin</div><div>  ...</div><div>  #pragma clang assume_availability(macosx, 10.8) end</div></div><div><br></div><div>Is this something you'll look at as well?</div><div><br></div><div>Nico</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jul 5, 2016 at 2:59 PM, Erik Pilkington via cfe-dev <span dir="ltr"><<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hello,<br>
<br>
I'm an intern at Apple this summer, and my project is to add the following<br>
feature to C and Objective-C.<br>
<br>
The feature in question is adding the ability to safely access APIs that are<br>
only available in some of the deployment targets available, based on the<br>
availability attribute that the declarations were declared with.<br>
<br>
Swift has an analogous feature exposed through the following syntax:<br>
<br>
  if #available(iOS 8, *) {<br>
    // do something iOS8-ey<br>
  }<br>
<br>
In the context of the body of the `if`, accesses to declarations that are marked<br>
as being available in iOS version 8 or below can be accessed safely and without<br>
compiler errors, even if the deployment target is iOS 7, for example. Outside of<br>
that block, accessing the declarations would be a hard error.<br>
<br>
Currently, Clang exposes no safe way to perform a similar check. Right now,<br>
there are 2 main methods for checking for availability in Objective-C:<br>
<br>
  1. Using respondsToSelector<br>
  2. Checking if a weak symbol is NULL<br>
<br>
There are two main problems with these methods. Firstly, they allow programmers<br>
to accidentally use SPIs ("Secret" Programming Interface, aka internal stuff),<br>
ignoring that they are marked as being unavailable to them. Secondly, we cannot<br>
use them for diagnostics in all cases, as they can be combined with arbitrary<br>
control flow. If we were to infer the availability of a declaration based on<br>
these existing checks, then code would be fragile — a small change that doesn’t<br>
alter the semantics of the function could cause the compiler to become confused<br>
and incorrectly handle diagnostics.<br>
<br>
There also does exist a -Wpartial-availability (introduced in r232750), which<br>
just statically compares the deployment target with the marked availability of<br>
the API, potentially warning if necessary. This doesn't allow using a newer API<br>
with an older deployment target, as this feature does.<br>
<br>
My proposal is to implement a similar feature to Swift for C and Objective-C.<br>
The current syntax (subject to change) is as follows:<br>
<br>
  if (@available(macos 10.10, *)) {<br>
    fancy_new_fn();<br>
  }<br>
<br>
And the following for C and C++:<br>
<br>
  if (__builtin_available(macos 10.10, *)) {<br>
    fancy_new_fn();<br>
  }<br>
<br>
And would have similar semantics to the swift version discussed above, meaning<br>
it would compile to a runtime check of the availability, branching on the<br>
result. In the body of the if, the deployment target would effectively be the<br>
target in the @available check. This means that any declaration that is marked<br>
with an `__attribute__((availability))` which was introduced before or at MacOS<br>
10.10 can be accessed in the block. Here is a complete example:<br>
<br>
  void flashy_new_function() __attribute__((availability(macosx, introduced=10.10)));<br>
  void boring_old_function() __attribute__((availability(macosx, introduced=10.9)));<br>
<br>
  int main() {<br>
    if (@available(macos 10.10, *))<br>
      flashy_new_function();<br>
    else<br>
      boring_old_function();<br>
  }<br>
<br>
And compiled with:<br>
<br>
  $ clang example.m -mmacos-version-min=10.9<br>
<br>
In this case, since the call to fancy_new_function() is guarded by the runtime<br>
check, clang would emit no warnings. If main were instead:<br>
<br>
  int main() {<br>
    flashy_new_function();<br>
  }<br>
<br>
Then clang will warn that the call is unsafe. Additionally, Clang will emit a<br>
fixit that could wrap the call to flashy_new_function in an @available (or<br>
__builtin_available, when needed) check.<br>
<br>
I would appreciate hearing any thoughts or questions about this feature.<br>
<br>
Cheers,<br>
Erik Pilkington<br>
<br>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
</blockquote></div><br></div>