mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-28 01:34:21 +00:00
parser: allow ABIs from literal macro fragments
This commit is contained in:
parent
49def0769c
commit
1db4d607e7
@ -1205,27 +1205,41 @@ impl<'a> Parser<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Parses `extern` followed by an optional ABI string, or nothing.
|
||||
/// Parses `extern string_literal?`.
|
||||
/// If `extern` is not found, the Rust ABI is used.
|
||||
/// If `extern` is found and a `string_literal` does not follow, the C ABI is used.
|
||||
fn parse_extern_abi(&mut self) -> PResult<'a, Abi> {
|
||||
Ok(if self.eat_keyword(kw::Extern) {
|
||||
let ext_sp = self.prev_span;
|
||||
self.parse_opt_abi()?.unwrap_or_else(|| Abi::new(sym::C, ext_sp))
|
||||
self.parse_opt_abi()?
|
||||
} else {
|
||||
Abi::default()
|
||||
})
|
||||
}
|
||||
|
||||
/// Parses a string as an ABI spec on an extern type or module.
|
||||
fn parse_opt_abi(&mut self) -> PResult<'a, Option<Abi>> {
|
||||
match self.token.kind {
|
||||
token::Literal(token::Lit { kind: token::Str, symbol, suffix }) |
|
||||
token::Literal(token::Lit { kind: token::StrRaw(..), symbol, suffix }) => {
|
||||
self.expect_no_suffix(self.token.span, "an ABI spec", suffix);
|
||||
self.bump();
|
||||
Ok(Some(Abi::new(symbol, self.prev_span)))
|
||||
/// Parses a string literal as an ABI spec.
|
||||
/// If one is not found, the "C" ABI is used.
|
||||
fn parse_opt_abi(&mut self) -> PResult<'a, Abi> {
|
||||
let span = if self.token.can_begin_literal_or_bool() {
|
||||
let ast::Lit { span, kind, .. } = self.parse_lit()?;
|
||||
match kind {
|
||||
ast::LitKind::Str(symbol, _) => return Ok(Abi::new(symbol, span)),
|
||||
ast::LitKind::Err(_) => {}
|
||||
_ => {
|
||||
self.struct_span_err(span, "non-string ABI literal")
|
||||
.span_suggestion(
|
||||
span,
|
||||
"specify the ABI with a string literal",
|
||||
"\"C\"".to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
_ => Ok(None),
|
||||
}
|
||||
span
|
||||
} else {
|
||||
self.prev_span
|
||||
};
|
||||
Ok(Abi::new(sym::C, span))
|
||||
}
|
||||
|
||||
/// We are parsing `async fn`. If we are on Rust 2015, emit an error.
|
||||
|
@ -1116,7 +1116,11 @@ impl<'a> Parser<'a> {
|
||||
Err(self.span_fatal(token.span, &msg))
|
||||
}
|
||||
Err(err) => {
|
||||
let (lit, span) = (token.expect_lit(), token.span);
|
||||
let span = token.span;
|
||||
let lit = match token.kind {
|
||||
token::Literal(lit) => lit,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
self.bump();
|
||||
self.error_literal_from_token(err, lit, span);
|
||||
// Pack possible quotes and prefixes from the original literal into
|
||||
|
@ -110,7 +110,7 @@ impl<'a> Parser<'a> {
|
||||
return Ok(Some(self.parse_item_extern_crate(lo, vis, attrs)?));
|
||||
}
|
||||
|
||||
let abi = self.parse_opt_abi()?.unwrap_or_else(|| Abi::new(sym::C, extern_sp));
|
||||
let abi = self.parse_opt_abi()?;
|
||||
|
||||
if self.eat_keyword(kw::Fn) {
|
||||
// EXTERN FUNCTION ITEM
|
||||
|
@ -402,13 +402,6 @@ impl Token {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn expect_lit(&self) -> Lit {
|
||||
match self.kind {
|
||||
Literal(lit) => lit,
|
||||
_ => panic!("`expect_lit` called on non-literal"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the token is any literal, a minus (which can prefix a literal,
|
||||
/// for example a '-42', or one of the boolean idents).
|
||||
pub fn can_begin_literal_or_bool(&self) -> bool {
|
||||
|
@ -1,9 +1,9 @@
|
||||
extern
|
||||
"C"suffix //~ ERROR suffixes on an ABI spec are invalid
|
||||
"C"suffix //~ ERROR suffixes on a string literal are invalid
|
||||
fn foo() {}
|
||||
|
||||
extern
|
||||
"C"suffix //~ ERROR suffixes on an ABI spec are invalid
|
||||
"C"suffix //~ ERROR suffixes on a string literal are invalid
|
||||
{}
|
||||
|
||||
fn main() {
|
||||
|
@ -1,10 +1,10 @@
|
||||
error: suffixes on an ABI spec are invalid
|
||||
error: suffixes on a string literal are invalid
|
||||
--> $DIR/bad-lit-suffixes.rs:2:5
|
||||
|
|
||||
LL | "C"suffix
|
||||
| ^^^^^^^^^ invalid suffix `suffix`
|
||||
|
||||
error: suffixes on an ABI spec are invalid
|
||||
error: suffixes on a string literal are invalid
|
||||
--> $DIR/bad-lit-suffixes.rs:6:5
|
||||
|
|
||||
LL | "C"suffix
|
||||
|
26
src/test/ui/parser/extern-abi-from-mac-literal-frag.rs
Normal file
26
src/test/ui/parser/extern-abi-from-mac-literal-frag.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// check-pass
|
||||
|
||||
// In this test we check that the parser accepts an ABI string when it
|
||||
// comes from a macro `literal` fragment as opposed to a hardcoded string.
|
||||
|
||||
fn main() {}
|
||||
|
||||
macro_rules! abi_from_lit_frag {
|
||||
($abi:literal) => {
|
||||
extern $abi {
|
||||
fn _import();
|
||||
}
|
||||
|
||||
extern $abi fn _export() {}
|
||||
|
||||
type _PTR = extern $abi fn();
|
||||
}
|
||||
}
|
||||
|
||||
mod rust {
|
||||
abi_from_lit_frag!("Rust");
|
||||
}
|
||||
|
||||
mod c {
|
||||
abi_from_lit_frag!("C");
|
||||
}
|
Loading…
Reference in New Issue
Block a user