diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-10-28 00:29:23 +0100 |
|---|---|---|
| committer | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-11-07 05:25:31 +0100 |
| commit | 1db4d607e7621a7d813743e83125859a47970f79 (patch) | |
| tree | cde776509b2b3fbfb57b2a8bb9c4d33ef3856978 /src/libsyntax/parse | |
| parent | 49def0769c51d182bf6c321eefdcda288e3ad218 (diff) | |
| download | rust-1db4d607e7621a7d813743e83125859a47970f79.tar.gz rust-1db4d607e7621a7d813743e83125859a47970f79.zip | |
parser: allow ABIs from literal macro fragments
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 40 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser/expr.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser/item.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/parse/token.rs | 7 |
4 files changed, 33 insertions, 22 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 382c1a517aa..0c358b1caaf 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -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. diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 97b1092452a..80ea8f380fb 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -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 diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index 76411e7cf13..ebb1cf12996 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -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 diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index ea82aad0eae..6f3da344ccf 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -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 { |
