clang reports _Generic type coersion as passing NULL to strlen
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Given this code:
```C
#include
#include
struct MyString
{
char *chars;
size_t len;
};
#define coerce_type(x, ty) \
_Generic(x, ty: x, default: (ty){})
#define slen(s) \
_Generic(s, \
char*: strlen(coerce_type(s, char*)), \
struct MyString: coerce_type(s, struct MyString).len \
)
int main()
{
struct MyString ms = {"123", 3};
size_t i = slen(ms);
size_t i2 = slen("4567");
printf("%zu %zu", i, i2);
}
```
Which is a common technique when using `_Generic` to make sure all branches are valid expressions.
Clang generates the following reports:
```console
:22:16: warning: null passed to a callee that requires a non-null argument [-Wnonnull]
22 | size_t i = slen(ms);
| ^~~~~~~~
:15:19: note: expanded from macro 'slen'
15 | char*: strlen(coerce_type(s, char*)), \
| ^~~~~~~~~~~~~~~~~~~~~
:10:28: note: expanded from macro 'coerce_type'
10 | #define coerce_type(x, ty) \
| ^
11 | _Generic(x, ty: x, default: (ty){})
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
```
In reality, the expression `strlen((ty){})` (which expands to `strlen((char*){})` aka `strlen(NULL)`) will never be the result of the `_Generic` when passing a `struct MyString`.
[Godbolt link](https://godbolt.org/z/13dKnWTET)
Contributor guide
Assessment
This issue has not been assessed yet.