Skip to content

Commit 51e80be

Browse files
committed
Merge branch 'master' into init
2 parents 37c4ca8 + 1ee81b4 commit 51e80be

11 files changed

Lines changed: 122 additions & 17 deletions

File tree

‎cpp2rust/converter/rules/decls.cpp‎

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,25 @@ const clang::Expr *GetMacroMemberBase(const clang::SourceManager &sm,
8080
}
8181
}
8282

83+
namespace {
84+
85+
std::vector<clang::TemplateArgument> deducedArguments(
86+
clang::Sema &sema, clang::TemplateParameterList *params,
87+
llvm::SmallVectorImpl<clang::DeducedTemplateArgument> &deduced) {
88+
for (unsigned i = 0; i < deduced.size(); ++i) {
89+
auto nttp =
90+
llvm::dyn_cast<clang::NonTypeTemplateParmDecl>(params->getParam(i));
91+
if (nttp && !nttp->getType()->isDependentType() &&
92+
deduced[i].getKind() == clang::TemplateArgument::Integral) {
93+
deduced[i] = clang::TemplateArgument(
94+
sema.Context, deduced[i].getAsIntegral(), nttp->getType());
95+
}
96+
}
97+
return std::vector<clang::TemplateArgument>(deduced.begin(), deduced.end());
98+
}
99+
100+
} // namespace
101+
83102
std::optional<std::vector<clang::TemplateArgument>>
84103
DeduceFromType(clang::Sema &sema, clang::TemplateParameterList *params,
85104
clang::QualType pattern, clang::QualType actual) {
@@ -94,16 +113,27 @@ DeduceFromType(clang::Sema &sema, clang::TemplateParameterList *params,
94113
trial.failed()) {
95114
return std::nullopt;
96115
}
97-
for (unsigned i = 0; i < deduced.size(); ++i) {
98-
auto nttp =
99-
llvm::dyn_cast<clang::NonTypeTemplateParmDecl>(params->getParam(i));
100-
if (nttp && !nttp->getType()->isDependentType() &&
101-
deduced[i].getKind() == clang::TemplateArgument::Integral) {
102-
deduced[i] = clang::TemplateArgument(
103-
sema.Context, deduced[i].getAsIntegral(), nttp->getType());
104-
}
116+
return deducedArguments(sema, params, deduced);
117+
}
118+
119+
std::optional<std::vector<clang::TemplateArgument>>
120+
DeduceFromArguments(clang::Sema &sema, clang::TemplateParameterList *params,
121+
llvm::ArrayRef<clang::TemplateArgumentLoc> pattern,
122+
llvm::ArrayRef<clang::TemplateArgument> actual) {
123+
Trial trial(sema);
124+
llvm::SmallVector<clang::TemplateArgument, 4> written;
125+
for (const auto &arg : pattern) {
126+
written.push_back(arg.getArgument());
105127
}
106-
return std::vector<clang::TemplateArgument>(deduced.begin(), deduced.end());
128+
llvm::SmallVector<clang::DeducedTemplateArgument, 4> deduced(params->size());
129+
clang::sema::TemplateDeductionInfo info(params->getTemplateLoc());
130+
if (sema.DeduceTemplateArguments(params, written, actual, info, deduced,
131+
/*NumberOfArgumentsMustMatch=*/false) !=
132+
clang::TemplateDeductionResult::Success ||
133+
trial.failed()) {
134+
return std::nullopt;
135+
}
136+
return deducedArguments(sema, params, deduced);
107137
}
108138

109139
namespace {

‎cpp2rust/converter/rules/decls.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ std::optional<std::vector<clang::TemplateArgument>>
4646
DeduceFromType(clang::Sema &sema, clang::TemplateParameterList *params,
4747
clang::QualType pattern, clang::QualType actual);
4848

49+
std::optional<std::vector<clang::TemplateArgument>>
50+
DeduceFromArguments(clang::Sema &sema, clang::TemplateParameterList *params,
51+
llvm::ArrayRef<clang::TemplateArgumentLoc> pattern,
52+
llvm::ArrayRef<clang::TemplateArgument> actual);
53+
4954
std::optional<std::vector<clang::TemplateArgument>>
5055
DeduceMemberType(clang::Sema &sema, const clang::TemplateDecl *rule,
5156
clang::QualType pattern, clang::QualType use);

‎cpp2rust/converter/rules/expr_matcher.cpp‎

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <clang/AST/DeclCXX.h>
77
#include <clang/AST/DeclTemplate.h>
88
#include <clang/AST/ExprCXX.h>
9+
#include <clang/AST/IgnoreExpr.h>
910
#include <clang/Basic/OperatorKinds.h>
1011
#include <clang/Lex/Lexer.h>
1112
#include <clang/Sema/EnterExpressionEvaluationContext.h>
@@ -160,7 +161,9 @@ std::vector<clang::Expr *> getOperands(clang::ASTContext &ctx,
160161
operands.assign(op->arg_begin(), op->arg_end());
161162
if (!operands.empty() &&
162163
llvm::isa_and_nonnull<clang::CXXMethodDecl>(op->getDirectCallee())) {
163-
operands[0] = operands[0]->IgnoreParenImpCasts();
164+
operands[0] =
165+
clang::IgnoreExprNodes(operands[0], clang::IgnoreParensSingleStep,
166+
clang::IgnoreImplicitCastsSingleStep);
164167
}
165168
} else if (auto call = llvm::dyn_cast<clang::CXXMemberCallExpr>(expr)) {
166169
operands.push_back(getObject(
@@ -323,6 +326,44 @@ void deduceFromExplicitArgs(clang::Sema &sema,
323326
}
324327
}
325328

329+
std::optional<std::vector<clang::TemplateArgument>>
330+
deduceFromCallee(clang::Sema &sema, clang::FunctionTemplateDecl *rule,
331+
const clang::Expr *use) {
332+
auto returned = RuleDecls::GetReturned(rule->getTemplatedDecl());
333+
if (!returned) {
334+
return std::nullopt;
335+
}
336+
returned = RuleDecls::SkipImplicit(returned);
337+
if (auto call = llvm::dyn_cast<clang::CallExpr>(returned)) {
338+
returned = call->getCallee()->IgnoreParenImpCasts();
339+
}
340+
llvm::ArrayRef<clang::TemplateArgumentLoc> written;
341+
if (auto overload = llvm::dyn_cast<clang::OverloadExpr>(returned);
342+
overload && overload->hasExplicitTemplateArgs()) {
343+
written = overload->template_arguments();
344+
} else if (auto ref =
345+
llvm::dyn_cast<clang::DependentScopeDeclRefExpr>(returned);
346+
ref && ref->hasExplicitTemplateArgs()) {
347+
written = ref->template_arguments();
348+
} else {
349+
return std::nullopt;
350+
}
351+
use = RuleDecls::SkipImplicit(use);
352+
const clang::Decl *used = nullptr;
353+
if (auto call = llvm::dyn_cast<clang::CallExpr>(use)) {
354+
used = call->getDirectCallee();
355+
} else if (auto ref = llvm::dyn_cast<clang::DeclRefExpr>(use)) {
356+
used = ref->getDecl();
357+
}
358+
auto specialization = llvm::dyn_cast_or_null<clang::FunctionDecl>(used);
359+
if (!specialization || !specialization->getTemplateSpecializationArgs()) {
360+
return std::nullopt;
361+
}
362+
return RuleDecls::DeduceFromArguments(
363+
sema, rule->getTemplateParameters(), written,
364+
specialization->getTemplateSpecializationArgs()->asArray());
365+
}
366+
326367
clang::TemplateArgumentListInfo getResultArgs(clang::Sema &sema,
327368
clang::FunctionTemplateDecl *rule,
328369
const clang::Expr *use) {
@@ -345,6 +386,13 @@ clang::TemplateArgumentListInfo getResultArgs(clang::Sema &sema,
345386
.getCanonicalType()
346387
.getUnqualifiedType())
347388
.value_or(std::vector<clang::TemplateArgument>(params->size()));
389+
if (auto from_callee = deduceFromCallee(sema, rule, use)) {
390+
for (unsigned i = 0; i < deduced.size(); ++i) {
391+
if (deduced[i].isNull()) {
392+
deduced[i] = (*from_callee)[i];
393+
}
394+
}
395+
}
348396
deduceMemberTypesFromOperands(sema, rule, use, deduced);
349397
deduceFromExplicitArgs(sema, rule, use, deduced);
350398
auto last = static_cast<unsigned>(deducible.find_last_unset());

‎cpp2rust/converter/rules/registry.cpp‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ unsigned iteratorOverGeneric(const TranslationRule::ExprRule &rule,
115115
unsigned n) {
116116
for (unsigned i = 0; i < rule.generics.size(); ++i) {
117117
for (const auto &bound : rule.generics[i]) {
118-
if (llvm::StringRef(bound.trait_name).ends_with("Iterator") &&
118+
llvm::StringRef trait = bound.trait_name;
119+
if ((trait.ends_with("Iterator") || trait == "CppArray") &&
119120
llvm::is_contained(bound.args, n)) {
120121
return i + 1;
121122
}
@@ -404,6 +405,9 @@ clang::QualType iteratorElementType(clang::ASTContext &ctx,
404405
if (iterator->isPointerType()) {
405406
return iterator->getPointeeType().getUnqualifiedType();
406407
}
408+
if (auto *array = ctx.getAsArrayType(iterator)) {
409+
return array->getElementType().getUnqualifiedType();
410+
}
407411
auto [rule, bindings] = Search(ctx, iterator);
408412
assert(rule && !bindings.empty() &&
409413
bindings[0].getKind() == clang::TemplateArgument::Type &&

‎rules/unique_ptr/shim.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Copyright (c) 2022-present INESC-ID.
2+
// Distributed under the MIT license that can be found in the LICENSE file.
3+
4+
pub trait CppArray<T> {}

‎rules/unique_ptr/src_cxx14.cpp‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
#include <memory>
66
#include <utility>
77

8-
template <typename T1> std::unique_ptr<T1[]> f1(std::size_t n) {
9-
return std::make_unique<T1[]>(n);
8+
template <typename T1> auto f1(std::size_t a0) {
9+
return std::make_unique<T1>(a0);
1010
}
1111

1212
template <typename T1, typename... T2> std::unique_ptr<T1> f8(T2 &&...a0) {

‎rules/unique_ptr/tgt_refcount.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ fn t4<T1>() -> Ptr<T1> {
2121
Ptr::null()
2222
}
2323

24-
fn f1<T1: Default>(a0: usize) -> Option<Value<Box<[T1]>>> {
24+
fn f1<T1: CppArray<T2>, T2: Default>(a0: usize) -> Option<Value<Box<[T2]>>> {
2525
Some(Rc::new(RefCell::new(
26-
(0..a0).map(|_| <T1>::default()).collect::<Box<[_]>>(),
26+
(0..a0).map(|_| <T2>::default()).collect::<Box<[_]>>(),
2727
)))
2828
}
2929

‎rules/unique_ptr/tgt_unsafe.rs‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright (c) 2022-present INESC-ID.
22
// Distributed under the MIT license that can be found in the LICENSE file.
33

4+
use libcc2rs::*;
5+
46
fn t1<T1>() -> Option<Box<T1>> {
57
None
68
}
@@ -17,8 +19,8 @@ fn t4<T1>() -> *mut T1 {
1719
::std::ptr::null_mut()
1820
}
1921

20-
unsafe fn f1<T1: Default>(a0: usize) -> Option<Box<[T1]>> {
21-
Some((0..a0).map(|_| <T1>::default()).collect::<Box<[_]>>())
22+
unsafe fn f1<T1: CppArray<T2>, T2: Default>(a0: usize) -> Option<Box<[T2]>> {
23+
Some((0..a0).map(|_| <T2>::default()).collect::<Box<[_]>>())
2224
}
2325
unsafe fn f2<T1>(a0: &mut Option<Box<T1>>) -> *mut T1 {
2426
a0.as_deref_mut()

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ fn main_0() -> i32 {
2626
(r2).clone()
2727
};
2828
assert!(v1.decay().offset(0_usize as isize).read());
29+
{
30+
v1.decay().offset(0_usize as isize).write(false);
31+
v1.decay().offset(0_usize as isize)
32+
};
33+
assert!(!(v1.decay().offset(0_usize as isize).read()));
2934
return 0;
3035
}
3136
pub fn __cpp2rust_init_globals() {}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ unsafe fn main_0() -> i32 {
2828
r2
2929
};
3030
assert!(*(&mut (v1)[0_usize as usize] as *mut bool));
31+
{
32+
*(&mut (v1)[0_usize as usize] as *mut bool) = false;
33+
(&mut (v1)[0_usize as usize] as *mut bool)
34+
};
35+
assert!(!(*(&mut (v1)[0_usize as usize] as *mut bool)));
3136
return 0;
3237
}
3338
pub unsafe fn __cpp2rust_init_globals() {}

0 commit comments

Comments
 (0)