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]

[3.4 PATCH] PR 16693: TYPE_PRECISION of C++ enums


I was hoping I could just forward port Alexandre Oliva's fix for
PR c++/11667 from the gcc-3_3-branch
http://gcc.gnu.org/ml/gcc-patches/2003-07/msg02359.html
But unfortunately it looks like someone's completely rewritten
the g++ front-end since then :>

The following single line patch achieves exactly the same thing.
As explained in the comment, this tweaks cp/decl.c's finish_enum
such that we once again set the TYPE_PRECISION of enumerated types
to be the same as the width of the underlying integer type.  This
was changed with Mark's fix to implement DR377 thereby fixing PR
10796.  Unfortunately, the inability of GCC's middle-end to
describe "unextended" types has caused a plethora of middle-end
optimization issues.


My proposal is to commit this to the gcc-3_4-branch, and once
testing has completed, also to mainline.  Then on mainline use an
extra bit in a type to distinguish "extended" from "paradoxical"
fractional integers (where TYPE_PRECISION(t) < GET_MODE_BITSIZE)
to differentiate C++ enums from scalarized C/C++ bitfields.  Next
convert the existing constant folding workarounds to check this
flag.  Add similar checks to the remaining unsafe transformations.
Then possibly add the necessary RTL expansion code to insert
masking and/or sign extension instructions as necessary.

At that point the middle-end should be able to handle both
constrained and unconstrained fractional integer types.  So
whatever the outcome of the current language lawyer discussions
or ISO C++ DR, the g++ front-end will be able to specify to the
middle-end exactly which behaviour is required, perhaps even
controlled by a new command line option.


The following patch has been tested on i686-pc-linux-gnu against
the gcc-3_4-branch with a full "make bootstrap", all default
languages, and regression tested with a top-level "make -k check"
with no new failures.  Three of the four new test cases fail
without this patch, but all pass with it.  [The fourth currently
also fails on mainline, and should be fixed by this patch].

Ok for 3.4.2?  Ok for mainline after additional testing passes
there?



2004-08-25  Roger Sayle  <roger@eyesopen.com>

	PR middle-end/16693
	PR tree-optimization/16372
	* decl.c (finish_enum): Make the precision of the enumerated
	type the same width as the underlying integer type.

	* g++.dg/opt/enum2.C: New test case.
	* g++.dg/opt/pr16372-1.C: New test case.
	* g++.dg/opt/pr16693-1.C: New test case.
	* g++.dg/opt/pr16693-2.C: New test case.


Index: decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1174.2.22
diff -c -3 -p -r1.1174.2.22 decl.c
*** decl.c	2 Aug 2004 01:56:27 -0000	1.1174.2.22
--- decl.c	25 Aug 2004 03:40:44 -0000
*************** finish_enum (tree enumtype)
*** 9861,9867 ****
       underlying type in the range bmin to bmax, where bmin and bmax are,
       respectively, the smallest and largest values of the smallest bit-
       field that can store emin and emax.  */
!   TYPE_PRECISION (enumtype) = precision;
    set_min_and_max_values_for_integral_type (enumtype, precision, unsignedp);

    /* [dcl.enum]
--- 9861,9874 ----
       underlying type in the range bmin to bmax, where bmin and bmax are,
       respectively, the smallest and largest values of the smallest bit-
       field that can store emin and emax.  */
!
!   /* The middle-end currently assumes that types with TYPE_PRECISION
!      narrower than their underlying type are suitably zero or sign
!      extended to fill their mode.  g++ doesn't make these guarantees.
!      Until the middle-end can represent such paradoxical types, we
!      set the TYPE_PRECISON to the width of the underlying type.  */
!   TYPE_PRECISION (enumtype) = TYPE_PRECISION (underlying_type);
!
    set_min_and_max_values_for_integral_type (enumtype, precision, unsignedp);

    /* [dcl.enum]


// http://gcc.gnu.org/ml/gcc/2004-08/msg01129.html
// { dg-do run }
// { dg-options "-O2" }

extern "C" void abort(void);

enum E { e = 0x0f };

void test(int n)
{
  enum E x, y;

  x = (E)0x10;
  y = (E)n;

  if (x != y)
    abort ();
}

int main()
{
  test(0x10);
  return 0;
}



// PR tree-optimization/16372
// { dg-do run }
// { dg-options "-O1" }

extern "C" void abort();

enum number {ZERO, ONE, TWO, THREE, FOUR, FIVE};

int main() {
  number n = FIVE;

  if((n == ONE) || (n == TWO) || (n == THREE)) {
    abort ();
  }
  return 0;
}


// PR middle-end/16693
// { dg-do run }
// { dg-options "-O2" }

extern "C" void abort();

unsigned short ret6666(int) {
    return 0x66;
}

typedef enum {
    a   = 0x0, b   = 0x1, c   = 0x2, d   = 0x3, e   = 0x4, f   = 0x5,
    g   = 0x6, h   = 0x7, i   = 0x8, j   = 0x9, k   = 0xa, l   = 0xb,
    m   = 0xc, n   = 0xd, o   = 0xe, p   = 0xf
} Test_Enum;

int main(void) {
    unsigned char r1;
    r1 = static_cast<Test_Enum>(0xf & ret6666(44));

    if(r1 != 0x6)
        abort();
    return 0;
}


// PR middle-end/16693
// { dg-do run }
// { dg-options "-O2" }

extern "C" void abort();

char foo()
{
  return 0x10;
}

enum E { e = 0x0f };

int main()
{
  char c = (char)(E)(e & foo());
  if (c != 0)
    abort();
  return 0;
}


Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


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