diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-12-02 21:49:08 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2022-05-14 11:43:49 +0000 | 
| commit | 4824e7fd18a1223177218d4aec1b3c6c5c4a444e (patch) | |
| tree | 5ca6493b1b0bf6a41f257794c0116d5e50fbf37c /contrib/llvm-project/clang/lib/StaticAnalyzer/Core | |
| parent | 5e801ac66d24704442eba426ed13c3effb8a34e7 (diff) | |
| parent | f65dcba83ce5035ab88a85fe17628b447eb56e1b (diff) | |
Diffstat (limited to 'contrib/llvm-project/clang/lib/StaticAnalyzer/Core')
3 files changed, 86 insertions, 19 deletions
diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp index bc939d252800..d57bab154b61 100644 --- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -686,8 +686,8 @@ SwitchNodeBuilder::generateDefaultCaseNode(ProgramStateRef St,    assert(Src->succ_rbegin() != Src->succ_rend());    CFGBlock *DefaultBlock = *Src->succ_rbegin(); -  // Sanity check for default blocks that are unreachable and not caught -  // by earlier stages. +  // Basic correctness check for default blocks that are unreachable and not +  // caught by earlier stages.    if (!DefaultBlock)      return nullptr; diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp index 74403a160b8e..23c67c64f975 100644 --- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp +++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp @@ -2191,6 +2191,42 @@ LLVM_NODISCARD ProgramStateRef reAssume(ProgramStateRef State,                                       Constraint->getMaxValue(), true);  } +// Simplify the given symbol with the help of the SValBuilder. In +// SValBuilder::symplifySval, we traverse the symbol tree and query the +// constraint values for the sub-trees and if a value is a constant we do the +// constant folding. Compound symbols might collapse to simpler symbol tree +// that is still possible to further simplify. Thus, we do the simplification on +// a new symbol tree until we reach the simplest form, i.e. the fixpoint. +// +// Consider the following symbol `(b * b) * b * b` which has this tree: +//       * +//      / \ +//     *   b +//    /  \ +//   /    b +// (b * b) +// Now, if the `b * b == 1` new constraint is added then during the first +// iteration we have the following transformations: +//       *                  * +//      / \                / \ +//     *   b     -->      b   b +//    /  \ +//   /    b +//  1 +// We need another iteration to reach the final result `1`. +LLVM_NODISCARD +static SVal simplifyUntilFixpoint(SValBuilder &SVB, ProgramStateRef State, +                                  const SymbolRef Sym) { +  SVal Val = SVB.makeSymbolVal(Sym); +  SVal SimplifiedVal = SVB.simplifySVal(State, Val); +  // Do the simplification until we can. +  while (SimplifiedVal != Val) { +    Val = SimplifiedVal; +    SimplifiedVal = SVB.simplifySVal(State, Val); +  } +  return SimplifiedVal; +} +  // Iterate over all symbols and try to simplify them. Once a symbol is  // simplified then we check if we can merge the simplified symbol's equivalence  // class to this class. This way, we simplify not just the symbols but the @@ -2202,7 +2238,8 @@ EquivalenceClass::simplify(SValBuilder &SVB, RangeSet::Factory &F,    SymbolSet ClassMembers = Class.getClassMembers(State);    for (const SymbolRef &MemberSym : ClassMembers) { -    const SVal SimplifiedMemberVal = simplifyToSVal(State, MemberSym); +    const SVal SimplifiedMemberVal = +        simplifyUntilFixpoint(SVB, State, MemberSym);      const SymbolRef SimplifiedMemberSym = SimplifiedMemberVal.getAsSymbol();      // The symbol is collapsed to a constant, check if the current State is diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp index 681a1f64eadc..4ca35dd06ae5 100644 --- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -372,6 +372,15 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,    NonLoc InputLHS = lhs;    NonLoc InputRHS = rhs; +  // Constraints may have changed since the creation of a bound SVal. Check if +  // the values can be simplified based on those new constraints. +  SVal simplifiedLhs = simplifySVal(state, lhs); +  SVal simplifiedRhs = simplifySVal(state, rhs); +  if (auto simplifiedLhsAsNonLoc = simplifiedLhs.getAs<NonLoc>()) +    lhs = *simplifiedLhsAsNonLoc; +  if (auto simplifiedRhsAsNonLoc = simplifiedRhs.getAs<NonLoc>()) +    rhs = *simplifiedRhsAsNonLoc; +    // Handle trivial case where left-side and right-side are the same.    if (lhs == rhs)      switch (op) { @@ -619,16 +628,6 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,          }        } -      // Does the symbolic expression simplify to a constant? -      // If so, "fold" the constant by setting 'lhs' to a ConcreteInt -      // and try again. -      SVal simplifiedLhs = simplifySVal(state, lhs); -      if (simplifiedLhs != lhs) -        if (auto simplifiedLhsAsNonLoc = simplifiedLhs.getAs<NonLoc>()) { -          lhs = *simplifiedLhsAsNonLoc; -          continue; -        } -        // Is the RHS a constant?        if (const llvm::APSInt *RHSValue = getKnownValue(state, rhs))          return MakeSymIntVal(Sym, op, *RHSValue, resultTy); @@ -1103,7 +1102,6 @@ const llvm::APSInt *SimpleSValBuilder::getKnownValue(ProgramStateRef state,    if (SymbolRef Sym = V.getAsSymbol())      return state->getConstraintManager().getSymVal(state, Sym); -  // FIXME: Add support for SymExprs.    return nullptr;  } @@ -1135,6 +1133,24 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {        return cache(Sym, SVB.makeSymbolVal(Sym));      } +    // Return the known const value for the Sym if available, or return Undef +    // otherwise. +    SVal getConst(SymbolRef Sym) { +      const llvm::APSInt *Const = +          State->getConstraintManager().getSymVal(State, Sym); +      if (Const) +        return Loc::isLocType(Sym->getType()) ? (SVal)SVB.makeIntLocVal(*Const) +                                              : (SVal)SVB.makeIntVal(*Const); +      return UndefinedVal(); +    } + +    SVal getConstOrVisit(SymbolRef Sym) { +      const SVal Ret = getConst(Sym); +      if (Ret.isUndef()) +        return Visit(Sym); +      return Ret; +    } +    public:      Simplifier(ProgramStateRef State)          : State(State), SVB(State->getStateManager().getSValBuilder()) {} @@ -1148,15 +1164,14 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {        return SVB.makeSymbolVal(S);      } -    // TODO: Support SymbolCast. Support IntSymExpr when/if we actually -    // start producing them. +    // TODO: Support SymbolCast.      SVal VisitSymIntExpr(const SymIntExpr *S) {        auto I = Cached.find(S);        if (I != Cached.end())          return I->second; -      SVal LHS = Visit(S->getLHS()); +      SVal LHS = getConstOrVisit(S->getLHS());        if (isUnchanged(S->getLHS(), LHS))          return skip(S); @@ -1183,6 +1198,20 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {            S, SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType()));      } +    SVal VisitIntSymExpr(const IntSymExpr *S) { +      auto I = Cached.find(S); +      if (I != Cached.end()) +        return I->second; + +      SVal RHS = getConstOrVisit(S->getRHS()); +      if (isUnchanged(S->getRHS(), RHS)) +        return skip(S); + +      SVal LHS = SVB.makeIntVal(S->getLHS()); +      return cache( +          S, SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType())); +    } +      SVal VisitSymSymExpr(const SymSymExpr *S) {        auto I = Cached.find(S);        if (I != Cached.end()) @@ -1196,8 +1225,9 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {            Loc::isLocType(S->getRHS()->getType()))          return skip(S); -      SVal LHS = Visit(S->getLHS()); -      SVal RHS = Visit(S->getRHS()); +      SVal LHS = getConstOrVisit(S->getLHS()); +      SVal RHS = getConstOrVisit(S->getRHS()); +        if (isUnchanged(S->getLHS(), LHS) && isUnchanged(S->getRHS(), RHS))          return skip(S);  | 
