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
26 changes: 26 additions & 0 deletions cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,28 @@ std::string Converter::GetUnboxedTypeAsString(clang::QualType qual_type) {
return ToString(qual_type);
}

std::string
Converter::GetTemplateArgumentAsString(const clang::TemplateArgument &arg) {
switch (arg.getKind()) {
case clang::TemplateArgument::Type:
return GetUnboxedTypeAsString(arg.getAsType());
case clang::TemplateArgument::Integral:
case clang::TemplateArgument::NullPtr:
case clang::TemplateArgument::Declaration:
case clang::TemplateArgument::StructuralValue: {
auto expr = GetSema().BuildExpressionFromNonTypeTemplateArgument(
arg, clang::SourceLocation());
assert(expr.isUsable() && "cannot build non-type template argument");
Buffer buf(*this);
Convert(expr.get());
return std::move(buf).str();
}
default:
assert(0 && "template parameter is not bound to a type or a value");
return {};
}
}

bool Converter::ConvertMappedType(clang::QualType qual_type) {
std::string type_as_string = Mapper::Map(*this, qual_type);
if (type_as_string == token::kIgnoreRule) {
Expand Down Expand Up @@ -747,6 +769,10 @@ bool Converter::IsPassThroughRule(clang::Expr *expr) const {
}

bool Converter::RecordDerivesCopy(const clang::RecordDecl *decl) {
if (auto cxx = llvm::dyn_cast<clang::CXXRecordDecl>(decl);
cxx && cxx->isLambda()) {
return false;
}
if (auto rule =
RuleRegistry::Search(ctx_, ctx_.getCanonicalTagType(decl)).first) {
auto &derives = rule->type_info.derives;
Expand Down
2 changes: 2 additions & 0 deletions cpp2rust/converter/converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {

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

std::string GetTemplateArgumentAsString(const clang::TemplateArgument &arg);

bool VisitRecoveryExpr(clang::RecoveryExpr *expr);

virtual void EmitFilePreamble();
Expand Down
28 changes: 4 additions & 24 deletions cpp2rust/converter/printer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@
#include <clang/Basic/SourceManager.h>
#include <clang/Lex/Lexer.h>

#include <array>
#include <cctype>
#include <format>
#include <regex>
#include <string_view>
#include <utility>

Expand Down Expand Up @@ -78,24 +76,6 @@ clang::QualType normalizeQualType(clang::ASTContext &ctx,
ctx);
}

std::string normalizeTranslationRule(std::string rule) {
// Detach pointer from double reference. Useful for matching translation
// rules.
ReplaceAll(rule, "*&&", "* &&");

static const std::array<std::pair<std::regex, std::string>, 1>
normalization_rules{{
// Ignore constant template parameters, i.e. replace them with _.
{std::regex(R"(\b\d+\b)"), "_"},
}};

for (const auto &r : normalization_rules) {
rule = std::regex_replace(rule, r.first, r.second);
}

return rule;
}

} // namespace

std::string ToRustName(std::string name) {
Expand Down Expand Up @@ -171,7 +151,7 @@ std::string ToString(clang::ASTContext &ctx, clang::QualType qual_type,
std::string out;
llvm::raw_string_ostream os(out);
ctx.getPointerType(pointee).print(os, getPrintPolicy(ctx));
return normalizeTranslationRule(std::move(out));
return out;
}
}

Expand Down Expand Up @@ -200,7 +180,7 @@ std::string ToString(clang::ASTContext &ctx, clang::QualType qual_type,
std::string type;
llvm::raw_string_ostream os(type);
normalizeQualType(ctx, qual_type).print(os, getPrintPolicy(ctx));
return normalizeTranslationRule(std::move(type));
return type;
}

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

if (!func_decl) {
decl->printQualifiedName(os, getPrintPolicy(ctx));
return normalizeTranslationRule(std::move(out));
return out;
}

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

return normalizeTranslationRule(std::move(out));
return out;
}

std::string ToString(clang::ASTContext &ctx, const clang::Expr *expr) {
Expand Down
22 changes: 10 additions & 12 deletions cpp2rust/converter/rules/matcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,20 @@ namespace cpp2rust::Matcher {

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

// Substitutes concrete types into a target template string using the provided
// type mapping. Each template parameter in `tgt_template` is replaced with its
// corresponding instantiated type from `types`.
// Substitutes template arguments into a target template string. Each template
// parameter in `tgt_template` is replaced with its corresponding argument from
// `bindings`, which is either a type or a value.
//
// Example:
// types = { int }
// tgt_template = "Vec<T1>"
// result = "Vec<i32>"
std::string InstantiateTgt(Converter &converter, const Bindings &types,
// bindings = { int, 4 }
// tgt_template = "[T1; T2]"
// result = "[i32; 4_usize]"
std::string InstantiateTgt(Converter &converter, const Bindings &bindings,
const std::string &tgt_template) {
assert(types.size() <= TranslationRule::kMaxGenerics &&
assert(bindings.size() <= TranslationRule::kMaxGenerics &&
"template placeholder exceeds kMaxGenerics");
std::string instantiated_template = tgt_template;
std::string::size_type pos = 0;
Expand All @@ -40,7 +38,7 @@ std::string InstantiateTgt(Converter &converter, const Bindings &types,
continue;
}
auto repl =
MapBinding(converter, types, instantiated_template[pos + 1] - '1');
MapBinding(converter, bindings, instantiated_template[pos + 1] - '1');
instantiated_template.replace(pos, 2, repl);
pos += repl.length();
}
Expand Down
6 changes: 3 additions & 3 deletions cpp2rust/converter/rules/matcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <clang/AST/ASTContext.h>
#include <clang/AST/Decl.h>
#include <clang/AST/Expr.h>
#include <clang/AST/Type.h>
#include <clang/AST/TemplateBase.h>

#include <string>
#include <utility>
Expand All @@ -19,13 +19,13 @@ class Converter;
}

namespace cpp2rust::Matcher {
using Bindings = std::vector<clang::QualType>;
using Bindings = std::vector<clang::TemplateArgument>;

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

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

std::string InstantiateTgt(Converter &converter, const Bindings &types,
std::string InstantiateTgt(Converter &converter, const Bindings &bindings,
const std::string &tgt_template);
} // namespace cpp2rust::Matcher
4 changes: 2 additions & 2 deletions cpp2rust/converter/rules/registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,11 +265,11 @@ Matcher::Bindings getBindings(const clang::NamedDecl *rule,
auto name = params->getParam(i)->getName();
unsigned n = 0;
if (!name.consume_front("T") || name.getAsInteger(10, n) ||
args[i].getKind() != clang::TemplateArgument::Type) {
args[i].getKind() == clang::TemplateArgument::Pack) {
continue;
}
bindings.resize(std::max<size_t>(bindings.size(), n));
bindings[n - 1] = args[i].getAsType();
bindings[n - 1] = args[i];
}
return bindings;
}
Expand Down
2 changes: 2 additions & 0 deletions cpp2rust/converter/rules/rules_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@ class RuleUsageCollector
case clang::TemplateArgument::Null:
case clang::TemplateArgument::Integral:
case clang::TemplateArgument::NullPtr:
case clang::TemplateArgument::Declaration:
case clang::TemplateArgument::StructuralValue:
case clang::TemplateArgument::Expression:
case clang::TemplateArgument::Template:
break;
Expand Down
16 changes: 16 additions & 0 deletions rules/pair/src.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,19 @@ template <typename T1, typename T2> const T2 &f15(const std::pair<T1, T2> &a0) {
template <typename T1, typename T2> const T1 &f16(const std::pair<T1, T2> &a0) {
return a0.first;
}

template <typename T1, typename T2> T1 &f17(std::pair<T1, T2> &a0) {
return std::get<0>(a0);
}

template <typename T1, typename T2> T2 &f18(std::pair<T1, T2> &a0) {
return std::get<1>(a0);
}

template <typename T1, typename T2> const T1 &f19(const std::pair<T1, T2> &a0) {
return std::get<0>(a0);
}

template <typename T1, typename T2> const T2 &f20(const std::pair<T1, T2> &a0) {
return std::get<1>(a0);
}
16 changes: 16 additions & 0 deletions rules/pair/tgt_refcount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,19 @@ fn f15<T1, T2>(a0: (Value<T1>, Value<T2>)) -> Value<T2> {
fn f16<T1, T2>(a0: (Value<T1>, Value<T2>)) -> Value<T1> {
a0.0
}

fn f17<T1, T2>(a0: (Value<T1>, Value<T2>)) -> Ptr<T1> {
a0.0.as_pointer()
}

fn f18<T1, T2>(a0: (Value<T1>, Value<T2>)) -> Ptr<T2> {
a0.1.as_pointer()
}

fn f19<T1, T2>(a0: (Value<T1>, Value<T2>)) -> Ptr<T1> {
a0.0.as_pointer()
}

fn f20<T1, T2>(a0: (Value<T1>, Value<T2>)) -> Ptr<T2> {
a0.1.as_pointer()
}
16 changes: 16 additions & 0 deletions rules/pair/tgt_unsafe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,19 @@ unsafe fn f15<T1, T2>(a0: (T1, T2)) -> T2 {
unsafe fn f16<T1, T2>(a0: (T1, T2)) -> T1 {
a0.0
}

unsafe fn f17<T1, T2>(a0: &mut (T1, T2)) -> *mut T1 {
&mut a0.0
}

unsafe fn f18<T1, T2>(a0: &mut (T1, T2)) -> *mut T2 {
&mut a0.1
}

unsafe fn f19<T1, T2>(a0: &(T1, T2)) -> *const T1 {
&a0.0
}

unsafe fn f20<T1, T2>(a0: &(T1, T2)) -> *const T2 {
&a0.1
}
2 changes: 0 additions & 2 deletions tests/unit/lambda_as_field.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
// ADDITIONAL_COMPILE_FLAGS: -std=c++23
// no-compile
// Blocked by https://github.com/Cpp2Rust/cpp2rust/issues/435
#include <assert.h>
#include <utility>

Expand Down
2 changes: 0 additions & 2 deletions tests/unit/lambda_decltype_type.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
// ADDITIONAL_COMPILE_FLAGS: -std=c++23
// no-compile
// Blocked by https://github.com/Cpp2Rust/cpp2rust/issues/435
#include <assert.h>

template <typename Cmp> struct Sorted {
Expand Down
30 changes: 30 additions & 0 deletions tests/unit/nttp_distinct_specializations.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include <cassert>

template <int N> struct S {
int v;
int get() const { return v * N; }
};

template <> struct S<2> {
int v;
int w;
int get() const { return v - w; }
};

template <int N> int scale(int x) { return x * N; }

template <> int scale<2>(int x) { return x - 2; }

int main() {
S<1> s1{5};
S<2> s2{5, 1};
S<3> s3{5};
assert(s1.get() == 5);
assert(s2.get() == 4);
assert(s3.get() == 15);

assert(scale<1>(7) == 7);
assert(scale<2>(7) == 5);
assert(scale<3>(7) == 21);
return 0;
}
Loading
Loading