+2019-11-15 Joseph Myers <joseph@codesourcery.com>
+
+ * c-attribs.c (handle_deprecated_attribute): Remove static.
+ * c-common.h (handle_deprecated_attribute): Declare.
+
2019-11-14 Joseph Myers <joseph@codesourcery.com>
* c-lex.c (lex_charconst): Make CPP_UTF8CHAR constants unsigned
static tree handle_tm_attribute (tree *, tree, tree, int, bool *);
static tree handle_tm_wrap_attribute (tree *, tree, tree, int, bool *);
static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
-static tree handle_deprecated_attribute (tree *, tree, tree, int,
- bool *);
static tree handle_vector_size_attribute (tree *, tree, tree, int,
bool *);
static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
/* Handle a "deprecated" attribute; arguments as in
struct attribute_spec.handler. */
-static tree
+tree
handle_deprecated_attribute (tree *node, tree name,
tree args, int flags,
bool *no_add_attrs)
/* In c-attribs.c. */
extern bool attribute_takes_identifier_p (const_tree);
+extern tree handle_deprecated_attribute (tree *, tree, tree, int, bool *);
extern tree handle_unused_attribute (tree *, tree, tree, int, bool *);
extern int parse_tm_stmt_attr (tree, int);
extern int tm_attr_to_mask (tree);
+2019-11-15 Joseph Myers <joseph@codesourcery.com>
+
+ * c-decl.c (std_attribute_table): New.
+ (c_init_decl_processing): Register attributes from
+ std_attribute_table.
+ * c-parser.c (c_parser_attribute_arguments): Add arguments
+ require_string and allow_empty_args. All callers changed.
+ (c_parser_std_attribute): Set require_string argument for
+ "deprecated" attribute.
+
2019-11-14 Joseph Myers <joseph@codesourcery.com>
* c-parser.c (c_parser_postfix_expression)
}
\f
+/* Table of supported standard (C2x) attributes. */
+const struct attribute_spec std_attribute_table[] =
+{
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+ affects_type_identity, handler, exclude } */
+ { "deprecated", 0, 1, false, false, false, false,
+ handle_deprecated_attribute, NULL },
+ { NULL, 0, 0, false, false, false, false, NULL, NULL }
+};
+
/* Create the predefined scalar types of C,
and some nodes representing standard constants (0, 1, (void *) 0).
Initialize the global scope.
/* Initialize reserved words for parser. */
c_parse_init ();
+ register_scoped_attributes (std_attribute_table, NULL);
+
current_function_decl = NULL_TREE;
gcc_obstack_init (&parser_obstack);
allow identifiers declared as types to start the arguments? */
static tree
-c_parser_attribute_arguments (c_parser *parser, bool takes_identifier)
+c_parser_attribute_arguments (c_parser *parser, bool takes_identifier,
+ bool require_string, bool allow_empty_args)
{
vec<tree, va_gc> *expr_list;
tree attr_args;
else
{
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- attr_args = NULL_TREE;
+ {
+ if (!allow_empty_args)
+ error_at (c_parser_peek_token (parser)->location,
+ "parentheses must be omitted if "
+ "attribute argument list is empty");
+ attr_args = NULL_TREE;
+ }
+ else if (require_string)
+ {
+ /* The only valid argument for this attribute is a string
+ literal. Handle this specially here to avoid accepting
+ string literals with excess parentheses. */
+ tree string = c_parser_string_literal (parser, false, true).value;
+ attr_args = build_tree_list (NULL_TREE, string);
+ }
else
{
expr_list = c_parser_expr_list (parser, false, true,
tree attr_args
= c_parser_attribute_arguments (parser,
- attribute_takes_identifier_p (attr_name));
+ attribute_takes_identifier_p (attr_name),
+ false, true);
attr = build_tree_list (attr_name, attr_args);
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
= (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);
+ = c_parser_attribute_arguments (parser, takes_identifier,
+ require_string, false);
}
else
c_parser_balanced_token_sequence (parser);
+2019-11-15 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/c2x-attr-deprecated-1.c, gcc.dg/c2x-attr-deprecated-2.c,
+ gcc.dg/c2x-attr-deprecated-3.c: New tests.
+
2019-11-14 Joseph Myers <joseph@codesourcery.com>
* gcc.dg/c11-utf8char-1.c, gcc.dg/c2x-utf8char-1.c,
--- /dev/null
+/* Test C2x deprecated attribute: valid uses. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+/* Similar to tests from gnu2x-attrs-1.c, but using the standard
+ attribute instead of gnu::deprecated, and sometimes using
+ __deprecated__ or a string-literal argument. */
+
+[[deprecated]] void f1 (void);
+
+[[deprecated]] typedef int dep_int;
+
+dep_int dv; /* { dg-warning "deprecated" } */
+
+void
+g (void)
+{
+ f1 (); /* { dg-warning "deprecated" } */
+}
+
+int
+f2 (void)
+{
+ [[deprecated ("for this reason")]] int a = 1;
+ return a; /* { dg-warning "for this reason" } */
+}
+
+int
+f3 (void)
+{
+ int a [[__deprecated__]] = 1;
+ return a; /* { dg-warning "deprecated" } */
+}
+
+struct s2 { [[__deprecated__("some other message")]] int a; int b [[deprecated]]; } x;
+
+int
+f4 (void)
+{
+ return x.a; /* { dg-warning "some other message" } */
+}
+
+int
+f5 (void)
+{
+ return x.b; /* { dg-warning "deprecated" } */
+}
+
+enum e { E1 [[deprecated("third message")]] };
+
+enum e
+f6 (void)
+{
+ return E1; /* { dg-warning "third message" } */
+}
+
+int
+f7 ([[deprecated]] int y)
+{
+ return y; /* { dg-warning "deprecated" } */
+}
+
+union [[__deprecated__]] u { int x; };
+
+void
+f8 (void)
+{
+ union u var; /* { dg-warning "deprecated" } */
+}
+
+enum [[deprecated("edep reason")]] edep { E2 };
+
+void
+f9 (void)
+{
+ enum edep var; /* { dg-warning "edep reason" } */
+}
+
+union u2 { [[__deprecated__]] int a; int b [[deprecated]]; } y;
+
+int
+f10 (void)
+{
+ return y.a; /* { dg-warning "deprecated" } */
+}
+
+int
+f11 (void)
+{
+ return y.b; /* { dg-warning "deprecated" } */
+}
--- /dev/null
+/* Test C2x deprecated attribute: invalid contexts. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+/* 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" } */
+
+int [[deprecated]] var; /* { dg-warning "ignored" } */
+/* { dg-message "that appertains to a type-specifier" "appertains" { target *-*-* } .-1 } */
+
+int array_with_dep_type[2] [[deprecated]]; /* { dg-warning "ignored" } */
+/* { dg-message "that appertains to a type-specifier" "appertains" { target *-*-* } .-1 } */
+
+void fn_with_dep_type () [[deprecated]]; /* { dg-warning "ignored" } */
+/* { dg-message "that appertains to a type-specifier" "appertains" { target *-*-* } .-1 } */
+
+void
+f (void)
+{
+ int a;
+ [[deprecated]]; /* { dg-warning "ignored" } */
+ [[deprecated]] a = 1; /* { dg-warning "ignored" } */
+}
--- /dev/null
+/* Test C2x deprecated attribute: invalid syntax. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+[[deprecated()]] int a; /* { dg-error "parentheses must be omitted if attribute argument list is empty" } */
+
+[[deprecated(0)]] int b; /* { dg-error "expected" } */
+
+[[deprecated("", 123)]] int c; /* { dg-error "expected" } */
+
+[[deprecated((""))]] int d; /* { dg-error "expected" } */