llvm-project/clang/test/Analysis/logical-ops.c

55 lines
1.4 KiB
C
Raw Normal View History

[analyzer] PR37501: Disable assertion for logical op short circuit evaluation. The transfer function for the CFG element that represents a logical operation computes the value of the operation and does nothing else. The element appears after all the short circuit decisions were made, so they don't need to be made again at this point. Because our expression evaluation is imprecise, it is often hard to discriminate between: (1) we don't know the value of the RHS because we failed to evaluate it and (2) we don't know the value of the RHS because it didn't need to be evaluated. This is hard because it depends on our knowledge about the value of the LHS (eg., if LHS is true, then RHS in (LHS || RHS) doesn't need to be computed) but LHS itself may have been evaluated imprecisely and we don't know whether it is true or not. Additionally, the Analyzer wouldn't necessarily even remember what the value of the LHS was because theoretically it's not really necessary to know it for any future evaluations. In order to work around these issues, the transfer function for logical operations consists in looking at the ExplodedGraph we've constructed so far in order to figure out from which CFG direction did we arrive here. Such post-factum backtracking that doesn't involve looking up LHS and RHS values is usually possible. However sometimes it fails because when we deduplicate exploded nodes with the same program point and the same program state we may end up in a situation when we reached the same program point from two or more different directions. By removing the assertion, we admit that the procedure indeed sometimes fails to work. When it fails, we also admit that we don't know the value of the logical operator. Differential Revision: https://reviews.llvm.org/D59857 llvm-svn: 357325
2019-03-30 06:43:34 +08:00
// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,debug.ExprInspection\
// RUN: -analyzer-config eagerly-assume=false -verify %s
void clang_analyzer_eval(int);
void testAnd(int i, int *p) {
int *nullP = 0;
int *knownP = &i;
clang_analyzer_eval((knownP && knownP) == 1); // expected-warning{{TRUE}}
clang_analyzer_eval((knownP && nullP) == 0); // expected-warning{{TRUE}}
clang_analyzer_eval((knownP && p) == 1); // expected-warning{{UNKNOWN}}
}
void testOr(int i, int *p) {
int *nullP = 0;
int *knownP = &i;
clang_analyzer_eval((nullP || knownP) == 1); // expected-warning{{TRUE}}
clang_analyzer_eval((nullP || nullP) == 0); // expected-warning{{TRUE}}
clang_analyzer_eval((nullP || p) == 1); // expected-warning{{UNKNOWN}}
}
// PR13461
int testTypeIsInt(int i, void *p) {
if (i | (p && p))
return 1;
return 0;
}
// These crashed the analyzer at some point.
int between(char *x) {
extern char start[];
extern char end[];
return x >= start && x < end;
}
[analyzer] PR37501: Disable assertion for logical op short circuit evaluation. The transfer function for the CFG element that represents a logical operation computes the value of the operation and does nothing else. The element appears after all the short circuit decisions were made, so they don't need to be made again at this point. Because our expression evaluation is imprecise, it is often hard to discriminate between: (1) we don't know the value of the RHS because we failed to evaluate it and (2) we don't know the value of the RHS because it didn't need to be evaluated. This is hard because it depends on our knowledge about the value of the LHS (eg., if LHS is true, then RHS in (LHS || RHS) doesn't need to be computed) but LHS itself may have been evaluated imprecisely and we don't know whether it is true or not. Additionally, the Analyzer wouldn't necessarily even remember what the value of the LHS was because theoretically it's not really necessary to know it for any future evaluations. In order to work around these issues, the transfer function for logical operations consists in looking at the ExplodedGraph we've constructed so far in order to figure out from which CFG direction did we arrive here. Such post-factum backtracking that doesn't involve looking up LHS and RHS values is usually possible. However sometimes it fails because when we deduplicate exploded nodes with the same program point and the same program state we may end up in a situation when we reached the same program point from two or more different directions. By removing the assertion, we admit that the procedure indeed sometimes fails to work. When it fails, we also admit that we don't know the value of the logical operator. Differential Revision: https://reviews.llvm.org/D59857 llvm-svn: 357325
2019-03-30 06:43:34 +08:00
int undef(void) {}
void useUndef(void) { 0 || undef(); }
void testPointer(void) { (void) (1 && testPointer && 0); }
[analyzer] PR37501: Disable assertion for logical op short circuit evaluation. The transfer function for the CFG element that represents a logical operation computes the value of the operation and does nothing else. The element appears after all the short circuit decisions were made, so they don't need to be made again at this point. Because our expression evaluation is imprecise, it is often hard to discriminate between: (1) we don't know the value of the RHS because we failed to evaluate it and (2) we don't know the value of the RHS because it didn't need to be evaluated. This is hard because it depends on our knowledge about the value of the LHS (eg., if LHS is true, then RHS in (LHS || RHS) doesn't need to be computed) but LHS itself may have been evaluated imprecisely and we don't know whether it is true or not. Additionally, the Analyzer wouldn't necessarily even remember what the value of the LHS was because theoretically it's not really necessary to know it for any future evaluations. In order to work around these issues, the transfer function for logical operations consists in looking at the ExplodedGraph we've constructed so far in order to figure out from which CFG direction did we arrive here. Such post-factum backtracking that doesn't involve looking up LHS and RHS values is usually possible. However sometimes it fails because when we deduplicate exploded nodes with the same program point and the same program state we may end up in a situation when we reached the same program point from two or more different directions. By removing the assertion, we admit that the procedure indeed sometimes fails to work. When it fails, we also admit that we don't know the value of the logical operator. Differential Revision: https://reviews.llvm.org/D59857 llvm-svn: 357325
2019-03-30 06:43:34 +08:00
char *global_ap, *global_bp, *global_cp;
void ambiguous_backtrack_1() {
for (;;) {
(global_bp - global_ap ? global_cp[global_bp - global_ap] : 0) || 1;
global_bp++;
}
}
int global_a, global_b;
void ambiguous_backtrack_2(int x) {
global_a = x >= 2 ? 1 : x;
global_b == x && 9 || 2;
}