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