Jakub pointed out I'd forgotten the spaces before the opening parens for function calls. The attached patch should fix all those, with no other changes.
Tested x86_64-linux. OK for trunk?
commit a7dc19cdc0c5d3762bb90d12ebd82a05d0013246 Author: Jonathan Wakely <jwak...@redhat.com> Date: Wed May 19 17:37:00 2021 c++: Add new warning options for C++ language mismatches This adds new warning flags, enabled by default: -Wc++11-extensions, -Wc++14-extensions, -Wc++17-extensions, and -Wc++20-extensions. The names of the flags are copied from Clang, which already has similar options. No new diagnostics are added, but the new OPT_Wxxx variables are used to control existing pedwarns about occurences of new C++ constructs in code using an old C++ standard dialect. This allows several existing warnings that cannot currently be disabled to be controlled by the appropriate -Wno-xxx flag. For example, it will now be possible to disable warnings about using variadic templates in C++98 code, by using the new -Wno-c++11-extensions option. This will allow libstdc++ headers to disable those warnings unconditionally by using diagnostic pragmas, so that they are not emitted even if -Wsystem-headers is used. Some of the affected diagnostics are currently only given when -Wpedantic is used. Now that we have a more specific warning flag, we could consider making them not depend on -Wpedantic, and only on the new flag. This patch does not do that, as it intends to make no changes to what is accepted/rejected by default. The only effect should be that the new option is shown when -fdiagnostics-show-option is active, and that some warnings can be disabled by using the new flags (and for the warnings that previously only dependend on -Wpedantic, it will now be possible to disable just those warnings while still using -Wpedantic for its other benefits). A new helper function, warn_about_dialect_p, is introduced to avoid the repetition of `if (cxx_dialect < cxxNN && warn_cxxNN_extensions)` everywhere. gcc/c-family/ChangeLog: * c.opt (Wc++11-extensions, Wc++14-extensions) (Wc++17-extensions, Wc++20-extensions): New options. gcc/cp/ChangeLog: * call.c (maybe_warn_array_conv): Use new function and option. * cp-tree.h (warn_about_dialect_p): Declare new function. * error.c (maybe_warn_cpp0x): Use new function and options. (warn_about_dialect_p): Define new function. * parser.c (cp_parser_unqualified_id): Use new function and option. (cp_parser_pseudo_destructor_name): Likewise. (cp_parser_lambda_introducer): Likewise. (cp_parser_lambda_declarator_opt): Likewise. (cp_parser_init_statement): Likewise. (cp_parser_decomposition_declaration): Likewise. (cp_parser_function_specifier_opt): Likewise. (cp_parser_static_assert): Likewise. (cp_parser_namespace_definition): Likewise. (cp_parser_initializer_list): Likewise. (cp_parser_member_declaration): Likewise. * pt.c (check_template_variable): Likewise. diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 5fcf961fd96..a7605cf3a38 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -431,6 +431,22 @@ Wc++20-compat C++ ObjC++ Var(warn_cxx20_compat) Warning LangEnabledBy(C++ ObjC++,Wall) Warn about C++ constructs whose meaning differs between ISO C++ 2017 and ISO C++ 2020. +Wc++11-extensions +C++ ObjC++ Var(warn_cxx11_extensions) Warning LangEnabledBy(C++ ObjC++,Wall) Init(1) +Warn about C++11 constructs in code compiled with an older standard. + +Wc++14-extensions +C++ ObjC++ Var(warn_cxx14_extensions) Warning LangEnabledBy(C++ ObjC++,Wall) Init(1) +Warn about C++14 constructs in code compiled with an older standard. + +Wc++17-extensions +C++ ObjC++ Var(warn_cxx17_extensions) Warning LangEnabledBy(C++ ObjC++,Wall) Init(1) +Warn about C++17 constructs in code compiled with an older standard. + +Wc++20-extensions +C++ ObjC++ Var(warn_cxx20_extensions) Warning LangEnabledBy(C++ ObjC++,Wall) Init(1) +Warn about C++20 constructs in code compiled with an older standard. + Wcast-function-type C ObjC C++ ObjC++ Var(warn_cast_function_type) Warning EnabledBy(Wextra) Warn about casts between incompatible function types. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 1e2d1d43184..5134d10bb24 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -7464,8 +7464,10 @@ maybe_warn_array_conv (location_t loc, conversion *c, tree expr) || TYPE_DOMAIN (type) == NULL_TREE) return; - if (conv_binds_to_array_of_unknown_bound (c)) - pedwarn (loc, OPT_Wpedantic, "conversions to arrays of unknown bound " + if (conv_binds_to_array_of_unknown_bound (c) + && pedantic && warn_about_dialect_p (cxx20)) + pedwarn (loc, OPT_Wc__20_extensions, + "conversions to arrays of unknown bound " "are only available with %<-std=c++20%> or %<-std=gnu++20%>"); } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 580db914d40..f0cf5552437 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6821,6 +6821,7 @@ extern const char *language_to_string (enum languages); extern const char *class_key_or_enum_as_string (tree); extern void maybe_warn_variadic_templates (void); extern void maybe_warn_cpp0x (cpp0x_warn_str str); +extern bool warn_about_dialect_p (enum cxx_dialect); extern bool pedwarn_cxx98 (location_t, int, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4); extern location_t location_of (tree); extern void qualified_name_lookup_error (tree, tree, tree, diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 3c2276b1976..99689b229b4 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -4403,81 +4403,82 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec, void maybe_warn_cpp0x (cpp0x_warn_str str) { - if (cxx_dialect == cxx98) + if (warn_about_dialect_p (cxx11)) switch (str) { case CPP0X_INITIALIZER_LISTS: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "extended initializer lists " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_EXPLICIT_CONVERSION: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "explicit conversion operators " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_VARIADIC_TEMPLATES: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "variadic templates " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_LAMBDA_EXPR: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "lambda expressions " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_AUTO: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "C++11 auto only available with %<-std=c++11%> or " "%<-std=gnu++11%>"); break; case CPP0X_SCOPED_ENUMS: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "scoped enums only available with %<-std=c++11%> or " "%<-std=gnu++11%>"); break; case CPP0X_DEFAULTED_DELETED: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "defaulted and deleted functions " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_INLINE_NAMESPACES: - pedwarn (input_location, OPT_Wpedantic, - "inline namespaces " - "only available with %<-std=c++11%> or %<-std=gnu++11%>"); + if (pedantic) + pedwarn (input_location, OPT_Wc__11_extensions, + "inline namespaces " + "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_OVERRIDE_CONTROLS: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "override controls (override/final) " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_NSDMI: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "non-static data member initializers " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_USER_DEFINED_LITERALS: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "user-defined literals " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_DELEGATING_CTORS: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "delegating constructors " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_INHERITING_CTORS: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "inheriting constructors " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_ATTRIBUTES: - pedwarn (input_location, 0, - "c++11 attributes " + pedwarn (input_location, OPT_Wc__11_extensions, + "C++11 attributes " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; case CPP0X_REF_QUALIFIER: - pedwarn (input_location, 0, + pedwarn (input_location, OPT_Wc__11_extensions, "ref-qualifiers " "only available with %<-std=c++11%> or %<-std=gnu++11%>"); break; @@ -4493,6 +4494,27 @@ maybe_warn_variadic_templates (void) maybe_warn_cpp0x (CPP0X_VARIADIC_TEMPLATES); } +/* Whether to warn about constructs from C++ standard DIALECT. */ +bool +warn_about_dialect_p (enum cxx_dialect dialect) +{ + if (cxx_dialect >= dialect) + return false; + + switch (dialect) + { + case cxx11: + return warn_cxx11_extensions; + case cxx14: + return warn_cxx14_extensions; + case cxx17: + return warn_cxx17_extensions; + case cxx20: + return warn_cxx20_extensions; + default: + gcc_unreachable (); + } +} /* Issue an ISO C++98 pedantic warning at LOCATION, conditional on option OPT with text GMSGID. Use this function to report diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index c0b57955954..3652649c6c6 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -6324,8 +6324,8 @@ cp_parser_unqualified_id (cp_parser* parser, /* ~auto means the destructor of whatever the object is. */ if (cp_parser_is_keyword (token, RID_AUTO)) { - if (cxx_dialect < cxx14) - pedwarn (loc, 0, + if (warn_about_dialect_p (cxx14)) + pedwarn (loc, OPT_Wc__14_extensions, "%<~auto%> only available with " "%<-std=c++14%> or %<-std=gnu++14%>"); cp_lexer_consume_token (parser->lexer); @@ -8352,8 +8352,8 @@ cp_parser_pseudo_destructor_name (cp_parser* parser, && cp_lexer_nth_token_is_keyword (parser->lexer, 2, RID_AUTO) && !type_dependent_expression_p (object)) { - if (cxx_dialect < cxx14) - pedwarn (input_location, 0, + if (warn_about_dialect_p (cxx14)) + pedwarn (input_location, OPT_Wc__14_extensions, "%<~auto%> only available with " "%<-std=c++14%> or %<-std=gnu++14%>"); cp_lexer_consume_token (parser->lexer); @@ -11041,9 +11041,10 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) && cp_lexer_nth_token_is_keyword (parser->lexer, 2, RID_THIS)) { location_t loc = cp_lexer_peek_token (parser->lexer)->location; - if (cxx_dialect < cxx17) - pedwarn (loc, 0, "%<*this%> capture only available with " - "%<-std=c++17%> or %<-std=gnu++17%>"); + if (warn_about_dialect_p (cxx17)) + pedwarn (loc, OPT_Wc__17_extensions, + "%<*this%> capture only available with " + "%<-std=c++17%> or %<-std=gnu++17%>"); cp_lexer_consume_token (parser->lexer); cp_lexer_consume_token (parser->lexer); if (LAMBDA_EXPR_THIS_CAPTURE (lambda_expr)) @@ -11080,8 +11081,9 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)) { ellipsis_loc = cp_lexer_peek_token (parser->lexer)->location; - if (cxx_dialect < cxx20) - pedwarn (ellipsis_loc, 0, "pack init-capture only available with " + if (warn_about_dialect_p (cxx20)) + pedwarn (ellipsis_loc, OPT_Wc__20_extensions, + "pack init-capture only available with " "%<-std=c++20%> or %<-std=gnu++20%>"); cp_lexer_consume_token (parser->lexer); init_pack_expansion = true; @@ -11121,8 +11123,8 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) { bool direct, non_constant; /* An explicit initializer exists. */ - if (cxx_dialect < cxx14) - pedwarn (input_location, 0, + if (warn_about_dialect_p (cxx14)) + pedwarn (input_location, OPT_Wc__14_extensions, "lambda capture initializers " "only available with %<-std=c++14%> or %<-std=gnu++14%>"); capture_init_expr = cp_parser_initializer (parser, &direct, @@ -11295,12 +11297,12 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) an opening angle if present. */ if (cp_lexer_next_token_is (parser->lexer, CPP_LESS)) { - if (cxx_dialect < cxx14) - pedwarn (parser->lexer->next_token->location, 0, + if (warn_about_dialect_p (cxx14)) + pedwarn (parser->lexer->next_token->location, OPT_Wc__14_extensions, "lambda templates are only available with " "%<-std=c++14%> or %<-std=gnu++14%>"); - else if (cxx_dialect < cxx20) - pedwarn (parser->lexer->next_token->location, OPT_Wpedantic, + else if (pedantic && warn_about_dialect_p (cxx20)) + pedwarn (parser->lexer->next_token->location, OPT_Wc__20_extensions, "lambda templates are only available with " "%<-std=c++20%> or %<-std=gnu++20%>"); @@ -13421,8 +13423,9 @@ cp_parser_init_statement (cp_parser *parser, tree *decl) /* It is a range-for, consume the ':'. */ cp_lexer_consume_token (parser->lexer); is_range_for = true; - if (cxx_dialect < cxx11) - pedwarn (cp_lexer_peek_token (parser->lexer)->location, 0, + if (warn_about_dialect_p (cxx11)) + pedwarn (cp_lexer_peek_token (parser->lexer)->location, + OPT_Wc__11_extensions, "range-based %<for%> loops only available with " "%<-std=c++11%> or %<-std=gnu++11%>"); } @@ -14664,9 +14667,10 @@ cp_parser_decomposition_declaration (cp_parser *parser, } } - if (cxx_dialect < cxx17) - pedwarn (loc, 0, "structured bindings only available with " - "%<-std=c++17%> or %<-std=gnu++17%>"); + if (warn_about_dialect_p (cxx17)) + pedwarn (loc, OPT_Wc__17_extensions, + "structured bindings only available with " + "%<-std=c++17%> or %<-std=gnu++17%>"); tree pushed_scope; cp_declarator *declarator = make_declarator (cdk_decomp); @@ -15260,8 +15264,8 @@ cp_parser_function_specifier_opt (cp_parser* parser, parser->type_definition_forbidden_message = G_("types may not be defined in explicit-specifier"); - if (cxx_dialect < cxx20) - pedwarn (token->location, 0, + if (warn_about_dialect_p (cxx20)) + pedwarn (token->location, OPT_Wc__20_extensions, "%<explicit(bool)%> only available with %<-std=c++20%> " "or %<-std=gnu++20%>"); @@ -15428,8 +15432,8 @@ cp_parser_static_assert(cp_parser *parser, bool member_p) if (cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN) { - if (cxx_dialect < cxx17) - pedwarn (input_location, OPT_Wpedantic, + if (pedantic && warn_about_dialect_p (cxx17)) + pedwarn (input_location, OPT_Wc__17_extensions, "%<static_assert%> without a message " "only available with %<-std=c++17%> or %<-std=gnu++17%>"); /* Eat the ')' */ @@ -20445,8 +20449,8 @@ cp_parser_namespace_definition (cp_parser* parser) break; } - if (!nested_definition_count && cxx_dialect < cxx17) - pedwarn (input_location, OPT_Wpedantic, + if (!nested_definition_count && pedantic && warn_about_dialect_p (cxx17)) + pedwarn (input_location, OPT_Wc__17_extensions, "nested namespace definitions only available with " "%<-std=c++17%> or %<-std=gnu++17%>"); @@ -24455,8 +24459,8 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p, || (cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_OPEN_BRACE))) { - if (cxx_dialect < cxx20) - pedwarn (loc, OPT_Wpedantic, + if (pedantic && warn_about_dialect_p (cxx20)) + pedwarn (loc, OPT_Wc__20_extensions, "C++ designated initializers only available with " "%<-std=c++20%> or %<-std=gnu++20%>"); /* Consume the `.'. */ @@ -26186,9 +26190,9 @@ cp_parser_member_declaration (cp_parser* parser) { location_t loc = cp_lexer_peek_token (parser->lexer)->location; - if (cxx_dialect < cxx20 + if (warn_about_dialect_p (cxx20) && identifier != NULL_TREE) - pedwarn (loc, 0, + pedwarn (loc, OPT_Wc__20_extensions, "default member initializers for bit-fields " "only available with %<-std=c++20%> or " "%<-std=gnu++20%>"); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index bf996358328..6b7a0419154 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -2702,8 +2702,8 @@ check_template_variable (tree decl) if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl) && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl))) { - if (cxx_dialect < cxx14) - pedwarn (DECL_SOURCE_LOCATION (decl), 0, + if (warn_about_dialect_p (cxx14)) + pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wc__14_extensions, "variable templates only available with " "%<-std=c++14%> or %<-std=gnu++14%>");