Auto merge of #69833 - Centril:rollup-mh74yue, r=Centril
Rollup of 7 pull requests Successful merges: - #69120 (Don't give invalid suggestion on desugared span.) - #69326 (mir-interpret: add method to read wide strings from Memory) - #69608 (Expose target libdir information via print command) - #69734 (Change DIBuilderCreateEnumerator signature to match LLVM 9) - #69800 (Compile address sanitizer test with debuginfo) - #69807 (Cleanup E0391 explanation) - #69820 (clean up E0392 explanation) Failed merges: r? @ghost
This commit is contained in:
commit
2cb0b8582e
15 changed files with 152 additions and 72 deletions
|
|
@ -146,6 +146,7 @@ The valid types of print values are:
|
|||
- `crate-name` — The name of the crate.
|
||||
- `file-names` — The names of the files created by the `link` emit kind.
|
||||
- `sysroot` — Path to the sysroot.
|
||||
- `target-libdir` - Path to the target libdir.
|
||||
- `cfg` — List of cfg values. See [conditional compilation] for more
|
||||
information about cfg values.
|
||||
- `target-list` — List of known targets. The target may be selected with the
|
||||
|
|
|
|||
|
|
@ -612,6 +612,11 @@ impl<'tcx, Tag> ScalarMaybeUndef<Tag> {
|
|||
self.not_undef()?.to_u8()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn to_u16(self) -> InterpResult<'tcx, u16> {
|
||||
self.not_undef()?.to_u16()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn to_u32(self) -> InterpResult<'tcx, u32> {
|
||||
self.not_undef()?.to_u32()
|
||||
|
|
@ -632,6 +637,11 @@ impl<'tcx, Tag> ScalarMaybeUndef<Tag> {
|
|||
self.not_undef()?.to_i8()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn to_i16(self) -> InterpResult<'tcx, i16> {
|
||||
self.not_undef()?.to_i16()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn to_i32(self) -> InterpResult<'tcx, i32> {
|
||||
self.not_undef()?.to_i32()
|
||||
|
|
|
|||
|
|
@ -1779,13 +1779,20 @@ fn prepare_enum_metadata(
|
|||
.discriminants(cx.tcx)
|
||||
.zip(&def.variants)
|
||||
.map(|((_, discr), v)| {
|
||||
let name = SmallCStr::new(&v.ident.as_str());
|
||||
let name = v.ident.as_str();
|
||||
let is_unsigned = match discr.ty.kind {
|
||||
ty::Int(_) => false,
|
||||
ty::Uint(_) => true,
|
||||
_ => bug!("non integer discriminant"),
|
||||
};
|
||||
unsafe {
|
||||
Some(llvm::LLVMRustDIBuilderCreateEnumerator(
|
||||
DIB(cx),
|
||||
name.as_ptr(),
|
||||
name.as_ptr().cast(),
|
||||
name.len(),
|
||||
// FIXME: what if enumeration has i128 discriminant?
|
||||
discr.val as u64,
|
||||
discr.val as i64,
|
||||
is_unsigned,
|
||||
))
|
||||
}
|
||||
})
|
||||
|
|
@ -1794,13 +1801,15 @@ fn prepare_enum_metadata(
|
|||
.as_generator()
|
||||
.variant_range(enum_def_id, cx.tcx)
|
||||
.map(|variant_index| {
|
||||
let name = SmallCStr::new(&substs.as_generator().variant_name(variant_index));
|
||||
let name = substs.as_generator().variant_name(variant_index);
|
||||
unsafe {
|
||||
Some(llvm::LLVMRustDIBuilderCreateEnumerator(
|
||||
DIB(cx),
|
||||
name.as_ptr(),
|
||||
// FIXME: what if enumeration has i128 discriminant?
|
||||
variant_index.as_usize() as u64,
|
||||
name.as_ptr().cast(),
|
||||
name.len(),
|
||||
// Generators use u32 as discriminant type.
|
||||
variant_index.as_u32().into(),
|
||||
true, // IsUnsigned
|
||||
))
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1776,7 +1776,9 @@ extern "C" {
|
|||
pub fn LLVMRustDIBuilderCreateEnumerator(
|
||||
Builder: &DIBuilder<'a>,
|
||||
Name: *const c_char,
|
||||
Val: u64,
|
||||
NameLen: size_t,
|
||||
Value: i64,
|
||||
IsUnsigned: bool,
|
||||
) -> &'a DIEnumerator;
|
||||
|
||||
pub fn LLVMRustDIBuilderCreateEnumerationType(
|
||||
|
|
|
|||
|
|
@ -680,6 +680,10 @@ impl RustcDefaultCalls {
|
|||
println!("{}", targets.join("\n"));
|
||||
}
|
||||
Sysroot => println!("{}", sess.sysroot.display()),
|
||||
TargetLibdir => println!(
|
||||
"{}",
|
||||
sess.target_tlib_path.as_ref().unwrap_or(&sess.host_tlib_path).dir.display()
|
||||
),
|
||||
TargetSpec => println!("{}", sess.target.target.to_json().pretty()),
|
||||
FileNames | CrateName => {
|
||||
let input = input.unwrap_or_else(|| {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
This error indicates that some types or traits depend on each other
|
||||
and therefore cannot be constructed.
|
||||
A type dependency cycle has been encountered.
|
||||
|
||||
The following example contains a circular dependency between two traits:
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0391
|
||||
trait FirstTrait : SecondTrait {
|
||||
|
|
@ -12,3 +11,6 @@ trait SecondTrait : FirstTrait {
|
|||
|
||||
}
|
||||
```
|
||||
|
||||
The previous example contains a circular dependency between two traits:
|
||||
`FirstTrait` depends on `SecondTrait` which itself depends on `FirstTrait`.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
This error indicates that a type or lifetime parameter has been declared
|
||||
but not actually used. Here is an example that demonstrates the error:
|
||||
A type or lifetime parameter has been declared but is not actually used.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0392
|
||||
enum Foo<T> {
|
||||
|
|
|
|||
|
|
@ -329,40 +329,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
if self.body.local_decls[local].is_user_variable() =>
|
||||
{
|
||||
let local_decl = &self.body.local_decls[local];
|
||||
let suggestion = match local_decl.local_info {
|
||||
LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf(_))) => {
|
||||
Some(suggest_ampmut_self(self.infcx.tcx, local_decl))
|
||||
}
|
||||
|
||||
LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
|
||||
mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(_),
|
||||
opt_ty_info,
|
||||
..
|
||||
},
|
||||
))) => Some(suggest_ampmut(
|
||||
self.infcx.tcx,
|
||||
self.body,
|
||||
local,
|
||||
local_decl,
|
||||
opt_ty_info,
|
||||
)),
|
||||
|
||||
LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
|
||||
mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByReference(_),
|
||||
..
|
||||
},
|
||||
))) => {
|
||||
let pattern_span = local_decl.source_info.span;
|
||||
suggest_ref_mut(self.infcx.tcx, pattern_span)
|
||||
.map(|replacement| (pattern_span, replacement))
|
||||
}
|
||||
|
||||
LocalInfo::User(ClearCrossCrate::Clear) => bug!("saw cleared local state"),
|
||||
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let (pointer_sigil, pointer_desc) = if local_decl.ty.is_region_ptr() {
|
||||
("&", "reference")
|
||||
|
|
@ -370,17 +336,53 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
("*const", "pointer")
|
||||
};
|
||||
|
||||
if let Some((err_help_span, suggested_code)) = suggestion {
|
||||
err.span_suggestion(
|
||||
err_help_span,
|
||||
&format!("consider changing this to be a mutable {}", pointer_desc),
|
||||
suggested_code,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
|
||||
match self.local_names[local] {
|
||||
Some(name) if !local_decl.from_compiler_desugaring() => {
|
||||
let suggestion = match local_decl.local_info {
|
||||
LocalInfo::User(ClearCrossCrate::Set(
|
||||
mir::BindingForm::ImplicitSelf(_),
|
||||
)) => Some(suggest_ampmut_self(self.infcx.tcx, local_decl)),
|
||||
|
||||
LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
|
||||
mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(_),
|
||||
opt_ty_info,
|
||||
..
|
||||
},
|
||||
))) => Some(suggest_ampmut(
|
||||
self.infcx.tcx,
|
||||
self.body,
|
||||
local,
|
||||
local_decl,
|
||||
opt_ty_info,
|
||||
)),
|
||||
|
||||
LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
|
||||
mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByReference(_),
|
||||
..
|
||||
},
|
||||
))) => {
|
||||
let pattern_span = local_decl.source_info.span;
|
||||
suggest_ref_mut(self.infcx.tcx, pattern_span)
|
||||
.map(|replacement| (pattern_span, replacement))
|
||||
}
|
||||
|
||||
LocalInfo::User(ClearCrossCrate::Clear) => {
|
||||
bug!("saw cleared local state")
|
||||
}
|
||||
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
if let Some((err_help_span, suggested_code)) = suggestion {
|
||||
err.span_suggestion(
|
||||
err_help_span,
|
||||
&format!("consider changing this to be a mutable {}", pointer_desc),
|
||||
suggested_code,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
err.span_label(
|
||||
span,
|
||||
format!(
|
||||
|
|
|
|||
|
|
@ -798,6 +798,33 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
|
|||
self.get_raw(ptr.alloc_id)?.read_c_str(self, ptr)
|
||||
}
|
||||
|
||||
/// Reads a 0x0000-terminated u16-sequence from memory. Returns them as a Vec<u16>.
|
||||
/// Terminator 0x0000 is not included in the returned Vec<u16>.
|
||||
///
|
||||
/// Performs appropriate bounds checks.
|
||||
pub fn read_wide_str(&self, ptr: Scalar<M::PointerTag>) -> InterpResult<'tcx, Vec<u16>> {
|
||||
let size_2bytes = Size::from_bytes(2);
|
||||
let align_2bytes = Align::from_bytes(2).unwrap();
|
||||
// We need to read at least 2 bytes, so we *need* a ptr.
|
||||
let mut ptr = self.force_ptr(ptr)?;
|
||||
let allocation = self.get_raw(ptr.alloc_id)?;
|
||||
let mut u16_seq = Vec::new();
|
||||
|
||||
loop {
|
||||
ptr = self
|
||||
.check_ptr_access(ptr.into(), size_2bytes, align_2bytes)?
|
||||
.expect("cannot be a ZST");
|
||||
let single_u16 = allocation.read_scalar(self, ptr, size_2bytes)?.to_u16()?;
|
||||
if single_u16 != 0x0000 {
|
||||
u16_seq.push(single_u16);
|
||||
ptr = ptr.offset(size_2bytes, self)?;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(u16_seq)
|
||||
}
|
||||
|
||||
/// Writes the given stream of bytes into memory.
|
||||
///
|
||||
/// Performs appropriate bounds checks.
|
||||
|
|
|
|||
|
|
@ -391,6 +391,7 @@ impl ExternEntry {
|
|||
pub enum PrintRequest {
|
||||
FileNames,
|
||||
Sysroot,
|
||||
TargetLibdir,
|
||||
CrateName,
|
||||
Cfg,
|
||||
TargetList,
|
||||
|
|
@ -912,7 +913,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
|
|||
"",
|
||||
"print",
|
||||
"Compiler information to print on stdout",
|
||||
"[crate-name|file-names|sysroot|cfg|target-list|\
|
||||
"[crate-name|file-names|sysroot|target-libdir|cfg|target-list|\
|
||||
target-cpus|target-features|relocation-models|\
|
||||
code-models|tls-models|target-spec-json|native-static-libs]",
|
||||
),
|
||||
|
|
@ -1344,6 +1345,7 @@ fn collect_print_requests(
|
|||
"crate-name" => PrintRequest::CrateName,
|
||||
"file-names" => PrintRequest::FileNames,
|
||||
"sysroot" => PrintRequest::Sysroot,
|
||||
"target-libdir" => PrintRequest::TargetLibdir,
|
||||
"cfg" => PrintRequest::Cfg,
|
||||
"target-list" => PrintRequest::TargetList,
|
||||
"target-cpus" => PrintRequest::TargetCPUs,
|
||||
|
|
|
|||
|
|
@ -891,10 +891,10 @@ extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
|
|||
unwrap(InsertAtEnd)));
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef
|
||||
LLVMRustDIBuilderCreateEnumerator(LLVMRustDIBuilderRef Builder,
|
||||
const char *Name, uint64_t Val) {
|
||||
return wrap(Builder->createEnumerator(Name, Val));
|
||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
|
||||
LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
|
||||
int64_t Value, bool IsUnsigned) {
|
||||
return wrap(Builder->createEnumerator({Name, NameLen}, Value, IsUnsigned));
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
|
||||
|
|
|
|||
27
src/test/codegen/enum-discriminant-value.rs
Normal file
27
src/test/codegen/enum-discriminant-value.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Verify that DIEnumerator uses isUnsigned flag when appropriate.
|
||||
//
|
||||
// compile-flags: -g -C no-prepopulate-passes
|
||||
|
||||
#[repr(i64)]
|
||||
pub enum I64 {
|
||||
I64Min = std::i64::MIN,
|
||||
I64Max = std::i64::MAX,
|
||||
}
|
||||
|
||||
#[repr(u64)]
|
||||
pub enum U64 {
|
||||
U64Min = std::u64::MIN,
|
||||
U64Max = std::u64::MAX,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _a = I64::I64Min;
|
||||
let _b = I64::I64Max;
|
||||
let _c = U64::U64Min;
|
||||
let _d = U64::U64Max;
|
||||
}
|
||||
|
||||
// CHECK: !DIEnumerator(name: "I64Min", value: -9223372036854775808)
|
||||
// CHECK: !DIEnumerator(name: "I64Max", value: 9223372036854775807)
|
||||
// CHECK: !DIEnumerator(name: "U64Min", value: 0, isUnsigned: true)
|
||||
// CHECK: !DIEnumerator(name: "U64Max", value: 18446744073709551615, isUnsigned: true)
|
||||
|
|
@ -2,10 +2,7 @@ error[E0596]: cannot borrow data in a `&` reference as mutable
|
|||
--> $DIR/dont-print-desugared-async.rs:5:20
|
||||
|
|
||||
LL | async fn async_fn(&ref mut s: &[i32]) {}
|
||||
| -^^^^^^^^^
|
||||
| ||
|
||||
| |cannot borrow as mutable through `&` reference
|
||||
| help: consider changing this to be a mutable reference: `&mut ref mut s`
|
||||
| ^^^^^^^^^ cannot borrow as mutable through `&` reference
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,7 @@ error[E0596]: cannot borrow data in a `&` reference as mutable
|
|||
--> $DIR/dont-print-desugared.rs:4:10
|
||||
|
|
||||
LL | for &ref mut x in s {}
|
||||
| -^^^^^^^^^
|
||||
| ||
|
||||
| |cannot borrow as mutable through `&` reference
|
||||
| help: consider changing this to be a mutable reference: `&mut ref mut x`
|
||||
| ^^^^^^^^^ cannot borrow as mutable through `&` reference
|
||||
|
||||
error[E0597]: `y` does not live long enough
|
||||
--> $DIR/dont-print-desugared.rs:17:16
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
// needs-sanitizer-support
|
||||
// only-x86_64
|
||||
//
|
||||
// compile-flags: -Z sanitizer=address -O
|
||||
// compile-flags: -Z sanitizer=address -O -g
|
||||
//
|
||||
// run-fail
|
||||
// error-pattern: AddressSanitizer: stack-buffer-overflow
|
||||
// error-pattern: 'xs' <== Memory access at offset
|
||||
// error-pattern: 'xs' (line 15) <== Memory access at offset
|
||||
|
||||
#![feature(test)]
|
||||
|
||||
use std::hint::black_box;
|
||||
use std::mem;
|
||||
|
||||
fn main() {
|
||||
let xs = [0, 1, 2, 3];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue