[cfe-commits] r128127 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Parse/ include/clang/Sema/ include/clang/Serialization/ lib/AST/ lib/Basic/ lib/CodeGen/ lib/Parse/ lib/Sema/ lib/Serialization/ test/CodeGenObjC/ test/Parser/ test/Sema/ test/SemaCXX/ test/SemaObjC/ tools/libclang/

Douglas Gregor dgregor at apple.com
Tue Mar 22 17:50:04 PDT 2011


Author: dgregor
Date: Tue Mar 22 19:50:03 2011
New Revision: 128127

URL: http://llvm.org/viewvc/llvm-project?rev=128127&view=rev
Log:
Implement a new 'availability' attribute, that allows one to specify
which versions of an OS provide a certain facility. For example,

  void foo()
  __attribute__((availability(macosx,introduced=10.2,deprecated=10.4,obsoleted=10.6)));

says that the function "foo" was introduced in 10.2, deprecated in
10.4, and completely obsoleted in 10.6. This attribute ties in with
the deployment targets (e.g., -mmacosx-version-min=10.1 specifies that
we want to deploy back to Mac OS X 10.1). There are several concrete
behaviors that this attribute enables, as illustrated with the
function foo() above:

  - If we choose a deployment target >= Mac OS X 10.4, uses of "foo"
    will result in a deprecation warning, as if we had placed
    attribute((deprecated)) on it (but with a better diagnostic)
  - If we choose a deployment target >= Mac OS X 10.6, uses of "foo"
    will result in an "unavailable" warning (in C)/error (in C++), as
    if we had placed attribute((unavailable)) on it
  - If we choose a deployment target prior to 10.2, foo() is
    weak-imported (if it is a kind of entity that can be weak
    imported), as if we had placed the weak_import attribute on it.

Naturally, there can be multiple availability attributes on a
declaration, for different platforms; only the current platform
matters when checking availability attributes.

The only platforms this attribute currently works for are "ios" and
"macosx", since we already have -mxxxx-version-min flags for them and we
have experience there with macro tricks translating down to the
deprecated/unavailable/weak_import attributes. The end goal is to open
this up to other platforms, and even extension to other "platforms"
that are really libraries (say, through a #pragma clang
define_system), but that hasn't yet been designed and we may want to
shake out more issues with this narrower problem first.

Addresses <rdar://problem/6690412>.

As a drive-by bug-fix, if an entity is both deprecated and
unavailable, we only emit the "unavailable" diagnostic.

Added:
    cfe/trunk/include/clang/Basic/VersionTuple.h   (with props)
    cfe/trunk/lib/Basic/VersionTuple.cpp   (with props)
    cfe/trunk/test/CodeGenObjC/attr-availability.m
    cfe/trunk/test/Parser/attr-availability.c   (with props)
    cfe/trunk/test/Sema/attr-availability-ios.c   (with props)
    cfe/trunk/test/Sema/attr-availability-macosx.c   (with props)
    cfe/trunk/test/Sema/attr-availability.c   (with props)
Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Attr.h
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/include/clang/Basic/DiagnosticGroups.td
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/TargetInfo.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/AttributeList.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Serialization/ASTReader.h
    cfe/trunk/include/clang/Serialization/ASTWriter.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/Basic/CMakeLists.txt
    cfe/trunk/lib/Basic/TargetInfo.cpp
    cfe/trunk/lib/Basic/Targets.cpp
    cfe/trunk/lib/CodeGen/CGObjCMac.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/AttributeList.cpp
    cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaObjCProperty.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/SemaCXX/attr-unavailable.cpp
    cfe/trunk/test/SemaObjC/protocol-attribute.m
    cfe/trunk/test/SemaObjC/special-dep-unavail-warning.m
    cfe/trunk/tools/libclang/CIndex.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Tue Mar 22 19:50:03 2011
@@ -19,6 +19,7 @@
 #include "clang/Basic/LangOptions.h"
 #include "clang/Basic/OperatorKinds.h"
 #include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/VersionTuple.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/PrettyPrinter.h"

Modified: cfe/trunk/include/clang/AST/Attr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Attr.h (original)
+++ cfe/trunk/include/clang/AST/Attr.h Tue Mar 22 19:50:03 2011
@@ -17,9 +17,11 @@
 #include "llvm/Support/Casting.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
 #include "clang/Basic/AttrKinds.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/VersionTuple.h"
 #include <cassert>
 #include <cstring>
 #include <algorithm>

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Tue Mar 22 19:50:03 2011
@@ -119,14 +119,6 @@
     return getIdentifier() ? getIdentifier()->getName() : "";
   }
 
-  llvm::StringRef getMessageUnavailableAttr(bool unavailable) const {
-    if (!unavailable)
-      return "";
-    if (const UnavailableAttr *UA = getAttr<UnavailableAttr>())
-      return UA->getMessage();
-    return "";
-  }
-
   /// getNameAsString - Get a human-readable name for the declaration, even if
   /// it is one of the special kinds of names (C++ constructor, Objective-C
   /// selector, etc).  Creating this name requires expensive string

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Tue Mar 22 19:50:03 2011
@@ -62,6 +62,15 @@
 
 namespace clang {
 
+  /// \brief Captures the result of checking the availability of a
+  /// declaration.
+  enum AvailabilityResult {
+    AR_Available = 0,
+    AR_NotYetIntroduced,
+    AR_Deprecated,
+    AR_Unavailable
+  };
+
 /// Decl - This represents one declaration (or definition), e.g. a variable,
 /// typedef, function, struct, etc.
 ///
@@ -399,6 +408,52 @@
 
   void setUsed(bool U = true) { Used = U; }
 
+  /// \brief Determine the availability of the given declaration.
+  ///
+  /// This routine will determine the most restrictive availability of
+  /// the given declaration (e.g., preferring 'unavailable' to
+  /// 'deprecated').
+  ///
+  /// \param Message If non-NULL and the result is not \c
+  /// AR_Available, will be set to a (possibly empty) message
+  /// describing why the declaration has not been introduced, is
+  /// deprecated, or is unavailable.
+  AvailabilityResult getAvailability(std::string *Message = 0) const;
+
+  /// \brief Determine whether this declaration is marked 'deprecated'.
+  ///
+  /// \param Message If non-NULL and the declaration is deprecated,
+  /// this will be set to the message describing why the declaration
+  /// was deprecated (which may be empty).
+  bool isDeprecated(std::string *Message = 0) const {
+    return getAvailability(Message) == AR_Deprecated;
+  }
+
+  /// \brief Determine whether this declaration is marked 'unavailable'.
+  ///
+  /// \param Message If non-NULL and the declaration is unavailable,
+  /// this will be set to the message describing why the declaration
+  /// was made unavailable (which may be empty).
+  bool isUnavailable(std::string *Message = 0) const {
+    return getAvailability(Message) == AR_Unavailable;
+  }
+
+  /// \brief Determine whether this is a weak-imported symbol.
+  ///
+  /// Weak-imported symbols are typically marked with the
+  /// 'weak_import' attr+  /// 'availability' attribute where we're targing a platform prior to
+  /// the introduction of this feature.
+  bool isWeakImported() const;
+
+  /// \brief Determines whether this symbol can be weak-imported,
+  /// e.g., whether it would be well-formed to add the weak_import
+  /// attribute.
+  ///
+  /// \param IsDefinition Set to \c true to indicate that this
+  /// declaration cannot be weak-imported because it has a definition.
+  bool canBeWeakImported(bool &IsDefinition) const;
+
   /// \brief Retrieve the level of precompiled header from which this
   /// declaration was generated.
   ///

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Tue Mar 22 19:50:03 2011
@@ -55,6 +55,9 @@
 class UnsignedArgument<string name> : Argument<name>;
 class VariadicUnsignedArgument<string name> : Argument<name>;
 
+// A version of the form major.minor[.subminor].
+class VersionArgument<string name> : Argument<name>;
+
 // This one's a doozy, so it gets its own special type
 // It can be an unsigned integer, or a type. Either can
 // be dependent.
@@ -134,6 +137,19 @@
   let Args = [StringArgument<"Label">];
 }
 
+def Availability : InheritableAttr {
+  let Spellings = ["availability"];
+  let Args = [IdentifierArgument<"platform">, VersionArgument<"introduced">,
+              VersionArgument<"deprecated">, VersionArgument<"obsoleted">];
+  let AdditionalMembers =
+[{static llvm::StringRef getPrettyPlatformName(llvm::StringRef Platform) {
+    return llvm::StringSwitch<llvm::StringRef>(Platform)
+             .Case("ios", "iOS")
+             .Case("macosx", "Mac OS X")
+             .Default(llvm::StringRef());
+} }];
+}
+
 def Blocks : InheritableAttr {
   let Spellings = ["blocks"];
   let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];

Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Tue Mar 22 19:50:03 2011
@@ -24,6 +24,7 @@
 def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">;
 def : DiagGroup<"attributes">;
 def : DiagGroup<"bad-function-cast">;
+def Availability : DiagGroup<"availability">;
 def BoolConversions : DiagGroup<"bool-conversions">;
 def CXXCompat: DiagGroup<"c++-compat">;
 def CastAlign : DiagGroup<"cast-align">;

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Tue Mar 22 19:50:03 2011
@@ -119,6 +119,7 @@
   "function definition declared 'typedef'">;
 def err_iboutletcollection_builtintype : Error<
   "type argument of iboutletcollection attribute cannot be a builtin type">;
+
 def err_expected_fn_body : Error<
   "expected function body after function declarator">;
 def err_expected_method_body : Error<"expected method body">;
@@ -130,6 +131,7 @@
 def err_expected_lparen_after : Error<"expected '(' after '%0'">;
 def err_expected_lparen_after_id : Error<"expected '(' after %0">;
 def err_expected_less_after : Error<"expected '<' after '%0'">;
