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