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.
Tested x86_64-linux. OK for trunk?
commit ed749dcee73bff55fc27231c15d2bae265ec86b3
Author: Jonathan Wakely <[email protected]>
Date: Wed May 19 17:07:32 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..8b8c685127d 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..794effffd1a 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..48e37ac5ea2 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..a2a06066b27 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%>");