diff --git a/cpp2rust/converter/converter.h b/cpp2rust/converter/converter.h index 683ce155e..9c4b2df6a 100644 --- a/cpp2rust/converter/converter.h +++ b/cpp2rust/converter/converter.h @@ -503,6 +503,10 @@ class Converter : public clang::RecursiveASTVisitor { return true; } + bool TraverseExplicitInstantiationDecl(clang::ExplicitInstantiationDecl *) { + return true; + } + virtual bool VisitCXXStdInitializerListExpr(clang::CXXStdInitializerListExpr *expr); diff --git a/cpp2rust/converter/converter_lib.cpp b/cpp2rust/converter/converter_lib.cpp index 2ff808e32..10ed6199f 100644 --- a/cpp2rust/converter/converter_lib.cpp +++ b/cpp2rust/converter/converter_lib.cpp @@ -265,7 +265,15 @@ bool IsCodeUnitStringLiteral(const clang::StringLiteral *expr) { bool IsUserDefinedDecl(const clang::Decl *decl) { const auto &ctx = decl->getASTContext(); const auto &src_mgr = ctx.getSourceManager(); - const auto src_loc = decl->getLocation(); + auto src_loc = decl->getLocation(); + if (auto *spec = + clang::dyn_cast(decl); + spec && (spec->getSpecializationKind() == + clang::TSK_ExplicitInstantiationDeclaration || + spec->getSpecializationKind() == + clang::TSK_ExplicitInstantiationDefinition)) { + src_loc = spec->getSpecializedTemplate()->getLocation(); + } return !decl->getBeginLoc().isInvalid() && !decl->isImplicit() && !src_mgr.isInSystemHeader(src_loc) && !src_mgr.isInSystemMacro(src_loc); diff --git a/tests/unit/class_templates.cpp b/tests/unit/class_templates.cpp index c3888a519..6e34c5186 100644 --- a/tests/unit/class_templates.cpp +++ b/tests/unit/class_templates.cpp @@ -39,7 +39,20 @@ template struct Outer { Inner with(int n) const { return Inner{v, n}; } }; +struct Elem { + int i; +}; + +template class std::vector; + +template struct Boxed; + int main() { + std::vector ev; + ev.push_back(Elem{2}); + assert(ev[0].i == 2); + assert(Boxed::twice(2) == 4); + Outer oi{3}; assert(oi.with(4).sum() == 7); Outer ol{5}; diff --git a/tests/unit/out/refcount/class_templates.rs b/tests/unit/out/refcount/class_templates.rs index 2f208eced..b7d09e01d 100644 --- a/tests/unit/out/refcount/class_templates.rs +++ b/tests/unit/out/refcount/class_templates.rs @@ -28,6 +28,17 @@ pub struct MyContainer_float_ { vec_: Value>, } #[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(2)] +pub struct Boxed_short_ { + #[offset(0)] + pub value: i16, +} +impl Boxed_short_ { + pub fn twice(mut v: i16) -> i16 { + return (((v as i32) + (v as i32)) as i16); + } +} +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] #[byte_size(4)] pub struct Boxed_int_ { #[offset(0)] @@ -85,11 +96,24 @@ pub struct Outer_long_ { #[offset(0)] pub v: i64, } +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(4)] +pub struct Elem { + #[offset(0)] + pub i: i32, +} pub fn main() { __cpp2rust_init_globals(); std::process::exit(main_0()); } fn main_0() -> i32 { + let mut ev: Vec = Vec::new(); + { + let __a1 = Elem { i: 2 }; + ev.push(__a1) + }; + assert!(({ ev[0_usize].i } == 2)); + assert!(((({ Boxed_short_::twice(2_i16,) }) as i32) == 4)); let oi: Value = Rc::new(RefCell::new(Outer_int_ { v: 3 })); assert!( (({ @@ -181,6 +205,14 @@ impl Boxed_long_Impl for Ptr { return ((*self).with(|__s| __s.value) + other); } } +pub trait Boxed_short_Impl { + fn plus(&self, other: i16) -> i16; +} +impl Boxed_short_Impl for Ptr { + fn plus(&self, mut other: i16) -> i16 { + return ((((*self).with(|__s| __s.value) as i32) + (other as i32)) as i16); + } +} pub trait MyContainer_char_Impl { fn empty(&self) -> bool; fn size(&self) -> usize; diff --git a/tests/unit/out/unsafe/class_templates.rs b/tests/unit/out/unsafe/class_templates.rs index 04157333f..358652b3e 100644 --- a/tests/unit/out/unsafe/class_templates.rs +++ b/tests/unit/out/unsafe/class_templates.rs @@ -86,6 +86,19 @@ impl MyContainer_float_ { } #[repr(C)] #[derive(Copy, Clone, VaArg, FnPtrArg, Default)] +pub struct Boxed_short_ { + pub value: i16, +} +impl Boxed_short_ { + pub unsafe fn twice(mut v: i16) -> i16 { + return (((v as i32) + (v as i32)) as i16); + } + pub unsafe fn plus(&self, mut other: i16) -> i16 { + return (((self.value as i32) + (other as i32)) as i16); + } +} +#[repr(C)] +#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] pub struct Boxed_int_ { pub value: i32, } @@ -163,6 +176,11 @@ impl Outer_long_ { return Outer_long__Inner_int_ { t: self.v, u: n }; } } +#[repr(C)] +#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] +pub struct Elem { + pub i: i32, +} pub fn main() { unsafe { __cpp2rust_init_globals(); @@ -170,6 +188,13 @@ pub fn main() { } } unsafe fn main_0() -> i32 { + let mut ev: Vec = Vec::new(); + { + let __a1 = Elem { i: 2 }; + ev.push(__a1) + }; + assert!(((ev[(0_usize)].i) == (2))); + assert!((((unsafe { Boxed_short_::twice(2_i16,) }) as i32) == (4))); let mut oi: Outer_int_ = Outer_int_ { v: 3 }; assert!( ((unsafe { Outer_int__Inner_int_::sum(&(unsafe { Outer_int_::with(&oi, 4,) }),) }) == (7))