Skip to content

Commit eeabae7

Browse files
authored
Use generic get<N> for pair, array and tuple_element (#572)
std::pair::get is defined as: ```cpp template< std::size_t I, class T1, class T2 > typename std::tuple_element<I, std::pair<T1,T2> >::type& get( std::pair<T1, T2>& p ) noexcept; ``` Our rules wrote individual versions for `get<0>` and `get<1>`. This PR adds the generic version `get<N>` as declared by the standard. This PR also adds get for array and translates tuple_element. --- Rust does not allow writing a rule as `get<N>(a0: (T1, T2)) { return a.N }` with `N = {0, 1}`. So we need libcc2rs support for this. TupleElement is the translation of `std::tuple_element` and TupleGet uses TupleElement to translate `std::get`.
1 parent 5865db2 commit eeabae7

35 files changed

Lines changed: 383 additions & 141 deletions

‎cpp2rust/converter/converter.cpp‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ Converter::GetTemplateArgumentAsString(const clang::TemplateArgument &arg) {
133133
case clang::TemplateArgument::Type:
134134
return GetUnboxedTypeAsString(arg.getAsType());
135135
case clang::TemplateArgument::Integral:
136+
if (!arg.getIntegralType()->isBooleanType()) {
137+
llvm::SmallString<16> value;
138+
arg.getAsIntegral().toString(value);
139+
return std::string(value);
140+
}
141+
[[fallthrough]];
136142
case clang::TemplateArgument::NullPtr:
137143
case clang::TemplateArgument::Declaration:
138144
case clang::TemplateArgument::StructuralValue: {
@@ -5114,8 +5120,6 @@ std::string Converter::GetMappedAsString(clang::Expr *expr, clang::Expr **args,
51145120
if (!tgt_ir)
51155121
return {};
51165122

5117-
CheckRuleReturnType(expr);
5118-
51195123
auto saved_borrows = std::exchange(mut_borrows_, {});
51205124
auto *operand = tgt_ir->refExprOperand();
51215125
bool lvalue = operand && !isAddrOf();

‎cpp2rust/converter/converter.h‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -916,9 +916,6 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
916916
return false;
917917
}
918918

919-
// Checks that the rule of expr returns the type that expr returns in C++.
920-
virtual void CheckRuleReturnType(clang::Expr * /*expr*/) {}
921-
922919
bool RecordHasCopyableFields(const clang::RecordDecl *decl);
923920

924921
bool ShouldReplaceWithMappedBody(const clang::ValueDecl *decl) const;

‎cpp2rust/converter/mapper.cpp‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,4 @@ std::string GetParamType(Converter &converter, const clang::Expr *expr,
7474
return Matcher::InstantiateTgt(converter, subs, rule->params.at(index).type);
7575
}
7676

77-
std::string GetReturnType(Converter &converter, const clang::Expr *expr) {
78-
auto [rule, subs] = RuleRegistry::Search(converter.GetASTContext(), expr);
79-
return Matcher::InstantiateTgt(converter, subs, rule->return_type.type);
80-
}
81-
8277
} // namespace cpp2rust::Mapper

‎cpp2rust/converter/mapper.h‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,4 @@ std::string MapFunctionName(clang::ASTContext &ctx,
2727
const clang::FunctionDecl *decl);
2828
std::string GetParamType(Converter &converter, const clang::Expr *expr,
2929
unsigned index);
30-
std::string GetReturnType(Converter &converter, const clang::Expr *expr);
3130
} // namespace cpp2rust::Mapper

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -438,29 +438,6 @@ std::string ConverterRefCount::ConvertElementPtr(clang::Expr *arg) {
438438
return ConvertObject(arg, ObjectShape::Element);
439439
}
440440

441-
void ConverterRefCount::CheckRuleReturnType(clang::Expr *expr) {
442-
auto *call = clang::dyn_cast<clang::CallExpr>(expr);
443-
if (!call ||
444-
!RuleRegistry::GetExprRule(ctx_, expr)->return_type.is_refcount_pointer) {
445-
return;
446-
}
447-
auto type = RuleRegistry::GetDeclaredReturnType(expr);
448-
if (auto ref = type->getAs<clang::ReferenceType>()) {
449-
auto pointee = ref->getPointeeType();
450-
type = pointee->isRecordType() &&
451-
RuleRegistry::MapsToRefcountPointer(ctx_, pointee)
452-
? pointee
453-
: ctx_.getPointerType(pointee);
454-
}
455-
auto ret = NormalizeType(Mapper::GetReturnType(*this, expr));
456-
auto expected = NormalizeType(ToString(type));
457-
if (ret != expected) {
458-
llvm::errs() << "rule return type " << ret << " is not " << expected
459-
<< '\n';
460-
llvm::report_fatal_error("rule return type does not match the C++ one");
461-
}
462-
}
463-
464441
std::string ConverterRefCount::ConvertFreshObject(clang::Expr *expr) {
465442
return MakeFresh(ConvertObject(expr));
466443
}

‎cpp2rust/converter/models/converter_refcount.h‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,6 @@ class ConverterRefCount final : public Converter {
441441
// The method that makes a pointer to an object of the given type, which is
442442
// one to its elements if they are what ConvertObject wants.
443443
std::string AsPointerMethod(clang::QualType type);
444-
void CheckRuleReturnType(clang::Expr *expr) override;
445444

446445
std::string ConvertTemporaryPointer(
447446
clang::Expr *expr,

‎cpp2rust/converter/rules/expr_matcher.cpp‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,32 @@ getExplicitTemplateArgs(const clang::Expr *expr) {
298298
return {};
299299
}
300300

301+
void deduceNonTypeFromExplicitArg(
302+
clang::ASTContext &ctx, const clang::TemplateArgument &rule_arg,
303+
const clang::Expr *use, unsigned i,
304+
std::vector<clang::TemplateArgument> &deduced) {
305+
auto ref = llvm::dyn_cast<clang::DeclRefExpr>(
306+
rule_arg.getAsExpr()->IgnoreParenImpCasts());
307+
auto nttp =
308+
ref ? llvm::dyn_cast<clang::NonTypeTemplateParmDecl>(ref->getDecl())
309+
: nullptr;
310+
if (!nttp) {
311+
return;
312+
}
313+
auto call = llvm::cast<clang::CallExpr>(RuleDecls::SkipImplicit(use));
314+
auto callee = call->getDirectCallee();
315+
auto spec = callee ? callee->getTemplateSpecializationArgs() : nullptr;
316+
assert(spec && i < spec->size() &&
317+
"explicit template argument of a non-specialized callee");
318+
const auto &value = spec->get(i);
319+
assert(value.getKind() == clang::TemplateArgument::Integral &&
320+
"non-type template argument is not an integral");
321+
auto &slot = deduced[nttp->getIndex()];
322+
if (slot.isNull()) {
323+
slot = clang::TemplateArgument(ctx, value.getAsIntegral(), nttp->getType());
324+
}
325+
}
326+
301327
void deduceFromExplicitArgs(clang::Sema &sema,
302328
clang::FunctionTemplateDecl *rule,
303329
const clang::Expr *use,
@@ -308,6 +334,10 @@ void deduceFromExplicitArgs(clang::Sema &sema,
308334
for (unsigned i = 0; i < rule_args.size() && i < use_args.size(); ++i) {
309335
const auto &rule_arg = rule_args[i].getArgument();
310336
const auto &use_arg = use_args[i].getArgument();
337+
if (rule_arg.getKind() == clang::TemplateArgument::Expression) {
338+
deduceNonTypeFromExplicitArg(sema.Context, rule_arg, use, i, deduced);
339+
continue;
340+
}
311341
if (rule_arg.getKind() != clang::TemplateArgument::Type ||
312342
use_arg.getKind() != clang::TemplateArgument::Type) {
313343
continue;

‎cpp2rust/converter/rules/registry.cpp‎

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -496,23 +496,6 @@ std::string InitAliasName(Model model, const std::string &name) {
496496
model == Model::kRefCount ? "refcount" : "unsafe", name);
497497
}
498498

499-
clang::QualType GetDeclaredReturnType(const clang::Expr *expr) {
500-
auto match = findExpr(expr);
501-
assert(match.rule_decl && "expression must have a translation rule");
502-
auto function = match.rule_decl->decl->getAsFunction();
503-
assert(function && "rule is not a function");
504-
auto tmpl = function->getDescribedFunctionTemplate();
505-
if (!tmpl) {
506-
return function->getReturnType();
507-
}
508-
clang::MultiLevelTemplateArgumentList args(tmpl, match.args,
509-
/*Final=*/false);
510-
clang::Sema::InstantiatingTemplate inst(
511-
*sema_, expr->getBeginLoc(), const_cast<clang::FunctionDecl *>(function));
512-
return sema_->SubstType(function->getReturnType(), args, expr->getBeginLoc(),
513-
clang::DeclarationName());
514-
}
515-
516499
bool HasExprRule(const clang::FunctionDecl *decl) {
517500
auto key = RuleKeys::GetDeclKey(decl);
518501
if (!key) {

‎cpp2rust/converter/rules/registry.h‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ clang::QualType GetGenericType(clang::ASTContext &ctx, const clang::Expr *expr,
5050
clang::QualType GetConversionSourceType(clang::ASTContext &ctx,
5151
const clang::Expr *expr, unsigned to);
5252

53-
clang::QualType GetDeclaredReturnType(const clang::Expr *expr);
54-
5553
bool HasExprRule(const clang::FunctionDecl *decl);
5654
bool IsLibcPassthrough(clang::ASTContext &ctx, const clang::Expr *expr);
5755
bool ReturnsPointer(clang::ASTContext &ctx, const clang::Expr *expr);

‎rule-preprocessor/src/syntactic.rs‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -481,9 +481,16 @@ impl<'a> FnIrBuilder<'a> {
481481

482482
if let Some(gpl) = self.fn_item.generic_param_list() {
483483
for param in gpl.generic_params() {
484-
if let ast::GenericParam::TypeParam(tp) = param {
485-
let name = tp.name().map(|n| n.text().to_string()).unwrap_or_default();
486-
generics.insert(name, extract_bounds(tp.type_bound_list()));
484+
match param {
485+
ast::GenericParam::TypeParam(tp) => {
486+
let name = tp.name().map(|n| n.text().to_string()).unwrap_or_default();
487+
generics.insert(name, extract_bounds(tp.type_bound_list()));
488+
}
489+
ast::GenericParam::ConstParam(cp) => {
490+
let name = cp.name().map(|n| n.text().to_string()).unwrap_or_default();
491+
generics.insert(name, Vec::new());
492+
}
493+
_ => {}
487494
}
488495
}
489496
}

0 commit comments

Comments
 (0)