Skip to content

Commit b111cbc

Browse files
committed
Mangle overloaded methods
1 parent 360a2a5 commit b111cbc

8 files changed

Lines changed: 316 additions & 3 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3798,8 +3798,39 @@ Converter::GetOverloadedFunctionName(const clang::FunctionDecl *decl) {
37983798
name += '_';
37993799
}
38003800

3801+
if (const auto *targs = decl->getTemplateSpecializationArgs()) {
3802+
std::vector<clang::TemplateArgument> args;
3803+
for (const auto &arg : targs->asArray()) {
3804+
if (arg.getKind() == clang::TemplateArgument::Pack) {
3805+
args.insert(args.end(), arg.pack_begin(), arg.pack_end());
3806+
} else {
3807+
args.push_back(arg);
3808+
}
3809+
}
3810+
for (const auto &arg : args) {
3811+
name += '_';
3812+
switch (arg.getKind()) {
3813+
case clang::TemplateArgument::Type:
3814+
name += Mapper::ToRustName(
3815+
arg.getAsType().getCanonicalType().getAsString());
3816+
break;
3817+
case clang::TemplateArgument::Integral:
3818+
name += Mapper::ToRustName(
3819+
std::string(GetNumAsString(arg.getAsIntegral())));
3820+
break;
3821+
default:
3822+
name += "targ";
3823+
break;
3824+
}
3825+
}
3826+
}
3827+
38013828
auto pred = [](char ch) { return ch != ' ' && ch != '_'; };
38023829
name.erase(std::find_if(name.rbegin(), name.rend(), pred).base(), name.end());
3830+
3831+
if (decl->isVariadic()) {
3832+
name += "_va";
3833+
}
38033834
if (const auto *method = clang::dyn_cast<clang::CXXMethodDecl>(decl)) {
38043835
if (method->isConst()) {
38053836
name += "_const";
@@ -3819,6 +3850,9 @@ Converter::GetOverloadedFunctionName(const clang::FunctionDecl *decl) {
38193850
}
38203851
}
38213852

3853+
ReplaceAll(name, "[", "arr");
3854+
ReplaceAll(name, "]", "arr");
3855+
ReplaceAll(name, ";", "_");
38223856
name.erase(std::remove_if(name.begin(), name.end(),
38233857
[](char c) {
38243858
return c == '<' || c == '>' || c == ' ' ||
@@ -4111,15 +4145,19 @@ void Converter::ConvertCXXMethodDecls(
41114145
const clang::CXXRecordDecl *decl, const std::string_view signature,
41124146
bool (*predicate)(clang::CXXMethodDecl *)) {
41134147
bool first = true;
4114-
for (auto *method : decl->methods()) {
4148+
auto convert_method = [&](clang::CXXMethodDecl *method) {
41154149
if (predicate(method)) {
41164150
if (first) {
41174151
StrCat(signature, token::kOpenCurlyBracket);
41184152
first = false;
41194153
}
41204154
VisitCXXMethodDecl(method);
41214155
}
4156+
};
4157+
for (auto *method : decl->methods()) {
4158+
convert_method(method);
41224159
}
4160+
ForEachTemplateInstantiatedMethod(decl, convert_method);
41234161
if (!first) {
41244162
StrCat(token::kCloseCurlyBracket);
41254163
}

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33

44
#include "converter/converter_lib.h"
55

6+
#include <clang/AST/DeclTemplate.h>
67
#include <clang/AST/ExprCXX.h>
78
#include <clang/AST/Mangle.h>
89
#include <clang/AST/ParentMapContext.h>
910
#include <clang/Basic/SourceManager.h>
1011
#include <llvm/Support/Path.h>
12+
#include <llvm/Support/raw_ostream.h>
1113

1214
#include <algorithm>
1315
#include <array>
@@ -249,7 +251,28 @@ bool IsOverloadedFunction(const clang::FunctionDecl *decl) {
249251
return !lookup_result.isSingleResult();
250252
}
251253

254+
void ForEachTemplateInstantiatedMethod(
255+
const clang::CXXRecordDecl *decl,
256+
llvm::function_ref<void(clang::CXXMethodDecl *)> fn) {
257+
for (auto d : decl->decls()) {
258+
if (auto function_template_decl =
259+
llvm::dyn_cast<clang::FunctionTemplateDecl>(d)) {
260+
for (auto s : function_template_decl->specializations()) {
261+
if (auto m = clang::dyn_cast<clang::CXXMethodDecl>(s);
262+
m && !clang::isa<clang::CXXConstructorDecl>(m) &&
263+
m->getDefinition()) {
264+
fn(m);
265+
}
266+
}
267+
}
268+
}
269+
}
270+
252271
bool IsOverloadedMethod(const clang::CXXMethodDecl *decl) {
272+
if (decl->getTemplateSpecializationArgs() != nullptr &&
273+
IsUserDefinedDecl(decl)) {
274+
return true;
275+
}
253276
const auto method_name = decl->getNameAsString();
254277
const auto *record = decl->getParent();
255278
return std::count_if(record->method_begin(), record->method_end(),
@@ -502,6 +525,11 @@ static std::string GetParamSignature(const clang::Decl *decl) {
502525
for (unsigned i = 0; i < fdecl->getNumParams(); ++i) {
503526
args += fdecl->getParamDecl(i)->getType().getAsString();
504527
}
528+
if (const auto *targs = fdecl->getTemplateSpecializationArgs()) {
529+
llvm::raw_string_ostream os(args);
530+
clang::printTemplateArgumentList(
531+
os, targs->asArray(), fdecl->getASTContext().getPrintingPolicy());
532+
}
505533
}
506534
return args;
507535
}

‎cpp2rust/converter/converter_lib.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <clang/AST/Expr.h>
1010
#include <clang/AST/StmtCXX.h>
1111
#include <clang/AST/Type.h>
12+
#include <llvm/ADT/STLFunctionalExtras.h>
1213

1314
#include <optional>
1415
#include <string>
@@ -61,6 +62,10 @@ bool IsMutatingCall(const clang::CallExpr *expr);
6162

6263
bool IsOverloadedFunction(const clang::FunctionDecl *decl);
6364

65+
void ForEachTemplateInstantiatedMethod(
66+
const clang::CXXRecordDecl *decl,
67+
llvm::function_ref<void(clang::CXXMethodDecl *)> fn);
68+
6469
bool IsOverloadedMethod(const clang::CXXMethodDecl *decl);
6570

6671
bool IsUserDefinedCopyConstructor(const clang::CXXConstructorDecl *ctor);

‎cpp2rust/converter/mapper.cpp‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <clang/Lex/Lexer.h>
1010
#include <llvm/Support/ThreadPool.h>
1111

12+
#include <cctype>
1213
#include <cstdlib>
1314
#include <format>
1415
#include <optional>
@@ -834,6 +835,16 @@ std::string ToRustName(std::string name) {
834835
++pos;
835836
}
836837
ReplaceAll(name, "::", "_");
838+
ReplaceAll(name, "*", "ptr");
839+
ReplaceAll(name, "&", "ref");
840+
ReplaceAll(name, "[", "arr");
841+
ReplaceAll(name, "]", "arr");
842+
ReplaceAll(name, "-", "neg");
843+
for (auto &c : name) {
844+
if (!std::isalnum(static_cast<unsigned char>(c)) && c != '_') {
845+
c = '_';
846+
}
847+
}
837848
return name;
838849
}
839850

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2734,12 +2734,16 @@ void ConverterRefCount::ConvertLateInstantiatedMethods(
27342734
!IsMethodOnPtr(method) &&
27352735
!decl_ids_.contains(GetMethodID(method));
27362736
});
2737-
for (auto *method : decl->methods()) {
2737+
auto convert_method = [&](clang::CXXMethodDecl *method) {
27382738
if (IsEmittableMethod(method) && method->hasBody() &&
27392739
IsMethodOnPtr(method) && !decl_ids_.contains(GetMethodID(method))) {
27402740
ConvertMethodOnPtr(method);
27412741
}
2742+
};
2743+
for (auto *method : decl->methods()) {
2744+
convert_method(method);
27422745
}
2746+
ForEachTemplateInstantiatedMethod(decl, convert_method);
27432747
}
27442748

27452749
void ConverterRefCount::ConvertCXXRecordMethods(clang::CXXRecordDecl *decl) {
@@ -2751,11 +2755,15 @@ void ConverterRefCount::ConvertCXXRecordMethods(clang::CXXRecordDecl *decl) {
27512755
!IsMethodOnPtr(method);
27522756
});
27532757

2754-
for (auto *method : decl->methods()) {
2758+
auto convert_method = [&](clang::CXXMethodDecl *method) {
27552759
if (IsMethodOnPtr(method) && method->getDefinition()) {
27562760
ConvertMethodOnPtr(method);
27572761
}
2762+
};
2763+
for (auto *method : decl->methods()) {
2764+
convert_method(method);
27582765
}
2766+
ForEachTemplateInstantiatedMethod(decl, convert_method);
27592767

27602768
if (!GetUserDefinedDestructor(decl) && HasFieldsNeedingDestruction(decl)) {
27612769
MethodsOnPtrFor(decl).trait_body +=
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
extern crate libcc2rs;
2+
use libcc2rs::*;
3+
use std::cell::RefCell;
4+
use std::collections::BTreeMap;
5+
use std::io::prelude::*;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::AsFd;
8+
use std::rc::{Rc, Weak};
9+
#[derive(Default)]
10+
pub struct S {
11+
pub base: Value<i32>,
12+
}
13+
impl Clone for S {
14+
fn clone(&self) -> Self {
15+
let __this: Value<S> = Rc::new(RefCell::new(Self {
16+
base: Rc::new(RefCell::new((*self.base.borrow()))),
17+
}));
18+
let this: Ptr<S> = __this.as_pointer();
19+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
20+
}
21+
}
22+
impl ByteRepr for S {
23+
fn byte_size() -> usize {
24+
4
25+
}
26+
fn to_bytes(&self, buf: &mut [u8]) {
27+
(*self.base.borrow()).to_bytes(&mut buf[0..4]);
28+
}
29+
fn from_bytes(buf: &[u8]) -> Self {
30+
Self {
31+
base: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
32+
}
33+
}
34+
}
35+
#[derive(Default)]
36+
pub struct Box {
37+
pub v: Value<i32>,
38+
}
39+
impl Clone for Box {
40+
fn clone(&self) -> Self {
41+
let __this: Value<Box> = Rc::new(RefCell::new(Self {
42+
v: Rc::new(RefCell::new((*self.v.borrow()))),
43+
}));
44+
let this: Ptr<Box> = __this.as_pointer();
45+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
46+
}
47+
}
48+
impl ByteRepr for Box {
49+
fn byte_size() -> usize {
50+
4
51+
}
52+
fn to_bytes(&self, buf: &mut [u8]) {
53+
(*self.v.borrow()).to_bytes(&mut buf[0..4]);
54+
}
55+
fn from_bytes(buf: &[u8]) -> Self {
56+
Self {
57+
v: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
58+
}
59+
}
60+
}
61+
pub fn main() {
62+
std::process::exit(main_0());
63+
}
64+
fn main_0() -> i32 {
65+
let s: Value<S> = Rc::new(RefCell::new(S {
66+
base: Rc::new(RefCell::new(100)),
67+
}));
68+
assert!((({ SImpl::width_i32__char_const(&s.as_pointer(), 3,) }) == 103));
69+
assert!((({ SImpl::width_i32__int_const(&s.as_pointer(), 3,) }) == 112));
70+
assert!((({ SImpl::scale_i32__2_const(&s.as_pointer(), 5,) }) == 110));
71+
assert!((({ SImpl::scale_i32__3_const(&s.as_pointer(), 5,) }) == 115));
72+
assert!((({ SImpl::count_i32_const(&s.as_pointer(), 1,) }) == 101));
73+
assert!((({ SImpl::count_i32__int_long_const(&s.as_pointer(), 1,) }) == 103));
74+
assert!((({ SImpl::plain_i32_const(&s.as_pointer(), 1,) }) == 101));
75+
assert!((({ SImpl::plain_i64_const(&s.as_pointer(), 1_i64,) }) == 102));
76+
let b: Value<Box> = Rc::new(RefCell::new(Box {
77+
v: Rc::new(RefCell::new(4)),
78+
}));
79+
assert!(((*(*b.borrow()).v.borrow()) == 4));
80+
return 0;
81+
}
82+
pub trait SImpl {
83+
fn plain_i32_const(&self, x: i32) -> i32;
84+
fn plain_i64_const(&self, x: i64) -> i32;
85+
fn width_i32__char_const(&self, x: i32) -> i32;
86+
fn width_i32__int_const(&self, x: i32) -> i32;
87+
fn scale_i32__2_const(&self, x: i32) -> i32;
88+
fn scale_i32__3_const(&self, x: i32) -> i32;
89+
fn count_i32_const(&self, x: i32) -> i32;
90+
fn count_i32__int_long_const(&self, x: i32) -> i32;
91+
}
92+
impl SImpl for Ptr<S> {
93+
fn plain_i32_const(&self, x: i32) -> i32 {
94+
let x: Value<i32> = Rc::new(RefCell::new(x));
95+
return ((*(*(*self).upgrade().deref()).base.borrow()) + (*x.borrow()));
96+
}
97+
fn plain_i64_const(&self, x: i64) -> i32 {
98+
let x: Value<i64> = Rc::new(RefCell::new(x));
99+
return (((*(*(*self).upgrade().deref()).base.borrow()) + ((*x.borrow()) as i32)) + 1);
100+
}
101+
fn width_i32__char_const(&self, x: i32) -> i32 {
102+
let x: Value<i32> = Rc::new(RefCell::new(x));
103+
return ((*(*(*self).upgrade().deref()).base.borrow())
104+
+ ((*x.borrow()) * (::std::mem::size_of::<u8>() as i32)));
105+
}
106+
fn width_i32__int_const(&self, x: i32) -> i32 {
107+
let x: Value<i32> = Rc::new(RefCell::new(x));
108+
return ((*(*(*self).upgrade().deref()).base.borrow())
109+
+ ((*x.borrow()) * (::std::mem::size_of::<i32>() as i32)));
110+
}
111+
fn scale_i32__2_const(&self, x: i32) -> i32 {
112+
let x: Value<i32> = Rc::new(RefCell::new(x));
113+
return ((*(*(*self).upgrade().deref()).base.borrow()) + ((*x.borrow()) * 2));
114+
}
115+
fn scale_i32__3_const(&self, x: i32) -> i32 {
116+
let x: Value<i32> = Rc::new(RefCell::new(x));
117+
return ((*(*(*self).upgrade().deref()).base.borrow()) + ((*x.borrow()) * 3));
118+
}
119+
fn count_i32_const(&self, x: i32) -> i32 {
120+
let x: Value<i32> = Rc::new(RefCell::new(x));
121+
return (((*(*(*self).upgrade().deref()).base.borrow()) + (*x.borrow())) + (0 as i32));
122+
}
123+
fn count_i32__int_long_const(&self, x: i32) -> i32 {
124+
let x: Value<i32> = Rc::new(RefCell::new(x));
125+
return (((*(*(*self).upgrade().deref()).base.borrow()) + (*x.borrow())) + (2 as i32));
126+
}
127+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
extern crate libc;
2+
use libc::*;
3+
extern crate libcc2rs;
4+
use libcc2rs::*;
5+
use std::collections::BTreeMap;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
8+
use std::rc::Rc;
9+
#[repr(C)]
10+
#[derive(Copy, Clone, Default)]
11+
pub struct S {
12+
pub base: i32,
13+
}
14+
impl S {
15+
pub unsafe fn plain_i32_const(&self, mut x: i32) -> i32 {
16+
return ((self.base) + (x));
17+
}
18+
pub unsafe fn plain_i64_const(&self, mut x: i64) -> i32 {
19+
return (((self.base) + (x as i32)) + (1));
20+
}
21+
pub unsafe fn width_i32__char_const(&self, mut x: i32) -> i32 {
22+
return ((self.base) + ((x) * (::std::mem::size_of::<libc::c_char>() as i32)));
23+
}
24+
pub unsafe fn width_i32__int_const(&self, mut x: i32) -> i32 {
25+
return ((self.base) + ((x) * (::std::mem::size_of::<i32>() as i32)));
26+
}
27+
pub unsafe fn scale_i32__2_const(&self, mut x: i32) -> i32 {
28+
return ((self.base) + ((x) * (2)));
29+
}
30+
pub unsafe fn scale_i32__3_const(&self, mut x: i32) -> i32 {
31+
return ((self.base) + ((x) * (3)));
32+
}
33+
pub unsafe fn count_i32_const(&self, mut x: i32) -> i32 {
34+
return (((self.base) + (x)) + (0 as i32));
35+
}
36+
pub unsafe fn count_i32__int_long_const(&self, mut x: i32) -> i32 {
37+
return (((self.base) + (x)) + (2 as i32));
38+
}
39+
}
40+
#[repr(C)]
41+
#[derive(Copy, Clone, Default)]
42+
pub struct Box {
43+
pub v: i32,
44+
}
45+
pub fn main() {
46+
unsafe {
47+
std::process::exit(main_0() as i32);
48+
}
49+
}
50+
unsafe fn main_0() -> i32 {
51+
let mut s: S = S { base: 100 };
52+
assert!(((unsafe { S::width_i32__char_const(&s, 3,) }) == (103)));
53+
assert!(((unsafe { S::width_i32__int_const(&s, 3,) }) == (112)));
54+
assert!(((unsafe { S::scale_i32__2_const(&s, 5,) }) == (110)));
55+
assert!(((unsafe { S::scale_i32__3_const(&s, 5,) }) == (115)));
56+
assert!(((unsafe { S::count_i32_const(&s, 1,) }) == (101)));
57+
assert!(((unsafe { S::count_i32__int_long_const(&s, 1,) }) == (103)));
58+
assert!(((unsafe { S::plain_i32_const(&s, 1,) }) == (101)));
59+
assert!(((unsafe { S::plain_i64_const(&s, 1_i64,) }) == (102)));
60+
let mut b: Box = Box { v: 4 };
61+
assert!(((b.v) == (4)));
62+
return 0;
63+
}

0 commit comments

Comments
 (0)