Selaa lähdekoodia

Delay resolving on contract variable initializers

The initializer to contract variable may only be done once all the base
contract functions are resolved, as the initializer might be reference to
a function in base contract, for example:

    contract b {
        function testPtr(int a) public pure returns (int) {
            return a/2;
        }
    }

    contract testing is b {
        function(int) external pure returns (int) sfPtr = this.testPtr;
    }

Note this also fixes code like:

    contract test {
        uint x = y + 102;
	uint y = 102;
    }

Fixes #762

Signed-off-by: Sean Young <sean@mess.org>
Sean Young 3 vuotta sitten
vanhempi
sitoutus
db3755c08a
25 muutettua tiedostoa jossa 321 lisäystä ja 144 poistoa
  1. 41 12
      src/sema/contracts.rs
  2. 2 2
      src/sema/expression.rs
  3. 170 87
      src/sema/variables.rs
  4. 44 0
      tests/contract_testcases/solana/contract_var_base_function_init.dot
  5. 10 0
      tests/contract_testcases/solana/contract_var_base_function_init.sol
  6. 1 1
      tests/contract_testcases/substrate/primitives/address.dot
  7. 1 1
      tests/contract_testcases/substrate/primitives/address_01.dot
  8. 1 1
      tests/contract_testcases/substrate/primitives/address_02.dot
  9. 1 1
      tests/contract_testcases/substrate/primitives/address_03.dot
  10. 1 1
      tests/contract_testcases/substrate/primitives/address_04.dot
  11. 1 1
      tests/contract_testcases/substrate/primitives/address_09.dot
  12. 1 1
      tests/contract_testcases/substrate/primitives/test_literal_overflow.dot
  13. 1 1
      tests/contract_testcases/substrate/primitives/test_literal_overflow_01.dot
  14. 1 1
      tests/contract_testcases/substrate/primitives/test_literal_overflow_02.dot
  15. 1 1
      tests/contract_testcases/substrate/primitives/test_literal_overflow_03.dot
  16. 1 1
      tests/contract_testcases/substrate/primitives/test_literal_overflow_07.dot
  17. 1 1
      tests/contract_testcases/substrate/primitives/test_literal_overflow_08.dot
  18. 1 1
      tests/contract_testcases/substrate/primitives/test_literal_overflow_09.dot
  19. 1 1
      tests/contract_testcases/substrate/primitives/test_literal_overflow_10.dot
  20. 1 1
      tests/contract_testcases/substrate/variables/test_variable_initializer_errors.dot
  21. 1 1
      tests/contract_testcases/substrate/variables/test_variable_initializer_errors_01.dot
  22. 14 10
      tests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.dot
  23. 12 10
      tests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.dot
  24. 9 5
      tests/contract_testcases/substrate/variables/test_variable_initializer_errors_04.dot
  25. 3 2
      tests/contract_testcases/substrate/variables/test_variable_initializer_errors_04.sol

+ 41 - 12
src/sema/contracts.rs

@@ -76,10 +76,10 @@ pub fn resolve(
 
 
     // we need to resolve declarations first, so we call functions/constructors of
     // we need to resolve declarations first, so we call functions/constructors of
     // contracts before they are declared
     // contracts before they are declared
-    let mut function_bodies = Vec::new();
+    let mut delayed: ResolveLater = Default::default();
 
 
     for (contract_no, def) in contracts {
     for (contract_no, def) in contracts {
-        function_bodies.extend(resolve_declarations(def, file_no, *contract_no, ns));
+        resolve_declarations(def, file_no, *contract_no, ns, &mut delayed);
     }
     }
 
 
     // Resolve base contract constructor arguments on contract definition (not constructor definitions)
     // Resolve base contract constructor arguments on contract definition (not constructor definitions)
@@ -90,8 +90,11 @@ pub fn resolve(
         check_inheritance(*contract_no, ns);
         check_inheritance(*contract_no, ns);
     }
     }
 
 
+    // Now we can resolve the initializers
+    variables::resolve_initializers(&delayed.initializers, file_no, ns);
+
     // Now we can resolve the bodies
     // Now we can resolve the bodies
-    if !resolve_bodies(function_bodies, file_no, ns) {
+    if !resolve_bodies(delayed.function_bodies, file_no, ns) {
         // only if we could resolve all the bodies
         // only if we could resolve all the bodies
         for (contract_no, _) in contracts {
         for (contract_no, _) in contracts {
             check_base_args(*contract_no, ns);
             check_base_args(*contract_no, ns);
@@ -733,6 +736,23 @@ fn check_inheritance(contract_no: usize, ns: &mut ast::Namespace) {
     }
     }
 }
 }
 
 
+/// Function body which should be resolved.
+/// List of function_no, contract_no, and function parse tree
+struct DelayedResolveFunction<'a> {
+    function_no: usize,
+    contract_no: usize,
+    function: &'a pt::FunctionDefinition,
+}
+
+#[derive(Default)]
+
+/// Function bodies and state variable initializers can only be resolved once
+/// all function prototypes, bases contracts and state variables are resolved.
+struct ResolveLater<'a> {
+    function_bodies: Vec<DelayedResolveFunction<'a>>,
+    initializers: Vec<variables::DelayedResolveInitializer<'a>>,
+}
+
 /// Resolve functions declarations, constructor declarations, and contract variables
 /// Resolve functions declarations, constructor declarations, and contract variables
 /// This returns a list of function bodies to resolve
 /// This returns a list of function bodies to resolve
 fn resolve_declarations<'a>(
 fn resolve_declarations<'a>(
@@ -740,18 +760,20 @@ fn resolve_declarations<'a>(
     file_no: usize,
     file_no: usize,
     contract_no: usize,
     contract_no: usize,
     ns: &mut ast::Namespace,
     ns: &mut ast::Namespace,
-) -> Vec<(usize, usize, &'a pt::FunctionDefinition)> {
+    delayed: &mut ResolveLater<'a>,
+) {
     ns.diagnostics.push(ast::Diagnostic::debug(
     ns.diagnostics.push(ast::Diagnostic::debug(
         def.loc,
         def.loc,
         format!("found {} ‘{}’", def.ty, def.name.name),
         format!("found {} ‘{}’", def.ty, def.name.name),
     ));
     ));
 
 
     let mut function_no_bodies = Vec::new();
     let mut function_no_bodies = Vec::new();
-    let mut resolve_bodies = Vec::new();
 
 
     // resolve state variables. We may need a constant to resolve the array
     // resolve state variables. We may need a constant to resolve the array
     // dimension of a function argument.
     // dimension of a function argument.
-    variables::contract_variables(def, file_no, contract_no, ns);
+    delayed
+        .initializers
+        .extend(variables::contract_variables(def, file_no, contract_no, ns));
 
 
     // resolve function signatures
     // resolve function signatures
     for parts in &def.parts {
     for parts in &def.parts {
@@ -760,7 +782,11 @@ fn resolve_declarations<'a>(
                 functions::contract_function(def, f, file_no, contract_no, ns)
                 functions::contract_function(def, f, file_no, contract_no, ns)
             {
             {
                 if f.body.is_some() {
                 if f.body.is_some() {
-                    resolve_bodies.push((contract_no, function_no, f.as_ref()));
+                    delayed.function_bodies.push(DelayedResolveFunction {
+                        contract_no,
+                        function_no,
+                        function: f.as_ref(),
+                    });
                 } else {
                 } else {
                     function_no_bodies.push(function_no);
                     function_no_bodies.push(function_no);
                 }
                 }
@@ -791,8 +817,6 @@ fn resolve_declarations<'a>(
                 ));
                 ));
         }
         }
     }
     }
