Re: [PATCH] D17865: Add an optional string argument to DeprecatedAttr for Fix-It.

2016-03-19 Thread Aaron Ballman via cfe-commits
aaron.ballman accepted this revision.
aaron.ballman added a comment.
This revision is now accepted and ready to land.

One small documentation nit, but I'm fine with you fixing it then committing 
(no need for another round of review). Thanks!



Comment at: include/clang/Basic/AttrDocs.td:2189
@@ +2188,3 @@
+
+The deprecated attribute can have two optional string arguments. The first
+one is the message to display when emitting the warning; the second one

"When spelled as ``__attribute__((deprecated))``, the deprecated attribute 
can..."

"Otherwise, when spelled as ``[[gnu::deprecated]]`` or ``[[deprecated]]``, the 
attribute can have one optional string argument which is the message to display 
when emitting the warning."


http://reviews.llvm.org/D17865



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


Re: [PATCH] D17865: Add an optional string argument to DeprecatedAttr for Fix-It.

2016-03-19 Thread Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL263652: Add an optional string argument to DeprecatedAttr 
for Fix-It. (authored by mren).

Changed prior to commit:
  http://reviews.llvm.org/D17865?vs=50682=50844#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D17865

Files:
  cfe/trunk/include/clang/Basic/Attr.td
  cfe/trunk/include/clang/Basic/AttrDocs.td
  cfe/trunk/lib/Lex/PPMacroExpansion.cpp
  cfe/trunk/lib/Sema/SemaDeclAttr.cpp
  cfe/trunk/test/SemaCXX/attr-deprecated-replacement-error.cpp
  cfe/trunk/test/SemaCXX/attr-deprecated-replacement-fixit.cpp
  cfe/trunk/test/SemaCXX/cxx11-attr-print.cpp
  cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp

Index: cfe/trunk/lib/Lex/PPMacroExpansion.cpp
===
--- cfe/trunk/lib/Lex/PPMacroExpansion.cpp
+++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp
@@ -1079,6 +1079,7 @@
   .Case("attribute_cf_returns_retained", true)
   .Case("attribute_cf_returns_on_parameters", true)
   .Case("attribute_deprecated_with_message", true)
+  .Case("attribute_deprecated_with_replacement", true)
   .Case("attribute_ext_vector_type", true)
   .Case("attribute_ns_returns_not_retained", true)
   .Case("attribute_ns_returns_retained", true)
Index: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
===
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp
@@ -5136,12 +5136,27 @@
 }
   }
 
+  // Handle the cases where the attribute has a text message.
+  StringRef Str, Replacement;
+  if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0) &&
+  !S.checkStringLiteralArgumentAttr(Attr, 0, Str))
+return;
+
+  // Only support a single optional message for Declspec and CXX11.
+  if (Attr.isDeclspecAttribute() || Attr.isCXX11Attribute())
+checkAttributeAtMostNumArgs(S, Attr, 1);
+  else if (Attr.isArgExpr(1) && Attr.getArgAsExpr(1) &&
+   !S.checkStringLiteralArgumentAttr(Attr, 1, Replacement))
+return;
+
   if (!S.getLangOpts().CPlusPlus14)
 if (Attr.isCXX11Attribute() &&
 !(Attr.hasScope() && Attr.getScopeName()->isStr("gnu")))
   S.Diag(Attr.getLoc(), diag::ext_cxx14_attr) << Attr.getName();
 
-  handleAttrWithMessage(S, D, Attr);
+  D->addAttr(::new (S.Context) DeprecatedAttr(Attr.getRange(), S.Context, Str,
+   Replacement,
+   Attr.getAttributeSpellingListIndex()));
 }
 
 static void handleNoSanitizeAttr(Sema , Decl *D, const AttributeList ) {
@@ -6209,18 +6224,35 @@
 break;
   }
 
