Skip to content

Commit bf988e1

Browse files
authored
Delete implicit members whose definition does not compile (#563)
1 parent 26ff6db commit bf988e1

4 files changed

Lines changed: 74 additions & 6 deletions

File tree

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,10 @@ bool HasCallableCopyConstructor(const clang::RecordDecl *decl) {
678678
ctor->getDefinition();
679679
});
680680
}
681-
if (cxx->defaultedCopyConstructorIsDeleted()) {
681+
if (cxx->defaultedCopyConstructorIsDeleted() ||
682+
std::ranges::any_of(cxx->ctors(), [](const auto *ctor) {
683+
return ctor->isCopyConstructor() && ctor->isDeleted();
684+
})) {
682685
return false;
683686
}
684687
auto &ctx = cxx->getASTContext();
@@ -1607,27 +1610,48 @@ void DefineImplicitMembers(clang::Sema &sema, clang::CXXRecordDecl *decl) {
16071610
tu_scope.setEntity(sema.Context.getTranslationUnitDecl());
16081611
auto *saved_tu_scope = std::exchange(sema.TUScope, &tu_scope);
16091612
sema.ForceDeclarationOfImplicitMembers(decl);
1613+
auto define = [&](clang::FunctionDecl *fn, auto &&definer) {
1614+
RuleDecls::Trial trial(sema);
1615+
clang::DiagnosticErrorTrap errors(sema.getDiagnostics());
1616+
{
1617+
clang::Sema::GlobalEagerInstantiationScope instantiations(
1618+
sema, /*Enabled=*/true, /*AtEndOfTU=*/false);
1619+
definer();
1620+
instantiations.perform();
1621+
}
1622+
if (trial.failed() || errors.hasErrorOccurred()) {
1623+
fn->setDeletedAsWritten(true);
1624+
}
1625+
};
16101626
for (auto ctor : decl->ctors()) {
16111627
if (ctor->isCopyConstructor() && ctor->isImplicit() &&
16121628
!ctor->doesThisDeclarationHaveABody() && !ctor->isDeleted()) {
1613-
sema.DefineImplicitCopyConstructor(decl->getLocation(), ctor);
1629+
define(ctor, [&] {
1630+
sema.DefineImplicitCopyConstructor(decl->getLocation(), ctor);
1631+
});
16141632
}
16151633
if (ctor->isMoveConstructor() && !ctor->isUserProvided() &&
16161634
!ctor->doesThisDeclarationHaveABody() && !ctor->isDeleted() &&
16171635
!HasDefaultedCopyConstructor(decl)) {
1618-
sema.DefineImplicitMoveConstructor(decl->getLocation(), ctor);
1636+
define(ctor, [&] {
1637+
sema.DefineImplicitMoveConstructor(decl->getLocation(), ctor);
1638+
});
16191639
}
16201640
}
16211641
for (auto *method : decl->methods()) {
16221642
if (method->isMoveAssignmentOperator() && !method->isUserProvided() &&
16231643
!method->doesThisDeclarationHaveABody() && !method->isDeleted() &&
16241644
!HasDefaultedCopyAssignment(decl)) {
1625-
sema.DefineImplicitMoveAssignment(decl->getLocation(), method);
1645+
define(method, [&] {
1646+
sema.DefineImplicitMoveAssignment(decl->getLocation(), method);
1647+
});
16261648
}
16271649
if (method->isCopyAssignmentOperator() && !method->isUserProvided() &&
16281650
!method->doesThisDeclarationHaveABody() && !method->isDeleted() &&
16291651
NeedsDefaultedCopyAssignment(decl)) {
1630-
sema.DefineImplicitCopyAssignment(decl->getLocation(), method);
1652+
define(method, [&] {
1653+
sema.DefineImplicitCopyAssignment(decl->getLocation(), method);
1654+
});
16311655
}
16321656
}
16331657
auto define_defaulted_comparison = [&](clang::FunctionDecl *fn) {
@@ -1640,7 +1664,9 @@ void DefineImplicitMembers(clang::Sema &sema, clang::CXXRecordDecl *decl) {
16401664
#else
16411665
auto kind = sema.getDefaultedComparisonKind(fn);
16421666
#endif
1643-
sema.DefineDefaultedComparison(decl->getLocation(), fn, kind);
1667+
define(fn, [&] {
1668+
sema.DefineDefaultedComparison(decl->getLocation(), fn, kind);
1669+
});
16441670
};
16451671
for (auto *method : decl->methods()) {
16461672
define_defaulted_comparison(method);

‎tests/unit/copy_move_deleted.cpp‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <cassert>
22
#include <utility>
3+
#include <vector>
34

45
struct NoCopy {
56
int v;
@@ -43,6 +44,10 @@ struct Container {
4344
int tag;
4445
};
4546

47+
struct VecHolder {
48+
std::vector<NoCopy> items;
49+
};
50+
4651
static void bump(NoCopy *p) { p->v++; }
4752
static void bump_ref(Immovable &r) { r.v++; }
4853

@@ -71,5 +76,9 @@ int main() {
7176
Container c{NoCopy(6), 7};
7277
Container d(std::move(c));
7378
assert(d.inner.v == 6 && d.tag == 7 && c.inner.v == 0);
79+
80+
VecHolder h;
81+
VecHolder h2(std::move(h));
82+
assert(h2.items.size() == 0);
7483
return 0;
7584
}

‎tests/unit/out/refcount/copy_move_deleted.rs‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,20 @@ impl Container {
8080
}
8181
}
8282
}
83+
#[derive(Record, ByteRepr, FnPtrArg, MoveCtor, Default)]
84+
#[byte_size(24)]
85+
pub struct VecHolder {
86+
#[offset(0)]
87+
#[byte_size(24)]
88+
pub items: Vec<NoCopy>,
89+
}
90+
impl VecHolder {
91+
pub fn move_from(_a0: Ptr<VecHolder>) -> Self {
92+
Self {
93+
items: field!(_a0, items).with_mut(std::mem::take),
94+
}
95+
}
96+
}
8397
pub fn bump_0(mut p: Ptr<NoCopy>) {
8498
field!(p, v).with_mut(|__v| __v.postfix_inc());
8599
}
@@ -115,6 +129,9 @@ fn main_0() -> i32 {
115129
}));
116130
let mut d: Container = Container::move_from({ c.as_pointer() });
117131
assert!(((d.inner.v == 6) && (d.tag == 7)) && ({ (*c.borrow()).inner.v } == 0));
132+
let h: Value<VecHolder> = Rc::new(RefCell::new(<VecHolder>::default()));
133+
let mut h2: VecHolder = VecHolder::move_from({ h.as_pointer() });
134+
assert!((h2.items.len() == 0_usize));
118135
return 0;
119136
}
120137
pub trait ContainerImpl {

‎tests/unit/out/unsafe/copy_move_deleted.rs‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,19 @@ impl Container {
9292
return &mut (*(self as *mut Container));
9393
}
9494
}
95+
#[repr(C)]
96+
#[derive(FnPtrArg, MoveCtorUnsafe, Default)]
97+
pub struct VecHolder {
98+
pub items: Vec<NoCopy>,
99+
}
100+
impl VecHolder {
101+
pub unsafe fn move_from(_a0: *mut VecHolder) -> Self {
102+
let mut this = Self {
103+
items: std::mem::take(&mut (*_a0).items),
104+
};
105+
this
106+
}
107+
}
95108
pub unsafe fn bump_0(mut p: *mut NoCopy) {
96109
(*p).v.postfix_inc();
97110
}
@@ -129,6 +142,9 @@ unsafe fn main_0() -> i32 {
129142
};
130143
let mut d: Container = Container::move_from({ &mut c });
131144
assert!((((d.inner.v) == (6)) && ((d.tag) == (7))) && ((c.inner.v) == (0)));
145+
let mut h: VecHolder = <VecHolder>::default();
146+
let mut h2: VecHolder = VecHolder::move_from({ &mut h });
147+
assert!(((h2.items.len()) == (0_usize)));
132148
return 0;
133149
}
134150
pub unsafe fn __cpp2rust_init_globals() {}

0 commit comments

Comments
 (0)