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
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ set(rules_index_parts_dir ${CMAKE_BINARY_DIR}/rules_index/parts)
set(RULES_IR_DIR "${CMAKE_BINARY_DIR}/rules")
set(rust_rules_ir_outputs)
foreach(_rule_dir IN LISTS rule_subdirs)
file(GLOB _cpp_srcs ${_rule_dir}/src.c ${_rule_dir}/src.cpp ${_rule_dir}/src_cxx*.cpp)
file(GLOB _cpp_srcs ${_rule_dir}/src.c ${_rule_dir}/src.cpp ${_rule_dir}/src_*.cpp)
if(NOT _cpp_srcs)
continue()
endif()
Expand Down
3 changes: 3 additions & 0 deletions cpp2rust/converter/rules/rules_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,9 @@ std::string BuildRulesEpilogue(const std::unordered_set<std::string> &keys,
if (auto since = rule->getInteger("since"); since && *since > standard) {
continue;
}
if (auto until = rule->getInteger("until"); until && *until <= standard) {
continue;
}
if (auto required = rule->getArray("requires");
required &&
!llvm::all_of(*required, [&](const llvm::json::Value &key) {
Expand Down
32 changes: 24 additions & 8 deletions cpp2rust/rule_preprocessing/cpp_rule_indexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,15 +335,27 @@ llvm::json::Object ReadJson(const fs::path &path) {
return std::move(*parsed->getAsObject());
}

unsigned SinceStandard(const fs::path &src_path) {
struct StandardRange {
unsigned since = 11;
unsigned until = 0;
};

StandardRange RuleFileStandards(const fs::path &src_path) {
auto stem_string = src_path.stem().string();
llvm::StringRef stem = stem_string;
unsigned standard = 11;
if (stem.consume_front("src_cxx") && stem.getAsInteger(10, standard)) {
StandardRange range;
bool valid = stem.consume_front("src");
if (valid && stem.consume_front("_cxx")) {
valid = !stem.consumeInteger(10, range.since);
}
if (valid && stem.consume_front("_until_cxx")) {
valid = !stem.consumeInteger(10, range.until);
}
if (!valid || !stem.empty()) {
llvm::errs() << "ERROR: unexpected rule file " << src_path.string() << '\n';
std::exit(EXIT_FAILURE);
}
return standard;
return range;
}

void MergeRules(llvm::json::Object &into, llvm::json::Object &&from) {
Expand All @@ -364,20 +376,24 @@ void IndexDir(const fs::path &rule_dir, const fs::path &out) {
for (const auto &entry : fs::directory_iterator(rule_dir)) {
auto name = entry.path().filename().string();
if (name == "src.c" || name == "src.cpp" ||
(name.starts_with("src_cxx") && name.ends_with(".cpp"))) {
(name.starts_with("src_") && name.ends_with(".cpp"))) {
cxx_srcs.push_back(entry.path());
}
}
std::ranges::sort(cxx_srcs);
llvm::json::Object cxx_rules;
for (const auto &src_path : cxx_srcs) {
auto standard = SinceStandard(src_path);
auto range = RuleFileStandards(src_path);
llvm::json::Object rules;
Index(src_path, /*is_c=*/false, dir_name,
{std::format("-std=c++{}", standard)}, rules);
{std::format("-std=c++{}", range.since)}, rules);
for (auto &[key, entries] : rules) {
for (auto &entry : *entries.getAsArray()) {
(*entry.getAsObject())["since"] = standard;
auto &rule = *entry.getAsObject();
rule["since"] = range.since;
if (range.until) {
rule["until"] = range.until;
}
}
}
MergeRules(cxx_rules, std::move(rules));
Expand Down
8 changes: 8 additions & 0 deletions rules/algorithm/src_until_cxx17.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) 2022-present INESC-ID.
// Distributed under the MIT license that can be found in the LICENSE file.

#include <algorithm>

template <typename T1> void f18(T1 first, T1 last) {
return std::random_shuffle(first, last);
}
13 changes: 13 additions & 0 deletions rules/algorithm/tgt_refcount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,16 @@ fn f16<T1: PartialOrd + Clone + ByteRepr>(a0: Ptr<T1>, a1: Ptr<T1>) -> Ptr<T1> {
fn f17<T1: PartialOrd + Clone + ByteRepr>(a0: Ptr<T1>, a1: Ptr<T1>) -> Ptr<T1> {
if a0.read() >= a1.read() { a0 } else { a1 }
}

fn f18<T1: Clone + ByteRepr>(a0: Ptr<T1>, a1: Ptr<T1>) {
let count = a1.get_offset() - a0.get_offset();
let random = std::hash::RandomState::new();
for i in (1..count).rev() {
let j = std::hash::BuildHasher::hash_one(&random, i) as usize % (i + 1);
let x = a0.offset(i);
let y = a0.offset(j);
let tmp = x.read();
x.write(y.read());
y.write(tmp);
}
}
8 changes: 8 additions & 0 deletions rules/algorithm/tgt_unsafe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,11 @@ unsafe fn f17<T1: PartialOrd>(a0: *const T1, a1: *const T1) -> *const T1 {
(a1) as *const _
}
}

unsafe fn f18<T1>(a0: *mut T1, a1: *mut T1) {
let len = a1.offset_from(a0) as usize;
let slice = ::std::slice::from_raw_parts_mut(a0, len);
for i in (1..len).rev() {
slice.swap(i, libc::rand() as usize % (i + 1));
}
}
6 changes: 6 additions & 0 deletions rules/string/src_until_cxx20.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright (c) 2022-present INESC-ID.
// Distributed under the MIT license that can be found in the LICENSE file.

#include <string>

bool f31(const std::string &a, const char *b) { return a != b; }
4 changes: 4 additions & 0 deletions rules/string/tgt_refcount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,7 @@ fn f29(a0: Ptr<Vec<i8>>, a1: Vec<i8>) {
fn f30(a0: Ptr<Vec<i8>>, a1: &mut Vec<i8>) {
a0.write(std::mem::take(&mut *a1))
}

fn f31(a0: Vec<i8>, a1: Ptr<i8>) -> bool {
a1.with_c_str(|__s| a0[..a0.len().saturating_sub(1)] != *__s)
}
7 changes: 7 additions & 0 deletions rules/string/tgt_unsafe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,10 @@ unsafe fn f29(a0: &mut Vec<libc::c_char>, a1: Vec<libc::c_char>) {
unsafe fn f30(a0: &mut Vec<libc::c_char>, a1: &mut Vec<libc::c_char>) {
*a0 = std::mem::take(&mut *a1)
}

unsafe fn f31(a0: Vec<libc::c_char>, a1: *const libc::c_char) -> bool {
a0 != {
let s = a1;
std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1).to_vec()
}
}
3 changes: 3 additions & 0 deletions tests/unit/elidable_iterator_copy_cxx11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@ int main() {
std::vector<int>::iterator it = std::find(v.begin(), v.end(), 7);
assert(it != v.end());
assert(*it == 7);
std::random_shuffle(v.begin(), v.end());
std::sort(v.begin(), v.end());
assert(v[0] == 4 && v[1] == 7);
return 0;
}
15 changes: 15 additions & 0 deletions tests/unit/out/refcount/elidable_iterator_copy_cxx11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,21 @@ fn main_0() -> i32 {
};
assert!(it != (v.as_pointer() as Ptr<i32>).to_end());
assert!(((it.read()) == 7));
{
let count = (v.as_pointer() as Ptr<i32>).to_end().get_offset()
- (v.as_pointer() as Ptr<i32>).get_offset();
let random = std::hash::RandomState::new();
for i in (1..count).rev() {
let j = std::hash::BuildHasher::hash_one(&random, i) as usize % (i + 1);
let x = (v.as_pointer() as Ptr<i32>).offset(i);
let y = (v.as_pointer() as Ptr<i32>).offset(j);
let tmp = x.read();
x.write(y.read());
y.write(tmp);
}
};
(v.as_pointer() as Ptr<i32>).sort((v.as_pointer() as Ptr<i32>).to_end().get_offset());
assert!(({ (*v.borrow())[0_usize] } == 4) && ({ (*v.borrow())[1_usize] } == 7));
return 0;
}
pub fn __cpp2rust_init_globals() {}
8 changes: 8 additions & 0 deletions tests/unit/out/refcount/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ fn main_0() -> i32 {
Ptr::<i8>::from_string_literal(b"hello")
.with_c_str(|__s| (*s1.borrow())[..(*s1.borrow()).len().saturating_sub(1)] == *__s)
);
assert!(
Ptr::<i8>::from_string_literal(b"world")
.with_c_str(|__s| (*s1.borrow())[..(*s1.borrow()).len().saturating_sub(1)] != *__s)
);
assert!(
!(Ptr::<i8>::from_string_literal(b"hello")
.with_c_str(|__s| (*s1.borrow())[..(*s1.borrow()).len().saturating_sub(1)] != *__s))
);
let mut p1: Ptr<i8> = (s1.as_pointer() as Ptr<i8>);
assert!((((elem!(p1, 0).read()) as i32) == (('h' as i8) as i32)));
assert!((((elem!(p1, 1).read()) as i32) == (('e' as i8) as i32)));
Expand Down
12 changes: 12 additions & 0 deletions tests/unit/out/unsafe/elidable_iterator_copy_cxx11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ unsafe fn main_0() -> i32 {
};
assert!(it != v.as_mut_ptr().add(v.len()));
assert!(((*it) == (7)));
{
let len = v.as_mut_ptr().add(v.len()).offset_from(v.as_mut_ptr()) as usize;
let slice = ::std::slice::from_raw_parts_mut(v.as_mut_ptr(), len);
for i in (1..len).rev() {
slice.swap(i, libc::rand() as usize % (i + 1));
}
};
{
let len = v.as_mut_ptr().add(v.len()).offset_from(v.as_mut_ptr()) as usize;
::std::slice::from_raw_parts_mut(v.as_mut_ptr(), len).sort()
};
assert!(((v[(0_usize)]) == (4)) && ((v[(1_usize)]) == (7)));
return 0;
}
pub unsafe fn __cpp2rust_init_globals() {}
14 changes: 14 additions & 0 deletions tests/unit/out/unsafe/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ unsafe fn main_0() -> i32 {
.to_vec()
}
);
assert!(
s1 != {
let s = c"world".as_ptr();
std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1)
.to_vec()
}
);
assert!(
!(s1 != {
let s = c"hello".as_ptr();
std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1)
.to_vec()
})
);
let mut p1: *const libc::c_char = (s1.as_mut_ptr()).cast_const();
assert!((((*p1.offset((0) as isize)) as i32) == (('h' as libc::c_char) as i32)));
assert!((((*p1.offset((1) as isize)) as i32) == (('e' as libc::c_char) as i32)));
Expand Down
3 changes: 3 additions & 0 deletions tests/unit/string.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ADDITIONAL_COMPILE_FLAGS: -std=c++17
#include <cassert>
#include <cstdint>
#include <string>
Expand All @@ -14,6 +15,8 @@ int main() {
assert(s1[3] == 'l');
assert(s1[4] == 'o');
assert(s1 == "hello");
assert(s1 != "world");
assert(!(s1 != "hello"));
const char *p1 = s1.data();
assert(p1[0] == 'h');
assert(p1[1] == 'e');
Expand Down
Loading