r261163 - Add 'nopartial' qualifier for availability attributes.
Duncan P. N. Exon Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 18 07:16:09 PST 2016
> On 2016-Feb-17, at 14:05, Manman Ren via cfe-commits <cfe-commits at 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 at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list