[clang] 38404df - [clang][dataflow] Fix bug in handling of `return` statements.
Yitzhak Mandelbaum via cfe-commits
cfe-commits at lists.llvm.org
Thu Dec 22 06:42:26 PST 2022
Author: Yitzhak Mandelbaum
Date: 2022-12-22T14:42:17Z
New Revision: 38404df9d879483784a7024b2b4a366388d6d476
URL: https://github.com/llvm/llvm-project/commit/38404df9d879483784a7024b2b4a366388d6d476
DIFF: https://github.com/llvm/llvm-project/commit/38404df9d879483784a7024b2b4a366388d6d476.diff
LOG: [clang][dataflow] Fix bug in handling of `return` statements.
The handling of return statements, added in support of context-sensitive
analysis, has a bug relating to functions that return reference
types. Specifically, interpretation of such functions can result in a crash from
a bad cast. This patch fixes the bug and guards all of that code with the
context-sensitive option, since there's no reason to execute at all when
context-sensitive analysis is off.
Differential Revision: https://reviews.llvm.org/D140430
Added:
Modified:
clang/lib/Analysis/FlowSensitive/Transfer.cpp
clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
Removed:
################################################################################
diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index 43d004697799..336de81b0653 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -429,6 +429,9 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
}
void VisitReturnStmt(const ReturnStmt *S) {
+ if (!Options.ContextSensitiveOpts)
+ return;
+
auto *Ret = S->getRetValue();
if (Ret == nullptr)
return;
@@ -443,6 +446,10 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
auto *Loc = Env.getReturnStorageLocation();
assert(Loc != nullptr);
+ // FIXME: Support reference-type returns.
+ if (Loc->getType()->isReferenceType())
+ return;
+
// FIXME: Model NRVO.
Env.setValue(*Loc, *Val);
}
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index 299837aee928..b5e10b24fffb 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -4018,6 +4018,35 @@ TEST(TransferTest, ContextSensitiveOptionDisabled) {
{TransferOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
}
+// This test is a regression test, based on a real crash.
+TEST(TransferTest, ContextSensitiveReturnReferenceFromNonReferenceLvalue) {
+ // This code exercises an unusual code path. If we return an lvalue directly,
+ // the code will catch that it's an l-value based on the `Value`'s kind. If we
+ // pass through a dummy function, the framework won't populate a value at
+ // all. In contrast, this code results in a (fresh) value, but it is not
+ // `ReferenceValue`. This test verifies that we catch this case as well.
+ std::string Code = R"(
+ class S {};
+ S& target(bool b, S &s) {
+ return b ? s : s;
+ // [[p]]
+ }
+ )";
+ runDataflow(
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {
+ ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
+ const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
+
+ auto *Loc = Env.getReturnStorageLocation();
+ ASSERT_THAT(Loc, NotNull());
+
+ EXPECT_THAT(Env.getValue(*Loc), IsNull());
+ },
+ {TransferOptions{ContextSensitiveOptions{}}});
+}
+
TEST(TransferTest, ContextSensitiveDepthZero) {
std::string Code = R"(
bool GiveBool();
More information about the cfe-commits
mailing list