[PATCH] D56892: Add a priority field to availability attributes to prioritize explicit attributes from declaration over attributes from '#pragma clang attribute'

2019-01-24 Thread Alex Lorenz via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL352084: Add a priority field to availability attributes to 
prioritize explicit (authored by arphaman, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D56892?vs=182608=183353#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56892/new/

https://reviews.llvm.org/D56892

Files:
  cfe/trunk/include/clang/Basic/Attr.td
  cfe/trunk/include/clang/Basic/AttrDocs.td
  cfe/trunk/include/clang/Sema/ParsedAttr.h
  cfe/trunk/include/clang/Sema/Sema.h
  cfe/trunk/lib/Sema/SemaAttr.cpp
  cfe/trunk/lib/Sema/SemaDecl.cpp
  cfe/trunk/lib/Sema/SemaDeclAttr.cpp
  cfe/trunk/test/SemaObjC/attr-availability-priority.m

Index: cfe/trunk/include/clang/Sema/Sema.h
===
--- cfe/trunk/include/clang/Sema/Sema.h
+++ cfe/trunk/include/clang/Sema/Sema.h
@@ -2459,18 +2459,38 @@
 AMK_ProtocolImplementation,
   };
 
+  /// Describes the kind of priority given to an availability attribute.
+  ///
+  /// The sum of priorities deteremines the final priority of the attribute.
+  /// The final priority determines how the attribute will be merged.
+  /// An attribute with a lower priority will always remove higher priority
+  /// attributes for the specified platform when it is being applied. An
+  /// attribute with a higher priority will not be applied if the declaration
+  /// already has an availability attribute with a lower priority for the
+  /// specified platform. The final prirority values are not expected to match
+  /// the values in this enumeration, but instead should be treated as a plain
+  /// integer value. This enumeration just names the priority weights that are
+  /// used to calculate that final vaue.
+  enum AvailabilityPriority : int {
+/// The availability attribute was specified explicitly next to the
+/// declaration.
+AP_Explicit = 0,
+
+/// The availability attribute was applied using '#pragma clang attribute'.
+AP_PragmaClangAttribute = 1,
+
+/// The availability attribute for a specific platform was inferred from
+/// an availability attribute for another platform.
+AP_InferredFromOtherPlatform = 2
+  };
+
   /// Attribute merging methods. Return true if a new attribute was added.
-  AvailabilityAttr *mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
-  IdentifierInfo *Platform,
-  bool Implicit,
-  VersionTuple Introduced,
-  VersionTuple Deprecated,
-  VersionTuple Obsoleted,
-  bool IsUnavailable,
-  StringRef Message,
-  bool IsStrict, StringRef Replacement,
-  AvailabilityMergeKind AMK,
-  unsigned AttrSpellingListIndex);
+  AvailabilityAttr *mergeAvailabilityAttr(
+  NamedDecl *D, SourceRange Range, IdentifierInfo *Platform, bool Implicit,
+  VersionTuple Introduced, VersionTuple Deprecated, VersionTuple Obsoleted,
+  bool IsUnavailable, StringRef Message, bool IsStrict,
+  StringRef Replacement, AvailabilityMergeKind AMK, int Priority,
+  unsigned AttrSpellingListIndex);
   TypeVisibilityAttr *mergeTypeVisibilityAttr(Decl *D, SourceRange Range,
TypeVisibilityAttr::VisibilityType Vis,
   unsigned AttrSpellingListIndex);
Index: cfe/trunk/include/clang/Sema/ParsedAttr.h
===
--- cfe/trunk/include/clang/Sema/ParsedAttr.h
+++ cfe/trunk/include/clang/Sema/ParsedAttr.h
@@ -207,6 +207,9 @@
   /// A cached value.
   mutable unsigned ProcessingCache : 8;
 
+  /// True if the attribute is specified using '#pragma clang attribute'.
+  mutable unsigned IsPragmaClangAttribute : 1;
+
   /// The location of the 'unavailable' keyword in an
   /// availability attribute.
   SourceLocation UnavailableLoc;
