public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* C++ PATCH for c++/38007
@ 2008-11-12 21:05 Jason Merrill
  0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2008-11-12 21:05 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 277 bytes --]

When we changed the type of bitfield FIELD_DECLs to reflect the range 
allowed by the bitfield, we didn't update cp_build_modify_expr 
accordingly.  This patch does that.

Tested x86_64-pc-linux-gnu, applied to trunk.  I'll test and apply to 
4.3 and 4.2 as well as they pass.

[-- Attachment #2: 38007.patch --]
[-- Type: text/x-patch, Size: 8562 bytes --]

2008-11-12  Jason Merrill  <jason@redhat.com>

	PR c++/38007
gcc/cp/
	* typeck.c (cp_build_modify_expr): Update bitfield handling.
gcc/
	* c-common.c (c_common_signed_or_unsigned_type): Remove C++
	special casing.
gcc/testsuite/
	* g++.dg/conversion/bitfield10.C: New test.
	* g++.dg/warn/pr35635.C (func1): Accept additional warning.
	* g++.old-deja/g++.mike/enum1.C: Expect warn about assignment.
	* g++.dg/expr/bitfield9.C: Pass -Wno-overflow.

Index: cp/typeck.c
===================================================================
*** cp/typeck.c	(revision 141769)
--- cp/typeck.c	(working copy)
*************** cp_build_modify_expr (tree lhs, enum tre
*** 5801,5807 ****
    tree newrhs = rhs;
    tree lhstype = TREE_TYPE (lhs);
    tree olhstype = lhstype;
-   tree olhs = NULL_TREE;
    bool plain_assign = (modifycode == NOP_EXPR);
  
    /* Avoid duplicate error messages from operands that had errors.  */
--- 5801,5806 ----
*************** cp_build_modify_expr (tree lhs, enum tre
*** 6005,6039 ****
  	return error_mark_node;
      }
  
!   /* If storing into a structure or union member, it has probably been
!      given type `int'.  Compute the type that would go with the actual
!      amount of storage the member occupies.  */
  
!   if (TREE_CODE (lhs) == COMPONENT_REF
!       && (TREE_CODE (lhstype) == INTEGER_TYPE
! 	  || TREE_CODE (lhstype) == REAL_TYPE
! 	  || TREE_CODE (lhstype) == ENUMERAL_TYPE))
!     {
!       lhstype = TREE_TYPE (get_unwidened (lhs, 0));
! 
!       /* If storing in a field that is in actuality a short or narrower
! 	 than one, we must store in the field in its actual type.  */
! 
!       if (lhstype != TREE_TYPE (lhs))
! 	{
! 	  /* Avoid warnings converting integral types back into enums for
! 	     enum bit fields.  */
! 	  if (TREE_CODE (lhstype) == INTEGER_TYPE
! 	      && TREE_CODE (olhstype) == ENUMERAL_TYPE)
! 	    {
! 	      if (TREE_SIDE_EFFECTS (lhs))
! 		lhs = stabilize_reference (lhs);
! 	      olhs = lhs;
! 	    }
! 	  lhs = copy_node (lhs);
! 	  TREE_TYPE (lhs) = lhstype;
! 	}
!     }
  
    /* Convert new value to destination type.  */
  
--- 6004,6014 ----
  	return error_mark_node;
      }
  
!   /* If storing into a structure or union member, it may have been given a
!      lowered bitfield type.  We need to convert to the declared type first,
!      so retrieve it now.  */
  
!   olhstype = unlowered_expr_type (lhs);
  
    /* Convert new value to destination type.  */
  
*************** cp_build_modify_expr (tree lhs, enum tre
*** 6073,6094 ****
      }
  
    if (modifycode == INIT_EXPR)
!     newrhs = convert_for_initialization (lhs, lhstype, newrhs, LOOKUP_NORMAL,
  					 "initialization", NULL_TREE, 0,
                                           complain);
    else
      {
-       /* Avoid warnings on enum bit fields.  */
-       if (TREE_CODE (olhstype) == ENUMERAL_TYPE
- 	  && TREE_CODE (lhstype) == INTEGER_TYPE)
- 	{
- 	  newrhs = convert_for_assignment (olhstype, newrhs, "assignment",
- 					   NULL_TREE, 0, complain);
- 	  newrhs = convert_force (lhstype, newrhs, 0);
- 	}
-       else
- 	newrhs = convert_for_assignment (lhstype, newrhs, "assignment",
- 					 NULL_TREE, 0, complain);
        if (TREE_CODE (newrhs) == CALL_EXPR
  	  && TYPE_NEEDS_CONSTRUCTING (lhstype))
  	newrhs = build_cplus_new (lhstype, newrhs);
--- 6048,6065 ----
      }
  
    if (modifycode == INIT_EXPR)
!     newrhs = convert_for_initialization (lhs, olhstype, newrhs, LOOKUP_NORMAL,
  					 "initialization", NULL_TREE, 0,
                                           complain);
    else
+     newrhs = convert_for_assignment (olhstype, newrhs, "assignment",
+ 				     NULL_TREE, 0, complain);
+ 
+   if (!same_type_p (lhstype, olhstype))
+     newrhs = cp_convert_and_check (lhstype, newrhs);
+ 
+   if (modifycode != INIT_EXPR)
      {
        if (TREE_CODE (newrhs) == CALL_EXPR
  	  && TYPE_NEEDS_CONSTRUCTING (lhstype))
  	newrhs = build_cplus_new (lhstype, newrhs);
*************** cp_build_modify_expr (tree lhs, enum tre
*** 6120,6140 ****
    if (!plain_assign)
      TREE_NO_WARNING (result) = 1;
  
!   /* If we got the LHS in a different type for storing in,
!      convert the result back to the nominal type of LHS
!      so that the value we return always has the same type
!      as the LHS argument.  */
! 
!   if (olhstype == TREE_TYPE (result))
!     return result;
!   if (olhs)
!     {
!       result = build2 (COMPOUND_EXPR, olhstype, result, olhs);
!       TREE_NO_WARNING (result) = 1;
!       return result;
!     }
!   return convert_for_assignment (olhstype, result, "assignment",
! 				 NULL_TREE, 0, complain);
  }
  
  tree
--- 6091,6097 ----
    if (!plain_assign)
      TREE_NO_WARNING (result) = 1;
  
!   return result;
  }
  
  tree
Index: c-common.c
===================================================================
*** c-common.c	(revision 141769)
--- c-common.c	(working copy)
*************** c_common_signed_or_unsigned_type (int un
*** 2719,2725 ****
  
  #define TYPE_OK(node)							    \
    (TYPE_MODE (type) == TYPE_MODE (node)					    \
!    && (c_dialect_cxx () || TYPE_PRECISION (type) == TYPE_PRECISION (node)))
    if (TYPE_OK (signed_char_type_node))
      return unsignedp ? unsigned_char_type_node : signed_char_type_node;
    if (TYPE_OK (integer_type_node))
--- 2719,2725 ----
  
  #define TYPE_OK(node)							    \
    (TYPE_MODE (type) == TYPE_MODE (node)					    \
!    && TYPE_PRECISION (type) == TYPE_PRECISION (node))
    if (TYPE_OK (signed_char_type_node))
      return unsignedp ? unsigned_char_type_node : signed_char_type_node;
    if (TYPE_OK (integer_type_node))
*************** c_common_signed_or_unsigned_type (int un
*** 2749,2758 ****
      return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
  #undef TYPE_OK
  
!   if (c_dialect_cxx ())
!     return type;
!   else
!     return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
  }
  
  /* Build a bit-field integer type for the given WIDTH and UNSIGNEDP.  */
--- 2749,2755 ----
      return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
  #undef TYPE_OK
  
!   return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
  }
  
  /* Build a bit-field integer type for the given WIDTH and UNSIGNEDP.  */
Index: testsuite/g++.old-deja/g++.mike/enum1.C
===================================================================
*** testsuite/g++.old-deja/g++.mike/enum1.C	(revision 141769)
--- testsuite/g++.old-deja/g++.mike/enum1.C	(working copy)
*************** struct Type {
*** 8,11 ****
    void setBTK();
  };
  
! void Type::setBTK() { kind = DTK; }
--- 8,11 ----
    void setBTK();
  };
  
! void Type::setBTK() { kind = DTK; } // { dg-warning "truncate" }
Index: testsuite/g++.dg/warn/pr35635.C
===================================================================
*** testsuite/g++.dg/warn/pr35635.C	(revision 141769)
--- testsuite/g++.dg/warn/pr35635.C	(working copy)
*************** void func1()
*** 32,38 ****
    /* At least one branch of ? does not fit in the destination, thus
       warn.  */
    unsigned_bit.x = bar != 0 ? 2 : 0; /* { dg-warning "conversion" } */
!   unsigned_bit.x = bar != 0 ? 0 : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
  }
  
  void func2()
--- 32,38 ----
    /* At least one branch of ? does not fit in the destination, thus
       warn.  */
    unsigned_bit.x = bar != 0 ? 2 : 0; /* { dg-warning "conversion" } */
!   unsigned_bit.x = bar != 0 ? 0 : -1; /* { dg-warning "conver" } */
  }
  
  void func2()
Index: testsuite/g++.dg/expr/bitfield9.C
===================================================================
*** testsuite/g++.dg/expr/bitfield9.C	(revision 141769)
--- testsuite/g++.dg/expr/bitfield9.C	(working copy)
***************
*** 1,5 ****
--- 1,6 ----
  // PR c++/32346
  // { dg-do run }
+ // { dg-options "-Wno-overflow" }
  
  extern "C" void abort();
  
Index: testsuite/g++.dg/conversion/bitfield10.C
===================================================================
*** testsuite/g++.dg/conversion/bitfield10.C	(revision 0)
--- testsuite/g++.dg/conversion/bitfield10.C	(revision 0)
***************
*** 0 ****
--- 1,24 ----
+ // PR c++/38007
+ // We need to use the conversion function to the declared type of a bitfield,
+ // not the lowered bitfield type.
+ // { dg-do link }
+ 
+ struct A
+ {
+   operator unsigned int() { return 42; }
+   operator unsigned char();
+ };
+ 
+ struct B
+ {
+   unsigned int b : 8;
+ };
+ 
+ int
+ main ()
+ {
+   A u;
+   unsigned int v = u;
+   B w;
+   w.b = u;
+ }

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2008-11-12 20:50 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-11-12 21:05 C++ PATCH for c++/38007 Jason Merrill

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).