-
-    resolve_bodies
 }
 }
 
 
 /// Resolve the using declarations in a contract
 /// Resolve the using declarations in a contract
@@ -863,14 +887,19 @@ fn resolve_using(
 
 
 /// Resolve contract functions bodies
 /// Resolve contract functions bodies
 fn resolve_bodies(
 fn resolve_bodies(
-    bodies: Vec<(usize, usize, &pt::FunctionDefinition)>,
+    bodies: Vec<DelayedResolveFunction>,
     file_no: usize,
     file_no: usize,
     ns: &mut ast::Namespace,
     ns: &mut ast::Namespace,
 ) -> bool {
 ) -> bool {
     let mut broken = false;
     let mut broken = false;
 
 
-    for (contract_no, function_no, def) in bodies {
-        if statements::resolve_function_body(def, file_no, Some(contract_no), function_no, ns)
+    for DelayedResolveFunction {
+        contract_no,
+        function_no,
+        function,
+    } in bodies
+    {
+        if statements::resolve_function_body(function, file_no, Some(contract_no), function_no, ns)
             .is_err()
             .is_err()
         {
         {
             broken = true;
             broken = true;

+ 2 - 2
src/sema/expression.rs

@@ -4203,7 +4203,7 @@ fn member_access(
                 let mut name_matches = 0;
                 let mut name_matches = 0;
                 let mut expr = Err(());
                 let mut expr = Err(());
 
 
-                for function_no in &ns.contracts[call_contract_no].functions {
+                for function_no in ns.contracts[call_contract_no].all_functions.keys() {
                     let func = &ns.functions[*function_no];
                     let func = &ns.functions[*function_no];
 
 
                     if func.name != id.name || func.ty != pt::FunctionTy::Function {
                     if func.name != id.name || func.ty != pt::FunctionTy::Function {
@@ -4457,7 +4457,7 @@ fn member_access(
             let mut name_matches = 0;
             let mut name_matches = 0;
             let mut ext_expr = Err(());
             let mut ext_expr = Err(());
 
 
-            for function_no in &ns.contracts[ref_contract_no].functions {
+            for function_no in ns.contracts[ref_contract_no].all_functions.keys() {
                 let func = &ns.functions[*function_no];
                 let func = &ns.functions[*function_no];
 
 
                 if func.name != id.name || func.ty != pt::FunctionTy::Function || !func.is_public()
                 if func.name != id.name || func.ty != pt::FunctionTy::Function || !func.is_public()

+ 170 - 87
src/sema/variables.rs

@@ -10,31 +10,45 @@ use super::{
 };
 };
 use crate::parser::pt::{self, CodeLocation, OptionalCodeLocation};
 use crate::parser::pt::{self, CodeLocation, OptionalCodeLocation};
 
 
-pub fn contract_variables(
-    def: &pt::ContractDefinition,
+pub struct DelayedResolveInitializer<'a> {
+    var_no: usize,
+    contract_no: usize,
+    initializer: &'a pt::Expression,
+}
+
+pub fn contract_variables<'a>(
+    def: &'a pt::ContractDefinition,
     file_no: usize,
     file_no: usize,
     contract_no: usize,
     contract_no: usize,
     ns: &mut Namespace,
     ns: &mut Namespace,
-) {
+) -> Vec<DelayedResolveInitializer<'a>> {
     let mut symtable = Symtable::new();
     let mut symtable = Symtable::new();
+    let mut delayed = Vec::new();
 
 
     for parts in &def.parts {
     for parts in &def.parts {
         if let pt::ContractPart::VariableDefinition(ref s) = parts {
         if let pt::ContractPart::VariableDefinition(ref s) = parts {
-            variable_decl(Some(def), s, file_no, Some(contract_no), ns, &mut symtable);
+            if let Some(delay) =
+                variable_decl(Some(def), s, file_no, Some(contract_no), ns, &mut symtable)
+            {
+                delayed.push(delay);
+            }
         }
         }
     }
     }
+
+    delayed
 }
 }
 
 
-pub fn variable_decl(
+pub fn variable_decl<'a>(
     contract: Option<&pt::ContractDefinition>,
     contract: Option<&pt::ContractDefinition>,
-    s: &pt::VariableDefinition,
+    def: &'a pt::VariableDefinition,
     file_no: usize,
     file_no: usize,
     contract_no: Option<usize>,
     contract_no: Option<usize>,
     ns: &mut Namespace,
     ns: &mut Namespace,
     symtable: &mut Symtable,
     symtable: &mut Symtable,
-) {
-    let mut attrs = s.attrs.clone();
-    let mut ty = s.ty.clone();
+) -> Option<DelayedResolveInitializer<'a>> {
+    let mut attrs = def.attrs.clone();
+    let mut ty = def.ty.clone();
+    let mut ret = None;
 
 
     // For function types, the parser adds the attributes incl visibility to the type,
     // For function types, the parser adds the attributes incl visibility to the type,
     // not the pt::VariableDefinition attrs. We need to chomp off the visibility
     // not the pt::VariableDefinition attrs. We need to chomp off the visibility
@@ -66,7 +80,7 @@ pub fn variable_decl(
         Ok(s) => s,
         Ok(s) => s,
         Err(()) => {
         Err(()) => {
             ns.diagnostics.extend(diagnostics);
             ns.diagnostics.extend(diagnostics);
-            return;
+            return None;
         }
         }
     };
     };
 
 
@@ -113,14 +127,14 @@ pub fn variable_decl(
                     v.loc().unwrap(),
                     v.loc().unwrap(),
                     format!("‘{}’: global variable cannot have visibility specifier", v),
                     format!("‘{}’: global variable cannot have visibility specifier", v),
                 ));
                 ));
-                return;
+                return None;
             }
             }
             pt::VariableAttribute::Visibility(pt::Visibility::External(loc)) => {
             pt::VariableAttribute::Visibility(pt::Visibility::External(loc)) => {
                 ns.diagnostics.push(Diagnostic::error(
                 ns.diagnostics.push(Diagnostic::error(
                     loc.unwrap(),
                     loc.unwrap(),
                     "variable cannot be declared external".to_string(),
                     "variable cannot be declared external".to_string(),
                 ));
                 ));
-                return;
+                return None;
             }
             }
             pt::VariableAttribute::Visibility(v) => {
             pt::VariableAttribute::Visibility(v) => {
                 if let Some(e) = &visibility {
                 if let Some(e) = &visibility {
@@ -130,7 +144,7 @@ pub fn variable_decl(
                         e.loc().unwrap(),
                         e.loc().unwrap(),
                         format!("location of previous declaration of `{}'", e),
                         format!("location of previous declaration of `{}'", e),
                     ));
                     ));
-                    return;
+                    return None;
                 }
                 }
 
 
                 visibility = Some(v.clone());
                 visibility = Some(v.clone());
@@ -150,7 +164,7 @@ pub fn variable_decl(
 
 
     let visibility = match visibility {
     let visibility = match visibility {
         Some(v) => v,
         Some(v) => v,
-        None => pt::Visibility::Internal(Some(s.ty.loc())),
+        None => pt::Visibility::Internal(Some(def.ty.loc())),
     };
     };
 
 
     if let pt::Visibility::Public(_) = &visibility {
     if let pt::Visibility::Public(_) = &visibility {
@@ -163,33 +177,33 @@ pub fn variable_decl(
         has_override = None;
         has_override = None;
     }
     }
 
 
-    if let Some(def) = contract {
-        if matches!(def.ty, pt::ContractTy::Interface(_))
-            || (matches!(def.ty, pt::ContractTy::Library(_)) && !constant)
+    if let Some(contract) = contract {
+        if matches!(contract.ty, pt::ContractTy::Interface(_))
+            || (matches!(contract.ty, pt::ContractTy::Library(_)) && !constant)
         {
         {
             ns.diagnostics.push(Diagnostic::error(
             ns.diagnostics.push(Diagnostic::error(
-                s.loc,
+                def.loc,
                 format!(
                 format!(
                     "{} ‘{}’ is not allowed to have contract variable ‘{}’",
                     "{} ‘{}’ is not allowed to have contract variable ‘{}’",
-                    def.ty, def.name.name, s.name.name
+                    contract.ty, contract.name.name, def.name.name
                 ),
                 ),
             ));
             ));
-            return;
+            return None;
         }
         }
     } else {
     } else {
         if !constant {
         if !constant {
             ns.diagnostics.push(Diagnostic::error(
             ns.diagnostics.push(Diagnostic::error(
-                s.ty.loc(),
+                def.ty.loc(),
                 "global variable must be constant".to_string(),
                 "global variable must be constant".to_string(),
             ));
             ));
-            return;
+            return None;
         }
         }
         if ty.contains_internal_function(ns) {
         if ty.contains_internal_function(ns) {
             ns.diagnostics.push(Diagnostic::error(
             ns.diagnostics.push(Diagnostic::error(
-                s.ty.loc(),
+                def.ty.loc(),
                 "global variable cannot be of type internal function".to_string(),
                 "global variable cannot be of type internal function".to_string(),
             ));
             ));
-            return;
+            return None;
         }
         }
     }
     }
 
 
@@ -200,66 +214,70 @@ pub fn variable_decl(
         )
         )
     {
     {
         ns.diagnostics.push(Diagnostic::error(
         ns.diagnostics.push(Diagnostic::error(
-            s.ty.loc(),
+            def.ty.loc(),
             format!(
             format!(
                 "variable of type internal function cannot be ‘{}’",
                 "variable of type internal function cannot be ‘{}’",
                 visibility
                 visibility
             ),
             ),
         ));
         ));
-        return;
+        return None;
     } else if let Some(ty) = ty.contains_builtins(ns, BuiltinStruct::AccountInfo) {
     } else if let Some(ty) = ty.contains_builtins(ns, BuiltinStruct::AccountInfo) {
         let message = format!("variable cannot be of builtin type ‘{}’", ty.to_string(ns));
         let message = format!("variable cannot be of builtin type ‘{}’", ty.to_string(ns));
-        ns.diagnostics.push(Diagnostic::error(s.ty.loc(), message));
-        return;
+        ns.diagnostics
+            .push(Diagnostic::error(def.ty.loc(), message));
+        return None;
     } else if let Some(ty) = ty.contains_builtins(ns, BuiltinStruct::AccountMeta) {
     } else if let Some(ty) = ty.contains_builtins(ns, BuiltinStruct::AccountMeta) {
         let message = format!("variable cannot be of builtin type ‘{}’", ty.to_string(ns));
         let message = format!("variable cannot be of builtin type ‘{}’", ty.to_string(ns));
-        ns.diagnostics.push(Diagnostic::error(s.ty.loc(), message));
-        return;
+        ns.diagnostics
+            .push(Diagnostic::error(def.ty.loc(), message));
+        return None;
     }
     }
 
 
-    let initializer = if let Some(initializer) = &s.initializer {
-        let mut diagnostics = Vec::new();
-        let context = ExprContext {
-            file_no,
-            unchecked: false,
-            contract_no,
-            function_no: None,
-            constant,
-            lvalue: false,
-            yul_function: false,
-        };
+    let initializer = if constant {
+        if let Some(initializer) = &def.initializer {
+            let mut diagnostics = Vec::new();
+            let context = ExprContext {
+                file_no,
+                unchecked: false,
+                contract_no,
+                function_no: None,
+                constant,
+                lvalue: false,
+                yul_function: false,
+            };
 
 
-        match expression(
-            initializer,
-            &context,
-            ns,
-            symtable,
-            &mut diagnostics,
-            ResolveTo::Type(&ty),
-        ) {
-            Ok(res) => {
-                // implicitly conversion to correct ty
-                match res.cast(&s.loc, &ty, true, ns, &mut diagnostics) {
-                    Ok(res) => Some(res),
-                    Err(_) => {
-                        ns.diagnostics.extend(diagnostics);
-                        None
+            match expression(
+                initializer,
+                &context,
+                ns,
+                symtable,
+                &mut diagnostics,
+                ResolveTo::Type(&ty),
+            ) {
+                Ok(res) => {
+                    // implicitly conversion to correct ty
+                    match res.cast(&def.loc, &ty, true, ns, &mut diagnostics) {
+                        Ok(res) => Some(res),
+                        Err(_) => {
+                            ns.diagnostics.extend(diagnostics);
+                            None
+                        }
                     }
                     }
                 }
                 }
+                Err(()) => {
+                    ns.diagnostics.extend(diagnostics);
+                    None
+                }
             }
             }
-            Err(()) => {
-                ns.diagnostics.extend(diagnostics);
-                None
-            }
-        }
-    } else {
-        if constant {
+        } else {
             ns.diagnostics.push(Diagnostic::decl_error(
             ns.diagnostics.push(Diagnostic::decl_error(
-                s.loc,
+                def.loc,
                 "missing initializer for constant".to_string(),
                 "missing initializer for constant".to_string(),
             ));
             ));
-        }
 
 
+            None
+        }
+    } else {
         None
         None
     };
     };
 
 
@@ -274,13 +292,13 @@ pub fn variable_decl(
     };
     };
 
 
     let tags = resolve_tags(
     let tags = resolve_tags(
-        s.name.loc.file_no(),
+        def.name.loc.file_no(),
         if contract_no.is_none() {
         if contract_no.is_none() {
             "global variable"
             "global variable"
         } else {
         } else {
             "state variable"
             "state variable"
         },
         },
-        &s.doc,
+        &def.doc,
         None,
         None,
         None,
         None,
         Some(&bases),
         Some(&bases),
@@ -288,37 +306,47 @@ pub fn variable_decl(
     );
     );
 
 
     let sdecl = Variable {
     let sdecl = Variable {
-        name: s.name.name.to_string(),
-        loc: s.loc,
+        name: def.name.name.to_string(),
+        loc: def.loc,
         tags,
         tags,
         visibility: visibility.clone(),
         visibility: visibility.clone(),
         ty: ty.clone(),
         ty: ty.clone(),
         constant,
         constant,
         immutable: has_immutable.is_some(),
         immutable: has_immutable.is_some(),
-        assigned: initializer.is_some(),
+        assigned: def.initializer.is_some(),
         initializer,
         initializer,
         read: matches!(visibility, pt::Visibility::Public(_)),
         read: matches!(visibility, pt::Visibility::Public(_)),
     };
     };
 
 
-    let pos = if let Some(contract_no) = contract_no {
-        let pos = ns.contracts[contract_no].variables.len();
+    let var_no = if let Some(contract_no) = contract_no {
+        let var_no = ns.contracts[contract_no].variables.len();
 
 
         ns.contracts[contract_no].variables.push(sdecl);
         ns.contracts[contract_no].variables.push(sdecl);
 
 
-        pos
+        if !constant {
+            if let Some(initializer) = &def.initializer {
+                ret = Some(DelayedResolveInitializer {
+                    var_no,
+                    contract_no,
+                    initializer,
+                });
+            }
+        }
+
+        var_no
     } else {
     } else {
-        let pos = ns.constants.len();
+        let var_no = ns.constants.len();
 
 
         ns.constants.push(sdecl);
         ns.constants.push(sdecl);
 
 
-        pos
+        var_no
     };
     };
 
 
     let success = ns.add_symbol(
     let success = ns.add_symbol(
         file_no,
         file_no,
         contract_no,
         contract_no,
-        &s.name,
-        Symbol::Variable(s.loc, contract_no, pos),
+        &def.name,
+        Symbol::Variable(def.loc, contract_no, var_no),
     );
     );
 
 
     // for public variables in contracts, create an accessor function
     // for public variables in contracts, create an accessor function
@@ -326,13 +354,18 @@ pub fn variable_decl(
         if let Some(contract_no) = contract_no {
         if let Some(contract_no) = contract_no {
             // The accessor function returns the value of the storage variable, constant or not.
             // The accessor function returns the value of the storage variable, constant or not.
             let mut expr = if constant {
             let mut expr = if constant {
-                Expression::ConstantVariable(pt::Loc::Implicit, ty.clone(), Some(contract_no), pos)
+                Expression::ConstantVariable(
+                    pt::Loc::Implicit,
+                    ty.clone(),
+                    Some(contract_no),
+                    var_no,
+                )
             } else {
             } else {
                 Expression::StorageVariable(
                 Expression::StorageVariable(
                     pt::Loc::Implicit,
                     pt::Loc::Implicit,
                     Type::StorageRef(false, Box::new(ty.clone())),
                     Type::StorageRef(false, Box::new(ty.clone())),
                     contract_no,
                     contract_no,
-                    pos,
+                    var_no,
                 )
                 )
             };
             };
 
 
@@ -345,26 +378,26 @@ pub fn variable_decl(
             if ty.contains_mapping(ns) {
             if ty.contains_mapping(ns) {
                 // we can't return a mapping
                 // we can't return a mapping
                 ns.diagnostics.push(Diagnostic::decl_error(
                 ns.diagnostics.push(Diagnostic::decl_error(
-                    s.loc,
+                    def.loc,
                     "mapping in a struct variable cannot be public".to_string(),
                     "mapping in a struct variable cannot be public".to_string(),
                 ));
                 ));
             }
             }
 
 
             let mut func = Function::new(
             let mut func = Function::new(
-                s.name.loc,
-                s.name.name.to_owned(),
+                def.name.loc,
+                def.name.name.to_owned(),
                 Some(contract_no),
                 Some(contract_no),
                 Vec::new(),
                 Vec::new(),
                 pt::FunctionTy::Function,
                 pt::FunctionTy::Function,
                 // accessors for constant variables have view mutability
                 // accessors for constant variables have view mutability
-                Some(pt::Mutability::View(s.name.loc)),
+                Some(pt::Mutability::View(def.name.loc)),
                 visibility,
                 visibility,
                 params,
                 params,
                 vec![Parameter {
                 vec![Parameter {
                     id: None,
                     id: None,
-                    loc: s.name.loc,
+                    loc: def.name.loc,
                     ty: ty.clone(),
                     ty: ty.clone(),
-                    ty_loc: Some(s.ty.loc()),
+                    ty_loc: Some(def.ty.loc()),
                     indexed: false,
                     indexed: false,
                     readonly: false,
                     readonly: false,
                 }],
                 }],
@@ -393,14 +426,20 @@ pub fn variable_decl(
             ns.contracts[contract_no].functions.push(func_no);
             ns.contracts[contract_no].functions.push(func_no);
 
 
             // we already have a symbol for
             // we already have a symbol for
-            let symbol = Symbol::Function(vec![(s.loc, func_no)]);
+            let symbol = Symbol::Function(vec![(def.loc, func_no)]);
 
 
             ns.function_symbols.insert(
             ns.function_symbols.insert(
-                (s.loc.file_no(), Some(contract_no), s.name.name.to_owned()),
+                (
+                    def.loc.file_no(),
+                    Some(contract_no),
+                    def.name.name.to_owned(),
+                ),
                 symbol,
                 symbol,
             );
             );
         }
         }
     }
     }
+
+    ret
 }
 }
 
 
 /// For accessor functions, create the parameter list and the return expression
 /// For accessor functions, create the parameter list and the return expression
@@ -506,3 +545,47 @@ fn collect_parameters<'a>(
         _ => ty,
         _ => ty,
     }
     }
 }
 }
+
+pub fn resolve_initializers(
+    initializers: &[DelayedResolveInitializer],
+    file_no: usize,
+    ns: &mut Namespace,
+) {
+    let mut symtable = Symtable::new();
+    let mut diagnostics = Vec::new();
+
+    for DelayedResolveInitializer {
+        var_no,
+        contract_no,
+        initializer,
+    } in initializers
+    {
+        let var = &ns.contracts[*contract_no].variables[*var_no];
+        let ty = var.ty.clone();
+
+        let context = ExprContext {
+            file_no,
+            unchecked: false,
+            contract_no: Some(*contract_no),
+            function_no: None,
+            constant: false,
+            lvalue: false,
+            yul_function: false,
+        };
+
+        if let Ok(res) = expression(
+            initializer,
+            &context,
+            ns,
+            &mut symtable,
+            &mut diagnostics,
+            ResolveTo::Type(&ty),
+        ) {
+            if let Ok(res) = res.cast(&initializer.loc(), &ty, true, ns, &mut diagnostics) {
+                ns.contracts[*contract_no].variables[*var_no].initializer = Some(res);
+            }
+        }
+    }
+
+    ns.diagnostics.extend(diagnostics);
+}

+ 44 - 0
tests/contract_testcases/solana/contract_var_base_function_init.dot

@@ -0,0 +1,44 @@
+strict digraph "tests/contract_testcases/solana/contract_var_base_function_init.sol" {
+	contract [label="contract b\ntests/contract_testcases/solana/contract_var_base_function_init.sol:1:1-12"]
+	testPtr [label="function testPtr\ncontract: b\ntests/contract_testcases/solana/contract_var_base_function_init.sol:2:5-54\nsignature testPtr(int256)\nvisibility public\nmutability pure"]
+	parameters [label="parameters\nint256 a"]
+	returns [label="returns\nint256 "]
+	return [label="return\ntests/contract_testcases/solana/contract_var_base_function_init.sol:3:9-19"]
+	divide [label="divide\nint256\ntests/contract_testcases/solana/contract_var_base_function_init.sol:3:17-18"]
+	variable [label="variable: a\nint256\ntests/contract_testcases/solana/contract_var_base_function_init.sol:3:16-17"]
+	number_literal [label="int256 literal: 2\ntests/contract_testcases/solana/contract_var_base_function_init.sol:3:18-19"]
+	contract_10 [label="contract testing\ntests/contract_testcases/solana/contract_var_base_function_init.sol:6:1-7:22"]
+	base [label="base b\ntests/contract_testcases/solana/contract_var_base_function_init.sol:7:21-22"]
+	var [label="variable sfPtr\nvisibility internal\ntests/contract_testcases/solana/contract_var_base_function_init.sol:8:5-67"]
+	cast [label="cast function(int256) external pure returns (int256)\ntests/contract_testcases/solana/contract_var_base_function_init.sol:8:55-67"]
+	external_function [label="function(int256) external pure returns (int256)\nb.testPtr\ntests/contract_testcases/solana/contract_var_base_function_init.sol:8:60-67"]
+	builtins [label="builtin GetAddress\ntests/contract_testcases/solana/contract_var_base_function_init.sol:8:55-59"]
+	var_16 [label="variable sgPtr\nvisibility internal\ntests/contract_testcases/solana/contract_var_base_function_init.sol:9:5-62"]
+	cast_17 [label="cast function(int256) internal pure returns (int256)\ntests/contract_testcases/solana/contract_var_base_function_init.sol:9:55-62"]
+	internal_function [label="function(int256) internal pure returns (int256)\nb.testPtr\ntests/contract_testcases/solana/contract_var_base_function_init.sol:9:55-62"]
+	diagnostic [label="found contract ‘b’\nlevel Debug\ntests/contract_testcases/solana/contract_var_base_function_init.sol:1:1-12"]
+	diagnostic_21 [label="found contract ‘testing’\nlevel Debug\ntests/contract_testcases/solana/contract_var_base_function_init.sol:6:1-7:22"]
+	diagnostic_22 [label="storage variable ‘sfPtr‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/solana/contract_var_base_function_init.sol:8:5-67"]
+	diagnostic_23 [label="storage variable ‘sgPtr‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/solana/contract_var_base_function_init.sol:9:5-62"]
+	contracts -> contract
+	contract -> testPtr [label="function"]
+	testPtr -> parameters [label="parameters"]
+	testPtr -> returns [label="returns"]
+	testPtr -> return [label="body"]
+	return -> divide [label="expr"]
+	divide -> variable [label="left"]
+	divide -> number_literal [label="right"]
+	contracts -> contract_10
+	contract_10 -> base [label="base"]
+	contract_10 -> var [label="variable"]
+	var -> cast [label="initializer"]
+	cast -> external_function [label="expr"]
+	external_function -> builtins [label="address"]
+	contract_10 -> var_16 [label="variable"]
+	var_16 -> cast_17 [label="initializer"]
+	cast_17 -> internal_function [label="expr"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_21 [label="Debug"]
+	diagnostics -> diagnostic_22 [label="Warning"]
+	diagnostics -> diagnostic_23 [label="Warning"]
+}

+ 10 - 0
tests/contract_testcases/solana/contract_var_base_function_init.sol

@@ -0,0 +1,10 @@
+contract b {
+    function testPtr(int a) public pure returns (int) {
+        return a/2;
+    }
+}
+
+contract testing is b {
+    function(int) external pure returns (int) sfPtr = this.testPtr;
+    function(int) internal pure returns (int) sgPtr = testPtr;
+}

+ 1 - 1
tests/contract_testcases/substrate/primitives/address.dot

@@ -3,7 +3,7 @@ strict digraph "tests/contract_testcases/substrate/primitives/address.sol" {
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/address.sol:2:13-51"]
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/address.sol:2:13-51"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/address.sol:1:1-15"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/address.sol:1:1-15"]
 	diagnostic_6 [label="expected ‘address’, found integer\nlevel Error\ntests/contract_testcases/substrate/primitives/address.sol:2:28-51"]
 	diagnostic_6 [label="expected ‘address’, found integer\nlevel Error\ntests/contract_testcases/substrate/primitives/address.sol:2:28-51"]
-	diagnostic_7 [label="storage variable ‘foo‘ has never been used\nlevel Warning\ntests/contract_testcases/substrate/primitives/address.sol:2:13-51"]
+	diagnostic_7 [label="storage variable ‘foo‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/primitives/address.sol:2:13-51"]
 	contracts -> contract
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> var [label="variable"]
 	diagnostics -> diagnostic [label="Debug"]
 	diagnostics -> diagnostic [label="Debug"]

+ 1 - 1
tests/contract_testcases/substrate/primitives/address_01.dot

@@ -3,7 +3,7 @@ strict digraph "tests/contract_testcases/substrate/primitives/address_01.sol" {
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/address_01.sol:2:13-93"]
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/address_01.sol:2:13-93"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/address_01.sol:1:1-15"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/address_01.sol:1:1-15"]
 	diagnostic_6 [label="expected ‘address’, found integer\nlevel Error\ntests/contract_testcases/substrate/primitives/address_01.sol:2:27-93"]
 	diagnostic_6 [label="expected ‘address’, found integer\nlevel Error\ntests/contract_testcases/substrate/primitives/address_01.sol:2:27-93"]
-	diagnostic_7 [label="storage variable ‘foo‘ has never been used\nlevel Warning\ntests/contract_testcases/substrate/primitives/address_01.sol:2:13-93"]
+	diagnostic_7 [label="storage variable ‘foo‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/primitives/address_01.sol:2:13-93"]
 	contracts -> contract
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> var [label="variable"]
 	diagnostics -> diagnostic [label="Debug"]
 	diagnostics -> diagnostic [label="Debug"]

+ 1 - 1
tests/contract_testcases/substrate/primitives/address_02.dot

@@ -3,7 +3,7 @@ strict digraph "tests/contract_testcases/substrate/primitives/address_02.sol" {
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/address_02.sol:2:13-83"]
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/address_02.sol:2:13-83"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/address_02.sol:1:1-15"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/address_02.sol:1:1-15"]
 	diagnostic_6 [label="address literal 5GBWmgdFAMqm8ZgAHGobqDqX6tjLxJhv53ygjNtaaAn3sje incorrect length of 34\nlevel Error\ntests/contract_testcases/substrate/primitives/address_02.sol:2:27-83"]
 	diagnostic_6 [label="address literal 5GBWmgdFAMqm8ZgAHGobqDqX6tjLxJhv53ygjNtaaAn3sje incorrect length of 34\nlevel Error\ntests/contract_testcases/substrate/primitives/address_02.sol:2:27-83"]
-	diagnostic_7 [label="storage variable ‘foo‘ has never been used\nlevel Warning\ntests/contract_testcases/substrate/primitives/address_02.sol:2:13-83"]
+	diagnostic_7 [label="storage variable ‘foo‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/primitives/address_02.sol:2:13-83"]
 	contracts -> contract
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> var [label="variable"]
 	diagnostics -> diagnostic [label="Debug"]
 	diagnostics -> diagnostic [label="Debug"]

+ 1 - 1
tests/contract_testcases/substrate/primitives/address_03.dot

@@ -3,7 +3,7 @@ strict digraph "tests/contract_testcases/substrate/primitives/address_03.sol" {
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/address_03.sol:2:13-84"]
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/address_03.sol:2:13-84"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/address_03.sol:1:1-15"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/address_03.sol:1:1-15"]
 	diagnostic_6 [label="address literal 5GBWmgdFAMqm8ZgAHGobqDqX6tjLxJhv53ygjNtaaAn3sj%Z invalid character '%'\nlevel Error\ntests/contract_testcases/substrate/primitives/address_03.sol:2:73"]
 	diagnostic_6 [label="address literal 5GBWmgdFAMqm8ZgAHGobqDqX6tjLxJhv53ygjNtaaAn3sj%Z invalid character '%'\nlevel Error\ntests/contract_testcases/substrate/primitives/address_03.sol:2:73"]
-	diagnostic_7 [label="storage variable ‘foo‘ has never been used\nlevel Warning\ntests/contract_testcases/substrate/primitives/address_03.sol:2:13-84"]
+	diagnostic_7 [label="storage variable ‘foo‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/primitives/address_03.sol:2:13-84"]
 	contracts -> contract
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> var [label="variable"]
 	diagnostics -> diagnostic [label="Debug"]
 	diagnostics -> diagnostic [label="Debug"]

+ 1 - 1
tests/contract_testcases/substrate/primitives/address_04.dot

@@ -3,7 +3,7 @@ strict digraph "tests/contract_testcases/substrate/primitives/address_04.sol" {
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/address_04.sol:2:13-84"]
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/address_04.sol:2:13-84"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/address_04.sol:1:1-15"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/address_04.sol:1:1-15"]
 	diagnostic_6 [label="address literal 5GBWmgdFAMqm8ZgAHGobqDqX6tjLxJhv53ygjNtaaAn3sjZZ hash incorrect checksum\nlevel Error\ntests/contract_testcases/substrate/primitives/address_04.sol:2:27-84"]
 	diagnostic_6 [label="address literal 5GBWmgdFAMqm8ZgAHGobqDqX6tjLxJhv53ygjNtaaAn3sjZZ hash incorrect checksum\nlevel Error\ntests/contract_testcases/substrate/primitives/address_04.sol:2:27-84"]
-	diagnostic_7 [label="storage variable ‘foo‘ has never been used\nlevel Warning\ntests/contract_testcases/substrate/primitives/address_04.sol:2:13-84"]
+	diagnostic_7 [label="storage variable ‘foo‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/primitives/address_04.sol:2:13-84"]
 	contracts -> contract
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> var [label="variable"]
 	diagnostics -> diagnostic [label="Debug"]
 	diagnostics -> diagnostic [label="Debug"]

+ 1 - 1
tests/contract_testcases/substrate/primitives/address_09.dot

@@ -3,7 +3,7 @@ strict digraph "tests/contract_testcases/substrate/primitives/address_09.sol" {
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/address_09.sol:2:13-69"]
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/address_09.sol:2:13-69"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/address_09.sol:1:1-15"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/address_09.sol:1:1-15"]
 	diagnostic_6 [label="ethereum address literal ‘0x5b0Ddf2835f0A76c96D6113D47F6482e51a55487’ not supported on target substrate\nlevel Error\ntests/contract_testcases/substrate/primitives/address_09.sol:2:27-69"]
 	diagnostic_6 [label="ethereum address literal ‘0x5b0Ddf2835f0A76c96D6113D47F6482e51a55487’ not supported on target substrate\nlevel Error\ntests/contract_testcases/substrate/primitives/address_09.sol:2:27-69"]
-	diagnostic_7 [label="storage variable ‘foo‘ has never been used\nlevel Warning\ntests/contract_testcases/substrate/primitives/address_09.sol:2:13-69"]
+	diagnostic_7 [label="storage variable ‘foo‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/primitives/address_09.sol:2:13-69"]
 	contracts -> contract
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> var [label="variable"]
 	diagnostics -> diagnostic [label="Debug"]
 	diagnostics -> diagnostic [label="Debug"]

+ 1 - 1
tests/contract_testcases/substrate/primitives/test_literal_overflow.dot

@@ -3,7 +3,7 @@ strict digraph "tests/contract_testcases/substrate/primitives/test_literal_overf
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/test_literal_overflow.sol:2:13-28"]
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/test_literal_overflow.sol:2:13-28"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/test_literal_overflow.sol:1:1-15"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/test_literal_overflow.sol:1:1-15"]
 	diagnostic_6 [label="literal 300 is too large to fit into type ‘uint8’\nlevel Error\ntests/contract_testcases/substrate/primitives/test_literal_overflow.sol:2:25-28"]
 	diagnostic_6 [label="literal 300 is too large to fit into type ‘uint8’\nlevel Error\ntests/contract_testcases/substrate/primitives/test_literal_overflow.sol:2:25-28"]
-	diagnostic_7 [label="storage variable ‘foo‘ has never been used\nlevel Warning\ntests/contract_testcases/substrate/primitives/test_literal_overflow.sol:2:13-28"]
+	diagnostic_7 [label="storage variable ‘foo‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/primitives/test_literal_overflow.sol:2:13-28"]
 	contracts -> contract
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> var [label="variable"]
 	diagnostics -> diagnostic [label="Debug"]
 	diagnostics -> diagnostic [label="Debug"]

+ 1 - 1
tests/contract_testcases/substrate/primitives/test_literal_overflow_01.dot

@@ -3,7 +3,7 @@ strict digraph "tests/contract_testcases/substrate/primitives/test_literal_overf
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/test_literal_overflow_01.sol:2:13-33"]
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/test_literal_overflow_01.sol:2:13-33"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/test_literal_overflow_01.sol:1:1-15"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/test_literal_overflow_01.sol:1:1-15"]
 	diagnostic_6 [label="literal 65536 is too large to fit into type ‘uint16’\nlevel Error\ntests/contract_testcases/substrate/primitives/test_literal_overflow_01.sol:2:26-33"]
 	diagnostic_6 [label="literal 65536 is too large to fit into type ‘uint16’\nlevel Error\ntests/contract_testcases/substrate/primitives/test_literal_overflow_01.sol:2:26-33"]
-	diagnostic_7 [label="storage variable ‘foo‘ has never been used\nlevel Warning\ntests/contract_testcases/substrate/primitives/test_literal_overflow_01.sol:2:13-33"]
+	diagnostic_7 [label="storage variable ‘foo‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/primitives/test_literal_overflow_01.sol:2:13-33"]
 	contracts -> contract
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> var [label="variable"]
 	diagnostics -> diagnostic [label="Debug"]
 	diagnostics -> diagnostic [label="Debug"]

+ 1 - 1
tests/contract_testcases/substrate/primitives/test_literal_overflow_02.dot

@@ -3,7 +3,7 @@ strict digraph "tests/contract_testcases/substrate/primitives/test_literal_overf
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/test_literal_overflow_02.sol:2:13-29"]
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/test_literal_overflow_02.sol:2:13-29"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/test_literal_overflow_02.sol:1:1-15"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/test_literal_overflow_02.sol:1:1-15"]
 	diagnostic_6 [label="literal 128 is too large to fit into type ‘int8’\nlevel Error\ntests/contract_testcases/substrate/primitives/test_literal_overflow_02.sol:2:24-29"]
 	diagnostic_6 [label="literal 128 is too large to fit into type ‘int8’\nlevel Error\ntests/contract_testcases/substrate/primitives/test_literal_overflow_02.sol:2:24-29"]
-	diagnostic_7 [label="storage variable ‘foo‘ has never been used\nlevel Warning\ntests/contract_testcases/substrate/primitives/test_literal_overflow_02.sol:2:13-29"]
+	diagnostic_7 [label="storage variable ‘foo‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/primitives/test_literal_overflow_02.sol:2:13-29"]
 	contracts -> contract
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> var [label="variable"]
 	diagnostics -> diagnostic [label="Debug"]
 	diagnostics -> diagnostic [label="Debug"]

+ 1 - 1
tests/contract_testcases/substrate/primitives/test_literal_overflow_03.dot

@@ -3,7 +3,7 @@ strict digraph "tests/contract_testcases/substrate/primitives/test_literal_overf
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/test_literal_overflow_03.sol:2:13-28"]
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/test_literal_overflow_03.sol:2:13-28"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/test_literal_overflow_03.sol:1:1-15"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/test_literal_overflow_03.sol:1:1-15"]
 	diagnostic_6 [label="literal -129 is too large to fit into type ‘int8’\nlevel Error\ntests/contract_testcases/substrate/primitives/test_literal_overflow_03.sol:2:24-25"]
 	diagnostic_6 [label="literal -129 is too large to fit into type ‘int8’\nlevel Error\ntests/contract_testcases/substrate/primitives/test_literal_overflow_03.sol:2:24-25"]
-	diagnostic_7 [label="storage variable ‘foo‘ has never been used\nlevel Warning\ntests/contract_testcases/substrate/primitives/test_literal_overflow_03.sol:2:13-28"]
+	diagnostic_7 [label="storage variable ‘foo‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/primitives/test_literal_overflow_03.sol:2:13-28"]
 	contracts -> contract
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> var [label="variable"]
 	diagnostics -> diagnostic [label="Debug"]
 	diagnostics -> diagnostic [label="Debug"]

+ 1 - 1
tests/contract_testcases/substrate/primitives/test_literal_overflow_07.dot

@@ -3,7 +3,7 @@ strict digraph "tests/contract_testcases/substrate/primitives/test_literal_overf
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/test_literal_overflow_07.sol:2:13-30"]
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/test_literal_overflow_07.sol:2:13-30"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/test_literal_overflow_07.sol:1:1-15"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/test_literal_overflow_07.sol:1:1-15"]
 	diagnostic_6 [label="negative literal -130 not allowed for unsigned type ‘uint8’\nlevel Error\ntests/contract_testcases/substrate/primitives/test_literal_overflow_07.sol:2:25-26"]
 	diagnostic_6 [label="negative literal -130 not allowed for unsigned type ‘uint8’\nlevel Error\ntests/contract_testcases/substrate/primitives/test_literal_overflow_07.sol:2:25-26"]
-	diagnostic_7 [label="storage variable ‘foo‘ has never been used\nlevel Warning\ntests/contract_testcases/substrate/primitives/test_literal_overflow_07.sol:2:13-30"]
+	diagnostic_7 [label="storage variable ‘foo‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/primitives/test_literal_overflow_07.sol:2:13-30"]
 	contracts -> contract
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> var [label="variable"]
 	diagnostics -> diagnostic [label="Debug"]
 	diagnostics -> diagnostic [label="Debug"]

+ 1 - 1
tests/contract_testcases/substrate/primitives/test_literal_overflow_08.dot

@@ -3,7 +3,7 @@ strict digraph "tests/contract_testcases/substrate/primitives/test_literal_overf
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/test_literal_overflow_08.sol:2:13-46"]
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/test_literal_overflow_08.sol:2:13-46"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/test_literal_overflow_08.sol:1:1-15"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/test_literal_overflow_08.sol:1:1-15"]
 	diagnostic_6 [label="literal 18446744073709551616 is too large to fit into type ‘int64’\nlevel Error\ntests/contract_testcases/substrate/primitives/test_literal_overflow_08.sol:2:25-46"]
 	diagnostic_6 [label="literal 18446744073709551616 is too large to fit into type ‘int64’\nlevel Error\ntests/contract_testcases/substrate/primitives/test_literal_overflow_08.sol:2:25-46"]
-	diagnostic_7 [label="storage variable ‘foo‘ has never been used\nlevel Warning\ntests/contract_testcases/substrate/primitives/test_literal_overflow_08.sol:2:13-46"]
+	diagnostic_7 [label="storage variable ‘foo‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/primitives/test_literal_overflow_08.sol:2:13-46"]
 	contracts -> contract
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> var [label="variable"]
 	diagnostics -> diagnostic [label="Debug"]
 	diagnostics -> diagnostic [label="Debug"]

+ 1 - 1
tests/contract_testcases/substrate/primitives/test_literal_overflow_09.dot

@@ -3,7 +3,7 @@ strict digraph "tests/contract_testcases/substrate/primitives/test_literal_overf
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/test_literal_overflow_09.sol:2:13-34"]
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/test_literal_overflow_09.sol:2:13-34"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/test_literal_overflow_09.sol:1:1-15"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/test_literal_overflow_09.sol:1:1-15"]
 	diagnostic_6 [label="hex literal 0xf12233 must be 8 digits for type ‘bytes4’\nlevel Error\ntests/contract_testcases/substrate/primitives/test_literal_overflow_09.sol:2:26-34"]
 	diagnostic_6 [label="hex literal 0xf12233 must be 8 digits for type ‘bytes4’\nlevel Error\ntests/contract_testcases/substrate/primitives/test_literal_overflow_09.sol:2:26-34"]
-	diagnostic_7 [label="storage variable ‘foo‘ has never been used\nlevel Warning\ntests/contract_testcases/substrate/primitives/test_literal_overflow_09.sol:2:13-34"]
+	diagnostic_7 [label="storage variable ‘foo‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/primitives/test_literal_overflow_09.sol:2:13-34"]
 	contracts -> contract
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> var [label="variable"]
 	diagnostics -> diagnostic [label="Debug"]
 	diagnostics -> diagnostic [label="Debug"]

+ 1 - 1
tests/contract_testcases/substrate/primitives/test_literal_overflow_10.dot

@@ -3,7 +3,7 @@ strict digraph "tests/contract_testcases/substrate/primitives/test_literal_overf
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/test_literal_overflow_10.sol:2:13-38"]
 	var [label="variable foo\nvisibility internal\ntests/contract_testcases/substrate/primitives/test_literal_overflow_10.sol:2:13-38"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/test_literal_overflow_10.sol:1:1-15"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/primitives/test_literal_overflow_10.sol:1:1-15"]
 	diagnostic_6 [label="hex literal 0x0122334455 must be 8 digits for type ‘bytes4’\nlevel Error\ntests/contract_testcases/substrate/primitives/test_literal_overflow_10.sol:2:26-38"]
 	diagnostic_6 [label="hex literal 0x0122334455 must be 8 digits for type ‘bytes4’\nlevel Error\ntests/contract_testcases/substrate/primitives/test_literal_overflow_10.sol:2:26-38"]
-	diagnostic_7 [label="storage variable ‘foo‘ has never been used\nlevel Warning\ntests/contract_testcases/substrate/primitives/test_literal_overflow_10.sol:2:13-38"]
+	diagnostic_7 [label="storage variable ‘foo‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/primitives/test_literal_overflow_10.sol:2:13-38"]
 	contracts -> contract
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> var [label="variable"]
 	diagnostics -> diagnostic [label="Debug"]
 	diagnostics -> diagnostic [label="Debug"]

+ 1 - 1
tests/contract_testcases/substrate/variables/test_variable_initializer_errors.dot

@@ -6,7 +6,7 @@ strict digraph "tests/contract_testcases/substrate/variables/test_variable_initi
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors.sol:1:1-15"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors.sol:1:1-15"]
 	diagnostic_8 [label="cannot read contract variable ‘x’ in constant expression\nlevel Error\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors.sol:3:31-32"]
 	diagnostic_8 [label="cannot read contract variable ‘x’ in constant expression\nlevel Error\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors.sol:3:31-32"]
 	diagnostic_9 [label="storage variable ‘x‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors.sol:2:13-25"]
 	diagnostic_9 [label="storage variable ‘x‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors.sol:2:13-25"]
-	diagnostic_10 [label="storage variable ‘y‘ has never been used\nlevel Warning\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors.sol:3:13-36"]
+	diagnostic_10 [label="storage variable ‘y‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors.sol:3:13-36"]
 	contracts -> contract
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> var [label="variable"]
 	var -> number_literal [label="initializer"]
 	var -> number_literal [label="initializer"]

+ 1 - 1
tests/contract_testcases/substrate/variables/test_variable_initializer_errors_01.dot

@@ -7,7 +7,7 @@ strict digraph "tests/contract_testcases/substrate/variables/test_variable_initi
 	number_literal [label="uint256 literal: 102\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_01.sol:3:24-27"]
 	number_literal [label="uint256 literal: 102\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_01.sol:3:24-27"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_01.sol:1:1-15"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_01.sol:1:1-15"]
 	diagnostic_9 [label="cannot call function in constant expression\nlevel Error\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_01.sol:5:31-36"]
 	diagnostic_9 [label="cannot call function in constant expression\nlevel Error\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_01.sol:5:31-36"]
-	diagnostic_10 [label="storage variable ‘y‘ has never been used\nlevel Warning\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_01.sol:5:13-40"]
+	diagnostic_10 [label="storage variable ‘y‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_01.sol:5:13-40"]
 	contracts -> contract
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> var [label="variable"]
 	contract -> foo [label="function"]
 	contract -> foo [label="function"]

+ 14 - 10
tests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.dot

@@ -1,18 +1,22 @@
 strict digraph "tests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol" {
 strict digraph "tests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol" {
 	contract [label="contract test\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol:1:1-15"]
 	contract [label="contract test\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol:1:1-15"]
 	var [label="variable x\nvisibility internal\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol:2:13-29"]
 	var [label="variable x\nvisibility internal\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol:2:13-29"]
-	var_4 [label="variable y\nvisibility internal\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol:3:13-25"]
-	number_literal [label="uint256 literal: 102\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol:3:22-25"]
+	add [label="add\nuint256\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol:2:24-25"]
+	storage_load [label="storage load uint256\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol:2:22-23"]
+	storage_var [label="storage variable\ntest.y\nuint256 storage\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol:2:22-23"]
+	number_literal [label="uint256 literal: 102\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol:2:26-29"]
+	var_8 [label="variable y\nvisibility internal\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol:3:13-25"]
+	number_literal_9 [label="uint256 literal: 102\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol:3:22-25"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol:1:1-15"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol:1:1-15"]
-	diagnostic_8 [label="`y' is not found\nlevel Error\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol:2:22-23"]
-	diagnostic_9 [label="storage variable ‘x‘ has never been used\nlevel Warning\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol:2:13-29"]
-	diagnostic_10 [label="storage variable ‘y‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol:3:13-25"]
+	diagnostic_12 [label="storage variable ‘x‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_02.sol:2:13-29"]
 	contracts -> contract
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> var [label="variable"]
-	contract -> var_4 [label="variable"]
-	var_4 -> number_literal [label="initializer"]
+	var -> add [label="initializer"]
+	add -> storage_load [label="left"]
+	storage_load -> storage_var [label="expr"]
+	add -> number_literal [label="right"]
+	contract -> var_8 [label="variable"]
+	var_8 -> number_literal_9 [label="initializer"]
 	diagnostics -> diagnostic [label="Debug"]
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_8 [label="Error"]
-	diagnostics -> diagnostic_9 [label="Warning"]
-	diagnostics -> diagnostic_10 [label="Warning"]
+	diagnostics -> diagnostic_12 [label="Warning"]
 }
 }

+ 12 - 10
tests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.dot

@@ -1,18 +1,20 @@
 strict digraph "tests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.sol" {
 strict digraph "tests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.sol" {
 	contract [label="contract test\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.sol:1:1-15"]
 	contract [label="contract test\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.sol:1:1-15"]
 	var [label="variable x\nvisibility internal\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.sol:2:13-29"]
 	var [label="variable x\nvisibility internal\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.sol:2:13-29"]
-	var_4 [label="variable y\nvisibility internal\nconstant\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.sol:3:13-34"]
-	number_literal [label="uint256 literal: 102\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.sol:3:31-34"]
+	add [label="add\nuint256\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.sol:2:24-25"]
+	constant [label="constant variable\ntest.y\nuint256\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.sol:2:22-23"]
+	number_literal [label="uint256 literal: 102\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.sol:2:26-29"]
+	var_7 [label="variable y\nvisibility internal\nconstant\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.sol:3:13-34"]
+	number_literal_8 [label="uint256 literal: 102\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.sol:3:31-34"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.sol:1:1-15"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.sol:1:1-15"]
-	diagnostic_8 [label="`y' is not found\nlevel Error\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.sol:2:22-23"]
-	diagnostic_9 [label="storage variable ‘x‘ has never been used\nlevel Warning\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.sol:2:13-29"]
-	diagnostic_10 [label="storage variable ‘y‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.sol:3:13-34"]
+	diagnostic_11 [label="storage variable ‘x‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_03.sol:2:13-29"]
 	contracts -> contract
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> var [label="variable"]
-	contract -> var_4 [label="variable"]
-	var_4 -> number_literal [label="initializer"]
+	var -> add [label="initializer"]
+	add -> constant [label="left"]
+	add -> number_literal [label="right"]
+	contract -> var_7 [label="variable"]
+	var_7 -> number_literal_8 [label="initializer"]
 	diagnostics -> diagnostic [label="Debug"]
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_8 [label="Error"]
-	diagnostics -> diagnostic_9 [label="Warning"]
-	diagnostics -> diagnostic_10 [label="Warning"]
+	diagnostics -> diagnostic_11 [label="Warning"]
 }
 }

+ 9 - 5
tests/contract_testcases/substrate/variables/test_variable_initializer_errors_04.dot

@@ -1,12 +1,16 @@
 strict digraph "tests/contract_testcases/substrate/variables/test_variable_initializer_errors_04.sol" {
 strict digraph "tests/contract_testcases/substrate/variables/test_variable_initializer_errors_04.sol" {
 	contract [label="contract test\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_04.sol:1:1-15"]
 	contract [label="contract test\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_04.sol:1:1-15"]
-	var [label="variable x\nvisibility internal\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_04.sol:2:13-29"]
+	var [label="variable x\nvisibility internal\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_04.sol:3:5-21"]
+	add [label="add\nuint256\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_04.sol:3:16-17"]
+	storage_load [label="storage load uint256\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_04.sol:3:14-15"]
+	storage_var [label="storage variable\ntest.x\nuint256 storage\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_04.sol:3:14-15"]
+	number_literal [label="uint256 literal: 102\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_04.sol:3:18-21"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_04.sol:1:1-15"]
 	diagnostic [label="found contract ‘test’\nlevel Debug\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_04.sol:1:1-15"]
-	diagnostic_6 [label="`x' is not found\nlevel Error\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_04.sol:2:22-23"]
-	diagnostic_7 [label="storage variable ‘x‘ has never been used\nlevel Warning\ntests/contract_testcases/substrate/variables/test_variable_initializer_errors_04.sol:2:13-29"]
 	contracts -> contract
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> var [label="variable"]
+	var -> add [label="initializer"]
+	add -> storage_load [label="left"]
+	storage_load -> storage_var [label="expr"]
+	add -> number_literal [label="right"]
 	diagnostics -> diagnostic [label="Debug"]
 	diagnostics -> diagnostic [label="Debug"]
-	diagnostics -> diagnostic_6 [label="Error"]
-	diagnostics -> diagnostic_7 [label="Warning"]
 }
 }

+ 3 - 2
tests/contract_testcases/substrate/variables/test_variable_initializer_errors_04.sol

@@ -1,3 +1,4 @@
 contract test {
 contract test {
-            uint x = x + 102;
-        }
+    // solc permits this too
+    uint x = x + 102;
+}