[clang][dataflow] Ignore assignment where base class's operator is used (#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.
This commit is contained in:
Kinuko Yasuda 2023-09-14 20:45:56 +02:00 committed by GitHub
parent f45f1c3585
commit 0612c9b09a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 0 deletions

View File

@ -531,6 +531,13 @@ public:
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);

View File

@ -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 {};