You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
@@ -28,6 +28,33 @@ void record_context(int a, ...) {
28
28
};
29
29
}
30
30
31
+
// Ensure the correct behavior for promotable type UB checking.
32
+
voidpromotable(int a, ...) {
33
+
enum Unscoped1 { One = 0x7FFFFFFF };
34
+
(void)__builtin_va_arg(ap, Unscoped1); // ok
35
+
36
+
enum Unscoped2 { Two = 0xFFFFFFFF };
37
+
(void)__builtin_va_arg(ap, Unscoped2); // ok
38
+
39
+
enumclassScoped { Three };
40
+
(void)__builtin_va_arg(ap, Scoped); // ok
41
+
42
+
enum Fixed : int { Four };
43
+
(void)__builtin_va_arg(ap, Fixed); // ok
44
+
45
+
enum FixedSmall : char { Five };
46
+
(void)__builtin_va_arg(ap, FixedSmall); // expected-warning {{second argument to 'va_arg' is of promotable type 'FixedSmall'; this va_arg has undefined behavior because arguments will be promoted to 'int'}}
47
+
48
+
enum FixedLarge : longlong { Six };
49
+
(void)__builtin_va_arg(ap, FixedLarge); // ok
50
+
51
+
// Ensure that qualifiers are ignored.
52
+
(void)__builtin_va_arg(ap, constvolatileint); // ok
53
+
54
+
// Ensure that signed vs unsigned doesn't matter either.
55
+
(void)__builtin_va_arg(ap, unsignedint);
56
+
}
57
+
31
58
#if __cplusplus >= 201103L
32
59
// We used to have bugs identifying the correct enclosing function scope in a
0 commit comments