Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cpp2rust/converter/rules/registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ void addRule(clang::ASTContext &ctx, const std::string &dir,
assert(llvm::isa<clang::VarDecl>(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(
Expand Down
42 changes: 32 additions & 10 deletions cpp2rust/converter/rules/rule_keys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <clang/Basic/OperatorKinds.h>
#include <clang/Basic/SourceManager.h>
#include <clang/Lex/Lexer.h>
#include <clang/Sema/Sema.h>
#include <clang/Sema/TemplateDeduction.h>
#include <llvm/ADT/STLExtras.h>

#include <cassert>
Expand Down Expand Up @@ -56,32 +58,51 @@ const clang::Decl *getParent(const clang::Decl *decl) {
return nullptr;
}

std::vector<clang::QualType> resolveMemberType(clang::QualType type) {
llvm::SmallVector<clang::CXXRecordDecl *>
matchingDefinitions(clang::Sema &sema, clang::ClassTemplateDecl *tmpl,
const clang::TemplateSpecializationType *spec) {
llvm::SmallVector<clang::ClassTemplatePartialSpecializationDecl *> partials;
tmpl->getPartialSpecializations(partials);
llvm::SmallVector<clang::CXXRecordDecl *> 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<clang::QualType> resolveMemberType(clang::Sema &sema,
clang::QualType type) {
auto member = type->getAs<clang::DependentNameType>();
if (!member) {
return {type};
}
auto qualifier = member->getQualifier().getAsType();
assert(qualifier && "member type is not qualified by a type");
std::vector<clang::QualType> resolved;
for (auto owner : resolveMemberType(clang::QualType(qualifier, 0))) {
for (auto owner : resolveMemberType(sema, clang::QualType(qualifier, 0))) {
auto spec = owner->getAs<clang::TemplateSpecializationType>();
auto tmpl = spec ? llvm::dyn_cast_or_null<clang::ClassTemplateDecl>(
spec->getTemplateName().getAsTemplateDecl())
: nullptr;
assert(tmpl && "member type is not qualified by a class template");
llvm::SmallVector<clang::ClassTemplatePartialSpecializationDecl *> partials;
tmpl->getPartialSpecializations(partials);
llvm::SmallVector<clang::CXXRecordDecl *> 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<clang::TypedefNameDecl>(decl)) {
auto types = resolveMemberType(alias->getUnderlyingType());
auto types = resolveMemberType(sema, alias->getUnderlyingType());
resolved.insert(resolved.end(), types.begin(), types.end());
}
}
Expand Down Expand Up @@ -198,8 +219,9 @@ std::optional<ExprKey> GetExprKey(clang::ASTContext &ctx,
return std::nullopt;
}

std::vector<ExprKey> GetExprKeys(clang::ASTContext &ctx,
std::vector<ExprKey> GetExprKeys(clang::Sema &sema,
const clang::NamedDecl *rule) {
auto &ctx = sema.Context;
if (auto var = llvm::dyn_cast<clang::VarDecl>(rule)) {
auto key = GetExprKey(ctx, var->getInit());
assert(key && "expression rule has no key");
Expand All @@ -210,7 +232,7 @@ std::vector<ExprKey> GetExprKeys(clang::ASTContext &ctx,
if (auto construct =
llvm::dyn_cast<clang::CXXUnresolvedConstructExpr>(returned)) {
std::vector<ExprKey> keys;
for (auto type : resolveMemberType(construct->getTypeAsWritten())) {
for (auto type : resolveMemberType(sema, construct->getTypeAsWritten())) {
if (type->getAs<clang::TemplateTypeParmType>()) {
if (!llvm::is_contained(keys, ExprKey{kAnyConstructor})) {
keys.push_back(kAnyConstructor);
Expand Down
3 changes: 2 additions & 1 deletion cpp2rust/converter/rules/rule_keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <clang/AST/DeclarationName.h>
#include <clang/AST/Expr.h>
#include <clang/AST/Type.h>
#include <clang/Sema/Sema.h>
#include <llvm/ADT/Hashing.h>

#include <compare>
Expand Down Expand Up @@ -46,7 +47,7 @@ inline const Constructor kAnyConstructor{nullptr};
std::optional<ExprKey> GetExprKey(clang::ASTContext &ctx,
const clang::Expr *use);

std::vector<ExprKey> GetExprKeys(clang::ASTContext &ctx,
std::vector<ExprKey> GetExprKeys(clang::Sema &sema,
const clang::NamedDecl *rule);

std::optional<ExprKey> GetDeclKey(const clang::NamedDecl *decl);
Expand Down
6 changes: 6 additions & 0 deletions rules/vector/src.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,3 +254,9 @@ f116(std::vector<T1, T2> &o, typename std::vector<T1, T2>::const_iterator pos,
std::initializer_list<T1> l) {
return o.insert(pos, l);
}

template <typename T1>
typename std::vector<bool, T1>::reference
f117(const typename std::vector<bool, T1>::reference &a0) {
return typename std::vector<bool, T1>::reference(a0);
}
4 changes: 4 additions & 0 deletions rules/vector/tgt_unsafe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,3 +249,7 @@ unsafe fn f116<T1>(a0: &mut Vec<T1>, a1: UnsafeRandomAccessIterator<T1>, a2: Vec
a0.splice(__off..__off, a2);
UnsafeRandomAccessIterator::Vec(a0.as_mut_ptr().add(__off))
}

unsafe fn f117(a0: bool) -> bool {
a0
}
3 changes: 3 additions & 0 deletions tests/unit/out/refcount/simple_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ pub fn main() {
fn main_0() -> i32 {
let v: Value<Vec<bool>> = Rc::new(RefCell::new(Vec::from([true])));
assert!(({ (*v.borrow())[0_usize] } as bool));
let r: Value<bool> = Rc::new(RefCell::new({ (*v.borrow())[0_usize] }));
let copy: Value<bool> = Rc::new(RefCell::new((*r.borrow())));
assert!(((*copy.borrow()) as bool));
return 0;
}
pub fn __cpp2rust_init_globals() {}
3 changes: 3 additions & 0 deletions tests/unit/out/unsafe/simple_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ pub fn main() {
unsafe fn main_0() -> i32 {
let mut v: Vec<bool> = 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() {}
3 changes: 3 additions & 0 deletions tests/unit/simple_index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@
int main() {
std::vector<bool> v = {true};
assert(v[0]);
std::vector<bool>::reference r = v[0];
std::vector<bool>::reference copy = r;
assert(copy);
return 0;
}
Loading