https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111249

            Bug ID: 111249
           Summary: Aggressive loop optimization reports "iteration
                    2147483645 invokes undefined behavior"
           Product: gcc
           Version: 13.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jonathan.leffler at gmail dot com
  Target Milestone: ---

The problem occurs with GCC 12.2.0 and GCC 13.2.0.  It is difficult to see how
the loop could ever reach iteration 2147483645.  It would have had undefined
behaviour from iteration 3 onwards, anyway.

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/work1/gcc/v13.2.0/bin/../libexec/gcc/x86_64-pc-linux-gnu/13.2.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../gcc-13.2.0/configure --prefix=/usr/gcc/v13.2.0
CC=/usr/gcc/v12.2.0/bin/gcc CXX=/usr/gcc/v12.2.0/bin/g++
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 13.2.0 (GCC)

Command line:

gcc -std=c99 -O3 -Wall -pedantic -Wold-style-definition -Wold-style-declaration
-Wnested-externs -Wmissing-prototypes -Wextra -Werror -save-temps -c
gcc-inline-bug.c

Resulting errors:

In function ‘sbt_subclass_put’:
cc1: error: iteration 2147483645 invokes undefined behavior
[-Werror=aggressive-loop-optimizations]
In function ‘sbt_sendbuffer’,
    inlined from ‘sbt_subclass_put’ at gcc-inline-bug.c:95:15:
gcc-inline-bug.c:52:23: note: within this loop
   52 |     for (int i = 0; i < n_info; i++)
      |                     ~~^~~~~~~~
cc1: all warnings being treated as errors

Output file (gcc-inline-bug.i):

# 0 "gcc-inline-bug.c"
# 0 "<built-in>"
# 0 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 0 "<command-line>" 2
# 1 "gcc-inline-bug.c"
enum { E_Success = 0, E_Failure = -1 };

typedef long long LSN_t;
typedef struct BUF_s BUF_t;

typedef struct
{
    LSN_t slri_lsn;
    BUF_t *slri_buf;
} SLR_t;

typedef struct SBT_s SBT_t;

typedef struct
{
    int (*sbtop_put)(SBT_t *objp, LSN_t a_lsn, BUF_t *a_buf);
} OPS_t;

typedef struct
{
    SLR_t *slri_info;
} VAR_t;

struct SBT_s
{
    SBT_t *sbtv_next;
    LSN_t sbtv_last;
    OPS_t sbtv_ops;
    VAR_t sbtv_vars[24];
};

typedef struct
{
    int sish_txid;
} ISH_t;


extern int sbt_subclass_put(SBT_t *objp, LSN_t a_lsn, BUF_t *a_buf);


extern int ISH_read(BUF_t *inbufp, ISH_t *in_header);
extern int sbt_putbuf(SBT_t *objp, LSN_t a_lsn, BUF_t *a_buf);
extern int sbt_seterr(SBT_t *objp, int rc, int s);
extern void slri_decref(BUF_t *slrip, const char *file, int line);
extern void slri_set_empty(SLR_t *slrip);

static int
sbt_sendbuffer(SBT_t *objp, SLR_t **info, int n_info)
{
    int rc = E_Success;

    for (int i = 0; i < n_info; i++)
        {
        SLR_t *pendp = info[i];

        if (rc == E_Success)
            {

            int s = sbt_putbuf(objp->sbtv_next, pendp->slri_lsn,
pendp->slri_buf);
            if (s == E_Success)
                objp->sbtv_last = pendp->slri_lsn;
            else

                rc = sbt_seterr(objp, s, 39);
            }


        slri_decref(pendp->slri_buf, "gcc-inline-bug.c", 68);
        slri_set_empty(pendp);
        }

    return rc;
}

