Author: steven_wu Date: Mon Apr 16 16:34:18 2018 New Revision: 330166 URL: http://llvm.org/viewvc/llvm-project?rev=330166&view=rev Log: [Availability] Improve availability to consider functions run at load time
Summary: There are some functions/methods that run when the application launches or the library loads. Those functions will run reguardless the OS version as long as it satifies the minimum deployment target. Annotate them with availability attributes doesn't really make sense because they are essentially available on all targets since minimum deployment target. rdar://problem/36093384 Reviewers: arphaman, erik.pilkington Reviewed By: erik.pilkington Subscribers: erik.pilkington, cfe-commits Differential Revision: https://reviews.llvm.org/D45699 Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaDeclAttr.cpp cfe/trunk/lib/Sema/SemaDeclObjC.cpp cfe/trunk/test/SemaObjC/unguarded-availability.m Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=330166&r1=330165&r2=330166&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Apr 16 16:34:18 2018 @@ -2912,6 +2912,10 @@ def warn_mismatched_availability_overrid "%select{the protocol method it implements|its overridden method}1 is " "available">, InGroup<Availability>; +def warn_availability_on_static_initializer : Warning< + "ignoring availability attribute %select{on '+load' method|" + "with constructor attribute|with destructor attribute}0">, + InGroup<Availability>; def note_overridden_method : Note< "overridden method is here">; def note_protocol_method : Note< Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=330166&r1=330165&r2=330166&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Apr 16 16:34:18 2018 @@ -9139,6 +9139,21 @@ Sema::ActOnFunctionDeclarator(Scope *S, AddToScope = false; } + // Diagnose availability attributes. Availability cannot be used on functions + // that are run during load/unload. + if (const auto *attr = NewFD->getAttr<AvailabilityAttr>()) { + if (NewFD->hasAttr<ConstructorAttr>()) { + Diag(attr->getLocation(), diag::warn_availability_on_static_initializer) + << 1; + NewFD->dropAttr<AvailabilityAttr>(); + } + if (NewFD->hasAttr<DestructorAttr>()) { + Diag(attr->getLocation(), diag::warn_availability_on_static_initializer) + << 2; + NewFD->dropAttr<AvailabilityAttr>(); + } + } + return NewFD; } Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=330166&r1=330165&r2=330166&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Mon Apr 16 16:34:18 2018 @@ -6823,6 +6823,12 @@ static bool ShouldDiagnoseAvailabilityIn return false; // An implementation implicitly has the availability of the interface. + // Unless it is "+load" method. + if (const auto *MethodD = dyn_cast<ObjCMethodDecl>(Ctx)) + if (MethodD->isClassMethod() && + MethodD->getSelector().getAsString() == "load") + return true; + if (const auto *CatOrImpl = dyn_cast<ObjCImplDecl>(Ctx)) { if (const ObjCInterfaceDecl *Interface = CatOrImpl->getClassInterface()) if (CheckContext(Interface)) Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=330166&r1=330165&r2=330166&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Mon Apr 16 16:34:18 2018 @@ -4734,6 +4734,17 @@ Decl *Sema::ActOnMethodDeclaration( Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) checkObjCMethodX86VectorTypes(*this, ObjCMethod); + // + load method cannot have availability attributes. It get called on + // startup, so it has to have the availability of the deployment target. + if (const auto *attr = ObjCMethod->getAttr<AvailabilityAttr>()) { + if (ObjCMethod->isClassMethod() && + ObjCMethod->getSelector().getAsString() == "load") { + Diag(attr->getLocation(), diag::warn_availability_on_static_initializer) + << 0; + ObjCMethod->dropAttr<AvailabilityAttr>(); + } + } + ActOnDocumentableDecl(ObjCMethod); return ObjCMethod; Modified: cfe/trunk/test/SemaObjC/unguarded-availability.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/unguarded-availability.m?rev=330166&r1=330165&r2=330166&view=diff ============================================================================== --- cfe/trunk/test/SemaObjC/unguarded-availability.m (original) +++ cfe/trunk/test/SemaObjC/unguarded-availability.m Mon Apr 16 16:34:18 2018 @@ -7,7 +7,7 @@ typedef int AVAILABLE_10_12 new_int; // expected-note + {{marked partial here}} -int func_10_11() AVAILABLE_10_11; // expected-note 4 {{'func_10_11' has been explicitly marked partial here}} +int func_10_11() AVAILABLE_10_11; // expected-note 8 {{'func_10_11' has been explicitly marked partial here}} #ifdef OBJCPP // expected-note@+2 6 {{marked partial here}} @@ -311,3 +311,45 @@ void switchAnimals(Animals a) { (void)AK_Cat; // no warning (void)AK_CyborgCat; // expected-warning{{'AK_CyborgCat' is only available on macOS 10.12 or newer}} expected-note {{@available}} } + + +// test static initializers has the same availability as the deployment target and it cannot be overwritten. +@interface HasStaticInitializer : BaseClass ++ (void)load AVAILABLE_10_11; // expected-warning{{ignoring availability attribute on '+load' method}} +@end + +@implementation HasStaticInitializer ++ (void)load { + func_10_11(); // expected-warning{{'func_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'func_10_11' in an @available check to silence this warning}} +} +@end + +// test availability from interface is ignored when checking the unguarded availability in +load method. +AVAILABLE_10_11 +@interface HasStaticInitializer1 : BaseClass ++ (void)load; ++ (void)load: (int)x; // no warning. +@end + +@implementation HasStaticInitializer1 ++ (void)load { + func_10_11(); // expected-warning{{'func_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'func_10_11' in an @available check to silence this warning}} +} ++ (void)load: (int)x { + func_10_11(); // no warning. +} +@end + +__attribute__((constructor)) +void is_constructor(); + +AVAILABLE_10_11 // expected-warning{{ignoring availability attribute with constructor attribute}} +void is_constructor() { + func_10_11(); // expected-warning{{'func_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'func_10_11' in an @available check to silence this warning}} +} + +AVAILABLE_10_11 // expected-warning{{ignoring availability attribute with destructor attribute}} +__attribute__((destructor)) +void is_destructor() { + func_10_11(); // expected-warning{{'func_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'func_10_11' in an @available check to silence this warning}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits