+2019-11-25 Joseph Myers <joseph@codesourcery.com>
+
+ * attribs.c (decl_attributes): Do not ignore C++11 attributes on
+ types.
+
2019-11-25 Bernd Schmidt <bernds_cb1@t-online.de>
* config/m68k/m68k.c (output_move_himode, output_move_qimode):
}
gcc_assert (is_attribute_p (spec->name, name));
- if (TYPE_P (*node)
- && cxx11_attr_p
- && !(flags & ATTR_FLAG_TYPE_IN_PLACE))
- {
- /* This is a c++11 attribute that appertains to a
- type-specifier, outside of the definition of, a class
- type. Ignore it. */
- auto_diagnostic_group d;
- if (warning (OPT_Wattributes, "attribute ignored"))
- inform (input_location,
- "an attribute that appertains to a type-specifier "
- "is ignored");
- continue;
- }
-
if (spec->decl_required && !DECL_P (*anode))
{
if (flags & ((int) ATTR_FLAG_DECL_NEXT
+2019-11-25 Joseph Myers <joseph@codesourcery.com>
+
+ * c-tree.h (struct c_declarator): Use a structure for id member.
+ * c-decl.c (grokdeclarator): Extract attributes from cdk_id
+ declarators at the start, not when handling individual declarators
+ later. Use u.id.id instead of u.id.
+ (grokfield): Use u.id.id instead of u.id.
+ (build_id_declarator): Set u.id.id and u.id.attrs.
+ (finish_declspecs): Handle postfix attributes in case of typedef
+ name or typeof used.
+ * c-parser.c (c_parser_direct_declarator)
+ (c_parser_direct_declarator_inner): Place declarator for
+ attributes inside that for function or array, not outside. Set
+ u.id.attrs for identifiers.
+ (c_parser_parameter_declaration): Use u.id.id instead of u.id.
+ * gimple-parser.c (c_parser_gimple_declaration): Use u.id.id
+ instead of u.id.
+
2019-11-22 Jakub Jelinek <jakub@redhat.com>
PR c/90677
bool array_parm_static = false;
bool array_parm_vla_unspec_p = false;
tree returned_attrs = NULL_TREE;
+ tree decl_id_attrs = NULL_TREE;
bool bitfield = width != NULL;
tree element_type;
tree orig_qual_type = NULL;
case cdk_id:
loc = decl->id_loc;
- if (decl->u.id)
- name = decl->u.id;
+ if (decl->u.id.id)
+ name = decl->u.id.id;
+ decl_id_attrs = decl->u.id.attrs;
if (first_non_attr_kind == cdk_attrs)
first_non_attr_kind = decl->kind;
decl = 0;
Standard attributes applied to a function or array
declarator apply exactly to that type; standard
attributes applied to the identifier apply to the
- declaration rather than to the type. */
+ declaration rather than to the type, and are specified
+ using a cdk_id declarator rather than using
+ cdk_attrs. */
inner_decl = declarator;
while (inner_decl->kind == cdk_attrs)
inner_decl = inner_decl->declarator;
else if (inner_decl->kind == cdk_array)
attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
}
- if (cxx11_attribute_p (attrs) && inner_decl->kind == cdk_id)
- returned_attrs = chainon (returned_attrs, attrs);
- else
- {
- attrs = c_warn_type_attributes (attrs);
- returned_attrs = decl_attributes (&type,
- chainon (returned_attrs,
- attrs),
- attr_flags);
- }
+ attrs = c_warn_type_attributes (attrs);
+ returned_attrs = decl_attributes (&type,
+ chainon (returned_attrs, attrs),
+ attr_flags);
break;
}
case cdk_array:
}
}
*decl_attrs = chainon (returned_attrs, *decl_attrs);
+ *decl_attrs = chainon (decl_id_attrs, *decl_attrs);
/* Now TYPE has the actual type, apart from any qualifiers in
TYPE_QUALS. */
type = c_build_qualified_type (type, type_quals, orig_qual_type,
orig_qual_indirect);
decl = build_decl (declarator->id_loc,
- TYPE_DECL, declarator->u.id, type);
+ TYPE_DECL, declarator->u.id.id, type);
if (declspecs->explicit_signed_p)
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
if (declspecs->inline_p)
if (declspecs->noreturn_p)
pedwarn (loc, 0,"typedef %q+D declared %<_Noreturn%>", decl);
- if (warn_cxx_compat && declarator->u.id != NULL_TREE)
+ if (warn_cxx_compat && declarator->u.id.id != NULL_TREE)
{
- struct c_binding *b = I_TAG_BINDING (declarator->u.id);
+ struct c_binding *b = I_TAG_BINDING (declarator->u.id.id);
if (b != NULL
&& b->decl != NULL_TREE
type = c_build_qualified_type (type, type_quals);
decl = build_decl (declarator->id_loc,
- PARM_DECL, declarator->u.id, type);
+ PARM_DECL, declarator->u.id.id, type);
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
C_ARRAY_PARAMETER (decl) = array_parameter_p;
type = c_build_qualified_type (type, type_quals, orig_qual_type,
orig_qual_indirect);
decl = build_decl (declarator->id_loc,
- FIELD_DECL, declarator->u.id, type);
+ FIELD_DECL, declarator->u.id.id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
- if (bitfield && !declarator->u.id)
+ if (bitfield && !declarator->u.id.id)
{
TREE_NO_WARNING (decl) = 1;
DECL_PADDING_P (decl) = 1;
}
decl = build_decl (declarator->id_loc,
- FUNCTION_DECL, declarator->u.id, type);
+ FUNCTION_DECL, declarator->u.id.id, type);
decl = build_decl_attribute_variant (decl, decl_attr);
if (type_quals & TYPE_QUAL_ATOMIC)
/* Record presence of `inline' and `_Noreturn', if it is
reasonable. */
- if (flag_hosted && MAIN_NAME_P (declarator->u.id))
+ if (flag_hosted && MAIN_NAME_P (declarator->u.id.id))
{
if (declspecs->inline_p)
pedwarn (loc, 0, "cannot inline function %<main%>");
the 'extern' declaration is taken to refer to that decl.) */
if (extern_ref && current_scope != file_scope)
{
- tree global_decl = identifier_global_value (declarator->u.id);
- tree visible_decl = lookup_name (declarator->u.id);
+ tree global_decl = identifier_global_value (declarator->u.id.id);
+ tree visible_decl = lookup_name (declarator->u.id.id);
if (global_decl
&& global_decl != visible_decl
}
decl = build_decl (declarator->id_loc,
- VAR_DECL, declarator->u.id, type);
+ VAR_DECL, declarator->u.id.id, type);
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
{
tree value;
- if (declarator->kind == cdk_id && declarator->u.id == NULL_TREE
+ if (declarator->kind == cdk_id && declarator->u.id.id == NULL_TREE
&& width == NULL_TREE)
{
/* This is an unnamed decl.
struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
ret->kind = cdk_id;
ret->declarator = 0;
- ret->u.id = ident;
+ ret->u.id.id = ident;
+ ret->u.id.attrs = NULL_TREE;
/* Default value - may get reset to a more precise location. */
ret->id_loc = input_location;
return ret;
/* Set a dummy type. */
if (TREE_CODE (specs->type) == ERROR_MARK)
specs->type = integer_type_node;
- return specs;
+ goto handle_postfix_attrs;
}
/* If none of "void", "_Bool", "char", "int", "float" or "double"
default:
gcc_unreachable ();
}
+ handle_postfix_attrs:
if (specs->type != NULL)
{
specs->postfix_attrs = c_warn_type_attributes (specs->postfix_attrs);
inner->id_loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
if (c_parser_nth_token_starts_std_attributes (parser, 1))
- {
- tree std_attrs = c_parser_std_attribute_specifier_sequence (parser);
- if (std_attrs)
- inner = build_attrs_declarator (std_attrs, inner);
- }
+ inner->u.id.attrs = c_parser_std_attribute_specifier_sequence (parser);
return c_parser_direct_declarator_inner (parser, *seen_id, inner);
}
return NULL;
else
{
- inner
- = build_function_declarator (args,
- build_id_declarator (NULL_TREE));
+ inner = build_id_declarator (NULL_TREE);
if (!(args->types
&& args->types != error_mark_node
&& TREE_CODE (TREE_VALUE (args->types)) == IDENTIFIER_NODE)
if (std_attrs)
inner = build_attrs_declarator (std_attrs, inner);
}
+ inner = build_function_declarator (args, inner);
return c_parser_direct_declarator_inner (parser, *seen_id,
inner);
}
static_seen, star_seen);
if (declarator == NULL)
return NULL;
- inner = set_array_declarator_inner (declarator, inner);
if (c_parser_nth_token_starts_std_attributes (parser, 1))
{
tree std_attrs
if (std_attrs)
inner = build_attrs_declarator (std_attrs, inner);
}
+ inner = set_array_declarator_inner (declarator, inner);
return c_parser_direct_declarator_inner (parser, id_present, inner);
}
else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
return NULL;
else
{
- inner = build_function_declarator (args, inner);
if (!(args->types
&& args->types != error_mark_node
&& TREE_CODE (TREE_VALUE (args->types)) == IDENTIFIER_NODE)
if (std_attrs)
inner = build_attrs_declarator (std_attrs, inner);
}
+ inner = build_function_declarator (args, inner);
return c_parser_direct_declarator_inner (parser, id_present, inner);
}
}
c_declarator *id_declarator = declarator;
while (id_declarator && id_declarator->kind != cdk_id)
id_declarator = id_declarator->declarator;
- location_t caret_loc = (id_declarator->u.id
+ location_t caret_loc = (id_declarator->u.id.id
? id_declarator->id_loc
: start_loc);
location_t param_loc = make_location (caret_loc, start_loc, end_loc);
/* Except for cdk_id, the contained declarator. For cdk_id, NULL. */
struct c_declarator *declarator;
union {
- /* For identifiers, an IDENTIFIER_NODE or NULL_TREE if an abstract
- declarator. */
- tree id;
+ /* For identifiers. */
+ struct {
+ /* An IDENTIFIER_NODE, or NULL_TREE if an abstract
+ declarator. */
+ tree id;
+ /* Any attributes (which apply to the declaration rather than to
+ the type described by the outer declarators). */
+ tree attrs;
+ } id;
/* For functions. */
struct c_arg_info *arg_info;
/* For arrays. */
unsigned version, ver_offset;
if (declarator->kind == cdk_id
&& is_gimple_reg_type (specs->type)
- && c_parser_parse_ssa_name_id (declarator->u.id,
+ && c_parser_parse_ssa_name_id (declarator->u.id.id,
&version, &ver_offset)
/* The following restricts it to unnamed anonymous SSA names
which fails parsing of named ones in dumps (we could
decide to not dump their name for -gimple). */
&& ver_offset == 0)
- c_parser_parse_ssa_name (parser, declarator->u.id, specs->type,
+ c_parser_parse_ssa_name (parser, declarator->u.id.id, specs->type,
version, ver_offset);
else
{
+2019-11-25 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/gnu2x-attrs-1.c: Do not expect message about attributes
+ appertaining to types.
+ * gcc.dg/gnu2x-attrs-2.c: New test.
+ * g++.dg/cpp0x/gen-attrs-1.C, g++.dg/cpp0x/gen-attrs-22.C,
+ g++.dg/cpp0x/gen-attrs-4.C, g++.dg/cpp0x/lambda/lambda-attr1.C:
+ Update expected diagnostics.
+
2019-11-25 Tamar Christina <tamar.christina@arm.com>
* gcc.dg/torture/fp-int-convert-timode-1.c: Always run if int128.
// { dg-do compile { target c++11 } }
-int **** [[gnu::format(printf, 1, 2)]] foo(const char *, ...); // { dg-warning "ignored" }
+int **** [[gnu::format(printf, 1, 2)]] foo(const char *, ...); // { dg-warning "only applies to function types" }
void f()
{
- static_cast<float *[[gnu::unused]]>(0); // { dg-warning "ignored" }
+ static_cast<float *[[gnu::unused]]>(0);
}
[[gnu::unused]]
int
five(void)
-[[noreturn]] // { dg-warning "ignored" }
+[[noreturn]] // { dg-warning "does not apply to types" }
{ return 0; }
[[noreturn]]
// { dg-do compile { target c++11 } }
-auto l = []() [[noreturn]] {}; // { dg-warning "ignored" }
+auto l = []() [[noreturn]] {}; // { dg-warning "does not apply to types" }
[[gnu::alias("f")]] void g (void); /* { dg-error "only weak" "" { target *-*-darwin* } } */
-void [[gnu::alias("f")]] h (void); /* { dg-warning "ignored" } */
-/* { dg-message "that appertains to a type-specifier" "appertains" { target *-*-* } .-1 } */
+void [[gnu::alias("f")]] h (void); /* { dg-warning "does not apply to types" } */
struct [[gnu::packed]] s { int a; char b; };
_Static_assert (sizeof (struct s) == (sizeof (int) + sizeof (char)));
--- /dev/null
+/* Test C2x attribute syntax. Test GNU attributes appertain to
+ appropriate constructs. Attributes on types not being defined at
+ the time. */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu2x -Wformat" } */
+
+typedef void va_type (const char *, ...);
+typedef va_type [[gnu::format (printf, 1, 2)]] printf_like_1;
+typedef void printf_like_2 (const char *, ...) [[gnu::format (printf, 1, 2)]];
+typedef __typeof__ (void (const char *, ...) [[gnu::format (printf, 1, 2)]])
+ printf_like_3;
+
+va_type func1;
+printf_like_1 func2;
+printf_like_2 func3;
+printf_like_3 func4;
+va_type [[gnu::format (printf, 1, 2)]] *func5 (void);
+
+void
+func_test (void)
+{
+ func1 ("%s", 1);
+ func2 ("%s", 1); /* { dg-warning "expects argument" } */
+ func3 ("%s", 1); /* { dg-warning "expects argument" } */
+ func4 ("%s", 1); /* { dg-warning "expects argument" } */
+ func5 () ("%s", 1); /* { dg-warning "expects argument" } */
+}
+
+typedef int A[2];
+
+__typeof__ (int [[gnu::deprecated]]) var1; /* { dg-warning "deprecated" } */
+__typeof__ (A [[gnu::deprecated]]) var2; /* { dg-warning "deprecated" } */
+__typeof__ (int [3] [[gnu::deprecated]]) var3; /* { dg-warning "deprecated" } */