diff options
-rw-r--r-- | gcc/c-family/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/c-family/c-attribs.c | 4 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 1 | ||||
-rw-r--r-- | gcc/c/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/c/c-decl.c | 12 | ||||
-rw-r--r-- | gcc/c/c-parser.c | 28 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c2x-attr-deprecated-1.c | 91 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c2x-attr-deprecated-2.c | 25 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c | 11 |
10 files changed, 185 insertions, 7 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index f4fdccc..571cf2b 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,8 @@ +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 diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index c62cebf..18b829f 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -115,8 +115,6 @@ static tree handle_pure_attribute (tree *, tree, tree, int, bool *); 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 *); @@ -3468,7 +3466,7 @@ handle_novops_attribute (tree *node, tree ARG_UNUSED (name), /* 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) diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 80a8c9f..ad40c15 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1357,6 +1357,7 @@ extern void warn_for_multistatement_macros (location_t, location_t, /* 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); diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index b881cab..fdc9153 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,13 @@ +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) diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index f809059..a7f7c69 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -4336,6 +4336,16 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind, location_t loc) } +/* 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. @@ -4349,6 +4359,8 @@ c_init_decl_processing (void) /* 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); diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 8ce4e70..721158a 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -4478,7 +4478,8 @@ c_parser_gnu_attribute_any_word (c_parser *parser) 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; @@ -4518,7 +4519,21 @@ c_parser_attribute_arguments (c_parser *parser, bool takes_identifier) 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, @@ -4601,7 +4616,8 @@ c_parser_gnu_attribute (c_parser *parser, tree attrs, 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)) @@ -4835,8 +4851,12 @@ c_parser_std_attribute (c_parser *parser) = (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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 51624b7..17494d0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +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, diff --git a/gcc/testsuite/gcc.dg/c2x-attr-deprecated-1.c b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-1.c new file mode 100644 index 0000000..de0ae51 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-1.c @@ -0,0 +1,91 @@ +/* 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" } */ +} diff --git a/gcc/testsuite/gcc.dg/c2x-attr-deprecated-2.c b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-2.c new file mode 100644 index 0000000..2d47606 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-2.c @@ -0,0 +1,25 @@ +/* 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" } */ +} diff --git a/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c new file mode 100644 index 0000000..044725e --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c @@ -0,0 +1,11 @@ +/* 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" } */ |