Bug 43663 - Can't take a const-ref to a bit field
Summary: Can't take a const-ref to a bit field
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.3.2
: P3 normal
Target Milestone: 4.7.0
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2010-04-06 10:49 UTC by Daryl Haresign
Modified: 2012-10-11 02:37 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.7.0, 4.8.0
Known to fail: 2.95.4, 4.5.0
Last reconfirmed: 2010-04-06 10:57:58


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Daryl Haresign 2010-04-06 10:49:20 UTC
Given the code below, gcc emits the following error:

error: attempt to take address of bit-field structure member 'MyClass::field1'

This compiles fine with Sun's CC, IBM's xlC, and Comeau. The C++ 2003 standard mentions in 9.6p2 that a non-const reference can't be bound to a bit field, but that a const reference can be (although it's actually bound to a temporary initialized with a copy of the bit field rather than the field itself) so I expect the below code to work fine.

// Code
class MyClass
{
public:
  MyClass() { field1 = 0; };
  int field1 : 4;
};

int main()
{
  MyClass myClass;

  const int &fieldRef1 = myClass.field1;

  return 0;
}
Comment 1 Richard Biener 2010-04-06 10:57:58 UTC
Confirmed.  Note that the frontend would need to make sure to unfold the
reference for the middle-end - the middle-end can't bear taking the address
of a bitfield.
Comment 2 Steven Bosscher 2010-04-06 11:01:30 UTC
Wow, taking the address of a bit field. That can only be C++. This should be closed as a dup of bug 5...  Oh, well... :-)
Comment 3 Paolo Carlini 2010-04-06 11:05:49 UTC
Why C++0x?!?
Comment 4 Jonathan Wakely 2010-04-06 11:38:27 UTC
Noone's taking the address of a bitfield, the stnadard specifically says "The address-of operator & shall not be applied to a bit-field, so there are no pointers to bit-fields."

What happens is the same as:

double d = 0;
const int& i = d;

a temporary is created and the reference bound to it.

And this definitely isn't new in C++0x! The reference for C++03 should be 9.6p3 rather than p2
Comment 5 Jason Merrill 2010-04-07 21:19:37 UTC
Long-standing bug.
Comment 6 James Dennett 2011-05-15 11:52:01 UTC
Here's a quick hack that causes a temporary to be generated when binding a bit-field to a reference-to-const.

$ svn diff
Index: call.c
===================================================================
--- call.c	(revision 173769)
+++ call.c	(working copy)
@@ -8594,7 +8594,7 @@
 	expr = error_mark_node;
       else
 	{
-	  if (!lvalue_or_rvalue_with_address_p (expr))
+	  if (is_bitfield_expr_with_lowered_type (expr) || !lvalue_or_rvalue_with_address_p (expr))
 	    {
 	      tree init;
 	      var = set_up_extended_ref_temp (decl, expr, cleanup, &init);

I'll try to make time to clean that up and add regression tests before running it by someone with stronger gcc-fu.
Comment 7 James Dennett 2011-05-15 11:55:47 UTC
Unsurprisingly the quick hack isn't really good enough -- it'll happily bind a non-const reference to a temporary initialized from a bitfield.  (...and I guess that's why we have tests, and code reviews.)
Comment 8 James Dennett 2011-05-15 12:34:51 UTC
Interestingly this works with Apple's g++ 4.2.1, specifically i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3), but not with their 4.0.1 release.

Tested with:

int main() {
  struct S {
    S(): i(0) {}
    int i : 3;
  };
  S s;
  printf("&s: %p\n", (void*)&s);
  int const& cr(s.i);  // should compile, binding to a temporary
  printf("&cr: %p\n", (void*)&cr);
}

A non-const reference still correctly gives an error:
st.cc:12: error: invalid initialization of reference of type ‘int&’ from expression of type ‘signed char:3’
Comment 9 Paolo Carlini 2012-10-11 01:42:19 UTC
This is fixed in 4.7.0. I'm adding the testcase and closing the PR.
Comment 10 paolo@gcc.gnu.org 2012-10-11 02:34:39 UTC
Author: paolo
Date: Thu Oct 11 02:34:32 2012
New Revision: 192347

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=192347
Log:
2012-10-10  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/43663
	* g++.dg/init/bitfield3.C: New.

Added:
    trunk/gcc/testsuite/g++.dg/init/bitfield3.C
Modified:
    trunk/gcc/testsuite/ChangeLog
Comment 11 Paolo Carlini 2012-10-11 02:37:29 UTC
Done.