|  | // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Stream,unix.Errno,unix.StdCLibraryFunctions,debug.ExprInspection \ | 
|  | // RUN:   -analyzer-config unix.Stream:Pedantic=true \ | 
|  | // RUN:   -analyzer-config unix.StdCLibraryFunctions:ModelPOSIX=true -verify %s | 
|  |  | 
|  | #include "Inputs/system-header-simulator.h" | 
|  | #include "Inputs/errno_func.h" | 
|  |  | 
|  | extern void clang_analyzer_eval(int); | 
|  | extern void clang_analyzer_dump(int); | 
|  | extern void clang_analyzer_printState(); | 
|  |  | 
|  | void check_fopen(void) { | 
|  | FILE *F = fopen("xxx", "r"); | 
|  | if (!F) { | 
|  | clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} | 
|  | if (errno) {} // no-warning | 
|  | return; | 
|  | } | 
|  | if (errno) {} // expected-warning{{An undefined value may be read from 'errno' [unix.Errno]}} | 
|  | } | 
|  |  | 
|  | void check_fdopen(int Fd) { | 
|  | FILE *F = fdopen(Fd, "r"); | 
|  | if (!F) { | 
|  | clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} | 
|  | if (errno) {}                    // no-warning | 
|  | } else { | 
|  | if (errno) {}                    // expected-warning{{An undefined value may be read from 'errno' [unix.Errno]}} | 
|  | } | 
|  | } | 
|  |  | 
|  | void check_tmpfile(void) { | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) { | 
|  | clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} | 
|  | if (errno) {} // no-warning | 
|  | return; | 
|  | } | 
|  | if (errno) {} // expected-warning{{An undefined value may be read from 'errno' [unix.Errno]}} | 
|  | } | 
|  |  | 
|  | void check_freopen(void) { | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  | F = freopen("xxx", "w", F); | 
|  | if (!F) { | 
|  | clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} | 
|  | if (errno) {} // no-warning | 
|  | return; | 
|  | } | 
|  | if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} | 
|  | } | 
|  |  | 
|  | void check_fclose(void) { | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  | int Ret = fclose(F); | 
|  | if (Ret == EOF) { | 
|  | clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} | 
|  | if (errno) {} // no-warning | 
|  | return; | 
|  | } | 
|  | if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} | 
|  | } | 
|  |  | 
|  | void check_fread_size0(void) { | 
|  | char Buf[10]; | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  | fread(Buf, 0, 1, F); | 
|  | if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} | 
|  | } | 
|  |  | 
|  | void check_fread_nmemb0(void) { | 
|  | char Buf[10]; | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  | fread(Buf, 1, 0, F); | 
|  | if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} | 
|  | } | 
|  |  | 
|  | void check_fread(void) { | 
|  | char Buf[10]; | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  |  | 
|  | int R = fread(Buf, 1, 10, F); | 
|  | if (R < 10) { | 
|  | clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} | 
|  | if (errno) {} // no-warning | 
|  | fclose(F); | 
|  | return; | 
|  | } | 
|  | if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} | 
|  | } | 
|  |  | 
|  | void check_fwrite_size0(void) { | 
|  | char Buf[] = "0123456789"; | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  | fwrite(Buf, 0, 1, F); | 
|  | if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} | 
|  | } | 
|  |  | 
|  | void check_fwrite_nmemb0(void) { | 
|  | char Buf[] = "0123456789"; | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  | fwrite(Buf, 1, 0, F); | 
|  | if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} | 
|  | } | 
|  |  | 
|  | void check_fwrite(void) { | 
|  | char Buf[] = "0123456789"; | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  |  | 
|  | int R = fwrite(Buf, 1, 10, F); | 
|  | if (R < 10) { | 
|  | clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} | 
|  | if (errno) {} // no-warning | 
|  | fclose(F); | 
|  | return; | 
|  | } | 
|  | if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} | 
|  | } | 
|  |  | 
|  | void check_fseek(void) { | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  | int S = fseek(F, 11, SEEK_SET); | 
|  | if (S != 0) { | 
|  | clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} | 
|  | clang_analyzer_eval(S == -1);    // expected-warning{{TRUE}} | 
|  | if (errno) {} // no-warning | 
|  | fclose(F); | 
|  | return; | 
|  | } | 
|  | if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} | 
|  | } | 
|  |  | 
|  | void check_fseeko(void) { | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  | int S = fseeko(F, 11, SEEK_SET); | 
|  | if (S == -1) { | 
|  | clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} | 
|  | if (errno) {}                    // no-warning | 
|  | } else { | 
|  | clang_analyzer_eval(S == 0);     // expected-warning{{TRUE}} | 
|  | if (errno) {}                    // expected-warning{{An undefined value may be read from 'errno'}} | 
|  | } | 
|  | fclose(F); | 
|  | } | 
|  |  | 
|  | void check_no_errno_change(void) { | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  | errno = 1; | 
|  | clearerr(F); | 
|  | if (errno) {} // no-warning | 
|  | feof(F); | 
|  | if (errno) {} // no-warning | 
|  | ferror(F); | 
|  | if (errno) {} // no-warning | 
|  | fileno(F); | 
|  | if (errno) {} // no-warning | 
|  | clang_analyzer_eval(errno == 1); // expected-warning{{TRUE}} | 
|  | fclose(F); | 
|  | } | 
|  |  | 
|  | void check_fgetpos(void) { | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  | errno = 0; | 
|  | fpos_t Pos; | 
|  | int Ret = fgetpos(F, &Pos); | 
|  | if (Ret) | 
|  | clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} | 
|  | else | 
|  | clang_analyzer_eval(errno == 0); // expected-warning{{TRUE}} | 
|  | if (errno) {} // no-warning | 
|  | fclose(F); | 
|  | } | 
|  |  | 
|  | void check_fsetpos(void) { | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  | errno = 0; | 
|  | fpos_t Pos; | 
|  | int Ret = fsetpos(F, &Pos); | 
|  | if (Ret) | 
|  | clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} | 
|  | else | 
|  | clang_analyzer_eval(errno == 0); // expected-warning{{TRUE}} | 
|  | if (errno) {} // no-warning | 
|  | fclose(F); | 
|  | } | 
|  |  | 
|  | void check_ftell(void) { | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  | errno = 0; | 
|  | long Ret = ftell(F); | 
|  | if (Ret == -1) { | 
|  | clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} | 
|  | } else { | 
|  | clang_analyzer_eval(errno == 0); // expected-warning{{TRUE}} | 
|  | clang_analyzer_eval(Ret >= 0); // expected-warning{{TRUE}} | 
|  | } | 
|  | if (errno) {} // no-warning | 
|  | fclose(F); | 
|  | } | 
|  |  | 
|  | void check_ftello(void) { | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  | off_t Ret = ftello(F); | 
|  | if (Ret >= 0) { | 
|  | if (errno) {}                    // expected-warning{{An undefined value may be read from 'errno'}} | 
|  | } else { | 
|  | clang_analyzer_eval(Ret == -1);  // expected-warning{{TRUE}} | 
|  | clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} | 
|  | if (errno) {}                    // no-warning | 
|  | } | 
|  | fclose(F); | 
|  | } | 
|  |  | 
|  | void check_rewind(void) { | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  | errno = 0; | 
|  | rewind(F); | 
|  | clang_analyzer_eval(errno == 0); | 
|  | // expected-warning@-1{{FALSE}} | 
|  | // expected-warning@-2{{TRUE}} | 
|  | fclose(F); | 
|  | } | 
|  |  | 
|  | void check_fflush_opened_file(void) { | 
|  | FILE *F = tmpfile(); | 
|  | if (!F) | 
|  | return; | 
|  | int N = fflush(F); | 
|  | if (N == EOF) { | 
|  | clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} | 
|  | if (errno) {}                    // no-warning | 
|  | } else { | 
|  | clang_analyzer_eval(N == 0);     // expected-warning{{TRUE}} | 
|  | if (errno) {}                    // expected-warning{{An undefined value may be read from 'errno'}} | 
|  | } | 
|  | fclose(F); | 
|  | } | 
|  |  | 
|  | void check_fflush_all(void) { | 
|  | int N = fflush(NULL); | 
|  | if (N == 0) { | 
|  | if (errno) {}                    // expected-warning{{An undefined value may be read from 'errno'}} | 
|  | } else { | 
|  | clang_analyzer_eval(N == EOF);   // expected-warning{{TRUE}} | 
|  | clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} | 
|  | if (errno) {}                    // no-warning | 
|  | } | 
|  | } |