1 // RUN: %clang_cc1 -fsyntax-only -Wformat -verify %s -Wno-error=non-pod-varargs
2 // RUN: %clang_cc1 -fsyntax-only -Wformat -verify -std=c++98 %s -Wno-error=non-pod-varargs
3 // RUN: %clang_cc1 -fsyntax-only -Wformat -verify -std=c++11 %s -Wno-error=non-pod-varargs
4 
5 #include <stdarg.h>
6 
7 extern "C" {
8 extern int printf(const char *restrict, ...);
9 extern int sprintf(char *, const char *restrict, ...);
10 }
11 
12 class HasCStr {
13   const char *str;
14  public:
HasCStr(const char * s)15   HasCStr(const char *s): str(s) { }
c_str()16   const char *c_str() {return str;}
17 };
18 
19 class HasNoCStr {
20   const char *str;
21  public:
HasNoCStr(const char * s)22   HasNoCStr(const char *s): str(s) { }
not_c_str()23   const char *not_c_str() {return str;}
24 };
25 
26 extern const char extstr[16];
pod_test()27 void pod_test() {
28   char str[] = "test";
29   char dest[32];
30   char formatString[] = "non-const %s %s";
31   HasCStr hcs(str);
32   HasNoCStr hncs(str);
33   int n = 10;
34 
35   printf("%d: %s\n", n, hcs.c_str());
36   printf("%d: %s\n", n, hcs);
37 #if __cplusplus <= 199711L
38   // expected-warning@-2 {{cannot pass non-POD object of type 'HasCStr' to variadic function; expected type from format string was 'char *'}}
39   // expected-note@-3 {{did you mean to call the c_str() method?}}
40 #else
41   // expected-warning@-5 {{format specifies type 'char *' but the argument has type 'HasCStr'}}
42 #endif
43 
44   printf("%d: %s\n", n, hncs);
45 #if __cplusplus <= 199711L
46  // expected-warning@-2 {{cannot pass non-POD object of type 'HasNoCStr' to variadic function; expected type from format string was 'char *'}}
47 #else
48   // expected-warning@-4 {{format specifies type 'char *' but the argument has type 'HasNoCStr'}}
49 #endif
50 
51   sprintf(str, "%d: %s", n, hcs);
52 #if __cplusplus <= 199711L
53   // expected-warning@-2 {{cannot pass non-POD object of type 'HasCStr' to variadic function; expected type from format string was 'char *'}}
54   // expected-note@-3 {{did you mean to call the c_str() method?}}
55 #else
56   // expected-warning@-5 {{format specifies type 'char *' but the argument has type 'HasCStr'}}
57 #endif
58 
59   printf(formatString, hcs, hncs);
60 #if __cplusplus <= 199711L
61   // expected-warning@-2 {{cannot pass object of non-POD type 'HasCStr' through variadic function}}
62   // expected-warning@-3 {{cannot pass object of non-POD type 'HasNoCStr' through variadic function}}
63 #endif
64 
65   printf(extstr, hcs, n);
66 #if __cplusplus <= 199711L
67   // expected-warning@-2 {{cannot pass object of non-POD type 'HasCStr' through variadic function}}
68 #endif
69 }
70 
71 struct Printf {
72   Printf();
73   Printf(const Printf&);
74   Printf(const char *,...) __attribute__((__format__(__printf__,2,3)));
75 };
76 
constructor_test()77 void constructor_test() {
78   const char str[] = "test";
79   HasCStr hcs(str);
80   Printf p("%s %d %s", str, 10, 10); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
81   Printf q("%s %d", hcs, 10);
82 #if __cplusplus <= 199711L
83   // expected-warning@-2 {{cannot pass non-POD object of type 'HasCStr' to variadic constructor; expected type from format string was 'char *'}}
84   // expected-note@-3 {{did you mean to call the c_str() method?}}
85 #else
86   // expected-warning@-5 {{format specifies type 'char *' but the argument has type 'HasCStr'}}
87 #endif
88 }
89