* [C++ PATCH] C++2A P0386R1 - default member initializers for bit-fields
@ 2017-09-19 12:54 Jakub Jelinek
2017-09-19 12:59 ` Tim Song
2017-09-27 14:55 ` Nathan Sidwell
0 siblings, 2 replies; 12+ messages in thread
From: Jakub Jelinek @ 2017-09-19 12:54 UTC (permalink / raw)
To: Jason Merrill, Nathan Sidwell; +Cc: gcc-patches
Hi!
The following patch implements P0386R1 - NSDMIs for bit-fields.
While working on that, I've discovered our parser mishandles attributes
on bitfields, already C++11 says:
identifier[opt] attribute-specifier-seq[opt] : constant-expression
in the grammar, but we actually parsed
identifier[opt] : constant-expression attribute-specifier-seq[opt]
I had to resolve a few issues:
1) cp_parser_constant_expression doesn't actually parse a
constant-expression, but a constant assignment-expression; the
rationale is that it gives better diagnostics etc. For
the bitfield parsing, we really need a constant expression.
The patch has the parsing code inline, another option is to
adjust cp_parser_constant_expression so that it has (a defaulted)
bool argument strict or something similar and if that argument is true,
don't call cp_parser_assignment_expression in it, but instead do inline
the
cp_expr expr
= cp_parser_binary_expression (parser, false, false, false,
PREC_NOT_OPERATOR, NULL);
/* If the next token is a `?' then we're actually looking at
a conditional-expression; otherwise we're done. */
if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
expr = cp_parser_question_colon_clause (parser, expr);
part. Another option is to add another argument to
cp_parser_assignment_expression too and do it in there, or add
cp_parser_conditional_expression and call it conditionally from
cp_parser_constant_expression (based on this strict or force_conditional
or whatever arg) and unconditionally from cp_parser_assignment_expression.
Preferences?
2) the above attribute issue; in the patch I parse attributes in both
spots unless NSDMI is present (in that case only at the right spot,
since there is no need for backwards compatibility). Should there be
some pedwarn or something similar if attributes appear in the old
(incorrect) spot? Only for C++11 attributes or for both C++11 and GNU?
3) we were temporarily (until check_bitfield_decl) stashing the bit width
expression in DECL_INITIAL, which obviously doesn't work too well when we
need to stash the NSDMI there temporarily. I've tried to put it temporarily
into DECL_SIZE, but that doesn't work too well, because e.g.
variably_modified_type_p is called on still incomplete aggregate types and
it then thinks that such incomplete type is variable length.
So in the end I'm temporarily abusing DECL_BIT_FIELD_REPRESENTATIVE,
which seems to work fine (the middle-end only uses it after the type is
completed).
4) I hope default member initializers aren't valid for unnamed bit-fields,
but am not 100% sure if the current standard wording really disallows it.
There is:
"A brace-or-equal-initializer shall appear only in the declaration of a data member."
so, are unnamed bit-fields not data members?
There is additionally
"A data member is a non-function member introduced by a member-declarator."
and a paragraph before says that unnamed bit-field is not a member of the
class.
Bootstrapped/regtested on x86_64-linux and i686-linux (including make
check-c++-all), ok for trunk? Or any preferences on 1) or 2) above?
2017-09-19 Jakub Jelinek <jakub@redhat.com>
P0386R1 - default member initializers for bit-fields
c-family/
* c-attribs.c (handle_packed_attribute): Test DECL_C_BIT_FIELD
rather than DECL_INITIAL.
(common_handle_aligned_attribute): Likewise.
c/
* c-decl.c (grokfield): Use SET_DECL_C_BIT_FIELD here if
with is non-NULL.
(finish_struct): Test DECL_C_BIT_FIELD instead of DECL_INITIAL,
don't SET_DECL_C_BIT_FIELD here.
cp/
* cp-tree.h (grokbitfield): Add INIT parameter.
* parser.c (cp_parser_member_declaration): Parse attributes before
colon of a bitfield in addition to after colon. Parse C++2A bitfield
NSDMIs. Adjust grokbitfield caller. Handle DECL_INITIAL also for
DECL_C_BIT_FIELDs.
(cp_parser_objc_class_ivars): Adjust grokbitfield caller.
* class.c (check_bitfield_decl): Retrieve and clear width from
DECL_BIT_FIELD_REPRESENTATIVE rather than DECL_INITIAL.
(check_field_decl): Recurse even for DECL_C_BIT_FIELDs.
(check_field_decls): Test DECL_BIT_FIELD_REPRESENTATIVE rather than
DECL_INITIAL.
(remove_zero_width_bit_fields): Adjust comment.
* decl2.c (grokbitfield): Add INIT parameter, pass it to
cp_finish_decl. Stash width into DECL_BIT_FIELD_REPRESENTATIVE rather
than DECL_INITIAL.
* pt.c (tsubst_decl): For DECL_C_BIT_FIELD, tsubst_expr
DECL_BIT_FIELD_REPRESENTATIVE rather than DECL_INITIAL for width,
and handle DECL_INITIAL for all FIELD_DECLs, not just non-bitfields.
* Make-lang.in (check-c++-all): Test also c++2a.
objc/
* objc-act.c (check_ivars, gen_declaration): For OBJCPLUS look at
DECL_BIT_FIELD_REPRESENTATIVE rather than DECL_INITIAL.
testsuite/
* g++.dg/ext/bitfield6.C: New test.
* g++.dg/ext/bitfield7.C: New test.
* g++.dg/ext/bitfield8.C: New test.
* g++.dg/cpp2a/bitfield1.C: New test.
* g++.dg/cpp2a/bitfield2.C: New test.
* g++.dg/cpp2a/bitfield3.C: New test.
--- gcc/c-family/c-attribs.c.jj 2017-09-18 20:48:53.731871226 +0200
+++ gcc/c-family/c-attribs.c 2017-09-19 09:51:21.928612658 +0200
@@ -426,7 +426,7 @@ handle_packed_attribute (tree *node, tre
{
if (TYPE_ALIGN (TREE_TYPE (*node)) <= BITS_PER_UNIT
/* Still pack bitfields. */
- && ! DECL_INITIAL (*node))
+ && ! DECL_C_BIT_FIELD (*node))
warning (OPT_Wattributes,
"%qE attribute ignored for field of type %qT",
name, TREE_TYPE (*node));
@@ -1773,7 +1773,7 @@ common_handle_aligned_attribute (tree *n
{
if (warn_if_not_aligned_p)
{
- if (TREE_CODE (decl) == FIELD_DECL && !DECL_INITIAL (decl))
+ if (TREE_CODE (decl) == FIELD_DECL && !DECL_C_BIT_FIELD (decl))
{
SET_DECL_WARN_IF_NOT_ALIGN (decl, (1U << i) * BITS_PER_UNIT);
warn_if_not_aligned_p = false;
--- gcc/c/c-decl.c.jj 2017-09-12 21:57:59.000000000 +0200
+++ gcc/c/c-decl.c 2017-09-19 10:43:30.898898784 +0200
@@ -7602,6 +7602,8 @@ grokfield (location_t loc,
finish_decl (value, loc, NULL_TREE, NULL_TREE, NULL_TREE);
DECL_INITIAL (value) = width;
+ if (width)
+ SET_DECL_C_BIT_FIELD (value);
if (warn_cxx_compat && DECL_NAME (value) != NULL_TREE)
{
@@ -7946,12 +7948,11 @@ finish_struct (location_t loc, tree t, t
if (C_DECL_VARIABLE_SIZE (x))
C_TYPE_VARIABLE_SIZE (t) = 1;
- if (DECL_INITIAL (x))
+ if (DECL_C_BIT_FIELD (x))
{
unsigned HOST_WIDE_INT width = tree_to_uhwi (DECL_INITIAL (x));
DECL_SIZE (x) = bitsize_int (width);
DECL_BIT_FIELD (x) = 1;
- SET_DECL_C_BIT_FIELD (x);
}
if (TYPE_PACKED (t)
--- gcc/cp/cp-tree.h.jj 2017-09-18 20:48:53.539873617 +0200
+++ gcc/cp/cp-tree.h 2017-09-19 09:51:21.917612801 +0200
@@ -6151,7 +6151,7 @@ extern void check_member_template (tree
extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *,
tree, bool, tree, tree);
extern tree grokbitfield (const cp_declarator *, cp_decl_specifier_seq *,
- tree, tree);
+ tree, tree, tree);
extern bool any_dependent_type_attributes_p (tree);
extern tree cp_reconstruct_complex_type (tree, tree);
extern bool attributes_naming_typedef_ok (tree);
--- gcc/cp/parser.c.jj 2017-09-18 20:48:53.480874352 +0200
+++ gcc/cp/parser.c 2017-09-19 09:51:21.915612827 +0200
@@ -23412,35 +23412,133 @@ cp_parser_member_declaration (cp_parser*
{
tree attributes = NULL_TREE;
tree first_attribute;
+ tree initializer;
+ bool is_bitfld = false;
+ bool named_bitfld = false;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
+ if (cp_next_tokens_can_be_attribute_p (parser)
+ || (token->type == CPP_NAME
+ && cp_nth_tokens_can_be_attribute_p (parser, 2)
+ && (named_bitfld = true)))
+ {
+ cp_parser_parse_tentatively (parser);
+ if (named_bitfld)
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_attributes_opt (parser);
+ token = cp_lexer_peek_token (parser->lexer);
+ is_bitfld = cp_lexer_next_token_is (parser->lexer, CPP_COLON);
+ cp_parser_abort_tentative_parse (parser);
+ }
+
/* Check for a bitfield declaration. */
- if (token->type == CPP_COLON
+ if (is_bitfld
+ || token->type == CPP_COLON
|| (token->type == CPP_NAME
- && cp_lexer_peek_nth_token (parser->lexer, 2)->type
- == CPP_COLON))
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON)
+ && (named_bitfld = true)))
{
tree identifier;
tree width;
+ tree late_attributes = NULL_TREE;
- /* Get the name of the bitfield. Note that we cannot just
- check TOKEN here because it may have been invalidated by
- the call to cp_lexer_peek_nth_token above. */
- if (cp_lexer_peek_token (parser->lexer)->type != CPP_COLON)
+ if (named_bitfld)
identifier = cp_parser_identifier (parser);
else
identifier = NULL_TREE;
+ /* Look for attributes that apply to the bitfield. */
+ attributes = cp_parser_attributes_opt (parser);
+
/* Consume the `:' token. */
cp_lexer_consume_token (parser->lexer);
+ initializer = NULL_TREE;
/* Get the width of the bitfield. */
- width
- = cp_parser_constant_expression (parser);
+ if (cxx_dialect >= cxx11)
+ {
+ /* In C++2A and as extension for C++11 and above we allow
+ NSDMI for bit-fields. As cp_parser_constant_expression
+ doesn't actually parse a constant-expression, i.e.
+ conditional-expression, but assignment-expression, we
+ can't use cp_parser_constant_expression for this. */
+ bool saved_integral_constant_expression_p
+ = parser->integral_constant_expression_p;
+ bool saved_allow_non_integral_constant_expression_p
+ = parser->allow_non_integral_constant_expression_p;
+ bool saved_non_integral_constant_expression_p
+ = parser->non_integral_constant_expression_p;
+ /* We are now parsing a constant-expression. */
+ parser->integral_constant_expression_p = true;
+ parser->allow_non_integral_constant_expression_p = true;
+ parser->non_integral_constant_expression_p = false;
+
+ /* Parse the binary expressions (logical-or-expression). */
+ cp_expr expr
+ = cp_parser_binary_expression (parser, false, false, false,
+ PREC_NOT_OPERATOR, NULL);
+ /* If the next token is a `?' then we're actually looking at
+ a conditional-expression; otherwise we're done. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
+ expr = cp_parser_question_colon_clause (parser, expr);
+
+ parser->integral_constant_expression_p
+ = saved_integral_constant_expression_p;
+ parser->allow_non_integral_constant_expression_p
+ = saved_allow_non_integral_constant_expression_p;
+ tree decay = expr;
+ if (TREE_TYPE (expr)
+ && TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE)
+ decay = build_address (expr);
+ bool is_const = potential_rvalue_constant_expression (decay);
+ parser->non_integral_constant_expression_p = !is_const;
+ if (!is_const)
+ require_potential_rvalue_constant_expression (decay);
+ parser->non_integral_constant_expression_p
+ = saved_non_integral_constant_expression_p;
+
+ width = expr;
+
+ /* Now save the NSDMI if any. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_EQ)
+ || cp_lexer_next_token_is (parser->lexer,
+ CPP_OPEN_BRACE))
+ {
+ location_t loc
+ = cp_lexer_peek_token (parser->lexer)->location;
+ if (cxx_dialect < cxx2a
+ && !in_system_header_at (loc)
+ && identifier != NULL_TREE)
+ pedwarn (loc, 0,
+ "default member initializers for bit-fields "
+ "only available with -std=c++2a or "
+ "-std=gnu++2a");
+
+ initializer = cp_parser_save_nsdmi (parser);
+ if (identifier == NULL_TREE)
+ {
+ error_at (loc, "default member initializer for "
+ "unnamed bit-field");
+ initializer = NULL_TREE;
+ }
+ }
+ else
+ /* Look for attributes that apply to the bitfield; we
+ used to be parsing attributes here instead of the
+ the standard required spot before the colon.
+ Only parse them here when not using NSDMI. */
+ late_attributes = cp_parser_attributes_opt (parser);
+ }
+ else
+ {
+ width = cp_parser_constant_expression (parser);
+ /* Look for attributes that apply to the bitfield. */
+ late_attributes = cp_parser_attributes_opt (parser);
+ }
+
+ attributes = chainon (attributes, late_attributes);
- /* Look for attributes that apply to the bitfield. */
- attributes = cp_parser_attributes_opt (parser);
/* Remember which attributes are prefix attributes and
which are not. */
first_attribute = attributes;
@@ -23454,13 +23552,12 @@ cp_parser_member_declaration (cp_parser*
sfk_none)
: NULL,
&decl_specifiers,
- width,
+ width, initializer,
attributes);
}
else
{
cp_declarator *declarator;
- tree initializer;
tree asm_specification;
int ctor_dtor_or_conv_p;
@@ -23679,7 +23776,6 @@ cp_parser_member_declaration (cp_parser*
if (TREE_CODE (decl) == FUNCTION_DECL)
cp_parser_save_default_args (parser, decl);
else if (TREE_CODE (decl) == FIELD_DECL
- && !DECL_C_BIT_FIELD (decl)
&& DECL_INITIAL (decl))
/* Add DECL to the queue of NSDMI to be parsed later. */
vec_safe_push (unparsed_nsdmis, decl);
@@ -30020,10 +30116,9 @@ cp_parser_objc_class_ivars (cp_parser* p
attributes = chainon (prefix_attributes, attributes);
if (width)
- /* Create the bitfield declaration. */
- decl = grokbitfield (declarator, &declspecs,
- width,
- attributes);
+ /* Create the bitfield declaration. */
+ decl = grokbitfield (declarator, &declspecs,
+ width, NULL_TREE, attributes);
else
decl = grokfield (declarator, &declspecs,
NULL_TREE, /*init_const_expr_p=*/false,
--- gcc/cp/class.c.jj 2017-09-18 20:48:53.509873991 +0200
+++ gcc/cp/class.c 2017-09-19 10:31:35.435961690 +0200
@@ -3231,12 +3231,12 @@ check_bitfield_decl (tree field)
tree w;
/* Extract the declared width of the bitfield, which has been
- temporarily stashed in DECL_INITIAL. */
- w = DECL_INITIAL (field);
+ temporarily stashed in DECL_BIT_FIELD_REPRESENTATIVE. */
+ w = DECL_BIT_FIELD_REPRESENTATIVE (field);
gcc_assert (w != NULL_TREE);
/* Remove the bit-field width indicator so that the rest of the
- compiler does not treat that value as an initializer. */
- DECL_INITIAL (field) = NULL_TREE;
+ compiler does not treat that value as a qualifier. */
+ DECL_BIT_FIELD_REPRESENTATIVE (field) = NULL_TREE;
/* Detect invalid bit-field type. */
if (!INTEGRAL_OR_ENUMERATION_TYPE_P (type))
@@ -3324,7 +3324,7 @@ check_field_decl (tree field,
{
for (tree fields = TYPE_FIELDS (type); fields;
fields = DECL_CHAIN (fields))
- if (TREE_CODE (fields) == FIELD_DECL && !DECL_C_BIT_FIELD (field))
+ if (TREE_CODE (fields) == FIELD_DECL)
any_default_members |= check_field_decl (fields, t,
cant_have_const_ctor,
no_const_asn_ref);
@@ -3571,7 +3571,8 @@ check_field_decls (tree t, tree *access_
DECL_PACKED (x) = 1;
}
- if (DECL_C_BIT_FIELD (x) && integer_zerop (DECL_INITIAL (x)))
+ if (DECL_C_BIT_FIELD (x)
+ && integer_zerop (DECL_BIT_FIELD_REPRESENTATIVE (x)))
/* We don't treat zero-width bitfields as making a class
non-empty. */
;
@@ -3635,10 +3636,10 @@ check_field_decls (tree t, tree *access_
/* We set DECL_C_BIT_FIELD in grokbitfield.
If the type and width are valid, we'll also set DECL_BIT_FIELD. */
- if ((! DECL_C_BIT_FIELD (x) || ! check_bitfield_decl (x))
- && check_field_decl (x, t,
- cant_have_const_ctor_p,
- no_const_asn_ref_p))
+ if (DECL_C_BIT_FIELD (x))
+ check_bitfield_decl (x);
+
+ if (check_field_decl (x, t, cant_have_const_ctor_p, no_const_asn_ref_p))
{
if (any_default_members
&& TREE_CODE (t) == UNION_TYPE)
@@ -5268,9 +5269,9 @@ remove_zero_width_bit_fields (tree t)
{
if (TREE_CODE (*fieldsp) == FIELD_DECL
&& DECL_C_BIT_FIELD (*fieldsp)
- /* We should not be confused by the fact that grokbitfield
+ /* We should not be confused by the fact that grokbitfield
temporarily sets the width of the bit field into
- DECL_INITIAL (*fieldsp).
+ DECL_BIT_FIELD_REPRESENTATIVE (*fieldsp).
check_bitfield_decl eventually sets DECL_SIZE (*fieldsp)
to that width. */
&& (DECL_SIZE (*fieldsp) == NULL_TREE
--- gcc/cp/decl2.c.jj 2017-09-18 20:48:53.388875498 +0200
+++ gcc/cp/decl2.c 2017-09-19 10:31:45.066839694 +0200
@@ -973,10 +973,11 @@ grokfield (const cp_declarator *declarat
tree
grokbitfield (const cp_declarator *declarator,
- cp_decl_specifier_seq *declspecs, tree width,
+ cp_decl_specifier_seq *declspecs, tree width, tree init,
tree attrlist)
{
- tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, &attrlist);
+ tree value = grokdeclarator (declarator, declspecs, BITFIELD,
+ init != NULL_TREE, &attrlist);
if (value == error_mark_node)
return NULL_TREE; /* friends went bad. */
@@ -1031,7 +1032,11 @@ grokbitfield (const cp_declarator *decla
error ("static member %qD cannot be a bit-field", value);
return NULL_TREE;
}
- cp_finish_decl (value, NULL_TREE, false, NULL_TREE, 0);
+
+ int flags = LOOKUP_IMPLICIT;
+ if (init && DIRECT_LIST_INIT_P (init))
+ flags = LOOKUP_NORMAL;
+ cp_finish_decl (value, init, false, NULL_TREE, flags);
if (width != error_mark_node)
{
@@ -1042,7 +1047,8 @@ grokbitfield (const cp_declarator *decla
TREE_TYPE (width));
else
{
- DECL_INITIAL (value) = width;
+ /* Temporarily stash the width in DECL_BIT_FIELD_REPRESENTATIVE. */
+ DECL_BIT_FIELD_REPRESENTATIVE (value) = width;
SET_DECL_C_BIT_FIELD (value);
}
}
--- gcc/cp/pt.c.jj 2017-09-18 20:48:53.435874912 +0200
+++ gcc/cp/pt.c 2017-09-19 10:31:56.250698026 +0200
@@ -12809,14 +12809,13 @@ tsubst_decl (tree t, tree args, tsubst_f
cp_apply_type_quals_to_decl (cp_type_quals (type), r);
if (DECL_C_BIT_FIELD (r))
- /* For bit-fields, DECL_INITIAL gives the number of bits. For
- non-bit-fields DECL_INITIAL is a non-static data member
- initializer, which gets deferred instantiation. */
- DECL_INITIAL (r)
- = tsubst_expr (DECL_INITIAL (t), args,
+ /* For bit-fields, DECL_BIT_FIELD_REPRESENTATIVE gives the
+ number of bits. */
+ DECL_BIT_FIELD_REPRESENTATIVE (r)
+ = tsubst_expr (DECL_BIT_FIELD_REPRESENTATIVE (t), args,
complain, in_decl,
/*integral_constant_expression_p=*/true);
- else if (DECL_INITIAL (t))
+ if (DECL_INITIAL (t))
{
/* Set up DECL_TEMPLATE_INFO so that we can get at the
NSDMI in perform_member_init. Still set DECL_INITIAL
--- gcc/cp/Make-lang.in.jj 2017-09-18 20:48:53.592872957 +0200
+++ gcc/cp/Make-lang.in 2017-09-19 09:51:21.918612788 +0200
@@ -176,7 +176,7 @@ check-c++17:
# Run the testsuite in all standard conformance levels.
check-c++-all:
- $(MAKE) RUNTESTFLAGS="$(RUNTESTFLAGS) --stds=98,11,14,17,concepts" check-g++
+ $(MAKE) RUNTESTFLAGS="$(RUNTESTFLAGS) --stds=98,11,14,17,2a,concepts" check-g++
# Run the testsuite with garbage collection at every opportunity.
check-g++-strict-gc:
--- gcc/objc/objc-act.c.jj 2017-01-01 12:45:46.000000000 +0100
+++ gcc/objc/objc-act.c 2017-09-19 13:01:06.917412755 +0200
@@ -4602,8 +4602,14 @@ check_ivars (tree inter, tree imp)
t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
if (!comptypes (t1, t2)
+#ifdef OBJCPLUS
+ || !tree_int_cst_equal (DECL_BIT_FIELD_REPRESENTATIVE (intdecls),
+ DECL_BIT_FIELD_REPRESENTATIVE (impdecls))
+#else
|| !tree_int_cst_equal (DECL_INITIAL (intdecls),
- DECL_INITIAL (impdecls)))
+ DECL_INITIAL (impdecls))
+#endif
+ )
{
if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
{
@@ -8895,10 +8901,14 @@ gen_declaration (tree decl)
strcat (errbuf, IDENTIFIER_POINTER (DECL_NAME (decl)));
}
- if (DECL_INITIAL (decl)
- && TREE_CODE (DECL_INITIAL (decl)) == INTEGER_CST)
+#ifdef OBJCPLUS
+ tree w = DECL_BIT_FIELD_REPRESENTATIVE (decl);
+#else
+ tree w = DECL_INITIAL (decl);
+#endif
+ if (w && TREE_CODE (w) == INTEGER_CST)
sprintf (errbuf + strlen (errbuf), ": " HOST_WIDE_INT_PRINT_DEC,
- TREE_INT_CST_LOW (DECL_INITIAL (decl)));
+ TREE_INT_CST_LOW (w));
}
return errbuf;
--- gcc/testsuite/g++.dg/ext/bitfield6.C.jj 2017-09-19 10:26:48.005602981 +0200
+++ gcc/testsuite/g++.dg/ext/bitfield6.C 2017-09-19 10:25:54.000000000 +0200
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+struct S {
+ char a [[gnu::packed]] = 1; // { dg-warning "attribute ignored for field of type" }
+ char b [[gnu::packed]] : 8;
+ char c [[gnu::packed]] : 8 = 2; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+};
+template <typename U>
+struct T {
+ U d [[gnu::packed]] = 1; // { dg-warning "attribute ignored for field of type" }
+ U e [[gnu::packed]] : 8;
+ U f [[gnu::packed]] : 8 = 2; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+};
+T<char> t;
--- gcc/testsuite/g++.dg/ext/bitfield7.C.jj 2017-09-19 10:27:07.128360543 +0200
+++ gcc/testsuite/g++.dg/ext/bitfield7.C 2017-09-19 10:27:21.596177128 +0200
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-options "-Wno-packed-bitfield-compat -mno-ms-bitfields" { target { i?86-*-mingw* x86_64-*-mingw* } } } */
+
+struct t /* { dg-message "note: offset of packed bit-field 't::b' has changed in GCC 4.4" "" { target pcc_bitfield_type_matters } } */
+{
+ char a:4;
+ char b __attribute__ ((packed)) : 8;
+ char c:4;
+};
+
+int assrt[sizeof (struct t) == 2 ? 1 : -1];
--- gcc/testsuite/g++.dg/ext/bitfield8.C.jj 2017-09-19 10:28:06.911603108 +0200
+++ gcc/testsuite/g++.dg/ext/bitfield8.C 2017-09-19 10:28:23.663390910 +0200
@@ -0,0 +1,12 @@
+/* { dg-do compile { target c++11 } } */
+/* { dg-options "" } */
+/* { dg-options "-Wno-packed-bitfield-compat -mno-ms-bitfields" { target { i?86-*-mingw* x86_64-*-mingw* } } } */
+
+struct t /* { dg-message "note: offset of packed bit-field 't::b' has changed in GCC 4.4" "" { target pcc_bitfield_type_matters } } */
+{
+ char a:4;
+ char b [[gnu::packed]] : 8;
+ char c:4;
+};
+
+int assrt[sizeof (struct t) == 2 ? 1 : -1];
--- gcc/testsuite/g++.dg/cpp2a/bitfield1.C.jj 2017-09-19 09:51:21.927612671 +0200
+++ gcc/testsuite/g++.dg/cpp2a/bitfield1.C 2017-09-19 09:51:21.927612671 +0200
@@ -0,0 +1,77 @@
+// P0683R1
+// { dg-do run { target c++11 } }
+// { dg-options "" }
+
+extern "C" void abort ();
+int a;
+const int b = 0;
+struct S {
+ int c : 5 = 1; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int d : 6 { 2 }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int e : true ? 7 : a = 3;
+ int f : (true ? 8 : b) = 4; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int g : (true ? 9 : b) { 5 }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int h : 1 || new int { 0 };
+};
+#if __cplusplus >= 201402L
+static_assert (S{}.c == 1);
+static_assert (S{}.d == 2);
+static_assert (S{}.e == 0);
+static_assert (S{}.f == 4);
+static_assert (S{}.g == 5);
+static_assert (S{}.h == 0);
+#endif
+template <bool V, int W>
+struct U {
+ int j : W = 7; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int k : W { 8 }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int l : V ? 7 : a = 3;
+ int m : (V ? W : b) = 9; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int n : (V ? W : b) { 10 }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int o : 1 || new int { 0 };
+};
+#if __cplusplus >= 201402L
+static_assert (U<true, 12>{}.j == 7);
+static_assert (U<true, 13>{}.k == 8);
+static_assert (U<true, 10>{}.l == 0);
+static_assert (U<true, 11>{}.m == 9);
+static_assert (U<true, 8>{}.n == 10);
+static_assert (U<true, 7>{}.o == 0);
+#endif
+S s;
+U<true, 10> u;
+
+int
+main ()
+{
+ if (s.c != 1 || s.d != 2 || s.e != 0 || s.f != 4 || s.g != 5 || s.h != 0)
+ abort ();
+ s.c = 47; // { dg-warning "overflow in conversion from" }
+ s.d = 47 * 2; // { dg-warning "overflow in conversion from" }
+ s.e = 47 * 4; // { dg-warning "overflow in conversion from" }
+ s.f = 47 * 8; // { dg-warning "overflow in conversion from" }
+ s.g = 47 * 16; // { dg-warning "overflow in conversion from" }
+ s.h = 2; // { dg-warning "overflow in conversion from" }
+ if (s.c != 15 || s.d != 15 * 2 || s.e != 15 * 4 || s.f != 15 * 8 || s.g != 15 * 16 || s.h != 0)
+ abort ();
+ if (u.j != 7 || u.k != 8 || u.l != 0 || u.m != 9 || u.n != 10 || u.o != 0)
+ abort ();
+ u.j = 47 * 32; // { dg-warning "overflow in conversion from" }
+ u.k = 47 * 32; // { dg-warning "overflow in conversion from" }
+ u.l = 47 * 4; // { dg-warning "overflow in conversion from" }
+ u.m = 47 * 32; // { dg-warning "overflow in conversion from" }
+ u.n = 47 * 32; // { dg-warning "overflow in conversion from" }
+ u.o = 2; // { dg-warning "overflow in conversion from" }
+ if (u.j != 15 * 32 || u.k != 15 * 32 || u.l != 15 * 4 || u.m != 15 * 32 || u.n != 15 * 32 || u.o != 0)
+ abort ();
+ s.c = 15;
+ s.d = 15 * 2;
+ s.e = 15 * 4;
+ s.f = 16 * 8;
+ s.g = 15 * 16;
+ u.j = 15 * 32;
+ u.k = 15 * 32;
+ u.l = 15 * 4;
+ u.m = 15 * 32;
+ u.n = 15 * 32;
+}
--- gcc/testsuite/g++.dg/cpp2a/bitfield2.C.jj 2017-09-19 09:51:21.927612671 +0200
+++ gcc/testsuite/g++.dg/cpp2a/bitfield2.C 2017-09-19 09:51:21.927612671 +0200
@@ -0,0 +1,26 @@
+// P0683R1
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+int a;
+const int b = 0;
+struct T {
+ int i : true ? 10 : b = 6; // { dg-error "assignment of read-only variable" }
+ int : 4 = 10; // { dg-error "default member initializer for unnamed bit-field" }
+ int : 5 = a + b; // { dg-error "default member initializer for unnamed bit-field" }
+};
+template <bool V, int W>
+struct U {
+ int j : W = 7; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int k : W { 8 }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int l : V ? 7 : a = 3; // { dg-error "modification of .a. is not a constant expression" }
+ // { dg-error "width not an integer constant" "" { target *-*-* } .-1 }
+ int m : (V ? W : b) = 9; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ // { dg-error "zero width for bit-field" "" { target *-*-* } .-1 }
+ int n : (V ? W : b) { 10 }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ // { dg-error "zero width for bit-field" "" { target *-*-* } .-1 }
+ int o : 1 || new int { 0 };
+ int : 4 = 10; // { dg-error "default member initializer for unnamed bit-field" }
+ int : 5 = a + b; // { dg-error "default member initializer for unnamed bit-field" }
+};
+U<false, 10> u;
--- gcc/testsuite/g++.dg/cpp2a/bitfield3.C.jj 2017-09-19 09:51:21.926612684 +0200
+++ gcc/testsuite/g++.dg/cpp2a/bitfield3.C 2017-09-19 09:51:21.926612684 +0200
@@ -0,0 +1,55 @@
+// P0683R1
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+extern "C" void abort ();
+
+int
+foo ()
+{
+ return 2;
+}
+
+int a = foo ();
+const int b = 0;
+struct S {
+ int c : 5 = 2 * a; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int d : 6 { c + a }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ // { dg-warning "narrowing conversion of" "" { target *-*-* } .-1 }
+ int e : true ? 7 : a = 3;
+ int f : (true ? 8 : b) = d + a; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int g : (true ? 9 : b) { f + a }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ // { dg-warning "narrowing conversion of" "" { target *-*-* } .-1 }
+ int h : 1 || new int { 0 };
+ int i = g + a;
+};
+S c;
+template <bool V, int W>
+struct U {
+ int j : W = 3 * a; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int k : W { j + a }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ // { dg-warning "narrowing conversion of" "" { target *-*-* } .-1 }
+ int l : V ? 7 : a = 3;
+ int m : (V ? W : b) = k + a; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int n : (V ? W : b) { m + a }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ // { dg-warning "narrowing conversion of" "" { target *-*-* } .-1 }
+ int o : 1 || new int { 0 };
+ int p = n + a;
+};
+U<true, 10> d;
+
+int
+main ()
+{
+ a = 1;
+ if (c.c != 4 || c.d != 6 || c.e != 0 || c.f != 8 || c.g != 10 || c.h != 0 || c.i != 12)
+ abort ();
+ if (d.j != 6 || d.k != 8 || d.l != 0 || d.m != 10 || d.n != 12 || d.o != 0 || d.p != 14)
+ abort ();
+ S s;
+ U<true, 10> u;
+ if (s.c != 2 || s.d != 3 || s.f != 4 || s.g != 5 || s.i != 6)
+ abort ();
+ if (u.j != 3 || u.k != 4 || u.m != 5 || u.n != 6 || u.p != 7)
+ abort ();
+}
Jakub
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [C++ PATCH] C++2A P0386R1 - default member initializers for bit-fields
2017-09-19 12:54 [C++ PATCH] C++2A P0386R1 - default member initializers for bit-fields Jakub Jelinek
@ 2017-09-19 12:59 ` Tim Song
2017-09-19 13:01 ` Jakub Jelinek
2017-09-27 14:55 ` Nathan Sidwell
1 sibling, 1 reply; 12+ messages in thread
From: Tim Song @ 2017-09-19 12:59 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: Jason Merrill, Nathan Sidwell, gcc-patches
On Tue, Sep 19, 2017 at 8:54 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> The following patch implements P0386R1 - NSDMIs for bit-fields.
It's P0683R1.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [C++ PATCH] C++2A P0386R1 - default member initializers for bit-fields
2017-09-19 12:59 ` Tim Song
@ 2017-09-19 13:01 ` Jakub Jelinek
0 siblings, 0 replies; 12+ messages in thread
From: Jakub Jelinek @ 2017-09-19 13:01 UTC (permalink / raw)
To: Tim Song; +Cc: Jason Merrill, Nathan Sidwell, gcc-patches
On Tue, Sep 19, 2017 at 08:59:23AM -0400, Tim Song wrote:
> On Tue, Sep 19, 2017 at 8:54 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> > Hi!
> >
> > The following patch implements P0386R1 - NSDMIs for bit-fields.
>
> It's P0683R1.
Oops, got it right in the testcases, just not in the ChangeLog line
from which I've pasted the subject. Fixed in my copy.
Jakub
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [C++ PATCH] C++2A P0386R1 - default member initializers for bit-fields
2017-09-19 12:54 [C++ PATCH] C++2A P0386R1 - default member initializers for bit-fields Jakub Jelinek
2017-09-19 12:59 ` Tim Song
@ 2017-09-27 14:55 ` Nathan Sidwell
2017-09-28 18:47 ` [C++ PATCH] Fix attribute parsing for bitfields Jakub Jelinek
` (3 more replies)
1 sibling, 4 replies; 12+ messages in thread
From: Nathan Sidwell @ 2017-09-27 14:55 UTC (permalink / raw)
To: Jakub Jelinek, Jason Merrill; +Cc: gcc-patches
Jakub,
> The following patch implements P0386R1 - NSDMIs for bit-fields.
> While working on that, I've discovered our parser mishandles attributes
> on bitfields, already C++11 says:
> identifier[opt] attribute-specifier-seq[opt] : constant-expression
> in the grammar, but we actually parsed
> identifier[opt] : constant-expression attribute-specifier-seq[opt]
I'm sorry for my tardiness. It think the patch would be better broken
apart:
1) fix the parsing bug you found and move to (ab)using
DECL_BIT_FIELD_REPRESENTATIVE
2) the new c++2a feature
Is that feasible?
WRT your questions
1, I think a default strict arg on cp_parser_constant_expression is
the way to go. That makes it clear that its default behaviour is
'sloppy', saving someone the detective work you've done.
2. I'm all for a pedwarn, Jason is often more conservative than me
though.
3. D_B_F_R is quite probably fine -- you'll know better than me,
having poked at it
4. They are not valid on unamed bitfields. You may have spotted an
inconsistency in the spec.
nathan
--
Nathan Sidwell
^ permalink raw reply [flat|nested] 12+ messages in thread
* [C++ PATCH] Fix attribute parsing for bitfields
2017-09-27 14:55 ` Nathan Sidwell
@ 2017-09-28 18:47 ` Jakub Jelinek
2017-09-28 23:37 ` Nathan Sidwell
2017-09-28 18:49 ` [C++ PATCH] Stash bitfield width into DECL_BIT_FIELD_REPRESENTATIVE instead of DECL_INITIAL Jakub Jelinek
` (2 subsequent siblings)
3 siblings, 1 reply; 12+ messages in thread
From: Jakub Jelinek @ 2017-09-28 18:47 UTC (permalink / raw)
To: Nathan Sidwell, Jason Merrill; +Cc: gcc-patches
On Wed, Sep 27, 2017 at 07:55:20AM -0700, Nathan Sidwell wrote:
> Jakub,
> > The following patch implements P0386R1 - NSDMIs for bit-fields.
> > While working on that, I've discovered our parser mishandles attributes
> > on bitfields, already C++11 says:
> > identifier[opt] attribute-specifier-seq[opt] : constant-expression
> > in the grammar, but we actually parsed
> > identifier[opt] : constant-expression attribute-specifier-seq[opt]
>
> I'm sorry for my tardiness. It think the patch would be better broken
> apart:
> 1) fix the parsing bug you found and move to (ab)using
> DECL_BIT_FIELD_REPRESENTATIVE
>
> 2) the new c++2a feature
I don't see the first half of 1) related to second half thereof, the
DECL_BIT_FIELD_REPRESENTATIVE is unrelated to the parsing bug, and a needed
precondition of 2).
Therefore, I'm going to split the patch into 4 patches, one the
parsing bug (make sure we allow attributes where the standard allows them),
attached below, including pedwarn. Note we already error for the old
spot when using C++11 [[ ]] attributes there, like int a : 8 [[gnu::packed]];
because when parsing the width expression we see [ after 8 and so it could
be say 8[var] or similar, but error out because [[ must not appear in that
spot. But alignas there didn't result in error, neither __attribute__.
The other patches will follow, second patch will be
DECL_BIT_FIELD_REPRESENTATIVE, third one the Make-lang.in tweak and fourth
one, to be rewritten tomorrow on top of the rest will be the new c++2a
feature.
The following has been bootstrapped/regtested on x86_64-linux and i686-linux
(together with the Make-lang.in patch, but without the second and fourth
patch), ok for trunk?
As I said on IRC, I hope [[/__attribute__/alignas early is rare enough that
the tentative parsing shouldn't be a big deal, if it is, we could add some
cheaper function that allows us to skip over attributes (return a peek
offset after the attributes given a starting peek offset).
2017-09-28 Jakub Jelinek <jakub@redhat.com>
cp/
* parser.c (cp_parser_member_declaration): Parse attributes before
colon of a bitfield in addition to after colon.
testsuite/
* g++.dg/ext/bitfield7.C: New test.
* g++.dg/ext/bitfield8.C: New test.
* g++.dg/ext/bitfield9.C: New test.
--- gcc/cp/parser.c.jj 2017-09-22 20:51:48.181537880 +0200
+++ gcc/cp/parser.c 2017-09-27 17:50:15.082792676 +0200
@@ -23443,35 +23443,64 @@ cp_parser_member_declaration (cp_parser*
{
tree attributes = NULL_TREE;
tree first_attribute;
+ bool is_bitfld = false;
+ bool named_bitfld = false;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
+ if (cp_next_tokens_can_be_attribute_p (parser)
+ || (token->type == CPP_NAME
+ && cp_nth_tokens_can_be_attribute_p (parser, 2)
+ && (named_bitfld = true)))
+ {
+ cp_parser_parse_tentatively (parser);
+ if (named_bitfld)
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_attributes_opt (parser);
+ token = cp_lexer_peek_token (parser->lexer);
+ is_bitfld = cp_lexer_next_token_is (parser->lexer, CPP_COLON);
+ cp_parser_abort_tentative_parse (parser);
+ }
+
/* Check for a bitfield declaration. */
- if (token->type == CPP_COLON
+ if (is_bitfld
+ || token->type == CPP_COLON
|| (token->type == CPP_NAME
- && cp_lexer_peek_nth_token (parser->lexer, 2)->type
- == CPP_COLON))
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON)
+ && (named_bitfld = true)))
{
tree identifier;
tree width;
+ tree late_attributes = NULL_TREE;
- /* Get the name of the bitfield. Note that we cannot just
- check TOKEN here because it may have been invalidated by
- the call to cp_lexer_peek_nth_token above. */
- if (cp_lexer_peek_token (parser->lexer)->type != CPP_COLON)
+ if (named_bitfld)
identifier = cp_parser_identifier (parser);
else
identifier = NULL_TREE;
+ /* Look for attributes that apply to the bitfield. */
+ attributes = cp_parser_attributes_opt (parser);
+
/* Consume the `:' token. */
cp_lexer_consume_token (parser->lexer);
+
/* Get the width of the bitfield. */
- width
- = cp_parser_constant_expression (parser);
+ width = cp_parser_constant_expression (parser);
+
+ /* Look for attributes that apply to the bitfield after
+ the `:' token and width. This is where GCC used to
+ parse attributes in the past, pedwarn if there is
+ a std attribute. */
+ if (cp_next_tokens_can_be_std_attribute_p (parser))
+ pedwarn (input_location, OPT_Wpedantic,
+ "ISO C++ allows bit-field attributes only before "
+ "the %<:%> token");
+
+ late_attributes = cp_parser_attributes_opt (parser);
+
+ attributes = chainon (attributes, late_attributes);
- /* Look for attributes that apply to the bitfield. */
- attributes = cp_parser_attributes_opt (parser);
/* Remember which attributes are prefix attributes and
which are not. */
first_attribute = attributes;
--- gcc/testsuite/g++.dg/ext/bitfield7.C.jj 2017-09-27 17:37:11.118154267 +0200
+++ gcc/testsuite/g++.dg/ext/bitfield7.C 2017-09-27 17:37:11.118154267 +0200
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-options "-Wno-packed-bitfield-compat -mno-ms-bitfields" { target { i?86-*-mingw* x86_64-*-mingw* } } } */
+
+struct t /* { dg-message "note: offset of packed bit-field 't::b' has changed in GCC 4.4" "" { target pcc_bitfield_type_matters } } */
+{
+ char a:4;
+ char b __attribute__ ((packed)) : 8;
+ char c:4;
+};
+
+int assrt[sizeof (struct t) == 2 ? 1 : -1];
--- gcc/testsuite/g++.dg/ext/bitfield8.C.jj 2017-09-27 17:37:11.118154267 +0200
+++ gcc/testsuite/g++.dg/ext/bitfield8.C 2017-09-27 17:37:11.118154267 +0200
@@ -0,0 +1,12 @@
+/* { dg-do compile { target c++11 } } */
+/* { dg-options "" } */
+/* { dg-options "-Wno-packed-bitfield-compat -mno-ms-bitfields" { target { i?86-*-mingw* x86_64-*-mingw* } } } */
+
+struct t /* { dg-message "note: offset of packed bit-field 't::b' has changed in GCC 4.4" "" { target pcc_bitfield_type_matters } } */
+{
+ char a:4;
+ char b [[gnu::packed]] : 8;
+ char c:4;
+};
+
+int assrt[sizeof (struct t) == 2 ? 1 : -1];
--- gcc/testsuite/g++.dg/ext/bitfield9.C.jj 2017-09-27 18:00:54.903153797 +0200
+++ gcc/testsuite/g++.dg/ext/bitfield9.C 2017-09-27 18:20:24.823186005 +0200
@@ -0,0 +1,10 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-pedantic" }
+
+struct S
+{
+ char a:4;
+ char b:8 alignas(int); // { dg-warning "ISO C\\+\\+ allows bit-field attributes only before the ':' token" }
+ char c:8 [[gnu::aligned(8)]]; // { dg-warning "ISO C\\+\\+ allows bit-field attributes only before the ':' token" }
+ // { dg-error "two consecutive '\\\[' shall only introduce an attribute before '\\\[' token" "" { target *-*-* } .-1 }
+};
Jakub
^ permalink raw reply [flat|nested] 12+ messages in thread
* [C++ PATCH] Stash bitfield width into DECL_BIT_FIELD_REPRESENTATIVE instead of DECL_INITIAL
2017-09-27 14:55 ` Nathan Sidwell
2017-09-28 18:47 ` [C++ PATCH] Fix attribute parsing for bitfields Jakub Jelinek
@ 2017-09-28 18:49 ` Jakub Jelinek
2017-09-28 23:28 ` Nathan Sidwell
2017-09-28 18:51 ` [C++ PATCH] Let make check-c++-all test also c++2a Jakub Jelinek
2017-09-29 12:27 ` [C++ PATCH] C++2A P0683R1 - default member initializers for bit-fields (take 2) Jakub Jelinek
3 siblings, 1 reply; 12+ messages in thread
From: Jakub Jelinek @ 2017-09-28 18:49 UTC (permalink / raw)
To: Nathan Sidwell, Jason Merrill; +Cc: gcc-patches
Hi!
On Wed, Sep 27, 2017 at 07:55:20AM -0700, Nathan Sidwell wrote:
> 1) fix the parsing bug you found and move to (ab)using
> DECL_BIT_FIELD_REPRESENTATIVE
The following patch is the D_B_F_R part of the above.
Bootstrapped/regtested on top of the patch I've just posted, ok for trunk?
2017-09-28 Jakub Jelinek <jakub@redhat.com>
c-family/
* c-attribs.c (handle_packed_attribute): Test DECL_C_BIT_FIELD
rather than DECL_INITIAL.
(common_handle_aligned_attribute): Likewise.
c/
* c-decl.c (grokfield): Use SET_DECL_C_BIT_FIELD here if
with is non-NULL.
(finish_struct): Test DECL_C_BIT_FIELD instead of DECL_INITIAL,
don't SET_DECL_C_BIT_FIELD here.
cp/
* class.c (check_bitfield_decl): Retrieve and clear width from
DECL_BIT_FIELD_REPRESENTATIVE rather than DECL_INITIAL.
(check_field_decls): Test DECL_BIT_FIELD_REPRESENTATIVE rather than
DECL_INITIAL.
(remove_zero_width_bit_fields): Adjust comment.
* decl2.c (grokbitfield): Stash width into
DECL_BIT_FIELD_REPRESENTATIVE rather than DECL_INITIAL.
* pt.c (tsubst_decl): For DECL_C_BIT_FIELD, tsubst_expr
DECL_BIT_FIELD_REPRESENTATIVE rather than DECL_INITIAL for width.
objc/
* objc-act.c (check_ivars, gen_declaration): For OBJCPLUS look at
DECL_BIT_FIELD_REPRESENTATIVE rather than DECL_INITIAL.
--- gcc/c-family/c-attribs.c.jj 2017-09-18 20:48:53.731871226 +0200
+++ gcc/c-family/c-attribs.c 2017-09-19 09:51:21.928612658 +0200
@@ -426,7 +426,7 @@ handle_packed_attribute (tree *node, tre
{
if (TYPE_ALIGN (TREE_TYPE (*node)) <= BITS_PER_UNIT
/* Still pack bitfields. */
- && ! DECL_INITIAL (*node))
+ && ! DECL_C_BIT_FIELD (*node))
warning (OPT_Wattributes,
"%qE attribute ignored for field of type %qT",
name, TREE_TYPE (*node));
@@ -1773,7 +1773,7 @@ common_handle_aligned_attribute (tree *n
{
if (warn_if_not_aligned_p)
{
- if (TREE_CODE (decl) == FIELD_DECL && !DECL_INITIAL (decl))
+ if (TREE_CODE (decl) == FIELD_DECL && !DECL_C_BIT_FIELD (decl))
{
SET_DECL_WARN_IF_NOT_ALIGN (decl, (1U << i) * BITS_PER_UNIT);
warn_if_not_aligned_p = false;
--- gcc/c/c-decl.c.jj 2017-09-12 21:57:59.000000000 +0200
+++ gcc/c/c-decl.c 2017-09-19 10:43:30.898898784 +0200
@@ -7602,6 +7602,8 @@ grokfield (location_t loc,
finish_decl (value, loc, NULL_TREE, NULL_TREE, NULL_TREE);
DECL_INITIAL (value) = width;
+ if (width)
+ SET_DECL_C_BIT_FIELD (value);
if (warn_cxx_compat && DECL_NAME (value) != NULL_TREE)
{
@@ -7946,12 +7948,11 @@ finish_struct (location_t loc, tree t, t
if (C_DECL_VARIABLE_SIZE (x))
C_TYPE_VARIABLE_SIZE (t) = 1;
- if (DECL_INITIAL (x))
+ if (DECL_C_BIT_FIELD (x))
{
unsigned HOST_WIDE_INT width = tree_to_uhwi (DECL_INITIAL (x));
DECL_SIZE (x) = bitsize_int (width);
DECL_BIT_FIELD (x) = 1;
- SET_DECL_C_BIT_FIELD (x);
}
if (TYPE_PACKED (t)
--- gcc/cp/class.c.jj 2017-09-18 20:48:53.509873991 +0200
+++ gcc/cp/class.c 2017-09-19 10:31:35.435961690 +0200
@@ -3231,12 +3231,12 @@ check_bitfield_decl (tree field)
tree w;
/* Extract the declared width of the bitfield, which has been
- temporarily stashed in DECL_INITIAL. */
- w = DECL_INITIAL (field);
+ temporarily stashed in DECL_BIT_FIELD_REPRESENTATIVE. */
+ w = DECL_BIT_FIELD_REPRESENTATIVE (field);
gcc_assert (w != NULL_TREE);
/* Remove the bit-field width indicator so that the rest of the
- compiler does not treat that value as an initializer. */
- DECL_INITIAL (field) = NULL_TREE;
+ compiler does not treat that value as a qualifier. */
+ DECL_BIT_FIELD_REPRESENTATIVE (field) = NULL_TREE;
/* Detect invalid bit-field type. */
if (!INTEGRAL_OR_ENUMERATION_TYPE_P (type))
@@ -3571,7 +3571,8 @@ check_field_decls (tree t, tree *access_
DECL_PACKED (x) = 1;
}
- if (DECL_C_BIT_FIELD (x) && integer_zerop (DECL_INITIAL (x)))
+ if (DECL_C_BIT_FIELD (x)
+ && integer_zerop (DECL_BIT_FIELD_REPRESENTATIVE (x)))
/* We don't treat zero-width bitfields as making a class
non-empty. */
;
@@ -5268,9 +5269,9 @@ remove_zero_width_bit_fields (tree t)
{
if (TREE_CODE (*fieldsp) == FIELD_DECL
&& DECL_C_BIT_FIELD (*fieldsp)
- /* We should not be confused by the fact that grokbitfield
+ /* We should not be confused by the fact that grokbitfield
temporarily sets the width of the bit field into
- DECL_INITIAL (*fieldsp).
+ DECL_BIT_FIELD_REPRESENTATIVE (*fieldsp).
check_bitfield_decl eventually sets DECL_SIZE (*fieldsp)
to that width. */
&& (DECL_SIZE (*fieldsp) == NULL_TREE
--- gcc/cp/decl2.c.jj 2017-09-18 20:48:53.388875498 +0200
+++ gcc/cp/decl2.c 2017-09-19 10:31:45.066839694 +0200
@@ -1042,7 +1047,8 @@ grokbitfield (const cp_declarator *decla
TREE_TYPE (width));
else
{
- DECL_INITIAL (value) = width;
+ /* Temporarily stash the width in DECL_BIT_FIELD_REPRESENTATIVE. */
+ DECL_BIT_FIELD_REPRESENTATIVE (value) = width;
SET_DECL_C_BIT_FIELD (value);
}
}
--- gcc/cp/pt.c.jj 2017-09-18 20:48:53.435874912 +0200
+++ gcc/cp/pt.c 2017-09-19 10:31:56.250698026 +0200
@@ -12809,14 +12809,13 @@ tsubst_decl (tree t, tree args, tsubst_f
cp_apply_type_quals_to_decl (cp_type_quals (type), r);
if (DECL_C_BIT_FIELD (r))
- /* For bit-fields, DECL_INITIAL gives the number of bits. For
- non-bit-fields DECL_INITIAL is a non-static data member
- initializer, which gets deferred instantiation. */
- DECL_INITIAL (r)
- = tsubst_expr (DECL_INITIAL (t), args,
+ /* For bit-fields, DECL_BIT_FIELD_REPRESENTATIVE gives the
+ number of bits. */
+ DECL_BIT_FIELD_REPRESENTATIVE (r)
+ = tsubst_expr (DECL_BIT_FIELD_REPRESENTATIVE (t), args,
complain, in_decl,
/*integral_constant_expression_p=*/true);
- else if (DECL_INITIAL (t))
+ else if (DECL_INITIAL (t))
{
/* Set up DECL_TEMPLATE_INFO so that we can get at the
NSDMI in perform_member_init. Still set DECL_INITIAL
--- gcc/objc/objc-act.c.jj 2017-01-01 12:45:46.000000000 +0100
+++ gcc/objc/objc-act.c 2017-09-19 13:01:06.917412755 +0200
@@ -4602,8 +4602,14 @@ check_ivars (tree inter, tree imp)
t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
if (!comptypes (t1, t2)
+#ifdef OBJCPLUS
+ || !tree_int_cst_equal (DECL_BIT_FIELD_REPRESENTATIVE (intdecls),
+ DECL_BIT_FIELD_REPRESENTATIVE (impdecls))
+#else
|| !tree_int_cst_equal (DECL_INITIAL (intdecls),
- DECL_INITIAL (impdecls)))
+ DECL_INITIAL (impdecls))
+#endif
+ )
{
if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
{
@@ -8895,10 +8901,14 @@ gen_declaration (tree decl)
strcat (errbuf, IDENTIFIER_POINTER (DECL_NAME (decl)));
}
- if (DECL_INITIAL (decl)
- && TREE_CODE (DECL_INITIAL (decl)) == INTEGER_CST)
+#ifdef OBJCPLUS
+ tree w = DECL_BIT_FIELD_REPRESENTATIVE (decl);
+#else
+ tree w = DECL_INITIAL (decl);
+#endif
+ if (w && TREE_CODE (w) == INTEGER_CST)
sprintf (errbuf + strlen (errbuf), ": " HOST_WIDE_INT_PRINT_DEC,
- TREE_INT_CST_LOW (DECL_INITIAL (decl)));
+ TREE_INT_CST_LOW (w));
}
return errbuf;
Jakub
^ permalink raw reply [flat|nested] 12+ messages in thread
* [C++ PATCH] Let make check-c++-all test also c++2a
2017-09-27 14:55 ` Nathan Sidwell
2017-09-28 18:47 ` [C++ PATCH] Fix attribute parsing for bitfields Jakub Jelinek
2017-09-28 18:49 ` [C++ PATCH] Stash bitfield width into DECL_BIT_FIELD_REPRESENTATIVE instead of DECL_INITIAL Jakub Jelinek
@ 2017-09-28 18:51 ` Jakub Jelinek
2017-09-28 23:38 ` Nathan Sidwell
2017-09-29 12:27 ` [C++ PATCH] C++2A P0683R1 - default member initializers for bit-fields (take 2) Jakub Jelinek
3 siblings, 1 reply; 12+ messages in thread
From: Jakub Jelinek @ 2017-09-28 18:51 UTC (permalink / raw)
To: Nathan Sidwell; +Cc: gcc-patches
Hi!
On Wed, Sep 27, 2017 at 07:55:20AM -0700, Nathan Sidwell wrote:
> I'm sorry for my tardiness. It think the patch would be better broken
> apart:
> 1) fix the parsing bug you found and move to (ab)using
> DECL_BIT_FIELD_REPRESENTATIVE
>
> 2) the new c++2a feature
>
> Is that feasible?
Here is the third patch, which enables testing c++2a in make check-c++-all.
Regtested and regtested with make check-c++-all on x86_64-linux and
i686-linux, ok for trunk?
2017-09-28 Jakub Jelinek <jakub@redhat.com>
* Make-lang.in (check-c++-all): Test also c++2a.
--- gcc/cp/Make-lang.in.jj 2017-09-18 20:48:53.592872957 +0200
+++ gcc/cp/Make-lang.in 2017-09-19 09:51:21.918612788 +0200
@@ -176,7 +176,7 @@ check-c++17:
# Run the testsuite in all standard conformance levels.
check-c++-all:
- $(MAKE) RUNTESTFLAGS="$(RUNTESTFLAGS) --stds=98,11,14,17,concepts" check-g++
+ $(MAKE) RUNTESTFLAGS="$(RUNTESTFLAGS) --stds=98,11,14,17,2a,concepts" check-g++
# Run the testsuite with garbage collection at every opportunity.
check-g++-strict-gc:
Jakub
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [C++ PATCH] Stash bitfield width into DECL_BIT_FIELD_REPRESENTATIVE instead of DECL_INITIAL
2017-09-28 18:49 ` [C++ PATCH] Stash bitfield width into DECL_BIT_FIELD_REPRESENTATIVE instead of DECL_INITIAL Jakub Jelinek
@ 2017-09-28 23:28 ` Nathan Sidwell
0 siblings, 0 replies; 12+ messages in thread
From: Nathan Sidwell @ 2017-09-28 23:28 UTC (permalink / raw)
To: Jakub Jelinek, Jason Merrill; +Cc: gcc-patches
On 09/28/2017 11:49 AM, Jakub Jelinek wrote:
> The following patch is the D_B_F_R part of the above.
> Bootstrapped/regtested on top of the patch I've just posted, ok for trunk?
Looks good, a couple of nits. I think the bits out of the cp FE are
sufficiently obvious given the cp changes.
> c/
> * c-decl.c (grokfield): Use SET_DECL_C_BIT_FIELD here if
> with is non-NULL.
/with/width
> --- gcc/c-family/c-attribs.c.jj 2017-09-18 20:48:53.731871226 +0200
> +++ gcc/c-family/c-attribs.c 2017-09-19 09:51:21.928612658 +0200
> @@ -426,7 +426,7 @@ handle_packed_attribute (tree *node, tre
> --- gcc/cp/class.c.jj 2017-09-18 20:48:53.509873991 +0200
> +++ gcc/cp/class.c 2017-09-19 10:31:35.435961690 +0200
> @@ -3231,12 +3231,12 @@ check_bitfield_decl (tree field)
> tree w;
>
> /* Extract the declared width of the bitfield, which has been
> - temporarily stashed in DECL_INITIAL. */
> - w = DECL_INITIAL (field);
> + temporarily stashed in DECL_BIT_FIELD_REPRESENTATIVE. */
While you're here, could you point the comment at grokbitfield?
> +++ gcc/cp/decl2.c 2017-09-19 10:31:45.066839694 +0200
> @@ -1042,7 +1047,8 @@ grokbitfield (const cp_declarator *decla
> TREE_TYPE (width));
> else
> {
> - DECL_INITIAL (value) = width;
> + /* Temporarily stash the width in DECL_BIT_FIELD_REPRESENTATIVE. */
And likewise here point at ceheck_bitfield_decl? (answering the
temporarily 'til when? question)
> +++ gcc/objc/objc-act.c 2017-09-19 13:01:06.917412755 +0200
> @@ -4602,8 +4602,14 @@ check_ivars (tree inter, tree imp)
> t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
>
> if (!comptypes (t1, t2)
> +#ifdef OBJCPLUS
> + || !tree_int_cst_equal (DECL_BIT_FIELD_REPRESENTATIVE (intdecls),
> + DECL_BIT_FIELD_REPRESENTATIVE (impdecls))
> +#else
> || !tree_int_cst_equal (DECL_INITIAL (intdecls),
> - DECL_INITIAL (impdecls)))
> + DECL_INITIAL (impdecls))
> +#endif
This is a little unfortunate. Feel like adding a cleanup task to the
easy-projects wiki? You'll see I added a few I've been spotting.
ok for trunk.
nathan
--
Nathan Sidwell
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [C++ PATCH] Fix attribute parsing for bitfields
2017-09-28 18:47 ` [C++ PATCH] Fix attribute parsing for bitfields Jakub Jelinek
@ 2017-09-28 23:37 ` Nathan Sidwell
0 siblings, 0 replies; 12+ messages in thread
From: Nathan Sidwell @ 2017-09-28 23:37 UTC (permalink / raw)
To: Jakub Jelinek, Jason Merrill; +Cc: gcc-patches
On 09/28/2017 11:47 AM, Jakub Jelinek wrote:
> I don't see the first half of 1) related to second half thereof, the
> DECL_BIT_FIELD_REPRESENTATIVE is unrelated to the parsing bug, and a needed
> precondition of 2).
That's very conscientious of you.
> As I said on IRC, I hope [[/__attribute__/alignas early is rare enough that
> the tentative parsing shouldn't be a big deal, if it is, we could add some
> cheaper function that allows us to skip over attributes (return a peek
> offset after the attributes given a starting peek offset).
I agree.
> --- gcc/cp/parser.c.jj 2017-09-22 20:51:48.181537880 +0200
> +++ gcc/cp/parser.c 2017-09-27 17:50:15.082792676 +0200
> @@ -23443,35 +23443,64 @@ cp_parser_member_declaration (cp_parser*
> /* Peek at the next token. */
> token = cp_lexer_peek_token (parser->lexer);
>
> + if (cp_next_tokens_can_be_attribute_p (parser)
> + || (token->type == CPP_NAME
> + && cp_nth_tokens_can_be_attribute_p (parser, 2)
> + && (named_bitfld = true)))
> + {
Please insert a comment describing why we're doing the lookahead and our
supposition that it is rare, so the simplicity of a tentative parse is
worth the expense. Also, as I mentioned before, the other alternative
is to let the non-bitfield declarator parsing get an unnamed decl and
then look for the ':'. But that's a more complicated change we decided
not to do.
the mid-condition assignment is ugly, but probably the least ugly.
ok for trunk.
nathan
--
Nathan Sidwell
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [C++ PATCH] Let make check-c++-all test also c++2a
2017-09-28 18:51 ` [C++ PATCH] Let make check-c++-all test also c++2a Jakub Jelinek
@ 2017-09-28 23:38 ` Nathan Sidwell
0 siblings, 0 replies; 12+ messages in thread
From: Nathan Sidwell @ 2017-09-28 23:38 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: gcc-patches
On 09/28/2017 11:50 AM, Jakub Jelinek wrote:
> Hi!
> Here is the third patch, which enables testing c++2a in make check-c++-all.
> Regtested and regtested with make check-c++-all on x86_64-linux and
> i686-linux, ok for trunk?
yup, thanks.
--
Nathan Sidwell
^ permalink raw reply [flat|nested] 12+ messages in thread
* [C++ PATCH] C++2A P0683R1 - default member initializers for bit-fields (take 2)
2017-09-27 14:55 ` Nathan Sidwell
` (2 preceding siblings ...)
2017-09-28 18:51 ` [C++ PATCH] Let make check-c++-all test also c++2a Jakub Jelinek
@ 2017-09-29 12:27 ` Jakub Jelinek
2017-09-29 14:15 ` Nathan Sidwell
3 siblings, 1 reply; 12+ messages in thread
From: Jakub Jelinek @ 2017-09-29 12:27 UTC (permalink / raw)
To: Nathan Sidwell; +Cc: Jason Merrill, gcc-patches
Hi!
On Wed, Sep 27, 2017 at 07:55:20AM -0700, Nathan Sidwell wrote:
> 1) fix the parsing bug you found and move to (ab)using
> DECL_BIT_FIELD_REPRESENTATIVE
>
> 2) the new c++2a feature
And here is the 2) patch, on top of the previous 3 ones.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2017-09-29 Jakub Jelinek <jakub@redhat.com>
P0683R1 - default member initializers for bit-fields
cp/
* cp-tree.h (grokbitfield): Add INIT parameter.
* parser.c (cp_parser_constant_expression): Add STRICT_P argument,
if true, parse a conditional-expression rather than
assignment-expression.
(cp_parser_member_declaration): For C++11 and later pass true
as STRICT_P to cp_parser_constant_expression. Parse C++2A bitfield
NSDMIs. Adjust grokbitfield caller. Handle DECL_INITIAL also for
DECL_C_BIT_FIELDs.
(cp_parser_objc_class_ivars): Adjust grokbitfield caller.
* class.c (check_field_decl): Recurse even for DECL_C_BIT_FIELDs.
(check_field_decls): Call check_field_decl even for DECL_C_BIT_FIELDs.
* decl2.c (grokbitfield): Add INIT parameter, pass it to
cp_finish_decl.
* pt.c (tsubst_decl): Handle DECL_INITIAL for all FIELD_DECLs, not
just non-bitfields.
testsuite/
* g++.dg/ext/bitfield6.C: New test.
* g++.dg/cpp2a/bitfield1.C: New test.
* g++.dg/cpp2a/bitfield2.C: New test.
* g++.dg/cpp2a/bitfield3.C: New test.
--- gcc/cp/cp-tree.h.jj 2017-09-29 09:07:33.554063918 +0200
+++ gcc/cp/cp-tree.h 2017-09-29 10:24:26.846373177 +0200
@@ -6159,7 +6159,7 @@ extern void check_member_template (tree
extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *,
tree, bool, tree, tree);
extern tree grokbitfield (const cp_declarator *, cp_decl_specifier_seq *,
- tree, tree);
+ tree, tree, tree);
extern bool any_dependent_type_attributes_p (tree);
extern tree cp_reconstruct_complex_type (tree, tree);
extern bool attributes_naming_typedef_ok (tree);
--- gcc/cp/parser.c.jj 2017-09-29 09:47:43.978411525 +0200
+++ gcc/cp/parser.c 2017-09-29 10:55:51.364348848 +0200
@@ -2089,7 +2089,7 @@ static enum tree_code cp_parser_assignme
static cp_expr cp_parser_expression
(cp_parser *, cp_id_kind * = NULL, bool = false, bool = false);
static cp_expr cp_parser_constant_expression
- (cp_parser *, bool = false, bool * = NULL);
+ (cp_parser *, bool = false, bool * = NULL, bool = false);
static cp_expr cp_parser_builtin_offsetof
(cp_parser *);
static cp_expr cp_parser_lambda_expression
@@ -9626,12 +9626,15 @@ cp_parser_expression (cp_parser* parser,
If ALLOW_NON_CONSTANT_P a non-constant expression is silently
accepted. If ALLOW_NON_CONSTANT_P is true and the expression is not
constant, *NON_CONSTANT_P is set to TRUE. If ALLOW_NON_CONSTANT_P
- is false, NON_CONSTANT_P should be NULL. */
+ is false, NON_CONSTANT_P should be NULL. If STRICT_P is true,
+ only parse a conditional-expression, otherwise parse an
+ assignment-expression. See below for rationale. */
static cp_expr
cp_parser_constant_expression (cp_parser* parser,
bool allow_non_constant_p,
- bool *non_constant_p)
+ bool *non_constant_p,
+ bool strict_p)
{
bool saved_integral_constant_expression_p;
bool saved_allow_non_integral_constant_expression_p;
@@ -9665,16 +9668,27 @@ cp_parser_constant_expression (cp_parser
parser->allow_non_integral_constant_expression_p
= (allow_non_constant_p || cxx_dialect >= cxx11);
parser->non_integral_constant_expression_p = false;
- /* Although the grammar says "conditional-expression", we parse an
- "assignment-expression", which also permits "throw-expression"
- and the use of assignment operators. In the case that
- ALLOW_NON_CONSTANT_P is false, we get better errors than we would
+ /* Although the grammar says "conditional-expression", when not STRICT_P,
+ we parse an "assignment-expression", which also permits
+ "throw-expression" and the use of assignment operators. In the case
+ that ALLOW_NON_CONSTANT_P is false, we get better errors than we would
otherwise. In the case that ALLOW_NON_CONSTANT_P is true, it is
actually essential that we look for an assignment-expression.
For example, cp_parser_initializer_clauses uses this function to
determine whether a particular assignment-expression is in fact
constant. */
- expression = cp_parser_assignment_expression (parser);
+ if (strict_p)
+ {
+ /* Parse the binary expressions (logical-or-expression). */
+ expression = cp_parser_binary_expression (parser, false, false, false,
+ PREC_NOT_OPERATOR, NULL);
+ /* If the next token is a `?' then we're actually looking at
+ a conditional-expression; otherwise we're done. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
+ expression = cp_parser_question_colon_clause (parser, expression);
+ }
+ else
+ expression = cp_parser_assignment_expression (parser);
/* Restore the old settings. */
parser->integral_constant_expression_p
= saved_integral_constant_expression_p;
@@ -23445,6 +23459,7 @@ cp_parser_member_declaration (cp_parser*
{
tree attributes = NULL_TREE;
tree first_attribute;
+ tree initializer;
bool is_bitfld = false;
bool named_bitfld = false;
@@ -23492,18 +23507,48 @@ cp_parser_member_declaration (cp_parser*
cp_lexer_consume_token (parser->lexer);
/* Get the width of the bitfield. */
- width = cp_parser_constant_expression (parser);
+ width = cp_parser_constant_expression (parser, false, NULL,
+ cxx_dialect >= cxx11);
- /* Look for attributes that apply to the bitfield after
- the `:' token and width. This is where GCC used to
- parse attributes in the past, pedwarn if there is
- a std attribute. */
- if (cp_next_tokens_can_be_std_attribute_p (parser))
- pedwarn (input_location, OPT_Wpedantic,
- "ISO C++ allows bit-field attributes only before "
- "the %<:%> token");
+ /* In C++2A and as extension for C++11 and above we allow
+ default member initializers for bit-fields. */
+ initializer = NULL_TREE;
+ if (cxx_dialect >= cxx11
+ && (cp_lexer_next_token_is (parser->lexer, CPP_EQ)
+ || cp_lexer_next_token_is (parser->lexer,
+ CPP_OPEN_BRACE)))
+ {
+ location_t loc
+ = cp_lexer_peek_token (parser->lexer)->location;
+ if (cxx_dialect < cxx2a
+ && !in_system_header_at (loc)
+ && identifier != NULL_TREE)
+ pedwarn (loc, 0,
+ "default member initializers for bit-fields "
+ "only available with -std=c++2a or "
+ "-std=gnu++2a");
- late_attributes = cp_parser_attributes_opt (parser);
+ initializer = cp_parser_save_nsdmi (parser);
+ if (identifier == NULL_TREE)
+ {
+ error_at (loc, "default member initializer for "
+ "unnamed bit-field");
+ initializer = NULL_TREE;
+ }
+ }
+ else
+ {
+ /* Look for attributes that apply to the bitfield after
+ the `:' token and width. This is where GCC used to
+ parse attributes in the past, pedwarn if there is
+ a std attribute. */
+ if (cp_next_tokens_can_be_std_attribute_p (parser))
+ pedwarn (input_location, OPT_Wpedantic,
+ "ISO C++ allows bit-field attributes only "
+ "before the %<:%> token");
+
+ late_attributes = cp_parser_attributes_opt (parser);
+ }
attributes = chainon (attributes, late_attributes);
@@ -23520,13 +23565,12 @@ cp_parser_member_declaration (cp_parser*
sfk_none)
: NULL,
&decl_specifiers,
- width,
+ width, initializer,
attributes);
}
else
{
cp_declarator *declarator;
- tree initializer;
tree asm_specification;
int ctor_dtor_or_conv_p;
@@ -23745,7 +23789,6 @@ cp_parser_member_declaration (cp_parser*
if (TREE_CODE (decl) == FUNCTION_DECL)
cp_parser_save_default_args (parser, decl);
else if (TREE_CODE (decl) == FIELD_DECL
- && !DECL_C_BIT_FIELD (decl)
&& DECL_INITIAL (decl))
/* Add DECL to the queue of NSDMI to be parsed later. */
vec_safe_push (unparsed_nsdmis, decl);
@@ -30086,10 +30129,9 @@ cp_parser_objc_class_ivars (cp_parser* p
attributes = chainon (prefix_attributes, attributes);
if (width)
- /* Create the bitfield declaration. */
- decl = grokbitfield (declarator, &declspecs,
- width,
- attributes);
+ /* Create the bitfield declaration. */
+ decl = grokbitfield (declarator, &declspecs,
+ width, NULL_TREE, attributes);
else
decl = grokfield (declarator, &declspecs,
NULL_TREE, /*init_const_expr_p=*/false,
--- gcc/cp/class.c.jj 2017-09-29 09:57:12.585423540 +0200
+++ gcc/cp/class.c 2017-09-29 10:24:26.863372969 +0200
@@ -3324,7 +3324,7 @@ check_field_decl (tree field,
{
for (tree fields = TYPE_FIELDS (type); fields;
fields = DECL_CHAIN (fields))
- if (TREE_CODE (fields) == FIELD_DECL && !DECL_C_BIT_FIELD (field))
+ if (TREE_CODE (fields) == FIELD_DECL)
any_default_members |= check_field_decl (fields, t,
cant_have_const_ctor,
no_const_asn_ref);
@@ -3636,10 +3636,10 @@ check_field_decls (tree t, tree *access_
/* We set DECL_C_BIT_FIELD in grokbitfield.
If the type and width are valid, we'll also set DECL_BIT_FIELD. */
- if ((! DECL_C_BIT_FIELD (x) || ! check_bitfield_decl (x))
- && check_field_decl (x, t,
- cant_have_const_ctor_p,
- no_const_asn_ref_p))
+ if (DECL_C_BIT_FIELD (x))
+ check_bitfield_decl (x);
+
+ if (check_field_decl (x, t, cant_have_const_ctor_p, no_const_asn_ref_p))
{
if (any_default_members
&& TREE_CODE (t) == UNION_TYPE)
--- gcc/cp/decl2.c.jj 2017-09-29 09:57:12.586423527 +0200
+++ gcc/cp/decl2.c 2017-09-29 10:24:26.864372956 +0200
@@ -978,10 +978,11 @@ grokfield (const cp_declarator *declarat
tree
grokbitfield (const cp_declarator *declarator,
- cp_decl_specifier_seq *declspecs, tree width,
+ cp_decl_specifier_seq *declspecs, tree width, tree init,
tree attrlist)
{
- tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, &attrlist);
+ tree value = grokdeclarator (declarator, declspecs, BITFIELD,
+ init != NULL_TREE, &attrlist);
if (value == error_mark_node)
return NULL_TREE; /* friends went bad. */
@@ -1036,7 +1037,11 @@ grokbitfield (const cp_declarator *decla
error ("static member %qD cannot be a bit-field", value);
return NULL_TREE;
}
- cp_finish_decl (value, NULL_TREE, false, NULL_TREE, 0);
+
+ int flags = LOOKUP_IMPLICIT;
+ if (init && DIRECT_LIST_INIT_P (init))
+ flags = LOOKUP_NORMAL;
+ cp_finish_decl (value, init, false, NULL_TREE, flags);
if (width != error_mark_node)
{
--- gcc/cp/pt.c.jj 2017-09-29 10:24:26.872372858 +0200
+++ gcc/cp/pt.c 2017-09-29 10:24:58.639983280 +0200
@@ -12841,7 +12841,7 @@ tsubst_decl (tree t, tree args, tsubst_f
= tsubst_expr (DECL_BIT_FIELD_REPRESENTATIVE (t), args,
complain, in_decl,
/*integral_constant_expression_p=*/true);
- else if (DECL_INITIAL (t))
+ if (DECL_INITIAL (t))
{
/* Set up DECL_TEMPLATE_INFO so that we can get at the
NSDMI in perform_member_init. Still set DECL_INITIAL
--- gcc/testsuite/g++.dg/ext/bitfield6.C.jj 2017-09-29 10:24:26.874372834 +0200
+++ gcc/testsuite/g++.dg/ext/bitfield6.C 2017-09-29 10:24:26.874372834 +0200
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+struct S {
+ char a [[gnu::packed]] = 1; // { dg-warning "attribute ignored for field of type" }
+ char b [[gnu::packed]] : 8;
+ char c [[gnu::packed]] : 8 = 2; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+};
+template <typename U>
+struct T {
+ U d [[gnu::packed]] = 1; // { dg-warning "attribute ignored for field of type" }
+ U e [[gnu::packed]] : 8;
+ U f [[gnu::packed]] : 8 = 2; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+};
+T<char> t;
--- gcc/testsuite/g++.dg/cpp2a/bitfield1.C.jj 2017-09-29 10:24:26.874372834 +0200
+++ gcc/testsuite/g++.dg/cpp2a/bitfield1.C 2017-09-29 10:24:26.874372834 +0200
@@ -0,0 +1,77 @@
+// P0683R1
+// { dg-do run { target c++11 } }
+// { dg-options "" }
+
+extern "C" void abort ();
+int a;
+const int b = 0;
+struct S {
+ int c : 5 = 1; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int d : 6 { 2 }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int e : true ? 7 : a = 3;
+ int f : (true ? 8 : b) = 4; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int g : (true ? 9 : b) { 5 }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int h : 1 || new int { 0 };
+};
+#if __cplusplus >= 201402L
+static_assert (S{}.c == 1);
+static_assert (S{}.d == 2);
+static_assert (S{}.e == 0);
+static_assert (S{}.f == 4);
+static_assert (S{}.g == 5);
+static_assert (S{}.h == 0);
+#endif
+template <bool V, int W>
+struct U {
+ int j : W = 7; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int k : W { 8 }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int l : V ? 7 : a = 3;
+ int m : (V ? W : b) = 9; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int n : (V ? W : b) { 10 }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int o : 1 || new int { 0 };
+};
+#if __cplusplus >= 201402L
+static_assert (U<true, 12>{}.j == 7);
+static_assert (U<true, 13>{}.k == 8);
+static_assert (U<true, 10>{}.l == 0);
+static_assert (U<true, 11>{}.m == 9);
+static_assert (U<true, 8>{}.n == 10);
+static_assert (U<true, 7>{}.o == 0);
+#endif
+S s;
+U<true, 10> u;
+
+int
+main ()
+{
+ if (s.c != 1 || s.d != 2 || s.e != 0 || s.f != 4 || s.g != 5 || s.h != 0)
+ abort ();
+ s.c = 47; // { dg-warning "overflow in conversion from" }
+ s.d = 47 * 2; // { dg-warning "overflow in conversion from" }
+ s.e = 47 * 4; // { dg-warning "overflow in conversion from" }
+ s.f = 47 * 8; // { dg-warning "overflow in conversion from" }
+ s.g = 47 * 16; // { dg-warning "overflow in conversion from" }
+ s.h = 2; // { dg-warning "overflow in conversion from" }
+ if (s.c != 15 || s.d != 15 * 2 || s.e != 15 * 4 || s.f != 15 * 8 || s.g != 15 * 16 || s.h != 0)
+ abort ();
+ if (u.j != 7 || u.k != 8 || u.l != 0 || u.m != 9 || u.n != 10 || u.o != 0)
+ abort ();
+ u.j = 47 * 32; // { dg-warning "overflow in conversion from" }
+ u.k = 47 * 32; // { dg-warning "overflow in conversion from" }
+ u.l = 47 * 4; // { dg-warning "overflow in conversion from" }
+ u.m = 47 * 32; // { dg-warning "overflow in conversion from" }
+ u.n = 47 * 32; // { dg-warning "overflow in conversion from" }
+ u.o = 2; // { dg-warning "overflow in conversion from" }
+ if (u.j != 15 * 32 || u.k != 15 * 32 || u.l != 15 * 4 || u.m != 15 * 32 || u.n != 15 * 32 || u.o != 0)
+ abort ();
+ s.c = 15;
+ s.d = 15 * 2;
+ s.e = 15 * 4;
+ s.f = 16 * 8;
+ s.g = 15 * 16;
+ u.j = 15 * 32;
+ u.k = 15 * 32;
+ u.l = 15 * 4;
+ u.m = 15 * 32;
+ u.n = 15 * 32;
+}
--- gcc/testsuite/g++.dg/cpp2a/bitfield2.C.jj 2017-09-29 10:24:26.875372822 +0200
+++ gcc/testsuite/g++.dg/cpp2a/bitfield2.C 2017-09-29 10:24:26.875372822 +0200
@@ -0,0 +1,26 @@
+// P0683R1
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+int a;
+const int b = 0;
+struct T {
+ int i : true ? 10 : b = 6; // { dg-error "assignment of read-only variable" }
+ int : 4 = 10; // { dg-error "default member initializer for unnamed bit-field" }
+ int : 5 = a + b; // { dg-error "default member initializer for unnamed bit-field" }
+};
+template <bool V, int W>
+struct U {
+ int j : W = 7; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int k : W { 8 }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int l : V ? 7 : a = 3; // { dg-error "modification of .a. is not a constant expression" }
+ // { dg-error "width not an integer constant" "" { target *-*-* } .-1 }
+ int m : (V ? W : b) = 9; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ // { dg-error "zero width for bit-field" "" { target *-*-* } .-1 }
+ int n : (V ? W : b) { 10 }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ // { dg-error "zero width for bit-field" "" { target *-*-* } .-1 }
+ int o : 1 || new int { 0 };
+ int : 4 = 10; // { dg-error "default member initializer for unnamed bit-field" }
+ int : 5 = a + b; // { dg-error "default member initializer for unnamed bit-field" }
+};
+U<false, 10> u;
--- gcc/testsuite/g++.dg/cpp2a/bitfield3.C.jj 2017-09-29 10:24:26.875372822 +0200
+++ gcc/testsuite/g++.dg/cpp2a/bitfield3.C 2017-09-29 10:24:26.875372822 +0200
@@ -0,0 +1,55 @@
+// P0683R1
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+extern "C" void abort ();
+
+int
+foo ()
+{
+ return 2;
+}
+
+int a = foo ();
+const int b = 0;
+struct S {
+ int c : 5 = 2 * a; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int d : 6 { c + a }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ // { dg-warning "narrowing conversion of" "" { target *-*-* } .-1 }
+ int e : true ? 7 : a = 3;
+ int f : (true ? 8 : b) = d + a; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int g : (true ? 9 : b) { f + a }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ // { dg-warning "narrowing conversion of" "" { target *-*-* } .-1 }
+ int h : 1 || new int { 0 };
+ int i = g + a;
+};
+S c;
+template <bool V, int W>
+struct U {
+ int j : W = 3 * a; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int k : W { j + a }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ // { dg-warning "narrowing conversion of" "" { target *-*-* } .-1 }
+ int l : V ? 7 : a = 3;
+ int m : (V ? W : b) = k + a; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ int n : (V ? W : b) { m + a }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } }
+ // { dg-warning "narrowing conversion of" "" { target *-*-* } .-1 }
+ int o : 1 || new int { 0 };
+ int p = n + a;
+};
+U<true, 10> d;
+
+int
+main ()
+{
+ a = 1;
+ if (c.c != 4 || c.d != 6 || c.e != 0 || c.f != 8 || c.g != 10 || c.h != 0 || c.i != 12)
+ abort ();
+ if (d.j != 6 || d.k != 8 || d.l != 0 || d.m != 10 || d.n != 12 || d.o != 0 || d.p != 14)
+ abort ();
+ S s;
+ U<true, 10> u;
+ if (s.c != 2 || s.d != 3 || s.f != 4 || s.g != 5 || s.i != 6)
+ abort ();
+ if (u.j != 3 || u.k != 4 || u.m != 5 || u.n != 6 || u.p != 7)
+ abort ();
+}
Jakub
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [C++ PATCH] C++2A P0683R1 - default member initializers for bit-fields (take 2)
2017-09-29 12:27 ` [C++ PATCH] C++2A P0683R1 - default member initializers for bit-fields (take 2) Jakub Jelinek
@ 2017-09-29 14:15 ` Nathan Sidwell
0 siblings, 0 replies; 12+ messages in thread
From: Nathan Sidwell @ 2017-09-29 14:15 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: Jason Merrill, gcc-patches
On 09/29/2017 05:26 AM, Jakub Jelinek wrote:
> Hi!
>
> On Wed, Sep 27, 2017 at 07:55:20AM -0700, Nathan Sidwell wrote:
>> 1) fix the parsing bug you found and move to (ab)using
>> DECL_BIT_FIELD_REPRESENTATIVE
>>
>> 2) the new c++2a feature
>
> And here is the 2) patch, on top of the previous 3 ones.
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Ok. One nit ...
> --- gcc/cp/decl2.c.jj 2017-09-29 09:57:12.586423527 +0200
> +++ gcc/cp/decl2.c 2017-09-29 10:24:26.864372956 +0200
> @@ -978,10 +978,11 @@ grokfield (const cp_declarator *declarat
>
> tree
> grokbitfield (const cp_declarator *declarator,
> - cp_decl_specifier_seq *declspecs, tree width,
> + cp_decl_specifier_seq *declspecs, tree width, tree init,
> tree attrlist)
The new parm needs documenting. I notice the current description of
WIDTH is wonky:
WIDTH is non-NULL for bit fields only, and is an INTEGER_CST node.
while true, makes one wonder if it could be NULL. Feel free to make
that comment saner.
thanks
nathan
--
Nathan Sidwell
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2017-09-29 14:15 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-19 12:54 [C++ PATCH] C++2A P0386R1 - default member initializers for bit-fields Jakub Jelinek
2017-09-19 12:59 ` Tim Song
2017-09-19 13:01 ` Jakub Jelinek
2017-09-27 14:55 ` Nathan Sidwell
2017-09-28 18:47 ` [C++ PATCH] Fix attribute parsing for bitfields Jakub Jelinek
2017-09-28 23:37 ` Nathan Sidwell
2017-09-28 18:49 ` [C++ PATCH] Stash bitfield width into DECL_BIT_FIELD_REPRESENTATIVE instead of DECL_INITIAL Jakub Jelinek
2017-09-28 23:28 ` Nathan Sidwell
2017-09-28 18:51 ` [C++ PATCH] Let make check-c++-all test also c++2a Jakub Jelinek
2017-09-28 23:38 ` Nathan Sidwell
2017-09-29 12:27 ` [C++ PATCH] C++2A P0683R1 - default member initializers for bit-fields (take 2) Jakub Jelinek
2017-09-29 14:15 ` Nathan Sidwell
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).