浏览代码

New tests: ensure parsed ast is stable and compare entire ast

The graphviz dot file includes the entire ast and all the diagnostics.
We store the original file, and the dot file for comparison. This way
we can ensure there are no parsing regressions, that parsing is stable,
and it is easy to add new parser tests.

Signed-off-by: Sean Young <sean@mess.org>
Sean Young 4 年之前
父节点
当前提交
2986642dcc
共有 100 个文件被更改,包括 1340 次插入60 次删除
  1. 24 10
      src/bin/solang.rs
  2. 3 3
      src/codegen/cfg.rs
  3. 10 0
      src/lib.rs
  4. 1 1
      src/parser/pt.rs
  5. 6 6
      src/sema/ast.rs
  6. 7 7
      src/sema/contracts.rs
  7. 47 27
      src/sema/dotgraphviz.rs
  8. 2 2
      src/sema/expression.rs
  9. 2 2
      src/sema/format.rs
  10. 2 2
      src/sema/statements.rs
  11. 84 0
      tests/contract.rs
  12. 12 0
      tests/contract_testcases/ewasm/call/call.dot
  13. 7 0
      tests/contract_testcases/ewasm/call/call.sol
  14. 12 0
      tests/contract_testcases/ewasm/call/call_01.dot
  15. 7 0
      tests/contract_testcases/ewasm/call/call_01.sol
  16. 30 0
      tests/contract_testcases/ewasm/call/call_02.dot
  17. 7 0
      tests/contract_testcases/ewasm/call/call_02.sol
  18. 18 0
      tests/contract_testcases/solana/accessor/constant.dot
  19. 4 0
      tests/contract_testcases/solana/accessor/constant.sol
  20. 22 0
      tests/contract_testcases/solana/accessor/constant_01.dot
  21. 5 0
      tests/contract_testcases/solana/accessor/constant_01.sol
  22. 12 0
      tests/contract_testcases/solana/assembly/parse.dot
  23. 9 0
      tests/contract_testcases/solana/assembly/parse.sol
  24. 10 0
      tests/contract_testcases/solana/call/calltys.dot
  25. 8 0
      tests/contract_testcases/solana/call/calltys.sol
  26. 10 0
      tests/contract_testcases/solana/call/calltys_01.dot
  27. 8 0
      tests/contract_testcases/solana/call/calltys_01.sol
  28. 10 0
      tests/contract_testcases/solana/call/calltys_02.dot
  29. 8 0
      tests/contract_testcases/solana/call/calltys_02.sol
  30. 28 0
      tests/contract_testcases/solana/constant/not_constant.dot
  31. 12 0
      tests/contract_testcases/solana/constant/not_constant.sol
  32. 30 0
      tests/contract_testcases/solana/constant/not_constant_01.dot
  33. 12 0
      tests/contract_testcases/solana/constant/not_constant_01.sol
  34. 16 0
      tests/contract_testcases/solana/create_contract/base_contract.dot
  35. 13 0
      tests/contract_testcases/solana/create_contract/base_contract.sol
  36. 24 0
      tests/contract_testcases/solana/create_contract/base_contract_01.dot
  37. 19 0
      tests/contract_testcases/solana/create_contract/base_contract_01.sol
  38. 22 0
      tests/contract_testcases/solana/create_contract/base_contract_02.dot
  39. 15 0
      tests/contract_testcases/solana/create_contract/base_contract_02.sol
  40. 14 0
      tests/contract_testcases/solana/create_contract/syntax.dot
  41. 8 0
      tests/contract_testcases/solana/create_contract/syntax.sol
  42. 14 0
      tests/contract_testcases/solana/create_contract/syntax_01.dot
  43. 8 0
      tests/contract_testcases/solana/create_contract/syntax_01.sol
  44. 42 0
      tests/contract_testcases/solana/expressions/bytes32_0.dot
  45. 14 0
      tests/contract_testcases/solana/expressions/bytes32_0.sol
  46. 12 0
      tests/contract_testcases/solana/expressions/bytes32_0_01.dot
  47. 6 0
      tests/contract_testcases/solana/expressions/bytes32_0_01.sol
  48. 12 0
      tests/contract_testcases/solana/expressions/bytes32_0_02.dot
  49. 6 0
      tests/contract_testcases/solana/expressions/bytes32_0_02.sol
  50. 24 0
      tests/contract_testcases/solana/expressions/const_in_type.dot
  51. 6 0
      tests/contract_testcases/solana/expressions/const_in_type.sol
  52. 60 0
      tests/contract_testcases/solana/expressions/contract_no_init.dot
  53. 16 0
      tests/contract_testcases/solana/expressions/contract_no_init.sol
  54. 12 0
      tests/contract_testcases/solana/expressions/interfaceid.dot
  55. 6 0
      tests/contract_testcases/solana/expressions/interfaceid.sol
  56. 10 0
      tests/contract_testcases/solana/expressions/pushpop.dot
  57. 8 0
      tests/contract_testcases/solana/expressions/pushpop.sol
  58. 10 0
      tests/contract_testcases/solana/expressions/pushpop_01.dot
  59. 8 0
      tests/contract_testcases/solana/expressions/pushpop_01.sol
  60. 16 0
      tests/contract_testcases/solana/expressions/selector_in_free_function.dot
  61. 11 0
      tests/contract_testcases/solana/expressions/selector_in_free_function.sol
  62. 30 0
      tests/contract_testcases/solana/expressions/selector_in_free_function_01.dot
  63. 10 0
      tests/contract_testcases/solana/expressions/selector_in_free_function_01.sol
  64. 32 0
      tests/contract_testcases/solana/expressions/selector_in_free_function_02.dot
  65. 11 0
      tests/contract_testcases/solana/expressions/selector_in_free_function_02.sol
  66. 12 0
      tests/contract_testcases/solana/expressions/tx.dot
  67. 6 0
      tests/contract_testcases/solana/expressions/tx.sol
  68. 12 0
      tests/contract_testcases/solana/expressions/tx_01.dot
  69. 6 0
      tests/contract_testcases/solana/expressions/tx_01.sol
  70. 10 0
      tests/contract_testcases/solana/hash/constants_hash_tests.dot
  71. 8 0
      tests/contract_testcases/solana/hash/constants_hash_tests.sol
  72. 10 0
      tests/contract_testcases/solana/hash/constants_hash_tests_01.dot
  73. 8 0
      tests/contract_testcases/solana/hash/constants_hash_tests_01.sol
  74. 12 0
      tests/contract_testcases/solana/rational/rational.dot
  75. 7 0
      tests/contract_testcases/solana/rational/rational.sol
  76. 16 0
      tests/contract_testcases/solana/returns/return_err.dot
  77. 8 0
      tests/contract_testcases/solana/returns/return_err.sol
  78. 18 0
      tests/contract_testcases/solana/returns/return_err_01.dot
  79. 8 0
      tests/contract_testcases/solana/returns/return_err_01.sol
  80. 36 0
      tests/contract_testcases/solana/returns/return_err_02.dot
  81. 11 0
      tests/contract_testcases/solana/returns/return_err_02.sol
  82. 34 0
      tests/contract_testcases/solana/returns/return_err_03.dot
  83. 11 0
      tests/contract_testcases/solana/returns/return_err_03.sol
  84. 12 0
      tests/contract_testcases/solana/returns/return_err_04.dot
  85. 7 0
      tests/contract_testcases/solana/returns/return_err_04.sol
  86. 8 0
      tests/contract_testcases/substrate/arrays/array_dimensions.dot
  87. 4 0
      tests/contract_testcases/substrate/arrays/array_dimensions.sol
  88. 8 0
      tests/contract_testcases/substrate/arrays/array_dimensions_01.dot
  89. 4 0
      tests/contract_testcases/substrate/arrays/array_dimensions_01.sol
  90. 8 0
      tests/contract_testcases/substrate/arrays/array_dimensions_02.dot
  91. 4 0
      tests/contract_testcases/substrate/arrays/array_dimensions_02.sol
  92. 10 0
      tests/contract_testcases/substrate/arrays/array_dimensions_03.dot
  93. 5 0
      tests/contract_testcases/substrate/arrays/array_dimensions_03.sol
  94. 10 0
      tests/contract_testcases/substrate/arrays/array_dimensions_04.dot
  95. 7 0
      tests/contract_testcases/substrate/arrays/array_dimensions_04.sol
  96. 8 0
      tests/contract_testcases/substrate/arrays/data_locations.dot
  97. 5 0
      tests/contract_testcases/substrate/arrays/data_locations.sol
  98. 8 0
      tests/contract_testcases/substrate/arrays/data_locations_01.dot
  99. 5 0
      tests/contract_testcases/substrate/arrays/data_locations_01.sol
  100. 10 0
      tests/contract_testcases/substrate/arrays/data_locations_02.dot

+ 24 - 10
src/bin/solang.rs

@@ -468,15 +468,6 @@ fn process_file(
         diagnostics::print_messages(resolver, &ns, verbose);
     }
 