+  CharSourceRange UseRange;
+  StringRef Replacement;
+  if (K == Sema::AD_Deprecation) {
+if (auto attr = D->getAttr())
+  Replacement = attr->getReplacement();
+
+if (!Replacement.empty())
+  UseRange =
+  CharSourceRange::getCharRange(Loc, S.getLocForEndOfToken(Loc));
+  }
+
   if (!Message.empty()) {
-S.Diag(Loc, diag_message) << D << Message;
+S.Diag(Loc, diag_message) << D << Message
+  << (UseRange.isValid() ?
+  FixItHint::CreateReplacement(UseRange, Replacement) : FixItHint());
 if (ObjCProperty)
   S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
   << ObjCProperty->getDeclName() << property_note_select;
   } else if (!UnknownObjCClass) {
-S.Diag(Loc, diag) << D;
+S.Diag(Loc, diag) << D
+  << (UseRange.isValid() ?
+  FixItHint::CreateReplacement(UseRange, Replacement) : FixItHint());
 if (ObjCProperty)
   S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
   << ObjCProperty->getDeclName() << property_note_select;
   } else {
-S.Diag(Loc, diag_fwdclass_message) << D;
+S.Diag(Loc, diag_fwdclass_message) << D
+  << (UseRange.isValid() ?
+  FixItHint::CreateReplacement(UseRange, Replacement) : FixItHint());
 S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
   }
 
Index: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
===
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
@@ -,6 +,15 @@
  << "  OS << \"";
 }
 
+static void writeDeprecatedAttrValue(raw_ostream , std::string ) {
+  OS << "\\\"\" << getMessage() << \"\\\"\";\n";
+  // Only GNU deprecated has an optional fixit argument at the second position.
+  if (Variety == "GNU")
+ OS << "if (!getReplacement().empty()) OS << \", \\\"\""
+   " << getReplacement() << \"\\\"\";\n";
+  OS << "OS << \"";
+}
+
 static void writeGetSpellingFunction(Record , raw_ostream ) {
   std::vector Spellings = GetFlattenedSpellings(R);
 
@@ -1224,6 +1233,8 @@
   OS << "(";
 if (Spelling == "availability") {
   writeAvailabilityValue(OS);
+} else if (Spelling == "deprecated" || Spelling == "gnu::deprecated") {
+

Re: [PATCH] D17865: Add an optional string argument to DeprecatedAttr for Fix-It.

2016-03-14 Thread Manman Ren via cfe-commits
manmanren updated this revision to Diff 50682.

http://reviews.llvm.org/D17865

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  lib/Lex/PPMacroExpansion.cpp
  lib/Sema/SemaDeclAttr.cpp
  test/SemaCXX/attr-deprecated-replacement-error.cpp
  test/SemaCXX/attr-deprecated-replacement-fixit.cpp
  test/SemaCXX/cxx11-attr-print.cpp
  utils/TableGen/ClangAttrEmitter.cpp

Index: test/SemaCXX/attr-deprecated-replacement-fixit.cpp
===
--- /dev/null
+++ test/SemaCXX/attr-deprecated-replacement-fixit.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -verify -fsyntax-only %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: cp %s %t
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fixit %t
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -Werror %t
+
+#if !__has_feature(attribute_deprecated_with_replacement)
+#error "Missing __has_feature"
+#endif
+
+void f_8(int) __attribute__((deprecated("message", "new8"))); // expected-note {{'f_8' has been explicitly marked deprecated here}}
+void new8(int);
+void test() {
+  f_8(0); // expected-warning{{'f_8' is deprecated}}
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:6}:"new8"
+}
Index: test/SemaCXX/attr-deprecated-replacement-error.cpp
===
--- /dev/null
+++ test/SemaCXX/attr-deprecated-replacement-error.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -verify -fsyntax-only -std=c++11 -fms-extensions %s
+
+#if !__has_feature(attribute_deprecated_with_replacement)
+#error "Missing __has_feature"
+#endif
+
+int a1 [[deprecated("warning", "fixit")]]; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
+int a2 [[deprecated("warning", 1)]]; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
+
+int b1 [[gnu::deprecated("warning", "fixit")]]; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
+int b2 [[gnu::deprecated("warning", 1)]]; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
+
+__declspec(deprecated("warning", "fixit")) int c1; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
+__declspec(deprecated("warning", 1)) int c2; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
+
+int d1 __attribute__((deprecated("warning", "fixit")));
+int d2 __attribute__((deprecated("warning", 1))); // expected-error{{'deprecated' attribute requires a string}}
Index: utils/TableGen/ClangAttrEmitter.cpp
===
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -,6 +,15 @@
  << "  OS << \"";
 }
 