+def err_expected_equal_after : Error<"expected '=' after %0">;
 def err_expected_comma : Error<"expected ','">;
 def err_expected_lbrace_in_compound_literal : Error<
   "expected '{' in compound literal">;
@@ -431,6 +433,21 @@
 def err_sizeof_parameter_pack : Error<
   "expected parenthesized parameter pack name in 'sizeof...' expression">;
 
+// Availability attribute
+def err_expected_version : Error<
+  "expected a version of the form 'major[.minor[.subminor]]'">;
+def err_zero_version : Error<
+  "version number must have non-zero major, minor, or sub-minor version">;
+def err_availability_expected_platform : Error<
+  "expected a platform name, e.g., 'macosx'">;
+def err_availability_expected_change : Error<
+  "expected 'introduced', 'deprecated', or 'obsoleted'">;
+def err_availability_unknown_change : Error<
+  "%0 is not an availability stage; use 'introduced', 'deprecated', or "
+  "'obsoleted'">;
+def err_availability_redundant : Error<
+  "redundant %0 availability change; only the last specified change will "        "be used">;
+
 // Language specific pragmas
 // - Generic warnings
 def warn_pragma_expected_lparen : Warning<

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Mar 22 19:50:03 2011
@@ -1148,6 +1148,14 @@
   "attribute was previously declared "
   "%plural{0:without the regparm|:with the regparm(%1)}1 attribute">;
 
+// Availability attribute
+def warn_availability_unknown_platform : Warning<
+  "unknown platform %0 in availability macro">;
+def warn_availability_version_ordering : Warning<
+  "feature cannot be %select{introduced|deprecated|obsoleted}0 in %1 version "
+  "%2 before it was %select{introduced|deprecated|obsoleted}3 in version %4; "
+  "attribute ignored">;
+
 def warn_impcast_vector_scalar : Warning<
   "implicit conversion turns vector to scalar: %0 to %1">,
   InGroup<DiagGroup<"conversion">>, DefaultIgnore;
@@ -1339,11 +1347,11 @@
 def err_ovl_ambiguous_call : Error<
   "call to %0 is ambiguous">;
 def err_ovl_deleted_call : Error<
-  "call to %select{unavailable|deleted}0 function %1 %2">;
+  "call to %select{unavailable|deleted}0 function %1%2">;
 def err_ovl_ambiguous_member_call : Error<
   "call to member function %0 is ambiguous">;
 def err_ovl_deleted_member_call : Error<
-  "call to %select{unavailable|deleted}0 member function %1 %2">;
+  "call to %select{unavailable|deleted}0 member function %1%2">;
 def note_ovl_too_many_candidates : Note<
     "remaining %0 candidate%s0 omitted; "
     "pass -fshow-overloads=all to show them">;
@@ -1495,7 +1503,7 @@
   "use of overloaded operator '%0' is ambiguous (with operand types %1 and %2)">;
 def err_ovl_no_viable_oper : Error<"no viable overloaded '%0'">;
 def err_ovl_deleted_oper : Error<
-  "overload resolution selected %select{unavailable|deleted}0 operator '%1' %2">;
+  "overload resolution selected %select{unavailable|deleted}0 operator '%1'%2">;
 def err_ovl_no_viable_subscript :
     Error<"no viable overloaded operator[] for type %0">;
 def err_ovl_no_oper :
@@ -1509,7 +1517,7 @@
 def err_ovl_ambiguous_object_call : Error<
   "call to object of type %0 is ambiguous">;
 def err_ovl_deleted_object_call : Error<
-  "call to %select{unavailable|deleted}0 function call operator in type %1 %2">;
+  "call to %select{unavailable|deleted}0 function call operator in type %1%2">;
 def note_ovl_surrogate_cand : Note<"conversion candidate of type %0">;
 def err_member_call_without_object : Error<
   "call to non-static member function without an object argument">;
@@ -3831,5 +3839,6 @@
 def note_parameter_pack_here : Note<"parameter pack %0 declared here">;
 
 } // end of sema category
+
 } // end of sema component.
 

Modified: cfe/trunk/include/clang/Basic/TargetInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TargetInfo.h?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TargetInfo.h (original)
+++ cfe/trunk/include/clang/Basic/TargetInfo.h Tue Mar 22 19:50:03 2011
@@ -16,17 +16,18 @@
 
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/Support/DataTypes.h"
 #include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/VersionTuple.h"
 #include <cassert>
 #include <vector>
 #include <string>
 
 namespace llvm {
 struct fltSemantics;
-class StringRef;
 }
 
 namespace clang {
@@ -81,6 +82,9 @@
   TargetCXXABI CXXABI;
   const LangAS::Map *AddrSpaceMap;
 
+  mutable llvm::StringRef PlatformName;
+  mutable VersionTuple PlatformMinVersion;
+
   unsigned HasAlignMac68kSupport : 1;
   unsigned RealTypeUsesObjCFPRet : 3;
 
@@ -537,6 +541,14 @@
     return *AddrSpaceMap;
   }
 
+  /// \brief Retrieve the name of the platform as it is used in the
+  /// availability attribute.
+  llvm::StringRef getPlatformName() const { return PlatformName; }
+
+  /// \brief Retrieve the minimum desired version of the platform, to
+  /// which the program should be compiled.
+  VersionTuple getPlatformMinVersion() const { return PlatformMinVersion; }
+
 protected:
   virtual uint64_t getPointerWidthV(unsigned AddrSpace) const {
     return PointerWidth;

Added: cfe/trunk/include/clang/Basic/VersionTuple.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/VersionTuple.h?rev=128127&view=auto
==============================================================================
--- cfe/trunk/include/clang/Basic/VersionTuple.h (added)
+++ cfe/trunk/include/clang/Basic/VersionTuple.h Tue Mar 22 19:50:03 2011
@@ -0,0 +1,126 @@
+//===- VersionTuple.h - Version Number Handling -----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines the VersionTuple class, which represents a version in
+// the form major[.minor[.subminor]].
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_BASIC_VERSIONTUPLE_H
+#define LLVM_CLANG_BASIC_VERSIONTUPLE_H
+
+#include "llvm/ADT/Optional.h"
+#include <string>
+
+namespace llvm {
+  class raw_ostream;
+}
+
+namespace clang {
+
+/// \brief Represents a version number in the form major[.minor[.subminor]].
+class VersionTuple {
+  unsigned Major;
+  unsigned Minor : 31;
+  unsigned Subminor : 31;
+  unsigned HasMinor : 1;
+  unsigned HasSubminor : 1;
+
+public:
+  VersionTuple() 
+    : Major(0), Minor(0), Subminor(0), HasMinor(false), HasSubminor(false) { }
+
+  explicit VersionTuple(unsigned Major)
+    : Major(Major), Minor(0), Subminor(0), HasMinor(false), HasSubminor(false)
+  { }
+
+  explicit VersionTuple(unsigned Major, unsigned Minor)
+    : Major(Major), Minor(Minor), Subminor(0), HasMinor(true), 
+      HasSubminor(false)
+  { }
+
+  explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor)
+    : Major(Major), Minor(Minor), Subminor(Subminor), HasMinor(true), 
+      HasSubminor(true)
+  { }
+
+  /// \brief Determine whether this version information is empty
+  /// (e.g., all version components are zero).
+  bool empty() const { return Major == 0 && Minor == 0 && Subminor == 0; }
+
+  /// \brief Retrieve the major version number.
+  unsigned getMajor() const { return Major; }
+
+  /// \brief Retrieve the minor version number, if provided.
+  llvm::Optional<unsigned> getMinor() const { 
+    if (!HasMinor)
+      return llvm::Optional<unsigned>();
+    return Minor;
+  }
+
+  /// \brief Retrieve the subminor version number, if provided.
+  llvm::Optional<unsigned> getSubminor() const { 
+    if (!HasSubminor)
+      return llvm::Optional<unsigned>();
+    return Subminor;
+  }
+
+  /// \brief Determine if two version numbers are equivalent. If not
+  /// provided, minor and subminor version numbers are considered to be zero.
+  friend bool operator==(const VersionTuple& X, const VersionTuple &Y) {
+    return X.Major == Y.Major && X.Minor == Y.Minor && X.Subminor == Y.Subminor;
+  }
+
+  /// \brief Determine if two version numbers are not equivalent. If
+  /// not provided, minor and subminor version numbers are considered to be 
+  /// zero.
+  friend bool operator!=(const VersionTuple &X, const VersionTuple &Y) {
+    return !(X == Y);
+  }
+
+  /// \brief Determine whether one version number precedes another. If not
+  /// provided, minor and subminor version numbers are considered to be zero.
+  friend bool operator<(const VersionTuple &X, const VersionTuple &Y) {
+    if (X.Major != Y.Major)
+      return X.Major < Y.Major;
+
+    if (X.Minor != Y.Minor)
+      return X.Minor < Y.Minor;
+
+    return X.Subminor < Y.Subminor;
+  }
+
+  /// \brief Determine whether one version number follows another. If not
+  /// provided, minor and subminor version numbers are considered to be zero.
+  friend bool operator>(const VersionTuple &X, const VersionTuple &Y) {
+    return Y < X;
+  }
+
+  /// \brief Determine whether one version number precedes or is
+  /// equivalent to another. If not provided, minor and subminor
+  /// version numbers are considered to be zero.
+  friend bool operator<=(const VersionTuple &X, const VersionTuple &Y) {
+    return !(Y < X);
+  }
+
+  /// \brief Determine whether one version number follows or is
+  /// equivalent to another. If not provided, minor and subminor
+  /// version numbers are considered to be zero.
+  friend bool operator>=(const VersionTuple &X, const VersionTuple &Y) {
+    return !(X < Y);
+  }
+
+  /// \brief Retrieve a string representation of the version number/
+  std::string getAsString() const;
+};
+
+/// \brief Print a version number.
+llvm::raw_ostream& operator<<(llvm::raw_ostream &Out, const VersionTuple &V);
+
+} // end namespace clang
+#endif // LLVM_CLANG_BASIC_VERSIONTUPLE_H

Propchange: cfe/trunk/include/clang/Basic/VersionTuple.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/include/clang/Basic/VersionTuple.h
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/include/clang/Basic/VersionTuple.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Tue Mar 22 19:50:03 2011
@@ -33,7 +33,8 @@
   class PragmaUnusedHandler;
   class ColonProtectionRAIIObject;
   class InMessageExpressionRAIIObject;
-  
+  class VersionTuple;
+
 /// PrettyStackTraceParserEntry - If a crash happens while the parser is active,
 /// an entry is printed for it.
 class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry {
@@ -111,6 +112,15 @@
   IdentifierInfo *Ident_vector;
   IdentifierInfo *Ident_pixel;
 
+  /// \brief Identifier for "introduced".
+  IdentifierInfo *Ident_introduced;
+
+  /// \brief Identifier for "deprecated".
+  IdentifierInfo *Ident_deprecated;
+
+  /// \brief Identifier for "obsoleted".
+  IdentifierInfo *Ident_obsoleted;
+
   /// C++0x contextual keywords. 
   mutable IdentifierInfo *Ident_final;
   mutable IdentifierInfo *Ident_override;
@@ -1547,6 +1557,12 @@
   void ParseOpenCLAttributes(ParsedAttributes &attrs);
   void ParseOpenCLQualifiers(DeclSpec &DS);
 
+  VersionTuple ParseVersionTuple(SourceRange &Range);
+  void ParseAvailabilityAttribute(IdentifierInfo &Availability,
+                                  SourceLocation AvailabilityLoc,
+                                  ParsedAttributes &attrs,
+                                  SourceLocation *endLoc);
+
   void ParseTypeofSpecifier(DeclSpec &DS);
   void ParseDecltypeSpecifier(DeclSpec &DS);
   

Modified: cfe/trunk/include/clang/Sema/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/AttributeList.h (original)
+++ cfe/trunk/include/clang/Sema/AttributeList.h Tue Mar 22 19:50:03 2011
@@ -18,6 +18,7 @@
 #include "llvm/Support/Allocator.h"
 #include "clang/Sema/Ownership.h"
 #include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/VersionTuple.h"
 #include "clang/AST/Expr.h"
 #include <cassert>
 
@@ -25,6 +26,23 @@
   class IdentifierInfo;
   class Expr;
 
+/// \brief Represents information about a change in availability for
+/// an entity, which is part of the encoding of the 'availability'
+/// attribute.
+struct AvailabilityChange {
+  /// \brief The location of the keyword indicating the kind of change.
+  SourceLocation KeywordLoc;
+
+  /// \brief The version number at which the change occurred.
+  VersionTuple Version;
+
+  /// \brief The source range covering the version number.
+  SourceRange VersionRange;
+
+  /// \brief Determine whether this availability change is valid.
+  bool isValid() const { return !Version.empty(); }
+};
+
 /// AttributeList - Represents GCC's __attribute__ declaration. There are
 /// 4 forms of this construct...they are:
 ///
@@ -48,6 +66,11 @@
   AttributeList *Next;
   bool DeclspecAttribute, CXX0XAttribute;
 
+  // For the 'availability' attribute.
+  AvailabilityChange AvailabilityIntroduced;
+  AvailabilityChange AvailabilityDeprecated;
+  AvailabilityChange AvailabilityObsoleted;
+
   /// True if already diagnosed as invalid.
   mutable bool Invalid;
 
@@ -61,6 +84,15 @@
                 IdentifierInfo *ParmName, SourceLocation ParmLoc,
                 Expr **args, unsigned numargs,
                 bool declspec, bool cxx0x);
+
+  AttributeList(llvm::BumpPtrAllocator &Alloc,
+                IdentifierInfo *AttrName, SourceLocation AttrLoc,
+                IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
+                IdentifierInfo *ParmName, SourceLocation ParmLoc,
+                const AvailabilityChange &Introduced,
+                const AvailabilityChange &Deprecated,
+                const AvailabilityChange &Obsoleted,
+                bool declspec, bool cxx0x);
 public:
   class Factory {
     llvm::BumpPtrAllocator Alloc;
@@ -78,6 +110,20 @@
         return Mem;
       }
 
+    AttributeList *Create(IdentifierInfo *AttrName, SourceLocation AttrLoc,
+      IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
+      IdentifierInfo *ParmName, SourceLocation ParmLoc,
+      const AvailabilityChange &Introduced,
+      const AvailabilityChange &Deprecated,
+      const AvailabilityChange &Obsoleted,
+      bool declspec = false, bool cxx0x = false) {
+        AttributeList *Mem = Alloc.Allocate<AttributeList>();
+        new (Mem) AttributeList(Alloc, AttrName, AttrLoc, ScopeName, ScopeLoc,
+                                ParmName, ParmLoc, Introduced, Deprecated,
+                                Obsoleted, declspec, cxx0x);
+        return Mem;
+      }
+
     AttributeList* CreateIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
                                           SourceLocation TokLoc, int Arg) {
       Expr* IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t)Arg),
@@ -96,6 +142,7 @@
     AT_always_inline,
     AT_analyzer_noreturn,
     AT_annotate,
+    AT_availability,      // Clang-specific
     AT_base_check,
     AT_blocks,
     AT_carries_dependency,
@@ -244,6 +291,21 @@
   arg_iterator arg_end() const {
     return arg_iterator(Args, NumArgs);
   }
+
+  const AvailabilityChange &getAvailabilityIntroduced() const {
+    assert(getKind() == AT_availability && "Not an availability attribute");
+    return AvailabilityIntroduced;
+  }
+
+  const AvailabilityChange &getAvailabilityDeprecated() const {
+    assert(getKind() == AT_availability && "Not an availability attribute");
+    return AvailabilityDeprecated;
+  }
+
+  const AvailabilityChange &getAvailabilityObsoleted() const {
+    assert(getKind() == AT_availability && "Not an availability attribute");
+    return AvailabilityObsoleted;
+  }
 };
 
 /// addAttributeLists - Add two AttributeLists together

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Mar 22 19:50:03 2011
@@ -1901,6 +1901,7 @@
 
   bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, 
                          bool UnknownObjCClass=false);
+  std::string getDeletedOrUnavailableSuffix(const FunctionDecl *FD);
   bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD,
                                         ObjCMethodDecl *Getter,
                                         SourceLocation Loc);

Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Tue Mar 22 19:50:03 2011
@@ -69,6 +69,7 @@
 class ASTIdentifierLookupTrait;
 class TypeLocReader;
 struct HeaderFileInfo;
+class VersionTuple;
 
 struct PCHPredefinesBlock {
   /// \brief The file ID for this predefines buffer in a PCH file.
@@ -1208,6 +1209,9 @@
   // \brief Read a string
   std::string ReadString(const RecordData &Record, unsigned &Idx);
 
+  /// \brief Read a version tuple.
+  VersionTuple ReadVersionTuple(const RecordData &Record, unsigned &Idx);
+
   CXXTemporary *ReadCXXTemporary(const RecordData &Record, unsigned &Idx);
       
   /// \brief Reads attributes from the current stream position.

Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Tue Mar 22 19:50:03 2011
@@ -56,6 +56,7 @@
 class SourceManager;
 class SwitchCase;
 class TargetInfo;
+class VersionTuple;
 
 /// \brief Writes an AST file containing the contents of a translation unit.
 ///
@@ -514,6 +515,9 @@
   /// \brief Add a string to the given record.
   void AddString(llvm::StringRef Str, RecordDataImpl &Record);
 
+  /// \brief Add a version tuple to the given record
+  void AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record);
+
   /// \brief Mark a declaration context as needing an update.
   void AddUpdatedDeclContext(const DeclContext *DC) {
     UpdatedDeclContexts.insert(DC);

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Mar 22 19:50:03 2011
@@ -451,7 +451,6 @@
   }
 }
 
-
 MemberSpecializationInfo *
 ASTContext::getInstantiatedFromStaticDataMember(const VarDecl *Var) {
   assert(Var->isStaticDataMember() && "Not a static data member");

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Tue Mar 22 19:50:03 2011
@@ -25,6 +25,7 @@
 #include "clang/AST/Stmt.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/ASTMutationListener.h"
+#include "clang/Basic/TargetInfo.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
@@ -241,6 +242,155 @@
   return false; 
 }
 
+/// \brief Determine the availability of the given declaration based on
+/// the target platform.
+///
+/// When it returns an availability result other than \c AR_Available,
+/// if the \p Message parameter is non-NULL, it will be set to a
+/// string describing why the entity is unavailable.
+///
+/// FIXME: Make these strings localizable, since they end up in
+/// diagnostics.
+static AvailabilityResult CheckAvailability(ASTContext &Context,
+                                            const AvailabilityAttr *A,
+                                            std::string *Message) {
+  llvm::StringRef TargetPlatform = Context.Target.getPlatformName();
+  llvm::StringRef PrettyPlatformName
+    = AvailabilityAttr::getPrettyPlatformName(TargetPlatform);
+  if (PrettyPlatformName.empty())
+    PrettyPlatformName = TargetPlatform;
+
+  VersionTuple TargetMinVersion = Context.Target.getPlatformMinVersion();
+  if (TargetMinVersion.empty())
+    return AR_Available;
+
+  // Match the platform name.
+  if (A->getPlatform()->getName() != TargetPlatform)
+    return AR_Available;
+
+  // Make sure that this declaration has already been introduced.
+  if (!A->getIntroduced().empty() && 
+      TargetMinVersion < A->getIntroduced()) {
+    if (Message) {
+      Message->clear();
+      llvm::raw_string_ostream Out(*Message);
+      Out << "introduced in " << PrettyPlatformName << ' ' 
+          << A->getIntroduced();
+    }
+
+    return AR_NotYetIntroduced;
+  }
+
+  // Make sure that this declaration hasn't been obsoleted.
+  if (!A->getObsoleted().empty() && TargetMinVersion >= A->getObsoleted()) {
+    if (Message) {
+      Message->clear();
+      llvm::raw_string_ostream Out(*Message);
+      Out << "obsoleted in " << PrettyPlatformName << ' ' 
+          << A->getObsoleted();
+    }
+    
+    return AR_Unavailable;
+  }
+
+  // Make sure that this declaration hasn't been deprecated.
+  if (!A->getDeprecated().empty() && TargetMinVersion >= A->getDeprecated()) {
+    if (Message) {
+      Message->clear();
+      llvm::raw_string_ostream Out(*Message);
+      Out << "first deprecated in " << PrettyPlatformName << ' '
+          << A->getDeprecated();
+    }
+    
+    return AR_Deprecated;
+  }
+
+  return AR_Available;
+}
+
+AvailabilityResult Decl::getAvailability(std::string *Message) const {
+  AvailabilityResult Result = AR_Available;
+  std::string ResultMessage;
+
+  for (attr_iterator A = attr_begin(), AEnd = attr_end(); A != AEnd; ++A) {
+    if (DeprecatedAttr *Deprecated = dyn_cast<DeprecatedAttr>(*A)) {
+      if (Result >= AR_Deprecated)
+        continue;
+
+      if (Message)
+        ResultMessage = Deprecated->getMessage();
+
+      Result = AR_Deprecated;
+      continue;
+    }
+
+    if (UnavailableAttr *Unavailable = dyn_cast<UnavailableAttr>(*A)) {
+      if (Message)
+        *Message = Unavailable->getMessage();
+      return AR_Unavailable;
+    }
+
+    if (AvailabilityAttr *Availability = dyn_cast<AvailabilityAttr>(*A)) {
+      AvailabilityResult AR = CheckAvailability(getASTContext(), Availability,
+                                                Message);
+
+      if (AR == AR_Unavailable)
+        return AR_Unavailable;
+
+      if (AR > Result) {
+        Result = AR;
+        if (Message)
+          ResultMessage.swap(*Message);
+      }
+      continue;
+    }
+  }
+
+  if (Message)
+    Message->swap(ResultMessage);
+  return Result;
+}
+
+bool Decl::canBeWeakImported(bool &IsDefinition) const {
+  IsDefinition = false;
+  if (const VarDecl *Var = dyn_cast<VarDecl>(this)) {
+    if (!Var->hasExternalStorage() || Var->getInit()) {
+      IsDefinition = true;
+      return false;
+    }
+  } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this)) {
+    if (FD->hasBody()) {
+      IsDefinition = true;
+      return false;
+    }
+  } else if (isa<ObjCPropertyDecl>(this) || isa<ObjCMethodDecl>(this))
+    return false;
+  else if (!(getASTContext().getLangOptions().ObjCNonFragileABI &&
+             isa<ObjCInterfaceDecl>(this)))
+    return false;
+
+  return true;
+}
+
+bool Decl::isWeakImported() const {
+  bool IsDefinition;
+  if (!canBeWeakImported(IsDefinition))
+    return false;
+
+  ASTContext &Context = getASTContext();
+  for (attr_iterator A = attr_begin(), AEnd = attr_end(); A != AEnd; ++A) {
+    if (isa<WeakImportAttr>(*A))
+      return true;
+
+    if (AvailabilityAttr *Availability = dyn_cast<AvailabilityAttr>(*A)) {
+      if (CheckAvailability(getASTContext(), Availability, 0) 
+                                                         == AR_NotYetIntroduced)
+        return true;
+    }
+  }
+
+  return false;
+}
 
 unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
   switch (DeclKind) {

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Tue Mar 22 19:50:03 2011
@@ -175,7 +175,7 @@
   const ValueDecl* Decl = DeclRef->getDecl();
   if (Decl->hasAttr<WeakAttr>() ||
       Decl->hasAttr<WeakRefAttr>() ||
-      Decl->hasAttr<WeakImportAttr>())
+      Decl->isWeakImported())
     return false;
 
   return true;

Modified: cfe/trunk/lib/Basic/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/CMakeLists.txt?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/CMakeLists.txt (original)
+++ cfe/trunk/lib/Basic/CMakeLists.txt Tue Mar 22 19:50:03 2011
@@ -14,6 +14,7 @@
   Targets.cpp
   TokenKinds.cpp
   Version.cpp
+  VersionTuple.cpp
   )
 
 # Determine Subversion revision.

Modified: cfe/trunk/lib/Basic/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/TargetInfo.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/TargetInfo.cpp (original)
+++ cfe/trunk/lib/Basic/TargetInfo.cpp Tue Mar 22 19:50:03 2011
@@ -70,6 +70,10 @@
 
   // Default to an empty address space map.
   AddrSpaceMap = &DefaultAddrSpaceMap;
+
+  // Default to an unknown platform name.
+  PlatformName = "unknown";
+  PlatformMinVersion = VersionTuple();
 }
 
 // Out of line virtual dtor for TargetInfo.

Modified: cfe/trunk/lib/Basic/Targets.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Targets.cpp (original)
+++ cfe/trunk/lib/Basic/Targets.cpp Tue Mar 22 19:50:03 2011
@@ -76,7 +76,9 @@
 
 
 static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
-                             const llvm::Triple &Triple) {
+                             const llvm::Triple &Triple,
+                             llvm::StringRef &PlatformName,
+                             VersionTuple &PlatformMinVersion) {
   Builder.defineMacro("__APPLE_CC__", "5621");
   Builder.defineMacro("__APPLE__");
   Builder.defineMacro("__MACH__");
@@ -120,6 +122,9 @@
     Str[4] = '0' + (Rev % 10);
     Str[5] = '\0';
     Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__", Str);
+
+    PlatformName = "ios";
+    PlatformMinVersion = VersionTuple(Maj, Min, Rev);
   } else {
     // For historical reasons that make little sense, the version passed here is
     // the "darwin" version, which drops the 10 and offsets by 4.
@@ -136,6 +141,9 @@
     Str[3] = '0' + Rev;
     Str[4] = '\0';
     Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", Str);
+
+    PlatformName = "macosx";
+    PlatformMinVersion = VersionTuple(Maj, Min, Rev);
   }
 }
 
@@ -145,7 +153,8 @@
 protected:
   virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
                             MacroBuilder &Builder) const {
-    getDarwinDefines(Builder, Opts, Triple);
+    getDarwinDefines(Builder, Opts, Triple, this->PlatformName, 
+                     this->PlatformMinVersion);
   }
 
 public:
@@ -2005,7 +2014,7 @@
 protected:
   virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
                             MacroBuilder &Builder) const {
-    getDarwinDefines(Builder, Opts, Triple);
+    getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
   }
 
 public:

Added: cfe/trunk/lib/Basic/VersionTuple.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/VersionTuple.cpp?rev=128127&view=auto
==============================================================================
--- cfe/trunk/lib/Basic/VersionTuple.cpp (added)
+++ cfe/trunk/lib/Basic/VersionTuple.cpp Tue Mar 22 19:50:03 2011
@@ -0,0 +1,36 @@
+//===- VersionTuple.cpp - Version Number Handling ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the VersionTuple class, which represents a version in
+// the form major[.minor[.subminor]].
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Basic/VersionTuple.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+
+std::string VersionTuple::getAsString() const {
+  std::string Result;
+  {
+    llvm::raw_string_ostream Out(Result);
+    Out << *this;
+  }
+  return Result;
+}
+
+llvm::raw_ostream& clang::operator<<(llvm::raw_ostream &Out, 
+                                     const VersionTuple &V) {
+  Out << V.getMajor();
+  if (llvm::Optional<unsigned> Minor = V.getMinor())
+    Out << '.' << *Minor;
+  if (llvm::Optional<unsigned> Subminor = V.getSubminor())
+    Out << '.' << *Subminor;
+  return Out;
+}

Propchange: cfe/trunk/lib/Basic/VersionTuple.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/lib/Basic/VersionTuple.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/lib/Basic/VersionTuple.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Tue Mar 22 19:50:03 2011
@@ -5018,14 +5018,14 @@
     while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
       Root = Super;
     IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
-    if (Root->hasAttr<WeakImportAttr>())
+    if (Root->isWeakImported())
       IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
     // work on super class metadata symbol.
     std::string SuperClassName =
       ObjCMetaClassName + 
         ID->getClassInterface()->getSuperClass()->getNameAsString();
     SuperClassGV = GetClassGlobal(SuperClassName);
-    if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>())
+    if (ID->getClassInterface()->getSuperClass()->isWeakImported())
       SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
   }
   llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
@@ -5055,7 +5055,7 @@
     std::string RootClassName =
       ID->getClassInterface()->getSuperClass()->getNameAsString();
     SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
-    if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>())
+    if (ID->getClassInterface()->getSuperClass()->isWeakImported())
       SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
   }
   GetClassSizeInfo(ID, InstanceStart, InstanceSize);
@@ -5137,7 +5137,7 @@
   Values[0] = GetClassName(OCD->getIdentifier());
   // meta-class entry symbol
   llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
-  if (Interface->hasAttr<WeakImportAttr>())
+  if (Interface->isWeakImported())
     ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
   
   Values[1] = ClassGV;
