Hi Nico,

> On Jan 8, 2015, at 6:14 PM, Nico Weber <[email protected]> wrote:
> 
> Hi,
> 
> the Mac OS X and iOS SDKs add new functions in new releases. Apple recommends 
> using the newest SDK and setting the deployment target to whatever old OS 
> version one wants to support, and only calling new functions after checking 
> that they are available at runtime.
> 
> In practice, we (Chromium) get this wrong. Others who support old OS X 
> versions get this wrong too. Hence, we (Chromium) use a very old SDK and then 
> manually declare new functions when we want to call them – this reduces the 
> chance of us forgetting if they are available at runtime considerably, in 
> practice. But using an old SDK has its problems – sometimes the frameworks 
> check which SDK an app was linked against and only then activate bug fixes, 
> and newer Xcodes don't ship include old SDKs.

That’s an interesting approach to handling the availability problem; I hadn’t 
heard of it before, but I see the logic there.

> Ideally, we could use a new SDK but get a warning when we use a new API 
> without a manual redeclaration – this protects us against new APIs the same 
> way using an old SDK does without the drawbacks that this brings.
> 
> The attached patch is a sketch how such a warning might work. How repulsive 
> is this idea? Are there other approaches to this problem? If the basic idea 
> is ok:

This is a drastically different approach than I’d imagined. Whenever I’ve 
thought about this problem, I’ve always come back to some form of dataflow 
analysis that checks whether uses of “not-yet-introduced” API is used in a sane 
way: is it dominated by some check that implies the availability, e.g., a 
-respondsToSelector: check on a method with at least that availability, or 
checking whether “[NSFoo class]” is non-null when the class has availability. I 
suspect that’s the idea behind Deploymate (http://www.deploymateapp.com 
<http://www.deploymateapp.com/>), although I’ve never used it, and it has the 
benefit that it should make idiomatic code (that does the right checking) just 
work.

It’s also a heck of a lot more work to implement than the approach you’re using.

> Any comments on the implementation?

The implementation generally looks fine. One minor comment:

+    case AR_NotYetIntroduced: {
+      // don't do this for enums, they can't be redeclared.
+      if (isa<EnumConstantDecl>(D) || isa<EnumDecl>(D))
+        break;
+      bool FoundRedecl = false;
+      for (Decl *Redecl = D->getMostRecentDecl(); Redecl && !FoundRedecl;
+           Redecl = Redecl->getPreviousDecl()) {
+        if (Redecl->getAttr<AvailabilityAttr>()->isInherited())
+          FoundRedecl = true;
+      }
+      if (!FoundRedecl)
+        S.EmitAvailabilityWarning(Sema::AD_Partial, D, Message, Loc,
+                                  UnknownObjCClass, ObjCPDecl,
+                                  ObjCPropertyAccess);
+      break;
+    }

Generally speaking, name lookup will always find the most recent declaration, 
so you might be able to skip the D->getMostRecentDecl() bit entirely and just 
check that the availability attribute was inherited.

        - Doug


_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to