]> git.lizzy.rs Git - rust.git/blobdiff - src/libsyntax/codemap.rs
Only retain external static symbols across LTO
[rust.git] / src / libsyntax / codemap.rs
index 9557310f318e9b4f3ef4cc9d04126c408a77eec3..74302e2f6a0fdb7b0f32cfaa9fe5bd0ebadfccdb 100644 (file)
@@ -1052,9 +1052,18 @@ fn span_to_expanded_string_internal(&self, sp:Span, indent: &str) -> String {
     /// the macro callsite that expanded to it.
     pub fn source_callsite(&self, sp: Span) -> Span {
         let mut span = sp;
+        // Special case - if a macro is parsed as an argument to another macro, the source
+        // callsite is the first callsite, which is also source-equivalent to the span.
+        let mut first = true;
         while span.expn_id != NO_EXPANSION && span.expn_id != COMMAND_LINE_EXPN {
             if let Some(callsite) = self.with_expn_info(span.expn_id,
                                                |ei| ei.map(|ei| ei.call_site.clone())) {
+                if first && span.source_equal(&callsite) {
+                    if self.lookup_char_pos(span.lo).file.is_real_file() {
+                        return Span { expn_id: NO_EXPANSION, .. span };
+                    }
+                }
+                first = false;
                 span = callsite;
             }
             else {
@@ -1064,6 +1073,37 @@ pub fn source_callsite(&self, sp: Span) -> Span {
         span
     }
 
+    /// Return the source callee.
+    ///
+    /// Returns None if the supplied span has no expansion trace,
+    /// else returns the NameAndSpan for the macro definition
+    /// corresponding to the source callsite.
+    pub fn source_callee(&self, sp: Span) -> Option<NameAndSpan> {
+        let mut span = sp;
+        // Special case - if a macro is parsed as an argument to another macro, the source
+        // callsite is source-equivalent to the span, and the source callee is the first callee.
+        let mut first = true;
+        while let Some(callsite) = self.with_expn_info(span.expn_id,
+                                            |ei| ei.map(|ei| ei.call_site.clone())) {
+            if first && span.source_equal(&callsite) {
+                if self.lookup_char_pos(span.lo).file.is_real_file() {
+                    return self.with_expn_info(span.expn_id,
+                                               |ei| ei.map(|ei| ei.callee.clone()));
+                }
+            }
+            first = false;
+            if let Some(_) = self.with_expn_info(callsite.expn_id,
+                                                 |ei| ei.map(|ei| ei.call_site.clone())) {
+                span = callsite;
+            }
+            else {
+                return self.with_expn_info(span.expn_id,
+                                           |ei| ei.map(|ei| ei.callee.clone()));
+            }
+        }
+        None
+    }
+
     pub fn span_to_filename(&self, sp: Span) -> FileName {
         self.lookup_char_pos(sp.lo).file.name.to_string()
     }