about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libproc_macro/lib.rs10
-rw-r--r--src/libproc_macro/quote.rs4
-rw-r--r--src/librustc_metadata/cstore.rs7
-rw-r--r--src/librustc_metadata/cstore_impl.rs14
-rw-r--r--src/librustc_metadata/decoder.rs49
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs12
-rw-r--r--src/librustc_resolve/macros.rs4
-rw-r--r--src/libsyntax/ext/base.rs67
-rw-r--r--src/libsyntax/ext/proc_macro_server.rs7
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs70
-rw-r--r--src/libsyntax/parse/parser.rs9
-rw-r--r--src/libsyntax_ext/lib.rs8
-rw-r--r--src/test/ui/auxiliary/cond_plugin.rs1
-rw-r--r--src/test/ui/auxiliary/proc_macro_def.rs1
-rw-r--r--src/test/ui/macros/auxiliary/proc_macro_sequence.rs20
-rw-r--r--src/test/ui/macros/same-sequence-span.stderr12
-rw-r--r--src/test/ui/proc-macro/attributes-on-definitions.rs12
-rw-r--r--src/test/ui/proc-macro/attributes-on-definitions.stderr8
-rw-r--r--src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs23
-rw-r--r--src/test/ui/proc-macro/multispan.stderr133
-rw-r--r--src/test/ui/proc-macro/three-equals.stderr19
21 files changed, 318 insertions, 172 deletions
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index c0f7714ca21..d408fef7515 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -19,12 +19,15 @@
 
 #![feature(nll)]
 #![feature(staged_api)]
+#![feature(allow_internal_unstable)]
 #![feature(const_fn)]
+#![feature(decl_macro)]
 #![feature(extern_types)]
 #![feature(in_band_lifetimes)]
 #![feature(optin_builtin_traits)]
 #![feature(mem_take)]
 #![feature(non_exhaustive)]
+#![feature(rustc_attrs)]
 #![feature(specialization)]
 
 #![recursion_limit="256"]
