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
61 changed files with 1052 additions and 604 deletions
|
|
@ -245,7 +245,7 @@ fn print_backtrace(backtrace: &mut Backtrace) {
|
||||||
eprintln!("\n\nAn error occurred in miri:\n{:?}", 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 {
|
fn from(err: ErrorHandled) -> Self {
|
||||||
match err {
|
match err {
|
||||||
ErrorHandled::Reported => err_inval!(ReferencedConstant),
|
ErrorHandled::Reported => err_inval!(ReferencedConstant),
|
||||||
|
|
@ -291,7 +291,7 @@ pub enum InvalidProgramInfo<'tcx> {
|
||||||
Layout(layout::LayoutError<'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 {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
use InvalidProgramInfo::*;
|
use InvalidProgramInfo::*;
|
||||||
match self {
|
match self {
|
||||||
|
|
@ -321,6 +321,8 @@ pub enum UndefinedBehaviorInfo {
|
||||||
RemainderByZero,
|
RemainderByZero,
|
||||||
/// Overflowing inbounds pointer arithmetic.
|
/// Overflowing inbounds pointer arithmetic.
|
||||||
PointerArithOverflow,
|
PointerArithOverflow,
|
||||||
|
/// Invalid metadata in a wide pointer (using `str` to avoid allocations).
|
||||||
|
InvalidMeta(&'static str),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for UndefinedBehaviorInfo {
|
impl fmt::Debug for UndefinedBehaviorInfo {
|
||||||
|
|
@ -338,6 +340,7 @@ impl fmt::Debug for UndefinedBehaviorInfo {
|
||||||
DivisionByZero => write!(f, "dividing by zero"),
|
DivisionByZero => write!(f, "dividing by zero"),
|
||||||
RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"),
|
RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"),
|
||||||
PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"),
|
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),
|
Unsupported(String),
|
||||||
|
|
||||||
/// When const-prop encounters a situation it does not support, it raises this error.
|
/// When const-prop encounters a situation it does not support, it raises this error.
|
||||||
/// This must not allocate for performance reasons.
|
/// This must not allocate for performance reasons (hence `str`, not `String`).
|
||||||
ConstPropUnsupported(&'tcx str),
|
ConstPropUnsupported(&'static str),
|
||||||
|
|
||||||
// -- Everything below is not categorized yet --
|
// -- Everything below is not categorized yet --
|
||||||
FunctionAbiMismatch(Abi, Abi),
|
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 {
|
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> {
|
pub fn meta(&self, span: Span) -> Option<MetaItem> {
|
||||||
Some(MetaItem {
|
Some(MetaItem {
|
||||||
path: self.path.clone(),
|
path: self.path.clone(),
|
||||||
|
|
@ -437,7 +441,7 @@ impl MetaItem {
|
||||||
I: Iterator<Item = TokenTree>,
|
I: Iterator<Item = TokenTree>,
|
||||||
{
|
{
|
||||||
// FIXME: Share code with `parse_path`.
|
// 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::Ident(..), span }))
|
||||||
| Some(TokenTree::Token(Token { kind: kind @ token::ModSep, span })) => 'arm: {
|
| Some(TokenTree::Token(Token { kind: kind @ token::ModSep, span })) => 'arm: {
|
||||||
let mut segments = if let token::Ident(name, _) = kind {
|
let mut segments = if let token::Ident(name, _) = kind {
|
||||||
|
|
@ -453,7 +457,7 @@ impl MetaItem {
|
||||||
};
|
};
|
||||||
loop {
|
loop {
|
||||||
if let Some(TokenTree::Token(Token { kind: token::Ident(name, _), span })) =
|
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)));
|
segments.push(PathSegment::from_ident(Ident::new(name, span)));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -470,7 +474,6 @@ impl MetaItem {
|
||||||
Path { span, segments }
|
Path { span, segments }
|
||||||
}
|
}
|
||||||
Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. })) => match *nt {
|
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::NtMeta(ref item) => return item.meta(item.path.span),
|
||||||
token::Nonterminal::NtPath(ref path) => path.clone(),
|
token::Nonterminal::NtPath(ref path) => path.clone(),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ use rustc_macros::HashStable_Generic;
|
||||||
use rustc_span::symbol::kw;
|
use rustc_span::symbol::kw;
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use rustc_span::{self, Span, DUMMY_SP};
|
use rustc_span::{self, Span, DUMMY_SP};
|
||||||
use std::fmt;
|
use std::borrow::Cow;
|
||||||
use std::mem;
|
use std::{fmt, mem};
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
|
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
|
||||||
#[derive(HashStable_Generic)]
|
#[derive(HashStable_Generic)]
|
||||||
|
|
@ -225,8 +225,15 @@ pub enum TokenKind {
|
||||||
/* Literals */
|
/* Literals */
|
||||||
Literal(Lit),
|
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),
|
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),
|
Lifetime(ast::Name),
|
||||||
|
|
||||||
Interpolated(Lrc<Nonterminal>),
|
Interpolated(Lrc<Nonterminal>),
|
||||||
|
|
@ -328,6 +335,19 @@ impl Token {
|
||||||
mem::replace(self, Token::dummy())
|
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 {
|
pub fn is_op(&self) -> bool {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..)
|
OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..)
|
||||||
|
|
@ -345,7 +365,7 @@ impl Token {
|
||||||
|
|
||||||
/// Returns `true` if the token can appear at the start of an expression.
|
/// Returns `true` if the token can appear at the start of an expression.
|
||||||
pub fn can_begin_expr(&self) -> bool {
|
pub fn can_begin_expr(&self) -> bool {
|
||||||
match self.kind {
|
match self.uninterpolate().kind {
|
||||||
Ident(name, is_raw) =>
|
Ident(name, is_raw) =>
|
||||||
ident_can_begin_expr(name, self.span, is_raw), // value name or keyword
|
ident_can_begin_expr(name, self.span, is_raw), // value name or keyword
|
||||||
OpenDelim(..) | // tuple, array or block
|
OpenDelim(..) | // tuple, array or block
|
||||||
|
|
@ -363,12 +383,10 @@ impl Token {
|
||||||
Lifetime(..) | // labeled loop
|
Lifetime(..) | // labeled loop
|
||||||
Pound => true, // expression attributes
|
Pound => true, // expression attributes
|
||||||
Interpolated(ref nt) => match **nt {
|
Interpolated(ref nt) => match **nt {
|
||||||
NtIdent(ident, is_raw) => ident_can_begin_expr(ident.name, ident.span, is_raw),
|
|
||||||
NtLiteral(..) |
|
NtLiteral(..) |
|
||||||
NtExpr(..) |
|
NtExpr(..) |
|
||||||
NtBlock(..) |
|
NtBlock(..) |
|
||||||
NtPath(..) |
|
NtPath(..) => true,
|
||||||
NtLifetime(..) => true,
|
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
_ => false,
|
_ => false,
|
||||||
|
|
@ -377,7 +395,7 @@ impl Token {
|
||||||
|
|
||||||
/// Returns `true` if the token can appear at the start of a type.
|
/// Returns `true` if the token can appear at the start of a type.
|
||||||
pub fn can_begin_type(&self) -> bool {
|
pub fn can_begin_type(&self) -> bool {
|
||||||
match self.kind {
|
match self.uninterpolate().kind {
|
||||||
Ident(name, is_raw) =>
|
Ident(name, is_raw) =>
|
||||||
ident_can_begin_type(name, self.span, is_raw), // type name or keyword
|
ident_can_begin_type(name, self.span, is_raw), // type name or keyword
|
||||||
OpenDelim(Paren) | // tuple
|
OpenDelim(Paren) | // tuple
|
||||||
|
|
@ -391,8 +409,7 @@ impl Token {
|
||||||
Lt | BinOp(Shl) | // associated path
|
Lt | BinOp(Shl) | // associated path
|
||||||
ModSep => true, // global path
|
ModSep => true, // global path
|
||||||
Interpolated(ref nt) => match **nt {
|
Interpolated(ref nt) => match **nt {
|
||||||
NtIdent(ident, is_raw) => ident_can_begin_type(ident.name, ident.span, is_raw),
|
NtTy(..) | NtPath(..) => true,
|
||||||
NtTy(..) | NtPath(..) | NtLifetime(..) => true,
|
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
_ => false,
|
_ => false,
|
||||||
|
|
@ -433,11 +450,10 @@ impl Token {
|
||||||
///
|
///
|
||||||
/// Keep this in sync with `Lit::from_token`.
|
/// Keep this in sync with `Lit::from_token`.
|
||||||
pub fn can_begin_literal_or_bool(&self) -> bool {
|
pub fn can_begin_literal_or_bool(&self) -> bool {
|
||||||
match self.kind {
|
match self.uninterpolate().kind {
|
||||||
Literal(..) | BinOp(Minus) => true,
|
Literal(..) | BinOp(Minus) => true,
|
||||||
Ident(name, false) if name.is_bool_lit() => true,
|
Ident(name, false) if name.is_bool_lit() => true,
|
||||||
Interpolated(ref nt) => match &**nt {
|
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(_)),
|
NtExpr(e) | NtLiteral(e) => matches!(e.kind, ast::ExprKind::Lit(_)),
|
||||||
_ => false,
|
_ => 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.
|
/// Returns an identifier if this token is an identifier.
|
||||||
pub fn ident(&self) -> Option<(ast::Ident, /* is_raw */ bool)> {
|
pub fn ident(&self) -> Option<(ast::Ident, /* is_raw */ bool)> {
|
||||||
match self.kind {
|
let token = self.uninterpolate();
|
||||||
Ident(name, is_raw) => Some((ast::Ident::new(name, self.span), is_raw)),
|
match token.kind {
|
||||||
Interpolated(ref nt) => match **nt {
|
Ident(name, is_raw) => Some((ast::Ident::new(name, token.span), is_raw)),
|
||||||
NtIdent(ident, is_raw) => Some((ident, is_raw)),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a lifetime identifier if this token is a lifetime.
|
/// Returns a lifetime identifier if this token is a lifetime.
|
||||||
pub fn lifetime(&self) -> Option<ast::Ident> {
|
pub fn lifetime(&self) -> Option<ast::Ident> {
|
||||||
match self.kind {
|
let token = self.uninterpolate();
|
||||||
Lifetime(name) => Some(ast::Ident::new(name, self.span)),
|
match token.kind {
|
||||||
Interpolated(ref nt) => match **nt {
|
Lifetime(name) => Some(ast::Ident::new(name, token.span)),
|
||||||
NtLifetime(ident) => Some(ident),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -714,6 +741,24 @@ pub enum Nonterminal {
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
rustc_data_structures::static_assert_size!(Nonterminal, 40);
|
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 {
|
impl PartialEq for Nonterminal {
|
||||||
fn eq(&self, rhs: &Self) -> bool {
|
fn eq(&self, rhs: &Self) -> bool {
|
||||||
match (self, rhs) {
|
match (self, rhs) {
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,13 @@ impl TokenTree {
|
||||||
pub fn close_tt(span: DelimSpan, delim: DelimToken) -> TokenTree {
|
pub fn close_tt(span: DelimSpan, delim: DelimToken) -> TokenTree {
|
||||||
TokenTree::token(token::CloseDelim(delim), span.close)
|
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
|
impl<CTX> HashStable<CTX> for TokenStream
|
||||||
|
|
|
||||||
|
|
@ -191,23 +191,16 @@ impl Lit {
|
||||||
///
|
///
|
||||||
/// Keep this in sync with `Token::can_begin_literal_or_bool`.
|
/// Keep this in sync with `Token::can_begin_literal_or_bool`.
|
||||||
pub fn from_token(token: &Token) -> Result<Lit, LitError> {
|
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::Ident(name, false) if name.is_bool_lit() => {
|
||||||
token::Lit::new(token::Bool, name, None)
|
token::Lit::new(token::Bool, name, None)
|
||||||
}
|
}
|
||||||
token::Literal(lit) => lit,
|
token::Literal(lit) => lit,
|
||||||
token::Interpolated(ref nt) => {
|
token::Interpolated(ref nt) => {
|
||||||
match &**nt {
|
if let token::NtExpr(expr) | token::NtLiteral(expr) = &**nt {
|
||||||
token::NtIdent(ident, false) if ident.name.is_bool_lit() => {
|
if let ast::ExprKind::Lit(lit) = &expr.kind {
|
||||||
let lit = token::Lit::new(token::Bool, ident.name, None);
|
return Ok(lit.clone());
|
||||||
return Lit::from_lit_token(lit, ident.span);
|
|
||||||
}
|
}
|
||||||
token::NtExpr(expr) | token::NtLiteral(expr) => {
|
|
||||||
if let ast::ExprKind::Lit(lit) = &expr.kind {
|
|
||||||
return Ok(lit.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
return Err(LitError::NotLiteral);
|
return Err(LitError::NotLiteral);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -156,44 +156,43 @@ fn parse_args<'a>(
|
||||||
if p.token == token::Eof {
|
if p.token == token::Eof {
|
||||||
break;
|
break;
|
||||||
} // accept trailing commas
|
} // accept trailing commas
|
||||||
if p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq) {
|
match p.token.ident() {
|
||||||
named = true;
|
Some((ident, _)) if p.look_ahead(1, |t| *t == token::Eq) => {
|
||||||
let name = if let token::Ident(name, _) = p.normalized_token.kind {
|
named = true;
|
||||||
p.bump();
|
p.bump();
|
||||||
name
|
p.expect(&token::Eq)?;
|
||||||
} else {
|
let e = p.parse_expr()?;
|
||||||
unreachable!();
|
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")
|
||||||
p.expect(&token::Eq)?;
|
.span_label(e.span, "duplicate argument")
|
||||||
let e = p.parse_expr()?;
|
.emit();
|
||||||
if let Some(prev) = names.get(&name) {
|
continue;
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
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))
|
Ok((fmtstr, args, names))
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_data_structures::const_cstr;
|
use rustc_data_structures::const_cstr;
|
||||||
use rustc_data_structures::fingerprint::Fingerprint;
|
use rustc_data_structures::fingerprint::Fingerprint;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::small_c_str::SmallCStr;
|
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_fs_util::path_to_c_string;
|
use rustc_fs_util::path_to_c_string;
|
||||||
use rustc_hir::def::CtorKind;
|
use rustc_hir::def::CtorKind;
|
||||||
|
|
@ -49,7 +48,6 @@ use rustc_target::abi::HasDataLayout;
|
||||||
|
|
||||||
use libc::{c_longlong, c_uint};
|
use libc::{c_longlong, c_uint};
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
use std::ffi::CString;
|
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
@ -227,11 +225,11 @@ impl TypeMap<'ll, 'tcx> {
|
||||||
/// Gets the unique type ID string for an enum variant part.
|
/// Gets the unique type ID string for an enum variant part.
|
||||||
/// Variant parts are not types and shouldn't really have their own ID,
|
/// Variant parts are not types and shouldn't really have their own ID,
|
||||||
/// but it makes `set_members_of_composite_type()` simpler.
|
/// 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 {
|
fn get_unique_type_id_str_of_enum_variant_part(
|
||||||
let variant_part_type_id =
|
&mut self,
|
||||||
format!("{}_variant_part", self.get_unique_type_id_as_string(enum_type_id));
|
enum_type_id: UniqueTypeId,
|
||||||
let interner_key = self.unique_id_interner.intern(&variant_part_type_id);
|
) -> String {
|
||||||
self.unique_id_interner.get(interner_key)
|
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
|
// type is going to see *something* weird - the only
|
||||||
// question is what exactly it will see.
|
// question is what exactly it will see.
|
||||||
let (size, align) = cx.size_and_align_of(t);
|
let (size, align) = cx.size_and_align_of(t);
|
||||||
|
let name = "<recur_type>";
|
||||||
llvm::LLVMRustDIBuilderCreateBasicType(
|
llvm::LLVMRustDIBuilderCreateBasicType(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
SmallCStr::new("<recur_type>").as_ptr(),
|
name.as_ptr().cast(),
|
||||||
|
name.len(),
|
||||||
size.bits(),
|
size.bits(),
|
||||||
align.bits() as u32,
|
align.bits() as u32,
|
||||||
DW_ATE_unsigned,
|
DW_ATE_unsigned,
|
||||||
|
|
@ -786,16 +786,17 @@ fn file_metadata_raw(
|
||||||
let (file_name, directory) = v.key();
|
let (file_name, directory) = v.key();
|
||||||
debug!("file_metadata: file_name: {:?}, directory: {:?}", file_name, directory);
|
debug!("file_metadata: file_name: {:?}, directory: {:?}", file_name, directory);
|
||||||
|
|
||||||
let file_name = SmallCStr::new(if let Some(file_name) = file_name {
|
let file_name = file_name.as_deref().unwrap_or("<unknown>");
|
||||||
&file_name
|
let directory = directory.as_deref().unwrap_or("");
|
||||||
} else {
|
|
||||||
"<unknown>"
|
|
||||||
});
|
|
||||||
let directory =
|
|
||||||
SmallCStr::new(if let Some(directory) = directory { &directory } else { "" });
|
|
||||||
|
|
||||||
let file_metadata = unsafe {
|
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);
|
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 (size, align) = cx.size_and_align_of(t);
|
||||||
let name = SmallCStr::new(name);
|
|
||||||
let ty_metadata = unsafe {
|
let ty_metadata = unsafe {
|
||||||
llvm::LLVMRustDIBuilderCreateBasicType(
|
llvm::LLVMRustDIBuilderCreateBasicType(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
name.as_ptr(),
|
name.as_ptr().cast(),
|
||||||
|
name.len(),
|
||||||
size.bits(),
|
size.bits(),
|
||||||
align.bits() as u32,
|
align.bits() as u32,
|
||||||
encoding,
|
encoding,
|
||||||
|
|
@ -851,14 +852,15 @@ fn pointer_type_metadata(
|
||||||
) -> &'ll DIType {
|
) -> &'ll DIType {
|
||||||
let (pointer_size, pointer_align) = cx.size_and_align_of(pointer_type);
|
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 = compute_debuginfo_type_name(cx.tcx, pointer_type, false);
|
||||||
let name = SmallCStr::new(&name);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMRustDIBuilderCreatePointerType(
|
llvm::LLVMRustDIBuilderCreatePointerType(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
pointee_type_metadata,
|
pointee_type_metadata,
|
||||||
pointer_size.bits(),
|
pointer_size.bits(),
|
||||||
pointer_align.bits() as u32,
|
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 producer = format!("clang LLVM ({})", rustc_producer);
|
||||||
|
|
||||||
let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
|
let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
|
||||||
let name_in_debuginfo = SmallCStr::new(&name_in_debuginfo);
|
let work_dir = tcx.sess.working_dir.0.to_string_lossy();
|
||||||
let work_dir = SmallCStr::new(&tcx.sess.working_dir.0.to_string_lossy());
|
|
||||||
let producer = CString::new(producer).unwrap();
|
|
||||||
let flags = "\0";
|
let flags = "\0";
|
||||||
let split_name = "\0";
|
let split_name = "";
|
||||||
|
|
||||||
// FIXME(#60020):
|
// FIXME(#60020):
|
||||||
//
|
//
|
||||||
|
|
@ -916,19 +916,23 @@ pub fn compile_unit_metadata(
|
||||||
unsafe {
|
unsafe {
|
||||||
let file_metadata = llvm::LLVMRustDIBuilderCreateFile(
|
let file_metadata = llvm::LLVMRustDIBuilderCreateFile(
|
||||||
debug_context.builder,
|
debug_context.builder,
|
||||||
name_in_debuginfo.as_ptr(),
|
name_in_debuginfo.as_ptr().cast(),
|
||||||
work_dir.as_ptr(),
|
name_in_debuginfo.len(),
|
||||||
|
work_dir.as_ptr().cast(),
|
||||||
|
work_dir.len(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
|
let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
|
||||||
debug_context.builder,
|
debug_context.builder,
|
||||||
DW_LANG_RUST,
|
DW_LANG_RUST,
|
||||||
file_metadata,
|
file_metadata,
|
||||||
producer.as_ptr(),
|
producer.as_ptr().cast(),
|
||||||
|
producer.len(),
|
||||||
tcx.sess.opts.optimize != config::OptLevel::No,
|
tcx.sess.opts.optimize != config::OptLevel::No,
|
||||||
flags.as_ptr().cast(),
|
flags.as_ptr().cast(),
|
||||||
0,
|
0,
|
||||||
split_name.as_ptr().cast(),
|
split_name.as_ptr().cast(),
|
||||||
|
split_name.len(),
|
||||||
kind,
|
kind,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -1021,12 +1025,12 @@ impl<'ll> MemberDescription<'ll> {
|
||||||
cx: &CodegenCx<'ll, '_>,
|
cx: &CodegenCx<'ll, '_>,
|
||||||
composite_type_metadata: &'ll DIScope,
|
composite_type_metadata: &'ll DIScope,
|
||||||
) -> &'ll DIType {
|
) -> &'ll DIType {
|
||||||
let member_name = CString::new(self.name).unwrap();
|
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMRustDIBuilderCreateVariantMemberType(
|
llvm::LLVMRustDIBuilderCreateVariantMemberType(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
composite_type_metadata,
|
composite_type_metadata,
|
||||||
member_name.as_ptr(),
|
self.name.as_ptr().cast(),
|
||||||
|
self.name.len(),
|
||||||
unknown_file_metadata(cx),
|
unknown_file_metadata(cx),
|
||||||
UNKNOWN_LINE_NUMBER,
|
UNKNOWN_LINE_NUMBER,
|
||||||
self.size.bits(),
|
self.size.bits(),
|
||||||
|
|
@ -1827,9 +1831,13 @@ fn prepare_enum_metadata(
|
||||||
let discriminant_base_type_metadata =
|
let discriminant_base_type_metadata =
|
||||||
type_metadata(cx, discr.to_ty(cx.tcx), rustc_span::DUMMY_SP);
|
type_metadata(cx, discr.to_ty(cx.tcx), rustc_span::DUMMY_SP);
|
||||||
|
|
||||||
|
let item_name;
|
||||||
let discriminant_name = match enum_type.kind {
|
let discriminant_name = match enum_type.kind {
|
||||||
ty::Adt(..) => SmallCStr::new(&cx.tcx.item_name(enum_def_id).as_str()),
|
ty::Adt(..) => {
|
||||||
ty::Generator(..) => SmallCStr::new(&enum_name),
|
item_name = cx.tcx.item_name(enum_def_id).as_str();
|
||||||
|
&*item_name
|
||||||
|
}
|
||||||
|
ty::Generator(..) => enum_name.as_str(),
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1837,7 +1845,8 @@ fn prepare_enum_metadata(
|
||||||
llvm::LLVMRustDIBuilderCreateEnumerationType(
|
llvm::LLVMRustDIBuilderCreateEnumerationType(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
containing_scope,
|
containing_scope,
|
||||||
discriminant_name.as_ptr(),
|
discriminant_name.as_ptr().cast(),
|
||||||
|
discriminant_name.len(),
|
||||||
file_metadata,
|
file_metadata,
|
||||||
UNKNOWN_LINE_NUMBER,
|
UNKNOWN_LINE_NUMBER,
|
||||||
discriminant_size.bits(),
|
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) {
|
if use_enum_fallback(cx) {
|
||||||
let discriminant_type_metadata = match layout.variants {
|
let discriminant_type_metadata = match layout.variants {
|
||||||
layout::Variants::Single { .. }
|
layout::Variants::Single { .. }
|
||||||
|
|
@ -1891,20 +1895,27 @@ fn prepare_enum_metadata(
|
||||||
} => Some(discriminant_type_metadata(discr.value)),
|
} => Some(discriminant_type_metadata(discr.value)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let enum_metadata = unsafe {
|
let enum_metadata = {
|
||||||
llvm::LLVMRustDIBuilderCreateUnionType(
|
let type_map = debug_context(cx).type_map.borrow();
|
||||||
DIB(cx),
|
let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id);
|
||||||
containing_scope,
|
|
||||||
enum_name.as_ptr(),
|
unsafe {
|
||||||
file_metadata,
|
llvm::LLVMRustDIBuilderCreateUnionType(
|
||||||
UNKNOWN_LINE_NUMBER,
|
DIB(cx),
|
||||||
layout.size.bits(),
|
containing_scope,
|
||||||
layout.align.abi.bits() as u32,
|
enum_name.as_ptr().cast(),
|
||||||
DIFlags::FlagZero,
|
enum_name.len(),
|
||||||
None,
|
file_metadata,
|
||||||
0, // RuntimeLang
|
UNKNOWN_LINE_NUMBER,
|
||||||
unique_type_id_str.as_ptr(),
|
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(
|
return create_and_register_recursive_type_forward_declaration(
|
||||||
|
|
@ -1924,10 +1935,9 @@ fn prepare_enum_metadata(
|
||||||
}
|
}
|
||||||
|
|
||||||
let discriminator_name = match &enum_type.kind {
|
let discriminator_name = match &enum_type.kind {
|
||||||
ty::Generator(..) => Some(SmallCStr::new(&"__state")),
|
ty::Generator(..) => "__state",
|
||||||
_ => None,
|
_ => "",
|
||||||
};
|
};
|
||||||
let discriminator_name = discriminator_name.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut());
|
|
||||||
let discriminator_metadata = match layout.variants {
|
let discriminator_metadata = match layout.variants {
|
||||||
// A single-variant enum has no discriminant.
|
// A single-variant enum has no discriminant.
|
||||||
layout::Variants::Single { .. } => None,
|
layout::Variants::Single { .. } => None,
|
||||||
|
|
@ -1955,7 +1965,8 @@ fn prepare_enum_metadata(
|
||||||
Some(llvm::LLVMRustDIBuilderCreateMemberType(
|
Some(llvm::LLVMRustDIBuilderCreateMemberType(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
containing_scope,
|
containing_scope,
|
||||||
discriminator_name,
|
discriminator_name.as_ptr().cast(),
|
||||||
|
discriminator_name.len(),
|
||||||
file_metadata,
|
file_metadata,
|
||||||
UNKNOWN_LINE_NUMBER,
|
UNKNOWN_LINE_NUMBER,
|
||||||
size.bits(),
|
size.bits(),
|
||||||
|
|
@ -1981,7 +1992,8 @@ fn prepare_enum_metadata(
|
||||||
Some(llvm::LLVMRustDIBuilderCreateMemberType(
|
Some(llvm::LLVMRustDIBuilderCreateMemberType(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
containing_scope,
|
containing_scope,
|
||||||
discriminator_name,
|
discriminator_name.as_ptr().cast(),
|
||||||
|
discriminator_name.len(),
|
||||||
file_metadata,
|
file_metadata,
|
||||||
UNKNOWN_LINE_NUMBER,
|
UNKNOWN_LINE_NUMBER,
|
||||||
size.bits(),
|
size.bits(),
|
||||||
|
|
@ -2010,18 +2022,18 @@ fn prepare_enum_metadata(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let variant_part_unique_type_id_str = SmallCStr::new(
|
let variant_part_unique_type_id_str = debug_context(cx)
|
||||||
debug_context(cx)
|
.type_map
|
||||||
.type_map
|
.borrow_mut()
|
||||||
.borrow_mut()
|
.get_unique_type_id_str_of_enum_variant_part(unique_type_id);
|
||||||
.get_unique_type_id_str_of_enum_variant_part(unique_type_id),
|
|
||||||
);
|
|
||||||
let empty_array = create_DIArray(DIB(cx), &[]);
|
let empty_array = create_DIArray(DIB(cx), &[]);
|
||||||
|
let name = "";
|
||||||
let variant_part = unsafe {
|
let variant_part = unsafe {
|
||||||
llvm::LLVMRustDIBuilderCreateVariantPart(
|
llvm::LLVMRustDIBuilderCreateVariantPart(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
containing_scope,
|
containing_scope,
|
||||||
ptr::null_mut(),
|
name.as_ptr().cast(),
|
||||||
|
name.len(),
|
||||||
file_metadata,
|
file_metadata,
|
||||||
UNKNOWN_LINE_NUMBER,
|
UNKNOWN_LINE_NUMBER,
|
||||||
layout.size.bits(),
|
layout.size.bits(),
|
||||||
|
|
@ -2029,29 +2041,38 @@ fn prepare_enum_metadata(
|
||||||
DIFlags::FlagZero,
|
DIFlags::FlagZero,
|
||||||
discriminator_metadata,
|
discriminator_metadata,
|
||||||
empty_array,
|
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));
|
outer_fields.push(Some(variant_part));
|
||||||
|
|
||||||
// The variant part must be wrapped in a struct according to DWARF.
|
let struct_wrapper = {
|
||||||
let type_array = create_DIArray(DIB(cx), &outer_fields);
|
// The variant part must be wrapped in a struct according to DWARF.
|
||||||
let struct_wrapper = unsafe {
|
let type_array = create_DIArray(DIB(cx), &outer_fields);
|
||||||
llvm::LLVMRustDIBuilderCreateStructType(
|
|
||||||
DIB(cx),
|
let type_map = debug_context(cx).type_map.borrow();
|
||||||
Some(containing_scope),
|
let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id);
|
||||||
enum_name.as_ptr(),
|
|
||||||
file_metadata,
|
unsafe {
|
||||||
UNKNOWN_LINE_NUMBER,
|
llvm::LLVMRustDIBuilderCreateStructType(
|
||||||
layout.size.bits(),
|
DIB(cx),
|
||||||
layout.align.abi.bits() as u32,
|
Some(containing_scope),
|
||||||
DIFlags::FlagZero,
|
enum_name.as_ptr().cast(),
|
||||||
None,
|
enum_name.len(),
|
||||||
type_array,
|
file_metadata,
|
||||||
0,
|
UNKNOWN_LINE_NUMBER,
|
||||||
None,
|
layout.size.bits(),
|
||||||
unique_type_id_str.as_ptr(),
|
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(
|
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);
|
cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
|
||||||
let actual_type_metadata =
|
let actual_type_metadata =
|
||||||
type_metadata(cx, actual_type, rustc_span::DUMMY_SP);
|
type_metadata(cx, actual_type, rustc_span::DUMMY_SP);
|
||||||
let name = SmallCStr::new(&name.as_str());
|
let name = &name.as_str();
|
||||||
Some(unsafe {
|
Some(unsafe {
|
||||||
Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
|
Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
None,
|
None,
|
||||||
name.as_ptr(),
|
name.as_ptr().cast(),
|
||||||
|
name.len(),
|
||||||
actual_type_metadata,
|
actual_type_metadata,
|
||||||
unknown_file_metadata(cx),
|
unknown_file_metadata(cx),
|
||||||
0,
|
0,
|
||||||
|
|
@ -2200,10 +2222,9 @@ fn create_struct_stub(
|
||||||
) -> &'ll DICompositeType {
|
) -> &'ll DICompositeType {
|
||||||
let (struct_size, struct_align) = cx.size_and_align_of(struct_type);
|
let (struct_size, struct_align) = cx.size_and_align_of(struct_type);
|
||||||
|
|
||||||
let name = SmallCStr::new(struct_type_name);
|
let type_map = debug_context(cx).type_map.borrow();
|
||||||
let unique_type_id = SmallCStr::new(
|
let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id);
|
||||||
debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id),
|
|
||||||
);
|
|
||||||
let metadata_stub = unsafe {
|
let metadata_stub = unsafe {
|
||||||
// `LLVMRustDIBuilderCreateStructType()` wants an empty array. A null
|
// `LLVMRustDIBuilderCreateStructType()` wants an empty array. A null
|
||||||
// pointer will lead to hard to trace and debug LLVM assertions
|
// pointer will lead to hard to trace and debug LLVM assertions
|
||||||
|
|
@ -2213,7 +2234,8 @@ fn create_struct_stub(
|
||||||
llvm::LLVMRustDIBuilderCreateStructType(
|
llvm::LLVMRustDIBuilderCreateStructType(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
containing_scope,
|
containing_scope,
|
||||||
name.as_ptr(),
|
struct_type_name.as_ptr().cast(),
|
||||||
|
struct_type_name.len(),
|
||||||
unknown_file_metadata(cx),
|
unknown_file_metadata(cx),
|
||||||
UNKNOWN_LINE_NUMBER,
|
UNKNOWN_LINE_NUMBER,
|
||||||
struct_size.bits(),
|
struct_size.bits(),
|
||||||
|
|
@ -2223,7 +2245,8 @@ fn create_struct_stub(
|
||||||
empty_array,
|
empty_array,
|
||||||
0,
|
0,
|
||||||
None,
|
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 {
|
) -> &'ll DICompositeType {
|
||||||
let (union_size, union_align) = cx.size_and_align_of(union_type);
|
let (union_size, union_align) = cx.size_and_align_of(union_type);
|
||||||
|
|
||||||
let name = SmallCStr::new(union_type_name);
|
let type_map = debug_context(cx).type_map.borrow();
|
||||||
let unique_type_id = SmallCStr::new(
|
let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id);
|
||||||
debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id),
|
|
||||||
);
|
|
||||||
let metadata_stub = unsafe {
|
let metadata_stub = unsafe {
|
||||||
// `LLVMRustDIBuilderCreateUnionType()` wants an empty array. A null
|
// `LLVMRustDIBuilderCreateUnionType()` wants an empty array. A null
|
||||||
// pointer will lead to hard to trace and debug LLVM assertions
|
// pointer will lead to hard to trace and debug LLVM assertions
|
||||||
|
|
@ -2252,7 +2274,8 @@ fn create_union_stub(
|
||||||
llvm::LLVMRustDIBuilderCreateUnionType(
|
llvm::LLVMRustDIBuilderCreateUnionType(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
containing_scope,
|
containing_scope,
|
||||||
name.as_ptr(),
|
union_type_name.as_ptr().cast(),
|
||||||
|
union_type_name.len(),
|
||||||
unknown_file_metadata(cx),
|
unknown_file_metadata(cx),
|
||||||
UNKNOWN_LINE_NUMBER,
|
UNKNOWN_LINE_NUMBER,
|
||||||
union_size.bits(),
|
union_size.bits(),
|
||||||
|
|
@ -2260,7 +2283,8 @@ fn create_union_stub(
|
||||||
DIFlags::FlagZero,
|
DIFlags::FlagZero,
|
||||||
Some(empty_array),
|
Some(empty_array),
|
||||||
0, // RuntimeLang
|
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 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 variable_type = Instance::mono(cx.tcx, def_id).monomorphic_ty(cx.tcx);
|
||||||
let type_metadata = type_metadata(cx, variable_type, span);
|
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 {
|
let linkage_name = if no_mangle {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id));
|
Some(mangled_name_of_instance(cx, Instance::mono(tcx, def_id)).name.as_str())
|
||||||
Some(SmallCStr::new(&linkage_name.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);
|
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(
|
llvm::LLVMRustDIBuilderCreateStaticVariable(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
Some(var_scope),
|
Some(var_scope),
|
||||||
var_name.as_ptr(),
|
var_name.as_ptr().cast(),
|
||||||
// If null, linkage_name field is omitted,
|
var_name.len(),
|
||||||
// which is what we want for no_mangle statics
|
linkage_name.as_ptr().cast(),
|
||||||
linkage_name.as_ref().map_or(ptr::null(), |name| name.as_ptr()),
|
linkage_name.len(),
|
||||||
file_metadata,
|
file_metadata,
|
||||||
line_number,
|
line_number,
|
||||||
type_metadata,
|
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
|
// pointer will lead to hard to trace and debug LLVM assertions
|
||||||
// later on in `llvm/lib/IR/Value.cpp`.
|
// later on in `llvm/lib/IR/Value.cpp`.
|
||||||
let empty_array = create_DIArray(DIB(cx), &[]);
|
let empty_array = create_DIArray(DIB(cx), &[]);
|
||||||
|
let name = "vtable";
|
||||||
let name = const_cstr!("vtable");
|
|
||||||
|
|
||||||
// Create a new one each time. We don't want metadata caching
|
// Create a new one each time. We don't want metadata caching
|
||||||
// here, because each vtable will refer to a unique containing
|
// 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(
|
let vtable_type = llvm::LLVMRustDIBuilderCreateStructType(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
NO_SCOPE_METADATA,
|
NO_SCOPE_METADATA,
|
||||||
name.as_ptr(),
|
name.as_ptr().cast(),
|
||||||
|
name.len(),
|
||||||
unknown_file_metadata(cx),
|
unknown_file_metadata(cx),
|
||||||
UNKNOWN_LINE_NUMBER,
|
UNKNOWN_LINE_NUMBER,
|
||||||
Size::ZERO.bits(),
|
Size::ZERO.bits(),
|
||||||
|
|
@ -2358,14 +2384,18 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: &
|
||||||
empty_array,
|
empty_array,
|
||||||
0,
|
0,
|
||||||
Some(type_metadata),
|
Some(type_metadata),
|
||||||
name.as_ptr(),
|
name.as_ptr().cast(),
|
||||||
|
name.len(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let linkage_name = "";
|
||||||
llvm::LLVMRustDIBuilderCreateStaticVariable(
|
llvm::LLVMRustDIBuilderCreateStaticVariable(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
NO_SCOPE_METADATA,
|
NO_SCOPE_METADATA,
|
||||||
name.as_ptr(),
|
name.as_ptr().cast(),
|
||||||
ptr::null(),
|
name.len(),
|
||||||
|
linkage_name.as_ptr().cast(),
|
||||||
|
linkage_name.len(),
|
||||||
unknown_file_metadata(cx),
|
unknown_file_metadata(cx),
|
||||||
UNKNOWN_LINE_NUMBER,
|
UNKNOWN_LINE_NUMBER,
|
||||||
vtable_type,
|
vtable_type,
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,11 @@ use rustc::ty::{self, Instance, ParamEnv, Ty};
|
||||||
use rustc_codegen_ssa::debuginfo::type_names;
|
use rustc_codegen_ssa::debuginfo::type_names;
|
||||||
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
|
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::small_c_str::SmallCStr;
|
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
|
|
||||||
use libc::c_uint;
|
use libc::c_uint;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::ffi::CString;
|
|
||||||
|
|
||||||
use rustc::ty::layout::{self, HasTyCtxt, LayoutOf, Size};
|
use rustc::ty::layout::{self, HasTyCtxt, LayoutOf, Size};
|
||||||
use rustc_ast::ast;
|
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
|
// Get the linkage_name, which is just the symbol name
|
||||||
let linkage_name = mangled_name_of_instance(self, instance);
|
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?
|
// FIXME(eddyb) does this need to be separate from `loc.line` for some reason?
|
||||||
let scope_line = loc.line;
|
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;
|
let mut flags = DIFlags::FlagPrototyped;
|
||||||
|
|
||||||
if fn_abi.ret.layout.abi.is_uninhabited() {
|
if fn_abi.ret.layout.abi.is_uninhabited() {
|
||||||
|
|
@ -303,8 +299,10 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||||
llvm::LLVMRustDIBuilderCreateFunction(
|
llvm::LLVMRustDIBuilderCreateFunction(
|
||||||
DIB(self),
|
DIB(self),
|
||||||
containing_scope,
|
containing_scope,
|
||||||
function_name.as_ptr(),
|
name.as_ptr().cast(),
|
||||||
linkage_name.as_ptr(),
|
name.len(),
|
||||||
|
linkage_name.as_ptr().cast(),
|
||||||
|
linkage_name.len(),
|
||||||
file_metadata,
|
file_metadata,
|
||||||
loc.line as c_uint,
|
loc.line as c_uint,
|
||||||
function_type_metadata,
|
function_type_metadata,
|
||||||
|
|
@ -424,12 +422,13 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||||
cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
|
cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
|
||||||
let actual_type_metadata =
|
let actual_type_metadata =
|
||||||
type_metadata(cx, actual_type, rustc_span::DUMMY_SP);
|
type_metadata(cx, actual_type, rustc_span::DUMMY_SP);
|
||||||
let name = SmallCStr::new(&name.as_str());
|
let name = name.as_str();
|
||||||
Some(unsafe {
|
Some(unsafe {
|
||||||
Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
|
Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
None,
|
None,
|
||||||
name.as_ptr(),
|
name.as_ptr().cast(),
|
||||||
|
name.len(),
|
||||||
actual_type_metadata,
|
actual_type_metadata,
|
||||||
file_metadata,
|
file_metadata,
|
||||||
0,
|
0,
|
||||||
|
|
@ -542,13 +541,14 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||||
};
|
};
|
||||||
let align = self.align_of(variable_type);
|
let align = self.align_of(variable_type);
|
||||||
|
|
||||||
let name = SmallCStr::new(&variable_name.as_str());
|
let name = variable_name.as_str();
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMRustDIBuilderCreateVariable(
|
llvm::LLVMRustDIBuilderCreateVariable(
|
||||||
DIB(self),
|
DIB(self),
|
||||||
dwarf_tag,
|
dwarf_tag,
|
||||||
scope_metadata,
|
scope_metadata,
|
||||||
name.as_ptr(),
|
name.as_ptr().cast(),
|
||||||
|
name.len(),
|
||||||
file_metadata,
|
file_metadata,
|
||||||
loc.line as c_uint,
|
loc.line as c_uint,
|
||||||
type_metadata,
|
type_metadata,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
// Namespace Handling.
|
// Namespace Handling.
|
||||||
|
|
||||||
use super::metadata::{unknown_file_metadata, UNKNOWN_LINE_NUMBER};
|
|
||||||
use super::utils::{debug_context, DIB};
|
use super::utils::{debug_context, DIB};
|
||||||
use rustc::ty::{self, Instance};
|
use rustc::ty::{self, Instance};
|
||||||
|
|
||||||
|
|
@ -10,8 +9,6 @@ use crate::llvm::debuginfo::DIScope;
|
||||||
use rustc::hir::map::DefPathData;
|
use rustc::hir::map::DefPathData;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
|
||||||
use rustc_data_structures::small_c_str::SmallCStr;
|
|
||||||
|
|
||||||
pub fn mangled_name_of_instance<'a, 'tcx>(
|
pub fn mangled_name_of_instance<'a, 'tcx>(
|
||||||
cx: &CodegenCx<'a, 'tcx>,
|
cx: &CodegenCx<'a, 'tcx>,
|
||||||
instance: Instance<'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),
|
DefPathData::CrateRoot => cx.tcx.crate_name(def_id.krate),
|
||||||
data => data.as_symbol(),
|
data => data.as_symbol(),
|
||||||
};
|
};
|
||||||
|
let namespace_name = namespace_name.as_str();
|
||||||
let namespace_name = SmallCStr::new(&namespace_name.as_str());
|
|
||||||
|
|
||||||
let scope = unsafe {
|
let scope = unsafe {
|
||||||
llvm::LLVMRustDIBuilderCreateNameSpace(
|
llvm::LLVMRustDIBuilderCreateNameSpace(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
parent_scope,
|
parent_scope,
|
||||||
namespace_name.as_ptr(),
|
namespace_name.as_ptr().cast(),
|
||||||
unknown_file_metadata(cx),
|
namespace_name.len(),
|
||||||
UNKNOWN_LINE_NUMBER,
|
false, // ExportSymbols (only relevant for C++ anonymous namespaces)
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1607,17 +1607,21 @@ extern "C" {
|
||||||
Lang: c_uint,
|
Lang: c_uint,
|
||||||
File: &'a DIFile,
|
File: &'a DIFile,
|
||||||
Producer: *const c_char,
|
Producer: *const c_char,
|
||||||
|
ProducerLen: size_t,
|
||||||
isOptimized: bool,
|
isOptimized: bool,
|
||||||
Flags: *const c_char,
|
Flags: *const c_char,
|
||||||
RuntimeVer: c_uint,
|
RuntimeVer: c_uint,
|
||||||
SplitName: *const c_char,
|
SplitName: *const c_char,
|
||||||
|
SplitNameLen: size_t,
|
||||||
kind: DebugEmissionKind,
|
kind: DebugEmissionKind,
|
||||||
) -> &'a DIDescriptor;
|
) -> &'a DIDescriptor;
|
||||||
|
|
||||||
pub fn LLVMRustDIBuilderCreateFile(
|
pub fn LLVMRustDIBuilderCreateFile(
|
||||||
Builder: &DIBuilder<'a>,
|
Builder: &DIBuilder<'a>,
|
||||||
Filename: *const c_char,
|
Filename: *const c_char,
|
||||||
|
FilenameLen: size_t,
|
||||||
Directory: *const c_char,
|
Directory: *const c_char,
|
||||||
|
DirectoryLen: size_t,
|
||||||
) -> &'a DIFile;
|
) -> &'a DIFile;
|
||||||
|
|
||||||
pub fn LLVMRustDIBuilderCreateSubroutineType(
|
pub fn LLVMRustDIBuilderCreateSubroutineType(
|
||||||
|
|
@ -1630,7 +1634,9 @@ extern "C" {
|
||||||
Builder: &DIBuilder<'a>,
|
Builder: &DIBuilder<'a>,
|
||||||
Scope: &'a DIDescriptor,
|
Scope: &'a DIDescriptor,
|
||||||
Name: *const c_char,
|
Name: *const c_char,
|
||||||
|
NameLen: size_t,
|
||||||
LinkageName: *const c_char,
|
LinkageName: *const c_char,
|
||||||
|
LinkageNameLen: size_t,
|
||||||
File: &'a DIFile,
|
File: &'a DIFile,
|
||||||
LineNo: c_uint,
|
LineNo: c_uint,
|
||||||
Ty: &'a DIType,
|
Ty: &'a DIType,
|
||||||
|
|
@ -1645,6 +1651,7 @@ extern "C" {
|
||||||
pub fn LLVMRustDIBuilderCreateBasicType(
|
pub fn LLVMRustDIBuilderCreateBasicType(
|
||||||
Builder: &DIBuilder<'a>,
|
Builder: &DIBuilder<'a>,
|
||||||
Name: *const c_char,
|
Name: *const c_char,
|
||||||
|
NameLen: size_t,
|
||||||
SizeInBits: u64,
|
SizeInBits: u64,
|
||||||
AlignInBits: u32,
|
AlignInBits: u32,
|
||||||
Encoding: c_uint,
|
Encoding: c_uint,
|
||||||
|
|
@ -1655,13 +1662,16 @@ extern "C" {
|
||||||
PointeeTy: &'a DIType,
|
PointeeTy: &'a DIType,
|
||||||
SizeInBits: u64,
|
SizeInBits: u64,
|
||||||
AlignInBits: u32,
|
AlignInBits: u32,
|
||||||
|
AddressSpace: c_uint,
|
||||||
Name: *const c_char,
|
Name: *const c_char,
|
||||||
|
NameLen: size_t,
|
||||||
) -> &'a DIDerivedType;
|
) -> &'a DIDerivedType;
|
||||||
|
|
||||||
pub fn LLVMRustDIBuilderCreateStructType(
|
pub fn LLVMRustDIBuilderCreateStructType(
|
||||||
Builder: &DIBuilder<'a>,
|
Builder: &DIBuilder<'a>,
|
||||||
Scope: Option<&'a DIDescriptor>,
|
Scope: Option<&'a DIDescriptor>,
|
||||||
Name: *const c_char,
|
Name: *const c_char,
|
||||||
|
NameLen: size_t,
|
||||||
File: &'a DIFile,
|
File: &'a DIFile,
|
||||||
LineNumber: c_uint,
|
LineNumber: c_uint,
|
||||||
SizeInBits: u64,
|
SizeInBits: u64,
|
||||||
|
|
@ -1672,12 +1682,14 @@ extern "C" {
|
||||||
RunTimeLang: c_uint,
|
RunTimeLang: c_uint,
|
||||||
VTableHolder: Option<&'a DIType>,
|
VTableHolder: Option<&'a DIType>,
|
||||||
UniqueId: *const c_char,
|
UniqueId: *const c_char,
|
||||||
|
UniqueIdLen: size_t,
|
||||||
) -> &'a DICompositeType;
|
) -> &'a DICompositeType;
|
||||||
|
|
||||||
pub fn LLVMRustDIBuilderCreateMemberType(
|
pub fn LLVMRustDIBuilderCreateMemberType(
|
||||||
Builder: &DIBuilder<'a>,
|
Builder: &DIBuilder<'a>,
|
||||||
Scope: &'a DIDescriptor,
|
Scope: &'a DIDescriptor,
|
||||||
Name: *const c_char,
|
Name: *const c_char,
|
||||||
|
NameLen: size_t,
|
||||||
File: &'a DIFile,
|
File: &'a DIFile,
|
||||||
LineNo: c_uint,
|
LineNo: c_uint,
|
||||||
SizeInBits: u64,
|
SizeInBits: u64,
|
||||||
|
|
@ -1691,6 +1703,7 @@ extern "C" {
|
||||||
Builder: &DIBuilder<'a>,
|
Builder: &DIBuilder<'a>,
|
||||||
Scope: &'a DIScope,
|
Scope: &'a DIScope,
|
||||||
Name: *const c_char,
|
Name: *const c_char,
|
||||||
|
NameLen: size_t,
|
||||||
File: &'a DIFile,
|
File: &'a DIFile,
|
||||||
LineNumber: c_uint,
|
LineNumber: c_uint,
|
||||||
SizeInBits: u64,
|
SizeInBits: u64,
|
||||||
|
|
@ -1719,7 +1732,9 @@ extern "C" {
|
||||||
Builder: &DIBuilder<'a>,
|
Builder: &DIBuilder<'a>,
|
||||||
Context: Option<&'a DIScope>,
|
Context: Option<&'a DIScope>,
|
||||||
Name: *const c_char,
|
Name: *const c_char,
|
||||||
|
NameLen: size_t,
|
||||||
LinkageName: *const c_char,
|
LinkageName: *const c_char,
|
||||||
|
LinkageNameLen: size_t,
|
||||||
File: &'a DIFile,
|
File: &'a DIFile,
|
||||||
LineNo: c_uint,
|
LineNo: c_uint,
|
||||||
Ty: &'a DIType,
|
Ty: &'a DIType,
|
||||||
|
|
@ -1734,6 +1749,7 @@ extern "C" {
|
||||||
Tag: c_uint,
|
Tag: c_uint,
|
||||||
Scope: &'a DIDescriptor,
|
Scope: &'a DIDescriptor,
|
||||||
Name: *const c_char,
|
Name: *const c_char,
|
||||||
|
NameLen: size_t,
|
||||||
File: &'a DIFile,
|
File: &'a DIFile,
|
||||||
LineNo: c_uint,
|
LineNo: c_uint,
|
||||||
Ty: &'a DIType,
|
Ty: &'a DIType,
|
||||||
|
|
@ -1785,6 +1801,7 @@ extern "C" {
|
||||||
Builder: &DIBuilder<'a>,
|
Builder: &DIBuilder<'a>,
|
||||||
Scope: &'a DIScope,
|
Scope: &'a DIScope,
|
||||||
Name: *const c_char,
|
Name: *const c_char,
|
||||||
|
NameLen: size_t,
|
||||||
File: &'a DIFile,
|
File: &'a DIFile,
|
||||||
LineNumber: c_uint,
|
LineNumber: c_uint,
|
||||||
SizeInBits: u64,
|
SizeInBits: u64,
|
||||||
|
|
@ -1798,6 +1815,7 @@ extern "C" {
|
||||||
Builder: &DIBuilder<'a>,
|
Builder: &DIBuilder<'a>,
|
||||||
Scope: &'a DIScope,
|
Scope: &'a DIScope,
|
||||||
Name: *const c_char,
|
Name: *const c_char,
|
||||||
|
NameLen: size_t,
|
||||||
File: &'a DIFile,
|
File: &'a DIFile,
|
||||||
LineNumber: c_uint,
|
LineNumber: c_uint,
|
||||||
SizeInBits: u64,
|
SizeInBits: u64,
|
||||||
|
|
@ -1806,12 +1824,14 @@ extern "C" {
|
||||||
Elements: Option<&'a DIArray>,
|
Elements: Option<&'a DIArray>,
|
||||||
RunTimeLang: c_uint,
|
RunTimeLang: c_uint,
|
||||||
UniqueId: *const c_char,
|
UniqueId: *const c_char,
|
||||||
|
UniqueIdLen: size_t,
|
||||||
) -> &'a DIType;
|
) -> &'a DIType;
|
||||||
|
|
||||||
pub fn LLVMRustDIBuilderCreateVariantPart(
|
pub fn LLVMRustDIBuilderCreateVariantPart(
|
||||||
Builder: &DIBuilder<'a>,
|
Builder: &DIBuilder<'a>,
|
||||||
Scope: &'a DIScope,
|
Scope: &'a DIScope,
|
||||||
Name: *const c_char,
|
Name: *const c_char,
|
||||||
|
NameLen: size_t,
|
||||||
File: &'a DIFile,
|
File: &'a DIFile,
|
||||||
LineNo: c_uint,
|
LineNo: c_uint,
|
||||||
SizeInBits: u64,
|
SizeInBits: u64,
|
||||||
|
|
@ -1820,6 +1840,7 @@ extern "C" {
|
||||||
Discriminator: Option<&'a DIDerivedType>,
|
Discriminator: Option<&'a DIDerivedType>,
|
||||||
Elements: &'a DIArray,
|
Elements: &'a DIArray,
|
||||||
UniqueId: *const c_char,
|
UniqueId: *const c_char,
|
||||||
|
UniqueIdLen: size_t,
|
||||||
) -> &'a DIDerivedType;
|
) -> &'a DIDerivedType;
|
||||||
|
|
||||||
pub fn LLVMSetUnnamedAddr(GlobalVar: &Value, UnnamedAddr: Bool);
|
pub fn LLVMSetUnnamedAddr(GlobalVar: &Value, UnnamedAddr: Bool);
|
||||||
|
|
@ -1828,6 +1849,7 @@ extern "C" {
|
||||||
Builder: &DIBuilder<'a>,
|
Builder: &DIBuilder<'a>,
|
||||||
Scope: Option<&'a DIScope>,
|
Scope: Option<&'a DIScope>,
|
||||||
Name: *const c_char,
|
Name: *const c_char,
|
||||||
|
NameLen: size_t,
|
||||||
Ty: &'a DIType,
|
Ty: &'a DIType,
|
||||||
File: &'a DIFile,
|
File: &'a DIFile,
|
||||||
LineNo: c_uint,
|
LineNo: c_uint,
|
||||||
|
|
@ -1838,8 +1860,8 @@ extern "C" {
|
||||||
Builder: &DIBuilder<'a>,
|
Builder: &DIBuilder<'a>,
|
||||||
Scope: Option<&'a DIScope>,
|
Scope: Option<&'a DIScope>,
|
||||||
Name: *const c_char,
|
Name: *const c_char,
|
||||||
File: &'a DIFile,
|
NameLen: size_t,
|
||||||
LineNo: c_uint,
|
ExportSymbols: bool,
|
||||||
) -> &'a DINameSpace;
|
) -> &'a DINameSpace;
|
||||||
|
|
||||||
pub fn LLVMRustDICompositeTypeReplaceArrays(
|
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 `_`.
|
/// The token is an identifier, but not `_`.
|
||||||
/// We prohibit passing `_` to macros expecting `ident` for now.
|
/// We prohibit passing `_` to macros expecting `ident` for now.
|
||||||
fn get_macro_name(token: &Token) -> Option<(Name, bool)> {
|
fn get_macro_ident(token: &Token) -> Option<(Ident, bool)> {
|
||||||
match token.kind {
|
token.ident().filter(|(ident, _)| ident.name != kw::Underscore)
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks whether a non-terminal may begin with a particular token.
|
/// 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)
|
&& !token.is_keyword(kw::Let)
|
||||||
}
|
}
|
||||||
sym::ty => token.can_begin_type(),
|
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::literal => token.can_begin_literal_or_bool(),
|
||||||
sym::vis => match token.kind {
|
sym::vis => match token.kind {
|
||||||
// The follow-set of :vis + "priv" keyword + interpolated
|
// 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()?),
|
sym::ty => token::NtTy(p.parse_ty()?),
|
||||||
// this could be handled like a token, since it is one
|
// this could be handled like a token, since it is one
|
||||||
sym::ident => {
|
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();
|
p.bump();
|
||||||
token::NtIdent(Ident::new(name, p.normalized_prev_token.span), is_raw)
|
token::NtIdent(ident, is_raw)
|
||||||
} else {
|
} else {
|
||||||
let token_str = pprust::token_to_string(&p.token);
|
let token_str = pprust::token_to_string(&p.token);
|
||||||
let msg = &format!("expected ident, found {}", &token_str);
|
let msg = &format!("expected ident, found {}", &token_str);
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,12 @@ fn validate_and_turn_into_const<'tcx>(
|
||||||
if cid.promoted.is_none() {
|
if cid.promoted.is_none() {
|
||||||
let mut ref_tracking = RefTracking::new(mplace);
|
let mut ref_tracking = RefTracking::new(mplace);
|
||||||
while let Some((mplace, path)) = ref_tracking.todo.pop() {
|
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.
|
// 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.
|
// Check if this brought us over the size limit.
|
||||||
if size.bytes() >= self.tcx.data_layout().obj_size_bound() {
|
if size.bytes() >= self.tcx.data_layout().obj_size_bound() {
|
||||||
throw_ub_format!(
|
throw_ub!(InvalidMeta("total size is bigger than largest supported object"));
|
||||||
"wide pointer metadata contains invalid information: \
|
|
||||||
total size is bigger than largest supported object"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Ok(Some((size, align)))
|
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.
|
// Make sure the slice is not too big.
|
||||||
let size = elem.size.checked_mul(len, &*self.tcx).ok_or_else(|| {
|
let size = elem.size.checked_mul(len, &*self.tcx).ok_or_else(|| {
|
||||||
err_ub_format!(
|
err_ub!(InvalidMeta("slice is bigger than largest supported object"))
|
||||||
"invalid slice: \
|
|
||||||
total size is bigger than largest supported object"
|
|
||||||
)
|
|
||||||
})?;
|
})?;
|
||||||
Ok(Some((size, elem.align.abi)))
|
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
|
// invariant -- that is, unless a function somehow has a ptr to
|
||||||
// its return place... but the way MIR is currently generated, the
|
// its return place... but the way MIR is currently generated, the
|
||||||
// return place is always a local and then this cannot happen.
|
// 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 {
|
} else {
|
||||||
// Uh, that shouldn't happen... the function did not intend to return
|
// Uh, that shouldn't happen... the function did not intend to return
|
||||||
|
|
|
||||||
|
|
@ -689,7 +689,7 @@ where
|
||||||
|
|
||||||
if M::enforce_validity(self) {
|
if M::enforce_validity(self) {
|
||||||
// Data got changed, better make sure it matches the type!
|
// 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(())
|
Ok(())
|
||||||
|
|
@ -706,7 +706,7 @@ where
|
||||||
|
|
||||||
if M::enforce_validity(self) {
|
if M::enforce_validity(self) {
|
||||||
// Data got changed, better make sure it matches the type!
|
// Data got changed, better make sure it matches the type!
|
||||||
self.validate_operand(dest.into(), vec![], None)?;
|
self.validate_operand(dest.into())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -843,7 +843,7 @@ where
|
||||||
|
|
||||||
if M::enforce_validity(self) {
|
if M::enforce_validity(self) {
|
||||||
// Data got changed, better make sure it matches the type!
|
// 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(())
|
Ok(())
|
||||||
|
|
@ -951,7 +951,7 @@ where
|
||||||
|
|
||||||
if M::enforce_validity(self) {
|
if M::enforce_validity(self) {
|
||||||
// Data got changed, better make sure it matches the type!
|
// Data got changed, better make sure it matches the type!
|
||||||
self.validate_operand(dest.into(), vec![], None)?;
|
self.validate_operand(dest.into())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,8 @@ macro_rules! try_validation {
|
||||||
($e:expr, $what:expr, $where:expr, $details:expr) => {{
|
($e:expr, $what:expr, $where:expr, $details:expr) => {{
|
||||||
match $e {
|
match $e {
|
||||||
Ok(x) => x,
|
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),
|
Err(_) => throw_validation_failure!($what, $where, $details),
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
|
@ -53,6 +55,8 @@ macro_rules! try_validation {
|
||||||
($e:expr, $what:expr, $where:expr) => {{
|
($e:expr, $what:expr, $where:expr) => {{
|
||||||
match $e {
|
match $e {
|
||||||
Ok(x) => x,
|
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),
|
Err(_) => throw_validation_failure!($what, $where),
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
|
@ -167,6 +171,7 @@ struct ValidityVisitor<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
|
||||||
path: Vec<PathElem>,
|
path: Vec<PathElem>,
|
||||||
ref_tracking_for_consts:
|
ref_tracking_for_consts:
|
||||||
Option<&'rt mut RefTracking<MPlaceTy<'tcx, M::PointerTag>, Vec<PathElem>>>,
|
Option<&'rt mut RefTracking<MPlaceTy<'tcx, M::PointerTag>, Vec<PathElem>>>,
|
||||||
|
may_ref_to_static: bool,
|
||||||
ecx: &'rt InterpCx<'mir, 'tcx, M>,
|
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)?;
|
self.check_wide_ptr_meta(place.meta, place.layout)?;
|
||||||
}
|
}
|
||||||
// Make sure this is dereferenceable and all.
|
// Make sure this is dereferenceable and all.
|
||||||
let (size, align) = self
|
let size_and_align = match self.ecx.size_and_align_of(place.meta, place.layout) {
|
||||||
.ecx
|
Ok(res) => res,
|
||||||
.size_and_align_of(place.meta, place.layout)?
|
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
|
// for the purpose of validity, consider foreign types to have
|
||||||
// alignment and size determined by the layout (size will be 0,
|
// alignment and size determined by the layout (size will be 0,
|
||||||
// alignment should take attributes into account).
|
// 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),
|
format_args!("a dangling {} (created from integer)", kind),
|
||||||
self.path
|
self.path
|
||||||
),
|
),
|
||||||
_ => throw_validation_failure!(
|
err_unsup!(PointerOutOfBounds { .. }) | err_unsup!(DanglingPointerDeref) => {
|
||||||
format_args!("a dangling {} (not entirely in bounds)", kind),
|
throw_validation_failure!(
|
||||||
self.path
|
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) {
|
if !did.is_local() || self.ecx.tcx.is_foreign_item(did) {
|
||||||
return Ok(());
|
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!
|
// 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) => {
|
err_unsup!(ReadPointerAsBytes) => {
|
||||||
throw_validation_failure!("a pointer", self.path, "plain (non-pointer) bytes")
|
throw_validation_failure!("a pointer", self.path, "plain (non-pointer) bytes")
|
||||||
}
|
}
|
||||||
|
// Propagate upwards (that will also check for unexpected errors).
|
||||||
_ => return Err(err),
|
_ => 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> {
|
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
|
fn validate_operand_internal(
|
||||||
/// 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(
|
|
||||||
&self,
|
&self,
|
||||||
op: OpTy<'tcx, M::PointerTag>,
|
op: OpTy<'tcx, M::PointerTag>,
|
||||||
path: Vec<PathElem>,
|
path: Vec<PathElem>,
|
||||||
ref_tracking_for_consts: Option<
|
ref_tracking_for_consts: Option<
|
||||||
&mut RefTracking<MPlaceTy<'tcx, M::PointerTag>, Vec<PathElem>>,
|
&mut RefTracking<MPlaceTy<'tcx, M::PointerTag>, Vec<PathElem>>,
|
||||||
>,
|
>,
|
||||||
|
may_ref_to_static: bool,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
trace!("validate_operand: {:?}, {:?}", *op, op.layout.ty);
|
trace!("validate_operand_internal: {:?}, {:?}", *op, op.layout.ty);
|
||||||
|
|
||||||
// Construct a visitor
|
// 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.
|
// Try to cast to ptr *once* instead of all the time.
|
||||||
let op = self.force_op_ptr(op).unwrap_or(op);
|
let op = self.force_op_ptr(op).unwrap_or(op);
|
||||||
|
|
||||||
// Run it
|
// Run it.
|
||||||
visitor.visit_value(op)
|
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) {
|
let r = match f(self) {
|
||||||
Ok(val) => Some(val),
|
Ok(val) => Some(val),
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
use rustc::mir::interpret::{
|
// Some errors shouldn't come up because creating them causes
|
||||||
InterpError::*, UndefinedBehaviorInfo, UnsupportedOpInfo,
|
// an allocation, which we should avoid. When that happens,
|
||||||
};
|
// dedicated error variants should be introduced instead.
|
||||||
match error.kind {
|
// Only test this in debug builds though to avoid disruptions.
|
||||||
MachineStop(_) => bug!("ConstProp does not stop"),
|
debug_assert!(
|
||||||
|
!error.kind.allocates(),
|
||||||
// Some error shouldn't come up because creating them causes
|
"const-prop encountered allocating error: {}",
|
||||||
// an allocation, which we should avoid. When that happens,
|
error
|
||||||
// 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.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -654,11 +637,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
source_info: SourceInfo,
|
source_info: SourceInfo,
|
||||||
) {
|
) {
|
||||||
trace!("attepting to replace {:?} with {:?}", rval, value);
|
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,
|
value,
|
||||||
vec![],
|
vec![],
|
||||||
// FIXME: is ref tracking too expensive?
|
// 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);
|
trace!("validation error, attempt failed: {:?}", e);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
|
|
||||||
use rustc_ast::ast;
|
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::tokenstream::{self, TokenStream, TokenTree};
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_data_structures::sync::Lrc;
|
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);
|
let mut parser = stream_to_parser(sess, stream, None);
|
||||||
parser.unclosed_delims = unclosed_delims;
|
parser.unclosed_delims = unclosed_delims;
|
||||||
if parser.token == token::Eof {
|
if parser.token == token::Eof {
|
||||||
let span = Span::new(end_pos, end_pos, parser.token.span.ctxt());
|
parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt());
|
||||||
parser.set_token(Token::new(token::Eof, span));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(parser)
|
Ok(parser)
|
||||||
|
|
|
||||||
|
|
@ -192,17 +192,19 @@ impl<'a> Parser<'a> {
|
||||||
TokenKind::CloseDelim(token::DelimToken::Brace),
|
TokenKind::CloseDelim(token::DelimToken::Brace),
|
||||||
TokenKind::CloseDelim(token::DelimToken::Paren),
|
TokenKind::CloseDelim(token::DelimToken::Paren),
|
||||||
];
|
];
|
||||||
if let token::Ident(name, false) = self.normalized_token.kind {
|
match self.token.ident() {
|
||||||
if Ident::new(name, self.normalized_token.span).is_raw_guess()
|
Some((ident, false))
|
||||||
&& self.look_ahead(1, |t| valid_follow.contains(&t.kind))
|
if ident.is_raw_guess()
|
||||||
|
&& self.look_ahead(1, |t| valid_follow.contains(&t.kind)) =>
|
||||||
{
|
{
|
||||||
err.span_suggestion(
|
err.span_suggestion(
|
||||||
self.normalized_token.span,
|
ident.span,
|
||||||
"you can escape reserved keywords to use them as identifiers",
|
"you can escape reserved keywords to use them as identifiers",
|
||||||
format!("r#{}", name),
|
format!("r#{}", ident.name),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
if let Some(token_descr) = super::token_descr_opt(&self.token) {
|
if let Some(token_descr) = super::token_descr_opt(&self.token) {
|
||||||
err.span_label(self.token.span, format!("expected identifier, found {}", token_descr));
|
err.span_label(self.token.span, format!("expected identifier, found {}", token_descr));
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,6 @@ macro_rules! maybe_whole_expr {
|
||||||
AttrVec::new(),
|
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>> {
|
fn parse_expr_catch_underscore(&mut self) -> PResult<'a, P<Expr>> {
|
||||||
match self.parse_expr() {
|
match self.parse_expr() {
|
||||||
Ok(expr) => Ok(expr),
|
Ok(expr) => Ok(expr),
|
||||||
Err(mut err) => match self.normalized_token.kind {
|
Err(mut err) => match self.token.ident() {
|
||||||
token::Ident(name, false)
|
Some((Ident { name: kw::Underscore, .. }, false))
|
||||||
if name == kw::Underscore && self.look_ahead(1, |t| t == &token::Comma) =>
|
if self.look_ahead(1, |t| t == &token::Comma) =>
|
||||||
{
|
{
|
||||||
// Special-case handling of `foo(_, _, _)`
|
// Special-case handling of `foo(_, _, _)`
|
||||||
err.emit();
|
err.emit();
|
||||||
|
|
@ -331,21 +330,19 @@ impl<'a> Parser<'a> {
|
||||||
///
|
///
|
||||||
/// Also performs recovery for `and` / `or` which are mistaken for `&&` and `||` respectively.
|
/// Also performs recovery for `and` / `or` which are mistaken for `&&` and `||` respectively.
|
||||||
fn check_assoc_op(&self) -> Option<Spanned<AssocOp>> {
|
fn check_assoc_op(&self) -> Option<Spanned<AssocOp>> {
|
||||||
Some(Spanned {
|
let (op, span) = match (AssocOp::from_token(&self.token), self.token.ident()) {
|
||||||
node: match (AssocOp::from_token(&self.token), &self.normalized_token.kind) {
|
(Some(op), _) => (op, self.token.span),
|
||||||
(Some(op), _) => op,
|
(None, Some((Ident { name: sym::and, span }, false))) => {
|
||||||
(None, token::Ident(sym::and, false)) => {
|
self.error_bad_logical_op("and", "&&", "conjunction");
|
||||||
self.error_bad_logical_op("and", "&&", "conjunction");
|
(AssocOp::LAnd, span)
|
||||||
AssocOp::LAnd
|
}
|
||||||
}
|
(None, Some((Ident { name: sym::or, span }, false))) => {
|
||||||
(None, token::Ident(sym::or, false)) => {
|
self.error_bad_logical_op("or", "||", "disjunction");
|
||||||
self.error_bad_logical_op("or", "||", "disjunction");
|
(AssocOp::LOr, span)
|
||||||
AssocOp::LOr
|
}
|
||||||
}
|
_ => return None,
|
||||||
_ => return None,
|
};
|
||||||
},
|
Some(source_map::respan(span, op))
|
||||||
span: self.normalized_token.span,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Error on `and` and `or` suggesting `&&` and `||` respectively.
|
/// 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 attrs = self.parse_or_use_outer_attributes(attrs)?;
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
// Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr()
|
// 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::Not => self.parse_unary_expr(lo, UnOp::Not), // `!expr`
|
||||||
token::Tilde => self.recover_tilde_expr(lo), // `~expr`
|
token::Tilde => self.recover_tilde_expr(lo), // `~expr`
|
||||||
token::BinOp(token::Minus) => self.parse_unary_expr(lo, UnOp::Neg), // `-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 {
|
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
|
// These tokens can start an expression after `!`, but
|
||||||
// can't continue an expression after an ident
|
// can't continue an expression after an ident
|
||||||
token::Ident(name, is_raw) => token::ident_can_begin_expr(name, t.span, is_raw),
|
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| {
|
expr.map(|mut expr| {
|
||||||
attrs.extend::<Vec<_>>(expr.attrs.into());
|
attrs.extend::<Vec<_>>(expr.attrs.into());
|
||||||
expr.attrs = attrs;
|
expr.attrs = attrs;
|
||||||
self.error_attr_on_if_expr(&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>> {
|
fn parse_dot_or_call_expr_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
|
||||||
loop {
|
loop {
|
||||||
if self.eat(&token::Question) {
|
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>> {
|
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::Ident(..) => self.parse_dot_suffix(base, lo),
|
||||||
token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => {
|
token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => {
|
||||||
Ok(self.parse_tuple_field_access_expr(lo, base, 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.
|
/// 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>> {
|
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);
|
return self.mk_await_expr(self_arg, lo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -964,7 +952,7 @@ impl<'a> Parser<'a> {
|
||||||
// | ^ expected expression
|
// | ^ expected expression
|
||||||
self.bump();
|
self.bump();
|
||||||
Ok(self.mk_expr_err(self.token.span))
|
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.
|
// `Span::rust_2018()` is somewhat expensive; don't get it repeatedly.
|
||||||
if self.check_keyword(kw::Async) {
|
if self.check_keyword(kw::Async) {
|
||||||
if self.is_async_block() {
|
if self.is_async_block() {
|
||||||
|
|
@ -1397,11 +1385,14 @@ impl<'a> Parser<'a> {
|
||||||
let movability =
|
let movability =
|
||||||
if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable };
|
if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable };
|
||||||
|
|
||||||
let asyncness =
|
let asyncness = if self.token.uninterpolated_span().rust_2018() {
|
||||||
if self.normalized_token.span.rust_2018() { self.parse_asyncness() } else { Async::No };
|
self.parse_asyncness()
|
||||||
if asyncness.is_async() {
|
} else {
|
||||||
|
Async::No
|
||||||
|
};
|
||||||
|
if let Async::Yes { span, .. } = asyncness {
|
||||||
// Feature-gate `async ||` closures.
|
// 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();
|
let capture_clause = self.parse_capture_clause();
|
||||||
|
|
@ -1757,7 +1748,7 @@ impl<'a> Parser<'a> {
|
||||||
fn is_try_block(&self) -> bool {
|
fn is_try_block(&self) -> bool {
|
||||||
self.token.is_keyword(kw::Try) &&
|
self.token.is_keyword(kw::Try) &&
|
||||||
self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) &&
|
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.
|
// Prevent `while try {} {}`, `if try {} {} else {}`, etc.
|
||||||
!self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
|
!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 }`.
|
/// Use in case of error after field-looking code: `S { foo: () with a }`.
|
||||||
fn find_struct_error_after_field_looking_code(&self) -> Option<Field> {
|
fn find_struct_error_after_field_looking_code(&self) -> Option<Field> {
|
||||||
if let token::Ident(name, _) = self.normalized_token.kind {
|
match self.token.ident() {
|
||||||
if !self.token.is_reserved_ident() && self.look_ahead(1, |t| *t == token::Colon) {
|
Some((ident, is_raw))
|
||||||
return Some(ast::Field {
|
if (is_raw || !ident.is_reserved())
|
||||||
ident: Ident::new(name, self.normalized_token.span),
|
&& self.look_ahead(1, |t| *t == token::Colon) =>
|
||||||
|
{
|
||||||
|
Some(ast::Field {
|
||||||
|
ident,
|
||||||
span: self.token.span,
|
span: self.token.span,
|
||||||
expr: self.mk_expr_err(self.token.span),
|
expr: self.mk_expr_err(self.token.span),
|
||||||
is_shorthand: false,
|
is_shorthand: false,
|
||||||
attrs: AttrVec::new(),
|
attrs: AttrVec::new(),
|
||||||
id: DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
is_placeholder: false,
|
is_placeholder: false,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
_ => None,
|
||||||
}
|
}
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recover_struct_comma_after_dotdot(&mut self, span: Span) {
|
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.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As))
|
||||||
{
|
{
|
||||||
self.bump(); // `default`
|
self.bump(); // `default`
|
||||||
Defaultness::Default(self.normalized_prev_token.span)
|
Defaultness::Default(self.prev_token.uninterpolated_span())
|
||||||
} else {
|
} else {
|
||||||
Defaultness::Final
|
Defaultness::Final
|
||||||
}
|
}
|
||||||
|
|
@ -750,10 +750,10 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> {
|
fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> {
|
||||||
match self.normalized_token.kind {
|
match self.token.ident() {
|
||||||
token::Ident(name @ kw::Underscore, false) => {
|
Some((ident @ Ident { name: kw::Underscore, .. }, false)) => {
|
||||||
self.bump();
|
self.bump();
|
||||||
Ok(Ident::new(name, self.normalized_prev_token.span))
|
Ok(ident)
|
||||||
}
|
}
|
||||||
_ => self.parse_ident(),
|
_ => self.parse_ident(),
|
||||||
}
|
}
|
||||||
|
|
@ -1544,7 +1544,9 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let is_name_required = match self.token.kind {
|
let is_name_required = match self.token.kind {
|
||||||
token::DotDotDot => false,
|
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() {
|
let (pat, ty) = if is_name_required || self.is_named_param() {
|
||||||
debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
|
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.
|
/// Returns the parsed optional self parameter and whether a self shortcut was used.
|
||||||
fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
|
fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
|
||||||
// Extract an identifier *after* having confirmed that the token is one.
|
// Extract an identifier *after* having confirmed that the token is one.
|
||||||
let expect_self_ident = |this: &mut Self| {
|
let expect_self_ident = |this: &mut Self| match this.token.ident() {
|
||||||
match this.normalized_token.kind {
|
Some((ident, false)) => {
|
||||||
// Preserve hygienic context.
|
this.bump();
|
||||||
token::Ident(name, _) => {
|
ident
|
||||||
this.bump();
|
|
||||||
Ident::new(name, this.normalized_prev_token.span)
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
// Is `self` `n` tokens ahead?
|
// Is `self` `n` tokens ahead?
|
||||||
let is_isolated_self = |this: &Self, n| {
|
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
|
// 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.
|
// else is parsed as a normal function parameter list, so some lookahead is required.
|
||||||
let eself_lo = self.token.span;
|
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) => {
|
token::BinOp(token::And) => {
|
||||||
let eself = if is_isolated_self(self, 1) {
|
let eself = if is_isolated_self(self, 1) {
|
||||||
// `&self`
|
// `&self`
|
||||||
|
|
|
||||||
|
|
@ -88,21 +88,10 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Parser<'a> {
|
pub struct Parser<'a> {
|
||||||
pub sess: &'a ParseSess,
|
pub sess: &'a ParseSess,
|
||||||
/// The current non-normalized token.
|
/// The current token.
|
||||||
pub token: Token,
|
pub token: Token,
|
||||||
/// The current normalized token.
|
/// The previous 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.
|
|
||||||
pub prev_token: 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,
|
restrictions: Restrictions,
|
||||||
/// Used to determine the path to externally loaded source files.
|
/// Used to determine the path to externally loaded source files.
|
||||||
pub(super) directory: Directory,
|
pub(super) directory: Directory,
|
||||||
|
|
@ -374,9 +363,7 @@ impl<'a> Parser<'a> {
|
||||||
let mut parser = Parser {
|
let mut parser = Parser {
|
||||||
sess,
|
sess,
|
||||||
token: Token::dummy(),
|
token: Token::dummy(),
|
||||||
normalized_token: Token::dummy(),
|
|
||||||
prev_token: Token::dummy(),
|
prev_token: Token::dummy(),
|
||||||
normalized_prev_token: Token::dummy(),
|
|
||||||
restrictions: Restrictions::empty(),
|
restrictions: Restrictions::empty(),
|
||||||
recurse_into_file_modules,
|
recurse_into_file_modules,
|
||||||
directory: Directory {
|
directory: Directory {
|
||||||
|
|
@ -480,9 +467,9 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> {
|
fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> {
|
||||||
match self.normalized_token.kind {
|
match self.token.ident() {
|
||||||
token::Ident(name, _) => {
|
Some((ident, is_raw)) => {
|
||||||
if self.token.is_reserved_ident() {
|
if !is_raw && ident.is_reserved() {
|
||||||
let mut err = self.expected_ident_found();
|
let mut err = self.expected_ident_found();
|
||||||
if recover {
|
if recover {
|
||||||
err.emit();
|
err.emit();
|
||||||
|
|
@ -491,7 +478,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.bump();
|
self.bump();
|
||||||
Ok(Ident::new(name, self.normalized_prev_token.span))
|
Ok(ident)
|
||||||
}
|
}
|
||||||
_ => Err(match self.prev_token.kind {
|
_ => Err(match self.prev_token.kind {
|
||||||
TokenKind::DocComment(..) => {
|
TokenKind::DocComment(..) => {
|
||||||
|
|
@ -609,7 +596,7 @@ impl<'a> Parser<'a> {
|
||||||
Some((first, second)) if first == expected => {
|
Some((first, second)) if first == expected => {
|
||||||
let first_span = self.sess.source_map().start_point(self.token.span);
|
let first_span = self.sess.source_map().start_point(self.token.span);
|
||||||
let second_span = self.token.span.with_lo(first_span.hi());
|
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));
|
self.bump_with(Token::new(second, second_span));
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
@ -817,23 +804,6 @@ impl<'a> Parser<'a> {
|
||||||
self.parse_delim_comma_seq(token::Paren, f)
|
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.
|
/// Advance the parser by one token using provided token as the next one.
|
||||||
fn bump_with(&mut self, next_token: Token) {
|
fn bump_with(&mut self, next_token: Token) {
|
||||||
// Bumping after EOF is a bad sign, usually an infinite loop.
|
// 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.
|
// Update the current and previous tokens.
|
||||||
self.prev_token = self.token.take();
|
self.prev_token = mem::replace(&mut self.token, next_token);
|
||||||
self.normalized_prev_token = self.normalized_token.take();
|
|
||||||
self.set_token(next_token);
|
|
||||||
|
|
||||||
// Diagnostics.
|
// Diagnostics.
|
||||||
self.expected_tokens.clear();
|
self.expected_tokens.clear();
|
||||||
|
|
@ -884,7 +852,7 @@ impl<'a> Parser<'a> {
|
||||||
/// Parses asyncness: `async` or nothing.
|
/// Parses asyncness: `async` or nothing.
|
||||||
fn parse_asyncness(&mut self) -> Async {
|
fn parse_asyncness(&mut self) -> Async {
|
||||||
if self.eat_keyword(kw::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 }
|
Async::Yes { span, closure_id: DUMMY_NODE_ID, return_impl_trait_id: DUMMY_NODE_ID }
|
||||||
} else {
|
} else {
|
||||||
Async::No
|
Async::No
|
||||||
|
|
@ -894,7 +862,7 @@ impl<'a> Parser<'a> {
|
||||||
/// Parses unsafety: `unsafe` or nothing.
|
/// Parses unsafety: `unsafe` or nothing.
|
||||||
fn parse_unsafety(&mut self) -> Unsafe {
|
fn parse_unsafety(&mut self) -> Unsafe {
|
||||||
if self.eat_keyword(kw::Unsafe) {
|
if self.eat_keyword(kw::Unsafe) {
|
||||||
Unsafe::Yes(self.normalized_prev_token.span)
|
Unsafe::Yes(self.prev_token.uninterpolated_span())
|
||||||
} else {
|
} else {
|
||||||
Unsafe::No
|
Unsafe::No
|
||||||
}
|
}
|
||||||
|
|
@ -903,7 +871,7 @@ impl<'a> Parser<'a> {
|
||||||
/// Parses constness: `const` or nothing.
|
/// Parses constness: `const` or nothing.
|
||||||
fn parse_constness(&mut self) -> Const {
|
fn parse_constness(&mut self) -> Const {
|
||||||
if self.eat_keyword(kw::Const) {
|
if self.eat_keyword(kw::Const) {
|
||||||
Const::Yes(self.normalized_prev_token.span)
|
Const::Yes(self.prev_token.uninterpolated_span())
|
||||||
} else {
|
} else {
|
||||||
Const::No
|
Const::No
|
||||||
}
|
}
|
||||||
|
|
@ -1005,7 +973,7 @@ impl<'a> Parser<'a> {
|
||||||
&mut self.token_cursor.frame,
|
&mut self.token_cursor.frame,
|
||||||
self.token_cursor.stack.pop().unwrap(),
|
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();
|
self.bump();
|
||||||
TokenTree::Delimited(frame.span, frame.delim, frame.tree_cursor.stream)
|
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 `|`
|
/// 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.
|
/// 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 {
|
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::FatArrow // e.g. `a | => 0,`.
|
||||||
| token::Ident(kw::If, false) // e.g. `a | if expr`.
|
| token::Ident(kw::If, false) // e.g. `a | if expr`.
|
||||||
| token::Eq // e.g. `let a | = 0`.
|
| 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> {
|
pub(super) fn parse_path_segment_ident(&mut self) -> PResult<'a, Ident> {
|
||||||
match self.normalized_token.kind {
|
match self.token.ident() {
|
||||||
token::Ident(name, _) if name.is_path_segment_keyword() => {
|
Some((ident, false)) if ident.is_path_segment_keyword() => {
|
||||||
self.bump();
|
self.bump();
|
||||||
Ok(Ident::new(name, self.normalized_prev_token.span))
|
Ok(ident)
|
||||||
}
|
}
|
||||||
_ => self.parse_ident(),
|
_ => self.parse_ident(),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -323,7 +323,7 @@ impl<'a> Parser<'a> {
|
||||||
/// Is a `dyn B0 + ... + Bn` type allowed here?
|
/// Is a `dyn B0 + ... + Bn` type allowed here?
|
||||||
fn is_explicit_dyn_type(&mut self) -> bool {
|
fn is_explicit_dyn_type(&mut self) -> bool {
|
||||||
self.check_keyword(kw::Dyn)
|
self.check_keyword(kw::Dyn)
|
||||||
&& (self.normalized_token.span.rust_2018()
|
&& (self.token.uninterpolated_span().rust_2018()
|
||||||
|| self.look_ahead(1, |t| {
|
|| self.look_ahead(1, |t| {
|
||||||
t.can_begin_bound() && !can_continue_type_after_non_fn_ident(t)
|
t.can_begin_bound() && !can_continue_type_after_non_fn_ident(t)
|
||||||
}))
|
}))
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@ impl Handler {
|
||||||
pub unsafe fn new() -> Handler {
|
pub unsafe fn new() -> Handler {
|
||||||
make_handler()
|
make_handler()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn null() -> Handler {
|
||||||
|
Handler { _data: crate::ptr::null_mut() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Handler {
|
impl Drop for Handler {
|
||||||
|
|
@ -108,13 +112,20 @@ mod imp {
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut MAIN_ALTSTACK: *mut libc::c_void = ptr::null_mut();
|
static mut MAIN_ALTSTACK: *mut libc::c_void = ptr::null_mut();
|
||||||
|
static mut NEED_ALTSTACK: bool = false;
|
||||||
|
|
||||||
pub unsafe fn init() {
|
pub unsafe fn init() {
|
||||||
let mut action: sigaction = mem::zeroed();
|
let mut action: sigaction = mem::zeroed();
|
||||||
action.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
for &signal in &[SIGSEGV, SIGBUS] {
|
||||||
action.sa_sigaction = signal_handler as sighandler_t;
|
sigaction(signal, ptr::null_mut(), &mut action);
|
||||||
sigaction(SIGSEGV, &action, ptr::null_mut());
|
// Configure our signal handler if one is not already set.
|
||||||
sigaction(SIGBUS, &action, ptr::null_mut());
|
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();
|
let handler = make_handler();
|
||||||
MAIN_ALTSTACK = handler._data;
|
MAIN_ALTSTACK = handler._data;
|
||||||
|
|
@ -152,6 +163,9 @@ mod imp {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn make_handler() -> Handler {
|
pub unsafe fn make_handler() -> Handler {
|
||||||
|
if !NEED_ALTSTACK {
|
||||||
|
return Handler::null();
|
||||||
|
}
|
||||||
let mut stack = mem::zeroed();
|
let mut stack = mem::zeroed();
|
||||||
sigaltstack(ptr::null(), &mut stack);
|
sigaltstack(ptr::null(), &mut stack);
|
||||||
// Configure alternate signal stack, if one is not already set.
|
// Configure alternate signal stack, if one is not already set.
|
||||||
|
|
@ -160,7 +174,7 @@ mod imp {
|
||||||
sigaltstack(&stack, ptr::null_mut());
|
sigaltstack(&stack, ptr::null_mut());
|
||||||
Handler { _data: stack.ss_sp as *mut libc::c_void }
|
Handler { _data: stack.ss_sp as *mut libc::c_void }
|
||||||
} else {
|
} else {
|
||||||
Handler { _data: ptr::null_mut() }
|
Handler::null()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -191,14 +205,12 @@ mod imp {
|
||||||
target_os = "openbsd"
|
target_os = "openbsd"
|
||||||
)))]
|
)))]
|
||||||
mod imp {
|
mod imp {
|
||||||
use crate::ptr;
|
|
||||||
|
|
||||||
pub unsafe fn init() {}
|
pub unsafe fn init() {}
|
||||||
|
|
||||||
pub unsafe fn cleanup() {}
|
pub unsafe fn cleanup() {}
|
||||||
|
|
||||||
pub unsafe fn make_handler() -> super::Handler {
|
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) {}
|
pub unsafe fn drop_handler(_handler: &mut super::Handler) {}
|
||||||
|
|
|
||||||
|
|
@ -665,20 +665,24 @@ extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
|
||||||
|
|
||||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
|
||||||
LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
|
LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
|
||||||
const char *Producer, bool isOptimized, const char *Flags,
|
const char *Producer, size_t ProducerLen, bool isOptimized,
|
||||||
unsigned RuntimeVer, const char *SplitName,
|
const char *Flags, unsigned RuntimeVer,
|
||||||
|
const char *SplitName, size_t SplitNameLen,
|
||||||
LLVMRustDebugEmissionKind Kind) {
|
LLVMRustDebugEmissionKind Kind) {
|
||||||
auto *File = unwrapDI<DIFile>(FileRef);
|
auto *File = unwrapDI<DIFile>(FileRef);
|
||||||
|
|
||||||
return wrap(Builder->createCompileUnit(Lang, File, Producer, isOptimized,
|
return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
|
||||||
Flags, RuntimeVer, SplitName,
|
isOptimized, Flags, RuntimeVer,
|
||||||
|
StringRef(SplitName, SplitNameLen),
|
||||||
fromRust(Kind)));
|
fromRust(Kind)));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" LLVMMetadataRef
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
|
||||||
LLVMRustDIBuilderCreateFile(LLVMRustDIBuilderRef Builder, const char *Filename,
|
LLVMRustDIBuilderRef Builder,
|
||||||
const char *Directory) {
|
const char *Filename, size_t FilenameLen,
|
||||||
return wrap(Builder->createFile(Filename, Directory));
|
const char *Directory, size_t DirectoryLen) {
|
||||||
|
return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
|
||||||
|
StringRef(Directory, DirectoryLen)));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" LLVMMetadataRef
|
extern "C" LLVMMetadataRef
|
||||||
|
|
@ -690,8 +694,10 @@ LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
|
||||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
|
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
||||||
const char *LinkageName, LLVMMetadataRef File, unsigned LineNo,
|
const char *Name, size_t NameLen,
|
||||||
|
const char *LinkageName, size_t LinkageNameLen,
|
||||||
|
LLVMMetadataRef File, unsigned LineNo,
|
||||||
LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
|
LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
|
||||||
LLVMRustDISPFlags SPFlags, LLVMValueRef Fn, LLVMMetadataRef TParam,
|
LLVMRustDISPFlags SPFlags, LLVMValueRef Fn, LLVMMetadataRef TParam,
|
||||||
LLVMMetadataRef Decl) {
|
LLVMMetadataRef Decl) {
|
||||||
|
|
@ -705,8 +711,11 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
|
||||||
llvmFlags |= DINode::DIFlags::FlagMainSubprogram;
|
llvmFlags |= DINode::DIFlags::FlagMainSubprogram;
|
||||||
#endif
|
#endif
|
||||||
DISubprogram *Sub = Builder->createFunction(
|
DISubprogram *Sub = Builder->createFunction(
|
||||||
unwrapDI<DIScope>(Scope), Name, LinkageName, unwrapDI<DIFile>(File),
|
unwrapDI<DIScope>(Scope),
|
||||||
LineNo, unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
|
StringRef(Name, NameLen),
|
||||||
|
StringRef(LinkageName, LinkageNameLen),
|
||||||
|
unwrapDI<DIFile>(File), LineNo,
|
||||||
|
unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
|
||||||
llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
|
llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
|
||||||
#else
|
#else
|
||||||
bool IsLocalToUnit = isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit);
|
bool IsLocalToUnit = isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit);
|
||||||
|
|
@ -716,8 +725,11 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
|
||||||
if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram))
|
if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram))
|
||||||
llvmFlags |= DINode::DIFlags::FlagMainSubprogram;
|
llvmFlags |= DINode::DIFlags::FlagMainSubprogram;
|
||||||
DISubprogram *Sub = Builder->createFunction(
|
DISubprogram *Sub = Builder->createFunction(
|
||||||
unwrapDI<DIScope>(Scope), Name, LinkageName, unwrapDI<DIFile>(File),
|
unwrapDI<DIScope>(Scope),
|
||||||
LineNo, unwrapDI<DISubroutineType>(Ty), IsLocalToUnit, IsDefinition,
|
StringRef(Name, NameLen),
|
||||||
|
StringRef(LinkageName, LinkageNameLen),
|
||||||
|
unwrapDI<DIFile>(File), LineNo,
|
||||||
|
unwrapDI<DISubroutineType>(Ty), IsLocalToUnit, IsDefinition,
|
||||||
ScopeLine, llvmFlags, IsOptimized, TParams,
|
ScopeLine, llvmFlags, IsOptimized, TParams,
|
||||||
unwrapDIPtr<DISubprogram>(Decl));
|
unwrapDIPtr<DISubprogram>(Decl));
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -725,53 +737,59 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
|
||||||
return wrap(Sub);
|
return wrap(Sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" LLVMMetadataRef
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
|
||||||
LLVMRustDIBuilderCreateBasicType(LLVMRustDIBuilderRef Builder, const char *Name,
|
LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
|
||||||
uint64_t SizeInBits, uint32_t AlignInBits,
|
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding) {
|
||||||
unsigned Encoding) {
|
return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
|
||||||
return wrap(Builder->createBasicType(Name, SizeInBits, Encoding));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
|
||||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
|
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),
|
return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
|
||||||
SizeInBits, AlignInBits,
|
SizeInBits, AlignInBits,
|
||||||
/* DWARFAddressSpace */ None,
|
AddressSpace,
|
||||||
Name));
|
StringRef(Name, NameLen)));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
|
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,
|
LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
|
||||||
uint32_t AlignInBits, LLVMRustDIFlags Flags,
|
uint32_t AlignInBits, LLVMRustDIFlags Flags,
|
||||||
LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
|
LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
|
||||||
unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
|
unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
|
||||||
const char *UniqueId) {
|
const char *UniqueId, size_t UniqueIdLen) {
|
||||||
return wrap(Builder->createStructType(
|
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),
|
SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
|
||||||
DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
|
DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
|
||||||
unwrapDI<DIType>(VTableHolder), UniqueId));
|
unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
|
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,
|
LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
|
||||||
uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
|
uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
|
||||||
LLVMMetadataRef Elements, const char *UniqueId) {
|
LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
|
||||||
return wrap(Builder->createVariantPart(
|
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),
|
SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
|
||||||
DINodeArray(unwrapDI<MDTuple>(Elements)), UniqueId));
|
DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
|
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,
|
LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
|
||||||
uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
|
uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
|
||||||
LLVMMetadataRef Ty) {
|
LLVMMetadataRef Ty) {
|
||||||
return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope), Name,
|
return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
|
||||||
|
StringRef(Name, NameLen),
|
||||||
unwrapDI<DIFile>(File), LineNo,
|
unwrapDI<DIFile>(File), LineNo,
|
||||||
SizeInBits, AlignInBits, OffsetInBits,
|
SizeInBits, AlignInBits, OffsetInBits,
|
||||||
fromRust(Flags), unwrapDI<DIType>(Ty)));
|
fromRust(Flags), unwrapDI<DIType>(Ty)));
|
||||||
|
|
@ -779,14 +797,15 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
|
||||||
|
|
||||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
|
||||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
||||||
const char *Name, LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
|
const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
|
||||||
uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
|
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
|
||||||
LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
|
LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
|
||||||
llvm::ConstantInt* D = nullptr;
|
llvm::ConstantInt* D = nullptr;
|
||||||
if (Discriminant) {
|
if (Discriminant) {
|
||||||
D = unwrap<llvm::ConstantInt>(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,
|
unwrapDI<DIFile>(File), LineNo,
|
||||||
SizeInBits, AlignInBits, OffsetInBits, D,
|
SizeInBits, AlignInBits, OffsetInBits, D,
|
||||||
fromRust(Flags), unwrapDI<DIType>(Ty)));
|
fromRust(Flags), unwrapDI<DIType>(Ty)));
|
||||||
|
|
@ -808,8 +827,10 @@ LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
|
||||||
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context, const char *Name,
|
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
|
||||||
const char *LinkageName, LLVMMetadataRef File, unsigned LineNo,
|
const char *Name, size_t NameLen,
|
||||||
|
const char *LinkageName, size_t LinkageNameLen,
|
||||||
|
LLVMMetadataRef File, unsigned LineNo,
|
||||||
LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
|
LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
|
||||||
LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
|
LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
|
||||||
llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
|
llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
|
||||||
|
|
@ -825,7 +846,8 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
|
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,
|
unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
|
||||||
#if LLVM_VERSION_GE(10, 0)
|
#if LLVM_VERSION_GE(10, 0)
|
||||||
/* isDefined */ true,
|
/* isDefined */ true,
|
||||||
|
|
@ -843,17 +865,20 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
|
||||||
|
|
||||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
|
||||||
LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
|
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,
|
LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
|
||||||
unsigned ArgNo, uint32_t AlignInBits) {
|
unsigned ArgNo, uint32_t AlignInBits) {
|
||||||
if (Tag == 0x100) { // DW_TAG_auto_variable
|
if (Tag == 0x100) { // DW_TAG_auto_variable
|
||||||
return wrap(Builder->createAutoVariable(
|
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));
|
unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
|
||||||
} else {
|
} else {
|
||||||
return wrap(Builder->createParameterVariable(
|
return wrap(Builder->createParameterVariable(
|
||||||
unwrapDI<DIDescriptor>(Scope), Name, ArgNo, unwrapDI<DIFile>(File),
|
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
|
||||||
LineNo, unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
|
unwrapDI<DIFile>(File), LineNo,
|
||||||
|
unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -894,47 +919,50 @@ extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
|
||||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
|
||||||
LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
|
LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
|
||||||
int64_t Value, bool IsUnsigned) {
|
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(
|
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,
|
LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
|
||||||
uint32_t AlignInBits, LLVMMetadataRef Elements,
|
uint32_t AlignInBits, LLVMMetadataRef Elements,
|
||||||
LLVMMetadataRef ClassTy, bool IsScoped) {
|
LLVMMetadataRef ClassTy, bool IsScoped) {
|
||||||
return wrap(Builder->createEnumerationType(
|
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)),
|
SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
|
||||||
unwrapDI<DIType>(ClassTy), "", IsScoped));
|
unwrapDI<DIType>(ClassTy), "", IsScoped));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
|
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,
|
LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
|
||||||
uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
|
uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
|
||||||
unsigned RunTimeLang, const char *UniqueId) {
|
unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
|
||||||
return wrap(Builder->createUnionType(
|
return wrap(Builder->createUnionType(
|
||||||
unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber,
|
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
|
||||||
SizeInBits, AlignInBits, fromRust(Flags),
|
LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
|
||||||
DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang, UniqueId));
|
DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
|
||||||
|
StringRef(UniqueId, UniqueIdLen)));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
|
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,
|
LLVMMetadataRef Ty, LLVMMetadataRef File, unsigned LineNo,
|
||||||
unsigned ColumnNo) {
|
unsigned ColumnNo) {
|
||||||
return wrap(Builder->createTemplateTypeParameter(
|
return wrap(Builder->createTemplateTypeParameter(
|
||||||
unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIType>(Ty)));
|
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty)));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" LLVMMetadataRef
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
|
||||||
LLVMRustDIBuilderCreateNameSpace(LLVMRustDIBuilderRef Builder,
|
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
||||||
LLVMMetadataRef Scope, const char *Name,
|
const char *Name, size_t NameLen, bool ExportSymbols) {
|
||||||
LLVMMetadataRef File, unsigned LineNo) {
|
|
||||||
return wrap(Builder->createNameSpace(
|
return wrap(Builder->createNameSpace(
|
||||||
unwrapDI<DIDescriptor>(Scope), Name,
|
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
|
||||||
false // ExportSymbols (only relevant for C++ anonymous namespaces)
|
));
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void
|
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
|
const TEST: () = { unsafe { //~ NOTE
|
||||||
let slice: *const [u8] = mem::transmute((1usize, usize::MAX));
|
let slice: *const [u8] = mem::transmute((1usize, usize::MAX));
|
||||||
let _val = &*slice; //~ ERROR: any use of this value will cause an error
|
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
|
//~^^ on by default
|
||||||
} };
|
} };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ error: any use of this value will cause an error
|
||||||
LL | / const TEST: () = { unsafe {
|
LL | / const TEST: () = { unsafe {
|
||||||
LL | | let slice: *const [u8] = mem::transmute((1usize, usize::MAX));
|
LL | | let slice: *const [u8] = mem::transmute((1usize, usize::MAX));
|
||||||
LL | | let _val = &*slice;
|
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 | |
|
LL | |
|
||||||
LL | | } };
|
LL | | } };
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,16 @@ const STR_VALID: &str = unsafe { mem::transmute((&42u8, 1usize)) };
|
||||||
// bad str
|
// bad str
|
||||||
const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
|
const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
|
||||||
//~^ ERROR it is undefined behavior to use this value
|
//~^ 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
|
// bad str
|
||||||
const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
|
const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
|
||||||
//~^ ERROR it is undefined behavior to use this value
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
// bad str in user-defined unsized type
|
// bad str in user-defined unsized type
|
||||||
const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
|
const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
|
||||||
//~^ ERROR it is undefined behavior to use this value
|
//~^ 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
|
// invalid UTF-8
|
||||||
const STR_NO_UTF8: &str = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) };
|
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
|
// # raw slice
|
||||||
const RAW_SLICE_VALID: *const [u8] = unsafe { mem::transmute((&42u8, 1usize)) }; // ok
|
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_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 {
|
const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
|
||||||
//~^ ERROR it is undefined behavior to use this value
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
let uninit_len = MaybeUninit::<usize> { uninit: () };
|
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.
|
= 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
|
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)) };
|
LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
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)) };
|
LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-wide-ptr.rs:42:1
|
--> $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]) };
|
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>
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
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]) };
|
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
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
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 | / const SLICE_LENGTH_UNINIT: &[u8] = unsafe {
|
||||||
LL | |
|
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.
|
= 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
|
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)) };
|
LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds)
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
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)) };
|
LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
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)) };
|
LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (not entirely in bounds)
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
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)) };
|
LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
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) }];
|
LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>[0], but expected a boolean
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
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]);
|
LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.0, but expected a boolean
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
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) }]);
|
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
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
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 | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
|
||||||
LL | |
|
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.
|
= 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
|
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)) };
|
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
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
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)) };
|
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
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
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)) };
|
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
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
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) };
|
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
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
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)) };
|
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
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
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)) };
|
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
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
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))
|
LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer
|
||||||
|
|
||||||
error[E0080]: could not evaluate static initializer
|
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))
|
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
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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`.
|
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
|
--> $DIR/const-points-to-static.rs:5:1
|
||||||
|
|
|
|
||||||
LL | const TEST: &u8 = &MY_STATIC;
|
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.
|
= 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 | | .slice
|
||||||
LL | | };
|
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.
|
= 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 | | unsafe { &*(&FOO as *const _ as *const usize) }
|
||||||
LL | |
|
LL | |
|
||||||
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.
|
= 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 | | &FOO
|
||||||
LL | |
|
LL | |
|
||||||
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.
|
= 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
|
//~^ ERROR an inner attribute is not permitted in this context
|
||||||
#[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
|
#[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
|
||||||
//~^ ERROR an inner attribute is not permitted in this context
|
//~^ 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] {}; }
|
#[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
|
||||||
//~^ ERROR expected `{`, found `#`
|
//~^ ERROR expected `{`, found `#`
|
||||||
#[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
|
#[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
|
||||||
|
|
@ -51,14 +49,11 @@ fn main() {}
|
||||||
#[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
|
#[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
|
||||||
//~^ ERROR an inner attribute is not permitted in this context
|
//~^ ERROR an inner attribute is not permitted in this context
|
||||||
#[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
|
#[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] {}; }
|
#[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
|
||||||
//~^ ERROR expected `{`, found `#`
|
//~^ ERROR expected `{`, found `#`
|
||||||
#[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
|
#[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
|
||||||
//~^ ERROR an inner attribute is not permitted in this context
|
//~^ 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] {}; }
|
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
|
||||||
//~^ ERROR expected `{`, found `#`
|
//~^ ERROR expected `{`, found `#`
|
||||||
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
|
#[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]}; }
|
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
|
||||||
//~^ ERROR an inner attribute is not permitted in this context
|
//~^ ERROR an inner attribute is not permitted in this context
|
||||||
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
|
#[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] {}; }
|
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
|
||||||
//~^ ERROR expected `{`, found `#`
|
//~^ ERROR expected `{`, found `#`
|
||||||
#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
|
#[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.
|
= 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 `#`
|
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] {}; }
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
|
||||||
| -- ^ --- help: try placing this code inside a block: `{ {}; }`
|
| -- ^ --- 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
|
| this `if` expression has a condition, but no block
|
||||||
|
|
||||||
error: an inner attribute is not permitted in this context
|
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]}; }
|
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.
|
= 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 `#`
|
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 {}; }
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; }
|
||||||
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
|
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
|
||||||
|
|
||||||
error: expected `{`, found `#`
|
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] {}; }
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
|
||||||
| ^ --- help: try placing this code inside a block: `{ {}; }`
|
| ^ --- help: try placing this code inside a block: `{ {}; }`
|
||||||
|
|
@ -174,21 +168,15 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
|
||||||
| expected `{`
|
| expected `{`
|
||||||
|
|
||||||
error: an inner attribute is not permitted in this context
|
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]}; }
|
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.
|
= 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 `#`
|
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 {}; }
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
|
||||||
| ^ -------- help: try placing this code inside a block: `{ 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 `{`
|
| expected `{`
|
||||||
|
|
||||||
error: expected `{`, found `#`
|
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] {}; }
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
|
||||||
| -- ^ --- help: try placing this code inside a block: `{ {}; }`
|
| -- ^ --- 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
|
| this `if` expression has a condition, but no block
|
||||||
|
|
||||||
error: an inner attribute is not permitted in this context
|
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]}; }
|
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.
|
= 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 `#`
|
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] {}; }
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
|
||||||
| -- ^ --- help: try placing this code inside a block: `{ {}; }`
|
| -- ^ --- 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
|
| this `if` expression has a condition, but no block
|
||||||
|
|
||||||
error: an inner attribute is not permitted in this context
|
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]}; }
|
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.
|
= 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 `#`
|
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 {}; }
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
|
||||||
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
|
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
|
||||||
|
|
||||||
error: expected `{`, found `#`
|
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] {}; }
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
|
||||||
| ^ --- help: try placing this code inside a block: `{ {}; }`
|
| ^ --- help: try placing this code inside a block: `{ {}; }`
|
||||||
|
|
@ -250,21 +232,15 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
|
||||||
| expected `{`
|
| expected `{`
|
||||||
|
|
||||||
error: an inner attribute is not permitted in this context
|
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]}; }
|
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.
|
= 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 `#`
|
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 {}; }
|
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 {}; }`
|
| ^ ---------------- 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 `{`
|
| expected `{`
|
||||||
|
|
||||||
error: expected `{`, found `#`
|
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] {}; }
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
|
||||||
| -- ^ --- help: try placing this code inside a block: `{ {}; }`
|
| -- ^ --- 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
|
| this `if` expression has a condition, but no block
|
||||||
|
|
||||||
error: an inner attribute is not permitted in this context
|
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]}; }
|
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.
|
= 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
|
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; }
|
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; }
|
||||||
| ------- ^^^^^^^^ not permitted following an outer attribute
|
| ------- ^^^^^^^^ 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.
|
= 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
|
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; }
|
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; }
|
||||||
| ------- ^^^^^^^^ not permitted following an outer attribute
|
| ------- ^^^^^^^^ 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.
|
= 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
|
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!(); }
|
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
|
||||||
| ------- ^^^^^^^^ not permitted following an outer attribute
|
| ------- ^^^^^^^^ 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.
|
= 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
|
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![]; }
|
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
|
||||||
| ------- ^^^^^^^^ not permitted following an outer attribute
|
| ------- ^^^^^^^^ 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.
|
= 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
|
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!{}; }
|
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
|
||||||
| ------- ^^^^^^^^ not permitted following an outer attribute
|
| ------- ^^^^^^^^ 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.
|
= 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
|
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 => () } }
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
|
||||||
| ^^^ help: use `..` instead
|
| ^^^ 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`)
|
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
|
||||||
|
|
||||||
error: expected one of `=>`, `if`, or `|`, found `#`
|
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 => () } }
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
|
||||||
| ^ expected one of `=>`, `if`, or `|`
|
| ^ expected one of `=>`, `if`, or `|`
|
||||||
|
|
||||||
error[E0586]: inclusive range with no end
|
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 => () } }
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
|
||||||
| ^^^ help: use `..` instead
|
| ^^^ 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`)
|
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
|
||||||
|
|
||||||
error: expected one of `=>`, `if`, or `|`, found `#`
|
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 => () } }
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
|
||||||
| ^ expected one of `=>`, `if`, or `|`
|
| ^ expected one of `=>`, `if`, or `|`
|
||||||
|
|
||||||
error: unexpected token: `#`
|
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 => () } }
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error[E0586]: inclusive range with no end
|
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 => () } }
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
|
||||||
| ^^^ help: use `..` instead
|
| ^^^ 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`)
|
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
|
||||||
|
|
||||||
error: expected one of `=>`, `if`, or `|`, found `#`
|
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 => () } }
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
|
||||||
| ^ expected one of `=>`, `if`, or `|`
|
| ^ expected one of `=>`, `if`, or `|`
|
||||||
|
|
||||||
error: unexpected token: `#`
|
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(); }
|
LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: expected one of `.`, `;`, `?`, or an operator, found `#`
|
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(); }
|
LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
|
||||||
| ^ expected one of `.`, `;`, `?`, or an operator
|
| ^ expected one of `.`, `;`, `?`, or an operator
|
||||||
|
|
||||||
error: unexpected token: `#`
|
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(); }
|
LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: expected one of `.`, `;`, `?`, or an operator, found `#`
|
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(); }
|
LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
|
||||||
| ^ expected one of `.`, `;`, `?`, or an operator
|
| ^ expected one of `.`, `;`, `?`, or an operator
|
||||||
|
|
||||||
error: expected statement after outer attribute
|
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]; } } }
|
LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } }
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: expected statement after outer attribute
|
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] } } }
|
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`.
|
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…
Add table
Add a link
Reference in a new issue