From 79f4bb7aad1b7c53f8a3bc43d89de0efdef8286d Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 13 Jun 2013 02:02:51 +0000 Subject: [PATCH] Add -Wdeprecated warnings and fixits for things deprecated in C++11: - '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 | 2 ++ include/clang/Basic/DiagnosticSemaKinds.td | 4 +++ lib/Parse/ParseDecl.cpp | 3 ++ lib/Parse/ParseDeclCXX.cpp | 13 ++++++++ test/CXX/class/class.friend/p6.cpp | 4 +++ .../stmt.stmt/stmt.iter/stmt.ranged/p1.cpp | 2 +- test/FixIt/fixit-cxx0x.cpp | 5 +++ test/Sema/thread-specifier.c | 4 +-- test/SemaCXX/attr-cxx0x.cpp | 2 +- test/SemaCXX/deprecated.cpp | 31 +++++++++++++++++++ 10 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 test/SemaCXX/deprecated.cpp diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 44d3acfc17..38c7c78a5c 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -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; def err_expected_case_before_expression: Error< "expected 'case' keyword before expression">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index ac76e4d400..1c9d2955ec 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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; +def warn_exception_spec_deprecated : Warning< + "dynamic exception specifications are deprecated">, + InGroup, DefaultIgnore; +def note_exception_spec_deprecated : Note<"use '%0' instead">; def warn_global_constructor : Warning< "declaration requires a global constructor">, diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index b3e8412dcf..8d96d6e6cc 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -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; diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index ae1ff37e6b..71ee3118c9 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -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; } diff --git a/test/CXX/class/class.friend/p6.cpp b/test/CXX/class/class.friend/p6.cpp index 82ca50e485..ae327391a9 100644 --- a/test/CXX/class/class.friend/p6.cpp +++ b/test/CXX/class/class.friend/p6.cpp @@ -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}} diff --git a/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp b/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp index b159a15b8d..c23cd28f31 100644 --- a/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp +++ b/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp @@ -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}} diff --git a/test/FixIt/fixit-cxx0x.cpp b/test/FixIt/fixit-cxx0x.cpp index 1f6275f933..bfd8c3dcfe 100644 --- a/test/FixIt/fixit-cxx0x.cpp +++ b/test/FixIt/fixit-cxx0x.cpp @@ -132,3 +132,8 @@ namespace NonStaticConstexpr { } }; } + +int RegisterVariable() { + register int n; // expected-warning {{'register' storage class specifier is deprecated}} + return n; +} diff --git a/test/Sema/thread-specifier.c b/test/Sema/thread-specifier.c index 9d516e8f14..bf1ce9e26e 100644 --- a/test/Sema/thread-specifier.c +++ b/test/Sema/thread-specifier.c @@ -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. diff --git a/test/SemaCXX/attr-cxx0x.cpp b/test/SemaCXX/attr-cxx0x.cpp index e9276cd2d9..fb46af4035 100644 --- a/test/SemaCXX/attr-cxx0x.cpp +++ b/test/SemaCXX/attr-cxx0x.cpp @@ -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 index 0000000000..fde2c3754c --- /dev/null +++ b/test/SemaCXX/deprecated.cpp @@ -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}} +}; -- 2.40.0