1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,debug.ExprInspection -verify %s
2 // RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,debug.ExprInspection -verify %s
5 // This file is for tests that may eventually go into string.c, or may be
6 // deleted outright. At one point these tests passed, but only because we
7 // weren't correctly modelling the behavior of the relevant string functions.
8 // The tests aren't incorrect, but require the analyzer to be smarter about
9 // conjured values than it currently is.
11 //===----------------------------------------------------------------------===
13 //===----------------------------------------------------------------------===
15 // Some functions are so similar to each other that they follow the same code
16 // path, such as memcpy and __memcpy_chk, or memcmp and bcmp. If VARIANT is
17 // defined, make sure to use the variants instead to make sure they are still
18 // checked by the analyzer.
20 // Some functions are implemented as builtins. These should be #defined as
21 // BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined.
23 // Functions that have variants and are also available as builtins should be
24 // declared carefully! See memcpy() for an example.
27 # define BUILTIN(f) __builtin_ ## f
28 #else /* USE_BUILTINS */
30 #endif /* USE_BUILTINS */
33 typedef typeof(sizeof(int)) size_t;
35 void clang_analyzer_eval(int);
37 //===----------------------------------------------------------------------===
39 //===----------------------------------------------------------------------===
41 #define strnlen BUILTIN(strnlen)
42 size_t strnlen(const char *s
, size_t maxlen
);
44 void strnlen_liveness(const char *x
) {
45 if (strnlen(x
, 10) < 5)
47 clang_analyzer_eval(strnlen(x
, 10) < 5); // expected-warning{{FALSE}}
50 void strnlen_subregion() {
51 struct two_stringsn
{ char a
[2], b
[2]; };
52 extern void use_two_stringsn(struct two_stringsn
*);
54 struct two_stringsn z
;
57 size_t a
= strnlen(z
.a
, 10);
59 size_t b
= strnlen(z
.a
, 10);
61 clang_analyzer_eval(b
== 0); // expected-warning{{TRUE}}
65 size_t c
= strnlen(z
.a
, 10);
67 clang_analyzer_eval(c
== 0); // expected-warning{{UNKNOWN}}
70 extern void use_stringn(char *);
71 void strnlen_argument(char *x
) {
72 size_t a
= strnlen(x
, 10);
73 size_t b
= strnlen(x
, 10);
75 clang_analyzer_eval(b
== 0); // expected-warning{{TRUE}}
79 size_t c
= strnlen(x
, 10);
81 clang_analyzer_eval(c
== 0); // expected-warning{{UNKNOWN}}
84 extern char global_strn
[];
85 void strnlen_global() {
86 size_t a
= strnlen(global_strn
, 10);
87 size_t b
= strnlen(global_strn
, 10);
89 clang_analyzer_eval(b
== 0); // expected-warning{{TRUE}}
91 // Call a function with unknown effects, which should invalidate globals.
94 size_t c
= strnlen(global_strn
, 10);
96 clang_analyzer_eval(c
== 0); // expected-warning{{UNKNOWN}}
99 void strnlen_indirect(char *x
) {
100 size_t a
= strnlen(x
, 10);
103 size_t b
= strnlen(x
, 10);
105 clang_analyzer_eval(b
== 0); // expected-warning{{TRUE}}
107 extern void use_stringn_ptr(char*const*);
110 size_t c
= strnlen(x
, 10);
112 clang_analyzer_eval(c
== 0); // expected-warning{{UNKNOWN}}