@@ -123,8 +123,13 @@ bool Converter::VisitBuiltinType(clang::BuiltinType *type) {
123123 StrCat (" f64" );
124124 break ;
125125 case clang::BuiltinType::Char_S:
126- case clang::BuiltinType::UChar:
126+ case clang::BuiltinType::Char_U:
127+ StrCat (CharRustType ());
128+ break ;
127129 case clang::BuiltinType::SChar:
130+ StrCat (" i8" );
131+ break ;
132+ case clang::BuiltinType::UChar:
128133 StrCat (" u8" );
129134 break ;
130135 case clang::BuiltinType::UShort:
@@ -753,6 +758,11 @@ void Converter::EmitRustStructOrUnion(clang::RecordDecl *decl) {
753758 }
754759 }
755760
761+ if (decl->isUnion ()) {
762+ EmitRustUnion (decl);
763+ return ;
764+ }
765+
756766 // Derived traits
757767 if (EmitsReprCForRecords ()) {
758768 StrCat (" #[repr(C)]" );
@@ -770,8 +780,7 @@ void Converter::EmitRustStructOrUnion(clang::RecordDecl *decl) {
770780 auto access = clang::dyn_cast<clang::CXXRecordDecl>(decl)
771781 ? AccessSpecifierAsString (decl->getAccess ())
772782 : keyword::kPub ;
773- StrCat (access, decl->isUnion () ? keyword::kUnion : keyword::kStruct ,
774- GetRecordName (decl));
783+ StrCat (access, keyword::kStruct , GetRecordName (decl));
775784 {
776785 PushBrace brace (*this );
777786 for (auto *field : decl->fields ()) {
@@ -810,9 +819,32 @@ void Converter::EmitRustStructOrUnion(clang::RecordDecl *decl) {
810819 // Traits
811820 if (auto *cxx = clang::dyn_cast<clang::CXXRecordDecl>(decl)) {
812821 AddOrdTrait (cxx);
813- AddCloneTrait (cxx);
814822 AddDropTrait (cxx);
815823 }
824+ AddCloneTrait (decl);
825+ AddDefaultTrait (decl);
826+ AddByteReprTrait (decl);
827+ }
828+
829+ void Converter::EmitRustUnion (clang::RecordDecl *decl) {
830+ StrCat (" #[repr(C)]" );
831+ auto attrs = GetStructAttributes (decl);
832+ Mapper::SetDerives (ctx_.getCanonicalTagType (decl),
833+ std::vector<std::string>(attrs.begin (), attrs.end ()));
834+ StrCat (" #[derive(" );
835+ for (auto *attr : attrs) {
836+ StrCat (attr, ' ,' );
837+ }
838+ StrCat (" )]" );
839+
840+ StrCat (keyword::kPub , keyword::kUnion , GetRecordName (decl));
841+ {
842+ PushBrace brace (*this );
843+ for (auto *field : decl->fields ()) {
844+ VisitFieldDecl (field);
845+ }
846+ }
847+
816848 AddDefaultTrait (decl);
817849 AddByteReprTrait (decl);
818850}
@@ -1383,7 +1415,8 @@ bool Converter::GetFmtArg(clang::Expr *arg, std::string &fmt,
13831415 } else if (arg_str.contains (" Setw" )) {
13841416 fmt_width = Trim (ToString (arg));
13851417 } else if (!arg->getType ()->isCharType () &&
1386- Mapper::Map (arg->getType ()) != " Vec<u8>" ) {
1418+ Mapper::Map (arg->getType ()) !=
1419+ std::format (" Vec<{}>" , CharRustType ())) {
13871420 fmt += (" {:" + fmt_width + fmt_trait + " }" );
13881421 fmt_width.clear (); // Reset setw after first usage
13891422 arg_str = ToString (arg);
@@ -1399,11 +1432,13 @@ bool Converter::GetFmtArg(clang::Expr *arg, std::string &fmt,
13991432
14001433bool Converter::GetRawArg (clang::Expr *arg, std::string &raw_args) {
14011434 if (arg->getType ()->isCharType ()) {
1402- raw_args += " (&[" + ToString (arg) + ' ]' ;
1403- } else if (Mapper::Map (arg->getType ()) == " Vec<u8>" ) {
1435+ raw_args += " (&[" + ToString (arg) + " as u8]" ;
1436+ } else if (Mapper::Map (arg->getType ()) ==
1437+ std::format (" Vec<{}>" , CharRustType ())) {
14041438 PushExprKind push (*this , ExprKind::RValue);
14051439 std::string str = ToString (arg);
1406- raw_args += " (&(" + str + " )[..(" + str + " ).len() - 1]" ;
1440+ raw_args += " (&(" + str + " ).iter().take((" + str +
1441+ " ).len() - 1).map(|&c| c as u8).collect::<Vec<u8>>()[..]" ;
14071442 } else if (Mapper::ToString (arg).contains (" std::endl" )) {
14081443 raw_args += " (&[b'\\ n']" ;
14091444 } else if (clang::isa<clang::StringLiteral>(arg->IgnoreImplicit ())) {
@@ -1688,6 +1723,24 @@ Converter::CallInfo Converter::CollectCallInfo(clang::CallExpr *expr) {
16881723 }
16891724 }
16901725
1726+ // Inline arguments that don't alias
1727+ clang::Expr *receiver = GetCallObject (expr);
1728+ for (auto &ca : info.args ) {
1729+ if (ca.kind != Kind::Hoisted) {
1730+ continue ;
1731+ }
1732+ bool aliases = receiver && ArgsMayAlias (ca.expr , receiver);
1733+ for (const auto &other : info.args ) {
1734+ if (&other != &ca && ArgsMayAlias (ca.expr , other.expr )) {
1735+ aliases = true ;
1736+ break ;
1737+ }
1738+ }
1739+ if (!aliases) {
1740+ ca.kind = Kind::Inline;
1741+ }
1742+ }
1743+
16911744 return info;
16921745}
16931746
@@ -1824,6 +1877,14 @@ Converter::ConvertCallExpr(clang::CallExpr *expr) {
18241877 return std::nullopt ;
18251878}
18261879
1880+ static std::string getTypedLiteral (const char *num, std::string_view type) {
1881+ if (type.contains (" ::" )) {
1882+ // Not a builtin type
1883+ return std::format (" ({} as {})" , num, type);
1884+ }
1885+ return std::format (" {}_{}" , num, type);
1886+ }
1887+
18271888std::string Converter::getIntegerLiteral (clang::IntegerLiteral *expr,
18281889 bool incl_type,
18291890 const clang::QualType *type) {
@@ -1845,7 +1906,7 @@ std::string Converter::getIntegerLiteral(clang::IntegerLiteral *expr,
18451906 return init;
18461907 }
18471908 }
1848- return std::format ( " {}_{} " , num_as_string.c_str (), type_as_string);
1909+ return getTypedLiteral ( num_as_string.c_str (), type_as_string);
18491910 }
18501911
18511912 return static_cast <std::string>(num_as_string);
@@ -1938,19 +1999,30 @@ bool Converter::VisitStringLiteral(clang::StringLiteral *expr) {
19381999 if (auto *arr_ty = ctx_.getAsConstantArrayType (curr_init_type_.back ())) {
19392000 uint64_t arr_size = arr_ty->getSize ().getZExtValue ();
19402001 if (expr->getString ().empty ()) {
1941- StrCat (std::format (" [0u8 ; {}]" , arr_size));
2002+ StrCat (std::format (" [0 as libc::c_char ; {}]" , arr_size));
19422003 return false ;
19432004 }
19442005 uint64_t pad = arr_size > expr->getString ().size ()
19452006 ? arr_size - expr->getString ().size ()
19462007 : 0 ;
1947- StrCat (token:: kStar ,
1948- std::format ( " b{} " , GetEscapedStringLiteral (expr, pad)));
2008+ StrCat (std::format ( " std::mem::transmute(*b{}) " ,
2009+ GetEscapedStringLiteral (expr, pad)));
19492010 return false ;
19502011 }
1951- StrCat (token::kStar );
2012+ StrCat (std::format (" std::mem::transmute(*b{})" ,
2013+ GetEscapedStringLiteral (expr, 1 )));
2014+ return false ;
2015+ }
2016+ if (expr->getString ().contains (' \0 ' )) {
2017+ std::string out = " (&[" ;
2018+ for (unsigned char c : expr->getString ()) {
2019+ out += getTypedLiteral (std::to_string (c).c_str (), CharRustType ()) + " , " ;
2020+ }
2021+ out += getTypedLiteral (" 0" , CharRustType ()) + " ])" ;
2022+ StrCat (out);
2023+ return false ;
19522024 }
1953- StrCat (std::format (" b {}" , GetEscapedStringLiteral (expr, 1 )));
2025+ StrCat (std::format (" c {}" , GetEscapedStringLiteral (expr, 0 )));
19542026 return false ;
19552027}
19562028
@@ -2033,15 +2105,6 @@ bool Converter::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
20332105 }
20342106 bool dest_pointee_const =
20352107 expr->getType ()->getPointeeType ().isConstQualified ();
2036- if (const auto *member =
2037- clang::dyn_cast<clang::MemberExpr>(sub_expr->IgnoreParenImpCasts ());
2038- member && IsCharArrayFieldFromLibc (member->getMemberDecl ())) {
2039- PushParen paren (*this );
2040- Convert (sub_expr);
2041- StrCat (dest_pointee_const ? " .as_ptr()" : " .as_mut_ptr()" );
2042- StrCat (keyword::kAs , dest_pointee_const ? " *const u8" : " *mut u8" );
2043- break ;
2044- }
20452108 Convert (sub_expr);
20462109 if (clang::isa<clang::StringLiteral>(sub_expr) ||
20472110 clang::isa<clang::PredefinedExpr>(sub_expr)) {
@@ -2233,7 +2296,8 @@ void Converter::ConvertBinaryOperator(clang::BinaryOperator *expr) {
22332296 if (auto *cmpd_assign_op =
22342297 llvm::dyn_cast<clang::CompoundAssignOperator>(expr);
22352298 expr->isCompoundAssignmentOp () &&
2236- lhs_type != cmpd_assign_op->getComputationResultType ()) {
2299+ GetUnsafeTypeAsString (lhs_type) !=
2300+ GetUnsafeTypeAsString (cmpd_assign_op->getComputationResultType ())) {
22372301 auto computation_result_type = cmpd_assign_op->getComputationResultType ();
22382302 if (IsUnsignedArithOp (cmpd_assign_op)) {
22392303 Convert (lhs);
@@ -2257,7 +2321,7 @@ void Converter::ConvertBinaryOperator(clang::BinaryOperator *expr) {
22572321 auto op = opcode_as_string;
22582322 op.remove_suffix (1 ); // remove '=' from operator
22592323 StrCat (op);
2260- Convert (rhs);
2324+ Convert (rhs, computation_result_type );
22612325 }
22622326 if (lhs_type->isBooleanType ()) {
22632327 StrCat (token::kDiff , token::kZero );
@@ -2729,16 +2793,6 @@ bool Converter::VisitMemberExpr(clang::MemberExpr *expr) {
27292793 return false ;
27302794 }
27312795
2732- // char* fields in libc structs are *mut i8. We represent char* as *mut u8. Do
2733- // the i8 -> u8 conversion here.
2734- if (IsCharPointerFieldFromLibc (member)) {
2735- StrCat (std::format (" ({} as {})" , str,
2736- member->getType ()->getPointeeType ().isConstQualified ()
2737- ? " *const u8"
2738- : " *mut u8" ));
2739- return false ;
2740- }
2741-
27422796 StrCat (str);
27432797 return false ;
27442798}
@@ -2903,7 +2957,8 @@ bool Converter::VisitCompoundLiteralExpr(clang::CompoundLiteralExpr *expr) {
29032957
29042958bool Converter::VisitArraySubscriptExpr (clang::ArraySubscriptExpr *expr) {
29052959 auto *base = expr->getBase ();
2906- if (base->IgnoreCasts ()->getType ()->isPointerType ()) {
2960+ if (base->IgnoreCasts ()->getType ()->isPointerType () ||
2961+ clang::isa<clang::StringLiteral>(base->IgnoreCasts ())) {
29072962 ConvertPointerSubscript (expr);
29082963 } else {
29092964 ConvertArraySubscript (base, expr->getIdx (), expr->getType ());
@@ -3158,6 +3213,7 @@ bool Converter::VisitEnumDecl(clang::EnumDecl *decl) {
31583213
31593214 AddFromImpl (decl);
31603215 AddIncDecImpls (decl);
3216+ AddByteReprTrait (decl);
31613217 return false ;
31623218}
31633219
@@ -3438,11 +3494,11 @@ std::string Converter::GetDefaultAsStringFallback(clang::QualType qual_type) {
34383494 }
34393495
34403496 if (qual_type->isIntegerType () && !qual_type->isEnumeralType ()) {
3441- return std::format ( " 0_{} " , ToString (qual_type));
3497+ return getTypedLiteral ( " 0 " , ToString (qual_type));
34423498 }
34433499
34443500 if (qual_type->isFloatingType ()) {
3445- return std::format (" 0.0_{} " , ToString (qual_type));
3501+ return getTypedLiteral (" 0.0 " , ToString (qual_type));
34463502 }
34473503
34483504 if (auto record = qual_type->getAsRecordDecl ();
@@ -3757,7 +3813,7 @@ void Converter::ConvertFunctionMain(const clang::FunctionDecl *decl,
37573813pub fn main() {{
37583814 let mut args: Vec<Vec<u8>> = std::env::args().map(|arg| arg.as_bytes().to_vec()).collect();
37593815 args.iter_mut().for_each(|v| v.push(0));
3760- let mut argv: Vec<*mut u8 > = args.iter().map(|arg| arg.as_ptr() as *mut u8 ).collect();
3816+ let mut argv: Vec<*mut libc::c_char > = args.iter().map(|arg| arg.as_ptr() as *mut libc::c_char ).collect();
37613817 argv.push(::std::ptr::null_mut());
37623818 unsafe {{
37633819 ::std::process::exit(main_0((argv.len() - 1) as i32, argv.as_mut_ptr()) as i32)
@@ -3881,7 +3937,7 @@ void Converter::AddOrdTrait(const clang::CXXRecordDecl *decl) {
38813937 ConvertOrdAndPartialOrdTraits (decl, methods[0 ]);
38823938}
38833939
3884- void Converter::AddCloneTrait (const clang::CXXRecordDecl *decl) {}
3940+ void Converter::AddCloneTrait (const clang::RecordDecl *decl) {}
38853941
38863942void Converter::AddDropTrait (const clang::CXXRecordDecl *decl) {}
38873943
@@ -3940,6 +3996,8 @@ void Converter::EmitDefaultStructLiteral(const clang::RecordDecl *decl) {
39403996
39413997void Converter::AddByteReprTrait (const clang::RecordDecl *decl) {}
39423998
3999+ void Converter::AddByteReprTrait (const clang::EnumDecl *decl) {}
4000+
39434001void Converter::ConvertUnsignedArithBinaryOperator (clang::BinaryOperator *op,
39444002 clang::Expr *expr) {
39454003 StrCat (token::kDot );
0 commit comments