This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/36170] New: enum variable operation behaviour and -O2
- From: "john dot spelis at 3dlabs dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 7 May 2008 15:01:34 -0000
- Subject: [Bug c++/36170] New: enum variable operation behaviour and -O2
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
The following program shows a case where
the 4.3.0 C++ compiler omits a check on an ENUM
variable when compiled with -O2 but keeps it when
-O is used ?
Targets where this occurs; at least x86, arm-*-linux-*
optEnum = (Options::Id::Type) getopt_long( ... ) ;
if( optEnum == -1 ) /* This test skipped with -O2 but not -O */
break;
switch( optEnum ) {
:
}
The workaround for this "bug" is explicitly set
an enum value of -1
i.e.
enum Type {
eHelp = 'h',
::
Dummy = -1 /* fixes issue */
}
Some people say this is an interpretation of the C++ Spec
but why does the program behaviour change so radically
with/without the optimiser and without any warnings ?
This behviour is reproducible with the attached program on
an x86 build of 4.3.0
E.g.
./configure --enable-languages=c,c++ --prefix=/tmp/gcc
g++ -O -o m m.cxx
./m -> program runs and exit's
g++ -O2 -o m m.cxx
./m -> program prints -1 forever
=====
m.cxx
=====
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
typedef unsigned long uint32_t ;
typedef unsigned char uint8_t ;
#define ANSI_BOLD ""
#define ANSI_RED ""
#define ANSI_RESET ""
#define HAVE_GETOPT 1
class Background {
public:
enum Type {
eMandel = 0,
eGrid,
eFlat,
eGouraud,
};
};
class Options {
public:
Options( void ) {
memset( this, 0x00, sizeof(*this) );
bailOut = 4;
maxIteration = 240;
size[0] = 64;
size[1] = 32;
surfSize[0] = size[0];
surfSize[1] = size[1];
offset[0] = 0;
offset[1] = 0;
coordX[0] = -2;
coordX[1] = 2;
coordY[0] = -2;
coordY[1] = 2;
bRandomColours = true;
background = Background::eMandel;
#if USE_HARDWARE
bUseTCSET = true;
#endif
}
bool bAnimate;
bool bUseGUI;
bool bSetMode;
bool bListModes;
bool bDumpImage;
bool bUseTCSET;
bool bWantClears;
bool bRandomColours;
bool bFixedAspect;
bool bFullScreen;
bool bSingleBuffer;
uint32_t modeX, modeY;
uint32_t vidDevice;
uint32_t vidRotate;
uint32_t bailOut;
uint32_t maxIteration;
uint32_t loopCount;
uint32_t size[2];
uint32_t surfSize[2];
uint32_t offset[2];
float coordX[2];
float coordY[2];
Background::Type background;
bool bStall;
uint32_t benchmarkMode;
};
bool gVerbose = false;
bool gVeryVerbose = false;
bool gAbortNow = false;
bool processArgs( int argc, char *const argv[], Options &opts )
{
#if HAVE_GETOPT
class Options {
public:
class Id {
public:
enum Type {
eHelp = 'h',
eHelpL = 1,
eSize,
eCoords,
eCoordSet,
eClearFirst,
eBail,
eMaxIt,
eColourMap,
eAnimate,
eSetMode,
eLoop,
eFullScreen,
eListModes,
eOffset,
eAspect,
eDemo,
eNoSync,
eVidDevice,
eNoTCSET,
eGUI,
eDumpImage,
eBackground,
eRotate,
eVerbose,
eStall,
eBench,
#if 0 /* set to '1' as workaround */
eDummy = -1
#endif
};
};
class Args {
public:
enum Type {
eNone,
eReq,
eOpt,
};
};
const char *name;
Options::Args::Type args;
Id::Type id;
const char *help;
};
Options::Id::Type optEnum;
int optIndex;
uint32_t i;
bool bSuccess = true;
static Options options[] = {
{ "help", Options::Args::eNone, Options::Id::eHelp,
"Show this help message" },
{ "size", Options::Args::eReq, Options::Id::eSize,
"Size of rendered image" },
{ "coords", Options::Args::eReq, Options::Id::eCoords,
"Co-ordinates of rendered image" },
{ "coordSet", Options::Args::eReq, Options::Id::eCoordSet,
"Select a predefined set of co-ordinates" },
{ "clearFirst", Options::Args::eNone,
Options::Id::eClearFirst, NULL },
{ "bail", Options::Args::eReq, Options::Id::eBail,
"Bailout value" },
{ "maxIt", Options::Args::eReq, Options::Id::eMaxIt,
"Maximum iteration count" },
{ "colourMap", Options::Args::eReq, Options::Id::eColourMap,
"Set the colour style" },
{ "animate", Options::Args::eNone, Options::Id::eAnimate,
"Run in animation mode" },
{ "setMode", Options::Args::eOpt, Options::Id::eSetMode,
"Set the given video mode" },
{ "loop", Options::Args::eOpt, Options::Id::eLoop,
"Number of times to loop in animation mode" },
{ "fullScreen", Options::Args::eNone,
Options::Id::eFullScreen, "Buffer size matches video resolution even if render
size is smaller" },
{ "listModes", Options::Args::eNone, Options::Id::eListModes,
"List available video modes" },
{ "offset", Options::Args::eOpt, Options::Id::eOffset,
"Offset to render area if render size is smaller than video resolution" },
{ "aspect", Options::Args::eOpt, Options::Id::eAspect,
"Keep 1:1 aspect ratio or stretch to fill" },
{ "demo", Options::Args::eNone, Options::Id::eDemo,
"Enable demo mode (480x272 animation)" },
{ "noSync", Options::Args::eNone, Options::Id::eNoSync,
"Disable video sync by running single buffered" },
{ "vidDevice", Options::Args::eReq, Options::Id::eVidDevice,
"Use the given video device" },
{ "noTCSET", Options::Args::eNone, Options::Id::eNoTCSET,
"Do not use the TCSET ioctl" },
{ "gui", Options::Args::eNone, Options::Id::eGUI,
"Run in GUI mode" },
{ "dump", Options::Args::eNone, Options::Id::eDumpImage,
"Dump the rendered image as ascii text" },
{ "back", Options::Args::eReq,
Options::Id::eBackground, "Set the background style for animation mode" },
{ "rotate", Options::Args::eReq, Options::Id::eRotate,
"Rotate the video output by 90, 180, 270, FlipV, FlipH" },
{ "verbose", Options::Args::eNone, Options::Id::eVerbose,
"Enable debugging output" },
{ "stall", Options::Args::eNone, Options::Id::eStall,
"Stall on the first frame" },
{ "bench", Options::Args::eOpt, Options::Id::eBench,
"Benchmark mode" },
};
asm("L:");
while( 1 ) {
optEnum = (Options::Id::Type) getopt_long( argc, argv, "h",
NULL, &optIndex);
if( optEnum == -1 )
break;
switch( optEnum ) {
case Options::Id::eVerbose:
gVerbose = true;
gVeryVerbose = true;
continue;
case Options::Id::eHelp:
case Options::Id::eHelpL:
printf( "Mandelbrot options:\n" );
bSuccess = false;
continue;
case Options::Id::eBail:
opts.bailOut = atoi( optarg );
printf("Setting bail out to %d\n",
opts.bailOut);
continue;
case Options::Id::eMaxIt:
opts.maxIteration = atoi( optarg );
printf("Setting maximum iteration to %d\n",
opts.maxIteration);
continue;
case Options::Id::eColourMap:
opts.bRandomColours = atoi( optarg );
printf("Setting colour map to type #%d\n",
opts.bRandomColours);
continue;
case Options::Id::eCoordSet:
i = atoi(optarg);
switch( i ) {
case 0:
opts.coordX[0] = -2;
opts.coordX[1] = 2;
opts.coordY[0] = -2;
opts.coordY[1] = 2;
opts.bRandomColours = true;
break;
case 1:
opts.coordX[0] =
-0.55472656250f; opts.coordX[1] = 0.016328125f - 0.55472656250f;
opts.coordY[0] =
-0.50505859375f; opts.coordY[1] = 0.016328125f - 0.50505859375f;
opts.bRandomColours = false;
break;
default:
fprintf(stderr, ANSI_BOLD
ANSI_RED "Invalidate co-ordinate set request: %d!" ANSI_RESET "\n", i);
}
printf( "Coords set to (%f, %f) -> (%f, %f)\n",
opts.coordX[0], opts.coordY[0], opts.coordX[1], opts.coordY[1] );
continue;
case Options::Id::eSize:
sscanf( optarg, "%dx%d", &opts.size[0],
&opts.size[1] );
printf( "Size set to %d x %d\n", opts.size[0],
opts.size[1] );
continue;
case Options::Id::eOffset:
if( optarg ) {
sscanf( optarg, "%d,%d",
&opts.offset[0], &opts.offset[1] );
printf( "Offset set to (%d, %d)\n",
opts.offset[0], opts.offset[1] );
} else
opts.offset[0] = opts.offset[1] = ~0U;
continue;
case Options::Id::eCoords:
sscanf( optarg, "%f,%f,%f,%f", &opts.coordX[0],
&opts.coordY[0], &opts.coordX[1], &opts.coordY[1] );
printf( "Coords set to (%f, %f) -> (%f, %f)\n",
opts.coordX[0], opts.coordY[0], opts.coordX[1], opts.coordY[1] );
continue;
case Options::Id::eClearFirst:
opts.bWantClears = true;
continue;
case Options::Id::eAnimate:
opts.bAnimate = true;
continue;
case Options::Id::eGUI:
opts.bUseGUI = true;
continue;
case Options::Id::eDumpImage:
opts.bDumpImage = true;
continue;
case Options::Id::eSetMode:
opts.bSetMode = true;
if( optarg ) {
sscanf( optarg, "%dx%d", &opts.modeX,
&opts.modeY );
printf( "Mode size set to %d x %d\n",
opts.modeX, opts.modeY );
}
continue;
case Options::Id::eVidDevice:
sscanf( optarg, "%d", &opts.vidDevice );
printf( "Video device set to %d\n",
opts.vidDevice );
continue;
case Options::Id::eListModes:
opts.bListModes = true;
continue;
case Options::Id::eLoop:
if( optarg ) {
sscanf( optarg, "%d", &opts.loopCount
);
printf( "Loop count set to %d\n",
opts.loopCount );
opts.loopCount--;
} else
opts.loopCount = ~0;
continue;
case Options::Id::eFullScreen:
opts.bFullScreen = true;
continue;
case Options::Id::eAspect:
if( optarg ) {
sscanf( optarg, "%d", &i );
opts.bFixedAspect = i ? true : false;
printf( "Fixed aspect set to %d\n",
opts.bFixedAspect );
} else
opts.bFixedAspect = true;
continue;
case Options::Id::eNoSync:
opts.bSingleBuffer = true;
continue;
case Options::Id::eNoTCSET:
opts.bUseTCSET = false;
continue;
case Options::Id::eDemo:
if( gVerbose ) printf( "Running with demo options.\n" );
opts.bFixedAspect = true;
opts.bFullScreen = true;
opts.bAnimate = true;
opts.bSetMode = true;
opts.loopCount = 1;
opts.offset[0] = ~0U;
opts.offset[1] = ~0U;
opts.size[0] = 272;
opts.size[1] = 272;
continue;
case Options::Id::eBackground:
sscanf( optarg, "%d", &i );
opts.background = (Background::Type) i;
printf( "Background style set to %d\n",
opts.background );
continue;
case Options::Id::eRotate:
sscanf( optarg, "%d", &opts.vidRotate );
printf( "Video rotation set to %d\n",
opts.vidRotate );
continue;
case Options::Id::eStall:
opts.bStall = true;
continue;
case Options::Id::eBench:
if( optarg )
sscanf( optarg, "%d", &opts.benchmarkMode );
else
opts.benchmarkMode = 1;
printf( "Benchmark mode set to %d\n", opts.benchmarkMode );
continue;
default:
break;
}
fprintf(stderr, ANSI_BOLD ANSI_RED "Got unknown option id: %d!"
ANSI_RESET "\n", optEnum);
bSuccess = false;
}
return bSuccess;
#else
fprintf(stderr, ANSI_BOLD ANSI_RED "No getopt. Ignoring command line
arguments!" ANSI_RESET "\n");
return true;
#endif
}
int main( int argc, char *argv[] )
{
bool bSuccess = true;
const char *env;
class Options opts ;
if( !processArgs(argc, argv, opts) ) {
fprintf( stderr, ANSI_BOLD ANSI_RED "Failed to process command
line arguments!" ANSI_RESET "\n" );
bSuccess = false;
}
return(0) ;
}
--
Summary: enum variable operation behaviour and -O2
Product: gcc
Version: 4.3.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: john dot spelis at 3dlabs dot com
GCC build triplet: i686-pc-linux-gnu
GCC host triplet: i686-pc-linux-gnu
GCC target triplet: i686-pc-linux-gnu
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36170