From 3e576dd19465b264e9f93e71d0ffe19c7b782130 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Sat, 19 Sep 2026 22:07:54 +0100 Subject: [PATCH] Translate variable template declarations --- cpp2rust/converter/converter.cpp | 7 +++++++ cpp2rust/converter/converter.h | 1 + cpp2rust/converter/converter_lib.cpp | 4 ++++ tests/unit/out/refcount/templates.rs | 16 +++++++++++++++- tests/unit/out/unsafe/templates.rs | 14 +++++++++++++- tests/unit/templates.cpp | 7 +++++++ 6 files changed, 47 insertions(+), 2 deletions(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index cf33029e6..8d27b141b 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -490,6 +490,13 @@ bool Converter::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *decl) { return false; } +bool Converter::VisitVarTemplateDecl(clang::VarTemplateDecl *decl) { + for (auto *var_decl : decl->specializations()) { + VisitVarDecl(var_decl); + } + return false; +} + void Converter::ConvertVaListVarDecl(clang::VarDecl *decl) { if (clang::isa(decl)) { // va_list parameter (decayed to __va_list_tag *) diff --git a/cpp2rust/converter/converter.h b/cpp2rust/converter/converter.h index 9387ee749..b87feedaa 100644 --- a/cpp2rust/converter/converter.h +++ b/cpp2rust/converter/converter.h @@ -98,6 +98,7 @@ class Converter : public clang::RecursiveASTVisitor { void EmitHoistedDecls(clang::CompoundStmt *body); virtual bool VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *decl); + bool VisitVarTemplateDecl(clang::VarTemplateDecl *decl); virtual bool VisitVarDecl(clang::VarDecl *decl); virtual bool LazyStaticInit() const { return true; } diff --git a/cpp2rust/converter/converter_lib.cpp b/cpp2rust/converter/converter_lib.cpp index 0dbb2fd11..08d572d8d 100644 --- a/cpp2rust/converter/converter_lib.cpp +++ b/cpp2rust/converter/converter_lib.cpp @@ -574,6 +574,10 @@ static std::string GetParamSignature(const clang::Decl *decl) { static std::string GetLexicalSpecializationID(const clang::Decl *decl) { std::string id; + if (const auto *var = + clang::dyn_cast(decl)) { + id += clang::ASTNameGenerator(var->getASTContext()).getName(var); + } if (const auto *spec = clang::dyn_cast( decl->getLexicalDeclContext()); diff --git a/tests/unit/out/refcount/templates.rs b/tests/unit/out/refcount/templates.rs index 8c662110d..bda085f1d 100644 --- a/tests/unit/out/refcount/templates.rs +++ b/tests/unit/out/refcount/templates.rs @@ -44,6 +44,12 @@ pub fn func_5(x1: f64, x2: i32, x3: f64) -> i32 { let x3: Value = Rc::new(RefCell::new(x3)); return ((((*x1.borrow()) + ((*x2.borrow()) as f64)) + (*x3.borrow())) as i32); } +thread_local!( + pub static half_6: Value = Rc::new(RefCell::new((1 / 2))); +); +thread_local!( + pub static half_7: Value = Rc::new(RefCell::new((1_f64 / 2_f64))); +); pub fn main() { __cpp2rust_init_globals(); std::process::exit(main_0()); @@ -59,6 +65,14 @@ fn main_0() -> i32 { + (({ func_5(2.0E+0, (*x.borrow()), (*y.borrow()),) }) as f64)) == 68_f64) ); + assert!((half_6.with(|rc| rc.borrow().clone()) == 0)); + assert!((half_7.with(|rc| rc.borrow().clone()) == 5.0E-1)); + (*half_6.with(Value::clone).borrow_mut()) = 7; + assert!((half_6.with(|rc| rc.borrow().clone()) == 7)); + assert!((half_7.with(|rc| rc.borrow().clone()) == 5.0E-1)); return 0; } -pub fn __cpp2rust_init_globals() {} +pub fn __cpp2rust_init_globals() { + let _ = half_6.with(|_| ()); + let _ = half_7.with(|_| ()); +} diff --git a/tests/unit/out/unsafe/templates.rs b/tests/unit/out/unsafe/templates.rs index f9300b546..267a70314 100644 --- a/tests/unit/out/unsafe/templates.rs +++ b/tests/unit/out/unsafe/templates.rs @@ -24,6 +24,10 @@ pub unsafe fn func_4(mut x1: i32, mut x2: i32, mut x3: i32) -> i32 { pub unsafe fn func_5(mut x1: f64, mut x2: i32, mut x3: f64) -> i32 { return ((((x1) + (x2 as f64)) + (x3)) as i32); } +pub static mut half_6: std::cell::LazyCell = + std::cell::LazyCell::new(|| unsafe { ((1) / (2)) }); +pub static mut half_7: std::cell::LazyCell = + std::cell::LazyCell::new(|| unsafe { ((1_f64) / (2_f64)) }); pub fn main() { unsafe { __cpp2rust_init_globals(); @@ -41,6 +45,14 @@ unsafe fn main_0() -> i32 { + ((unsafe { func_5(2.0E+0, x, y,) }) as f64)) == (68_f64)) ); + assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut half_6)) == (0))); + assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut half_7)) == (5.0E-1))); + (*std::cell::LazyCell::force_mut(&mut *&raw mut half_6)) = 7; + assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut half_6)) == (7))); + assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut half_7)) == (5.0E-1))); return 0; } -pub unsafe fn __cpp2rust_init_globals() {} +pub unsafe fn __cpp2rust_init_globals() { + std::cell::LazyCell::force(&*&raw const half_6); + std::cell::LazyCell::force(&*&raw const half_7); +} diff --git a/tests/unit/templates.cpp b/tests/unit/templates.cpp index c0af5c3c6..e7b238154 100644 --- a/tests/unit/templates.cpp +++ b/tests/unit/templates.cpp @@ -8,11 +8,18 @@ template int func(T1 x1, T2 x2, T3 x3) { return x1 + x2 + x3; } +template T half = T(1) / T(2); + int main() { int x = 10; double y = x; assert(foo(x) + foo(y) + *bar(&x, true) + *bar(&y, true) + func(1, 2, 3) + func(2.0, x, y) == 68); + assert(half == 0); + assert(half == 0.5); + half = 7; + assert(half == 7); + assert(half == 0.5); return 0; }