diff --git a/docs/LanguageExtensions.html b/docs/LanguageExtensions.html
index 48d5aa64a1..8faa555f5c 100644
--- a/docs/LanguageExtensions.html
+++ b/docs/LanguageExtensions.html
@@ -23,6 +23,7 @@ td {
Include File Checking Macros
Builtin Macros
Vectors and Extended Vectors
+Deprecated and Unavailable attribute with Message
Checks for Standard Language Features
- C++ exceptions
@@ -266,6 +267,14 @@ float4 foo(float2 a, float2 b) {
See also __builtin_shufflevector.
+
+Deprecated and Unavailable attribute with Message
+
+
+ Optional string message can be added to Deprecated and Available attributes.
+
+ Message will be added to deprecated warning or unavailable error if present.
+
Checks for Standard Language Features
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index fbbaec2766..506f76f004 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -374,6 +374,7 @@ def TransparentUnion : Attr {
def Unavailable : Attr {
let Spellings = ["unavailable"];
+ let Args = [StringArgument<"Message">];
}
def Unused : Attr {
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index e43c837680..2d2ed63762 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1748,6 +1748,7 @@ def warn_deprecated : Warning<"%0 is deprecated">,
def warn_deprecated_message : Warning<"%0 is deprecated: %1">,
InGroup;
def err_unavailable : Error<"%0 is unavailable">;
+def err_unavailable_message : Error<"%0 is unavailable: %1">;
def note_unavailable_here : Note<
"function has been explicitly marked %select{unavailable|deleted}0 here">;
def warn_not_enough_argument : Warning<
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 3e1ced29a8..e9ee50fe75 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -929,12 +929,26 @@ static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
- if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ int noArgs = Attr.getNumArgs();
+ if (noArgs > 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "0 or 1";
return;
}
-
- d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context));
+ // Handle the case where unavailable attribute has a text message.
+ StringLiteral *SE;
+ if (noArgs == 1) {
+ Expr *ArgExpr = static_cast(Attr.getArg(0));
+ SE = dyn_cast(ArgExpr);
+ if (!SE) {
+ S.Diag(ArgExpr->getLocStart(),
+ diag::err_attribute_not_string) << "unavailable";
+ return;
+ }
+ }
+ else
+ SE = StringLiteral::CreateEmpty(S.Context, 1);
+ d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context,
+ SE->getString()));
}
static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index fa1ce7a21c..f6dc441bff 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -64,8 +64,12 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
}
// See if the decl is unavailable
- if (D->getAttr()) {
- Diag(Loc, diag::err_unavailable) << D->getDeclName();
+ if (const UnavailableAttr *UA = D->getAttr()) {
+ if (UA->getMessage().empty())
+ Diag(Loc, diag::err_unavailable) << D->getDeclName();
+ else
+ Diag(Loc, diag::err_unavailable_message)
+ << D->getDeclName() << UA->getMessage().data();
Diag(D->getLocation(), diag::note_unavailable_here) << 0;
}
diff --git a/test/Sema/attr-unavailable-message.c b/test/Sema/attr-unavailable-message.c
new file mode 100644
index 0000000000..4d07a238a9
--- /dev/null
+++ b/test/Sema/attr-unavailable-message.c
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// rdar: //6734520
+
+int foo(int) __attribute__((__unavailable__("USE IFOO INSTEAD"))); // expected-note {{function has been explicitly marked unavailable here}}
+double dfoo(double) __attribute__((__unavailable__("NO LONGER"))); // expected-note 2 {{function has been explicitly marked unavailable here}}
+
+void bar() __attribute__((__unavailable__)); // expected-note {{explicitly marked unavailable}}
+
+void test_foo() {
+ int ir = foo(1); // expected-error {{'foo' is unavailable: USE IFOO INSTEAD}}
+ double dr = dfoo(1.0); // expected-error {{'dfoo' is unavailable: NO LONGER}}
+
+ void (*fp)() = &bar; // expected-error {{'bar' is unavailable}}
+
+ double (*fp4)(double) = dfoo; // expected-error {{'dfoo' is unavailable: NO LONGER}}
+}