This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ PATCH] C++2A P0386R1 - default member initializers for bit-fields


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]