Ver Fonte

Merge pull request #924 from seanyoung/create-program-address

Improve slice support and add `create_program_address()` solana builtin
Sean Young há 3 anos atrás
pai
commit
08ee36e3b4
100 ficheiros alterados com 1420 adições e 599 exclusões
  1. 4 0
      docs/language/builtins.rst
  2. 48 9
      docs/targets/solana.rst
  3. 9 0
      integration/solana/builtins.sol
  4. 11 0
      integration/solana/builtins.spec.ts
  5. 1 1
      src/abi/substrate.rs
  6. 1 1
      src/bin/languageserver/mod.rs
  7. 23 5
      src/codegen/cfg.rs
  8. 21 16
      src/codegen/expression.rs
  9. 6 3
      src/codegen/external_functions.rs
  10. 2 0
      src/codegen/mod.rs
  11. 3 2
      src/codegen/statements.rs
  12. 1 1
      src/codegen/vector_to_slice.rs
  13. 5 5
      src/codegen/yul/expression.rs
  14. 26 7
      src/codegen/yul/tests/expression.rs
  15. 26 15
      src/emit/binary.rs
  16. 20 11
      src/emit/ethabiencoder.rs
  17. 106 8
      src/emit/mod.rs
  18. 196 23
      src/emit/solana.rs
  19. 11 9
      src/emit/substrate.rs
  20. 26 2
      src/sema/ast.rs
  21. 150 5
      src/sema/builtin.rs
  22. 6 2
      src/sema/dotgraphviz.rs
  23. 79 23
      src/sema/expression.rs
  24. 1 0
      src/sema/mutability.rs
  25. 6 4
      src/sema/namespace.rs
  26. 44 30
      src/sema/types.rs
  27. 7 4
      src/sema/yul/expression.rs
  28. 2 2
      src/sema/yul/tests/expression.rs
  29. 4 4
      tests/codegen_testcases/solidity/slice1.sol
  30. 2 2
      tests/contract_testcases/ewasm/public_internal_function.dot
  31. 2 2
      tests/contract_testcases/solana/comment.dot
  32. 5 5
      tests/contract_testcases/solana/create_contract/base_contract.dot
  33. 10 10
      tests/contract_testcases/solana/create_contract/base_contract_01.dot
  34. 10 10
      tests/contract_testcases/solana/create_contract/base_contract_02.dot
  35. 16 6
      tests/contract_testcases/solana/expressions/selector_in_free_function.dot
  36. 4 4
      tests/contract_testcases/solana/immutable_function.dot
  37. 36 14
      tests/contract_testcases/solana/import_contracts_via_object.dot
  38. 54 36
      tests/contract_testcases/solana/keep_on_resolving.dot
  39. 122 100
      tests/contract_testcases/solana/override.dot
  40. 3 3
      tests/contract_testcases/solana/structs/parse_structs_06.dot
  41. 29 15
      tests/contract_testcases/solana/type_called_error.dot
  42. 12 8
      tests/contract_testcases/solana/type_decl_broken_more.dot
  43. 69 25
      tests/contract_testcases/solana/using_import.dot
  44. 41 21
      tests/contract_testcases/solana/using_list.dot
  45. 21 7
      tests/contract_testcases/solana/using_literal.dot
  46. 6 6
      tests/contract_testcases/substrate/account_info.dot
  47. 2 2
      tests/contract_testcases/substrate/arrays/array_dimensions.dot
  48. 2 2
      tests/contract_testcases/substrate/arrays/array_dimensions_01.dot
  49. 2 2
      tests/contract_testcases/substrate/arrays/array_dimensions_02.dot
  50. 2 2
      tests/contract_testcases/substrate/arrays/array_dimensions_03.dot
  51. 2 2
      tests/contract_testcases/substrate/arrays/array_dimensions_04.dot
  52. 2 2
      tests/contract_testcases/substrate/arrays/data_locations.dot
  53. 2 2
      tests/contract_testcases/substrate/arrays/data_locations_01.dot
  54. 2 2
      tests/contract_testcases/substrate/arrays/data_locations_02.dot
  55. 2 2
      tests/contract_testcases/substrate/arrays/data_locations_03.dot
  56. 2 2
      tests/contract_testcases/substrate/arrays/data_locations_04.dot
  57. 2 2
      tests/contract_testcases/substrate/arrays/data_locations_05.dot
  58. 2 2
      tests/contract_testcases/substrate/arrays/data_locations_06.dot
  59. 2 2
      tests/contract_testcases/substrate/arrays/data_locations_07.dot
  60. 2 2
      tests/contract_testcases/substrate/arrays/data_locations_08.dot
  61. 2 2
      tests/contract_testcases/substrate/calls/payable_functions.dot
  62. 2 2
      tests/contract_testcases/substrate/calls/payable_functions_01.dot
  63. 2 2
      tests/contract_testcases/substrate/calls/payable_functions_02.dot
  64. 2 2
      tests/contract_testcases/substrate/calls/payable_functions_03.dot
  65. 2 2
      tests/contract_testcases/substrate/contracts/contract_name.dot
  66. 3 3
      tests/contract_testcases/substrate/contracts/contract_name_01.dot
  67. 4 4
      tests/contract_testcases/substrate/contracts/contract_name_02.dot
  68. 3 3
      tests/contract_testcases/substrate/contracts/contract_name_03.dot
  69. 2 2
      tests/contract_testcases/substrate/events/event_decl.dot
  70. 5 5
      tests/contract_testcases/substrate/events/event_decl_02.dot
  71. 3 3
      tests/contract_testcases/substrate/events/event_decl_03.dot
  72. 2 2
      tests/contract_testcases/substrate/events/event_decl_04.dot
  73. 2 2
      tests/contract_testcases/substrate/events/event_decl_05.dot
  74. 3 3
      tests/contract_testcases/substrate/events/event_decl_06.dot
  75. 2 2
      tests/contract_testcases/substrate/events/event_decl_07.dot
  76. 2 2
      tests/contract_testcases/substrate/events/event_decl_08.dot
  77. 2 2
      tests/contract_testcases/substrate/events/event_decl_09.dot
  78. 2 2
      tests/contract_testcases/substrate/events/event_decl_10.dot
  79. 2 2
      tests/contract_testcases/substrate/function_types/decls_06.dot
  80. 2 2
      tests/contract_testcases/substrate/function_types/decls_07.dot
  81. 2 2
      tests/contract_testcases/substrate/function_types/decls_08.dot
  82. 4 4
      tests/contract_testcases/substrate/functions/payable.dot
  83. 4 4
      tests/contract_testcases/substrate/functions/payable_01.dot
  84. 4 4
      tests/contract_testcases/substrate/functions/payable_02.dot
  85. 4 4
      tests/contract_testcases/substrate/functions/payable_03.dot
  86. 2 2
      tests/contract_testcases/substrate/functions/return_not_returns.dot
  87. 2 2
      tests/contract_testcases/substrate/functions/stray_semicolon_01.dot
  88. 6 6
      tests/contract_testcases/substrate/inheritance/inherit_types_03.dot
  89. 4 4
      tests/contract_testcases/substrate/inheritance/test_interface.dot
  90. 2 2
      tests/contract_testcases/substrate/inheritance/test_interface_01.dot
  91. 3 3
      tests/contract_testcases/substrate/inheritance/test_interface_02.dot
  92. 2 2
      tests/contract_testcases/substrate/inheritance/test_interface_03.dot
  93. 2 2
      tests/contract_testcases/substrate/inheritance/test_interface_07.dot
  94. 2 2
      tests/contract_testcases/substrate/inheritance/test_interface_08.dot
  95. 3 3
      tests/contract_testcases/substrate/inheritance/test_override.dot
  96. 2 2
      tests/contract_testcases/substrate/inheritance/test_super.dot
  97. 2 2
      tests/contract_testcases/substrate/inheritance/test_virtual.dot
  98. 2 2
      tests/contract_testcases/substrate/libraries/restrictions.dot
  99. 2 2
      tests/contract_testcases/substrate/libraries/restrictions_01.dot
  100. 2 2
      tests/contract_testcases/substrate/libraries/restrictions_02.dot

+ 4 - 0
docs/language/builtins.rst

@@ -143,6 +143,10 @@ AccountInfo[] ``tx.accounts``
         }
     }
 
+address ``tx.program_id``
+    The address or account of the currently executing program. Only available on
+    Solana.
+
 ``block`` properties
 ++++++++++++++++++++++
 

+ 48 - 9
docs/targets/solana.rst

@@ -11,7 +11,7 @@ Solana has the following differences to Ethereum Solidity:
   signatures.
 - Solana has no concept of gas, so there is no gas functions
 - Solana balance is stored in a ``uint64``, so *address* ``.balance``, ``.transfer()`` and ``.send()``
-  all use uint64 rather than `uint256`.
+  all use ``uint64`` rather than ``uint256``.
 
 This is how to build your Solidity for Solana:
 
@@ -82,25 +82,26 @@ The Solidity langauge on Ethereum allows value transfers with an external call
 or constructor, using the ``auction.bid{value: 501}()`` syntax.
 Solana Cross Program Invocation (CPI) does not support this. This means that:
 
- - Specifying `value:`` on an external call or constructor is not permitted
- - The `payable` keyword has no effect
- - `msg.value` is not supported
+ - Specifying ``value:`` on an external call or constructor is not permitted
+ - The ``payable`` keyword has no effect
+ - ``msg.value`` is not supported
 
 .. note::
 
-    Hypothetically, the caller could transfer native balance and then inform the
-    callee about the amount transferred by specifying this in the instruction data.
-    However, it would be trivial to forge such an operation.
+    Hypothetically, this could be implemented like so: the caller could transfer
+    native balance and then inform the callee about the amount transferred by
+    specifying this in the instruction data. However, it would be trivial to
+    forge such an operation.
 
 Receive function
 ________________
 
-In Solidity the `receive()` function, when defined, is called whenever the native
+In Solidity the ``receive()`` function, when defined, is called whenever the native
 balance for an account gets credited, for example through a contract calling
 ``account.transfer(value);``. On Solana, there is no method that implement
 this. The balance of an account can be credited without any code being executed.
 
-`receive()` functions are not permitted on the Solana target.
+``receive()`` functions are not permitted on the Solana target.
 
 Builtin Imports
 ________________
@@ -178,6 +179,44 @@ bool ``is_writable``
 bool ``is_signer``
     Can the callee assume this account signed the transaction
 
+Builtin create_program_address
+++++++++++++++++++++++++++++++
+
+This function returns the program derived address for a program address and
+the provided seeds. See the Solana documentation on
+`program derived adddresses <https://edge.docs.solana.com/developing/programming-model/calling-between-programs#program-derived-addresses>`_.
+
+.. code-block:: solidity
+
+    import {create_program_address} from 'solana';
+
+    contract pda {
+        address token = address"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
+
+        function create_pda(bytes seed2) public returns (address) {
+            return create_program_address(["kabang", seed2], token);
+        }
+    }
+
+Builtin try_find_program_address
+++++++++++++++++++++++++++++++++
+
+This function returns the program derived address for a program address and
+the provided seeds, along with a seed bump. See the Solana documentation on
+`program derived adddresses <https://edge.docs.solana.com/developing/programming-model/calling-between-programs#program-derived-addresses>`_.
+
+.. code-block:: solidity
+
+    import {try_find_program_address} from 'solana';
+
+    contract pda {
+        address token = address"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
+
+        function create_pda(bytes seed2) public returns (address, bytes1) {
+            return try_find_program_address(["kabang", seed2], token);
+        }
+    }
+
 Using spl-token
 _______________
 

+ 9 - 0
integration/solana/builtins.sol

