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

            Bug ID: 111489
           Summary: Incorrect "-Wmaybe-uninitialized" warning from GCC
                    13.2.0
           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 13.2.0, and the submitted code also produces the
warning in GCC 12.2.0, but minor variations on the code tested while reducing
the production code did not always reproduce with 12 even though it did with
13. I also tested versions 7.3.0, 8.2.0, 9.3.0, 10.3.0, 11.2.0; none of them
produced the warning for me.  I'm not clear if this is a regression in 13 (and
12), or whether the older versions are oblivious to the and 12 and 13 are
trying to spot a problem but not recognizing why there isn't a problem in the
code.

The gist of the problem is that a variable is defined but not initialized
immediately:

    uint16_t pg_version;
    …
    if (flags == PGR_VERSION)
        pg_version = GET_PGVERS(pg_old);
    …
    for (…)
    {
        …
        if (flags == PGR_VERSION)
        {
            cur_rowid = ROWID(PAGE(sav_rowid), i, PT_BIGRID(cur_partp));
            pg_expand(GET_SLOTPTR(pg_old, old_slot), row_data, pg_version);
        }
    }

GCC complains that pg_version may be used uninitialized, but pg_value is only
used in the loop body if the condition that assigned it a value outside the
loop applies inside the body too.

The workaround is simple: initialize pg_version to 0 when it is defined.


Compiler information:
Using built-in specs.
COLLECT_GCC=gcc
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=c18 -O3 -Wall -Wextra -Werror -save-temps -v -c -o gcc-bug.o gcc-bug.c


Compilation output:
Using built-in specs.
COLLECT_GCC=gcc
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) 
COLLECT_GCC_OPTIONS='-std=c17' '-O3' '-Wall' '-Wextra' '-Werror' '-save-temps'
'-v' '-c' '-o' 'gcc-bug.o' '-mtune=generic' '-march=x86-64'
 /work1/gcc/v13.2.0/bin/../libexec/gcc/x86_64-pc-linux-gnu/13.2.0/cc1 -E -quiet
-v -iprefix /work1/gcc/v13.2.0/bin/../lib/gcc/x86_64-pc-linux-gnu/13.2.0/
gcc-bug.c -mtune=generic -march=x86-64 -std=c17 -Wall -Wextra -Werror -O3
-fpch-preprocess -o gcc-bug.i
ignoring nonexistent directory
"/work1/gcc/v13.2.0/bin/../lib/gcc/x86_64-pc-linux-gnu/13.2.0/../../../../x86_64-pc-linux-gnu/include"
ignoring duplicate directory
"/work1/gcc/v13.2.0/bin/../lib/gcc/../../lib/gcc/x86_64-pc-linux-gnu/13.2.0/include"
ignoring duplicate directory
"/work1/gcc/v13.2.0/bin/../lib/gcc/../../lib/gcc/x86_64-pc-linux-gnu/13.2.0/include-fixed"
ignoring nonexistent directory
"/work1/gcc/v13.2.0/bin/../lib/gcc/../../lib/gcc/x86_64-pc-linux-gnu/13.2.0/../../../../x86_64-pc-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /work1/gcc/v13.2.0/bin/../lib/gcc/x86_64-pc-linux-gnu/13.2.0/include
 /work1/gcc/v13.2.0/bin/../lib/gcc/x86_64-pc-linux-gnu/13.2.0/include-fixed
 /usr/local/include
 /work1/gcc/v13.2.0/bin/../lib/gcc/../../include
 /usr/include
End of search list.
COLLECT_GCC_OPTIONS='-std=c17' '-O3' '-Wall' '-Wextra' '-Werror' '-save-temps'
'-v' '-c' '-o' 'gcc-bug.o' '-mtune=generic' '-march=x86-64'
 /work1/gcc/v13.2.0/bin/../libexec/gcc/x86_64-pc-linux-gnu/13.2.0/cc1
-fpreprocessed gcc-bug.i -quiet -dumpbase gcc-bug.c -dumpbase-ext .c
-mtune=generic -march=x86-64 -O3 -Wall -Wextra -Werror -std=c17 -version -o
gcc-bug.s
GNU C17 (GCC) version 13.2.0 (x86_64-pc-linux-gnu)
        compiled by GNU C version 13.2.0, GMP version 6.3.0, MPFR version
4.2.0, MPC version 1.3.1, isl version isl-0.24-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 76c675c9da56a319124364c69f2f4d48
gcc-bug.c: In function ‘pg_reorg’:
gcc-bug.c:186:13: error: ‘pg_version’ may be used uninitialized
[-Werror=maybe-uninitialized]
  186 |             pg_expand(GET_SLOTPTR(pg_old, old_slot), row_data,
pg_version);
      |            
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                 
gcc-bug.c:141:14: note: ‘pg_version’ was declared here
  141 |     uint16_t pg_version;
      |              ^~~~~~~~~~
cc1: all warnings being treated as errors



The code is as reduced as I could make it, but not as minimal as I'd like.  It
does not use any headers; I copied definitions for size_t and [u]intN_t from
<stddef.h> and <stdint.h> to the top of the file (before it was compiled). 
There is a horrendous collection of macros building up the expressions.



# 0 "gcc-bug.c"
# 0 "<built-in>"
# 0 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 0 "<command-line>" 2
# 1 "gcc-bug.c"

typedef long unsigned int size_t;
typedef short int int16_t;
typedef int int32_t;
typedef long int int64_t;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long int uint64_t;

typedef struct
{
    uint16_t pgv1_size;
    uint16_t pgv1_flags1;
    uint16_t pgv1_flags2;
    uint16_t pgv1_flags3;
    uint16_t pgv1_nslots;
    uint32_t pgv1_generic;
} page_v1_t;

typedef struct
{
    page_v1_t pgv2_hdr;
    int64_t pgv2_next;
    int64_t pgv2_prev;
} page_v2_t;

typedef struct
{
    union
    {
        struct
        {
            uint16_t pgv0_size;
            uint16_t pgv0_flags;
        };
        uint32_t pgv0_nslots;
    };
    uint32_t pgv0_mode;
    uint32_t pgv0_next;
} page_v0_t;

typedef struct
{
    uint16_t sl4_off;
    uint16_t sl4_len;
} slot4_t;

typedef struct
{
    uint32_t sl8_off;
    uint32_t sl8_len;
} slot8_t;
# 132 "gcc-bug.c"
extern int64_t cur_rowid;

extern uint8_t *pg_alloc(size_t pg_size);
extern void mem_move(void *dst, const void *src, size_t len);
extern void pg_expand(uint8_t *row_in, uint8_t *row_out, uint16_t pg_version);
extern void pg_reorg(uint32_t flags, uint8_t *pg_old, uint16_t slotnum, uint8_t
*row_data, uint64_t cur_partp);

void pg_reorg(uint32_t flags, uint8_t *pg_old, uint16_t slotnum, uint8_t
*row_data, uint64_t cur_partp)
{
    uint16_t pg_version;
    size_t pg_size = ((((page_v1_t *)(pg_old))->pgv1_flags3 == 3) ?
(((page_v1_t *)(pg_old))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_old))->pgv0_size & 0xF800)));
    uint8_t *pg_new = pg_alloc(pg_size);
    uint8_t *old_slot = ((((((page_v1_t *)(pg_old))->pgv1_flags3 == 3) ?
(((page_v1_t *)(pg_old))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_old))->pgv0_size & 0xF800))) > 0x4000) ? (&(pg_old)[((((page_v1_t
*)(pg_old))->pgv1_flags3 == 3) ? (((page_v1_t *)(pg_old))->pgv1_size*1024) :
(uint16_t)(0x0800 + (((page_v0_t *)(pg_old))->pgv0_size & 0xF800))) -
sizeof(int64_t) - (1*sizeof(slot8_t))]) : ((((page_v0_t *)(pg_old))->pgv0_mode
& 1) ? (&(pg_old)[((((page_v1_t *)(pg_old))->pgv1_flags3 == 3) ? (((page_v1_t
*)(pg_old))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_old))->pgv0_size & 0xF800))) - sizeof(int64_t) - (1*sizeof(slot4_t))]) :
(&(pg_old)[((((page_v1_t *)(pg_old))->pgv1_flags3 == 3) ? (((page_v1_t
*)(pg_old))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_old))->pgv0_size & 0xF800))) - sizeof(int32_t) - (1*sizeof(slot4_t))])));
    uint8_t *new_slot = ((((((page_v1_t *)(pg_new))->pgv1_flags3 == 3) ?
(((page_v1_t *)(pg_new))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_new))->pgv0_size & 0xF800))) > 0x4000) ? (&(pg_new)[((((page_v1_t
*)(pg_new))->pgv1_flags3 == 3) ? (((page_v1_t *)(pg_new))->pgv1_size*1024) :
(uint16_t)(0x0800 + (((page_v0_t *)(pg_new))->pgv0_size & 0xF800))) -
sizeof(int64_t) - (1*sizeof(slot8_t))]) : ((((page_v0_t *)(pg_new))->pgv0_mode
& 1) ? (&(pg_new)[((((page_v1_t *)(pg_new))->pgv1_flags3 == 3) ? (((page_v1_t
*)(pg_new))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_new))->pgv0_size & 0xF800))) - sizeof(int64_t) - (1*sizeof(slot4_t))]) :
(&(pg_new)[((((page_v1_t *)(pg_new))->pgv1_flags3 == 3) ? (((page_v1_t
*)(pg_new))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_new))->pgv0_size & 0xF800))) - sizeof(int32_t) - (1*sizeof(slot4_t))])));

    if (flags == 2)
    {

        pg_version = ((((page_v1_t *)(pg_old))->pgv1_flags3 == 3) ?
(((page_v1_t *)(pg_old))->pgv1_generic >> 24) : ((uint32_t)((page_v0_t
*)(pg_old))->pgv0_next >> 24));
    }

    int64_t sav_rowid = cur_rowid;


    for (uint16_t i = 1; i <= ((((page_v1_t *)(pg_old))->pgv1_flags3 == 3) ?
(((page_v1_t *)(pg_old))->pgv1_nslots) : (((page_v0_t
*)(pg_old))->pgv0_nslots)); i++,
         (old_slot -= ((((((page_v1_t *)(pg_old))->pgv1_flags3 == 3) ?
(((page_v1_t *)(pg_old))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_old))->pgv0_size & 0xF800))) > 0x4000) ? sizeof(slot8_t) :
sizeof(slot4_t))), (new_slot -= ((((((page_v1_t *)(pg_new))->pgv1_flags3 == 3)
? (((page_v1_t *)(pg_new))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_new))->pgv0_size & 0xF800))) > 0x4000) ? sizeof(slot8_t) :
sizeof(slot4_t))))
    {
        size_t length;


        if (flags == 1 && (slotnum == 0 || i == slotnum))
        {
            uint16_t slotlen = ((((((page_v1_t *)(pg_old))->pgv1_flags3 == 3) ?
(((page_v1_t *)(pg_old))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_old))->pgv0_size & 0xF800))) > 0x4000) ? (((slot8_t
*)(old_slot))->sl8_len & 0x000FFFFF) : (((slot4_t *)(old_slot))->sl4_len &
0x3FFF));
            ((((((page_v1_t *)(pg_new))->pgv1_flags3 == 3) ? (((page_v1_t
*)(pg_new))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_new))->pgv0_size & 0xF800))) > 0x4000) ? (((slot8_t
*)(new_slot))->sl8_len = (((((((page_v1_t *)(pg_new))->pgv1_flags3 == 3) ?
(((page_v1_t *)(pg_new))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_new))->pgv0_size & 0xF800))) > 0x4000) ? (((slot8_t
*)(new_slot))->sl8_len & 0xFFF00000) : (((slot4_t *)(new_slot))->sl4_len &
0xC000)) | ((slotlen) & 0x000FFFFF))) : (((slot4_t *)(new_slot))->sl4_len =
(((((((page_v1_t *)(pg_new))->pgv1_flags3 == 3) ? (((page_v1_t
*)(pg_new))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_new))->pgv0_size & 0xF800))) > 0x4000) ? (((slot8_t
*)(new_slot))->sl8_len & 0xFFF00000) : (((slot4_t *)(new_slot))->sl4_len &
0xC000)) | ((slotlen) & 0x3FFF))));
            length = ((((((page_v1_t *)(pg_old))->pgv1_flags3 == 3) ?
(((page_v1_t *)(pg_old))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_old))->pgv0_size & 0xF800))) > 0x4000) ? (((slot8_t
*)(old_slot))->sl8_len & 0x000FFFFF) : (((slot4_t *)(old_slot))->sl4_len &
0x3FFF));
        }
        else
        {
            length = ((((((page_v1_t *)(pg_old))->pgv1_flags3 == 3) ?
(((page_v1_t *)(pg_old))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_old))->pgv0_size & 0xF800))) > 0x4000) ? (((slot8_t
*)(old_slot))->sl8_len & 0x000FFFFF) : (((slot4_t *)(old_slot))->sl4_len &
0x3FFF));
            ((((((page_v1_t *)(pg_new))->pgv1_flags3 == 3) ? (((page_v1_t
*)(pg_new))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_new))->pgv0_size & 0xF800))) > 0x4000) ? (((slot8_t
*)(new_slot))->sl8_len = (((((((page_v1_t *)(pg_new))->pgv1_flags3 == 3) ?
(((page_v1_t *)(pg_new))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_new))->pgv0_size & 0xF800))) > 0x4000) ? (((slot8_t
*)(new_slot))->sl8_len & 0xFFF00000) : (((slot4_t *)(new_slot))->sl4_len &
0xC000)) | ((length) & 0x000FFFFF))) : (((slot4_t *)(new_slot))->sl4_len =
(((((((page_v1_t *)(pg_new))->pgv1_flags3 == 3) ? (((page_v1_t
*)(pg_new))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_new))->pgv0_size & 0xF800))) > 0x4000) ? (((slot8_t
*)(new_slot))->sl8_len & 0xFFF00000) : (((slot4_t *)(new_slot))->sl4_len &
0xC000)) | ((length) & 0x3FFF))));
        }


        if (((((((page_v1_t *)(pg_old))->pgv1_flags3 == 3) ? (((page_v1_t
*)(pg_old))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_old))->pgv0_size & 0xF800))) > 0x4000) ? (((slot8_t *)old_slot)->sl8_off)
: (((slot4_t *)old_slot)->sl4_off)) == 0)
        {
            ((((((page_v1_t *)(pg_new))->pgv1_flags3 == 3) ? (((page_v1_t
*)(pg_new))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_new))->pgv0_size & 0xF800))) > 0x4000) ? (((slot8_t *)new_slot)->sl8_off
= (0)) : (((slot4_t *)new_slot)->sl4_off = (0)));
            continue;
        }

        ((((((page_v1_t *)(pg_new))->pgv1_flags3 == 3) ? (((page_v1_t
*)(pg_new))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_new))->pgv0_size & 0xF800))) > 0x4000) ? (((slot8_t *)new_slot)->sl8_off
= (0)) : (((slot4_t *)new_slot)->sl4_off = (0)));

        if (flags == 2)
        {
            cur_rowid = (((((cur_partp) & 0x400000000) ? 1 : 0)) ?
(uint64_t)(((((int64_t)((((uint64_t)(sav_rowid) & ((uint64_t)1 << 63)) ?
(int64_t)(((sav_rowid) & 0x7FFFFFFFFFFF0000) >> 16) : (int64_t)(((sav_rowid) &
0xFFFFFF00) >> 8)))) << 16) + (i)) | ((uint64_t)1 << 63)) :
(uint64_t)((((int32_t)((((uint64_t)(sav_rowid) & ((uint64_t)1 << 63)) ?
(int64_t)(((sav_rowid) & 0x7FFFFFFFFFFF0000) >> 16) : (int64_t)(((sav_rowid) &
0xFFFFFF00) >> 8)))) << 8) + (i)));
            pg_expand(((((((page_v1_t *)(pg_old))->pgv1_flags3 == 3) ?
(((page_v1_t *)(pg_old))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_old))->pgv0_size & 0xF800))) > 0x4000) ? (((uint8_t*)(pg_old)) +
((slot8_t *)old_slot)->sl8_off) : (((uint8_t*)(pg_old)) + ((slot4_t
*)old_slot)->sl4_off)), row_data, pg_version);
        }
        else
        {

            mem_move(((((((page_v1_t *)(pg_new))->pgv1_flags3 == 3) ?
(((page_v1_t *)(pg_new))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_new))->pgv0_size & 0xF800))) > 0x4000) ? (((uint8_t*)(pg_new)) +
((slot8_t *)new_slot)->sl8_off) : (((uint8_t*)(pg_new)) + ((slot4_t
*)new_slot)->sl4_off)), ((((((page_v1_t *)(pg_old))->pgv1_flags3 == 3) ?
(((page_v1_t *)(pg_old))->pgv1_size*1024) : (uint16_t)(0x0800 + (((page_v0_t
*)(pg_old))->pgv0_size & 0xF800))) > 0x4000) ? (((uint8_t*)(pg_old)) +
((slot8_t *)old_slot)->sl8_off) : (((uint8_t*)(pg_old)) + ((slot4_t
*)old_slot)->sl4_off)), length);
        }
    }
}



This is the unpreprocessed source code.  It contains some comments about what
cannot be removed without the warning going away.



/* Relevant parts of <stddef.h> and <stdint.h> */
typedef long unsigned int size_t;
typedef short int int16_t;
typedef int int32_t;
typedef long int int64_t;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long int uint64_t;

typedef struct
{
    uint16_t pgv1_size;
    uint16_t pgv1_flags1;
    uint16_t pgv1_flags2;
    uint16_t pgv1_flags3;
    uint16_t pgv1_nslots;
    uint32_t pgv1_generic;
} page_v1_t;

typedef struct
{
    page_v1_t pgv2_hdr;
    int64_t pgv2_next;
    int64_t pgv2_prev;
} page_v2_t;

typedef struct
{
    union
    {
        struct
        {
            uint16_t pgv0_size;
            uint16_t pgv0_flags;
        };
        uint32_t pgv0_nslots;
    };
    uint32_t pgv0_mode;
    uint32_t pgv0_next;
} page_v0_t;

typedef struct
{
    uint16_t sl4_off;
    uint16_t sl4_len;
} slot4_t;

typedef struct
{
    uint32_t sl8_off;
    uint32_t sl8_len;
} slot8_t;

#define PG_EXTENDED 0x10000
#define PGMD_8BTS   1
#define SL4_MASK    0xC000
#define SL4_LENG    0x3FFF
#define SL8_MASK    0xFFF00000
#define SL8_LENG    0x000FFFFF
#define PGR_SLOTSZ  1
#define PGR_VERSION 2
#define BIGRID_BIT  ((uint64_t)1 << 63)

