Bladeren bron

Permit memory-safe flag on assembly (#1530)

Fixes https://github.com/hyperledger/solang/issues/1526

Signed-off-by: Sean Young <sean@mess.org>
Sean Young 2 jaren geleden
bovenliggende
commit
ea4baceaa2
6 gewijzigde bestanden met toevoegingen van 49 en 7 verwijderingen
  1. 27 6
      src/sema/statements.rs
  2. 1 0
      src/sema/tests/mod.rs
  3. 4 0
      src/sema/yul/ast.rs
  4. 2 0
      src/sema/yul/mod.rs
  5. 14 0
      tests/contract_testcases/evm/memory_safe.sol
  6. 1 1
      tests/evm.rs

+ 27 - 6
src/sema/statements.rs

@@ -888,17 +888,38 @@ fn statement(
                 return Err(());
             }
 
+            let mut memory_safe = None;
+
             if let Some(flags) = flags {
                 for flag in flags {
-                    ns.diagnostics.push(Diagnostic::error(
-                        flag.loc,
-                        format!("flag '{}' not supported", flag.string),
-                    ));
+                    if flag.string == "memory-safe" && ns.target == Target::EVM {
+                        if let Some(prev) = &memory_safe {
+                            ns.diagnostics.push(Diagnostic::error_with_note(
+                                flag.loc,
+                                format!("flag '{}' already specified", flag.string),
+                                *prev,
+                                "previous location".into(),
+                            ));
+                        } else {
+                            memory_safe = Some(flag.loc);
+                        }
+                    } else {
+                        ns.diagnostics.push(Diagnostic::error(
+                            flag.loc,
+                            format!("flag '{}' not supported", flag.string),
+                        ));
+                    }
                 }
             }
 
-            let resolved_asm =
-                resolve_inline_assembly(loc, &block.statements, context, symtable, ns);
+            let resolved_asm = resolve_inline_assembly(
+                loc,
+                memory_safe.is_some(),
+                &block.statements,
+                context,
+                symtable,
+                ns,
+            );
             res.push(Statement::Assembly(resolved_asm.0, resolved_asm.1));
             Ok(resolved_asm.1)
         }

+ 1 - 0
src/sema/tests/mod.rs

@@ -128,6 +128,7 @@ fn test_statement_reachable() {
             Statement::Assembly(
                 InlineAssembly {
                     loc,
+                    memory_safe: false,
                     body: vec![],
                     functions: std::ops::Range { start: 0, end: 0 },
                 },

+ 4 - 0
src/sema/yul/ast.rs

@@ -12,6 +12,10 @@ use std::sync::Arc;
 #[derive(Debug, Clone)]
 pub struct InlineAssembly {
     pub loc: pt::Loc,
+    /// is the assembly ("memory-safe") { .. } flag specified
+    /// This flag is only permitted on EVM. It is not used by solang itself, however external
+    /// tools that wish to use our AST can use it.
+    pub memory_safe: bool,
     pub body: Vec<YulStatement>,
     // (begin, end) offset for Namespace::yul_functions
     pub functions: std::ops::Range<usize>,

+ 2 - 0
src/sema/yul/mod.rs

@@ -24,6 +24,7 @@ mod unused_variable;
 /// Returns the resolved block and a bool to indicate if the next statement is reachable.
 pub fn resolve_inline_assembly(
     loc: &pt::Loc,
+    memory_safe: bool,
     statements: &[pt::YulStatement],
     context: &ExprContext,
     symtable: &mut Symtable,
@@ -54,6 +55,7 @@ pub fn resolve_inline_assembly(
     (
         InlineAssembly {
             loc: *loc,
+            memory_safe,
             body,
             functions: std::ops::Range { start, end },
         },

+ 14 - 0
tests/contract_testcases/evm/memory_safe.sol

@@ -0,0 +1,14 @@
+pragma solidity ^0.8.0;
+
+library Issue1526 {
+    function extSloads() public pure {
+        assembly ("memory-safe", "foo", "memory-safe") {
+
+        }
+    }
+}
+
+// ---- Expect: diagnostics ----
+// error: 5:34-39: flag 'foo' not supported
+// error: 5:41-54: flag 'memory-safe' already specified
+// 	note 5:19-32: previous location

+ 1 - 1
tests/evm.rs

@@ -249,7 +249,7 @@ fn ethereum_solidity_tests() {
         })
         .sum();
 
-    assert_eq!(errors, 1032);
+    assert_eq!(errors, 1030);
 }
 
 fn set_file_contents(source: &str, path: &Path) -> (FileResolver, Vec<String>) {