mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-24 12:54:00 +00:00
Auto merge of #69851 - Centril:rollup-iivxvah, r=Centril
Rollup of 6 pull requests Successful merges: - #69201 (Permit attributes on 'if' expressions) - #69685 (unix: Don't override existing SIGSEGV/BUS handlers) - #69762 (Ensure that validity only raises validity errors) - #69779 (librustc_codegen_llvm: Use slices in preference to 0-terminated strings) - #69801 (rustc_parse: Remove `Parser::normalized(_prev)_token`) - #69842 (Add more regression tests) Failed merges: r? @ghost
This commit is contained in:
commit
3dbade652e
@ -245,7 +245,7 @@ fn print_backtrace(backtrace: &mut Backtrace) {
|
||||
eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace);
|
||||
}
|
||||
|
||||
impl From<ErrorHandled> for InterpErrorInfo<'tcx> {
|
||||
impl From<ErrorHandled> for InterpErrorInfo<'_> {
|
||||
fn from(err: ErrorHandled) -> Self {
|
||||
match err {
|
||||
ErrorHandled::Reported => err_inval!(ReferencedConstant),
|
||||
@ -291,7 +291,7 @@ pub enum InvalidProgramInfo<'tcx> {
|
||||
Layout(layout::LayoutError<'tcx>),
|
||||
}
|
||||
|
||||
impl fmt::Debug for InvalidProgramInfo<'tcx> {
|
||||
impl fmt::Debug for InvalidProgramInfo<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use InvalidProgramInfo::*;
|
||||
match self {
|
||||
@ -321,6 +321,8 @@ pub enum UndefinedBehaviorInfo {
|
||||
RemainderByZero,
|
||||
/// Overflowing inbounds pointer arithmetic.
|
||||
PointerArithOverflow,
|
||||
/// Invalid metadata in a wide pointer (using `str` to avoid allocations).
|
||||
InvalidMeta(&'static str),
|
||||
}
|
||||
|
||||
impl fmt::Debug for UndefinedBehaviorInfo {
|
||||
@ -338,6 +340,7 @@ impl fmt::Debug for UndefinedBehaviorInfo {
|
||||
DivisionByZero => write!(f, "dividing by zero"),
|
||||
RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"),
|
||||
PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"),
|
||||
InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {}", msg),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -354,8 +357,8 @@ pub enum UnsupportedOpInfo<'tcx> {
|
||||
Unsupported(String),
|
||||
|
||||
/// When const-prop encounters a situation it does not support, it raises this error.
|
||||
/// This must not allocate for performance reasons.
|
||||
ConstPropUnsupported(&'tcx str),
|
||||
/// This must not allocate for performance reasons (hence `str`, not `String`).
|
||||
ConstPropUnsupported(&'static str),
|
||||
|
||||
// -- Everything below is not categorized yet --
|
||||
FunctionAbiMismatch(Abi, Abi),
|
||||
@ -612,3 +615,19 @@ impl fmt::Debug for InterpError<'_> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InterpError<'_> {
|
||||
/// Some errors allocate to be created as they contain free-form strings.
|
||||
/// And sometimes we want to be sure that did not happen as it is a
|
||||
/// waste of resources.
|
||||
pub fn allocates(&self) -> bool {
|
||||
match self {
|
||||
InterpError::MachineStop(_)
|
||||
| InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
|
||||
| InterpError::Unsupported(UnsupportedOpInfo::ValidationFailure(_))
|
||||
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
|
||||
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::UbExperimental(_)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -286,6 +286,10 @@ impl MetaItem {
|
||||
}
|
||||
|
||||
impl AttrItem {
|
||||
pub fn span(&self) -> Span {
|
||||
self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span))
|
||||
}
|
||||
|
||||
pub fn meta(&self, span: Span) -> Option<MetaItem> {
|
||||
Some(MetaItem {
|
||||
path: self.path.clone(),
|
||||
@ -437,7 +441,7 @@ impl MetaItem {
|
||||
I: Iterator<Item = TokenTree>,
|
||||
{
|
||||
// FIXME: Share code with `parse_path`.
|
||||
let path = match tokens.next() {
|
||||
let path = match tokens.next().map(TokenTree::uninterpolate) {
|
||||
Some(TokenTree::Token(Token { kind: kind @ token::Ident(..), span }))
|
||||
| Some(TokenTree::Token(Token { kind: kind @ token::ModSep, span })) => 'arm: {
|
||||
let mut segments = if let token::Ident(name, _) = kind {
|
||||
@ -453,7 +457,7 @@ impl MetaItem {
|
||||
};
|
||||
loop {
|
||||
if let Some(TokenTree::Token(Token { kind: token::Ident(name, _), span })) =
|
||||
tokens.next()
|
||||
tokens.next().map(TokenTree::uninterpolate)
|
||||
{
|
||||
segments.push(PathSegment::from_ident(Ident::new(name, span)));
|
||||
} else {
|
||||
@ -470,7 +474,6 @@ impl MetaItem {
|
||||
Path { span, segments }
|
||||
}
|
||||
Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. })) => match *nt {
|
||||
token::Nonterminal::NtIdent(ident, _) => Path::from_ident(ident),
|
||||
token::Nonterminal::NtMeta(ref item) => return item.meta(item.path.span),
|
||||
token::Nonterminal::NtPath(ref path) => path.clone(),
|
||||
_ => return None,
|
||||
|
@ -14,8 +14,8 @@ use rustc_macros::HashStable_Generic;
|
||||
use rustc_span::symbol::kw;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{self, Span, DUMMY_SP};
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::borrow::Cow;
|
||||
use std::{fmt, mem};
|
||||
|
||||
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
|
||||
#[derive(HashStable_Generic)]
|
||||
@ -225,8 +225,15 @@ pub enum TokenKind {
|
||||
/* Literals */
|
||||
Literal(Lit),
|
||||
|
||||
/* Name components */
|
||||
/// Identifier token.
|
||||
/// Do not forget about `NtIdent` when you want to match on identifiers.
|
||||
/// It's recommended to use `Token::(ident,uninterpolate,uninterpolated_span)` to
|
||||
/// treat regular and interpolated identifiers in the same way.
|
||||
Ident(ast::Name, /* is_raw */ bool),
|
||||
/// Lifetime identifier token.
|
||||
/// Do not forget about `NtLifetime` when you want to match on lifetime identifiers.
|
||||
/// It's recommended to use `Token::(lifetime,uninterpolate,uninterpolated_span)` to
|
||||
/// treat regular and interpolated lifetime identifiers in the same way.
|
||||
Lifetime(ast::Name),
|
||||
|
||||
Interpolated(Lrc<Nonterminal>),
|
||||
@ -328,6 +335,19 @@ impl Token {
|
||||
mem::replace(self, Token::dummy())
|
||||
}
|
||||
|
||||
/// For interpolated tokens, returns a span of the fragment to which the interpolated
|
||||
/// token refers. For all other tokens this is just a regular span.
|
||||
/// It is particularly important to use this for identifiers and lifetimes
|
||||
/// for which spans affect name resolution and edition checks.
|
||||
/// Note that keywords are also identifiers, so they should use this
|
||||
/// if they keep spans or perform edition checks.
|
||||
pub fn uninterpolated_span(&self) -> Span {
|
||||
match &self.kind {
|
||||
Interpolated(nt) => nt.span(),
|
||||
_ => self.span,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_op(&self) -> bool {
|
||||
match self.kind {
|
||||
OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..)
|
||||
@ -345,7 +365,7 @@ impl Token {
|
||||
|
||||
/// Returns `true` if the token can appear at the start of an expression.
|
||||
pub fn can_begin_expr(&self) -> bool {
|
||||
match self.kind {
|
||||
match self.uninterpolate().kind {
|
||||
Ident(name, is_raw) =>
|
||||
ident_can_begin_expr(name, self.span, is_raw), // value name or keyword
|
||||
OpenDelim(..) | // tuple, array or block
|
||||
@ -363,12 +383,10 @@ impl Token {
|
||||
Lifetime(..) | // labeled loop
|
||||
Pound => true, // expression attributes
|
||||
Interpolated(ref nt) => match **nt {
|
||||
NtIdent(ident, is_raw) => ident_can_begin_expr(ident.name, ident.span, is_raw),
|
||||
NtLiteral(..) |
|
||||
NtExpr(..) |
|
||||
NtBlock(..) |
|
||||
NtPath(..) |
|
||||
NtLifetime(..) => true,
|
||||
NtPath(..) => true,
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
@ -377,7 +395,7 @@ impl Token {
|
||||
|
||||
/// Returns `true` if the token can appear at the start of a type.
|
||||
pub fn can_begin_type(&self) -> bool {
|
||||
match self.kind {
|
||||
match self.uninterpolate().kind {
|
||||
Ident(name, is_raw) =>
|
||||
ident_can_begin_type(name, self.span, is_raw), // type name or keyword
|
||||
OpenDelim(Paren) | // tuple
|
||||
@ -391,8 +409,7 @@ impl Token {
|
||||
Lt | BinOp(Shl) | // associated path
|
||||
ModSep => true, // global path
|
||||
Interpolated(ref nt) => match **nt {
|
||||
NtIdent(ident, is_raw) => ident_can_begin_type(ident.name, ident.span, is_raw),
|
||||
NtTy(..) | NtPath(..) | NtLifetime(..) => true,
|
||||
NtTy(..) | NtPath(..) => true,
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
@ -433,11 +450,10 @@ impl Token {
|
||||
///
|
||||
/// Keep this in sync with `Lit::from_token`.
|
||||
pub fn can_begin_literal_or_bool(&self) -> bool {
|
||||
match self.kind {
|
||||
match self.uninterpolate().kind {
|
||||
Literal(..) | BinOp(Minus) => true,
|
||||
Ident(name, false) if name.is_bool_lit() => true,
|
||||
Interpolated(ref nt) => match &**nt {
|
||||
NtIdent(ident, false) if ident.name.is_bool_lit() => true,
|
||||
NtExpr(e) | NtLiteral(e) => matches!(e.kind, ast::ExprKind::Lit(_)),
|
||||
_ => false,
|
||||
},
|
||||
@ -445,26 +461,37 @@ impl Token {
|
||||
}
|
||||
}
|
||||
|
||||
// A convenience function for matching on identifiers during parsing.
|
||||
// Turns interpolated identifier (`$i: ident`) or lifetime (`$l: lifetime`) token
|
||||
// into the regular identifier or lifetime token it refers to,
|
||||
// otherwise returns the original token.
|
||||
pub fn uninterpolate(&self) -> Cow<'_, Token> {
|
||||
match &self.kind {
|
||||
Interpolated(nt) => match **nt {
|
||||
NtIdent(ident, is_raw) => {
|
||||
Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span))
|
||||
}
|
||||
NtLifetime(ident) => Cow::Owned(Token::new(Lifetime(ident.name), ident.span)),
|
||||
_ => Cow::Borrowed(self),
|
||||
},
|
||||
_ => Cow::Borrowed(self),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an identifier if this token is an identifier.
|
||||
pub fn ident(&self) -> Option<(ast::Ident, /* is_raw */ bool)> {
|
||||
match self.kind {
|
||||
Ident(name, is_raw) => Some((ast::Ident::new(name, self.span), is_raw)),
|
||||
Interpolated(ref nt) => match **nt {
|
||||
NtIdent(ident, is_raw) => Some((ident, is_raw)),
|
||||
_ => None,
|
||||
},
|
||||
let token = self.uninterpolate();
|
||||
match token.kind {
|
||||
Ident(name, is_raw) => Some((ast::Ident::new(name, token.span), is_raw)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a lifetime identifier if this token is a lifetime.
|
||||
pub fn lifetime(&self) -> Option<ast::Ident> {
|
||||
match self.kind {
|
||||
Lifetime(name) => Some(ast::Ident::new(name, self.span)),
|
||||
Interpolated(ref nt) => match **nt {
|
||||
NtLifetime(ident) => Some(ident),
|
||||
_ => None,
|
||||
},
|
||||
let token = self.uninterpolate();
|
||||
match token.kind {
|
||||
Lifetime(name) => Some(ast::Ident::new(name, token.span)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -714,6 +741,24 @@ pub enum Nonterminal {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
rustc_data_structures::static_assert_size!(Nonterminal, 40);
|
||||
|
||||
impl Nonterminal {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
NtItem(item) => item.span,
|
||||
NtBlock(block) => block.span,
|
||||
NtStmt(stmt) => stmt.span,
|
||||
NtPat(pat) => pat.span,
|
||||
NtExpr(expr) | NtLiteral(expr) => expr.span,
|
||||
NtTy(ty) => ty.span,
|
||||
NtIdent(ident, _) | NtLifetime(ident) => ident.span,
|
||||
NtMeta(attr_item) => attr_item.span(),
|
||||
NtPath(path) => path.span,
|
||||
NtVis(vis) => vis.span,
|
||||
NtTT(tt) => tt.span(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Nonterminal {
|
||||
fn eq(&self, rhs: &Self) -> bool {
|
||||
match (self, rhs) {
|
||||
|
@ -116,6 +116,13 @@ impl TokenTree {
|
||||
pub fn close_tt(span: DelimSpan, delim: DelimToken) -> TokenTree {
|
||||
TokenTree::token(token::CloseDelim(delim), span.close)
|
||||
}
|
||||
|
||||
pub fn uninterpolate(self) -> TokenTree {
|
||||
match self {
|
||||
TokenTree::Token(token) => TokenTree::Token(token.uninterpolate().into_owned()),
|
||||
tt => tt,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<CTX> HashStable<CTX> for TokenStream
|
||||
|
@ -191,23 +191,16 @@ impl Lit {
|
||||
///
|
||||
/// Keep this in sync with `Token::can_begin_literal_or_bool`.
|
||||
pub fn from_token(token: &Token) -> Result<Lit, LitError> {
|
||||
let lit = match token.kind {
|
||||
let lit = match token.uninterpolate().kind {
|
||||
token::Ident(name, false) if name.is_bool_lit() => {
|
||||
token::Lit::new(token::Bool, name, None)
|
||||
}
|
||||
token::Literal(lit) => lit,
|
||||
token::Interpolated(ref nt) => {
|
||||
match &**nt {
|
||||
token::NtIdent(ident, false) if ident.name.is_bool_lit() => {
|
||||
let lit = token::Lit::new(token::Bool, ident.name, None);
|
||||
return Lit::from_lit_token(lit, ident.span);
|
||||
if let token::NtExpr(expr) | token::NtLiteral(expr) = &**nt {
|
||||
if let ast::ExprKind::Lit(lit) = &expr.kind {
|
||||
return Ok(lit.clone());
|
||||
}
|
||||
token::NtExpr(expr) | token::NtLiteral(expr) => {
|
||||
if let ast::ExprKind::Lit(lit) = &expr.kind {
|
||||
return Ok(lit.clone());
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
return Err(LitError::NotLiteral);
|
||||
}
|
||||
|
@ -156,44 +156,43 @@ fn parse_args<'a>(
|
||||
if p.token == token::Eof {
|
||||
break;
|
||||
} // accept trailing commas
|
||||
if p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq) {
|
||||
named = true;
|
||||
let name = if let token::Ident(name, _) = p.normalized_token.kind {
|
||||
match p.token.ident() {
|
||||
Some((ident, _)) if p.look_ahead(1, |t| *t == token::Eq) => {
|
||||
named = true;
|
||||
p.bump();
|
||||
name
|
||||
} else {
|
||||
unreachable!();
|
||||
};
|
||||
|
||||
p.expect(&token::Eq)?;
|
||||
let e = p.parse_expr()?;
|
||||
if let Some(prev) = names.get(&name) {
|
||||
ecx.struct_span_err(e.span, &format!("duplicate argument named `{}`", name))
|
||||
.span_label(args[*prev].span, "previously here")
|
||||
.span_label(e.span, "duplicate argument")
|
||||
.emit();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Resolve names into slots early.
|
||||
// Since all the positional args are already seen at this point
|
||||
// if the input is valid, we can simply append to the positional
|
||||
// args. And remember the names.
|
||||
let slot = args.len();
|
||||
names.insert(name, slot);
|
||||
args.push(e);
|
||||
} else {
|
||||
let e = p.parse_expr()?;
|
||||
if named {
|
||||
let mut err = ecx
|
||||
.struct_span_err(e.span, "positional arguments cannot follow named arguments");
|
||||
err.span_label(e.span, "positional arguments must be before named arguments");
|
||||
for pos in names.values() {
|
||||
err.span_label(args[*pos].span, "named argument");
|
||||
p.expect(&token::Eq)?;
|
||||
let e = p.parse_expr()?;
|
||||
if let Some(prev) = names.get(&ident.name) {
|
||||
ecx.struct_span_err(e.span, &format!("duplicate argument named `{}`", ident))
|
||||
.span_label(args[*prev].span, "previously here")
|
||||
.span_label(e.span, "duplicate argument")
|
||||
.emit();
|
||||
continue;
|
||||
}
|
||||
err.emit();
|
||||
|
||||
// Resolve names into slots early.
|
||||
// Since all the positional args are already seen at this point
|
||||
// if the input is valid, we can simply append to the positional
|
||||
// args. And remember the names.
|
||||
let slot = args.len();
|
||||
names.insert(ident.name, slot);
|
||||
args.push(e);
|
||||
}
|
||||
_ => {
|
||||
let e = p.parse_expr()?;
|
||||
if named {
|
||||
let mut err = ecx.struct_span_err(
|
||||
e.span,
|
||||
"positional arguments cannot follow named arguments",
|
||||
);
|
||||
err.span_label(e.span, "positional arguments must be before named arguments");
|
||||
for pos in names.values() {
|
||||
err.span_label(args[*pos].span, "named argument");
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
args.push(e);
|
||||
}
|
||||
args.push(e);
|
||||
}
|
||||
}
|
||||
Ok((fmtstr, args, names))
|
||||
|
@ -37,7 +37,6 @@ use rustc_codegen_ssa::traits::*;
|
||||
use rustc_data_structures::const_cstr;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::small_c_str::SmallCStr;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_fs_util::path_to_c_string;
|
||||
use rustc_hir::def::CtorKind;
|
||||
@ -49,7 +48,6 @@ use rustc_target::abi::HasDataLayout;
|
||||
|
||||
use libc::{c_longlong, c_uint};
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::ffi::CString;
|
||||
use std::fmt::{self, Write};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::iter;
|
||||
@ -227,11 +225,11 @@ impl TypeMap<'ll, 'tcx> {
|
||||
/// Gets the unique type ID string for an enum variant part.
|
||||
/// Variant parts are not types and shouldn't really have their own ID,
|
||||
/// but it makes `set_members_of_composite_type()` simpler.
|
||||
fn get_unique_type_id_str_of_enum_variant_part(&mut self, enum_type_id: UniqueTypeId) -> &str {
|
||||
let variant_part_type_id =
|
||||
format!("{}_variant_part", self.get_unique_type_id_as_string(enum_type_id));
|
||||
let interner_key = self.unique_id_interner.intern(&variant_part_type_id);
|
||||
self.unique_id_interner.get(interner_key)
|
||||
fn get_unique_type_id_str_of_enum_variant_part(
|
||||
&mut self,
|
||||
enum_type_id: UniqueTypeId,
|
||||
) -> String {
|
||||
format!("{}_variant_part", self.get_unique_type_id_as_string(enum_type_id))
|
||||
}
|
||||
}
|
||||
|
||||
@ -640,9 +638,11 @@ pub fn type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, usage_site_span: Sp
|
||||
// type is going to see *something* weird - the only
|
||||
// question is what exactly it will see.
|
||||
let (size, align) = cx.size_and_align_of(t);
|
||||
let name = "<recur_type>";
|
||||
llvm::LLVMRustDIBuilderCreateBasicType(
|
||||
DIB(cx),
|
||||
SmallCStr::new("<recur_type>").as_ptr(),
|
||||
name.as_ptr().cast(),
|
||||
name.len(),
|
||||
size.bits(),
|
||||
align.bits() as u32,
|
||||
DW_ATE_unsigned,
|
||||
@ -786,16 +786,17 @@ fn file_metadata_raw(
|
||||
let (file_name, directory) = v.key();
|
||||
debug!("file_metadata: file_name: {:?}, directory: {:?}", file_name, directory);
|
||||
|
||||
let file_name = SmallCStr::new(if let Some(file_name) = file_name {
|
||||
&file_name
|
||||
} else {
|
||||
"<unknown>"
|
||||
});
|
||||
let directory =
|
||||
SmallCStr::new(if let Some(directory) = directory { &directory } else { "" });
|
||||
let file_name = file_name.as_deref().unwrap_or("<unknown>");
|
||||
let directory = directory.as_deref().unwrap_or("");
|
||||
|
||||
let file_metadata = unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateFile(DIB(cx), file_name.as_ptr(), directory.as_ptr())
|
||||
llvm::LLVMRustDIBuilderCreateFile(
|
||||
DIB(cx),
|
||||
file_name.as_ptr().cast(),
|
||||
file_name.len(),
|
||||
directory.as_ptr().cast(),
|
||||
directory.len(),
|
||||
)
|
||||
};
|
||||
|
||||
v.insert(file_metadata);
|
||||
@ -819,11 +820,11 @@ fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
|
||||
};
|
||||
|
||||
let (size, align) = cx.size_and_align_of(t);
|
||||
let name = SmallCStr::new(name);
|
||||
let ty_metadata = unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateBasicType(
|
||||
DIB(cx),
|
||||
name.as_ptr(),
|
||||
name.as_ptr().cast(),
|
||||
name.len(),
|
||||
size.bits(),
|
||||
align.bits() as u32,
|
||||
encoding,
|
||||
@ -851,14 +852,15 @@ fn pointer_type_metadata(
|
||||
) -> &'ll DIType {
|
||||
let (pointer_size, pointer_align) = cx.size_and_align_of(pointer_type);
|
||||
let name = compute_debuginfo_type_name(cx.tcx, pointer_type, false);
|
||||
let name = SmallCStr::new(&name);
|
||||
unsafe {
|
||||
llvm::LLVMRustDIBuilderCreatePointerType(
|
||||
DIB(cx),
|
||||
pointee_type_metadata,
|
||||
pointer_size.bits(),
|
||||
pointer_align.bits() as u32,
|
||||
name.as_ptr(),
|
||||
0, // Ignore DWARF address space.
|
||||
name.as_ptr().cast(),
|
||||
name.len(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -889,11 +891,9 @@ pub fn compile_unit_metadata(
|
||||
let producer = format!("clang LLVM ({})", rustc_producer);
|
||||
|
||||
let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
|
||||
let name_in_debuginfo = SmallCStr::new(&name_in_debuginfo);
|
||||
let work_dir = SmallCStr::new(&tcx.sess.working_dir.0.to_string_lossy());
|
||||
let producer = CString::new(producer).unwrap();
|
||||
let work_dir = tcx.sess.working_dir.0.to_string_lossy();
|
||||
let flags = "\0";
|
||||
let split_name = "\0";
|
||||
let split_name = "";
|
||||
|
||||
// FIXME(#60020):
|
||||
//
|
||||
@ -916,19 +916,23 @@ pub fn compile_unit_metadata(
|
||||
unsafe {
|
||||
let file_metadata = llvm::LLVMRustDIBuilderCreateFile(
|
||||
debug_context.builder,
|
||||
name_in_debuginfo.as_ptr(),
|
||||
work_dir.as_ptr(),
|
||||
name_in_debuginfo.as_ptr().cast(),
|
||||
name_in_debuginfo.len(),
|
||||
work_dir.as_ptr().cast(),
|
||||
work_dir.len(),
|
||||
);
|
||||
|
||||
let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
|
||||
debug_context.builder,
|
||||
DW_LANG_RUST,
|
||||
file_metadata,
|
||||
producer.as_ptr(),
|
||||
producer.as_ptr().cast(),
|
||||
producer.len(),
|
||||
tcx.sess.opts.optimize != config::OptLevel::No,
|
||||
flags.as_ptr().cast(),
|
||||
0,
|
||||
split_name.as_ptr().cast(),
|
||||
split_name.len(),
|
||||
kind,
|
||||
);
|
||||
|
||||
@ -1021,12 +1025,12 @@ impl<'ll> MemberDescription<'ll> {
|
||||
cx: &CodegenCx<'ll, '_>,
|
||||
composite_type_metadata: &'ll DIScope,
|
||||
) -> &'ll DIType {
|
||||
let member_name = CString::new(self.name).unwrap();
|
||||
unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateVariantMemberType(
|
||||
DIB(cx),
|
||||
composite_type_metadata,
|
||||
member_name.as_ptr(),
|
||||
self.name.as_ptr().cast(),
|
||||
self.name.len(),
|
||||
unknown_file_metadata(cx),
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
self.size.bits(),
|
||||
@ -1827,9 +1831,13 @@ fn prepare_enum_metadata(
|
||||
let discriminant_base_type_metadata =
|
||||
type_metadata(cx, discr.to_ty(cx.tcx), rustc_span::DUMMY_SP);
|
||||
|
||||
let item_name;
|
||||
let discriminant_name = match enum_type.kind {
|
||||
ty::Adt(..) => SmallCStr::new(&cx.tcx.item_name(enum_def_id).as_str()),
|
||||
ty::Generator(..) => SmallCStr::new(&enum_name),
|
||||
ty::Adt(..) => {
|
||||
item_name = cx.tcx.item_name(enum_def_id).as_str();
|
||||
&*item_name
|
||||
}
|
||||
ty::Generator(..) => enum_name.as_str(),
|
||||
_ => bug!(),
|
||||
};
|
||||
|
||||
@ -1837,7 +1845,8 @@ fn prepare_enum_metadata(
|
||||
llvm::LLVMRustDIBuilderCreateEnumerationType(
|
||||
DIB(cx),
|
||||
containing_scope,
|
||||
discriminant_name.as_ptr(),
|
||||
discriminant_name.as_ptr().cast(),
|
||||
discriminant_name.len(),
|
||||
file_metadata,
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
discriminant_size.bits(),
|
||||
@ -1872,11 +1881,6 @@ fn prepare_enum_metadata(
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let enum_name = SmallCStr::new(&enum_name);
|
||||
let unique_type_id_str = SmallCStr::new(
|
||||
debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id),
|
||||
);
|
||||
|
||||
if use_enum_fallback(cx) {
|
||||
let discriminant_type_metadata = match layout.variants {
|
||||
layout::Variants::Single { .. }
|
||||
@ -1891,20 +1895,27 @@ fn prepare_enum_metadata(
|
||||
} => Some(discriminant_type_metadata(discr.value)),
|
||||
};
|
||||
|
||||
let enum_metadata = unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateUnionType(
|
||||
DIB(cx),
|
||||
containing_scope,
|
||||
enum_name.as_ptr(),
|
||||
file_metadata,
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
layout.size.bits(),
|
||||
layout.align.abi.bits() as u32,
|
||||
DIFlags::FlagZero,
|
||||
None,
|
||||
0, // RuntimeLang
|
||||
unique_type_id_str.as_ptr(),
|
||||
)
|
||||
let enum_metadata = {
|
||||
let type_map = debug_context(cx).type_map.borrow();
|
||||
let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id);
|
||||
|
||||
unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateUnionType(
|
||||
DIB(cx),
|
||||
containing_scope,
|
||||
enum_name.as_ptr().cast(),
|
||||
enum_name.len(),
|
||||
file_metadata,
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
layout.size.bits(),
|
||||
layout.align.abi.bits() as u32,
|
||||
DIFlags::FlagZero,
|
||||
None,
|
||||
0, // RuntimeLang
|
||||
unique_type_id_str.as_ptr().cast(),
|
||||
unique_type_id_str.len(),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
return create_and_register_recursive_type_forward_declaration(
|
||||
@ -1924,10 +1935,9 @@ fn prepare_enum_metadata(
|
||||
}
|
||||
|
||||
let discriminator_name = match &enum_type.kind {
|
||||
ty::Generator(..) => Some(SmallCStr::new(&"__state")),
|
||||
_ => None,
|
||||
ty::Generator(..) => "__state",
|
||||
_ => "",
|
||||
};
|
||||
let discriminator_name = discriminator_name.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut());
|
||||
let discriminator_metadata = match layout.variants {
|
||||
// A single-variant enum has no discriminant.
|
||||
layout::Variants::Single { .. } => None,
|
||||
@ -1955,7 +1965,8 @@ fn prepare_enum_metadata(
|
||||
Some(llvm::LLVMRustDIBuilderCreateMemberType(
|
||||
DIB(cx),
|
||||
containing_scope,
|
||||
discriminator_name,
|
||||
discriminator_name.as_ptr().cast(),
|
||||
discriminator_name.len(),
|
||||
file_metadata,
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
size.bits(),
|
||||
@ -1981,7 +1992,8 @@ fn prepare_enum_metadata(
|
||||
Some(llvm::LLVMRustDIBuilderCreateMemberType(
|
||||
DIB(cx),
|
||||
containing_scope,
|
||||
discriminator_name,
|
||||
discriminator_name.as_ptr().cast(),
|
||||
discriminator_name.len(),
|
||||
file_metadata,
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
size.bits(),
|
||||
@ -2010,18 +2022,18 @@ fn prepare_enum_metadata(
|
||||
}
|
||||
};
|
||||
|
||||
let variant_part_unique_type_id_str = SmallCStr::new(
|
||||
debug_context(cx)
|
||||
.type_map
|
||||
.borrow_mut()
|
||||
.get_unique_type_id_str_of_enum_variant_part(unique_type_id),
|
||||
);
|
||||
let variant_part_unique_type_id_str = debug_context(cx)
|
||||
.type_map
|
||||
.borrow_mut()
|
||||
.get_unique_type_id_str_of_enum_variant_part(unique_type_id);
|
||||
let empty_array = create_DIArray(DIB(cx), &[]);
|
||||
let name = "";
|
||||
let variant_part = unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateVariantPart(
|
||||
DIB(cx),
|
||||
containing_scope,
|
||||
ptr::null_mut(),
|
||||
name.as_ptr().cast(),
|
||||
name.len(),
|
||||
file_metadata,
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
layout.size.bits(),
|
||||
@ -2029,29 +2041,38 @@ fn prepare_enum_metadata(
|
||||
DIFlags::FlagZero,
|
||||
discriminator_metadata,
|
||||
empty_array,
|
||||
variant_part_unique_type_id_str.as_ptr(),
|
||||
variant_part_unique_type_id_str.as_ptr().cast(),
|
||||
variant_part_unique_type_id_str.len(),
|
||||
)
|
||||
};
|
||||
outer_fields.push(Some(variant_part));
|
||||
|
||||
// The variant part must be wrapped in a struct according to DWARF.
|
||||
let type_array = create_DIArray(DIB(cx), &outer_fields);
|
||||
let struct_wrapper = unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateStructType(
|
||||
DIB(cx),
|
||||
Some(containing_scope),
|
||||
enum_name.as_ptr(),
|
||||
file_metadata,
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
layout.size.bits(),
|
||||
layout.align.abi.bits() as u32,
|
||||
DIFlags::FlagZero,
|
||||
None,
|
||||
type_array,
|
||||
0,
|
||||
None,
|
||||
unique_type_id_str.as_ptr(),
|
||||
)
|
||||
let struct_wrapper = {
|
||||
// The variant part must be wrapped in a struct according to DWARF.
|
||||
let type_array = create_DIArray(DIB(cx), &outer_fields);
|
||||
|
||||
let type_map = debug_context(cx).type_map.borrow();
|
||||
let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id);
|
||||
|
||||
unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateStructType(
|
||||
DIB(cx),
|
||||
Some(containing_scope),
|
||||
enum_name.as_ptr().cast(),
|
||||
enum_name.len(),
|
||||
file_metadata,
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
layout.size.bits(),
|
||||
layout.align.abi.bits() as u32,
|
||||
DIFlags::FlagZero,
|
||||
None,
|
||||
type_array,
|
||||
0,
|
||||
None,
|
||||
unique_type_id_str.as_ptr().cast(),
|
||||
unique_type_id_str.len(),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
return create_and_register_recursive_type_forward_declaration(
|
||||
@ -2156,12 +2177,13 @@ fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> Option<&'
|
||||
cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
|
||||
let actual_type_metadata =
|
||||
type_metadata(cx, actual_type, rustc_span::DUMMY_SP);
|
||||
let name = SmallCStr::new(&name.as_str());
|
||||
let name = &name.as_str();
|
||||
Some(unsafe {
|
||||
Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
|
||||
DIB(cx),
|
||||
None,
|
||||
name.as_ptr(),
|
||||
name.as_ptr().cast(),
|
||||
name.len(),
|
||||
actual_type_metadata,
|
||||
unknown_file_metadata(cx),
|
||||
0,
|
||||
@ -2200,10 +2222,9 @@ fn create_struct_stub(
|
||||
) -> &'ll DICompositeType {
|
||||
let (struct_size, struct_align) = cx.size_and_align_of(struct_type);
|
||||
|
||||
let name = SmallCStr::new(struct_type_name);
|
||||
let unique_type_id = SmallCStr::new(
|
||||
debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id),
|
||||
);
|
||||
let type_map = debug_context(cx).type_map.borrow();
|
||||
let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id);
|
||||
|
||||
let metadata_stub = unsafe {
|
||||
// `LLVMRustDIBuilderCreateStructType()` wants an empty array. A null
|
||||
// pointer will lead to hard to trace and debug LLVM assertions
|
||||
@ -2213,7 +2234,8 @@ fn create_struct_stub(
|
||||
llvm::LLVMRustDIBuilderCreateStructType(
|
||||
DIB(cx),
|
||||
containing_scope,
|
||||
name.as_ptr(),
|
||||
struct_type_name.as_ptr().cast(),
|
||||
struct_type_name.len(),
|
||||
unknown_file_metadata(cx),
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
struct_size.bits(),
|
||||
@ -2223,7 +2245,8 @@ fn create_struct_stub(
|
||||
empty_array,
|
||||
0,
|
||||
None,
|
||||
unique_type_id.as_ptr(),
|
||||
unique_type_id.as_ptr().cast(),
|
||||
unique_type_id.len(),
|
||||
)
|
||||
};
|
||||
|
||||
@ -2239,10 +2262,9 @@ fn create_union_stub(
|
||||
) -> &'ll DICompositeType {
|
||||
let (union_size, union_align) = cx.size_and_align_of(union_type);
|
||||
|
||||
let name = SmallCStr::new(union_type_name);
|
||||
let unique_type_id = SmallCStr::new(
|
||||
debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id),
|
||||
);
|
||||
let type_map = debug_context(cx).type_map.borrow();
|
||||
let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id);
|
||||
|
||||
let metadata_stub = unsafe {
|
||||
// `LLVMRustDIBuilderCreateUnionType()` wants an empty array. A null
|
||||
// pointer will lead to hard to trace and debug LLVM assertions
|
||||
@ -2252,7 +2274,8 @@ fn create_union_stub(
|
||||
llvm::LLVMRustDIBuilderCreateUnionType(
|
||||
DIB(cx),
|
||||
containing_scope,
|
||||
name.as_ptr(),
|
||||
union_type_name.as_ptr().cast(),
|
||||
union_type_name.len(),
|
||||
unknown_file_metadata(cx),
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
union_size.bits(),
|
||||
@ -2260,7 +2283,8 @@ fn create_union_stub(
|
||||
DIFlags::FlagZero,
|
||||
Some(empty_array),
|
||||
0, // RuntimeLang
|
||||
unique_type_id.as_ptr(),
|
||||
unique_type_id.as_ptr().cast(),
|
||||
unique_type_id.len(),
|
||||
)
|
||||
};
|
||||
|
||||
@ -2294,13 +2318,15 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global
|
||||
let is_local_to_unit = is_node_local_to_unit(cx, def_id);
|
||||
let variable_type = Instance::mono(cx.tcx, def_id).monomorphic_ty(cx.tcx);
|
||||
let type_metadata = type_metadata(cx, variable_type, span);
|
||||
let var_name = SmallCStr::new(&tcx.item_name(def_id).as_str());
|
||||
let var_name = tcx.item_name(def_id).as_str();
|
||||
let linkage_name = if no_mangle {
|
||||
None
|
||||
} else {
|
||||
let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id));
|
||||
Some(SmallCStr::new(&linkage_name.name.as_str()))
|
||||
Some(mangled_name_of_instance(cx, Instance::mono(tcx, def_id)).name.as_str())
|
||||
};
|
||||
// When empty, linkage_name field is omitted,
|
||||
// which is what we want for no_mangle statics
|
||||
let linkage_name = linkage_name.as_deref().unwrap_or("");
|
||||
|
||||
let global_align = cx.align_of(variable_type);
|
||||
|
||||
@ -2308,10 +2334,10 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global
|
||||
llvm::LLVMRustDIBuilderCreateStaticVariable(
|
||||
DIB(cx),
|
||||
Some(var_scope),
|
||||
var_name.as_ptr(),
|
||||
// If null, linkage_name field is omitted,
|
||||
// which is what we want for no_mangle statics
|
||||
linkage_name.as_ref().map_or(ptr::null(), |name| name.as_ptr()),
|
||||
var_name.as_ptr().cast(),
|
||||
var_name.len(),
|
||||
linkage_name.as_ptr().cast(),
|
||||
linkage_name.len(),
|
||||
file_metadata,
|
||||
line_number,
|
||||
type_metadata,
|
||||
@ -2339,8 +2365,7 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: &
|
||||
// pointer will lead to hard to trace and debug LLVM assertions
|
||||
// later on in `llvm/lib/IR/Value.cpp`.
|
||||
let empty_array = create_DIArray(DIB(cx), &[]);
|
||||
|
||||
let name = const_cstr!("vtable");
|
||||
let name = "vtable";
|
||||
|
||||
// Create a new one each time. We don't want metadata caching
|
||||
// here, because each vtable will refer to a unique containing
|
||||
@ -2348,7 +2373,8 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: &
|
||||
let vtable_type = llvm::LLVMRustDIBuilderCreateStructType(
|
||||
DIB(cx),
|
||||
NO_SCOPE_METADATA,
|
||||
name.as_ptr(),
|
||||
name.as_ptr().cast(),
|
||||
name.len(),
|
||||
unknown_file_metadata(cx),
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
Size::ZERO.bits(),
|
||||
@ -2358,14 +2384,18 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: &
|
||||
empty_array,
|
||||
0,
|
||||
Some(type_metadata),
|
||||
name.as_ptr(),
|
||||
name.as_ptr().cast(),
|
||||
name.len(),
|
||||
);
|
||||
|
||||
let linkage_name = "";
|
||||
llvm::LLVMRustDIBuilderCreateStaticVariable(
|
||||
DIB(cx),
|
||||
NO_SCOPE_METADATA,
|
||||
name.as_ptr(),
|
||||
ptr::null(),
|
||||
name.as_ptr().cast(),
|
||||
name.len(),
|
||||
linkage_name.as_ptr().cast(),
|
||||
linkage_name.len(),
|
||||
unknown_file_metadata(cx),
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
vtable_type,
|
||||
|
@ -25,13 +25,11 @@ use rustc::ty::{self, Instance, ParamEnv, Ty};
|
||||
use rustc_codegen_ssa::debuginfo::type_names;
|
||||
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::small_c_str::SmallCStr;
|
||||
use rustc_index::vec::IndexVec;
|
||||
|
||||
use libc::c_uint;
|
||||
use log::debug;
|
||||
use std::cell::RefCell;
|
||||
use std::ffi::CString;
|
||||
|
||||
use rustc::ty::layout::{self, HasTyCtxt, LayoutOf, Size};
|
||||
use rustc_ast::ast;
|
||||
@ -273,13 +271,11 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
|
||||
// Get the linkage_name, which is just the symbol name
|
||||
let linkage_name = mangled_name_of_instance(self, instance);
|
||||
let linkage_name = linkage_name.name.as_str();
|
||||
|
||||
// FIXME(eddyb) does this need to be separate from `loc.line` for some reason?
|
||||
let scope_line = loc.line;
|
||||
|
||||
let function_name = CString::new(name).unwrap();
|
||||
let linkage_name = SmallCStr::new(&linkage_name.name.as_str());
|
||||
|
||||
let mut flags = DIFlags::FlagPrototyped;
|
||||
|
||||
if fn_abi.ret.layout.abi.is_uninhabited() {
|
||||
@ -303,8 +299,10 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
llvm::LLVMRustDIBuilderCreateFunction(
|
||||
DIB(self),
|
||||
containing_scope,
|
||||
function_name.as_ptr(),
|
||||
linkage_name.as_ptr(),
|
||||
name.as_ptr().cast(),
|
||||
name.len(),
|
||||
linkage_name.as_ptr().cast(),
|
||||
linkage_name.len(),
|
||||
file_metadata,
|
||||
loc.line as c_uint,
|
||||
function_type_metadata,
|
||||
@ -424,12 +422,13 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
|
||||
let actual_type_metadata =
|
||||
type_metadata(cx, actual_type, rustc_span::DUMMY_SP);
|
||||
let name = SmallCStr::new(&name.as_str());
|
||||
let name = name.as_str();
|
||||
Some(unsafe {
|
||||
Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
|
||||
DIB(cx),
|
||||
None,
|
||||
name.as_ptr(),
|
||||
name.as_ptr().cast(),
|
||||
name.len(),
|
||||
actual_type_metadata,
|
||||
file_metadata,
|
||||
0,
|
||||
@ -542,13 +541,14 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
};
|
||||
let align = self.align_of(variable_type);
|
||||
|
||||
let name = SmallCStr::new(&variable_name.as_str());
|
||||
let name = variable_name.as_str();
|
||||
unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateVariable(
|
||||
DIB(self),
|
||||
dwarf_tag,
|
||||
scope_metadata,
|
||||
name.as_ptr(),
|
||||
name.as_ptr().cast(),
|
||||
name.len(),
|
||||
file_metadata,
|
||||
loc.line as c_uint,
|
||||
type_metadata,
|
||||
|
@ -1,6 +1,5 @@
|
||||
// Namespace Handling.
|
||||
|
||||
use super::metadata::{unknown_file_metadata, UNKNOWN_LINE_NUMBER};
|
||||
use super::utils::{debug_context, DIB};
|
||||
use rustc::ty::{self, Instance};
|
||||
|
||||
@ -10,8 +9,6 @@ use crate::llvm::debuginfo::DIScope;
|
||||
use rustc::hir::map::DefPathData;
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
||||
use rustc_data_structures::small_c_str::SmallCStr;
|
||||
|
||||
pub fn mangled_name_of_instance<'a, 'tcx>(
|
||||
cx: &CodegenCx<'a, 'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
@ -34,16 +31,15 @@ pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope {
|
||||
DefPathData::CrateRoot => cx.tcx.crate_name(def_id.krate),
|
||||
data => data.as_symbol(),
|
||||
};
|
||||
|
||||
let namespace_name = SmallCStr::new(&namespace_name.as_str());
|
||||
let namespace_name = namespace_name.as_str();
|
||||
|
||||
let scope = unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateNameSpace(
|
||||
DIB(cx),
|
||||
parent_scope,
|
||||
namespace_name.as_ptr(),
|
||||
unknown_file_metadata(cx),
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
namespace_name.as_ptr().cast(),
|
||||
namespace_name.len(),
|
||||
false, // ExportSymbols (only relevant for C++ anonymous namespaces)
|
||||
)
|
||||
};
|
||||
|
||||
|
@ -1607,17 +1607,21 @@ extern "C" {
|
||||
Lang: c_uint,
|
||||
File: &'a DIFile,
|
||||
Producer: *const c_char,
|
||||
ProducerLen: size_t,
|
||||
isOptimized: bool,
|
||||
Flags: *const c_char,
|
||||
RuntimeVer: c_uint,
|
||||
SplitName: *const c_char,
|
||||
SplitNameLen: size_t,
|
||||
kind: DebugEmissionKind,
|
||||
) -> &'a DIDescriptor;
|
||||
|
||||
pub fn LLVMRustDIBuilderCreateFile(
|
||||
Builder: &DIBuilder<'a>,
|
||||
Filename: *const c_char,
|
||||
FilenameLen: size_t,
|
||||
Directory: *const c_char,
|
||||
DirectoryLen: size_t,
|
||||
) -> &'a DIFile;
|
||||
|
||||
pub fn LLVMRustDIBuilderCreateSubroutineType(
|
||||
@ -1630,7 +1634,9 @@ extern "C" {
|
||||
Builder: &DIBuilder<'a>,
|
||||
Scope: &'a DIDescriptor,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
LinkageName: *const c_char,
|
||||
LinkageNameLen: size_t,
|
||||
File: &'a DIFile,
|
||||
LineNo: c_uint,
|
||||
Ty: &'a DIType,
|
||||
@ -1645,6 +1651,7 @@ extern "C" {
|
||||
pub fn LLVMRustDIBuilderCreateBasicType(
|
||||
Builder: &DIBuilder<'a>,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
SizeInBits: u64,
|
||||
AlignInBits: u32,
|
||||
Encoding: c_uint,
|
||||
@ -1655,13 +1662,16 @@ extern "C" {
|
||||
PointeeTy: &'a DIType,
|
||||
SizeInBits: u64,
|
||||
AlignInBits: u32,
|
||||
AddressSpace: c_uint,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
) -> &'a DIDerivedType;
|
||||
|
||||
pub fn LLVMRustDIBuilderCreateStructType(
|
||||
Builder: &DIBuilder<'a>,
|
||||
Scope: Option<&'a DIDescriptor>,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
File: &'a DIFile,
|
||||
LineNumber: c_uint,
|
||||
SizeInBits: u64,
|
||||
@ -1672,12 +1682,14 @@ extern "C" {
|
||||
RunTimeLang: c_uint,
|
||||
VTableHolder: Option<&'a DIType>,
|
||||
UniqueId: *const c_char,
|
||||
UniqueIdLen: size_t,
|
||||
) -> &'a DICompositeType;
|
||||
|
||||
pub fn LLVMRustDIBuilderCreateMemberType(
|
||||
Builder: &DIBuilder<'a>,
|
||||
Scope: &'a DIDescriptor,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
File: &'a DIFile,
|
||||
LineNo: c_uint,
|
||||
SizeInBits: u64,
|
||||
@ -1691,6 +1703,7 @@ extern "C" {
|
||||
Builder: &DIBuilder<'a>,
|
||||
Scope: &'a DIScope,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
File: &'a DIFile,
|
||||
LineNumber: c_uint,
|
||||
SizeInBits: u64,
|
||||
@ -1719,7 +1732,9 @@ extern "C" {
|
||||
Builder: &DIBuilder<'a>,
|
||||
Context: Option<&'a DIScope>,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
LinkageName: *const c_char,
|
||||
LinkageNameLen: size_t,
|
||||
File: &'a DIFile,
|
||||
LineNo: c_uint,
|
||||
Ty: &'a DIType,
|
||||
@ -1734,6 +1749,7 @@ extern "C" {
|
||||
Tag: c_uint,
|
||||
Scope: &'a DIDescriptor,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
File: &'a DIFile,
|
||||
LineNo: c_uint,
|
||||
Ty: &'a DIType,
|
||||
@ -1785,6 +1801,7 @@ extern "C" {
|
||||
Builder: &DIBuilder<'a>,
|
||||
Scope: &'a DIScope,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
File: &'a DIFile,
|
||||
LineNumber: c_uint,
|
||||
SizeInBits: u64,
|
||||
@ -1798,6 +1815,7 @@ extern "C" {
|
||||
Builder: &DIBuilder<'a>,
|
||||
Scope: &'a DIScope,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
File: &'a DIFile,
|
||||
LineNumber: c_uint,
|
||||
SizeInBits: u64,
|
||||
@ -1806,12 +1824,14 @@ extern "C" {
|
||||
Elements: Option<&'a DIArray>,
|
||||
RunTimeLang: c_uint,
|
||||
UniqueId: *const c_char,
|
||||
UniqueIdLen: size_t,
|
||||
) -> &'a DIType;
|
||||
|
||||
pub fn LLVMRustDIBuilderCreateVariantPart(
|
||||
Builder: &DIBuilder<'a>,
|
||||
Scope: &'a DIScope,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
File: &'a DIFile,
|
||||
LineNo: c_uint,
|
||||
SizeInBits: u64,
|
||||
@ -1820,6 +1840,7 @@ extern "C" {
|
||||
Discriminator: Option<&'a DIDerivedType>,
|
||||
Elements: &'a DIArray,
|
||||
UniqueId: *const c_char,
|
||||
UniqueIdLen: size_t,
|
||||
) -> &'a DIDerivedType;
|
||||
|
||||
pub fn LLVMSetUnnamedAddr(GlobalVar: &Value, UnnamedAddr: Bool);
|
||||
@ -1828,6 +1849,7 @@ extern "C" {
|
||||
Builder: &DIBuilder<'a>,
|
||||
Scope: Option<&'a DIScope>,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
Ty: &'a DIType,
|
||||
File: &'a DIFile,
|
||||
LineNo: c_uint,
|
||||
@ -1838,8 +1860,8 @@ extern "C" {
|
||||
Builder: &DIBuilder<'a>,
|
||||
Scope: Option<&'a DIScope>,
|
||||
Name: *const c_char,
|
||||
File: &'a DIFile,
|
||||
LineNo: c_uint,
|
||||
NameLen: size_t,
|
||||
ExportSymbols: bool,
|
||||
) -> &'a DINameSpace;
|
||||
|
||||
pub fn LLVMRustDICompositeTypeReplaceArrays(
|
||||
|
@ -750,17 +750,8 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
|
||||
|
||||
/// The token is an identifier, but not `_`.
|
||||
/// We prohibit passing `_` to macros expecting `ident` for now.
|
||||
fn get_macro_name(token: &Token) -> Option<(Name, bool)> {
|
||||
match token.kind {
|
||||
token::Ident(name, is_raw) if name != kw::Underscore => Some((name, is_raw)),
|
||||
token::Interpolated(ref nt) => match **nt {
|
||||
token::NtIdent(ident, is_raw) if ident.name != kw::Underscore => {
|
||||
Some((ident.name, is_raw))
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
fn get_macro_ident(token: &Token) -> Option<(Ident, bool)> {
|
||||
token.ident().filter(|(ident, _)| ident.name != kw::Underscore)
|
||||
}
|
||||
|
||||
/// Checks whether a non-terminal may begin with a particular token.
|
||||
@ -783,7 +774,7 @@ fn may_begin_with(token: &Token, name: Name) -> bool {
|
||||
&& !token.is_keyword(kw::Let)
|
||||
}
|
||||
sym::ty => token.can_begin_type(),
|
||||
sym::ident => get_macro_name(token).is_some(),
|
||||
sym::ident => get_macro_ident(token).is_some(),
|
||||
sym::literal => token.can_begin_literal_or_bool(),
|
||||
sym::vis => match token.kind {
|
||||
// The follow-set of :vis + "priv" keyword + interpolated
|
||||
@ -888,9 +879,9 @@ fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a,
|
||||
sym::ty => token::NtTy(p.parse_ty()?),
|
||||
// this could be handled like a token, since it is one
|
||||
sym::ident => {
|
||||
if let Some((name, is_raw)) = get_macro_name(&p.token) {
|
||||
if let Some((ident, is_raw)) = get_macro_ident(&p.token) {
|
||||
p.bump();
|
||||
token::NtIdent(Ident::new(name, p.normalized_prev_token.span), is_raw)
|
||||
token::NtIdent(ident, is_raw)
|
||||
} else {
|
||||
let token_str = pprust::token_to_string(&p.token);
|
||||
let msg = &format!("expected ident, found {}", &token_str);
|
||||
|
@ -186,7 +186,12 @@ fn validate_and_turn_into_const<'tcx>(
|
||||
if cid.promoted.is_none() {
|
||||
let mut ref_tracking = RefTracking::new(mplace);
|
||||
while let Some((mplace, path)) = ref_tracking.todo.pop() {
|
||||
ecx.validate_operand(mplace.into(), path, Some(&mut ref_tracking))?;
|
||||
ecx.const_validate_operand(
|
||||
mplace.into(),
|
||||
path,
|
||||
&mut ref_tracking,
|
||||
/*may_ref_to_static*/ is_static,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
// Now that we validated, turn this into a proper constant.
|
||||
|
@ -457,10 +457,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
|
||||
// Check if this brought us over the size limit.
|
||||
if size.bytes() >= self.tcx.data_layout().obj_size_bound() {
|
||||
throw_ub_format!(
|
||||
"wide pointer metadata contains invalid information: \
|
||||
total size is bigger than largest supported object"
|
||||
);
|
||||
throw_ub!(InvalidMeta("total size is bigger than largest supported object"));
|
||||
}
|
||||
Ok(Some((size, align)))
|
||||
}
|
||||
@ -476,10 +473,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
|
||||
// Make sure the slice is not too big.
|
||||
let size = elem.size.checked_mul(len, &*self.tcx).ok_or_else(|| {
|
||||
err_ub_format!(
|
||||
"invalid slice: \
|
||||
total size is bigger than largest supported object"
|
||||
)
|
||||
err_ub!(InvalidMeta("slice is bigger than largest supported object"))
|
||||
})?;
|
||||
Ok(Some((size, elem.align.abi)))
|
||||
}
|
||||
@ -685,7 +679,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
// invariant -- that is, unless a function somehow has a ptr to
|
||||
// its return place... but the way MIR is currently generated, the
|
||||
// return place is always a local and then this cannot happen.
|
||||
self.validate_operand(self.place_to_op(return_place)?, vec![], None)?;
|
||||
self.validate_operand(self.place_to_op(return_place)?)?;
|
||||
}
|
||||
} else {
|
||||
// Uh, that shouldn't happen... the function did not intend to return
|
||||
|
@ -689,7 +689,7 @@ where
|
||||
|
||||
if M::enforce_validity(self) {
|
||||
// Data got changed, better make sure it matches the type!
|
||||
self.validate_operand(self.place_to_op(dest)?, vec![], None)?;
|
||||
self.validate_operand(self.place_to_op(dest)?)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -706,7 +706,7 @@ where
|
||||
|
||||
if M::enforce_validity(self) {
|
||||
// Data got changed, better make sure it matches the type!
|
||||
self.validate_operand(dest.into(), vec![], None)?;
|
||||
self.validate_operand(dest.into())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -843,7 +843,7 @@ where
|
||||
|
||||
if M::enforce_validity(self) {
|
||||
// Data got changed, better make sure it matches the type!
|
||||
self.validate_operand(self.place_to_op(dest)?, vec![], None)?;
|
||||
self.validate_operand(self.place_to_op(dest)?)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -951,7 +951,7 @@ where
|
||||
|
||||
if M::enforce_validity(self) {
|
||||
// Data got changed, better make sure it matches the type!
|
||||
self.validate_operand(dest.into(), vec![], None)?;
|
||||
self.validate_operand(dest.into())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -46,6 +46,8 @@ macro_rules! try_validation {
|
||||
($e:expr, $what:expr, $where:expr, $details:expr) => {{
|
||||
match $e {
|
||||
Ok(x) => x,
|
||||
// We re-throw the error, so we are okay with allocation:
|
||||
// this can only slow down builds that fail anyway.
|
||||
Err(_) => throw_validation_failure!($what, $where, $details),
|
||||
}
|
||||
}};
|
||||
@ -53,6 +55,8 @@ macro_rules! try_validation {
|
||||
($e:expr, $what:expr, $where:expr) => {{
|
||||
match $e {
|
||||
Ok(x) => x,
|
||||
// We re-throw the error, so we are okay with allocation:
|
||||
// this can only slow down builds that fail anyway.
|
||||
Err(_) => throw_validation_failure!($what, $where),
|
||||
}
|
||||
}};
|
||||
@ -167,6 +171,7 @@ struct ValidityVisitor<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
|
||||
path: Vec<PathElem>,
|
||||
ref_tracking_for_consts:
|
||||
Option<&'rt mut RefTracking<MPlaceTy<'tcx, M::PointerTag>, Vec<PathElem>>>,
|
||||
may_ref_to_static: bool,
|
||||
ecx: &'rt InterpCx<'mir, 'tcx, M>,
|
||||
}
|
||||
|
||||
@ -320,9 +325,17 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
|
||||
self.check_wide_ptr_meta(place.meta, place.layout)?;
|
||||
}
|
||||
// Make sure this is dereferenceable and all.
|
||||
let (size, align) = self
|
||||
.ecx
|
||||
.size_and_align_of(place.meta, place.layout)?
|
||||
let size_and_align = match self.ecx.size_and_align_of(place.meta, place.layout) {
|
||||
Ok(res) => res,
|
||||
Err(err) => match err.kind {
|
||||
err_ub!(InvalidMeta(msg)) => throw_validation_failure!(
|
||||
format_args!("invalid {} metadata: {}", kind, msg),
|
||||
self.path
|
||||
),
|
||||
_ => bug!("Unexpected error during ptr size_and_align_of: {}", err),
|
||||
},
|
||||
};
|
||||
let (size, align) = size_and_align
|
||||
// for the purpose of validity, consider foreign types to have
|
||||
// alignment and size determined by the layout (size will be 0,
|
||||
// alignment should take attributes into account).
|
||||
@ -359,10 +372,13 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
|
||||
format_args!("a dangling {} (created from integer)", kind),
|
||||
self.path
|
||||
),
|
||||
_ => throw_validation_failure!(
|
||||
format_args!("a dangling {} (not entirely in bounds)", kind),
|
||||
self.path
|
||||
),
|
||||
err_unsup!(PointerOutOfBounds { .. }) | err_unsup!(DanglingPointerDeref) => {
|
||||
throw_validation_failure!(
|
||||
format_args!("a dangling {} (not entirely in bounds)", kind),
|
||||
self.path
|
||||
)
|
||||
}
|
||||
_ => bug!("Unexpected error during ptr inbounds test: {}", err),
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -380,6 +396,12 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
|
||||
if !did.is_local() || self.ecx.tcx.is_foreign_item(did) {
|
||||
return Ok(());
|
||||
}
|
||||
if !self.may_ref_to_static && self.ecx.tcx.is_static(did) {
|
||||
throw_validation_failure!(
|
||||
format_args!("a {} pointing to a static variable", kind),
|
||||
self.path
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Proceed recursively even for ZST, no reason to skip them!
|
||||
@ -638,6 +660,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
||||
err_unsup!(ReadPointerAsBytes) => {
|
||||
throw_validation_failure!("a pointer", self.path, "plain (non-pointer) bytes")
|
||||
}
|
||||
// Propagate upwards (that will also check for unexpected errors).
|
||||
_ => return Err(err),
|
||||
},
|
||||
}
|
||||
@ -773,31 +796,59 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
/// This function checks the data at `op`. `op` is assumed to cover valid memory if it
|
||||
/// is an indirect operand.
|
||||
/// It will error if the bits at the destination do not match the ones described by the layout.
|
||||
///
|
||||
/// `ref_tracking_for_consts` can be `None` to avoid recursive checking below references.
|
||||
/// This also toggles between "run-time" (no recursion) and "compile-time" (with recursion)
|
||||
/// validation (e.g., pointer values are fine in integers at runtime) and various other const
|
||||
/// specific validation checks.
|
||||
pub fn validate_operand(
|
||||
fn validate_operand_internal(
|
||||
&self,
|
||||
op: OpTy<'tcx, M::PointerTag>,
|
||||
path: Vec<PathElem>,
|
||||
ref_tracking_for_consts: Option<
|
||||
&mut RefTracking<MPlaceTy<'tcx, M::PointerTag>, Vec<PathElem>>,
|
||||
>,
|
||||
may_ref_to_static: bool,
|
||||
) -> InterpResult<'tcx> {
|
||||
trace!("validate_operand: {:?}, {:?}", *op, op.layout.ty);
|
||||
trace!("validate_operand_internal: {:?}, {:?}", *op, op.layout.ty);
|
||||
|
||||
// Construct a visitor
|
||||
let mut visitor = ValidityVisitor { path, ref_tracking_for_consts, ecx: self };
|
||||
let mut visitor =
|
||||
ValidityVisitor { path, ref_tracking_for_consts, may_ref_to_static, ecx: self };
|
||||
|
||||
// Try to cast to ptr *once* instead of all the time.
|
||||
let op = self.force_op_ptr(op).unwrap_or(op);
|
||||
|
||||
// Run it
|
||||
visitor.visit_value(op)
|
||||
// Run it.
|
||||
match visitor.visit_value(op) {
|
||||
Ok(()) => Ok(()),
|
||||
Err(err) if matches!(err.kind, err_unsup!(ValidationFailure { .. })) => Err(err),
|
||||
Err(err) if cfg!(debug_assertions) => {
|
||||
bug!("Unexpected error during validation: {}", err)
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
/// This function checks the data at `op` to be const-valid.
|
||||
/// `op` is assumed to cover valid memory if it is an indirect operand.
|
||||
/// It will error if the bits at the destination do not match the ones described by the layout.
|
||||
///
|
||||
/// `ref_tracking` is used to record references that we encounter so that they
|
||||
/// can be checked recursively by an outside driving loop.
|
||||
///
|
||||
/// `may_ref_to_static` controls whether references are allowed to point to statics.
|
||||
#[inline(always)]
|
||||
pub fn const_validate_operand(
|
||||
&self,
|
||||
op: OpTy<'tcx, M::PointerTag>,
|
||||
path: Vec<PathElem>,
|
||||
ref_tracking: &mut RefTracking<MPlaceTy<'tcx, M::PointerTag>, Vec<PathElem>>,
|
||||
may_ref_to_static: bool,
|
||||
) -> InterpResult<'tcx> {
|
||||
self.validate_operand_internal(op, path, Some(ref_tracking), may_ref_to_static)
|
||||
}
|
||||
|
||||
/// This function checks the data at `op` to be runtime-valid.
|
||||
/// `op` is assumed to cover valid memory if it is an indirect operand.
|
||||
/// It will error if the bits at the destination do not match the ones described by the layout.
|
||||
#[inline(always)]
|
||||
pub fn validate_operand(&self, op: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> {
|
||||
self.validate_operand_internal(op, vec![], None, false)
|
||||
}
|
||||
}
|
||||
|
@ -404,32 +404,15 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
let r = match f(self) {
|
||||
Ok(val) => Some(val),
|
||||
Err(error) => {
|
||||
use rustc::mir::interpret::{
|
||||
InterpError::*, UndefinedBehaviorInfo, UnsupportedOpInfo,
|
||||
};
|
||||
match error.kind {
|
||||
MachineStop(_) => bug!("ConstProp does not stop"),
|
||||
|
||||
// Some error shouldn't come up because creating them causes
|
||||
// an allocation, which we should avoid. When that happens,
|
||||
// dedicated error variants should be introduced instead.
|
||||
// Only test this in debug builds though to avoid disruptions.
|
||||
Unsupported(UnsupportedOpInfo::Unsupported(_))
|
||||
| Unsupported(UnsupportedOpInfo::ValidationFailure(_))
|
||||
| UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
|
||||
| UndefinedBehavior(UndefinedBehaviorInfo::UbExperimental(_))
|
||||
if cfg!(debug_assertions) =>
|
||||
{
|
||||
bug!("const-prop encountered allocating error: {:?}", error.kind);
|
||||
}
|
||||
|
||||
Unsupported(_)
|
||||
| UndefinedBehavior(_)
|
||||
| InvalidProgram(_)
|
||||
| ResourceExhaustion(_) => {
|
||||
// Ignore these errors.
|
||||
}
|
||||
}
|
||||
// Some errors shouldn't come up because creating them causes
|
||||
// an allocation, which we should avoid. When that happens,
|
||||
// dedicated error variants should be introduced instead.
|
||||
// Only test this in debug builds though to avoid disruptions.
|
||||
debug_assert!(
|
||||
!error.kind.allocates(),
|
||||
"const-prop encountered allocating error: {}",
|
||||
error
|
||||
);
|
||||
None
|
||||
}
|
||||
};
|
||||
@ -654,11 +637,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
source_info: SourceInfo,
|
||||
) {
|
||||
trace!("attepting to replace {:?} with {:?}", rval, value);
|
||||
if let Err(e) = self.ecx.validate_operand(
|
||||
if let Err(e) = self.ecx.const_validate_operand(
|
||||
value,
|
||||
vec![],
|
||||
// FIXME: is ref tracking too expensive?
|
||||
Some(&mut interpret::RefTracking::empty()),
|
||||
&mut interpret::RefTracking::empty(),
|
||||
/*may_ref_to_static*/ true,
|
||||
) {
|
||||
trace!("validation error, attempt failed: {:?}", e);
|
||||
return;
|
||||
|
@ -4,7 +4,7 @@
|
||||
#![feature(crate_visibility_modifier)]
|
||||
|
||||
use rustc_ast::ast;
|
||||
use rustc_ast::token::{self, Nonterminal, Token};
|
||||
use rustc_ast::token::{self, Nonterminal};
|
||||
use rustc_ast::tokenstream::{self, TokenStream, TokenTree};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
@ -171,8 +171,7 @@ fn maybe_source_file_to_parser(
|
||||
let mut parser = stream_to_parser(sess, stream, None);
|
||||
parser.unclosed_delims = unclosed_delims;
|
||||
if parser.token == token::Eof {
|
||||
let span = Span::new(end_pos, end_pos, parser.token.span.ctxt());
|
||||
parser.set_token(Token::new(token::Eof, span));
|
||||
parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt());
|
||||
}
|
||||
|
||||
Ok(parser)
|
||||
|
@ -192,17 +192,19 @@ impl<'a> Parser<'a> {
|
||||
TokenKind::CloseDelim(token::DelimToken::Brace),
|
||||
TokenKind::CloseDelim(token::DelimToken::Paren),
|
||||
];
|
||||
if let token::Ident(name, false) = self.normalized_token.kind {
|
||||
if Ident::new(name, self.normalized_token.span).is_raw_guess()
|
||||
&& self.look_ahead(1, |t| valid_follow.contains(&t.kind))
|
||||
match self.token.ident() {
|
||||
Some((ident, false))
|
||||
if ident.is_raw_guess()
|
||||
&& self.look_ahead(1, |t| valid_follow.contains(&t.kind)) =>
|
||||
{
|
||||
err.span_suggestion(
|
||||
self.normalized_token.span,
|
||||
ident.span,
|
||||
"you can escape reserved keywords to use them as identifiers",
|
||||
format!("r#{}", name),
|
||||
format!("r#{}", ident.name),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if let Some(token_descr) = super::token_descr_opt(&self.token) {
|
||||
err.span_label(self.token.span, format!("expected identifier, found {}", token_descr));
|
||||
|
@ -50,7 +50,6 @@ macro_rules! maybe_whole_expr {
|
||||
AttrVec::new(),
|
||||
));
|
||||
}
|
||||
// N.B., `NtIdent(ident)` is normalized to `Ident` in `fn bump`.
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
@ -97,9 +96,9 @@ impl<'a> Parser<'a> {
|
||||
fn parse_expr_catch_underscore(&mut self) -> PResult<'a, P<Expr>> {
|
||||
match self.parse_expr() {
|
||||
Ok(expr) => Ok(expr),
|
||||
Err(mut err) => match self.normalized_token.kind {
|
||||
token::Ident(name, false)
|
||||
if name == kw::Underscore && self.look_ahead(1, |t| t == &token::Comma) =>
|
||||
Err(mut err) => match self.token.ident() {
|
||||
Some((Ident { name: kw::Underscore, .. }, false))
|
||||
if self.look_ahead(1, |t| t == &token::Comma) =>
|
||||
{
|
||||
// Special-case handling of `foo(_, _, _)`
|
||||
err.emit();
|
||||
@ -331,21 +330,19 @@ impl<'a> Parser<'a> {
|
||||
///
|
||||
/// Also performs recovery for `and` / `or` which are mistaken for `&&` and `||` respectively.
|
||||
fn check_assoc_op(&self) -> Option<Spanned<AssocOp>> {
|
||||
Some(Spanned {
|
||||
node: match (AssocOp::from_token(&self.token), &self.normalized_token.kind) {
|
||||
(Some(op), _) => op,
|
||||
(None, token::Ident(sym::and, false)) => {
|
||||
self.error_bad_logical_op("and", "&&", "conjunction");
|
||||
AssocOp::LAnd
|
||||
}
|
||||
(None, token::Ident(sym::or, false)) => {
|
||||
self.error_bad_logical_op("or", "||", "disjunction");
|
||||
AssocOp::LOr
|
||||
}
|
||||
_ => return None,
|
||||
},
|
||||
span: self.normalized_token.span,
|
||||
})
|
||||
let (op, span) = match (AssocOp::from_token(&self.token), self.token.ident()) {
|
||||
(Some(op), _) => (op, self.token.span),
|
||||
(None, Some((Ident { name: sym::and, span }, false))) => {
|
||||
self.error_bad_logical_op("and", "&&", "conjunction");
|
||||
(AssocOp::LAnd, span)
|
||||
}
|
||||
(None, Some((Ident { name: sym::or, span }, false))) => {
|
||||
self.error_bad_logical_op("or", "||", "disjunction");
|
||||
(AssocOp::LOr, span)
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
Some(source_map::respan(span, op))
|
||||
}
|
||||
|
||||
/// Error on `and` and `or` suggesting `&&` and `||` respectively.
|
||||
@ -436,7 +433,7 @@ impl<'a> Parser<'a> {
|
||||
let attrs = self.parse_or_use_outer_attributes(attrs)?;
|
||||
let lo = self.token.span;
|
||||
// Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr()
|
||||
let (hi, ex) = match self.normalized_token.kind {
|
||||
let (hi, ex) = match self.token.uninterpolate().kind {
|
||||
token::Not => self.parse_unary_expr(lo, UnOp::Not), // `!expr`
|
||||
token::Tilde => self.recover_tilde_expr(lo), // `~expr`
|
||||
token::BinOp(token::Minus) => self.parse_unary_expr(lo, UnOp::Neg), // `-expr`
|
||||
@ -483,7 +480,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
fn is_mistaken_not_ident_negation(&self) -> bool {
|
||||
let token_cannot_continue_expr = |t: &Token| match t.kind {
|
||||
let token_cannot_continue_expr = |t: &Token| match t.uninterpolate().kind {
|
||||
// These tokens can start an expression after `!`, but
|
||||
// can't continue an expression after an ident
|
||||
token::Ident(name, is_raw) => token::ident_can_begin_expr(name, t.span, is_raw),
|
||||
@ -718,20 +715,11 @@ impl<'a> Parser<'a> {
|
||||
expr.map(|mut expr| {
|
||||
attrs.extend::<Vec<_>>(expr.attrs.into());
|
||||
expr.attrs = attrs;
|
||||
self.error_attr_on_if_expr(&expr);
|
||||
expr
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn error_attr_on_if_expr(&self, expr: &Expr) {
|
||||
if let (ExprKind::If(..), [a0, ..]) = (&expr.kind, &*expr.attrs) {
|
||||
// Just point to the first attribute in there...
|
||||
self.struct_span_err(a0.span, "attributes are not yet allowed on `if` expressions")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_dot_or_call_expr_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
|
||||
loop {
|
||||
if self.eat(&token::Question) {
|
||||
@ -756,7 +744,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
fn parse_dot_suffix_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
|
||||
match self.normalized_token.kind {
|
||||
match self.token.uninterpolate().kind {
|
||||
token::Ident(..) => self.parse_dot_suffix(base, lo),
|
||||
token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => {
|
||||
Ok(self.parse_tuple_field_access_expr(lo, base, symbol, suffix))
|
||||
@ -850,7 +838,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
/// Assuming we have just parsed `.`, continue parsing into an expression.
|
||||
fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
|
||||
if self.normalized_token.span.rust_2018() && self.eat_keyword(kw::Await) {
|
||||
if self.token.uninterpolated_span().rust_2018() && self.eat_keyword(kw::Await) {
|
||||
return self.mk_await_expr(self_arg, lo);
|
||||
}
|
||||
|
||||
@ -964,7 +952,7 @@ impl<'a> Parser<'a> {
|
||||
// | ^ expected expression
|
||||
self.bump();
|
||||
Ok(self.mk_expr_err(self.token.span))
|
||||
} else if self.normalized_token.span.rust_2018() {
|
||||
} else if self.token.uninterpolated_span().rust_2018() {
|
||||
// `Span::rust_2018()` is somewhat expensive; don't get it repeatedly.
|
||||
if self.check_keyword(kw::Async) {
|
||||
if self.is_async_block() {
|
||||
@ -1397,11 +1385,14 @@ impl<'a> Parser<'a> {
|
||||
let movability =
|
||||
if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable };
|
||||
|
||||
let asyncness =
|
||||
if self.normalized_token.span.rust_2018() { self.parse_asyncness() } else { Async::No };
|
||||
if asyncness.is_async() {
|
||||
let asyncness = if self.token.uninterpolated_span().rust_2018() {
|
||||
self.parse_asyncness()
|
||||
} else {
|
||||
Async::No
|
||||
};
|
||||
if let Async::Yes { span, .. } = asyncness {
|
||||
// Feature-gate `async ||` closures.
|
||||
self.sess.gated_spans.gate(sym::async_closure, self.normalized_prev_token.span);
|
||||
self.sess.gated_spans.gate(sym::async_closure, span);
|
||||
}
|
||||
|
||||
let capture_clause = self.parse_capture_clause();
|
||||
@ -1757,7 +1748,7 @@ impl<'a> Parser<'a> {
|
||||
fn is_try_block(&self) -> bool {
|
||||
self.token.is_keyword(kw::Try) &&
|
||||
self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) &&
|
||||
self.normalized_token.span.rust_2018() &&
|
||||
self.token.uninterpolated_span().rust_2018() &&
|
||||
// Prevent `while try {} {}`, `if try {} {} else {}`, etc.
|
||||
!self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
|
||||
}
|
||||
@ -1907,20 +1898,23 @@ impl<'a> Parser<'a> {
|
||||
|
||||
/// Use in case of error after field-looking code: `S { foo: () with a }`.
|
||||
fn find_struct_error_after_field_looking_code(&self) -> Option<Field> {
|
||||
if let token::Ident(name, _) = self.normalized_token.kind {
|
||||
if !self.token.is_reserved_ident() && self.look_ahead(1, |t| *t == token::Colon) {
|
||||
return Some(ast::Field {
|
||||
ident: Ident::new(name, self.normalized_token.span),
|
||||
match self.token.ident() {
|
||||
Some((ident, is_raw))
|
||||
if (is_raw || !ident.is_reserved())
|
||||
&& self.look_ahead(1, |t| *t == token::Colon) =>
|
||||
{
|
||||
Some(ast::Field {
|
||||
ident,
|
||||
span: self.token.span,
|
||||
expr: self.mk_expr_err(self.token.span),
|
||||
is_shorthand: false,
|
||||
attrs: AttrVec::new(),
|
||||
id: DUMMY_NODE_ID,
|
||||
is_placeholder: false,
|
||||
});
|
||||
})
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn recover_struct_comma_after_dotdot(&mut self, span: Span) {
|
||||
|
@ -574,7 +574,7 @@ impl<'a> Parser<'a> {
|
||||
&& self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As))
|
||||
{
|
||||
self.bump(); // `default`
|
||||
Defaultness::Default(self.normalized_prev_token.span)
|
||||
Defaultness::Default(self.prev_token.uninterpolated_span())
|
||||
} else {
|
||||
Defaultness::Final
|
||||
}
|
||||
@ -750,10 +750,10 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> {
|
||||
match self.normalized_token.kind {
|
||||
token::Ident(name @ kw::Underscore, false) => {
|
||||
match self.token.ident() {
|
||||
Some((ident @ Ident { name: kw::Underscore, .. }, false)) => {
|
||||
self.bump();
|
||||
Ok(Ident::new(name, self.normalized_prev_token.span))
|
||||
Ok(ident)
|
||||
}
|
||||
_ => self.parse_ident(),
|
||||
}
|
||||
@ -1544,7 +1544,9 @@ impl<'a> Parser<'a> {
|
||||
|
||||
let is_name_required = match self.token.kind {
|
||||
token::DotDotDot => false,
|
||||
_ => req_name(self.normalized_token.span.edition()),
|
||||
// FIXME: Consider using interpolated token for this edition check,
|
||||
// it should match the intent of edition hygiene better.
|
||||
_ => req_name(self.token.uninterpolate().span.edition()),
|
||||
};
|
||||
let (pat, ty) = if is_name_required || self.is_named_param() {
|
||||
debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
|
||||
@ -1609,15 +1611,12 @@ impl<'a> Parser<'a> {
|
||||
/// Returns the parsed optional self parameter and whether a self shortcut was used.
|
||||
fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
|
||||
// Extract an identifier *after* having confirmed that the token is one.
|
||||
let expect_self_ident = |this: &mut Self| {
|
||||
match this.normalized_token.kind {
|
||||
// Preserve hygienic context.
|
||||
token::Ident(name, _) => {
|
||||
this.bump();
|
||||
Ident::new(name, this.normalized_prev_token.span)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
let expect_self_ident = |this: &mut Self| match this.token.ident() {
|
||||
Some((ident, false)) => {
|
||||
this.bump();
|
||||
ident
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
// Is `self` `n` tokens ahead?
|
||||
let is_isolated_self = |this: &Self, n| {
|
||||
@ -1651,7 +1650,7 @@ impl<'a> Parser<'a> {
|
||||
// Only a limited set of initial token sequences is considered `self` parameters; anything
|
||||
// else is parsed as a normal function parameter list, so some lookahead is required.
|
||||
let eself_lo = self.token.span;
|
||||
let (eself, eself_ident, eself_hi) = match self.normalized_token.kind {
|
||||
let (eself, eself_ident, eself_hi) = match self.token.uninterpolate().kind {
|
||||
token::BinOp(token::And) => {
|
||||
let eself = if is_isolated_self(self, 1) {
|
||||
// `&self`
|
||||
|
@ -88,21 +88,10 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath {
|
||||
#[derive(Clone)]
|
||||
pub struct Parser<'a> {
|
||||
pub sess: &'a ParseSess,
|
||||
/// The current non-normalized token.
|
||||
/// The current token.
|
||||
pub token: Token,
|
||||
/// The current normalized token.
|
||||
/// "Normalized" means that some interpolated tokens
|
||||
/// (`$i: ident` and `$l: lifetime` meta-variables) are replaced
|
||||
/// with non-interpolated identifier and lifetime tokens they refer to.
|
||||
/// Use this if you need to check for `token::Ident` or `token::Lifetime` specifically,
|
||||
/// this also includes edition checks for edition-specific keyword identifiers.
|
||||
pub normalized_token: Token,
|
||||
/// The previous non-normalized token.
|
||||
/// The previous token.
|
||||
pub prev_token: Token,
|
||||
/// The previous normalized token.
|
||||
/// Use this if you need to check for `token::Ident` or `token::Lifetime` specifically,
|
||||
/// this also includes edition checks for edition-specific keyword identifiers.
|
||||
pub normalized_prev_token: Token,
|
||||
restrictions: Restrictions,
|
||||
/// Used to determine the path to externally loaded source files.
|
||||
pub(super) directory: Directory,
|
||||
@ -374,9 +363,7 @@ impl<'a> Parser<'a> {
|
||||
let mut parser = Parser {
|
||||
sess,
|
||||
token: Token::dummy(),
|
||||
normalized_token: Token::dummy(),
|
||||
prev_token: Token::dummy(),
|
||||
normalized_prev_token: Token::dummy(),
|
||||
restrictions: Restrictions::empty(),
|
||||
recurse_into_file_modules,
|
||||
directory: Directory {
|
||||
@ -480,9 +467,9 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> {
|
||||
match self.normalized_token.kind {
|
||||
token::Ident(name, _) => {
|
||||
if self.token.is_reserved_ident() {
|
||||
match self.token.ident() {
|
||||
Some((ident, is_raw)) => {
|
||||
if !is_raw && ident.is_reserved() {
|
||||
let mut err = self.expected_ident_found();
|
||||
if recover {
|
||||
err.emit();
|
||||
@ -491,7 +478,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
self.bump();
|
||||
Ok(Ident::new(name, self.normalized_prev_token.span))
|
||||
Ok(ident)
|
||||
}
|
||||
_ => Err(match self.prev_token.kind {
|
||||
TokenKind::DocComment(..) => {
|
||||
@ -609,7 +596,7 @@ impl<'a> Parser<'a> {
|
||||
Some((first, second)) if first == expected => {
|
||||
let first_span = self.sess.source_map().start_point(self.token.span);
|
||||
let second_span = self.token.span.with_lo(first_span.hi());
|
||||
self.set_token(Token::new(first, first_span));
|
||||
self.token = Token::new(first, first_span);
|
||||
self.bump_with(Token::new(second, second_span));
|
||||
true
|
||||
}
|
||||
@ -817,23 +804,6 @@ impl<'a> Parser<'a> {
|
||||
self.parse_delim_comma_seq(token::Paren, f)
|
||||
}
|
||||
|
||||
// Interpolated identifier (`$i: ident`) and lifetime (`$l: lifetime`)
|
||||
// tokens are replaced with usual identifier and lifetime tokens,
|
||||
// so the former are never encountered during normal parsing.
|
||||
crate fn set_token(&mut self, token: Token) {
|
||||
self.token = token;
|
||||
self.normalized_token = match &self.token.kind {
|
||||
token::Interpolated(nt) => match **nt {
|
||||
token::NtIdent(ident, is_raw) => {
|
||||
Token::new(token::Ident(ident.name, is_raw), ident.span)
|
||||
}
|
||||
token::NtLifetime(ident) => Token::new(token::Lifetime(ident.name), ident.span),
|
||||
_ => self.token.clone(),
|
||||
},
|
||||
_ => self.token.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Advance the parser by one token using provided token as the next one.
|
||||
fn bump_with(&mut self, next_token: Token) {
|
||||
// Bumping after EOF is a bad sign, usually an infinite loop.
|
||||
@ -843,9 +813,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
// Update the current and previous tokens.
|
||||
self.prev_token = self.token.take();
|
||||
self.normalized_prev_token = self.normalized_token.take();
|
||||
self.set_token(next_token);
|
||||
self.prev_token = mem::replace(&mut self.token, next_token);
|
||||
|
||||
// Diagnostics.
|
||||
self.expected_tokens.clear();
|
||||
@ -884,7 +852,7 @@ impl<'a> Parser<'a> {
|
||||
/// Parses asyncness: `async` or nothing.
|
||||
fn parse_asyncness(&mut self) -> Async {
|
||||
if self.eat_keyword(kw::Async) {
|
||||
let span = self.normalized_prev_token.span;
|
||||
let span = self.prev_token.uninterpolated_span();
|
||||
Async::Yes { span, closure_id: DUMMY_NODE_ID, return_impl_trait_id: DUMMY_NODE_ID }
|
||||
} else {
|
||||
Async::No
|
||||
@ -894,7 +862,7 @@ impl<'a> Parser<'a> {
|
||||
/// Parses unsafety: `unsafe` or nothing.
|
||||
fn parse_unsafety(&mut self) -> Unsafe {
|
||||
if self.eat_keyword(kw::Unsafe) {
|
||||
Unsafe::Yes(self.normalized_prev_token.span)
|
||||
Unsafe::Yes(self.prev_token.uninterpolated_span())
|
||||
} else {
|
||||
Unsafe::No
|
||||
}
|
||||
@ -903,7 +871,7 @@ impl<'a> Parser<'a> {
|
||||
/// Parses constness: `const` or nothing.
|
||||
fn parse_constness(&mut self) -> Const {
|
||||
if self.eat_keyword(kw::Const) {
|
||||
Const::Yes(self.normalized_prev_token.span)
|
||||
Const::Yes(self.prev_token.uninterpolated_span())
|
||||
} else {
|
||||
Const::No
|
||||
}
|
||||
@ -1005,7 +973,7 @@ impl<'a> Parser<'a> {
|
||||
&mut self.token_cursor.frame,
|
||||
self.token_cursor.stack.pop().unwrap(),
|
||||
);
|
||||
self.set_token(Token::new(TokenKind::CloseDelim(frame.delim), frame.span.close));
|
||||
self.token = Token::new(TokenKind::CloseDelim(frame.delim), frame.span.close);
|
||||
self.bump();
|
||||
TokenTree::Delimited(frame.span, frame.delim, frame.tree_cursor.stream)
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ impl<'a> Parser<'a> {
|
||||
/// Note that there are more tokens such as `@` for which we know that the `|`
|
||||
/// is an illegal parse. However, the user's intent is less clear in that case.
|
||||
fn recover_trailing_vert(&mut self, lo: Option<Span>) -> bool {
|
||||
let is_end_ahead = self.look_ahead(1, |token| match &token.kind {
|
||||
let is_end_ahead = self.look_ahead(1, |token| match &token.uninterpolate().kind {
|
||||
token::FatArrow // e.g. `a | => 0,`.
|
||||
| token::Ident(kw::If, false) // e.g. `a | if expr`.
|
||||
| token::Eq // e.g. `let a | = 0`.
|
||||
|
@ -240,10 +240,10 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
pub(super) fn parse_path_segment_ident(&mut self) -> PResult<'a, Ident> {
|
||||
match self.normalized_token.kind {
|
||||
token::Ident(name, _) if name.is_path_segment_keyword() => {
|
||||
match self.token.ident() {
|
||||
Some((ident, false)) if ident.is_path_segment_keyword() => {
|
||||
self.bump();
|
||||
Ok(Ident::new(name, self.normalized_prev_token.span))
|
||||
Ok(ident)
|
||||
}
|
||||
_ => self.parse_ident(),
|
||||
}
|
||||
|
@ -323,7 +323,7 @@ impl<'a> Parser<'a> {
|
||||
/// Is a `dyn B0 + ... + Bn` type allowed here?
|
||||
fn is_explicit_dyn_type(&mut self) -> bool {
|
||||
self.check_keyword(kw::Dyn)
|
||||
&& (self.normalized_token.span.rust_2018()
|
||||
&& (self.token.uninterpolated_span().rust_2018()
|
||||
|| self.look_ahead(1, |t| {
|
||||
t.can_begin_bound() && !can_continue_type_after_non_fn_ident(t)
|
||||
}))
|
||||
|
@ -13,6 +13,10 @@ impl Handler {
|
||||
pub unsafe fn new() -> Handler {
|
||||
make_handler()
|
||||
}
|
||||
|
||||
fn null() -> Handler {
|
||||
Handler { _data: crate::ptr::null_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Handler {
|
||||
@ -108,13 +112,20 @@ mod imp {
|
||||
}
|
||||
|
||||
static mut MAIN_ALTSTACK: *mut libc::c_void = ptr::null_mut();
|
||||
static mut NEED_ALTSTACK: bool = false;
|
||||
|
||||
pub unsafe fn init() {
|
||||
let mut action: sigaction = mem::zeroed();
|
||||
action.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
||||
action.sa_sigaction = signal_handler as sighandler_t;
|
||||
sigaction(SIGSEGV, &action, ptr::null_mut());
|
||||
sigaction(SIGBUS, &action, ptr::null_mut());
|
||||
for &signal in &[SIGSEGV, SIGBUS] {
|
||||
sigaction(signal, ptr::null_mut(), &mut action);
|
||||
// Configure our signal handler if one is not already set.
|
||||
if action.sa_sigaction == SIG_DFL {
|
||||
action.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
||||
action.sa_sigaction = signal_handler as sighandler_t;
|
||||
sigaction(signal, &action, ptr::null_mut());
|
||||
NEED_ALTSTACK = true;
|
||||
}
|
||||
}
|
||||
|
||||
let handler = make_handler();
|
||||
MAIN_ALTSTACK = handler._data;
|
||||
@ -152,6 +163,9 @@ mod imp {
|
||||
}
|
||||
|
||||
pub unsafe fn make_handler() -> Handler {
|
||||
if !NEED_ALTSTACK {
|
||||
return Handler::null();
|
||||
}
|
||||
let mut stack = mem::zeroed();
|
||||
sigaltstack(ptr::null(), &mut stack);
|
||||
// Configure alternate signal stack, if one is not already set.
|
||||
@ -160,7 +174,7 @@ mod imp {
|
||||
sigaltstack(&stack, ptr::null_mut());
|
||||
Handler { _data: stack.ss_sp as *mut libc::c_void }
|
||||
} else {
|
||||
Handler { _data: ptr::null_mut() }
|
||||
Handler::null()
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,14 +205,12 @@ mod imp {
|
||||
target_os = "openbsd"
|
||||
)))]
|
||||
mod imp {
|
||||
use crate::ptr;
|
||||
|
||||
pub unsafe fn init() {}
|
||||
|
||||
pub unsafe fn cleanup() {}
|
||||
|
||||
pub unsafe fn make_handler() -> super::Handler {
|
||||
super::Handler { _data: ptr::null_mut() }
|
||||
super::Handler::null()
|
||||
}
|
||||
|
||||
pub unsafe fn drop_handler(_handler: &mut super::Handler) {}
|
||||
|
@ -665,20 +665,24 @@ extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
|
||||
|
||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
|
||||
LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
|
||||
const char *Producer, bool isOptimized, const char *Flags,
|
||||
unsigned RuntimeVer, const char *SplitName,
|
||||
const char *Producer, size_t ProducerLen, bool isOptimized,
|
||||
const char *Flags, unsigned RuntimeVer,
|
||||
const char *SplitName, size_t SplitNameLen,
|
||||
LLVMRustDebugEmissionKind Kind) {
|
||||
auto *File = unwrapDI<DIFile>(FileRef);
|
||||
|
||||
return wrap(Builder->createCompileUnit(Lang, File, Producer, isOptimized,
|
||||
Flags, RuntimeVer, SplitName,
|
||||
return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
|
||||
isOptimized, Flags, RuntimeVer,
|
||||
StringRef(SplitName, SplitNameLen),
|
||||
fromRust(Kind)));
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef
|
||||
LLVMRustDIBuilderCreateFile(LLVMRustDIBuilderRef Builder, const char *Filename,
|
||||
const char *Directory) {
|
||||
return wrap(Builder->createFile(Filename, Directory));
|
||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
|
||||
LLVMRustDIBuilderRef Builder,
|
||||
const char *Filename, size_t FilenameLen,
|
||||
const char *Directory, size_t DirectoryLen) {
|
||||
return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
|
||||
StringRef(Directory, DirectoryLen)));
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef
|
||||
@ -690,8 +694,10 @@ LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
|
||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
|
||||
const char *LinkageName, LLVMMetadataRef File, unsigned LineNo,
|
||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
||||
const char *Name, size_t NameLen,
|
||||
const char *LinkageName, size_t LinkageNameLen,
|
||||
LLVMMetadataRef File, unsigned LineNo,
|
||||
LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
|
||||
LLVMRustDISPFlags SPFlags, LLVMValueRef Fn, LLVMMetadataRef TParam,
|
||||
LLVMMetadataRef Decl) {
|
||||
@ -705,8 +711,11 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
|
||||
llvmFlags |= DINode::DIFlags::FlagMainSubprogram;
|
||||
#endif
|
||||
DISubprogram *Sub = Builder->createFunction(
|
||||
unwrapDI<DIScope>(Scope), Name, LinkageName, unwrapDI<DIFile>(File),
|
||||
LineNo, unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
|
||||
unwrapDI<DIScope>(Scope),
|
||||
StringRef(Name, NameLen),
|
||||
StringRef(LinkageName, LinkageNameLen),
|
||||
unwrapDI<DIFile>(File), LineNo,
|
||||
unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
|
||||
llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
|
||||
#else
|
||||
bool IsLocalToUnit = isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit);
|
||||
@ -716,8 +725,11 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
|
||||
if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram))
|
||||
llvmFlags |= DINode::DIFlags::FlagMainSubprogram;
|
||||
DISubprogram *Sub = Builder->createFunction(
|
||||
unwrapDI<DIScope>(Scope), Name, LinkageName, unwrapDI<DIFile>(File),
|
||||
LineNo, unwrapDI<DISubroutineType>(Ty), IsLocalToUnit, IsDefinition,
|
||||
unwrapDI<DIScope>(Scope),
|
||||
StringRef(Name, NameLen),
|
||||
StringRef(LinkageName, LinkageNameLen),
|
||||
unwrapDI<DIFile>(File), LineNo,
|
||||
unwrapDI<DISubroutineType>(Ty), IsLocalToUnit, IsDefinition,
|
||||
ScopeLine, llvmFlags, IsOptimized, TParams,
|
||||
unwrapDIPtr<DISubprogram>(Decl));
|
||||
#endif
|
||||
@ -725,53 +737,59 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
|
||||
return wrap(Sub);
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef
|
||||
LLVMRustDIBuilderCreateBasicType(LLVMRustDIBuilderRef Builder, const char *Name,
|
||||
uint64_t SizeInBits, uint32_t AlignInBits,
|
||||
unsigned Encoding) {
|
||||
return wrap(Builder->createBasicType(Name, SizeInBits, Encoding));
|
||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
|
||||
LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
|
||||
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding) {
|
||||
return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
|
||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
|
||||
uint64_t SizeInBits, uint32_t AlignInBits, const char *Name) {
|
||||
uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
|
||||
const char *Name, size_t NameLen) {
|
||||
return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
|
||||
SizeInBits, AlignInBits,
|
||||
/* DWARFAddressSpace */ None,
|
||||
Name));
|
||||
AddressSpace,
|
||||
StringRef(Name, NameLen)));
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
|
||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
|
||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
||||
const char *Name, size_t NameLen,
|
||||
LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
|
||||
uint32_t AlignInBits, LLVMRustDIFlags Flags,
|
||||
LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
|
||||
unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
|
||||
const char *UniqueId) {
|
||||
const char *UniqueId, size_t UniqueIdLen) {
|
||||
return wrap(Builder->createStructType(
|
||||
unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber,
|
||||
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
|
||||
unwrapDI<DIFile>(File), LineNumber,
|
||||
SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
|
||||
DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
|
||||
unwrapDI<DIType>(VTableHolder), UniqueId));
|
||||
unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
|
||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
|
||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
||||
const char *Name, size_t NameLen,
|
||||
LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
|
||||
uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
|
||||
LLVMMetadataRef Elements, const char *UniqueId) {
|
||||
LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
|
||||
return wrap(Builder->createVariantPart(
|
||||
unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber,
|
||||
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
|
||||
unwrapDI<DIFile>(File), LineNumber,
|
||||
SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
|
||||
DINodeArray(unwrapDI<MDTuple>(Elements)), UniqueId));
|
||||
DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
|
||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
|
||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
||||
const char *Name, size_t NameLen,
|
||||
LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
|
||||
uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
|
||||
LLVMMetadataRef Ty) {
|
||||
return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope), Name,
|
||||
return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
|
||||
StringRef(Name, NameLen),
|
||||
unwrapDI<DIFile>(File), LineNo,
|
||||
SizeInBits, AlignInBits, OffsetInBits,
|
||||
fromRust(Flags), unwrapDI<DIType>(Ty)));
|
||||
@ -779,14 +797,15 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
|
||||
|
||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
|
||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
||||
const char *Name, LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
|
||||
uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
|
||||
const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
|
||||
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
|
||||
LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
|
||||
llvm::ConstantInt* D = nullptr;
|
||||
if (Discriminant) {
|
||||
D = unwrap<llvm::ConstantInt>(Discriminant);
|
||||
}
|
||||
return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope), Name,
|
||||
return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
|
||||
StringRef(Name, NameLen),
|
||||
unwrapDI<DIFile>(File), LineNo,
|
||||
SizeInBits, AlignInBits, OffsetInBits, D,
|
||||
fromRust(Flags), unwrapDI<DIType>(Ty)));
|
||||
@ -808,8 +827,10 @@ LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
|
||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context, const char *Name,
|
||||
const char *LinkageName, LLVMMetadataRef File, unsigned LineNo,
|
||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
|
||||
const char *Name, size_t NameLen,
|
||||
const char *LinkageName, size_t LinkageNameLen,
|
||||
LLVMMetadataRef File, unsigned LineNo,
|
||||
LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
|
||||
LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
|
||||
llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
|
||||
@ -825,7 +846,8 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
|
||||
}
|
||||
|
||||
llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
|
||||
unwrapDI<DIDescriptor>(Context), Name, LinkageName,
|
||||
unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
|
||||
StringRef(LinkageName, LinkageNameLen),
|
||||
unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
|
||||
#if LLVM_VERSION_GE(10, 0)
|
||||
/* isDefined */ true,
|
||||
@ -843,17 +865,20 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
|
||||
|
||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
|
||||
LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
|
||||
const char *Name, LLVMMetadataRef File, unsigned LineNo,
|
||||
const char *Name, size_t NameLen,
|
||||
LLVMMetadataRef File, unsigned LineNo,
|
||||
LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
|
||||
unsigned ArgNo, uint32_t AlignInBits) {
|
||||
if (Tag == 0x100) { // DW_TAG_auto_variable
|
||||
return wrap(Builder->createAutoVariable(
|
||||
unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNo,
|
||||
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
|
||||
unwrapDI<DIFile>(File), LineNo,
|
||||
unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
|
||||
} else {
|
||||
return wrap(Builder->createParameterVariable(
|
||||
unwrapDI<DIDescriptor>(Scope), Name, ArgNo, unwrapDI<DIFile>(File),
|
||||
LineNo, unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
|
||||
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
|
||||
unwrapDI<DIFile>(File), LineNo,
|
||||
unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -894,47 +919,50 @@ extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
|
||||
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));
|
||||
return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
|
||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
|
||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
||||
const char *Name, size_t NameLen,
|
||||
LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
|
||||
uint32_t AlignInBits, LLVMMetadataRef Elements,
|
||||
LLVMMetadataRef ClassTy, bool IsScoped) {
|
||||
return wrap(Builder->createEnumerationType(
|
||||
unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber,
|
||||
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
|
||||
unwrapDI<DIFile>(File), LineNumber,
|
||||
SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
|
||||
unwrapDI<DIType>(ClassTy), "", IsScoped));
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
|
||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
|
||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
||||
const char *Name, size_t NameLen,
|
||||
LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
|
||||
uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
|
||||
unsigned RunTimeLang, const char *UniqueId) {
|
||||
unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
|
||||
return wrap(Builder->createUnionType(
|
||||
unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber,
|
||||
SizeInBits, AlignInBits, fromRust(Flags),
|
||||
DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang, UniqueId));
|
||||
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
|
||||
LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
|
||||
DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
|
||||
StringRef(UniqueId, UniqueIdLen)));
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
|
||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
|
||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
||||
const char *Name, size_t NameLen,
|
||||
LLVMMetadataRef Ty, LLVMMetadataRef File, unsigned LineNo,
|
||||
unsigned ColumnNo) {
|
||||
return wrap(Builder->createTemplateTypeParameter(
|
||||
unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIType>(Ty)));
|
||||
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty)));
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef
|
||||
LLVMRustDIBuilderCreateNameSpace(LLVMRustDIBuilderRef Builder,
|
||||
LLVMMetadataRef Scope, const char *Name,
|
||||
LLVMMetadataRef File, unsigned LineNo) {
|
||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
|
||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
||||
const char *Name, size_t NameLen, bool ExportSymbols) {
|
||||
return wrap(Builder->createNameSpace(
|
||||
unwrapDI<DIDescriptor>(Scope), Name,
|
||||
false // ExportSymbols (only relevant for C++ anonymous namespaces)
|
||||
));
|
||||
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
|
||||
));
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
|
37
src/test/pretty/if-attr.rs
Normal file
37
src/test/pretty/if-attr.rs
Normal file
@ -0,0 +1,37 @@
|
||||
// pp-exact
|
||||
|
||||
#[cfg(FALSE)]
|
||||
fn simple_attr() {
|
||||
|
||||
#[attr]
|
||||
if true { }
|
||||
|
||||
#[allow_warnings]
|
||||
if true { }
|
||||
}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
fn if_else_chain() {
|
||||
|
||||
#[first_attr]
|
||||
if true { } else if false { } else { }
|
||||
}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
fn if_let() {
|
||||
|
||||
#[attr]
|
||||
if let Some(_) = Some(true) { }
|
||||
}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
fn let_attr_if() {
|
||||
let _ = #[attr] if let _ = 0 { };
|
||||
let _ = #[attr] if true { };
|
||||
|
||||
let _ = #[attr] if let _ = 0 { } else { };
|
||||
let _ = #[attr] if true { } else { };
|
||||
}
|
||||
|
||||
|
||||
fn main() { }
|
@ -0,0 +1,17 @@
|
||||
// Regression test for #54239, shouldn't trigger lint.
|
||||
// check-pass
|
||||
// edition:2018
|
||||
|
||||
#![deny(missing_debug_implementations)]
|
||||
|
||||
struct DontLookAtMe(i32);
|
||||
|
||||
async fn secret() -> DontLookAtMe {
|
||||
DontLookAtMe(41)
|
||||
}
|
||||
|
||||
pub async fn looking() -> i32 { // Shouldn't trigger lint here.
|
||||
secret().await.0
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -6,7 +6,7 @@ use std::{mem, usize};
|
||||
const TEST: () = { unsafe { //~ NOTE
|
||||
let slice: *const [u8] = mem::transmute((1usize, usize::MAX));
|
||||
let _val = &*slice; //~ ERROR: any use of this value will cause an error
|
||||
//~^ NOTE: total size is bigger than largest supported object
|
||||
//~^ NOTE: slice is bigger than largest supported object
|
||||
//~^^ on by default
|
||||
} };
|
||||
|
||||
|
@ -4,7 +4,7 @@ error: any use of this value will cause an error
|
||||
LL | / const TEST: () = { unsafe {
|
||||
LL | | let slice: *const [u8] = mem::transmute((1usize, usize::MAX));
|
||||
LL | | let _val = &*slice;
|
||||
| | ^^^^^^^ invalid slice: total size is bigger than largest supported object
|
||||
| | ^^^^^^^ invalid metadata in wide pointer: slice is bigger than largest supported object
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | } };
|
||||
|
@ -31,12 +31,16 @@ const STR_VALID: &str = unsafe { mem::transmute((&42u8, 1usize)) };
|
||||
// bad str
|
||||
const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
// bad str
|
||||
const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
// bad str in user-defined unsized type
|
||||
const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
|
||||
// invalid UTF-8
|
||||
const STR_NO_UTF8: &str = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) };
|
||||
@ -83,7 +87,7 @@ const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute
|
||||
// # raw slice
|
||||
const RAW_SLICE_VALID: *const [u8] = unsafe { mem::transmute((&42u8, 1usize)) }; // ok
|
||||
const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, 999usize)) }; // ok because raw
|
||||
const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, usize::max_value())) }; // ok because raw
|
||||
const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, usize::MAX)) }; // ok because raw
|
||||
const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
let uninit_len = MaybeUninit::<usize> { uninit: () };
|
||||
|
@ -7,7 +7,15 @@ LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:35:1
|
||||
--> $DIR/ub-wide-ptr.rs:34:1
|
||||
|
|
||||
LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid reference metadata: slice is bigger than largest supported object at .0
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:37:1
|
||||
|
|
||||
LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
||||
@ -15,7 +23,7 @@ LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:38:1
|
||||
--> $DIR/ub-wide-ptr.rs:40:1
|
||||
|
|
||||
LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
||||
@ -25,13 +33,21 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:42:1
|
||||
|
|
||||
LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid reference metadata: slice is bigger than largest supported object
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:46:1
|
||||
|
|
||||
LL | const STR_NO_UTF8: &str = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:45:1
|
||||
--> $DIR/ub-wide-ptr.rs:49:1
|
||||
|
|
||||
LL | const MYSTR_NO_UTF8: &MyStr = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>.0
|
||||
@ -39,7 +55,7 @@ LL | const MYSTR_NO_UTF8: &MyStr = unsafe { mem::transmute::<&[u8], _>(&[0xFF])
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:52:1
|
||||
--> $DIR/ub-wide-ptr.rs:56:1
|
||||
|
|
||||
LL | / const SLICE_LENGTH_UNINIT: &[u8] = unsafe {
|
||||
LL | |
|
||||
@ -51,7 +67,7 @@ LL | | };
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:58:1
|
||||
--> $DIR/ub-wide-ptr.rs:62:1
|
||||
|
|
||||
LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds)
|
||||
@ -59,7 +75,7 @@ LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:61:1
|
||||
--> $DIR/ub-wide-ptr.rs:65:1
|
||||
|
|
||||
LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
||||
@ -67,7 +83,7 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:64:1
|
||||
--> $DIR/ub-wide-ptr.rs:68:1
|
||||
|
|
||||
LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (not entirely in bounds)
|
||||
@ -75,7 +91,7 @@ LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999us
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:67:1
|
||||
--> $DIR/ub-wide-ptr.rs:71:1
|
||||
|
|
||||
LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
||||
@ -83,7 +99,7 @@ LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:71:1
|
||||
--> $DIR/ub-wide-ptr.rs:75:1
|
||||
|
|
||||
LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>[0], but expected a boolean
|
||||
@ -91,7 +107,7 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:77:1
|
||||
--> $DIR/ub-wide-ptr.rs:81:1
|
||||
|
|
||||
LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.0, but expected a boolean
|
||||
@ -99,7 +115,7 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:80:1
|
||||
--> $DIR/ub-wide-ptr.rs:84:1
|
||||
|
|
||||
LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.1[0], but expected a boolean
|
||||
@ -107,7 +123,7 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::tran
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:87:1
|
||||
--> $DIR/ub-wide-ptr.rs:91:1
|
||||
|
|
||||
LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
|
||||
LL | |
|
||||
@ -119,7 +135,7 @@ LL | | };
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:95:1
|
||||
--> $DIR/ub-wide-ptr.rs:99:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8, &3u8)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
|
||||
@ -127,7 +143,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:98:1
|
||||
--> $DIR/ub-wide-ptr.rs:102:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
|
||||
@ -135,7 +151,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:101:1
|
||||
--> $DIR/ub-wide-ptr.rs:105:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4usize)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
|
||||
@ -143,7 +159,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4u
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:105:1
|
||||
--> $DIR/ub-wide-ptr.rs:109:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.<dyn-downcast>, but expected a boolean
|
||||
@ -151,7 +167,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_,
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:109:1
|
||||
--> $DIR/ub-wide-ptr.rs:113:1
|
||||
|
|
||||
LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
|
||||
@ -159,7 +175,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:111:1
|
||||
--> $DIR/ub-wide-ptr.rs:115:1
|
||||
|
|
||||
LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
|
||||
@ -167,17 +183,17 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: could not evaluate static initializer
|
||||
--> $DIR/ub-wide-ptr.rs:117:5
|
||||
--> $DIR/ub-wide-ptr.rs:121:5
|
||||
|
|
||||
LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer
|
||||
|
||||
error[E0080]: could not evaluate static initializer
|
||||
--> $DIR/ub-wide-ptr.rs:121:5
|
||||
--> $DIR/ub-wide-ptr.rs:125:5
|
||||
|
|
||||
LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N
|
||||
|
||||
error: aborting due to 22 previous errors
|
||||
error: aborting due to 24 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
|
@ -8,7 +8,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/const-points-to-static.rs:5:1
|
||||
|
|
||||
LL | const TEST: &u8 = &MY_STATIC;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a reference pointing to a static variable
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
|
@ -8,7 +8,7 @@ LL | | ptr: &42,
|
||||
... |
|
||||
LL | | .slice
|
||||
LL | | };
|
||||
| |__^ invalid slice: total size is bigger than largest supported object
|
||||
| |__^ type validation failed: encountered invalid reference metadata: slice is bigger than largest supported object
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
|
@ -48,7 +48,7 @@ LL | | static FOO: AtomicUsize = AtomicUsize::new(0);
|
||||
LL | | unsafe { &*(&FOO as *const _ as *const usize) }
|
||||
LL | |
|
||||
LL | | };
|
||||
| |__^ constant accesses static
|
||||
| |__^ type validation failed: encountered a reference pointing to a static variable
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
@ -97,7 +97,7 @@ LL | | static FOO: usize = 0;
|
||||
LL | | &FOO
|
||||
LL | |
|
||||
LL | | };
|
||||
| |__^ constant accesses static
|
||||
| |__^ type validation failed: encountered a reference pointing to a static variable
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
|
9
src/test/ui/generator/issue-64620-yield-array-element.rs
Normal file
9
src/test/ui/generator/issue-64620-yield-array-element.rs
Normal file
@ -0,0 +1,9 @@
|
||||
// Regression test for #64620
|
||||
|
||||
#![feature(generators)]
|
||||
|
||||
pub fn crash(arr: [usize; 1]) {
|
||||
yield arr[0]; //~ ERROR: yield expression outside of generator literal
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,9 @@
|
||||
error[E0627]: yield expression outside of generator literal
|
||||
--> $DIR/issue-64620-yield-array-element.rs:6:5
|
||||
|
|
||||
LL | yield arr[0];
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0627`.
|
5
src/test/ui/if-attrs/bad-cfg.rs
Normal file
5
src/test/ui/if-attrs/bad-cfg.rs
Normal file
@ -0,0 +1,5 @@
|
||||
#![feature(stmt_expr_attributes)]
|
||||
|
||||
fn main() {
|
||||
let _ = #[cfg(FALSE)] if true {}; //~ ERROR removing an expression
|
||||
}
|
8
src/test/ui/if-attrs/bad-cfg.stderr
Normal file
8
src/test/ui/if-attrs/bad-cfg.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
error: removing an expression is not supported in this position
|
||||
--> $DIR/bad-cfg.rs:4:13
|
||||
|
|
||||
LL | let _ = #[cfg(FALSE)] if true {};
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
12
src/test/ui/if-attrs/builtin-if-attr.rs
Normal file
12
src/test/ui/if-attrs/builtin-if-attr.rs
Normal file
@ -0,0 +1,12 @@
|
||||
// check-pass
|
||||
|
||||
fn main() {
|
||||
#[allow(unused_variables)]
|
||||
if true {
|
||||
let a = 1;
|
||||
} else if false {
|
||||
let b = 1;
|
||||
} else {
|
||||
let c = 1;
|
||||
}
|
||||
}
|
43
src/test/ui/if-attrs/cfg-false-if-attr.rs
Normal file
43
src/test/ui/if-attrs/cfg-false-if-attr.rs
Normal file
@ -0,0 +1,43 @@
|
||||
// check-pass
|
||||
|
||||
#[cfg(FALSE)]
|
||||
fn simple_attr() {
|
||||
#[attr] if true {}
|
||||
#[allow_warnings] if true {}
|
||||
}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
fn if_else_chain() {
|
||||
#[first_attr] if true {
|
||||
} else if false {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
fn if_let() {
|
||||
#[attr] if let Some(_) = Some(true) {}
|
||||
}
|
||||
|
||||
fn bar() {
|
||||
#[cfg(FALSE)]
|
||||
if true {
|
||||
let x: () = true; // Should not error due to the #[cfg(FALSE)]
|
||||
}
|
||||
|
||||
#[cfg_attr(not(unset_attr), cfg(FALSE))]
|
||||
if true {
|
||||
let a: () = true; // Should not error due to the applied #[cfg(FALSE)]
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! custom_macro {
|
||||
($expr:expr) => {}
|
||||
}
|
||||
|
||||
custom_macro! {
|
||||
#[attr] if true {}
|
||||
}
|
||||
|
||||
|
||||
fn main() {}
|
25
src/test/ui/if-attrs/else-attrs.rs
Normal file
25
src/test/ui/if-attrs/else-attrs.rs
Normal file
@ -0,0 +1,25 @@
|
||||
#[cfg(FALSE)]
|
||||
fn if_else_parse_error() {
|
||||
if true {
|
||||
} #[attr] else if false { //~ ERROR expected
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
fn else_attr_ifparse_error() {
|
||||
if true {
|
||||
} else #[attr] if false { //~ ERROR expected
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
fn else_parse_error() {
|
||||
if true {
|
||||
} else if false {
|
||||
} #[attr] else { //~ ERROR expected
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
27
src/test/ui/if-attrs/else-attrs.stderr
Normal file
27
src/test/ui/if-attrs/else-attrs.stderr
Normal file
@ -0,0 +1,27 @@
|
||||
error: expected expression, found keyword `else`
|
||||
--> $DIR/else-attrs.rs:4:15
|
||||
|
|
||||
LL | } #[attr] else if false {
|
||||
| ^^^^ expected expression
|
||||
|
||||
error: expected `{`, found `#`
|
||||
--> $DIR/else-attrs.rs:11:12
|
||||
|
|
||||
LL | } else #[attr] if false {
|
||||
| ^ expected `{`
|
||||
|
|
||||
help: try placing this code inside a block
|
||||
|
|
||||
LL | } else #[attr] { if false {
|
||||
LL | } else {
|
||||
LL | } }
|
||||
|
|
||||
|
||||
error: expected expression, found keyword `else`
|
||||
--> $DIR/else-attrs.rs:20:15
|
||||
|
|
||||
LL | } #[attr] else {
|
||||
| ^^^^ expected expression
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
15
src/test/ui/if-attrs/gate-whole-expr.rs
Normal file
15
src/test/ui/if-attrs/gate-whole-expr.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// run-pass
|
||||
|
||||
fn main() {
|
||||
let x = 1;
|
||||
|
||||
#[cfg(FALSE)]
|
||||
if false {
|
||||
x = 2;
|
||||
} else if true {
|
||||
x = 3;
|
||||
} else {
|
||||
x = 4;
|
||||
}
|
||||
assert_eq!(x, 1);
|
||||
}
|
13
src/test/ui/if-attrs/let-chains-attr.rs
Normal file
13
src/test/ui/if-attrs/let-chains-attr.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(let_chains)] //~ WARN the feature `let_chains` is incomplete
|
||||
|
||||
#[cfg(FALSE)]
|
||||
fn foo() {
|
||||
#[attr]
|
||||
if let Some(_) = Some(true) && let Ok(_) = Ok(1) {
|
||||
} else if let Some(false) = Some(true) {
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
8
src/test/ui/if-attrs/let-chains-attr.stderr
Normal file
8
src/test/ui/if-attrs/let-chains-attr.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
warning: the feature `let_chains` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/let-chains-attr.rs:3:12
|
||||
|
|
||||
LL | #![feature(let_chains)]
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
6
src/test/ui/if-attrs/stmt-expr-gated.rs
Normal file
6
src/test/ui/if-attrs/stmt-expr-gated.rs
Normal file
@ -0,0 +1,6 @@
|
||||
fn main() {
|
||||
let _ = #[deny(warnings)] if true { //~ ERROR attributes on expressions
|
||||
} else if false {
|
||||
} else {
|
||||
};
|
||||
}
|
12
src/test/ui/if-attrs/stmt-expr-gated.stderr
Normal file
12
src/test/ui/if-attrs/stmt-expr-gated.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
error[E0658]: attributes on expressions are experimental
|
||||
--> $DIR/stmt-expr-gated.rs:2:13
|
||||
|
|
||||
LL | let _ = #[deny(warnings)] if true {
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
|
||||
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
15
src/test/ui/impl-trait/issue-57200.rs
Normal file
15
src/test/ui/impl-trait/issue-57200.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// Regression test for #57200
|
||||
// FIXME: The error is temporary hack, we'll revisit here at some point.
|
||||
|
||||
#![feature(impl_trait_in_bindings)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
fn bug<'a, 'b, T>()
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
let f: impl Fn(&'a T) -> &'b T = |x| x;
|
||||
//~^ ERROR: lifetimes in impl Trait types in bindings are not currently supported
|
||||
}
|
||||
|
||||
fn main() {}
|
8
src/test/ui/impl-trait/issue-57200.stderr
Normal file
8
src/test/ui/impl-trait/issue-57200.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
error: lifetimes in impl Trait types in bindings are not currently supported
|
||||
--> $DIR/issue-57200.rs:11:12
|
||||
|
|
||||
LL | let f: impl Fn(&'a T) -> &'b T = |x| x;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
15
src/test/ui/impl-trait/issue-57201.rs
Normal file
15
src/test/ui/impl-trait/issue-57201.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// Regression test for #57201
|
||||
// FIXME: The error is temporary hack, we'll revisit here at some point.
|
||||
|
||||
#![feature(impl_trait_in_bindings)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
fn bug<'a, 'b, T>()
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
let f: &impl Fn(&'a T) -> &'b T = &|x| x;
|
||||
//~^ ERROR: lifetimes in impl Trait types in bindings are not currently supported
|
||||
}
|
||||
|
||||
fn main() {}
|
8
src/test/ui/impl-trait/issue-57201.stderr
Normal file
8
src/test/ui/impl-trait/issue-57201.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
error: lifetimes in impl Trait types in bindings are not currently supported
|
||||
--> $DIR/issue-57201.rs:11:13
|
||||
|
|
||||
LL | let f: &impl Fn(&'a T) -> &'b T = &|x| x;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
17
src/test/ui/impl-trait/issue-60473.rs
Normal file
17
src/test/ui/impl-trait/issue-60473.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Regression test for #60473
|
||||
|
||||
#![feature(impl_trait_in_bindings)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
struct A<'a>(&'a ());
|
||||
|
||||
trait Trait<T> {
|
||||
}
|
||||
|
||||
impl<T> Trait<T> for () {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x: impl Trait<A> = (); // FIXME: The error doesn't seem correct.
|
||||
//~^ ERROR: opaque type expands to a recursive type
|
||||
}
|
11
src/test/ui/impl-trait/issue-60473.stderr
Normal file
11
src/test/ui/impl-trait/issue-60473.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0720]: opaque type expands to a recursive type
|
||||
--> $DIR/issue-60473.rs:15:12
|
||||
|
|
||||
LL | let x: impl Trait<A> = (); // FIXME: The error doesn't seem correct.
|
||||
| ^^^^^^^^^^^^^ expands to a recursive type
|
||||
|
|
||||
= note: type resolves to itself
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0720`.
|
11
src/test/ui/impl-trait/issue-67166.rs
Normal file
11
src/test/ui/impl-trait/issue-67166.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// Regression test for #67166
|
||||
|
||||
#![feature(impl_trait_in_bindings)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
pub fn run() {
|
||||
let _foo: Box<impl Copy + '_> = Box::new(()); // FIXME: The error doesn't much make sense.
|
||||
//~^ ERROR: opaque type expands to a recursive type
|
||||
}
|
||||
|
||||
fn main() {}
|
11
src/test/ui/impl-trait/issue-67166.stderr
Normal file
11
src/test/ui/impl-trait/issue-67166.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0720]: opaque type expands to a recursive type
|
||||
--> $DIR/issue-67166.rs:7:19
|
||||
|
|
||||
LL | let _foo: Box<impl Copy + '_> = Box::new(()); // FIXME: The error doesn't much make sense.
|
||||
| ^^^^^^^^^^^^^^ expands to a recursive type
|
||||
|
|
||||
= note: type resolves to itself
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0720`.
|
@ -38,8 +38,6 @@ fn main() {}
|
||||
//~^ ERROR an inner attribute is not permitted in this context
|
||||
#[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
|
||||
//~^ ERROR an inner attribute is not permitted in this context
|
||||
#[cfg(FALSE)] fn e() { let _ = #[attr] if 0 {}; }
|
||||
//~^ ERROR attributes are not yet allowed on `if` expressions
|
||||
#[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
|
||||
//~^ ERROR expected `{`, found `#`
|
||||
#[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
|
||||
@ -51,14 +49,11 @@ fn main() {}
|
||||
#[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
|
||||
//~^ ERROR an inner attribute is not permitted in this context
|
||||
#[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
|
||||
//~^ ERROR attributes are not yet allowed on `if` expressions
|
||||
//~| ERROR expected `{`, found `#`
|
||||
//~^ ERROR expected `{`, found `#`
|
||||
#[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
|
||||
//~^ ERROR expected `{`, found `#`
|
||||
#[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
|
||||
//~^ ERROR an inner attribute is not permitted in this context
|
||||
#[cfg(FALSE)] fn e() { let _ = #[attr] if let _ = 0 {}; }
|
||||
//~^ ERROR attributes are not yet allowed on `if` expressions
|
||||
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
|
||||
//~^ ERROR expected `{`, found `#`
|
||||
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
|
||||
@ -70,8 +65,7 @@ fn main() {}
|
||||
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
|
||||
//~^ ERROR an inner attribute is not permitted in this context
|
||||
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
|
||||
//~^ ERROR attributes are not yet allowed on `if` expressions
|
||||
//~| ERROR expected `{`, found `#`
|
||||
//~^ ERROR expected `{`, found `#`
|
||||
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
|
||||
//~^ ERROR expected `{`, found `#`
|
||||
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
|
||||
|
@ -136,14 +136,8 @@ LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
|
||||
|
|
||||
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
|
||||
|
||||
error: attributes are not yet allowed on `if` expressions
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:41:32
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if 0 {}; }
|
||||
| ^^^^^^^
|
||||
|
||||
error: expected `{`, found `#`
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:43:37
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:41:37
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
|
||||
| -- ^ --- help: try placing this code inside a block: `{ {}; }`
|
||||
@ -152,7 +146,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
|
||||
| this `if` expression has a condition, but no block
|
||||
|
||||
error: an inner attribute is not permitted in this context
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:45:38
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:43:38
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
|
||||
| ^^^^^^^^
|
||||
@ -160,13 +154,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
|
||||
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
|
||||
|
||||
error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:47:40
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:45:40
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; }
|
||||
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
|
||||
|
||||
error: expected `{`, found `#`
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:49:45
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:47:45
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
|
||||
| ^ --- help: try placing this code inside a block: `{ {}; }`
|
||||
@ -174,21 +168,15 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
|
||||
| expected `{`
|
||||
|
||||
error: an inner attribute is not permitted in this context
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:51:46
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:49:46
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
|
||||
|
||||
error: attributes are not yet allowed on `if` expressions
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:53:45
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
|
||||
| ^^^^^^^
|
||||
|
||||
error: expected `{`, found `#`
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:53:45
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:51:45
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
|
||||
| ^ -------- help: try placing this code inside a block: `{ if 0 {}; }`
|
||||
@ -196,7 +184,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
|
||||
| expected `{`
|
||||
|
||||
error: expected `{`, found `#`
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:56:50
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:53:50
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
|
||||
| -- ^ --- help: try placing this code inside a block: `{ {}; }`
|
||||
@ -205,21 +193,15 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
|
||||
| this `if` expression has a condition, but no block
|
||||
|
||||
error: an inner attribute is not permitted in this context
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:58:51
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:55:51
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
|
||||
|
||||
error: attributes are not yet allowed on `if` expressions
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:60:32
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if let _ = 0 {}; }
|
||||
| ^^^^^^^
|
||||
|
||||
error: expected `{`, found `#`
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:62:45
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:57:45
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
|
||||
| -- ^ --- help: try placing this code inside a block: `{ {}; }`
|
||||
@ -228,7 +210,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
|
||||
| this `if` expression has a condition, but no block
|
||||
|
||||
error: an inner attribute is not permitted in this context
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:64:46
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:59:46
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
|
||||
| ^^^^^^^^
|
||||
@ -236,13 +218,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
|
||||
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
|
||||
|
||||
error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:66:48
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:61:48
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
|
||||
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
|
||||
|
||||
error: expected `{`, found `#`
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:68:53
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:63:53
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
|
||||
| ^ --- help: try placing this code inside a block: `{ {}; }`
|
||||
@ -250,21 +232,15 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
|
||||
| expected `{`
|
||||
|
||||
error: an inner attribute is not permitted in this context
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:70:54
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:65:54
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
|
||||
|
||||
error: attributes are not yet allowed on `if` expressions
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:72:53
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
|
||||
| ^^^^^^^
|
||||
|
||||
error: expected `{`, found `#`
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:72:53
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:67:53
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
|
||||
| ^ ---------------- help: try placing this code inside a block: `{ if let _ = 0 {}; }`
|
||||
@ -272,7 +248,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}
|
||||
| expected `{`
|
||||
|
||||
error: expected `{`, found `#`
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:75:66
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:69:66
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
|
||||
| -- ^ --- help: try placing this code inside a block: `{ {}; }`
|
||||
@ -281,7 +257,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}
|
||||
| this `if` expression has a condition, but no block
|
||||
|
||||
error: an inner attribute is not permitted in this context
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:77:67
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:71:67
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
|
||||
| ^^^^^^^^
|
||||
@ -289,7 +265,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}
|
||||
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
|
||||
|
||||
error: an inner attribute is not permitted following an outer attribute
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:80:32
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:74:32
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; }
|
||||
| ------- ^^^^^^^^ not permitted following an outer attribute
|
||||
@ -299,7 +275,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; }
|
||||
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
|
||||
|
||||
error: an inner attribute is not permitted following an outer attribute
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:82:32
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:76:32
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; }
|
||||
| ------- ^^^^^^^^ not permitted following an outer attribute
|
||||
@ -309,7 +285,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; }
|
||||
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
|
||||
|
||||
error: an inner attribute is not permitted following an outer attribute
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:84:32
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:78:32
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
|
||||
| ------- ^^^^^^^^ not permitted following an outer attribute
|
||||
@ -319,7 +295,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
|
||||
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
|
||||
|
||||
error: an inner attribute is not permitted following an outer attribute
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:86:32
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:80:32
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
|
||||
| ------- ^^^^^^^^ not permitted following an outer attribute
|
||||
@ -329,7 +305,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
|
||||
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
|
||||
|
||||
error: an inner attribute is not permitted following an outer attribute
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:88:32
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:82:32
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
|
||||
| ------- ^^^^^^^^ not permitted following an outer attribute
|
||||
@ -339,7 +315,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
|
||||
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
|
||||
|
||||
error[E0586]: inclusive range with no end
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:94:35
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:88:35
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
|
||||
| ^^^ help: use `..` instead
|
||||
@ -347,13 +323,13 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
|
||||
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
|
||||
|
||||
error: expected one of `=>`, `if`, or `|`, found `#`
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:94:38
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:88:38
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
|
||||
| ^ expected one of `=>`, `if`, or `|`
|
||||
|
||||
error[E0586]: inclusive range with no end
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:97:35
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:91:35
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
|
||||
| ^^^ help: use `..` instead
|
||||
@ -361,19 +337,19 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
|
||||
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
|
||||
|
||||
error: expected one of `=>`, `if`, or `|`, found `#`
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:97:38
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:91:38
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
|
||||
| ^ expected one of `=>`, `if`, or `|`
|
||||
|
||||
error: unexpected token: `#`
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:100:39
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:94:39
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
|
||||
| ^
|
||||
|
||||
error[E0586]: inclusive range with no end
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:102:35
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:96:35
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
|
||||
| ^^^ help: use `..` instead
|
||||
@ -381,47 +357,47 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
|
||||
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
|
||||
|
||||
error: expected one of `=>`, `if`, or `|`, found `#`
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:102:38
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:96:38
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
|
||||
| ^ expected one of `=>`, `if`, or `|`
|
||||
|
||||
error: unexpected token: `#`
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:106:34
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:100:34
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
|
||||
| ^
|
||||
|
||||
error: expected one of `.`, `;`, `?`, or an operator, found `#`
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:106:34
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:100:34
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
|
||||
| ^ expected one of `.`, `;`, `?`, or an operator
|
||||
|
||||
error: unexpected token: `#`
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:109:34
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:103:34
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
|
||||
| ^
|
||||
|
||||
error: expected one of `.`, `;`, `?`, or an operator, found `#`
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:109:34
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:103:34
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
|
||||
| ^ expected one of `.`, `;`, `?`, or an operator
|
||||
|
||||
error: expected statement after outer attribute
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:114:37
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:108:37
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } }
|
||||
| ^^^^^^^
|
||||
|
||||
error: expected statement after outer attribute
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:116:37
|
||||
--> $DIR/attr-stmt-expr-attr-bad.rs:110:37
|
||||
|
|
||||
LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } }
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to 57 previous errors
|
||||
error: aborting due to 53 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0586`.
|
||||
|
@ -1,9 +0,0 @@
|
||||
fn main() {
|
||||
#[attr] if true {};
|
||||
//~^ ERROR cannot find attribute
|
||||
//~| ERROR attributes are not yet allowed on `if` expressions
|
||||
#[attr] if true {};
|
||||
//~^ ERROR cannot find attribute
|
||||
//~| ERROR attributes are not yet allowed on `if` expressions
|
||||
let _recovery_witness: () = 0; //~ ERROR mismatched types
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
error: attributes are not yet allowed on `if` expressions
|
||||
--> $DIR/recovery-attr-on-if.rs:2:5
|
||||
|
|
||||
LL | #[attr] if true {};
|
||||
| ^^^^^^^
|
||||
|
||||
error: attributes are not yet allowed on `if` expressions
|
||||
--> $DIR/recovery-attr-on-if.rs:5:5
|
||||
|
|
||||
LL | #[attr] if true {};
|
||||
| ^^^^^^^
|
||||
|
||||
error: cannot find attribute `attr` in this scope
|
||||
--> $DIR/recovery-attr-on-if.rs:5:7
|
||||
|
|
||||
LL | #[attr] if true {};
|
||||
| ^^^^
|
||||
|
||||
error: cannot find attribute `attr` in this scope
|
||||
--> $DIR/recovery-attr-on-if.rs:2:7
|
||||
|
|
||||
LL | #[attr] if true {};
|
||||
| ^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/recovery-attr-on-if.rs:8:33
|
||||
|
|
||||
LL | let _recovery_witness: () = 0;
|
||||
| -- ^ expected `()`, found integer
|
||||
| |
|
||||
| expected due to this
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
19
src/test/ui/sanitize/badfree.rs
Normal file
19
src/test/ui/sanitize/badfree.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// needs-sanitizer-support
|
||||
// only-x86_64
|
||||
//
|
||||
// compile-flags: -Z sanitizer=address -O
|
||||
//
|
||||
// run-fail
|
||||
// error-pattern: AddressSanitizer: SEGV
|
||||
|
||||
use std::ffi::c_void;
|
||||
|
||||
extern "C" {
|
||||
fn free(ptr: *mut c_void);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
free(1 as *mut c_void);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user