1 // RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-vararg %t
2
3 void f(int i);
4 void f_vararg(int i, ...);
5
6 struct C {
7 void g_vararg(...);
8 void g(const char*);
9 } c;
10
11 template<typename... P>
12 void cpp_vararg(P... p);
13
check()14 void check() {
15 f_vararg(1, 7, 9);
16 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not call c-style vararg functions [cppcoreguidelines-pro-type-vararg]
17 c.g_vararg("foo");
18 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not call c-style vararg functions
19
20 f(3); // OK
21 c.g("foo"); // OK
22 cpp_vararg(1, 7, 9); // OK
23 }
24
25 // ... as a parameter is allowed (e.g. for SFINAE)
26 template <typename T>
CallFooIfAvailableImpl(T & t,...)27 void CallFooIfAvailableImpl(T& t, ...) {
28 // nothing
29 }
30 template <typename T>
31 void CallFooIfAvailableImpl(T& t, decltype(t.foo())*) {
32 t.foo();
33 }
34 template <typename T>
CallFooIfAvailable(T & t)35 void CallFooIfAvailable(T& t) {
36 CallFooIfAvailableImpl(t, 0); // OK to call variadic function when the argument is a literal 0
37 }
38
39 #include <stdarg.h>
my_printf(const char * format,...)40 void my_printf(const char* format, ...) {
41 va_list ap;
42 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare variables of type va_list; use variadic templates instead
43 va_start(ap, format);
44 va_list n;
45 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare variables of type va_list; use variadic templates instead
46 va_copy(n, ap);
47 int i = va_arg(ap, int);
48 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not use va_arg to define c-style vararg functions; use variadic templates instead
49 va_end(ap);
50 }
51
52 int my_vprintf(const char* format, va_list arg ); // OK to declare function taking va_list
53
ignoredBuiltinsTest()54 void ignoredBuiltinsTest() {
55 (void)__builtin_assume_aligned(0, 8);
56 (void)__builtin_constant_p(0);
57 (void)__builtin_fpclassify(0, 0, 0, 0, 0, 0.f);
58 (void)__builtin_isinf_sign(0.f);
59 (void)__builtin_prefetch(nullptr);
60 }
61
62 // Some implementations of __builtin_va_list and __builtin_ms_va_list desugared
63 // as 'char *' or 'void *'. This test checks whether we are handling this case
64 // correctly and not generating false positives.
no_false_positive_desugar_va_list(char * in)65 void no_false_positive_desugar_va_list(char *in) {
66 char *tmp1 = in;
67 void *tmp2 = in;
68 }
69