about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-11-10 00:44:59 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-11-16 21:21:37 +0300
commit00bc4496026a3168eed95e88c29f17dac2739d48 (patch)
tree8848a81d29817d48c21111a119637703cae0656f
parent266f5471272532989332117e8a2e0bacb5b94ccf (diff)
downloadrust-00bc4496026a3168eed95e88c29f17dac2739d48.tar.gz
rust-00bc4496026a3168eed95e88c29f17dac2739d48.zip
ast: Keep string literals in ABIs precisely
-rw-r--r--src/librustc/hir/lowering/item.rs6
-rw-r--r--src/librustc_parse/parser/item.rs4
-rw-r--r--src/librustc_parse/parser/mod.rs11
-rw-r--r--src/libsyntax/ast.rs42
-rw-r--r--src/libsyntax/feature_gate/check.rs6
-rw-r--r--src/libsyntax/print/pprust.rs10
6 files changed, 49 insertions, 30 deletions
diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs
index 2dc7e014445..f689e7f9622 100644
--- a/src/librustc/hir/lowering/item.rs
+++ b/src/librustc/hir/lowering/item.rs
@@ -1287,8 +1287,8 @@ impl LoweringContext<'_> {
         }
     }
 
-    pub(super) fn lower_abi(&mut self, abi: Abi) -> abi::Abi {
-        abi::lookup(&abi.symbol.as_str()).unwrap_or_else(|| {
+    pub(super) fn lower_abi(&mut self, abi: StrLit) -> abi::Abi {
+        abi::lookup(&abi.symbol_unescaped.as_str()).unwrap_or_else(|| {
             self.error_on_invalid_abi(abi);
             abi::Abi::Rust
         })
@@ -1302,7 +1302,7 @@ impl LoweringContext<'_> {
         }
     }
 
-    fn error_on_invalid_abi(&self, abi: Abi) {
+    fn error_on_invalid_abi(&self, abi: StrLit) {
         struct_span_err!(
             self.sess,
             abi.span,
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index fe86d03c6e7..3b824dc939f 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -1100,7 +1100,7 @@ impl<'a> Parser<'a> {
     fn parse_item_foreign_mod(
         &mut self,
         lo: Span,
-        abi: Option<Abi>,
+        abi: Option<StrLit>,
         visibility: Visibility,
         mut attrs: Vec<Attribute>,
         extern_sp: Span,
@@ -1778,7 +1778,7 @@ impl<'a> Parser<'a> {
         let is_c_abi = match header.ext {
             ast::Extern::None => false,
             ast::Extern::Implicit => true,
-            ast::Extern::Explicit(abi) => abi.symbol == sym::C,
+            ast::Extern::Explicit(abi) => abi.symbol_unescaped == sym::C,
         };
         let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
             is_self_allowed: false,
diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs
index 2d05a696791..2b49091192c 100644
--- a/src/librustc_parse/parser/mod.rs
+++ b/src/librustc_parse/parser/mod.rs
@@ -15,7 +15,7 @@ use crate::{Directory, DirectoryOwnership};
 use crate::lexer::UnmatchedBrace;
 
 use syntax::ast::{
-    self, Abi, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident,
+    self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident,
     IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety,
 };
 
@@ -1221,11 +1221,14 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a string literal as an ABI spec.
-    fn parse_opt_abi(&mut self) -> PResult<'a, Option<Abi>> {
+    fn parse_opt_abi(&mut self) -> PResult<'a, Option<StrLit>> {
         if self.token.can_begin_literal_or_bool() {
-            let ast::Lit { span, kind, .. } = self.parse_lit()?;
+            let ast::Lit { token: token::Lit { symbol, suffix, .. }, span, kind }
+                = self.parse_lit()?;
             match kind {
-                ast::LitKind::Str(symbol, _) => return Ok(Some(Abi { symbol, span })),
+                ast::LitKind::Str(symbol_unescaped, style) => return Ok(Some(StrLit {
+                    style, symbol, suffix, span, symbol_unescaped,
+                })),
                 ast::LitKind::Err(_) => {}
                 _ => {
                     self.struct_span_err(span, "non-string ABI literal")
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 575795758ae..dee493a708e 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1422,6 +1422,33 @@ pub struct Lit {
     pub span: Span,
 }
 
+/// Same as `Lit`, but restricted to string literals.
+#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
+pub struct StrLit {
+    /// The original literal token as written in source code.
+    pub style: StrStyle,
+    pub symbol: Symbol,
+    pub suffix: Option<Symbol>,
+    pub span: Span,
+    /// The unescaped "semantic" representation of the literal lowered from the original token.
+    /// FIXME: Remove this and only create the semantic representation during lowering to HIR.
+    pub symbol_unescaped: Symbol,
+}
+
+impl StrLit {
+    crate fn as_lit(&self) -> Lit {
+        let token_kind = match self.style {
+            StrStyle::Cooked => token::Str,
+            StrStyle::Raw(n) => token::StrRaw(n),
+        };
+        Lit {
+            token: token::Lit::new(token_kind, self.symbol, self.suffix),
+            span: self.span,
+            kind: LitKind::Str(self.symbol_unescaped, self.style),
+        }
+    }
+}
+
 // Clippy uses Hash and PartialEq
 /// Type of the integer literal based on provided suffix.
 #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)]
@@ -2128,7 +2155,7 @@ pub struct Mod {
 /// E.g., `extern { .. }` or `extern C { .. }`.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct ForeignMod {
-    pub abi: Option<Abi>,
+    pub abi: Option<StrLit>,
     pub items: Vec<ForeignItem>,
 }
 
@@ -2411,25 +2438,16 @@ impl Item {
     }
 }
 
-/// A reference to an ABI.
-///
-/// In AST our notion of an ABI is still syntactic unlike in `rustc_target::spec::abi::Abi`.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, PartialEq)]
-pub struct Abi {
-    pub symbol: Symbol,
-    pub span: Span,
-}
-
 /// `extern` qualifier on a function item or function type.
 #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
 pub enum Extern {
     None,
     Implicit,
-    Explicit(Abi),
+    Explicit(StrLit),
 }
 
 impl Extern {
-    pub fn from_abi(abi: Option<Abi>) -> Extern {
+    pub fn from_abi(abi: Option<StrLit>) -> Extern {
         match abi {
             Some(abi) => Extern::Explicit(abi),
             None => Extern::Implicit,
diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs
index d90fa9addf7..abf9adefd3c 100644
--- a/src/libsyntax/feature_gate/check.rs
+++ b/src/libsyntax/feature_gate/check.rs
@@ -191,10 +191,10 @@ macro_rules! gate_feature_post {
 }
 
 impl<'a> PostExpansionVisitor<'a> {
-    fn check_abi(&self, abi: ast::Abi) {
-        let ast::Abi { symbol, span } = abi;
+    fn check_abi(&self, abi: ast::StrLit) {
+        let ast::StrLit { symbol_unescaped, span, .. } = abi;
 
-        match &*symbol.as_str() {
+        match &*symbol_unescaped.as_str() {
             // Stable
             "Rust" |
             "C" |
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index de28bd6cf83..17a7cbddff9 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1233,7 +1233,8 @@ impl<'a> State<'a> {
             ast::ItemKind::ForeignMod(ref nmod) => {
                 self.head("extern");
                 if let Some(abi) = nmod.abi {
-                    self.print_abi(abi);
+                    self.print_literal(&abi.as_lit());
+                    self.nbsp();
                 }
                 self.bopen();
                 self.print_foreign_mod(nmod, &item.attrs);
@@ -2875,17 +2876,14 @@ impl<'a> State<'a> {
             }
             ast::Extern::Explicit(abi) => {
                 self.word_nbsp("extern");
-                self.print_abi(abi);
+                self.print_literal(&abi.as_lit());
+                self.nbsp();
             }
         }
 
         self.s.word("fn")
     }
 
-    fn print_abi(&mut self, abi: ast::Abi) {
-        self.word_nbsp(format!("\"{}\"", abi.symbol));
-    }
-
     crate fn print_unsafety(&mut self, s: ast::Unsafety) {
         match s {
             ast::Unsafety::Normal => {},