Skip to content

Commit bc2c759

Browse files
author
Gabor Marton
committed
[analyzer] Fix assertion failure after getKnownValue call
Depends on D126560. `getKnownValue` has been changed by the parent patch in a way that simplification was removed. This is not correct when the function is called by the Checkers. Thus, a new internal function is introduced, `getConstValue`, which simply queries the constraint manager. This `getConstValue` is used internally in the `SimpleSValBuilder` when a binop is evaluated, this way we avoid the recursion into the `Simplifier`. Differential Revision: https://reviews.llvm.org/D127285
1 parent b8c2781 commit bc2c759

File tree

2 files changed

+35
-9
lines changed

2 files changed

+35
-9
lines changed

clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ using namespace ento;
2222
namespace {
2323
class SimpleSValBuilder : public SValBuilder {
2424

25+
// Query the constraint manager whether the SVal has only one possible
26+
// (integer) value. If that is the case, the value is returned. Otherwise,
27+
// returns NULL.
28+
// This is an implementation detail. Checkers should use `getKnownValue()`
29+
// instead.
30+
const llvm::APSInt *getConstValue(ProgramStateRef state, SVal V);
31+
2532
// With one `simplifySValOnce` call, a compound symbols might collapse to
2633
// simpler symbol tree that is still possible to further simplify. Thus, we
2734
// do the simplification on a new symbol tree until we reach the simplest
@@ -45,7 +52,7 @@ class SimpleSValBuilder : public SValBuilder {
4552
SVal simplifyUntilFixpoint(ProgramStateRef State, SVal Val);
4653

4754
// Recursively descends into symbolic expressions and replaces symbols
48-
// with their known values (in the sense of the getKnownValue() method).
55+
// with their known values (in the sense of the getConstValue() method).
4956
// We traverse the symbol tree and query the constraint values for the
5057
// sub-trees and if a value is a constant we do the constant folding.
5158
SVal simplifySValOnce(ProgramStateRef State, SVal V);
@@ -65,8 +72,9 @@ class SimpleSValBuilder : public SValBuilder {
6572
SVal evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op,
6673
Loc lhs, NonLoc rhs, QualType resultTy) override;
6774

68-
/// getKnownValue - evaluates a given SVal. If the SVal has only one possible
69-
/// (integer) value, that value is returned. Otherwise, returns NULL.
75+
/// Evaluates a given SVal by recursively evaluating and
76+
/// simplifying the children SVals. If the SVal has only one possible
77+
/// (integer) value, that value is returned. Otherwise, returns NULL.
7078
const llvm::APSInt *getKnownValue(ProgramStateRef state, SVal V) override;
7179

7280
SVal simplifySVal(ProgramStateRef State, SVal V) override;
@@ -532,7 +540,7 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
532540
llvm::APSInt LHSValue = lhs.castAs<nonloc::ConcreteInt>().getValue();
533541

534542
// If we're dealing with two known constants, just perform the operation.
535-
if (const llvm::APSInt *KnownRHSValue = getKnownValue(state, rhs)) {
543+
if (const llvm::APSInt *KnownRHSValue = getConstValue(state, rhs)) {
536544
llvm::APSInt RHSValue = *KnownRHSValue;
537545
if (BinaryOperator::isComparisonOp(op)) {
538546
// We're looking for a type big enough to compare the two values.
@@ -652,7 +660,7 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
652660
}
653661

654662
// For now, only handle expressions whose RHS is a constant.
655-
if (const llvm::APSInt *RHSValue = getKnownValue(state, rhs)) {
663+
if (const llvm::APSInt *RHSValue = getConstValue(state, rhs)) {
656664
// If both the LHS and the current expression are additive,
657665
// fold their constants and try again.
658666
if (BinaryOperator::isAdditiveOp(op)) {
@@ -699,7 +707,7 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
699707
}
700708

701709
// Is the RHS a constant?
702-
if (const llvm::APSInt *RHSValue = getKnownValue(state, rhs))
710+
if (const llvm::APSInt *RHSValue = getConstValue(state, rhs))
703711
return MakeSymIntVal(Sym, op, *RHSValue, resultTy);
704712

705713
if (Optional<NonLoc> V = tryRearrange(state, op, lhs, rhs, resultTy))
@@ -1187,8 +1195,8 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
11871195
return UnknownVal();
11881196
}
11891197

1190-
const llvm::APSInt *SimpleSValBuilder::getKnownValue(ProgramStateRef state,
1191-
SVal V) {
1198+
const llvm::APSInt *SimpleSValBuilder::getConstValue(ProgramStateRef state,
1199+
SVal V) {
11921200
if (V.isUnknownOrUndef())
11931201
return nullptr;
11941202

@@ -1204,6 +1212,11 @@ const llvm::APSInt *SimpleSValBuilder::getKnownValue(ProgramStateRef state,
12041212
return nullptr;
12051213
}
12061214

1215+
const llvm::APSInt *SimpleSValBuilder::getKnownValue(ProgramStateRef state,
1216+
SVal V) {
1217+
return getConstValue(state, simplifySVal(state, V));
1218+
}
1219+
12071220
SVal SimpleSValBuilder::simplifyUntilFixpoint(ProgramStateRef State, SVal Val) {
12081221
SVal SimplifiedVal = simplifySValOnce(State, Val);
12091222
while (SimplifiedVal != Val) {
@@ -1270,7 +1283,7 @@ SVal SimpleSValBuilder::simplifySValOnce(ProgramStateRef State, SVal V) {
12701283
SVal VisitSymbolData(const SymbolData *S) {
12711284
// No cache here.
12721285
if (const llvm::APSInt *I =
1273-
SVB.getKnownValue(State, SVB.makeSymbolVal(S)))
1286+
State->getConstraintManager().getSymVal(State, S))
12741287
return Loc::isLocType(S->getType()) ? (SVal)SVB.makeIntLocVal(*I)
12751288
: (SVal)SVB.makeIntVal(*I);
12761289
return SVB.makeSymbolVal(S);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %clang_analyze_cc1 %s \
2+
// RUN: -analyzer-checker=core \
3+
// RUN: -analyzer-checker=debug.ExprInspection \
4+
// RUN: -verify
5+
6+
// Here, we test that svalbuilder simplification does not produce any
7+
// assertion failure.
8+
9+
void crashing(long a, _Bool b) {
10+
(void)(a & 1 && 0);
11+
b = a & 1;
12+
(void)(b << 1); // expected-warning{{core.UndefinedBinaryOperatorResult}}
13+
}

0 commit comments

Comments
 (0)