github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/transpiler/cast.go (about) 1 package transpiler 2 3 import ( 4 "fmt" 5 goast "go/ast" 6 7 "github.com/Konstantin8105/c4go/ast" 8 "github.com/Konstantin8105/c4go/program" 9 "github.com/Konstantin8105/c4go/types" 10 "github.com/Konstantin8105/c4go/util" 11 ) 12 13 func transpileImplicitCastExpr(n *ast.ImplicitCastExpr, p *program.Program, exprIsStmt bool) ( 14 expr goast.Expr, 15 exprType string, 16 preStmts []goast.Stmt, 17 postStmts []goast.Stmt, 18 err error) { 19 defer func() { 20 if err != nil { 21 err = fmt.Errorf("cannot transpileImplicitCastExpr. err = %v", err) 22 } 23 if exprType == "" { 24 exprType = "ImplicitCastExprWrongType" 25 } 26 }() 27 28 n.Type = util.GenerateCorrectType(n.Type) 29 n.Type2 = util.GenerateCorrectType(n.Type2) 30 31 if n.Kind == ast.CStyleCastExprNullToPointer { 32 expr = goast.NewIdent("nil") 33 exprType = types.NullPointer 34 return 35 } 36 37 // avoid unsigned overflow 38 // ImplicitCastExpr 0x2e649b8 <col:6, col:7> 'unsigned int' <IntegralCast> 39 // `-UnaryOperator 0x2e64998 <col:6, col:7> 'int' prefix '-' 40 if types.IsCUnsignedType(n.Type) { 41 if un, ok := n.Children()[0].(*ast.UnaryOperator); ok && un.Operator == "-" { 42 un.Type = n.Type 43 } 44 } 45 46 expr, exprType, preStmts, postStmts, err = transpileToExpr( 47 n.Children()[0], p, exprIsStmt) 48 if err != nil { 49 return nil, "", nil, nil, err 50 } 51 if exprType == types.NullPointer { 52 expr = goast.NewIdent("nil") 53 return 54 } 55 56 // avoid cast to qsort type function 57 if n.Type == "__compar_fn_t" { 58 return 59 } 60 61 // type casting 62 if n.Kind == "BitCast" && types.IsPointer(exprType, p) && types.IsPointer(n.Type, p) { 63 var newPost []goast.Stmt 64 expr, exprType, newPost, err = PntBitCast(expr, exprType, n.Type, p) 65 postStmts = append(postStmts, newPost...) 66 if err != nil { 67 return nil, "BitCastWrongType", nil, nil, err 68 } 69 return 70 } 71 72 if n.Kind == "IntegralToPointer" { 73 // ImplicitCastExpr 'double *' <IntegralToPointer> 74 // `-ImplicitCastExpr 'long' <LValueToRValue> 75 // `-DeclRefExpr 'long' lvalue Var 0x30e91d8 'pnt' 'long' 76 if types.IsCPointer(n.Type, p) { 77 if t, ok := ast.GetTypeIfExist(n.Children()[0]); ok { 78 // 79 // ImplicitCastExpr 'char *' <IntegralToPointer> 80 // `-ImplicitCastExpr 'char' <LValueToRValue> 81 // `-ArraySubscriptExpr 'char' lvalue 82 // |-ImplicitCastExpr 'char *' <LValueToRValue> 83 // | `-DeclRefExpr 'char *' lvalue Var 0x413c8a8 'b' 'char *' 84 // `-IntegerLiteral 'int' 3 85 // 86 // n.Type = 'char *' 87 // *t = 'char' 88 // 89 90 if ind, ok := expr.(*goast.IndexExpr); ok { 91 // from : 92 // 93 // 0 *ast.IndexExpr { 94 // 1 . X: *ast.Ident { 95 // 3 . . Name: "b" 96 // 4 . } 97 // 6 . Index: *ast.BasicLit { ... } 98 // 12 } 99 // 100 // to: 101 // 102 // 88 0: *ast.SliceExpr { 103 // 89 . X: *ast.Ident { 104 // 91 . . Name: "b" 105 // 93 . } 106 // 95 . Low: *ast.BasicLit { ... } 107 // 99 . } 108 // 102 } 109 expr = &goast.SliceExpr{ 110 X: ind.X, 111 Low: ind.Index, 112 Slice3: false, 113 } 114 exprType = n.Type 115 return 116 } else if types.IsCInteger(p, *t) { 117 resolveType := n.Type 118 resolveType, err = types.ResolveType(p, n.Type) 119 if err != nil { 120 return nil, "", nil, nil, err 121 } 122 expr = &goast.StarExpr{ 123 X: &goast.ParenExpr{ 124 X: &goast.CallExpr{ 125 Fun: &goast.ParenExpr{X: goast.NewIdent("*" + resolveType)}, 126 Args: []goast.Expr{ 127 &goast.CallExpr{ 128 Fun: goast.NewIdent("unsafe.Pointer"), 129 Args: []goast.Expr{ 130 &goast.CallExpr{ 131 Fun: goast.NewIdent("uintptr"), 132 Args: []goast.Expr{expr}, 133 }, 134 }, 135 }, 136 }, 137 }, 138 }, 139 } 140 p.GenerateWarningMessage( 141 fmt.Errorf("used unsafe convert from integer to pointer"), n) 142 exprType = n.Type 143 return 144 } 145 } 146 } 147 } 148 149 var cast bool = true 150 if in, ok := n.Children()[0].(*ast.IntegerLiteral); ok && in.Type == "int" { 151 if types.IsCInteger(p, n.Type) || types.IsCFloat(p, n.Type) { 152 cast = false 153 exprType = n.Type 154 } 155 } 156 157 if len(n.Type) != 0 && len(n.Type2) != 0 && n.Type != n.Type2 && cast { 158 var tt string 159 tt, err = types.ResolveType(p, n.Type) 160 if err != nil && n.Type2 != "" { 161 tt, err = types.ResolveType(p, n.Type2) 162 } 163 expr = util.NewCallExpr(tt, expr) 164 exprType = n.Type 165 return 166 } 167 168 if util.IsFunction(exprType) { 169 cast = false 170 } 171 if n.Kind == ast.ImplicitCastExprArrayToPointerDecay { 172 cast = false 173 } 174 if n.Kind == "PointerToIntegral" { 175 cast = false 176 } 177 178 if cast { 179 expr, err = types.CastExpr(p, expr, exprType, n.Type) 180 if err != nil { 181 return nil, "", nil, nil, err 182 } 183 exprType = n.Type 184 } 185 186 // Convert from struct member array to slice 187 // ImplicitCastExpr 'char *' <ArrayToPointerDecay> 188 // `-MemberExpr 'char [20]' lvalue .input_str 0x3662ba0 189 // `-DeclRefExpr 'struct s_inp':'struct s_inp' lvalue Var 0x3662c50 's' 'struct s_inp':'struct s_inp' 190 if types.IsCPointer(n.Type, p) { 191 if len(n.Children()) > 0 { 192 if memb, ok := n.Children()[0].(*ast.MemberExpr); ok && types.IsCArray(memb.Type, p) { 193 expr = &goast.SliceExpr{ 194 X: expr, 195 Lbrack: 1, 196 Slice3: false, 197 } 198 } 199 } 200 } 201 202 return 203 } 204 205 func transpileCStyleCastExpr(n *ast.CStyleCastExpr, p *program.Program, exprIsStmt bool) ( 206 expr goast.Expr, 207 exprType string, 208 preStmts []goast.Stmt, 209 postStmts []goast.Stmt, 210 err error) { 211 defer func() { 212 if err != nil { 213 err = fmt.Errorf("cannot transpileImplicitCastExpr. err = %v", err) 214 } 215 if exprType == "" { 216 exprType = "CStyleCastExpr" 217 } 218 }() 219 220 n.Type = util.GenerateCorrectType(n.Type) 221 n.Type2 = util.GenerateCorrectType(n.Type2) 222 223 // Char overflow 224 // example for byte(-1) 225 // CStyleCastExpr 0x365f628 <col:12, col:23> 'char' <IntegralCast> 226 // `-ParenExpr 0x365f608 <col:18, col:23> 'int' 227 // `-ParenExpr 0x365f5a8 <col:19, col:22> 'int' 228 // `-UnaryOperator 0x365f588 <col:20, col:21> 'int' prefix '-' 229 // `-IntegerLiteral 0x365f568 <col:21> 'int' 1 230 if n.Type == "char" { 231 if par, ok := n.Children()[0].(*ast.ParenExpr); ok { 232 if par2, ok := par.Children()[0].(*ast.ParenExpr); ok { 233 if u, ok := par2.Children()[0].(*ast.UnaryOperator); ok && u.IsPrefix { 234 if _, ok := u.Children()[0].(*ast.IntegerLiteral); ok { 235 return transpileToExpr(&ast.BinaryOperator{ 236 Type: "int", 237 Type2: "int", 238 Operator: "+", 239 ChildNodes: []ast.Node{ 240 u, 241 &ast.IntegerLiteral{ 242 Type: "int", 243 Value: "256", 244 }, 245 }, 246 }, p, false) 247 } 248 } 249 } 250 } 251 } 252 253 if n.Kind == ast.CStyleCastExprNullToPointer { 254 expr = goast.NewIdent("nil") 255 exprType = types.NullPointer 256 return 257 } 258 259 expr, exprType, preStmts, postStmts, err = atomicOperation( 260 n.Children()[0], p) 261 if err != nil { 262 return nil, "", nil, nil, err 263 } 264 265 if exprType == types.NullPointer { 266 expr = goast.NewIdent("nil") 267 return 268 } 269 270 // 271 // struct sqlite3_pcache_page { 272 // void *pBuf; /* The content of the page */ 273 // void *pExtra; /* Extra information associated with the page */ 274 // }; 275 // 276 // *(void **)pPage->page.pExtra = 0; 277 // 278 // UnaryOperator 'void *' lvalue prefix '*' 279 // `-CStyleCastExpr 'void **' <BitCast> 280 // `-ImplicitCastExpr 'void *' <LValueToRValue> 281 // `-MemberExpr 'void *' lvalue .pExtra 0x2876098 282 // `-MemberExpr 'sqlite3_pcache_page':'struct sqlite3_pcache_page' lvalue ->page 0x2bdc9d0 283 // `-ImplicitCastExpr 'PgHdr1 *' <LValueToRValue> 284 // `-DeclRefExpr 'PgHdr1 *' lvalue Var 0x2bf5cd0 'pPage' 'PgHdr1 *' 285 // 286 // BinaryOperator 'const char **' '=' 287 // |-DeclRefExpr 'const char **' lvalue Var 0x39a4380 'non_options' 'const char **' 288 // `-CStyleCastExpr 'const char **' <BitCast> 289 // `-ImplicitCastExpr 'void *' <LValueToRValue> 290 // `-DeclRefExpr 'void *' lvalue Var 0x39a62b0 'tmp' 'void *' 291 // 292 // type casting 293 if n.Kind == "BitCast" && types.IsPointer(exprType, p) && types.IsPointer(n.Type, p) { 294 var newPost []goast.Stmt 295 expr, exprType, newPost, err = PntBitCast(expr, exprType, n.Type, p) 296 postStmts = append(postStmts, newPost...) 297 if err != nil { 298 return nil, "BitCastWrongType", nil, nil, err 299 } 300 return 301 } 302 303 if len(n.Type) != 0 && len(n.Type2) != 0 && n.Type != n.Type2 { 304 var tt string 305 tt, err = types.ResolveType(p, n.Type) 306 if err != nil { 307 // `-CStyleCastExpr 0x9b32c0 <> '__clock_t':'long' <IntegralCast> 308 // `-IntegerLiteral 0x9b3290 <> 'int' 1000000 309 tt, err = types.ResolveType(p, n.Type2) 310 } 311 expr = util.NewCallExpr(tt, expr) 312 exprType = n.Type 313 return 314 } 315 316 if n.Kind == ast.CStyleCastExprToVoid { 317 exprType = types.ToVoid 318 return 319 } 320 321 if !util.IsFunction(exprType) && 322 n.Kind != ast.ImplicitCastExprArrayToPointerDecay && 323 n.Kind != "PointerToIntegral" { 324 expr, err = types.CastExpr(p, expr, exprType, n.Type) 325 if err != nil { 326 return nil, "", nil, nil, err 327 } 328 exprType = n.Type 329 } 330 331 // CStyleCastExpr 'int' <PointerToIntegral> 332 // `-UnaryOperator 'long *' prefix '&' 333 // `-DeclRefExpr 'long' lvalue Var 0x42b5268 'l' 'long' 334 // 335 // CStyleCastExpr 'int' <PointerToIntegral> 336 // `-ParenExpr 'long *' 337 // `-UnaryOperator 'long *' prefix '&' 338 // `-DeclRefExpr 'long' lvalue Var 0x38cb568 'l' 'long' 339 if len(n.Children()) > 0 { 340 if types.IsCInteger(p, n.Type) { 341 if t, ok := ast.GetTypeIfExist(n.Children()[0]); ok { 342 if types.IsPointer(*t, p) { 343 // main information : https://go101.org/article/unsafe.html 344 sizeof, err := types.SizeOf(p, types.GetBaseType(*t)) 345 if err != nil { 346 return nil, "", nil, nil, err 347 } 348 var retType string = "long long" 349 var newPost []goast.Stmt 350 expr, newPost, err = GetPointerAddress(p, expr, *t, sizeof) 351 if err != nil { 352 return nil, "", nil, nil, err 353 } 354 postStmts = append(postStmts, newPost...) 355 356 expr, err = types.CastExpr(p, expr, retType, n.Type) 357 if err != nil { 358 return nil, "", nil, nil, err 359 } 360 361 exprType = n.Type 362 } 363 } 364 } 365 } 366 367 return 368 }