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

            Bug ID: 107618
           Summary: Incorrect diagnostics when using -Og,
                    builtin_expect(), and function attribute "warning" or
                    "error"
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: other
          Assignee: unassigned at gcc dot gnu.org
          Reporter: yann at droneaud dot fr
  Target Milestone: ---

Created attachment 53872
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=53872&action=edit
reproducer for -Og, __builtin_expect(), and function
__attribute__((warning("")))

The code below compiled with -Og triggers a warning message that is not
mandated:

    $ gcc -Og  warning.c
    warning.c: In function ‘test_expect’:
    warning.c:26:17: warning: call to ‘size_mismatch_expect’ declared with
attribute warning: size mismatch (builtin_expect) [-Wattribute-warning]
       26 |                 size_mismatch_expect();
          |                 ^~~~~~~~~~~~~~~~~~~~~~


    $ cat warning.c
    #include <stdbool.h>
    #include <stddef.h>
    #include <stdlib.h>

    extern void size_mismatch_nonexpect(void)
    __attribute__((__warning__("size mismatch")));

    static bool
    test_nonexpect(const void *addr, size_t len)
    {
            size_t sz = __builtin_object_size(addr, 0);
            if (sz != (size_t)-1 && sz < len) {
                    size_mismatch_nonexpect();
                    return false;
            }

            return true;
    }

    extern void size_mismatch_expect(void)
    __attribute__((__warning__("size mismatch (builtin_expect)")));

    static bool
    test_expect(const void *addr, size_t len)
    {
            size_t sz = __builtin_object_size(addr, 0);
            if (__builtin_expect(sz != (size_t)-1 && sz < len, 0)) {
                    size_mismatch_expect();
                    return false;
            }

            return true;
    }

    int main(void)
    {
            int i = 0;

            if (!test_nonexpect(&i, sizeof(i)))
                    return EXIT_FAILURE;

            if (!test_expect(&i, sizeof(i)))
                    return EXIT_FAILURE;

            return EXIT_SUCCESS;
    }

The warning at -Og level is not expected because there's no call to the
size_mismatch_expect() in the generated assembler (for x86-64):

    $ head warning.s
            .file        "warning.c"
            .text
            .type        test_nonexpect, @function
    test_nonexpect:
            movl        $1, %eax
            ret
            .size        test_nonexpect, .-test_nonexpect
            .type        test_expect, @function
    test_expect:
            movl        $1, %eax
            ret
            .size        test_expect, .-test_expect
            .globl        main
            .type        main, @function
    main:
            endbr64
            subq        $24, %rsp
            movq        %fs:40, %rax
            movq        %rax, 8(%rsp)
            xorl        %eax, %eax
            movl        $0, 4(%rsp)
            leaq        4(%rsp), %rdi
            movl        $4, %esi
            call        test_nonexpect
            testb        %al, %al
            jne        .L11
            movl        $1, %eax
    .L5:
            movq        8(%rsp), %rdx
            subq        %fs:40, %rdx
            jne        .L12
            addq        $24, %rsp
            ret
    .L11:
            leaq        4(%rsp), %rdi
            movl        $4, %esi
            call        test_expect
            testb        %al, %al
            je        .L9
            movl        $0, %eax
            jmp        .L5
    .L9:
            movl        $1, %eax
            jmp        .L5


See also https://godbolt.org/z/KEsaavhvG

Compiling at optimization level s, z, 1, 2, or 3 doesn't produce that warning.
(but compiling with -O0 does produces two warnings, as expected, since calls to
the two functions are emitted).

Having the warning at debug optimization level makes using -Og in some complex
code base challenging for no good reason when __attribute__((error(""))) is
used (or -Werror=attribute-warning).

It should also be noted clang doesn't generate the warning for optimization
level above 0.

Reply via email to