diff --git a/src/typesystem.rs b/src/typesystem.rs index 0464632cb4..2a9bd3f4e4 100644 --- a/src/typesystem.rs +++ b/src/typesystem.rs @@ -701,6 +701,10 @@ impl DataTypeInformation { let inner_type_size = inner_type_info.get_size_in_bits(index); let arr_size = self.get_size_in_bits(index); + if inner_type_size == 0 { + return None; + } + Some((arr_size / inner_type_size) as usize) } } diff --git a/src/validation.rs b/src/validation.rs index d42f7ca71c..ec948f745b 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -48,6 +48,15 @@ impl<'s, T: AnnotationMap> ValidationContext<'s, T> { } } + fn with_optional_qualifier(&self, qualifier: Option<&'s str>) -> Self { + ValidationContext { + annotations: self.annotations, + index: self.index, + qualifier, + is_call: self.is_call, + } + } + fn find_pou(&self, stmt: &AstNode) -> Option<&PouIndexEntry> { self.annotations.get_call_name(stmt).and_then(|pou_name| { self.index diff --git a/src/validation/array.rs b/src/validation/array.rs index 8e591c6871..d96bf767c2 100644 --- a/src/validation/array.rs +++ b/src/validation/array.rs @@ -58,6 +58,10 @@ fn validate_array( let len_lhs = lhs_type.get_array_length(context.index).unwrap_or(0); let len_rhs = statement_to_array_length(stmt_rhs); + if len_lhs == 0 { + return; + } + if len_lhs < len_rhs { let name = lhs_type.get_name(); let location = stmt_rhs.get_location(); diff --git a/src/validation/tests/snapshots/rusty__validation__tests__variable_validation_tests__type_initializers_in_structs_are_validated.snap b/src/validation/tests/snapshots/rusty__validation__tests__variable_validation_tests__type_initializers_in_structs_are_validated.snap new file mode 100644 index 0000000000..e5529788e5 --- /dev/null +++ b/src/validation/tests/snapshots/rusty__validation__tests__variable_validation_tests__type_initializers_in_structs_are_validated.snap @@ -0,0 +1,17 @@ +--- +source: src/validation/tests/variable_validation_tests.rs +expression: diagnostics +--- +error: Could not resolve reference to xxx + ┌─ :7:41 + │ +7 │ unknown_reference : foo := (xxx := 1); + │ ^^^ Could not resolve reference to xxx + +error: Array assignments must be surrounded with `[]` + ┌─ :8:62 + │ +8 │ invalid_array_assignment : ARRAY[0..1] OF INT := 0; + │ ^ Array assignments must be surrounded with `[]` + + diff --git a/src/validation/tests/variable_validation_tests.rs b/src/validation/tests/variable_validation_tests.rs index 1317ac49a3..27a3c4af7a 100644 --- a/src/validation/tests/variable_validation_tests.rs +++ b/src/validation/tests/variable_validation_tests.rs @@ -1,4 +1,6 @@ +use crate::test_utils::tests::parse_and_validate_buffered; use crate::{assert_validation_snapshot, test_utils::tests::parse_and_validate}; +use insta::assert_snapshot; #[test] fn uninitialized_constants_fall_back_to_the_default() { @@ -360,3 +362,21 @@ mod overflows { assert_validation_snapshot!(diagnostics); } } + +#[test] +fn type_initializers_in_structs_are_validated() { + let diagnostics = parse_and_validate_buffered( + " + TYPE foo : STRUCT + x : DINT; + END_STRUCT END_TYPE + + TYPE MyStruct: STRUCT + unknown_reference : foo := (xxx := 1); + invalid_array_assignment : ARRAY[0..1] OF INT := 0; + END_STRUCT END_TYPE + ", + ); + + assert_snapshot!(diagnostics); +} diff --git a/src/validation/types.rs b/src/validation/types.rs index b85ad9a60b..af27651df1 100644 --- a/src/validation/types.rs +++ b/src/validation/types.rs @@ -28,6 +28,7 @@ pub fn visit_data_type( ) { validate_data_type(validator, data_type, location); + let context = &context.with_optional_qualifier(data_type.get_name()); match data_type { DataType::StructType { variables, .. } => { variables.iter().for_each(|v| visit_variable(validator, v, context)) diff --git a/src/validation/variable.rs b/src/validation/variable.rs index 234f95f74f..75723101a4 100644 --- a/src/validation/variable.rs +++ b/src/validation/variable.rs @@ -43,7 +43,6 @@ pub fn visit_variable( context: &ValidationContext, ) { validate_variable(validator, variable, context); - visit_data_type_declaration(validator, &variable.data_type_declaration, context); }