elliotchance / c2go

⚖️ A tool for transpiling C to Go.
MIT License
2.09k stars 155 forks source link

transpile: enum literals in C are converted to nil expressions in Go; ConstantExpr not yet handled in transpileToExpr #848

Closed mewmew closed 4 years ago

mewmew commented 4 years ago

When transpiling C source code using enum literals in expressions, nil values are used for their corresponding Go expressions.

Example input C source code

typedef enum T {
    FOO = 1,
    BAR = 2,
} T;

int f(int t) {
    switch (t) {
    case FOO:
        return 42;
    case BAR:
        return 10;
    default:
        return 0;
    }
}

Example output Go source code

Notice the case nil: lines of function f.

/*
    Package main - transpiled by c2go version: v0.25.9 Dubnium 2018-12-30

    If you have found any issues, please raise an issue at:
    https://github.com/elliotchance/c2go/
*/

// Warning (ConstantExpr):  /home/u/Desktop/ccc/m/m.c:2 : cannot transpile to expr
// Warning (ConstantExpr):  /home/u/Desktop/ccc/m/m.c:3 : cannot transpile to expr
// Warning (ConstantExpr):  /home/u/Desktop/ccc/m/m.c:8 : cannot transpile to expr
// Warning (ConstantExpr):  /home/u/Desktop/ccc/m/m.c:10 : cannot transpile to expr

package main

type T int32

const ( // Warning (ConstantExpr):  /home/u/Desktop/ccc/m/m.c:2 : cannot transpile to expr
    FOO T = 0 // Warning (ConstantExpr):  /home/u/Desktop/ccc/m/m.c:3 : cannot transpile to expr
    BAR   = 1
)

type T int32

// f - transpiled function from  /home/u/Desktop/ccc/m/m.c:6
// Warning (ConstantExpr):  /home/u/Desktop/ccc/m/m.c:8 : cannot transpile to expr
// Warning (ConstantExpr):  /home/u/Desktop/ccc/m/m.c:10 : cannot transpile to expr
func f(t int32) (c2goDefaultReturn int32) {
    switch t {
    case nil:
        {
            return int32(42)
        }
    case nil:
        {
            return int32(10)
        }
    default:
        {
            return int32(0)
        }
    }
    return
}
func init() {
}

C AST

$ c2go ast m.c
TranslationUnitDecl 0x5557af1279f8 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x5557af128290 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
| `-BuiltinType 0x5557af127f90 '__int128'
|-TypedefDecl 0x5557af128300 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x5557af127fb0 'unsigned __int128'
|-TypedefDecl 0x5557af1285e8 <<invalid sloc>> <invalid sloc> implicit __NSConstantString 'struct __NSConstantString_tag'
| `-RecordType 0x5557af1283e0 'struct __NSConstantString_tag'
|   `-Record 0x5557af128358 '__NSConstantString_tag'
|-TypedefDecl 0x5557af128680 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x5557af128640 'char *'
|   `-BuiltinType 0x5557af127a90 'char'
|-TypedefDecl 0x5557af128958 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]'
| `-ConstantArrayType 0x5557af128900 'struct __va_list_tag [1]' 1 
|   `-RecordType 0x5557af128760 'struct __va_list_tag'
|     `-Record 0x5557af1286d8 '__va_list_tag'
|-EnumDecl 0x5557af186760 </home/u/Desktop/ccc/m/m.c:1:9, line:4:1> line:1:14 T
| |-EnumConstantDecl 0x5557af186858 <line:2:2, col:8> col:2 referenced FOO 'int'
| | `-ConstantExpr 0x5557af186840 <col:8> 'int'
| |   `-IntegerLiteral 0x5557af186820 <col:8> 'int' 1
| `-EnumConstantDecl 0x5557af1868e0 <line:3:2, col:8> col:2 referenced BAR 'int'
|   `-ConstantExpr 0x5557af1868c8 <col:8> 'int'
|     `-IntegerLiteral 0x5557af1868a8 <col:8> 'int' 2
|-TypedefDecl 0x5557af186988 <line:1:1, line:4:3> col:3 T 'enum T':'enum T'
| `-ElaboratedType 0x5557af186930 'enum T' sugar
|   `-EnumType 0x5557af186800 'enum T'
|     `-Enum 0x5557af186760 'T'
`-FunctionDecl 0x5557af186ae0 <line:6:1, line:15:1> line:6:5 f 'int (int)'
  |-ParmVarDecl 0x5557af186a10 <col:7, col:11> col:11 used t 'int'
  `-CompoundStmt 0x5557af186dc0 <col:14, line:15:1>
    `-SwitchStmt 0x5557af186c08 <line:7:2, line:14:2>
      |-ImplicitCastExpr 0x5557af186bf0 <line:7:10> 'int' <LValueToRValue>
      | `-DeclRefExpr 0x5557af186bd0 <col:10> 'int' lvalue ParmVar 0x5557af186a10 't' 'int'
      `-CompoundStmt 0x5557af186d98 <col:13, line:14:2>
        |-CaseStmt 0x5557af186c60 <line:8:2, line:9:10>
        | |-ConstantExpr 0x5557af186c48 <line:8:7> 'int'
        | | `-DeclRefExpr 0x5557af186c28 <col:7> 'int' EnumConstant 0x5557af186858 'FOO' 'int'
        | `-ReturnStmt 0x5557af186ca8 <line:9:3, col:10>
        |   `-IntegerLiteral 0x5557af186c88 <col:10> 'int' 42
        |-CaseStmt 0x5557af186cf0 <line:10:2, line:11:10>
        | |-ConstantExpr 0x5557af186cd8 <line:10:7> 'int'
        | | `-DeclRefExpr 0x5557af186cb8 <col:7> 'int' EnumConstant 0x5557af1868e0 'BAR' 'int'
        | `-ReturnStmt 0x5557af186d38 <line:11:3, col:10>
        |   `-IntegerLiteral 0x5557af186d18 <col:10> 'int' 10
        `-DefaultStmt 0x5557af186d78 <line:12:2, line:13:10>
          `-ReturnStmt 0x5557af186d68 <col:3, col:10>
            `-IntegerLiteral 0x5557af186d48 <col:10> 'int' 0
mewmew commented 4 years ago

After applying PR #850, the Go output looks as follows:

/*
    Package main - transpiled by c2go version: v0.25.9 Dubnium 2018-12-30

    If you have found any issues, please raise an issue at:
    https://github.com/elliotchance/c2go/
*/

package main

type T int32

const (
    FOO T = 0
    BAR   = 1
)

type T int32

// f - transpiled function from  /home/u/Desktop/ccc/m/m.c:6
func f(t int32) (c2goDefaultReturn int32) {
    switch t {
    case FOO:
        {
            return int32(42)
        }
    case BAR:
        {
            return int32(10)
        }
    default:
        {
            return int32(0)
        }
    }
    return
}
func init() {
}