diff --git a/clang/unittests/Analysis/FlowSensitive/SignAnalysisTest.cpp b/clang/unittests/Analysis/FlowSensitive/SignAnalysisTest.cpp --- a/clang/unittests/Analysis/FlowSensitive/SignAnalysisTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/SignAnalysisTest.cpp @@ -114,12 +114,10 @@ return {nullptr, {}, {}}; // Value of the unary op. - auto *UnaryOpValue = State.Env.getValue(*UO, SkipPast::None); + auto *UnaryOpValue = State.Env.getValueStrict(*UO); if (!UnaryOpValue) { - auto &Loc = State.Env.createStorageLocation(*UO); - State.Env.setStorageLocation(*UO, Loc); UnaryOpValue = &State.Env.makeAtomicBoolValue(); - State.Env.setValue(Loc, *UnaryOpValue); + State.Env.setValueStrict(*UO, *UnaryOpValue); } // Properties for the operand (sub expression). @@ -133,22 +131,17 @@ void transferBinary(const BinaryOperator *BO, const MatchFinder::MatchResult &M, LatticeTransferState &State) { - StorageLocation *Loc = State.Env.getStorageLocation(*BO, SkipPast::None); - if (!Loc) { - Loc = &State.Env.createStorageLocation(*BO); - State.Env.setStorageLocation(*BO, *Loc); - } - BoolValue *Comp = cast_or_null(State.Env.getValue(*Loc)); + BoolValue *Comp = cast_or_null(State.Env.getValueStrict(*BO)); if (!Comp) { Comp = &State.Env.makeAtomicBoolValue(); - State.Env.setValue(*Loc, *Comp); + State.Env.setValueStrict(*BO, *Comp); } // FIXME Use this as well: // auto *NegatedComp = &State.Env.makeNot(*Comp); - auto *LHS = State.Env.getValue(*BO->getLHS(), SkipPast::None); - auto *RHS = State.Env.getValue(*BO->getRHS(), SkipPast::None); + auto *LHS = State.Env.getValueStrict(*BO->getLHS()); + auto *RHS = State.Env.getValueStrict(*BO->getRHS()); if (!LHS || !RHS) return; @@ -244,19 +237,43 @@ } } +// Returns the `Value` associated with `E` (which may be either a prvalue or +// glvalue). Creates a `Value` or `StorageLocation` as needed if `E` does not +// have either of these associated with it yet. +// +// If this functionality turns out to be needed in more cases, this function +// should be moved to a more central location. +Value *getOrCreateValue(const Expr *E, Environment &Env) { + Value *Val = nullptr; + if (E->isGLValue()) { + StorageLocation *Loc = Env.getStorageLocationStrict(*E); + if (!Loc) { + Loc = &Env.createStorageLocation(*E); + Env.setStorageLocationStrict(*E, *Loc); + } + Val = Env.getValue(*Loc); + if (!Val) { + Val = Env.createValue(E->getType()); + Env.setValue(*Loc, *Val); + } + } else { + Val = Env.getValueStrict(*E); + if (!Val) { + Val = Env.createValue(E->getType()); + Env.setValueStrict(*E, *Val); + } + } + assert(Val != nullptr); + + return Val; +} + void transferExpr(const Expr *E, const MatchFinder::MatchResult &M, LatticeTransferState &State) { const ASTContext &Context = *M.Context; - StorageLocation *Loc = State.Env.getStorageLocation(*E, SkipPast::None); - if (!Loc) { - Loc = &State.Env.createStorageLocation(*E); - State.Env.setStorageLocation(*E, *Loc); - } - Value *Val = State.Env.getValue(*Loc); - if (!Val) { - Val = State.Env.createValue(Context.IntTy); - State.Env.setValue(*Loc, *Val); - } + + Value *Val = getOrCreateValue(E, State.Env); + // The sign symbolic values have been initialized already. if (Val->getProperty("neg")) return;