Skip to content
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

[clang][dataflow] Ignore assignment where base class's operator is used #66364

Merged
merged 1 commit into from
Sep 14, 2023

Conversation

kinu
Copy link
Contributor

@kinu kinu commented Sep 14, 2023

In C++ it seems it is legit to use base class's operator (e.g. using Base::operator=) to perform copy if the base class is the common ancestor of the source and destination object. In such a case we shouldn't try to access fields beyond that of the base class, however such a case seems to be very rare (typical code would implement a copy constructor instead), and could add complexities, so in this patch we simply bail if the method operator's parent class is different from the type of the destination object that this framework recognizes.

…rator is used

In C++ it seems it is legit to use base class's operator (e.g. `using
Base::operator=`) to perform copy if the base class is the common
ancestor of the source and destination object. In such a case we
shouldn't try to access fields beyond that of the base class, however
such a case seems to be very rare (typical code would implement a copy
constructor instead), and could add complexities, so in this patch we
simply bail if the method operator's parent class is different from the
type of the destination object that this framework recognizes.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:dataflow Clang Dataflow Analysis framework - https://clang.llvm.org/docs/DataFlowAnalysisIntro.html clang:analysis labels Sep 14, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Sep 14, 2023

@llvm/pr-subscribers-clang-analysis

@llvm/pr-subscribers-clang

Changes In C++ it seems it is legit to use base class's operator (e.g. `using Base::operator=`) to perform copy if the base class is the common ancestor of the source and destination object. In such a case we shouldn't try to access fields beyond that of the base class, however such a case seems to be very rare (typical code would implement a copy constructor instead), and could add complexities, so in this patch we simply bail if the method operator's parent class is different from the type of the destination object that this framework recognizes. -- Full diff: https://github.com//pull/66364.diff

2 Files Affected:

  • (modified) clang/lib/Analysis/FlowSensitive/Transfer.cpp (+7)
  • (modified) clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (+24)
diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index b46c947c691b9b9..b510114a7a355eb 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -531,6 +531,13 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
       auto *LocDst =
           cast_or_null<RecordStorageLocation>(Env.getStorageLocation(*Arg0));
 
+      // The assignment operators are different from the type of the destination
+      // in this model (i.e. in one of their base classes). This must be very rare
+      // and we just bail.
+      if (Method->getThisObjectType().getCanonicalType().getUnqualifiedType() !=
+          LocDst->getType().getCanonicalType().getUnqualifiedType())
+        return;
+
       if (LocSrc != nullptr && LocDst != nullptr) {
         copyRecord(*LocSrc, *LocDst, Env);
         Env.setStorageLocation(*S, *LocDst);
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index 0abd171f1d0b7cb..e0e3b71503d2176 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -2124,6 +2124,30 @@ TEST(TransferTest, AssignmentOperator) {
       });
 }
 
+TEST(TransferTest, AssignmentOperatorFromBase) {
+  // This is a crash repro. We don't model the copy this case, so no
+  // expectations on the copied field of the base class are checked.
+  std::string Code = R"(
+    struct Base {
+      int base;
+    };
+    struct Derived : public Base {
+      using Base::operator=;
+      int derived;
+    };
+    void target(Base B, Derived D) {
+      D.base = 1;
+      D.derived = 1;
+      D = B;
+      // [[p]]
+    }
+  )";
+  runDataflow(
+      Code,
+      [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+         ASTContext &ASTCtx) {});
+}
+
 TEST(TransferTest, AssignmentOperatorFromCallResult) {
   std::string Code = R"(
     struct A {};

@kinu
Copy link
Contributor Author

kinu commented Sep 14, 2023

@martinboehme @sam-mccall @ymand
appreciated if any of you (or other owners) can review and merge

@sam-mccall sam-mccall merged commit 0612c9b into llvm:main Sep 14, 2023
5 checks passed
ZijunZhaoCCK pushed a commit to ZijunZhaoCCK/llvm-project that referenced this pull request Sep 19, 2023
…ed (llvm#66364)

In C++ it seems it is legit to use base class's operator (e.g. `using
Base::operator=`) to perform copy if the base class is the common
ancestor of the source and destination object. In such a case we
shouldn't try to access fields beyond that of the base class, however
such a case seems to be very rare (typical code would implement a copy
constructor instead), and could add complexities, so in this patch we
simply bail if the method operator's parent class is different from the
type of the destination object that this framework recognizes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:analysis clang:dataflow Clang Dataflow Analysis framework - https://clang.llvm.org/docs/DataFlowAnalysisIntro.html clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants