Bug 38007 - [4.2/4.3 Regression] g++ instantiate same operator twice due to bitfield in -O0 mode, causing symbol already defined assembler error
Summary: [4.2/4.3 Regression] g++ instantiate same operator twice due to bitfield in -...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.2.4
: P1 critical
Target Milestone: 4.3.3
Assignee: Jason Merrill
URL:
Keywords: assemble-failure
Depends on:
Blocks:
 
Reported: 2008-11-03 19:23 UTC by Jeng-Liang Tsai
Modified: 2009-04-29 15:19 UTC (History)
6 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.1.1 4.4.0
Known to fail: 4.3.0
Last reconfirmed: 2008-11-07 22:24:09


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jeng-Liang Tsai 2008-11-03 19:23:25 UTC
Following code produces symbol already defined assembler error when compiled with g++ 4.2.4 with -O0 flag.  It can compile without problem with g++ 4.1.1.

=== foo.hpp ===
class foo {
    public:
        template <typename T> operator T ();
};
 
template <typename T>
    inline foo::operator T () {
        return (T)0;
    }
 
=== foo.cpp ===
#include "foo.hpp"
 
struct bar {
    unsigned int _bar : 24;
};
 
int main() {
    foo a;
    unsigned int b = a;
    bar c;
    c._bar = a;
    return 1;
}

====
compile with g++ -O0 foo.cpp

Regards,
Jeng-Liang
Comment 1 Andrew Pinski 2008-11-03 20:07:32 UTC
Confirmed, a regression from GCC 4.1.1.
Here is a self contained example :):
class foo {
    public:
        template <typename T> operator T ();
};

template <typename T>
    inline foo::operator T () {
        return (T)0;
    }

struct bar {
    unsigned int _bar : 24;
};

int main() {
    foo a;
    unsigned int b = a;
    bar c;
    c._bar = a;
    return 1;
}
Comment 2 Richard Biener 2008-11-04 10:39:42 UTC
The following also fails the same way with optimization:

class foo {
public:
    template <typename T> __attribute__((noinline))
    operator T () { return (T)0; }
};

struct bar {
    unsigned int _bar : 24;
};

int main()
{
    foo a;
    unsigned int b = a;
    bar c;
    c._bar = a;
    return 0;
}


we instantiate the operator for unsigned int and unsigned int : 24

what we probably should do is treat

  c._bar = a;

as

  c._bar = (unsigned int : 24)(unsigned int)a;

instead.
Comment 3 Jakub Jelinek 2008-11-06 15:15:31 UTC
And for:
struct A
{
  template <typename T> __attribute__((noinline)) operator T ()
  {
    return (T) 0;
  }
};

struct B
{
  unsigned int b : 8;
};

int
main ()
{
  A u;
  unsigned int v = u;
  B w;
  w.b = u;
}

we instantiate both
A::operator unsigned int<unsigned int>()
A::operator unsigned char<unsigned char>()
Shouldn't it use unsigned int conversion in both cases as well, or is it allowed (or required) to use the lowered type?  I see 3.4 through 4.4 all use unsigned char, if RHS' type isn't MAYBE_CLASS_TYPE_P, then I understand it, but for
class RHS it is an important difference.

I believe the place which needs to be revisited is cp_build_modify_expr, if is_bitfield_expr_with_lowered_type use the type returned by that in convert_for_assignment.  But I'm e.g. confused by:

  /* 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));
...
    }

That seems like a remnant from the past, as get_unwidened for COMPONENT_REF does
nothing but return the passed object.  See http://gcc.gnu.org/ml/gcc-patches/2008-03/msg01621.html
Comment 4 Jason Merrill 2008-11-12 20:52:10 UTC
Subject: Bug 38007

Author: jason
Date: Wed Nov 12 20:50:45 2008
New Revision: 141800

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=141800
Log:
        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.                                                   

Added:
    trunk/gcc/testsuite/g++.dg/conversion/bitfield10.C
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/c-common.c
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/typeck.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/g++.dg/expr/bitfield9.C
    trunk/gcc/testsuite/g++.dg/warn/pr35635.C
    trunk/gcc/testsuite/g++.old-deja/g++.mike/enum1.C

Comment 5 Jason Merrill 2008-11-12 22:09:44 UTC
Subject: Bug 38007

Author: jason
Date: Wed Nov 12 22:08:01 2008
New Revision: 141808

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=141808
Log:
        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.                                                   

Added:
    branches/gcc-4_3-branch/gcc/testsuite/g++.dg/conversion/bitfield10.C
      - copied unchanged from r141800, trunk/gcc/testsuite/g++.dg/conversion/bitfield10.C
Modified:
    branches/gcc-4_3-branch/gcc/ChangeLog
    branches/gcc-4_3-branch/gcc/c-common.c
    branches/gcc-4_3-branch/gcc/cp/ChangeLog
    branches/gcc-4_3-branch/gcc/cp/typeck.c
    branches/gcc-4_3-branch/gcc/testsuite/ChangeLog
    branches/gcc-4_3-branch/gcc/testsuite/g++.dg/expr/bitfield9.C
    branches/gcc-4_3-branch/gcc/testsuite/g++.old-deja/g++.mike/enum1.C

Comment 6 Jason Merrill 2008-11-12 22:14:57 UTC
Subject: Bug 38007

Author: jason
Date: Wed Nov 12 22:13:26 2008
New Revision: 141809

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=141809
Log:
        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.                                                   

Added:
    branches/gcc-4_2-branch/gcc/testsuite/g++.dg/conversion/bitfield10.C
      - copied unchanged from r141800, trunk/gcc/testsuite/g++.dg/conversion/bitfield10.C
Modified:
    branches/gcc-4_2-branch/gcc/ChangeLog
    branches/gcc-4_2-branch/gcc/c-common.c
    branches/gcc-4_2-branch/gcc/cp/ChangeLog
    branches/gcc-4_2-branch/gcc/cp/typeck.c
    branches/gcc-4_2-branch/gcc/testsuite/ChangeLog
    branches/gcc-4_2-branch/gcc/testsuite/g++.dg/expr/bitfield9.C
    branches/gcc-4_2-branch/gcc/testsuite/g++.old-deja/g++.mike/enum1.C

Comment 7 Jason Merrill 2008-11-12 22:15:31 UTC
Fixed on all open branches.