Commit 192961ff by Joseph Myers Committed by Joseph Myers

Change some bad uses of C2x attributes into pedwarns.

Certain bad uses of C2x standard attributes (that is, attributes
inside [[]] with only a name but no namespace specified) are
constraint violations, and so should be diagnosed with a pedwarn (or
error) where GCC currently uses a warning.  This patch implements this
in some cases (not yet for attributes used on types, nor for some bad
uses of fallthrough attributes).  Specifically, this applies to
unknown standard attributes (taking care not to pedwarn for nodiscard,
which is known but not implemented for C), and to all currently
implemented standard attributes in attribute declarations (including
when mixed with fallthrough) and on statements.

Bootstrapped with no regressions on x86_64-pc-linux-gnu.

gcc/c:
	* c-decl.c (c_warn_unused_attributes): Use pedwarn not warning for
	standard attributes.
	* c-parser.c (c_parser_std_attribute): Take argument for_tm.  Use
	pedwarn for unknown standard attributes and return error_mark_node
	for them.

gcc/c-family:
	* c-common.c (attribute_fallthrough_p): In C, use pedwarn not
	warning for standard attributes mixed with fallthrough attributes.

gcc/testsuite:
	* gcc.dg/c2x-attr-fallthrough-5.c, gcc.dg/c2x-attr-syntax-5.c: New
	tests.
	* gcc.dg/c2x-attr-deprecated-2.c, gcc.dg/c2x-attr-deprecated-4.c,
	gcc.dg/c2x-attr-fallthrough-2.c, gcc.dg/c2x-attr-maybe_unused-2.c,
	gcc.dg/c2x-attr-maybe_unused-4.c: Expect errors in place of some
	warnings.

