+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>
* c-attribs.c (handle_fallthrough_attribute): Remove static.
{
tree name = get_attribute_name (t);
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;
}
+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>
* c-parser.c (c_parser_parse_rtl_body): Always call
c_warn_unused_attributes (tree attrs)
{
for (tree t = attrs; t != NULL_TREE; t = TREE_CHAIN (t))
- warning (OPT_Wattributes, "%qE attribute ignored",
- get_attribute_name (t));
+ if (get_attribute_namespace (t) == NULL_TREE)
+ /* 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));
}
\f
/* Called when a declaration is seen that contains no names to declare.
*/
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);
tree ns, name, attribute;
attribute = build_tree_list (build_tree_list (ns, name), NULL_TREE);
/* 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));
- if ((as && as->max_length == 0)
- /* Special-case the transactional-memory attribute "outer",
- 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);
+ if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
+ goto out;
+ {
+ location_t open_loc = c_parser_peek_token (parser)->location;
+ matching_parens parens;
+ parens.consume_open (parser);
+ if ((as && as->max_length == 0)
+ /* Special-case the transactional-memory attribute "outer",
+ 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;
}
- 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;
}
c_parser_consume_token (parser);
continue;
}
- tree attribute = c_parser_std_attribute (parser);
+ tree attribute = c_parser_std_attribute (parser, for_tm);
if (attribute != error_mark_node)
{
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>
* g++.dg/cpp0x/addressof2.C: Test locations too.
/* This attribute is not valid in most cases on types other than their
definitions, or on statements, or as an attribute-declaration. */
-[[deprecated]]; /* { dg-warning "ignored" } */
+[[deprecated]]; /* { dg-error "ignored" } */
int [[deprecated]] var; /* { dg-warning "ignored" } */
/* { dg-message "that appertains to a type-specifier" "appertains" { target *-*-* } .-1 } */
f (void)
{
int a;
- [[deprecated]]; /* { dg-warning "ignored" } */
- [[deprecated]] a = 1; /* { dg-warning "ignored" } */
+ [[deprecated]]; /* { dg-error "ignored" } */
+ [[deprecated]] a = 1; /* { dg-error "ignored" } */
}
[[__deprecated__, deprecated("message")]] int b; /* { 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" } */
-/* { dg-warning "ignored" "ignored" { target *-*-* } .-1 } */
+/* { dg-error "ignored" "ignored" { target *-*-* } .-1 } */
/* Separate attribute lists in the same attribute specifier sequence,
with the same attribute in them, are OK. */
b += 5;
break;
}
- [[fallthrough]] return b; /* { dg-warning "ignored" } */
+ [[fallthrough]] return b; /* { dg-error "ignored" } */
}
--- /dev/null
+/* 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;
+}
/* This attribute is not valid in most cases on types other than their
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" } */
/* { dg-message "that appertains to a type-specifier" "appertains" { target *-*-* } .-1 } */
f (void)
{
int a;
- [[maybe_unused]]; /* { dg-warning "ignored" } */
- [[maybe_unused]] a = 1; /* { dg-warning "ignored" } */
+ [[maybe_unused]]; /* { dg-error "ignored" } */
+ [[maybe_unused]] a = 1; /* { dg-error "ignored" } */
}
[[__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" } */
[[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,
with the same attribute in them, are OK. */
--- /dev/null
+/* 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" } */