From 841804baff6ea8ba1904a2ba81265aae1479e882 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 17 Oct 2011 23:06:20 +0000 Subject: [PATCH] Add -Wc++98-compat warnings for uses of the new keywords 'alignof', 'char16_t', 'char32_t', 'constexpr', 'decltype', 'noexcept', 'nullptr' and 'static_assert'. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142302 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticParseKinds.td | 15 +++++++++++++++ include/clang/Basic/DiagnosticSemaKinds.td | 11 +++++++++++ lib/Parse/ParseDeclCXX.cpp | 4 ++++ lib/Parse/ParseExpr.cpp | 7 ++++++- lib/Sema/DeclSpec.cpp | 8 ++++++++ test/SemaCXX/cxx98-compat.cpp | 10 ++++++++++ 6 files changed, 54 insertions(+), 1 deletion(-) diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 91220e4b5d..b1cb8935ff 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -71,6 +71,9 @@ def ext_ms_enum_fixed_underlying_type : Extension< def warn_cxx98_compat_enum_fixed_underlying_type : Warning< "enumeration types with a fixed underlying type are incompatible with C++98">, InGroup, DefaultIgnore; +def warn_cxx98_compat_alignof : Warning< + "alignof expressions are incompatible with C++98">, + InGroup, DefaultIgnore; def ext_c1x_generic_selection : Extension< "generic selections are a C1X-specific feature">, InGroup; @@ -290,6 +293,9 @@ def err_bool_redeclaration : Error< "redeclaration of C++ built-in type 'bool'">; def ext_c1x_static_assert : Extension< "_Static_assert is a C1X-specific feature">, InGroup; +def warn_cxx98_compat_static_assert : Warning< + "static_assert declarations are incompatible with C++98">, + InGroup, DefaultIgnore; /// Objective-C parser diagnostics def err_expected_minus_or_plus : Error< @@ -371,6 +377,9 @@ def ext_ellipsis_exception_spec : Extension< "exception specification of '...' is a Microsoft extension">; def err_dynamic_and_noexcept_specification : Error< "cannot have both throw() and noexcept() clause on the same function">; +def warn_cxx98_compat_noexcept_decl : Warning< + "noexcept specifications are incompatible with C++98">, + InGroup, DefaultIgnore; def err_expected_catch : Error<"expected catch">; def err_expected_lbrace_or_comma : Error<"expected '{' or ','">; def err_using_namespace_in_class : Error< @@ -401,6 +410,12 @@ def err_default_delete_in_multiple_declaration : Error< "'= %select{default|delete}0' is a function definition and must occur in a " "standalone declaration">; +def warn_cxx98_compat_noexcept_expr : Warning< + "noexcept expressions are incompatible with C++98">, + InGroup, DefaultIgnore; +def warn_cxx98_compat_nullptr : Warning< + "'nullptr' is incompatible with C++98">, InGroup, DefaultIgnore; + def warn_cxx98_compat_alignas : Warning<"'alignas' is incompatible with C++98">, InGroup, DefaultIgnore; def warn_cxx98_compat_attribute : Warning< diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 2b9cf406d2..f66019b76f 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1081,6 +1081,9 @@ def err_temp_copy_incomplete : Error< // C++11 decltype def err_cannot_determine_declared_type_of_overloaded_function : Error< "cannot determine the type of an overloaded function">; +def warn_cxx98_compat_decltype : Warning< + "'decltype' type specifier is incompatible with C++98">, + InGroup, DefaultIgnore; // C++11 auto def warn_cxx98_compat_auto_type_specifier : Warning< @@ -1194,6 +1197,9 @@ def note_for_range_begin_end : Note< "selected '%select{begin|end}0' %select{function|template }1%2 with iterator type %3">; // C++11 constexpr +def warn_cxx98_compat_constexpr : Warning< + "'constexpr' specifier is incompatible with C++98">, + InGroup, DefaultIgnore; def err_invalid_constexpr : Error< "%select{function parameter|typedef|non-static data member}0 " "cannot be constexpr">; @@ -1273,6 +1279,11 @@ def note_non_literal_nontrivial_dtor : Note< "%0 is not literal because it has a non-trivial destructor">; def note_non_literal_mutable_field : Note< "%0 is not literal because it has a mutable data member">; + +// C++11 char16_t/char32_t +def warn_cxx98_compat_unicode_type : Warning< + "'%0' type specifier is incompatible with C++98">, + InGroup, DefaultIgnore; // Objective-C++ def err_objc_decls_may_only_appear_in_global_scope : Error< diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 45562d908c..7583ccafeb 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -587,6 +587,8 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ if (Tok.is(tok::kw__Static_assert) && !getLang().C1X) Diag(Tok, diag::ext_c1x_static_assert); + if (Tok.is(tok::kw_static_assert)) + Diag(Tok, diag::warn_cxx98_compat_static_assert); SourceLocation StaticAssertLoc = ConsumeToken(); @@ -2401,6 +2403,8 @@ Parser::MaybeParseExceptionSpecification(SourceRange &SpecificationRange, if (Tok.isNot(tok::kw_noexcept)) return Result; + Diag(Tok, diag::warn_cxx98_compat_noexcept_decl); + // If we already had a dynamic specification, parse the noexcept for, // recovery, but emit a diagnostic and don't store the results. SourceRange NoexceptRange; diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index aa86bb4d71..83075ab5db 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -654,6 +654,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, return ParseCXXBoolLiteral(); case tok::kw_nullptr: + Diag(Tok, diag::warn_cxx98_compat_nullptr); return Actions.ActOnCXXNullPtrLiteral(ConsumeToken()); case tok::annot_primary_expr: @@ -1031,6 +1032,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, return ParseCXXDeleteExpression(false, Tok.getLocation()); case tok::kw_noexcept: { // [C++0x] 'noexcept' '(' expression ')' + Diag(Tok, diag::warn_cxx98_compat_noexcept_expr); SourceLocation KeyLoc = ConsumeToken(); BalancedDelimiterTracker T(*this, tok::l_paren); @@ -1537,7 +1539,10 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { *Name, NameLoc, RParenLoc); } - + + if (OpTok.is(tok::kw_alignof)) + Diag(OpTok, diag::warn_cxx98_compat_alignof); + bool isCastExpr; ParsedType CastTy; SourceRange CastRange; diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index f0a763e4ec..18ecf9ef52 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -15,6 +15,7 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/LocInfoType.h" #include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/SemaDiagnostic.h" #include "clang/Sema/Sema.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" @@ -889,6 +890,13 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) { StorageClassSpec == SCS_auto) Diag(D, StorageClassSpecLoc, diag::warn_auto_storage_class) << FixItHint::CreateRemoval(StorageClassSpecLoc); + if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32) + Diag(D, TSTLoc, diag::warn_cxx98_compat_unicode_type) + << (TypeSpecType == TST_char16 ? "char16_t" : "char32_t"); + if (TypeSpecType == TST_decltype) + Diag(D, TSTLoc, diag::warn_cxx98_compat_decltype); + if (Constexpr_specified) + Diag(D, ConstexprLoc, diag::warn_cxx98_compat_constexpr); // C++ [class.friend]p6: // No storage-class-specifier shall appear in the decl-specifier-seq diff --git a/test/SemaCXX/cxx98-compat.cpp b/test/SemaCXX/cxx98-compat.cpp index 927df1f971..a2e98e4743 100644 --- a/test/SemaCXX/cxx98-compat.cpp +++ b/test/SemaCXX/cxx98-compat.cpp @@ -90,3 +90,13 @@ inline namespace N { // expected-warning {{inline namespaces are incompatible wi auto auto_deduction = 0; // expected-warning {{'auto' type specifier is incompatible with C++98}} int *p = new auto(0); // expected-warning {{'auto' type specifier is incompatible with C++98}} + +const int align_of = alignof(int); // expected-warning {{alignof expressions are incompatible with C++98}} +char16_t c16 = 0; // expected-warning {{'char16_t' type specifier is incompatible with C++98}} +char32_t c32 = 0; // expected-warning {{'char32_t' type specifier is incompatible with C++98}} +constexpr int const_expr = 0; // expected-warning {{'constexpr' specifier is incompatible with C++98}} +decltype(const_expr) decl_type = 0; // expected-warning {{'decltype' type specifier is incompatible with C++98}} +void no_except() noexcept; // expected-warning {{noexcept specifications are incompatible with C++98}} +bool no_except_expr = noexcept(1 + 1); // expected-warning {{noexcept expressions are incompatible with C++98}} +void *null = nullptr; // expected-warning {{'nullptr' is incompatible with C++98}} +static_assert(true, "!"); // expected-warning {{static_assert declarations are incompatible with C++98}} -- 2.40.0