Index: clang/lib/StaticAnalyzer/Core/SValBuilder.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ clang/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -871,12 +871,16 @@ // Symbol to bool. if (!OriginalTy.isNull() && CastTy->isBooleanType()) { - // Non-float to bool. - if (Loc::isLocType(OriginalTy) || - OriginalTy->isIntegralOrEnumerationType() || - OriginalTy->isMemberPointerType()) { - BasicValueFactory &BVF = getBasicValueFactory(); - return makeNonLoc(SE, BO_NE, BVF.getValue(0, SE->getType()), CastTy); + // Symbolic integer to bool. + if (OriginalTy->isIntegralOrEnumerationType()) { + + // Integer is known to be non-zero or zero only. + auto truth = State->isNonNull(V); + if (truth.isConstrained()) + return makeTruthVal(truth.isConstrainedTrue(), CastTy); + + // Unconstrained integer to bool. + return V; } } else { // Symbol to integer. Index: clang/test/Analysis/cast_symbolic_ints_to_bool.cpp =================================================================== --- /dev/null +++ clang/test/Analysis/cast_symbolic_ints_to_bool.cpp @@ -0,0 +1,67 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s + +template +void clang_analyzer_dump(T); + +void test_int_to_bool(bool b, int x) { + clang_analyzer_dump(b); // expected-warning{{reg_$0<_Bool b>}} + b = x; + clang_analyzer_dump(b); // expected-warning{{reg_$1}} + if (x < 0) { + b = x; + clang_analyzer_dump(b); // expected-warning{{1 U1b}} + } else if (x > 0) { + b = x; + clang_analyzer_dump(b); // expected-warning{{1 U1b}} + } else { + b = x; + clang_analyzer_dump(b); // expected-warning{{0 U1b}} + } +} + +void test_char_to_bool(char x) { + bool b = x; + clang_analyzer_dump(b); // expected-warning{{reg_$0}} + if (x < 0) { + bool b = x; + clang_analyzer_dump(b); // expected-warning{{1 U1b}} + } else if (x > 0) { + bool b = x; + clang_analyzer_dump(b); // expected-warning{{1 U1b}} + } else { + bool b = x; + clang_analyzer_dump(b); // expected-warning{{0 U1b}} + } +} + +void test_unsigned_to_bool(bool b, unsigned x) { + clang_analyzer_dump(b); // expected-warning{{reg_$0<_Bool b>}} + b = x; + clang_analyzer_dump(b); // expected-warning{{reg_$1}} + if (x) { + b = x; + clang_analyzer_dump(b); // expected-warning{{1 U1b}} + } else { + b = x; + clang_analyzer_dump(b); // expected-warning{{0 U1b}} + } +} + +void test_unsigned_to_bool(unsigned char x) { + bool b = x; + clang_analyzer_dump(b); // expected-warning{{reg_$0}} + if (x < 42) { + b = x; + clang_analyzer_dump(b); // expected-warning{{reg_$0}} + if (x) { + b = x; + clang_analyzer_dump(b); // expected-warning{{1 U1b}} + } else { + b = x; + clang_analyzer_dump(b); // expected-warning{{0 U1b}} + } + } else { + b = x; + clang_analyzer_dump(b); // expected-warning{{1 U1b}} + } +}