llvm / llvm/llvm-project

clang reports _Generic type coersion as passing NULL to strlen

Open
#178,702 3 comments 0 reactions 0 assignees View on GitHub
clang:diagnostics false-positive
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.