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