Correct the behavior of va_arg checking in C++
authorAaron Ballman <aaron@aaronballman.com>
Wed, 9 Jun 2021 11:15:15 +0000 (07:15 -0400)
committerAaron Ballman <aaron@aaronballman.com>
Wed, 9 Jun 2021 11:18:32 +0000 (07:18 -0400)
commitc92f505346b80fd053ef191bbc66810c9d564b0c
tree4faad490e8a4a4b231f8ef42869806d8dde2e857
parentc25572bf2993438f24b57d859d072e8b2aa975d2
Correct the behavior of va_arg checking in C++

Clang checks whether the type given to va_arg will automatically cause
undefined behavior, but this check was issuing false positives for
enumerations in C++. The issue turned out to be because
typesAreCompatible() in C++ checks whether the types are *the same*, so
this uses custom logic if the type compatibility check fails.

This issue was found by a user on code like:

typedef enum {
  CURLINFO_NONE,
  CURLINFO_EFFECTIVE_URL,
  CURLINFO_LASTONE = 60
} CURLINFO;

...

__builtin_va_arg(list, CURLINFO); // false positive warning

Given that C++ defers to C for the rules around va_arg, the behavior
should be the same in both C and C++ and not diagnose because int and
CURLINFO are "compatible enough" types for va_arg.
clang/lib/Sema/SemaExpr.cpp
clang/test/SemaCXX/varargs.cpp