@@ -1,3 +1,4 @@
+import 'solana';
 
 contract builtins {
 	function hash_ripemd160(bytes bs) public returns (bytes20) {
@@ -19,4 +20,12 @@ contract builtins {
 	function mr_slot() public returns (uint64) {
 		return block.slot;
 	}
+
+	function pda(bytes seed1, bytes seed2, address addr) public returns (address) {
+		return create_program_address([seed1, seed2], addr);
+	}
+
+	function pda_with_bump(bytes seed1, bytes seed2, address addr) public returns (address, bytes1) {
+		return try_find_program_address([seed1, seed2], addr);
+	}
 }

+ 11 - 0
integration/solana/builtins.spec.ts

@@ -1,5 +1,7 @@
 import expect from 'expect';
 import { loadContract } from './setup';
+import { publicKeyToHex } from '@solana/solidity';
+import { PublicKey } from '@solana/web3.js';
 
 describe('Deploy solang contract and test', function () {
     this.timeout(500000);
@@ -20,6 +22,15 @@ describe('Deploy solang contract and test', function () {
 
         expect(res.result).toBe("0x823ad8e1757b879aac338f9a18542928c668e479b37e4a56f024016215c5928c");
 
+        let addrs = new PublicKey("BPFLoaderUpgradeab1e11111111111111111111111");
+        let expected = new PublicKey("BwqrghZA2htAcqq8dzP1WDAhTXYTYWj7CHxF5j7TDBAe");
+        res = await contract.functions.pda('0x', '0x01', publicKeyToHex(addrs));
+        expect(res.result).toBe(publicKeyToHex(expected));
+
+        res = await contract.functions.pda_with_bump('0x', '0x01', publicKeyToHex(addrs));
+        expect(res.result[0]).toBe("0x00c13b4820057d4d07cddf24058df4034cd3379a5f863b4e061ad2c29be62fd5");
+        expect(res.result[1]).toBe("0xfe");
+
         res = await contract.functions.mr_now([]);
 
         let now = Math.floor(+new Date() / 1000);

+ 1 - 1
src/abi/substrate.rs

@@ -532,7 +532,7 @@ fn ty_to_abi(ty: &ast::Type, ns: &ast::Namespace, registry: &mut Abi) -> ParamTy
             let mut param_ty = ty_to_abi(ty, ns, registry);
 
             for d in dims {
-                if let Some(d) = d {
+                if let ast::ArrayLength::Fixed(d) = d {
                     param_ty = ParamType {
                         ty: registry.builtin_array_type(param_ty.ty, d.to_usize().unwrap()),
                         display_name: vec![],

+ 1 - 1
src/bin/languageserver/mod.rs

@@ -949,7 +949,7 @@ impl SolangServer {
         }
 
         for fnc in &ns.functions {
-            if fnc.is_accessor {
+            if fnc.is_accessor || fnc.loc == pt::Loc::Builtin {
                 // accessor functions are synthetic; ignore them, all the locations are fake
                 continue;
             }

+ 23 - 5
src/codegen/cfg.rs

@@ -285,8 +285,9 @@ impl Instr {
 #[derive(Clone, Debug)]
 #[allow(clippy::large_enum_variant)]
 pub enum InternalCallTy {
-    Static(usize),
+    Static { cfg_no: usize },
     Dynamic(Expression),
+    Builtin { ast_func_no: usize },
 }
 
 #[derive(Clone, PartialEq)]
@@ -904,7 +905,24 @@ impl ControlFlowGraph {
             }
             Instr::Call {
                 res,
-                call: InternalCallTy::Static(cfg_no),
+                call: InternalCallTy::Builtin { ast_func_no },
+                args,
+                ..
+            } => format!(
+                "{} = call builtin {} {}",
+                res.iter()
+                    .map(|local| format!("%{}", self.vars[local].id.name))
+                    .collect::<Vec<String>>()
+                    .join(", "),
+                ns.functions[*ast_func_no].name,
+                args.iter()
+                    .map(|expr| self.expr_to_string(contract, ns, expr))
+                    .collect::<Vec<String>>()
+                    .join(", ")
+            ),
+            Instr::Call {
+                res,
+                call: InternalCallTy::Static { cfg_no },
                 args,
                 ..
             } => format!(
@@ -1492,7 +1510,7 @@ fn function_cfg(
                     Instr::Call {
                         res: Vec::new(),
                         return_tys: Vec::new(),
-                        call: InternalCallTy::Static(cfg_no),
+                        call: InternalCallTy::Static { cfg_no },
                         args,
                     },
                 );
@@ -1504,7 +1522,7 @@ fn function_cfg(
                     Instr::Call {
                         res: Vec::new(),
                         return_tys: Vec::new(),
-                        call: InternalCallTy::Static(cfg_no),
+                        call: InternalCallTy::Static { cfg_no },
                         args: Vec::new(),
                     },
                 );
@@ -1695,7 +1713,7 @@ pub fn generate_modifier_dispatch(
     // create the instruction for the place holder
     let placeholder = Instr::Call {
         res: func.symtable.returns.clone(),
-        call: InternalCallTy::Static(cfg_no),
+        call: InternalCallTy::Static { cfg_no },
         return_tys,
         args: func
             .params

+ 21 - 16
src/codegen/expression.rs

@@ -11,7 +11,10 @@ use crate::codegen::unused_variable::should_remove_assignment;
 use crate::codegen::{Builtin, Expression};
 use crate::sema::{
     ast,
-    ast::{CallTy, FormatArg, Function, Namespace, Parameter, RetrieveType, StringLocation, Type},
+    ast::{
+        ArrayLength, CallTy, FormatArg, Function, Namespace, Parameter, RetrieveType,
+        StringLocation, Type,
+    },
     diagnostics::Diagnostics,
     eval::{eval_const_number, eval_const_rational},
     expression::{bigint_to_expression, ResolveTo},
@@ -374,7 +377,7 @@ pub fn expression(
                     elem_ty: elem_ty.clone(),
                 },
                 Type::Array(_, dim) => match dim.last().unwrap() {
-                    None => {
+                    ArrayLength::Dynamic => {
                         if ns.target == Target::Solana {
                             Expression::StorageArrayLength {
                                 loc: *loc,
@@ -386,7 +389,7 @@ pub fn expression(
                             load_storage(loc, &ns.storage_type(), array, cfg, vartab)
                         }
                     }
-                    Some(length) => {
+                    ArrayLength::Fixed(length) => {
                         let ast_expr = bigint_to_expression(
                             loc,
                             length,
@@ -397,6 +400,7 @@ pub fn expression(
                         .unwrap();
                         expression(&ast_expr, cfg, contract_no, func, ns, vartab, opt)
                     }
+                    _ => unreachable!(),
                 },
                 _ => unreachable!(),
             }
@@ -2008,14 +2012,22 @@ pub fn emit_function_call(
                     .collect();
 
                 let function_no = if let Some(signature) = signature {
-                    &ns.contracts[callee_contract_no].virtual_functions[signature]
+                    ns.contracts[callee_contract_no].virtual_functions[signature]
                 } else {
-                    function_no
+                    *function_no
                 };
 
-                let cfg_no = ns.contracts[callee_contract_no].all_functions[function_no];
+                let ftype = &ns.functions[function_no];
 
-                let ftype = &ns.functions[*function_no];
+                let call = if ns.functions[function_no].loc == pt::Loc::Builtin {
+                    InternalCallTy::Builtin {
+                        ast_func_no: function_no,
+                    }
+                } else {
+                    InternalCallTy::Static {
+                        cfg_no: ns.contracts[callee_contract_no].all_functions[&function_no],
+                    }
+                };
 
                 if !ftype.returns.is_empty() {
                     let mut res = Vec::new();
@@ -2038,7 +2050,7 @@ pub fn emit_function_call(
                         vartab,
                         Instr::Call {
                             res,
-                            call: InternalCallTy::Static(cfg_no),
+                            call,
                             args,
                             return_tys,
                         },
@@ -2051,7 +2063,7 @@ pub fn emit_function_call(
                         Instr::Call {
                             res: Vec::new(),
                             return_tys: Vec::new(),
-                            call: InternalCallTy::Static(cfg_no),
+                            call,
                             args,
                         },
                     );
@@ -2806,13 +2818,6 @@ fn array_subscript(
                     )),
                 )
             }
-            Type::Array(_, dim) if dim.last().unwrap().is_some() => Expression::Subscript(
-                *loc,
-                elem_ty.clone(),
-                array_ty.clone(),
-                Box::new(array),
-                Box::new(Expression::Variable(index_loc, coerced_ty, pos)),
-            ),
             Type::DynamicBytes | Type::Array(..) => Expression::Subscript(
                 *loc,
                 elem_ty.clone(),

+ 6 - 3
src/codegen/external_functions.rs

@@ -1,6 +1,7 @@
 use crate::sema::ast::{DestructureField, Expression, Namespace, Statement};
 use crate::sema::Recurse;
 use indexmap::IndexSet;
+use solang_parser::pt;
 
 #[derive(Default)]
 struct CallList {
@@ -42,9 +43,11 @@ pub fn add_external_functions(contract_no: usize, ns: &mut Namespace) {
 
         // add functions to contract functions list
         for function_no in &call_list.solidity {
-            ns.contracts[contract_no]
-                .all_functions
-                .insert(*function_no, usize::MAX);
+            if ns.functions[*function_no].loc != pt::Loc::Builtin {
+                ns.contracts[contract_no]
+                    .all_functions
+                    .insert(*function_no, usize::MAX);
+            }
         }
 
         for yul_function_no in &call_list.yul {

+ 2 - 0
src/codegen/mod.rs

@@ -1214,6 +1214,7 @@ pub enum Builtin {
     Ripemd160,
     Sender,
     Slot,
+    ProgramId,
     Sha256,
     Signature,
     SignatureVerify,
@@ -1274,6 +1275,7 @@ impl From<&ast::Builtin> for Builtin {
             ast::Builtin::Ripemd160 => Builtin::Ripemd160,
             ast::Builtin::Sender => Builtin::Sender,
             ast::Builtin::Slot => Builtin::Slot,
+            ast::Builtin::ProgramId => Builtin::ProgramId,
             ast::Builtin::Sha256 => Builtin::Sha256,
             ast::Builtin::Signature => Builtin::Signature,
             ast::Builtin::SignatureVerify => Builtin::SignatureVerify,

+ 3 - 2
src/codegen/statements.rs

@@ -15,7 +15,8 @@ use crate::codegen::yul::inline_assembly_cfg;
 use crate::codegen::{Builtin, Expression};
 use crate::sema::ast::RetrieveType;
 use crate::sema::ast::{
-    CallTy, DestructureField, Function, Namespace, Parameter, Statement, TryCatch, Type,
+    ArrayLength, CallTy, DestructureField, Function, Namespace, Parameter, Statement, TryCatch,
+    Type,
 };
 use crate::sema::Recurse;
 use num_traits::Zero;
@@ -1495,7 +1496,7 @@ impl Type {
             Type::Array(ty, dims) => {
                 ty.default(ns)?;
 
-                if dims.last().unwrap().is_none() {
+                if dims.last() == Some(&ArrayLength::Dynamic) {
                     Some(Expression::AllocDynamicArray(
                         pt::Loc::Codegen,
                         self.clone(),

+ 1 - 1
src/codegen/vector_to_slice.rs

@@ -214,7 +214,7 @@ fn update_vectors_to_slice(
                 res,
                 expr: Expression::AllocDynamicArray(
                     *loc,
-                    Type::Slice,
+                    Type::Slice(Box::new(Type::Bytes(1))),
                     len.clone(),
                     Some(bs.clone()),
                 ),

+ 5 - 5
src/codegen/yul/expression.rs

@@ -1,4 +1,4 @@
-use crate::ast::{Namespace, Type};
+use crate::ast::{ArrayLength, Namespace, Type};
 use crate::codegen;
 use crate::codegen::cfg::{ControlFlowGraph, Instr, InternalCallTy};
 use crate::codegen::vartable::Vartable;
@@ -138,7 +138,7 @@ fn process_suffix_access(
                 Some(StorageLocation::Calldata(_)),
                 var_no,
             ) => {
-                if dims.last().unwrap().is_none() {
+                if dims.last() == Some(&ArrayLength::Dynamic) {
                     return Expression::Cast(
                         *loc,
                         Type::Uint(256),
@@ -158,7 +158,7 @@ fn process_suffix_access(
                 _,
             ) = expr
             {
-                if dims.last().unwrap().is_none() {
+                if dims.last() == Some(&ArrayLength::Dynamic) {
                     return Expression::Builtin(
                         *loc,
                         vec![Type::Uint(32)],
@@ -224,7 +224,7 @@ pub(crate) fn process_function_call(
             Instr::Call {
                 res: Vec::new(),
                 return_tys: Vec::new(),
-                call: InternalCallTy::Static(cfg_no),
+                call: InternalCallTy::Static { cfg_no },
                 args: codegen_args,
             },
         );
@@ -252,7 +252,7 @@ pub(crate) fn process_function_call(
         vartab,
         Instr::Call {
             res,
-            call: InternalCallTy::Static(cfg_no),
+            call: InternalCallTy::Static { cfg_no },
             args: codegen_args,
             return_tys,
         },

+ 26 - 7
src/codegen/yul/tests/expression.rs

@@ -5,6 +5,7 @@ use crate::codegen::cfg::ControlFlowGraph;
 use crate::codegen::vartable::Vartable;
 use crate::codegen::yul::expression::expression;
 use crate::codegen::{Builtin, Expression, Options};
+use crate::sema::ast::ArrayLength;
 use crate::sema::yul::ast;
 use crate::sema::yul::ast::YulSuffix;
 use crate::{sema, Target};
@@ -355,7 +356,7 @@ fn offset_suffix() {
         loc,
         Box::new(ast::YulExpression::SolidityLocalVariable(
             loc,
-            Type::Array(Box::new(Type::Uint(256)), vec![None]),
+            Type::Array(Box::new(Type::Uint(256)), vec![ArrayLength::Dynamic]),
             Some(StorageLocation::Calldata(loc)),
             1,
         )),
@@ -369,7 +370,7 @@ fn offset_suffix() {
             Type::Uint(256),
             Box::new(Expression::Variable(
                 loc,
-                Type::Array(Box::new(Type::Uint(256)), vec![None]),
+                Type::Array(Box::new(Type::Uint(256)), vec![ArrayLength::Dynamic]),
                 1
             ))
         )
@@ -389,7 +390,10 @@ fn offset_suffix_panic_calldata() {
         loc,
         Box::new(ast::YulExpression::SolidityLocalVariable(
             loc,
-            Type::Array(Box::new(Type::Uint(32)), vec![None, Some(BigInt::from(3))]),
+            Type::Array(
+                Box::new(Type::Uint(32)),
+                vec![ArrayLength::Dynamic, ArrayLength::Fixed(BigInt::from(3))],
+            ),
             Some(StorageLocation::Calldata(loc)),
             3,
         )),
@@ -431,7 +435,11 @@ fn length_suffix() {
             loc,
             Type::Array(
                 Box::new(Type::Uint(32)),
-                vec![None, Some(BigInt::from(3)), None],
+                vec![
+                    ArrayLength::Dynamic,
+                    ArrayLength::Fixed(BigInt::from(3)),
+                    ArrayLength::Dynamic,
+                ],
             ),
             Some(StorageLocation::Calldata(loc)),
             3,
@@ -450,7 +458,11 @@ fn length_suffix() {
                 loc,
                 Type::Array(
                     Box::new(Type::Uint(32)),
-                    vec![None, Some(BigInt::from(3)), None]
+                    vec![
+                        ArrayLength::Dynamic,
+                        ArrayLength::Fixed(BigInt::from(3)),
+                        ArrayLength::Dynamic
+                    ]
                 ),
                 3
             )]
@@ -471,7 +483,10 @@ fn length_suffix_panic() {
         loc,
         Box::new(ast::YulExpression::SolidityLocalVariable(
             loc,
-            Type::Array(Box::new(Type::Uint(32)), vec![None, Some(BigInt::from(3))]),
+            Type::Array(
+                Box::new(Type::Uint(32)),
+                vec![ArrayLength::Dynamic, ArrayLength::Fixed(BigInt::from(3))],
+            ),
             Some(StorageLocation::Calldata(loc)),
             3,
         )),
@@ -489,7 +504,11 @@ fn length_suffix_panic() {
                 loc,
                 Type::Array(
                     Box::new(Type::Uint(32)),
-                    vec![None, Some(BigInt::from(3)), None]
+                    vec![
+                        ArrayLength::Dynamic,
+                        ArrayLength::Fixed(BigInt::from(3)),
+                        ArrayLength::Dynamic
+                    ]
                 ),
                 3
             )]

+ 26 - 15
src/emit/binary.rs

@@ -1,4 +1,4 @@
-use crate::sema::ast::{BuiltinStruct, Contract, Namespace, Type};
+use crate::sema::ast::{ArrayLength, BuiltinStruct, Contract, Namespace, Type};
 use std::cell::RefCell;
 use std::ffi::CStr;
 use std::path::Path;
@@ -762,7 +762,7 @@ impl<'a> Binary<'a> {
     pub(crate) fn llvm_field_ty(&self, ty: &Type, ns: &Namespace) -> BasicTypeEnum<'a> {
         let llvm_ty = self.llvm_type(ty, ns);
         match ty.deref_memory() {
-            Type::Array(_, dim) if dim.last().unwrap().is_none() => {
+            Type::Array(_, dim) if dim.last() == Some(&ArrayLength::Dynamic) => {
                 llvm_ty.ptr_type(AddressSpace::Generic).as_basic_type_enum()
             }
             Type::DynamicBytes | Type::String => {
@@ -806,18 +806,24 @@ impl<'a> Binary<'a> {
                     let mut dims = dims.iter();
 
                     let mut aty = match dims.next().unwrap() {
-                        Some(d) => ty.array_type(d.to_u32().unwrap()),
-                        None => {
+                        ArrayLength::Fixed(d) => ty.array_type(d.to_u32().unwrap()),
+                        ArrayLength::Dynamic => {
                             return self.module.get_struct_type("struct.vector").unwrap().into()
                         }
+                        ArrayLength::AnyFixed => {
+                            unreachable!()
+                        }
                     };
 
                     for dim in dims {
                         match dim {
-                            Some(d) => aty = aty.array_type(d.to_u32().unwrap()),
-                            None => {
+                            ArrayLength::Fixed(d) => aty = aty.array_type(d.to_u32().unwrap()),
+                            ArrayLength::Dynamic => {
                                 return self.module.get_struct_type("struct.vector").unwrap().into()
                             }
+                            ArrayLength::AnyFixed => {
+                                unreachable!()
+                            }
                         }
                     }
 
@@ -857,14 +863,15 @@ impl<'a> Binary<'a> {
                             .ptr_type(AddressSpace::Generic),
                     )
                 }
-                Type::Slice => BasicTypeEnum::StructType(
+                Type::Slice(ty) => BasicTypeEnum::StructType(
                     self.context.struct_type(
                         &[
-                            self.context
-                                .i8_type()
+                            self.llvm_type(ty, ns)
                                 .ptr_type(AddressSpace::Generic)
                                 .into(),
-                            self.context.i32_type().into(),
+                            self.context
+                                .custom_width_int_type(ns.target.ptr_size().into())
+                                .into(),
                         ],
                         false,
                     ),
@@ -946,10 +953,14 @@ impl<'a> Binary<'a> {
             // slice
             let slice = vector.into_struct_value();
 
-            self.builder
-                .build_extract_value(slice, 1, "slice_len")
-                .unwrap()
-                .into_int_value()
+            self.builder.build_int_truncate(
+                self.builder
+                    .build_extract_value(slice, 1, "slice_len")
+                    .unwrap()
+                    .into_int_value(),
+                self.context.i32_type(),
+                "len",
+            )
         } else {
             let struct_ty = vector
                 .into_pointer_value()
@@ -1055,7 +1066,7 @@ impl<'a> Binary<'a> {
     ) -> PointerValue<'a> {
         match array_ty {
             Type::Array(_, dim) => {
-                if dim.last().unwrap().is_some() {
+                if matches!(dim.last(), Some(ArrayLength::Fixed(_))) {
                     // fixed size array
                     unsafe {
                         self.builder.build_gep(

+ 20 - 11
src/emit/ethabiencoder.rs

@@ -194,11 +194,12 @@ impl<'a, 'b> EncoderBuilder<'a, 'b> {
                 let sum = binary.context.i32_type().const_zero();
 
                 let len = match dims.last().unwrap() {
-                    None => binary.vector_len(arg),
-                    Some(d) => binary
+                    ast::ArrayLength::Dynamic => binary.vector_len(arg),
+                    ast::ArrayLength::Fixed(d) => binary
                         .context
                         .i32_type()
                         .const_int(d.to_u64().unwrap(), false),
+                    _ => unreachable!(),
                 };
 
                 let normal_array = binary.context.append_basic_block(function, "normal_array");
@@ -286,11 +287,12 @@ impl<'a, 'b> EncoderBuilder<'a, 'b> {
                 };
 
                 let len = match dims.last().unwrap() {
-                    None => binary.vector_len(arg),
-                    Some(d) => binary
+                    ast::ArrayLength::Dynamic => binary.vector_len(arg),
+                    ast::ArrayLength::Fixed(d) => binary
                         .context
                         .i32_type()
                         .const_int(d.to_u64().unwrap(), false),
+                    _ => unreachable!(),
                 };
 
                 // plus fixed size elements
@@ -449,7 +451,7 @@ impl<'a, 'b> EncoderBuilder<'a, 'b> {
                 let mut sum = binary.context.i32_type().const_zero();
 
                 let len = match dims.last().unwrap() {
-                    None => {
+                    ast::ArrayLength::Dynamic => {
                         let array_len = binary.vector_len(arg);
 
                         // A dynamic array will store its own length
@@ -461,10 +463,11 @@ impl<'a, 'b> EncoderBuilder<'a, 'b> {
 
                         array_len
                     }
-                    Some(d) => binary
+                    ast::ArrayLength::Fixed(d) => binary
                         .context
                         .i32_type()
                         .const_int(d.to_u64().unwrap(), false),
+                    _ => unreachable!(),
                 };
 
                 // plus fixed size elements
@@ -614,7 +617,7 @@ impl<'a, 'b> EncoderBuilder<'a, 'b> {
                 // The array must be fixed, dynamic arrays are handled above
                 let product: u64 = dims
                     .iter()
-                    .map(|d| d.as_ref().unwrap().to_u64().unwrap())
+                    .map(|d| d.array_length().unwrap().to_u64().unwrap())
                     .product();
 
                 product * EncoderBuilder::encoded_fixed_length(ty, ns)
@@ -770,7 +773,7 @@ impl<'a, 'b> EncoderBuilder<'a, 'b> {
                     )
                 };
 
-                let array_length = if let Some(d) = &dim.last().unwrap() {
+                let array_length = if let Some(ast::ArrayLength::Fixed(d)) = dim.last() {
                     // fixed length
                     binary
                         .context
@@ -991,7 +994,13 @@ impl<'a, 'b> EncoderBuilder<'a, 'b> {
                     arg
                 };
 
-                let dim = dim.last().unwrap().as_ref().unwrap().to_u64().unwrap();
+                let dim = dim
+                    .last()
+                    .unwrap()
+                    .array_length()
+                    .unwrap()
+                    .to_u64()
+                    .unwrap();
 
                 let normal_array = binary.context.append_basic_block(function, "normal_array");
                 let null_array = binary.context.append_basic_block(function, "null_array");
@@ -1772,7 +1781,7 @@ impl<'a, 'b> EncoderBuilder<'a, 'b> {
                     arg
                 };
 
-                let array_length = if let Some(d) = &dim.last().unwrap() {
+                let array_length = if let Some(ast::ArrayLength::Fixed(d)) = dim.last() {
                     // fixed length
                     binary
                         .context
@@ -2688,7 +2697,7 @@ impl EthAbiDecoder {
 
                 let dest;
 
-                if let Some(d) = &dim.last().unwrap() {
+                if let Some(ast::ArrayLength::Fixed(d)) = dim.last() {
                     dest = to.unwrap_or_else(|| {
                         let new = binary
                             .builder

+ 106 - 8
src/emit/mod.rs

@@ -1,7 +1,8 @@
 use crate::codegen::{Builtin, Expression};
 use crate::sema::ast::RetrieveType;
 use crate::sema::ast::{
-    BuiltinStruct, CallTy, Contract, FormatArg, Namespace, Parameter, StringLocation, Type,
+    ArrayLength, BuiltinStruct, CallTy, Contract, FormatArg, Function, Namespace, Parameter,
+    StringLocation, Type,
 };
 use solang_parser::pt;
 use std::convert::TryFrom;
@@ -235,6 +236,16 @@ pub trait TargetRuntime<'a> {
     /// Return failure without any result
     fn assert_failure<'b>(&self, bin: &'b Binary, data: PointerValue, length: IntValue);
 
+    fn builtin_function(
+        &self,
+        _binary: &Binary<'a>,
+        _func: &Function,
+        _args: &[BasicMetadataValueEnum<'a>],
+        _ns: &Namespace,
+    ) -> BasicValueEnum<'a> {
+        unimplemented!();
+    }
+
     /// Calls constructor
     fn create_contract<'b>(
         &mut self,
@@ -407,7 +418,7 @@ pub trait TargetRuntime<'a> {
         match ty {
             Type::Ref(ty) => self.storage_load_slot(bin, ty, slot, slot_ptr, function, ns),
             Type::Array(elem_ty, dim) => {
-                if let Some(d) = &dim.last().unwrap() {
+                if let Some(ArrayLength::Fixed(d)) = dim.last() {
                     let llvm_ty = bin.llvm_type(ty.deref_any(), ns);
                     // LLVMSizeOf() produces an i64
                     let size = bin.builder.build_int_truncate(
@@ -699,7 +710,7 @@ pub trait TargetRuntime<'a> {
     ) {
         match ty.deref_any() {
             Type::Array(elem_ty, dim) => {
-                if let Some(d) = &dim.last().unwrap() {
+                if let Some(ArrayLength::Fixed(d)) = dim.last() {
                     bin.emit_static_loop_with_int(
                         function,
                         bin.context.i64_type().const_zero(),
@@ -1010,7 +1021,7 @@ pub trait TargetRuntime<'a> {
             Type::Array(_, dim) => {
                 let ty = ty.array_deref();
 
-                if let Some(d) = &dim.last().unwrap() {
+                if let Some(ArrayLength::Fixed(d)) = dim.last() {
                     bin.emit_static_loop_with_int(
                         function,
                         bin.context.i64_type().const_zero(),
@@ -2466,7 +2477,7 @@ pub trait TargetRuntime<'a> {
                 array.into()
             }
             Expression::AllocDynamicArray(_, ty, size, init) => {
-                if *ty == Type::Slice {
+                if matches!(ty, Type::Slice(_)) {
                     let init = init.as_ref().unwrap();
 
                     let data = bin.emit_global_string("const_string", init, true);
@@ -2476,14 +2487,14 @@ pub trait TargetRuntime<'a> {
                         .const_named_struct(&[
                             data.into(),
                             bin.context
-                                .i32_type()
+                                .custom_width_int_type(ns.target.ptr_size().into())
                                 .const_int(init.len() as u64, false)
                                 .into(),
                         ])
                         .into()
                 } else {
                     let elem = match ty {
-                        Type::Slice | Type::String | Type::DynamicBytes => Type::Bytes(1),
+                        Type::Slice(_) | Type::String | Type::DynamicBytes => Type::Bytes(1),
                         _ => ty.array_elem(),
                     };
 
@@ -3237,6 +3248,24 @@ pub trait TargetRuntime<'a> {
                     "ptr_to_int",
                 )
                 .into()
+        } else if matches!((from, to), (Type::DynamicBytes, Type::Slice(_))) {
+            let slice = bin.build_alloca(function, bin.llvm_type(to, ns), "slice");
+
+            let data = bin.vector_bytes(val);
+
+            let data_ptr = bin.builder.build_struct_gep(slice, 0, "data").unwrap();
+
+            bin.builder.build_store(data_ptr, data);
+
+            let len =
+                bin.builder
+                    .build_int_z_extend(bin.vector_len(val), bin.context.i64_type(), "len");
+
+            let len_ptr = bin.builder.build_struct_gep(slice, 1, "len").unwrap();
+
+            bin.builder.build_store(len_ptr, len);
+
+            bin.builder.build_load(slice, "slice")
         } else {
             val
         }
@@ -3854,7 +3883,7 @@ pub trait TargetRuntime<'a> {
                     }
                     Instr::Call {
                         res,
-                        call: InternalCallTy::Static(cfg_no),
+                        call: InternalCallTy::Static { cfg_no },
                         args,
                         ..
                     } => {
@@ -3930,6 +3959,75 @@ pub trait TargetRuntime<'a> {
                             }
                         }
                     }
+                    Instr::Call {
+                        res,
+                        call: InternalCallTy::Builtin { ast_func_no },
+                        args,
+                        ..
+                    } => {
+                        let mut parms = args
+                            .iter()
+                            .map(|p| self.expression(bin, p, &w.vars, function, ns).into())
+                            .collect::<Vec<BasicMetadataValueEnum>>();
+
+                        let func = &ns.functions[*ast_func_no];
+
+                        if !res.is_empty() {
+                            for v in func.returns.iter() {
+                                parms.push(if ns.target == Target::Solana {
+                                    bin.build_alloca(
+                                        function,
+                                        bin.llvm_var_ty(&v.ty, ns),
+                                        v.name_as_str(),
+                                    )
+                                    .into()
+                                } else {
+                                    bin.builder
+                                        .build_alloca(bin.llvm_var_ty(&v.ty, ns), v.name_as_str())
+                                        .into()
+                                });
+                            }
+                        }
+
+                        let ret = self.builtin_function(bin, func, &parms, ns);
+
+                        let success = bin.builder.build_int_compare(
+                            IntPredicate::EQ,
+                            ret.into_int_value(),
+                            bin.return_values[&ReturnCode::Success],
+                            "success",
+                        );
+
+                        let success_block = bin.context.append_basic_block(function, "success");
+                        let bail_block = bin.context.append_basic_block(function, "bail");
+                        bin.builder
+                            .build_conditional_branch(success, success_block, bail_block);
+
+                        bin.builder.position_at_end(bail_block);
+
+                        bin.builder.build_return(Some(&ret));
+                        bin.builder.position_at_end(success_block);
+
+                        if !res.is_empty() {
+                            for (i, v) in func.returns.iter().enumerate() {
+                                let val = bin.builder.build_load(
+                                    parms[args.len() + i].into_pointer_value(),
+                                    v.name_as_str(),
+                                );
+
+                                let dest = w.vars[&res[i]].value;
+
+                                if dest.is_pointer_value()
+                                    && !(v.ty.is_reference_type(ns)
+                                        || matches!(v.ty, Type::ExternalFunction { .. }))
+                                {
+                                    bin.builder.build_store(dest.into_pointer_value(), val);
+                                } else {
+                                    w.vars.get_mut(&res[i]).unwrap().value = val;
+                                }
+                            }
+                        }
+                    }
                     Instr::Call {
                         res,
                         call: InternalCallTy::Dynamic(call_expr),

+ 196 - 23
src/emit/solana.rs

@@ -73,7 +73,7 @@ impl SolanaTarget {
             context.i64_type().const_int(2u64 << 32, false),
         );
         // externals
-        target.declare_externals(&mut binary);
+        target.declare_externals(&mut binary, ns);
 
         target.emit_functions(&mut binary, contract, ns);
 
@@ -151,7 +151,7 @@ impl SolanaTarget {
         );
 
         // externals
-        target.declare_externals(&mut binary);
+        target.declare_externals(&mut binary, namespaces[0]);
 
         let mut contracts: Vec<Contract> = Vec::new();
 
@@ -204,6 +204,8 @@ impl SolanaTarget {
             "sol_alloc_free_",
             "sol_get_return_data",
             "sol_set_return_data",
+            "sol_create_program_address",
+            "sol_try_find_program_address",
             "sol_sha256",
             "sol_keccak256",
             "sol_log_data",
@@ -212,11 +214,17 @@ impl SolanaTarget {
         binary
     }
 
-    fn declare_externals(&self, binary: &mut Binary) {
+    fn declare_externals(&self, binary: &mut Binary, ns: &ast::Namespace) {
         let void_ty = binary.context.void_type();
         let u8_ptr = binary.context.i8_type().ptr_type(AddressSpace::Generic);
         let u64_ty = binary.context.i64_type();
         let u32_ty = binary.context.i32_type();
+        let address = binary.address_type(ns).ptr_type(AddressSpace::Generic);
+        let seeds = binary.llvm_type(
+            &Type::Ref(Box::new(Type::Slice(Box::new(Type::Bytes(1))))),
+            ns,
+        );
+
         let sol_bytes = binary
             .context
             .struct_type(&[u8_ptr.into(), u64_ty.into()], false)
@@ -309,6 +317,36 @@ impl SolanaTarget {
         function
             .as_global_value()
             .set_unnamed_address(UnnamedAddress::Local);
+
+        let function = binary.module.add_function(
+            "sol_create_program_address",
+            u64_ty.fn_type(
+                &[seeds.into(), u64_ty.into(), address.into(), address.into()],
+                false,
+            ),
+            None,
+        );
+        function
+            .as_global_value()
+            .set_unnamed_address(UnnamedAddress::Local);
+
+        let function = binary.module.add_function(
+            "sol_try_find_program_address",
+            u64_ty.fn_type(
+                &[
+                    seeds.into(),
+                    u64_ty.into(),
+                    address.into(),
+                    address.into(),
+                    u8_ptr.into(),
+                ],
+                false,
+            ),
+            None,
+        );
+        function
+            .as_global_value()
+            .set_unnamed_address(UnnamedAddress::Local);
     }
 
     /// Returns the SolAccountInfo of the executing binary
@@ -807,7 +845,7 @@ impl SolanaTarget {
             let mut free_array = None;
 
             if elem_ty.is_dynamic(ns) || zero {
-                let length = if let Some(length) = dim.last().unwrap().as_ref() {
+                let length = if let Some(ast::ArrayLength::Fixed(length)) = dim.last() {
                     binary
                         .context
                         .i32_type()
@@ -1511,20 +1549,16 @@ impl SolanaTarget {
             ),
             // data
             2 => {
-                let data_len = binary.builder.build_int_truncate(
-                    binary
-                        .builder
-                        .build_load(
-                            binary
-                                .builder
-                                .build_struct_gep(account_info, 2, "data_len")
-                                .unwrap(),
-                            "data_len",
-                        )
-                        .into_int_value(),
-                    binary.context.i32_type(),
-                    "data_len",
-                );
+                let data_len = binary
+                    .builder
+                    .build_load(
+                        binary
+                            .builder
+                            .build_struct_gep(account_info, 2, "data_len")
+                            .unwrap(),
+                        "data_len",
+                    )
+                    .into_int_value();
 
                 let data = binary.builder.build_load(
                     binary
@@ -1536,7 +1570,7 @@ impl SolanaTarget {
 
                 let slice_alloca = binary.build_alloca(
                     function,
-                    binary.llvm_type(&ast::Type::Slice, ns),
+                    binary.llvm_type(&ast::Type::Slice(Box::new(Type::Bytes(1))), ns),
                     "slice_alloca",
                 );
                 let data_elem = binary
@@ -2252,7 +2286,7 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
                 let length;
                 let mut slot = *slot;
 
-                if dim.last().unwrap().is_some() {
+                if matches!(dim.last().unwrap(), ast::ArrayLength::Fixed(_)) {
                     // LLVMSizeOf() produces an i64 and malloc takes i32
                     let size = binary.builder.build_int_truncate(
                         llvm_ty.size_of().unwrap(),
@@ -2278,7 +2312,11 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
                         "dest",
                     );
                     length = binary.context.i32_type().const_int(
-                        dim.last().unwrap().as_ref().unwrap().to_u64().unwrap(),
+                        if let Some(ast::ArrayLength::Fixed(d)) = dim.last() {
+                            d.to_u64().unwrap()
+                        } else {
+                            unreachable!()
+                        },
                         false,
                     );
                 } else {
@@ -2553,7 +2591,7 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
                 "offset_ptr",
             );
 
-            let length = if let Some(length) = dim.last().unwrap().as_ref() {
+            let length = if let Some(ast::ArrayLength::Fixed(length)) = dim.last() {
                 binary
                     .context
                     .i32_type()
@@ -2564,7 +2602,7 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
 
             let mut elem_slot = *offset;
 
-            if dim.last().unwrap().is_none() {
+            if Some(&ast::ArrayLength::Dynamic) == dim.last() {
                 // reallocate to the right size
                 let member_size = binary
                     .context
@@ -3034,6 +3072,119 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
         }
     }
 
+    fn builtin_function(
+        &self,
+        binary: &Binary<'a>,
+        func: &ast::Function,
+        args: &[BasicMetadataValueEnum<'a>],
+        ns: &ast::Namespace,
+    ) -> BasicValueEnum<'a> {
+        if func.name == "create_program_address" {
+            let func = binary
+                .module
+                .get_function("sol_create_program_address")
+                .unwrap();
+
+            // first argument are the seeds
+            let seeds = binary.builder.build_pointer_cast(
+                args[0].into_pointer_value(),
+                func.get_first_param()
+                    .unwrap()
+                    .get_type()
+                    .into_pointer_type(),
+                "seeds",
+            );
+
+            let seed_count = binary.context.i64_type().const_int(
+                args[0]
+                    .into_pointer_value()
+                    .get_type()
+                    .get_element_type()
+                    .into_array_type()
+                    .len() as u64,
+                false,
+            );
+
+            // address
+            let address = binary
+                .builder
+                .build_alloca(binary.address_type(ns), "address");
+
+            binary
+                .builder
+                .build_store(address, args[1].into_array_value());
+
+            binary
+                .builder
+                .build_call(
+                    func,
+                    &[
+                        seeds.into(),
+                        seed_count.into(),
+                        address.into(),
+                        args[2], // return value
+                    ],
+                    "",
+                )
+                .try_as_basic_value()
+                .left()
+                .unwrap()
+        } else if func.name == "try_find_program_address" {
+            let func = binary
+                .module
+                .get_function("sol_try_find_program_address")
+                .unwrap();
+
+            // first argument are the seeds
+            let seeds = binary.builder.build_pointer_cast(
+                args[0].into_pointer_value(),
+                func.get_first_param()
+                    .unwrap()
+                    .get_type()
+                    .into_pointer_type(),
+                "seeds",
+            );
+
+            let seed_count = binary.context.i64_type().const_int(
+                args[0]
+                    .into_pointer_value()
+                    .get_type()
+                    .get_element_type()
+                    .into_array_type()
+                    .len() as u64,
+                false,
+            );
+
+            // address
+            let address = binary
+                .builder
+                .build_alloca(binary.address_type(ns), "address");
+
+            binary
+                .builder
+                .build_store(address, args[1].into_array_value());
+
+            binary
+                .builder
+                .build_call(
+                    func,
+                    &[
+                        seeds.into(),
+                        seed_count.into(),
+                        address.into(),
+                        args[2], // return address/pubkey
+                        args[3], // return seed bump
+                    ],
+                    "",
+                )
+                .try_as_basic_value()
+                .left()
+                .unwrap()
+        } else {
+            unreachable!();
+        }
+    }
+
     /// Call external binary
     fn external_call<'b>(
         &self,
@@ -3631,6 +3782,28 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
 
                 binary.builder.build_load(value, "self_address")
             }
+            codegen::Expression::Builtin(_, _, codegen::Builtin::ProgramId, _) => {
+                let parameters = self.sol_parameters(binary);
+
+                let account_id = binary
+                    .builder
+                    .build_load(
+                        binary
+                            .builder
+                            .build_struct_gep(parameters, 7, "program_id")
+                            .unwrap(),
+                        "program_id",
+                    )
+                    .into_pointer_value();
+
+                let value = binary.builder.build_pointer_cast(
+                    account_id,
+                    binary.address_type(ns).ptr_type(AddressSpace::Generic),
+                    "",
+                );
+
+                binary.builder.build_load(value, "program_id")
+            }
             codegen::Expression::Builtin(_, _, codegen::Builtin::Calldata, _) => {
                 let sol_params = self.sol_parameters(binary);
 

+ 11 - 9
src/emit/substrate.rs

@@ -800,7 +800,7 @@ impl SubstrateTarget {
                 dest.into()
             }
             ast::Type::Array(_, dim) => {
-                if let Some(d) = &dim.last().unwrap() {
+                if let Some(ast::ArrayLength::Fixed(d)) = dim.last() {
                     let llvm_ty = binary.llvm_type(ty.deref_any(), ns);
 
                     let size = llvm_ty
@@ -1216,7 +1216,7 @@ impl SubstrateTarget {
                 arg,
                 data,
             ),
-            ast::Type::Array(_, dim) if dim.last().unwrap().is_some() => {
+            ast::Type::Array(_, dim) if matches!(dim.last(), Some(ast::ArrayLength::Fixed(_))) => {
                 let arg = if load {
                     binary
                         .builder
@@ -1230,7 +1230,7 @@ impl SubstrateTarget {
                 let normal_array = binary.context.append_basic_block(function, "normal_array");
                 let done_array = binary.context.append_basic_block(function, "done_array");
 
-                let dim = dim.last().unwrap().as_ref().unwrap().to_u64().unwrap();
+                let dim = ty.array_length().unwrap().to_u64().unwrap();
 
                 let elem_ty = ty.array_deref();
 
@@ -1690,11 +1690,13 @@ impl SubstrateTarget {
 
                 sum.as_basic_value().into_int_value()
             }
-            ast::Type::Array(_, dims) if dims.last().unwrap().is_some() => {
-                let array_length = binary.context.i32_type().const_int(
-                    dims.last().unwrap().as_ref().unwrap().to_u64().unwrap(),
-                    false,
-                );
+            ast::Type::Array(_, dims)
+                if matches!(dims.last(), Some(ast::ArrayLength::Fixed(_))) =>
+            {
+                let array_length = binary
+                    .context
+                    .i32_type()
+                    .const_int(ty.array_length().unwrap().to_u64().unwrap(), false);
 
                 let elem_ty = ty.array_deref();
 
@@ -1811,7 +1813,7 @@ impl SubstrateTarget {
                     )
                 }
             }
-            ast::Type::Array(_, dims) if dims.last().unwrap().is_none() => {
+            ast::Type::Array(_, dims) if dims.last() == Some(&ast::ArrayLength::Dynamic) => {
                 let arg = if load {
                     binary.builder.build_load(arg.into_pointer_value(), "")
                 } else {

+ 26 - 2
src/sema/ast.rs

@@ -27,7 +27,7 @@ pub enum Type {
     Bytes(u8),
     DynamicBytes,
     String,
-    Array(Box<Type>, Vec<Option<BigInt>>),
+    Array(Box<Type>, Vec<ArrayLength>),
     /// The usize is an index into enums in the namespace
     Enum(usize),
     /// The usize is an index into contracts in the namespace
@@ -56,11 +56,34 @@ pub enum Type {
     Void,
     Unreachable,
     /// DynamicBytes and String are lowered to a vector.
-    Slice,
+    Slice(Box<Type>),
     /// We could not resolve this type
     Unresolved,
 }
 
+#[derive(PartialEq, Clone, Eq, Hash, Debug)]
+pub enum ArrayLength {
+    Fixed(BigInt),
+    Dynamic,
+    /// Fixed length arrays, any length permitted. This is useful for when we
+    /// do not want dynamic length, but want to permit any length. For example
+    /// the create_program_address() call takes any number of seeds as its
+    /// first argument, and we don't want to allocate a dynamic array for
+    /// this parameter as this would be wasteful to allocate a vector for
+    /// this argument.
+    AnyFixed,
+}
+
+impl ArrayLength {
+    /// Get the length, if fixed
+    pub fn array_length(&self) -> Option<&BigInt> {
+        match self {
+            ArrayLength::Fixed(len) => Some(len),
+            _ => None,
+        }
+    }
+}
+
 pub trait RetrieveType {
     /// Return the type for this expression. This assumes the expression has a single value,
     /// panics will occur otherwise
@@ -1000,6 +1023,7 @@ pub enum Builtin {
     GasLimit,
     BlockNumber,
     Slot,
+    ProgramId,
     Timestamp,
     Calldata,
     Sender,

+ 150 - 5
src/sema/builtin.rs

@@ -1,6 +1,6 @@
 use super::ast::{
-    Builtin, BuiltinStruct, Diagnostic, Expression, File, Namespace, Parameter, StructDecl, Symbol,
-    Type,
+    ArrayLength, Builtin, BuiltinStruct, Diagnostic, Expression, File, Function, Namespace,
+    Parameter, StructDecl, Symbol, Type,
 };
 use super::diagnostics::Diagnostics;
 use super::eval::eval_const_number;
@@ -11,8 +11,8 @@ use crate::Target;
 use num_bigint::BigInt;
 use num_traits::One;
 use once_cell::sync::Lazy;
-use solang_parser::pt;
 use solang_parser::pt::CodeLocation;
+use solang_parser::pt::{self, Identifier};
 use std::path::PathBuf;
 
 pub struct Prototype {
@@ -339,7 +339,7 @@ static BUILTIN_FUNCTIONS: Lazy<[Prototype; 27]> = Lazy::new(|| {
 });
 
 // A list of all Solidity builtins variables
-static BUILTIN_VARIABLE: Lazy<[Prototype; 15]> = Lazy::new(|| {
+static BUILTIN_VARIABLE: Lazy<[Prototype; 16]> = Lazy::new(|| {
     [
         Prototype {
             builtin: Builtin::BlockCoinbase,
@@ -396,6 +396,17 @@ static BUILTIN_VARIABLE: Lazy<[Prototype; 15]> = Lazy::new(|| {
             doc: "Current slot number",
             constant: false,
         },
+        Prototype {
+            builtin: Builtin::ProgramId,
+            namespace: Some("tx"),
+            method: None,
+            name: "program_id",
+            params: vec![],
+            ret: vec![Type::Address(false)],
+            target: vec![Target::Solana],
+            doc: "Program ID of currently executing program",
+            constant: false,
+        },
         Prototype {
             builtin: Builtin::Timestamp,
             namespace: Some("block"),
@@ -501,7 +512,10 @@ static BUILTIN_VARIABLE: Lazy<[Prototype; 15]> = Lazy::new(|| {
             method: None,
             name: "accounts",
             params: vec![],
-            ret: vec![Type::Array(Box::new(Type::Struct(0)), vec![None])],
+            ret: vec![Type::Array(
+                Box::new(Type::Struct(0)),
+                vec![ArrayLength::Dynamic],
+            )],
             target: vec![Target::Solana],
             doc: "Accounts passed into transaction",
             constant: false,
@@ -1608,5 +1622,136 @@ impl Namespace {
             &id,
             Symbol::Struct(pt::Loc::Builtin, account_meta_no)
         ));
+
+        let mut func = Function::new(
+            pt::Loc::Builtin,
+            "create_program_address".to_string(),
+            None,
+            Vec::new(),
+            pt::FunctionTy::Function,
+            None,
+            pt::Visibility::Public(None),
+            vec![
+                Parameter {
+                    loc: pt::Loc::Builtin,
+                    id: None,
+                    ty: Type::Array(
+                        Box::new(Type::Slice(Box::new(Type::Bytes(1)))),
+                        vec![ArrayLength::AnyFixed],
+                    ),
+                    ty_loc: None,
+                    readonly: false,
+                    indexed: false,
+                    recursive: false,
+                },
+                Parameter {
+                    loc: pt::Loc::Builtin,
+                    id: None,
+                    ty: Type::Address(false),
+                    ty_loc: None,
+                    readonly: false,
+                    indexed: false,
+                    recursive: false,
+                },
+            ],
+            vec![Parameter {
+                loc: pt::Loc::Builtin,
+                id: None,
+                ty: Type::Address(false),
+                ty_loc: None,
+                readonly: false,
+                indexed: false,
+                recursive: false,
+            }],
+            self,
+        );
+
+        func.has_body = true;
+
+        let func_no = self.functions.len();
+        let id = Identifier {
+            name: func.name.to_owned(),
+            loc: pt::Loc::Builtin,
+        };
+
+        self.functions.push(func);
+
+        assert!(self.add_symbol(
+            file_no,
+            None,
+            &id,
+            Symbol::Function(vec![(pt::Loc::Builtin, func_no)])
+        ));
+
+        let mut func = Function::new(
+            pt::Loc::Builtin,
+            "try_find_program_address".to_string(),
+            None,
+            Vec::new(),
+            pt::FunctionTy::Function,
+            None,
+            pt::Visibility::Public(None),
+            vec![
+                Parameter {
+                    loc: pt::Loc::Builtin,
+                    id: None,
+                    ty: Type::Array(
+                        Box::new(Type::Slice(Box::new(Type::Bytes(1)))),
+                        vec![ArrayLength::AnyFixed],
+                    ),
+                    ty_loc: None,
+                    readonly: false,
+                    indexed: false,
+                    recursive: false,
+                },
+                Parameter {
+                    loc: pt::Loc::Builtin,
+                    id: None,
+                    ty: Type::Address(false),
+                    ty_loc: None,
+                    readonly: false,
+                    indexed: false,
+                    recursive: false,
+                },
+            ],
+            vec![
+                Parameter {
+                    loc: pt::Loc::Builtin,
+                    id: None,
+                    ty: Type::Address(false),
+                    ty_loc: None,
+                    readonly: false,
+                    indexed: false,
+                    recursive: false,
+                },
+                Parameter {
+                    loc: pt::Loc::Builtin,
+                    id: None,
+                    ty: Type::Bytes(1),
+                    ty_loc: None,
+                    readonly: false,
+                    indexed: false,
+                    recursive: false,
+                },
+            ],
+            self,
+        );
+
+        func.has_body = true;
+
+        let func_no = self.functions.len();
+        let id = Identifier {
+            name: func.name.to_owned(),
+            loc: pt::Loc::Builtin,
+        };
+
+        self.functions.push(func);
+
+        assert!(self.add_symbol(
+            file_no,
+            None,
+            &id,
+            Symbol::Function(vec![(pt::Loc::Builtin, func_no)])
+        ));
     }
 }

+ 6 - 2
src/sema/dotgraphviz.rs

@@ -2166,11 +2166,15 @@ impl Namespace {
         }
 
         // free functions
-        if !self.functions.iter().any(|func| func.contract_no.is_some()) {
+        if self
+            .functions
+            .iter()
+            .any(|func| func.contract_no.is_none() && func.loc != pt::Loc::Builtin)
+        {
             let functions = dot.add_node(Node::new("free_functions", Vec::new()), None, None);
 
             for func in &self.functions {
-                if func.contract_no.is_none() {
+                if func.contract_no.is_none() && func.loc != pt::Loc::Builtin {
                     dot.add_function(func, self, functions);
                 }
             }

+ 79 - 23
src/sema/expression.rs

@@ -1,7 +1,7 @@
 use super::address::to_hexstr_eip55;
 use super::ast::{
-    Builtin, BuiltinStruct, CallArgs, CallTy, Diagnostic, Expression, Function, Mutability,
-    Namespace, StringLocation, Symbol, Type,
+    ArrayLength, Builtin, BuiltinStruct, CallArgs, CallTy, Diagnostic, Expression, Function,
+    Mutability, Namespace, StringLocation, Symbol, Type,
 };
 use super::builtin;
 use super::contracts::is_base;
@@ -1061,6 +1061,20 @@ impl Expression {
                     Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
                 }
             }
+            // Match any array with ArrayLength::AnyFixed if is it fixed for that dimension, and the
+            // element type and other dimensions also match
+            (Type::Array(from_elem, from_dim), Type::Array(to_elem, to_dim))
+                if from_elem == to_elem
+                    && from_dim.len() == to_dim.len()
+                    && from_dim.iter().zip(to_dim.iter()).all(|(f, t)| {
+                        f == t || matches!((f, t), (ArrayLength::Fixed(_), ArrayLength::AnyFixed))
+                    }) =>
+            {
+                Ok(self.clone())
+            }
+            (Type::DynamicBytes, Type::Slice(ty)) if ty.as_ref() == &Type::Bytes(1) => {
+                Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
+            }
             _ => {
                 diagnostics.push(Diagnostic::cast_error(
                     *loc,
@@ -1640,7 +1654,7 @@ pub fn expression(
         pt::Expression::StringLiteral(v) => {
             Ok(string_literal(v, context.file_no, diagnostics, resolve_to))
         }
-        pt::Expression::HexLiteral(v) => hex_literal(v, diagnostics),
+        pt::Expression::HexLiteral(v) => hex_literal(v, diagnostics, resolve_to),
         pt::Expression::NumberLiteral(loc, integer, exp) => number_literal(
             loc,
             integer,
@@ -2200,8 +2214,8 @@ fn string_literal(
 
     let length = result.len();
 
-    if let ResolveTo::Type(Type::String) = resolve_to {
-        Expression::AllocDynamicArray(
+    match resolve_to {
+        ResolveTo::Type(Type::String) => Expression::AllocDynamicArray(
             loc,
             Type::String,
             Box::new(Expression::NumberLiteral(
@@ -2210,13 +2224,28 @@ fn string_literal(
                 BigInt::from(length),
             )),
             Some(result),
-        )
-    } else {
-        Expression::BytesLiteral(loc, Type::Bytes(length as u8), result)
+        ),
+        ResolveTo::Type(Type::Slice(ty)) if ty.as_ref() == &Type::Bytes(1) => {
+            Expression::AllocDynamicArray(
+                loc,
+                Type::Slice(ty.clone()),
+                Box::new(Expression::NumberLiteral(
+                    loc,
+                    Type::Uint(32),
+                    BigInt::from(length),
+                )),
+                Some(result),
+            )
+        }
+        _ => Expression::BytesLiteral(loc, Type::Bytes(length as u8), result),
     }
 }
 
-fn hex_literal(v: &[pt::HexLiteral], diagnostics: &mut Diagnostics) -> Result<Expression, ()> {
+fn hex_literal(
+    v: &[pt::HexLiteral],
+    diagnostics: &mut Diagnostics,
+    resolve_to: ResolveTo,
+) -> Result<Expression, ()> {
     let mut result = Vec::new();
     let mut loc = v[0].loc;
 
@@ -2235,11 +2264,35 @@ fn hex_literal(v: &[pt::HexLiteral], diagnostics: &mut Diagnostics) -> Result<Ex
 
     let length = result.len();
 
-    Ok(Expression::BytesLiteral(
-        loc,
-        Type::Bytes(length as u8),
-        result,
-    ))
+    match resolve_to {
+        ResolveTo::Type(Type::Slice(ty)) if ty.as_ref() == &Type::Bytes(1) => {
+            Ok(Expression::AllocDynamicArray(
+                loc,
+                Type::Slice(ty.clone()),
+                Box::new(Expression::NumberLiteral(
+                    loc,
+                    Type::Uint(32),
+                    BigInt::from(length),
+                )),
+                Some(result),
+            ))
+        }
+        ResolveTo::Type(Type::DynamicBytes) => Ok(Expression::AllocDynamicArray(
+            loc,
+            Type::DynamicBytes,
+            Box::new(Expression::NumberLiteral(
+                loc,
+                Type::Uint(32),
+                BigInt::from(length),
+            )),
+            Some(result),
+        )),
+        _ => Ok(Expression::BytesLiteral(
+            loc,
+            Type::Bytes(length as u8),
+            result,
+        )),
+    }
 }
 
 fn hex_number_literal(
@@ -3551,7 +3604,7 @@ pub fn new(
 
     match &ty {
         Type::Array(ty, dim) => {
-            if dim.last().unwrap().is_some() {
+            if matches!(dim.last(), Some(ArrayLength::Fixed(_))) {
                 diagnostics.push(Diagnostic::error(
                     *loc,
                     format!(
@@ -4591,13 +4644,13 @@ fn member_access(
         Type::Array(_, dim) => {
             if id.name == "length" {
                 return match dim.last().unwrap() {
-                    None => Ok(Expression::Builtin(
+                    ArrayLength::Dynamic => Ok(Expression::Builtin(
                         *loc,
                         vec![Type::Uint(32)],
                         Builtin::ArrayLength,
                         vec![expr],
                     )),
-                    Some(d) => {
+                    ArrayLength::Fixed(d) => {
                         //We should not eliminate an array from the code when 'length' is called
                         //So the variable is also assigned a value to be read from 'length'
                         assigned_variable(ns, &expr, symtable);
@@ -4610,6 +4663,7 @@ fn member_access(
                             ResolveTo::Type(&Type::Uint(32)),
                         )
                     }
+                    ArrayLength::AnyFixed => unreachable!(),
                 };
             }
         }
@@ -4652,7 +4706,7 @@ fn member_access(
                 if id.name == "length" {
                     let elem_ty = expr.ty().storage_array_elem().deref_into();
 
-                    if let Some(dim) = &dim.last().unwrap() {
+                    if let Some(ArrayLength::Fixed(dim)) = dim.last() {
                         // sparse array could be large than ns.storage_type() on Solana
                         if dim.bits() > ns.storage_type().bits(ns) as u64 {
                             return Ok(Expression::StorageArrayLength {
@@ -5943,7 +5997,7 @@ fn method_call_pos_args(
                 }
 
                 if func.name == "push" {
-                    if dim.last().unwrap().is_some() {
+                    if matches!(dim.last(), Some(ArrayLength::Fixed(_))) {
                         diagnostics.push(Diagnostic::error(
                             func.loc,
                             "method 'push()' not allowed on fixed length array".to_string(),
@@ -5999,7 +6053,7 @@ fn method_call_pos_args(
                     ));
                 }
                 if func.name == "pop" {
-                    if dim.last().unwrap().is_some() {
+                    if matches!(dim.last(), Some(ArrayLength::Fixed(_))) {
                         diagnostics.push(Diagnostic::error(
                             func.loc,
                             "method 'pop()' not allowed on fixed length array".to_string(),
@@ -6918,7 +6972,7 @@ fn array_literal(
 
     // We follow the solidity scheme were everthing gets implicitly converted to the
     // type of the first element
-    let first = expression(
+    let mut first = expression(
         flattened.next().unwrap(),
         context,
         ns,
@@ -6928,6 +6982,8 @@ fn array_literal(
     )?;
 
     let ty = if let ResolveTo::Type(ty) = resolve_to {
+        first = first.cast(&first.loc(), ty, true, ns, diagnostics)?;
+
         ty.clone()
     } else {
         first.ty()
@@ -6950,8 +7006,8 @@ fn array_literal(
     let aty = Type::Array(
         Box::new(ty),
         dims.iter()
-            .map(|n| Some(BigInt::from_u32(*n).unwrap()))
-            .collect::<Vec<Option<BigInt>>>(),
+            .map(|n| ArrayLength::Fixed(BigInt::from_u32(*n).unwrap()))
+            .collect::<Vec<ArrayLength>>(),
     );
 
     if context.constant {

+ 1 - 0
src/sema/mutability.rs

@@ -246,6 +246,7 @@ fn read_expression(expr: &Expression, state: &mut StateCheck) -> bool {
         Expression::Builtin(loc, _, Builtin::GetAddress, _)
         | Expression::Builtin(loc, _, Builtin::BlockNumber, _)
         | Expression::Builtin(loc, _, Builtin::Timestamp, _)
+        | Expression::Builtin(loc, _, Builtin::ProgramId, _)
         | Expression::Builtin(loc, _, Builtin::BlockCoinbase, _)
         | Expression::Builtin(loc, _, Builtin::BlockDifficulty, _)
         | Expression::Builtin(loc, _, Builtin::BlockHash, _)

+ 6 - 4
src/sema/namespace.rs

@@ -1,5 +1,7 @@
 use super::{
-    ast::{Diagnostic, Mutability, Namespace, Note, Parameter, RetrieveType, Symbol, Type},
+    ast::{
+        ArrayLength, Diagnostic, Mutability, Namespace, Note, Parameter, RetrieveType, Symbol, Type,
+    },
     builtin,
     diagnostics::Diagnostics,
     eval::eval_const_number,
@@ -757,7 +759,7 @@ impl Namespace {
         fn resolve_dimensions(
             ast_dimensions: &[Option<(pt::Loc, BigInt)>],
             diagnostics: &mut Diagnostics,
-        ) -> Result<Vec<Option<BigInt>>, ()> {
+        ) -> Result<Vec<ArrayLength>, ()> {
             let mut dimensions = Vec::new();
 
             for d in ast_dimensions.iter().rev() {
@@ -775,9 +777,9 @@ impl Namespace {
                         ));
                         return Err(());
                     }
-                    dimensions.push(Some(n.clone()));
+                    dimensions.push(ArrayLength::Fixed(n.clone()));
                 } else {
-                    dimensions.push(None);
+                    dimensions.push(ArrayLength::Dynamic);
                 }
             }
 

+ 44 - 30
src/sema/types.rs

@@ -2,8 +2,8 @@ use super::tags::resolve_tags;
 use super::SOLANA_BUCKET_SIZE;
 use super::{
     ast::{
-        BuiltinStruct, Contract, Diagnostic, EnumDecl, EventDecl, Namespace, Parameter, StructDecl,
-        Symbol, Tag, Type, UserTypeDecl,
+        ArrayLength, BuiltinStruct, Contract, Diagnostic, EnumDecl, EventDecl, Namespace,
+        Parameter, StructDecl, Symbol, Tag, Type, UserTypeDecl,
     },
     diagnostics::Diagnostics,
     SOLANA_SPARSE_ARRAY_SIZE,
@@ -794,9 +794,9 @@ impl Type {
                 "{}{}",
                 ty.to_string(ns),
                 len.iter()
-                    .map(|l| match l {
-                        None => "[]".to_string(),
-                        Some(l) => format!("[{}]", l),
+                    .map(|len| match len {
+                        ArrayLength::Fixed(len) => format!("[{}]", len),
+                        _ => "[]".to_string(),
                     })
                     .collect::<String>()
             ),
@@ -850,7 +850,7 @@ impl Type {
             Type::StorageRef(_, ty) => format!("{} storage", ty.to_string(ns)),
             Type::Void => "void".to_owned(),
             Type::Unreachable => "unreachable".to_owned(),
-            Type::Slice => "slice".to_owned(),
+            Type::Slice(ty) => format!("{} slice", ty.to_string(ns)),
             Type::Unresolved => "unresolved".to_owned(),
         }
     }
@@ -890,9 +890,9 @@ impl Type {
                 "{}{}",
                 ty.to_signature_string(say_tuple, ns),
                 len.iter()
-                    .map(|l| match l {
-                        None => "[]".to_string(),
-                        Some(l) => format!("[{}]", l),
+                    .map(|len| match len {
+                        ArrayLength::Fixed(len) => format!("[{}]", len),
+                        _ => "[]".to_string(),
                     })
                     .collect::<String>()
             ),
@@ -914,6 +914,7 @@ impl Type {
             Type::UserType(n) => ns.user_types[*n].ty.to_signature_string(say_tuple, ns),
             // TODO: should an unresolved type not match another unresolved type?
             Type::Unresolved => "unresolved".to_owned(),
+            Type::Slice(ty) => format!("{} slice", ty.to_string(ns)),
             _ => unreachable!(),
         }
     }
@@ -945,7 +946,7 @@ impl Type {
             Type::Bytes(_) => false,
             Type::Enum(_) => false,
             Type::Struct(_) => true,
-            Type::Array(_, dims) => dims.last().unwrap().is_some(),
+            Type::Array(_, dims) => matches!(dims.last(), Some(ArrayLength::Fixed(_))),
             Type::DynamicBytes => false,
             Type::String => false,
             Type::Mapping(..) => false,
@@ -954,7 +955,7 @@ impl Type {
             Type::StorageRef(..) => false,
             Type::InternalFunction { .. } => false,
             Type::ExternalFunction { .. } => false,
-            Type::Slice => false,
+            Type::Slice(_) => false,
             Type::Unresolved => false,
             _ => unreachable!("{:?}", self),
         }
@@ -996,7 +997,7 @@ impl Type {
         match self {
             Type::StorageRef(_, ty) => ty.array_length(),
             Type::Ref(ty) => ty.array_length(),
-            Type::Array(_, dim) => dim.last().unwrap().as_ref(),
+            Type::Array(_, dim) => dim.last().unwrap().array_length(),
             _ => panic!("array_length on non-array"),
         }
     }
@@ -1016,8 +1017,9 @@ impl Type {
                 ty.memory_size_of(ns).mul(
                     dims.iter()
                         .map(|d| match d {
-                            None => &pointer_size,
-                            Some(n) => n,
+                            ArrayLength::Dynamic => &pointer_size,
+                            ArrayLength::Fixed(n) => n,
+                            ArrayLength::AnyFixed => unreachable!(),
                         })
                         .product::<BigInt>(),
                 )
@@ -1052,8 +1054,9 @@ impl Type {
                 ty.solana_storage_size(ns).mul(
                     dims.iter()
                         .map(|d| match d {
-                            None => &pointer_size,
-                            Some(d) => d,
+                            ArrayLength::Dynamic => &pointer_size,
+                            ArrayLength::Fixed(d) => d,
+                            ArrayLength::AnyFixed => panic!("unknown length"),
                         })
                         .product::<BigInt>(),
                 )
@@ -1155,7 +1158,9 @@ impl Type {
                 Type::Value => BigInt::from(ns.value_length),
                 Type::Uint(n) | Type::Int(n) => BigInt::from(n / 8),
                 Type::Rational => unreachable!(),
-                Type::Array(_, dims) if dims.last().unwrap().is_none() => BigInt::from(4),
+                Type::Array(_, dims) if dims.last() == Some(&ArrayLength::Dynamic) => {
+                    BigInt::from(4)
+                }
                 Type::Array(ty, dims) => {
                     let pointer_size = BigInt::from(4);
                     if self.is_sparse_solana(ns) {
@@ -1164,8 +1169,11 @@ impl Type {
                         ty.storage_slots(ns).mul(
                             dims.iter()
                                 .map(|d| match d {
-                                    None => &pointer_size,
-                                    Some(d) => d,
+                                    ArrayLength::Dynamic => &pointer_size,
+                                    ArrayLength::Fixed(d) => d,
+                                    ArrayLength::AnyFixed => {
+                                        panic!("unknown length");
+                                    }
                                 })
                                 .product::<BigInt>(),
                         )
@@ -1207,9 +1215,12 @@ impl Type {
                     ty.storage_slots(ns)
                         * dims
                             .iter()
-                            .map(|l| match l {
-                                None => &one,
-                                Some(l) => l,
+                            .map(|len| match len {
+                                ArrayLength::Dynamic => &one,
+                                ArrayLength::Fixed(len) => len,
+                                ArrayLength::AnyFixed => {
+                                    unreachable!("unknown length")
+                                }
                             })
                             .product::<BigInt>()
                 }
@@ -1229,7 +1240,9 @@ impl Type {
                 Type::Value => BigInt::from(ns.value_length),
                 Type::Uint(n) | Type::Int(n) => BigInt::from(n / 8),
                 Type::Rational => unreachable!(),
-                Type::Array(_, dims) if dims.last().unwrap().is_none() => BigInt::from(4),
+                Type::Array(_, dims) if dims.last() == Some(&ArrayLength::Dynamic) => {
+                    BigInt::from(4)
+                }
                 Type::Array(ty, _) => {
                     if self.is_sparse_solana(ns) {
                         BigInt::from(4)
@@ -1299,7 +1312,7 @@ impl Type {
             Type::String | Type::DynamicBytes => true,
             Type::Ref(r) => r.is_dynamic(ns),
             Type::Array(ty, dim) => {
-                if dim.iter().any(|d| d.is_none()) {
+                if dim.iter().any(|d| d == &ArrayLength::Dynamic) {
                     return true;
                 }
 
@@ -1334,7 +1347,7 @@ impl Type {
     pub fn is_dynamic_memory(&self) -> bool {
         match self {
             Type::String | Type::DynamicBytes => true,
-            Type::Array(_, dim) if dim.last().unwrap().is_none() => true,
+            Type::Array(_, dim) if dim.last() == Some(&ArrayLength::Dynamic) => true,
             Type::Ref(ty) => ty.is_dynamic_memory(),
             _ => false,
         }
@@ -1470,8 +1483,8 @@ impl Type {
                 ty.to_llvm_string(ns),
                 len.iter()
                     .map(|r| match r {
-                        None => ":".to_string(),
-                        Some(r) => format!(":{}", r),
+                        ArrayLength::Dynamic | ArrayLength::AnyFixed => ":".to_string(),
+                        ArrayLength::Fixed(r) => format!(":{}", r),
                     })
                     .collect::<String>()
             ),
@@ -1484,6 +1497,7 @@ impl Type {
             Type::Ref(r) => r.to_llvm_string(ns),
             Type::StorageRef(_, r) => r.to_llvm_string(ns),
             Type::UserType(no) => ns.user_types[*no].ty.to_llvm_string(ns),
+            Type::Slice(ty) => format!("slice:{}", ty.to_llvm_string(ns)),
             _ => unreachable!(),
         }
     }
@@ -1492,14 +1506,14 @@ impl Type {
     pub fn is_sparse_solana(&self, ns: &Namespace) -> bool {
         match self.deref_any() {
             Type::Mapping(..) => true,
-            Type::Array(_, dims) if dims.last().unwrap().is_none() => false,
+            Type::Array(_, dims) if dims.last() == Some(&ArrayLength::Dynamic) => false,
             Type::Array(ty, dims) => {
                 let pointer_size = BigInt::from(4);
                 let len = ty.storage_slots(ns).mul(
                     dims.iter()
                         .map(|d| match d {
-                            None => &pointer_size,
-                            Some(d) => d,
+                            ArrayLength::Fixed(d) => d,
+                            _ => &pointer_size,
                         })
                         .product::<BigInt>(),
                 );

+ 7 - 4
src/sema/yul/expression.rs

@@ -1,4 +1,4 @@
-use crate::ast::{Namespace, Parameter, Symbol, Type};
+use crate::ast::{ArrayLength, Namespace, Parameter, Symbol, Type};
 use crate::sema::diagnostics::Diagnostics;
 use crate::sema::expression::{unescape, ExprContext};
 use crate::sema::symtable::{Symtable, VariableUsage};
@@ -562,13 +562,16 @@ fn resolve_suffix_access(
             Some(StorageLocation::Calldata(_)),
             _,
         ) => {
-            if dims.last().unwrap().is_none() && id.name != "offset" && id.name != "length" {
+            if dims.last() == Some(&ArrayLength::Dynamic)
+                && id.name != "offset"
+                && id.name != "length"
+            {
                 ns.diagnostics.push(Diagnostic::error(
                     resolved_expr.loc(),
                     "calldata variables only support '.offset' and '.length'".to_string(),
                 ));
                 return Err(());
-            } else if dims.last().unwrap().is_some() {
+            } else if matches!(dims.last(), Some(ArrayLength::Fixed(_))) {
                 ns.diagnostics.push(Diagnostic::error(
                     resolved_expr.loc(),
                     format!(
@@ -769,7 +772,7 @@ pub(crate) fn check_type(
             Some(StorageLocation::Calldata(_)),
             ..,
         ) => {
-            if dims.last().unwrap().is_none() {
+            if dims.last() == Some(&ArrayLength::Dynamic) {
                 return Some(Diagnostic::error(
                     expr.loc(),
                     "Calldata arrays must be accessed with '.offset', '.length' and the 'calldatacopy' function".to_string()

+ 2 - 2
src/sema/yul/tests/expression.rs

@@ -1,6 +1,6 @@
 #![cfg(test)]
 
-use crate::ast::{Namespace, Parameter, Symbol, Type, Variable};
+use crate::ast::{ArrayLength, Namespace, Parameter, Symbol, Type, Variable};
 use crate::diagnostics::Diagnostics;
 use crate::sema::expression::ExprContext;
 use crate::sema::symtable::{Symtable, VariableInitializer, VariableUsage};
@@ -986,7 +986,7 @@ fn test_check_types() {
 
     let expr = YulExpression::SolidityLocalVariable(
         loc,
-        Type::Array(Box::new(Type::Int(8)), vec![None]),
+        Type::Array(Box::new(Type::Int(8)), vec![ArrayLength::Dynamic]),
         Some(StorageLocation::Calldata(loc)),
         0,
     );

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

@@ -3,8 +3,8 @@ contract c {
 // BEGIN-CHECK: c::function::test1
 	function test1() public pure{
 		bytes x = "foo1";
-		// x is not being used, so it can be a slice
-// CHECK: alloc slice uint32 4 "foo1"
+		// x is not being used, so it can be a bytes1 slice
+// CHECK: alloc bytes1 slice uint32 4 "foo1"
 	bytes y = x;
 	}
 
@@ -27,7 +27,7 @@ contract c {
 		bytes x = "foo3";
 
 		foo(x);
-		// no slices for function arguments yet, so it must be a vector
+		// no bytes1 slices for function arguments yet, so it must be a vector
 // CHECK: alloc bytes uint32 4 "foo3"
 	}
 
@@ -44,7 +44,7 @@ contract c {
 		string y = x + "if";
 
 		print(x);
-// CHECK: alloc slice uint32 4 "foo4"
+// CHECK: alloc bytes1 slice uint32 4 "foo4"
 	}
 
 // BEGIN-CHECK: c::function::test5

+ 2 - 2
tests/contract_testcases/ewasm/public_internal_function.dot

@@ -2,9 +2,9 @@ strict digraph "tests/contract_testcases/ewasm/public_internal_function.sol" {
 	A [label="name:A\ncontract: foo\ntests/contract_testcases/ewasm/public_internal_function.sol:2:12-13\nfield name:a ty:function() internal"]
 	contract [label="contract foo\ntests/contract_testcases/ewasm/public_internal_function.sol:1:1-7:2"]
 	diagnostic [label="found contract 'foo'\nlevel Debug\ntests/contract_testcases/ewasm/public_internal_function.sol:1:1-7:2"]
-	diagnostic_7 [label="variable of type internal function cannot be 'public'\nlevel Error\ntests/contract_testcases/ewasm/public_internal_function.sol:6:5-8"]
+	diagnostic_6 [label="variable of type internal function cannot be 'public'\nlevel Error\ntests/contract_testcases/ewasm/public_internal_function.sol:6:5-8"]
 	structs -> A
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Error"]
+	diagnostics -> diagnostic_6 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/solana/comment.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/solana/comment.sol" {
 	contract [label="contract Hello\ntests/contract_testcases/solana/comment.sol:1:24-4:2"]
 	diagnostic [label="pragma 'solidity' is ignored\nlevel Debug\ntests/contract_testcases/solana/comment.sol:1:1-23"]
-	diagnostic_6 [label="found contract 'Hello'\nlevel Debug\ntests/contract_testcases/solana/comment.sol:1:24-4:2"]
+	diagnostic_5 [label="found contract 'Hello'\nlevel Debug\ntests/contract_testcases/solana/comment.sol:1:24-4:2"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_6 [label="Debug"]
+	diagnostics -> diagnostic_5 [label="Debug"]
 }

+ 5 - 5
tests/contract_testcases/solana/create_contract/base_contract.dot

@@ -2,15 +2,15 @@ strict digraph "tests/contract_testcases/solana/create_contract/base_contract.so
 	MathError [label="name: MathError\ncontract: Math\ntests/contract_testcases/solana/create_contract/base_contract.sol:3:13-5:14\nvalue: NO_ERROR"]
 	WithMath [label="name:WithMath\ncontract: IsMath\ntests/contract_testcases/solana/create_contract/base_contract.sol:9:20-28\nfield name:math ty:enum Math.MathError"]
 	contract [label="contract Math\ntests/contract_testcases/solana/create_contract/base_contract.sol:2:9-6:10"]
-	contract_7 [label="contract IsMath\ntests/contract_testcases/solana/create_contract/base_contract.sol:8:9-12:10"]
+	contract_6 [label="contract IsMath\ntests/contract_testcases/solana/create_contract/base_contract.sol:8:9-12:10"]
 	base [label="base Math\ntests/contract_testcases/solana/create_contract/base_contract.sol:8:28-32"]
 	diagnostic [label="found contract 'Math'\nlevel Debug\ntests/contract_testcases/solana/create_contract/base_contract.sol:2:9-6:10"]
-	diagnostic_11 [label="found contract 'IsMath'\nlevel Debug\ntests/contract_testcases/solana/create_contract/base_contract.sol:8:9-12:10"]
+	diagnostic_10 [label="found contract 'IsMath'\nlevel Debug\ntests/contract_testcases/solana/create_contract/base_contract.sol:8:9-12:10"]
 	enums -> MathError
 	structs -> WithMath
 	contracts -> contract
-	contracts -> contract_7
-	contract_7 -> base [label="base"]
+	contracts -> contract_6
+	contract_6 -> base [label="base"]
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_11 [label="Debug"]
+	diagnostics -> diagnostic_10 [label="Debug"]
 }

+ 10 - 10
tests/contract_testcases/solana/create_contract/base_contract_01.dot

@@ -3,22 +3,22 @@ strict digraph "tests/contract_testcases/solana/create_contract/base_contract_01
 	MathError [label="name: MathError\ncontract: Math\ntests/contract_testcases/solana/create_contract/base_contract_01.sol:8:13-10:14\nvalue: NO_ERROR"]
 	WithMath [label="name:WithMath\ncontract: IsMath\ntests/contract_testcases/solana/create_contract/base_contract_01.sol:14:20-28\nfield name:math ty:enum Math.MathError\nfield name:logic ty:enum Logic.LogicError"]
 	contract [label="contract Logic\ntests/contract_testcases/solana/create_contract/base_contract_01.sol:2:9-6:10"]
-	contract_8 [label="contract Math\ntests/contract_testcases/solana/create_contract/base_contract_01.sol:7:9-11:10"]
+	contract_7 [label="contract Math\ntests/contract_testcases/solana/create_contract/base_contract_01.sol:7:9-11:10"]
 	base [label="base Logic\ntests/contract_testcases/solana/create_contract/base_contract_01.sol:7:26-31"]
-	contract_10 [label="contract IsMath\ntests/contract_testcases/solana/create_contract/base_contract_01.sol:13:9-18:10"]
-	base_11 [label="base Math\ntests/contract_testcases/solana/create_contract/base_contract_01.sol:13:28-32"]
+	contract_9 [label="contract IsMath\ntests/contract_testcases/solana/create_contract/base_contract_01.sol:13:9-18:10"]
+	base_10 [label="base Math\ntests/contract_testcases/solana/create_contract/base_contract_01.sol:13:28-32"]
 	diagnostic [label="found contract 'Logic'\nlevel Debug\ntests/contract_testcases/solana/create_contract/base_contract_01.sol:2:9-6:10"]
-	diagnostic_14 [label="found contract 'Math'\nlevel Debug\ntests/contract_testcases/solana/create_contract/base_contract_01.sol:7:9-11:10"]
-	diagnostic_15 [label="found contract 'IsMath'\nlevel Debug\ntests/contract_testcases/solana/create_contract/base_contract_01.sol:13:9-18:10"]
+	diagnostic_13 [label="found contract 'Math'\nlevel Debug\ntests/contract_testcases/solana/create_contract/base_contract_01.sol:7:9-11:10"]
+	diagnostic_14 [label="found contract 'IsMath'\nlevel Debug\ntests/contract_testcases/solana/create_contract/base_contract_01.sol:13:9-18:10"]
 	enums -> LogicError
 	enums -> MathError
 	structs -> WithMath
 	contracts -> contract
-	contracts -> contract_8
-	contract_8 -> base [label="base"]
-	contracts -> contract_10
-	contract_10 -> base_11 [label="base"]
+	contracts -> contract_7
+	contract_7 -> base [label="base"]
+	contracts -> contract_9
+	contract_9 -> base_10 [label="base"]
 	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_13 [label="Debug"]
 	diagnostics -> diagnostic_14 [label="Debug"]
-	diagnostics -> diagnostic_15 [label="Debug"]
 }

+ 10 - 10
tests/contract_testcases/solana/create_contract/base_contract_02.dot

@@ -2,21 +2,21 @@ strict digraph "tests/contract_testcases/solana/create_contract/base_contract_02
 	LogicFields [label="name:LogicFields\ncontract: Logic\ntests/contract_testcases/solana/create_contract/base_contract_02.sol:3:20-31\nfield name:logia ty:uint256"]
 	WithMath [label="name:WithMath\ncontract: IsMath\ntests/contract_testcases/solana/create_contract/base_contract_02.sol:11:20-28\nfield name:logia ty:struct Logic.LogicFields"]
 	contract [label="contract Logic\ntests/contract_testcases/solana/create_contract/base_contract_02.sol:2:9-6:10"]
-	contract_6 [label="contract Math\ntests/contract_testcases/solana/create_contract/base_contract_02.sol:7:9-8:10"]
+	contract_5 [label="contract Math\ntests/contract_testcases/solana/create_contract/base_contract_02.sol:7:9-8:10"]
 	base [label="base Logic\ntests/contract_testcases/solana/create_contract/base_contract_02.sol:7:26-31"]
-	contract_8 [label="contract IsMath\ntests/contract_testcases/solana/create_contract/base_contract_02.sol:10:9-14:10"]
-	base_9 [label="base Math\ntests/contract_testcases/solana/create_contract/base_contract_02.sol:10:28-32"]
+	contract_7 [label="contract IsMath\ntests/contract_testcases/solana/create_contract/base_contract_02.sol:10:9-14:10"]
+	base_8 [label="base Math\ntests/contract_testcases/solana/create_contract/base_contract_02.sol:10:28-32"]
 	diagnostic [label="found contract 'Logic'\nlevel Debug\ntests/contract_testcases/solana/create_contract/base_contract_02.sol:2:9-6:10"]
-	diagnostic_12 [label="found contract 'Math'\nlevel Debug\ntests/contract_testcases/solana/create_contract/base_contract_02.sol:7:9-8:10"]
-	diagnostic_13 [label="found contract 'IsMath'\nlevel Debug\ntests/contract_testcases/solana/create_contract/base_contract_02.sol:10:9-14:10"]
+	diagnostic_11 [label="found contract 'Math'\nlevel Debug\ntests/contract_testcases/solana/create_contract/base_contract_02.sol:7:9-8:10"]
+	diagnostic_12 [label="found contract 'IsMath'\nlevel Debug\ntests/contract_testcases/solana/create_contract/base_contract_02.sol:10:9-14:10"]
 	structs -> LogicFields
 	structs -> WithMath
 	contracts -> contract
-	contracts -> contract_6
-	contract_6 -> base [label="base"]
-	contracts -> contract_8
-	contract_8 -> base_9 [label="base"]
+	contracts -> contract_5
+	contract_5 -> base [label="base"]
+	contracts -> contract_7
+	contract_7 -> base_8 [label="base"]
 	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_11 [label="Debug"]
 	diagnostics -> diagnostic_12 [label="Debug"]
-	diagnostics -> diagnostic_13 [label="Debug"]
 }

+ 16 - 6
tests/contract_testcases/solana/expressions/selector_in_free_function.dot

@@ -1,16 +1,26 @@
 strict digraph "tests/contract_testcases/solana/expressions/selector_in_free_function.sol" {
+	x [label="function x\ntests/contract_testcases/solana/expressions/selector_in_free_function.sol:6:9-38\nsignature x()\nvisibility internal\nmutability nonpayable"]
+	returns [label="returns\nbytes4 "]
+	return [label="return\ntests/contract_testcases/solana/expressions/selector_in_free_function.sol:7:13-32"]
+	builtins [label="builtin FunctionSelector\ntests/contract_testcases/solana/expressions/selector_in_free_function.sol:7:20-23"]
+	internal_function [label="function(bytes) internal returns (void)\nI.X\ntests/contract_testcases/solana/expressions/selector_in_free_function.sol:7:20-21"]
 	contract [label="contract I\ntests/contract_testcases/solana/expressions/selector_in_free_function.sol:2:9-4:10"]
 	X [label="function X\ncontract: I\ntests/contract_testcases/solana/expressions/selector_in_free_function.sol:3:13-39\nsignature X(bytes)\nvisibility external\nmutability nonpayable\nvirtual"]
 	parameters [label="parameters\nbytes "]
-	contract_5 [label="contract foo\ntests/contract_testcases/solana/expressions/selector_in_free_function.sol:10:9-24"]
+	contract_11 [label="contract foo\ntests/contract_testcases/solana/expressions/selector_in_free_function.sol:10:9-24"]
 	diagnostic [label="found interface 'I'\nlevel Debug\ntests/contract_testcases/solana/expressions/selector_in_free_function.sol:2:9-4:10"]
-	diagnostic_8 [label="function can be declared 'pure'\nlevel Warning\ntests/contract_testcases/solana/expressions/selector_in_free_function.sol:6:9-38"]
-	diagnostic_9 [label="found contract 'foo'\nlevel Debug\ntests/contract_testcases/solana/expressions/selector_in_free_function.sol:10:9-24"]
+	diagnostic_14 [label="function can be declared 'pure'\nlevel Warning\ntests/contract_testcases/solana/expressions/selector_in_free_function.sol:6:9-38"]
+	diagnostic_15 [label="found contract 'foo'\nlevel Debug\ntests/contract_testcases/solana/expressions/selector_in_free_function.sol:10:9-24"]
+	free_functions -> x [label="function"]
+	x -> returns [label="returns"]
+	x -> return [label="body"]
+	return -> builtins [label="expr"]
+	builtins -> internal_function [label="arg #0"]
 	contracts -> contract
 	contract -> X [label="function"]
 	X -> parameters [label="parameters"]
-	contracts -> contract_5
+	contracts -> contract_11
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_8 [label="Warning"]
-	diagnostics -> diagnostic_9 [label="Debug"]
+	diagnostics -> diagnostic_14 [label="Warning"]
+	diagnostics -> diagnostic_15 [label="Debug"]
 }

+ 4 - 4
tests/contract_testcases/solana/immutable_function.dot

@@ -1,10 +1,10 @@
 strict digraph "tests/contract_testcases/solana/immutable_function.sol" {
 	contract [label="contract t\ntests/contract_testcases/solana/immutable_function.sol:1:26-4:2"]
 	diagnostic [label="function cannot be declared 'immutable'\nlevel Error\ntests/contract_testcases/solana/immutable_function.sol:1:14-23"]
-	diagnostic_6 [label="found contract 't'\nlevel Debug\ntests/contract_testcases/solana/immutable_function.sol:1:26-4:2"]
-	diagnostic_7 [label="function cannot be declared 'immutable'\nlevel Error\ntests/contract_testcases/solana/immutable_function.sol:3:18-27"]
+	diagnostic_5 [label="found contract 't'\nlevel Debug\ntests/contract_testcases/solana/immutable_function.sol:1:26-4:2"]
+	diagnostic_6 [label="function cannot be declared 'immutable'\nlevel Error\ntests/contract_testcases/solana/immutable_function.sol:3:18-27"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Error"]
-	diagnostics -> diagnostic_6 [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Error"]
+	diagnostics -> diagnostic_5 [label="Debug"]
+	diagnostics -> diagnostic_6 [label="Error"]
 }

+ 36 - 14
tests/contract_testcases/solana/import_contracts_via_object.dot

@@ -1,28 +1,50 @@
 strict digraph "tests/contract_testcases/solana/import_contracts_via_object.sol" {
 	S [label="name:S\ntests/contract_testcases/solana/simple.sol:3:8-9\nfield name:f1 ty:int64\nfield name:f2 ty:bool"]
+	inc [label="function inc\ntests/contract_testcases/solana/simple.sol:6:2-7:23\nsignature inc((int64,bool))\nvisibility internal\nmutability pure"]
+	parameters [label="parameters\nstruct S s"]
+	expr [label="expression\ntests/contract_testcases/solana/simple.sol:7:26-35"]
+	assign [label="assign\nvoid\ntests/contract_testcases/solana/simple.sol:7:26-35"]
+	structmember [label="struct member #0 int64\ntests/contract_testcases/solana/simple.sol:7:28-30"]
+	variable [label="variable: s\nstruct S\ntests/contract_testcases/solana/simple.sol:7:26-27"]
+	add [label="add\nint64\ntests/contract_testcases/solana/simple.sol:7:26-35"]
+	load [label="load int64\ntests/contract_testcases/solana/simple.sol:7:26-35"]
+	structmember_11 [label="struct member #0 int64\ntests/contract_testcases/solana/simple.sol:7:28-30"]
+	variable_12 [label="variable: s\nstruct S\ntests/contract_testcases/solana/simple.sol:7:26-27"]
+	number_literal [label="int64 literal: 1\ntests/contract_testcases/solana/simple.sol:7:34-35"]
 	contract [label="contract C\ntests/contract_testcases/solana/import_contracts_via_object.sol:2:1-11:2"]
 	base [label="base A\ntests/contract_testcases/solana/import_contracts_via_object.sol:3:15-20"]
 	using [label="library L"]
-	node_6 [label="constructor \ncontract: C\ntests/contract_testcases/solana/import_contracts_via_object.sol:5:2-23\nsignature ()\nvisibility public\nmutability nonpayable"]
+	node_18 [label="constructor \ncontract: C\ntests/contract_testcases/solana/import_contracts_via_object.sol:5:2-23\nsignature ()\nvisibility public\nmutability nonpayable"]
 	foo [label="function foo\ncontract: C\ntests/contract_testcases/solana/import_contracts_via_object.sol:8:2-23\nsignature foo()\nvisibility public\nmutability nonpayable"]
-	contract_8 [label="contract A\ntests/contract_testcases/solana/simple.sol:1:1-14"]
-	contract_9 [label="contract L\ntests/contract_testcases/solana/simple.sol:1:14-2:13"]
+	contract_20 [label="contract A\ntests/contract_testcases/solana/simple.sol:1:1-14"]
+	contract_21 [label="contract L\ntests/contract_testcases/solana/simple.sol:1:14-2:13"]
 	diagnostic [label="found contract 'C'\nlevel Debug\ntests/contract_testcases/solana/import_contracts_via_object.sol:2:1-11:2"]
-	diagnostic_12 [label="revert with custom error 'IMP.E' not supported yet\nlevel Error\ntests/contract_testcases/solana/import_contracts_via_object.sol:6:10-15"]
-	diagnostic_13 [label="revert with custom errors or named arguments not supported yet\nlevel Error\ntests/contract_testcases/solana/import_contracts_via_object.sol:9:3-25"]
-	diagnostic_14 [label="found contract 'A'\nlevel Debug\ntests/contract_testcases/solana/simple.sol:1:1-14"]
-	diagnostic_15 [label="found library 'L'\nlevel Debug\ntests/contract_testcases/solana/simple.sol:1:14-2:13"]
+	diagnostic_24 [label="revert with custom error 'IMP.E' not supported yet\nlevel Error\ntests/contract_testcases/solana/import_contracts_via_object.sol:6:10-15"]
+	diagnostic_25 [label="revert with custom errors or named arguments not supported yet\nlevel Error\ntests/contract_testcases/solana/import_contracts_via_object.sol:9:3-25"]
+	diagnostic_26 [label="found contract 'A'\nlevel Debug\ntests/contract_testcases/solana/simple.sol:1:1-14"]
+	diagnostic_27 [label="found library 'L'\nlevel Debug\ntests/contract_testcases/solana/simple.sol:1:14-2:13"]
 	structs -> S
+	free_functions -> inc [label="function"]
+	inc -> parameters [label="parameters"]
+	inc -> expr [label="body"]
+	expr -> assign [label="expr"]
+	assign -> structmember [label="left"]
+	structmember -> variable [label="var"]
+	assign -> add [label="right"]
+	add -> load [label="left"]
+	load -> structmember_11 [label="expr"]
+	structmember_11 -> variable_12 [label="var"]
+	add -> number_literal [label="right"]
 	contracts -> contract
 	contract -> base [label="base"]
 	contract -> using [label="base"]
-	contract -> node_6 [label="constructor"]
+	contract -> node_18 [label="constructor"]
 	contract -> foo [label="function"]
-	contracts -> contract_8
-	contracts -> contract_9
+	contracts -> contract_20
+	contracts -> contract_21
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_12 [label="Error"]
-	diagnostics -> diagnostic_13 [label="Error"]
-	diagnostics -> diagnostic_14 [label="Debug"]
-	diagnostics -> diagnostic_15 [label="Debug"]
+	diagnostics -> diagnostic_24 [label="Error"]
+	diagnostics -> diagnostic_25 [label="Error"]
+	diagnostics -> diagnostic_26 [label="Debug"]
+	diagnostics -> diagnostic_27 [label="Debug"]
 }

+ 54 - 36
tests/contract_testcases/solana/keep_on_resolving.dot

@@ -4,59 +4,77 @@ strict digraph "tests/contract_testcases/solana/keep_on_resolving.sol" {
 	GlobalFoo [label="name:GlobalFoo\ncontract: c\ntests/contract_testcases/solana/type_decl_broken.sol:7:9-18\nfield name:f1 ty:int256"]
 	GlobalFoo_5 [label="name:GlobalFoo ty:address payable\ntests/contract_testcases/solana/type_decl_broken.sol:1:1-34"]
 	Value [label="name:Value ty:uint128\ncontract: c\ntests/contract_testcases/solana/type_decl_broken.sol:9:2-23"]
+	f [label="function f\ntests/contract_testcases/solana/keep_on_resolving.sol:6:1-7:30\nsignature f((unresolved))\nvisibility internal\nmutability nonpayable"]
+	parameters [label="parameters\nstruct S s"]
+	returns [label="returns\nint256 "]
+	return [label="return\ntests/contract_testcases/solana/keep_on_resolving.sol:8:2-13"]
+	load [label="load unresolved\ntests/contract_testcases/solana/keep_on_resolving.sol:8:2-13"]
+	structmember [label="struct member #0 unresolved\ntests/contract_testcases/solana/keep_on_resolving.sol:8:11-13"]
+	variable [label="variable: s\nstruct S\ntests/contract_testcases/solana/keep_on_resolving.sol:8:9-10"]
+	g [label="function g\ntests/contract_testcases/solana/keep_on_resolving.sol:10:1-11:17\nsignature g((unresolved))\nvisibility internal\nmutability nonpayable"]
+	parameters_16 [label="parameters\nstruct S s"]
 	contract [label="contract c\ntests/contract_testcases/solana/type_decl_broken.sol:2:1-19:2"]
 	inc_and_wrap [label="function inc_and_wrap\ncontract: c\ntests/contract_testcases/solana/type_decl_broken.sol:12:2-56\nsignature inc_and_wrap(int128)\nvisibility public\nmutability nonpayable"]
-	parameters [label="parameters\nint128 v"]
-	returns [label="returns\nusertype c.Value "]
+	parameters_20 [label="parameters\nint128 v"]
+	returns_21 [label="returns\nusertype c.Value "]
 	dec_and_unwrap [label="function dec_and_unwrap\ncontract: c\ntests/contract_testcases/solana/type_decl_broken.sol:16:2-59\nsignature dec_and_unwrap(uint128)\nvisibility public\nmutability nonpayable"]
-	parameters_13 [label="parameters\nusertype c.Value v"]
-	returns_14 [label="returns\nuint128 "]
-	return [label="return\ntests/contract_testcases/solana/type_decl_broken.sol:17:3-29"]
+	parameters_23 [label="parameters\nusertype c.Value v"]
+	returns_24 [label="returns\nuint128 "]
+	return_25 [label="return\ntests/contract_testcases/solana/type_decl_broken.sol:17:3-29"]
 	subtract [label="subtract\nuint128\ntests/contract_testcases/solana/type_decl_broken.sol:17:10-29"]
 	builtins [label="builtin UserTypeUnwrap\ntests/contract_testcases/solana/type_decl_broken.sol:17:10-25"]
-	variable [label="variable: v\nusertype c.Value\ntests/contract_testcases/solana/type_decl_broken.sol:17:23-24"]
+	variable_28 [label="variable: v\nusertype c.Value\ntests/contract_testcases/solana/type_decl_broken.sol:17:23-24"]
 	number_literal [label="uint128 literal: 1\ntests/contract_testcases/solana/type_decl_broken.sol:17:28-29"]
 	diagnostic [label="type 'in' not found\nlevel Error\ntests/contract_testcases/solana/keep_on_resolving.sol:4:2-4"]
-	diagnostic_22 [label="expected 'struct S', found integer\nlevel Error\ntests/contract_testcases/solana/keep_on_resolving.sol:15:6-7"]
-	diagnostic_23 [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/solana/type_decl_broken.sol:2:1-19:2"]
-	diagnostic_24 [label="foo is already defined as a struct\nlevel Error\ntests/contract_testcases/solana/type_decl_broken.sol:5:7-10"]
+	diagnostic_32 [label="expected 'struct S', found integer\nlevel Error\ntests/contract_testcases/solana/keep_on_resolving.sol:15:6-7"]
+	diagnostic_33 [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/solana/type_decl_broken.sol:2:1-19:2"]
+	diagnostic_34 [label="foo is already defined as a struct\nlevel Error\ntests/contract_testcases/solana/type_decl_broken.sol:5:7-10"]
 	note [label="location of previous definition\ntests/contract_testcases/solana/type_decl_broken.sol:4:9-12"]
-	diagnostic_26 [label="'int256[2]' is not an elementary value type\nlevel Error\ntests/contract_testcases/solana/type_decl_broken.sol:5:14-20"]
-	diagnostic_27 [label="foo is already defined as a struct\nlevel Error\ntests/contract_testcases/solana/type_decl_broken.sol:6:7-10"]
-	note_28 [label="location of previous definition\ntests/contract_testcases/solana/type_decl_broken.sol:4:9-12"]
-	diagnostic_29 [label="GlobalFoo is already defined as an user type\nlevel Warning\ntests/contract_testcases/solana/type_decl_broken.sol:7:9-18"]
-	note_30 [label="location of previous definition\ntests/contract_testcases/solana/type_decl_broken.sol:1:6-15"]
-	diagnostic_31 [label="Value is already defined as an user type\nlevel Error\ntests/contract_testcases/solana/type_decl_broken.sol:10:9-14"]
-	note_32 [label="location of previous definition\ntests/contract_testcases/solana/type_decl_broken.sol:9:7-12"]
-	diagnostic_33 [label="implicit conversion would change sign from int136 to uint128\nlevel Error\ntests/contract_testcases/solana/type_decl_broken.sol:13:21-26"]
+	diagnostic_36 [label="'int256[2]' is not an elementary value type\nlevel Error\ntests/contract_testcases/solana/type_decl_broken.sol:5:14-20"]
+	diagnostic_37 [label="foo is already defined as a struct\nlevel Error\ntests/contract_testcases/solana/type_decl_broken.sol:6:7-10"]
+	note_38 [label="location of previous definition\ntests/contract_testcases/solana/type_decl_broken.sol:4:9-12"]
+	diagnostic_39 [label="GlobalFoo is already defined as an user type\nlevel Warning\ntests/contract_testcases/solana/type_decl_broken.sol:7:9-18"]
+	note_40 [label="location of previous definition\ntests/contract_testcases/solana/type_decl_broken.sol:1:6-15"]
+	diagnostic_41 [label="Value is already defined as an user type\nlevel Error\ntests/contract_testcases/solana/type_decl_broken.sol:10:9-14"]
+	note_42 [label="location of previous definition\ntests/contract_testcases/solana/type_decl_broken.sol:9:7-12"]
+	diagnostic_43 [label="implicit conversion would change sign from int136 to uint128\nlevel Error\ntests/contract_testcases/solana/type_decl_broken.sol:13:21-26"]
 	structs -> S
 	structs -> foo
 	structs -> GlobalFoo
 	types -> GlobalFoo_5
 	types -> Value
+	free_functions -> f [label="function"]
+	f -> parameters [label="parameters"]
+	f -> returns [label="returns"]
+	f -> return [label="body"]
+	return -> load [label="expr"]
+	load -> structmember [label="expr"]
+	structmember -> variable [label="var"]
+	free_functions -> g [label="function"]
+	g -> parameters_16 [label="parameters"]
 	contracts -> contract
 	contract -> inc_and_wrap [label="function"]
-	inc_and_wrap -> parameters [label="parameters"]
-	inc_and_wrap -> returns [label="returns"]
+	inc_and_wrap -> parameters_20 [label="parameters"]
+	inc_and_wrap -> returns_21 [label="returns"]
 	contract -> dec_and_unwrap [label="function"]
-	dec_and_unwrap -> parameters_13 [label="parameters"]
-	dec_and_unwrap -> returns_14 [label="returns"]
-	dec_and_unwrap -> return [label="body"]
-	return -> subtract [label="expr"]
+	dec_and_unwrap -> parameters_23 [label="parameters"]
+	dec_and_unwrap -> returns_24 [label="returns"]
+	dec_and_unwrap -> return_25 [label="body"]
+	return_25 -> subtract [label="expr"]
 	subtract -> builtins [label="left"]
-	builtins -> variable [label="arg #0"]
+	builtins -> variable_28 [label="arg #0"]
 	subtract -> number_literal [label="right"]
 	diagnostics -> diagnostic [label="Error"]
-	diagnostics -> diagnostic_22 [label="Error"]
-	diagnostics -> diagnostic_23 [label="Debug"]
-	diagnostics -> diagnostic_24 [label="Error"]
-	diagnostic_24 -> note [label="note"]
-	diagnostics -> diagnostic_26 [label="Error"]
-	diagnostics -> diagnostic_27 [label="Error"]
-	diagnostic_27 -> note_28 [label="note"]
-	diagnostics -> diagnostic_29 [label="Warning"]
-	diagnostic_29 -> note_30 [label="note"]
-	diagnostics -> diagnostic_31 [label="Error"]
-	diagnostic_31 -> note_32 [label="note"]
-	diagnostics -> diagnostic_33 [label="Error"]
+	diagnostics -> diagnostic_32 [label="Error"]
+	diagnostics -> diagnostic_33 [label="Debug"]
+	diagnostics -> diagnostic_34 [label="Error"]
+	diagnostic_34 -> note [label="note"]
+	diagnostics -> diagnostic_36 [label="Error"]
+	diagnostics -> diagnostic_37 [label="Error"]
+	diagnostic_37 -> note_38 [label="note"]
+	diagnostics -> diagnostic_39 [label="Warning"]
+	diagnostic_39 -> note_40 [label="note"]
+	diagnostics -> diagnostic_41 [label="Error"]
+	diagnostic_41 -> note_42 [label="note"]
+	diagnostics -> diagnostic_43 [label="Error"]
 }

+ 122 - 100
tests/contract_testcases/solana/override.dot

@@ -1,5 +1,16 @@
 strict digraph "tests/contract_testcases/solana/override.sol" {
 	S [label="name:S\ntests/contract_testcases/solana/simple.sol:3:8-9\nfield name:f1 ty:int64\nfield name:f2 ty:bool"]
+	inc [label="function inc\ntests/contract_testcases/solana/simple.sol:6:2-7:23\nsignature inc((int64,bool))\nvisibility internal\nmutability pure"]
+	parameters [label="parameters\nstruct S s"]
+	expr [label="expression\ntests/contract_testcases/solana/simple.sol:7:26-35"]
+	assign [label="assign\nvoid\ntests/contract_testcases/solana/simple.sol:7:26-35"]
+	structmember [label="struct member #0 int64\ntests/contract_testcases/solana/simple.sol:7:28-30"]
+	variable [label="variable: s\nstruct S\ntests/contract_testcases/solana/simple.sol:7:26-27"]
+	add [label="add\nint64\ntests/contract_testcases/solana/simple.sol:7:26-35"]
+	load [label="load int64\ntests/contract_testcases/solana/simple.sol:7:26-35"]
+	structmember_11 [label="struct member #0 int64\ntests/contract_testcases/solana/simple.sol:7:28-30"]
+	variable_12 [label="variable: s\nstruct S\ntests/contract_testcases/solana/simple.sol:7:26-27"]
+	number_literal [label="int64 literal: 1\ntests/contract_testcases/solana/simple.sol:7:34-35"]
 	contract [label="contract C\ntests/contract_testcases/solana/override.sol:4:1-7:2"]
 	base [label="base A\ntests/contract_testcases/solana/override.sol:5:15-20"]
 	var [label="variable meh\nvisibility public\ntests/contract_testcases/solana/override.sol:6:2-32"]
@@ -8,61 +19,72 @@ strict digraph "tests/contract_testcases/solana/override.sol" {
 	return [label="return\nimplicit"]
 	storage_load [label="storage load int256\nimplicit"]
 	storage_var [label="storage variable\nC.meh\nint256 storage\nimplicit"]
-	contract_11 [label="contract A\ntests/contract_testcases/solana/override.sol:8:1-11:2"]
+	contract_23 [label="contract A\ntests/contract_testcases/solana/override.sol:8:1-11:2"]
 	foo [label="function foo\ncontract: A\ntests/contract_testcases/solana/override.sol:10:5-43\nsignature foo()\nvisibility external\nmutability nonpayable\nvirtual"]
-	returns_13 [label="returns\nuint256 "]
-	contract_14 [label="contract B\ntests/contract_testcases/solana/override.sol:11:2-14:2"]
-	foo_15 [label="function foo\ncontract: B\ntests/contract_testcases/solana/override.sol:13:5-43\nsignature foo()\nvisibility external\nmutability nonpayable\nvirtual"]
-	returns_16 [label="returns\nuint256 "]
-	contract_17 [label="contract X\ntests/contract_testcases/solana/override.sol:14:2-17:2"]
-	base_18 [label="base A\ntests/contract_testcases/solana/override.sol:15:15-16"]
-	base_19 [label="base B\ntests/contract_testcases/solana/override.sol:15:18-19"]
-	var_20 [label="variable foo\nvisibility public\ntests/contract_testcases/solana/override.sol:16:9-39"]
-	foo_21 [label="function foo\ncontract: X\ntests/contract_testcases/solana/override.sol:16:36-39\nsignature foo()\nvisibility public\nmutability view\noverride A\noverride B"]
-	returns_22 [label="returns\nuint256 "]
-	return_23 [label="return\nimplicit"]
-	storage_load_24 [label="storage load uint256\nimplicit"]
-	storage_var_25 [label="storage variable\nX.foo\nuint256 storage\nimplicit"]
-	contract_26 [label="contract Y\ntests/contract_testcases/solana/override.sol:17:2-19:2"]
-	base_27 [label="base X\ntests/contract_testcases/solana/override.sol:18:15-16"]
-	contract_28 [label="contract A2\ntests/contract_testcases/solana/override.sol:20:1-23:2"]
-	foo_29 [label="function foo\ncontract: A2\ntests/contract_testcases/solana/override.sol:22:5-51\nsignature foo()\nvisibility external\nmutability nonpayable\nvirtual"]
-	returns_30 [label="returns\nuint256 "]
-	return_31 [label="return\ntests/contract_testcases/solana/override.sol:22:54-62"]
-	number_literal [label="uint256 literal: 1\ntests/contract_testcases/solana/override.sol:22:61-62"]
-	contract_33 [label="contract B2\ntests/contract_testcases/solana/override.sol:23:2-26:2"]
-	foo_34 [label="function foo\ncontract: B2\ntests/contract_testcases/solana/override.sol:25:5-51\nsignature foo()\nvisibility external\nmutability nonpayable\nvirtual"]
-	returns_35 [label="returns\nuint256 "]
-	return_36 [label="return\ntests/contract_testcases/solana/override.sol:25:54-62"]
-	number_literal_37 [label="uint256 literal: 2\ntests/contract_testcases/solana/override.sol:25:61-62"]
-	contract_38 [label="contract X2\ntests/contract_testcases/solana/override.sol:26:2-29:2"]
-	base_39 [label="base A2\ntests/contract_testcases/solana/override.sol:27:16-18"]
-	base_40 [label="base B2\ntests/contract_testcases/solana/override.sol:27:20-22"]
-	var_41 [label="variable foo\nvisibility public\ntests/contract_testcases/solana/override.sol:28:9-37"]
-	foo_42 [label="function foo\ncontract: X2\ntests/contract_testcases/solana/override.sol:28:34-37\nsignature foo()\nvisibility public\nmutability view\noverride A2"]
-	returns_43 [label="returns\nuint256 "]
-	return_44 [label="return\nimplicit"]
-	storage_load_45 [label="storage load uint256\nimplicit"]
-	storage_var_46 [label="storage variable\nX2.foo\nuint256 storage\nimplicit"]
-	contract_47 [label="contract Y2\ntests/contract_testcases/solana/override.sol:29:2-31:2"]
-	base_48 [label="base X2\ntests/contract_testcases/solana/override.sol:30:16-18"]
-	contract_49 [label="contract A\ntests/contract_testcases/solana/simple.sol:1:1-14"]
-	contract_50 [label="contract L\ntests/contract_testcases/solana/simple.sol:1:14-2:13"]
+	returns_25 [label="returns\nuint256 "]
+	contract_26 [label="contract B\ntests/contract_testcases/solana/override.sol:11:2-14:2"]
+	foo_27 [label="function foo\ncontract: B\ntests/contract_testcases/solana/override.sol:13:5-43\nsignature foo()\nvisibility external\nmutability nonpayable\nvirtual"]
+	returns_28 [label="returns\nuint256 "]
+	contract_29 [label="contract X\ntests/contract_testcases/solana/override.sol:14:2-17:2"]
+	base_30 [label="base A\ntests/contract_testcases/solana/override.sol:15:15-16"]
+	base_31 [label="base B\ntests/contract_testcases/solana/override.sol:15:18-19"]
+	var_32 [label="variable foo\nvisibility public\ntests/contract_testcases/solana/override.sol:16:9-39"]
+	foo_33 [label="function foo\ncontract: X\ntests/contract_testcases/solana/override.sol:16:36-39\nsignature foo()\nvisibility public\nmutability view\noverride A\noverride B"]
+	returns_34 [label="returns\nuint256 "]
+	return_35 [label="return\nimplicit"]
+	storage_load_36 [label="storage load uint256\nimplicit"]
+	storage_var_37 [label="storage variable\nX.foo\nuint256 storage\nimplicit"]
+	contract_38 [label="contract Y\ntests/contract_testcases/solana/override.sol:17:2-19:2"]
+	base_39 [label="base X\ntests/contract_testcases/solana/override.sol:18:15-16"]
+	contract_40 [label="contract A2\ntests/contract_testcases/solana/override.sol:20:1-23:2"]
+	foo_41 [label="function foo\ncontract: A2\ntests/contract_testcases/solana/override.sol:22:5-51\nsignature foo()\nvisibility external\nmutability nonpayable\nvirtual"]
+	returns_42 [label="returns\nuint256 "]
+	return_43 [label="return\ntests/contract_testcases/solana/override.sol:22:54-62"]
+	number_literal_44 [label="uint256 literal: 1\ntests/contract_testcases/solana/override.sol:22:61-62"]
+	contract_45 [label="contract B2\ntests/contract_testcases/solana/override.sol:23:2-26:2"]
+	foo_46 [label="function foo\ncontract: B2\ntests/contract_testcases/solana/override.sol:25:5-51\nsignature foo()\nvisibility external\nmutability nonpayable\nvirtual"]
+	returns_47 [label="returns\nuint256 "]
+	return_48 [label="return\ntests/contract_testcases/solana/override.sol:25:54-62"]
+	number_literal_49 [label="uint256 literal: 2\ntests/contract_testcases/solana/override.sol:25:61-62"]
+	contract_50 [label="contract X2\ntests/contract_testcases/solana/override.sol:26:2-29:2"]
+	base_51 [label="base A2\ntests/contract_testcases/solana/override.sol:27:16-18"]
+	base_52 [label="base B2\ntests/contract_testcases/solana/override.sol:27:20-22"]
+	var_53 [label="variable foo\nvisibility public\ntests/contract_testcases/solana/override.sol:28:9-37"]
+	foo_54 [label="function foo\ncontract: X2\ntests/contract_testcases/solana/override.sol:28:34-37\nsignature foo()\nvisibility public\nmutability view\noverride A2"]
+	returns_55 [label="returns\nuint256 "]
+	return_56 [label="return\nimplicit"]
+	storage_load_57 [label="storage load uint256\nimplicit"]
+	storage_var_58 [label="storage variable\nX2.foo\nuint256 storage\nimplicit"]
+	contract_59 [label="contract Y2\ntests/contract_testcases/solana/override.sol:29:2-31:2"]
+	base_60 [label="base X2\ntests/contract_testcases/solana/override.sol:30:16-18"]
+	contract_61 [label="contract A\ntests/contract_testcases/solana/simple.sol:1:1-14"]
+	contract_62 [label="contract L\ntests/contract_testcases/solana/simple.sol:1:14-2:13"]
 	diagnostic [label="global variable has no bases contracts to override\nlevel Error\ntests/contract_testcases/solana/override.sol:3:14-22"]
-	diagnostic_53 [label="found contract 'C'\nlevel Debug\ntests/contract_testcases/solana/override.sol:4:1-7:2"]
-	diagnostic_54 [label="'meh' does not override anything\nlevel Error\ntests/contract_testcases/solana/override.sol:6:29-32"]
-	diagnostic_55 [label="found interface 'A'\nlevel Debug\ntests/contract_testcases/solana/override.sol:8:1-11:2"]
-	diagnostic_56 [label="found interface 'B'\nlevel Debug\ntests/contract_testcases/solana/override.sol:11:2-14:2"]
-	diagnostic_57 [label="found contract 'X'\nlevel Debug\ntests/contract_testcases/solana/override.sol:14:2-17:2"]
-	diagnostic_58 [label="found contract 'Y'\nlevel Debug\ntests/contract_testcases/solana/override.sol:17:2-19:2"]
-	diagnostic_59 [label="found abstract contract 'A2'\nlevel Debug\ntests/contract_testcases/solana/override.sol:20:1-23:2"]
-	diagnostic_60 [label="found abstract contract 'B2'\nlevel Debug\ntests/contract_testcases/solana/override.sol:23:2-26:2"]
-	diagnostic_61 [label="found contract 'X2'\nlevel Debug\ntests/contract_testcases/solana/override.sol:26:2-29:2"]
-	diagnostic_62 [label="function 'foo' missing overrides 'B2', specify 'override(B2,A2)'\nlevel Error\ntests/contract_testcases/solana/override.sol:28:21-33"]
-	diagnostic_63 [label="found contract 'Y2'\nlevel Debug\ntests/contract_testcases/solana/override.sol:29:2-31:2"]
-	diagnostic_64 [label="found contract 'A'\nlevel Debug\ntests/contract_testcases/solana/simple.sol:1:1-14"]
-	diagnostic_65 [label="found library 'L'\nlevel Debug\ntests/contract_testcases/solana/simple.sol:1:14-2:13"]
+	diagnostic_65 [label="found contract 'C'\nlevel Debug\ntests/contract_testcases/solana/override.sol:4:1-7:2"]
+	diagnostic_66 [label="'meh' does not override anything\nlevel Error\ntests/contract_testcases/solana/override.sol:6:29-32"]
+	diagnostic_67 [label="found interface 'A'\nlevel Debug\ntests/contract_testcases/solana/override.sol:8:1-11:2"]
+	diagnostic_68 [label="found interface 'B'\nlevel Debug\ntests/contract_testcases/solana/override.sol:11:2-14:2"]
+	diagnostic_69 [label="found contract 'X'\nlevel Debug\ntests/contract_testcases/solana/override.sol:14:2-17:2"]
+	diagnostic_70 [label="found contract 'Y'\nlevel Debug\ntests/contract_testcases/solana/override.sol:17:2-19:2"]
+	diagnostic_71 [label="found abstract contract 'A2'\nlevel Debug\ntests/contract_testcases/solana/override.sol:20:1-23:2"]
+	diagnostic_72 [label="found abstract contract 'B2'\nlevel Debug\ntests/contract_testcases/solana/override.sol:23:2-26:2"]
+	diagnostic_73 [label="found contract 'X2'\nlevel Debug\ntests/contract_testcases/solana/override.sol:26:2-29:2"]
+	diagnostic_74 [label="function 'foo' missing overrides 'B2', specify 'override(B2,A2)'\nlevel Error\ntests/contract_testcases/solana/override.sol:28:21-33"]
+	diagnostic_75 [label="found contract 'Y2'\nlevel Debug\ntests/contract_testcases/solana/override.sol:29:2-31:2"]
+	diagnostic_76 [label="found contract 'A'\nlevel Debug\ntests/contract_testcases/solana/simple.sol:1:1-14"]
+	diagnostic_77 [label="found library 'L'\nlevel Debug\ntests/contract_testcases/solana/simple.sol:1:14-2:13"]
 	structs -> S
+	free_functions -> inc [label="function"]
+	inc -> parameters [label="parameters"]
+	inc -> expr [label="body"]
+	expr -> assign [label="expr"]
+	assign -> structmember [label="left"]
+	structmember -> variable [label="var"]
+	assign -> add [label="right"]
+	add -> load [label="left"]
+	load -> structmember_11 [label="expr"]
+	structmember_11 -> variable_12 [label="var"]
+	add -> number_literal [label="right"]
 	contracts -> contract
 	contract -> base [label="base"]
 	contract -> var [label="variable"]
@@ -71,58 +93,58 @@ strict digraph "tests/contract_testcases/solana/override.sol" {
 	meh -> return [label="body"]
 	return -> storage_load [label="expr"]
 	storage_load -> storage_var [label="expr"]
-	contracts -> contract_11
-	contract_11 -> foo [label="function"]
-	foo -> returns_13 [label="returns"]
-	contracts -> contract_14
-	contract_14 -> foo_15 [label="function"]
-	foo_15 -> returns_16 [label="returns"]
-	contracts -> contract_17
-	contract_17 -> base_18 [label="base"]
-	contract_17 -> base_19 [label="base"]
-	contract_17 -> var_20 [label="variable"]
-	contract_17 -> foo_21 [label="function"]
-	foo_21 -> returns_22 [label="returns"]
-	foo_21 -> return_23 [label="body"]
-	return_23 -> storage_load_24 [label="expr"]
-	storage_load_24 -> storage_var_25 [label="expr"]
+	contracts -> contract_23
+	contract_23 -> foo [label="function"]
+	foo -> returns_25 [label="returns"]
 	contracts -> contract_26
-	contract_26 -> base_27 [label="base"]
-	contracts -> contract_28
-	contract_28 -> foo_29 [label="function"]
-	foo_29 -> returns_30 [label="returns"]
-	foo_29 -> return_31 [label="body"]
-	return_31 -> number_literal [label="expr"]
-	contracts -> contract_33
-	contract_33 -> foo_34 [label="function"]
-	foo_34 -> returns_35 [label="returns"]
-	foo_34 -> return_36 [label="body"]
-	return_36 -> number_literal_37 [label="expr"]
+	contract_26 -> foo_27 [label="function"]
+	foo_27 -> returns_28 [label="returns"]
+	contracts -> contract_29
+	contract_29 -> base_30 [label="base"]
+	contract_29 -> base_31 [label="base"]
+	contract_29 -> var_32 [label="variable"]
+	contract_29 -> foo_33 [label="function"]
+	foo_33 -> returns_34 [label="returns"]
+	foo_33 -> return_35 [label="body"]
+	return_35 -> storage_load_36 [label="expr"]
+	storage_load_36 -> storage_var_37 [label="expr"]
 	contracts -> contract_38
 	contract_38 -> base_39 [label="base"]
-	contract_38 -> base_40 [label="base"]
-	contract_38 -> var_41 [label="variable"]
-	contract_38 -> foo_42 [label="function"]
-	foo_42 -> returns_43 [label="returns"]
-	foo_42 -> return_44 [label="body"]
-	return_44 -> storage_load_45 [label="expr"]
-	storage_load_45 -> storage_var_46 [label="expr"]
-	contracts -> contract_47
-	contract_47 -> base_48 [label="base"]
-	contracts -> contract_49
+	contracts -> contract_40
+	contract_40 -> foo_41 [label="function"]
+	foo_41 -> returns_42 [label="returns"]
+	foo_41 -> return_43 [label="body"]
+	return_43 -> number_literal_44 [label="expr"]
+	contracts -> contract_45
+	contract_45 -> foo_46 [label="function"]
+	foo_46 -> returns_47 [label="returns"]
+	foo_46 -> return_48 [label="body"]
+	return_48 -> number_literal_49 [label="expr"]
 	contracts -> contract_50
+	contract_50 -> base_51 [label="base"]
+	contract_50 -> base_52 [label="base"]
+	contract_50 -> var_53 [label="variable"]
+	contract_50 -> foo_54 [label="function"]
+	foo_54 -> returns_55 [label="returns"]
+	foo_54 -> return_56 [label="body"]
+	return_56 -> storage_load_57 [label="expr"]
+	storage_load_57 -> storage_var_58 [label="expr"]
+	contracts -> contract_59
+	contract_59 -> base_60 [label="base"]
+	contracts -> contract_61
+	contracts -> contract_62
 	diagnostics -> diagnostic [label="Error"]
-	diagnostics -> diagnostic_53 [label="Debug"]
-	diagnostics -> diagnostic_54 [label="Error"]
-	diagnostics -> diagnostic_55 [label="Debug"]
-	diagnostics -> diagnostic_56 [label="Debug"]
-	diagnostics -> diagnostic_57 [label="Debug"]
-	diagnostics -> diagnostic_58 [label="Debug"]
-	diagnostics -> diagnostic_59 [label="Debug"]
-	diagnostics -> diagnostic_60 [label="Debug"]
-	diagnostics -> diagnostic_61 [label="Debug"]
-	diagnostics -> diagnostic_62 [label="Error"]
-	diagnostics -> diagnostic_63 [label="Debug"]
-	diagnostics -> diagnostic_64 [label="Debug"]
 	diagnostics -> diagnostic_65 [label="Debug"]
+	diagnostics -> diagnostic_66 [label="Error"]
+	diagnostics -> diagnostic_67 [label="Debug"]
+	diagnostics -> diagnostic_68 [label="Debug"]
+	diagnostics -> diagnostic_69 [label="Debug"]
+	diagnostics -> diagnostic_70 [label="Debug"]
+	diagnostics -> diagnostic_71 [label="Debug"]
+	diagnostics -> diagnostic_72 [label="Debug"]
+	diagnostics -> diagnostic_73 [label="Debug"]
+	diagnostics -> diagnostic_74 [label="Error"]
+	diagnostics -> diagnostic_75 [label="Debug"]
+	diagnostics -> diagnostic_76 [label="Debug"]
+	diagnostics -> diagnostic_77 [label="Debug"]
 }

+ 3 - 3
tests/contract_testcases/solana/structs/parse_structs_06.dot

@@ -2,11 +2,11 @@ strict digraph "tests/contract_testcases/solana/structs/parse_structs_06.sol" {
 	Foo [label="name:Foo\ncontract: test_struct_parsing\ntests/contract_testcases/solana/structs/parse_structs_06.sol:3:20-23\nfield name:x ty:bool\nfield name:y ty:struct test_struct_parsing.Foo"]
 	contract [label="contract test_struct_parsing\ntests/contract_testcases/solana/structs/parse_structs_06.sol:2:9-7:10"]
 	diagnostic [label="found contract 'test_struct_parsing'\nlevel Debug\ntests/contract_testcases/solana/structs/parse_structs_06.sol:2:9-7:10"]
-	diagnostic_7 [label="struct 'Foo' has infinite size\nlevel Error\ntests/contract_testcases/solana/structs/parse_structs_06.sol:3:20-23"]
+	diagnostic_6 [label="struct 'Foo' has infinite size\nlevel Error\ntests/contract_testcases/solana/structs/parse_structs_06.sol:3:20-23"]
 	note [label="recursive field 'y'\ntests/contract_testcases/solana/structs/parse_structs_06.sol:5:17-22"]
 	structs -> Foo
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Error"]
-	diagnostic_7 -> note [label="note"]
+	diagnostics -> diagnostic_6 [label="Error"]
+	diagnostic_6 -> note [label="note"]
 }

+ 29 - 15
tests/contract_testcases/solana/type_called_error.dot

@@ -1,38 +1,52 @@
 strict digraph "tests/contract_testcases/solana/type_called_error.sol" {
 	error [label="name:error\ntests/contract_testcases/solana/type_called_error.sol:1:8-13\nfield name:f1 ty:int256"]
+	member [label="function member\ntests/contract_testcases/solana/type_called_error.sol:2:1-3:44\nsignature member((int256))\nvisibility internal\nmutability pure"]
+	parameters [label="parameters\nstruct error e"]
+	returns [label="returns\nint256 "]
+	return [label="return\ntests/contract_testcases/solana/type_called_error.sol:4:2-13"]
+	load [label="load int256\ntests/contract_testcases/solana/type_called_error.sol:4:2-13"]
+	structmember [label="struct member #0 int256\ntests/contract_testcases/solana/type_called_error.sol:4:11-13"]
+	variable [label="variable: e\nstruct error\ntests/contract_testcases/solana/type_called_error.sol:4:9-10"]
 	contract [label="contract c\ntests/contract_testcases/solana/type_called_error.sol:8:1-16:2"]
 	var [label="variable v1\nvisibility public\ntests/contract_testcases/solana/type_called_error.sol:10:2-17"]
 	v1 [label="function v1\ncontract: c\ntests/contract_testcases/solana/type_called_error.sol:10:15-17\nsignature v1()\nvisibility public\nmutability view"]
-	returns [label="returns\nstruct error "]
-	return [label="return\nimplicit"]
+	returns_14 [label="returns\nstruct error "]
+	return_15 [label="return\nimplicit"]
 	storage_load [label="storage load struct error\nimplicit"]
 	storage_var [label="storage variable\nc.v1\nstruct error storage\nimplicit"]
 	test [label="function test\ncontract: c\ntests/contract_testcases/solana/type_called_error.sol:12:2-54\nsignature test((int256))\nvisibility internal\nmutability pure"]
-	parameters [label="parameters\nstruct error e"]
-	returns_12 [label="returns\nstruct error "]
+	parameters_19 [label="parameters\nstruct error e"]
+	returns_20 [label="returns\nstruct error "]
 	expr [label="expression\ntests/contract_testcases/solana/type_called_error.sol:13:3-13"]
 	call_internal_function [label="call internal function\ntests/contract_testcases/solana/type_called_error.sol:13:3-13"]
 	internal_function [label="function(struct error) internal pure returns (void)\nfree function member\ntests/contract_testcases/solana/type_called_error.sol:13:3-13"]
-	variable [label="variable: e\nstruct error\ntests/contract_testcases/solana/type_called_error.sol:13:3-4"]
-	return_17 [label="return\ntests/contract_testcases/solana/type_called_error.sol:14:3-11"]
-	variable_18 [label="variable: e\nstruct error\ntests/contract_testcases/solana/type_called_error.sol:14:10-11"]
+	variable_24 [label="variable: e\nstruct error\ntests/contract_testcases/solana/type_called_error.sol:13:3-4"]
+	return_25 [label="return\ntests/contract_testcases/solana/type_called_error.sol:14:3-11"]
+	variable_26 [label="variable: e\nstruct error\ntests/contract_testcases/solana/type_called_error.sol:14:10-11"]
 	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/solana/type_called_error.sol:8:1-16:2"]
 	structs -> error
+	free_functions -> member [label="function"]
+	member -> parameters [label="parameters"]
+	member -> returns [label="returns"]
+	member -> return [label="body"]
+	return -> load [label="expr"]
+	load -> structmember [label="expr"]
+	structmember -> variable [label="var"]
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> v1 [label="function"]
-	v1 -> returns [label="returns"]
-	v1 -> return [label="body"]
-	return -> storage_load [label="expr"]
+	v1 -> returns_14 [label="returns"]
+	v1 -> return_15 [label="body"]
+	return_15 -> storage_load [label="expr"]
 	storage_load -> storage_var [label="expr"]
 	contract -> test [label="function"]
-	test -> parameters [label="parameters"]
-	test -> returns_12 [label="returns"]
+	test -> parameters_19 [label="parameters"]
+	test -> returns_20 [label="returns"]
 	test -> expr [label="body"]
 	expr -> call_internal_function [label="expr"]
 	call_internal_function -> internal_function [label="function"]
-	call_internal_function -> variable [label="arg #0"]
-	expr -> return_17 [label="next"]
-	return_17 -> variable_18 [label="expr"]
+	call_internal_function -> variable_24 [label="arg #0"]
+	expr -> return_25 [label="next"]
+	return_25 -> variable_26 [label="expr"]
 	diagnostics -> diagnostic [label="Debug"]
 }

+ 12 - 8
tests/contract_testcases/solana/type_decl_broken_more.dot

@@ -1,22 +1,26 @@
 strict digraph "tests/contract_testcases/solana/type_decl_broken_more.sol" {
 	Addr [label="name:Addr ty:address payable\ntests/contract_testcases/solana/type_decl.sol:1:1-2:29"]
 	Binary [label="name:Binary ty:bool\ncontract: x\ntests/contract_testcases/solana/type_decl.sol:5:2-21"]
+	bar [label="function bar\ntests/contract_testcases/solana/type_decl_broken_more.sol:4:1-5:24\nsignature bar(int256)\nvisibility internal\nmutability nonpayable"]
+	parameters [label="parameters\nint256 Addr"]
 	contract [label="contract x\ntests/contract_testcases/solana/type_decl.sol:3:1-8:2"]
 	f [label="function f\ncontract: x\ntests/contract_testcases/solana/type_decl.sol:7:2-33\nsignature f(bytes32,bool)\nvisibility public\nmutability nonpayable"]
-	parameters [label="parameters\nusertype Addr \nusertype x.Binary "]
+	parameters_10 [label="parameters\nusertype Addr \nusertype x.Binary "]
 	diagnostic [label="'Addr' is an user type\nlevel Error\ntests/contract_testcases/solana/type_decl_broken_more.sol:3:14-18"]
-	diagnostic_10 [label="declaration of 'Addr' shadows type\nlevel Warning\ntests/contract_testcases/solana/type_decl_broken_more.sol:5:18-22"]
+	diagnostic_13 [label="declaration of 'Addr' shadows type\nlevel Warning\ntests/contract_testcases/solana/type_decl_broken_more.sol:5:18-22"]
 	note [label="previous declaration of type\ntests/contract_testcases/solana/type_decl.sol:2:6-10"]
-	diagnostic_12 [label="found contract 'x'\nlevel Debug\ntests/contract_testcases/solana/type_decl.sol:3:1-8:2"]
-	diagnostic_13 [label="function can be declared 'pure'\nlevel Warning\ntests/contract_testcases/solana/type_decl.sol:7:2-33"]
+	diagnostic_15 [label="found contract 'x'\nlevel Debug\ntests/contract_testcases/solana/type_decl.sol:3:1-8:2"]
+	diagnostic_16 [label="function can be declared 'pure'\nlevel Warning\ntests/contract_testcases/solana/type_decl.sol:7:2-33"]
 	types -> Addr
 	types -> Binary
+	free_functions -> bar [label="function"]
+	bar -> parameters [label="parameters"]
 	contracts -> contract
 	contract -> f [label="function"]
-	f -> parameters [label="parameters"]
+	f -> parameters_10 [label="parameters"]
 	diagnostics -> diagnostic [label="Error"]
-	diagnostics -> diagnostic_10 [label="Warning"]
-	diagnostic_10 -> note [label="note"]
-	diagnostics -> diagnostic_12 [label="Debug"]
 	diagnostics -> diagnostic_13 [label="Warning"]
+	diagnostic_13 -> note [label="note"]
+	diagnostics -> diagnostic_15 [label="Debug"]
+	diagnostics -> diagnostic_16 [label="Warning"]
 }

+ 69 - 25
tests/contract_testcases/solana/using_import.dot

@@ -1,38 +1,82 @@
 strict digraph "tests/contract_testcases/solana/using_import.sol" {
 	S [label="name:S\ntests/contract_testcases/solana/simple.sol:3:8-9\nfield name:f1 ty:int64\nfield name:f2 ty:bool"]
+	inc [label="function inc\ntests/contract_testcases/solana/simple.sol:6:2-7:23\nsignature inc((int64,bool))\nvisibility internal\nmutability pure"]
+	parameters [label="parameters\nstruct S s"]
+	expr [label="expression\ntests/contract_testcases/solana/simple.sol:7:26-35"]
+	assign [label="assign\nvoid\ntests/contract_testcases/solana/simple.sol:7:26-35"]
+	structmember [label="struct member #0 int64\ntests/contract_testcases/solana/simple.sol:7:28-30"]
+	variable [label="variable: s\nstruct S\ntests/contract_testcases/solana/simple.sol:7:26-27"]
+	add [label="add\nint64\ntests/contract_testcases/solana/simple.sol:7:26-35"]
+	load [label="load int64\ntests/contract_testcases/solana/simple.sol:7:26-35"]
+	structmember_11 [label="struct member #0 int64\ntests/contract_testcases/solana/simple.sol:7:28-30"]
+	variable_12 [label="variable: s\nstruct S\ntests/contract_testcases/solana/simple.sol:7:26-27"]
+	number_literal [label="int64 literal: 1\ntests/contract_testcases/solana/simple.sol:7:34-35"]
+	dec [label="function dec\ntests/contract_testcases/solana/using_import.sol:2:1-3:31\nsignature dec((int64,bool))\nvisibility internal\nmutability pure"]
+	parameters_15 [label="parameters\nstruct S s"]
+	expr_16 [label="expression\ntests/contract_testcases/solana/using_import.sol:3:34-43"]
+	assign_17 [label="assign\nvoid\ntests/contract_testcases/solana/using_import.sol:3:34-43"]
+	structmember_18 [label="struct member #0 int64\ntests/contract_testcases/solana/using_import.sol:3:36-38"]
+	variable_19 [label="variable: s\nstruct S\ntests/contract_testcases/solana/using_import.sol:3:34-35"]
+	subtract [label="subtract\nint64\ntests/contract_testcases/solana/using_import.sol:3:34-43"]
+	load_21 [label="load int64\ntests/contract_testcases/solana/using_import.sol:3:34-43"]
+	structmember_22 [label="struct member #0 int64\ntests/contract_testcases/solana/using_import.sol:3:36-38"]
+	variable_23 [label="variable: s\nstruct S\ntests/contract_testcases/solana/using_import.sol:3:34-35"]
+	number_literal_24 [label="int64 literal: 1\ntests/contract_testcases/solana/using_import.sol:3:42-43"]
 	contract [label="contract c\ntests/contract_testcases/solana/using_import.sol:5:1-11:2"]
 	test [label="function test\ncontract: c\ntests/contract_testcases/solana/using_import.sol:7:2-35\nsignature test((int64,bool))\nvisibility public\nmutability nonpayable"]
-	parameters [label="parameters\nstruct S s"]
-	expr [label="expression\ntests/contract_testcases/solana/using_import.sol:8:3-10"]
+	parameters_28 [label="parameters\nstruct S s"]
+	expr_29 [label="expression\ntests/contract_testcases/solana/using_import.sol:8:3-10"]
 	call_internal_function [label="call internal function\ntests/contract_testcases/solana/using_import.sol:8:3-10"]
 	internal_function [label="function(struct S) internal pure returns (void)\nfree function inc\ntests/contract_testcases/solana/using_import.sol:8:3-10"]
-	variable [label="variable: s\nstruct S\ntests/contract_testcases/solana/using_import.sol:8:3-4"]
-	expr_10 [label="expression\ntests/contract_testcases/solana/using_import.sol:9:3-10"]
-	call_internal_function_11 [label="call internal function\ntests/contract_testcases/solana/using_import.sol:9:3-10"]
-	internal_function_12 [label="function(struct S) internal pure returns (void)\nfree function dec\ntests/contract_testcases/solana/using_import.sol:9:3-10"]
-	variable_13 [label="variable: s\nstruct S\ntests/contract_testcases/solana/using_import.sol:9:3-4"]
-	contract_14 [label="contract A\ntests/contract_testcases/solana/simple.sol:1:1-14"]
-	contract_15 [label="contract L\ntests/contract_testcases/solana/simple.sol:1:14-2:13"]
+	variable_32 [label="variable: s\nstruct S\ntests/contract_testcases/solana/using_import.sol:8:3-4"]
+	expr_33 [label="expression\ntests/contract_testcases/solana/using_import.sol:9:3-10"]
+	call_internal_function_34 [label="call internal function\ntests/contract_testcases/solana/using_import.sol:9:3-10"]
+	internal_function_35 [label="function(struct S) internal pure returns (void)\nfree function dec\ntests/contract_testcases/solana/using_import.sol:9:3-10"]
+	variable_36 [label="variable: s\nstruct S\ntests/contract_testcases/solana/using_import.sol:9:3-4"]
+	contract_37 [label="contract A\ntests/contract_testcases/solana/simple.sol:1:1-14"]
+	contract_38 [label="contract L\ntests/contract_testcases/solana/simple.sol:1:14-2:13"]
 	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/solana/using_import.sol:5:1-11:2"]
-	diagnostic_18 [label="function can be declared 'pure'\nlevel Warning\ntests/contract_testcases/solana/using_import.sol:7:2-35"]
-	diagnostic_19 [label="found contract 'A'\nlevel Debug\ntests/contract_testcases/solana/simple.sol:1:1-14"]
-	diagnostic_20 [label="found library 'L'\nlevel Debug\ntests/contract_testcases/solana/simple.sol:1:14-2:13"]
+	diagnostic_41 [label="function can be declared 'pure'\nlevel Warning\ntests/contract_testcases/solana/using_import.sol:7:2-35"]
+	diagnostic_42 [label="found contract 'A'\nlevel Debug\ntests/contract_testcases/solana/simple.sol:1:1-14"]
+	diagnostic_43 [label="found library 'L'\nlevel Debug\ntests/contract_testcases/solana/simple.sol:1:14-2:13"]
 	structs -> S
+	free_functions -> inc [label="function"]
+	inc -> parameters [label="parameters"]
+	inc -> expr [label="body"]
+	expr -> assign [label="expr"]
+	assign -> structmember [label="left"]
+	structmember -> variable [label="var"]
+	assign -> add [label="right"]
+	add -> load [label="left"]
+	load -> structmember_11 [label="expr"]
+	structmember_11 -> variable_12 [label="var"]
+	add -> number_literal [label="right"]
+	free_functions -> dec [label="function"]
+	dec -> parameters_15 [label="parameters"]
+	dec -> expr_16 [label="body"]
+	expr_16 -> assign_17 [label="expr"]
+	assign_17 -> structmember_18 [label="left"]
+	structmember_18 -> variable_19 [label="var"]
+	assign_17 -> subtract [label="right"]
+	subtract -> load_21 [label="left"]
+	load_21 -> structmember_22 [label="expr"]
+	structmember_22 -> variable_23 [label="var"]
+	subtract -> number_literal_24 [label="right"]
 	contracts -> contract
 	contract -> test [label="function"]
-	test -> parameters [label="parameters"]
-	test -> expr [label="body"]
-	expr -> call_internal_function [label="expr"]
+	test -> parameters_28 [label="parameters"]
+	test -> expr_29 [label="body"]
+	expr_29 -> call_internal_function [label="expr"]
 	call_internal_function -> internal_function [label="function"]
-	call_internal_function -> variable [label="arg #0"]
-	expr -> expr_10 [label="next"]
-	expr_10 -> call_internal_function_11 [label="expr"]
-	call_internal_function_11 -> internal_function_12 [label="function"]
-	call_internal_function_11 -> variable_13 [label="arg #0"]
-	contracts -> contract_14
-	contracts -> contract_15
+	call_internal_function -> variable_32 [label="arg #0"]
+	expr_29 -> expr_33 [label="next"]
+	expr_33 -> call_internal_function_34 [label="expr"]
+	call_internal_function_34 -> internal_function_35 [label="function"]
+	call_internal_function_34 -> variable_36 [label="arg #0"]
+	contracts -> contract_37
+	contracts -> contract_38
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_18 [label="Warning"]
-	diagnostics -> diagnostic_19 [label="Debug"]
-	diagnostics -> diagnostic_20 [label="Debug"]
+	diagnostics -> diagnostic_41 [label="Warning"]
+	diagnostics -> diagnostic_42 [label="Debug"]
+	diagnostics -> diagnostic_43 [label="Debug"]
 }

+ 41 - 21
tests/contract_testcases/solana/using_list.dot

@@ -1,36 +1,56 @@
 strict digraph "tests/contract_testcases/solana/using_list.sol" {
+	id [label="function id\ntests/contract_testcases/solana/using_list.sol:1:1-40\nsignature id(uint256)\nvisibility internal\nmutability pure"]
+	parameters [label="parameters\nuint256 x"]
+	returns [label="returns\nuint256 "]
+	return [label="return\ntests/contract_testcases/solana/using_list.sol:2:5-13"]
+	variable [label="variable: x\nuint256\ntests/contract_testcases/solana/using_list.sol:2:12-13"]
+	zero [label="function zero\ntests/contract_testcases/solana/using_list.sol:4:1-5:40\nsignature zero(uint256)\nvisibility internal\nmutability pure"]
+	parameters_8 [label="parameters\nuint256 "]
+	returns_9 [label="returns\nuint256 "]
+	return_10 [label="return\ntests/contract_testcases/solana/using_list.sol:6:5-13"]
+	number_literal [label="uint256 literal: 0\ntests/contract_testcases/solana/using_list.sol:6:12-13"]
 	contract [label="contract C\ntests/contract_testcases/solana/using_list.sol:8:1-19:2"]
 	using [label="using for uint256\nfunction id tests/contract_testcases/solana/using_list.sol:1:1-40\nfunction zero tests/contract_testcases/solana/using_list.sol:4:1-5:40"]
 	f [label="function f\ncontract: C\ntests/contract_testcases/solana/using_list.sol:10:5-51\nsignature f(uint256)\nvisibility external\nmutability pure"]
-	parameters [label="parameters\nuint256 z"]
-	returns [label="returns\nuint256 "]
-	return [label="return\ntests/contract_testcases/solana/using_list.sol:11:9-22"]
+	parameters_16 [label="parameters\nuint256 z"]
+	returns_17 [label="returns\nuint256 "]
+	return_18 [label="return\ntests/contract_testcases/solana/using_list.sol:11:9-22"]
 	call_internal_function [label="call internal function\ntests/contract_testcases/solana/using_list.sol:11:16-22"]
 	internal_function [label="function(uint256) internal pure returns (uint256)\nfree function id\ntests/contract_testcases/solana/using_list.sol:11:16-22"]
-	variable [label="variable: z\nuint256\ntests/contract_testcases/solana/using_list.sol:11:16-17"]
+	variable_21 [label="variable: z\nuint256\ntests/contract_testcases/solana/using_list.sol:11:16-17"]
 	g [label="function g\ncontract: C\ntests/contract_testcases/solana/using_list.sol:14:5-52\nsignature g(uint256)\nvisibility external\nmutability pure"]
-	parameters_12 [label="parameters\nuint256 z"]
-	returns_13 [label="returns\nuint256 "]
-	return_14 [label="return\ntests/contract_testcases/solana/using_list.sol:15:9-24"]
-	call_internal_function_15 [label="call internal function\ntests/contract_testcases/solana/using_list.sol:15:16-24"]
-	internal_function_16 [label="function(uint256) internal pure returns (uint256)\nfree function zero\ntests/contract_testcases/solana/using_list.sol:15:16-24"]
-	variable_17 [label="variable: z\nuint256\ntests/contract_testcases/solana/using_list.sol:15:16-17"]
+	parameters_23 [label="parameters\nuint256 z"]
+	returns_24 [label="returns\nuint256 "]
+	return_25 [label="return\ntests/contract_testcases/solana/using_list.sol:15:9-24"]
+	call_internal_function_26 [label="call internal function\ntests/contract_testcases/solana/using_list.sol:15:16-24"]
+	internal_function_27 [label="function(uint256) internal pure returns (uint256)\nfree function zero\ntests/contract_testcases/solana/using_list.sol:15:16-24"]
+	variable_28 [label="variable: z\nuint256\ntests/contract_testcases/solana/using_list.sol:15:16-17"]
 	diagnostic [label="found contract 'C'\nlevel Debug\ntests/contract_testcases/solana/using_list.sol:8:1-19:2"]
+	free_functions -> id [label="function"]
+	id -> parameters [label="parameters"]
+	id -> returns [label="returns"]
+	id -> return [label="body"]
+	return -> variable [label="expr"]
+	free_functions -> zero [label="function"]
+	zero -> parameters_8 [label="parameters"]
+	zero -> returns_9 [label="returns"]
+	zero -> return_10 [label="body"]
+	return_10 -> number_literal [label="expr"]
 	contracts -> contract
 	contract -> using [label="base"]
 	contract -> f [label="function"]
-	f -> parameters [label="parameters"]
-	f -> returns [label="returns"]
-	f -> return [label="body"]
-	return -> call_internal_function [label="expr"]
+	f -> parameters_16 [label="parameters"]
+	f -> returns_17 [label="returns"]
+	f -> return_18 [label="body"]
+	return_18 -> call_internal_function [label="expr"]
 	call_internal_function -> internal_function [label="function"]
-	call_internal_function -> variable [label="arg #0"]
+	call_internal_function -> variable_21 [label="arg #0"]
 	contract -> g [label="function"]
-	g -> parameters_12 [label="parameters"]
-	g -> returns_13 [label="returns"]
-	g -> return_14 [label="body"]
-	return_14 -> call_internal_function_15 [label="expr"]
-	call_internal_function_15 -> internal_function_16 [label="function"]
-	call_internal_function_15 -> variable_17 [label="arg #0"]
+	g -> parameters_23 [label="parameters"]
+	g -> returns_24 [label="returns"]
+	g -> return_25 [label="body"]
+	return_25 -> call_internal_function_26 [label="expr"]
+	call_internal_function_26 -> internal_function_27 [label="function"]
+	call_internal_function_26 -> variable_28 [label="arg #0"]
 	diagnostics -> diagnostic [label="Debug"]
 }

+ 21 - 7
tests/contract_testcases/solana/using_literal.dot

@@ -1,18 +1,32 @@
 strict digraph "tests/contract_testcases/solana/using_literal.sol" {
+	double [label="function double\ntests/contract_testcases/solana/using_literal.sol:1:1-42\nsignature double(int256)\nvisibility internal\nmutability pure"]
+	parameters [label="parameters\nint256 x"]
+	returns [label="returns\nint256 "]
+	return [label="return\ntests/contract_testcases/solana/using_literal.sol:1:45-57"]
+	multiply [label="multiply\nint256\ntests/contract_testcases/solana/using_literal.sol:1:52-57"]
+	variable [label="variable: x\nint256\ntests/contract_testcases/solana/using_literal.sol:1:52-53"]
+	number_literal [label="int256 literal: 2\ntests/contract_testcases/solana/using_literal.sol:1:56-57"]
 	contract [label="contract C\ntests/contract_testcases/solana/using_literal.sol:4:1-9:2"]
 	foo [label="function foo\ncontract: C\ntests/contract_testcases/solana/using_literal.sol:6:2-42\nsignature foo()\nvisibility public\nmutability pure"]
-	returns [label="returns\nint256 "]
-	return [label="return\ntests/contract_testcases/solana/using_literal.sol:7:3-21"]
+	returns_12 [label="returns\nint256 "]
+	return_13 [label="return\ntests/contract_testcases/solana/using_literal.sol:7:3-21"]
 	call_internal_function [label="call internal function\ntests/contract_testcases/solana/using_literal.sol:7:10-21"]
 	internal_function [label="function(int256) internal pure returns (int256)\nfree function double\ntests/contract_testcases/solana/using_literal.sol:7:10-21"]
-	number_literal [label="int256 literal: 42\ntests/contract_testcases/solana/using_literal.sol:7:10-12"]
+	number_literal_16 [label="int256 literal: 42\ntests/contract_testcases/solana/using_literal.sol:7:10-12"]
 	diagnostic [label="found contract 'C'\nlevel Debug\ntests/contract_testcases/solana/using_literal.sol:4:1-9:2"]
+	free_functions -> double [label="function"]
+	double -> parameters [label="parameters"]
+	double -> returns [label="returns"]
+	double -> return [label="body"]
+	return -> multiply [label="expr"]
+	multiply -> variable [label="left"]
+	multiply -> number_literal [label="right"]
 	contracts -> contract
 	contract -> foo [label="function"]
-	foo -> returns [label="returns"]
-	foo -> return [label="body"]
-	return -> call_internal_function [label="expr"]
+	foo -> returns_12 [label="returns"]
+	foo -> return_13 [label="body"]
+	return_13 -> call_internal_function [label="expr"]
 	call_internal_function -> internal_function [label="function"]
-	call_internal_function -> number_literal [label="arg #0"]
+	call_internal_function -> number_literal_16 [label="arg #0"]
 	diagnostics -> diagnostic [label="Debug"]
 }

+ 6 - 6
tests/contract_testcases/substrate/account_info.dot

@@ -1,16 +1,16 @@
 strict digraph "tests/contract_testcases/substrate/account_info.sol" {
 	contract [label="contract c\ntests/contract_testcases/substrate/account_info.sol:1:1-6:2"]
 	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/account_info.sol:1:1-6:2"]
-	diagnostic_5 [label="type 'AccountInfo' not found\nlevel Error\ntests/contract_testcases/substrate/account_info.sol:2:2-13"]
-	diagnostic_6 [label="type 'AccountInfo' not found\nlevel Error\ntests/contract_testcases/substrate/account_info.sol:4:15-26"]
-	diagnostic_7 [label="type 'AccountInfo' not found\nlevel Error\ntests/contract_testcases/substrate/account_info.sol:4:44-55"]
-	diagnostic_8 [label="type 'AccountInfo' not found\nlevel Error\ntests/contract_testcases/substrate/account_info.sol:5:18-29"]
-	diagnostic_9 [label="type 'AccountInfo' not found\nlevel Error\ntests/contract_testcases/substrate/account_info.sol:5:48-59"]
+	diagnostic_4 [label="type 'AccountInfo' not found\nlevel Error\ntests/contract_testcases/substrate/account_info.sol:2:2-13"]
+	diagnostic_5 [label="type 'AccountInfo' not found\nlevel Error\ntests/contract_testcases/substrate/account_info.sol:4:15-26"]
+	diagnostic_6 [label="type 'AccountInfo' not found\nlevel Error\ntests/contract_testcases/substrate/account_info.sol:4:44-55"]
+	diagnostic_7 [label="type 'AccountInfo' not found\nlevel Error\ntests/contract_testcases/substrate/account_info.sol:5:18-29"]
+	diagnostic_8 [label="type 'AccountInfo' not found\nlevel Error\ntests/contract_testcases/substrate/account_info.sol:5:48-59"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_4 [label="Error"]
 	diagnostics -> diagnostic_5 [label="Error"]
 	diagnostics -> diagnostic_6 [label="Error"]
 	diagnostics -> diagnostic_7 [label="Error"]
 	diagnostics -> diagnostic_8 [label="Error"]
-	diagnostics -> diagnostic_9 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/arrays/array_dimensions.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/arrays/array_dimensions.sol" {
 	contract [label="contract foo\ntests/contract_testcases/substrate/arrays/array_dimensions.sol:2:9-4:10"]
 	diagnostic [label="found contract 'foo'\nlevel Debug\ntests/contract_testcases/substrate/arrays/array_dimensions.sol:2:9-4:10"]
-	diagnostic_5 [label="zero size array not permitted\nlevel Error\ntests/contract_testcases/substrate/arrays/array_dimensions.sol:3:18-25"]
+	diagnostic_4 [label="zero size array not permitted\nlevel Error\ntests/contract_testcases/substrate/arrays/array_dimensions.sol:3:18-25"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/arrays/array_dimensions_01.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/arrays/array_dimensions_01.sol" {
 	contract [label="contract foo\ntests/contract_testcases/substrate/arrays/array_dimensions_01.sol:2:9-4:10"]
 	diagnostic [label="found contract 'foo'\nlevel Debug\ntests/contract_testcases/substrate/arrays/array_dimensions_01.sol:2:9-4:10"]
-	diagnostic_5 [label="negative literal -10 not allowed for unsigned type 'uint256'\nlevel Error\ntests/contract_testcases/substrate/arrays/array_dimensions_01.sol:3:18-21"]
+	diagnostic_4 [label="negative literal -10 not allowed for unsigned type 'uint256'\nlevel Error\ntests/contract_testcases/substrate/arrays/array_dimensions_01.sol:3:18-21"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/arrays/array_dimensions_02.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/arrays/array_dimensions_02.sol" {
 	contract [label="contract foo\ntests/contract_testcases/substrate/arrays/array_dimensions_02.sol:2:9-4:10"]
 	diagnostic [label="found contract 'foo'\nlevel Debug\ntests/contract_testcases/substrate/arrays/array_dimensions_02.sol:2:9-4:10"]
-	diagnostic_5 [label="zero size array not permitted\nlevel Error\ntests/contract_testcases/substrate/arrays/array_dimensions_02.sol:3:18-24"]
+	diagnostic_4 [label="zero size array not permitted\nlevel Error\ntests/contract_testcases/substrate/arrays/array_dimensions_02.sol:3:18-24"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/arrays/array_dimensions_03.dot

@@ -2,9 +2,9 @@ strict digraph "tests/contract_testcases/substrate/arrays/array_dimensions_03.so
 	e [label="name: e\ncontract: foo\ntests/contract_testcases/substrate/arrays/array_dimensions_03.sol:3:13-34\nvalue: e1\nvalue: e2\nvalue: e3"]
 	contract [label="contract foo\ntests/contract_testcases/substrate/arrays/array_dimensions_03.sol:2:9-5:10"]
 	diagnostic [label="found contract 'foo'\nlevel Debug\ntests/contract_testcases/substrate/arrays/array_dimensions_03.sol:2:9-5:10"]
-	diagnostic_7 [label="divide by zero\nlevel Error\ntests/contract_testcases/substrate/arrays/array_dimensions_03.sol:4:15-20"]
+	diagnostic_6 [label="divide by zero\nlevel Error\ntests/contract_testcases/substrate/arrays/array_dimensions_03.sol:4:15-20"]
 	enums -> e
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Error"]
+	diagnostics -> diagnostic_6 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/arrays/array_dimensions_04.dot

@@ -2,9 +2,9 @@ strict digraph "tests/contract_testcases/substrate/arrays/array_dimensions_04.so
 	bar [label="name:bar\ncontract: foo\ntests/contract_testcases/substrate/arrays/array_dimensions_04.sol:3:20-23\nfield name:x ty:int32"]
 	contract [label="contract foo\ntests/contract_testcases/substrate/arrays/array_dimensions_04.sol:2:9-7:10"]
 	diagnostic [label="found contract 'foo'\nlevel Debug\ntests/contract_testcases/substrate/arrays/array_dimensions_04.sol:2:9-7:10"]
-	diagnostic_7 [label="divide by zero\nlevel Error\ntests/contract_testcases/substrate/arrays/array_dimensions_04.sol:6:17-22"]
+	diagnostic_6 [label="divide by zero\nlevel Error\ntests/contract_testcases/substrate/arrays/array_dimensions_04.sol:6:17-22"]
 	structs -> bar
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Error"]
+	diagnostics -> diagnostic_6 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/arrays/data_locations.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/arrays/data_locations.sol" {
 	contract [label="contract foo\ntests/contract_testcases/substrate/arrays/data_locations.sol:2:9-5:10"]
 	diagnostic [label="found contract 'foo'\nlevel Debug\ntests/contract_testcases/substrate/arrays/data_locations.sol:2:9-5:10"]
-	diagnostic_5 [label="data location 'storage' can only be specified for array, struct or mapping\nlevel Error\ntests/contract_testcases/substrate/arrays/data_locations.sol:3:31-38"]
+	diagnostic_4 [label="data location 'storage' can only be specified for array, struct or mapping\nlevel Error\ntests/contract_testcases/substrate/arrays/data_locations.sol:3:31-38"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/arrays/data_locations_01.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/arrays/data_locations_01.sol" {
 	contract [label="contract foo\ntests/contract_testcases/substrate/arrays/data_locations_01.sol:2:9-5:10"]
 	diagnostic [label="found contract 'foo'\nlevel Debug\ntests/contract_testcases/substrate/arrays/data_locations_01.sol:2:9-5:10"]
-	diagnostic_5 [label="data location 'calldata' can only be specified for array, struct or mapping\nlevel Error\ntests/contract_testcases/substrate/arrays/data_locations_01.sol:3:31-39"]
+	diagnostic_4 [label="data location 'calldata' can only be specified for array, struct or mapping\nlevel Error\ntests/contract_testcases/substrate/arrays/data_locations_01.sol:3:31-39"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/arrays/data_locations_02.dot

@@ -2,9 +2,9 @@ strict digraph "tests/contract_testcases/substrate/arrays/data_locations_02.sol"
 	foo2 [label="name: foo2\ncontract: foo\ntests/contract_testcases/substrate/arrays/data_locations_02.sol:3:13-37\nvalue: bar1\nvalue: bar2"]
 	contract [label="contract foo\ntests/contract_testcases/substrate/arrays/data_locations_02.sol:2:9-6:10"]
 	diagnostic [label="found contract 'foo'\nlevel Debug\ntests/contract_testcases/substrate/arrays/data_locations_02.sol:2:9-6:10"]
-	diagnostic_7 [label="data location 'memory' can only be specified for array, struct or mapping\nlevel Error\ntests/contract_testcases/substrate/arrays/data_locations_02.sol:4:31-37"]
+	diagnostic_6 [label="data location 'memory' can only be specified for array, struct or mapping\nlevel Error\ntests/contract_testcases/substrate/arrays/data_locations_02.sol:4:31-37"]
 	enums -> foo2
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Error"]
+	diagnostics -> diagnostic_6 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/arrays/data_locations_03.dot

@@ -2,9 +2,9 @@ strict digraph "tests/contract_testcases/substrate/arrays/data_locations_03.sol"
 	foo2 [label="name: foo2\ncontract: foo\ntests/contract_testcases/substrate/arrays/data_locations_03.sol:3:13-37\nvalue: bar1\nvalue: bar2"]
 	contract [label="contract foo\ntests/contract_testcases/substrate/arrays/data_locations_03.sol:2:9-6:10"]
 	diagnostic [label="found contract 'foo'\nlevel Debug\ntests/contract_testcases/substrate/arrays/data_locations_03.sol:2:9-6:10"]
-	diagnostic_7 [label="data location 'calldata' can only be specified for array, struct or mapping\nlevel Error\ntests/contract_testcases/substrate/arrays/data_locations_03.sol:4:55-63"]
+	diagnostic_6 [label="data location 'calldata' can only be specified for array, struct or mapping\nlevel Error\ntests/contract_testcases/substrate/arrays/data_locations_03.sol:4:55-63"]
 	enums -> foo2
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Error"]
+	diagnostics -> diagnostic_6 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/arrays/data_locations_04.dot

@@ -2,9 +2,9 @@ strict digraph "tests/contract_testcases/substrate/arrays/data_locations_04.sol"
 	foo2 [label="name: foo2\ncontract: foo\ntests/contract_testcases/substrate/arrays/data_locations_04.sol:3:13-37\nvalue: bar1\nvalue: bar2"]
 	contract [label="contract foo\ntests/contract_testcases/substrate/arrays/data_locations_04.sol:2:9-6:10"]
 	diagnostic [label="found contract 'foo'\nlevel Debug\ntests/contract_testcases/substrate/arrays/data_locations_04.sol:2:9-6:10"]
-	diagnostic_7 [label="data location 'calldata' can only be specified for array, struct or mapping\nlevel Error\ntests/contract_testcases/substrate/arrays/data_locations_04.sol:4:55-63"]
+	diagnostic_6 [label="data location 'calldata' can only be specified for array, struct or mapping\nlevel Error\ntests/contract_testcases/substrate/arrays/data_locations_04.sol:4:55-63"]
 	enums -> foo2
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Error"]
+	diagnostics -> diagnostic_6 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/arrays/data_locations_05.dot

@@ -2,9 +2,9 @@ strict digraph "tests/contract_testcases/substrate/arrays/data_locations_05.sol"
 	foo2 [label="name: foo2\ncontract: foo\ntests/contract_testcases/substrate/arrays/data_locations_05.sol:3:13-37\nvalue: bar1\nvalue: bar2"]
 	contract [label="contract foo\ntests/contract_testcases/substrate/arrays/data_locations_05.sol:2:9-6:10"]
 	diagnostic [label="found contract 'foo'\nlevel Debug\ntests/contract_testcases/substrate/arrays/data_locations_05.sol:2:9-6:10"]
-	diagnostic_7 [label="data location 'storage' can only be specified for array, struct or mapping\nlevel Error\ntests/contract_testcases/substrate/arrays/data_locations_05.sol:4:54-61"]
+	diagnostic_6 [label="data location 'storage' can only be specified for array, struct or mapping\nlevel Error\ntests/contract_testcases/substrate/arrays/data_locations_05.sol:4:54-61"]
 	enums -> foo2
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Error"]
+	diagnostics -> diagnostic_6 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/arrays/data_locations_06.dot

@@ -2,9 +2,9 @@ strict digraph "tests/contract_testcases/substrate/arrays/data_locations_06.sol"
 	foo2 [label="name: foo2\ncontract: foo\ntests/contract_testcases/substrate/arrays/data_locations_06.sol:3:13-37\nvalue: bar1\nvalue: bar2"]
 	contract [label="contract foo\ntests/contract_testcases/substrate/arrays/data_locations_06.sol:2:9-6:10"]
 	diagnostic [label="found contract 'foo'\nlevel Debug\ntests/contract_testcases/substrate/arrays/data_locations_06.sol:2:9-6:10"]
-	diagnostic_7 [label="parameter of type 'storage' not allowed public or external functions\nlevel Error\ntests/contract_testcases/substrate/arrays/data_locations_06.sol:4:34-41"]
+	diagnostic_6 [label="parameter of type 'storage' not allowed public or external functions\nlevel Error\ntests/contract_testcases/substrate/arrays/data_locations_06.sol:4:34-41"]
 	enums -> foo2
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Error"]
+	diagnostics -> diagnostic_6 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/arrays/data_locations_07.dot

@@ -2,9 +2,9 @@ strict digraph "tests/contract_testcases/substrate/arrays/data_locations_07.sol"
 	foo2 [label="name: foo2\ncontract: foo\ntests/contract_testcases/substrate/arrays/data_locations_07.sol:3:13-37\nvalue: bar1\nvalue: bar2"]
 	contract [label="contract foo\ntests/contract_testcases/substrate/arrays/data_locations_07.sol:2:9-6:10"]
 	diagnostic [label="found contract 'foo'\nlevel Debug\ntests/contract_testcases/substrate/arrays/data_locations_07.sol:2:9-6:10"]
-	diagnostic_7 [label="return type of type 'storage' not allowed public or external functions\nlevel Error\ntests/contract_testcases/substrate/arrays/data_locations_07.sol:4:52-59"]
+	diagnostic_6 [label="return type of type 'storage' not allowed public or external functions\nlevel Error\ntests/contract_testcases/substrate/arrays/data_locations_07.sol:4:52-59"]
 	enums -> foo2
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Error"]
+	diagnostics -> diagnostic_6 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/arrays/data_locations_08.dot

@@ -2,9 +2,9 @@ strict digraph "tests/contract_testcases/substrate/arrays/data_locations_08.sol"
 	foo2 [label="name: foo2\ncontract: foo\ntests/contract_testcases/substrate/arrays/data_locations_08.sol:3:13-37\nvalue: bar1\nvalue: bar2"]
 	contract [label="contract foo\ntests/contract_testcases/substrate/arrays/data_locations_08.sol:2:9-6:10"]
 	diagnostic [label="found contract 'foo'\nlevel Debug\ntests/contract_testcases/substrate/arrays/data_locations_08.sol:2:9-6:10"]
-	diagnostic_7 [label="return type of type 'storage' not allowed public or external functions\nlevel Error\ntests/contract_testcases/substrate/arrays/data_locations_08.sol:4:53-60"]
+	diagnostic_6 [label="return type of type 'storage' not allowed public or external functions\nlevel Error\ntests/contract_testcases/substrate/arrays/data_locations_08.sol:4:53-60"]
 	enums -> foo2
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Error"]
+	diagnostics -> diagnostic_6 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/calls/payable_functions.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/calls/payable_functions.sol" {
 	contract [label="contract c\ntests/contract_testcases/substrate/calls/payable_functions.sol:2:9-6:10"]
 	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/calls/payable_functions.sol:2:9-6:10"]
-	diagnostic_5 [label="receive function must be declared external\nlevel Error\ntests/contract_testcases/substrate/calls/payable_functions.sol:3:13-29"]
+	diagnostic_4 [label="receive function must be declared external\nlevel Error\ntests/contract_testcases/substrate/calls/payable_functions.sol:3:13-29"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/calls/payable_functions_01.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/calls/payable_functions_01.sol" {
 	contract [label="contract c\ntests/contract_testcases/substrate/calls/payable_functions_01.sol:2:9-6:10"]
 	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/calls/payable_functions_01.sol:2:9-6:10"]
-	diagnostic_5 [label="receive function must be declared payable\nlevel Error\ntests/contract_testcases/substrate/calls/payable_functions_01.sol:3:13-31"]
+	diagnostic_4 [label="receive function must be declared payable\nlevel Error\ntests/contract_testcases/substrate/calls/payable_functions_01.sol:3:13-31"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/calls/payable_functions_02.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/calls/payable_functions_02.sol" {
 	contract [label="contract c\ntests/contract_testcases/substrate/calls/payable_functions_02.sol:2:9-6:10"]
 	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/calls/payable_functions_02.sol:2:9-6:10"]
-	diagnostic_5 [label="fallback function must not be declare payable, use 'receive() external payable' instead\nlevel Error\ntests/contract_testcases/substrate/calls/payable_functions_02.sol:3:13-40"]
+	diagnostic_4 [label="fallback function must not be declare payable, use 'receive() external payable' instead\nlevel Error\ntests/contract_testcases/substrate/calls/payable_functions_02.sol:3:13-40"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/calls/payable_functions_03.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/calls/payable_functions_03.sol" {
 	contract [label="contract c\ntests/contract_testcases/substrate/calls/payable_functions_03.sol:2:9-6:10"]
 	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/calls/payable_functions_03.sol:2:9-6:10"]
-	diagnostic_5 [label="fallback function must be declared external\nlevel Error\ntests/contract_testcases/substrate/calls/payable_functions_03.sol:3:13-30"]
+	diagnostic_4 [label="fallback function must be declared external\nlevel Error\ntests/contract_testcases/substrate/calls/payable_functions_03.sol:3:13-30"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/contracts/contract_name.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/contracts/contract_name.sol" {
 	contract [label="contract test\ntests/contract_testcases/substrate/contracts/contract_name.sol:1:1-3:10"]
 	diagnostic [label="found contract 'test'\nlevel Debug\ntests/contract_testcases/substrate/contracts/contract_name.sol:1:1-3:10"]
-	diagnostic_5 [label="function cannot have same name as the contract\nlevel Error\ntests/contract_testcases/substrate/contracts/contract_name.sol:2:13-35"]
+	diagnostic_4 [label="function cannot have same name as the contract\nlevel Error\ntests/contract_testcases/substrate/contracts/contract_name.sol:2:13-35"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 3 - 3
tests/contract_testcases/substrate/contracts/contract_name_01.dot

@@ -2,11 +2,11 @@ strict digraph "tests/contract_testcases/substrate/contracts/contract_name_01.so
 	test [label="name: test\ncontract: test\ntests/contract_testcases/substrate/contracts/contract_name_01.sol:2:13-27\nvalue: a"]
 	contract [label="contract test\ntests/contract_testcases/substrate/contracts/contract_name_01.sol:1:1-3:10"]
 	diagnostic [label="found contract 'test'\nlevel Debug\ntests/contract_testcases/substrate/contracts/contract_name_01.sol:1:1-3:10"]
-	diagnostic_7 [label="test is already defined as a contract name\nlevel Warning\ntests/contract_testcases/substrate/contracts/contract_name_01.sol:2:18-22"]
+	diagnostic_6 [label="test is already defined as a contract name\nlevel Warning\ntests/contract_testcases/substrate/contracts/contract_name_01.sol:2:18-22"]
 	note [label="location of previous definition\ntests/contract_testcases/substrate/contracts/contract_name_01.sol:1:1-3:10"]
 	enums -> test
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Warning"]
-	diagnostic_7 -> note [label="note"]
+	diagnostics -> diagnostic_6 [label="Warning"]
+	diagnostic_6 -> note [label="note"]
 }

+ 4 - 4
tests/contract_testcases/substrate/contracts/contract_name_02.dot

@@ -2,13 +2,13 @@ strict digraph "tests/contract_testcases/substrate/contracts/contract_name_02.so
 	contract [label="contract test\ntests/contract_testcases/substrate/contracts/contract_name_02.sol:1:1-3:10"]
 	var [label="variable test\nvisibility internal\ntests/contract_testcases/substrate/contracts/contract_name_02.sol:2:13-22"]
 	diagnostic [label="found contract 'test'\nlevel Debug\ntests/contract_testcases/substrate/contracts/contract_name_02.sol:1:1-3:10"]
-	diagnostic_6 [label="storage variable 'test' has never been used\nlevel Warning\ntests/contract_testcases/substrate/contracts/contract_name_02.sol:2:13-22"]
-	diagnostic_7 [label="test is already defined as a contract name\nlevel Warning\ntests/contract_testcases/substrate/contracts/contract_name_02.sol:2:18-22"]
+	diagnostic_5 [label="storage variable 'test' has never been used\nlevel Warning\ntests/contract_testcases/substrate/contracts/contract_name_02.sol:2:13-22"]
+	diagnostic_6 [label="test is already defined as a contract name\nlevel Warning\ntests/contract_testcases/substrate/contracts/contract_name_02.sol:2:18-22"]
 	note [label="location of previous definition\ntests/contract_testcases/substrate/contracts/contract_name_02.sol:1:1-3:10"]
 	contracts -> contract
 	contract -> var [label="variable"]
 	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_5 [label="Warning"]
 	diagnostics -> diagnostic_6 [label="Warning"]
-	diagnostics -> diagnostic_7 [label="Warning"]
-	diagnostic_7 -> note [label="note"]
+	diagnostic_6 -> note [label="note"]
 }

+ 3 - 3
tests/contract_testcases/substrate/contracts/contract_name_03.dot

@@ -2,11 +2,11 @@ strict digraph "tests/contract_testcases/substrate/contracts/contract_name_03.so
 	test [label="name:test\ncontract: test\ntests/contract_testcases/substrate/contracts/contract_name_03.sol:2:20-24\nfield name:a ty:bool"]
 	contract [label="contract test\ntests/contract_testcases/substrate/contracts/contract_name_03.sol:1:1-3:10"]
 	diagnostic [label="found contract 'test'\nlevel Debug\ntests/contract_testcases/substrate/contracts/contract_name_03.sol:1:1-3:10"]
-	diagnostic_7 [label="test is already defined as a contract name\nlevel Warning\ntests/contract_testcases/substrate/contracts/contract_name_03.sol:2:20-24"]
+	diagnostic_6 [label="test is already defined as a contract name\nlevel Warning\ntests/contract_testcases/substrate/contracts/contract_name_03.sol:2:20-24"]
 	note [label="location of previous definition\ntests/contract_testcases/substrate/contracts/contract_name_03.sol:1:1-3:10"]
 	structs -> test
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Warning"]
-	diagnostic_7 -> note [label="note"]
+	diagnostics -> diagnostic_6 [label="Warning"]
+	diagnostic_6 -> note [label="note"]
 }

+ 2 - 2
tests/contract_testcases/substrate/events/event_decl.dot

@@ -2,9 +2,9 @@ strict digraph "tests/contract_testcases/substrate/events/event_decl.sol" {
 	foo [label="name:foo\ncontract: 0\ntests/contract_testcases/substrate/events/event_decl.sol:3:19-22"]
 	contract [label="contract c\ntests/contract_testcases/substrate/events/event_decl.sol:2:9-4:10"]
 	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/events/event_decl.sol:2:9-4:10"]
-	diagnostic_7 [label="event 'foo' has never been emitted\nlevel Warning\ntests/contract_testcases/substrate/events/event_decl.sol:3:19-22"]
+	diagnostic_6 [label="event 'foo' has never been emitted\nlevel Warning\ntests/contract_testcases/substrate/events/event_decl.sol:3:19-22"]
 	events -> foo
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Warning"]
+	diagnostics -> diagnostic_6 [label="Warning"]
 }

+ 5 - 5
tests/contract_testcases/substrate/events/event_decl_02.dot

@@ -3,14 +3,14 @@ strict digraph "tests/contract_testcases/substrate/events/event_decl_02.sol" {
 	e_3 [label="name:e\ncontract: 0\ntests/contract_testcases/substrate/events/event_decl_02.sol:4:19-20"]
 	contract [label="contract c\ntests/contract_testcases/substrate/events/event_decl_02.sol:3:9-5:10"]
 	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/events/event_decl_02.sol:3:9-5:10"]
-	diagnostic_9 [label="e is already defined as an enum\nlevel Warning\ntests/contract_testcases/substrate/events/event_decl_02.sol:4:19-20"]
+	diagnostic_8 [label="e is already defined as an enum\nlevel Warning\ntests/contract_testcases/substrate/events/event_decl_02.sol:4:19-20"]
 	note [label="location of previous definition\ntests/contract_testcases/substrate/events/event_decl_02.sol:2:14-15"]
-	diagnostic_11 [label="event 'e' has never been emitted\nlevel Warning\ntests/contract_testcases/substrate/events/event_decl_02.sol:4:19-20"]
+	diagnostic_10 [label="event 'e' has never been emitted\nlevel Warning\ntests/contract_testcases/substrate/events/event_decl_02.sol:4:19-20"]
 	enums -> e
 	events -> e_3
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_9 [label="Warning"]
-	diagnostic_9 -> note [label="note"]
-	diagnostics -> diagnostic_11 [label="Warning"]
+	diagnostics -> diagnostic_8 [label="Warning"]
+	diagnostic_8 -> note [label="note"]
+	diagnostics -> diagnostic_10 [label="Warning"]
 }

+ 3 - 3
tests/contract_testcases/substrate/events/event_decl_03.dot

@@ -2,11 +2,11 @@ strict digraph "tests/contract_testcases/substrate/events/event_decl_03.sol" {
 	e [label="name: e\ncontract: c\ntests/contract_testcases/substrate/events/event_decl_03.sol:3:13-26\nvalue: a1"]
 	contract [label="contract c\ntests/contract_testcases/substrate/events/event_decl_03.sol:2:9-5:10"]
 	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/events/event_decl_03.sol:2:9-5:10"]
-	diagnostic_7 [label="e is already defined as an enum\nlevel Error\ntests/contract_testcases/substrate/events/event_decl_03.sol:4:19-20"]
+	diagnostic_6 [label="e is already defined as an enum\nlevel Error\ntests/contract_testcases/substrate/events/event_decl_03.sol:4:19-20"]
 	note [label="location of previous definition\ntests/contract_testcases/substrate/events/event_decl_03.sol:3:18-19"]
 	enums -> e
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Error"]
-	diagnostic_7 -> note [label="note"]
+	diagnostics -> diagnostic_6 [label="Error"]
+	diagnostic_6 -> note [label="note"]
 }

+ 2 - 2
tests/contract_testcases/substrate/events/event_decl_04.dot

@@ -2,9 +2,9 @@ strict digraph "tests/contract_testcases/substrate/events/event_decl_04.sol" {
 	foo [label="name:foo\ncontract: 0\ntests/contract_testcases/substrate/events/event_decl_04.sol:3:19-22\nfield name:x ty:unresolved indexed:no"]
 	contract [label="contract c\ntests/contract_testcases/substrate/events/event_decl_04.sol:2:9-4:10"]
 	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/events/event_decl_04.sol:2:9-4:10"]
-	diagnostic_7 [label="mapping type is not permitted as event field\nlevel Error\ntests/contract_testcases/substrate/events/event_decl_04.sol:3:24-48"]
+	diagnostic_6 [label="mapping type is not permitted as event field\nlevel Error\ntests/contract_testcases/substrate/events/event_decl_04.sol:3:24-48"]
 	events -> foo
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Error"]
+	diagnostics -> diagnostic_6 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/events/event_decl_05.dot

@@ -3,10 +3,10 @@ strict digraph "tests/contract_testcases/substrate/events/event_decl_05.sol" {
 	foo [label="name:foo\ncontract: 0\ntests/contract_testcases/substrate/events/event_decl_05.sol:7:19-22\nfield name:x ty:unresolved indexed:no"]
 	contract [label="contract c\ntests/contract_testcases/substrate/events/event_decl_05.sol:6:9-8:10"]
 	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/events/event_decl_05.sol:6:9-8:10"]
-	diagnostic_9 [label="mapping type is not permitted as event field\nlevel Error\ntests/contract_testcases/substrate/events/event_decl_05.sol:7:24-27"]
+	diagnostic_8 [label="mapping type is not permitted as event field\nlevel Error\ntests/contract_testcases/substrate/events/event_decl_05.sol:7:24-27"]
 	structs -> s
 	events -> foo
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_9 [label="Error"]
+	diagnostics -> diagnostic_8 [label="Error"]
 }

+ 3 - 3
tests/contract_testcases/substrate/events/event_decl_06.dot

@@ -2,11 +2,11 @@ strict digraph "tests/contract_testcases/substrate/events/event_decl_06.sol" {
 	foo [label="name:foo\ncontract: 0\ntests/contract_testcases/substrate/events/event_decl_06.sol:3:19-22\nfield name:x ty:bool indexed:no\nfield name:y ty:uint32 indexed:no"]
 	contract [label="contract c\ntests/contract_testcases/substrate/events/event_decl_06.sol:2:9-4:10"]
 	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/events/event_decl_06.sol:2:9-4:10"]
-	diagnostic_7 [label="event 'foo' has duplicate field name 'x'\nlevel Error\ntests/contract_testcases/substrate/events/event_decl_06.sol:3:50-51"]
+	diagnostic_6 [label="event 'foo' has duplicate field name 'x'\nlevel Error\ntests/contract_testcases/substrate/events/event_decl_06.sol:3:50-51"]
 	note [label="location of previous declaration of 'x'\ntests/contract_testcases/substrate/events/event_decl_06.sol:3:24-30"]
 	events -> foo
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Error"]
-	diagnostic_7 -> note [label="note"]
+	diagnostics -> diagnostic_6 [label="Error"]
+	diagnostic_6 -> note [label="note"]
 }

+ 2 - 2
tests/contract_testcases/substrate/events/event_decl_07.dot

@@ -2,9 +2,9 @@ strict digraph "tests/contract_testcases/substrate/events/event_decl_07.sol" {
 	foo [label="name:foo\ncontract: 0\ntests/contract_testcases/substrate/events/event_decl_07.sol:3:19-22\nfield name:f1 ty:bool indexed:yes\nfield name:f2 ty:bool indexed:yes\nfield name:f3 ty:bool indexed:yes\nfield name:f4 ty:bool indexed:yes"]
 	contract [label="contract c\ntests/contract_testcases/substrate/events/event_decl_07.sol:2:9-4:10"]
 	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/events/event_decl_07.sol:2:9-4:10"]
-	diagnostic_7 [label="event definition for 'foo' has 4 indexed fields where 3 permitted\nlevel Error\ntests/contract_testcases/substrate/events/event_decl_07.sol:3:19-22"]
+	diagnostic_6 [label="event definition for 'foo' has 4 indexed fields where 3 permitted\nlevel Error\ntests/contract_testcases/substrate/events/event_decl_07.sol:3:19-22"]
 	events -> foo
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Error"]
+	diagnostics -> diagnostic_6 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/events/event_decl_08.dot

@@ -2,9 +2,9 @@ strict digraph "tests/contract_testcases/substrate/events/event_decl_08.sol" {
 	foo [label="name:foo\ncontract: 0\ntests/contract_testcases/substrate/events/event_decl_08.sol:3:19-22\nfield name:f1 ty:bool indexed:yes\nfield name:f2 ty:bool indexed:yes\nfield name:f3 ty:bool indexed:yes"]
 	contract [label="contract c\ntests/contract_testcases/substrate/events/event_decl_08.sol:2:9-4:10"]
 	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/events/event_decl_08.sol:2:9-4:10"]
-	diagnostic_7 [label="event 'foo' has never been emitted\nlevel Warning\ntests/contract_testcases/substrate/events/event_decl_08.sol:3:19-22"]
+	diagnostic_6 [label="event 'foo' has never been emitted\nlevel Warning\ntests/contract_testcases/substrate/events/event_decl_08.sol:3:19-22"]
 	events -> foo
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Warning"]
+	diagnostics -> diagnostic_6 [label="Warning"]
 }

+ 2 - 2
tests/contract_testcases/substrate/events/event_decl_09.dot

@@ -2,9 +2,9 @@ strict digraph "tests/contract_testcases/substrate/events/event_decl_09.sol" {
 	foo [label="name:foo\ncontract: 0\ntests/contract_testcases/substrate/events/event_decl_09.sol:3:19-22\nanonymous\nfield name:f1 ty:bool indexed:yes\nfield name:f2 ty:bool indexed:yes\nfield name:f3 ty:bool indexed:yes\nfield name:f4 ty:bool indexed:yes\nfield name:f5 ty:bool indexed:yes"]
 	contract [label="contract c\ntests/contract_testcases/substrate/events/event_decl_09.sol:2:9-4:10"]
 	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/events/event_decl_09.sol:2:9-4:10"]
-	diagnostic_7 [label="anonymous event definition for 'foo' has 5 indexed fields where 4 permitted\nlevel Error\ntests/contract_testcases/substrate/events/event_decl_09.sol:3:19-22"]
+	diagnostic_6 [label="anonymous event definition for 'foo' has 5 indexed fields where 4 permitted\nlevel Error\ntests/contract_testcases/substrate/events/event_decl_09.sol:3:19-22"]
 	events -> foo
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Error"]
+	diagnostics -> diagnostic_6 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/events/event_decl_10.dot

@@ -2,9 +2,9 @@ strict digraph "tests/contract_testcases/substrate/events/event_decl_10.sol" {
 	foo [label="name:foo\ncontract: 0\ntests/contract_testcases/substrate/events/event_decl_10.sol:3:19-22\nanonymous\nfield name:f1 ty:bool indexed:yes\nfield name:f2 ty:bool indexed:yes\nfield name:f3 ty:bool indexed:yes\nfield name:f4 ty:bool indexed:yes"]
 	contract [label="contract c\ntests/contract_testcases/substrate/events/event_decl_10.sol:2:9-4:10"]
 	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/events/event_decl_10.sol:2:9-4:10"]
-	diagnostic_7 [label="event 'foo' has never been emitted\nlevel Warning\ntests/contract_testcases/substrate/events/event_decl_10.sol:3:19-22"]
+	diagnostic_6 [label="event 'foo' has never been emitted\nlevel Warning\ntests/contract_testcases/substrate/events/event_decl_10.sol:3:19-22"]
 	events -> foo
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Warning"]
+	diagnostics -> diagnostic_6 [label="Warning"]
 }

+ 2 - 2
tests/contract_testcases/substrate/function_types/decls_06.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/function_types/decls_06.sol" {
 	contract [label="contract test\ntests/contract_testcases/substrate/function_types/decls_06.sol:1:1-4:10"]
 	diagnostic [label="found contract 'test'\nlevel Debug\ntests/contract_testcases/substrate/function_types/decls_06.sol:1:1-4:10"]
-	diagnostic_5 [label="parameter of type 'function internal' not allowed public or external functions\nlevel Error\ntests/contract_testcases/substrate/function_types/decls_06.sol:2:26-72"]
+	diagnostic_4 [label="parameter of type 'function internal' not allowed public or external functions\nlevel Error\ntests/contract_testcases/substrate/function_types/decls_06.sol:2:26-72"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/function_types/decls_07.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/function_types/decls_07.sol" {
 	contract [label="contract test\ntests/contract_testcases/substrate/function_types/decls_07.sol:1:1-4:10"]
 	diagnostic [label="found contract 'test'\nlevel Debug\ntests/contract_testcases/substrate/function_types/decls_07.sol:1:1-4:10"]
-	diagnostic_5 [label="return type 'function internal' not allowed in public or external functions\nlevel Error\ntests/contract_testcases/substrate/function_types/decls_07.sol:2:44-90"]
+	diagnostic_4 [label="return type 'function internal' not allowed in public or external functions\nlevel Error\ntests/contract_testcases/substrate/function_types/decls_07.sol:2:44-90"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/function_types/decls_08.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/function_types/decls_08.sol" {
 	contract [label="contract test\ntests/contract_testcases/substrate/function_types/decls_08.sol:1:1-3:10"]
 	diagnostic [label="found contract 'test'\nlevel Debug\ntests/contract_testcases/substrate/function_types/decls_08.sol:1:1-3:10"]
-	diagnostic_5 [label="variable of type internal function cannot be 'public'\nlevel Error\ntests/contract_testcases/substrate/function_types/decls_08.sol:2:13-66"]
+	diagnostic_4 [label="variable of type internal function cannot be 'public'\nlevel Error\ntests/contract_testcases/substrate/function_types/decls_08.sol:2:13-66"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 4 - 4
tests/contract_testcases/substrate/functions/payable.dot

@@ -3,12 +3,12 @@ strict digraph "tests/contract_testcases/substrate/functions/payable.sol" {
 	var [label="variable i\nvisibility internal\ntests/contract_testcases/substrate/functions/payable.sol:5:13-24"]
 	number_literal [label="int32 literal: 0\ntests/contract_testcases/substrate/functions/payable.sol:5:23-24"]
 	diagnostic [label="pragma 'solidity' is ignored\nlevel Debug\ntests/contract_testcases/substrate/functions/payable.sol:2:9-26"]
-	diagnostic_7 [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/functions/payable.sol:4:9-10:10"]
-	diagnostic_8 [label="internal or private function cannot be payable\nlevel Error\ntests/contract_testcases/substrate/functions/payable.sol:7:29-36"]
+	diagnostic_6 [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/functions/payable.sol:4:9-10:10"]
+	diagnostic_7 [label="internal or private function cannot be payable\nlevel Error\ntests/contract_testcases/substrate/functions/payable.sol:7:29-36"]
 	contracts -> contract
 	contract -> var [label="variable"]
 	var -> number_literal [label="initializer"]
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Debug"]
-	diagnostics -> diagnostic_8 [label="Error"]
+	diagnostics -> diagnostic_6 [label="Debug"]
+	diagnostics -> diagnostic_7 [label="Error"]
 }

+ 4 - 4
tests/contract_testcases/substrate/functions/payable_01.dot

@@ -3,12 +3,12 @@ strict digraph "tests/contract_testcases/substrate/functions/payable_01.sol" {
 	var [label="variable i\nvisibility internal\ntests/contract_testcases/substrate/functions/payable_01.sol:5:13-24"]
 	number_literal [label="int32 literal: 0\ntests/contract_testcases/substrate/functions/payable_01.sol:5:23-24"]
 	diagnostic [label="pragma 'solidity' is ignored\nlevel Debug\ntests/contract_testcases/substrate/functions/payable_01.sol:2:9-26"]
-	diagnostic_7 [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/functions/payable_01.sol:4:9-10:10"]
-	diagnostic_8 [label="internal or private function cannot be payable\nlevel Error\ntests/contract_testcases/substrate/functions/payable_01.sol:7:29-36"]
+	diagnostic_6 [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/functions/payable_01.sol:4:9-10:10"]
+	diagnostic_7 [label="internal or private function cannot be payable\nlevel Error\ntests/contract_testcases/substrate/functions/payable_01.sol:7:29-36"]
 	contracts -> contract
 	contract -> var [label="variable"]
 	var -> number_literal [label="initializer"]
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Debug"]
-	diagnostics -> diagnostic_8 [label="Error"]
+	diagnostics -> diagnostic_6 [label="Debug"]
+	diagnostics -> diagnostic_7 [label="Error"]
 }

+ 4 - 4
tests/contract_testcases/substrate/functions/payable_02.dot

@@ -3,12 +3,12 @@ strict digraph "tests/contract_testcases/substrate/functions/payable_02.sol" {
 	var [label="variable i\nvisibility internal\ntests/contract_testcases/substrate/functions/payable_02.sol:5:13-24"]
 	number_literal [label="int32 literal: 0\ntests/contract_testcases/substrate/functions/payable_02.sol:5:23-24"]
 	diagnostic [label="pragma 'solidity' is ignored\nlevel Debug\ntests/contract_testcases/substrate/functions/payable_02.sol:2:9-26"]
-	diagnostic_7 [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/functions/payable_02.sol:4:9-10:10"]
-	diagnostic_8 [label="receive function must be declared payable\nlevel Error\ntests/contract_testcases/substrate/functions/payable_02.sol:7:13-31"]
+	diagnostic_6 [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/functions/payable_02.sol:4:9-10:10"]
+	diagnostic_7 [label="receive function must be declared payable\nlevel Error\ntests/contract_testcases/substrate/functions/payable_02.sol:7:13-31"]
 	contracts -> contract
 	contract -> var [label="variable"]
 	var -> number_literal [label="initializer"]
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Debug"]
-	diagnostics -> diagnostic_8 [label="Error"]
+	diagnostics -> diagnostic_6 [label="Debug"]
+	diagnostics -> diagnostic_7 [label="Error"]
 }

+ 4 - 4
tests/contract_testcases/substrate/functions/payable_03.dot

@@ -3,12 +3,12 @@ strict digraph "tests/contract_testcases/substrate/functions/payable_03.sol" {
 	var [label="variable i\nvisibility internal\ntests/contract_testcases/substrate/functions/payable_03.sol:5:13-24"]
 	number_literal [label="int32 literal: 0\ntests/contract_testcases/substrate/functions/payable_03.sol:5:23-24"]
 	diagnostic [label="pragma 'solidity' is ignored\nlevel Debug\ntests/contract_testcases/substrate/functions/payable_03.sol:2:9-26"]
-	diagnostic_7 [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/functions/payable_03.sol:4:9-10:10"]
-	diagnostic_8 [label="fallback function must not be declare payable, use 'receive() external payable' instead\nlevel Error\ntests/contract_testcases/substrate/functions/payable_03.sol:7:13-40"]
+	diagnostic_6 [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/functions/payable_03.sol:4:9-10:10"]
+	diagnostic_7 [label="fallback function must not be declare payable, use 'receive() external payable' instead\nlevel Error\ntests/contract_testcases/substrate/functions/payable_03.sol:7:13-40"]
 	contracts -> contract
 	contract -> var [label="variable"]
 	var -> number_literal [label="initializer"]
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Debug"]
-	diagnostics -> diagnostic_8 [label="Error"]
+	diagnostics -> diagnostic_6 [label="Debug"]
+	diagnostics -> diagnostic_7 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/functions/return_not_returns.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/functions/return_not_returns.sol" {
 	contract [label="contract test\ntests/contract_testcases/substrate/functions/return_not_returns.sol:1:1-5:10"]
 	diagnostic [label="found contract 'test'\nlevel Debug\ntests/contract_testcases/substrate/functions/return_not_returns.sol:1:1-5:10"]
-	diagnostic_5 [label="'return' unexpected. Did you mean 'returns'?\nlevel Error\ntests/contract_testcases/substrate/functions/return_not_returns.sol:2:40-46"]
+	diagnostic_4 [label="'return' unexpected. Did you mean 'returns'?\nlevel Error\ntests/contract_testcases/substrate/functions/return_not_returns.sol:2:40-46"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/functions/stray_semicolon_01.dot

@@ -2,9 +2,9 @@ strict digraph "tests/contract_testcases/substrate/functions/stray_semicolon_01.
 	a [label="name:a\ncontract: x\ntests/contract_testcases/substrate/functions/stray_semicolon_01.sol:1:21-22\nfield name:f1 ty:uint32"]
 	contract [label="contract x\ntests/contract_testcases/substrate/functions/stray_semicolon_01.sol:1:1-40"]
 	diagnostic [label="found contract 'x'\nlevel Debug\ntests/contract_testcases/substrate/functions/stray_semicolon_01.sol:1:1-40"]
-	diagnostic_7 [label="stray semicolon\nlevel Error\ntests/contract_testcases/substrate/functions/stray_semicolon_01.sol:1:37-38"]
+	diagnostic_6 [label="stray semicolon\nlevel Error\ntests/contract_testcases/substrate/functions/stray_semicolon_01.sol:1:37-38"]
 	structs -> a
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_7 [label="Error"]
+	diagnostics -> diagnostic_6 [label="Error"]
 }

+ 6 - 6
tests/contract_testcases/substrate/inheritance/inherit_types_03.dot

@@ -1,14 +1,14 @@
 strict digraph "tests/contract_testcases/substrate/inheritance/inherit_types_03.sol" {
 	enum_x [label="name: enum_x\ncontract: b\ntests/contract_testcases/substrate/inheritance/inherit_types_03.sol:9:13-35\nvalue: x1\nvalue: x2"]
 	contract [label="contract a\ntests/contract_testcases/substrate/inheritance/inherit_types_03.sol:2:9-6:10"]
-	contract_5 [label="contract b\ntests/contract_testcases/substrate/inheritance/inherit_types_03.sol:8:9-10:10"]
+	contract_4 [label="contract b\ntests/contract_testcases/substrate/inheritance/inherit_types_03.sol:8:9-10:10"]
 	diagnostic [label="found contract 'a'\nlevel Debug\ntests/contract_testcases/substrate/inheritance/inherit_types_03.sol:2:9-6:10"]
-	diagnostic_8 [label="type 'enum_x' not found\nlevel Error\ntests/contract_testcases/substrate/inheritance/inherit_types_03.sol:3:45-51"]
-	diagnostic_9 [label="found contract 'b'\nlevel Debug\ntests/contract_testcases/substrate/inheritance/inherit_types_03.sol:8:9-10:10"]
+	diagnostic_7 [label="type 'enum_x' not found\nlevel Error\ntests/contract_testcases/substrate/inheritance/inherit_types_03.sol:3:45-51"]
+	diagnostic_8 [label="found contract 'b'\nlevel Debug\ntests/contract_testcases/substrate/inheritance/inherit_types_03.sol:8:9-10:10"]
 	enums -> enum_x
 	contracts -> contract
-	contracts -> contract_5
+	contracts -> contract_4
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_8 [label="Error"]
-	diagnostics -> diagnostic_9 [label="Debug"]
+	diagnostics -> diagnostic_7 [label="Error"]
+	diagnostics -> diagnostic_8 [label="Debug"]
 }

+ 4 - 4
tests/contract_testcases/substrate/inheritance/test_interface.dot

@@ -1,10 +1,10 @@
 strict digraph "tests/contract_testcases/substrate/inheritance/test_interface.sol" {
 	contract [label="contract foo\ntests/contract_testcases/substrate/inheritance/test_interface.sol:2:9-5:10"]
 	diagnostic [label="found interface 'foo'\nlevel Debug\ntests/contract_testcases/substrate/inheritance/test_interface.sol:2:9-5:10"]
-	diagnostic_5 [label="constructor not allowed in an interface\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_interface.sol:3:13-41"]
-	diagnostic_6 [label="'public': visibility for constructors is ignored\nlevel Warning\ntests/contract_testcases/substrate/inheritance/test_interface.sol:3:35-41"]
+	diagnostic_4 [label="constructor not allowed in an interface\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_interface.sol:3:13-41"]
+	diagnostic_5 [label="'public': visibility for constructors is ignored\nlevel Warning\ntests/contract_testcases/substrate/inheritance/test_interface.sol:3:35-41"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
-	diagnostics -> diagnostic_6 [label="Warning"]
+	diagnostics -> diagnostic_4 [label="Error"]
+	diagnostics -> diagnostic_5 [label="Warning"]
 }

+ 2 - 2
tests/contract_testcases/substrate/inheritance/test_interface_01.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/inheritance/test_interface_01.sol" {
 	contract [label="contract foo\ntests/contract_testcases/substrate/inheritance/test_interface_01.sol:2:9-4:10"]
 	diagnostic [label="found interface 'foo'\nlevel Debug\ntests/contract_testcases/substrate/inheritance/test_interface_01.sol:2:9-4:10"]
-	diagnostic_5 [label="function in an interface cannot have a body\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_interface_01.sol:3:13-36"]
+	diagnostic_4 [label="function in an interface cannot have a body\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_interface_01.sol:3:13-36"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 3 - 3
tests/contract_testcases/substrate/inheritance/test_interface_02.dot

@@ -1,10 +1,10 @@
 strict digraph "tests/contract_testcases/substrate/inheritance/test_interface_02.sol" {
 	contract [label="contract foo\ntests/contract_testcases/substrate/inheritance/test_interface_02.sol:2:9-4:10"]
 	diagnostic [label="found interface 'foo'\nlevel Debug\ntests/contract_testcases/substrate/inheritance/test_interface_02.sol:2:9-4:10"]
-	diagnostic_5 [label="function marked 'virtual' cannot also be 'private'\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_interface_02.sol:3:13-35"]
-	diagnostic_6 [label="functions must be declared 'external' in an interface\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_interface_02.sol:3:13-35"]
+	diagnostic_4 [label="function marked 'virtual' cannot also be 'private'\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_interface_02.sol:3:13-35"]
+	diagnostic_5 [label="functions must be declared 'external' in an interface\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_interface_02.sol:3:13-35"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_4 [label="Error"]
 	diagnostics -> diagnostic_5 [label="Error"]
-	diagnostics -> diagnostic_6 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/inheritance/test_interface_03.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/inheritance/test_interface_03.sol" {
 	contract [label="contract foo\ntests/contract_testcases/substrate/inheritance/test_interface_03.sol:2:9-4:10"]
 	diagnostic [label="found interface 'foo'\nlevel Debug\ntests/contract_testcases/substrate/inheritance/test_interface_03.sol:2:9-4:10"]
-	diagnostic_5 [label="functions must be declared 'external' in an interface\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_interface_03.sol:3:13-36"]
+	diagnostic_4 [label="functions must be declared 'external' in an interface\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_interface_03.sol:3:13-36"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/inheritance/test_interface_07.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/inheritance/test_interface_07.sol" {
 	contract [label="contract bar\ntests/contract_testcases/substrate/inheritance/test_interface_07.sol:2:9-4:10"]
 	diagnostic [label="found interface 'bar'\nlevel Debug\ntests/contract_testcases/substrate/inheritance/test_interface_07.sol:2:9-4:10"]
-	diagnostic_5 [label="interface 'bar' is not allowed to have contract variable 'x'\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_interface_07.sol:3:13-18"]
+	diagnostic_4 [label="interface 'bar' is not allowed to have contract variable 'x'\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_interface_07.sol:3:13-18"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/inheritance/test_interface_08.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/inheritance/test_interface_08.sol" {
 	contract [label="contract bar\ntests/contract_testcases/substrate/inheritance/test_interface_08.sol:2:9-4:10"]
 	diagnostic [label="found interface 'bar'\nlevel Debug\ntests/contract_testcases/substrate/inheritance/test_interface_08.sol:2:9-4:10"]
-	diagnostic_5 [label="interface 'bar' is not allowed to have contract variable 'x'\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_interface_08.sol:3:13-31"]
+	diagnostic_4 [label="interface 'bar' is not allowed to have contract variable 'x'\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_interface_08.sol:3:13-31"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 3 - 3
tests/contract_testcases/substrate/inheritance/test_override.dot

@@ -1,10 +1,10 @@
 strict digraph "tests/contract_testcases/substrate/inheritance/test_override.sol" {
 	contract [label="contract base\ntests/contract_testcases/substrate/inheritance/test_override.sol:2:9-6:10"]
 	diagnostic [label="found contract 'base'\nlevel Debug\ntests/contract_testcases/substrate/inheritance/test_override.sol:2:9-6:10"]
-	diagnostic_5 [label="function redeclared 'override'\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_override.sol:3:45-53"]
+	diagnostic_4 [label="function redeclared 'override'\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_override.sol:3:45-53"]
 	note [label="location of previous declaration of 'override'\ntests/contract_testcases/substrate/inheritance/test_override.sol:3:36-44"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
-	diagnostic_5 -> note [label="note"]
+	diagnostics -> diagnostic_4 [label="Error"]
+	diagnostic_4 -> note [label="note"]
 }

+ 2 - 2
tests/contract_testcases/substrate/inheritance/test_super.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/inheritance/test_super.sol" {
 	contract [label="contract super\ntests/contract_testcases/substrate/inheritance/test_super.sol:1:1-18"]
 	diagnostic [label="found contract 'super'\nlevel Debug\ntests/contract_testcases/substrate/inheritance/test_super.sol:1:1-18"]
-	diagnostic_5 [label="'super' shadows name of a builtin\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_super.sol:1:10-15"]
+	diagnostic_4 [label="'super' shadows name of a builtin\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_super.sol:1:10-15"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/inheritance/test_virtual.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/inheritance/test_virtual.sol" {
 	contract [label="contract c\ntests/contract_testcases/substrate/inheritance/test_virtual.sol:2:9-4:10"]
 	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/substrate/inheritance/test_virtual.sol:2:9-4:10"]
-	diagnostic_5 [label="function with no body missing 'virtual'. This was permitted in older versions of the Solidity language, please update.\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_virtual.sol:3:13-35"]
+	diagnostic_4 [label="function with no body missing 'virtual'. This was permitted in older versions of the Solidity language, please update.\nlevel Error\ntests/contract_testcases/substrate/inheritance/test_virtual.sol:3:13-35"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/libraries/restrictions.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/libraries/restrictions.sol" {
 	contract [label="contract c\ntests/contract_testcases/substrate/libraries/restrictions.sol:2:9-4:10"]
 	diagnostic [label="found library 'c'\nlevel Debug\ntests/contract_testcases/substrate/libraries/restrictions.sol:2:9-4:10"]
-	diagnostic_5 [label="constructor not allowed in a library\nlevel Error\ntests/contract_testcases/substrate/libraries/restrictions.sol:3:13-27"]
+	diagnostic_4 [label="constructor not allowed in a library\nlevel Error\ntests/contract_testcases/substrate/libraries/restrictions.sol:3:13-27"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/libraries/restrictions_01.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/libraries/restrictions_01.sol" {
 	contract [label="contract c\ntests/contract_testcases/substrate/libraries/restrictions_01.sol:2:9-4:10"]
 	diagnostic [label="found library 'c'\nlevel Debug\ntests/contract_testcases/substrate/libraries/restrictions_01.sol:2:9-4:10"]
-	diagnostic_5 [label="receive not allowed in a library\nlevel Error\ntests/contract_testcases/substrate/libraries/restrictions_01.sol:3:13-31"]
+	diagnostic_4 [label="receive not allowed in a library\nlevel Error\ntests/contract_testcases/substrate/libraries/restrictions_01.sol:3:13-31"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/libraries/restrictions_02.dot

@@ -1,8 +1,8 @@
 strict digraph "tests/contract_testcases/substrate/libraries/restrictions_02.sol" {
 	contract [label="contract c\ntests/contract_testcases/substrate/libraries/restrictions_02.sol:2:9-4:10"]
 	diagnostic [label="found library 'c'\nlevel Debug\ntests/contract_testcases/substrate/libraries/restrictions_02.sol:2:9-4:10"]
-	diagnostic_5 [label="fallback not allowed in a library\nlevel Error\ntests/contract_testcases/substrate/libraries/restrictions_02.sol:3:13-32"]
+	diagnostic_4 [label="fallback not allowed in a library\nlevel Error\ntests/contract_testcases/substrate/libraries/restrictions_02.sol:3:13-32"]
 	contracts -> contract
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_5 [label="Error"]
+	diagnostics -> diagnostic_4 [label="Error"]
 }

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff