Skip to content

Commit 21e51a4

Browse files
authored
Stop masking NTTP arguments (#534)
Closes #435
1 parent 79910b3 commit 21e51a4

22 files changed

Lines changed: 544 additions & 142 deletions

‎cpp2rust/converter/converter.cpp‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,28 @@ std::string Converter::GetUnboxedTypeAsString(clang::QualType qual_type) {
139139
return ToString(qual_type);
140140
}
141141

142+
std::string
143+
Converter::GetTemplateArgumentAsString(const clang::TemplateArgument &arg) {
144+
switch (arg.getKind()) {
145+
case clang::TemplateArgument::Type:
146+
return GetUnboxedTypeAsString(arg.getAsType());
147+
case clang::TemplateArgument::Integral:
148+
case clang::TemplateArgument::NullPtr:
149+
case clang::TemplateArgument::Declaration:
150+
case clang::TemplateArgument::StructuralValue: {
151+
auto expr = GetSema().BuildExpressionFromNonTypeTemplateArgument(
152+
arg, clang::SourceLocation());
153+
assert(expr.isUsable() && "cannot build non-type template argument");
154+
Buffer buf(*this);
155+
Convert(expr.get());
156+
return std::move(buf).str();
157+
}
158+
default:
159+
assert(0 && "template parameter is not bound to a type or a value");
160+
return {};
161+
}
162+
}
163+
142164
bool Converter::ConvertMappedType(clang::QualType qual_type) {
143165
std::string type_as_string = Mapper::Map(*this, qual_type);
144166
if (type_as_string == token::kIgnoreRule) {
@@ -747,6 +769,10 @@ bool Converter::IsPassThroughRule(clang::Expr *expr) const {
747769
}
748770

749771
bool Converter::RecordDerivesCopy(const clang::RecordDecl *decl) {
772+
if (auto cxx = llvm::dyn_cast<clang::CXXRecordDecl>(decl);
773+
cxx && cxx->isLambda()) {
774+
return false;
775+
}
750776
if (auto rule =
751777
RuleRegistry::Search(ctx_, ctx_.getCanonicalTagType(decl)).first) {
752778
auto &derives = rule->type_info.derives;

‎cpp2rust/converter/converter.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
6363

6464
virtual std::string GetUnboxedTypeAsString(clang::QualType qual_type);
6565

66+
std::string GetTemplateArgumentAsString(const clang::TemplateArgument &arg);
67+
6668
bool VisitRecoveryExpr(clang::RecoveryExpr *expr);
6769

6870
virtual void EmitFilePreamble();

‎cpp2rust/converter/printer.cpp‎

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@
88
#include <clang/Basic/SourceManager.h>
99
#include <clang/Lex/Lexer.h>
1010

11-
#include <array>
1211
#include <cctype>
1312
#include <format>
14-
#include <regex>
1513
#include <string_view>
1614
#include <utility>
1715

@@ -78,24 +76,6 @@ clang::QualType normalizeQualType(clang::ASTContext &ctx,
7876
ctx);
7977
}
8078

81-
std::string normalizeTranslationRule(std::string rule) {
82-
// Detach pointer from double reference. Useful for matching translation
83-
// rules.
84-
ReplaceAll(rule, "*&&", "* &&");
85-
86-
static const std::array<std::pair<std::regex, std::string>, 1>
87-
normalization_rules{{
88-
// Ignore constant template parameters, i.e. replace them with _.
89-
{std::regex(R"(\b\d+\b)"), "_"},
90-
}};
91-
92-
for (const auto &r : normalization_rules) {
93-
rule = std::regex_replace(rule, r.first, r.second);
94-
}
95-
96-
return rule;
97-
}
98-
9979
} // namespace
10080

10181
std::string ToRustName(std::string name) {
@@ -171,7 +151,7 @@ std::string ToString(clang::ASTContext &ctx, clang::QualType qual_type,
171151
std::string out;
172152
llvm::raw_string_ostream os(out);
173153
ctx.getPointerType(pointee).print(os, getPrintPolicy(ctx));
174-
return normalizeTranslationRule(std::move(out));
154+
return out;
175155
}
176156
}
177157

@@ -200,7 +180,7 @@ std::string ToString(clang::ASTContext &ctx, clang::QualType qual_type,
200180
std::string type;
201181
llvm::raw_string_ostream os(type);
202182
normalizeQualType(ctx, qual_type).print(os, getPrintPolicy(ctx));
203-
return normalizeTranslationRule(std::move(type));
183+
return type;
204184
}
205185

206186
std::string ToString(clang::ASTContext &ctx, const clang::NamedDecl *decl) {
@@ -237,7 +217,7 @@ std::string ToString(clang::ASTContext &ctx, const clang::NamedDecl *decl) {
237217

238218
if (!func_decl) {
239219
decl->printQualifiedName(os, getPrintPolicy(ctx));
240-
return normalizeTranslationRule(std::move(out));
220+
return out;
241221
}
242222

243223
os << ToString(ctx, func_decl->getReturnType()) << ' ';
@@ -324,7 +304,7 @@ std::string ToString(clang::ASTContext &ctx, const clang::NamedDecl *decl) {
324304
}
325305
}
326306

327-
return normalizeTranslationRule(std::move(out));
307+
return out;
328308
}
329309

330310
std::string ToString(clang::ASTContext &ctx, const clang::Expr *expr) {

‎cpp2rust/converter/rules/matcher.cpp‎

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,20 @@ namespace cpp2rust::Matcher {
1212

1313
std::string MapBinding(Converter &converter, const Bindings &bindings,
1414
unsigned n) {
15-
auto type = bindings.at(n);
16-
assert(!type.isNull() && "template parameter is not bound to a type");
17-
return converter.GetUnboxedTypeAsString(type);
15+
return converter.GetTemplateArgumentAsString(bindings.at(n));
1816
}
1917

20-
// Substitutes concrete types into a target template string using the provided
21-
// type mapping. Each template parameter in `tgt_template` is replaced with its
22-
// corresponding instantiated type from `types`.
18+
// Substitutes template arguments into a target template string. Each template
19+
// parameter in `tgt_template` is replaced with its corresponding argument from
20+
// `bindings`, which is either a type or a value.
2321
//
2422
// Example:
25-
// types = { int }
26-
// tgt_template = "Vec<T1>"
27-
// result = "Vec<i32>"
28-
std::string InstantiateTgt(Converter &converter, const Bindings &types,
23+
// bindings = { int, 4 }
24+
// tgt_template = "[T1; T2]"
25+
// result = "[i32; 4_usize]"
26+
std::string InstantiateTgt(Converter &converter, const Bindings &bindings,
2927
const std::string &tgt_template) {
30-
assert(types.size() <= TranslationRule::kMaxGenerics &&
28+
assert(bindings.size() <= TranslationRule::kMaxGenerics &&
3129
"template placeholder exceeds kMaxGenerics");
3230
std::string instantiated_template = tgt_template;
3331
std::string::size_type pos = 0;
@@ -40,7 +38,7 @@ std::string InstantiateTgt(Converter &converter, const Bindings &types,
4038
continue;
4139
}
4240
auto repl =
43-
MapBinding(converter, types, instantiated_template[pos + 1] - '1');
41+
MapBinding(converter, bindings, instantiated_template[pos + 1] - '1');
4442
instantiated_template.replace(pos, 2, repl);
4543
pos += repl.length();
4644
}

‎cpp2rust/converter/rules/matcher.h‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#include <clang/AST/ASTContext.h>
77
#include <clang/AST/Decl.h>
88
#include <clang/AST/Expr.h>
9-
#include <clang/AST/Type.h>
9+
#include <clang/AST/TemplateBase.h>
1010

1111
#include <string>
1212
#include <utility>
@@ -19,13 +19,13 @@ class Converter;
1919
}
2020

2121
namespace cpp2rust::Matcher {
22-
using Bindings = std::vector<clang::QualType>;
22+
using Bindings = std::vector<clang::TemplateArgument>;
2323

2424
template <typename Rule> using Match = std::pair<Rule *, Bindings>;
2525

2626
std::string MapBinding(Converter &converter, const Bindings &bindings,
2727
unsigned n);
2828

29-
std::string InstantiateTgt(Converter &converter, const Bindings &types,
29+
std::string InstantiateTgt(Converter &converter, const Bindings &bindings,
3030
const std::string &tgt_template);
3131
} // namespace cpp2rust::Matcher

‎cpp2rust/converter/rules/registry.cpp‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,11 +265,11 @@ Matcher::Bindings getBindings(const clang::NamedDecl *rule,
265265
auto name = params->getParam(i)->getName();
266266
unsigned n = 0;
267267
if (!name.consume_front("T") || name.getAsInteger(10, n) ||
268-
args[i].getKind() != clang::TemplateArgument::Type) {
268+
args[i].getKind() == clang::TemplateArgument::Pack) {
269269
continue;
270270
}
271271
bindings.resize(std::max<size_t>(bindings.size(), n));
272-
bindings[n - 1] = args[i].getAsType();
272+
bindings[n - 1] = args[i];
273273
}
274274
return bindings;
275275
}

‎cpp2rust/converter/rules/rules_loader.cpp‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@ class RuleUsageCollector
237237
case clang::TemplateArgument::Null:
238238
case clang::TemplateArgument::Integral:
239239
case clang::TemplateArgument::NullPtr:
240+
case clang::TemplateArgument::Declaration:
241+
case clang::TemplateArgument::StructuralValue:
240242
case clang::TemplateArgument::Expression:
241243
case clang::TemplateArgument::Template:
242244
break;

‎rules/pair/src.cpp‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,19 @@ template <typename T1, typename T2> const T2 &f15(const std::pair<T1, T2> &a0) {
4848
template <typename T1, typename T2> const T1 &f16(const std::pair<T1, T2> &a0) {
4949
return a0.first;
5050
}
51+
52+
template <typename T1, typename T2> T1 &f17(std::pair<T1, T2> &a0) {
53+
return std::get<0>(a0);
54+
}
55+
56+
template <typename T1, typename T2> T2 &f18(std::pair<T1, T2> &a0) {
57+
return std::get<1>(a0);
58+
}
59+
60+
template <typename T1, typename T2> const T1 &f19(const std::pair<T1, T2> &a0) {
61+
return std::get<0>(a0);
62+
}
63+
64+
template <typename T1, typename T2> const T2 &f20(const std::pair<T1, T2> &a0) {
65+
return std::get<1>(a0);
66+
}

‎rules/pair/tgt_refcount.rs‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,19 @@ fn f15<T1, T2>(a0: (Value<T1>, Value<T2>)) -> Value<T2> {
6868
fn f16<T1, T2>(a0: (Value<T1>, Value<T2>)) -> Value<T1> {
6969
a0.0
7070
}
71+
72+
fn f17<T1, T2>(a0: (Value<T1>, Value<T2>)) -> Ptr<T1> {
73+
a0.0.as_pointer()
74+
}
75+
76+
fn f18<T1, T2>(a0: (Value<T1>, Value<T2>)) -> Ptr<T2> {
77+
a0.1.as_pointer()
78+
}
79+
80+
fn f19<T1, T2>(a0: (Value<T1>, Value<T2>)) -> Ptr<T1> {
81+
a0.0.as_pointer()
82+
}
83+
84+
fn f20<T1, T2>(a0: (Value<T1>, Value<T2>)) -> Ptr<T2> {
85+
a0.1.as_pointer()
86+
}

‎rules/pair/tgt_unsafe.rs‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,19 @@ unsafe fn f15<T1, T2>(a0: (T1, T2)) -> T2 {
3737
unsafe fn f16<T1, T2>(a0: (T1, T2)) -> T1 {
3838
a0.0
3939
}
40+
41+
unsafe fn f17<T1, T2>(a0: &mut (T1, T2)) -> *mut T1 {
42+
&mut a0.0
43+
}
44+
45+
unsafe fn f18<T1, T2>(a0: &mut (T1, T2)) -> *mut T2 {
46+
&mut a0.1
47+
}
48+
49+
unsafe fn f19<T1, T2>(a0: &(T1, T2)) -> *const T1 {
50+
&a0.0
51+
}
52+
53+
unsafe fn f20<T1, T2>(a0: &(T1, T2)) -> *const T2 {
54+
&a0.1
55+
}

0 commit comments

Comments
 (0)