From-SVN: r278428
parent 95d4434f
2019-11-19 Joseph Myers <joseph@codesourcery.com>
* c-common.c (attribute_fallthrough_p): In C, use pedwarn not
warning for standard attributes mixed with fallthrough attributes.
2019-11-15 Joseph Myers <joseph@codesourcery.com> 2019-11-15 Joseph Myers <joseph@codesourcery.com>
* c-attribs.c (handle_fallthrough_attribute): Remove static. * c-attribs.c (handle_fallthrough_attribute): Remove static.
......
...@@ -5702,7 +5702,15 @@ attribute_fallthrough_p (tree attr) ...@@ -5702,7 +5702,15 @@ attribute_fallthrough_p (tree attr)
{ {
tree name = get_attribute_name (t); tree name = get_attribute_name (t);
if (!is_attribute_p ("fallthrough", name)) if (!is_attribute_p ("fallthrough", name))
warning (OPT_Wattributes, "%qE attribute ignored", name); {
if (!c_dialect_cxx () && get_attribute_namespace (t) == NULL_TREE)
/* The specifications of standard attributes in C mean
this is a constraint violation. */
pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored",
get_attribute_name (t));
else
warning (OPT_Wattributes, "%qE attribute ignored", name);
}
} }
return true; return true;
} }
......
2019-11-19 Joseph Myers <joseph@codesourcery.com>
* c-decl.c (c_warn_unused_attributes): Use pedwarn not warning for
standard attributes.
* c-parser.c (c_parser_std_attribute): Take argument for_tm. Use
pedwarn for unknown standard attributes and return error_mark_node
for them.
2019-11-18 Matthew Malcomson <matthew.malcomson@arm.com> 2019-11-18 Matthew Malcomson <matthew.malcomson@arm.com>
* c-parser.c (c_parser_parse_rtl_body): Always call * c-parser.c (c_parser_parse_rtl_body): Always call
......
...@@ -4516,8 +4516,14 @@ void ...@@ -4516,8 +4516,14 @@ void
c_warn_unused_attributes (tree attrs) c_warn_unused_attributes (tree attrs)
{ {
for (tree t = attrs; t != NULL_TREE; t = TREE_CHAIN (t)) for (tree t = attrs; t != NULL_TREE; t = TREE_CHAIN (t))
warning (OPT_Wattributes, "%qE attribute ignored", if (get_attribute_namespace (t) == NULL_TREE)
get_attribute_name (t)); /* The specifications of standard attributes mean this is a
constraint violation. */
pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored",
get_attribute_name (t));
else
warning (OPT_Wattributes, "%qE attribute ignored",
get_attribute_name (t));
} }
/* Called when a declaration is seen that contains no names to declare. /* Called when a declaration is seen that contains no names to declare.
......
...@@ -4803,7 +4803,7 @@ c_parser_balanced_token_sequence (c_parser *parser) ...@@ -4803,7 +4803,7 @@ c_parser_balanced_token_sequence (c_parser *parser)
*/ */
static tree static tree
c_parser_std_attribute (c_parser *parser) c_parser_std_attribute (c_parser *parser, bool for_tm)
{ {
c_token *token = c_parser_peek_token (parser); c_token *token = c_parser_peek_token (parser);
tree ns, name, attribute; tree ns, name, attribute;
...@@ -4834,39 +4834,53 @@ c_parser_std_attribute (c_parser *parser) ...@@ -4834,39 +4834,53 @@ c_parser_std_attribute (c_parser *parser)
attribute = build_tree_list (build_tree_list (ns, name), NULL_TREE); attribute = build_tree_list (build_tree_list (ns, name), NULL_TREE);
/* Parse the arguments, if any. */ /* Parse the arguments, if any. */
if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
return attribute;
location_t open_loc = c_parser_peek_token (parser)->location;
matching_parens parens;
parens.consume_open (parser);
const attribute_spec *as = lookup_attribute_spec (TREE_PURPOSE (attribute)); const attribute_spec *as = lookup_attribute_spec (TREE_PURPOSE (attribute));
if ((as && as->max_length == 0) if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
/* Special-case the transactional-memory attribute "outer", goto out;
which is specially handled but not registered as an {
attribute, to avoid allowing arbitrary balanced token location_t open_loc = c_parser_peek_token (parser)->location;
sequences as arguments. */ matching_parens parens;
|| is_attribute_p ("outer", name)) parens.consume_open (parser);
{ if ((as && as->max_length == 0)
error_at (open_loc, "%qE attribute does not take any arguments", name); /* Special-case the transactional-memory attribute "outer",
parens.skip_until_found_close (parser); which is specially handled but not registered as an
attribute, to avoid allowing arbitrary balanced token
sequences as arguments. */
|| is_attribute_p ("outer", name))
{
error_at (open_loc, "%qE attribute does not take any arguments", name);
parens.skip_until_found_close (parser);
return error_mark_node;
}
if (as)
{
bool takes_identifier
= (ns != NULL_TREE
&& strcmp (IDENTIFIER_POINTER (ns), "gnu") == 0
&& attribute_takes_identifier_p (name));
bool require_string
= (ns == NULL_TREE
&& strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0);
TREE_VALUE (attribute)
= c_parser_attribute_arguments (parser, takes_identifier,
require_string, false);
}
else
c_parser_balanced_token_sequence (parser);
parens.require_close (parser);
}
out:
if (ns == NULL_TREE && !for_tm && !as && !is_attribute_p ("nodiscard", name))
{
/* An attribute with standard syntax and no namespace specified
is a constraint violation if it is not one of the known
standard attributes (of which nodiscard is the only one
without a handler in GCC). Diagnose it here with a pedwarn
and then discard it to prevent a duplicate warning later. */
pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored",
name);
return error_mark_node; return error_mark_node;
} }
if (as)
{
bool takes_identifier
= (ns != NULL_TREE
&& strcmp (IDENTIFIER_POINTER (ns), "gnu") == 0
&& attribute_takes_identifier_p (name));
bool require_string
= (ns == NULL_TREE
&& strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0);
TREE_VALUE (attribute)
= c_parser_attribute_arguments (parser, takes_identifier,
require_string, false);
}
else
c_parser_balanced_token_sequence (parser);
parens.require_close (parser);
return attribute; return attribute;
} }
...@@ -4898,7 +4912,7 @@ c_parser_std_attribute_specifier (c_parser *parser, bool for_tm) ...@@ -4898,7 +4912,7 @@ c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
c_parser_consume_token (parser); c_parser_consume_token (parser);
continue; continue;
} }
tree attribute = c_parser_std_attribute (parser); tree attribute = c_parser_std_attribute (parser, for_tm);
if (attribute != error_mark_node) if (attribute != error_mark_node)
{ {
bool duplicate = false; bool duplicate = false;
......
2019-11-19 Joseph Myers <joseph@codesourcery.com>
* gcc.dg/c2x-attr-fallthrough-5.c, gcc.dg/c2x-attr-syntax-5.c: New
tests.
* gcc.dg/c2x-attr-deprecated-2.c, gcc.dg/c2x-attr-deprecated-4.c,
gcc.dg/c2x-attr-fallthrough-2.c, gcc.dg/c2x-attr-maybe_unused-2.c,
gcc.dg/c2x-attr-maybe_unused-4.c: Expect errors in place of some
warnings.
2019-11-18 Paolo Carlini <paolo.carlini@oracle.com> 2019-11-18 Paolo Carlini <paolo.carlini@oracle.com>
* g++.dg/cpp0x/addressof2.C: Test locations too. * g++.dg/cpp0x/addressof2.C: Test locations too.
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
/* This attribute is not valid in most cases on types other than their /* This attribute is not valid in most cases on types other than their
definitions, or on statements, or as an attribute-declaration. */ definitions, or on statements, or as an attribute-declaration. */
[[deprecated]]; /* { dg-warning "ignored" } */ [[deprecated]]; /* { dg-error "ignored" } */
int [[deprecated]] var; /* { dg-warning "ignored" } */ int [[deprecated]] var; /* { dg-warning "ignored" } */
/* { dg-message "that appertains to a type-specifier" "appertains" { target *-*-* } .-1 } */ /* { dg-message "that appertains to a type-specifier" "appertains" { target *-*-* } .-1 } */
...@@ -20,6 +20,6 @@ void ...@@ -20,6 +20,6 @@ void
f (void) f (void)
{ {
int a; int a;
[[deprecated]]; /* { dg-warning "ignored" } */ [[deprecated]]; /* { dg-error "ignored" } */
[[deprecated]] a = 1; /* { dg-warning "ignored" } */ [[deprecated]] a = 1; /* { dg-error "ignored" } */
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
[[__deprecated__, deprecated("message")]] int b; /* { dg-error "can appear at most once" } */ [[__deprecated__, deprecated("message")]] int b; /* { dg-error "can appear at most once" } */
int c [[deprecated("message"), deprecated]]; /* { dg-error "can appear at most once" } */ int c [[deprecated("message"), deprecated]]; /* { dg-error "can appear at most once" } */
[[deprecated, deprecated]]; /* { dg-error "can appear at most once" } */ [[deprecated, deprecated]]; /* { dg-error "can appear at most once" } */
/* { dg-warning "ignored" "ignored" { target *-*-* } .-1 } */ /* { dg-error "ignored" "ignored" { target *-*-* } .-1 } */
/* Separate attribute lists in the same attribute specifier sequence, /* Separate attribute lists in the same attribute specifier sequence,
with the same attribute in them, are OK. */ with the same attribute in them, are OK. */
......
...@@ -31,5 +31,5 @@ f (int a) ...@@ -31,5 +31,5 @@ f (int a)
b += 5; b += 5;
break; break;
} }
[[fallthrough]] return b; /* { dg-warning "ignored" } */ [[fallthrough]] return b; /* { dg-error "ignored" } */
} }
/* Test C2x fallthrough attribute: mixtures with other attributes. */
/* { dg-do compile } */
/* { dg-options "-std=c2x -pedantic-errors" } */
/* Use of other standard attributes together with "fallthrough" goes
through a different path to diagnosing ignored attributes from that
used in attribute declarations without "fallthrough". Verify that
such ignored attributes result in a pedwarn (for use in a context
not permitted in the constraints for those attributes) in this case
as well. */
int
f (int a)
{
switch (a)
{
case 1:
a++;
[[fallthrough, deprecated]]; /* { dg-error "attribute ignored" } */
case 2:
a++;
[[maybe_unused]] [[fallthrough]]; /* { dg-error "attribute ignored" } */
case 3:
a++;
[[__nodiscard__, fallthrough]]; /* { dg-error "attribute ignored" } */
case 4:
a++;
}
return a;
}
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
/* This attribute is not valid in most cases on types other than their /* This attribute is not valid in most cases on types other than their
definitions, or on statements, or as an attribute-declaration. */ definitions, or on statements, or as an attribute-declaration. */
[[maybe_unused]]; /* { dg-warning "ignored" } */ [[maybe_unused]]; /* { dg-error "ignored" } */
int [[maybe_unused]] var; /* { dg-warning "ignored" } */ int [[maybe_unused]] var; /* { dg-warning "ignored" } */
/* { dg-message "that appertains to a type-specifier" "appertains" { target *-*-* } .-1 } */ /* { dg-message "that appertains to a type-specifier" "appertains" { target *-*-* } .-1 } */
...@@ -20,6 +20,6 @@ void ...@@ -20,6 +20,6 @@ void
f (void) f (void)
{ {
int a; int a;
[[maybe_unused]]; /* { dg-warning "ignored" } */ [[maybe_unused]]; /* { dg-error "ignored" } */
[[maybe_unused]] a = 1; /* { dg-warning "ignored" } */ [[maybe_unused]] a = 1; /* { dg-error "ignored" } */
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
[[__maybe_unused__, maybe_unused]] int b; /* { dg-error "can appear at most once" } */ [[__maybe_unused__, maybe_unused]] int b; /* { dg-error "can appear at most once" } */
int c [[maybe_unused, maybe_unused]]; /* { dg-error "can appear at most once" } */ int c [[maybe_unused, maybe_unused]]; /* { dg-error "can appear at most once" } */
[[maybe_unused, maybe_unused]]; /* { dg-error "can appear at most once" } */ [[maybe_unused, maybe_unused]]; /* { dg-error "can appear at most once" } */
/* { dg-warning "ignored" "ignored" { target *-*-* } .-1 } */ /* { dg-error "ignored" "ignored" { target *-*-* } .-1 } */
/* Separate attribute lists in the same attribute specifier sequence, /* Separate attribute lists in the same attribute specifier sequence,
with the same attribute in them, are OK. */ with the same attribute in them, are OK. */
......
/* Test C2x attribute syntax. Test unknown standard attributes
diagnosed with a pedwarn. */
/* { dg-do compile } */
/* { dg-options "-std=c2x -pedantic-errors" } */
[[unknown_attribute]]; /* { dg-error "attribute ignored" } */
[[unknown_attribute]] extern int a; /* { dg-error "attribute ignored" } */
extern int [[unknown_attribute(123)]] a; /* { dg-error "attribute ignored" } */
extern int a [[unknown_attribute("")]]; /* { dg-error "attribute ignored" } */
int f () [[unknown_attribute]]; /* { dg-error "attribute ignored" } */
int f (void) [[unknown_attribute(1)]]; /* { dg-error "attribute ignored" } */
int g ([[unknown_attribute]] int a); /* { dg-error "attribute ignored" } */
int g (int [[unknown_attribute]] a); /* { dg-error "attribute ignored" } */
int g (int a [[unknown_attribute]]); /* { dg-error "attribute ignored" } */
int g ([[unknown_attribute]] int); /* { dg-error "attribute ignored" } */
int g (int [[unknown_attribute]]); /* { dg-error "attribute ignored" } */
int g (int) [[unknown_attribute]]; /* { dg-error "attribute ignored" } */
int *[[unknown_attribute]] p; /* { dg-error "attribute ignored" } */
int b[3] [[unknown_attribute]]; /* { dg-error "attribute ignored" } */
int h (int () [[unknown_attribute]]); /* { dg-error "attribute ignored" } */
struct [[unknown_attribute]] s; /* { dg-error "attribute ignored" } */
union [[unknown_attribute]] u; /* { dg-error "attribute ignored" } */
struct [[unknown_attribute]] s2 { int a; }; /* { dg-error "attribute ignored" } */
union [[unknown_attribute(x)]] u2 { int a; }; /* { dg-error "attribute ignored" } */
struct s3 { [[unknown_attribute]] int a; }; /* { dg-error "attribute ignored" } */
struct s4 { int [[unknown_attribute]] a; }; /* { dg-error "attribute ignored" } */
union u3 { [[unknown_attribute]] int a; }; /* { dg-error "attribute ignored" } */
union u4 { int [[unknown_attribute]] a; }; /* { dg-error "attribute ignored" } */
int z = sizeof (int [[unknown_attribute]]); /* { dg-error "attribute ignored" } */
enum [[unknown_attribute]] { E1 }; /* { dg-error "attribute ignored" } */
enum { E2 [[unknown_attribute]] }; /* { dg-error "attribute ignored" } */
enum { E3 [[unknown_attribute]] = 4 }; /* { dg-error "attribute ignored" } */
void
func (void) [[unknown_attribute]] { /* { dg-error "attribute ignored" } */
[[unknown_attribute]] int var; /* { dg-error "attribute ignored" } */
[[unknown_attribute]] { } /* { dg-error "attribute ignored" } */
[[unknown_attribute(!)]]; /* { dg-error "attribute ignored" } */
[[unknown_attribute]] var = 1; /* { dg-error "attribute ignored" } */
[[unknown_attribute]] x: var = 2; /* { dg-error "attribute ignored" } */
for ([[unknown_attribute]] int zz = 1; zz < 10; zz++) ; /* { dg-error "attribute ignored" } */
}
/* nodiscard is not yet implemented, but is a standard attribute, so
its use is not a constraint violation and should only receive a
warning. */
[[nodiscard]] int ndfunc (void); /* { dg-warning "attribute directive ignored" } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment