Issue 169494
Summary [clang] _Pragma() in macro interfering with macro return type
Labels clang
Assignees
Reporter alexveden
    I have a macro that started behaving differently after upgrading to clang-22, it worked previously in CI for:
- GCC - 10, 11, 12, 13, 14, 15
- Clang - 13, 14, 15, 16, 17, 18, 19, 20, 21

Minimal example:
```c
#include <stdio.h>
#include <stdint.h>

size_t
_cexds__arr_len(const void* arr)
{
    // This function is a mock for returning length of dynamic arrays
    return (arr) ? 6969 : 0;
}

#    define arr$len(arr)                                                                           \
        ({                                                                                         \
            _Pragma("GCC diagnostic push");                                                        \
            /* NOTE: temporary disable syntax error to support both static array length and        \
             * arr$(T) */                                                                          \
            _Pragma("GCC diagnostic ignored \"-Wsizeof-pointer-div\"");                            \
            /* NOLINTBEGIN */                                                                      \
            __builtin_types_compatible_p(                                                          \
                typeof(arr),                                                                       \
                typeof(&(arr)[0])                                                                  \
            )                          /* check if array or ptr */                                 \
                ? _cexds__arr_len(arr) /* some pointer or arr$ */                                  \
                : (                                                                                \
                      sizeof(arr) / sizeof((arr)[0]) /* static array[] */                          \
                  );                                                                               \
            /* NOLINTEND */                                                                        \
            _Pragma("GCC diagnostic pop");                                                         \
        })

int main(int argc, char** argv) {
    char* a[] = {"a", "b"};
    printf("a is static, arr$len=%zu\n", arr$len(a));

    char* a1 = (void*)0xbadcaffe;
    printf("a is kinda dynamic, arr$len=%zu\n", arr$len(a1));
    return 0;
}
```

Returns:
```
~/code/cex/clang22issues ➜ /home/av/code/emsdk/upstream/bin/clang -ferror-limit=100000 ./clang_test.c
./clang_test.c:32:42: error: argument type 'void' is incomplete
   32 |     printf("a is static, arr$len=%zu\n", arr$len(a));
      |                                          ^
./clang_test.c:12:9: note: expanded from macro 'arr$len'
   12 |         ({                                                                                         \
      |         ^
./clang_test.c:35:49: error: argument type 'void' is incomplete
   35 |     printf("a is kinda dynamic, arr$len=%zu\n", arr$len(a1));
      |                                                 ^
./clang_test.c:12:9: note: expanded from macro 'arr$len'
   12 |         ({                                                                                         \
      |         ^
2 errors generated.
```

If you remove `_Pragma("GCC diagnostic pop");    ` in `arr$len()` macro, it compiles and runs properly.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to