+static void writeDeprecatedAttrValue(raw_ostream , std::string ) {
+  OS << "\\\"\" << getMessage() << \"\\\"\";\n";
+  // Only GNU deprecated has an optional fixit argument at the second position.
+  if (Variety == "GNU")
+ OS << "if (!getReplacement().empty()) OS << \", \\\"\""
+   " << getReplacement() << \"\\\"\";\n";
+  OS << "OS << \"";
+}
+
 static void writeGetSpellingFunction(Record , raw_ostream ) {
   std::vector Spellings = GetFlattenedSpellings(R);
 
@@ -1224,6 +1233,8 @@
   OS << "(";
 if (Spelling == "availability") {
   writeAvailabilityValue(OS);
+} else if (Spelling == "deprecated" || Spelling == "gnu::deprecated") {
+writeDeprecatedAttrValue(OS, Variety);
 } else {
   unsigned index = 0;
   for (const auto  : Args) {
Index: test/SemaCXX/cxx11-attr-print.cpp
===
--- test/SemaCXX/cxx11-attr-print.cpp
+++ test/SemaCXX/cxx11-attr-print.cpp
@@ -16,6 +16,15 @@
 // CHECK: int b {{\[}}[gnu::deprecated("warning")]];
 int b [[gnu::deprecated("warning")]];
 
+// CHECK: __declspec(deprecated("warning"))
+__declspec(deprecated("warning")) int c;
+
+// CHECK: int d {{\[}}[deprecated("warning")]];
+int d [[deprecated("warning")]];
+
+// CHECK: __attribute__((deprecated("warning", "fixit")));
+int e __attribute__((deprecated("warning", "fixit")));
+
 // CHECK: int cxx11_alignas alignas(4);
 alignas(4) int cxx11_alignas;
 
Index: lib/Sema/SemaDeclAttr.cpp
===
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -5127,12 +5127,27 @@
 }
   }
 
+  // Handle the cases where the attribute has a text message.
+  StringRef Str, Replacement;
+  if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0) &&
+  !S.checkStringLiteralArgumentAttr(Attr, 0, Str))
+return;
+
+  // Only support a single optional message for Declspec and CXX11.
+  if (Attr.isDeclspecAttribute() || Attr.isCXX11Attribute())
+checkAttributeAtMostNumArgs(S, Attr, 1);
+  else if (Attr.isArgExpr(1) && Attr.getArgAsExpr(1) &&
+   

Re: [PATCH] D17865: Add an optional string argument to DeprecatedAttr for Fix-It.

2016-03-14 Thread Aaron Ballman via cfe-commits
aaron.ballman added a comment.

In http://reviews.llvm.org/D17865#374939, @manmanren wrote:

> In http://reviews.llvm.org/D17865#374659, @aaron.ballman wrote:
>
> > Aside from the missing attribute documentation, looks good to me.
>
>
> Hi Aaron,
>
> Which document are you referring to? "include/clang/Basic/AttrDocs.td"?


Yes, AttrDocs.td that you then reference in to Attr.td.

> We don't have a section for DeprecatedAttr, should I start one?


Yes, please! We used to get away with relying on GCC to document the attribute, 
so now that we're adding Clang-specific behavior, we should bite the bullet and 
document the attribute properly. :-)

Thanks!


http://reviews.llvm.org/D17865



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


Re: [PATCH] D17865: Add an optional string argument to DeprecatedAttr for Fix-It.

2016-03-14 Thread Aaron Ballman via cfe-commits
aaron.ballman added a comment.

Aside from the missing attribute documentation, looks good to me.


http://reviews.llvm.org/D17865



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


