Repository: Konstantin8105/c4go
Pull request #318 (2019-03-15 19:22:54)

simplification pointer arith

codecov[bot]: # [Codecov](https://codecov.io/gh/Konstantin8105/c4go/pull/318?src=pr&el=h1) Report
> Merging [#318](https://codecov.io/gh/Konstantin8105/c4go/pull/318?src=pr&el=desc) into [master](https://codecov.io/gh/Konstantin8105/c4go/commit/8fa0f3ab32a4f783901b7e2956e85e34810dfe48?src=pr&el=desc) will **decrease** coverage by `0.02%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/Konstantin8105/c4go/pull/318/graphs/tree.svg?width=650&token=esH2rHXlZ2&height=150&src=pr)](https://codecov.io/gh/Konstantin8105/c4go/pull/318?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #318      +/-   ##
==========================================
- Coverage    86.8%   86.78%   -0.03%     
==========================================
  Files         184      184              
  Lines       10451    10447       -4     
==========================================
- Hits         9072     9066       -6     
- Misses        970      971       +1     
- Partials      409      410       +1
```


| [Impacted Files](https://codecov.io/gh/Konstantin8105/c4go/pull/318?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [transpiler/binary.go](https://codecov.io/gh/Konstantin8105/c4go/pull/318/diff?src=pr&el=tree#diff-dHJhbnNwaWxlci9iaW5hcnkuZ28=) | `74.15% <100%> (+0.29%)` | :arrow_up: |
| [transpiler/unary.go](https://codecov.io/gh/Konstantin8105/c4go/pull/318/diff?src=pr&el=tree#diff-dHJhbnNwaWxlci91bmFyeS5nbw==) | `77.84% <0%> (-1.24%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/Konstantin8105/c4go/pull/318?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/Konstantin8105/c4go/pull/318?src=pr&el=footer). Last update [8fa0f3a...f5741b5](https://codecov.io/gh/Konstantin8105/c4go/pull/318?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/README.md b/README.md
index e1fb7cd..9c3fb31 100644
--- a/README.md
+++ b/README.md
@@ -249,15 +249,15 @@ func main() {
 	// C-pointer from array
 	a(i4)
 	b(i4, 2)
-	var i5 []int32 = *((*[]int32)(unsafe.Pointer(uintptr(i2[1]))))
+	var i5 []int32 = i2[1:]
 	// C-pointer from array
 	a(i5)
 	b(i5, 1)
-	var i6 []int32 = (*[100000000]int32)(unsafe.Pointer(&i5[0+1]))[:]
+	var i6 []int32 = i5[0+1:]
 	// pointer arithmetic
 	a(i6)
 	b(i6, 1)
-	var i7 []int32 = (*[100000000]int32)(unsafe.Pointer(&i5[1+0+0+0]))[:]
+	var i7 []int32 = i5[1+0+0+0:]
 	// pointer arithmetic
 	a(i7)
 	b(i7, 1)
diff --git a/transpiler/binary.go b/transpiler/binary.go
index d269e8f..5d2ab21 100644
--- a/transpiler/binary.go
+++ b/transpiler/binary.go
@@ -250,29 +250,19 @@ func transpileBinaryOperator(n *ast.BinaryOperator, p *program.Program, exprIsSt
 			}
 
 			if !haveSub {
-				var def string
-				def, err = types.GetDereferenceType(n.Type)
-				if err != nil {
-					return
-				}
 
 				fakeUnary := &ast.UnaryOperator{
 					Type:     n.Type,
-					Operator: "&",
+					Operator: "*",
 					ChildNodes: []ast.Node{
-						&ast.UnaryOperator{
-							Type:     def,
-							Operator: "*",
-							ChildNodes: []ast.Node{
-								n,
-							},
-						},
+						n,
 					},
 				}
 
 				var newPre, newPost []goast.Stmt
 				expr, eType, newPre, newPost, err =
-					transpileUnaryOperator(fakeUnary, p)
+					transpilePointerArith(fakeUnary, p)
+				eType = n.Type
 
 				if err != nil {
 					return
@@ -283,6 +273,14 @@ func transpileBinaryOperator(n *ast.BinaryOperator, p *program.Program, exprIsSt
 				preStmts, postStmts =
 					combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)
 
+				if ind, ok := expr.(*goast.IndexExpr); ok {
+					expr = &goast.SliceExpr{
+						X:      ind.X,
+						Low:    ind.Index,
+						Slice3: false,
+					}
+				}
+
 				return
 			}
 		}
diff --git a/transpiler/cast.go b/transpiler/cast.go
index 191a9a7..38011a8 100644
--- a/transpiler/cast.go
+++ b/transpiler/cast.go
@@ -46,7 +46,45 @@ func transpileImplicitCastExpr(n *ast.ImplicitCastExpr, p *program.Program, expr
 		//   `-DeclRefExpr 'long' lvalue Var 0x30e91d8 'pnt' 'long'
 		if util.IsCPointer(n.Type) {
 			if t, ok := ast.GetTypeIfExist(n.Children()[0]); ok {
-				if types.IsCInteger(p, *t) {
+				//
+				// ImplicitCastExpr 'char *' <IntegralToPointer>
+				// `-ImplicitCastExpr 'char' <LValueToRValue>
+				//   `-ArraySubscriptExpr 'char' lvalue
+				//     |-ImplicitCastExpr 'char *' <LValueToRValue>
+				//     | `-DeclRefExpr 'char *' lvalue Var 0x413c8a8 'b' 'char *'
+				//     `-IntegerLiteral 'int' 3
+				//
+				// n.Type = 'char *'
+				// *t     = 'char'
+				//
+
+				if ind, ok := expr.(*goast.IndexExpr); ok {
+					// from :
+					//
+					// 0  *ast.IndexExpr {
+					// 1  .  X: *ast.Ident {
+					// 3  .  .  Name: "b"
+					// 4  .  }
+					// 6  .  Index: *ast.BasicLit { ... }
+					// 12  }
+					//
+					// to:
+					//
+					// 88  0: *ast.SliceExpr {
+					// 89  .  X: *ast.Ident {
+					// 91  .  .  Name: "b"
+					// 93  .  }
+					// 95  .  Low: *ast.BasicLit { ... }
+					// 99  .  }
+					// 102  }
+					expr = &goast.SliceExpr{
+						X:      ind.X,
+						Low:    ind.Index,
+						Slice3: false,
+					}
+					exprType = n.Type
+					return
+				} else if types.IsCInteger(p, *t) {
 					resolveType := n.Type
 					resolveType, err = types.ResolveType(p, n.Type)
 					if err != nil {
@@ -74,43 +112,6 @@ func transpileImplicitCastExpr(n *ast.ImplicitCastExpr, p *program.Program, expr
 						fmt.Errorf("used unsafe convert from integer to pointer"), n)
 					exprType = n.Type
 					return
-				} else {
-					//
-					// ImplicitCastExpr 'char *' <IntegralToPointer>
-					// `-ImplicitCastExpr 'char' <LValueToRValue>
-					//   `-ArraySubscriptExpr 'char' lvalue
-					//     |-ImplicitCastExpr 'char *' <LValueToRValue>
-					//     | `-DeclRefExpr 'char *' lvalue Var 0x413c8a8 'b' 'char *'
-					//     `-IntegerLiteral 'int' 3
-					//
-					// n.Type = 'char *'
-					// *t     = 'char'
-					//
-
-					if ind, ok := expr.(*goast.IndexExpr); ok {
-						// from :
-						//
-						// 0  *ast.IndexExpr {
-						// 1  .  X: *ast.Ident {
-						// 3  .  .  Name: "b"
-						// 4  .  }
-						// 6  .  Index: *ast.BasicLit { ... }
-						// 12  }
-						//
-						// to:
-						//
-						// 88  0: *ast.SliceExpr {
-						// 89  .  X: *ast.Ident {
-						// 91  .  .  Name: "b"
-						// 93  .  }
-						// 95  .  Low: *ast.BasicLit { ... }
-						// 99  .  }
-						// 102  }
-						expr = &goast.SliceExpr{
-							X:   ind.X,
-							Low: ind.Index,
-						}
-					}
 				}
 			}
 		}
diff --git a/transpiler/unary.go b/transpiler/unary.go
index 8021275..f48a663 100644
--- a/transpiler/unary.go
+++ b/transpiler/unary.go
@@ -273,6 +273,34 @@ func transpileUnaryOperatorAmpersant(n *ast.UnaryOperator, p *program.Program) (
 		return
 	}
 
+	if ind, ok := expr.(*goast.IndexExpr); ok {
+		// from :
+		//
+		// 0  *ast.IndexExpr {
+		// 1  .  X: *ast.Ident {
+		// 3  .  .  Name: "b"
+		// 4  .  }
+		// 6  .  Index: *ast.BasicLit { ... }
+		// 12  }
+		//
+		// to:
+		//
+		// 88  0: *ast.SliceExpr {
+		// 89  .  X: *ast.Ident {
+		// 91  .  .  Name: "b"
+		// 93  .  }
+		// 95  .  Low: *ast.BasicLit { ... }
+		// 99  .  }
+		// 102  }
+		expr = &goast.SliceExpr{
+			X:      ind.X,
+			Low:    ind.Index,
+			Slice3: false,
+		}
+		eType = n.Type
+		return
+	}
+
 	// In : eType = 'int'
 	// Out: eType = 'int *'
 	// FIXME: This will need to use a real slice to reference the original
@@ -374,6 +402,8 @@ func pointerParts(node *ast.Node, p *program.Program) (
 			// type is not pointer
 			switch (*node).(type) {
 			case *ast.CallExpr,
+				*ast.ArraySubscriptExpr,
+				*ast.MemberExpr,
 				*ast.CStyleCastExpr:
 				return
 			}


Test patch:
diff --git a/tests/ap.c b/tests/ap.c
new file mode 100644
index 0000000..1024cc7
--- /dev/null
+++ b/tests/ap.c
@@ -0,0 +1,55 @@
+#include <stdio.h>
+#include "tests.h"
+
+// input argument - C-pointer
+void a(int *v1) { printf("a: %d\n",*v1); }
+
+// input argument - C-array
+void b(int v1[], int size) {
+	for (size-- ; size >= 0 ; size-- ) { printf("b: %d %d\n", size,  v1[size]); }
+}
+
+long get() {
+	return (long)(0);
+}
+
+int main() {
+    plan(0);
+
+	diag("value");
+	int i1 = 42; a(&i1); b(&i1, 1);
+
+	diag("C-array");
+	int i2[] = {11,22} ; a(i2); b(i2,2);
+	
+	diag("C-pointer from value");
+	int *i3 = &i1      ; a(i3); b(i3,1);
+	
+	diag("C-pointer from array");
+	int *i4 = i2       ; a(i4); b(i4,2);
+	
+	diag("C-pointer from array");
+	int *i5 =&i2[1]    ; a(i5); b(i5,1);
+	
+	diag("pointer arithmetic 1");
+	i5 = &i2[0];
+	int *i6 = i5 + 1   ; a(i6); b(i6,1);
+	
+	diag("pointer arithmetic 2");
+	int val = 2-2;
+	int *i7 = 1 + (1 - 1) + val + 0*(100-2) + i5 + 0 - 0*0; a(i7); b(i7,1);
+	
+	diag("pointer arithmetic 3");
+	int *i8 = i5 + 1 + 0 ; a(i8); b(i8,1);
+	
+	diag("pointer arithmetic 4");
+	int i9[] = {*i3, *(i3+1)} ; a(i9); b(i9,1);
+	
+	diag("pointer arithmetic 5");
+	int *i10 = 1 + 0 + i5 + 5*get() + get() + (12 + 3)*get(); a(i10); b(i10,1);
+	
+	diag("pointer arithmetic 6");
+	int *i11 = 1 + 0 + i5 + 5*get() + get() - (12 + 3)*get(); a(i11); b(i11,1);
+
+    done_testing();
+}
diff --git a/tests/array.c b/tests/array.c
index 7e53448..86f6d61 100644
--- a/tests/array.c
+++ b/tests/array.c
@@ -534,7 +534,7 @@ void test_string_array()
 
 int main()
 {
-    plan(174);
+    plan(180);
 
     test_parg_struct();
     START_TEST(struct_init);
@@ -750,6 +750,27 @@ int main()
             i++;
         }
     }
+    diag("Pointer to Pointer. 13");
+    {
+		struct temp_str{
+			double * qwe;
+		};
+		struct temp_str t;
+		double a[5] = { 10., 20., 30., 40., 50. };
+		t.qwe = &a[0];
+        double * ptr;
+        int i = 0;
+        for (ptr = &t.qwe[0]; i < 5; ptr++) {
+            is_eq(*ptr, t.qwe[i]);
+            i++;
+        }
+        for (ptr = t.qwe; i < 5; ptr++) {
+            is_eq(*ptr, t.qwe[i]);
+            i++;
+        }
+		ptr = 0 + t.qwe + 1;
+		is_eq(*ptr, t.qwe[1]);
+    }
     diag("Operation += 1 for double array");
     {
         float** m;
diff --git a/tests/code_quality/ap.expected.c b/tests/code_quality/ap.expected.c
index 1b3c33d..713310d 100644
--- a/tests/code_quality/ap.expected.c
+++ b/tests/code_quality/ap.expected.c
@@ -49,11 +49,11 @@ func main() {
 	// C-pointer from array
 	a(i4)
 	b(i4, 2)
-	var i5 []int32 = *((*[]int32)(unsafe.Pointer(uintptr(i2[1]))))
+	var i5 []int32 = i2[1:]
 	// C-pointer from array
 	a(i5)
 	b(i5, 1)
-	var i6 []int32 = (*[100000000]int32)(unsafe.Pointer(&i5[0+1]))[:]
+	var i6 []int32 = i5[0+1:]
 	// pointer arithmetic
 	a(i6)
 	b(i6, 1)
@@ -62,7 +62,7 @@ func main() {
 	// pointer arithmetic
 	a(i7)
 	b(i7, 1)
-	var i8 []int32 = (*[100000000]int32)(unsafe.Pointer(&i5[0+1+0]))[:]
+	var i8 []int32 = i5[0+1+0:]
 	// pointer arithmetic
 	a(i8)
 	b(i8, 1)
@@ -70,11 +70,11 @@ func main() {
 	// pointer arithmetic
 	a(i9)
 	b(i9, 1)
-	var i10 []int32 = (*[100000000]int32)(unsafe.Pointer(&i5[1+0+0+5*get()+get()+(12+3)*get()]))[:]
+	var i10 []int32 = i5[1+0+0+5*get()+get()+(12+3)*get():]
 	// pointer arithmetic
 	a(i10)
 	b(i10, 1)
-	var i11 []int32 = (*(*[1000000000]int32)(unsafe.Pointer(uintptr(unsafe.Pointer(&(*[100000000]int32)(unsafe.Pointer(&i5[1+0+0+5*get()+get()]))[:][0])) - (uintptr)((12+3)*get())*unsafe.Sizeof((*[100000000]int32)(unsafe.Pointer(&i5[1+0+0+5*get()+get()]))[:][0]))))[:]
+	var i11 []int32 = (*(*[1000000000]int32)(unsafe.Pointer(uintptr(unsafe.Pointer(&i5[1+0+0+5*get()+get():][0])) - (uintptr)((12+3)*get())*unsafe.Sizeof(i5[1+0+0+5*get()+get():][0]))))[:]
 	// pointer arithmetic
 	a(i11)
 	b(i11, 1)