Repository: Konstantin8105/c4go
Pull request #274 (2019-02-15 14:26:55)

CStyleCastExpr: saving pointer address 


Patch:
diff --git a/ast/ast.go b/ast/ast.go
index b64d67f..866ba74 100644
--- a/ast/ast.go
+++ b/ast/ast.go
@@ -323,3 +323,35 @@ func groupsFromRegex(rx, line string) map[string]string {
 
 	return result
 }
+
+// GetTypeIfExist return string inside field Type of struct
+func GetTypeIfExist(node Node) (Type *string, ok bool) {
+	switch v := node.(type) {
+	case *DeclRefExpr:
+		return &v.Type2, true
+	case *ArraySubscriptExpr:
+		return &v.Type, true
+	case *UnaryOperator:
+		return &v.Type, true
+	case *ParenExpr:
+		return &v.Type, true
+	case *BinaryOperator:
+		return &v.Type, true
+	case *ImplicitCastExpr:
+		return &v.Type, true
+	case *CStyleCastExpr:
+		return &v.Type, true
+	case *VAArgExpr:
+		return &v.Type, true
+	case *MemberExpr:
+		return &v.Type, true
+	case *CallExpr:
+		return &v.Type, true
+	case *CharacterLiteral:
+		return &v.Type, true
+	case *StringLiteral:
+		return &v.Type, true
+	}
+
+	return nil, false
+}
diff --git a/transpiler/cast.go b/transpiler/cast.go
index 769d216..7f3f562 100644
--- a/transpiler/cast.go
+++ b/transpiler/cast.go
@@ -40,6 +40,44 @@ func transpileImplicitCastExpr(n *ast.ImplicitCastExpr, p *program.Program, expr
 		expr = goast.NewIdent("nil")
 		return
 	}
+	if n.Kind == "IntegralToPointer" {
+		// ImplicitCastExpr 'double *' <IntegralToPointer>
+		// `-ImplicitCastExpr 'long' <LValueToRValue>
+		//   `-DeclRefExpr 'long' lvalue Var 0x30e91d8 'pnt' 'long'
+		if types.IsCPointer(n.Type) {
+			if t, ok := ast.GetTypeIfExist(n.Children()[0]); ok {
+				if types.IsCInteger(p, *t) {
+					resolveType := n.Type
+					resolveType, err = types.ResolveType(p, n.Type)
+					if err != nil {
+						return nil, "", nil, nil, err
+					}
+					expr = &goast.StarExpr{
+						X: &goast.ParenExpr{
+							X: &goast.CallExpr{
+								Fun: &goast.ParenExpr{X: goast.NewIdent("*" + resolveType)},
+								Args: []goast.Expr{
+									&goast.CallExpr{
+										Fun: goast.NewIdent("unsafe.Pointer"),
+										Args: []goast.Expr{
+											&goast.CallExpr{
+												Fun:  goast.NewIdent("uintptr"),
+												Args: []goast.Expr{expr},
+											},
+										},
+									},
+								},
+							},
+						},
+					}
+					p.GenerateWarningMessage(
+						fmt.Errorf("used unsafe convert from integer to pointer"), n)
+					exprType = n.Type
+					return
+				}
+			}
+		}
+	}
 
 	var cast bool = true
 	if in, ok := n.Children()[0].(*ast.IntegerLiteral); ok && in.Type == "int" {
@@ -76,9 +114,9 @@ func transpileImplicitCastExpr(n *ast.ImplicitCastExpr, p *program.Program, expr
 	}
 
 	// Convert from struct member array to slice
-	// ImplicitCastExpr 0x3662e28 <col:17, col:19> 'char *' <ArrayToPointerDecay>
-	// `-MemberExpr 0x3662d18 <col:17, col:19> 'char [20]' lvalue .input_str 0x3662ba0
-	//   `-DeclRefExpr 0x3662cf0 <col:17> 'struct s_inp':'struct s_inp' lvalue Var 0x3662c50 's' 'struct s_inp':'struct s_inp'
+	// ImplicitCastExpr 'char *' <ArrayToPointerDecay>
+	// `-MemberExpr 'char [20]' lvalue .input_str 0x3662ba0
+	//   `-DeclRefExpr 'struct s_inp':'struct s_inp' lvalue Var 0x3662c50 's' 'struct s_inp':'struct s_inp'
 	if types.IsCPointer(n.Type) {
 		if len(n.Children()) > 0 {
 			if memb, ok := n.Children()[0].(*ast.MemberExpr); ok && types.IsCArray(memb.Type) {
@@ -178,5 +216,33 @@ func transpileCStyleCastExpr(n *ast.CStyleCastExpr, p *program.Program, exprIsSt
 		}
 		exprType = n.Type
 	}
+
+	// CStyleCastExpr 'int' <PointerToIntegral>
+	// `-UnaryOperator 'long *' prefix '&'
+	//   `-DeclRefExpr 'long' lvalue Var 0x42b5268 'l' 'long'
+	//
+	// CStyleCastExpr 'int' <PointerToIntegral>
+	// `-ParenExpr 'long *'
+	//   `-UnaryOperator 'long *' prefix '&'
+	//     `-DeclRefExpr 'long' lvalue Var 0x38cb568 'l' 'long'
+	if len(n.Children()) > 0 {
+		if types.IsCInteger(p, n.Type) {
+			if t, ok := ast.GetTypeIfExist(n.Children()[0]); ok {
+				if types.IsPointer(*t) {
+					// main information	: https://go101.org/article/unsafe.html
+					var retType string
+					expr, retType = util.GetUintptrForSlice(expr)
+
+					expr, err = types.CastExpr(p, expr, retType, n.Type)
+					if err != nil {
+						return nil, "", nil, nil, err
+					}
+
+					exprType = n.Type
+				}
+			}
+		}
+	}
+
 	return
 }
diff --git a/transpiler/operators.go b/transpiler/operators.go
index e8adbba..ff1c92d 100644
--- a/transpiler/operators.go
+++ b/transpiler/operators.go
@@ -786,6 +786,9 @@ func atomicOperation(n ast.Node, p *program.Program) (
 		if _, ok := v.Children()[0].(*ast.IntegerLiteral); ok {
 			return
 		}
+		if v.Kind == "IntegralToPointer" {
+			return
+		}
 
 		// for case : overflow char
 		// ImplicitCastExpr 0x2027358 <col:6, col:7> 'char' <IntegralCast>
diff --git a/transpiler/unary.go b/transpiler/unary.go
index 133c924..8bd0013 100644
--- a/transpiler/unary.go
+++ b/transpiler/unary.go
@@ -431,46 +431,19 @@ func transpilePointerArith(n *ast.UnaryOperator, p *program.Program) (
 
 	var typesParentBefore []string
 	for i := range parents {
-		switch v := parents[i].(type) {
-		case *ast.ParenExpr:
-			typesParentBefore = append(typesParentBefore, v.Type)
-			v.Type = "int"
-		case *ast.BinaryOperator:
-			typesParentBefore = append(typesParentBefore, v.Type)
-			v.Type = "int"
-		case *ast.ImplicitCastExpr:
-			typesParentBefore = append(typesParentBefore, v.Type)
-			v.Type = "int"
-		case *ast.CStyleCastExpr:
-			typesParentBefore = append(typesParentBefore, v.Type)
-			v.Type = "int"
-		case *ast.VAArgExpr:
-			typesParentBefore = append(typesParentBefore, v.Type)
-			v.Type = "int"
-		case *ast.MemberExpr:
-			typesParentBefore = append(typesParentBefore, v.Type)
-			v.Type = "int"
-		default:
-			panic(fmt.Errorf("Not support parent type %T in pointer seaching", v))
+		if t, ok := ast.GetTypeIfExist(parents[i]); ok {
+			typesParentBefore = append(typesParentBefore, *t)
+			*t = "int"
+		} else {
+			panic(fmt.Errorf("Not support parent type %T in pointer seaching", parents[i]))
 		}
 	}
 	defer func() {
 		for i := range parents {
-			switch v := parents[i].(type) {
-			case *ast.ParenExpr:
-				v.Type = typesParentBefore[i]
-			case *ast.BinaryOperator:
-				v.Type = typesParentBefore[i]
-			case *ast.ImplicitCastExpr:
-				v.Type = typesParentBefore[i]
-			case *ast.CStyleCastExpr:
-				v.Type = typesParentBefore[i]
-			case *ast.VAArgExpr:
-				v.Type = typesParentBefore[i]
-			case *ast.MemberExpr:
-				v.Type = typesParentBefore[i]
-			default:
-				panic(fmt.Errorf("Not support parent type %T in pointer seaching", v))
+			if t, ok := ast.GetTypeIfExist(parents[i]); ok {
+				*t = typesParentBefore[i]
+			} else {
+				panic(fmt.Errorf("Not support parent type %T in pointer seaching", parents[i]))
 			}
 		}
 	}()
@@ -611,33 +584,12 @@ func transpileUnaryExprOrTypeTraitExpr(n *ast.UnaryExprOrTypeTraitExpr, p *progr
 		}
 
 		if t == "" {
-			switch ty := realFirstChild.(type) {
-			case *ast.DeclRefExpr:
-				t = ty.Type2
-
-			case *ast.ArraySubscriptExpr:
-				t = ty.Type
-
-			case *ast.MemberExpr:
-				t = ty.Type
-
-			case *ast.UnaryOperator:
-				t = ty.Type
-
-			case *ast.ParenExpr:
-				t = ty.Type
-
-			case *ast.CallExpr:
-				t = ty.Type
-
-			case *ast.CharacterLiteral:
-				t = ty.Type
-
-			case *ast.StringLiteral:
-				t = ty.Type
-
-			default:
-				panic(fmt.Sprintf("cannot do unary on: %#v", ty))
+			if node, ok := realFirstChild.(ast.Node); ok {
+				if ty, ok := ast.GetTypeIfExist(node); ok {
+					t = *ty
+				} else {
+					panic(fmt.Sprintf("cannot do unary on: %#v", realFirstChild))
+				}
 			}
 		}
 	}
diff --git a/types/cast.go b/types/cast.go
index db569b3..959938b 100644
--- a/types/cast.go
+++ b/types/cast.go
@@ -99,7 +99,7 @@ func CastExpr(p *program.Program, expr goast.Expr, cFromType, cToType string) (
 
 	// Only for "stddef.h"
 	if p.IncludeHeaderIsExists("stddef.h") {
-		if cFromType == "long" && cToType == "ptrdiff_t" {
+		if cFromType == "long long" && cToType == "ptrdiff_t" {
 			expr = &goast.BinaryExpr{
 				X:  expr,
 				Op: token.QUO,
diff --git a/util/goast.go b/util/goast.go
index 96f9ab9..142b1ca 100644
--- a/util/goast.go
+++ b/util/goast.go
@@ -305,10 +305,10 @@ func ConvertFunctionNameFromCtoGo(name string) string {
 // GetUintptrForSlice - return uintptr for slice
 // Example : uint64(uintptr(unsafe.Pointer((*(**int)(unsafe.Pointer(& ...slice... )))))))
 func GetUintptrForSlice(expr goast.Expr) (goast.Expr, string) {
-	returnType := "long"
+	returnType := "long long"
 
 	return &goast.CallExpr{
-		Fun:    goast.NewIdent("uint64"),
+		Fun:    goast.NewIdent("int64"),
 		Lparen: 1,
 		Args: []goast.Expr{&goast.CallExpr{
 			Fun:    goast.NewIdent("uintptr"),


Test patch:
diff --git a/tests/cast.c b/tests/cast.c
index 54929f3..6539e6a 100644
--- a/tests/cast.c
+++ b/tests/cast.c
@@ -91,26 +91,65 @@ void test_bool_to_int()
     is_eq(x, 11);
 }
 
-// void test_unsafe_pnt()
-// {
+
+// TODO:
+void test_unsafe_pnt()
+{
 	// (otri).orient = (int) ((unsigned long) (ptr) & (unsigned long) 3l);
-	// int pnt;
-	// long l = 42;
-	// pnt = (int) (&l);
-	// long *l_pnt = (long *)(l);
-	// is_eq(*l_pnt,42);
-// }
+	// {
+		// long pnt;
+		// double d = 42.0;
+		// double *dd = &d;
+		// long pnt2 = (long) (dd);
+		// pnt = pnt2;
+		// double *ddd = pnt;
+		// is_eq(*ddd, 42);
+		// (void)pnt;
+	// }
+	// {
+		// int pnt;
+		// long l = 42;
+		// pnt = (int)&l;
+		// long *l_pnt = (long *)(pnt);
+		// is_eq(*l_pnt,42);
+	// }
+	// {
+		// int pnt;
+		// long l = 42;
+		// pnt = (int) (&l);
+		// long *l_pnt = (long *)(pnt);
+		// is_eq(*l_pnt,42);
+	// }
+	{
+		void * pnt;
+		long l = 42;
+		long *d = &l;
+		pnt = d;
+		long l_pnt = 24;
+		l_pnt = *((long *)(pnt));
+		is_eq(l_pnt,42);
+		(void)pnt;
+	}
+	// {
+		// int pnt;
+		// long l = 42;
+		// long *d = &l;
+		// pnt = (int)(d);
+		// long *l_pnt = (long *)(pnt);
+		// is_eq(*l_pnt,42);
+	// }
+}
 
 int main()
 {
-    plan(33);
+    plan(34);
 
+	START_TEST(unsafe_pnt);
     START_TEST(bool_to_int);
     START_TEST(cast);
     START_TEST(castbool);
     START_TEST(vertex);
     START_TEST(strCh);
-	// START_TEST(unsafe_pnt);
 
     {
         typedef unsigned int u32;