-    if ns.contracts.is_empty() || diagnostics::any_errors(&ns.diagnostics) {
-        return Err(());
-    }
-
-    if let Some("ast") = matches.value_of("EMIT") {
-        println!("{}", ns.print(filename));
-        return Ok(ns);
-    }
-
     if let Some("ast-dot") = matches.value_of("EMIT") {
         let filepath = PathBuf::from(filename);
         let stem = filepath.file_stem().unwrap().to_string_lossy();
@@ -486,13 +477,36 @@ fn process_file(
             eprintln!("info: Saving graphviz dot {}", dot_filename.display());
         }
 
-        if let Err(err) = ns.dotgraphviz(&dot_filename) {
+        let dot = ns.dotgraphviz();
+
+        let mut file = match File::create(&dot_filename) {
+            Ok(file) => file,
+            Err(err) => {
+                eprintln!(
+                    "error: cannot create file ‘{}’: {}",
+                    dot_filename.display(),
+                    err,
+                );
+                std::process::exit(1);
+            }
+        };
+
+        if let Err(err) = file.write_all(dot.as_bytes()) {
             eprintln!("{}: error: {}", dot_filename.display(), err);
             std::process::exit(1);
         }
         return Ok(ns);
     }
 
+    if ns.contracts.is_empty() || diagnostics::any_errors(&ns.diagnostics) {
+        return Err(());
+    }
+
+    if let Some("ast") = matches.value_of("EMIT") {
+        println!("{}", ns.print(filename));
+        return Ok(ns);
+    }
+
     // emit phase
     for contract_no in 0..ns.contracts.len() {
         let resolved_contract = &ns.contracts[contract_no];

+ 3 - 3
src/codegen/cfg.rs

@@ -1,5 +1,5 @@
 use indexmap::IndexMap;
-use std::collections::{BTreeSet, HashMap, HashSet};
+use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
 use std::fmt;
 use std::str;
 
@@ -1359,8 +1359,8 @@ fn function_cfg(
     // known the top level constructor, since the arguments can be specified elsewhere
     // on a constructor for a superior class
     if func.ty == pt::FunctionTy::Constructor && func.contract_no == Some(contract_no) {
-        let mut all_base_args = HashMap::new();
-        let mut diagnostics = HashSet::new();
+        let mut all_base_args = BTreeMap::new();
+        let mut diagnostics = BTreeSet::new();
 
         // Find all the resolved arguments for base contracts. These can be attached
         // to the contract, or the constructor. Contracts can have multiple constructors

+ 10 - 0
src/lib.rs

@@ -66,6 +66,16 @@ impl Target {
             value_length: 16,
         }
     }
+
+    /// Creates a target from a string
+    pub fn from(name: &str) -> Option<Self> {
+        match name {
+            "solana" => Some(Target::Solana),
+            "substrate" => Some(Target::default_substrate()),
+            "ewasm" => Some(Target::Ewasm),
+            _ => None,
+        }
+    }
 }
 
 /// Compile a solidity file to list of wasm files and their ABIs. The filename is only used for error messages;

+ 1 - 1
src/parser/pt.rs

@@ -2,7 +2,7 @@ use num_bigint::BigInt;
 use num_rational::BigRational;
 use std::fmt;
 
-#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
+#[derive(Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Clone, Copy)]
 /// file no, start offset, end offset (in bytes)
 pub struct Loc(pub usize, pub usize, pub usize);
 

+ 6 - 6
src/sema/ast.rs

@@ -159,7 +159,7 @@ pub struct Function {
     pub params: Vec<Parameter>,
     pub returns: Vec<Parameter>,
     // constructor arguments for base contracts, only present on constructors
-    pub bases: HashMap<usize, (pt::Loc, usize, Vec<Expression>)>,
+    pub bases: BTreeMap<usize, (pt::Loc, usize, Vec<Expression>)>,
     // modifiers for functions
     pub modifiers: Vec<Expression>,
     pub is_virtual: bool,
@@ -213,7 +213,7 @@ impl Function {
             visibility,
             params,
             returns,
-            bases: HashMap::new(),
+            bases: BTreeMap::new(),
             modifiers: Vec::new(),
             is_virtual: false,
             is_accessor: false,
@@ -1517,7 +1517,7 @@ impl Statement {
     }
 }
 
-#[derive(Debug, Eq, Hash, PartialEq)]
+#[derive(Debug, Eq, Hash, PartialOrd, Ord, PartialEq)]
 pub enum Level {
     Debug,
     Info,
@@ -1525,7 +1525,7 @@ pub enum Level {
     Error,
 }
 
-#[derive(Debug, Eq, Hash, PartialEq)]
+#[derive(Debug, Eq, Hash, PartialOrd, Ord, PartialEq)]
 pub enum ErrorType {
     None,
     ParserError,
@@ -1535,13 +1535,13 @@ pub enum ErrorType {
     Warning,
 }
 
-#[derive(Debug, Eq, Hash, PartialEq)]
+#[derive(Debug, Eq, Hash, PartialOrd, Ord, PartialEq)]
 pub struct Note {
     pub pos: pt::Loc,
     pub message: String,
 }
 
-#[derive(Debug, Eq, Hash, PartialEq)]
+#[derive(Debug, Eq, Hash, PartialOrd, Ord, PartialEq)]
 pub struct Diagnostic {
     pub level: Level,
     pub ty: ErrorType,

+ 7 - 7
src/sema/contracts.rs

@@ -2,7 +2,7 @@ use crate::parser::pt;
 use inkwell::OptimizationLevel;
 use num_bigint::BigInt;
 use num_traits::Zero;
-use std::collections::{BTreeMap, HashMap, HashSet};
+use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
 use std::convert::TryInto;
 use tiny_keccak::{Hasher, Keccak};
 
@@ -272,7 +272,7 @@ pub fn is_base(base: usize, parent: usize, ns: &ast::Namespace) -> bool {
 fn check_inheritance(contract_no: usize, ns: &mut ast::Namespace) {
     let mut function_syms: HashMap<String, ast::Symbol> = HashMap::new();
     let mut variable_syms: HashMap<String, ast::Symbol> = HashMap::new();
-    let mut override_needed: HashMap<String, Vec<(usize, usize)>> = HashMap::new();
+    let mut override_needed: BTreeMap<String, Vec<(usize, usize)>> = BTreeMap::new();
 
     for base_contract_no in visit_bases(contract_no, ns) {
         // find file number where contract is defined
@@ -885,8 +885,8 @@ pub struct BaseOrModifier<'a> {
 pub fn collect_base_args<'a>(
     contract_no: usize,
     constructor_no: Option<usize>,
-    base_args: &mut HashMap<usize, BaseOrModifier<'a>>,
-    diagnostics: &mut HashSet<ast::Diagnostic>,
+    base_args: &mut BTreeMap<usize, BaseOrModifier<'a>>,
+    diagnostics: &mut BTreeSet<ast::Diagnostic>,
     ns: &'a ast::Namespace,
 ) {
     let contract = &ns.contracts[contract_no];
@@ -978,7 +978,7 @@ fn check_base_args(contract_no: usize, ns: &mut ast::Namespace) {
         return;
     }
 
-    let mut diagnostics = HashSet::new();
+    let mut diagnostics = BTreeSet::new();
     let base_args_needed = visit_bases(contract_no, ns)
         .into_iter()
         .filter(|base_no| {
@@ -992,7 +992,7 @@ fn check_base_args(contract_no: usize, ns: &mut ast::Namespace) {
             .iter()
             .filter(|function_no| ns.functions[**function_no].is_constructor())
         {
-            let mut base_args = HashMap::new();
+            let mut base_args = BTreeMap::new();
 
             collect_base_args(
                 contract_no,
@@ -1015,7 +1015,7 @@ fn check_base_args(contract_no: usize, ns: &mut ast::Namespace) {
             }
         }
     } else {
-        let mut base_args = HashMap::new();
+        let mut base_args = BTreeMap::new();
 
         collect_base_args(contract_no, None, &mut base_args, &mut diagnostics, ns);
 

+ 47 - 27
src/sema/dotgraphviz.rs

@@ -1,6 +1,5 @@
 use super::ast::*;
 use crate::parser::pt;
-use std::{fs::File, io, io::Write, path::Path};
 
 struct Node {
     name: String,
@@ -29,42 +28,36 @@ struct Dot {
 }
 
 impl Dot {
-    fn write(&self, path: &Path) -> Result<(), io::Error> {
-        let mut file = File::create(path)?;
-
-        writeln!(&mut file, "strict digraph \"{}\" {{", self.filename)?;
+    fn write(&self) -> String {
+        let mut result = format!("strict digraph \"{}\" {{\n", self.filename);
 
         for node in &self.nodes {
             if !node.labels.is_empty() {
-                writeln!(
-                    &mut file,
-                    "\t{} [label=\"{}\"]",
+                result.push_str(&format!(
+                    "\t{} [label=\"{}\"]\n",
                     node.name,
                     node.labels.join("\\n")
-                )
-                .unwrap();
+                ));
             }
         }
 
         for edge in &self.edges {
             if let Some(label) = &edge.label {
-                writeln!(
-                    &mut file,
-                    "\t{} -> {} [label=\"{}\"]",
+                result.push_str(&format!(
+                    "\t{} -> {} [label=\"{}\"]\n",
                     self.nodes[edge.from].name, self.nodes[edge.to].name, label
-                )?;
+                ));
             } else {
-                writeln!(
-                    &mut file,
-                    "\t{} -> {}",
+                result.push_str(&format!(
+                    "\t{} -> {}\n",
                     self.nodes[edge.from].name, self.nodes[edge.to].name
-                )?;
+                ));
             }
         }
 
-        writeln!(&mut file, "}}")?;
+        result.push_str("}\n");
 
-        Ok(())
+        result
     }
 
     fn add_node(
@@ -102,6 +95,21 @@ impl Dot {
         no
     }
 
+    fn add_tags(&mut self, tags: &[Tag], parent: usize) {
+        if !tags.is_empty() {
+            let labels = tags
+                .iter()
+                .map(|tag| format!("{}: {}", tag.tag, tag.value))
+                .collect();
+
+            self.add_node(
+                Node::new("tags", labels),
+                Some(parent),
+                Some(String::from("tags")),
+            );
+        }
+    }
+
     fn add_function(&mut self, func: &Function, ns: &Namespace, parent: usize) {
         let mut labels = vec![
             format!("{} {}", func.ty, func.name),
@@ -139,6 +147,8 @@ impl Dot {
             Some(format!("{}", func.ty)),
         );
 
+        self.add_tags(&func.tags, func_node);
+
         // parameters
         if !func.params.is_empty() {
             let mut labels = vec![String::from("parameters")];
@@ -181,7 +191,7 @@ impl Dot {
             );
 
             for (no, arg) in args.iter().enumerate() {
-                self.add_expression(arg, None, ns, node, format!("arg #{}", no));
+                self.add_expression(arg, Some(func), ns, node, format!("arg #{}", no));
             }
         }
 
@@ -1621,7 +1631,7 @@ impl Dot {
 }
 
 impl Namespace {
-    pub fn dotgraphviz(&self, path: &Path) -> Result<(), io::Error> {
+    pub fn dotgraphviz(&self) -> String {
         let mut dot = Dot {
             filename: format!("{}", self.files[0].path.display()),
             nodes: Vec::new(),
@@ -1647,7 +1657,9 @@ impl Namespace {
 
                 let e = Node::new(&decl.name, labels);
 
-                dot.add_node(e, Some(enums), None);
+                let node = dot.add_node(e, Some(enums), None);
+
+                dot.add_tags(&decl.tags, node);
             }
         }
 
@@ -1675,7 +1687,9 @@ impl Namespace {
 
                 let e = Node::new(&decl.name, labels);
 
-                dot.add_node(e, Some(structs), None);
+                let node = dot.add_node(e, Some(structs), None);
+
+                dot.add_tags(&decl.tags, node);
             }
         }
 
@@ -1708,13 +1722,15 @@ impl Namespace {
 
                 let e = Node::new(&decl.name, labels);
 
-                dot.add_node(e, Some(events), None);
+                let node = dot.add_node(e, Some(events), None);
+
+                dot.add_tags(&decl.tags, node);
             }
         }
 
         // free functions
         if !self.functions.iter().any(|func| func.contract_no.is_some()) {
-            let functions = dot.add_node(Node::new("free functions", Vec::new()), None, None);
+            let functions = dot.add_node(Node::new("free_functions", Vec::new()), None, None);
 
             for func in &self.functions {
                 if func.contract_no.is_none() {
@@ -1739,6 +1755,8 @@ impl Namespace {
                 None,
             );
 
+            dot.add_tags(&c.tags, contract);
+
             for base in &c.bases {
                 let node = dot.add_node(
                     Node::new(
@@ -1783,6 +1801,8 @@ impl Namespace {
                 if let Some(initializer) = &var.initializer {
                     dot.add_expression(initializer, None, self, node, String::from("initializer"));
                 }
+
+                dot.add_tags(&var.tags, node);
             }
 
             for (library, ty) in &c.using {
@@ -1849,6 +1869,6 @@ impl Namespace {
             }
         }
 
-        dot.write(path)
+        dot.write()
     }
 }

+ 2 - 2
src/sema/expression.rs

@@ -8,8 +8,8 @@ use num_traits::ToPrimitive;
 use num_traits::Zero;
 use std::cmp;
 use std::cmp::Ordering;
-use std::collections::HashMap;
 use std::collections::HashSet;
+use std::collections::{BTreeMap, HashMap};
 use std::ops::{Add, Shl, Sub};
 
 use super::address::to_hexstr_eip55;
@@ -3666,7 +3666,7 @@ pub fn constructor_named_args(
         ns.contracts[contract_no].creates.push(no);
     }
 
-    let mut arguments: HashMap<&String, &pt::Expression> = HashMap::new();
+    let mut arguments: BTreeMap<&String, &pt::Expression> = BTreeMap::new();
 
     for arg in args {
         if let Some(prev) = arguments.get(&arg.name.name) {

+ 2 - 2
src/sema/format.rs

@@ -249,7 +249,7 @@ impl<'a> Iterator for FormatIterator<'a> {
     fn next(&mut self) -> Option<Self::Item> {
         if let Some((offset, ch)) = self.literal.next() {
             let mut loc = self.loc;
-            loc.0 += offset;
+            loc.1 += offset;
 
             return Some((loc, ch));
         }
@@ -260,7 +260,7 @@ impl<'a> Iterator for FormatIterator<'a> {
 
             if let Some((offset, ch)) = self.literal.next() {
                 let mut loc = self.loc;
-                loc.0 += offset;
+                loc.1 += offset;
 
                 return Some((loc, ch));
             }

+ 2 - 2
src/sema/statements.rs

@@ -8,7 +8,7 @@ use super::symtable::{LoopScopes, Symtable};
 use crate::parser::pt;
 use crate::sema::symtable::VariableUsage;
 use crate::sema::unused_variable::{assigned_variable, check_function_call, used_variable};
-use std::collections::HashMap;
+use std::collections::{BTreeMap, HashMap};
 
 pub fn resolve_function_body(
     def: &pt::FunctionDefinition,
@@ -46,7 +46,7 @@ pub fn resolve_function_body(
     // constructors.
     if def.ty == pt::FunctionTy::Constructor {
         let contract_no = contract_no.unwrap();
-        let mut resolve_bases: HashMap<usize, pt::Loc> = HashMap::new();
+        let mut resolve_bases: BTreeMap<usize, pt::Loc> = BTreeMap::new();
         let mut all_ok = true;
 
         for attr in &def.attributes {

+ 84 - 0
tests/contract.rs

@@ -0,0 +1,84 @@
+use solang::{file_resolver::FileResolver, parse_and_resolve, Target};
+use std::{
+    fs::{read_dir, File},
+    io::{self, Read},
+    path::PathBuf,
+};
+
+#[test]
+fn contract_tests() -> io::Result<()> {
+    let targets = read_dir("tests/contract_testcases")?;
+
+    for target in targets {
+        let path = target?.path();
+
+        if let Some(filename) = path.file_name() {
+            if let Some(target) = Target::from(&filename.to_string_lossy()) {
+                recurse_directory(path, target)?;
+            }
+        }
+    }
+
+    Ok(())
+}
+
+fn recurse_directory(path: PathBuf, target: Target) -> io::Result<()> {
+    for entry in read_dir(path)? {
+        let path = entry?.path();
+
+        if path.is_dir() {
+            recurse_directory(path, target)?;
+        } else if let Some(ext) = path.extension() {
+            if ext.to_string_lossy() == "sol" {
+                parse_file(path, target)?;
+            }
+        }
+    }
+
+    Ok(())
+}
+
+fn parse_file(path: PathBuf, target: Target) -> io::Result<()> {
+    let mut cache = FileResolver::new();
+
+    let mut file = File::open(&path)?;
+
+    let mut source = String::new();
+
+    file.read_to_string(&mut source)?;
+
+    // make sure the path uses unix file separators, this is what the dot file uses
+    let filename = path.to_string_lossy().replace('\\', "/");
+
+    println!("Parsing {} for {}", path.display(), target);
+
+    // The files may have had their end of lines mangled on Windows
+    cache.set_file_contents(&filename, source.replace("\r\n", "\n"));
+
+    let ns = parse_and_resolve(&filename, &mut cache, target);
+
+    let mut path = path;
+
+    path.set_extension("dot");
+
+    let generated_dot = ns.dotgraphviz();
+
+    // use std::io::Write;
+
+    // let mut file = File::create(&path)?;
+
+    // file.write_all(generated_dot.as_bytes())?;
+
+    let mut file = File::open(&path)?;
+
+    let mut test_dot = String::new();
+
+    file.read_to_string(&mut test_dot)?;
+
+    // The dot files may have had their end of lines mangled on Windows
+    let test_dot = test_dot.replace("\r\n", "\n");
+
+    assert_eq!(generated_dot, test_dot);
+
+    Ok(())
+}

+ 12 - 0
tests/contract_testcases/ewasm/call/call.dot

@@ -0,0 +1,12 @@
+strict digraph "tests/contract_testcases/ewasm/call/call.sol" {
+	contract [label="contract x\ntests/contract_testcases/ewasm/call/call.sol:2:9-20"]
+	f [label="function f\ncontract: x\ntests/contract_testcases/ewasm/call/call.sol:3:13-49\nsignature f(address)\nvisibility public\nmutability nonpayable"]
+	parameters [label="parameters\naddress payable a"]
+	diagnostic [label="found contract ‘x’\nlevel Debug\ntests/contract_testcases/ewasm/call/call.sol:2:9-20"]
+	diagnostic_6 [label="‘delegatecall’ cannot have value specifed\nlevel Error\ntests/contract_testcases/ewasm/call/call.sol:4:45-73"]
+	contracts -> contract
+	contract -> f [label="function"]
+	f -> parameters [label="parameters"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_6 [label="Error"]
+}

+ 7 - 0
tests/contract_testcases/ewasm/call/call.sol

@@ -0,0 +1,7 @@
+
+        contract x {
+            function f(address payable a) public {
+                (bool s, bytes memory bs) = a.delegatecall{value: 2}("");
+            }
+        }
+        

+ 12 - 0
tests/contract_testcases/ewasm/call/call_01.dot

@@ -0,0 +1,12 @@
+strict digraph "tests/contract_testcases/ewasm/call/call_01.sol" {
+	contract [label="contract x\ntests/contract_testcases/ewasm/call/call_01.sol:2:9-20"]
+	f [label="function f\ncontract: x\ntests/contract_testcases/ewasm/call/call_01.sol:3:13-49\nsignature f(address)\nvisibility public\nmutability nonpayable"]
+	parameters [label="parameters\naddress payable a"]
+	diagnostic [label="found contract ‘x’\nlevel Debug\ntests/contract_testcases/ewasm/call/call_01.sol:2:9-20"]
+	diagnostic_6 [label="‘staticcall’ cannot have value specifed\nlevel Error\ntests/contract_testcases/ewasm/call/call_01.sol:4:45-71"]
+	contracts -> contract
+	contract -> f [label="function"]
+	f -> parameters [label="parameters"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_6 [label="Error"]
+}

+ 7 - 0
tests/contract_testcases/ewasm/call/call_01.sol

@@ -0,0 +1,7 @@
+
+        contract x {
+            function f(address payable a) public {
+                (bool s, bytes memory bs) = a.staticcall{value: 2}("");
+            }
+        }
+        

+ 30 - 0
tests/contract_testcases/ewasm/call/call_02.dot

@@ -0,0 +1,30 @@
+strict digraph "tests/contract_testcases/ewasm/call/call_02.sol" {
+	contract [label="contract x\ntests/contract_testcases/ewasm/call/call_02.sol:2:9-20"]
+	f [label="function f\ncontract: x\ntests/contract_testcases/ewasm/call/call_02.sol:3:13-49\nsignature f(address)\nvisibility public\nmutability nonpayable"]
+	parameters [label="parameters\naddress payable a"]
+	destructure [label="destructure\ntests/contract_testcases/ewasm/call/call_02.sol:4:17-65"]
+	param [label="bool s"]
+	param_6 [label="bytes bs"]
+	call_external_function [label="call external function\ntests/contract_testcases/ewasm/call/call_02.sol:4:45-65"]
+	variable [label="variable: a\naddress payable\ntests/contract_testcases/ewasm/call/call_02.sol:4:45-46"]
+	alloc_array [label="alloc array bytes\ninitializer: \ntests/contract_testcases/ewasm/call/call_02.sol:4:62-64"]
+	number_literal [label="uint32 literal: 0\ntests/contract_testcases/ewasm/call/call_02.sol:4:62-64"]
+	number_literal_11 [label="uint128 literal: 2\ntests/contract_testcases/ewasm/call/call_02.sol:4:59-60"]
+	diagnostic [label="found contract ‘x’\nlevel Debug\ntests/contract_testcases/ewasm/call/call_02.sol:2:9-20"]
+	diagnostic_14 [label="destructure variable 's' has never been used\nlevel Warning\ntests/contract_testcases/ewasm/call/call_02.sol:4:23-24"]
+	diagnostic_15 [label="destructure variable 'bs' has never been used\nlevel Warning\ntests/contract_testcases/ewasm/call/call_02.sol:4:39-41"]
+	contracts -> contract
+	contract -> f [label="function"]
+	f -> parameters [label="parameters"]
+	f -> destructure [label="body"]
+	destructure -> param [label="arg #0"]
+	destructure -> param_6 [label="arg #1"]
+	destructure -> call_external_function [label="expr"]
+	call_external_function -> variable [label="address"]
+	call_external_function -> alloc_array [label="args"]
+	alloc_array -> number_literal [label="length"]
+	call_external_function -> number_literal_11 [label="value"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_14 [label="Warning"]
+	diagnostics -> diagnostic_15 [label="Warning"]
+}

+ 7 - 0
tests/contract_testcases/ewasm/call/call_02.sol

@@ -0,0 +1,7 @@
+
+        contract x {
+            function f(address payable a) public {
+                (bool s, bytes memory bs) = a.call{value: 2}("");
+            }
+        }
+        

+ 18 - 0
tests/contract_testcases/solana/accessor/constant.dot

@@ -0,0 +1,18 @@
+strict digraph "tests/contract_testcases/solana/accessor/constant.sol" {
+	contract [label="contract x\ntests/contract_testcases/solana/accessor/constant.sol:2:9-20"]
+	var [label="variable z\nvisibility public\nconstant\ntests/contract_testcases/solana/accessor/constant.sol:3:13-53"]
+	z [label="function z\ncontract: x\ntests/contract_testcases/solana/accessor/constant.sol:3:37-38\nsignature z()\nvisibility public\nmutability view"]
+	returns [label="returns\nbytes32 "]
+	return [label="return\ntests/contract_testcases/solana/accessor/constant.sol:1:1"]
+	constant [label="constant variable\nx.z\nbytes32\ntests/contract_testcases/solana/accessor/constant.sol:1:1"]
+	diagnostic [label="found contract ‘x’\nlevel Debug\ntests/contract_testcases/solana/accessor/constant.sol:2:9-20"]
+	diagnostic_9 [label="cannot call function in constant expression\nlevel Error\ntests/contract_testcases/solana/accessor/constant.sol:3:41-53"]
+	contracts -> contract
+	contract -> var [label="variable"]
+	contract -> z [label="function"]
+	z -> returns [label="returns"]
+	z -> return [label="body"]
+	return -> constant [label="expr"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_9 [label="Error"]
+}

+ 4 - 0
tests/contract_testcases/solana/accessor/constant.sol

@@ -0,0 +1,4 @@
+
+        contract x {
+            bytes32 public constant z = blockhash(1);
+        }

+ 22 - 0
tests/contract_testcases/solana/accessor/constant_01.dot

@@ -0,0 +1,22 @@
+strict digraph "tests/contract_testcases/solana/accessor/constant_01.sol" {
+	contract [label="contract x\ntests/contract_testcases/solana/accessor/constant_01.sol:2:9-20"]
+	var [label="variable foo\nvisibility internal\ntests/contract_testcases/solana/accessor/constant_01.sol:3:13-22"]
+	var_3 [label="variable z\nvisibility public\nconstant\ntests/contract_testcases/solana/accessor/constant_01.sol:4:13-55"]
+	z [label="function z\ncontract: x\ntests/contract_testcases/solana/accessor/constant_01.sol:4:37-38\nsignature z()\nvisibility public\nmutability view"]
+	returns [label="returns\nbytes32 "]
+	return [label="return\ntests/contract_testcases/solana/accessor/constant_01.sol:1:1"]
+	constant [label="constant variable\nx.z\nbytes32\ntests/contract_testcases/solana/accessor/constant_01.sol:1:1"]
+	diagnostic [label="found contract ‘x’\nlevel Debug\ntests/contract_testcases/solana/accessor/constant_01.sol:2:9-20"]
+	diagnostic_10 [label="cannot read contract variable ‘foo’ in constant expression\nlevel Error\ntests/contract_testcases/solana/accessor/constant_01.sol:4:51-54"]
+	diagnostic_11 [label="storage variable 'foo' has never been used\nlevel Warning\ntests/contract_testcases/solana/accessor/constant_01.sol:3:13-22"]
+	contracts -> contract
+	contract -> var [label="variable"]
+	contract -> var_3 [label="variable"]
+	contract -> z [label="function"]
+	z -> returns [label="returns"]
+	z -> return [label="body"]
+	return -> constant [label="expr"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_10 [label="Error"]
+	diagnostics -> diagnostic_11 [label="Warning"]
+}

+ 5 - 0
tests/contract_testcases/solana/accessor/constant_01.sol

@@ -0,0 +1,5 @@
+
+        contract x {
+            bytes foo;
+            bytes32 public constant z = keccak256(foo);
+        }

+ 12 - 0
tests/contract_testcases/solana/assembly/parse.dot

@@ -0,0 +1,12 @@
+strict digraph "tests/contract_testcases/solana/assembly/parse.sol" {
+	contract [label="contract foo\ntests/contract_testcases/solana/assembly/parse.sol:2:9-22"]
+	get [label="function get\ncontract: foo\ntests/contract_testcases/solana/assembly/parse.sol:3:13-51\nsignature get()\nvisibility public\nmutability nonpayable"]
+	returns [label="returns\nbytes4 "]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/solana/assembly/parse.sol:2:9-22"]
+	diagnostic_6 [label="evm assembly not supported on target solana\nlevel Error\ntests/contract_testcases/solana/assembly/parse.sol:4:17-7:18"]
+	contracts -> contract
+	contract -> get [label="function"]
+	get -> returns [label="returns"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_6 [label="Error"]
+}

+ 9 - 0
tests/contract_testcases/solana/assembly/parse.sol

@@ -0,0 +1,9 @@
+
+        contract foo {
+            function get() public returns (bytes4) {
+                assembly {
+                    let returndata_size := mload(returndata)
+                    revert(add(32, returndata), returndata_size)
+                }
+            }
+        }

+ 10 - 0
tests/contract_testcases/solana/call/calltys.dot

@@ -0,0 +1,10 @@
+strict digraph "tests/contract_testcases/solana/call/calltys.sol" {
+	contract [label="contract main\ntests/contract_testcases/solana/call/calltys.sol:2:9-23"]
+	test [label="function test\ncontract: main\ntests/contract_testcases/solana/call/calltys.sol:3:13-35\nsignature test()\nvisibility public\nmutability nonpayable"]
+	diagnostic [label="found contract ‘main’\nlevel Debug\ntests/contract_testcases/solana/call/calltys.sol:2:9-23"]
+	diagnostic_5 [label="method ‘staticcall’ does not exist\nlevel Error\ntests/contract_testcases/solana/call/calltys.sol:6:19-29"]
+	contracts -> contract
+	contract -> test [label="function"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_5 [label="Error"]
+}

+ 8 - 0
tests/contract_testcases/solana/call/calltys.sol

@@ -0,0 +1,8 @@
+
+        contract main {
+            function test() public {
+                address x = address(0);
+
+                x.staticcall(hex"1222");
+            }
+        }

+ 10 - 0
tests/contract_testcases/solana/call/calltys_01.dot

@@ -0,0 +1,10 @@
+strict digraph "tests/contract_testcases/solana/call/calltys_01.sol" {
+	contract [label="contract main\ntests/contract_testcases/solana/call/calltys_01.sol:2:9-23"]
+	test [label="function test\ncontract: main\ntests/contract_testcases/solana/call/calltys_01.sol:3:13-35\nsignature test()\nvisibility public\nmutability nonpayable"]
+	diagnostic [label="found contract ‘main’\nlevel Debug\ntests/contract_testcases/solana/call/calltys_01.sol:2:9-23"]
+	diagnostic_5 [label="method ‘delegatecall’ does not exist\nlevel Error\ntests/contract_testcases/solana/call/calltys_01.sol:6:19-31"]
+	contracts -> contract
+	contract -> test [label="function"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_5 [label="Error"]
+}

+ 8 - 0
tests/contract_testcases/solana/call/calltys_01.sol

@@ -0,0 +1,8 @@
+
+        contract main {
+            function test() public {
+                address x = address(0);
+
+                x.delegatecall(hex"1222");
+            }
+        }

+ 10 - 0
tests/contract_testcases/solana/call/calltys_02.dot

@@ -0,0 +1,10 @@
+strict digraph "tests/contract_testcases/solana/call/calltys_02.sol" {
+	contract [label="contract main\ntests/contract_testcases/solana/call/calltys_02.sol:2:9-23"]
+	test [label="function test\ncontract: main\ntests/contract_testcases/solana/call/calltys_02.sol:3:13-35\nsignature test()\nvisibility public\nmutability nonpayable"]
+	diagnostic [label="found contract ‘main’\nlevel Debug\ntests/contract_testcases/solana/call/calltys_02.sol:2:9-23"]
+	diagnostic_5 [label="‘gas’ not permitted for external calls or constructors on solana\nlevel Error\ntests/contract_testcases/solana/call/calltys_02.sol:6:51-57"]
+	contracts -> contract
+	contract -> test [label="function"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_5 [label="Error"]
+}

+ 8 - 0
tests/contract_testcases/solana/call/calltys_02.sol

@@ -0,0 +1,8 @@
+
+        contract main {
+            function test() public {
+                address x = address(0);
+
+                (bool success, bytes bs) = x.call{gas: 5}(hex"1222");
+            }
+        }

+ 28 - 0
tests/contract_testcases/solana/constant/not_constant.dot

@@ -0,0 +1,28 @@
+strict digraph "tests/contract_testcases/solana/constant/not_constant.sol" {
+	contract [label="contract C\ntests/contract_testcases/solana/constant/not_constant.sol:2:9-20"]
+	var [label="variable STATIC\nvisibility public\nconstant\ntests/contract_testcases/solana/constant/not_constant.sol:3:13-48"]
+	number_literal [label="uint256 literal: 42\ntests/contract_testcases/solana/constant/not_constant.sol:3:46-48"]
+	STATIC [label="function STATIC\ncontract: C\ntests/contract_testcases/solana/constant/not_constant.sol:3:37-43\nsignature STATIC()\nvisibility public\nmutability view"]
+	returns [label="returns\nuint256 "]
+	return [label="return\ntests/contract_testcases/solana/constant/not_constant.sol:1:1"]
+	constant [label="constant variable\nC.STATIC\nuint256\ntests/contract_testcases/solana/constant/not_constant.sol:1:1"]
+	contract_8 [label="contract foo\ntests/contract_testcases/solana/constant/not_constant.sol:6:9-22"]
+	f [label="function f\ncontract: foo\ntests/contract_testcases/solana/constant/not_constant.sol:7:13-47\nsignature f()\nvisibility public\nmutability nonpayable"]
+	returns_10 [label="returns\nuint256 "]
+	diagnostic [label="found contract ‘C’\nlevel Debug\ntests/contract_testcases/solana/constant/not_constant.sol:2:9-20"]
+	diagnostic_13 [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/solana/constant/not_constant.sol:6:9-22"]
+	diagnostic_14 [label="`C' is a contract\nlevel Error\ntests/contract_testcases/solana/constant/not_constant.sol:8:26-27"]
+	contracts -> contract
+	contract -> var [label="variable"]
+	var -> number_literal [label="initializer"]
+	contract -> STATIC [label="function"]
+	STATIC -> returns [label="returns"]
+	STATIC -> return [label="body"]
+	return -> constant [label="expr"]
+	contracts -> contract_8
+	contract_8 -> f [label="function"]
+	f -> returns_10 [label="returns"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_13 [label="Debug"]
+	diagnostics -> diagnostic_14 [label="Error"]
+}

+ 12 - 0
tests/contract_testcases/solana/constant/not_constant.sol

@@ -0,0 +1,12 @@
+
+        contract C {
+            uint256 public constant STATIC = 42;
+        }
+
+        contract foo {
+            function f() public returns (uint) {
+                uint a = C.STATIC();
+                return a;
+            }
+        }
+        

+ 30 - 0
tests/contract_testcases/solana/constant/not_constant_01.dot

@@ -0,0 +1,30 @@
+strict digraph "tests/contract_testcases/solana/constant/not_constant_01.sol" {
+	contract [label="contract C\ntests/contract_testcases/solana/constant/not_constant_01.sol:2:9-20"]
+	var [label="variable NOT_CONSTANT\nvisibility public\ntests/contract_testcases/solana/constant/not_constant_01.sol:3:13-45"]
+	number_literal [label="uint256 literal: 42\ntests/contract_testcases/solana/constant/not_constant_01.sol:3:43-45"]
+	NOT_CONSTANT [label="function NOT_CONSTANT\ncontract: C\ntests/contract_testcases/solana/constant/not_constant_01.sol:3:28-40\nsignature NOT_CONSTANT()\nvisibility public\nmutability view"]
+	returns [label="returns\nuint256 "]
+	return [label="return\ntests/contract_testcases/solana/constant/not_constant_01.sol:1:1"]
+	storage_load [label="storage load uint256\ntests/contract_testcases/solana/constant/not_constant_01.sol:1:1"]
+	storage_var [label="storage variable\nC.NOT_CONSTANT\nuint256 storage\ntests/contract_testcases/solana/constant/not_constant_01.sol:1:1"]
+	contract_9 [label="contract foo\ntests/contract_testcases/solana/constant/not_constant_01.sol:6:9-22"]
+	f [label="function f\ncontract: foo\ntests/contract_testcases/solana/constant/not_constant_01.sol:7:13-47\nsignature f()\nvisibility public\nmutability nonpayable"]
+	returns_11 [label="returns\nuint256 "]
+	diagnostic [label="found contract ‘C’\nlevel Debug\ntests/contract_testcases/solana/constant/not_constant_01.sol:2:9-20"]
+	diagnostic_14 [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/solana/constant/not_constant_01.sol:6:9-22"]
+	diagnostic_15 [label="need instance of contract ‘C’ to get variable value ‘NOT_CONSTANT’\nlevel Error\ntests/contract_testcases/solana/constant/not_constant_01.sol:8:26-27"]
+	contracts -> contract
+	contract -> var [label="variable"]
+	var -> number_literal [label="initializer"]
+	contract -> NOT_CONSTANT [label="function"]
+	NOT_CONSTANT -> returns [label="returns"]
+	NOT_CONSTANT -> return [label="body"]
+	return -> storage_load [label="expr"]
+	storage_load -> storage_var [label="expr"]
+	contracts -> contract_9
+	contract_9 -> f [label="function"]
+	f -> returns_11 [label="returns"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_14 [label="Debug"]
+	diagnostics -> diagnostic_15 [label="Error"]
+}

+ 12 - 0
tests/contract_testcases/solana/constant/not_constant_01.sol

@@ -0,0 +1,12 @@
+
+        contract C {
+            uint256 public NOT_CONSTANT = 42;
+        }
+
+        contract foo {
+            function f() public returns (uint) {
+                uint a = C.NOT_CONSTANT;
+                return a;
+            }
+        }
+        

+ 16 - 0
tests/contract_testcases/solana/create_contract/base_contract.dot

@@ -0,0 +1,16 @@
+strict digraph "tests/contract_testcases/solana/create_contract/base_contract.sol" {
+	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-23"]
+	contract_7 [label="contract IsMath\ntests/contract_testcases/solana/create_contract/base_contract.sol:8:9-32"]
+	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-23"]
+	diagnostic_11 [label="found contract ‘IsMath’\nlevel Debug\ntests/contract_testcases/solana/create_contract/base_contract.sol:8:9-32"]
+	enums -> MathError
+	structs -> WithMath
+	contracts -> contract
+	contracts -> contract_7
+	contract_7 -> base [label="base"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_11 [label="Debug"]
+}

+ 13 - 0
tests/contract_testcases/solana/create_contract/base_contract.sol

@@ -0,0 +1,13 @@
+
+        contract Math {
+            enum MathError {
+                NO_ERROR
+            }
+        }
+
+        contract IsMath is Math {
+            struct WithMath {
+                MathError math;
+            }
+        }
+    

+ 24 - 0
tests/contract_testcases/solana/create_contract/base_contract_01.dot

@@ -0,0 +1,24 @@
+strict digraph "tests/contract_testcases/solana/create_contract/base_contract_01.sol" {
+	LogicError [label="name: LogicError\ncontract: Logic\ntests/contract_testcases/solana/create_contract/base_contract_01.sol:3:13-5:14\nvalue: LE_ERROR"]
+	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-24"]
+	contract_8 [label="contract Math\ntests/contract_testcases/solana/create_contract/base_contract_01.sol:7:9-31"]
+	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-32"]
+	base_11 [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-24"]
+	diagnostic_14 [label="found contract ‘Math’\nlevel Debug\ntests/contract_testcases/solana/create_contract/base_contract_01.sol:7:9-31"]
+	diagnostic_15 [label="found contract ‘IsMath’\nlevel Debug\ntests/contract_testcases/solana/create_contract/base_contract_01.sol:13:9-32"]
+	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"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_14 [label="Debug"]
+	diagnostics -> diagnostic_15 [label="Debug"]
+}

+ 19 - 0
tests/contract_testcases/solana/create_contract/base_contract_01.sol

@@ -0,0 +1,19 @@
+
+        contract Logic {
+            enum LogicError {
+                LE_ERROR
+            }
+        }
+        contract Math is Logic {
+            enum MathError {
+                NO_ERROR
+            }
+        }
+
+        contract IsMath is Math {
+            struct WithMath {
+                MathError math;
+                LogicError logic;
+            }
+        }
+    

+ 22 - 0
tests/contract_testcases/solana/create_contract/base_contract_02.dot

@@ -0,0 +1,22 @@
+strict digraph "tests/contract_testcases/solana/create_contract/base_contract_02.sol" {
+	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-24"]
+	contract_6 [label="contract Math\ntests/contract_testcases/solana/create_contract/base_contract_02.sol:7:9-31"]
+	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-32"]
+	base_9 [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-24"]
+	diagnostic_12 [label="found contract ‘Math’\nlevel Debug\ntests/contract_testcases/solana/create_contract/base_contract_02.sol:7:9-31"]
+	diagnostic_13 [label="found contract ‘IsMath’\nlevel Debug\ntests/contract_testcases/solana/create_contract/base_contract_02.sol:10:9-32"]
+	structs -> LogicFields
+	structs -> WithMath
+	contracts -> contract
+	contracts -> contract_6
+	contract_6 -> base [label="base"]
+	contracts -> contract_8
+	contract_8 -> base_9 [label="base"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_12 [label="Debug"]
+	diagnostics -> diagnostic_13 [label="Debug"]
+}

+ 15 - 0
tests/contract_testcases/solana/create_contract/base_contract_02.sol

@@ -0,0 +1,15 @@
+
+        contract Logic {
+            struct LogicFields {
+                uint logia;
+            }
+        }
+        contract Math is Logic {
+        }
+
+        contract IsMath is Math {
+            struct WithMath {
+                LogicFields logia;
+            }
+        }
+    

+ 14 - 0
tests/contract_testcases/solana/create_contract/syntax.dot

@@ -0,0 +1,14 @@
+strict digraph "tests/contract_testcases/solana/create_contract/syntax.sol" {
+	contract [label="contract y\ntests/contract_testcases/solana/create_contract/syntax.sol:2:9-20"]
+	f [label="function f\ncontract: y\ntests/contract_testcases/solana/create_contract/syntax.sol:3:13-32\nsignature f()\nvisibility public\nmutability nonpayable"]
+	contract_3 [label="contract x\ntests/contract_testcases/solana/create_contract/syntax.sol:7:9-20"]
+	diagnostic [label="found contract ‘y’\nlevel Debug\ntests/contract_testcases/solana/create_contract/syntax.sol:2:9-20"]
+	diagnostic_6 [label="found contract ‘x’\nlevel Debug\ntests/contract_testcases/solana/create_contract/syntax.sol:7:9-20"]
+	diagnostic_7 [label="‘gas’ not permitted for external calls or constructors on solana\nlevel Error\ntests/contract_testcases/solana/create_contract/syntax.sol:4:29-37"]
+	contracts -> contract
+	contract -> f [label="function"]
+	contracts -> contract_3
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_6 [label="Debug"]
+	diagnostics -> diagnostic_7 [label="Error"]
+}

+ 8 - 0
tests/contract_testcases/solana/create_contract/syntax.sol

@@ -0,0 +1,8 @@
+
+        contract y {
+            function f() public {
+                x a = new x{gas: 102}();
+            }
+        }
+        contract x {}
+    

+ 14 - 0
tests/contract_testcases/solana/create_contract/syntax_01.dot

@@ -0,0 +1,14 @@
+strict digraph "tests/contract_testcases/solana/create_contract/syntax_01.sol" {
+	contract [label="contract y\ntests/contract_testcases/solana/create_contract/syntax_01.sol:2:9-20"]
+	f [label="function f\ncontract: y\ntests/contract_testcases/solana/create_contract/syntax_01.sol:3:13-32\nsignature f()\nvisibility public\nmutability nonpayable"]
+	contract_3 [label="contract x\ntests/contract_testcases/solana/create_contract/syntax_01.sol:7:9-20"]
+	diagnostic [label="found contract ‘y’\nlevel Debug\ntests/contract_testcases/solana/create_contract/syntax_01.sol:2:9-20"]
+	diagnostic_6 [label="found contract ‘x’\nlevel Debug\ntests/contract_testcases/solana/create_contract/syntax_01.sol:7:9-20"]
+	diagnostic_7 [label="‘salt’ not permitted for external calls or constructors on solana\nlevel Error\ntests/contract_testcases/solana/create_contract/syntax_01.sol:4:29-38"]
+	contracts -> contract
+	contract -> f [label="function"]
+	contracts -> contract_3
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_6 [label="Debug"]
+	diagnostics -> diagnostic_7 [label="Error"]
+}

+ 8 - 0
tests/contract_testcases/solana/create_contract/syntax_01.sol

@@ -0,0 +1,8 @@
+
+        contract y {
+            function f() public {
+                x a = new x{salt: 102}();
+            }
+        }
+        contract x {}
+    

+ 42 - 0
tests/contract_testcases/solana/expressions/bytes32_0.dot

@@ -0,0 +1,42 @@
+strict digraph "tests/contract_testcases/solana/expressions/bytes32_0.sol" {
+	contract [label="contract x\ntests/contract_testcases/solana/expressions/bytes32_0.sol:2:9-20"]
+	b32 [label="function b32\ncontract: x\ntests/contract_testcases/solana/expressions/bytes32_0.sol:3:13-59\nsignature b32()\nvisibility public\nmutability pure"]
+	returns [label="returns\nbytes32 r"]
+	expr [label="expression\ntests/contract_testcases/solana/expressions/bytes32_0.sol:4:17-31"]
+	assign [label="assign\nbytes32\ntests/contract_testcases/solana/expressions/bytes32_0.sol:4:19-20"]
+	variable [label="variable: r\nbytes32\ntests/contract_testcases/solana/expressions/bytes32_0.sol:4:17-18"]
+	number_literal [label="bytes32 literal: 0\ntests/contract_testcases/solana/expressions/bytes32_0.sol:4:21-31"]
+	b4 [label="function b4\ncontract: x\ntests/contract_testcases/solana/expressions/bytes32_0.sol:7:13-57\nsignature b4()\nvisibility public\nmutability pure"]
+	returns_9 [label="returns\nbytes4 r"]
+	expr_10 [label="expression\ntests/contract_testcases/solana/expressions/bytes32_0.sol:8:17-39"]
+	assign_11 [label="assign\nbytes4\ntests/contract_testcases/solana/expressions/bytes32_0.sol:8:19-20"]
+	variable_12 [label="variable: r\nbytes4\ntests/contract_testcases/solana/expressions/bytes32_0.sol:8:17-18"]
+	number_literal_13 [label="bytes4 literal: 3405700781\ntests/contract_testcases/solana/expressions/bytes32_0.sol:8:21-39"]
+	b3 [label="function b3\ncontract: x\ntests/contract_testcases/solana/expressions/bytes32_0.sol:11:13-57\nsignature b3()\nvisibility public\nmutability pure"]
+	returns_15 [label="returns\nbytes3 r"]
+	expr_16 [label="expression\ntests/contract_testcases/solana/expressions/bytes32_0.sol:12:17-37"]
+	assign_17 [label="assign\nbytes3\ntests/contract_testcases/solana/expressions/bytes32_0.sol:12:19-20"]
+	variable_18 [label="variable: r\nbytes3\ntests/contract_testcases/solana/expressions/bytes32_0.sol:12:17-18"]
+	number_literal_19 [label="bytes3 literal: 74291\ntests/contract_testcases/solana/expressions/bytes32_0.sol:12:21-37"]
+	diagnostic [label="found contract ‘x’\nlevel Debug\ntests/contract_testcases/solana/expressions/bytes32_0.sol:2:9-20"]
+	contracts -> contract
+	contract -> b32 [label="function"]
+	b32 -> returns [label="returns"]
+	b32 -> expr [label="body"]
+	expr -> assign [label="expr"]
+	assign -> variable [label="left"]
+	assign -> number_literal [label="right"]
+	contract -> b4 [label="function"]
+	b4 -> returns_9 [label="returns"]
+	b4 -> expr_10 [label="body"]
+	expr_10 -> assign_11 [label="expr"]
+	assign_11 -> variable_12 [label="left"]
+	assign_11 -> number_literal_13 [label="right"]
+	contract -> b3 [label="function"]
+	b3 -> returns_15 [label="returns"]
+	b3 -> expr_16 [label="body"]
+	expr_16 -> assign_17 [label="expr"]
+	assign_17 -> variable_18 [label="left"]
+	assign_17 -> number_literal_19 [label="right"]
+	diagnostics -> diagnostic [label="Debug"]
+}

+ 14 - 0
tests/contract_testcases/solana/expressions/bytes32_0.sol

@@ -0,0 +1,14 @@
+
+        contract x {
+            function b32() public pure returns (bytes32 r) {
+                r = bytes32(0);
+            }
+
+            function b4() public pure returns (bytes4 r) {
+                r = bytes4(0xcafedead);
+            }
+
+            function b3() public pure returns (bytes3 r) {
+                r = bytes3(0x012233);
+            }
+        }

+ 12 - 0
tests/contract_testcases/solana/expressions/bytes32_0_01.dot

@@ -0,0 +1,12 @@
+strict digraph "tests/contract_testcases/solana/expressions/bytes32_0_01.sol" {
+	contract [label="contract foo\ntests/contract_testcases/solana/expressions/bytes32_0_01.sol:2:9-22"]
+	b32 [label="function b32\ncontract: foo\ntests/contract_testcases/solana/expressions/bytes32_0_01.sol:3:13-59\nsignature b32()\nvisibility public\nmutability pure"]
+	returns [label="returns\nbytes32 r"]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/solana/expressions/bytes32_0_01.sol:2:9-22"]
+	diagnostic_6 [label="number of 2 bytes cannot be converted to type ‘bytes32’\nlevel Error\ntests/contract_testcases/solana/expressions/bytes32_0_01.sol:4:21-36"]
+	contracts -> contract
+	contract -> b32 [label="function"]
+	b32 -> returns [label="returns"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_6 [label="Error"]
+}

+ 6 - 0
tests/contract_testcases/solana/expressions/bytes32_0_01.sol

@@ -0,0 +1,6 @@
+
+        contract foo {
+            function b32() public pure returns (bytes32 r) {
+                r = bytes32(0xffee);
+            }
+        }

+ 12 - 0
tests/contract_testcases/solana/expressions/bytes32_0_02.dot

@@ -0,0 +1,12 @@
+strict digraph "tests/contract_testcases/solana/expressions/bytes32_0_02.sol" {
+	contract [label="contract foo\ntests/contract_testcases/solana/expressions/bytes32_0_02.sol:2:9-22"]
+	b32 [label="function b32\ncontract: foo\ntests/contract_testcases/solana/expressions/bytes32_0_02.sol:3:13-59\nsignature b32()\nvisibility public\nmutability pure"]
+	returns [label="returns\nbytes32 r"]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/solana/expressions/bytes32_0_02.sol:2:9-22"]
+	diagnostic_6 [label="negative number cannot be converted to type ‘bytes32’\nlevel Error\ntests/contract_testcases/solana/expressions/bytes32_0_02.sol:4:21-32"]
+	contracts -> contract
+	contract -> b32 [label="function"]
+	b32 -> returns [label="returns"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_6 [label="Error"]
+}

+ 6 - 0
tests/contract_testcases/solana/expressions/bytes32_0_02.sol

@@ -0,0 +1,6 @@
+
+        contract foo {
+            function b32() public pure returns (bytes32 r) {
+                r = bytes32(-1);
+            }
+        }

+ 24 - 0
tests/contract_testcases/solana/expressions/const_in_type.dot

@@ -0,0 +1,24 @@
+strict digraph "tests/contract_testcases/solana/expressions/const_in_type.sol" {
+	contract [label="contract x\ntests/contract_testcases/solana/expressions/const_in_type.sol:2:9-20"]
+	var [label="variable Y\nvisibility public\nconstant\ntests/contract_testcases/solana/expressions/const_in_type.sol:3:13-40"]
+	number_literal [label="uint256 literal: 24\ntests/contract_testcases/solana/expressions/const_in_type.sol:3:38-40"]
+	Y [label="function Y\ncontract: x\ntests/contract_testcases/solana/expressions/const_in_type.sol:3:34-35\nsignature Y()\nvisibility public\nmutability view"]
+	returns [label="returns\nuint256 "]
+	return [label="return\ntests/contract_testcases/solana/expressions/const_in_type.sol:1:1"]
+	constant [label="constant variable\nx.Y\nuint256\ntests/contract_testcases/solana/expressions/const_in_type.sol:1:1"]
+	node_8 [label="constructor \ncontract: x\ntests/contract_testcases/solana/expressions/const_in_type.sol:5:13-48\nsignature (bytes32[24])\nvisibility public\nmutability nonpayable"]
+	parameters [label="parameters\nbytes32[24] foo"]
+	diagnostic [label="found contract ‘x’\nlevel Debug\ntests/contract_testcases/solana/expressions/const_in_type.sol:2:9-20"]
+	diagnostic_12 [label="function parameter 'foo' has never been read\nlevel Warning\ntests/contract_testcases/solana/expressions/const_in_type.sol:5:43-46"]
+	contracts -> contract
+	contract -> var [label="variable"]
+	var -> number_literal [label="initializer"]
+	contract -> Y [label="function"]
+	Y -> returns [label="returns"]
+	Y -> return [label="body"]
+	return -> constant [label="expr"]
+	contract -> node_8 [label="constructor"]
+	node_8 -> parameters [label="parameters"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_12 [label="Warning"]
+}

+ 6 - 0
tests/contract_testcases/solana/expressions/const_in_type.sol

@@ -0,0 +1,6 @@
+
+        contract x {
+            uint public constant Y = 24;
+
+            constructor(bytes32[Y] memory foo) {}
+        }

+ 60 - 0
tests/contract_testcases/solana/expressions/contract_no_init.dot

@@ -0,0 +1,60 @@
+strict digraph "tests/contract_testcases/solana/expressions/contract_no_init.sol" {
+	contract [label="contract other\ntests/contract_testcases/solana/expressions/contract_no_init.sol:2:9-24"]
+	var [label="variable a\nvisibility public\ntests/contract_testcases/solana/expressions/contract_no_init.sol:3:13-25"]
+	a [label="function a\ncontract: other\ntests/contract_testcases/solana/expressions/contract_no_init.sol:3:24-25\nsignature a()\nvisibility public\nmutability view"]
+	returns [label="returns\nint256 "]
+	return [label="return\ntests/contract_testcases/solana/expressions/contract_no_init.sol:1:1"]
+	storage_load [label="storage load int256\ntests/contract_testcases/solana/expressions/contract_no_init.sol:1:1"]
+	storage_var [label="storage variable\nother.a\nint256 storage\ntests/contract_testcases/solana/expressions/contract_no_init.sol:1:1"]
+	contract_8 [label="contract testing\ntests/contract_testcases/solana/expressions/contract_no_init.sol:6:9-26"]
+	test [label="function test\ncontract: testing\ntests/contract_testcases/solana/expressions/contract_no_init.sol:7:13-54\nsignature test(int256)\nvisibility public\nmutability nonpayable"]
+	parameters [label="parameters\nint256 x"]
+	returns_11 [label="returns\nint256 "]
+	var_decl [label="variable decl contract other o\ntests/contract_testcases/solana/expressions/contract_no_init.sol:8:17-24"]
+	dowhile [label="do while\ntests/contract_testcases/solana/expressions/contract_no_init.sol:9:17-12:30"]
+	expr [label="expression\ntests/contract_testcases/solana/expressions/contract_no_init.sol:10:21-24"]
+	post_decrement [label="post decrement\nint256\ntests/contract_testcases/solana/expressions/contract_no_init.sol:10:21-24"]
+	variable [label="variable: x\nint256\ntests/contract_testcases/solana/expressions/contract_no_init.sol:10:21-22"]
+	expr_17 [label="expression\ntests/contract_testcases/solana/expressions/contract_no_init.sol:11:21-36"]
+	assign [label="assign\ncontract other\ntests/contract_testcases/solana/expressions/contract_no_init.sol:11:23-24"]
+	variable_19 [label="variable: o\ncontract other\ntests/contract_testcases/solana/expressions/contract_no_init.sol:11:21-22"]
+	constructor [label="constructor contract other\ntests/contract_testcases/solana/expressions/contract_no_init.sol:11:25-36"]
+	more [label="more\ntests/contract_testcases/solana/expressions/contract_no_init.sol:12:26-27"]
+	variable_22 [label="variable: x\nint256\ntests/contract_testcases/solana/expressions/contract_no_init.sol:12:24-25"]
+	number_literal [label="int256 literal: 0\ntests/contract_testcases/solana/expressions/contract_no_init.sol:12:28-29"]
+	return_24 [label="return\ntests/contract_testcases/solana/expressions/contract_no_init.sol:14:17-29"]
+	call_external_function [label="call external function\ntests/contract_testcases/solana/expressions/contract_no_init.sol:14:24-29"]
+	external_function [label="function() external view returns (int256)\nother.a\ntests/contract_testcases/solana/expressions/contract_no_init.sol:14:24-29"]
+	variable_27 [label="variable: o\ncontract other\ntests/contract_testcases/solana/expressions/contract_no_init.sol:14:24-25"]
+	diagnostic [label="found contract ‘other’\nlevel Debug\ntests/contract_testcases/solana/expressions/contract_no_init.sol:2:9-24"]
+	diagnostic_30 [label="found contract ‘testing’\nlevel Debug\ntests/contract_testcases/solana/expressions/contract_no_init.sol:6:9-26"]
+	contracts -> contract
+	contract -> var [label="variable"]
+	contract -> a [label="function"]
+	a -> returns [label="returns"]
+	a -> return [label="body"]
+	return -> storage_load [label="expr"]
+	storage_load -> storage_var [label="expr"]
+	contracts -> contract_8
+	contract_8 -> test [label="function"]
+	test -> parameters [label="parameters"]
+	test -> returns_11 [label="returns"]
+	test -> var_decl [label="body"]
+	var_decl -> dowhile [label="next"]
+	dowhile -> expr [label="body"]
+	expr -> post_decrement [label="expr"]
+	post_decrement -> variable [label="expr"]
+	expr -> expr_17 [label="next"]
+	expr_17 -> assign [label="expr"]
+	assign -> variable_19 [label="left"]
+	assign -> constructor [label="right"]
+	dowhile -> more [label="cond"]
+	more -> variable_22 [label="left"]
+	more -> number_literal [label="right"]
+	dowhile -> return_24 [label="next"]
+	return_24 -> call_external_function [label="expr"]
+	call_external_function -> external_function [label="function"]
+	external_function -> variable_27 [label="address"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_30 [label="Debug"]
+}

+ 16 - 0
tests/contract_testcases/solana/expressions/contract_no_init.sol

@@ -0,0 +1,16 @@
+
+        contract other {
+            int public a;
+        }
+
+        contract testing {
+            function test(int x) public returns (int) {
+                other o;
+                do {
+                    x--;
+                    o = new other();
+                }while(x > 0);
+
+                return o.a();
+            }
+        }

+ 12 - 0
tests/contract_testcases/solana/expressions/interfaceid.dot

@@ -0,0 +1,12 @@
+strict digraph "tests/contract_testcases/solana/expressions/interfaceid.sol" {
+	contract [label="contract foo\ntests/contract_testcases/solana/expressions/interfaceid.sol:2:9-22"]
+	get [label="function get\ncontract: foo\ntests/contract_testcases/solana/expressions/interfaceid.sol:3:13-51\nsignature get()\nvisibility public\nmutability nonpayable"]
+	returns [label="returns\nbytes4 "]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/solana/expressions/interfaceid.sol:2:9-22"]
+	diagnostic_6 [label="type(…).interfaceId is permitted on interface, not contract foo\nlevel Error\ntests/contract_testcases/solana/expressions/interfaceid.sol:4:24-45"]
+	contracts -> contract
+	contract -> get [label="function"]
+	get -> returns [label="returns"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_6 [label="Error"]
+}

+ 6 - 0
tests/contract_testcases/solana/expressions/interfaceid.sol

@@ -0,0 +1,6 @@
+
+        contract foo {
+            function get() public returns (bytes4) {
+                return type(foo).interfaceId;
+            }
+        }

+ 10 - 0
tests/contract_testcases/solana/expressions/pushpop.dot

@@ -0,0 +1,10 @@
+strict digraph "tests/contract_testcases/solana/expressions/pushpop.sol" {
+	contract [label="contract foo\ntests/contract_testcases/solana/expressions/pushpop.sol:2:9-22"]
+	test [label="function test\ncontract: foo\ntests/contract_testcases/solana/expressions/pushpop.sol:3:13-35\nsignature test()\nvisibility public\nmutability nonpayable"]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/solana/expressions/pushpop.sol:2:9-22"]
+	diagnostic_5 [label="‘push()’ not supported on ‘bytes’ on target solana\nlevel Error\ntests/contract_testcases/solana/expressions/pushpop.sol:6:19-23"]
+	contracts -> contract
+	contract -> test [label="function"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_5 [label="Error"]
+}

+ 8 - 0
tests/contract_testcases/solana/expressions/pushpop.sol

@@ -0,0 +1,8 @@
+
+        contract foo {
+            function test() public {
+                bytes x;
+
+                x.push();
+            }
+        }

+ 10 - 0
tests/contract_testcases/solana/expressions/pushpop_01.dot

@@ -0,0 +1,10 @@
+strict digraph "tests/contract_testcases/solana/expressions/pushpop_01.sol" {
+	contract [label="contract foo\ntests/contract_testcases/solana/expressions/pushpop_01.sol:2:9-22"]
+	test [label="function test\ncontract: foo\ntests/contract_testcases/solana/expressions/pushpop_01.sol:3:13-35\nsignature test()\nvisibility public\nmutability nonpayable"]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/solana/expressions/pushpop_01.sol:2:9-22"]
+	diagnostic_5 [label="‘pop()’ not supported on ‘bytes’ on target solana\nlevel Error\ntests/contract_testcases/solana/expressions/pushpop_01.sol:6:19-22"]
+	contracts -> contract
+	contract -> test [label="function"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_5 [label="Error"]
+}

+ 8 - 0
tests/contract_testcases/solana/expressions/pushpop_01.sol

@@ -0,0 +1,8 @@
+
+        contract foo {
+            function test() public {
+                bytes x;
+
+                x.pop();
+            }
+        }

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

@@ -0,0 +1,16 @@
+strict digraph "tests/contract_testcases/solana/expressions/selector_in_free_function.sol" {
+	contract [label="contract I\ntests/contract_testcases/solana/expressions/selector_in_free_function.sol:2:9-21"]
+	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_4 [label="contract foo\ntests/contract_testcases/solana/expressions/selector_in_free_function.sol:10:9-22"]
+	diagnostic [label="found interface ‘I’\nlevel Debug\ntests/contract_testcases/solana/expressions/selector_in_free_function.sol:2:9-21"]
+	diagnostic_7 [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/solana/expressions/selector_in_free_function.sol:10:9-22"]
+	diagnostic_8 [label="function can be declared ‘pure’\nlevel Warning\ntests/contract_testcases/solana/expressions/selector_in_free_function.sol:6:9-38"]
+	contracts -> contract
+	contract -> X [label="function"]
+	X -> parameters [label="parameters"]
+	contracts -> contract_4
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_7 [label="Debug"]
+	diagnostics -> diagnostic_8 [label="Warning"]
+}

+ 11 - 0
tests/contract_testcases/solana/expressions/selector_in_free_function.sol

@@ -0,0 +1,11 @@
+
+        interface I {
+            function X(bytes) external;
+        }
+
+        function x() returns (bytes4) {
+            return I.X.selector;
+        }
+
+        contract foo {}
+        

+ 30 - 0
tests/contract_testcases/solana/expressions/selector_in_free_function_01.dot

@@ -0,0 +1,30 @@
+strict digraph "tests/contract_testcases/solana/expressions/selector_in_free_function_01.sol" {
+	contract [label="contract I\ntests/contract_testcases/solana/expressions/selector_in_free_function_01.sol:2:9-21"]
+	X [label="function X\ncontract: I\ntests/contract_testcases/solana/expressions/selector_in_free_function_01.sol:3:13-39\nsignature X(bytes)\nvisibility external\nmutability nonpayable\nvirtual"]
+	parameters [label="parameters\nbytes "]
+	contract_4 [label="contract X\ntests/contract_testcases/solana/expressions/selector_in_free_function_01.sol:6:9-20"]
+	x [label="function x\ncontract: X\ntests/contract_testcases/solana/expressions/selector_in_free_function_01.sol:7:13-49\nsignature x()\nvisibility public\nmutability nonpayable"]
+	returns [label="returns\nbytes4 "]
+	return [label="return\ntests/contract_testcases/solana/expressions/selector_in_free_function_01.sol:8:17-36"]
+	builtins [label="builtin FunctionSelector\ntests/contract_testcases/solana/expressions/selector_in_free_function_01.sol:8:24-27"]
+	internal_function [label="function(bytes) internal returns (void)\nI.X\ntests/contract_testcases/solana/expressions/selector_in_free_function_01.sol:8:24-25"]
+	diagnostic [label="found interface ‘I’\nlevel Debug\ntests/contract_testcases/solana/expressions/selector_in_free_function_01.sol:2:9-21"]
+	diagnostic_12 [label="X is already defined as a contract name\nlevel Warning\ntests/contract_testcases/solana/expressions/selector_in_free_function_01.sol:3:22-23"]
+	note [label="location of previous definition\ntests/contract_testcases/solana/expressions/selector_in_free_function_01.sol:6:9-20"]
+	diagnostic_14 [label="found contract ‘X’\nlevel Debug\ntests/contract_testcases/solana/expressions/selector_in_free_function_01.sol:6:9-20"]
+	diagnostic_15 [label="function can be declared ‘pure’\nlevel Warning\ntests/contract_testcases/solana/expressions/selector_in_free_function_01.sol:7:13-49"]
+	contracts -> contract
+	contract -> X [label="function"]
+	X -> parameters [label="parameters"]
+	contracts -> contract_4
+	contract_4 -> x [label="function"]
+	x -> returns [label="returns"]
+	x -> return [label="body"]
+	return -> builtins [label="expr"]
+	builtins -> internal_function [label="arg #0"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_12 [label="Warning"]
+	diagnostic_12 -> note [label="note"]
+	diagnostics -> diagnostic_14 [label="Debug"]
+	diagnostics -> diagnostic_15 [label="Warning"]
+}

+ 10 - 0
tests/contract_testcases/solana/expressions/selector_in_free_function_01.sol

@@ -0,0 +1,10 @@
+
+        interface I {
+            function X(bytes) external;
+        }
+
+        contract X {
+            function x() public returns (bytes4) {
+                return I.X.selector;
+            }
+        }

+ 32 - 0
tests/contract_testcases/solana/expressions/selector_in_free_function_02.dot

@@ -0,0 +1,32 @@
+strict digraph "tests/contract_testcases/solana/expressions/selector_in_free_function_02.sol" {
+	contract [label="contract I\ntests/contract_testcases/solana/expressions/selector_in_free_function_02.sol:2:9-20"]
+	X [label="function X\ncontract: I\ntests/contract_testcases/solana/expressions/selector_in_free_function_02.sol:3:13-34\nsignature X()\nvisibility external\nmutability nonpayable"]
+	contract_3 [label="contract foo\ntests/contract_testcases/solana/expressions/selector_in_free_function_02.sol:6:9-22"]
+	f [label="function f\ncontract: foo\ntests/contract_testcases/solana/expressions/selector_in_free_function_02.sol:7:13-52\nsignature f(bytes32)\nvisibility public\nmutability nonpayable"]
+	parameters [label="parameters\ncontract I t"]
+	returns [label="returns\nbytes4 "]
+	return [label="return\ntests/contract_testcases/solana/expressions/selector_in_free_function_02.sol:8:17-36"]
+	builtins [label="builtin FunctionSelector\ntests/contract_testcases/solana/expressions/selector_in_free_function_02.sol:8:24-27"]
+	external_function [label="function() external\nI.X\ntests/contract_testcases/solana/expressions/selector_in_free_function_02.sol:8:26-27"]
+	variable [label="variable: t\ncontract I\ntests/contract_testcases/solana/expressions/selector_in_free_function_02.sol:8:24-25"]
+	diagnostic [label="found contract ‘I’\nlevel Debug\ntests/contract_testcases/solana/expressions/selector_in_free_function_02.sol:2:9-20"]
+	diagnostic_13 [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/solana/expressions/selector_in_free_function_02.sol:6:9-22"]
+	diagnostic_14 [label="function parameter 't' has never been read\nlevel Warning\ntests/contract_testcases/solana/expressions/selector_in_free_function_02.sol:7:26-27"]
+	diagnostic_15 [label="function can be declared ‘pure’\nlevel Warning\ntests/contract_testcases/solana/expressions/selector_in_free_function_02.sol:3:13-34"]
+	diagnostic_16 [label="function can be declared ‘pure’\nlevel Warning\ntests/contract_testcases/solana/expressions/selector_in_free_function_02.sol:7:13-52"]
+	contracts -> contract
+	contract -> X [label="function"]
+	contracts -> contract_3
+	contract_3 -> f [label="function"]
+	f -> parameters [label="parameters"]
+	f -> returns [label="returns"]
+	f -> return [label="body"]
+	return -> builtins [label="expr"]
+	builtins -> external_function [label="arg #0"]
+	external_function -> variable [label="address"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_13 [label="Debug"]
+	diagnostics -> diagnostic_14 [label="Warning"]
+	diagnostics -> diagnostic_15 [label="Warning"]
+	diagnostics -> diagnostic_16 [label="Warning"]
+}

+ 11 - 0
tests/contract_testcases/solana/expressions/selector_in_free_function_02.sol

@@ -0,0 +1,11 @@
+
+        contract I {
+            function X() external {}
+        }
+
+        contract foo {
+            function f(I t) public returns (bytes4) {
+                return t.X.selector;
+            }
+        }
+        

+ 12 - 0
tests/contract_testcases/solana/expressions/tx.dot

@@ -0,0 +1,12 @@
+strict digraph "tests/contract_testcases/solana/expressions/tx.sol" {
+	contract [label="contract foo\ntests/contract_testcases/solana/expressions/tx.sol:2:9-22"]
+	test [label="function test\ncontract: foo\ntests/contract_testcases/solana/expressions/tx.sol:3:13-58\nsignature test()\nvisibility public\nmutability pure"]
+	returns [label="returns\naddress "]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/solana/expressions/tx.sol:2:9-22"]
+	diagnostic_6 [label="builtin ‘tx.origin’ does not exist\nlevel Error\ntests/contract_testcases/solana/expressions/tx.sol:4:24-26"]
+	contracts -> contract
+	contract -> test [label="function"]
+	test -> returns [label="returns"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_6 [label="Error"]
+}

+ 6 - 0
tests/contract_testcases/solana/expressions/tx.sol

@@ -0,0 +1,6 @@
+
+        contract foo {
+            function test() public pure returns (address) {
+                return tx.origin;
+            }
+        }

+ 12 - 0
tests/contract_testcases/solana/expressions/tx_01.dot

@@ -0,0 +1,12 @@
+strict digraph "tests/contract_testcases/solana/expressions/tx_01.sol" {
+	contract [label="contract foo\ntests/contract_testcases/solana/expressions/tx_01.sol:2:9-22"]
+	test [label="function test\ncontract: foo\ntests/contract_testcases/solana/expressions/tx_01.sol:3:13-57\nsignature test()\nvisibility public\nmutability pure"]
+	returns [label="returns\nuint64 "]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/solana/expressions/tx_01.sol:2:9-22"]
+	diagnostic_6 [label="builtin ‘tx.gasprice’ does not exist\nlevel Error\ntests/contract_testcases/solana/expressions/tx_01.sol:4:24-26"]
+	contracts -> contract
+	contract -> test [label="function"]
+	test -> returns [label="returns"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_6 [label="Error"]
+}

+ 6 - 0
tests/contract_testcases/solana/expressions/tx_01.sol

@@ -0,0 +1,6 @@
+
+        contract foo {
+            function test() public pure returns (uint64) {
+                return tx.gasprice;
+            }
+        }

+ 10 - 0
tests/contract_testcases/solana/hash/constants_hash_tests.dot

@@ -0,0 +1,10 @@
+strict digraph "tests/contract_testcases/solana/hash/constants_hash_tests.sol" {
+	contract [label="contract tester\ntests/contract_testcases/solana/hash/constants_hash_tests.sol:2:9-25"]
+	test [label="function test\ncontract: tester\ntests/contract_testcases/solana/hash/constants_hash_tests.sol:3:13-35\nsignature test()\nvisibility public\nmutability nonpayable"]
+	diagnostic [label="found contract ‘tester’\nlevel Debug\ntests/contract_testcases/solana/hash/constants_hash_tests.sol:2:9-25"]
+	diagnostic_5 [label="unknown function or type ‘blake2_256’\nlevel Error\ntests/contract_testcases/solana/hash/constants_hash_tests.sol:4:32-42"]
+	contracts -> contract
+	contract -> test [label="function"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_5 [label="Error"]
+}

+ 8 - 0
tests/contract_testcases/solana/hash/constants_hash_tests.sol

@@ -0,0 +1,8 @@
+
+        contract tester {
+            function test() public {
+                bytes32 hash = blake2_256("Hello, World!");
+
+                assert(hash == hex"527a6a4b9a6da75607546842e0e00105350b1aaf");
+            }
+        }

+ 10 - 0
tests/contract_testcases/solana/hash/constants_hash_tests_01.dot

@@ -0,0 +1,10 @@
+strict digraph "tests/contract_testcases/solana/hash/constants_hash_tests_01.sol" {
+	contract [label="contract tester\ntests/contract_testcases/solana/hash/constants_hash_tests_01.sol:2:9-25"]
+	test [label="function test\ncontract: tester\ntests/contract_testcases/solana/hash/constants_hash_tests_01.sol:3:13-35\nsignature test()\nvisibility public\nmutability nonpayable"]
+	diagnostic [label="found contract ‘tester’\nlevel Debug\ntests/contract_testcases/solana/hash/constants_hash_tests_01.sol:2:9-25"]
+	diagnostic_5 [label="unknown function or type ‘blake2_128’\nlevel Error\ntests/contract_testcases/solana/hash/constants_hash_tests_01.sol:4:32-42"]
+	contracts -> contract
+	contract -> test [label="function"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_5 [label="Error"]
+}

+ 8 - 0
tests/contract_testcases/solana/hash/constants_hash_tests_01.sol

@@ -0,0 +1,8 @@
+
+        contract tester {
+            function test() public {
+                bytes32 hash = blake2_128("Hello, World!");
+
+                assert(hash == hex"527a6a4b9a6da75607546842e0e00105350b1aaf");
+            }
+        }

+ 12 - 0
tests/contract_testcases/solana/rational/rational.dot

@@ -0,0 +1,12 @@
+strict digraph "tests/contract_testcases/solana/rational/rational.sol" {
+	contract [label="contract foo\ntests/contract_testcases/solana/rational/rational.sol:2:9-22"]
+	test [label="function test\ncontract: foo\ntests/contract_testcases/solana/rational/rational.sol:3:13-50\nsignature test()\nvisibility public\nmutability nonpayable"]
+	returns [label="returns\nuint256 "]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/solana/rational/rational.sol:2:9-22"]
+	diagnostic_6 [label="conversion to uint256 from rational not allowed\nlevel Error\ntests/contract_testcases/solana/rational/rational.sol:4:26-29"]
+	contracts -> contract
+	contract -> test [label="function"]
+	test -> returns [label="returns"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_6 [label="Error"]
+}

+ 7 - 0
tests/contract_testcases/solana/rational/rational.sol

@@ -0,0 +1,7 @@
+
+        contract foo {
+            function test() public returns (uint) {
+                uint y = 0.1;
+                return y;
+            }
+        }

+ 16 - 0
tests/contract_testcases/solana/returns/return_err.dot

@@ -0,0 +1,16 @@
+strict digraph "tests/contract_testcases/solana/returns/return_err.sol" {
+	contract [label="contract foo\ntests/contract_testcases/solana/returns/return_err.sol:2:9-22"]
+	var [label="variable val\nvisibility private\ntests/contract_testcases/solana/returns/return_err.sol:3:13-33"]
+	number_literal [label="uint256 literal: 0\ntests/contract_testcases/solana/returns/return_err.sol:3:32-33"]
+	get [label="function get\ncontract: foo\ntests/contract_testcases/solana/returns/return_err.sol:5:13-34\nsignature get()\nvisibility public\nmutability nonpayable"]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/solana/returns/return_err.sol:2:9-22"]
+	diagnostic_7 [label="function has no return values\nlevel Error\ntests/contract_testcases/solana/returns/return_err.sol:6:17-27"]
+	diagnostic_8 [label="storage variable 'val' has been assigned, but never read\nlevel Warning\ntests/contract_testcases/solana/returns/return_err.sol:3:13-33"]
+	contracts -> contract
+	contract -> var [label="variable"]
+	var -> number_literal [label="initializer"]
+	contract -> get [label="function"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_7 [label="Error"]
+	diagnostics -> diagnostic_8 [label="Warning"]
+}

+ 8 - 0
tests/contract_testcases/solana/returns/return_err.sol

@@ -0,0 +1,8 @@
+
+        contract foo {
+            uint private val = 0;
+
+            function get() public {
+                return val;
+            }
+        }

+ 18 - 0
tests/contract_testcases/solana/returns/return_err_01.dot

@@ -0,0 +1,18 @@
+strict digraph "tests/contract_testcases/solana/returns/return_err_01.sol" {
+	contract [label="contract foo\ntests/contract_testcases/solana/returns/return_err_01.sol:2:9-22"]
+	var [label="variable val\nvisibility private\ntests/contract_testcases/solana/returns/return_err_01.sol:3:13-33"]
+	number_literal [label="uint256 literal: 0\ntests/contract_testcases/solana/returns/return_err_01.sol:3:32-33"]
+	get [label="function get\ncontract: foo\ntests/contract_testcases/solana/returns/return_err_01.sol:5:13-55\nsignature get()\nvisibility public\nmutability nonpayable"]
+	returns [label="returns\nuint256 \nuint256 "]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/solana/returns/return_err_01.sol:2:9-22"]
+	diagnostic_8 [label="incorrect number of return values, expected 2 but got 3\nlevel Error\ntests/contract_testcases/solana/returns/return_err_01.sol:6:17-39"]
+	diagnostic_9 [label="storage variable 'val' has been assigned, but never read\nlevel Warning\ntests/contract_testcases/solana/returns/return_err_01.sol:3:13-33"]
+	contracts -> contract
+	contract -> var [label="variable"]
+	var -> number_literal [label="initializer"]
+	contract -> get [label="function"]
+	get -> returns [label="returns"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_8 [label="Error"]
+	diagnostics -> diagnostic_9 [label="Warning"]
+}

+ 8 - 0
tests/contract_testcases/solana/returns/return_err_01.sol

@@ -0,0 +1,8 @@
+
+        contract foo {
+            uint private val = 0;
+
+            function get() public returns (uint, uint) {
+                return (val, val, val);
+            }
+        }

+ 36 - 0
tests/contract_testcases/solana/returns/return_err_02.dot

@@ -0,0 +1,36 @@
+strict digraph "tests/contract_testcases/solana/returns/return_err_02.sol" {
+	contract [label="contract foo\ntests/contract_testcases/solana/returns/return_err_02.sol:2:9-22"]
+	var [label="variable val\nvisibility private\ntests/contract_testcases/solana/returns/return_err_02.sol:3:13-33"]
+	number_literal [label="uint256 literal: 0\ntests/contract_testcases/solana/returns/return_err_02.sol:3:32-33"]
+	f [label="function f\ncontract: foo\ntests/contract_testcases/solana/returns/return_err_02.sol:4:13-59\nsignature f()\nvisibility public\nmutability nonpayable"]
+	returns [label="returns\nuint256 \nuint256 \nuint256 "]
+	return [label="return\ntests/contract_testcases/solana/returns/return_err_02.sol:5:17-39"]
+	list [label="list\ntests/contract_testcases/solana/returns/return_err_02.sol:5:17-39"]
+	storage_load [label="storage load uint256\ntests/contract_testcases/solana/returns/return_err_02.sol:5:17-39"]
+	storage_var [label="storage variable\nfoo.val\nuint256 storage\ntests/contract_testcases/solana/returns/return_err_02.sol:5:25-28"]
+	storage_load_10 [label="storage load uint256\ntests/contract_testcases/solana/returns/return_err_02.sol:5:17-39"]
+	storage_var_11 [label="storage variable\nfoo.val\nuint256 storage\ntests/contract_testcases/solana/returns/return_err_02.sol:5:30-33"]
+	storage_load_12 [label="storage load uint256\ntests/contract_testcases/solana/returns/return_err_02.sol:5:17-39"]
+	storage_var_13 [label="storage variable\nfoo.val\nuint256 storage\ntests/contract_testcases/solana/returns/return_err_02.sol:5:35-38"]
+	get [label="function get\ncontract: foo\ntests/contract_testcases/solana/returns/return_err_02.sol:8:13-55\nsignature get()\nvisibility public\nmutability nonpayable"]
+	returns_15 [label="returns\nuint256 \nuint256 "]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/solana/returns/return_err_02.sol:2:9-22"]
+	diagnostic_18 [label="incorrect number of return values, expected 2 but got 3\nlevel Error\ntests/contract_testcases/solana/returns/return_err_02.sol:9:17-27"]
+	contracts -> contract
+	contract -> var [label="variable"]
+	var -> number_literal [label="initializer"]
+	contract -> f [label="function"]
+	f -> returns [label="returns"]
+	f -> return [label="body"]
+	return -> list [label="expr"]
+	list -> storage_load [label="entry #0"]
+	storage_load -> storage_var [label="expr"]
+	list -> storage_load_10 [label="entry #1"]
+	storage_load_10 -> storage_var_11 [label="expr"]
+	list -> storage_load_12 [label="entry #2"]
+	storage_load_12 -> storage_var_13 [label="expr"]
+	contract -> get [label="function"]
+	get -> returns_15 [label="returns"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_18 [label="Error"]
+}

+ 11 - 0
tests/contract_testcases/solana/returns/return_err_02.sol

@@ -0,0 +1,11 @@
+
+        contract foo {
+            uint private val = 0;
+            function f() public returns (uint, uint, uint) {
+                return (val, val, val);
+            }
+
+            function get() public returns (uint, uint) {
+                return f();
+            }
+        }

+ 34 - 0
tests/contract_testcases/solana/returns/return_err_03.dot

@@ -0,0 +1,34 @@
+strict digraph "tests/contract_testcases/solana/returns/return_err_03.sol" {
+	contract [label="contract foo\ntests/contract_testcases/solana/returns/return_err_03.sol:2:9-22"]
+	var [label="variable val\nvisibility private\ntests/contract_testcases/solana/returns/return_err_03.sol:3:13-33"]
+	number_literal [label="uint256 literal: 0\ntests/contract_testcases/solana/returns/return_err_03.sol:3:32-33"]
+	f [label="function f\ncontract: foo\ntests/contract_testcases/solana/returns/return_err_03.sol:4:13-59\nsignature f()\nvisibility public\nmutability nonpayable"]
+	returns [label="returns\nuint256 \nuint256 \nuint256 "]
+	return [label="return\ntests/contract_testcases/solana/returns/return_err_03.sol:5:17-39"]
+	list [label="list\ntests/contract_testcases/solana/returns/return_err_03.sol:5:17-39"]
+	storage_load [label="storage load uint256\ntests/contract_testcases/solana/returns/return_err_03.sol:5:17-39"]
+	storage_var [label="storage variable\nfoo.val\nuint256 storage\ntests/contract_testcases/solana/returns/return_err_03.sol:5:25-28"]
+	storage_load_10 [label="storage load uint256\ntests/contract_testcases/solana/returns/return_err_03.sol:5:17-39"]
+	storage_var_11 [label="storage variable\nfoo.val\nuint256 storage\ntests/contract_testcases/solana/returns/return_err_03.sol:5:30-33"]
+	storage_load_12 [label="storage load uint256\ntests/contract_testcases/solana/returns/return_err_03.sol:5:17-39"]
+	storage_var_13 [label="storage variable\nfoo.val\nuint256 storage\ntests/contract_testcases/solana/returns/return_err_03.sol:5:35-38"]
+	get [label="function get\ncontract: foo\ntests/contract_testcases/solana/returns/return_err_03.sol:8:13-34\nsignature get()\nvisibility public\nmutability nonpayable"]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/solana/returns/return_err_03.sol:2:9-22"]
+	diagnostic_17 [label="function has no return values\nlevel Error\ntests/contract_testcases/solana/returns/return_err_03.sol:9:17-27"]
+	contracts -> contract
+	contract -> var [label="variable"]
+	var -> number_literal [label="initializer"]
+	contract -> f [label="function"]
+	f -> returns [label="returns"]
+	f -> return [label="body"]
+	return -> list [label="expr"]
+	list -> storage_load [label="entry #0"]
+	storage_load -> storage_var [label="expr"]
+	list -> storage_load_10 [label="entry #1"]
+	storage_load_10 -> storage_var_11 [label="expr"]
+	list -> storage_load_12 [label="entry #2"]
+	storage_load_12 -> storage_var_13 [label="expr"]
+	contract -> get [label="function"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_17 [label="Error"]
+}

+ 11 - 0
tests/contract_testcases/solana/returns/return_err_03.sol

@@ -0,0 +1,11 @@
+
+        contract foo {
+            uint private val = 0;
+            function f() public returns (uint, uint, uint) {
+                return (val, val, val);
+            }
+
+            function get() public {
+                return f();
+            }
+        }

+ 12 - 0
tests/contract_testcases/solana/returns/return_err_04.dot

@@ -0,0 +1,12 @@
+strict digraph "tests/contract_testcases/solana/returns/return_err_04.sol" {
+	contract [label="contract foo\ntests/contract_testcases/solana/returns/return_err_04.sol:2:9-22"]
+	f [label="function f\ncontract: foo\ntests/contract_testcases/solana/returns/return_err_04.sol:3:13-59\nsignature f()\nvisibility public\nmutability nonpayable"]
+	returns [label="returns\nuint256 \nuint256 \nuint256 "]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/solana/returns/return_err_04.sol:2:9-22"]
+	diagnostic_6 [label="incorrect number of return values, expected 3 but got 1\nlevel Error\ntests/contract_testcases/solana/returns/return_err_04.sol:5:17-31"]
+	contracts -> contract
+	contract -> f [label="function"]
+	f -> returns [label="returns"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_6 [label="Error"]
+}

+ 7 - 0
tests/contract_testcases/solana/returns/return_err_04.sol

@@ -0,0 +1,7 @@
+
+        contract foo {
+            function f() public returns (uint, uint, uint) {
+                int a = 43;
+                return uint(a);
+            }
+        }

+ 8 - 0
tests/contract_testcases/substrate/arrays/array_dimensions.dot

@@ -0,0 +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-22"]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/substrate/arrays/array_dimensions.sol:2:9-22"]
+	diagnostic_5 [label="zero size array not permitted\nlevel Error\ntests/contract_testcases/substrate/arrays/array_dimensions.sol:3:21-22"]
+	contracts -> contract
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_5 [label="Error"]
+}

+ 4 - 0
tests/contract_testcases/substrate/arrays/array_dimensions.sol

@@ -0,0 +1,4 @@
+
+        contract foo {
+            bool[10 - 10] x;
+        }

+ 8 - 0
tests/contract_testcases/substrate/arrays/array_dimensions_01.dot

@@ -0,0 +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-22"]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/substrate/arrays/array_dimensions_01.sol:2:9-22"]
+	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-19"]
+	contracts -> contract
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_5 [label="Error"]
+}

+ 4 - 0
tests/contract_testcases/substrate/arrays/array_dimensions_01.sol

@@ -0,0 +1,4 @@
+
+        contract foo {
+            bool[-10 + 10] x;
+        }

+ 8 - 0
tests/contract_testcases/substrate/arrays/array_dimensions_02.dot

@@ -0,0 +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-22"]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/substrate/arrays/array_dimensions_02.sol:2:9-22"]
+	diagnostic_5 [label="zero size array not permitted\nlevel Error\ntests/contract_testcases/substrate/arrays/array_dimensions_02.sol:3:20-21"]
+	contracts -> contract
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_5 [label="Error"]
+}

+ 4 - 0
tests/contract_testcases/substrate/arrays/array_dimensions_02.sol

@@ -0,0 +1,4 @@
+
+        contract foo {
+            bool[1 / 10] x;
+        }

+ 10 - 0
tests/contract_testcases/substrate/arrays/array_dimensions_03.dot

@@ -0,0 +1,10 @@
+strict digraph "tests/contract_testcases/substrate/arrays/array_dimensions_03.sol" {
+	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-22"]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/substrate/arrays/array_dimensions_03.sol:2:9-22"]
+	diagnostic_7 [label="divide by zero\nlevel Error\ntests/contract_testcases/substrate/arrays/array_dimensions_03.sol:4:17-18"]
+	enums -> e
+	contracts -> contract
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_7 [label="Error"]
+}

+ 5 - 0
tests/contract_testcases/substrate/arrays/array_dimensions_03.sol

@@ -0,0 +1,5 @@
+
+        contract foo {
+            enum e { e1, e2, e3 }
+            e[1 / 0] x;
+        }

+ 10 - 0
tests/contract_testcases/substrate/arrays/array_dimensions_04.dot

@@ -0,0 +1,10 @@
+strict digraph "tests/contract_testcases/substrate/arrays/array_dimensions_04.sol" {
+	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-22"]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/substrate/arrays/array_dimensions_04.sol:2:9-22"]
+	diagnostic_7 [label="divide by zero\nlevel Error\ntests/contract_testcases/substrate/arrays/array_dimensions_04.sol:6:19-20"]
+	structs -> bar
+	contracts -> contract
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_7 [label="Error"]
+}

+ 7 - 0
tests/contract_testcases/substrate/arrays/array_dimensions_04.sol

@@ -0,0 +1,7 @@
+
+        contract foo {
+            struct bar {
+                int32 x;
+            }
+            bar[1 % 0] x;
+        }

+ 8 - 0
tests/contract_testcases/substrate/arrays/data_locations.dot

@@ -0,0 +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-22"]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/substrate/arrays/data_locations.sol:2:9-22"]
+	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"]
+	contracts -> contract
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_5 [label="Error"]
+}

+ 5 - 0
tests/contract_testcases/substrate/arrays/data_locations.sol

@@ -0,0 +1,5 @@
+
+        contract foo {
+            function bar(uint storage) public returns () {
+            }
+        }

+ 8 - 0
tests/contract_testcases/substrate/arrays/data_locations_01.dot

@@ -0,0 +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-22"]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/substrate/arrays/data_locations_01.sol:2:9-22"]
+	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"]
+	contracts -> contract
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_5 [label="Error"]
+}

+ 5 - 0
tests/contract_testcases/substrate/arrays/data_locations_01.sol

@@ -0,0 +1,5 @@
+
+        contract foo {
+            function bar(uint calldata x) public returns () {
+            }
+        }

+ 10 - 0
tests/contract_testcases/substrate/arrays/data_locations_02.dot

@@ -0,0 +1,10 @@
+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-22"]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/substrate/arrays/data_locations_02.sol:2:9-22"]
+	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"]
+	enums -> foo2
+	contracts -> contract
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_7 [label="Error"]
+}

部分文件因为文件数量过多而无法显示