[clang] [clang][nullability] Improve modeling of `++`/`--` operators. (PR #96601)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 24 23:49:59 PDT 2024
https://github.com/martinboehme created https://github.com/llvm/llvm-project/pull/96601
We definitely know that these operations change the value of their operand, so
clear out any value associated with it. We don't create a new value, instead
leaving it to the analysis to do this if desired.
>From 61a143e02eb9417a8a61bc5349522ee8d7dd04c8 Mon Sep 17 00:00:00 2001
From: Martin Braenne <mboehme at google.com>
Date: Tue, 25 Jun 2024 06:45:30 +0000
Subject: [PATCH] [clang][nullability] Improve modeling of `++`/`--` operators.
We definitely know that these operations change the value of their operand, so
clear out any value associated with it. We don't create a new value, instead
leaving it to the analysis to do this if desired.
---
clang/lib/Analysis/FlowSensitive/Transfer.cpp | 17 ++++++----
.../Analysis/FlowSensitive/TransferTest.cpp | 31 ++++++++++++++-----
2 files changed, 34 insertions(+), 14 deletions(-)
diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index 8109ac6a781e7..3c896d373a211 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -391,17 +391,22 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
}
case UO_PreInc:
case UO_PreDec:
- // Propagate the storage location, but don't create a new value; to
- // avoid generating unnecessary values, we leave it to the specific
- // analysis to do this if desired.
+ // Propagate the storage location and clear out any value associated with
+ // it (to represent the fact that the value has definitely changed).
+ // To avoid generating unnecessary values, we leave it to the specific
+ // analysis to create a new value if desired.
propagateStorageLocation(*S->getSubExpr(), *S, Env);
+ if (StorageLocation *Loc = Env.getStorageLocation(*S->getSubExpr()))
+ Env.clearValue(*Loc);
break;
case UO_PostInc:
case UO_PostDec:
- // Propagate the old value, but don't create a new value; to avoid
- // generating unnecessary values, we leave it to the specific analysis
- // to do this if desired.
+ // Propagate the old value, then clear out any value associated with the
+ // storage location (to represent the fact that the value has definitely
+ // changed). See above for rationale.
propagateValue(*S->getSubExpr(), *S, Env);
+ if (StorageLocation *Loc = Env.getStorageLocation(*S->getSubExpr()))
+ Env.clearValue(*Loc);
break;
default:
break;
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index cfbc64c77b0cc..e743eefa5d458 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -3789,36 +3789,51 @@ TEST(TransferTest, AddrOfReference) {
TEST(TransferTest, Preincrement) {
std::string Code = R"(
void target(int I) {
+ (void)0; // [[before]]
int &IRef = ++I;
- // [[p]]
+ // [[after]]
}
)";
runDataflow(
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
- const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
+ const Environment &EnvBefore =
+ getEnvironmentAtAnnotation(Results, "before");
+ const Environment &EnvAfter =
+ getEnvironmentAtAnnotation(Results, "after");
- EXPECT_EQ(&getLocForDecl(ASTCtx, Env, "IRef"),
- &getLocForDecl(ASTCtx, Env, "I"));
+ EXPECT_EQ(&getLocForDecl(ASTCtx, EnvAfter, "IRef"),
+ &getLocForDecl(ASTCtx, EnvBefore, "I"));
+
+ const ValueDecl *IDecl = findValueDecl(ASTCtx, "I");
+ EXPECT_NE(EnvBefore.getValue(*IDecl), nullptr);
+ EXPECT_EQ(EnvAfter.getValue(*IDecl), nullptr);
});
}
TEST(TransferTest, Postincrement) {
std::string Code = R"(
void target(int I) {
+ (void)0; // [[before]]
int OldVal = I++;
- // [[p]]
+ // [[after]]
}
)";
runDataflow(
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
- const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
+ const Environment &EnvBefore =
+ getEnvironmentAtAnnotation(Results, "before");
+ const Environment &EnvAfter =
+ getEnvironmentAtAnnotation(Results, "after");
+
+ EXPECT_EQ(&getValueForDecl(ASTCtx, EnvBefore, "I"),
+ &getValueForDecl(ASTCtx, EnvAfter, "OldVal"));
- EXPECT_EQ(&getValueForDecl(ASTCtx, Env, "OldVal"),
- &getValueForDecl(ASTCtx, Env, "I"));
+ const ValueDecl *IDecl = findValueDecl(ASTCtx, "I");
+ EXPECT_EQ(EnvAfter.getValue(*IDecl), nullptr);
});
}
More information about the cfe-commits
mailing list