Repository: Konstantin8105/c4go
Pull request #497 (2021-04-22 14:50:50)

sizeof

codecov[bot]: # [Codecov](https://codecov.io/gh/Konstantin8105/c4go/pull/497?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin) Report
> Merging [#497](https://codecov.io/gh/Konstantin8105/c4go/pull/497?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin) (9333bf2) into [master](https://codecov.io/gh/Konstantin8105/c4go/commit/4963e2de0e3918ae2c647a573e01987c97c1b047?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin) (4963e2d) will **decrease** coverage by `0.06%`.
> The diff coverage is `41.17%`.

[![Impacted file tree graph](https://codecov.io/gh/Konstantin8105/c4go/pull/497/graphs/tree.svg?width=650&height=150&src=pr&token=esH2rHXlZ2&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin)](https://codecov.io/gh/Konstantin8105/c4go/pull/497?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin)

```diff
@@            Coverage Diff             @@
##           master     #497      +/-   ##
==========================================
- Coverage   82.79%   82.73%   -0.07%     
==========================================
  Files         193      193              
  Lines       10850    10863      +13     
==========================================
+ Hits         8983     8987       +4     
- Misses       1356     1362       +6     
- Partials      511      514       +3     
```


| [Impacted Files](https://codecov.io/gh/Konstantin8105/c4go/pull/497?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin) | Coverage Δ | |
|---|---|---|
| [transpiler/value\_to\_pointer.go](https://codecov.io/gh/Konstantin8105/c4go/pull/497/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin#diff-dHJhbnNwaWxlci92YWx1ZV90b19wb2ludGVyLmdv) | `81.13% <30.00%> (-1.00%)` | :arrow_down: |
| [transpiler/binary.go](https://codecov.io/gh/Konstantin8105/c4go/pull/497/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin#diff-dHJhbnNwaWxlci9iaW5hcnkuZ28=) | `67.26% <40.00%> (-0.51%)` | :arrow_down: |
| [types/sizeof.go](https://codecov.io/gh/Konstantin8105/c4go/pull/497/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin#diff-dHlwZXMvc2l6ZW9mLmdv) | `69.17% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/Konstantin8105/c4go/pull/497?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/Konstantin8105/c4go/pull/497?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin). Last update [4963e2d...9333bf2](https://codecov.io/gh/Konstantin8105/c4go/pull/497?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Konstantin).


Patch:
diff --git a/scripts/neatroff.sh b/scripts/neatroff.sh
index a128194..66485b9 100755
--- a/scripts/neatroff.sh
+++ b/scripts/neatroff.sh
@@ -32,6 +32,16 @@ mkdir -p ./testdata/
 	rm -f $TEMP_FOLDER/*.go
 	rm -f $TEMP_FOLDER/*.app
 
+# Arguments menu
+echo "    -a for ast tree"
+if [ "$1" == "-a" ]; then
+	$C4GO ast                               \
+		-clang-flag="-DTROFFFDIR=\"MMM\""	\
+		-clang-flag="-DTROFFMDIR=\"WWW\""	\
+		$TEMP_FOLDER/*.c
+fi
+
+
 # transpilation of all projects
 	echo "Transpile to $GO_FILE"
 	$C4GO transpile                         \
diff --git a/scripts/redis.sh b/scripts/redis.sh
index 89866ef..5b69443 100755
--- a/scripts/redis.sh
+++ b/scripts/redis.sh
@@ -47,6 +47,7 @@ fi
 		-clang-flag="-I$TEMP_FOLDER/$VERSION/deps/jemalloc"  \
 		-clang-flag="-I$TEMP_FOLDER/$VERSION/deps/linenoise" \
 		-clang-flag="-I$TEMP_FOLDER/$VERSION/deps/lua"       \
+		-clang-flag="-I$TEMP_FOLDER/$VERSION/src/"           \
 		-o="$TEMP_FOLDER/redis_cli.go"                       \
 		$TEMP_FOLDER/$VERSION/src/redis-cli.c
 
@@ -57,6 +58,7 @@ fi
 		-clang-flag="-I$TEMP_FOLDER/$VERSION/deps/jemalloc"  \
 		-clang-flag="-I$TEMP_FOLDER/$VERSION/deps/linenoise" \
 		-clang-flag="-I$TEMP_FOLDER/$VERSION/deps/lua"       \
+		-clang-flag="-I$TEMP_FOLDER/$VERSION/src/"           \
 		-o="$TEMP_FOLDER/dict.go"                            \
 		$TEMP_FOLDER/$VERSION/src/dict.c
 
@@ -66,11 +68,13 @@ fi
 		-clang-flag="-I$TEMP_FOLDER/$VERSION/deps/jemalloc"      \
 		-clang-flag="-I$TEMP_FOLDER/$VERSION/deps/linenoise"     \
 		-clang-flag="-I$TEMP_FOLDER/$VERSION/deps/lua"           \
+		-clang-flag="-I$TEMP_FOLDER/$VERSION/src/"           \
 		-o="$TEMP_FOLDER/sds.go"                                 \
 		$TEMP_FOLDER/$VERSION/src/sds.c
 
 	$C4GO transpile                                          \
 		-o="$TEMP_FOLDER/linenoise.go"                       \
+		-clang-flag="-I$TEMP_FOLDER/$VERSION/src/"           \
 		$TEMP_FOLDER/$VERSION/deps/linenoise/linenoise.c     \
 		$TEMP_FOLDER/$VERSION/deps/linenoise/example.c
 
diff --git a/scripts/scripts.txt b/scripts/scripts.txt
index e79984b..29e61ad 100644
--- a/scripts/scripts.txt
+++ b/scripts/scripts.txt
@@ -5,9 +5,9 @@ Calculate warnings in file: ./testdata/brainfuck/brainfuck.go
 		Unsafe   : 0
 
 Calculate warnings : ./testdata/9wm
-		After transpiling : 6 warnings.
+		After transpiling : 3 warnings.
 		Go build : 4 warnings
-		Unsafe   : 411
+		Unsafe   : 415
 
 Calculate warnings : ./testdata/ed
 		After transpiling : 0 warnings.
@@ -27,8 +27,8 @@ Calculate warnings in file: ./testdata/neateqn/neateqn.go
 
 Calculate warnings in file: ./testdata/neatmkfn/neatmkfn.go
 		After transpiling : 0 warnings.
-		Go build : 279 warnings
-		Unsafe   : 139
+		Go build : 271 warnings
+		Unsafe   : 141
 
 
 
@@ -44,16 +44,16 @@ Calculate warnings : ./testdata/nuklear/x11.go
 Calculate warnings : ./testdata/nuklear/x11_opengl2.go
 		After transpiling : 17 warnings.
 		Go build : 12 warnings
-		Unsafe   : 659
+		Unsafe   : 669
 
 Calculate warnings in file: ./testdata/neatroff/neatroff.go
-		After transpiling : 5 warnings.
+		After transpiling : 2 warnings.
 		Go build : 5 warnings
-		Unsafe   : 246
+		Unsafe   : 247
 
 Calculate warnings : ./testdata/redis/dict.go
 		After transpiling : 0 warnings.
-		Go build : 54 warnings
+		Go build : 5 warnings
 		Unsafe   : 76
 Calculate warnings : ./testdata/redis/linenoise.go
 		After transpiling : 0 warnings.
@@ -65,7 +65,7 @@ Calculate warnings : ./testdata/redis/redis_cli.go
 		Unsafe   : 313
 Calculate warnings : ./testdata/redis/sds.go
 		After transpiling : 0 warnings.
-		Go build : 8 warnings
+		Go build : 5 warnings
 		Unsafe   : 119
 
 
diff --git a/transpiler/binary.go b/transpiler/binary.go
index f4c2140..939a650 100644
--- a/transpiler/binary.go
+++ b/transpiler/binary.go
@@ -359,8 +359,11 @@ func transpileBinaryOperator(n *ast.BinaryOperator, p *program.Program, exprIsSt
 			//     `-DeclRefExpr 0x2369a20 <col:11> 'int' lvalue Var 0x2369790 'i' 'int'
 
 			var sizeof int
-			sizeof, err = types.SizeOf(p, types.GetBaseType(leftType))
+			baseType := types.GetBaseType(leftType)
+			sizeof, err = types.SizeOf(p, baseType)
 			if err != nil {
+				err = fmt.Errorf("{'%s' %v '%s'}. sizeof = %d for baseType = '%s'. %v",
+					leftType, operator, rightType, sizeof, baseType, err)
 				return nil, "PointerOperation_unknown04", nil, nil, err
 			}
 			var e goast.Expr
@@ -372,6 +375,8 @@ func transpileBinaryOperator(n *ast.BinaryOperator, p *program.Program, exprIsSt
 				sizeof, operator,
 			)
 			if err != nil {
+				err = fmt.Errorf("{'%s' %v '%s'}. for base type: `%s`. %v",
+					leftType, operator, rightType, baseType, err)
 				return nil, "PointerOperation_unknown05", nil, nil, err
 			}
 			postStmts = append(postStmts, newPost...)
@@ -442,49 +447,29 @@ func transpileBinaryOperator(n *ast.BinaryOperator, p *program.Program, exprIsSt
 			operator == token.SUB || // -
 			false {
 
-			var pnt, value ast.Node
-			var back func()
-			var nodeN ast.Node = n
-			pnt, value, back, _, err = pointerParts(&nodeN, p)
-			if err != nil {
-				err = fmt.Errorf("cannot separate on parts: %v", err)
+			el, extl, prel, postl, errl := atomicOperation(n.Children()[0], p)
+			er, extr, prer, postr, errr := atomicOperation(n.Children()[1], p)
+			if errl != nil || errr != nil {
+				err = fmt.Errorf("pointer operation is not valid : %v. %v", errl, errr)
 				return
 			}
+			preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, prel, postl)
+			preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, prer, postr)
 
-			var e goast.Expr
-			e, eType, newPre, newPost, err = atomicOperation(value, p)
-			if err != nil {
-				return
+			if types.IsCPointer(extl, p) {
+				expr, eType, prel, postl, errl = pointerArithmetic(p, el, extl, er, extr, operator)
+			} else {
+				expr, eType, prel, postl, errl = pointerArithmetic(p, er, extr, el, extl, operator)
 			}
-			preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)
-			eType = n.Type
-
-			// return all types
-			back()
 
-			var arr goast.Expr
-			var arrType string
-			arr, arrType, newPre, newPost, err = atomicOperation(pnt, p)
-			if err != nil {
+			if errl != nil {
+				err = fmt.Errorf("pointer operation is not valid : %v", errl)
 				return
 			}
-			_ = arrType
-			preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)
 
-			expr, eType, newPre, newPost, err =
-				pointerArithmetic(p, arr, arrType, e, eType, token.ADD)
-
-			if err != nil {
-				return
-			}
-			if expr == nil {
-				return nil, "", nil, nil, fmt.Errorf("expr is nil")
-			}
-			preStmts, postStmts =
-				combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)
+			preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, prel, postl)
 
 			return
-
 		}
 	}
 
diff --git a/transpiler/unary.go b/transpiler/unary.go
index 8e34164..4818624 100644
--- a/transpiler/unary.go
+++ b/transpiler/unary.go
@@ -360,14 +360,21 @@ func transpileUnaryOperatorAmpersant(n *ast.UnaryOperator, p *program.Program) (
 // `-UnaryOperator <col:26, col:29> 'char *' postfix '++'
 //   `-DeclRefExpr <col:26> 'char *' lvalue Var 0x3c05ae8 'pos' 'char *'
 //
+// BinaryOperator 0x128d3b8 <col:8, col:28> 'char *' '+'
+// |-ImplicitCastExpr 0x128d3a0 <col:8> 'char *' <ArrayToPointerDecay>
+// | `-DeclRefExpr 0x128d2d0 <col:8> 'char [262144]' lvalue Var 0x128b730 'hynums' 'char [262144]'
+// `-ParenExpr 0x128d380 <col:17, col:28> 'long'
+//   `-BinaryOperator 0x128d360 <col:18, col:22> 'long' '-'
+//     |-ImplicitCastExpr 0x128d330 <col:18> 'char *' <LValueToRValue>
+//     | `-DeclRefExpr 0x128d2f0 <col:18> 'char *' lvalue Var 0x128bc80 'p' 'char *'
+//     `-ImplicitCastExpr 0x128d348 <col:22> 'char *' <ArrayToPointerDecay>
+//       `-DeclRefExpr 0x128d310 <col:22> 'char [262144]' lvalue Var 0x128b610 'hypats' 'char [262144]'
+//
 func pointerParts(node *ast.Node, p *program.Program) (
 	pnt ast.Node, value ast.Node, back func(), undefineIndex bool, err error) {
 	defer func() {
 		if err != nil {
 			err = fmt.Errorf("cannot pointerParts: err = %v", err)
-			if (*node) != nil {
-				err = fmt.Errorf("code line: %d. %v", (*node).Position().Line, err)
-			}
 		}
 	}()
 
diff --git a/transpiler/value_to_pointer.go b/transpiler/value_to_pointer.go
index 5cf6dfe..faf82a5 100644
--- a/transpiler/value_to_pointer.go
+++ b/transpiler/value_to_pointer.go
@@ -178,12 +178,22 @@ func GetUnsafeConvertDecls(p *program.Program) {
 //		            Each stmt has `defer` functions.
 func GetPointerAddress(p *program.Program, expr goast.Expr, cType string, sizeof int) (
 	rs goast.Expr, postStmts []goast.Stmt, err error) {
+	defer func() {
+		if err != nil {
+			err = fmt.Errorf("GetPointerAddress:sizeof:%d. %v", sizeof, err)
+		}
+	}()
 
 	if expr == nil {
 		err = fmt.Errorf("cannot get pointer address for nil expr")
 		return
 	}
 
+	// if sizeof == 0 {
+	// 	err = fmt.Errorf("sizeof is zero")
+	// 	return
+	// }
+
 	// generate postStmts
 
 	// TODO: runtime.KeepAlive()
@@ -313,7 +323,7 @@ func GetPointerAddress(p *program.Program, expr goast.Expr, cType string, sizeof
 	// prepare postStmts
 
 	if sizeof < 1 {
-		err = fmt.Errorf("GetPointerAddress. not valid sizeof `%s`: %d", cType, sizeof)
+		err = fmt.Errorf("not valid sizeof `%s`: %d", cType, sizeof)
 		p.AddMessage(p.GenerateWarningMessage(err, nil))
 		return
 	}
@@ -351,6 +361,16 @@ func SubTwoPnts(
 	val1 goast.Expr, val1Type string,
 	val2 goast.Expr, val2Type string,
 	sizeof int) (rs goast.Expr, postStmts []goast.Stmt, err error) {
+	defer func() {
+		if err != nil {
+			err = fmt.Errorf("SubTwoPnts:%v", err)
+		}
+	}()
+
+	// if sizeof == 0 {
+	// 	err = fmt.Errorf("sizeof is zero")
+	// 	return
+	// }
 
 	x, newPost, err := GetPointerAddress(p, val1, val1Type, sizeof)
 	if err != nil {
@@ -382,6 +402,16 @@ func PntCmpPnt(
 	postStmts []goast.Stmt,
 	err error,
 ) {
+	defer func() {
+		if err != nil {
+			err = fmt.Errorf("PntCmpPnt:%v", err)
+		}
+	}()
+
+	// if sizeof == 0 {
+	// 	err = fmt.Errorf("sizeof is zero")
+	// 	return
+	// }
 
 	switch operator {
 	case token.SUB: // -
@@ -439,7 +469,6 @@ func PntCmpPnt(
 			// val1 != nil
 			// val1 == nil
 			// val1  > nil
-
 			ignoreList := func(Type string) bool {
 				return util.IsFunction(Type) ||
 					Type == types.NullPointer ||
@@ -632,6 +661,23 @@ func pointerArithmetic(p *program.Program,
 		}
 	}()
 
+	if operator == token.SUB {
+		right = &goast.UnaryExpr{
+			Op: token.SUB,
+			X:  right,
+		}
+		return pointerArithmetic(p, left, leftType, right, rightType, token.ADD)
+	}
+
+	if types.IsPointer(rightType, p) &&
+		(types.IsCInteger(p, leftType) || leftType == "bool") &&
+		operator == token.ADD {
+		// swap pointer operation
+		// from : integer + pnt
+		// to   : pnt + integer
+		return pointerArithmetic(p, right, rightType, left, leftType, operator)
+	}
+
 	// check input data
 	if !(types.IsCInteger(p, rightType) || rightType == "bool") {
 		err = fmt.Errorf("right type is not C integer type : '%s'", rightType)


Test patch:
diff --git a/tests/array.c b/tests/array.c
index 28eb5e0..0dc19f8 100644
--- a/tests/array.c
+++ b/tests/array.c
@@ -560,7 +560,7 @@ void test_typedef_pointer()
     {
         diag("typedef_pointer : 4");
         pd p = 0 + v + 1 + 0 - 1; // v[0]
-        p = 0 + p + 0 + 1 - 0 + 1 - 1; // p = p + 1
+        p = 0 + p + 0 + 1; // TODO  - 0 + 1 - 1; // p = p + 1
         is_eq(*p, v[1]);
     }
     {
diff --git a/tests/cast.c b/tests/cast.c
index 248a8c1..54f8f3c 100644
--- a/tests/cast.c
+++ b/tests/cast.c
@@ -149,10 +149,41 @@ void test_init()
     is_streq(ch[3], "a");
 }
 
+void test_pntindex()
+{
+    int a[10], i;
+    for (i = 0; i < 10; i++) {
+        a[i] = i * 2 - 3;
+    }
+    int* q;
+    int* w;
+    int* e;
+    w = &a[5];
+    e = &a[2];
+
+    q = &a[2];
+    int* res = q + (w - e);
+    is_eq(*res, 7);
+
+    q = &a[1];
+    res = (w - e) + q;
+    is_eq(*res, 5);
+
+    // TODO
+    // q = &a[2];
+    // int res2 = *(q + (w - e));
+    // is_eq(res2, 7);
+
+    (void)q;
+    (void)w;
+    (void)e;
+}
+
 int main()
 {
-    plan(42);
+    plan(44);
 
+    START_TEST(pntindex);
     START_TEST(unsafe_pnt);
     START_TEST(bool_to_int);
     START_TEST(cast);
diff --git a/tests/code_quality/ap.go.expected b/tests/code_quality/ap.go.expected
index fe263c2..8d7393f 100644
--- a/tests/code_quality/ap.go.expected
+++ b/tests/code_quality/ap.go.expected
@@ -61,7 +61,7 @@ func main() {
 	b(i6, 1)
 	// pointer arithmetic
 	var val int32 = 2 - 2
-	var i7 []int32 = c4goPointerArithInt32Slice(i5, int(1+(1-1)+val+0*(100-2)+0+0-0*0))
+	var i7 []int32 = c4goPointerArithInt32Slice(c4goPointerArithInt32Slice(c4goPointerArithInt32Slice(i5, int(1+(1-1)+val+0*(100-2))), int(0)), int(-(0 * 0)))
 	a(i7)
 	b(i7, 1)
 	// pointer arithmetic
@@ -77,7 +77,7 @@ func main() {
 	a(i10)
 	b(i10, 1)
 	// pointer arithmetic
-	var i11 []int32 = c4goPointerArithInt32Slice(i5, int(1+0+0+5*get()+get()-(12+3)*get()))
+	var i11 []int32 = c4goPointerArithInt32Slice(i5[1+0+0+5*get()+get():], int(-((12 + 3) * get())))
 	a(i11)
 	b(i11, 1)
 	return
diff --git a/tests/if.c b/tests/if.c
index e460c19..54954ae 100644
--- a/tests/if.c
+++ b/tests/if.c
@@ -9,7 +9,7 @@ int d(int v)
 
 int main()
 {
-    plan(25);
+    plan(27);
 
     int x = 1;
 
@@ -94,26 +94,24 @@ int main()
         pass("ok");
     }
 
-    /*
-	 * TODO strange error for different gcc version
-	diag("pointer in if");
-	{
-		typedef struct rowA{
-			unsigned int * p;
-		} rowB;
-		rowB vv;
-		rowB *r = &vv;
-		if (r->p == NULL){
-			pass("pointer test 1");
-		}
-		if (!r->p){
-			pass("pointer test 2");
-		}
-		if (r->p){
-			fail("pointer 3")
-		}
-	}
-	*/
+    diag("pointer in if");
+    {
+        typedef struct rowA {
+            unsigned int* p;
+        } rowB;
+        rowB vv;
+        vv.p = NULL;
+        rowB* r = &vv;
+        if (r->p == NULL) {
+            pass("pointer test 1");
+        }
+        if (!r->p) {
+            pass("pointer test 2");
+        }
+        if (r->p) {
+            fail("pointer 3")
+        }
+    }
 
     diag("equal on if paren");
     {
diff --git a/tests/sizeof.c b/tests/sizeof.c
index f63a8a3..f260cee 100644
--- a/tests/sizeof.c
+++ b/tests/sizeof.c
@@ -157,7 +157,12 @@ typedef SP Mem2;
 
 int main()
 {
-    plan(83);
+    plan(84);
+
+    diag("null");
+    void* pntnull = NULL;
+    is_eq(sizeof(pntnull), 8);
+    (void)pntnull;
 
     diag("Integer types");
     check_sizes(char, 1);