fortrangoingonforty/armfortas / 2f7b197

Browse files

Test allocatable rank-2 row section assignment uses column-major stride

Authored by espadonne
Committed by mfwolffe
SHA
2f7b197db97510c1e7de235f377a79fd02d3467e
Parents
8807b88
Tree
8e19748

1 changed file

StatusFile+-
M tests/cli_driver.rs 43 0
tests/cli_driver.rsmodified
@@ -28623,6 +28623,49 @@ fn cmplx_whole_array_with_kind_keyword_returns_correct_kind_descriptor() {
2862328623
     let _ = std::fs::remove_file(&src);
2862428624
 }
2862528625
 
28626
+#[test]
28627
+fn allocatable_rank2_section_row_assignment_uses_columnmajor_stride() {
28628
+    // F2018 §6.5.3: section assignment to a "row" of a column-major
28629
+    // allocatable matrix (e.g. `a(1,:) = [...]`) must step through
28630
+    // memory by the column extent, not contiguously. The compiler
28631
+    // builds the section descriptor via afs_create_section using the
28632
+    // source array's per-dim stride, so the source descriptor's
28633
+    // strides must match the column-major canonical layout. For
28634
+    // stack arrays, materialize_array_descriptor_for_info computes
28635
+    // those correctly; for allocatables, afs_allocate_array used to
28636
+    // copy whatever stride the compiler emitted (always 1) and the
28637
+    // resulting section view collapsed into a contiguous walk —
28638
+    // `a(1,:) = [10,20,30]; a(2,:) = [100,200,300]` left a as
28639
+    // [[10,200,?],[100,300,?]] instead of [[10,20,30],[100,200,300]].
28640
+    // Matched stdlib_sparse_conversion (rebuild needed): from_ijv was
28641
+    // initializing COO%index via section assignment, then passing the
28642
+    // descriptor to assumed-size dummies that read garbage.
28643
+    let src = write_program(
28644
+        "program p\n  implicit none\n  integer, allocatable :: a(:,:)\n  allocate(a(2, 3))\n  a(1, :) = [10, 20, 30]\n  a(2, :) = [100, 200, 300]\n  if (a(1,1) /= 10  .or. a(1,2) /= 20  .or. a(1,3) /= 30 ) error stop 1\n  if (a(2,1) /= 100 .or. a(2,2) /= 200 .or. a(2,3) /= 300) error stop 2\n  print *, 'ok'\nend program\n",
28645
+        "f90",
28646
+    );
28647
+    let out = unique_path("allocatable_rank2_row_section", "bin");
28648
+    let compile = Command::new(compiler("armfortas"))
28649
+        .args([src.to_str().unwrap(), "-o", out.to_str().unwrap()])
28650
+        .output()
28651
+        .expect("allocatable rank-2 row section compile failed to spawn");
28652
+    assert!(
28653
+        compile.status.success(),
28654
+        "allocatable rank-2 row section compile failed: {}",
28655
+        String::from_utf8_lossy(&compile.stderr)
28656
+    );
28657
+    let run = Command::new(&out).output().expect("run failed");
28658
+    assert!(
28659
+        run.status.success() && String::from_utf8_lossy(&run.stdout).contains("ok"),
28660
+        "allocatable rank-2 row section run failed: status={:?} stdout={} stderr={}",
28661
+        run.status,
28662
+        String::from_utf8_lossy(&run.stdout),
28663
+        String::from_utf8_lossy(&run.stderr)
28664
+    );
28665
+    let _ = std::fs::remove_file(&out);
28666
+    let _ = std::fs::remove_file(&src);
28667
+}
28668
+
2862628669
 #[test]
2862728670
 fn allocate_stat_int64_writes_back_to_user_variable() {
2862828671
     // F2018 §9.7.1.3: STAT= variable receives the allocate status.