Re: [PATCH] D17865: Add an optional string argument to DeprecatedAttr for Fix-It.

2016-03-11 Thread Manman Ren via cfe-commits
manmanren marked 3 inline comments as done.
manmanren added a comment.

Upload patch to address review comments.

Thanks,
Manman


http://reviews.llvm.org/D17865



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


Re: [PATCH] D17865: Add an optional string argument to DeprecatedAttr for Fix-It.

2016-03-11 Thread Manman Ren via cfe-commits
manmanren updated this revision to Diff 50502.

http://reviews.llvm.org/D17865

Files:
  include/clang/Basic/Attr.td
  lib/Lex/PPMacroExpansion.cpp
  lib/Sema/SemaDeclAttr.cpp
  test/SemaCXX/attr-deprecated-replacement-error.cpp
  test/SemaCXX/attr-deprecated-replacement-fixit.cpp
  test/SemaCXX/cxx11-attr-print.cpp
  utils/TableGen/ClangAttrEmitter.cpp

Index: test/SemaCXX/attr-deprecated-replacement-fixit.cpp
===
--- /dev/null
+++ test/SemaCXX/attr-deprecated-replacement-fixit.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -verify -fsyntax-only %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: cp %s %t
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fixit %t
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -Werror %t
+
+#if !__has_feature(attribute_deprecated_with_replacement)
+#error "Missing __has_feature"
+#endif
+
+void f_8(int) __attribute__((deprecated("message", "new8"))); // expected-note {{'f_8' has been explicitly marked deprecated here}}
+void new8(int);
+void test() {
+  f_8(0); // expected-warning{{'f_8' is deprecated}}
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:6}:"new8"
+}
Index: test/SemaCXX/attr-deprecated-replacement-error.cpp
===
--- /dev/null
+++ test/SemaCXX/attr-deprecated-replacement-error.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -verify -fsyntax-only -std=c++11 -fms-extensions %s
+
+#if !__has_feature(attribute_deprecated_with_replacement)
+#error "Missing __has_feature"
+#endif
+
+int a1 [[deprecated("warning", "fixit")]]; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
+int a2 [[deprecated("warning", 1)]]; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
+
+int b1 [[gnu::deprecated("warning", "fixit")]]; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
+int b2 [[gnu::deprecated("warning", 1)]]; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
+
+__declspec(deprecated("warning", "fixit")) int c1; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
+__declspec(deprecated("warning", 1)) int c2; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
+
+int d1 __attribute__((deprecated("warning", "fixit")));
+int d2 __attribute__((deprecated("warning", 1))); // expected-error{{'deprecated' attribute requires a string}}
Index: utils/TableGen/ClangAttrEmitter.cpp
===
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -,6 +,15 @@
  << "  OS << \"";
 }
 
