about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-10-21 11:37:14 +0000
committerbors <bors@rust-lang.org>2014-10-21 11:37:14 +0000
commitb69cd73b7bd448dbfde4cf074b73a4b8384cad38 (patch)
treecd67057c778592286a506b7d0adea3c61b52f60a
parente8cc3f26ec998181a883d79c9a668fe55695e681 (diff)
parentdd55c8003cb9c4b065e8a8e54bbc0496ac0a3dfd (diff)
downloadrust-b69cd73b7bd448dbfde4cf074b73a4b8384cad38.tar.gz
rust-b69cd73b7bd448dbfde4cf074b73a4b8384cad38.zip
auto merge of #17508 : vberger/rust/stability_lint_for_nested_macros, r=pnkfelix
Finishes the job of #17286.

Now the stability lint will successfully detect patterns such as:
```
first_macro!(second_macro!(deprecated_function()));
```
```
macro_rules! foo (
    ($e: expr) => (bar!($e))
)
foo!(deprected_function());
```
and
```
println!("{}", deprecated_function());
```
even with more levels of nesting, such as
```
println!("{}", foo!(bar!(deprecated_function())));
```
-rw-r--r--src/librustc/lint/builtin.rs38
-rw-r--r--src/test/compile-fail/lint-stability.rs1
2 files changed, 23 insertions, 16 deletions
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 2205dc42d47..69575e51e0f 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -43,7 +43,7 @@ use syntax::abi;
 use syntax::ast_map;
 use syntax::attr::AttrMetaMethods;
 use syntax::attr;
-use syntax::codemap::{Span, NO_EXPANSION};
+use syntax::codemap::Span;
 use syntax::parse::token;
 use syntax::{ast, ast_util, visit};
 use syntax::ptr::P;
@@ -1473,27 +1473,33 @@ impl LintPass for Stability {
     }
 
     fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
-        // skip if `e` is not from macro arguments
-        let skip = cx.tcx.sess.codemap().with_expn_info(e.span.expn_id, |expninfo| {
+        // first, check if the given expression was generated by a macro or not
+        // we need to go back the expn_info tree to check only the arguments
+        // of the initial macro call, not the nested ones.
+        let mut expnid = e.span.expn_id;
+        let mut is_internal = false;
+        while cx.tcx.sess.codemap().with_expn_info(expnid, |expninfo| {
             match expninfo {
                 Some(ref info) => {
-                    if info.call_site.expn_id != NO_EXPANSION ||
-                       !( e.span.lo > info.call_site.lo && e.span.hi < info.call_site.hi ) {
-                        // This code is not from the arguments,
-                        // or this macro call was generated by an other macro
-                        // We can't handle it.
-                        true
-                    } else if info.callee.span.is_none() {
-                        // We don't want to mess with compiler builtins.
-                        true
+                    // save the parent expn_id for next loop iteration
+                    expnid = info.call_site.expn_id;
+                    if info.callee.span.is_none() {
+                        // it's a compiler built-in, we *really* don't want to mess with it
+                        // so we skip it, unless it was called by a regular macro, in which case
+                        // we will handle the caller macro next turn
+                        is_internal = true;
+                        true // continue looping
                     } else {
-                        false
+                        // was this expression from the current macro arguments ?
+                        is_internal = !( e.span.lo > info.call_site.lo &&
+                                         e.span.hi < info.call_site.hi );
+                        true // continue looping
                     }
                 },
-                _ => { false }
+                _ => false // stop looping
             }
-        });
-        if skip { return; }
+        }) { /* empty while loop body */ }
+        if is_internal { return; }
 
         let mut span = e.span;
 
diff --git a/src/test/compile-fail/lint-stability.rs b/src/test/compile-fail/lint-stability.rs
index 6a36e270740..fdb0d801164 100644
--- a/src/test/compile-fail/lint-stability.rs
+++ b/src/test/compile-fail/lint-stability.rs
@@ -116,6 +116,7 @@ mod cross_crate {
         // on macros themselves are not yet linted.
         macro_test!();
         macro_test_arg!(deprecated_text()); //~ ERROR use of deprecated item: text
+        macro_test_arg!(macro_test_arg!(deprecated_text())); //~ ERROR use of deprecated item: text
         macro_test_arg_nested!(deprecated_text);
     }