> On 2016-Feb-17, at 14:05, Manman Ren via cfe-commits > <cfe-commits@lists.llvm.org> wrote: > > 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
This should really be "``nopartial``" (code-quotes). However, I have a more substantial edit below. > 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. I'd rather de-emphasize the new flag. We're not expecting much adoption of it (just libc++), so we should keep the text focused on describing the default behaviour. I suggest leaving the wording more like the original: ``` A declaration can typically 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 . . . ``` ^ I've just added the word "typically". Later, add a paragraph: ``` The flag ``flag-name`` disallows using API when deploying back to a platform version prior to when the declaration was introduced. An attempt to use such API before its introduction causes a hard error. Weakly-linking is almost always a better API choice, since it allows users to query availability at runtime. ``` I'm also not sure about "nopartial" (my fault, this name was my idea). In the context of all the text we have about availability (here, and in the errors and notes) I think "strict" fits much better. > 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>; There's no testcase for this warning. However, I'm not sure you'll need all these new diagnostics given my other suggestions below. > 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 }; Why do we need "NotYetIntroduced"? We don't need a new DDKind for obsoleted API, so I don't think we need one here... and I think that will simplify the change quite a bit. This has an effect on the error and note text, but I actually think it's a good effect. > 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}} In the context of this note, I think "nopartial" isn't self-explanatory with the error/note text (sadly I came up with it). I think "strict" is better. Also, for consistency with obsoleted API, I think this should be "marked unavailable here" ("marked not-yet-introduced here" is awkward). > 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}} This error makes more sense to me: ``` expected-error{{'f6' is unavailable: not introduced until OS X 10.6}} ``` In combination with the note, we get something like: ``` ...: error: 'f6' is unavailable: not introduced until OS X 10.6 f6(0); ^ ...: note: 'f6' has been explicitly marked unavailable here void f6(int) __attribute__((availability(macosx,strict,introduced=10.6))); ^ ``` This is more consistent with the other reasons API might be unavailable, and I think the language is more clear. > } > > // rdar://10535640 > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits