Skip to content

Commit 6320ed2

Browse files
author
bors-servo
authored
Auto merge of #557 - scoopr:objc, r=emilio
objc: Implement whitelist tracing This implements the tracing facility to enable whitelisting. The most ugly thing is the collecting of the protocol ItemIds that a interface conforms to. I couldn't use the Item::from_ty because the protocols aren't actually types (in clang), I'm just making them look like one, as thats how they behave in bindgens perspective. So I resorted in linear search of all ItemIds, as it was easyish to implement (local to objc.rs), but there are several good avenues to make that faster if it needs to. The change to naming the types with the rust_name is also a suspect, I'm not totally sure of all the consequences but this allows the protocols/categories to be disambiguated, otherwise there could be multiple type items with the same name. Somehow I feel that I'm forgetting another rationale as well, from when I originally wrote that line few days ago. Locally I also got a test failure, but to me that does not seem like it was caused by these changes. In call-conv-field.rs: ```diff extern "stdcall" { - #[link_name = "_bar@0"] + #[link_name = "bar@0"] pub fn bar(); } ```
2 parents b71c7ba + 35159dc commit 6320ed2

File tree

4 files changed

+101
-3
lines changed

4 files changed

+101
-3
lines changed

src/ir/objc.rs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
//! Objective C types
22
3-
use super::context::BindgenContext;
3+
use super::context::{BindgenContext, ItemId};
44
use super::function::FunctionSig;
5+
use super::traversal::{Trace, Tracer};
6+
use super::ty::TypeKind;
57
use clang;
68
use clang_sys::CXChildVisit_Continue;
79
use clang_sys::CXCursor_ObjCCategoryDecl;
810
use clang_sys::CXCursor_ObjCClassRef;
911
use clang_sys::CXCursor_ObjCInstanceMethodDecl;
1012
use clang_sys::CXCursor_ObjCProtocolDecl;
13+
use clang_sys::CXCursor_ObjCProtocolRef;
1114

1215
/// Objective C interface as used in TypeKind
1316
///
@@ -22,6 +25,8 @@ pub struct ObjCInterface {
2225

2326
is_protocol: bool,
2427

28+
conforms_to: Vec<ItemId>,
29+
2530
/// List of the methods defined in this interfae
2631
methods: Vec<ObjCInstanceMethod>,
2732
}
@@ -46,6 +51,7 @@ impl ObjCInterface {
4651
name: name.to_owned(),
4752
category: None,
4853
is_protocol: false,
54+
conforms_to: Vec::new(),
4955
methods: Vec::new(),
5056
}
5157
}
@@ -97,6 +103,34 @@ impl ObjCInterface {
97103
interface.category = Some(cursor.spelling());
98104
}
99105
}
106+
CXCursor_ObjCProtocolRef => {
107+
// Gather protocols this interface conforms to
108+
let needle = format!("protocol_{}", c.spelling());
109+
let items_map = ctx.items();
110+
debug!("Interface {} conforms to {}, find the item", interface.name, needle);
111+
112+
for (id, item) in items_map
113+
{
114+
if let Some(ty) = item.as_type() {
115+
match *ty.kind() {
116+
TypeKind::ObjCInterface(ref protocol) => {
117+
if protocol.is_protocol
118+
{
119+
debug!("Checking protocol {}, ty.name {:?}", protocol.name, ty.name());
120+
if Some(needle.as_ref()) == ty.name()
121+
{
122+
debug!("Found conforming protocol {:?}", item);
123+
interface.conforms_to.push(*id);
124+
break;
125+
}
126+
}
127+
}
128+
_ => {}
129+
}
130+
}
131+
}
132+
133+
}
100134
CXCursor_ObjCInstanceMethodDecl => {
101135
let name = c.spelling();
102136
let signature =
@@ -168,3 +202,19 @@ impl ObjCInstanceMethod {
168202
.join("")
169203
}
170204
}
205+
206+
impl Trace for ObjCInterface {
207+
type Extra = ();
208+
209+
fn trace<T>(&self, context: &BindgenContext, tracer: &mut T, _: &())
210+
where T: Tracer,
211+
{
212+
for method in &self.methods {
213+
method.signature.trace(context, tracer, &());
214+
}
215+
216+
for protocol in &self.conforms_to {
217+
tracer.visit(*protocol);
218+
}
219+
}
220+
}

src/ir/ty.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,6 +1268,7 @@ impl Type {
12681268
CXType_ObjCInterface => {
12691269
let interface = ObjCInterface::from_ty(&location.unwrap(), ctx)
12701270
.expect("Not a valid objc interface?");
1271+
name = interface.rust_name();
12711272
TypeKind::ObjCInterface(interface)
12721273
}
12731274
_ => {
@@ -1325,8 +1326,8 @@ impl Trace for Type {
13251326
tracer.visit(id);
13261327
}
13271328

1328-
TypeKind::ObjCInterface(_) => {
1329-
// TODO:
1329+
TypeKind::ObjCInterface(ref interface) => {
1330+
interface.trace(context, tracer, &());
13301331
}
13311332

13321333
// None of these variants have edges to other items and types.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(non_snake_case)]
5+
6+
#![cfg(target_os="macos")]
7+
8+
#[macro_use]
9+
extern crate objc;
10+
#[allow(non_camel_case_types)]
11+
pub type id = *mut objc::runtime::Object;
12+
pub trait protocol_SomeProtocol {
13+
unsafe fn protocolMethod(self);
14+
}
15+
impl protocol_SomeProtocol for id {
16+
unsafe fn protocolMethod(self) { msg_send!(self , protocolMethod) }
17+
}
18+
pub trait WhitelistMe {
19+
unsafe fn method(self);
20+
}
21+
impl WhitelistMe for id {
22+
unsafe fn method(self) { msg_send!(self , method) }
23+
}
24+
pub trait WhitelistMe_InterestingCategory { }
25+
impl WhitelistMe_InterestingCategory for id { }

tests/headers/objc_whitelist.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// bindgen-flags: --objc-extern-crate --whitelist-type WhitelistMe --whitelist-type WhitelistMe_InterestingCategory -- -x objective-c
2+
// bindgen-osx-only
3+
4+
5+
// Protocol should be included, since it is used by the WhitelistMe
6+
@protocol SomeProtocol
7+
-(void)protocolMethod;
8+
@end
9+
10+
// The whitelisted item
11+
@interface WhitelistMe <SomeProtocol>
12+
-(void)method;
13+
@end
14+
15+
// This was also explicitly whitelisted
16+
@interface WhitelistMe (InterestingCategory)
17+
@end
18+
19+
// This was not automatically whitelisted
20+
@interface WhitelistMe (IgnoredCategory)
21+
@end
22+

0 commit comments

Comments
 (0)