mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-26 13:01:27 +03:00
Add miscompiled test cases
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
//! Regression test for issue <https://github.com/rust-lang/rust/issues/155241>.
|
||||
//! Arguments passed indirectly via a hidden pointer must be copied to an alloca,
|
||||
//! except for by-val or by-move.
|
||||
//@ add-minicore
|
||||
//@ revisions: x64-linux i686-linux i686-windows
|
||||
//@ compile-flags: -Cno-prepopulate-passes -Copt-level=3
|
||||
//@[x64-linux] compile-flags: --target x86_64-unknown-linux-gnu
|
||||
//@[x64-linux] needs-llvm-components: x86
|
||||
//@[i686-linux] compile-flags: --target i686-unknown-linux-gnu
|
||||
//@[i686-linux] needs-llvm-components: x86
|
||||
//@[i686-windows] compile-flags: --target i686-pc-windows-msvc
|
||||
//@[i686-windows] needs-llvm-components: x86
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(stmt_expr_attributes, no_core)]
|
||||
#![expect(unused)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
|
||||
extern crate minicore;
|
||||
use minicore::*;
|
||||
|
||||
struct Thing(u64, u64, u64);
|
||||
|
||||
impl Copy for Thing {}
|
||||
|
||||
// The argument of the second call is a by-move argument.
|
||||
|
||||
// CHECK-LABEL: @normal
|
||||
// CHECK: call void @llvm.memcpy{{.*}}(ptr{{.*}} [[normal_V1:%.*]], ptr{{.*}} %value,
|
||||
// CHECK: call void @opaque(ptr{{.*}} [[normal_V1]])
|
||||
// CHECK: call void @opaque(ptr{{.*}} %value)
|
||||
// CHECK: call void @llvm.memcpy{{.*}}(ptr{{.*}} [[normal_V3:%.*]], ptr{{.*}} @anon{{.*}},
|
||||
// CHECK: call void @opaque(ptr{{.*}} [[normal_V3]])
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn normal() {
|
||||
#[inline(never)]
|
||||
#[unsafe(no_mangle)]
|
||||
fn opaque(mut thing: Thing) {
|
||||
thing.0 = 1;
|
||||
}
|
||||
let value = Thing(0, 0, 0);
|
||||
opaque(value);
|
||||
opaque(value);
|
||||
const VALUE: Thing = Thing(0, 0, 0);
|
||||
opaque(VALUE);
|
||||
}
|
||||
|
||||
// FIXME: closure#0 and closure#1 are missing memcpy.
|
||||
|
||||
// CHECK-LABEL: @untupled
|
||||
// CHECK: call indirect_bycopy_bymove_byval::untupled::{closure#0}
|
||||
// CHECK-NEXT: call void @{{.*}}(ptr {{.*}}, ptr{{.*}} %value)
|
||||
// CHECK: call indirect_bycopy_bymove_byval::untupled::{closure#1}
|
||||
// CHECK-NEXT: call void @{{.*}}(ptr {{.*}}, ptr{{.*}} %value)
|
||||
// CHECK: call indirect_bycopy_bymove_byval::untupled::{closure#2}
|
||||
// CHECK-NEXT: call void @{{.*}}(ptr {{.*}}, ptr{{.*}} @anon{{.*}})
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn untupled() {
|
||||
let value = (Thing(0, 0, 0),);
|
||||
(#[inline(never)]
|
||||
|mut thing: Thing| {
|
||||
thing.0 = 1;
|
||||
})
|
||||
.call(value);
|
||||
(#[inline(never)]
|
||||
|mut thing: Thing| {
|
||||
thing.0 = 2;
|
||||
})
|
||||
.call(value);
|
||||
const VALUE: (Thing,) = (Thing(0, 0, 0),);
|
||||
(#[inline(never)]
|
||||
|mut thing: Thing| {
|
||||
thing.0 = 3;
|
||||
})
|
||||
.call(VALUE);
|
||||
}
|
||||
|
||||
// FIXME: all memcpy calls are redundant for byval.
|
||||
|
||||
// CHECK-LABEL: @byval
|
||||
// CHECK: call void @llvm.memcpy{{.*}}(ptr{{.*}} [[byval_V1:%.*]], ptr{{.*}} %value,
|
||||
// CHECK: call void @opaque_byval(ptr{{.*}} byval([24 x i8]){{.*}} [[byval_V1]])
|
||||
// CHECK: call void @opaque_byval(ptr{{.*}} byval([24 x i8]){{.*}} %value)
|
||||
// CHECK: call void @llvm.memcpy{{.*}}(ptr{{.*}} [[byval_V3:%.*]], ptr{{.*}} @anon{{.*}},
|
||||
// CHECK: call void @opaque_byval(ptr{{.*}} byval([24 x i8]){{.*}} [[byval_V3]])
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn byval() {
|
||||
#[repr(C)]
|
||||
struct Thing(u64, u64, u64);
|
||||
impl Copy for Thing {}
|
||||
#[inline(never)]
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn opaque_byval(mut thing: Thing) {
|
||||
thing.0 = 1;
|
||||
}
|
||||
let value = Thing(0, 0, 0);
|
||||
opaque_byval(value);
|
||||
opaque_byval(value);
|
||||
const VALUE: Thing = Thing(0, 0, 0);
|
||||
opaque_byval(VALUE);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
thread 'main' ($TID) panicked at $DIR/bycopy_untupled.rs:25:5:
|
||||
assertion `left == right` failed
|
||||
left: 1
|
||||
right: 0
|
||||
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||
@@ -0,0 +1 @@
|
||||
free(): double free detected in tcache 2
|
||||
@@ -0,0 +1,58 @@
|
||||
//@[noopt] run-fail
|
||||
//@[opt] run-crash
|
||||
//@ revisions: noopt opt
|
||||
//@ check-run-results
|
||||
//@[noopt] compile-flags: -C opt-level=0
|
||||
//@[opt] compile-flags: -C opt-level=3
|
||||
|
||||
#![feature(fn_traits, stmt_expr_attributes)]
|
||||
#![expect(unused)]
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct Thing {
|
||||
x: usize,
|
||||
y: usize,
|
||||
z: usize,
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn opt_0() {
|
||||
let value = (Thing { x: 0, y: 0, z: 0 },);
|
||||
(|mut thing: Thing| {
|
||||
thing.z = 1;
|
||||
})
|
||||
.call(value);
|
||||
assert_eq!(value.0.z, 0);
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn opt_3() {
|
||||
fn with(f: impl FnOnce(Vec<usize>)) {
|
||||
f(Vec::new())
|
||||
}
|
||||
with(|mut v| v.resize(2, 1));
|
||||
with(|v| {
|
||||
if v.len() != 0 {
|
||||
unreachable!();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn const_() {
|
||||
const VALUE: (Thing,) = (Thing { x: 0, y: 0, z: 0 },);
|
||||
|
||||
(#[inline(never)]
|
||||
|mut thing: Thing| {
|
||||
thing.z = 1;
|
||||
std::hint::black_box(&mut thing.z);
|
||||
assert_eq!(thing.z, 1);
|
||||
})
|
||||
.call(VALUE);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
opt_0();
|
||||
opt_3();
|
||||
const_();
|
||||
}
|
||||
Reference in New Issue
Block a user