blob: e5bf98f02d8b39f8ceec7efa2c3becdbffd1117b [file] [log] [blame]
// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-vararg %t
void f(int i);
void f_vararg(int i, ...);
struct C {
void g_vararg(...);
void g(const char*);
} c;
template<typename... P>
void cpp_vararg(P... p);
void check() {
f_vararg(1, 7, 9);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not call c-style vararg functions [cppcoreguidelines-pro-type-vararg]
c.g_vararg("foo");
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not call c-style vararg functions
f(3); // OK
c.g("foo"); // OK
cpp_vararg(1, 7, 9); // OK
}
// ... as a parameter is allowed (e.g. for SFINAE)
template <typename T>
void CallFooIfAvailableImpl(T& t, ...) {
// nothing
}
template <typename T>
void CallFooIfAvailableImpl(T& t, decltype(t.foo())*) {
t.foo();
}
template <typename T>
void CallFooIfAvailable(T& t) {
CallFooIfAvailableImpl(t, 0); // OK to call variadic function when the argument is a literal 0
}
#include <stdarg.h>
void my_printf(const char* format, ...) {
va_list ap;
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare variables of type va_list; use variadic templates instead
va_start(ap, format);
va_list n;
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare variables of type va_list; use variadic templates instead
va_copy(n, ap);
int i = va_arg(ap, int);
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not use va_arg to define c-style vararg functions; use variadic templates instead
va_end(ap);
}
int my_vprintf(const char* format, va_list arg ); // OK to declare function taking va_list
void ignoredBuiltinsTest() {
(void)__builtin_assume_aligned(0, 8);
(void)__builtin_constant_p(0);
(void)__builtin_fpclassify(0, 0, 0, 0, 0, 0.f);
(void)__builtin_isinf_sign(0.f);
(void)__builtin_prefetch(nullptr);
}
// Some implementations of __builtin_va_list and __builtin_ms_va_list desugared
// as 'char *' or 'void *'. This test checks whether we are handling this case
// correctly and not generating false positives.
void no_false_positive_desugar_va_list(char *in) {
char *tmp1 = in;
void *tmp2 = in;
}