From 33b598a808b9ef1a019e798f19855f203e09ad48 Mon Sep 17 00:00:00 2001
From: Eric Li
Date: Wed, 25 May 2022 19:21:08 +0000
Subject: [PATCH] [clang][dataflow] Relax assert on existence of `this` pointee
storage
Support for unions is incomplete (per 99f7d55e) and the `this` pointee
storage location is not set for unions. The assert in
`VisitCXXThisExpr` is then guaranteed to trigger when analyzing member
functions of a union.
This commit changes the assert to an early-return. Any expression may
be undefined, and so having a value for the `CXXThisExpr` is not a
postcondition of the transfer function.
Differential Revision: https://reviews.llvm.org/D126405
---
clang/lib/Analysis/FlowSensitive/Transfer.cpp | 5 +++-
.../Analysis/FlowSensitive/TransferTest.cpp | 28 ++++++++++++++++++++--
2 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index f884065..fc04e0b 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -279,7 +279,10 @@ public:
void VisitCXXThisExpr(const CXXThisExpr *S) {
auto *ThisPointeeLoc = Env.getThisPointeeStorageLocation();
- assert(ThisPointeeLoc != nullptr);
+ if (ThisPointeeLoc == nullptr)
+ // Unions are not supported yet, and will not have a location for the
+ // `this` expression's pointee.
+ return;
auto &Loc = Env.createStorageLocation(*S);
Env.setStorageLocation(*S, Loc);
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index b6d2940..bb6e269 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -42,10 +42,11 @@ protected:
template
void runDataflow(llvm::StringRef Code, Matcher Match,
LangStandard::Kind Std = LangStandard::lang_cxx17,
- bool ApplyBuiltinTransfer = true) {
+ bool ApplyBuiltinTransfer = true,
+ llvm::StringRef TargetFun = "target") {
ASSERT_THAT_ERROR(
test::checkDataflow(
- Code, "target",
+ Code, TargetFun,
[ApplyBuiltinTransfer](ASTContext &C, Environment &) {
return NoopAnalysis(C, ApplyBuiltinTransfer);
},
@@ -3175,4 +3176,27 @@ TEST_F(TransferTest, LoopWithStructReferenceAssignmentConverges) {
});
}
+TEST_F(TransferTest, DoesNotCrashOnUnionThisExpr) {
+ std::string Code = R"(
+ union Union {
+ int A;
+ float B;
+ };
+
+ void foo() {
+ Union A;
+ Union B;
+ A = B;
+ }
+ )";
+ // This is a crash regression test when calling the transfer function on a
+ // `CXXThisExpr` that refers to a union.
+ runDataflow(
+ Code,
+ [](llvm::ArrayRef<
+ std::pair>>,
+ ASTContext &) {},
+ LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
+}
+
} // namespace
--
2.7.4