root/tests/usr.bin/xlint/lint1/gcc.c
/*      $NetBSD: gcc.c,v 1.7 2026/01/20 23:46:36 rillig Exp $   */
# 3 "gcc.c"

/*
 * Miscellaneous tests that are specific to lint's GCC mode.
 */

/* lint1-extra-flags: -chaapbrz -X 351 */

// Before C99 introduced __func__, GCC already had __FUNCTION__ with the same
// semantics.
const char *
gcc_function(void)
{
        /* expect+1: error: negative array dimension (-13) [20] */
        typedef int size[-(int)sizeof __FUNCTION__];

        return __FUNCTION__;
}

// Before C99 introduced designators in initializers, GCC already had them,
// although with a different syntax for struct/union members and with the
// a...b for ranges of array elements.
int array_range_initializers[256] = {
        [2] = 1,
        [3] = 2,
        [4 ... 5] = 3
};

_Bool dbl_isinf(double);

// Test that the GCC '__extension__' and '__typeof' are recognized.
void
extension_and_typeof(void)
{
        double __logbw = 1;
        if (__extension__(({
                __typeof((__logbw)) x_ = (__logbw);
                !dbl_isinf((x_));
        })))
                __logbw = 1;
}

int
range_in_case_label(int i)
{
        switch (i) {
        case 1 ... 40:          // This is a GCC extension.
                return 1;
        default:
                return 2;
        }
}

union {
        int i;
        char *s;
} initialize_union_with_mixed_designators[] = {
        { i: 1 },               /* GCC-style */
        { s: "foo" },           /* GCC-style */
        { .i = 1 },             /* C99-style */
        { .s = "foo" }          /* C99-style */
};

union {
        int i[10];
        short s;
} initialize_union_with_gcc_designators[] = {
        { s: 2 },
        { i: { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } },
};

void
declaration_of_variable_array(int i)
{
        int array[i];
        while (i-- > 0)
                array[i] = 0;
}

/*
 * Before cgram.y 1.226 from 2021-05-03, lint could not parse typeof(...) if
 * there was a statement before it.
 */
void *
typeof_after_statement(void **ptr)
{
        return ({
                if (*ptr != (void *)0)
                        ptr++;
                __typeof__(*ptr) ret = *ptr;
                ret;
        });
}

const char *
auto_type(const char *ptr)
{
        __auto_type pp = &ptr;
        return *pp;
}

void
atomic_functions(void)
{
        static unsigned long long v, *pv;
        v = __atomic_load_n(pv, 0);
        v = __atomic_exchange_n(pv, 0, 0);
        v = __atomic_add_fetch(pv, 0, 0);
        v = __atomic_sub_fetch(pv, 0, 0);
        v = __atomic_and_fetch(pv, 0, 0);
        v = __atomic_xor_fetch(pv, 0, 0);
        v = __atomic_or_fetch(pv, 0, 0);
        v = __atomic_nand_fetch(pv, 0, 0);
        v = __atomic_fetch_add(pv, 0, 0);
        v = __atomic_fetch_sub(pv, 0, 0);
        v = __atomic_fetch_and(pv, 0, 0);
        v = __atomic_fetch_xor(pv, 0, 0);
        v = __atomic_fetch_or(pv, 0, 0);
        v = __atomic_fetch_nand(pv, 0, 0);

        static char c, *pc;
        c = __atomic_load_n(pc, 0);
        c = __atomic_exchange_n(pc, 0, 0);

        /* expect+1: warning: conversion from 'unsigned long long' to 'char' may lose accuracy [132] */
        c = __atomic_exchange_n(pv, 0, 0);
}

__float128 f128 = 0.0;