@@ -222,11 +225,10 @@ pub mod token_stream {
 ///
 /// Unquoting is done with `$`, and works by taking the single next ident as the unquoted term.
 /// To quote `$` itself, use `$$`.
-///
-/// This is a dummy macro, the actual implementation is in `quote::quote`.`
 #[unstable(feature = "proc_macro_quote", issue = "54722")]
-#[macro_export]
-macro_rules! quote { () => {} }
+#[allow_internal_unstable(proc_macro_def_site)]
+#[cfg_attr(not(bootstrap), rustc_builtin_macro)]
+pub macro quote ($($t:tt)*) { /* compiler built-in */ }
 
 #[unstable(feature = "proc_macro_internals", issue = "27812")]
 #[doc(hidden)]
diff --git a/src/libproc_macro/quote.rs b/src/libproc_macro/quote.rs
index e3d31b78f4a..144e2d6bac4 100644
--- a/src/libproc_macro/quote.rs
+++ b/src/libproc_macro/quote.rs
@@ -57,9 +57,9 @@ macro_rules! quote {
 }
 
 /// Quote a `TokenStream` into a `TokenStream`.
-/// This is the actual `quote!()` proc macro.
+/// This is the actual implementation of the `quote!()` proc macro.
 ///
-/// It is manually loaded in `CStore::load_macro_untracked`.
+/// It is loaded by the compiler in `register_builtin_macros`.
 #[unstable(feature = "proc_macro_quote", issue = "54722")]
 pub fn quote(stream: TokenStream) -> TokenStream {
     if stream.is_empty() {
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index efc77699313..5bf4067431f 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -95,11 +95,6 @@ pub struct CrateMetadata {
     pub raw_proc_macros: Option<&'static [ProcMacro]>,
 }
 
-pub struct FullProcMacro {
-    pub name: ast::Name,
-    pub ext: Lrc<SyntaxExtension>
-}
-
 pub struct CStore {
     metas: RwLock<IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>>,
     /// Map from NodeId's of local extern crate statements to crate numbers
@@ -109,7 +104,7 @@ pub struct CStore {
 
 pub enum LoadedMacro {
     MacroDef(ast::Item),
-    ProcMacro(Lrc<SyntaxExtension>),
+    ProcMacro(SyntaxExtension),
 }
 
 impl CStore {
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 7aeeef00ea9..5bfb315da47 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -30,11 +30,9 @@ use syntax::ast;
 use syntax::attr;
 use syntax::source_map;
 use syntax::edition::Edition;
-use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
-use syntax::ext::proc_macro::BangProcMacro;
 use syntax::parse::source_file_to_stream;
 use syntax::parse::parser::emit_unclosed_delims;
-use syntax::symbol::{Symbol, sym};
+use syntax::symbol::Symbol;
 use syntax_pos::{Span, FileName};
 use rustc_data_structures::bit_set::BitSet;
 
@@ -436,15 +434,7 @@ impl cstore::CStore {
     pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
         let data = self.get_crate_data(id.krate);
         if data.is_proc_macro_crate() {
-            return LoadedMacro::ProcMacro(data.get_proc_macro(id.index, sess).ext);
-        } else if data.name == sym::proc_macro && data.item_name(id.index) == sym::quote {
-            let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);
-            let kind = SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client }));
-            let ext = SyntaxExtension {
-                allow_internal_unstable: Some([sym::proc_macro_def_site][..].into()),
-                ..SyntaxExtension::default(kind, data.root.edition)
-            };
-            return LoadedMacro::ProcMacro(Lrc::new(ext));
+            return LoadedMacro::ProcMacro(data.load_proc_macro(id.index, sess));
         }
 
         let def = data.get_macro(id.index);
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 5b9cb966af2..c777b5ea409 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -1,6 +1,6 @@
 // Decoding metadata from a single crate's metadata
 
-use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule, FullProcMacro};
+use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule};
 use crate::schema::*;
 
 use rustc_data_structures::indexed_vec::IndexVec;
@@ -512,27 +512,8 @@ impl<'a, 'tcx> CrateMetadata {
         self.entry(index).span.decode((self, sess))
     }
 
-
-    pub fn get_proc_macro(&self, id: DefIndex, sess: &Session) -> FullProcMacro {
-        if sess.opts.debugging_opts.dual_proc_macros {
-            let host_lib = self.host_lib.as_ref().unwrap();
-            self.load_proc_macro(
-                &host_lib.metadata.get_root(),
-                id,
-                sess
-            )
-        } else {
-            self.load_proc_macro(&self.root, id, sess)
-        }
-    }
-
-    fn load_proc_macro(&self, root: &CrateRoot<'_>,
-                        id: DefIndex,
-                        sess: &Session)
-                        -> FullProcMacro {
-
-        let raw_macro = self.raw_proc_macro(id);
-        let (name, kind, helper_attrs) = match *raw_macro {
+    crate fn load_proc_macro(&self, id: DefIndex, sess: &Session) -> SyntaxExtension {
+        let (name, kind, helper_attrs) = match *self.raw_proc_macro(id) {
             ProcMacro::CustomDerive { trait_name, attributes, client } => {
                 let helper_attrs =
                     attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
@@ -551,17 +532,21 @@ impl<'a, 'tcx> CrateMetadata {
                 name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new()
             )
         };
+        let edition = if sess.opts.debugging_opts.dual_proc_macros {
+            self.host_lib.as_ref().unwrap().metadata.get_root().edition
+        } else {
+            self.root.edition
+        };
 
-        let span = self.get_span(id, sess);
-
-        FullProcMacro {
-            name: Symbol::intern(name),
-            ext: Lrc::new(SyntaxExtension {
-                span,
-                helper_attrs,
-                ..SyntaxExtension::default(kind, root.edition)
-            })
-        }
+        SyntaxExtension::new(
+            &sess.parse_sess,
+            kind,
+            self.get_span(id, sess),
+            helper_attrs,
+            edition,
+            Symbol::intern(name),
+            &self.get_attributes(&self.entry(id), sess),
+        )
     }
 
     pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 9a794ade729..165a4c707bb 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -150,12 +150,12 @@ impl<'a> Resolver<'a> {
             return Some(ext.clone());
         }
 
-        let macro_def = match self.cstore.load_macro_untracked(def_id, &self.session) {
-            LoadedMacro::MacroDef(macro_def) => macro_def,
-            LoadedMacro::ProcMacro(ext) => return Some(ext),
-        };
+        let ext = Lrc::new(match self.cstore.load_macro_untracked(def_id, &self.session) {
+            LoadedMacro::MacroDef(item) =>
+                self.compile_macro(&item, self.cstore.crate_edition_untracked(def_id.krate)),
+            LoadedMacro::ProcMacro(ext) => ext,
+        });
 
-        let ext = self.compile_macro(&macro_def, self.cstore.crate_edition_untracked(def_id.krate));
         self.macro_map.insert(def_id, ext.clone());
         Some(ext)
     }
@@ -1104,7 +1104,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
         let expansion = parent_scope.expansion;
         let (ext, ident, span, is_legacy) = match &item.node {
             ItemKind::MacroDef(def) => {
-                let ext = self.r.compile_macro(item, self.r.session.edition());
+                let ext = Lrc::new(self.r.compile_macro(item, self.r.session.edition()));
                 (ext, item.ident, item.span, def.legacy)
             }
             ItemKind::Fn(..) => match Self::proc_macro_stub(item) {
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 719167eb057..cc78e928380 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -800,7 +800,7 @@ impl<'a> Resolver<'a> {
 
     /// Compile the macro into a `SyntaxExtension` and possibly replace it with a pre-defined
     /// extension partially or entirely for built-in macros and legacy plugin macros.
-    crate fn compile_macro(&mut self, item: &ast::Item, edition: Edition) -> Lrc<SyntaxExtension> {
+    crate fn compile_macro(&mut self, item: &ast::Item, edition: Edition) -> SyntaxExtension {
         let mut result = macro_rules::compile(
             &self.session.parse_sess, self.session.features_untracked(), item, edition
         );
@@ -822,6 +822,6 @@ impl<'a> Resolver<'a> {
             }
         }
 
-        Lrc::new(result)
+        result
     }
 }
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index a63c4181d5e..10ff1b17285 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -1,11 +1,11 @@
 use crate::ast::{self, NodeId, Attribute, Name, PatKind};
-use crate::attr::{HasAttrs, Stability, Deprecation};
+use crate::attr::{self, HasAttrs, Stability, Deprecation};
 use crate::source_map::SourceMap;
 use crate::edition::Edition;
 use crate::ext::expand::{self, AstFragment, Invocation};
 use crate::ext::hygiene::{ExpnId, Transparency};
 use crate::mut_visit::{self, MutVisitor};
-use crate::parse::{self, parser, DirectoryOwnership};
+use crate::parse::{self, parser, ParseSess, DirectoryOwnership};
 use crate::parse::token;
 use crate::ptr::P;
 use crate::symbol::{kw, sym, Ident, Symbol};
@@ -601,6 +601,69 @@ impl SyntaxExtension {
         }
     }
 
+    /// Constructs a syntax extension with the given properties
+    /// and other properties converted from attributes.
+    pub fn new(
+        sess: &ParseSess,
+        kind: SyntaxExtensionKind,
+        span: Span,
+        helper_attrs: Vec<Symbol>,
+        edition: Edition,
+        name: Name,
+        attrs: &[ast::Attribute],
+    ) -> SyntaxExtension {
+        let allow_internal_unstable =
+            attr::find_by_name(attrs, sym::allow_internal_unstable).map(|attr| {
+                attr.meta_item_list()
+                    .map(|list| {
+                        list.iter()
+                            .filter_map(|it| {
+                                let name = it.ident().map(|ident| ident.name);
+                                if name.is_none() {
+                                    sess.span_diagnostic.span_err(
+                                        it.span(), "allow internal unstable expects feature names"
+                                    )
+                                }
+                                name
+                            })
+                            .collect::<Vec<Symbol>>()
+                            .into()
+                    })
+                    .unwrap_or_else(|| {
+                        sess.span_diagnostic.span_warn(
+                            attr.span,
+                            "allow_internal_unstable expects list of feature names. In the future \
+                             this will become a hard error. Please use `allow_internal_unstable(\
+                             foo, bar)` to only allow the `foo` and `bar` features",
+                        );
+                        vec![sym::allow_internal_unstable_backcompat_hack].into()
+                    })
+            });
+
+        let mut local_inner_macros = false;
+        if let Some(macro_export) = attr::find_by_name(attrs, sym::macro_export) {
+            if let Some(l) = macro_export.meta_item_list() {
+                local_inner_macros = attr::list_contains_name(&l, sym::local_inner_macros);
+            }
+        }
+
+        let is_builtin = attr::contains_name(attrs, sym::rustc_builtin_macro);
+
+        SyntaxExtension {
+            kind,
+            span,
+            allow_internal_unstable,
+            allow_internal_unsafe: attr::contains_name(attrs, sym::allow_internal_unsafe),
+            local_inner_macros,
+            stability: attr::find_stability(&sess, attrs, span),
+            deprecation: attr::find_deprecation(&sess, attrs, span),
+            helper_attrs,
+            edition,
+            is_builtin,
+            is_derive_copy: is_builtin && name == sym::Copy,
+        }
+    }
+
     pub fn dummy_bang(edition: Edition) -> SyntaxExtension {
         fn expander<'cx>(_: &'cx mut ExtCtxt<'_>, span: Span, _: &[TokenTree])
                          -> Box<dyn MacResult + 'cx> {
diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs
index b1bbd2aaac9..1a26b17dac7 100644
--- a/src/libsyntax/ext/proc_macro_server.rs
+++ b/src/libsyntax/ext/proc_macro_server.rs
@@ -360,12 +360,11 @@ pub(crate) struct Rustc<'a> {
 
 impl<'a> Rustc<'a> {
     pub fn new(cx: &'a ExtCtxt<'_>) -> Self {
-        // No way to determine def location for a proc macro right now, so use call location.
-        let location = cx.current_expansion.id.expn_data().call_site;
+        let expn_data = cx.current_expansion.id.expn_data();
         Rustc {
             sess: cx.parse_sess,
-            def_site: cx.with_def_site_ctxt(location),
-            call_site: cx.with_call_site_ctxt(location),
+            def_site: cx.with_def_site_ctxt(expn_data.def_site),
+            call_site: cx.with_call_site_ctxt(expn_data.call_site),
         }
     }
 
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 37cb8467ff5..46ffa52f7f5 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -1,3 +1,5 @@
+use crate::ast;
+use crate::attr::{self, TransparencyError};
 use crate::edition::Edition;
 use crate::ext::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander};
 use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind};
@@ -15,7 +17,6 @@ use crate::parse::token::{self, NtTT, Token};
 use crate::parse::{Directory, ParseSess};
 use crate::symbol::{kw, sym, Symbol};
 use crate::tokenstream::{DelimSpan, TokenStream, TokenTree};
-use crate::{ast, attr, attr::TransparencyError};
 
 use errors::{DiagnosticBuilder, FatalError};
 use log::debug;
@@ -290,6 +291,7 @@ pub fn compile(
     def: &ast::Item,
     edition: Edition,
 ) -> SyntaxExtension {
+    let diag = &sess.span_diagnostic;
     let lhs_nm = ast::Ident::new(sym::lhs, def.span);
     let rhs_nm = ast::Ident::new(sym::rhs, def.span);
     let tt_spec = ast::Ident::new(sym::tt, def.span);
@@ -423,13 +425,9 @@ pub fn compile(
     let (transparency, transparency_error) = attr::find_transparency(&def.attrs, body.legacy);
     match transparency_error {
         Some(TransparencyError::UnknownTransparency(value, span)) =>
-            sess.span_diagnostic.span_err(
-                span, &format!("unknown macro transparency: `{}`", value)
-            ),
+            diag.span_err(span, &format!("unknown macro transparency: `{}`", value)),
         Some(TransparencyError::MultipleTransparencyAttrs(old_span, new_span)) =>
-            sess.span_diagnostic.span_err(
-                vec![old_span, new_span], "multiple macro transparency attributes"
-            ),
+            diag.span_err(vec![old_span, new_span], "multiple macro transparency attributes"),
         None => {}
     }
 
@@ -437,57 +435,15 @@ pub fn compile(
         name: def.ident, span: def.span, transparency, lhses, rhses, valid
     });
 
-    let allow_internal_unstable =
-        attr::find_by_name(&def.attrs, sym::allow_internal_unstable).map(|attr| {
-            attr.meta_item_list()
-                .map(|list| {
-                    list.iter()
-                        .filter_map(|it| {
-                            let name = it.ident().map(|ident| ident.name);
-                            if name.is_none() {
-                                sess.span_diagnostic.span_err(
-                                    it.span(),
-                                    "allow internal unstable expects feature names",
-                                )
-                            }
-                            name
-                        })
-                        .collect::<Vec<Symbol>>()
-                        .into()
-                })
-                .unwrap_or_else(|| {
-                    sess.span_diagnostic.span_warn(
-                        attr.span,
-                        "allow_internal_unstable expects list of feature names. In the \
-                         future this will become a hard error. Please use `allow_internal_unstable(\
-                         foo, bar)` to only allow the `foo` and `bar` features",
-                    );
-                    vec![sym::allow_internal_unstable_backcompat_hack].into()
-                })
-        });
-
-    let mut local_inner_macros = false;
-    if let Some(macro_export) = attr::find_by_name(&def.attrs, sym::macro_export) {
-        if let Some(l) = macro_export.meta_item_list() {
-            local_inner_macros = attr::list_contains_name(&l, sym::local_inner_macros);
-        }
-    }
-
-    let is_builtin = attr::contains_name(&def.attrs, sym::rustc_builtin_macro);
-
-    SyntaxExtension {
-        kind: SyntaxExtensionKind::LegacyBang(expander),
-        span: def.span,
-        allow_internal_unstable,
-        allow_internal_unsafe: attr::contains_name(&def.attrs, sym::allow_internal_unsafe),
-        local_inner_macros,
-        stability: attr::find_stability(&sess, &def.attrs, def.span),
-        deprecation: attr::find_deprecation(&sess, &def.attrs, def.span),
-        helper_attrs: Vec::new(),
+    SyntaxExtension::new(
+        sess,
+        SyntaxExtensionKind::LegacyBang(expander),
+        def.span,
+        Vec::new(),
         edition,
-        is_builtin,
-        is_derive_copy: is_builtin && def.ident.name == sym::Copy,
-    }
+        def.ident.name,
+        &def.attrs,
+    )
 }
 
 fn check_lhs_nt_follows(
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 25ad2d4404c..2b20cb88796 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -375,10 +375,11 @@ impl<'a> Parser<'a> {
         if let Some(directory) = directory {
             parser.directory = directory;
         } else if !parser.token.span.is_dummy() {
-            if let FileName::Real(mut path) =
-                    sess.source_map().span_to_unmapped_path(parser.token.span) {
-                path.pop();
-                parser.directory.path = Cow::from(path);
+            if let Some(FileName::Real(path)) =
+                    &sess.source_map().lookup_char_pos(parser.token.span.lo()).file.unmapped_path {
+                if let Some(directory_path) = path.parent() {
+                    parser.directory.path = Cow::from(directory_path.to_path_buf());
+                }
             }
         }
 
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index 4add2261c6c..1a617691662 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -7,13 +7,18 @@
 #![feature(decl_macro)]
 #![feature(mem_take)]
 #![feature(nll)]
+#![feature(proc_macro_internals)]
+#![feature(proc_macro_quote)]
 #![feature(rustc_diagnostic_macros)]
 
+extern crate proc_macro;
+
 use crate::deriving::*;
 
 use syntax::ast::Ident;
 use syntax::edition::Edition;
 use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind, MacroExpanderFn};
+use syntax::ext::proc_macro::BangProcMacro;
 use syntax::symbol::sym;
 
 mod error_codes;
@@ -100,4 +105,7 @@ pub fn register_builtin_macros(resolver: &mut dyn syntax::ext::base::Resolver, e
         RustcDecodable: decodable::expand_deriving_rustc_decodable,
         RustcEncodable: encodable::expand_deriving_rustc_encodable,
     }
+
+    let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);
+    register(sym::quote, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })));
 }
diff --git a/src/test/ui/auxiliary/cond_plugin.rs b/src/test/ui/auxiliary/cond_plugin.rs
index 1f97b556a07..2819541bf69 100644
--- a/src/test/ui/auxiliary/cond_plugin.rs
+++ b/src/test/ui/auxiliary/cond_plugin.rs
@@ -3,6 +3,7 @@
 
 #![crate_type = "proc-macro"]
 #![feature(proc_macro_hygiene)]
+#![feature(proc_macro_quote)]
 
 extern crate proc_macro;
 
diff --git a/src/test/ui/auxiliary/proc_macro_def.rs b/src/test/ui/auxiliary/proc_macro_def.rs
index dfc5a42d19c..49cfb5518ba 100644
--- a/src/test/ui/auxiliary/proc_macro_def.rs
+++ b/src/test/ui/auxiliary/proc_macro_def.rs
@@ -3,6 +3,7 @@
 
 #![crate_type = "proc-macro"]
 #![feature(proc_macro_hygiene)]
+#![feature(proc_macro_quote)]
 
 extern crate proc_macro;
 
diff --git a/src/test/ui/macros/auxiliary/proc_macro_sequence.rs b/src/test/ui/macros/auxiliary/proc_macro_sequence.rs
index b50ed7ca92a..c460db36f1a 100644
--- a/src/test/ui/macros/auxiliary/proc_macro_sequence.rs
+++ b/src/test/ui/macros/auxiliary/proc_macro_sequence.rs
@@ -6,7 +6,7 @@
 
 extern crate proc_macro;
 
-use proc_macro::{quote, Span, TokenStream};
+use proc_macro::{quote, Span, TokenStream, TokenTree};
 
 fn assert_same_span(a: Span, b: Span) {
     assert_eq!(a.start(), b.start());
@@ -24,12 +24,22 @@ pub fn make_foo(_: TokenStream) -> TokenStream {
     };
 
     // Check that all spans are equal.
-    let mut span = None;
+    // FIXME: `quote!` gives def-site spans to idents and literals,
+    // but leaves (default) call-site spans on groups and punctuation.
+    let mut span_call = None;
+    let mut span_def = None;
     for tt in result.clone() {
-        match span {
-            None => span = Some(tt.span()),
-            Some(span) => assert_same_span(tt.span(), span),
+        match tt {
+            TokenTree::Ident(..) | TokenTree::Literal(..) => match span_def {
+                None => span_def = Some(tt.span()),
+                Some(span) => assert_same_span(tt.span(), span),
+            }
+            TokenTree::Punct(..) | TokenTree::Group(..) => match span_call {
+                None => span_call = Some(tt.span()),
+                Some(span) => assert_same_span(tt.span(), span),
+            }
         }
+
     }
 
     result
diff --git a/src/test/ui/macros/same-sequence-span.stderr b/src/test/ui/macros/same-sequence-span.stderr
index 250773a1853..0eef4a2a678 100644
--- a/src/test/ui/macros/same-sequence-span.stderr
+++ b/src/test/ui/macros/same-sequence-span.stderr
@@ -17,11 +17,15 @@ LL |                $(= $z:tt)*
 error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fragments
   --> $DIR/same-sequence-span.rs:20:1
    |
-LL | proc_macro_sequence::make_foo!();
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |   proc_macro_sequence::make_foo!();
+   |   ^--------------------------------
+   |   |
+   |  _in this macro invocation
    | |
-   | not allowed after `expr` fragments
-   | in this macro invocation
+LL | |
+LL | |
+LL | | fn main() {}
+...  |
    |
    = note: allowed there are: `=>`, `,` or `;`
 
diff --git a/src/test/ui/proc-macro/attributes-on-definitions.rs b/src/test/ui/proc-macro/attributes-on-definitions.rs
new file mode 100644
index 00000000000..055781d2c60
--- /dev/null
+++ b/src/test/ui/proc-macro/attributes-on-definitions.rs
@@ -0,0 +1,12 @@
+// check-pass
+// aux-build:attributes-on-definitions.rs
+
+#![forbid(unsafe_code)]
+
+extern crate attributes_on_definitions;
+
+attributes_on_definitions::with_attrs!();
+//~^ WARN use of deprecated item
+// No errors about the use of unstable and unsafe code inside the macro.
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/attributes-on-definitions.stderr b/src/test/ui/proc-macro/attributes-on-definitions.stderr
new file mode 100644
index 00000000000..c61e043b229
--- /dev/null
+++ b/src/test/ui/proc-macro/attributes-on-definitions.stderr
@@ -0,0 +1,8 @@
+warning: use of deprecated item 'attributes_on_definitions::with_attrs': test
+  --> $DIR/attributes-on-definitions.rs:8:1
+   |
+LL | attributes_on_definitions::with_attrs!();
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(deprecated)]` on by default
+
diff --git a/src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs b/src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs
new file mode 100644
index 00000000000..93a339840d6
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs
@@ -0,0 +1,23 @@
+// force-host
+// no-prefer-dynamic
+
+#![feature(allow_internal_unsafe)]
+#![feature(allow_internal_unstable)]
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+#[allow_internal_unstable(proc_macro_internals)]
+#[allow_internal_unsafe]
+#[deprecated(since = "1.0.0", note = "test")]
+pub fn with_attrs(_: TokenStream) -> TokenStream {
+    "
+    extern crate proc_macro;
+    use ::proc_macro::bridge;
+
+    fn contains_unsafe() { unsafe {} }
+    ".parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/multispan.stderr b/src/test/ui/proc-macro/multispan.stderr
index a0c1f9cd5c0..e7f705c7feb 100644
--- a/src/test/ui/proc-macro/multispan.stderr
+++ b/src/test/ui/proc-macro/multispan.stderr
@@ -1,8 +1,19 @@
 error: hello to you, too!
-  --> $DIR/multispan.rs:14:5
-   |
-LL |     hello!(hi);
-   |     ^^^^^^^^^^^ in this macro invocation
+  --> $DIR/auxiliary/multispan.rs:31:1
+   |
+LL | / pub fn hello(input: TokenStream) -> TokenStream {
+LL | |     if let Err(diag) = parse(input) {
+LL | |         diag.emit();
+LL | |     }
+LL | |
+LL | |     TokenStream::new()
+LL | | }
+   | |_^
+   | 
+  ::: $DIR/multispan.rs:14:5
+   |
+LL |       hello!(hi);
+   |       ----------- in this macro invocation
    |
 note: found these 'hi's
   --> $DIR/multispan.rs:14:12
@@ -11,10 +22,21 @@ LL |     hello!(hi);
    |            ^^
 
 error: hello to you, too!
-  --> $DIR/multispan.rs:17:5
-   |
-LL |     hello!(hi hi);
-   |     ^^^^^^^^^^^^^^ in this macro invocation
+  --> $DIR/auxiliary/multispan.rs:31:1
+   |
+LL | / pub fn hello(input: TokenStream) -> TokenStream {
+LL | |     if let Err(diag) = parse(input) {
+LL | |         diag.emit();
+LL | |     }
+LL | |
+LL | |     TokenStream::new()
+LL | | }
+   | |_^
+   | 
+  ::: $DIR/multispan.rs:17:5
+   |
+LL |       hello!(hi hi);
+   |       -------------- in this macro invocation
    |
 note: found these 'hi's
   --> $DIR/multispan.rs:17:12
@@ -23,10 +45,21 @@ LL |     hello!(hi hi);
    |            ^^ ^^
 
 error: hello to you, too!
-  --> $DIR/multispan.rs:20:5
-   |
-LL |     hello!(hi hi hi);
-   |     ^^^^^^^^^^^^^^^^^ in this macro invocation
+  --> $DIR/auxiliary/multispan.rs:31:1
+   |
+LL | / pub fn hello(input: TokenStream) -> TokenStream {
+LL | |     if let Err(diag) = parse(input) {
+LL | |         diag.emit();
+LL | |     }
+LL | |
+LL | |     TokenStream::new()
+LL | | }
+   | |_^
+   | 
+  ::: $DIR/multispan.rs:20:5
+   |
+LL |       hello!(hi hi hi);
+   |       ----------------- in this macro invocation
    |
 note: found these 'hi's
   --> $DIR/multispan.rs:20:12
@@ -35,10 +68,21 @@ LL |     hello!(hi hi hi);
    |            ^^ ^^ ^^
 
 error: hello to you, too!
-  --> $DIR/multispan.rs:23:5
-   |
-LL |     hello!(hi hey hi yo hi beep beep hi hi);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation
+  --> $DIR/auxiliary/multispan.rs:31:1
+   |
+LL | / pub fn hello(input: TokenStream) -> TokenStream {
+LL | |     if let Err(diag) = parse(input) {
+LL | |         diag.emit();
+LL | |     }
+LL | |
+LL | |     TokenStream::new()
+LL | | }
+   | |_^
+   | 
+  ::: $DIR/multispan.rs:23:5
+   |
+LL |       hello!(hi hey hi yo hi beep beep hi hi);
+   |       ---------------------------------------- in this macro invocation
    |
 note: found these 'hi's
   --> $DIR/multispan.rs:23:12
@@ -47,10 +91,21 @@ LL |     hello!(hi hey hi yo hi beep beep hi hi);
    |            ^^     ^^    ^^           ^^ ^^
 
 error: hello to you, too!
-  --> $DIR/multispan.rs:24:5
-   |
-LL |     hello!(hi there, hi how are you? hi... hi.);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation
+  --> $DIR/auxiliary/multispan.rs:31:1
+   |
+LL | / pub fn hello(input: TokenStream) -> TokenStream {
+LL | |     if let Err(diag) = parse(input) {
+LL | |         diag.emit();
+LL | |     }
+LL | |
+LL | |     TokenStream::new()
+LL | | }
+   | |_^
+   | 
+  ::: $DIR/multispan.rs:24:5
+   |
+LL |       hello!(hi there, hi how are you? hi... hi.);
+   |       -------------------------------------------- in this macro invocation
    |
 note: found these 'hi's
   --> $DIR/multispan.rs:24:12
@@ -59,10 +114,21 @@ LL |     hello!(hi there, hi how are you? hi... hi.);
    |            ^^        ^^              ^^    ^^
 
 error: hello to you, too!
-  --> $DIR/multispan.rs:25:5
-   |
-LL |     hello!(whoah. hi di hi di ho);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation
+  --> $DIR/auxiliary/multispan.rs:31:1
+   |
+LL | / pub fn hello(input: TokenStream) -> TokenStream {
+LL | |     if let Err(diag) = parse(input) {
+LL | |         diag.emit();
+LL | |     }
+LL | |
+LL | |     TokenStream::new()
+LL | | }
+   | |_^
+   | 
+  ::: $DIR/multispan.rs:25:5
+   |
+LL |       hello!(whoah. hi di hi di ho);
+   |       ------------------------------ in this macro invocation
    |
 note: found these 'hi's
   --> $DIR/multispan.rs:25:19
@@ -71,10 +137,21 @@ LL |     hello!(whoah. hi di hi di ho);
    |                   ^^    ^^
 
 error: hello to you, too!
-  --> $DIR/multispan.rs:26:5
-   |
-LL |     hello!(hi good hi and good bye);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation
+  --> $DIR/auxiliary/multispan.rs:31:1
+   |
+LL | / pub fn hello(input: TokenStream) -> TokenStream {
+LL | |     if let Err(diag) = parse(input) {
+LL | |         diag.emit();
+LL | |     }
+LL | |
+LL | |     TokenStream::new()
+LL | | }
+   | |_^
+   | 
+  ::: $DIR/multispan.rs:26:5
+   |
+LL |       hello!(hi good hi and good bye);
+   |       -------------------------------- in this macro invocation
    |
 note: found these 'hi's
   --> $DIR/multispan.rs:26:12
diff --git a/src/test/ui/proc-macro/three-equals.stderr b/src/test/ui/proc-macro/three-equals.stderr
index 0a6cbe13098..0698b0f4754 100644
--- a/src/test/ui/proc-macro/three-equals.stderr
+++ b/src/test/ui/proc-macro/three-equals.stderr
@@ -1,8 +1,19 @@
 error: found 2 equal signs, need exactly 3
-  --> $DIR/three-equals.rs:15:5
-   |
-LL |     three_equals!(==);
-   |     ^^^^^^^^^^^^^^^^^^ in this macro invocation
+  --> $DIR/auxiliary/three-equals.rs:42:1
+   |
+LL | / pub fn three_equals(input: TokenStream) -> TokenStream {
+LL | |     if let Err(diag) = parse(input) {
+LL | |         diag.emit();
+LL | |         return TokenStream::new();
+...  |
+LL | |     "3".parse().unwrap()
+LL | | }
+   | |_^
+   | 
+  ::: $DIR/three-equals.rs:15:5
+   |
+LL |       three_equals!(==);
+   |       ------------------ in this macro invocation
    |
    = help: input must be: `===`