@@ -5810,7 +5810,7 @@
 /// decl.
 llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
                                               const ObjCInterfaceDecl *ID) {
-  if (ID->hasAttr<WeakImportAttr>()) {
+  if (ID->isWeakImported()) {
     std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
     llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
     ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Mar 22 19:50:03 2011
@@ -509,7 +509,7 @@
   if (FD->hasAttr<DLLImportAttr>()) {
     F->setLinkage(llvm::Function::DLLImportLinkage);
   } else if (FD->hasAttr<WeakAttr>() ||
-             FD->hasAttr<WeakImportAttr>()) {
+             FD->isWeakImported()) {
     // "extern_weak" is overloaded in LLVM; we probably should have
     // separate linkage types for this.
     F->setLinkage(llvm::Function::ExternalWeakLinkage);
@@ -986,7 +986,7 @@
     } else {
       if (D->hasAttr<DLLImportAttr>())
         GV->setLinkage(llvm::GlobalValue::DLLImportLinkage);
-      else if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakImportAttr>())
+      else if (D->hasAttr<WeakAttr>() || D->isWeakImported())
         GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
 
       // Set visibility on a declaration only if it's explicit.
@@ -1530,7 +1530,7 @@
     }
   } else if (D->hasAttr<WeakAttr>() ||
              D->hasAttr<WeakRefAttr>() ||
-             D->hasAttr<WeakImportAttr>()) {
+             D->isWeakImported()) {
     GA->setLinkage(llvm::Function::WeakAnyLinkage);
   }
 

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue Mar 22 19:50:03 2011
@@ -112,8 +112,11 @@
       IdentifierInfo *AttrName = Tok.getIdentifierInfo();
       SourceLocation AttrNameLoc = ConsumeToken();
 
+      // Availability attributes have their own grammar.
+      if (AttrName->isStr("availability"))
+        ParseAvailabilityAttribute(*AttrName, AttrNameLoc, attrs, endLoc);
       // check if we have a "parameterized" attribute
-      if (Tok.is(tok::l_paren)) {
+      else if (Tok.is(tok::l_paren)) {
         ConsumeParen(); // ignore the left paren loc for now
 
         if (Tok.is(tok::identifier)) {
@@ -362,6 +365,241 @@
   }
 }
 
+/// \brief Parse a version number.
+///
+/// version:
+///   simple-integer
+///   simple-integer ',' simple-integer
+///   simple-integer ',' simple-integer ',' simple-integer
+VersionTuple Parser::ParseVersionTuple(SourceRange &Range) {
+  Range = Tok.getLocation();
+
+  if (!Tok.is(tok::numeric_constant)) {
+    Diag(Tok, diag::err_expected_version);
+    SkipUntil(tok::comma, tok::r_paren, true, true, true);
+    return VersionTuple();
+  }
+
+  // Parse the major (and possibly minor and subminor) versions, which
+  // are stored in the numeric constant. We utilize a quirk of the
+  // lexer, which is that it handles something like 1.2.3 as a single
+  // numeric constant, rather than two separate tokens.
+  llvm::SmallString<512> Buffer;
+  Buffer.resize(Tok.getLength()+1);
+  const char *ThisTokBegin = &Buffer[0];
+
+  // Get the spelling of the token, which eliminates trigraphs, etc.
+  bool Invalid = false;
+  unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin, &Invalid);
+  if (Invalid)
+    return VersionTuple();
+
+  // Parse the major version.
+  unsigned AfterMajor = 0;
+  unsigned Major = 0;
+  while (AfterMajor < ActualLength && isdigit(ThisTokBegin[AfterMajor])) {
+    Major = Major * 10 + ThisTokBegin[AfterMajor] - '0';
+    ++AfterMajor;
+  }
+
+  if (AfterMajor == 0) {
+    Diag(Tok, diag::err_expected_version);
+    SkipUntil(tok::comma, tok::r_paren, true, true, true);
+    return VersionTuple();
+  }
+
+  if (AfterMajor == ActualLength) {
+    ConsumeToken();
+
+    // We only had a single version component.
+    if (Major == 0) {
+      Diag(Tok, diag::err_zero_version);
+      return VersionTuple();
+    }
+
+    return VersionTuple(Major);
+  }
+
+  if (ThisTokBegin[AfterMajor] != '.' || (AfterMajor + 1 == ActualLength)) {
+    Diag(Tok, diag::err_expected_version);
+    SkipUntil(tok::comma, tok::r_paren, true, true, true);
+    return VersionTuple();
+  }
+
+  // Parse the minor version.
+  unsigned AfterMinor = AfterMajor + 1;
+  unsigned Minor = 0;
+  while (AfterMinor < ActualLength && isdigit(ThisTokBegin[AfterMinor])) {
+    Minor = Minor * 10 + ThisTokBegin[AfterMinor] - '0';
+    ++AfterMinor;
+  }
+
+  if (AfterMinor == ActualLength) {
+    ConsumeToken();
+    
+    // We had major.minor.
+    if (Major == 0 && Minor == 0) {
+      Diag(Tok, diag::err_zero_version);
+      return VersionTuple();
+    }
+
+    return VersionTuple(Major, Minor);      
+  }
+
+  // If what follows is not a '.', we have a problem.
+  if (ThisTokBegin[AfterMinor] != '.') {
+    Diag(Tok, diag::err_expected_version);
+    SkipUntil(tok::comma, tok::r_paren, true, true, true);
+    return VersionTuple();    
+  }
+
+  // Parse the subminor version.
+  unsigned AfterSubminor = AfterMinor + 1;
+  unsigned Subminor = 0;
+  while (AfterSubminor < ActualLength && isdigit(ThisTokBegin[AfterSubminor])) {
+    Subminor = Subminor * 10 + ThisTokBegin[AfterSubminor] - '0';
+    ++AfterSubminor;
+  }
+
+  if (AfterSubminor != ActualLength) {
+    Diag(Tok, diag::err_expected_version);
+    SkipUntil(tok::comma, tok::r_paren, true, true, true);
+    return VersionTuple();
+  }
+  ConsumeToken();
+  return VersionTuple(Major, Minor, Subminor);
+}
+
+/// \brief Parse the contents of the "availability" attribute.
+///
+/// availability-attribute:
+///   'availability' '(' platform ',' version-arg-list ')'
+///
+/// platform:
+///   identifier
+///
+/// version-arg-list:
+///   version-arg
+///   version-arg ',' version-arg-list
+///
+/// version-arg:
+///   'introduced' '=' version
+///   'deprecated' '=' version
+///   'removed' = version
+void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
+                                        SourceLocation AvailabilityLoc,
+                                        ParsedAttributes &attrs,
+                                        SourceLocation *endLoc) {
+  SourceLocation PlatformLoc;
+  IdentifierInfo *Platform = 0;
+
+  enum { Introduced, Deprecated, Obsoleted, Unknown };
+  AvailabilityChange Changes[Unknown];
+
+  // Opening '('.
+  SourceLocation LParenLoc;
+  if (!Tok.is(tok::l_paren)) {
+    Diag(Tok, diag::err_expected_lparen);
+    return;
+  }
+  LParenLoc = ConsumeParen();
+
+  // Parse the platform name,
+  if (Tok.isNot(tok::identifier)) {
+    Diag(Tok, diag::err_availability_expected_platform);
+    SkipUntil(tok::r_paren);
+    return;
+  }
+  Platform = Tok.getIdentifierInfo();
+  PlatformLoc = ConsumeToken();
+
+  // Parse the ',' following the platform name.
+  if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", tok::r_paren))
+    return;
+
+  // If we haven't grabbed the pointers for the identifiers
+  // "introduced", "deprecated", and "obsoleted", do so now.
+  if (!Ident_introduced) {
+    Ident_introduced = PP.getIdentifierInfo("introduced");
+    Ident_deprecated = PP.getIdentifierInfo("deprecated");
+    Ident_obsoleted = PP.getIdentifierInfo("obsoleted");
+  }
+
+  // Parse the set of introductions/deprecations/removals.
+  do {
+    if (Tok.isNot(tok::identifier)) {
+      Diag(Tok, diag::err_availability_expected_change);
+      SkipUntil(tok::r_paren);
+      return;
+    }
+    IdentifierInfo *Keyword = Tok.getIdentifierInfo();
+    SourceLocation KeywordLoc = ConsumeToken();
+
+    if (Tok.isNot(tok::equal)) {
+      Diag(Tok, diag::err_expected_equal_after)
+        << Keyword;
+      SkipUntil(tok::r_paren);
+      return;
+    }
+    ConsumeToken();
+    
+    SourceRange VersionRange;
+    VersionTuple Version = ParseVersionTuple(VersionRange);
+    
+    if (Version.empty()) {
+      SkipUntil(tok::r_paren);
+      return;
+    }
+
+    unsigned Index;
+    if (Keyword == Ident_introduced)
+      Index = Introduced;
+    else if (Keyword == Ident_deprecated)
+      Index = Deprecated;
+    else if (Keyword == Ident_obsoleted)
+      Index = Obsoleted;
+    else 
+      Index = Unknown;
+
+    if (Index < Unknown) {
+      if (!Changes[Index].KeywordLoc.isInvalid()) {
+        Diag(KeywordLoc, diag::err_availability_redundant)
+          << Keyword 
+          << SourceRange(Changes[Index].KeywordLoc,
+                         Changes[Index].VersionRange.getEnd());
+      }
+
+      Changes[Index].KeywordLoc = KeywordLoc;
+      Changes[Index].Version = Version;
+      Changes[Index].VersionRange = VersionRange;
+    } else {
+      Diag(KeywordLoc, diag::err_availability_unknown_change)
+        << Keyword << VersionRange;
+    }
+
+    if (Tok.isNot(tok::comma))
+      break;
+
+    ConsumeToken();
+  } while (true);
+
+  // Closing ')'.
+  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+  if (RParenLoc.isInvalid())
+    return;
+
+  if (endLoc)
+    *endLoc = RParenLoc;
+
+  // Record this attribute
+  attrs.add(AttrFactory.Create(&Availability, AvailabilityLoc,
+                               0, SourceLocation(),
+                               Platform, PlatformLoc,
+                               Changes[Introduced],
+                               Changes[Deprecated],
+                               Changes[Obsoleted], false, false));
+}
+
 void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) {
   Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed)
     << attrs.Range;

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Tue Mar 22 19:50:03 2011
@@ -422,6 +422,10 @@
     Ident_vector = &PP.getIdentifierTable().get("vector");
     Ident_pixel = &PP.getIdentifierTable().get("pixel");
   }
