]> granicus.if.org Git - clang/commitdiff
Add -Wdeprecated warnings and fixits for things deprecated in C++11:
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 13 Jun 2013 02:02:51 +0000 (02:02 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 13 Jun 2013 02:02:51 +0000 (02:02 +0000)
 - 'register' storage class
 - dynamic exception specifications

Only the former check is enabled by default for now (the latter might be quite noisy).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183881 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticParseKinds.td
include/clang/Basic/DiagnosticSemaKinds.td
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
test/CXX/class/class.friend/p6.cpp
test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
test/FixIt/fixit-cxx0x.cpp
test/Sema/thread-specifier.c
test/SemaCXX/attr-cxx0x.cpp
test/SemaCXX/deprecated.cpp [new file with mode: 0644]

index 44d3acfc17e8cab8e32a4b73a14de17aee29ebda..38c7c78a5c75870605fbb168c1c4c559a5dd0e6f 100644 (file)
@@ -309,6 +309,8 @@ def err_expected_class_name_not_template :
   Error<"'typename' is redundant; base classes are implicitly types">;
 def err_unspecified_vla_size_with_static : Error<
   "'static' may not be used with an unspecified variable length array size">;
+def warn_deprecated_register : Warning<
+  "'register' storage class specifier is deprecated">, InGroup<Deprecated>;
 
 def err_expected_case_before_expression: Error<
   "expected 'case' keyword before expression">;
index ac76e4d400bb72e78bd1372a5d132903c6b9b8cc..1c9d2955ec44d8bab49a0d87cb7f6f68165bac75 100644 (file)
@@ -287,6 +287,10 @@ def note_using_decl : Note<"%select{|previous }0using declaration">;
 def warn_access_decl_deprecated : Warning<
   "access declarations are deprecated; use using declarations instead">,
   InGroup<Deprecated>;
+def warn_exception_spec_deprecated : Warning<
+  "dynamic exception specifications are deprecated">,
+  InGroup<Deprecated>, DefaultIgnore;
+def note_exception_spec_deprecated : Note<"use '%0' instead">;
 
 def warn_global_constructor : Warning<
   "declaration requires a global constructor">,
index b3e8412dcf21cd1bedf62ed2d7fc6fa4fdc19881..8d96d6e6ccdf3d9a58f6460d98954ccd89524150 100644 (file)
@@ -2771,6 +2771,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
                                            PrevSpec, DiagID);
       break;
     case tok::kw_register:
+      if (getLangOpts().CPlusPlus11)
+        Diag(Tok, diag::warn_deprecated_register)
+          << FixItHint::CreateRemoval(Tok.getLocation());
       isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc,
                                          PrevSpec, DiagID);
       break;
index ae1ff37e6bc81c6d153fbec0f69d3e143145b869..71ee3118c9a0ee91cb9cca4b53a1855ffdc685ee 100644 (file)
@@ -2893,6 +2893,16 @@ Parser::tryParseExceptionSpecification(
   return Result;
 }
 
+static void diagnoseDynamicExceptionSpecification(
+    Parser &P, const SourceRange &Range, bool IsNoexcept) {
+  if (P.getLangOpts().CPlusPlus11) {
+    const char *Replacement = IsNoexcept ? "noexcept" : "noexcept(false)";
+    P.Diag(Range.getBegin(), diag::warn_exception_spec_deprecated) << Range;
+    P.Diag(Range.getBegin(), diag::note_exception_spec_deprecated)
+      << Replacement << FixItHint::CreateReplacement(Range, Replacement);
+  }
+}
+
 /// ParseDynamicExceptionSpecification - Parse a C++
 /// dynamic-exception-specification (C++ [except.spec]).
 ///
@@ -2926,6 +2936,7 @@ ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification(
       Diag(EllipsisLoc, diag::ext_ellipsis_exception_spec);
     T.consumeClose();
     SpecificationRange.setEnd(T.getCloseLocation());
+    diagnoseDynamicExceptionSpecification(*this, SpecificationRange, false);
     return EST_MSAny;
   }
 
@@ -2957,6 +2968,8 @@ ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification(
 
   T.consumeClose();
   SpecificationRange.setEnd(T.getCloseLocation());
+  diagnoseDynamicExceptionSpecification(*this, SpecificationRange,
+                                        Exceptions.empty());
   return Exceptions.empty() ? EST_DynamicNone : EST_Dynamic;
 }
 
