1// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -pedantic %s
2
3#include <stdarg.h>
4
5extern "C" {
6extern int scanf(const char *restrict, ...);
7extern int printf(const char *restrict, ...);
8extern int vprintf(const char *restrict, va_list);
9}
10
11@class NSString;
12
13@interface Format
14+ (void)print:(NSString *)format, ... __attribute__((format(NSString, 1, 2)));
15@end
16
17
18namespace Templates {
19  template<typename T>
20  void my_uninstantiated_print(const T &arg) {
21    [Format print:@"%d", arg];
22  }
23
24  template<typename T>
25  void my_print(const T &arg) {
26    [Format print:@"%d", arg]; // expected-warning {{format specifies type 'int' but the argument has type 'const char *'}}
27  }
28
29  void use_my_print() {
30    my_print("abc"); // expected-note {{requested here}}
31  }
32
33
34  template<typename T>
35  class UninstantiatedPrinter {
36  public:
37    static void print(const T &arg) {
38      [Format print:@"%d", arg]; // no-warning
39    }
40  };
41
42  template<typename T>
43  class Printer {
44  public:
45    void print(const T &arg) {
46      [Format print:@"%d", arg]; // expected-warning {{format specifies type 'int' but the argument has type 'const char *'}}
47    }
48  };
49
50  void use_class(Printer<const char *> &p) {
51    p.print("abc"); // expected-note {{requested here}}
52  }
53
54
55  template<typename T>
56  class UninstantiatedWrapper {
57  public:
58    class Printer {
59    public:
60      void print(const T &arg) {
61        [Format print:@"%d", arg]; // no-warning
62      }
63    };
64  };
65
66  template<typename T>
67  class Wrapper {
68  public:
69    class Printer {
70    public:
71      void print(const T &arg) {
72        [Format print:@"%d", arg]; // expected-warning {{format specifies type 'int' but the argument has type 'const char *'}}
73      }
74    };
75  };
76
77  void use_class(Wrapper<const char *>::Printer &p) {
78    p.print("abc"); // expected-note {{requested here}}
79  }
80}
81
82