mboehme updated this revision to Diff 531863. mboehme added a comment. Clarify that integer literals aren't typed.
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D152813/new/ https://reviews.llvm.org/D152813 Files: clang/include/clang/Analysis/FlowSensitive/Arena.h clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h clang/lib/Analysis/FlowSensitive/Arena.cpp clang/lib/Analysis/FlowSensitive/Transfer.cpp clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp =================================================================== --- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -811,6 +811,31 @@ }); } +TEST(TransferTest, BinaryOperatorAssignIntegerLiteral) { + std::string Code = R"( + void target() { + int Foo = 1; + // [[before]] + Foo = 2; + // [[after]] + } + )"; + runDataflow( + Code, + [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, + ASTContext &ASTCtx) { + const Environment &Before = + getEnvironmentAtAnnotation(Results, "before"); + const Environment &After = getEnvironmentAtAnnotation(Results, "after"); + + const auto &ValBefore = + getValueForDecl<IntegerValue>(ASTCtx, Before, "Foo"); + const auto &ValAfter = + getValueForDecl<IntegerValue>(ASTCtx, After, "Foo"); + EXPECT_NE(&ValBefore, &ValAfter); + }); +} + TEST(TransferTest, VarDeclInitAssign) { std::string Code = R"( void target() { @@ -3441,6 +3466,24 @@ }); } +TEST(TransferTest, IntegerLiteralEquality) { + std::string Code = R"( + void target() { + bool equal = (42 == 42); + // [[p]] + } + )"; + runDataflow( + Code, + [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, + ASTContext &ASTCtx) { + const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + + auto &Equal = getValueForDecl<BoolValue>(ASTCtx, Env, "equal"); + EXPECT_TRUE(Env.flowConditionImplies(Equal)); + }); +} + TEST(TransferTest, CorrelatedBranches) { std::string Code = R"( void target(bool B, bool C) { Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp =================================================================== --- clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -48,9 +48,15 @@ static BoolValue &evaluateBooleanEquality(const Expr &LHS, const Expr &RHS, Environment &Env) { - if (auto *LHSValue = dyn_cast_or_null<BoolValue>(Env.getValueStrict(LHS))) - if (auto *RHSValue = dyn_cast_or_null<BoolValue>(Env.getValueStrict(RHS))) - return Env.makeIff(*LHSValue, *RHSValue); + Value *LHSValue = Env.getValueStrict(LHS); + Value *RHSValue = Env.getValueStrict(RHS); + + if (LHSValue == RHSValue) + return Env.getBoolLiteralValue(true); + + if (auto *LHSBool = dyn_cast_or_null<BoolValue>(LHSValue)) + if (auto *RHSBool = dyn_cast_or_null<BoolValue>(RHSValue)) + return Env.makeIff(*LHSBool, *RHSBool); return Env.makeAtomicBoolValue(); } @@ -775,6 +781,10 @@ Env.setValueStrict(*S, Env.getBoolLiteralValue(S->getValue())); } + void VisitIntegerLiteral(const IntegerLiteral *S) { + Env.setValueStrict(*S, Env.getIntLiteralValue(S->getValue())); + } + void VisitParenExpr(const ParenExpr *S) { // The CFG does not contain `ParenExpr` as top-level statements in basic // blocks, however manual traversal to sub-expressions may encounter them. Index: clang/lib/Analysis/FlowSensitive/Arena.cpp =================================================================== --- clang/lib/Analysis/FlowSensitive/Arena.cpp +++ clang/lib/Analysis/FlowSensitive/Arena.cpp @@ -68,4 +68,12 @@ return *Res.first->second; } +IntegerValue &Arena::makeIntLiteral(llvm::APInt Value) { + auto [It, Inserted] = IntegerLiterals.try_emplace(Value, nullptr); + + if (Inserted) + It->second = &create<IntegerValue>(); + return *It->second; +} + } // namespace clang::dataflow Index: clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h =================================================================== --- clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -448,6 +448,12 @@ return DACtx->arena().create<T>(std::forward<Args>(args)...); } + /// Returns a symbolic integer value that models an integer literal equal to + /// `Value` + IntegerValue &getIntLiteralValue(llvm::APInt Value) const { + return DACtx->arena().makeIntLiteral(Value); + } + /// Returns a symbolic boolean value that models a boolean literal equal to /// `Value` AtomicBoolValue &getBoolLiteralValue(bool Value) const { Index: clang/include/clang/Analysis/FlowSensitive/Arena.h =================================================================== --- clang/include/clang/Analysis/FlowSensitive/Arena.h +++ clang/include/clang/Analysis/FlowSensitive/Arena.h @@ -84,6 +84,12 @@ /// will be a value that represents the true boolean literal. BoolValue &makeEquals(BoolValue &LHS, BoolValue &RHS); + /// Returns a symbolic integer value that models an integer literal equal to + /// `Value`. These literals are the same every time. + /// Integer literals are not typed; the type is determined by the `Expr` that + /// an integer literal is associated with. + IntegerValue &makeIntLiteral(llvm::APInt Value); + /// Returns a symbolic boolean value that models a boolean literal equal to /// `Value`. These literals are the same every time. AtomicBoolValue &makeLiteral(bool Value) const { @@ -103,8 +109,9 @@ std::vector<std::unique_ptr<StorageLocation>> Locs; std::vector<std::unique_ptr<Value>> Vals; - // Indices that are used to avoid recreating the same composite boolean - // values. + // Indices that are used to avoid recreating the same integer literals and + // composite boolean values. + llvm::DenseMap<llvm::APInt, IntegerValue *> IntegerLiterals; llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, ConjunctionValue *> ConjunctionVals; llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, DisjunctionValue *>
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits