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