-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[dataflow] CXXOperatorCallExpr equal operator might not be a glvalue #80991
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[dataflow] CXXOperatorCallExpr equal operator might not be a glvalue #80991
Conversation
@llvm/pr-subscribers-clang-analysis @llvm/pr-subscribers-clang Author: Paul Semel (paulsemel) ChangesAlthough in a normal implementation the assumption is reasonable, it seems that some esoteric implementation are not returning a T&. This should be handled correctly and the values be propagated. Full diff: https://github.com/llvm/llvm-project/pull/80991.diff 2 Files Affected:
diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index bb3aec763c29ca..fb1c6848197339 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -535,7 +535,19 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
return;
copyRecord(*LocSrc, *LocDst, Env);
- Env.setStorageLocation(*S, *LocDst);
+
+ // If the expr is a glvalue, we can reasonably assume the operator is
+ // returning T& and thus we can assign it `LocDst`.
+ if (S->isGLValue()) {
+ Env.setStorageLocation(*S, *LocDst);
+ } else if (S->getType()->isRecordType() && S->isPRValue()) {
+ // If the expr is a prvalue, we cannot really assume anything regarding
+ // the new value being created. We should just propagate it to ensure a
+ // `RecordValue` exist for it.
+ if (Env.getValue(*S) == nullptr)
+ refreshRecordValue(*S, Env);
+ }
+
return;
}
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index 8bbb04024dcce6..86f4081c798d55 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -2313,6 +2313,42 @@ TEST(TransferTest, AssignmentOperatorWithInitAndInheritance) {
ASTContext &ASTCtx) {});
}
+TEST(TransferTest, CXXOperatorCallExprEqualReturnsVoid) {
+ // This is a crash repro.
+ std::string Code = R"(
+ struct B {
+ void operator=(B&& other);
+ };
+ void target() {
+ B b;
+ b = B();
+ // [[p]]
+ }
+ )";
+ runDataflow(
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {});
+}
+
+TEST(TransferTest, CXXOperatorCallExprEqualReturnsPRValue) {
+ // This is a crash repro.
+ std::string Code = R"(
+ struct B {
+ B operator=(B&& other);
+ };
+ void target() {
+ B b;
+ b = B();
+ // [[p]]
+ }
+ )";
+ runDataflow(
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {});
+}
+
TEST(TransferTest, CopyConstructor) {
std::string Code = R"(
struct A {
|
if (Env.getValue(*S) == nullptr) | ||
refreshRecordValue(*S, Env); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this actually necessary? (It's not really doing anything?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, similarly to TransferCallExpr
, it ensures a RecordValue
exists. This is just a short path for not having to call TransferCallExpr
, since it is pretty much the only thing that will trigger if being called.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it. Added a suggested edit for the comment.
Although in a normal implementation the assumption is reasonable, it seems that some esoteric implementation are not returning a T&. This should be handled correctly and the values be propagated.
4aad700
to
0d03870
Compare
if (Env.getValue(*S) == nullptr) | ||
refreshRecordValue(*S, Env); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it. Added a suggested edit for the comment.
Co-authored-by: martinboehme <[email protected]>
Although in a normal implementation the assumption is reasonable, it seems that some esoteric implementation are not returning a T&. This should be handled correctly and the values be propagated.