int
sbt_subclass_put(SBT_t *objp, LSN_t a_lsn, BUF_t *a_buf)
{
    BUF_t *inbufp = a_buf;
    ISH_t in_header;
    int rc;

    if ((rc = ISH_read(inbufp, &in_header)) != E_Success)
        return E_Failure;

    VAR_t *vars = &objp->sbtv_vars[0];
    SLR_t *pendp = &vars->slri_info[in_header.sish_txid];
    ISH_t bef_header;

    if ((rc = ISH_read(pendp->slri_buf, &bef_header)) != E_Success)
        return E_Failure;

    SLR_t aft_bufinfo = { .slri_lsn = a_lsn, .slri_buf = inbufp };
    SLR_t *tosend[2] = { pendp, &aft_bufinfo };

    if ((rc = sbt_sendbuffer(objp, tosend, 2)) != E_Success)
        return E_Failure;

    return E_Success;
}

I was given a list of possible duplicates: 57199, 59651, 79517, 84867, 88272,
103724, and 106842.  Of those, 103724 (closed because the GCC 10 code line is
closed) and 106482 could be related, but neither deals with a function being
inlined and then producing the warning.  The others seem loosely related but
not relevant.

The original source code (gcc-inline-big.c) has some comments in it that the
preprocessor removes:

enum { E_Success = 0, E_Failure = -1 };

typedef long long LSN_t;
typedef struct BUF_s BUF_t;

typedef struct
{
    LSN_t slri_lsn;
    BUF_t *slri_buf;
} SLR_t;

typedef struct SBT_s SBT_t;

typedef struct
{
    int (*sbtop_put)(SBT_t *objp, LSN_t a_lsn, BUF_t *a_buf);
} OPS_t;

typedef struct
{
    SLR_t *slri_info;
} VAR_t;

struct SBT_s
{
    SBT_t *sbtv_next;
    LSN_t  sbtv_last;
    OPS_t  sbtv_ops;
    VAR_t  sbtv_vars[24];
};

typedef struct
{
    int sish_txid;
} ISH_t;

/* Entry point to module */
extern int sbt_subclass_put(SBT_t *objp, LSN_t a_lsn, BUF_t *a_buf);

/* Functions used by module */
extern int ISH_read(BUF_t *inbufp, ISH_t *in_header);
extern int sbt_putbuf(SBT_t *objp, LSN_t a_lsn, BUF_t *a_buf);
extern int sbt_seterr(SBT_t *objp, int rc, int s);
extern void slri_decref(BUF_t *slrip, const char *file, int line);
extern void slri_set_empty(SLR_t *slrip);

static int
sbt_sendbuffer(SBT_t *objp, SLR_t **info, int n_info)
{
    int rc = E_Success;

    for (int i = 0; i < n_info; i++)
        {
        SLR_t *pendp = info[i];

        if (rc == E_Success)
            {
            /* This call is part of the reproduction */
            int s = sbt_putbuf(objp->sbtv_next, pendp->slri_lsn,
pendp->slri_buf);
            if (s == E_Success)
                objp->sbtv_last = pendp->slri_lsn;
            else
                /* Change this to rc = E_Failure; and the bug goes away */
                rc = sbt_seterr(objp, s, 39);
            }

        /* These lines are part of the reproduction - delete either and the bug
goes away */
        slri_decref(pendp->slri_buf, __FILE__, __LINE__);
        slri_set_empty(pendp);
        }

    return rc;
}

int
sbt_subclass_put(SBT_t *objp, LSN_t a_lsn, BUF_t *a_buf)
{
    BUF_t *inbufp = a_buf;
    ISH_t in_header;
    int rc;

    if ((rc = ISH_read(inbufp, &in_header)) != E_Success)
        return E_Failure;

    VAR_t *vars = &objp->sbtv_vars[0];
    SLR_t *pendp = &vars->slri_info[in_header.sish_txid];
    ISH_t bef_header;

    if ((rc = ISH_read(pendp->slri_buf, &bef_header)) != E_Success)
        return E_Failure;

    SLR_t aft_bufinfo = { .slri_lsn = a_lsn, .slri_buf = inbufp };
    SLR_t *tosend[2] = { pendp, &aft_bufinfo };

    if ((rc = sbt_sendbuffer(objp, tosend, 2)) != E_Success)
        return E_Failure;

    return E_Success;
}
  • [Bug c/111249] New: Aggress... jonathan.leffler at gmail dot com via Gcc-bugs

Reply via email to