diff --git a/cpp2rust/converter/translation_rule.cpp b/cpp2rust/converter/translation_rule.cpp index 1d6a757a..06f21921 100644 --- a/cpp2rust/converter/translation_rule.cpp +++ b/cpp2rust/converter/translation_rule.cpp @@ -130,6 +130,16 @@ TypeRule ParseTypeRuleJSON(const llvm::json::Object &obj) { return rule; } +bool TargetOSMatchesHost(llvm::StringRef target_os) { +#if defined(__linux__) + return target_os == "linux"; +#elif defined(__APPLE__) + return target_os == "macos"; +#else + return false; +#endif +} + void LoadTgtFromIR(ExprRules &exprs, TypeRules &types, const std::filesystem::path &json_path) { auto buf = llvm::MemoryBuffer::getFile(json_path.string()); @@ -153,6 +163,11 @@ void LoadTgtFromIR(ExprRules &exprs, TypeRules &types, if (!obj) continue; + if (auto target_os = obj->getString("target_os"); + target_os && !TargetOSMatchesHost(*target_os)) { + continue; + } + auto name = entry_name.str(); if (name[0] == 'f') { exprs[std::move(name)] = ParseExprRuleJSON(*obj); diff --git a/rule-preprocessor/Cargo.toml b/rule-preprocessor/Cargo.toml index 691fc896..497c57ac 100644 --- a/rule-preprocessor/Cargo.toml +++ b/rule-preprocessor/Cargo.toml @@ -9,3 +9,4 @@ rules = { path = "../rules" } ra_ap_syntax = "0.0.266" serde = { version = "1", features = ["derive"] } serde_json = "1" +syn = "2" diff --git a/rule-preprocessor/src/ir.rs b/rule-preprocessor/src/ir.rs index 03be4230..9a0c5f58 100644 --- a/rule-preprocessor/src/ir.rs +++ b/rule-preprocessor/src/ir.rs @@ -48,7 +48,6 @@ pub struct TypeInfo { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct FnIr { - // Fields ordered alphabetically to match the old serde_json::Map output pub body: Vec, #[serde(skip_serializing_if = "Option::is_none")] pub generics: Option>>, @@ -58,6 +57,8 @@ pub struct FnIr { pub params: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub return_type: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub target_os: Option, } impl FnIr { diff --git a/rule-preprocessor/src/syntactic.rs b/rule-preprocessor/src/syntactic.rs index a535c42a..6f3ba7d6 100644 --- a/rule-preprocessor/src/syntactic.rs +++ b/rule-preprocessor/src/syntactic.rs @@ -258,6 +258,31 @@ impl<'a> FnIrBuilder<'a> { Self { fn_item } } + fn get_target_os(&self) -> Option { + use ast::HasAttrs; + for attr in self.fn_item.attrs() { + let meta_text = attr.meta()?.syntax().text().to_string(); + let syn::Meta::List(list) = syn::parse_str(&meta_text).ok()? else { + continue; + }; + if !list.path.is_ident("cfg") { + continue; + } + let mut found = None; + let _ = list.parse_nested_meta(|nested| { + if nested.path.is_ident("target_os") { + let lit: syn::LitStr = nested.value()?.parse()?; + found = Some(lit.value()); + } + Ok(()) + }); + if found.is_some() { + return found; + } + } + None + } + fn params(&self) -> Vec { let mut params = Vec::new(); let Some(param_list) = self.fn_item.param_list() else { @@ -499,6 +524,7 @@ impl<'a> FnIrBuilder<'a> { }, multi_statement, body, + target_os: self.get_target_os(), }; ir.validate(&format!("{}:{}", path.display(), fn_name)); ir diff --git a/rules/socket/ir_unsafe.json b/rules/socket/ir_unsafe.json index 68f4a473..c37b5314 100644 --- a/rules/socket/ir_unsafe.json +++ b/rules/socket/ir_unsafe.json @@ -8,5 +8,47 @@ "return_type": { "type": "i32" } + }, + "f2": { + "body": [ + { + "text": "libc::SOCK_STREAM" + } + ], + "return_type": { + "type": "i32" + } + }, + "f3": { + "body": [ + { + "text": "libc::SOCK_DGRAM" + } + ], + "return_type": { + "type": "i32" + } + }, + "f4": { + "body": [ + { + "text": "libc::SOCK_CLOEXEC" + } + ], + "return_type": { + "type": "i32" + }, + "target_os": "linux" + }, + "f5": { + "body": [ + { + "text": "libc::SOCK_NONBLOCK" + } + ], + "return_type": { + "type": "i32" + }, + "target_os": "linux" } } diff --git a/rules/socket/src.cpp b/rules/socket/src.cpp index 7b246ec3..b49b50d4 100644 --- a/rules/socket/src.cpp +++ b/rules/socket/src.cpp @@ -4,3 +4,21 @@ int f1() { return MSG_NOSIGNAL; } + +int f2() { + return SOCK_STREAM; +} + +int f3() { + return SOCK_DGRAM; +} + +#ifdef __linux__ +int f4() { + return SOCK_CLOEXEC; +} + +int f5() { + return SOCK_NONBLOCK; +} +#endif diff --git a/rules/socket/tgt_unsafe.rs b/rules/socket/tgt_unsafe.rs index de6e21d3..f39b4c40 100644 --- a/rules/socket/tgt_unsafe.rs +++ b/rules/socket/tgt_unsafe.rs @@ -1,3 +1,21 @@ unsafe fn f1() -> i32 { libc::MSG_NOSIGNAL } + +unsafe fn f2() -> i32 { + libc::SOCK_STREAM +} + +unsafe fn f3() -> i32 { + libc::SOCK_DGRAM +} + +#[cfg(target_os = "linux")] +unsafe fn f4() -> i32 { + libc::SOCK_CLOEXEC +} + +#[cfg(target_os = "linux")] +unsafe fn f5() -> i32 { + libc::SOCK_NONBLOCK +} diff --git a/tests/unit/out/refcount/socket_type_constants.rs b/tests/unit/out/refcount/socket_type_constants.rs new file mode 100644 index 00000000..605f0ca0 --- /dev/null +++ b/tests/unit/out/refcount/socket_type_constants.rs @@ -0,0 +1,16 @@ +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() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + assert!((((libc::SOCK_STREAM == 1) as i32) != 0)); + assert!((((libc::SOCK_DGRAM == 2) as i32) != 0)); + return 0; +} diff --git a/tests/unit/out/unsafe/socket_type_constants.rs b/tests/unit/out/unsafe/socket_type_constants.rs new file mode 100644 index 00000000..c7af392e --- /dev/null +++ b/tests/unit/out/unsafe/socket_type_constants.rs @@ -0,0 +1,18 @@ +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 { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + assert!(((((libc::SOCK_STREAM) == (1)) as i32) != 0)); + assert!(((((libc::SOCK_DGRAM) == (2)) as i32) != 0)); + return 0; +} diff --git a/tests/unit/socket_type_constants.c b/tests/unit/socket_type_constants.c new file mode 100644 index 00000000..1e5036f5 --- /dev/null +++ b/tests/unit/socket_type_constants.c @@ -0,0 +1,9 @@ +#include +#include +#include + +int main() { + assert(SOCK_STREAM == 1); + assert(SOCK_DGRAM == 2); + return 0; +}