diff options
Diffstat (limited to 'clang/test')
-rw-r--r-- | clang/test/Analysis/std-c-library-functions.c | 184 | ||||
-rw-r--r-- | clang/test/Analysis/std-c-library-functions.cpp | 14 |
2 files changed, 198 insertions, 0 deletions
diff --git a/clang/test/Analysis/std-c-library-functions.c b/clang/test/Analysis/std-c-library-functions.c new file mode 100644 index 00000000000..4c5cfb8b1c5 --- /dev/null +++ b/clang/test/Analysis/std-c-library-functions.c @@ -0,0 +1,184 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=unix.StdCLibraryFunctions,debug.ExprInspection -verify %s + +void clang_analyzer_eval(int); + +int glob; + +typedef struct FILE FILE; +#define EOF -1 + +int getc(FILE *); +void test_getc(FILE *fp) { + int x; + while ((x = getc(fp)) != EOF) { + clang_analyzer_eval(x > 255); // expected-warning{{FALSE}} + clang_analyzer_eval(x >= 0); // expected-warning{{TRUE}} + } +} + +int fgetc(FILE *); +void test_fgets(FILE *fp) { + clang_analyzer_eval(fgetc(fp) < 256); // expected-warning{{TRUE}} + clang_analyzer_eval(fgetc(fp) >= 0); // expected-warning{{UNKNOWN}} +} + + +typedef unsigned long size_t; +typedef signed long ssize_t; +ssize_t read(int, void *, size_t); +ssize_t write(int, const void *, size_t); +void test_read_write(int fd, char *buf) { + glob = 1; + ssize_t x = write(fd, buf, 10); + clang_analyzer_eval(glob); // expected-warning{{UNKNOWN}} + if (x >= 0) { + clang_analyzer_eval(x <= 10); // expected-warning{{TRUE}} + ssize_t y = read(fd, &glob, sizeof(glob)); + if (y >= 0) { + clang_analyzer_eval(y <= sizeof(glob)); // expected-warning{{TRUE}} + } else { + // -1 overflows on promotion! + clang_analyzer_eval(y <= sizeof(glob)); // expected-warning{{FALSE}} + } + } else { + clang_analyzer_eval(x == -1); // expected-warning{{TRUE}} + } +} + +size_t fread(void *, size_t, size_t, FILE *); +size_t fwrite(const void *restrict, size_t, size_t, FILE *restrict); +void test_fread_fwrite(FILE *fp, int *buf) { + size_t x = fwrite(buf, sizeof(int), 10, fp); + clang_analyzer_eval(x <= 10); // expected-warning{{TRUE}} + size_t y = fread(buf, sizeof(int), 10, fp); + clang_analyzer_eval(y <= 10); // expected-warning{{TRUE}} + size_t z = fwrite(buf, sizeof(int), y, fp); + // FIXME: should be TRUE once symbol-symbol constraint support is improved. + clang_analyzer_eval(z <= y); // expected-warning{{UNKNOWN}} +} + +ssize_t getline(char **, size_t *, FILE *); +void test_getline(FILE *fp) { + char *line = 0; + size_t n = 0; + ssize_t len; + while ((len = getline(&line, &n, fp)) != -1) { + clang_analyzer_eval(len == 0); // expected-warning{{FALSE}} + } +} + +int isascii(int); +void test_isascii(int x) { + clang_analyzer_eval(isascii(123)); // expected-warning{{TRUE}} + clang_analyzer_eval(isascii(-1)); // expected-warning{{FALSE}} + if (isascii(x)) { + clang_analyzer_eval(x < 128); // expected-warning{{TRUE}} + clang_analyzer_eval(x >= 0); // expected-warning{{TRUE}} + } else { + if (x > 42) + clang_analyzer_eval(x >= 128); // expected-warning{{TRUE}} + else + clang_analyzer_eval(x < 0); // expected-warning{{TRUE}} + } + glob = 1; + isascii('a'); + clang_analyzer_eval(glob); // expected-warning{{TRUE}} +} + +int islower(int); +void test_islower(int x) { + clang_analyzer_eval(islower('x')); // expected-warning{{TRUE}} + clang_analyzer_eval(islower('X')); // expected-warning{{FALSE}} + if (islower(x)) + clang_analyzer_eval(x < 'a'); // expected-warning{{FALSE}} +} + +int getchar(void); +void test_getchar() { + int x = getchar(); + if (x == EOF) + return; + clang_analyzer_eval(x < 0); // expected-warning{{FALSE}} + clang_analyzer_eval(x < 256); // expected-warning{{TRUE}} +} + +int isalpha(int); +void test_isalpha() { + clang_analyzer_eval(isalpha(']')); // expected-warning{{FALSE}} + clang_analyzer_eval(isalpha('Q')); // expected-warning{{TRUE}} + clang_analyzer_eval(isalpha(128)); // expected-warning{{UNKNOWN}} +} + +int isalnum(int); +void test_alnum() { + clang_analyzer_eval(isalnum('1')); // expected-warning{{TRUE}} + clang_analyzer_eval(isalnum(')')); // expected-warning{{FALSE}} +} + +int isblank(int); +void test_isblank() { + clang_analyzer_eval(isblank('\t')); // expected-warning{{TRUE}} + clang_analyzer_eval(isblank(' ')); // expected-warning{{TRUE}} + clang_analyzer_eval(isblank('\n')); // expected-warning{{FALSE}} +} + +int ispunct(int); +void test_ispunct(int x) { + clang_analyzer_eval(ispunct(' ')); // expected-warning{{FALSE}} + clang_analyzer_eval(ispunct(-1)); // expected-warning{{FALSE}} + clang_analyzer_eval(ispunct('#')); // expected-warning{{TRUE}} + clang_analyzer_eval(ispunct('_')); // expected-warning{{TRUE}} + if (ispunct(x)) + clang_analyzer_eval(x < 127); // expected-warning{{TRUE}} +} + +int isupper(int); +void test_isupper(int x) { + if (isupper(x)) + clang_analyzer_eval(x < 'A'); // expected-warning{{FALSE}} +} + +int isgraph(int); +int isprint(int); +void test_isgraph_isprint(int x) { + char y = x; + if (isgraph(y)) + clang_analyzer_eval(isprint(x)); // expected-warning{{TRUE}} +} + +int isdigit(int); +void test_mixed_branches(int x) { + if (isdigit(x)) { + clang_analyzer_eval(isgraph(x)); // expected-warning{{TRUE}} + clang_analyzer_eval(isblank(x)); // expected-warning{{FALSE}} + } else if (isascii(x)) { + // isalnum() bifurcates here. + clang_analyzer_eval(isalnum(x)); // expected-warning{{TRUE}} // expected-warning{{FALSE}} + clang_analyzer_eval(isprint(x)); // expected-warning{{TRUE}} // expected-warning{{FALSE}} + } +} + +int isspace(int); +void test_isspace(int x) { + if (!isascii(x)) + return; + char y = x; + if (y == ' ') + clang_analyzer_eval(isspace(x)); // expected-warning{{TRUE}} +} + +int isxdigit(int); +void test_isxdigit(int x) { + if (isxdigit(x) && isupper(x)) { + clang_analyzer_eval(x >= 'A'); // expected-warning{{TRUE}} + clang_analyzer_eval(x <= 'F'); // expected-warning{{TRUE}} + } +} + +void test_call_by_pointer() { + typedef int (*func)(int); + func f = isascii; + clang_analyzer_eval(f('A')); // expected-warning{{TRUE}} + f = ispunct; + clang_analyzer_eval(f('A')); // expected-warning{{FALSE}} +} diff --git a/clang/test/Analysis/std-c-library-functions.cpp b/clang/test/Analysis/std-c-library-functions.cpp new file mode 100644 index 00000000000..271fffde692 --- /dev/null +++ b/clang/test/Analysis/std-c-library-functions.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=unix.StdCLibraryFunctions,debug.ExprInspection -verify %s + +// Test that we don't model functions with broken prototypes. +// Because they probably work differently as well. +// +// This test lives in a separate file because we wanted to test all functions +// in the .c file, however in C there are no overloads. + +void clang_analyzer_eval(bool); +bool isalpha(char); + +void test() { + clang_analyzer_eval(isalpha('A')); // no-crash // expected-warning{{UNKNOWN}} +} |