1 | // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s |
2 | |
3 | // Nullability of const string-like globals, testing |
4 | // NonnullGlobalConstantsChecker. |
5 | |
6 | void clang_analyzer_eval(bool); |
7 | |
8 | @class NSString; |
9 | typedef const struct __CFString *CFStringRef; |
10 | typedef const struct __CFBoolean * CFBooleanRef; |
11 | |
12 | // Global NSString* is non-null. |
13 | extern NSString *const StringConstGlobal; |
14 | void stringConstGlobal() { |
15 | clang_analyzer_eval(StringConstGlobal); // expected-warning{{TRUE}} |
16 | } |
17 | |
18 | // The logic does not apply to local variables though. |
19 | extern NSString *stringGetter(); |
20 | void stringConstLocal() { |
21 | NSString *const local = stringGetter(); |
22 | clang_analyzer_eval(local); // expected-warning{{UNKNOWN}} |
23 | } |
24 | |
25 | // Global const CFStringRef's are also assumed to be non-null. |
26 | extern const CFStringRef CFStringConstGlobal; |
27 | void cfStringCheckGlobal() { |
28 | clang_analyzer_eval(CFStringConstGlobal); // expected-warning{{TRUE}} |
29 | } |
30 | |
31 | // But only "const" ones. |
32 | extern CFStringRef CFStringNonConstGlobal; |
33 | void cfStringCheckMutableGlobal() { |
34 | clang_analyzer_eval(CFStringNonConstGlobal); // expected-warning{{UNKNOWN}} |
35 | } |
36 | |
37 | // char* const is also assumed to be non-null. |
38 | extern const char *const ConstCharStarConst; |
39 | void constCharStarCheckGlobal() { |
40 | clang_analyzer_eval(ConstCharStarConst); // expected-warning{{TRUE}} |
41 | } |
42 | |
43 | // Pointer value can be mutable. |
44 | extern char *const CharStarConst; |
45 | void charStarCheckGlobal() { |
46 | clang_analyzer_eval(CharStarConst); // expected-warning{{TRUE}} |
47 | } |
48 | |
49 | // But the pointer itself should be immutable. |
50 | extern char *CharStar; |
51 | void charStartCheckMutableGlobal() { |
52 | clang_analyzer_eval(CharStar); // expected-warning{{UNKNOWN}} |
53 | } |
54 | |
55 | // Type definitions should also work across typedefs, for pointers: |
56 | typedef char *const str; |
57 | extern str globalStr; |
58 | void charStarCheckTypedef() { |
59 | clang_analyzer_eval(globalStr); // expected-warning{{TRUE}} |
60 | } |
61 | |
62 | // And for types. |
63 | typedef NSString *const NStr; |
64 | extern NStr globalNSString; |
65 | void NSStringCheckTypedef() { |
66 | clang_analyzer_eval(globalNSString); // expected-warning{{TRUE}} |
67 | } |
68 | |
69 | // Note that constness could be either inside |
70 | // the var declaration, or in a typedef. |
71 | typedef NSString *NStr2; |
72 | extern const NStr2 globalNSString2; |
73 | void NSStringCheckConstTypedef() { |
74 | clang_analyzer_eval(globalNSString2); // expected-warning{{TRUE}} |
75 | } |
76 | |
77 | // Nested typedefs should work as well. |
78 | typedef const CFStringRef str1; |
79 | typedef str1 str2; |
80 | extern str2 globalStr2; |
81 | void testNestedTypedefs() { |
82 | clang_analyzer_eval(globalStr2); // expected-warning{{TRUE}} |
83 | } |
84 | |
85 | // And for NSString *. |
86 | typedef NSString *const nstr1; |
87 | typedef nstr1 nstr2; |
88 | extern nstr2 nglobalStr2; |
89 | void testNestedTypedefsForNSString() { |
90 | clang_analyzer_eval(nglobalStr2); // expected-warning{{TRUE}} |
91 | } |
92 | |
93 | // And for CFBooleanRefs. |
94 | extern const CFBooleanRef kBool; |
95 | void testNonnullBool() { |
96 | clang_analyzer_eval(kBool); // expected-warning{{TRUE}} |
97 | } |
98 | |
99 | // And again, only for const one. |
100 | extern CFBooleanRef kBoolMutable; |
101 | void testNonnullNonconstBool() { |
102 | clang_analyzer_eval(kBoolMutable); // expected-warning{{UNKNOWN}} |
103 | } |
104 | |