+static void writeDeprecatedAttrValue(raw_ostream , std::string ) {
+  OS << "\\\"\" << getMessage() << \"\\\"\";\n";
+  // Only GNU deprecated has an optional fixit argument at the second position.
+  if (Variety == "GNU")
+ OS << "if (!getReplacement().empty()) OS << \", \\\"\""
+   " << getReplacement() << \"\\\"\";\n";
+  OS << "OS << \"";
+}
+
 static void writeGetSpellingFunction(Record , raw_ostream ) {
   std::vector Spellings = GetFlattenedSpellings(R);
 
@@ -1224,6 +1233,8 @@
   OS << "(";
 if (Spelling == "availability") {
   writeAvailabilityValue(OS);
+} else if (Spelling == "deprecated" || Spelling == "gnu::deprecated") {
+writeDeprecatedAttrValue(OS, Variety);
 } else {
   unsigned index = 0;
   for (const auto  : Args) {
Index: test/SemaCXX/cxx11-attr-print.cpp
===
--- test/SemaCXX/cxx11-attr-print.cpp
+++ test/SemaCXX/cxx11-attr-print.cpp
@@ -16,6 +16,15 @@
 // CHECK: int b {{\[}}[gnu::deprecated("warning")]];
 int b [[gnu::deprecated("warning")]];
 
+// CHECK: __declspec(deprecated("warning"))
+__declspec(deprecated("warning")) int c;
+
+// CHECK: int d {{\[}}[deprecated("warning")]];
+int d [[deprecated("warning")]];
+
+// CHECK: __attribute__((deprecated("warning", "fixit")));
+int e __attribute__((deprecated("warning", "fixit")));
+
 // CHECK: int cxx11_alignas alignas(4);
 alignas(4) int cxx11_alignas;
 
Index: lib/Sema/SemaDeclAttr.cpp
===
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -5127,12 +5127,27 @@
 }
   }
 
+  // Handle the cases where the attribute has a text message.
+  StringRef Str, Replacement;
+  if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0) &&
+  !S.checkStringLiteralArgumentAttr(Attr, 0, Str))
+return;
+
+  // Only support a single optional message for Declspec and CXX11.
+  if (Attr.isDeclspecAttribute() || Attr.isCXX11Attribute())
+checkAttributeAtMostNumArgs(S, Attr, 1);
+  else if (Attr.isArgExpr(1) && Attr.getArgAsExpr(1) &&
+   !S.checkStringLiteralArgumentAttr(Attr, 1, 

Re: [PATCH] D17865: Add an optional string argument to DeprecatedAttr for Fix-It.

2016-03-11 Thread Aaron Ballman via cfe-commits
aaron.ballman added inline comments.


Comment at: include/clang/Basic/Attr.td:726
@@ +725,3 @@
+  let Args = [StringArgument<"Message", 1>,
+  // An optional string argument that enables us to provide a Fix-It.
+  StringArgument<"Replacement", 1>];

The formatting here is a bit strange.


Comment at: lib/Sema/SemaDeclAttr.cpp:5143
@@ +5142,3 @@
+
+  D->addAttr(::new (S.Context) DeprecatedAttr(Attr.getRange(), S.Context, Str,
+   Replacement,

This should move back down below the extension warning (the effect is the same, 
but logically we want to warn before attaching).


Comment at: utils/TableGen/ClangAttrEmitter.cpp:1234
@@ +1233,3 @@
+if ((Spelling == "deprecated" || Spelling == "gnu::deprecated") &&
+Variety != "GNU" && index == 1)
+  continue;

manmanren wrote:
> This does not look pretty. Maybe we can implement a function 
> writeDeprecatedValue that can skip the second argument if it is empty?
I wouldn't be opposed to that approach; we already do it for 
`writeAvailabilityValue()`, so another one for deprecated wouldn't be that 
horrible.


http://reviews.llvm.org/D17865



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


Re: [PATCH] D17865: Add an optional string argument to DeprecatedAttr for Fix-It.

2016-03-10 Thread Manman Ren via cfe-commits
manmanren added inline comments.


Comment at: utils/TableGen/ClangAttrEmitter.cpp:1234
@@ +1233,3 @@
+if ((Spelling == "deprecated" || Spelling == "gnu::deprecated") &&
+Variety != "GNU" && index == 1)
+  continue;

This does not look pretty. Maybe we can implement a function 
writeDeprecatedValue that can skip the second argument if it is empty?


http://reviews.llvm.org/D17865



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


Re: [PATCH] D17865: Add an optional string argument to DeprecatedAttr for Fix-It.

2016-03-10 Thread Manman Ren via cfe-commits
manmanren retitled this revision from "Add replacement = "xxx" to 
DeprecatedAttr." to "Add an optional string argument to DeprecatedAttr for 
Fix-It.".
manmanren updated this revision to Diff 50374.

http://reviews.llvm.org/D17865

Files:
  include/clang/Basic/Attr.td
  lib/Lex/PPMacroExpansion.cpp
  lib/Sema/SemaDeclAttr.cpp
  test/SemaCXX/attr-deprecated-replacement-error.cpp
  test/SemaCXX/attr-deprecated-replacement-fixit.cpp
  test/SemaCXX/cxx11-attr-print.cpp
  utils/TableGen/ClangAttrEmitter.cpp

Index: utils/TableGen/ClangAttrEmitter.cpp
===
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -1228,6 +1228,11 @@
   unsigned index = 0;
   for (const auto  : Args) {
 if (arg->isFake()) continue;
+// Only GNU deprecated has an optional fixit argument at the second
+// position.
+if ((Spelling == "deprecated" || Spelling == "gnu::deprecated") &&
+Variety != "GNU" && index == 1)
+  continue;
 if (index++) OS << ", ";
 arg->writeValue(OS);
   }
Index: test/SemaCXX/cxx11-attr-print.cpp
===
--- test/SemaCXX/cxx11-attr-print.cpp
+++ test/SemaCXX/cxx11-attr-print.cpp
@@ -10,12 +10,18 @@
 // CHECK: int z {{\[}}[gnu::aligned(4)]];
 int z [[gnu::aligned(4)]];
 
-// CHECK: __attribute__((deprecated("warning")));
+// CHECK: __attribute__((deprecated("warning", "")));
 int a __attribute__((deprecated("warning")));
 
 // CHECK: int b {{\[}}[gnu::deprecated("warning")]];
 int b [[gnu::deprecated("warning")]];
 
+// CHECK: __attribute__((deprecated("", "")));
+int c __attribute__((deprecated));
+
+// CHECK: int d {{\[}}[deprecated("warning")]];
+int d [[deprecated("warning")]];
+
 // CHECK: int cxx11_alignas alignas(4);
 alignas(4) int cxx11_alignas;
 
Index: test/SemaCXX/attr-deprecated-replacement-fixit.cpp
===
--- test/SemaCXX/attr-deprecated-replacement-fixit.cpp
+++ test/SemaCXX/attr-deprecated-replacement-fixit.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -verify -fsyntax-only %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: cp %s %t
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fixit %t
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -Werror %t
+
+#if !__has_feature(attribute_deprecated_with_replacement)
+#error "Missing __has_feature"
+#endif
+
+void f_8(int) __attribute__((deprecated("message", "new8"))); // expected-note {{'f_8' has been explicitly marked deprecated here}}
+void new8(int);
+void test() {
+  f_8(0); // expected-warning{{'f_8' is deprecated}}
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:6}:"new8"
+}
Index: test/SemaCXX/attr-deprecated-replacement-error.cpp
===
--- test/SemaCXX/attr-deprecated-replacement-error.cpp
+++ test/SemaCXX/attr-deprecated-replacement-error.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -verify -fsyntax-only -std=c++11 -fms-extensions %s
+
+#if !__has_feature(attribute_deprecated_with_replacement)
+#error "Missing __has_feature"
+#endif
+
+int a1 [[deprecated("warning", "fixit")]]; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
+int a2 [[deprecated("warning", 1)]]; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
+
+int b1 [[gnu::deprecated("warning", "fixit")]]; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
+int b2 [[gnu::deprecated("warning", 1)]]; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
+
+__declspec(deprecated("warning", "fixit")) int c1; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
+__declspec(deprecated("warning", 1)) int c2; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
+
+int d1 __attribute__((deprecated("warning", "fixit")));
+int d2 __attribute__((deprecated("warning", 1))); // expected-error{{'deprecated' attribute requires a string}}
Index: lib/Sema/SemaDeclAttr.cpp
===
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -5127,12 +5127,27 @@
 }
   }
 
+  // Handle the cases where the attribute has a text message.
+  StringRef Str, Replacement;
+  if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0) &&
+  !S.checkStringLiteralArgumentAttr(Attr, 0, Str))
+return;
+
+  // Only support a single optional message for Declspec and CXX11.
+  if (Attr.isDeclspecAttribute() || Attr.isCXX11Attribute())
+checkAttributeAtMostNumArgs(S, Attr, 1);
+  else if (Attr.isArgExpr(1) && Attr.getArgAsExpr(1) &&
+   !S.checkStringLiteralArgumentAttr(Attr, 1, Replacement))
+return;
+
+  D->addAttr(::new (S.Context)