@@ -1731,6 +1731,16 @@ bool Converter::VisitCXXBoolLiteralExpr(clang::CXXBoolLiteralExpr *expr) {
17311731 return false ;
17321732}
17331733
1734+ void Converter::ConvertIntegerToEnumeralCast (clang::Expr *to,
1735+ clang::Expr *from) {
1736+ StrCat (GetUnsafeTypeAsString (to->getType ()), " ::from" );
1737+ PushParen paren (*this );
1738+ Convert (from);
1739+ if (!from->getType ()->isSpecificBuiltinType (clang::BuiltinType::Int)) {
1740+ StrCat (keyword::kAs , " i32" );
1741+ }
1742+ }
1743+
17341744bool Converter::VisitImplicitCastExpr (clang::ImplicitCastExpr *expr) {
17351745 auto *sub_expr = expr->getSubExpr ();
17361746 auto type = expr->getType ();
@@ -1846,6 +1856,10 @@ bool Converter::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
18461856 Convert (sub_expr);
18471857 break ;
18481858 }
1859+ if (type->isEnumeralType () && !sub_expr->getType ()->isEnumeralType ()) {
1860+ ConvertIntegerToEnumeralCast (expr, sub_expr);
1861+ break ;
1862+ }
18491863 {
18501864 PushParen outer (*this );
18511865 if (clang::isa<clang::BinaryOperator>(sub_expr)) {
@@ -1890,6 +1904,10 @@ bool Converter::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) {
18901904 StrCat (' )' );
18911905 return false ;
18921906 }
1907+ if (type->isEnumeralType () && !sub_expr->getType ()->isEnumeralType ()) {
1908+ ConvertIntegerToEnumeralCast (expr, sub_expr);
1909+ return false ;
1910+ }
18931911 {
18941912 PushParen paren (*this );
18951913 Convert (sub_expr);
@@ -2200,10 +2218,14 @@ std::string Converter::ConvertDeclRefExpr(clang::DeclRefExpr *expr) {
22002218 }
22012219
22022220 if (auto enum_constant = clang::dyn_cast<clang::EnumConstantDecl>(decl)) {
2203- return std::format (" {}::{}" ,
2204- GetRecordName (clang::dyn_cast<clang::EnumDecl>(
2205- enum_constant->getDeclContext ())),
2206- std::string_view (enum_constant->getName ()));
2221+ auto qualified = std::format (" {}::{}" ,
2222+ GetRecordName (clang::dyn_cast<clang::EnumDecl>(
2223+ enum_constant->getDeclContext ())),
2224+ std::string_view (enum_constant->getName ()));
2225+ if (!expr->getType ()->isEnumeralType ()) {
2226+ return std::format (" ({} as i32)" , qualified);
2227+ }
2228+ return qualified;
22072229 }
22082230
22092231 if (IsGlobalVar (expr)) {
@@ -2704,9 +2726,29 @@ bool Converter::VisitEnumDecl(clang::EnumDecl *decl) {
27042726 std::string_view (init.data (), init.size ())));
27052727 }
27062728 StrCat (" }" );
2729+
2730+ AddFromImpl (decl);
27072731 return false ;
27082732}
27092733
2734+ void Converter::AddFromImpl (clang::EnumDecl *decl) {
2735+ auto name = GetRecordName (decl);
2736+ StrCat (std::format (" impl From<i32> for {}" , name));
2737+ PushBrace impl (*this );
2738+ StrCat (std::format (" fn from(n: i32) -> {}" , name));
2739+ PushBrace fn (*this );
2740+ StrCat (" match n" );
2741+ PushBrace match (*this );
2742+ for (auto e : decl->enumerators ()) {
2743+ llvm::SmallVector<char , 32 > init;
2744+ e->getInitVal ().toString (init, 10 );
2745+ StrCat (std::format (" {} => {}::{}," ,
2746+ std::string_view (init.data (), init.size ()), name,
2747+ std::string_view (e->getName ())));
2748+ }
2749+ StrCat (std::format (" _ => panic!(\" invalid {} value: {{}}\" , n)," , name));
2750+ }
2751+
27102752bool Converter::VisitCXXDefaultArgExpr (clang::CXXDefaultArgExpr *expr) {
27112753 if (expr->getType ()->isPointerType ()) {
27122754 StrCat (keyword_default_);
0 commit comments