+
+  Ident_introduced = 0;
+  Ident_deprecated = 0;
+  Ident_obsoleted = 0;
 }
 
 /// ParseTopLevelDecl - Parse one top-level declaration, return whatever the

Modified: cfe/trunk/lib/Sema/AttributeList.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AttributeList.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/AttributeList.cpp (original)
+++ cfe/trunk/lib/Sema/AttributeList.cpp Tue Mar 22 19:50:03 2011
@@ -36,6 +36,24 @@
   }
 }
 
+AttributeList::AttributeList(llvm::BumpPtrAllocator &Alloc,
+                             IdentifierInfo *AttrName, SourceLocation AttrLoc,
+                             IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
+                             IdentifierInfo *ParmName, SourceLocation ParmLoc,
+                             const AvailabilityChange &Introduced,
+                             const AvailabilityChange &Deprecated,
+                             const AvailabilityChange &Obsoleted,
+                             bool declspec, bool cxx0x)
+  : AttrName(AttrName), AttrLoc(AttrLoc), ScopeName(ScopeName), 
+    ScopeLoc(ScopeLoc), ParmName(ParmName), ParmLoc(ParmLoc), 
+    Args(0), NumArgs(0), Next(0),
+    DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), 
+    AvailabilityIntroduced(Introduced),
+    AvailabilityDeprecated(Deprecated),
+    AvailabilityObsoleted(Obsoleted),
+    Invalid(false) {
+}
+
 AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
   llvm::StringRef AttrName = Name->getName();
 
@@ -83,6 +101,7 @@
     .Case("may_alias", AT_may_alias)
     .Case("base_check", AT_base_check)
     .Case("deprecated", AT_deprecated)
+    .Case("availability", AT_availability)
     .Case("visibility", AT_visibility)
     .Case("destructor", AT_destructor)
     .Case("format_arg", AT_format_arg)

Modified: cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp (original)
+++ cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp Tue Mar 22 19:50:03 2011
@@ -375,12 +375,21 @@
   switch (Kind) {
   case RK_Declaration:
     // Set the availability based on attributes.
-    Availability = CXAvailability_Available;      
-    if (Declaration->getAttr<UnavailableAttr>())
-      Availability = CXAvailability_NotAvailable;
-    else if (Declaration->getAttr<DeprecatedAttr>())
+    switch (Declaration->getAvailability()) {
+    case AR_Available:
+    case AR_NotYetIntroduced:
+      Availability = CXAvailability_Available;      
+      break;
+      
+    case AR_Deprecated:
       Availability = CXAvailability_Deprecated;
+      break;
       
+    case AR_Unavailable:
+      Availability = CXAvailability_NotAvailable;
+      break;
+    }
+
     if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration))
       if (Function->isDeleted())
         Availability = CXAvailability_NotAvailable;

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Tue Mar 22 19:50:03 2011
@@ -1074,6 +1074,57 @@
   d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context, Str));
 }
 
+static void HandleAvailabilityAttr(Decl *d, const AttributeList &Attr, 
+                                   Sema &S) {
+  IdentifierInfo *Platform = Attr.getParameterName();
+  SourceLocation PlatformLoc = Attr.getParameterLoc();
+
+  llvm::StringRef PlatformName
+    = AvailabilityAttr::getPrettyPlatformName(Platform->getName());
+  if (PlatformName.empty()) {
+    S.Diag(PlatformLoc, diag::warn_availability_unknown_platform)
+      << Platform;
+
+    PlatformName = Platform->getName();
+  }
+
+  AvailabilityChange Introduced = Attr.getAvailabilityIntroduced();
+  AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated();
+  AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted();
+
+  // Ensure that Introduced < Deprecated < Obsoleted (although not all
+  // of these steps are needed).
+  if (Introduced.isValid() && Deprecated.isValid() &&
+      !(Introduced.Version < Deprecated.Version)) {
+    S.Diag(Introduced.KeywordLoc, diag::warn_availability_version_ordering)
+      << 1 << PlatformName << Deprecated.Version.getAsString()
+      << 0 << Introduced.Version.getAsString();
+    return;
+  }
+
+  if (Introduced.isValid() && Obsoleted.isValid() &&
+      !(Introduced.Version < Obsoleted.Version)) {
+    S.Diag(Introduced.KeywordLoc, diag::warn_availability_version_ordering)
+      << 2 << PlatformName << Obsoleted.Version.getAsString()
+      << 0 << Introduced.Version.getAsString();
+    return;
+  }
+
+  if (Deprecated.isValid() && Obsoleted.isValid() &&
+      !(Deprecated.Version < Obsoleted.Version)) {
+    S.Diag(Deprecated.KeywordLoc, diag::warn_availability_version_ordering)
+      << 2 << PlatformName << Obsoleted.Version.getAsString()
+      << 1 << Deprecated.Version.getAsString();
+    return;
+  }
+
+  d->addAttr(::new (S.Context) AvailabilityAttr(Attr.getLoc(), S.Context, 
+                                                Platform,
+                                                Introduced.Version,
+                                                Deprecated.Version,
+                                                Obsoleted.Version));
+}
+
 static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
   // check the attribute arguments.
   if (Attr.getNumArgs() != 1) {
@@ -1380,27 +1431,18 @@
 
   // weak_import only applies to variable & function declarations.
   bool isDef = false;
-  if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
-    isDef = (!VD->hasExternalStorage() || VD->getInit());
-  } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
-    isDef = FD->hasBody();
-  } else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D)) {
-    // We ignore weak import on properties and methods
-    return;
-  } else if (!(S.LangOpts.ObjCNonFragileABI && isa<ObjCInterfaceDecl>(D))) {
-    // Don't issue the warning for darwin as target; yet, ignore the attribute.
-    if (S.Context.Target.getTriple().getOS() != llvm::Triple::Darwin ||
-        !isa<ObjCInterfaceDecl>(D)) 
+  if (!D->canBeWeakImported(isDef)) {
+    if (isDef)
+      S.Diag(Attr.getLoc(),
+             diag::warn_attribute_weak_import_invalid_on_definition)
+        << "weak_import" << 2 /*variable and function*/;
+    else if (S.Context.Target.getTriple().getOS() != llvm::Triple::Darwin ||
+             (!isa<ObjCInterfaceDecl>(D) &&
+              !isa<ObjCPropertyDecl>(D) &&
+              !isa<ObjCMethodDecl>(D)))
       S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
         << Attr.getName() << ExpectedVariableOrFunction;
-      return;
-  }
 
-  // Merge should handle any subsequent violations.
-  if (isDef) {
-    S.Diag(Attr.getLoc(),
-           diag::warn_attribute_weak_import_invalid_on_definition)
-      << "weak_import" << 2 /*variable and function*/;
     return;
   }
 
@@ -2745,6 +2787,7 @@
   case AttributeList::AT_analyzer_noreturn:
     HandleAnalyzerNoReturnAttr  (D, Attr, S); break;
   case AttributeList::AT_annotate:    HandleAnnotateAttr    (D, Attr, S); break;
+  case AttributeList::AT_availability:HandleAvailabilityAttr(D, Attr, S); break;
   case AttributeList::AT_carries_dependency:
                                       HandleDependencyAttr  (D, Attr, S); break;
   case AttributeList::AT_common:      HandleCommonAttr      (D, Attr, S); break;
@@ -3058,7 +3101,7 @@
 
 static bool isDeclDeprecated(Decl *D) {
   do {
-    if (D->hasAttr<DeprecatedAttr>())
+    if (D->isDeprecated())
       return true;
   } while ((D = cast_or_null<Decl>(D->getDeclContext())));
   return false;

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Tue Mar 22 19:50:03 2011
@@ -28,7 +28,7 @@
                                                 NamedDecl *ND,
                                                 SourceLocation ImplLoc,
                                                 int select) {
-  if (ND && ND->getAttr<DeprecatedAttr>()) {
+  if (ND && ND->isDeprecated()) {
     S.Diag(ImplLoc, diag::warn_deprecated_def) << select;
     if (select == 0)
       S.Diag(ND->getLocation(), diag::note_method_declared_at);
@@ -1369,15 +1369,14 @@
       PrevObjCMethod->setDefined(impl);
       // If a method is deprecated, push it in the global pool.
       // This is used for better diagnostics.
-      if (Method->getAttr<DeprecatedAttr>()) {
-        if (!PrevObjCMethod->getAttr<DeprecatedAttr>())
+      if (Method->isDeprecated()) {
+        if (!PrevObjCMethod->isDeprecated())
           List->Method = Method;
       }
       // If new method is unavailable, push it into global pool
       // unless previous one is deprecated.
-      if (Method->getAttr<UnavailableAttr>()) {
-        if (!PrevObjCMethod->getAttr<UnavailableAttr>() &&
-            !PrevObjCMethod->getAttr<DeprecatedAttr>())
+      if (Method->isUnavailable()) {
+        if (PrevObjCMethod->getAvailability() < AR_Deprecated)
           List->Method = Method;
       }
       return;

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Mar 22 19:50:03 2011
@@ -68,7 +68,7 @@
         Diag(Suppressed[I].first, Suppressed[I].second);
       
       // Clear out the list of suppressed diagnostics, so that we don't emit
-      // them again for this specialization. However, we don't remove this
+      // them again for this specialization. However, we don't obsolete this
       // entry from the table, because we want to avoid ever emitting these
       // diagnostics again.
       Suppressed.clear();
@@ -82,13 +82,28 @@
     return true;
   }
 
-  // See if the decl is deprecated.
-  if (const DeprecatedAttr *DA = D->getAttr<DeprecatedAttr>())
-    EmitDeprecationWarning(D, DA->getMessage(), Loc, UnknownObjCClass);
-
-  // See if the decl is unavailable
-  if (const UnavailableAttr *UA = D->getAttr<UnavailableAttr>()) {
-    if (UA->getMessage().empty()) {
+  // See if this is a deleted function.
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    if (FD->isDeleted()) {
+      Diag(Loc, diag::err_deleted_function_use);
+      Diag(D->getLocation(), diag::note_unavailable_here) << true;
+      return true;
+    }
+  }
+
+  // See if this declaration is unavailable or deprecated.
+  std::string Message;
+  switch (D->getAvailability(&Message)) {
+  case AR_Available:
+  case AR_NotYetIntroduced:
+    break;
+
+  case AR_Deprecated:
+    EmitDeprecationWarning(D, Message, Loc, UnknownObjCClass);
+    break;
+
+  case AR_Unavailable:
+    if (Message.empty()) {
       if (!UnknownObjCClass)
         Diag(Loc, diag::err_unavailable) << D->getDeclName();
       else
@@ -97,17 +112,9 @@
     }
     else 
       Diag(Loc, diag::err_unavailable_message) 
-        << D->getDeclName() << UA->getMessage();
-    Diag(D->getLocation(), diag::note_unavailable_here) << 0;
-  }
-
-  // See if this is a deleted function.
-  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
-    if (FD->isDeleted()) {
-      Diag(Loc, diag::err_deleted_function_use);
-      Diag(D->getLocation(), diag::note_unavailable_here) << true;
-      return true;
-    }
+        << D->getDeclName() << Message;
+    Diag(D->getLocation(), diag::note_unavailable_here) << 0;    
+    break;
   }
 
   // Warn if this is used but marked unused.
@@ -117,6 +124,23 @@
   return false;
 }
 
+/// \brief Retrieve the message suffix that should be added to a
+/// diagnostic complaining about the given function being deleted or
+/// unavailable.
+std::string Sema::getDeletedOrUnavailableSuffix(const FunctionDecl *FD) {
+  // FIXME: C++0x implicitly-deleted special member functions could be
+  // detected here so that we could improve diagnostics to say, e.g.,
+  // "base class 'A' had a deleted copy constructor".
+  if (FD->isDeleted())
+    return std::string();
+
+  std::string Message;
+  if (FD->getAvailability(&Message))
+    return ": " + Message;
+
+  return std::string();
+}
+
 /// DiagnoseSentinelCalls - This routine checks on method dispatch calls
 /// (and other functions in future), which have been declared with sentinel
 /// attribute. It warns if call does not have the sentinel argument.

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Mar 22 19:50:03 2011
@@ -1388,16 +1388,16 @@
     Candidates.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs);
     return true;
 
-  case OR_Deleted:
+  case OR_Deleted: {
     Diag(StartLoc, diag::err_ovl_deleted_call)
       << Best->Function->isDeleted()
       << Name 
-      << Best->Function->getMessageUnavailableAttr(
-             !Best->Function->isDeleted())
+      << getDeletedOrUnavailableSuffix(Best->Function)
       << Range;
     Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
     return true;
   }
+  }
   assert(false && "Unreachable, bad result from BestViableFunction");
   return true;
 }

Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)
+++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Tue Mar 22 19:50:03 2011
@@ -1138,10 +1138,14 @@
 static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod,
                              ObjCPropertyDecl *Property) {
   // Should we just clone all attributes over?
-  if (DeprecatedAttr *A = Property->getAttr<DeprecatedAttr>())
-    PropertyMethod->addAttr(A->clone(S.Context));
-  if (UnavailableAttr *A = Property->getAttr<UnavailableAttr>())
-    PropertyMethod->addAttr(A->clone(S.Context));
+  for (Decl::attr_iterator A = Property->attr_begin(), 
+                        AEnd = Property->attr_end(); 
+       A != AEnd; ++A) {
+    if (isa<DeprecatedAttr>(*A) || 
+        isa<UnavailableAttr>(*A) || 
+        isa<AvailabilityAttr>(*A))
+      PropertyMethod->addAttr((*A)->clone(S.Context));
+  }
 }
 
 /// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Mar 22 19:50:03 2011
