r261163 - Add 'nopartial' qualifier for availability attributes.

Manman Ren via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 17 14:05:49 PST 2016


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




More information about the cfe-commits mailing list