IBM Support

IJ36117: COMPILING WITH -O CAUSES INCORRECT EVALUATION OF IF STATEMENT

Subscribe to this APAR

By subscribing, you receive periodic emails alerting you to the status of the APAR, along with a link to the fix after it becomes available. You can track this item individually or track all items by product.

Notify me when this APAR changes.

Notify me when an APAR for this component changes.

 

APAR status

  • Closed as program error.

Error description

  • When compiling the provided test case with -O, the following if
    statement evaluates incorrectly:
    
    if ((dir <= 0) && (((indx >= 0) && (indx < 10000)) || (indx >
    20000)))
    
    returns TRUE with dir=-1 and indx=-2
    
    
    =====COMPILE COMMAND:
    xlc_r -DBUILD_ARCH64 -qcheck=divzero -q64 -qlanglvl=extc99
    -qhssngl -qchars=signed -qmaxmem=-1 -qcpluscmt -Q -Dpower64_aix4
     -Daix4  -DSAG_COM -Dunix   -O -qalias=noansi  -o
    test_loop.exe_nodebug test_loop.c
    
    
    =====TESTCASE:
    $ cat test_loop.c
    #define       i4              int
    #define       i2              short
    #define       u_i2            unsigned short
    typedef i4      nat;
    typedef         char *          PTR;
    typedef i2 DB_DT_ID;
    #include <stdio.h>
    
    
    
    typedef struct _DB_DATA_VALUE
    {
        PTR             db_data;
        i4              db_length;
        DB_DT_ID        db_datatype;
        i2              db_prec;
        i2              db_collID;
    }   DB_DATA_VALUE;
    
    
    typedef struct _DB_DATA_VALUE   *DBVARRAY;
    
    
    typedef struct iiscopes
    {
            char  *class;
            u_i2   usecount;
            char  *clientdata;
            char  * namestr;
            i2    resolved;
            struct iiscopes *parent;
            struct iiscopes *sibling;
            i2      source;
    } IISCOPES;
    
    typedef struct _QRY
    {
            i4              qr_zero;
            i4              qr_version;
    
    # define        QR_VERSION_MASK 0xff
    # define        QR_VERSION      3
    # define        QR_0_ROWS_OK    0x100
    # define        QR_ROWS_FOUND   0x200
    
            char            *qr_argv;
            char            *qr_putparam;
            const char      *qr_form;
            const char      *qr_table;
            struct _QRY     *qr_child;
            char            *qr_qdesc;
    } QRY;
    
    
    typedef struct _abrts_ds
    {
            nat             type;
    #define ABRTS_DSTYPE_CURSOR     1
    #define ABRTS_DSTYPE_UCARRAY    2
    #define ABRTS_DSTYPE_SARRAY     3
    
            nat  num_cols;
            char * target_obj;
            char **col_targs;
            char **col_names;
            char *datacache;
    
    } ABRTS_DATASET;
    
    
    
    typedef struct _abrtspv
    {
            DB_DATA_VALUE   abpvvalue;
            char            *abpvsymbol;
            char            *abpvdtype;
            i2              abpvbrtype;
            i2              abpvindx;
            i2              abpvmem;
    } ABRTSPV;
    
    
    
    
    typedef struct _abrtsprm
    {
            ABRTSPV         *pr_actuals;
            char            **pr_formals;
            nat             pr_argcnt;
            DB_DATA_VALUE   pr_retvalue;
            i2              pr_flags;
            u_i2            pr_usecount;
            PTR             pr_extblock;
            nat             pr_dataset_cnt;
            ABRTS_DATASET   *pr_datasets;
    } ABRTSPRM;
    
    
    
    typedef struct _abrts_dc
    {
            char            *tuple_buffer;
            nat             tb_size;
            PTR             descriptor;
            struct iiobject *cache;
    } ABRTS_DATACACHE;
    
    
    
    static void iiarPassArg (ABRTSPRM *, IISCOPES *, DBVARRAY, i4,
    char *, char *);
    
    
    main()
    {
    
            ABRTSPRM prm1;
            ABRTSPV prv[3];
            IISCOPES scopes;
            DBVARRAY dbvarray;
    
            prm1.pr_argcnt = 3;
            prv[0].abpvbrtype = 45;
            prv[0].abpvindx = -2;
            prv[1].abpvbrtype = 30;
            prv[1].abpvindx = 1;
            prv[2].abpvbrtype = 30;
            prv[2].abpvindx = 1;
    
            prm1.pr_actuals= &prv[0];
    
            iiarPassArg (&prm1, &scopes,dbvarray, -1, NULL, NULL);
    }
    
    static void
    iiarPassArg (
        ABRTSPRM    *prm,
        IISCOPES    *symtab,
        DBVARRAY    dbdvarr,
        i4          dir,
        char        *obj,
        char        *kind
    )
    {
            register ABRTSPV    *ap;
            nat                 cnt;
    
            for (ap = prm->pr_actuals, cnt = 0; cnt <
    prm->pr_argcnt; ++cnt,  ++ap)
            {
                    i4      indx;
    
                    indx = (i4)(ap->abpvindx);
    
    
                    if ((dir <= 0) && (((indx >= 0) && (indx <
    10000)) || (indx > 20000)))
                    {
                            printf ("TEST 1 TRUE for loop %d\n",
    cnt);
                    }
                    else
                    {
                            printf ("TEST 1 FALSE for loop %d\n",
    cnt);
                    }
    
                    if ((dir <= 0) && (((indx >= 0) && (indx <
    10000)) || (indx > 20000)))
                    {
                            printf ("TEST 2 TRUE continue for loop
    %d\n", cnt);
                            continue;
                    }
                    else
                    {
                            printf ("TEST 2 FALSE for loop %d\n",
    cnt);
                    }
                    printf ("WE PASS HERE %d\n", cnt);
    
            }
    }
    
    $
    
    ===== ACTUAL OUTPUT:
    $ ./test_loop.exe_nodebug
    TEST 1 TRUE for loop 0
    TEST 2 TRUE continue for loop 0
    TEST 1 TRUE for loop 1
    TEST 2 TRUE continue for loop 1
    TEST 1 TRUE for loop 2
    TEST 2 TRUE continue for loop 2
    $
    
    ===== EXPECTED OUTPUT:
    $ ./test_loop.exe_nodebug
    TEST 1 FALSE for loop 0
    TEST 2 FALSE for loop 0
    WE PASS HERE 0
    TEST 1 TRUE for loop 1
    TEST 2 TRUE continue for loop 1
    TEST 1 TRUE for loop 2
    TEST 2 TRUE continue for loop 2
    $
    

Local fix

  • N/A
    

Problem summary

  • USERS AFFECTED:
    Users who have test cases that make use of the ternary operator
    might be affected by this issue.
    
    PROBLEM DESCRIPTION:
    The compiler was not treating the types of the two branch
    statements of the ternary operator correctly leading to
    incorrect code gen causing the incorrect output.
    

Problem conclusion

  • A compiler fix has been implemented for the above mentioned
    issue.
    

Temporary fix

Comments

APAR Information

  • APAR number

    IJ36117

  • Reported component name

    XL C FOR AIX

  • Reported component ID

    5725C7100

  • Reported release

    D10

  • Status

    CLOSED PER

  • PE

    NoPE

  • HIPER

    NoHIPER

  • Special Attention

    NoSpecatt / Xsystem

  • Submitted date

    2021-11-23

  • Closed date

    2022-03-09

  • Last modified date

    2022-03-09

  • APAR is sysrouted FROM one or more of the following:

  • APAR is sysrouted TO one or more of the following:

    IJ36457

Fix information

  • Fixed component name

    XL C FOR AIX

  • Fixed component ID

    5725C7100

Applicable component levels

[{"Line of Business":{"code":"LOB57","label":"Power"},"Business Unit":{"code":"BU058","label":"IBM Infrastructure w\/TPS"},"Product":{"code":"SSGH2K","label":"XL C for AIX"},"Platform":[{"code":"PF025","label":"Platform Independent"}],"Version":"13.1"}]

Document Information

Modified date:
10 March 2022