@@ -6282,8 +6282,7 @@
 
   // Best is the best viable function.
   if (Best->Function &&
-      (Best->Function->isDeleted() ||
-       Best->Function->getAttr<UnavailableAttr>()))
+      (Best->Function->isDeleted() || Best->Function->isUnavailable()))
     return OR_Deleted;
 
   return OR_Success;
@@ -6735,7 +6734,7 @@
   FunctionDecl *Fn = Cand->Function;
 
   // Note deleted candidates, but only if they're viable.
-  if (Cand->Viable && (Fn->isDeleted() || Fn->hasAttr<UnavailableAttr>())) {
+  if (Cand->Viable && (Fn->isDeleted() || Fn->isUnavailable())) {
     std::string FnDesc;
     OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc);
 
@@ -7744,8 +7743,7 @@
       Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_deleted_call)
         << Best->Function->isDeleted()
         << ULE->getName()
-        << Best->Function->getMessageUnavailableAttr(
-             !Best->Function->isDeleted())
+        << getDeletedOrUnavailableSuffix(Best->Function)
         << Fn->getSourceRange();
       CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
     }
@@ -7928,8 +7926,7 @@
       Diag(OpLoc, diag::err_ovl_deleted_oper)
         << Best->Function->isDeleted()
         << UnaryOperator::getOpcodeStr(Opc)
-        << Best->Function->getMessageUnavailableAttr(
-             !Best->Function->isDeleted())
+        << getDeletedOrUnavailableSuffix(Best->Function)
         << Input->getSourceRange();
       CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
       return ExprError();
@@ -8199,8 +8196,7 @@
       Diag(OpLoc, diag::err_ovl_deleted_oper)
         << Best->Function->isDeleted()
         << BinaryOperator::getOpcodeStr(Opc)
-        << Best->Function->getMessageUnavailableAttr(
-             !Best->Function->isDeleted())
+        << getDeletedOrUnavailableSuffix(Best->Function)
         << Args[0]->getSourceRange() << Args[1]->getSourceRange();
       CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2);
       return ExprError();
@@ -8349,8 +8345,7 @@
     case OR_Deleted:
       Diag(LLoc, diag::err_ovl_deleted_oper)
         << Best->Function->isDeleted() << "[]"
-        << Best->Function->getMessageUnavailableAttr(
-             !Best->Function->isDeleted())
+        << getDeletedOrUnavailableSuffix(Best->Function)
         << Args[0]->getSourceRange() << Args[1]->getSourceRange();
       CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2,
                                   "[]", LLoc);
@@ -8468,8 +8463,7 @@
       Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call)
         << Best->Function->isDeleted()
         << DeclName 
-        << Best->Function->getMessageUnavailableAttr(
-             !Best->Function->isDeleted())
+        << getDeletedOrUnavailableSuffix(Best->Function)
         << MemExprE->getSourceRange();
       CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
       // FIXME: Leaking incoming expressions!
@@ -8643,8 +8637,7 @@
          diag::err_ovl_deleted_object_call)
       << Best->Function->isDeleted()
       << Object->getType() 
-      << Best->Function->getMessageUnavailableAttr(
-           !Best->Function->isDeleted())
+      << getDeletedOrUnavailableSuffix(Best->Function)
       << Object->getSourceRange();
     CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
     break;
@@ -8852,8 +8845,7 @@
     Diag(OpLoc,  diag::err_ovl_deleted_oper)
       << Best->Function->isDeleted()
       << "->" 
-      << Best->Function->getMessageUnavailableAttr(
-             !Best->Function->isDeleted())
+      << getDeletedOrUnavailableSuffix(Best->Function)
       << Base->getSourceRange();
     CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &Base, 1);
     return ExprError();

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Mar 22 19:50:03 2011
@@ -37,6 +37,7 @@
 #include "clang/Basic/FileSystemStatCache.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/Version.h"
+#include "clang/Basic/VersionTuple.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Bitcode/BitstreamReader.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -4870,6 +4871,18 @@
   return Result;
 }
 
+VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record, 
+                                         unsigned &Idx) {
+  unsigned Major = Record[Idx++];
+  unsigned Minor = Record[Idx++];
+  unsigned Subminor = Record[Idx++];
+  if (Minor == 0)
+    return VersionTuple(Major);
+  if (Subminor == 0)
+    return VersionTuple(Major, Minor - 1);
+  return VersionTuple(Major, Minor - 1, Subminor - 1);
+}
+
 CXXTemporary *ASTReader::ReadCXXTemporary(const RecordData &Record,
                                           unsigned &Idx) {
   CXXDestructorDecl *Decl = cast<CXXDestructorDecl>(GetDecl(Record[Idx++]));

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Mar 22 19:50:03 2011
@@ -37,6 +37,7 @@
 #include "clang/Basic/SourceManagerInternals.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/Version.h"
+#include "clang/Basic/VersionTuple.h"
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/StringExtras.h"
@@ -2622,6 +2623,19 @@
   Record.insert(Record.end(), Str.begin(), Str.end());
 }
 
