Skip to content

Commit 5cf9f0f

Browse files
authored
Fix operator name collisions (#307)
Changes how operators that are spelled using `<` or `>` are printed. Printing `<` or `>` collided with the search performed by `Mapper::matchTemplate`.
1 parent cf76c84 commit 5cf9f0f

7 files changed

Lines changed: 165 additions & 2 deletions

File tree

‎cpp2rust/converter/mapper.cpp‎

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "converter/mapper.h"
55

66
#include <clang/AST/ExprCXX.h>
7+
#include <clang/Basic/OperatorKinds.h>
78
#include <clang/Basic/SourceManager.h>
89
#include <clang/Lex/Lexer.h>
910
#include <llvm/Support/ThreadPool.h>
@@ -922,8 +923,30 @@ std::string ToString(const clang::NamedDecl *decl) {
922923
}
923924

924925
os << ToString(func_decl->getReturnType()) << ' ';
925-
if (const auto *method_decl =
926-
llvm::dyn_cast<clang::CXXMethodDecl>(func_decl)) {
926+
if (const auto op = func_decl->getOverloadedOperator();
927+
op >= clang::OverloadedOperatorKind::OO_LessLess &&
928+
op <= clang::OverloadedOperatorKind::OO_GreaterGreaterEqual) {
929+
// ensure matchTemplate does not consider these operator names when matching
930+
func_decl->getQualifier().print(os, getPrintPolicy());
931+
os << "operator ";
932+
switch (op) {
933+
case clang::OverloadedOperatorKind::OO_LessLess:
934+
os << "shl";
935+
break;
936+
case clang::OverloadedOperatorKind::OO_GreaterGreater:
937+
os << "shr";
938+
break;
939+
case clang::OverloadedOperatorKind::OO_LessLessEqual:
940+
os << "shleq";
941+
break;
942+
case clang::OverloadedOperatorKind::OO_GreaterGreaterEqual:
943+
os << "shreq";
944+
break;
945+
default:
946+
assert(0 && "Unexpected overloaded operator kind");
947+
}
948+
} else if (const auto *method_decl =
949+
llvm::dyn_cast<clang::CXXMethodDecl>(func_decl)) {
927950
if (method_decl->getParent()->isLambda() &&
928951
method_decl->getOverloadedOperator() == clang::OO_Call) {
929952
func_decl->printName(os, getPrintPolicy());

‎rules/cstddef/src.cpp‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright (c) 2022-present INESC-ID.
2+
// Distributed under the MIT license that can be found in the LICENSE file.
3+
4+
#include <cstddef>
5+
6+
using t1 = std::byte;
7+
8+
std::byte f1(const std::byte &a0, unsigned a1) { return operator<<(a0, a1); }
9+
10+
std::byte f2(const std::byte &a0, unsigned a1) { return operator>>(a0, a1); }
11+
12+
std::byte f3(std::byte &a0, unsigned a1) { return operator<<=(a0, a1); }
13+
14+
std::byte f4(std::byte &a0, unsigned a1) { return operator>>=(a0, a1); }

‎rules/cstddef/tgt_unsafe.rs‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright (c) 2022-present INESC-ID.
2+
// Distributed under the MIT license that can be found in the LICENSE file.
3+
4+
fn t1() -> u8 {
5+
Default::default()
6+
}
7+
8+
fn f1(a0: &mut u8, a1: u32) -> u8 {
9+
*a0 << a1
10+
}
11+
12+
fn f2(a0: &mut u8, a1: u32) -> u8 {
13+
*a0 >> a1
14+
}
15+
16+
fn f3(a0: &mut u8, a1: u32) -> u8 {
17+
let n_ = *a0 << a1;
18+
*a0 = n_;
19+
*a0
20+
}
21+
22+
fn f4(a0: &mut u8, a1: u32) -> u8 {
23+
let n_ = *a0 >> a1;
24+
*a0 = n_;
25+
*a0
26+
}

‎rules/src/modules.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ pub mod carray_tgt_refcount;
2828
pub mod carray_tgt_unsafe;
2929
#[path = r#"../cmath/tgt_unsafe.rs"#]
3030
pub mod cmath_tgt_unsafe;
31+
#[path = r#"../cstddef/tgt_unsafe.rs"#]
32+
pub mod cstddef_tgt_unsafe;
3133
#[path = r#"../cstdlib/tgt_refcount.rs"#]
3234
pub mod cstdlib_tgt_refcount;
3335
#[path = r#"../cstdlib/tgt_unsafe.rs"#]

‎tests/unit/byte.cpp‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright (c) 2022-present INESC-ID.
2+
// Distributed under the MIT license that can be found in the LICENSE file.
3+
4+
#include <cassert>
5+
#include <cstddef>
6+
7+
int main() {
8+
std::byte b1{0x01};
9+
10+
unsigned ushift1 = 3;
11+
std::byte shl1 = b1 << ushift1;
12+
assert(shl1 == std::byte(0x08));
13+
14+
unsigned ushift2 = 2;
15+
std::byte shr1 = shl1 >> ushift2;
16+
assert(shr1 == std::byte(0x02));
17+
18+
unsigned ushift3 = 5;
19+
b1 <<= ushift3;
20+
assert(b1 == std::byte(0x20));
21+
22+
unsigned ushift4 = 3;
23+
b1 >>= ushift4;
24+
assert(b1 == std::byte(0x04));
25+
return 0;
26+
}

‎tests/unit/out/refcount/byte.rs‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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+
pub fn main() {
10+
std::process::exit(main_0());
11+
}
12+
fn main_0() -> i32 {
13+
let b1: Value<u8> = Rc::new(RefCell::new(1_u8));
14+
let ushift1: Value<u32> = Rc::new(RefCell::new(3_u32));
15+
let shl1: Value<u8> = Rc::new(RefCell::new((*b1.borrow()) << (*ushift1.borrow())));
16+
assert!(((*shl1.borrow()) == 8));
17+
let ushift2: Value<u32> = Rc::new(RefCell::new(2_u32));
18+
let shr1: Value<u8> = Rc::new(RefCell::new((*shl1.borrow()) >> (*ushift2.borrow())));
19+
assert!(((*shr1.borrow()) == 2));
20+
let ushift3: Value<u32> = Rc::new(RefCell::new(5_u32));
21+
{
22+
let n_ = (*b1.borrow()) << (*ushift3.borrow());
23+
(*b1.borrow_mut()) = n_;
24+
(*b1.borrow())
25+
};
26+
assert!(((*b1.borrow()) == 32));
27+
let ushift4: Value<u32> = Rc::new(RefCell::new(3_u32));
28+
{
29+
let n_ = (*b1.borrow()) >> (*ushift4.borrow());
30+
(*b1.borrow_mut()) = n_;
31+
(*b1.borrow())
32+
};
33+
assert!(((*b1.borrow()) == 4));
34+
return 0;
35+
}

‎tests/unit/out/unsafe/byte.rs‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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+
pub fn main() {
10+
unsafe {
11+
std::process::exit(main_0() as i32);
12+
}
13+
}
14+
unsafe fn main_0() -> i32 {
15+
let mut b1: u8 = 1_u8;
16+
let mut ushift1: u32 = 3_u32;
17+
let mut shl1: u8 = b1 << ushift1;
18+
assert!(((shl1) == (8)));
19+
let mut ushift2: u32 = 2_u32;
20+
let mut shr1: u8 = shl1 >> ushift2;
21+
assert!(((shr1) == (2)));
22+
let mut ushift3: u32 = 5_u32;
23+
{
24+
let n_ = b1 << ushift3;
25+
b1 = n_;
26+
b1
27+
};
28+
assert!(((b1) == (32)));
29+
let mut ushift4: u32 = 3_u32;
30+
{
31+
let n_ = b1 >> ushift4;
32+
b1 = n_;
33+
b1
34+
};
35+
assert!(((b1) == (4)));
36+
return 0;
37+
}

0 commit comments

Comments
 (0)