diff --git a/cpp2rust/converter/rules/registry.cpp b/cpp2rust/converter/rules/registry.cpp index d186647e5..182cb1c80 100644 --- a/cpp2rust/converter/rules/registry.cpp +++ b/cpp2rust/converter/rules/registry.cpp @@ -170,7 +170,7 @@ void addRule(clang::ASTContext &ctx, const std::string &dir, assert(llvm::isa(decl) && "expression rule is neither a function nor a variable"); } - auto keys = RuleKeys::GetExprKeys(ctx, decl); + auto keys = RuleKeys::GetExprKeys(*sema_, decl); assert(!keys.empty() && "expression rule has no key"); for (const auto &key : keys) { exprs_.emplace( diff --git a/cpp2rust/converter/rules/rule_keys.cpp b/cpp2rust/converter/rules/rule_keys.cpp index bac8fc8d3..9c71050d5 100644 --- a/cpp2rust/converter/rules/rule_keys.cpp +++ b/cpp2rust/converter/rules/rule_keys.cpp @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include @@ -56,7 +58,30 @@ const clang::Decl *getParent(const clang::Decl *decl) { return nullptr; } -std::vector resolveMemberType(clang::QualType type) { +llvm::SmallVector +matchingDefinitions(clang::Sema &sema, clang::ClassTemplateDecl *tmpl, + const clang::TemplateSpecializationType *spec) { + llvm::SmallVector partials; + tmpl->getPartialSpecializations(partials); + llvm::SmallVector records; + for (auto partial : partials) { + RuleDecls::Trial trial(sema); + clang::sema::TemplateDeductionInfo info(partial->getLocation()); + if (sema.DeduceTemplateArguments(partial, spec->template_arguments(), + info) == + clang::TemplateDeductionResult::Success && + !trial.failed()) { + records.push_back(partial); + } + } + if (records.empty()) { + records.push_back(tmpl->getTemplatedDecl()); + } + return records; +} + +std::vector resolveMemberType(clang::Sema &sema, + clang::QualType type) { auto member = type->getAs(); if (!member) { return {type}; @@ -64,24 +89,20 @@ std::vector resolveMemberType(clang::QualType type) { auto qualifier = member->getQualifier().getAsType(); assert(qualifier && "member type is not qualified by a type"); std::vector resolved; - for (auto owner : resolveMemberType(clang::QualType(qualifier, 0))) { + for (auto owner : resolveMemberType(sema, clang::QualType(qualifier, 0))) { auto spec = owner->getAs(); auto tmpl = spec ? llvm::dyn_cast_or_null( spec->getTemplateName().getAsTemplateDecl()) : nullptr; assert(tmpl && "member type is not qualified by a class template"); - llvm::SmallVector partials; - tmpl->getPartialSpecializations(partials); - llvm::SmallVector records{tmpl->getTemplatedDecl()}; - records.append(partials.begin(), partials.end()); - for (auto record : records) { + for (auto record : matchingDefinitions(sema, tmpl, spec)) { if (!record->hasDefinition()) { continue; } for (auto decl : record->getDefinition()->lookup(member->getIdentifier())) { if (auto alias = llvm::dyn_cast(decl)) { - auto types = resolveMemberType(alias->getUnderlyingType()); + auto types = resolveMemberType(sema, alias->getUnderlyingType()); resolved.insert(resolved.end(), types.begin(), types.end()); } } @@ -198,8 +219,9 @@ std::optional GetExprKey(clang::ASTContext &ctx, return std::nullopt; } -std::vector GetExprKeys(clang::ASTContext &ctx, +std::vector GetExprKeys(clang::Sema &sema, const clang::NamedDecl *rule) { + auto &ctx = sema.Context; if (auto var = llvm::dyn_cast(rule)) { auto key = GetExprKey(ctx, var->getInit()); assert(key && "expression rule has no key"); @@ -210,7 +232,7 @@ std::vector GetExprKeys(clang::ASTContext &ctx, if (auto construct = llvm::dyn_cast(returned)) { std::vector keys; - for (auto type : resolveMemberType(construct->getTypeAsWritten())) { + for (auto type : resolveMemberType(sema, construct->getTypeAsWritten())) { if (type->getAs()) { if (!llvm::is_contained(keys, ExprKey{kAnyConstructor})) { keys.push_back(kAnyConstructor); diff --git a/cpp2rust/converter/rules/rule_keys.h b/cpp2rust/converter/rules/rule_keys.h index 9aaef1ebf..a29d8fe7a 100644 --- a/cpp2rust/converter/rules/rule_keys.h +++ b/cpp2rust/converter/rules/rule_keys.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -46,7 +47,7 @@ inline const Constructor kAnyConstructor{nullptr}; std::optional GetExprKey(clang::ASTContext &ctx, const clang::Expr *use); -std::vector GetExprKeys(clang::ASTContext &ctx, +std::vector GetExprKeys(clang::Sema &sema, const clang::NamedDecl *rule); std::optional GetDeclKey(const clang::NamedDecl *decl); diff --git a/rules/vector/src.cpp b/rules/vector/src.cpp index a7fea7f78..b825de408 100644 --- a/rules/vector/src.cpp +++ b/rules/vector/src.cpp @@ -254,3 +254,9 @@ f116(std::vector &o, typename std::vector::const_iterator pos, std::initializer_list l) { return o.insert(pos, l); } + +template +typename std::vector::reference +f117(const typename std::vector::reference &a0) { + return typename std::vector::reference(a0); +} diff --git a/rules/vector/tgt_unsafe.rs b/rules/vector/tgt_unsafe.rs index 3f54c32dc..4fe004b70 100644 --- a/rules/vector/tgt_unsafe.rs +++ b/rules/vector/tgt_unsafe.rs @@ -249,3 +249,7 @@ unsafe fn f116(a0: &mut Vec, a1: UnsafeRandomAccessIterator, a2: Vec a0.splice(__off..__off, a2); UnsafeRandomAccessIterator::Vec(a0.as_mut_ptr().add(__off)) } + +unsafe fn f117(a0: bool) -> bool { + a0 +} diff --git a/tests/unit/out/refcount/simple_index.rs b/tests/unit/out/refcount/simple_index.rs index 9f87fca4d..8a6a81e0e 100644 --- a/tests/unit/out/refcount/simple_index.rs +++ b/tests/unit/out/refcount/simple_index.rs @@ -13,6 +13,9 @@ pub fn main() { fn main_0() -> i32 { let v: Value> = Rc::new(RefCell::new(Vec::from([true]))); assert!(({ (*v.borrow())[0_usize] } as bool)); + let r: Value = Rc::new(RefCell::new({ (*v.borrow())[0_usize] })); + let copy: Value = Rc::new(RefCell::new((*r.borrow()))); + assert!(((*copy.borrow()) as bool)); return 0; } pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/simple_index.rs b/tests/unit/out/unsafe/simple_index.rs index 58d07cb3f..cfa91a74d 100644 --- a/tests/unit/out/unsafe/simple_index.rs +++ b/tests/unit/out/unsafe/simple_index.rs @@ -15,6 +15,9 @@ pub fn main() { unsafe fn main_0() -> i32 { let mut v: Vec = Vec::from([true]); assert!((v[(0_usize)] as bool)); + let mut r: bool = v[(0_usize)]; + let mut copy: bool = r; + assert!((copy as bool)); return 0; } pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/simple_index.cpp b/tests/unit/simple_index.cpp index afb16abc9..15afe7132 100644 --- a/tests/unit/simple_index.cpp +++ b/tests/unit/simple_index.cpp @@ -4,5 +4,8 @@ int main() { std::vector v = {true}; assert(v[0]); + std::vector::reference r = v[0]; + std::vector::reference copy = r; + assert(copy); return 0; }