+void ASTWriter::AddVersionTuple(const VersionTuple &Version,
+                                RecordDataImpl &Record) {
+  Record.push_back(Version.getMajor());
+  if (llvm::Optional<unsigned> Minor = Version.getMinor())
+    Record.push_back(*Minor + 1);
+  else
+    Record.push_back(0);
+  if (llvm::Optional<unsigned> Subminor = Version.getSubminor())
+    Record.push_back(*Subminor + 1);
+  else
+    Record.push_back(0);
+}
+
 /// \brief Note that the identifier II occurs at the given offset
 /// within the identifier table.
 void ASTWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) {

Added: cfe/trunk/test/CodeGenObjC/attr-availability.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/attr-availability.m?rev=128127&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjC/attr-availability.m (added)
+++ cfe/trunk/test/CodeGenObjC/attr-availability.m Tue Mar 22 19:50:03 2011
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -fobjc-nonfragile-abi "-triple" "x86_64-apple-darwin8.0.0" -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-10_4 %s
+// RUN: %clang_cc1 -fobjc-nonfragile-abi "-triple" "x86_64-apple-darwin9.0.0" -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-10_5 %s
+// RUN: %clang_cc1 -fobjc-nonfragile-abi "-triple" "x86_64-apple-darwin10.0.0" -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-10_6 %s
+
+// CHECK-10_4: @"OBJC_CLASS_$_WeakClass1" = extern_weak global
+// CHECK-10_5: @"OBJC_CLASS_$_WeakClass1" = external global
+// CHECK-10_6: @"OBJC_CLASS_$_WeakClass1" = external global
+__attribute__((availability(macosx,introduced=10.5)))
+ at interface WeakClass1 @end
+
+ at implementation WeakClass1(MyCategory) @end
+
+ at implementation WeakClass1(YourCategory) @end
+
+// CHECK-10_4: @"OBJC_CLASS_$_WeakClass2" = extern_weak global 
+// CHECK-10_5: @"OBJC_CLASS_$_WeakClass2" = extern_weak global 
+// CHECK-10_6: @"OBJC_CLASS_$_WeakClass2" = external global 
+__attribute__((availability(macosx,introduced=10.6)))
+ at interface WeakClass2 @end
+
+ at implementation WeakClass2(MyCategory) @end
+
+ at implementation WeakClass2(YourCategory) @end
+

Added: cfe/trunk/test/Parser/attr-availability.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/attr-availability.c?rev=128127&view=auto
==============================================================================
--- cfe/trunk/test/Parser/attr-availability.c (added)
+++ cfe/trunk/test/Parser/attr-availability.c Tue Mar 22 19:50:03 2011
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+void f0() __attribute__((availability(macosx,introduced=10.2,deprecated=10.4,obsoleted=10.6)));
+
+void f1() __attribute__((availability(macosx,deprecated=10.4,introduced=10.2,obsoleted=10.6)));
+
+void f2() __attribute__((availability(ios,deprecated=10.4.7,introduced=10,obsoleted=10.6)));
+
+void f3() __attribute__((availability(ios,deprecated=10.4.7,introduced=10,obsoleted=10.6,introduced=10.2))); // expected-error{{redundant 'introduced' availability change; only the last specified change will be used}}
+

Propchange: cfe/trunk/test/Parser/attr-availability.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/Parser/attr-availability.c
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/Parser/attr-availability.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/Sema/attr-availability-ios.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-availability-ios.c?rev=128127&view=auto
==============================================================================
--- cfe/trunk/test/Sema/attr-availability-ios.c (added)
+++ cfe/trunk/test/Sema/attr-availability-ios.c Tue Mar 22 19:50:03 2011
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 "-triple" "x86_64-apple-darwin3.0.0-iphoneos" -fsyntax-only -verify %s
+
+void f0(int) __attribute__((availability(ios,introduced=2.0,deprecated=2.1)));
+void f1(int) __attribute__((availability(ios,introduced=2.1)));
+void f2(int) __attribute__((availability(ios,introduced=2.0,deprecated=3.0)));
+void f3(int) __attribute__((availability(ios,introduced=3.0)));
+void f4(int) __attribute__((availability(macosx,introduced=10.1,deprecated=10.3,obsoleted=10.5), availability(ios,introduced=2.0,deprecated=2.1,obsoleted=3.0))); // expected-note{{explicitly marked unavailable}}
+
+void test() {
+  f0(0); // expected-warning{{'f0' is deprecated: first deprecated in iOS 2.1}}
+  f1(0);
+  f2(0); // expected-warning{{'f2' is deprecated: first deprecated in iOS 3.0}}
+  f3(0);
+  f4(0); // expected-error{{f4' is unavailable: obsoleted in iOS 3.0}}
+}

Propchange: cfe/trunk/test/Sema/attr-availability-ios.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/Sema/attr-availability-ios.c
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/Sema/attr-availability-ios.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/Sema/attr-availability-macosx.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-availability-macosx.c?rev=128127&view=auto
==============================================================================
--- cfe/trunk/test/Sema/attr-availability-macosx.c (added)
+++ cfe/trunk/test/Sema/attr-availability-macosx.c Tue Mar 22 19:50:03 2011
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 "-triple" "x86_64-apple-darwin9.0.0" -fsyntax-only -verify %s
+
+void f0(int) __attribute__((availability(macosx,introduced=10.4,deprecated=10.6)));
+void f1(int) __attribute__((availability(macosx,introduced=10.5)));
+void f2(int) __attribute__((availability(macosx,introduced=10.4,deprecated=10.5)));
+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 test() {
+  f0(0);
+  f1(0);
+  f2(0); // expected-warning{{'f2' is deprecated: first deprecated in Mac OS X 10.5}}
+  f3(0);
+  f4(0); // expected-error{{f4' is unavailable: obsoleted in Mac OS X 10.5}}
+}

Propchange: cfe/trunk/test/Sema/attr-availability-macosx.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/Sema/attr-availability-macosx.c
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/Sema/attr-availability-macosx.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/Sema/attr-availability.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-availability.c?rev=128127&view=auto
==============================================================================
--- cfe/trunk/test/Sema/attr-availability.c (added)
+++ cfe/trunk/test/Sema/attr-availability.c Tue Mar 22 19:50:03 2011
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+void f0() __attribute__((availability(macosx,introduced=10.4,deprecated=10.2))); // expected-warning{{feature cannot be deprecated in Mac OS X version 10.2 before it was introduced in version 10.4; attribute ignored}}
+void f1() __attribute__((availability(ios,obsoleted=2.1,deprecated=3.0)));  // expected-warning{{feature cannot be obsoleted in iOS version 2.1 before it was deprecated in version 3.0; attribute ignored}}
+
+void f2() __attribute__((availability(otheros,introduced=2.2))); // expected-warning{{unknown platform 'otheros' in availability macro}}

Propchange: cfe/trunk/test/Sema/attr-availability.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/Sema/attr-availability.c
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/Sema/attr-availability.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/test/SemaCXX/attr-unavailable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-unavailable.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/attr-unavailable.cpp (original)
+++ cfe/trunk/test/SemaCXX/attr-unavailable.cpp Tue Mar 22 19:50:03 2011
@@ -25,6 +25,6 @@
 
 void foo() FOO; // expected-note {{candidate function has been explicitly made unavailable}}
 void bar() {
-  foo(); // expected-error {{call to unavailable function 'foo' not available - replaced}}
+  foo(); // expected-error {{call to unavailable function 'foo': not available - replaced}}
 }
 }

Modified: cfe/trunk/test/SemaObjC/protocol-attribute.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/protocol-attribute.m?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/protocol-attribute.m (original)
+++ cfe/trunk/test/SemaObjC/protocol-attribute.m Tue Mar 22 19:50:03 2011
@@ -40,7 +40,7 @@
 
 __attribute ((unavailable)) __attribute ((deprecated)) @protocol XProto; // expected-note{{marked unavailable}}
 
-id <XProto> idX = 0; // expected-error {{'XProto' is unavailable}} expected-warning {{'XProto' is deprecated}}
+id <XProto> idX = 0; // expected-error {{'XProto' is unavailable}}
 
 int main ()
 {

Modified: cfe/trunk/test/SemaObjC/special-dep-unavail-warning.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/special-dep-unavail-warning.m?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/special-dep-unavail-warning.m (original)
+++ cfe/trunk/test/SemaObjC/special-dep-unavail-warning.m Tue Mar 22 19:50:03 2011
@@ -36,10 +36,8 @@
   [c unavailMeth1]; // expected-warning {{'unavailMeth1' maybe unavailable because receiver type is unknown}}
   [c depInA2]; // expected-warning {{'depInA2' maybe deprecated because receiver type is unknown}}
   [c unavailMeth2]; // expected-warning {{'unavailMeth2' maybe unavailable because receiver type is unknown}}
-  [c depunavailInA]; // expected-warning {{'depunavailInA' maybe deprecated because receiver type is unknown}} \
-                     // expected-warning {{'depunavailInA' maybe unavailable because receiver type is unknown}} 
-  [c depunavailInA1]; // expected-warning {{'depunavailInA1' maybe deprecated because receiver type is unknown}} \
-                      // expected-warning {{'depunavailInA1' maybe unavailable because receiver type is unknown}}
+  [c depunavailInA]; // expected-warning {{'depunavailInA' maybe unavailable because receiver type is unknown}} 
+  [c depunavailInA1];// expected-warning {{'depunavailInA1' maybe unavailable because receiver type is unknown}}
   [c FuzzyMeth];      // expected-warning {{'FuzzyMeth' maybe deprecated because receiver type is unknown}}
   [c FuzzyMeth1]; // expected-warning {{'FuzzyMeth1' maybe deprecated because receiver type is unknown}}
 

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=128127&r1=128126&r2=128127&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Tue Mar 22 19:50:03 2011
@@ -4897,14 +4897,22 @@
 enum CXAvailabilityKind clang_getCursorAvailability(CXCursor cursor) {
   if (clang_isDeclaration(cursor.kind))
     if (Decl *D = cxcursor::getCursorDecl(cursor)) {
-      if (D->hasAttr<UnavailableAttr>() ||
-          (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isDeleted()))
+      if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isDeleted())
         return CXAvailability_Available;
       
-      if (D->hasAttr<DeprecatedAttr>())
+      switch (D->getAvailability()) {
+      case AR_Available:
+      case AR_NotYetIntroduced:
+        return CXAvailability_Available;
+
+      case AR_Deprecated:
         return CXAvailability_Deprecated;
+
+      case AR_Unavailable:
+        return CXAvailability_NotAvailable;
+      }
     }
-  
+
   return CXAvailability_Available;
 }
 





More information about the cfe-commits mailing list