Author: henrywong Date: Tue Mar 6 04:29:09 2018 New Revision: 326776 URL: http://llvm.org/viewvc/llvm-project?rev=326776&view=rev Log: [Analyzer] More accurate modeling about the increment operator of the operand with type bool.
Summary: There is a problem with analyzer that a wrong value is given when modeling the increment operator of the operand with type bool. After `rL307604` is applied, a unsigned overflow may occur. Example: ``` void func() { bool b = true; // unsigned overflow occur, 2 -> 0 U1b b++; } ``` The use of an operand of type bool with the ++ operators is deprecated but valid untill C++17. And if the operand of the increment operator is of type bool, it is set to true. This patch includes two parts: - If the operand of the increment operator is of type bool or type _Bool, set to true. - Modify `BasicValueFactory::getTruthValue()`, use `getIntWidth()` instead `getTypeSize()` and use `unsigned` instead `signed`. Reviewers: alexshap, NoQ, dcoughlin, george.karpenkov Reviewed By: NoQ Subscribers: xazax.hun, szepet, a.sidorin, cfe-commits, MTC Differential Revision: https://reviews.llvm.org/D43741 Added: cfe/trunk/test/Analysis/_Bool-increment-decrement.c cfe/trunk/test/Analysis/bool-increment.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h?rev=326776&r1=326775&r2=326776&view=diff ============================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h Tue Mar 6 04:29:09 2018 @@ -211,7 +211,7 @@ public: } const llvm::APSInt &getTruthValue(bool b, QualType T) { - return getValue(b ? 1 : 0, Ctx.getTypeSize(T), false); + return getValue(b ? 1 : 0, Ctx.getIntWidth(T), true); } const llvm::APSInt &getTruthValue(bool b) { Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=326776&r1=326775&r2=326776&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Tue Mar 6 04:29:09 2018 @@ -1066,6 +1066,7 @@ void ExprEngine::VisitIncrementDecrement // constant value. If the UnaryOperator has location type, create the // constant with int type and pointer width. SVal RHS; + SVal Result; if (U->getType()->isAnyPointerType()) RHS = svalBuilder.makeArrayIndex(1); @@ -1074,7 +1075,14 @@ void ExprEngine::VisitIncrementDecrement else RHS = UnknownVal(); - SVal Result = evalBinOp(state, Op, V2, RHS, U->getType()); + // The use of an operand of type bool with the ++ operators is deprecated + // but valid until C++17. And if the operand of the ++ operator is of type + // bool, it is set to true until C++17. Note that for '_Bool', it is also + // set to true when it encounters ++ operator. + if (U->getType()->isBooleanType() && U->isIncrementOp()) + Result = svalBuilder.makeTruthVal(true, U->getType()); + else + Result = evalBinOp(state, Op, V2, RHS, U->getType()); // Conjure a new symbol if necessary to recover precision. if (Result.isUnknown()){ @@ -1096,7 +1104,6 @@ void ExprEngine::VisitIncrementDecrement Constraint = svalBuilder.evalEQ(state, SymVal, svalBuilder.makeZeroVal(U->getType())); - state = state->assume(Constraint, false); assert(state); } Added: cfe/trunk/test/Analysis/_Bool-increment-decrement.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/_Bool-increment-decrement.c?rev=326776&view=auto ============================================================================== --- cfe/trunk/test/Analysis/_Bool-increment-decrement.c (added) +++ cfe/trunk/test/Analysis/_Bool-increment-decrement.c Tue Mar 6 04:29:09 2018 @@ -0,0 +1,140 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -verify -std=c99 -Dbool=_Bool -Dtrue=1 -Dfalse=0 %s +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -verify -std=c11 -Dbool=_Bool -Dtrue=1 -Dfalse=0 %s +extern void clang_analyzer_eval(bool); + +void test__Bool_value() { + { + bool b = true; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } + + { + bool b = false; + clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} + } + + { + bool b = -10; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } + + { + bool b = 10; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } + + { + bool b = 10; + b++; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } + + { + bool b = 0; + b++; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } +} + +void test__Bool_increment() { + { + bool b = true; + b++; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } + + { + bool b = false; + b++; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } + + { + bool b = true; + ++b; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } + + { + bool b = false; + ++b; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } + + { + bool b = 0; + ++b; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } + + { + bool b = 10; + ++b; + ++b; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } + + { + bool b = -10; + ++b; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } + + { + bool b = -1; + ++b; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } +} + +void test__Bool_decrement() { + { + bool b = true; + b--; + clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} + } + + { + bool b = false; + b--; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } + + { + bool b = true; + --b; + clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} + } + + { + bool b = false; + --b; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } + + { + bool b = 0; + --b; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } + + { + bool b = 10; + --b; + clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} + --b; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } + + { + bool b = -10; + --b; + clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} + } + + { + bool b = 1; + --b; + clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} + } +} Added: cfe/trunk/test/Analysis/bool-increment.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/bool-increment.cpp?rev=326776&view=auto ============================================================================== --- cfe/trunk/test/Analysis/bool-increment.cpp (added) +++ cfe/trunk/test/Analysis/bool-increment.cpp Tue Mar 6 04:29:09 2018 @@ -0,0 +1,84 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -verify -std=c++98 -Wno-deprecated %s +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -verify -std=c++11 -Wno-deprecated %s +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -verify -std=c++14 -Wno-deprecated %s + +extern void clang_analyzer_eval(bool); + +void test_bool_value() { + { + bool b = true; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } + + { + bool b = false; + clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} + } + + { + bool b = -10; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } + + { + bool b = 10; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } + + { + bool b = 10; + b++; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } + + { + bool b = 0; + b++; + clang_analyzer_eval(b == 1); // expected-warning{{TRUE}} + } +} + +void test_bool_increment() { + { + bool b = true; + b++; + clang_analyzer_eval(b); // expected-warning{{TRUE}} + } + + { + bool b = false; + b++; + clang_analyzer_eval(b); // expected-warning{{TRUE}} + } + + { + bool b = true; + ++b; + clang_analyzer_eval(b); // expected-warning{{TRUE}} + } + + { + bool b = false; + ++b; + clang_analyzer_eval(b); // expected-warning{{TRUE}} + } + + { + bool b = 0; + ++b; + clang_analyzer_eval(b); // expected-warning{{TRUE}} + } + + { + bool b = 10; + ++b; + ++b; + clang_analyzer_eval(b); // expected-warning{{TRUE}} + } + + { + bool b = -10; + ++b; + clang_analyzer_eval(b); // expected-warning{{TRUE}} + } +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits