From 6ba8540376e6a563dbf22c97fd2708d4b84c354e Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Wed, 21 Oct 2026 14:25:14 +0100 Subject: [PATCH 1/3] Key unqualified dependent calls in rules --- cpp2rust/rule_preprocessing/cpp_rule_indexer.cpp | 3 +-- rules/cctype/src.cpp | 6 ++++++ rules/cctype/tgt_unsafe.rs | 11 +++++++++++ tests/unit/template_rule_unqualified_call.cpp | 7 +++++++ 4 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 rules/cctype/src.cpp create mode 100644 rules/cctype/tgt_unsafe.rs create mode 100644 tests/unit/template_rule_unqualified_call.cpp diff --git a/cpp2rust/rule_preprocessing/cpp_rule_indexer.cpp b/cpp2rust/rule_preprocessing/cpp_rule_indexer.cpp index 7879881b7..341d46ce3 100644 --- a/cpp2rust/rule_preprocessing/cpp_rule_indexer.cpp +++ b/cpp2rust/rule_preprocessing/cpp_rule_indexer.cpp @@ -179,8 +179,7 @@ std::string DependentExprKey(const clang::Expr *expr) { } } if (auto lookup = llvm::dyn_cast(callee); - lookup && lookup->getQualifier() && - !llvm::isa(call) && + lookup && !llvm::isa(call) && lookup->decls_begin() != lookup->decls_end()) { return RulesLoader::DeclKey( (*lookup->decls_begin())->getUnderlyingDecl()); diff --git a/rules/cctype/src.cpp b/rules/cctype/src.cpp new file mode 100644 index 000000000..2b2130576 --- /dev/null +++ b/rules/cctype/src.cpp @@ -0,0 +1,6 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +#include + +template int f1(T1 a0) { return toupper(a0); } diff --git a/rules/cctype/tgt_unsafe.rs b/rules/cctype/tgt_unsafe.rs new file mode 100644 index 000000000..2d1f5b980 --- /dev/null +++ b/rules/cctype/tgt_unsafe.rs @@ -0,0 +1,11 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +unsafe fn f1>(a0: T1) -> i32 { + let __c: i32 = a0.into(); + if (0..=255).contains(&__c) { + (__c as u8).to_ascii_uppercase() as i32 + } else { + __c + } +} diff --git a/tests/unit/template_rule_unqualified_call.cpp b/tests/unit/template_rule_unqualified_call.cpp new file mode 100644 index 000000000..1e79f85a0 --- /dev/null +++ b/tests/unit/template_rule_unqualified_call.cpp @@ -0,0 +1,7 @@ +#include +#include + +int main() { + printf("%d %d %d\n", toupper('a'), toupper('Z'), toupper('5')); + return 0; +} From 45555cc95feed0644813868d7c0bd4da832f8914 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Wed, 21 Oct 2026 14:50:43 +0100 Subject: [PATCH 2/3] Use asserts --- tests/unit/template_rule_unqualified_call.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/unit/template_rule_unqualified_call.cpp b/tests/unit/template_rule_unqualified_call.cpp index 1e79f85a0..ee729b511 100644 --- a/tests/unit/template_rule_unqualified_call.cpp +++ b/tests/unit/template_rule_unqualified_call.cpp @@ -1,7 +1,9 @@ +#include #include -#include int main() { - printf("%d %d %d\n", toupper('a'), toupper('Z'), toupper('5')); + assert(toupper('a') == 'A'); + assert(toupper('Z') == 'Z'); + assert(toupper('5') == '5'); return 0; } From a7782c222dd300b9156e363d0162738075ba3835 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Wed, 21 Oct 2026 14:53:04 +0100 Subject: [PATCH 3/3] Update tests --- .../template_rule_unqualified_call.rs | 46 ++++++++++++++++++ .../unsafe/template_rule_unqualified_call.rs | 48 +++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 tests/unit/out/refcount/template_rule_unqualified_call.rs create mode 100644 tests/unit/out/unsafe/template_rule_unqualified_call.rs diff --git a/tests/unit/out/refcount/template_rule_unqualified_call.rs b/tests/unit/out/refcount/template_rule_unqualified_call.rs new file mode 100644 index 000000000..4882145e2 --- /dev/null +++ b/tests/unit/out/refcount/template_rule_unqualified_call.rs @@ -0,0 +1,46 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + assert!( + ({ + let __c: i32 = (('a' as i8) as i32).into(); + if (0..=255).contains(&__c) { + (__c as u8).to_ascii_uppercase() as i32 + } else { + __c + } + } == (('A' as i8) as i32)) + ); + assert!( + ({ + let __c: i32 = (('Z' as i8) as i32).into(); + if (0..=255).contains(&__c) { + (__c as u8).to_ascii_uppercase() as i32 + } else { + __c + } + } == (('Z' as i8) as i32)) + ); + assert!( + ({ + let __c: i32 = (('5' as i8) as i32).into(); + if (0..=255).contains(&__c) { + (__c as u8).to_ascii_uppercase() as i32 + } else { + __c + } + } == (('5' as i8) as i32)) + ); + return 0; +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/template_rule_unqualified_call.rs b/tests/unit/out/unsafe/template_rule_unqualified_call.rs new file mode 100644 index 000000000..e7f619cf7 --- /dev/null +++ b/tests/unit/out/unsafe/template_rule_unqualified_call.rs @@ -0,0 +1,48 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + assert!( + (({ + let __c: i32 = (('a' as libc::c_char) as i32).into(); + if (0..=255).contains(&__c) { + (__c as u8).to_ascii_uppercase() as i32 + } else { + __c + } + }) == (('A' as libc::c_char) as i32)) + ); + assert!( + (({ + let __c: i32 = (('Z' as libc::c_char) as i32).into(); + if (0..=255).contains(&__c) { + (__c as u8).to_ascii_uppercase() as i32 + } else { + __c + } + }) == (('Z' as libc::c_char) as i32)) + ); + assert!( + (({ + let __c: i32 = (('5' as libc::c_char) as i32).into(); + if (0..=255).contains(&__c) { + (__c as u8).to_ascii_uppercase() as i32 + } else { + __c + } + }) == (('5' as libc::c_char) as i32)) + ); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() {}