Author: mren Date: Wed Feb 17 16:05:48 2016 New Revision: 261163 URL: http://llvm.org/viewvc/llvm-project?rev=261163&view=rev Log: Add 'nopartial' qualifier for availability attributes.
An optional nopartial can be placed after the platform name. int bar() __attribute__((availability(macosx,nopartial,introduced=10.12)) When deploying back to a platform version prior to when the declaration was introduced, with 'nopartial', Clang emits an error specifying that the function is not introduced yet; without 'nopartial', the behavior stays the same: the declaration is `weakly linked`. A member is added to the end of AttributeList to save the location of the 'nopartial' keyword. A bool member is added to AvailabilityAttr. The diagnostics for 'nopartial' not-yet-introduced is handled in the same way as we handle unavailable cases. Reviewed by Doug Gregor and Jordan Rose. rdar://23791325 Modified: cfe/trunk/include/clang/Basic/Attr.td cfe/trunk/include/clang/Basic/AttrDocs.td cfe/trunk/include/clang/Basic/DiagnosticGroups.td cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Parse/Parser.h cfe/trunk/include/clang/Sema/AttributeList.h cfe/trunk/include/clang/Sema/DelayedDiagnostic.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Parse/ParseDecl.cpp cfe/trunk/lib/Parse/Parser.cpp cfe/trunk/lib/Sema/DelayedDiagnostic.cpp cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaDeclAttr.cpp cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/test/Sema/attr-availability-macosx.c Modified: cfe/trunk/include/clang/Basic/Attr.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=261163&r1=261162&r2=261163&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/Attr.td (original) +++ cfe/trunk/include/clang/Basic/Attr.td Wed Feb 17 16:05:48 2016 @@ -450,7 +450,8 @@ def Availability : InheritableAttr { let Spellings = [GNU<"availability">]; let Args = [IdentifierArgument<"platform">, VersionArgument<"introduced">, VersionArgument<"deprecated">, VersionArgument<"obsoleted">, - BoolArgument<"unavailable">, StringArgument<"message">]; + BoolArgument<"unavailable">, StringArgument<"message">, + BoolArgument<"nopartial">]; let AdditionalMembers = [{static llvm::StringRef getPrettyPlatformName(llvm::StringRef Platform) { return llvm::StringSwitch<llvm::StringRef>(Platform) Modified: cfe/trunk/include/clang/Basic/AttrDocs.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=261163&r1=261162&r2=261163&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/AttrDocs.td (original) +++ cfe/trunk/include/clang/Basic/AttrDocs.td Wed Feb 17 16:05:48 2016 @@ -685,9 +685,14 @@ are: Apple's watchOS operating system. The minimum deployment target is specified by the ``-mwatchos-version-min=*version*`` command-line argument. -A declaration can be used even when deploying back to a platform version prior -to when the declaration was introduced. When this happens, the declaration is -`weakly linked +An optional nopartial can be placed after the platform name. +With the optional nopartial, when deploying back to a platform version prior to +when the declaration was introduced, Clang emits an error specifying that the +function is not introduced yet. + +Without the optional nopartial, a declaration can be used even when deploying back +to a platform version prior to when the declaration was introduced. When this +happens, the declaration is `weakly linked <https://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html>`_, as if the ``weak_import`` attribute were added to the declaration. A weakly-linked declaration may or may not be present a run-time, and a program Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=261163&r1=261162&r2=261163&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Wed Feb 17 16:05:48 2016 @@ -87,6 +87,7 @@ def DeprecatedAttributes : DiagGroup<"de def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">; def UnavailableDeclarations : DiagGroup<"unavailable-declarations">; def PartialAvailability : DiagGroup<"partial-availability">; +def NotYetIntroducedDeclarations : DiagGroup<"not-yet-introduced-declarations">; def DeprecatedImplementations :DiagGroup<"deprecated-implementations">; def DeprecatedIncrementBool : DiagGroup<"deprecated-increment-bool">; def DeprecatedRegister : DiagGroup<"deprecated-register">; Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=261163&r1=261162&r2=261163&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Feb 17 16:05:48 2016 @@ -837,7 +837,7 @@ def warn_accessor_property_type_mismatch def not_conv_function_declared_at : Note<"type conversion function declared here">; def note_method_declared_at : Note<"method %0 declared here">; def note_property_attribute : Note<"property %0 is declared " - "%select{deprecated|unavailable|partial}1 here">; + "%select{deprecated|unavailable|partial|not-yet-introduced}1 here">; def err_setter_type_void : Error<"type of setter must be void">; def err_duplicate_method_decl : Error<"duplicate declaration of method %0">; def warn_duplicate_method_decl : @@ -4120,9 +4120,14 @@ def err_unavailable_message : Error<"%0 def warn_unavailable_fwdclass_message : Warning< "%0 may be unavailable because the receiver type is unknown">, InGroup<UnavailableDeclarations>; +def err_notyetintroduced : Error<"%0 is not introduced yet">; +def err_notyetintroduced_message : Error<"%0 is not introduced yet: %1">; +def warn_notyetintroduced_fwdclass_message : Warning< + "%0 may not be introduced because the receiver type is unknown">, + InGroup<NotYetIntroducedDeclarations>; def note_availability_specified_here : Note< "%0 has been explicitly marked " - "%select{unavailable|deleted|deprecated|partial}1 here">; + "%select{unavailable|deleted|deprecated|partial|not-yet-introduced}1 here">; def note_implicitly_deleted : Note< "explicitly defaulted function was implicitly deleted here">; def note_inherited_deleted_here : Note< Modified: cfe/trunk/include/clang/Parse/Parser.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=261163&r1=261162&r2=261163&view=diff ============================================================================== --- cfe/trunk/include/clang/Parse/Parser.h (original) +++ cfe/trunk/include/clang/Parse/Parser.h Wed Feb 17 16:05:48 2016 @@ -134,6 +134,9 @@ class Parser : public CodeCompletionHand /// \brief Identifier for "message". IdentifierInfo *Ident_message; + /// \brief Identifier for "nopartial". + IdentifierInfo *Ident_nopartial; + /// C++0x contextual keywords. mutable IdentifierInfo *Ident_final; mutable IdentifierInfo *Ident_override; Modified: cfe/trunk/include/clang/Sema/AttributeList.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=261163&r1=261162&r2=261163&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/AttributeList.h (original) +++ cfe/trunk/include/clang/Sema/AttributeList.h Wed Feb 17 16:05:48 2016 @@ -157,6 +157,17 @@ private: + NumArgs)[index]; } + /// The location of the 'nopartial' keyword in an availability attribute. + SourceLocation *getNopartialSlot() { + return reinterpret_cast<SourceLocation*>( + &getAvailabilitySlot(ObsoletedSlot) + 1); + } + + SourceLocation const *getNopartialSlot() const { + return reinterpret_cast<SourceLocation const*>( + &getAvailabilitySlot(ObsoletedSlot) + 1); + } + public: struct TypeTagForDatatypeData { ParsedType *MatchingCType; @@ -233,7 +244,7 @@ private: const AvailabilityChange &obsoleted, SourceLocation unavailable, const Expr *messageExpr, - Syntax syntaxUsed) + Syntax syntaxUsed, SourceLocation nopartial) : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), @@ -245,6 +256,7 @@ private: new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced); new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated); new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted); + memcpy(getNopartialSlot(), &nopartial, sizeof(SourceLocation)); AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } @@ -412,6 +424,11 @@ public: return getAvailabilitySlot(ObsoletedSlot); } + SourceLocation getNopartialLoc() const { + assert(getKind() == AT_Availability && "Not an availability attribute"); + return *getNopartialSlot(); + } + SourceLocation getUnavailableLoc() const { assert(getKind() == AT_Availability && "Not an availability attribute"); return UnavailableLoc; @@ -488,7 +505,7 @@ public: AvailabilityAllocSize = sizeof(AttributeList) + ((3 * sizeof(AvailabilityChange) + sizeof(void*) + - sizeof(ArgsUnion) - 1) + sizeof(ArgsUnion) + sizeof(SourceLocation) - 1) / sizeof(void*) * sizeof(void*)), TypeTagForDatatypeAllocSize = sizeof(AttributeList) @@ -606,13 +623,14 @@ public: const AvailabilityChange &obsoleted, SourceLocation unavailable, const Expr *MessageExpr, - AttributeList::Syntax syntax) { + AttributeList::Syntax syntax, + SourceLocation nopartial) { void *memory = allocate(AttributeFactory::AvailabilityAllocSize); return add(new (memory) AttributeList(attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, obsoleted, unavailable, MessageExpr, - syntax)); + syntax, nopartial)); } AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, @@ -741,10 +759,12 @@ public: const AvailabilityChange &obsoleted, SourceLocation unavailable, const Expr *MessageExpr, - AttributeList::Syntax syntax) { + AttributeList::Syntax syntax, + SourceLocation nopartial) { AttributeList *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced, - deprecated, obsoleted, unavailable, MessageExpr, syntax); + deprecated, obsoleted, unavailable, MessageExpr, syntax, + nopartial); add(attr); return attr; } Modified: cfe/trunk/include/clang/Sema/DelayedDiagnostic.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DelayedDiagnostic.h?rev=261163&r1=261162&r2=261163&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/DelayedDiagnostic.h (original) +++ cfe/trunk/include/clang/Sema/DelayedDiagnostic.h Wed Feb 17 16:05:48 2016 @@ -113,7 +113,8 @@ private: /// the complete parsing of the current declaration. class DelayedDiagnostic { public: - enum DDKind { Deprecation, Unavailable, Access, ForbiddenType }; + enum DDKind { Deprecation, Unavailable, Access, ForbiddenType, + NotYetIntroduced }; unsigned char Kind; // actually a DDKind bool Triggered; @@ -165,13 +166,15 @@ public: } const NamedDecl *getDeprecationDecl() const { - assert((Kind == Deprecation || Kind == Unavailable) && + assert((Kind == Deprecation || Kind == Unavailable || + Kind == NotYetIntroduced) && "Not a deprecation diagnostic."); return DeprecationData.Decl; } StringRef getDeprecationMessage() const { - assert((Kind == Deprecation || Kind == Unavailable) && + assert((Kind == Deprecation || Kind == Unavailable || + Kind == NotYetIntroduced) && "Not a deprecation diagnostic."); return StringRef(DeprecationData.Message, DeprecationData.MessageLen); Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=261163&r1=261162&r2=261163&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Wed Feb 17 16:05:48 2016 @@ -2108,6 +2108,7 @@ public: VersionTuple Obsoleted, bool IsUnavailable, StringRef Message, + bool IsNopartial, AvailabilityMergeKind AMK, unsigned AttrSpellingListIndex); TypeVisibilityAttr *mergeTypeVisibilityAttr(Decl *D, SourceRange Range, @@ -3535,7 +3536,8 @@ public: void redelayDiagnostics(sema::DelayedDiagnosticPool &pool); - enum AvailabilityDiagnostic { AD_Deprecation, AD_Unavailable, AD_Partial }; + enum AvailabilityDiagnostic { AD_Deprecation, AD_Unavailable, AD_Partial, + AD_NotYetIntroduced }; void EmitAvailabilityWarning(AvailabilityDiagnostic AD, NamedDecl *D, StringRef Message, Modified: cfe/trunk/lib/Parse/ParseDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=261163&r1=261162&r2=261163&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseDecl.cpp (original) +++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed Feb 17 16:05:48 2016 @@ -833,11 +833,14 @@ VersionTuple Parser::ParseVersionTuple(S /// \brief Parse the contents of the "availability" attribute. /// /// availability-attribute: -/// 'availability' '(' platform ',' version-arg-list, opt-message')' +/// 'availability' '(' platform ',' opt-nopartial version-arg-list, opt-message')' /// /// platform: /// identifier /// +/// opt-nopartial: +/// 'nopartial' ',' +/// /// version-arg-list: /// version-arg /// version-arg ',' version-arg-list @@ -867,7 +870,7 @@ void Parser::ParseAvailabilityAttribute( return; } - // Parse the platform name, + // Parse the platform name. if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_availability_expected_platform); SkipUntil(tok::r_paren, StopAtSemi); @@ -889,10 +892,12 @@ void Parser::ParseAvailabilityAttribute( Ident_obsoleted = PP.getIdentifierInfo("obsoleted"); Ident_unavailable = PP.getIdentifierInfo("unavailable"); Ident_message = PP.getIdentifierInfo("message"); + Ident_nopartial = PP.getIdentifierInfo("nopartial"); } - // Parse the set of introductions/deprecations/removals. - SourceLocation UnavailableLoc; + // Parse the optional "nopartial" and the set of + // introductions/deprecations/removals. + SourceLocation UnavailableLoc, NopartialLoc; do { if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_availability_expected_change); @@ -902,6 +907,15 @@ void Parser::ParseAvailabilityAttribute( IdentifierInfo *Keyword = Tok.getIdentifierInfo(); SourceLocation KeywordLoc = ConsumeToken(); + if (Keyword == Ident_nopartial) { + if (NopartialLoc.isValid()) { + Diag(KeywordLoc, diag::err_availability_redundant) + << Keyword << SourceRange(NopartialLoc); + } + NopartialLoc = KeywordLoc; + continue; + } + if (Keyword == Ident_unavailable) { if (UnavailableLoc.isValid()) { Diag(KeywordLoc, diag::err_availability_redundant) @@ -1023,7 +1037,7 @@ void Parser::ParseAvailabilityAttribute( Changes[Deprecated], Changes[Obsoleted], UnavailableLoc, MessageExpr.get(), - Syntax); + Syntax, NopartialLoc); } /// \brief Parse the contents of the "objc_bridge_related" attribute. Modified: cfe/trunk/lib/Parse/Parser.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=261163&r1=261162&r2=261163&view=diff ============================================================================== --- cfe/trunk/lib/Parse/Parser.cpp (original) +++ cfe/trunk/lib/Parse/Parser.cpp Wed Feb 17 16:05:48 2016 @@ -491,6 +491,7 @@ void Parser::Initialize() { Ident_deprecated = nullptr; Ident_obsoleted = nullptr; Ident_unavailable = nullptr; + Ident_nopartial = nullptr; Ident__except = nullptr; Modified: cfe/trunk/lib/Sema/DelayedDiagnostic.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DelayedDiagnostic.cpp?rev=261163&r1=261162&r2=261163&view=diff ============================================================================== --- cfe/trunk/lib/Sema/DelayedDiagnostic.cpp (original) +++ cfe/trunk/lib/Sema/DelayedDiagnostic.cpp Wed Feb 17 16:05:48 2016 @@ -35,6 +35,9 @@ DelayedDiagnostic::makeAvailability(Sema case Sema::AD_Unavailable: DD.Kind = Unavailable; break; + case Sema::AD_NotYetIntroduced: + DD.Kind = NotYetIntroduced; + break; case Sema::AD_Partial: llvm_unreachable("AD_Partial diags should not be delayed"); } @@ -63,6 +66,7 @@ void DelayedDiagnostic::Destroy() { case Deprecation: case Unavailable: + case NotYetIntroduced: delete [] DeprecationData.Message; break; Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=261163&r1=261162&r2=261163&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Feb 17 16:05:48 2016 @@ -2196,7 +2196,7 @@ static bool mergeDeclAttribute(Sema &S, NewAttr = S.mergeAvailabilityAttr(D, AA->getRange(), AA->getPlatform(), AA->getIntroduced(), AA->getDeprecated(), AA->getObsoleted(), AA->getUnavailable(), - AA->getMessage(), AMK, + AA->getMessage(), AA->getNopartial(), AMK, AttrSpellingListIndex); else if (const auto *VA = dyn_cast<VisibilityAttr>(Attr)) NewAttr = S.mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility(), Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=261163&r1=261162&r2=261163&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Wed Feb 17 16:05:48 2016 @@ -1916,6 +1916,7 @@ AvailabilityAttr *Sema::mergeAvailabilit VersionTuple Obsoleted, bool IsUnavailable, StringRef Message, + bool IsNopartial, AvailabilityMergeKind AMK, unsigned AttrSpellingListIndex) { VersionTuple MergedIntroduced = Introduced; @@ -2062,7 +2063,7 @@ AvailabilityAttr *Sema::mergeAvailabilit return ::new (Context) AvailabilityAttr(Range, Context, Platform, Introduced, Deprecated, Obsoleted, IsUnavailable, Message, - AttrSpellingListIndex); + IsNopartial, AttrSpellingListIndex); } return nullptr; } @@ -2089,6 +2090,7 @@ static void handleAvailabilityAttr(Sema AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated(); AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted(); bool IsUnavailable = Attr.getUnavailableLoc().isValid(); + bool IsNopartial = Attr.getNopartialLoc().isValid(); StringRef Str; if (const StringLiteral *SE = dyn_cast_or_null<StringLiteral>(Attr.getMessageExpr())) @@ -2099,6 +2101,7 @@ static void handleAvailabilityAttr(Sema Deprecated.Version, Obsoleted.Version, IsUnavailable, Str, + IsNopartial, Sema::AMK_None, Index); if (NewAttr) @@ -2143,6 +2146,7 @@ static void handleAvailabilityAttr(Sema NewDeprecated, NewObsoleted, IsUnavailable, Str, + IsNopartial, Sema::AMK_None, Index); if (NewAttr) @@ -2165,6 +2169,7 @@ static void handleAvailabilityAttr(Sema Deprecated.Version, Obsoleted.Version, IsUnavailable, Str, + IsNopartial, Sema::AMK_None, Index); if (NewAttr) @@ -5957,6 +5962,14 @@ static void DoEmitAvailabilityWarning(Se property_note_select = /* partial */ 2; available_here_select_kind = /* partial */ 3; break; + + case Sema::AD_NotYetIntroduced: + diag = diag::err_notyetintroduced; + diag_message = diag::err_notyetintroduced_message; + diag_fwdclass_message = diag::warn_notyetintroduced_fwdclass_message; + property_note_select = /* deprecated */ 3; + available_here_select_kind = /* notyetintroduced */ 4; + break; } if (!Message.empty()) { @@ -5983,10 +5996,22 @@ static void DoEmitAvailabilityWarning(Se static void handleDelayedAvailabilityCheck(Sema &S, DelayedDiagnostic &DD, Decl *Ctx) { assert(DD.Kind == DelayedDiagnostic::Deprecation || - DD.Kind == DelayedDiagnostic::Unavailable); - Sema::AvailabilityDiagnostic AD = DD.Kind == DelayedDiagnostic::Deprecation - ? Sema::AD_Deprecation - : Sema::AD_Unavailable; + DD.Kind == DelayedDiagnostic::Unavailable || + DD.Kind == DelayedDiagnostic::NotYetIntroduced); + Sema::AvailabilityDiagnostic AD; + switch (DD.Kind) { + case DelayedDiagnostic::Deprecation: + AD = Sema::AD_Deprecation; + break; + case DelayedDiagnostic::Unavailable: + AD = Sema::AD_Unavailable; + break; + case DelayedDiagnostic::NotYetIntroduced: + AD = Sema::AD_NotYetIntroduced; + break; + default: + llvm_unreachable("Expecting: deprecated, unavailable, not-yet-introduced"); + } DD.Triggered = true; DoEmitAvailabilityWarning( S, AD, Ctx, DD.getDeprecationDecl(), DD.getDeprecationMessage(), DD.Loc, Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=261163&r1=261162&r2=261163&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Feb 17 16:05:48 2016 @@ -137,7 +137,7 @@ DiagnoseAvailabilityOfDecl(Sema &S, Name const ObjCPropertyDecl *ObjCPDecl = nullptr; if (Result == AR_Deprecated || Result == AR_Unavailable || - AR_NotYetIntroduced) { + Result == AR_NotYetIntroduced) { if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { if (const ObjCPropertyDecl *PD = MD->findPropertyDecl()) { AvailabilityResult PDeclResult = PD->getAvailability(nullptr); @@ -159,11 +159,20 @@ DiagnoseAvailabilityOfDecl(Sema &S, Name break; case AR_NotYetIntroduced: { + // With nopartial, the compiler will emit delayed error just like how + // "deprecated, unavailable" are handled. + AvailabilityAttr *AA = D->getAttr<AvailabilityAttr>(); + if (AA && AA->getNopartial() && + S.getCurContextAvailability() != AR_NotYetIntroduced) + S.EmitAvailabilityWarning(Sema::AD_NotYetIntroduced, + D, Message, Loc, UnknownObjCClass, ObjCPDecl, + ObjCPropertyAccess); + // Don't do this for enums, they can't be redeclared. if (isa<EnumConstantDecl>(D) || isa<EnumDecl>(D)) break; - bool Warn = !D->getAttr<AvailabilityAttr>()->isInherited(); + bool Warn = !AA->isInherited(); // Objective-C method declarations in categories are not modelled as // redeclarations, so manually look for a redeclaration in a category // if necessary. Modified: cfe/trunk/test/Sema/attr-availability-macosx.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-availability-macosx.c?rev=261163&r1=261162&r2=261163&view=diff ============================================================================== --- cfe/trunk/test/Sema/attr-availability-macosx.c (original) +++ cfe/trunk/test/Sema/attr-availability-macosx.c Wed Feb 17 16:05:48 2016 @@ -6,6 +6,7 @@ void f2(int) __attribute__((availability void f3(int) __attribute__((availability(macosx,introduced=10.6))); void f4(int) __attribute__((availability(macosx,introduced=10.1,deprecated=10.3,obsoleted=10.5), availability(ios,introduced=2.0,deprecated=3.0))); // expected-note{{explicitly marked unavailable}} void f5(int) __attribute__((availability(ios,introduced=3.2), availability(macosx,unavailable))); // expected-note{{'f5' has been explicitly marked unavailable here}} +void f6(int) __attribute__((availability(macosx,nopartial,introduced=10.6))); //expected-note{{'f6' has been explicitly marked not-yet-introduced here}} void test() { f0(0); @@ -14,6 +15,7 @@ void test() { f3(0); f4(0); // expected-error{{f4' is unavailable: obsoleted in OS X 10.5}} f5(0); // expected-error{{'f5' is unavailable: not available on OS X}} + f6(0); // expected-error{{'f6' is not introduced yet: introduced in OS X 10.6}} } // rdar://10535640 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits