Skip to content

Commit

Permalink
Fix tracing of opaque types
Browse files Browse the repository at this point in the history
This makes tracing opaque types' edges match what we codegen for opaque
types. Although we still generate constructors, methods, etc for opaque
types (just not fields and base members) we were not tracing them.

Fixes rust-lang#807
  • Loading branch information
fitzgen committed Jul 12, 2017
1 parent a00db04 commit c4da32a
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 13 deletions.
25 changes: 12 additions & 13 deletions src/ir/comp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1582,19 +1582,6 @@ impl Trace for CompInfo {
tracer.visit_kind(ty, EdgeKind::InnerType);
}

// We unconditionally trace `CompInfo`'s template parameters and inner
// types for the the usage analysis. However, we don't want to continue
// tracing anything else, if this type is marked opaque.
if item.is_opaque(context, &()) {
return;
}

for base in self.base_members() {
tracer.visit_kind(base.ty, EdgeKind::BaseMember);
}

self.fields.trace(context, tracer, &());

for &var in self.inner_vars() {
tracer.visit_kind(var, EdgeKind::InnerVar);
}
Expand All @@ -1606,5 +1593,17 @@ impl Trace for CompInfo {
for &ctor in self.constructors() {
tracer.visit_kind(ctor, EdgeKind::Constructor);
}

// Base members and fields are not generated for opaque types (but all
// of the above things are) so stop here.
if item.is_opaque(context, &()) {
return;
}

for base in self.base_members() {
tracer.visit_kind(base.ty, EdgeKind::BaseMember);
}

self.fields.trace(context, tracer, &());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/* automatically generated by rust-bindgen */


#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]


#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct Pupper {
pub _address: u8,
}
#[test]
fn bindgen_test_layout_Pupper() {
assert_eq!(::std::mem::size_of::<Pupper>() , 1usize , concat ! (
"Size of: " , stringify ! ( Pupper ) ));
assert_eq! (::std::mem::align_of::<Pupper>() , 1usize , concat ! (
"Alignment of " , stringify ! ( Pupper ) ));
}
impl Clone for Pupper {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct Doggo {
pub _address: u8,
}
#[test]
fn bindgen_test_layout_Doggo() {
assert_eq!(::std::mem::size_of::<Doggo>() , 1usize , concat ! (
"Size of: " , stringify ! ( Doggo ) ));
assert_eq! (::std::mem::align_of::<Doggo>() , 1usize , concat ! (
"Alignment of " , stringify ! ( Doggo ) ));
}
impl Clone for Doggo {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct SuchWow {
pub _address: u8,
}
#[test]
fn bindgen_test_layout_SuchWow() {
assert_eq!(::std::mem::size_of::<SuchWow>() , 1usize , concat ! (
"Size of: " , stringify ! ( SuchWow ) ));
assert_eq! (::std::mem::align_of::<SuchWow>() , 1usize , concat ! (
"Alignment of " , stringify ! ( SuchWow ) ));
}
impl Clone for SuchWow {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct Opaque {
pub _bindgen_opaque_blob: u8,
}
#[test]
fn bindgen_test_layout_Opaque() {
assert_eq!(::std::mem::size_of::<Opaque>() , 1usize , concat ! (
"Size of: " , stringify ! ( Opaque ) ));
assert_eq! (::std::mem::align_of::<Opaque>() , 1usize , concat ! (
"Alignment of " , stringify ! ( Opaque ) ));
}
extern "C" {
#[link_name = "_ZN6Opaque17eleven_out_of_tenEv"]
pub fn Opaque_eleven_out_of_ten(this: *mut Opaque) -> SuchWow;
}
extern "C" {
#[link_name = "_ZN6OpaqueC1E6Pupper"]
pub fn Opaque_Opaque(this: *mut Opaque, pup: Pupper);
}
impl Clone for Opaque {
fn clone(&self) -> Self { *self }
}
impl Opaque {
#[inline]
pub unsafe fn eleven_out_of_ten(&mut self) -> SuchWow {
Opaque_eleven_out_of_ten(self)
}
#[inline]
pub unsafe fn new(pup: Pupper) -> Self {
let mut __bindgen_tmp = ::std::mem::uninitialized();
Opaque_Opaque(&mut __bindgen_tmp, pup);
__bindgen_tmp
}
}
extern "C" {
#[link_name = "_ZN6Opaque11MAJESTIC_AFE"]
pub static mut Opaque_MAJESTIC_AF: Doggo;
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct Whitelisted {
pub some_member: Opaque,
}
#[test]
fn bindgen_test_layout_Whitelisted() {
assert_eq!(::std::mem::size_of::<Whitelisted>() , 1usize , concat ! (
"Size of: " , stringify ! ( Whitelisted ) ));
assert_eq! (::std::mem::align_of::<Whitelisted>() , 1usize , concat ! (
"Alignment of " , stringify ! ( Whitelisted ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const Whitelisted ) ) . some_member as * const
_ as usize } , 0usize , concat ! (
"Alignment of field: " , stringify ! ( Whitelisted ) , "::" ,
stringify ! ( some_member ) ));
}
impl Clone for Whitelisted {
fn clone(&self) -> Self { *self }
}
36 changes: 36 additions & 0 deletions tests/headers/issue-807-opaque-types-methods-being-generated.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// bindgen-flags: --whitelist-type Whitelisted --opaque-type Opaque -- -std=c++11

// These types are not explicitly whitelisted, but are reachable through the
// opaque type.
class Pupper {};
class Doggo {};
class SuchWow {};

// These types are not whitelisted, and would be reachable through `Opaque` if
// it were not marked opaque, but since it is, there should be no bindings
// generated for them.
class NoBindingsShouldBeGeneratedForMe1 {};
class NoBindingsShouldBeGeneratedForMe2 {};

// Exercise the different kinds of outgoing edges from an opaque type.
class Opaque
// Base member edge.
: public NoBindingsShouldBeGeneratedForMe1 {

protected:
// Field edge.
NoBindingsShouldBeGeneratedForMe2 field;

// Constructor edge.
Opaque(Pupper pup);

// Inner static variable edge.
static Doggo MAJESTIC_AF;

// Method edge.
SuchWow eleven_out_of_ten();
};

class Whitelisted {
Opaque some_member;
};

0 comments on commit c4da32a

Please sign in to comment.