diff --git a/src/semantic/expr.c b/src/semantic/expr.c index 0a9ced6c..e2222863 100755 --- a/src/semantic/expr.c +++ b/src/semantic/expr.c @@ -3015,9 +3015,12 @@ static void test_memcpy( struct semantic* semantic, struct expr_test* test, struct expr_test src; s_init_expr_test( &src, false, false ); test_nested_expr( semantic, test, &src, call->source ); - if ( ! s_same_type( &src.type, &dst.type ) ) { + if ( ! s_same_storageignored_type( &src.type, &dst.type ) ) { s_type_mismatch( semantic, "source", &src.type, "destination", &dst.type, &call->source->pos ); + s_diag( semantic, DIAG_NOTE | DIAG_POS, &call->source->pos, + "the source and destination arguments can have different storage " + "types" ); s_bail( semantic ); } // Source-offset. diff --git a/src/semantic/phase.h b/src/semantic/phase.h index 17987ee8..11edcdcd 100755 --- a/src/semantic/phase.h +++ b/src/semantic/phase.h @@ -250,5 +250,6 @@ bool s_is_void( struct type_info* type ); void s_reveal( struct type_info* type ); bool s_is_str( struct type_info* type ); bool s_is_struct_ref( struct type_info* type ); +bool s_same_storageignored_type( struct type_info* a, struct type_info* b ); #endif diff --git a/src/semantic/type.c b/src/semantic/type.c index 9e18f9e8..ccbfc71c 100755 --- a/src/semantic/type.c +++ b/src/semantic/type.c @@ -17,6 +17,7 @@ static void present_ref( struct ref* ref, struct str* string ); static void present_dim( struct type_info* type, struct str* string ); static void present_param_list( struct param* param, struct str* string ); static struct ref* dup_ref( struct ref* ref ); +static void set_storage( struct type_info* type, int storage ); void s_init_type_info( struct type_info* type, struct ref* ref, struct structure* structure, struct enumeration* enumeration, @@ -737,3 +738,37 @@ bool s_is_str( struct type_info* type ) { bool s_is_struct_ref( struct type_info* type ) { return ( s_describe_type( type ) == TYPEDESC_STRUCTREF ); } + +bool s_same_storageignored_type( struct type_info* a, struct type_info* b ) { + struct type_info temp_a; + struct type_info temp_b; + s_init_type_info_copy( &temp_a, a ); + s_init_type_info_copy( &temp_b, b ); + set_storage( &temp_a, STORAGE_MAP ); + set_storage( &temp_b, STORAGE_MAP ); + return s_same_type( &temp_a, &temp_b ); +} + +void set_storage( struct type_info* type, int storage ) { + if ( type->ref ) { + if ( ! type->ref->implicit ) { + create_implicit_ref( type ); + } + switch ( type->ref->type ) { + case REF_ARRAY: + { + struct ref_array* array = ( struct ref_array* ) type->ref; + array->storage = storage; + } + break; + case REF_STRUCTURE: + { + struct ref_struct* structure = ( struct ref_struct* ) type->ref; + structure->storage = storage; + } + break; + default: + break; + } + } +}