Procházet zdrojové kódy

Merge pull request #1166 from seanyoung/fixes

Fix --math-overflow flag and add tests
Sean Young před 2 roky
rodič
revize
2ea996160f

+ 17 - 0
integration/solana/overflow.sol

@@ -0,0 +1,17 @@
+contract overflow {
+	function addu32(uint32 a, uint32 b) public pure returns (uint32 c) {
+		c = a + b;
+	}
+
+	function subu32(uint32 a, uint32 b) public pure returns (uint32 c) {
+		c = a - b;
+	}
+
+	function mulu32(uint32 a, uint32 b) public pure returns (uint32 c) {
+		c = a * b;
+	}
+
+	function powu32(uint32 a, uint32 b) public pure returns (uint32 c) {
+		c = a ** b;
+	}
+}

+ 33 - 0
integration/solana/overflow.spec.ts

@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: Apache-2.0
+
+import expect from 'expect';
+import { loadContract } from './setup';
+import { BN } from '@project-serum/anchor';
+
+describe('Testing math overflow', function () {
+    this.timeout(500000);
+
+    it('overflow', async function () {
+        let { program } = await loadContract('overflow');
+
+        let res = await program.methods.addu32(new BN(1), new BN(3)).view();
+        expect(res).toEqual(4);
+
+        await expect(program.methods.addu32(new BN(2147483648), new BN(2147483648)).view()).rejects.toThrow();
+
+        res = await program.methods.subu32(new BN(7), new BN(3)).view();
+        expect(res).toEqual(4);
+
+        await expect(program.methods.subu32(new BN(2147483640), new BN(2147483648)).view()).rejects.toThrow();
+
+        res = await program.methods.mulu32(new BN(7), new BN(3)).view();
+        expect(res).toEqual(21);
+
+        await expect(program.methods.mulu32(new BN(2147483640), new BN(2147483648)).view()).rejects.toThrow();
+
+        res = await program.methods.powu32(new BN(7), new BN(3)).view();
+        expect(res).toEqual(343);
+
+        await expect(program.methods.powu32(new BN(2147483640), new BN(2147483648)).view()).rejects.toThrow();
+    });
+});

+ 1 - 1
integration/solana/package.json

@@ -4,7 +4,7 @@
   "description": "Integration tests with Solang and Solana",
   "scripts": {
     "test": "tsc; ts-node setup.ts; mocha --parallel *.spec.ts",
-    "build": "solang compile  *.sol --target solana -v"
+    "build": "solang compile *.sol --target solana -v; solang compile --math-overflow overflow.sol --target solana -v"
   },
   "author": "Sean Young <sean@mess.org>",
   "license": "MIT",

+ 24 - 17
src/bin/solang.rs

@@ -93,6 +93,7 @@ fn main() {
                         Arg::new("STD-JSON")
                             .help("mimic solidity json output on stdout")
                             .conflicts_with_all(["VERBOSE", "OUTPUT", "EMIT"])
+                            .action(ArgAction::SetTrue)
                             .long("standard-json"),
                     )
                     .arg(
@@ -167,19 +168,22 @@ fn main() {
                         Arg::new("MATHOVERFLOW")
                             .help("Enable math overflow checking")
                             .long("math-overflow")
+                            .action(ArgAction::SetTrue)
                             .display_order(6),
                     )
                     .arg(
                         Arg::new("LOGAPIRETURNS")
                             .help("Log the return codes of runtime API calls in the environment")
                             .long("log-api-return-codes")
-                            .action(ArgAction::SetTrue),
+                            .action(ArgAction::SetTrue)
+                            .display_order(7),
                     )
                     .arg(
                         Arg::new("GENERATEDEBUGINFORMATION")
                             .help("Enable generating debug information for LLVM IR")
                             .short('g')
                             .long("generate-debug-info")
+                            .action(ArgAction::SetTrue)
                             .hide(true),
                     ),
             )
@@ -332,7 +336,7 @@ fn doc(matches: &ArgMatches) {
     let target = target_arg(matches);
     let mut resolver = imports_arg(matches);
 
-    let verbose = *matches.get_one::<bool>("VERBOSE").unwrap();
+    let verbose = *matches.get_one("VERBOSE").unwrap();
     let mut success = true;
     let mut files = Vec::new();
 
@@ -366,7 +370,7 @@ fn doc(matches: &ArgMatches) {
 fn compile(matches: &ArgMatches) {
     let target = target_arg(matches);
 
-    let verbose = *matches.get_one::<bool>("VERBOSE").unwrap();
+    let verbose = *matches.get_one("VERBOSE").unwrap();
     let mut json = JsonResult {
         errors: Vec::new(),
         target: target.to_string(),
@@ -378,11 +382,11 @@ fn compile(matches: &ArgMatches) {
         eprintln!("info: Solang version {}", env!("SOLANG_VERSION"));
     }
 
-    let math_overflow_check = matches.contains_id("MATHOVERFLOW");
+    let math_overflow_check = *matches.get_one("MATHOVERFLOW").unwrap();
 
-    let generate_debug_info = matches.contains_id("GENERATEDEBUGINFORMATION");
+    let generate_debug_info = *matches.get_one("GENERATEDEBUGINFORMATION").unwrap();
 
-    let log_api_return_codes = *matches.get_one::<bool>("LOGAPIRETURNS").unwrap();
+    let log_api_return_codes = *matches.get_one("LOGAPIRETURNS").unwrap();
 
     let mut resolver = imports_arg(matches);
 
@@ -395,14 +399,14 @@ fn compile(matches: &ArgMatches) {
     };
 
     let opt = Options {
-        dead_storage: *matches.get_one::<bool>("DEADSTORAGE").unwrap(),
-        constant_folding: *matches.get_one::<bool>("CONSTANTFOLDING").unwrap(),
-        strength_reduce: *matches.get_one::<bool>("STRENGTHREDUCE").unwrap(),
-        vector_to_slice: *matches.get_one::<bool>("VECTORTOSLICE").unwrap(),
+        dead_storage: *matches.get_one("DEADSTORAGE").unwrap(),
+        constant_folding: *matches.get_one("CONSTANTFOLDING").unwrap(),
+        strength_reduce: *matches.get_one("STRENGTHREDUCE").unwrap(),
+        vector_to_slice: *matches.get_one("VECTORTOSLICE").unwrap(),
         math_overflow_check,
         generate_debug_information: generate_debug_info,
         common_subexpression_elimination: *matches
-            .get_one::<bool>("COMMONSUBEXPRESSIONELIMINATION")
+            .get_one("COMMONSUBEXPRESSIONELIMINATION")
             .unwrap(),
         opt_level,
         log_api_return_codes,
@@ -425,8 +429,10 @@ fn compile(matches: &ArgMatches) {
         exit(0);
     }
 
+    let std_json = *matches.get_one("STD-JSON").unwrap();
+
     if errors {
-        if matches.contains_id("STD-JSON") {
+        if std_json {
             println!("{}", serde_json::to_string(&json).unwrap());
             exit(0);
         } else {
@@ -435,7 +441,7 @@ fn compile(matches: &ArgMatches) {
         }
     }
 
-    if matches.contains_id("STD-JSON") {
+    if std_json {
         println!("{}", serde_json::to_string(&json).unwrap());
     }
 }
@@ -466,7 +472,8 @@ fn process_file(
     json: &mut JsonResult,
     opt: &Options,
 ) -> Result<Namespace, ()> {
-    let verbose = *matches.get_one::<bool>("VERBOSE").unwrap();
+    let verbose = *matches.get_one("VERBOSE").unwrap();
+    let std_json = *matches.get_one("STD-JSON").unwrap();
 
     let mut json_contracts = HashMap::new();
 
@@ -476,7 +483,7 @@ fn process_file(
     // codegen all the contracts; some additional errors/warnings will be detected here
     codegen(&mut ns, opt);
 
-    if matches.contains_id("STD-JSON") {
+    if std_json {
         let mut out = ns.diagnostics_as_json(resolver);
         json.errors.append(&mut out);
     } else {
@@ -546,7 +553,7 @@ fn process_file(
 
         let code = binary.code(Generate::Linked).expect("llvm build");
 
-        if matches.contains_id("STD-JSON") {
+        if std_json {
             json_contracts.insert(
                 binary.name.to_owned(),
                 JsonContract {
@@ -595,7 +602,7 @@ fn process_file(
 }
 
 fn save_intermediates(binary: &solang::emit::binary::Binary, matches: &ArgMatches) -> bool {
-    let verbose = *matches.get_one::<bool>("VERBOSE").unwrap();
+    let verbose = *matches.get_one("VERBOSE").unwrap();
 
     match matches.get_one::<String>("EMIT").map(|v| v.as_str()) {
         Some("llvm-ir") => {

+ 12 - 8
src/codegen/cfg.rs

@@ -610,13 +610,15 @@ impl ControlFlowGraph {
                     .collect::<Vec<String>>()
                     .join(", ")
             ),
-            Expression::Add(_, _, _, l, r) => format!(
-                "({} + {})",
+            Expression::Add(_, _, unchecked, l, r) => format!(
+                "({}{} + {})",
+                if *unchecked { "unchecked " } else { "" },
                 self.expr_to_string(contract, ns, l),
                 self.expr_to_string(contract, ns, r)
             ),
-            Expression::Subtract(_, _, _, l, r) => format!(
-                "({} - {})",
+            Expression::Subtract(_, _, unchecked, l, r) => format!(
+                "({}{} - {})",
+                if *unchecked { "unchecked " } else { "" },
                 self.expr_to_string(contract, ns, l),
                 self.expr_to_string(contract, ns, r)
             ),
@@ -645,8 +647,9 @@ impl ControlFlowGraph {
                 self.expr_to_string(contract, ns, l),
                 self.expr_to_string(contract, ns, r)
             ),
-            Expression::Multiply(_, _, _, l, r) => format!(
-                "({} * {})",
+            Expression::Multiply(_, _, unchecked, l, r) => format!(
+                "({}{} * {})",
+                if *unchecked { "unchecked " } else { "" },
                 self.expr_to_string(contract, ns, l),
                 self.expr_to_string(contract, ns, r)
             ),
@@ -670,8 +673,9 @@ impl ControlFlowGraph {
                 self.expr_to_string(contract, ns, l),
                 self.expr_to_string(contract, ns, r)
             ),
-            Expression::Power(_, _, _, l, r) => format!(
-                "({} ** {})",
+            Expression::Power(_, _, unchecked, l, r) => format!(
+                "({}{} ** {})",
+                if *unchecked { "unchecked " } else { "" },
                 self.expr_to_string(contract, ns, l),
                 self.expr_to_string(contract, ns, r)
             ),

+ 2 - 2
tests/codegen_testcases/solidity/common_subexpression_elimination.sol

@@ -40,7 +40,7 @@ contract c1 {
         // CHECK: ty:int256 %d = (%x * %1.cse_temp)
         // CHECK: ty:int256 %2.cse_temp = (%x + %d)
         // CHECK: ty:int256 %3.cse_temp = ((arg #0) - (arg #1))
-        // CEHCK: branchcond (signed more %2.cse_temp > int256 0), block1, block2
+        // CHECK: branchcond (signed more %2.cse_temp > int256 0), block1, block2
         if (x + d > 0) {
 			int t = a-b;
             // CHECK: ty:int256 %t = %3.cse_temp
@@ -162,7 +162,7 @@ contract c1 {
         // CHECK: ty:int256 %d = (%x * %1.cse_temp)
         // CHECK: ty:int256 %2.cse_temp = (%x + %d)
         // CHECK: ty:int256 %3.cse_temp = ((arg #0) - (arg #1))
-        // CEHCK: branchcond (%2.cse_temp > int256 0), block1, block2
+        // CHECK: branchcond (signed more %2.cse_temp > int256 0), block1, block2
         if (x + d > 0) {
 			int t = a-b;
             // CHECK: ty:int256 %t = %3.cse_temp

+ 4 - 4
tests/codegen_testcases/solidity/dead_storage.sol

@@ -137,8 +137,8 @@ contract deadstorage {
         return test11var[index] + test11var[index2];
     }
 
-// CHECK: load storage slot((uint256 8
-// CHECK: load storage slot((uint256 8
+// CHECK: load storage slot((unchecked uint256 8
+// CHECK: load storage slot((unchecked uint256 8
 
 // BEGIN-CHECK: deadstorage::function::test12
     // one load needed for this
@@ -147,8 +147,8 @@ contract deadstorage {
         return test12var[index] + test12var[index];
 
     }
-// CHECK: load storage slot((uint256 19
-// NOT-CHECK: load storage slot((uint256 19
+// CHECK: load storage slot((unchecked uint256 19
+// NOT-CHECK: load storage slot((unchecked uint256 19
 }
 
 contract foo {

+ 1 - 1
tests/codegen_testcases/solidity/unused_variable_elimination.sol

@@ -115,7 +115,7 @@ return 3;
         it2 = 1;
 
         return 2;
-// CHECK: store storage slot((%t2 + uint256 0)) ty:int256 =
+// CHECK: store storage slot((unchecked %t2 + uint256 0)) ty:int256 =
 // CHECK: store storage slot(uint256 2) ty:int256 =
 // NOT-CHECK: ty:struct c1.testStruct %t3 = struct { int256 1, int256 2 }
 // NOT-CHECK: alloc int256[] len uint32 5

+ 13 - 13
tests/codegen_testcases/yul/binary_arithmetic_builtins.sol

@@ -4,31 +4,31 @@ contract testing {
 // BEGIN-CHECK: testing::testing::function::add_sub_mul__int16_int32_uint256_uint128
     function add_sub_mul(int16 a, int32 b, uint256 c, uint128 d) public pure {
         assembly {
-            // CHECK: ty:uint256 %e = (sext uint256 ((sext int32 (arg #0)) + (arg #1)))
+            // CHECK: ty:uint256 %e = (sext uint256 (unchecked (sext int32 (arg #0)) + (arg #1)))
             let e := add(a, b)
 
-            // CHECK: ty:uint256 %f = uint256(((sext int256 (arg #1)) + int256((arg #2))))
+            // CHECK: ty:uint256 %f = uint256((unchecked (sext int256 (arg #1)) + int256((arg #2))))
             let f := add(b, c)
 
-            // CHECK: ty:uint256 %g = ((arg #2) + (zext uint256 (arg #3)))
+            // CHECK: ty:uint256 %g = (unchecked (arg #2) + (zext uint256 (arg #3)))
             let g := add(c, d)
 
-            // CHECK: ty:uint256 %h = (sext uint256 ((sext int136 (arg #0)) + (zext int136 (arg #3))))
+            // CHECK: ty:uint256 %h = (sext uint256 (unchecked (sext int136 (arg #0)) + (zext int136 (arg #3))))
             let h := add(a, d)
 
-            // CHECK: ty:uint256 %i = uint256(((sext int256 (arg #0)) + int256((arg #2))))
+            // CHECK: ty:uint256 %i = uint256((unchecked (sext int256 (arg #0)) + int256((arg #2))))
             let i := add(a, c)
 
-            // CHECK: ty:uint256 %j = (sext uint256 ((sext int136 (arg #1)) + (zext int136 (arg #3))))
+            // CHECK: ty:uint256 %j = (sext uint256 (unchecked (sext int136 (arg #1)) + (zext int136 (arg #3))))
             let j := add(b, d)
 
-            // CHECK: ty:int32 %k = ((sext int32 (arg #0)) - (arg #1))
+            // CHECK: ty:int32 %k = (unchecked (sext int32 (arg #0)) - (arg #1))
             let k : s32 := sub(a, b)
 
-            // CHECK: ty:int256 %l = int256(((arg #2) - (zext uint256 (arg #3))))
+            // CHECK: ty:int256 %l = int256((unchecked (arg #2) - (zext uint256 (arg #3))))
             let l : s256 := sub(c, d)
 
-            // CHECK: ty:uint256 %m = ((arg #2) * (zext uint256 (arg #3)))
+            // CHECK: ty:uint256 %m = (unchecked (arg #2) * (zext uint256 (arg #3)))
             let m := mul(c, d)
 
             // CHECK: ty:uint256 %n = uint256 43981
@@ -49,13 +49,13 @@ contract testing {
             // CHECK: ty:bool %s = true
             let s : bool := true
 
-            // CHECK: ty:uint256 %t = (uint256 22193982385802470 + uint256(false))
+            // CHECK: ty:uint256 %t = (unchecked uint256 22193982385802470 + uint256(false))
             let t := add(q, r)
 
             // CHECK: ty:uint256 %u = uint256 -1
             let u := sub(false, true)
 
-            // CHECK: ty:uint256 %v = uint256((true + false))
+            // CHECK: ty:uint256 %v = uint256((unchecked true + false))
             let v := add(s, r)
         }
     }
@@ -74,7 +74,7 @@ contract testing {
             // CHECK: block3: # endif
             // CHECK: # phis: temp.49
             // CHECK: ty:uint256 %e = %temp.49
-            
+
             let f := sdiv(c, d)
             // CHECK: branchcond ((arg #3) == int256 0), block4, block5
             // CHECK: block4: # then
@@ -117,7 +117,7 @@ contract testing {
 // BEGIN-CHECK: testing::testing::function::exponential__int128_int8
     function exponential(int128 a, int8 b) public pure {
         assembly {
-            // CHECK: ty:uint256 %x = (sext uint256 ((arg #0) ** (sext int128 (arg #1))))
+            // CHECK: ty:uint256 %x = (sext uint256 (unchecked (arg #0) ** (sext int128 (arg #1))))
             let x := exp(a, b)
         }
     }

+ 5 - 5
tests/codegen_testcases/yul/expression.sol

@@ -58,10 +58,10 @@ contract testing {
 // BEGIN-CHECK: testing::testing::function::yulLocalVariable__uint256
     function yulLocalVariable(uint256 a) public pure {
         assembly {
-            // CHECK: ty:uint256 %x = (uint256 2 + (arg #0))
+            // CHECK: ty:uint256 %x = (unchecked uint256 2 + (arg #0))
             let x := add(2, a)
 
-            // CHECK: ty:uint256 %y = (uint256 2 + (arg #0))
+            // CHECK: ty:uint256 %y = (unchecked uint256 2 + (arg #0))
             let y := x
         }
     }
@@ -166,14 +166,14 @@ contract testing {
                 let y := 9
             }
 
-            // CHECK: ty:int32 %k = (trunc int32 ((zext uint256 (arg #0)) + uint256 2))
+            // CHECK: ty:int32 %k = (trunc int32 (unchecked (zext uint256 (arg #0)) + uint256 2))
             let k : s32 := add(a, 2)
 
-            // CHECK: %ret.temp.58 = call testing::yul_function_0::get (sext uint256 (trunc int32 ((zext uint256 (arg #0)) + uint256 2)))
+            // CHECK: %ret.temp.58 = call testing::yul_function_0::get (sext uint256 (trunc int32 (unchecked (zext uint256 (arg #0)) + uint256 2)))
             let x := get(k)
             // CHECK: ty:uint256 %x = %ret.temp.58
 
-            // CHECK: %ret1.temp.59, %ret2.temp.60 = call testing::yul_function_2::multipleReturns %x, (trunc int32 ((zext uint256 (arg #0)) + uint256 2))
+            // CHECK: %ret1.temp.59, %ret2.temp.60 = call testing::yul_function_2::multipleReturns %x, (trunc int32 (unchecked (zext uint256 (arg #0)) + uint256 2))
             let l, m := multipleReturns(x, k)
             // CHECK: ty:uint256 %l = (zext uint256 %ret1.temp.59)
             // CHECK: ty:uint256 %m = (sext uint256 %ret2.temp.60)

+ 2 - 2
tests/codegen_testcases/yul/functions.sol

@@ -13,7 +13,7 @@ contract testing {
                 if lt(x, 2) {
                     // CHECK: block1: # then
                     x := sub(a, b)
-                    // CHECK: ty:uint256 %x = ((arg #0) - (arg #1))
+                    // CHECK: ty:uint256 %x = (unchecked (arg #0) - (arg #1))
                     leave
                     // CHECK: return
                 }
@@ -30,7 +30,7 @@ contract testing {
                 if lt(a, 2) {
                     // CHECK: block1: # then
                     ret1 := add(sub(a,b), mul(shr(a, 2), 3))
-                    // CHECK: ty:uint256 %ret1 = uint256(((int256((arg #0)) - (sext int256 (arg #1))) + int256(((uint256 2 >> (arg #0)) * uint256 3))))
+                    // CHECK: ty:uint256 %ret1 = uint256((unchecked (unchecked int256((arg #0)) - (sext int256 (arg #1))) + int256((unchecked (uint256 2 >> (arg #0)) * uint256 3))))
                     leave
                     // CHECK: return %ret1
                 }

+ 26 - 26
tests/codegen_testcases/yul/statements.sol

@@ -15,7 +15,7 @@ contract testing {
             // CHECK: assert-failure
             invalid()
 
-            // NOT-CHECK: ty:uint256 %x = 
+            // NOT-CHECK: ty:uint256 %x =
             let x := mul(a, b)
         }
     }
@@ -26,10 +26,10 @@ contract testing {
             // CHECK: ty:uint256 %x = (sext uint256 ((sext int24 (arg #1)) >> (zext int24 (arg #0))))
             let x := shr(a, b)
             {
-                // CHECK: ty:uint256 %y = ((sext uint256 ((sext int24 (arg #1)) >> (zext int24 (arg #0)))) * (zext uint256 (arg #0)))
+                // CHECK: ty:uint256 %y = (unchecked (sext uint256 ((sext int24 (arg #1)) >> (zext int24 (arg #0)))) * (zext uint256 (arg #0)))
                 let y := mul(x, a)
 
-                // CHECK: ty:uint8 %g = uint8((unsigned less int256(((sext uint256 ((sext int24 (arg #1)) >> (zext int24 (arg #0)))) * (zext uint256 (arg #0)))) < (sext int256 (arg #1))))
+                // CHECK: ty:uint8 %g = uint8((unsigned less int256((unchecked (sext uint256 ((sext int24 (arg #1)) >> (zext int24 (arg #0)))) * (zext uint256 (arg #0)))) < (sext int256 (arg #1))))
                 let g : u8 := lt(y, b)
             }
         }
@@ -58,7 +58,7 @@ contract testing {
 
             // CHECK: ty:uint256 %f = uint256(((arg #0) == bool 0))
             let f := iszero(a)
-            
+
 
             // CHECK: ty:uint256 %g = undef
             // CHECK: ty:uint256 %h = undef
@@ -74,7 +74,7 @@ contract testing {
             // CHECK: branchcond (arg #0), block1, block2
             if a {
             // CHECK: block1: # then
-            // CHECK: ty:uint256 %x = (uint256((arg #0)) + uint256 5)
+            // CHECK: ty:uint256 %x = (unchecked uint256((arg #0)) + uint256 5)
                 x := add(a, x)
 
                 // CHECK: ty:bool %a = false
@@ -135,10 +135,10 @@ contract testing {
                 let i := 1
             // CHECK: branch block1
             // CHECK: block1: # cond
-            // CHECK: branchcond (uint256 0 != (%i + uint256 1)), block3, block4
+            // CHECK: branchcond (uint256 0 != (unchecked %i + uint256 1)), block3, block4
             } add(i, 1) {
                 // CHECK: block2: # next
-                // CHECK: ty:uint256 %i = (%i - uint256 1)
+                // CHECK: ty:uint256 %i = (unchecked %i - uint256 1)
                 i := sub(i, 1)
                 // CHECK: branch block1
             } {
@@ -158,7 +158,7 @@ contract testing {
             } lt(i, 10) {
                 // CHECK: block6: # next
                 i := add(i, 1)
-                // CHECK: ty:uint256 %i.27 = (%i.27 + uint256 1)
+                // CHECK: ty:uint256 %i.27 = (unchecked %i.27 + uint256 1)
                 // CHECK: branch block5
             } {
                 // CHECK: block7: # body
@@ -176,13 +176,13 @@ contract testing {
                 // CHECK: branchcond %a, block11, block12
             } a {
                 // CHECK: block10: # next
-                // CHECK: ty:uint256 %i.28 = (uint256(%a) + uint256 1)
+                // CHECK: ty:uint256 %i.28 = (unchecked uint256(%a) + uint256 1)
                 i := add(a, 1)
                 // CHECK: ty:bool %a = false
                 a := false
             } {
                 // CHECK: block11: # body
-                // CHECK: ty:bool %a = (uint256 0 != (%i.28 + uint256 2))
+                // CHECK: ty:bool %a = (uint256 0 != (unchecked %i.28 + uint256 2))
                 a := add(i, 2)
                 // CHECK: branch block10
             }
@@ -196,7 +196,7 @@ contract testing {
                 // CHECK: branchcond (uint256 2 == uint256 0), block15, block16
             } eq(i, 0) {
                 // CHECK: block14: # next
-                // NOT-CHECK: ty:uint256 %i.29 = 
+                // NOT-CHECK: ty:uint256 %i.29 =
                 i := sub(i, 2)
             } {
                 // CHECK: block15: # body
@@ -236,7 +236,7 @@ contract testing {
             } lt(i, 10) {
                 // CHECK: block22: # next
                 i := add(i, 1)
-                // CHECK: ty:uint256 %i.31 = (%i.31 + uint256 1)
+                // CHECK: ty:uint256 %i.31 = (unchecked %i.31 + uint256 1)
                 // CHECK: branch block21
             } {
                 // CHECK: block23: # body
@@ -253,12 +253,12 @@ contract testing {
                     // CHECK: block25: # cond
                     // CHECK: branchcond (unsigned less %j.32 < uint256 10), block27, block28
                 } lt(j, 10) {
-                    // CHECK: ty:uint256 %j.32 = (%j.32 + uint256 1)
+                    // CHECK: ty:uint256 %j.32 = (unchecked %j.32 + uint256 1)
                     j := add(j, 1)
                     // CHECK: branch block25
                 } {
                     // CHECK: block27: # body
-                    // CHECK: ty:bool %a = (uint256 0 != (%i.31 + %j.32))
+                    // CHECK: ty:bool %a = (uint256 0 != (unchecked %i.31 + %j.32))
                     a := add(i, j)
                     // CHECK: branch block26
                 }
@@ -288,7 +288,7 @@ contract testing {
             // CHECK: branchcond (unsigned less %i < uint256 10), block3, block4
             } lt(i, 10) {i := add(i, 1)
             // CHECK: block2: # next
-            // CHECK: ty:uint256 %i = (%i + uint256 1)
+            // CHECK: ty:uint256 %i = (unchecked %i + uint256 1)
             // CHECK: branch block1
             } {
                 // CHECK: block3: # body
@@ -323,7 +323,7 @@ contract testing {
             } lt(i, 10) {
                 // CHECK: block2: # next
                 i := add(i, 1)
-                // CHECK: ty:uint256 %i = (%i + uint256 1)
+                // CHECK: ty:uint256 %i = (unchecked %i + uint256 1)
                 // CHECK: branch block1
             } {
                 for {
@@ -340,7 +340,7 @@ contract testing {
                     // CHECK: block5: # cond
                     // CHECK: branchcond (unsigned less %j < uint256 10), block7, block8
                     // CHECK: block6: # next
-                    // CHECK: ty:uint256 %j = (%j + uint256 1)
+                    // CHECK: ty:uint256 %j = (unchecked %j + uint256 1)
                     // CHECK: branch block5
                     j := add(j, 1)
                 } {
@@ -352,14 +352,14 @@ contract testing {
                     // After inner for:
                     // CHECK: block8: # end_for
                     // CHECK: branchcond (unsigned more %i > uint256 5), block11, block12
-                    
+
                     // Inside inner if:
                     // CHECK: block9: # then
                     // CHECK: branch block8
 
                     // After inner if:
                     // CHECK: block10: # endif
-                    // CHECK: ty:uint256 %j = (%i - uint256 2)
+                    // CHECK: ty:uint256 %j = (unchecked %i - uint256 2)
                     j := sub(i, 2)
                     // CHECK: branch block6
                 }
@@ -369,7 +369,7 @@ contract testing {
                     // CHECK: branch block4
                 }
                 // CHECK: block12: # endif
-                // CHECK: ty:uint256 %i = (%i - uint256 4)
+                // CHECK: ty:uint256 %i = (unchecked %i - uint256 4)
                 i := sub(i, 4)
                 // CHECK: branch block2
             }
@@ -386,7 +386,7 @@ contract testing {
             // CHECK: branchcond (unsigned less %i < uint256 10), block3, block4
             } lt(i, 10) {i := add(i, 1)
             // CHECK: block2: # next
-            // CHECK: ty:uint256 %i = (%i + uint256 1)
+            // CHECK: ty:uint256 %i = (unchecked %i + uint256 1)
             // CHECK: branch block1
             } {
                 // CHECK: block3: # body
@@ -421,7 +421,7 @@ contract testing {
             } lt(i, 10) {
                 // CHECK: block2: # next
                 i := add(i, 1)
-                // CHECK: ty:uint256 %i = (%i + uint256 1)
+                // CHECK: ty:uint256 %i = (unchecked %i + uint256 1)
                 // CHECK: branch block1
             } {
                 for {
@@ -438,7 +438,7 @@ contract testing {
                     // CHECK: block5: # cond
                     // CHECK: branchcond (unsigned less %j < uint256 10), block7, block8
                     // CHECK: block6: # next
-                    // CHECK: ty:uint256 %j = (%j + uint256 1)
+                    // CHECK: ty:uint256 %j = (unchecked %j + uint256 1)
                     // CHECK: branch block5
                     j := add(j, 1)
                 } {
@@ -450,14 +450,14 @@ contract testing {
                     // After inner for:
                     // CHECK: block8: # end_for
                     // CHECK: branchcond (unsigned more %i > uint256 5), block11, block12
-                    
+
                     // Inside inner if:
                     // CHECK: block9: # then
                     // CHECK: branch block6
 
                     // After inner if:
                     // CHECK: block10: # endif
-                    // CHECK: ty:uint256 %j = (%i - uint256 2)
+                    // CHECK: ty:uint256 %j = (unchecked %i - uint256 2)
                     j := sub(i, 2)
                     // CHECK: branch block6
                 }
@@ -467,7 +467,7 @@ contract testing {
                     // CHECK: branch block2
                 }
                 // CHECK: block12: # endif
-                // CHECK: ty:uint256 %i = (%i - uint256 4)
+                // CHECK: ty:uint256 %i = (unchecked %i - uint256 4)
                 i := sub(i, 4)
                 // CHECK: branch block2
             }