index 82ca50e485d684494da4b3cbae3d773a69bfa1a8..ae327391a9a8cb837f2ea893e3515caf416fcd1b 100644 (file)
@@ -4,7 +4,11 @@
 class A {
   friend static class B; // expected-error {{'static' is invalid in friend declarations}}
   friend extern class C; // expected-error {{'extern' is invalid in friend declarations}}
+#if __cplusplus < 201103L
   friend register class E; // expected-error {{'register' is invalid in friend declarations}}
+#else
+  friend register class E; // expected-error {{'register' is invalid in friend declarations}} expected-warning {{deprecated}}
+#endif
   friend mutable class F; // expected-error {{'mutable' is invalid in friend declarations}}
   friend typedef class G; // expected-error {{'typedef' is invalid in friend declarations}}
   friend __thread class G; // expected-error {{'__thread' is invalid in friend declarations}}
index b159a15b8d40f8a6253461f0406933fde018efad..c23cd28f313712b337400e0092cceabe3e6f7510 100644 (file)
@@ -117,7 +117,7 @@ void g() {
 
   for (extern int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'extern'}}
   for (static int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'static'}}
-  for (register int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'register'}}
+  for (register int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'register'}} expected-warning {{deprecated}}
   for (constexpr int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'constexpr'}}
 
   for (auto u : X::NoBeginADL()) { // expected-error {{invalid range expression of type 'X::NoBeginADL'; no viable 'begin' function available}}
index 1f6275f933bc7da096c7f0023ab000d3b3b9716c..bfd8c3dcfea6fa40e4639c0674bd6c9b13112a06 100644 (file)
@@ -132,3 +132,8 @@ namespace NonStaticConstexpr {
     }
   };
 }
+
+int RegisterVariable() {
+  register int n; // expected-warning {{'register' storage class specifier is deprecated}}
+  return n;
+}
index 9d516e8f14130a6c79fa8ffabbdfefa234b94a75..bf1ce9e26e4aaf02830cdbc3441a22f9ac25cd27 100644 (file)
@@ -2,8 +2,8 @@
 // RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -Wno-private-extern -verify -pedantic -x c++ %s -DGNU
 // RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -Wno-private-extern -verify -pedantic %s -DC11 -D__thread=_Thread_local
 // RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -Wno-private-extern -verify -pedantic -x c++ %s -DC11 -D__thread=_Thread_local
-// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -Wno-private-extern -verify -pedantic -x c++ %s -DCXX11 -D__thread=thread_local -std=c++11
-// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -Wno-private-extern -verify -pedantic -x c++ %s -DC11 -D__thread=_Thread_local -std=c++11
+// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -Wno-private-extern -verify -pedantic -x c++ %s -DCXX11 -D__thread=thread_local -std=c++11 -Wno-deprecated
+// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -Wno-private-extern -verify -pedantic -x c++ %s -DC11 -D__thread=_Thread_local -std=c++11 -Wno-deprecated
 
 #ifdef __cplusplus
 // In C++, we define __private_extern__ to extern.
index e9276cd2d9ee333d4da3821f5b1a79c66f2faabf..fb46af40359bd0200107a2af7b355db69d3d9d03 100644 (file)
@@ -12,7 +12,7 @@ struct align_member {
 };
 
 void f(alignas(1) char c) { // expected-error {{'alignas' attribute cannot be applied to a function parameter}}
-  alignas(1) register char k; // expected-error {{'alignas' attribute cannot be applied to a variable with 'register' storage class}}
+  alignas(1) register char k; // expected-error {{'alignas' attribute cannot be applied to a variable with 'register' storage class}} expected-warning {{deprecated}}
   try {
   } catch (alignas(4) int n) { // expected-error {{'alignas' attribute cannot be applied to a 'catch' variable}}
   }
diff --git a/test/SemaCXX/deprecated.cpp b/test/SemaCXX/deprecated.cpp
new file mode 100644 (file)
index 0000000..fde2c37
--- /dev/null
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -std=c++98 %s -Wdeprecated -verify
+// RUN: %clang_cc1 -std=c++11 %s -Wdeprecated -verify
+// RUN: %clang_cc1 -std=c++1y %s -Wdeprecated -verify
+
+void f() throw();
+void g() throw(int);
+void h() throw(...);
+#if __cplusplus >= 201103L
+// expected-warning@-4 {{dynamic exception specifications are deprecated}} expected-note@-4 {{use 'noexcept' instead}}
+// expected-warning@-4 {{dynamic exception specifications are deprecated}} expected-note@-4 {{use 'noexcept(false)' instead}}
+// expected-warning@-4 {{dynamic exception specifications are deprecated}} expected-note@-4 {{use 'noexcept(false)' instead}}
+#endif
+
+void stuff() {
+  register int n;
+#if __cplusplus >= 201103L
+  // expected-warning@-2 {{'register' storage class specifier is deprecated}}
+#endif
+
+  bool b;
+  ++b; // expected-warning {{incrementing expression of type bool is deprecated}}
+
+  // FIXME: This is ill-formed in C++11.
+  char *p = "foo"; // expected-warning {{conversion from string literal to 'char *' is deprecated}}
+}
+
+struct S { int n; };
+struct T : private S {
+  // FIXME: This is ill-formed in C++11.
+  S::n; // expected-warning {{access declarations are deprecated; use using declarations instead}}
+};