diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 038c2cb9..c9918c59 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -1172,6 +1172,12 @@ bool Converter::VisitTypedefDecl([[maybe_unused]] clang::TypedefDecl *decl) { return false; } +bool Converter::VisitStaticAssertDecl(clang::StaticAssertDecl *) { + return false; +} + +bool Converter::VisitConceptDecl(clang::ConceptDecl *) { return false; } + static bool IsaSemiColonStmt(const clang::Stmt *stmt) { switch (stmt->getStmtClass()) { case clang::Stmt::IfStmtClass: @@ -3407,6 +3413,21 @@ bool Converter::VisitUnaryExprOrTypeTraitExpr( return false; } +bool Converter::VisitConceptSpecializationExpr( + clang::ConceptSpecializationExpr *expr) { + assert(!expr->isValueDependent()); + StrCat(expr->isSatisfied() ? keyword::kTrue : keyword::kFalse); + computed_expr_type_ = ComputedExprType::FreshValue; + return false; +} + +bool Converter::VisitRequiresExpr(clang::RequiresExpr *expr) { + assert(!expr->isValueDependent()); + StrCat(expr->isSatisfied() ? keyword::kTrue : keyword::kFalse); + computed_expr_type_ = ComputedExprType::FreshValue; + return false; +} + bool Converter::VisitTypeTraitExpr(clang::TypeTraitExpr *expr) { clang::Expr::EvalResult result; ENSURE(expr->EvaluateAsInt(result, ctx_)); diff --git a/cpp2rust/converter/converter.h b/cpp2rust/converter/converter.h index a06830fe..e4cb99fe 100644 --- a/cpp2rust/converter/converter.h +++ b/cpp2rust/converter/converter.h @@ -157,6 +157,9 @@ class Converter : public clang::RecursiveASTVisitor { virtual bool VisitTypedefDecl(clang::TypedefDecl *decl); + bool VisitStaticAssertDecl(clang::StaticAssertDecl *decl); + bool VisitConceptDecl(clang::ConceptDecl *decl); + virtual bool VisitCompoundStmt(clang::CompoundStmt *stmt); virtual bool VisitDeclStmt(clang::DeclStmt *stmt); @@ -405,8 +408,13 @@ class Converter : public clang::RecursiveASTVisitor { VisitUnaryExprOrTypeTraitExpr(clang::UnaryExprOrTypeTraitExpr *expr); virtual bool VisitTypeTraitExpr(clang::TypeTraitExpr *expr); + virtual bool VisitSizeOfPackExpr(clang::SizeOfPackExpr *expr); + virtual bool + VisitConceptSpecializationExpr(clang::ConceptSpecializationExpr *expr); + virtual bool VisitRequiresExpr(clang::RequiresExpr *expr); + virtual bool VisitOffsetOfExpr(clang::OffsetOfExpr *expr); virtual bool VisitEnumDecl(clang::EnumDecl *decl); diff --git a/tests/unit/concepts.cpp b/tests/unit/concepts.cpp new file mode 100644 index 00000000..46dc7753 --- /dev/null +++ b/tests/unit/concepts.cpp @@ -0,0 +1,44 @@ +// ADDITIONAL_COMPILE_FLAGS: -std=c++20 +#include +#include + +template +concept Small = sizeof(T) <= 4; + +static_assert(Small); + +template +concept HasSize = requires(T t) { + { t.size() } -> std::same_as; +}; + +struct Sized { + int size() { return 4; } +}; + +template bool is_small() { return Small; } + +template bool has_size() { + return requires(T t) { t.size(); }; +} + +template int pick(T x) { + if (std::integral && Small) { + return 1; + } + return 2; +} + +int main() { + static_assert(!Small); + assert(is_small()); + assert(!is_small()); + assert(HasSize); + assert(!HasSize); + assert(has_size()); + assert(!has_size()); + assert(pick(1) == 1); + assert(pick(1L) == 2); + assert(pick(1.0f) == 2); + return 0; +} diff --git a/tests/unit/out/refcount/concepts.rs b/tests/unit/out/refcount/concepts.rs new file mode 100644 index 00000000..d75da0d9 --- /dev/null +++ b/tests/unit/out/refcount/concepts.rs @@ -0,0 +1,82 @@ +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}; +#[derive(Default)] +pub struct Sized {} +impl Clone for Sized { + fn clone(&self) -> Self { + let __this: Value = Rc::new(RefCell::new(Self {})); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } +} +impl ByteRepr for Sized { + fn byte_size() -> usize { + 1 + } + fn to_bytes(&self, buf: &mut [u8]) {} + fn from_bytes(buf: &[u8]) -> Self { + Self {} + } +} +pub fn is_small_0() -> bool { + return true; +} +pub fn is_small_1() -> bool { + return false; +} +pub fn has_size_2() -> bool { + return true; +} +pub fn has_size_3() -> bool { + return false; +} +pub fn pick_4(x: i32) -> i32 { + let x: Value = Rc::new(RefCell::new(x)); + if (true) && (true) { + return 1; + } + return 2; +} +pub fn pick_5(x: i64) -> i32 { + let x: Value = Rc::new(RefCell::new(x)); + if (true) && (false) { + return 1; + } + return 2; +} +pub fn pick_6(x: f32) -> i32 { + let x: Value = Rc::new(RefCell::new(x)); + if (false) && (true) { + return 1; + } + return 2; +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + assert!(({ is_small_0() })); + assert!(!({ is_small_1() })); + assert!(true); + assert!(!false); + assert!(({ has_size_2() })); + assert!(!({ has_size_3() })); + assert!((({ pick_4(1,) }) == 1)); + assert!((({ pick_5(1_i64,) }) == 2)); + assert!((({ pick_6(1.0E+0,) }) == 2)); + return 0; +} +pub trait SizedImpl { + fn size(&self) -> i32; +} +impl SizedImpl for Ptr { + fn size(&self) -> i32 { + return 4; + } +} diff --git a/tests/unit/out/unsafe/concepts.rs b/tests/unit/out/unsafe/concepts.rs new file mode 100644 index 00000000..65dc1701 --- /dev/null +++ b/tests/unit/out/unsafe/concepts.rs @@ -0,0 +1,63 @@ +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; +#[repr(C)] +#[derive(Copy, Clone, Default)] +pub struct Sized {} +impl Sized { + pub unsafe fn size(&mut self) -> i32 { + return 4; + } +} +pub unsafe fn is_small_0() -> bool { + return true; +} +pub unsafe fn is_small_1() -> bool { + return false; +} +pub unsafe fn has_size_2() -> bool { + return true; +} +pub unsafe fn has_size_3() -> bool { + return false; +} +pub unsafe fn pick_4(mut x: i32) -> i32 { + if (true) && (true) { + return 1; + } + return 2; +} +pub unsafe fn pick_5(mut x: i64) -> i32 { + if (true) && (false) { + return 1; + } + return 2; +} +pub unsafe fn pick_6(mut x: f32) -> i32 { + if (false) && (true) { + return 1; + } + return 2; +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + assert!((unsafe { is_small_0() })); + assert!(!(unsafe { is_small_1() })); + assert!(true); + assert!(!false); + assert!((unsafe { has_size_2() })); + assert!(!(unsafe { has_size_3() })); + assert!(((unsafe { pick_4(1,) }) == (1))); + assert!(((unsafe { pick_5(1_i64,) }) == (2))); + assert!(((unsafe { pick_6(1.0E+0,) }) == (2))); + return 0; +}