aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp18
-rw-r--r--clang/test/Analysis/errno-stdlibraryfunctions-notes.c12
-rw-r--r--clang/test/Analysis/std-c-library-functions-arg-constraints-note-tags.cpp4
-rw-r--r--clang/test/Analysis/std-c-library-functions-arg-constraints.c6
-rw-r--r--clang/test/Analysis/std-c-library-functions-path-notes.c17
-rw-r--r--clang/test/Analysis/stream-errno-note.c21
-rw-r--r--clang/test/Analysis/stream-note.c12
7 files changed, 31 insertions, 59 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 8d4fb12..1fb248b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -835,6 +835,7 @@ private:
for (ArgNo ArgN : VC->getArgsToTrack()) {
bugreporter::trackExpressionValue(N, Call.getArgExpr(ArgN), *R);
+ R->markInteresting(Call.getArgSVal(ArgN));
// All tracked arguments are important, highlight them.
R->addRange(Call.getArgSourceRange(ArgN));
}
@@ -1298,6 +1299,7 @@ void StdLibraryFunctionsChecker::checkPostCall(const CallEvent &Call,
// StdLibraryFunctionsChecker.
ExplodedNode *Pred = Node;
if (!Case.getNote().empty()) {
+ const SVal RV = Call.getReturnValue();
// If there is a description for this execution branch (summary case),
// use it as a note tag.
std::string Note =
@@ -1305,7 +1307,7 @@ void StdLibraryFunctionsChecker::checkPostCall(const CallEvent &Call,
cast<NamedDecl>(Call.getDecl())->getDeclName());
if (Summary.getInvalidationKd() == EvalCallAsPure) {
const NoteTag *Tag = C.getNoteTag(
- [Node, Note](PathSensitiveBugReport &BR) -> std::string {
+ [Node, Note, RV](PathSensitiveBugReport &BR) -> std::string {
// Try to omit the note if we know in advance which branch is
// taken (this means, only one branch exists).
// This check is performed inside the lambda, after other
@@ -1316,18 +1318,22 @@ void StdLibraryFunctionsChecker::checkPostCall(const CallEvent &Call,
// split that was performed by another checker (and can not find
// the successors). This is why this check is only used in the
// EvalCallAsPure case.
- if (Node->succ_size() > 1)
+ if (BR.isInteresting(RV) && Node->succ_size() > 1)
return Note;
return "";
- },
- /*IsPrunable=*/true);
+ });
Pred = C.addTransition(NewState, Pred, Tag);
} else {
- const NoteTag *Tag = C.getNoteTag(Note, /*IsPrunable=*/true);
+ const NoteTag *Tag =
+ C.getNoteTag([Note, RV](PathSensitiveBugReport &BR) -> std::string {
+ if (BR.isInteresting(RV))
+ return Note;
+ return "";
+ });
Pred = C.addTransition(NewState, Pred, Tag);
}
if (!Pred)
- break;
+ continue;
}
// If we can get a note tag for the errno change, add this additionally to
diff --git a/clang/test/Analysis/errno-stdlibraryfunctions-notes.c b/clang/test/Analysis/errno-stdlibraryfunctions-notes.c
index e520e4f..991384c 100644
--- a/clang/test/Analysis/errno-stdlibraryfunctions-notes.c
+++ b/clang/test/Analysis/errno-stdlibraryfunctions-notes.c
@@ -14,10 +14,8 @@ void clang_analyzer_warnIfReached();
void test1() {
access("path", 0);
- // expected-note@-1{{Assuming that 'access' fails}}
access("path", 0);
- // expected-note@-1{{Assuming that 'access' is successful}}
- // expected-note@-2{{'errno' may be undefined after successful call to 'access'}}
+ // expected-note@-1{{'errno' may be undefined after successful call to 'access'}}
if (errno != 0) {
// expected-warning@-1{{An undefined value may be read from 'errno'}}
// expected-note@-2{{An undefined value may be read from 'errno'}}
@@ -26,8 +24,7 @@ void test1() {
void test2() {
if (access("path", 0) == -1) {
- // expected-note@-1{{Assuming that 'access' fails}}
- // expected-note@-2{{Taking true branch}}
+ // expected-note@-1{{Taking true branch}}
// Failure path.
if (errno != 0) {
// expected-note@-1{{'errno' is not equal to 0}}
@@ -42,9 +39,8 @@ void test2() {
void test3() {
if (access("path", 0) != -1) {
// Success path.
- // expected-note@-2{{Assuming that 'access' is successful}}
- // expected-note@-3{{'errno' may be undefined after successful call to 'access'}}
- // expected-note@-4{{Taking true branch}}
+ // expected-note@-2{{'errno' may be undefined after successful call to 'access'}}
+ // expected-note@-3{{Taking true branch}}
if (errno != 0) {
// expected-warning@-1{{An undefined value may be read from 'errno'}}
// expected-note@-2{{An undefined value may be read from 'errno'}}
diff --git a/clang/test/Analysis/std-c-library-functions-arg-constraints-note-tags.cpp b/clang/test/Analysis/std-c-library-functions-arg-constraints-note-tags.cpp
index fc7116d..573b007 100644
--- a/clang/test/Analysis/std-c-library-functions-arg-constraints-note-tags.cpp
+++ b/clang/test/Analysis/std-c-library-functions-arg-constraints-note-tags.cpp
@@ -52,7 +52,7 @@ void test_buffer_size_note(char *buf, int y) {
int __test_case_note();
int test_case_note_1(int y) {
- int x0 = __test_case_note(); // expected-note{{Function returns 1}}
+ int x0 = __test_case_note();
int x = __test_case_note(); // expected-note{{Function returns 0}} \
// expected-note{{'x' initialized here}}
return y / x; // expected-warning{{Division by zero}} \
@@ -60,7 +60,7 @@ int test_case_note_1(int y) {
}
int test_case_note_2(int y) {
- int x = __test_case_note(); // expected-note{{Function returns 1}}
+ int x = __test_case_note();
return y / (x - 1); // expected-warning{{Division by zero}} \
// expected-note{{Division by zero}}
}
diff --git a/clang/test/Analysis/std-c-library-functions-arg-constraints.c b/clang/test/Analysis/std-c-library-functions-arg-constraints.c
index 2fdea1f..21f1d9f 100644
--- a/clang/test/Analysis/std-c-library-functions-arg-constraints.c
+++ b/clang/test/Analysis/std-c-library-functions-arg-constraints.c
@@ -35,8 +35,7 @@ void test_alnum_concrete(int v) {
}
void test_alnum_symbolic(int x) {
- int ret = isalnum(x); // \
- // bugpath-note{{Assuming the character is non-alphanumeric}}
+ int ret = isalnum(x);
(void)ret;
clang_analyzer_eval(EOF <= x && x <= 255); // \
@@ -170,8 +169,7 @@ void test_notnull_concrete(FILE *fp) {
// bugpath-note{{The 1st argument to 'fread' is NULL but should not be NULL}}
}
void test_notnull_symbolic(FILE *fp, int *buf) {
- fread(buf, sizeof(int), 10, fp); // \
- // bugpath-note{{'fread' fails}}
+ fread(buf, sizeof(int), 10, fp);
clang_analyzer_eval(buf != 0); // \
// report-warning{{TRUE}} \
// bugpath-warning{{TRUE}} \
diff --git a/clang/test/Analysis/std-c-library-functions-path-notes.c b/clang/test/Analysis/std-c-library-functions-path-notes.c
index 33d6152..6b5d1d7 100644
--- a/clang/test/Analysis/std-c-library-functions-path-notes.c
+++ b/clang/test/Analysis/std-c-library-functions-path-notes.c
@@ -22,11 +22,9 @@ char test_getenv() {
}
int test_isalpha(int *x, char c, char d) {
- int iad = isalpha(d);// \
- // expected-note{{Assuming the character is non-alphabetical}}
+ int iad = isalpha(d);
if (isalpha(c)) {// \
- // expected-note{{Taking true branch}} \
- // expected-note{{Assuming the character is alphabetical}}
+ // expected-note{{Taking true branch}}
x = NULL; // \
// expected-note{{Null pointer value stored to 'x'}}
}
@@ -38,7 +36,6 @@ int test_isalpha(int *x, char c, char d) {
int test_isdigit(int *x, char c) {
if (!isdigit(c)) {// \
- // expected-note{{Assuming the character is not a digit}} \
// expected-note{{Taking true branch}}
x = NULL; // \
// expected-note{{Null pointer value stored to 'x'}}
@@ -64,8 +61,7 @@ int test_islower(int *x) {
}
int test_bugpath_notes(FILE *f1, char c, FILE *f2) {
- int f = fileno(f2); // \
- // expected-note{{Assuming that 'fileno' is successful}}
+ int f = fileno(f2);
if (f == -1) // \
// expected-note{{Taking false branch}}
return 0;
@@ -77,3 +73,10 @@ int test_bugpath_notes(FILE *f1, char c, FILE *f2) {
// expected-warning{{The 1st argument to 'dup' is -1 but should be >= 0}} \
// expected-note{{The 1st argument to 'dup' is -1 but should be >= 0}}
}
+
+int test_fileno_arg_note(FILE *f1) {
+ return dup(fileno(f1)); // \
+ // expected-warning{{The 1st argument to 'dup' is < 0 but should be >= 0}} \
+ // expected-note{{The 1st argument to 'dup' is < 0 but should be >= 0}} \
+ // expected-note{{Assuming that 'fileno' fails}}
+}
diff --git a/clang/test/Analysis/stream-errno-note.c b/clang/test/Analysis/stream-errno-note.c
index d8aefba..4ab215a6 100644
--- a/clang/test/Analysis/stream-errno-note.c
+++ b/clang/test/Analysis/stream-errno-note.c
@@ -11,7 +11,6 @@
void check_fopen(void) {
FILE *F = fopen("xxx", "r");
// expected-note@-1{{'errno' may be undefined after successful call to 'fopen'}}
- // expected-note@-2{{'fopen' is successful}}
// expected-note@+2{{'F' is non-null}}
// expected-note@+1{{Taking false branch}}
if (!F)
@@ -24,7 +23,6 @@ void check_fopen(void) {
void check_tmpfile(void) {
FILE *F = tmpfile();
// expected-note@-1{{'errno' may be undefined after successful call to 'tmpfile'}}
- // expected-note@-2{{'tmpfile' is successful}}
// expected-note@+2{{'F' is non-null}}
// expected-note@+1{{Taking false branch}}
if (!F)
@@ -36,14 +34,12 @@ void check_tmpfile(void) {
void check_freopen(void) {
FILE *F = tmpfile();
- // expected-note@-1{{'tmpfile' is successful}}
// expected-note@+2{{'F' is non-null}}
// expected-note@+1{{Taking false branch}}
if (!F)
return;
F = freopen("xxx", "w", F);
// expected-note@-1{{'errno' may be undefined after successful call to 'freopen'}}
- // expected-note@-2{{'freopen' is successful}}
// expected-note@+2{{'F' is non-null}}
// expected-note@+1{{Taking false branch}}
if (!F)
@@ -55,14 +51,12 @@ void check_freopen(void) {
void check_fclose(void) {
FILE *F = tmpfile();
- // expected-note@-1{{'tmpfile' is successful}}
// expected-note@+2{{'F' is non-null}}
// expected-note@+1{{Taking false branch}}
if (!F)
return;
(void)fclose(F);
// expected-note@-1{{'errno' may be undefined after successful call to 'fclose'}}
- // expected-note@-2{{'fclose' is successful}}
if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}}
// expected-note@-1{{An undefined value may be read from 'errno'}}
}
@@ -70,14 +64,12 @@ void check_fclose(void) {
void check_fread(void) {
char Buf[10];
FILE *F = tmpfile();
- // expected-note@-1{{'tmpfile' is successful}}
// expected-note@+2{{'F' is non-null}}
// expected-note@+1{{Taking false branch}}
if (!F)
return;
(void)fread(Buf, 1, 10, F);
// expected-note@-1{{'errno' may be undefined after successful call to 'fread'}}
- // expected-note@-2{{'fread' is successful}}
if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}}
// expected-note@-1{{An undefined value may be read from 'errno'}}
(void)fclose(F);
@@ -86,14 +78,12 @@ void check_fread(void) {
void check_fread_size0(void) {
char Buf[10];
FILE *F = tmpfile();
- // expected-note@-1{{'tmpfile' is successful}}
// expected-note@+2{{'F' is non-null}}
// expected-note@+1{{Taking false branch}}
if (!F)
return;
fread(Buf, 0, 1, F);
// expected-note@-1{{'errno' may be undefined after successful call to 'fread'}}
- // expected-note@-2{{'fread' is successful}}
if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}}
// expected-note@-1{{An undefined value may be read from 'errno'}}
}
@@ -101,14 +91,12 @@ void check_fread_size0(void) {
void check_fread_nmemb0(void) {
char Buf[10];
FILE *F = tmpfile();
- // expected-note@-1{{'tmpfile' is successful}}
// expected-note@+2{{'F' is non-null}}
// expected-note@+1{{Taking false branch}}
if (!F)
return;
fread(Buf, 1, 0, F);
// expected-note@-1{{'errno' may be undefined after successful call to 'fread'}}
- // expected-note@-2{{'fread' is successful}}
if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}}
// expected-note@-1{{An undefined value may be read from 'errno'}}
}
@@ -116,14 +104,12 @@ void check_fread_nmemb0(void) {
void check_fwrite(void) {
char Buf[] = "0123456789";
FILE *F = tmpfile();
- // expected-note@-1{{'tmpfile' is successful}}
// expected-note@+2{{'F' is non-null}}
// expected-note@+1{{Taking false branch}}
if (!F)
return;
int R = fwrite(Buf, 1, 10, F);
// expected-note@-1{{'errno' may be undefined after successful call to 'fwrite'}}
- // expected-note@-2{{'fwrite' is successful}}
if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}}
// expected-note@-1{{An undefined value may be read from 'errno'}}
(void)fclose(F);
@@ -131,14 +117,12 @@ void check_fwrite(void) {
void check_fseek(void) {
FILE *F = tmpfile();
- // expected-note@-1{{'tmpfile' is successful}}
// expected-note@+2{{'F' is non-null}}
// expected-note@+1{{Taking false branch}}
if (!F)
return;
(void)fseek(F, 11, SEEK_SET);
// expected-note@-1{{'errno' may be undefined after successful call to 'fseek'}}
- // expected-note@-2{{'fseek' is successful}}
if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}}
// expected-note@-1{{An undefined value may be read from 'errno'}}
(void)fclose(F);
@@ -146,7 +130,6 @@ void check_fseek(void) {
void check_rewind_errnocheck(void) {
FILE *F = tmpfile();
- // expected-note@-1{{'tmpfile' is successful}}
// expected-note@+2{{'F' is non-null}}
// expected-note@+1{{Taking false branch}}
if (!F)
@@ -159,14 +142,12 @@ void check_rewind_errnocheck(void) {
void check_fileno(void) {
FILE *F = tmpfile();
- // expected-note@-1{{'tmpfile' is successful}}
// expected-note@+2{{'F' is non-null}}
// expected-note@+1{{Taking false branch}}
if (!F)
return;
fileno(F);
- // expected-note@-1{{Assuming that 'fileno' is successful}}
- // expected-note@-2{{'errno' may be undefined after successful call to 'fileno'}}
+ // expected-note@-1{{'errno' may be undefined after successful call to 'fileno'}}
if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}}
// expected-note@-1{{An undefined value may be read from 'errno'}}
(void)fclose(F);
diff --git a/clang/test/Analysis/stream-note.c b/clang/test/Analysis/stream-note.c
index 8d29771..2572457 100644
--- a/clang/test/Analysis/stream-note.c
+++ b/clang/test/Analysis/stream-note.c
@@ -13,7 +13,6 @@ void check_note_at_correct_open(void) {
// expected-note@-2 {{Taking false branch}}
return;
FILE *F2 = tmpfile();
- // stdargs-note@-1 {{'tmpfile' is successful}}
if (!F2) {
// expected-note@-1 {{'F2' is non-null}}
// expected-note@-2 {{Taking false branch}}
@@ -22,7 +21,6 @@ void check_note_at_correct_open(void) {
}
rewind(F2);
fclose(F2);
- // stdargs-note@-1 {{'fclose' fails}}
rewind(F1);
}
// expected-warning@-1 {{Opened stream never closed. Potential resource leak}}
@@ -59,7 +57,6 @@ void check_note_freopen(void) {
void check_note_leak_2(int c) {
FILE *F1 = fopen("foo1.c", "r"); // expected-note {{Stream opened here}}
// stdargs-note@-1 {{'fopen' is successful}}
- // stdargs-note@-2 {{'fopen' is successful}}
if (!F1)
// expected-note@-1 {{'F1' is non-null}}
// expected-note@-2 {{Taking false branch}}
@@ -68,7 +65,6 @@ void check_note_leak_2(int c) {
return;
FILE *F2 = fopen("foo2.c", "r"); // expected-note {{Stream opened here}}
// stdargs-note@-1 {{'fopen' is successful}}
- // stdargs-note@-2 {{'fopen' is successful}}
if (!F2) {
// expected-note@-1 {{'F2' is non-null}}
// expected-note@-2 {{Taking false branch}}
@@ -107,16 +103,13 @@ void check_eof_notes_feof_after_feof(void) {
FILE *F;
char Buf[10];
F = fopen("foo1.c", "r");
- // stdargs-note@-1 {{'fopen' is successful}}
if (F == NULL) { // expected-note {{Taking false branch}} expected-note {{'F' is not equal to NULL}}
return;
}
fread(Buf, 1, 1, F);
- // stdargs-note@-1 {{'fread' fails}}
if (feof(F)) { // expected-note {{Taking true branch}}
clearerr(F);
fread(Buf, 1, 1, F); // expected-note {{Assuming stream reaches end-of-file here}}
- // stdargs-note@-1 {{'fread' fails}}
if (feof(F)) { // expected-note {{Taking true branch}}
fread(Buf, 1, 1, F); // expected-warning {{Read function called when stream is in EOF state. Function has no effect}}
// expected-note@-1 {{Read function called when stream is in EOF state. Function has no effect}}
@@ -129,12 +122,10 @@ void check_eof_notes_feof_after_no_feof(void) {
FILE *F;
char Buf[10];
F = fopen("foo1.c", "r");
- // stdargs-note@-1 {{'fopen' is successful}}
if (F == NULL) { // expected-note {{Taking false branch}} expected-note {{'F' is not equal to NULL}}
return;
}
fread(Buf, 1, 1, F);
- // stdargs-note@-1 {{'fread' is successful}}
if (feof(F)) { // expected-note {{Taking false branch}}
fclose(F);
return;
@@ -143,7 +134,6 @@ void check_eof_notes_feof_after_no_feof(void) {
return;
}
fread(Buf, 1, 1, F); // expected-note {{Assuming stream reaches end-of-file here}}
- // stdargs-note@-1 {{'fread' fails}}
if (feof(F)) { // expected-note {{Taking true branch}}
fread(Buf, 1, 1, F); // expected-warning {{Read function called when stream is in EOF state. Function has no effect}}
// expected-note@-1 {{Read function called when stream is in EOF state. Function has no effect}}
@@ -155,11 +145,9 @@ void check_eof_notes_feof_or_no_error(void) {
FILE *F;
char Buf[10];
F = fopen("foo1.c", "r");
- // stdargs-note@-1 {{'fopen' is successful}}
if (F == NULL) // expected-note {{Taking false branch}} expected-note {{'F' is not equal to NULL}}
return;
int RRet = fread(Buf, 1, 1, F); // expected-note {{Assuming stream reaches end-of-file here}}
- // stdargs-note@-1 {{'fread' fails}}
if (ferror(F)) { // expected-note {{Taking false branch}}
} else {
fread(Buf, 1, 1, F); // expected-warning {{Read function called when stream is in EOF state. Function has no effect}}