@@ -238,7 +241,8 @@
 ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs),
 SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false),
 IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
-HasParsedType(false), HasProcessingCache(false) {
+HasParsedType(false), HasProcessingCache(false),
+IsPragmaClangAttribute(false) {
 if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion));
 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
   }
@@ -255,8 +259,8 @@
 ScopeLoc(scopeLoc), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false),
 UsedAsTypeAttr(false), 

[PATCH] D56892: Add a priority field to availability attributes to prioritize explicit attributes from declaration over attributes from '#pragma clang attribute'

2019-01-21 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman accepted this revision.
aaron.ballman added a comment.

LGTM with a suggested edit for the docs (which look great, btw!).




Comment at: include/clang/Basic/AttrDocs.td:1252
+  
+For platforms like ``watchOS`` and ``tvOS`` whose availability attributes can
+be implicitly inferred from an ``iOS`` availability attribute the logic is

tvOS whose -> tvOS, whose



Comment at: include/clang/Basic/AttrDocs.td:1253
+For platforms like ``watchOS`` and ``tvOS`` whose availability attributes can
+be implicitly inferred from an ``iOS`` availability attribute the logic is
+slightly more complex. The explicit and the pragma-applied availability

attribute the logic -> attribute, the logic


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56892/new/

https://reviews.llvm.org/D56892



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56892: Add a priority field to availability attributes to prioritize explicit attributes from declaration over attributes from '#pragma clang attribute'

2019-01-18 Thread Erik Pilkington via Phabricator via cfe-commits
erik.pilkington accepted this revision.
erik.pilkington added a comment.
This revision is now accepted and ready to land.

LGTM, thanks!


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56892/new/

https://reviews.llvm.org/D56892



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56892: Add a priority field to availability attributes to prioritize explicit attributes from declaration over attributes from '#pragma clang attribute'

2019-01-18 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman added a comment.

In D56892#1363089 , @aaron.ballman 
wrote:

> I think the documentation for the attribute should be updated to explain this 
> new behavior, otherwise this will be a very inexplicable feature to users.


Done

> One question I have is: will this feature also be needed by other attributes? 
> This seems like a somewhat general problem between explicit attributes, 
> implicit attributes, and attributes added via the pragma. It might not be 
> worth generalizing yet, but I'm curious to know whether we'll need this for 
> things like visibility and type_visibility as well.

Possibly. We haven't come across a use case that requires that yet, but we 
would be definitely willing to work on a more generalized solution in the 
future if such a need arises.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56892/new/

https://reviews.llvm.org/D56892



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56892: Add a priority field to availability attributes to prioritize explicit attributes from declaration over attributes from '#pragma clang attribute'

2019-01-18 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman updated this revision to Diff 182608.
arphaman marked 3 inline comments as done.
arphaman added a comment.

- Add documentation and expand a comment as suggested by Aaron.
- Address Erik's comments.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56892/new/

https://reviews.llvm.org/D56892

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Sema/ParsedAttr.h
  include/clang/Sema/Sema.h
  lib/Sema/SemaAttr.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  test/SemaObjC/attr-availability-priority.m

