]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/32346 (long long bitfield passed to int argument incorrectly)
authorMark Mitchell <mark@codesourcery.com>
Fri, 27 Jul 2007 21:46:33 +0000 (21:46 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 27 Jul 2007 21:46:33 +0000 (21:46 +0000)
PR c++/32346
* call.c (convert_for_arg_passing): Only widen bitfields to their
declared types if necessary.
PR c++/32346
* g++.dg/expr/bitfield9.C: New test.

From-SVN: r126999

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/expr/bitfield9.C [new file with mode: 0644]

index 0cce9080c734ddc04de66da2ee93420b5938e716..9be0feb488f01ca9deca2adba0f60bfd0922956f 100644 (file)
@@ -1,3 +1,9 @@
+2007-07-27  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/32346
+       * call.c (convert_for_arg_passing): Only widen bitfields to their
+       declared types if necessary.
+
 2007-07-24  Paolo Carlini  <pcarlini@suse.de>
 
        PR c++/30535
index 862c3d0ecca122b369c1377ac47cd339107839fd..848f3c894c8e53f748bbe5339211431bdd9da0fb 100644 (file)
@@ -4674,7 +4674,27 @@ type_passed_as (tree type)
 tree
 convert_for_arg_passing (tree type, tree val)
 {
-  val = convert_bitfield_to_declared_type (val);
+  tree bitfield_type;
+
+  /* If VAL is a bitfield, then -- since it has already been converted
+     to TYPE -- it cannot have a precision greater than TYPE.  
+
+     If it has a smaller precision, we must widen it here.  For
+     example, passing "int f:3;" to a function expecting an "int" will
+     not result in any conversion before this point.
+
+     If the precision is the same we must not risk widening.  For
+     example, the COMPONENT_REF for a 32-bit "long long" bitfield will
+     often have type "int", even though the C++ type for the field is
+     "long long".  If the value is being passed to a function
+     expecting an "int", then no conversions will be required.  But,
+     if we call convert_bitfield_to_declared_type, the bitfield will
+     be converted to "long long".  */
+  bitfield_type = is_bitfield_expr_with_lowered_type (val);
+  if (bitfield_type 
+      && TYPE_PRECISION (TREE_TYPE (val)) < TYPE_PRECISION (type))
+    val = convert_to_integer (TYPE_MAIN_VARIANT (bitfield_type), val);
+
   if (val == error_mark_node)
     ;
   /* Pass classes with copy ctors by invisible reference.  */
index b85440c001db637ee33cd5d542b7648e58780407..e6947a64201df185895d91a562018a7aaf91b9b6 100644 (file)
@@ -1,3 +1,8 @@
+2007-07-27  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/32346
+       * g++.dg/expr/bitfield9.C: New test.
+
 2007-07-25  Dorit Nuzman  <dorit@il.ibm.com>
            Devang Patel  <dpatel@apple.com>
            Uros Bizjak  <ubizjak@gmail.com>
diff --git a/gcc/testsuite/g++.dg/expr/bitfield9.C b/gcc/testsuite/g++.dg/expr/bitfield9.C
new file mode 100644 (file)
index 0000000..047b1bf
--- /dev/null
@@ -0,0 +1,25 @@
+// PR c++/32346
+// { dg-do run }
+
+extern "C" void abort();
+
+struct S {
+  long long i : 32;
+};
+
+void f(int i, int j) {
+  if (i != 0xabcdef01)
+    abort();
+  if (j != 0)
+    abort();
+}
+
+void g(S s) {
+  f(s.i, 0);
+}
+
+int main() {
+  S s;
+  s.i = 0xabcdef01;
+  g(s);
+}