Skip to content

Commit ec6c063

Browse files
authored
[NFC] Split responsibilities of Mapper (#434)
Mapper grew too big. It has 4 responsibilities at the same time: 1. Map expressions or types to a rust string 2. Match expressions or types against translation rules 3. Answer queries about the translation rules (ParamIsPointer, IsLibcPassthrough, etc) 4. Print string representation of expressions or types Only the first should be in Mapper, the rest should be split. For (2) I plan to add a new tree matcher instead of the current string matcher. To make the transition smooth I extracted the matching logic form Mapper into `cpp2rust/converter/rules/matcher.h`. For (3) I added `cpp2rust/converter/rules/registry.h` which keeps the `exprs_` and `rules_` multimaps + handles queries about the translation rules. For (4) I added `cpp2rust/converter/printer.h` which should BTW disappear after we switch to tree matching instead of string matching. This is a building block for fixing #435
1 parent b9f3781 commit ec6c063

16 files changed

Lines changed: 1424 additions & 1203 deletions

‎cpp2rust/converter/converter.cpp‎

Lines changed: 74 additions & 64 deletions
Large diffs are not rendered by default.

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626

2727
#include "converter/lex.h"
2828
#include "converter/mapper.h"
29+
#include "converter/printer.h"
30+
#include "converter/rules/registry.h"
2931

3032
// https://doc.rust-lang.org/reference/keywords.html
3133
static const char rust_keywords[][12] = {
@@ -717,25 +719,26 @@ static std::string GetParamSignature(const clang::Decl *decl) {
717719
}
718720

719721
static std::string GetLexicalSpecializationID(const clang::Decl *decl) {
722+
auto &ctx = decl->getASTContext();
720723
std::string id;
721724
if (const auto *var =
722725
clang::dyn_cast<clang::VarTemplateSpecializationDecl>(decl)) {
723726
id += clang::ASTNameGenerator(var->getASTContext()).getName(var);
724727
}
725728
if (const auto *self =
726729
clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(decl)) {
727-
id += Mapper::ToString(Mapper::GetTypeForDecl(self));
730+
id += Printer::ToString(ctx, GetTypeForDecl(ctx, self));
728731
}
729732
if (const auto *spec =
730733
clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(
731734
decl->getLexicalDeclContext());
732735
spec && decl->getLexicalDeclContext() != decl->getDeclContext()) {
733-
id += Mapper::ToString(Mapper::GetTypeForDecl(spec));
736+
id += Printer::ToString(ctx, GetTypeForDecl(ctx, spec));
734737
}
735738
for (const auto *dc = decl->getDeclContext(); dc; dc = dc->getParent()) {
736739
if (const auto *spec =
737740
clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(dc)) {
738-
id += Mapper::ToString(Mapper::GetTypeForDecl(spec));
741+
id += Printer::ToString(ctx, GetTypeForDecl(ctx, spec));
739742
}
740743
if (const auto *fn = clang::dyn_cast<clang::FunctionDecl>(dc);
741744
fn && fn->getTemplateSpecializationArgs()) {
@@ -755,6 +758,35 @@ std::string GetMethodID(const clang::CXXMethodDecl *decl) {
755758
return decl->getQualifiedNameAsString() + GetID(decl);
756759
}
757760

761+
clang::QualType GetTypeForDecl(clang::ASTContext &ctx,
762+
const clang::NamedDecl *decl) {
763+
if (const auto *spec =
764+
llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(decl)) {
765+
llvm::ArrayRef<clang::TemplateArgument> args =
766+
spec->getTemplateArgs().asArray();
767+
llvm::SmallVector<clang::TemplateArgument, 4> canon(args.begin(),
768+
args.end());
769+
ctx.canonicalizeTemplateArguments(canon);
770+
771+
return ctx.getTemplateSpecializationType(
772+
clang::ElaboratedTypeKeyword::None,
773+
clang::TemplateName(spec->getSpecializedTemplate()), args, canon);
774+
}
775+
776+
const auto *rdecl = llvm::dyn_cast<clang::TagDecl>(decl);
777+
assert(rdecl && "Unsupported decl type");
778+
779+
return ctx.getTagType(clang::ElaboratedTypeKeyword::None,
780+
rdecl->getQualifier(), rdecl, /*OwnsTag*/ false);
781+
}
782+
783+
bool HasFunctionParameterPack(const clang::FunctionDecl *decl) {
784+
if (auto *primary = decl->getPrimaryTemplate()) {
785+
decl = primary->getTemplatedDecl();
786+
}
787+
return decl->getNumParams() && decl->parameters().back()->isParameterPack();
788+
}
789+
758790
std::string DisambiguateAnonymousTag(const clang::TagDecl *tag) {
759791
if (!tag) {
760792
return "";
@@ -1462,15 +1494,15 @@ std::optional<clang::QualType> GetParamImplicitConvertTarget(clang::Expr *expr,
14621494
}
14631495

14641496
std::optional<IteratorCategory>
1465-
GetStrongestIteratorCategory(clang::QualType type) {
1497+
GetStrongestIteratorCategory(clang::ASTContext &ctx, clang::QualType type) {
14661498
type = type.getNonReferenceType().getUnqualifiedType();
1467-
if (!Mapper::Contains(type)) {
1499+
if (!Mapper::Contains(ctx, type)) {
14681500
return std::nullopt;
14691501
}
1470-
if (Mapper::MapsToRefcountPointer(type)) {
1502+
if (RuleRegistry::MapsToRefcountPointer(ctx, type)) {
14711503
return IteratorCategory::Contiguous;
14721504
}
1473-
auto mapped = Mapper::Map(type);
1505+
auto mapped = Mapper::Map(ctx, type);
14741506
if (mapped.empty()) {
14751507
return std::nullopt;
14761508
}
@@ -1547,15 +1579,17 @@ bool IsBuiltinVaStart(const clang::CallExpr *expr) {
15471579
return false;
15481580
}
15491581

1550-
bool NeedsImplicitScalarCast(clang::QualType from, clang::QualType to) {
1582+
bool NeedsImplicitScalarCast(clang::ASTContext &ctx, clang::QualType from,
1583+
clang::QualType to) {
15511584
return !from.isNull() && !to.isNull() && from->isIntegerType() &&
15521585
to->isIntegerType() &&
15531586
from.getCanonicalType().getUnqualifiedType() ==
15541587
to.getCanonicalType().getUnqualifiedType() &&
1555-
Mapper::Map(from) != Mapper::Map(to);
1588+
Mapper::Map(ctx, from) != Mapper::Map(ctx, to);
15561589
}
15571590

1558-
bool NeedsRefBindingTemp(const clang::Expr *arg, clang::QualType param_type) {
1591+
bool NeedsRefBindingTemp(clang::ASTContext &ctx, const clang::Expr *arg,
1592+
clang::QualType param_type) {
15591593
if (!param_type->isReferenceType()) {
15601594
return false;
15611595
}
@@ -1571,28 +1605,27 @@ bool NeedsRefBindingTemp(const clang::Expr *arg, clang::QualType param_type) {
15711605
// void foo(const size_t &) {} <-- size_t -> usize
15721606
// unsigned long x = 1; foo(x); <-- unsigned long -> u64
15731607
return param_type->getPointeeType().isConstQualified() &&
1574-
NeedsImplicitScalarCast(arg->IgnoreImplicit()->getType(),
1608+
NeedsImplicitScalarCast(ctx, arg->IgnoreImplicit()->getType(),
15751609
param_type.getNonReferenceType());
15761610
}
15771611

1578-
bool IsSizeType(clang::QualType type) {
1579-
auto rust_type = Mapper::Map(type);
1612+
bool IsSizeType(clang::ASTContext &ctx, clang::QualType type) {
1613+
auto rust_type = Mapper::Map(ctx, type);
15801614
return rust_type == "usize" || rust_type == "isize";
15811615
}
15821616

1583-
std::optional<clang::QualType>
1584-
GetOperandImplicitConversionTarget(const clang::BinaryOperator *op,
1585-
const clang::Expr *operand,
1586-
const clang::Expr *sibling) {
1617+
std::optional<clang::QualType> GetOperandImplicitConversionTarget(
1618+
clang::ASTContext &ctx, const clang::BinaryOperator *op,
1619+
const clang::Expr *operand, const clang::Expr *sibling) {
15871620
if (op->isComparisonOp()) {
1588-
if (NeedsImplicitScalarCast(operand->getType(), sibling->getType()) &&
1589-
IsSizeType(sibling->getType())) {
1621+
if (NeedsImplicitScalarCast(ctx, operand->getType(), sibling->getType()) &&
1622+
IsSizeType(ctx, sibling->getType())) {
15901623
return sibling->getType();
15911624
}
15921625
return std::nullopt;
15931626
}
15941627
if ((op->isAdditiveOp() || op->isMultiplicativeOp() || op->isBitwiseOp()) &&
1595-
NeedsImplicitScalarCast(operand->getType(), op->getType())) {
1628+
NeedsImplicitScalarCast(ctx, operand->getType(), op->getType())) {
15961629
return op->getType();
15971630
}
15981631
return std::nullopt;

‎cpp2rust/converter/converter_lib.h‎

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ enum class IteratorCategory {
3535
};
3636

3737
std::optional<IteratorCategory>
38-
GetStrongestIteratorCategory(clang::QualType type);
38+
GetStrongestIteratorCategory(clang::ASTContext &ctx, clang::QualType type);
3939
bool IsBuiltinConstantP(const clang::Expr *expr);
4040

4141
bool IsGlobalVar(const clang::VarDecl *decl);
@@ -169,6 +169,11 @@ std::string GetNamedDeclAsString(const clang::NamedDecl *decl);
169169

170170
std::string DisambiguateAnonymousTag(const clang::TagDecl *tag);
171171

172+
clang::QualType GetTypeForDecl(clang::ASTContext &ctx,
173+
const clang::NamedDecl *decl);
174+
175+
bool HasFunctionParameterPack(const clang::FunctionDecl *decl);
176+
172177
const char *AccessSpecifierAsString(clang::AccessSpecifier spec);
173178

174179
template <class T> llvm::SmallString<16> GetNumAsString(const T &num) {
@@ -272,16 +277,17 @@ std::string GetClassName(clang::QualType type);
272277

273278
bool IsVaListType(clang::QualType type);
274279

275-
bool NeedsImplicitScalarCast(clang::QualType from, clang::QualType to);
280+
bool NeedsImplicitScalarCast(clang::ASTContext &ctx, clang::QualType from,
281+
clang::QualType to);
276282

277-
bool NeedsRefBindingTemp(const clang::Expr *arg, clang::QualType param_type);
283+
bool NeedsRefBindingTemp(clang::ASTContext &ctx, const clang::Expr *arg,
284+
clang::QualType param_type);
278285

279-
bool IsSizeType(clang::QualType type);
286+
bool IsSizeType(clang::ASTContext &ctx, clang::QualType type);
280287

281-
std::optional<clang::QualType>
282-
GetOperandImplicitConversionTarget(const clang::BinaryOperator *op,
283-
const clang::Expr *operand,
284-
const clang::Expr *sibling);
288+
std::optional<clang::QualType> GetOperandImplicitConversionTarget(
289+
clang::ASTContext &ctx, const clang::BinaryOperator *op,
290+
const clang::Expr *operand, const clang::Expr *sibling);
285291

286292
bool IsBuiltinVaStart(const clang::CallExpr *expr);
287293

‎cpp2rust/converter/factory.cpp‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33

44
#include "converter/factory.h"
55

6-
#include "converter/mapper.h"
76
#include "converter/models/converter_refcount.h"
7+
#include "converter/rules/registry.h"
88

99
namespace cpp2rust {
1010

1111
std::unique_ptr<Converter> CreateConverter(std::string &rs_code,
1212
clang::ASTContext &ctx, Model model,
1313
const std::string &rules_dir) {
14-
Mapper::LoadTranslationRules(model, ctx, rules_dir);
14+
RuleRegistry::Load(model, rules_dir);
1515
switch (model) {
1616
case Model::kUnsafe:
1717
return std::make_unique<Converter>(rs_code, ctx);

0 commit comments

Comments
 (0)