| // RUN: %clang_analyze_cc1 -verify %s \ |
| // RUN: -analyzer-checker=core \ |
| // RUN: -analyzer-checker=unix.Stream \ |
| // RUN: -analyzer-config unix.Stream:Pedantic=true \ |
| // RUN: -analyzer-checker=debug.StreamTester \ |
| // RUN: -analyzer-checker=debug.ExprInspection |
| |
| #include "Inputs/system-header-simulator.h" |
| |
| void clang_analyzer_eval(int); |
| void clang_analyzer_dump(int); |
| void clang_analyzer_warnIfReached(void); |
| void StreamTesterChecker_make_feof_stream(FILE *); |
| void StreamTesterChecker_make_ferror_stream(FILE *); |
| void StreamTesterChecker_make_ferror_indeterminate_stream(FILE *); |
| |
| void error_fopen(void) { |
| FILE *F = fopen("file", "r"); |
| if (!F) |
| return; |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| fclose(F); |
| } |
| |
| void error_fdopen(int fd) { |
| FILE *F = fdopen(fd, "r"); |
| if (!F) |
| return; |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| fclose(F); |
| } |
| |
| void error_freopen(void) { |
| FILE *F = fopen("file", "r"); |
| if (!F) |
| return; |
| F = freopen(0, "w", F); |
| if (!F) |
| return; |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| fclose(F); |
| } |
| |
| void stream_error_feof(void) { |
| FILE *F = fopen("file", "r"); |
| if (!F) |
| return; |
| StreamTesterChecker_make_feof_stream(F); |
| clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| clearerr(F); |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| StreamTesterChecker_make_ferror_indeterminate_stream(F); |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| fclose(F); |
| } |
| |
| void stream_error_ferror(void) { |
| FILE *F = fopen("file", "r"); |
| if (!F) |
| return; |
| StreamTesterChecker_make_ferror_stream(F); |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} |
| clearerr(F); |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| StreamTesterChecker_make_ferror_indeterminate_stream(F); |
| clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} |
| fclose(F); |
| } |
| |
| void error_fread(void) { |
| FILE *F = tmpfile(); |
| if (!F) |
| return; |
| char Buf[10]; |
| int Ret = fread(Buf, 1, 10, F); |
| if (Ret == 10) { |
| clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}} |
| } else { |
| clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{TRUE}} |
| if (feof(F)) { |
| clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} |
| fread(Buf, 1, 10, F); // expected-warning {{Read function called when stream is in EOF state}} |
| clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| } |
| if (ferror(F)) { |
| clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} |
| fread(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}} |
| } |
| } |
| fclose(F); |
| Ret = fread(Buf, 1, 10, F); // expected-warning {{Stream might be already closed}} |
| } |
| |
| void error_fwrite(void) { |
| FILE *F = tmpfile(); |
| if (!F) |
| return; |
| const char *Buf = "123456789"; |
| int Ret = fwrite(Buf, 1, 10, F); |
| if (Ret == 10) { |
| clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}} |
| } else { |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} |
| fwrite(0, 1, 10, F); // expected-warning {{might be 'indeterminate'}} |
| } |
| fclose(F); |
| Ret = fwrite(0, 1, 10, F); // expected-warning {{Stream might be already closed}} |
| } |
| |
| void error_fgetc(void) { |
| FILE *F = tmpfile(); |
| if (!F) |
| return; |
| int Ret = fgetc(F); |
| if (0 <= Ret && Ret <= 255) { |
| clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}} |
| } else { |
| clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}} |
| clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{TRUE}} |
| if (feof(F)) { |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| fgetc(F); // expected-warning {{Read function called when stream is in EOF state}} |
| } else { |
| clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} |
| fgetc(F); // expected-warning {{might be 'indeterminate'}} |
| } |
| } |
| fclose(F); |
| fgetc(F); // expected-warning {{Stream might be already closed}} |
| } |
| |
| void error_fgets(void) { |
| FILE *F = tmpfile(); |
| char Buf[256]; |
| if (!F) |
| return; |
| char *Ret = fgets(Buf, sizeof(Buf), F); |
| if (Ret == Buf) { |
| clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}} |
| } else { |
| clang_analyzer_eval(Ret == NULL); // expected-warning {{TRUE}} |
| clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{TRUE}} |
| if (feof(F)) { |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| fgets(Buf, sizeof(Buf), F); // expected-warning {{Read function called when stream is in EOF state}} |
| } else { |
| clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} |
| fgets(Buf, sizeof(Buf), F); // expected-warning {{might be 'indeterminate'}} |
| } |
| } |
| fclose(F); |
| fgets(Buf, sizeof(Buf), F); // expected-warning {{Stream might be already closed}} |
| } |
| |
| void error_fputc(int fd) { |
| FILE *F = fdopen(fd, "w"); |
| if (!F) |
| return; |
| int Ret = fputc('X', F); |
| if (Ret == EOF) { |
| clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| fputc('Y', F); // expected-warning {{might be 'indeterminate'}} |
| } else { |
| clang_analyzer_eval(Ret == 'X'); // expected-warning {{TRUE}} |
| clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}} |
| fputc('Y', F); // no-warning |
| } |
| fclose(F); |
| fputc('A', F); // expected-warning {{Stream might be already closed}} |
| } |
| |
| void error_fputs(void) { |
| FILE *F = tmpfile(); |
| if (!F) |
| return; |
| int Ret = fputs("XYZ", F); |
| if (Ret >= 0) { |
| clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}} |
| fputs("QWD", F); // no-warning |
| } else { |
| clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| fputs("QWD", F); // expected-warning {{might be 'indeterminate'}} |
| } |
| fclose(F); |
| fputs("ABC", F); // expected-warning {{Stream might be already closed}} |
| } |
| |
| void error_fprintf(void) { |
| FILE *F = tmpfile(); |
| if (!F) |
| return; |
| int Ret = fprintf(F, "aaa"); |
| if (Ret >= 0) { |
| clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}} |
| fprintf(F, "bbb"); // no-warning |
| } else { |
| clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| fprintf(F, "bbb"); // expected-warning {{might be 'indeterminate'}} |
| } |
| fclose(F); |
| fprintf(F, "ccc"); // expected-warning {{Stream might be already closed}} |
| } |
| |
| void error_fscanf(int *A) { |
| FILE *F = tmpfile(); |
| if (!F) |
| return; |
| int Ret = fscanf(F, "a%ib", A); |
| if (Ret >= 0) { |
| clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}} |
| fscanf(F, "bbb"); // no-warning |
| } else { |
| if (ferror(F)) { |
| clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} |
| fscanf(F, "bbb"); // expected-warning {{might be 'indeterminate'}} |
| } else if (feof(F)) { |
| clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} |
| fscanf(F, "bbb"); // expected-warning {{is in EOF state}} |
| clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}} |
| } else { |
| clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} |
| fscanf(F, "bbb"); // expected-warning {{might be 'indeterminate'}} |
| } |
| } |
| fclose(F); |
| fscanf(F, "ccc"); // expected-warning {{Stream might be already closed}} |
| } |
| |
| void error_ungetc(int TestIndeterminate) { |
| FILE *F = tmpfile(); |
| if (!F) |
| return; |
| int Ret = ungetc('X', F); |
| clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}} |
| if (Ret == EOF) { |
| clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} |
| } else { |
| clang_analyzer_eval(Ret == 'X'); // expected-warning {{TRUE}} |
| } |
| fputc('Y', F); // no-warning |
| if (TestIndeterminate) { |
| StreamTesterChecker_make_ferror_indeterminate_stream(F); |
| ungetc('X', F); // expected-warning {{might be 'indeterminate'}} |
| } |
| fclose(F); |
| ungetc('A', F); // expected-warning {{Stream might be already closed}} |
| } |
| |
| void error_getdelim(char *P, size_t Sz) { |
| FILE *F = tmpfile(); |
| if (!F) |
| return; |
| ssize_t Ret = getdelim(&P, &Sz, '\t', F); |
| if (Ret >= 0) { |
| clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}} |
| } else { |
| clang_analyzer_eval(Ret == -1); // expected-warning {{TRUE}} |
| clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{TRUE}} |
| if (feof(F)) { |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| getdelim(&P, &Sz, '\n', F); // expected-warning {{Read function called when stream is in EOF state}} |
| } else { |
| clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} |
| getdelim(&P, &Sz, '\n', F); // expected-warning {{might be 'indeterminate'}} |
| } |
| } |
| fclose(F); |
| getdelim(&P, &Sz, '\n', F); // expected-warning {{Stream might be already closed}} |
| } |
| |
| void error_getline(char *P, size_t Sz) { |
| FILE *F = tmpfile(); |
| if (!F) |
| return; |
| ssize_t Ret = getline(&P, &Sz, F); |
| if (Ret >= 0) { |
| clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}} |
| } else { |
| clang_analyzer_eval(Ret == -1); // expected-warning {{TRUE}} |
| clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{TRUE}} |
| if (feof(F)) { |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| getline(&P, &Sz, F); // expected-warning {{Read function called when stream is in EOF state}} |
| } else { |
| clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} |
| getline(&P, &Sz, F); // expected-warning {{might be 'indeterminate'}} |
| } |
| } |
| fclose(F); |
| getline(&P, &Sz, F); // expected-warning {{Stream might be already closed}} |
| } |
| |
| void write_after_eof_is_allowed(void) { |
| FILE *F = tmpfile(); |
| if (!F) |
| return; |
| StreamTesterChecker_make_feof_stream(F); |
| if (fputs("QWD", F) >= 0) // no-warning |
| clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}} |
| StreamTesterChecker_make_feof_stream(F); |
| if (fputc('Q', F) == 'Q') // no-warning |
| clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}} |
| StreamTesterChecker_make_feof_stream(F); |
| if (fwrite("012345678", 1, 10, F) == 10) // no-warning |
| clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}} |
| fclose(F); |
| } |
| |
| void freadwrite_zerosize(FILE *F) { |
| size_t Ret; |
| Ret = fwrite(0, 1, 0, F); |
| clang_analyzer_dump(Ret); // expected-warning {{0 }} |
| Ret = fwrite(0, 0, 1, F); |
| clang_analyzer_dump(Ret); // expected-warning {{0 }} |
| Ret = fread(0, 1, 0, F); |
| clang_analyzer_dump(Ret); // expected-warning {{0 }} |
| Ret = fread(0, 0, 1, F); |
| clang_analyzer_dump(Ret); // expected-warning {{0 }} |
| } |
| |
| void freadwrite_zerosize_eofstate(FILE *F) { |
| fwrite(0, 1, 0, F); |
| fwrite(0, 0, 1, F); |
| fread(0, 1, 0, F); // expected-warning {{Read function called when stream is in EOF state}} |
| fread(0, 0, 1, F); // expected-warning {{Read function called when stream is in EOF state}} |
| } |
| |
| void error_fread_fwrite_zerosize(void) { |
| FILE *F = fopen("file", "r"); |
| if (!F) |
| return; |
| |
| freadwrite_zerosize(F); |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| |
| StreamTesterChecker_make_ferror_stream(F); |
| freadwrite_zerosize(F); |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} |
| |
| StreamTesterChecker_make_feof_stream(F); |
| freadwrite_zerosize_eofstate(F); |
| clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| |
| fclose(F); |
| } |
| |
| void error_fseek(void) { |
| FILE *F = fopen("file", "r"); |
| if (!F) |
| return; |
| int rc = fseek(F, 1, SEEK_SET); |
| if (rc) { |
| clang_analyzer_eval(rc == -1); // expected-warning {{TRUE}} |
| int IsFEof = feof(F), IsFError = ferror(F); |
| // Get ferror or no error. |
| clang_analyzer_eval(IsFError); // expected-warning {{FALSE}} \ |
| // expected-warning {{TRUE}} |
| clang_analyzer_eval(IsFEof); // expected-warning {{FALSE}} |
| // Error flags should not change. |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| if (IsFError) |
| clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} |
| } else { |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| // Error flags should not change. |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| } |
| fclose(F); |
| } |
| |
| void error_fseeko(void) { |
| FILE *F = fopen("file", "r"); |
| if (!F) |
| return; |
| int rc = fseeko(F, 1, SEEK_SET); |
| if (rc) { |
| // Get ferror or no error. |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} \ |
| // expected-warning {{TRUE}} |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| } else { |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| } |
| fclose(F); |
| } |
| |
| void error_fseek_0(void) { |
| FILE *F = fopen("file", "r"); |
| if (!F) |
| return; |
| int rc = fseek(F, 0, SEEK_SET); |
| if (rc == -1) { |
| int IsFEof = feof(F), IsFError = ferror(F); |
| // Get ferror or no error, but not feof. |
| clang_analyzer_eval(IsFError); |
| // expected-warning@-1 {{FALSE}} |
| // expected-warning@-2 {{TRUE}} |
| clang_analyzer_eval(IsFEof); |
| // expected-warning@-1 {{FALSE}} |
| // Error flags should not change. |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| if (IsFError) |
| clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} |
| else |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| } else { |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| // Error flags should not change. |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| } |
| fclose(F); |
| } |
| |
| void error_fseeko_0(void) { |
| FILE *F = fopen("file", "r"); |
| if (!F) |
| return; |
| int rc = fseeko(F, 0, SEEK_SET); |
| if (rc) { |
| int IsFEof = feof(F), IsFError = ferror(F); |
| // Get ferror or no error, but not feof. |
| clang_analyzer_eval(IsFError); |
| // expected-warning@-1 {{FALSE}} |
| // expected-warning@-2 {{TRUE}} |
| clang_analyzer_eval(IsFEof); |
| // expected-warning@-1 {{FALSE}} |
| } else { |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| } |
| fclose(F); |
| } |
| |
| void error_ftell(int TestIndeterminate) { |
| FILE *F = fopen("file", "r"); |
| if (!F) |
| return; |
| long rc = ftell(F); |
| if (rc >= 0) |
| clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} |
| else |
| clang_analyzer_eval(rc == -1); // expected-warning {{TRUE}} |
| clang_analyzer_eval(feof(F) && ferror(F)); // expected-warning {{FALSE}} |
| StreamTesterChecker_make_feof_stream(F); |
| rc = ftell(F); |
| clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| StreamTesterChecker_make_ferror_stream(F); |
| rc = ftell(F); |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} |
| if (TestIndeterminate) { |
| StreamTesterChecker_make_ferror_indeterminate_stream(F); |
| ftell(F); // expected-warning {{might be 'indeterminate'}} |
| } |
| fclose(F); |
| } |
| |
| void error_ftello(int TestIndeterminate) { |
| FILE *F = fopen("file", "r"); |
| if (!F) |
| return; |
| off_t rc = ftello(F); |
| if (rc >= 0) |
| clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} |
| else |
| clang_analyzer_eval(rc == -1); // expected-warning {{TRUE}} |
| clang_analyzer_eval(feof(F) && ferror(F)); // expected-warning {{FALSE}} |
| StreamTesterChecker_make_feof_stream(F); |
| rc = ftello(F); |
| clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| StreamTesterChecker_make_ferror_stream(F); |
| rc = ftello(F); |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} |
| if (TestIndeterminate) { |
| StreamTesterChecker_make_ferror_indeterminate_stream(F); |
| ftell(F); // expected-warning {{might be 'indeterminate'}} |
| } |
| fclose(F); |
| } |
| |
| void error_fileno(void) { |
| FILE *F = fopen("file", "r"); |
| if (!F) |
| return; |
| int N = fileno(F); |
| clang_analyzer_eval(N >= 0); // expected-warning {{TRUE}} |
| clang_analyzer_eval(feof(F) && ferror(F)); // expected-warning {{FALSE}} |
| StreamTesterChecker_make_feof_stream(F); |
| N = fileno(F); |
| clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} |
| StreamTesterChecker_make_ferror_stream(F); |
| N = fileno(F); |
| clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} |
| StreamTesterChecker_make_ferror_indeterminate_stream(F); |
| fileno(F); // no warning |
| fclose(F); |
| } |
| |
| void error_fflush_on_non_null_stream_clear_error_states(void) { |
| FILE *F0 = tmpfile(), *F1 = tmpfile(); |
| // `fflush` clears a non-EOF stream's error state. |
| if (F0) { |
| StreamTesterChecker_make_ferror_stream(F0); |
| if (fflush(F0) == 0) { // no-warning |
| clang_analyzer_eval(ferror(F0)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(feof(F0)); // expected-warning {{FALSE}} |
| } |
| fclose(F0); |
| } |
| // `fflush` clears an EOF stream's error state. |
| if (F1) { |
| StreamTesterChecker_make_feof_stream(F1); |
| if (fflush(F1) == 0) { // no-warning |
| clang_analyzer_eval(ferror(F1)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(feof(F1)); // expected-warning {{TRUE}} |
| } |
| fclose(F1); |
| } |
| } |
| |
| void error_fflush_on_null_stream_clear_error_states(void) { |
| FILE *F0 = tmpfile(), *F1 = tmpfile(); |
| // `fflush` clears all stream's error states, while retains their EOF states. |
| if (F0 && F1) { |
| StreamTesterChecker_make_ferror_stream(F0); |
| StreamTesterChecker_make_feof_stream(F1); |
| if (fflush(NULL) == 0) { // no-warning |
| clang_analyzer_eval(ferror(F0)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(feof(F0)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(ferror(F1)); // expected-warning {{FALSE}} |
| clang_analyzer_eval(feof(F1)); // expected-warning {{TRUE}} |
| } |
| } |
| if (F0) |
| fclose(F0); |
| if (F1) |
| fclose(F1); |
| } |
| |
| void error_indeterminate(void) { |
| FILE *F = fopen("file", "r+"); |
| if (!F) |
| return; |
| const char *Buf = "123456789"; |
| int rc = fseek(F, 0, SEEK_SET); |
| if (rc) { |
| if (feof(F)) { |
| fwrite(Buf, 1, 10, F); // no warning |
| } else if (ferror(F)) { |
| fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}} |
| } else { |
| fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}} |
| } |
| } |
| fclose(F); |
| } |
| |
| void error_indeterminate_clearerr(void) { |
| FILE *F = fopen("file", "r+"); |
| if (!F) |
| return; |
| const char *Buf = "123456789"; |
| int rc = fseek(F, 0, SEEK_SET); |
| if (rc) { |
| if (feof(F)) { |
| clearerr(F); |
| fwrite(Buf, 1, 10, F); // no warning |
| } else if (ferror(F)) { |
| clearerr(F); |
| fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}} |
| } else { |
| clearerr(F); |
| fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}} |
| } |
| } |
| fclose(F); |
| } |
| |
| void error_indeterminate_feof1(void) { |
| FILE *F = fopen("file", "r+"); |
| if (!F) |
| return; |
| char Buf[10]; |
| if (fread(Buf, 1, 10, F) < 10) { |
| if (feof(F)) { |
| // error is feof, should be non-indeterminate |
| fwrite("1", 1, 1, F); // no warning |
| } |
| } |
| fclose(F); |
| } |
| |
| void error_indeterminate_feof2(void) { |
| FILE *F = fopen("file", "r+"); |
| if (!F) |
| return; |
| char Buf[10]; |
| if (fread(Buf, 1, 10, F) < 10) { |
| if (ferror(F) == 0) { |
| // error is feof, should be non-indeterminate |
| fwrite("1", 1, 1, F); // no warning |
| } |
| } |
| fclose(F); |
| } |