#define TST_PGTHREE(p) (((page_v1_t *)(p))->pgv1_flags3 == 3)

#define GET_PGSIZE(pg) (TST_PGTHREE(pg) ? \
                          (((page_v1_t *)(pg))->pgv1_size*1024) : \
                          (uint16_t)(0x0800 + (((page_v0_t *)(pg))->pgv0_size &
0xF800)))

#define GET_PGFLAGS(pg) (TST_PGTHREE(pg) ? \
                        ((uint32_t)(((page_v1_t *)(pg))->pgv1_flags1) | \
                         (uint32_t)(((page_v1_t *)(pg))->pgv1_flags2 << 16)) :
\
                        (uint32_t)(((page_v0_t *)(pg))->pgv0_flags))

#define GET_PGNSLOTS(pg) (TST_PGTHREE(pg) ? \
                          (((page_v1_t *)(pg))->pgv1_nslots) : \
                          (((page_v0_t *)(pg))->pgv0_nslots))

#define GET_PGVERS(pg) (TST_PGTHREE(pg) ? \
                        (((page_v1_t *)(pg))->pgv1_generic >> 24) : \
                         ((uint32_t)((page_v0_t *)(pg))->pgv0_next >> 24))

#define PG_LRGSLTS(p) (GET_PGSIZE(p) > 0x4000)

#define GET_SLOT_T_SIZE(p) \
        (PG_LRGSLTS(p) ? sizeof(slot8_t) : sizeof(slot4_t))

#define GET_SLOTLEN(p, s) (PG_LRGSLTS(p) ? \
                          (((slot8_t *)(s))->sl8_len & SL8_LENG) : \
                          (((slot4_t *)(s))->sl4_len & SL4_LENG))

#define GET_SLOTFLGS(p, s) (PG_LRGSLTS(p) ? \
                          (((slot8_t *)(s))->sl8_len & SL8_MASK) : \
                          (((slot4_t *)(s))->sl4_len & SL4_MASK))

#define SET_SLOTLEN(p, s, l) \
        (PG_LRGSLTS(p) ? \
         (((slot8_t *)(s))->sl8_len = (GET_SLOTFLGS(p, s) | ((l) & SL8_LENG)))
: \
         (((slot4_t *)(s))->sl4_len = (GET_SLOTFLGS(p, s) | ((l) & SL4_LENG))))

#define GET_SLOTTAB(p, i) (PG_LRGSLTS(p) ? \
        (&(p)[GET_PGSIZE(p) - sizeof(int64_t) - (i*sizeof(slot8_t))]) : \
        ((((page_v0_t *)(p))->pgv0_mode & PGMD_8BTS) ? \
         (&(p)[GET_PGSIZE(p) - sizeof(int64_t) - (i*sizeof(slot4_t))]) : \
         (&(p)[GET_PGSIZE(p) - sizeof(int32_t) - (i*sizeof(slot4_t))])))

#define DEC_SLOTTAB(p, s) (s -= GET_SLOT_T_SIZE(p))

#define GET_SLOTPTR(p, s) (PG_LRGSLTS(p) ? \
                           (((uint8_t*)(p)) + ((slot8_t *)s)->sl8_off) : \
                           (((uint8_t*)(p)) + ((slot4_t *)s)->sl4_off))

#define GET_SLOTOFF(p, s) (PG_LRGSLTS(p) ? \
                           (((slot8_t *)s)->sl8_off) : \
                           (((slot4_t *)s)->sl4_off))

#define SET_SLOTOFF(p, s, n) (PG_LRGSLTS(p) ? \
                           (((slot8_t *)s)->sl8_off = (n)) : \
                           (((slot4_t *)s)->sl4_off = (n)))

#define PAGE(r) \
    (((uint64_t)(r) & BIGRID_BIT) ? (int64_t)(((r) & 0x7FFFFFFFFFFF0000) >> 16)
: \
     (int64_t)(((r) & 0xFFFFFF00) >> 8))

#define ROWID(p, s, br) \
    ((br) ? (uint64_t)(((((int64_t)(p)) << 16) + (s)) | BIGRID_BIT) : \
     (uint64_t)((((int32_t)(p)) << 8) + (s)))

#define PT_BIGRID(pt)   (((pt) & 0x400000000) ? 1 : 0)

extern int64_t cur_rowid;

extern uint8_t *pg_alloc(size_t pg_size);
extern void mem_move(void *dst, const void *src, size_t len);
extern void pg_expand(uint8_t *row_in, uint8_t *row_out, uint16_t pg_version);
extern void pg_reorg(uint32_t flags, uint8_t *pg_old, uint16_t slotnum, uint8_t
*row_data, uint64_t cur_partp);

void pg_reorg(uint32_t flags, uint8_t *pg_old, uint16_t slotnum, uint8_t
*row_data, uint64_t cur_partp)
{
    uint16_t pg_version;
    size_t   pg_size = GET_PGSIZE(pg_old);
    uint8_t *pg_new = pg_alloc(pg_size);
    uint8_t *old_slot = GET_SLOTTAB(pg_old, 1);
    uint8_t *new_slot = GET_SLOTTAB(pg_new, 1);

    if (flags == PGR_VERSION)
    {
        /* This invocation of GET_PGVERS is needed */
        pg_version = GET_PGVERS(pg_old);
    }

    int64_t sav_rowid = cur_rowid;

    /* The invocations of DEC_SLOTTAB are needed */
    for (uint16_t i = 1; i <= GET_PGNSLOTS(pg_old); i++,
         DEC_SLOTTAB(pg_old, old_slot), DEC_SLOTTAB(pg_new, new_slot))
    {
        size_t length;

        /* Some of this paragraph is needed */
        if (flags == PGR_SLOTSZ && (slotnum == 0 || i == slotnum))
        {
            uint16_t slotlen = GET_SLOTLEN(pg_old, old_slot);
            SET_SLOTLEN(pg_new, new_slot, slotlen);
            length = GET_SLOTLEN(pg_old, old_slot);
        }
        else
        {
            length = GET_SLOTLEN(pg_old, old_slot);
            SET_SLOTLEN(pg_new, new_slot, length);
        }

        /* Both the GET and the SET are needed */
        if (GET_SLOTOFF(pg_old, old_slot) == 0)
        {
            SET_SLOTOFF(pg_new, new_slot, 0);
            continue;
        }
        /* This SET is needed */
        SET_SLOTOFF(pg_new, new_slot, 0);

        if (flags == PGR_VERSION)
        {
            cur_rowid = ROWID(PAGE(sav_rowid), i, PT_BIGRID(cur_partp));
            pg_expand(GET_SLOTPTR(pg_old, old_slot), row_data, pg_version);
        }
        else
        {
            /* This else clause and a call using the macros is needed */
            mem_move(GET_SLOTPTR(pg_new, new_slot), GET_SLOTPTR(pg_old,
old_slot), length);
        }
    }
}

I was presented with bugs 60350, 64717, 69537, 86058, 102801, 107140, 112240 as
possible duplicates.  60350 is not relevant (the line numbers are reported
correctly in this code); the other 5-digit bugs are 'resolved fixed', as is
102801.  Neither 107140 nor 111240 seems relevant.

Reply via email to