@@ -13853,6 +13853,49 @@ fn inline_array_intrinsic_in_print_walks_descriptor_elements() { |
| 13853 | 13853 | let _ = std::fs::remove_file(&src); |
| 13854 | 13854 | } |
| 13855 | 13855 | |
| 13856 | +#[test] |
| 13857 | +fn complex_scalar_assigned_from_integer_promotes_via_buffer_not_pointer_cast() { |
| 13858 | + // F2018 §10.2.1.3: complex variables can be assigned a scalar of |
| 13859 | + // numeric type — the right-hand side is promoted to complex with |
| 13860 | + // imag=0. Our complex-assign lowering used to memcpy the 8/16 |
| 13861 | + // bytes from the RHS treating its register-resident value as if |
| 13862 | + // it were a pointer to a [fN x 2] buffer; for an integer/real RHS |
| 13863 | + // that meant memcpy(c, value_as_ptr, 8) and faulted on the bogus |
| 13864 | + // address. LAPACK CGEEV's `work(1) = maxwrk` (complex(sp) = i32) |
| 13865 | + // SEGV'd on this exact path, taking out every example_eig*, |
| 13866 | + // example_pseudoinverse, example_solve_{cg,bicgstab,pcg}, etc. |
| 13867 | + // The fix materializes a fresh [fN x 2] buffer when the RHS isn't |
| 13868 | + // already complex — covers scalar `c = i`, array element `a(k)=i`, |
| 13869 | + // and derived-type field `dt%c = i`. |
| 13870 | + let src = write_program( |
| 13871 | + "program t\n implicit none\n complex(4) :: c, a(5)\n type :: tt\n complex(4) :: f\n end type\n type(tt) :: dt\n integer :: i\n i = 42\n c = i\n a(3) = i\n dt%f = i\n if (abs(real(c) - 42.0) > 1.0e-5) error stop 1\n if (abs(aimag(c)) > 1.0e-5) error stop 2\n if (abs(real(a(3)) - 42.0) > 1.0e-5) error stop 3\n if (abs(aimag(a(3))) > 1.0e-5) error stop 4\n if (abs(real(dt%f) - 42.0) > 1.0e-5) error stop 5\n if (abs(aimag(dt%f)) > 1.0e-5) error stop 6\n print *, 'ok'\nend program\n", |
| 13872 | + "f90", |
| 13873 | + ); |
| 13874 | + let out = unique_path("cmplx_int_assign", "bin"); |
| 13875 | + let compile = Command::new(compiler("armfortas")) |
| 13876 | + .args([src.to_str().unwrap(), "-o", out.to_str().unwrap()]) |
| 13877 | + .output() |
| 13878 | + .expect("complex<-int compile failed"); |
| 13879 | + assert!( |
| 13880 | + compile.status.success(), |
| 13881 | + "complex<-int should compile: {}", |
| 13882 | + String::from_utf8_lossy(&compile.stderr) |
| 13883 | + ); |
| 13884 | + let run = Command::new(&out).output().expect("complex<-int run failed"); |
| 13885 | + assert!( |
| 13886 | + run.status.success(), |
| 13887 | + "complex<-int should pass: status={:?} stdout={} stderr={}", |
| 13888 | + run.status, |
| 13889 | + String::from_utf8_lossy(&run.stdout), |
| 13890 | + String::from_utf8_lossy(&run.stderr) |
| 13891 | + ); |
| 13892 | + let stdout = String::from_utf8_lossy(&run.stdout); |
| 13893 | + assert!(stdout.contains("ok"), "expected ok, got: {}", stdout); |
| 13894 | + |
| 13895 | + let _ = std::fs::remove_file(&out); |
| 13896 | + let _ = std::fs::remove_file(&src); |
| 13897 | +} |
| 13898 | + |
| 13856 | 13899 | #[test] |
| 13857 | 13900 | fn complex_dp_array_constructor_preserves_imaginary_lane_in_assignment() { |
| 13858 | 13901 | // F2018 §7.8: array-constructor element values for complex(dp) |