Index: test/SemaObjC/attr-availability-priority.m
===
--- /dev/null
+++ test/SemaObjC/attr-availability-priority.m
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -triple arm64-apple-tvos12.0 -fsyntax-only -verify %s
+
+void explicit() __attribute__((availability(tvos, introduced=11.0, deprecated=12.0))); // expected-note {{marked deprecated here}}
+void inferred() __attribute__((availability(ios, introduced=11.0, deprecated=12.0))); // expected-note {{marked deprecated here}}
+void explicitOverInferred()
+__attribute__((availability(ios, introduced=11.0, deprecated=12.0)))
+__attribute__((availability(tvos, introduced=11.0)));
+void explicitOverInferred2()
+__attribute__((availability(tvos, introduced=11.0)))
+__attribute__((availability(ios, introduced=11.0, deprecated=12.0)));
+
+void simpleUsage() {
+  explicit(); // expected-warning{{'explicit' is deprecated: first deprecated in tvOS 12.0}}
+  inferred(); // expected-warning{{'inferred' is deprecated: first deprecated in tvOS 12.0}}
+  // ok, not deprecated for tvOS.
+  explicitOverInferred();
+  explicitOverInferred2();
+}
+
+#pragma clang attribute push (__attribute__((availability(tvos, introduced=11.0, deprecated=12.0))), apply_to=function)
+
+void explicitFromPragma(); // expected-note {{marked deprecated here}}
+void explicitWinsOverExplicitFromPragma() __attribute__((availability(tvos, introduced=11.0)));
+void implicitLosesOverExplicitFromPragma() __attribute__((availability(ios, introduced=11.0))); // expected-note {{marked deprecated here}}
+
+#pragma clang attribute pop
+
+#pragma clang attribute push (__attribute__((availability(ios, introduced=11.0, deprecated=12.0))), apply_to=function)
+
+void implicitFromPragma(); // expected-note {{marked deprecated here}}
+void explicitWinsOverImplicitFromPragma() __attribute__((availability(tvos, introduced=11.0)));
+void implicitWinsOverImplicitFromPragma() __attribute__((availability(ios, introduced=11.0)));
+
+#pragma clang attribute pop
+
+#pragma clang attribute push (__attribute__((availability(tvos, introduced=11.0, deprecated=12.0))), apply_to=function)
+#pragma clang attribute push (__attribute__((availability(ios, introduced=11.0, deprecated=11.3))), apply_to=function)
+
+void pragmaExplicitWinsOverPragmaImplicit(); // expected-note {{marked deprecated here}}
+
+#pragma clang attribute pop
+#pragma clang attribute pop
+
+void pragmaUsage() {
+  explicitFromPragma(); // expected-warning {{'explicitFromPragma' is deprecated: first deprecated in tvOS 12.0}}
+  explicitWinsOverExplicitFromPragma(); // ok
+  implicitLosesOverExplicitFromPragma(); // expected-warning {{'implicitLosesOverExplicitFromPragma' is deprecated: first deprecated in tvOS 12.0}}
+
+  implicitFromPragma(); // expected-warning {{'implicitFromPragma' is deprecated: first deprecated in tvOS 12.0}}
+  explicitWinsOverImplicitFromPragma(); // ok
+  implicitWinsOverImplicitFromPragma(); // ok
+  pragmaExplicitWinsOverPragmaImplicit(); // expected-warning {{'pragmaExplicitWinsOverPragmaImplicit' is deprecated: first deprecated in tvOS 12.0}}
+}
Index: lib/Sema/SemaDeclAttr.cpp
===
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -2284,18 +2284,11 @@
   return false;
 }
 
-AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
-  IdentifierInfo *Platform,
-  bool Implicit,
-  VersionTuple Introduced,
-  VersionTuple Deprecated,
-  VersionTuple Obsoleted,
-  bool IsUnavailable,
-  StringRef Message,
-  bool IsStrict,
-  StringRef Replacement,
-  AvailabilityMergeKind AMK,
-  unsigned AttrSpellingListIndex) {
+AvailabilityAttr *Sema::mergeAvailabilityAttr(
+NamedDecl *D, SourceRange Range, IdentifierInfo *Platform, bool Implicit,
+VersionTuple Introduced, VersionTuple Deprecated, VersionTuple Obsoleted,
+bool 

[PATCH] D56892: Add a priority field to availability attributes to prioritize explicit attributes from declaration over attributes from '#pragma clang attribute'

2019-01-18 Thread Erik Pilkington via Phabricator via cfe-commits
erik.pilkington added a comment.

This seems pretty reasonable to me. I agree that a more general mechanism to 
override #pca (/implicit) attributes would be pretty useful, but I guess there 
is no need to jump the gun on that.




Comment at: include/clang/Sema/Sema.h:2471
+/// declaration.
+AP_Explicit,
+

Maybe add `= 0` (and `=1` and `=2`) explicitly to indicate that their relative 
values matter here.



Comment at: lib/Sema/SemaDeclAttr.cpp:2479
+  int PriorityModifier =
+  AL.isPragmaClangAttribute() ? Sema::AP_PragmaClangAttribute : 0;
+  AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(

Use AP_Explicit here instead of 0?



Comment at: lib/Sema/SemaDeclAttr.cpp:2483
+  Deprecated.Version, Obsoleted.Version, IsUnavailable, Str, IsStrict,
+  Replacement, Sema::AMK_None, PriorityModifier + Sema::AP_Explicit, 
Index);
   if (NewAttr)

... And the avoid adding it back on here?


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56892/new/

https://reviews.llvm.org/D56892



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56892: Add a priority field to availability attributes to prioritize explicit attributes from declaration over attributes from '#pragma clang attribute'

2019-01-18 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added a comment.

I think the documentation for the attribute should be updated to explain this 
new behavior, otherwise this will be a very inexplicable feature to users.

One question I have is: will this feature also be needed by other attributes? 
This seems like a somewhat general problem between explicit attributes, 
implicit attributes, and attributes added via the pragma. It might not be worth 
generalizing yet, but I'm curious to know whether we'll need this for things 
like visibility and type_visibility as well.




Comment at: include/clang/Sema/Sema.h:2467
+  /// already has an availability attribute with a lower priority for the
+  /// specified platform.
+  enum AvailabilityPriority : int {

We should have a comment somewhere (perhaps here) that makes it clear that the 
priorities we calculate and store on the semantic attribute object are not 
expected to match values in this enumeration, but instead be treated as a plain 
integer value. This enumeration is just giving a name to some of the addends 
used to calculate that value.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56892/new/

https://reviews.llvm.org/D56892



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56892: Add a priority field to availability attributes to prioritize explicit attributes from declaration over attributes from '#pragma clang attribute'

2019-01-17 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman updated this revision to Diff 182432.
arphaman added a comment.

Reverse the priority numbering direction as suggested by @dexonsmith .

Now the lower priority is the most important, and the less important priorities 
have a higher numerical value.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56892/new/

https://reviews.llvm.org/D56892

Files:
  include/clang/Basic/Attr.td
  include/clang/Sema/ParsedAttr.h
  include/clang/Sema/Sema.h
  lib/Sema/SemaAttr.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  test/SemaObjC/attr-availability-priority.m

Index: test/SemaObjC/attr-availability-priority.m
===
--- /dev/null
+++ test/SemaObjC/attr-availability-priority.m
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -triple arm64-apple-tvos12.0 -fsyntax-only -verify %s
+
+void explicit() __attribute__((availability(tvos, introduced=11.0, deprecated=12.0))); // expected-note {{marked deprecated here}}
+void inferred() __attribute__((availability(ios, introduced=11.0, deprecated=12.0))); // expected-note {{marked deprecated here}}
+void explicitOverInferred()
+__attribute__((availability(ios, introduced=11.0, deprecated=12.0)))
+__attribute__((availability(tvos, introduced=11.0)));
+void explicitOverInferred2()
+__attribute__((availability(tvos, introduced=11.0)))
+__attribute__((availability(ios, introduced=11.0, deprecated=12.0)));
+
+void simpleUsage() {
+  explicit(); // expected-warning{{'explicit' is deprecated: first deprecated in tvOS 12.0}}
+  inferred(); // expected-warning{{'inferred' is deprecated: first deprecated in tvOS 12.0}}
+  // ok, not deprecated for tvOS.
+  explicitOverInferred();
+  explicitOverInferred2();
+}
+
+#pragma clang attribute push (__attribute__((availability(tvos, introduced=11.0, deprecated=12.0))), apply_to=function)
+
+void explicitFromPragma(); // expected-note {{marked deprecated here}}
+void explicitWinsOverExplicitFromPragma() __attribute__((availability(tvos, introduced=11.0)));
+void implicitLosesOverExplicitFromPragma() __attribute__((availability(ios, introduced=11.0))); // expected-note {{marked deprecated here}}
+
+#pragma clang attribute pop
+
+#pragma clang attribute push (__attribute__((availability(ios, introduced=11.0, deprecated=12.0))), apply_to=function)
+
+void implicitFromPragma(); // expected-note {{marked deprecated here}}
+void explicitWinsOverImplicitFromPragma() __attribute__((availability(tvos, introduced=11.0)));
+void implicitWinsOverImplicitFromPragma() __attribute__((availability(ios, introduced=11.0)));
+
+#pragma clang attribute pop
+
+#pragma clang attribute push (__attribute__((availability(tvos, introduced=11.0, deprecated=12.0))), apply_to=function)
+#pragma clang attribute push (__attribute__((availability(ios, introduced=11.0, deprecated=11.3))), apply_to=function)
+
+void pragmaExplicitWinsOverPragmaImplicit(); // expected-note {{marked deprecated here}}
+
+#pragma clang attribute pop
+#pragma clang attribute pop
+
+void pragmaUsage() {
+  explicitFromPragma(); // expected-warning {{'explicitFromPragma' is deprecated: first deprecated in tvOS 12.0}}
+  explicitWinsOverExplicitFromPragma(); // ok
+  implicitLosesOverExplicitFromPragma(); // expected-warning {{'implicitLosesOverExplicitFromPragma' is deprecated: first deprecated in tvOS 12.0}}
+
+  implicitFromPragma(); // expected-warning {{'implicitFromPragma' is deprecated: first deprecated in tvOS 12.0}}
+  explicitWinsOverImplicitFromPragma(); // ok
+  implicitWinsOverImplicitFromPragma(); // ok
+  pragmaExplicitWinsOverPragmaImplicit(); // expected-warning {{'pragmaExplicitWinsOverPragmaImplicit' is deprecated: first deprecated in tvOS 12.0}}
+}
Index: lib/Sema/SemaDeclAttr.cpp
===
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -2284,18 +2284,11 @@
   return false;
 }
 
-AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
-  IdentifierInfo *Platform,
-  bool Implicit,
-  VersionTuple Introduced,
-  VersionTuple Deprecated,
-  VersionTuple Obsoleted,
-  bool IsUnavailable,
-  StringRef Message,
-  bool IsStrict,
-  StringRef Replacement,
-  AvailabilityMergeKind AMK,
-  unsigned AttrSpellingListIndex) {
+AvailabilityAttr *Sema::mergeAvailabilityAttr(
+NamedDecl *D, SourceRange Range, IdentifierInfo *Platform, bool Implicit,
+VersionTuple Introduced, VersionTuple Deprecated, VersionTuple 

[PATCH] D56892: Add a priority field to availability attributes to prioritize explicit attributes from declaration over attributes from '#pragma clang attribute'

2019-01-17 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman created this revision.
arphaman added reviewers: erik.pilkington, aaron.ballman.
Herald added subscribers: dexonsmith, jkorous.

We have an issue when using `#pragma clang attribute` with availability 
attributes:

- The explicit attribute that's specified next to the declaration is not 
guaranteed to be preferred over the attribute specified in the pragma.

This patch fixes this by introducing a `priority` field to the availability 
attribute to control how they're merged. Attributes with higher priority are 
applied over attributes with lower priority for the same platform. The 
implicitly inferred attributes are given the lower priority. This ensures that:

1. explicit attributes are preferred over all other attributes.
2. implicitly inferred attributes that are inferred from an explicit attribute 
are discarded if there's an explicit attribute or an attribute specified using 
a `#pragma` for the same platform.
3. implicitly inferred attributes that are inferred from an attribute in the 
`#pragma` are not used if there's an explicit, explicit `#pragma`, or an 
implicit attribute inferred from an explicit attribute for the declaration.

This is the resulting ranking:

`platform availability > platform availability from pragma > inferred 
availability > inferred availability from pragma`

rdar://46390243


Repository:
  rC Clang

https://reviews.llvm.org/D56892

Files:
  include/clang/Basic/Attr.td
  include/clang/Sema/ParsedAttr.h
  include/clang/Sema/Sema.h
  lib/Sema/SemaAttr.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  test/SemaObjC/attr-availability-priority.m

Index: test/SemaObjC/attr-availability-priority.m
===
--- /dev/null
+++ test/SemaObjC/attr-availability-priority.m
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -triple arm64-apple-tvos12.0 -fsyntax-only -verify %s
+
+void explicit() __attribute__((availability(tvos, introduced=11.0, deprecated=12.0))); // expected-note {{marked deprecated here}}
+void inferred() __attribute__((availability(ios, introduced=11.0, deprecated=12.0))); // expected-note {{marked deprecated here}}
+void explicitOverInferred()
+__attribute__((availability(ios, introduced=11.0, deprecated=12.0)))
+__attribute__((availability(tvos, introduced=11.0)));
+void explicitOverInferred2()
+__attribute__((availability(tvos, introduced=11.0)))
+__attribute__((availability(ios, introduced=11.0, deprecated=12.0)));
+
+void simpleUsage() {
+  explicit(); // expected-warning{{'explicit' is deprecated: first deprecated in tvOS 12.0}}
+  inferred(); // expected-warning{{'inferred' is deprecated: first deprecated in tvOS 12.0}}
+  // ok, not deprecated for tvOS.
+  explicitOverInferred();
+  explicitOverInferred2();
+}
+
+#pragma clang attribute push (__attribute__((availability(tvos, introduced=11.0, deprecated=12.0))), apply_to=function)
+
+void explicitFromPragma(); // expected-note {{marked deprecated here}}
+void explicitWinsOverExplicitFromPragma() __attribute__((availability(tvos, introduced=11.0)));
+void implicitLosesOverExplicitFromPragma() __attribute__((availability(ios, introduced=11.0))); // expected-note {{marked deprecated here}}
+
+#pragma clang attribute pop
+
+#pragma clang attribute push (__attribute__((availability(ios, introduced=11.0, deprecated=12.0))), apply_to=function)
+
+void implicitFromPragma(); // expected-note {{marked deprecated here}}
+void explicitWinsOverImplicitFromPragma() __attribute__((availability(tvos, introduced=11.0)));
+void implicitWinsOverImplicitFromPragma() __attribute__((availability(ios, introduced=11.0)));
+
+#pragma clang attribute pop
+
+#pragma clang attribute push (__attribute__((availability(tvos, introduced=11.0, deprecated=12.0))), apply_to=function)
+#pragma clang attribute push (__attribute__((availability(ios, introduced=11.0, deprecated=11.3))), apply_to=function)
+
+void pragmaExplicitWinsOverPragmaImplicit(); // expected-note {{marked deprecated here}}
+
+#pragma clang attribute pop
+#pragma clang attribute pop
+
+void pragmaUsage() {
+  explicitFromPragma(); // expected-warning {{'explicitFromPragma' is deprecated: first deprecated in tvOS 12.0}}
+  explicitWinsOverExplicitFromPragma(); // ok
+  implicitLosesOverExplicitFromPragma(); // expected-warning {{'implicitLosesOverExplicitFromPragma' is deprecated: first deprecated in tvOS 12.0}}
+
+  implicitFromPragma(); // expected-warning {{'implicitFromPragma' is deprecated: first deprecated in tvOS 12.0}}
+  explicitWinsOverImplicitFromPragma(); // ok
+  implicitWinsOverImplicitFromPragma(); // ok
+  pragmaExplicitWinsOverPragmaImplicit(); // expected-warning {{'pragmaExplicitWinsOverPragmaImplicit' is deprecated: first deprecated in tvOS 12.0}}
+}
Index: lib/Sema/SemaDeclAttr.cpp
===
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -2284,18 +2284,11 @@
   return false;
 }
 
-AvailabilityAttr