about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_attr/src/builtin.rs104
-rw-r--r--src/test/ui/attributes/nonterminal-expansion.rs4
-rw-r--r--src/test/ui/attributes/nonterminal-expansion.stderr14
-rw-r--r--src/test/ui/repr/issue-83921-ice.rs34
-rw-r--r--src/test/ui/repr/issue-83921-ice.stderr46
-rw-r--r--src/test/ui/repr/issue-83921-pretty.normal.stderr9
-rw-r--r--src/test/ui/repr/issue-83921-pretty.pretty.stdout19
-rw-r--r--src/test/ui/repr/issue-83921-pretty.rs14
8 files changed, 234 insertions, 10 deletions
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 20971ebb957..b7b053cd5dd 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -870,6 +870,23 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
                         sym::simd => Some(ReprSimd),
                         sym::transparent => Some(ReprTransparent),
                         sym::no_niche => Some(ReprNoNiche),
+                        sym::align => {
+                            let mut err = struct_span_err!(
+                                diagnostic,
+                                item.span(),
+                                E0589,
+                                "invalid `repr(align)` attribute: `align` needs an argument"
+                            );
+                            err.span_suggestion(
+                                item.span(),
+                                "supply an argument here",
+                                "align(...)".to_string(),
+                                Applicability::HasPlaceholders,
+                            );
+                            err.emit();
+                            recognised = true;
+                            None
+                        }
                         name => int_type_of_word(name).map(ReprInt),
                     };
 
@@ -891,33 +908,47 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
                             Ok(literal) => acc.push(ReprPacked(literal)),
                             Err(message) => literal_error = Some(message),
                         };
+                    } else if matches!(name, sym::C | sym::simd | sym::transparent | sym::no_niche)
+                        || int_type_of_word(name).is_some()
+                    {
+                        recognised = true;
+                        struct_span_err!(
+                                diagnostic,
+                                item.span(),
+                                E0552,
+                                "invalid representation hint: `{}` does not take a parenthesized argument list",
+                                name.to_ident_string(),
+                            ).emit();
                     }
                     if let Some(literal_error) = literal_error {
                         struct_span_err!(
                             diagnostic,
                             item.span(),
                             E0589,
-                            "invalid `repr(align)` attribute: {}",
+                            "invalid `repr({})` attribute: {}",
+                            name.to_ident_string(),
                             literal_error
                         )
                         .emit();
                     }
                 } else if let Some(meta_item) = item.meta_item() {
-                    if meta_item.has_name(sym::align) {
-                        if let MetaItemKind::NameValue(ref value) = meta_item.kind {
+                    if let MetaItemKind::NameValue(ref value) = meta_item.kind {
+                        if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) {
+                            let name = meta_item.name_or_empty().to_ident_string();
                             recognised = true;
                             let mut err = struct_span_err!(
                                 diagnostic,
                                 item.span(),
                                 E0693,
-                                "incorrect `repr(align)` attribute format"
+                                "incorrect `repr({})` attribute format",
+                                name,
                             );
                             match value.kind {
                                 ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
                                     err.span_suggestion(
                                         item.span(),
                                         "use parentheses instead",
-                                        format!("align({})", int),
+                                        format!("{}({})", name, int),
                                         Applicability::MachineApplicable,
                                     );
                                 }
@@ -925,19 +956,76 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
                                     err.span_suggestion(
                                         item.span(),
                                         "use parentheses instead",
-                                        format!("align({})", s),
+                                        format!("{}({})", name, s),
                                         Applicability::MachineApplicable,
                                     );
                                 }
                                 _ => {}
                             }
                             err.emit();
+                        } else {
+                            if matches!(
+                                meta_item.name_or_empty(),
+                                sym::C | sym::simd | sym::transparent | sym::no_niche
+                            ) || int_type_of_word(meta_item.name_or_empty()).is_some()
+                            {
+                                recognised = true;
+                                struct_span_err!(
+                                    diagnostic,
+                                    meta_item.span,
+                                    E0552,
+                                    "invalid representation hint: `{}` does not take a value",
+                                    meta_item.name_or_empty().to_ident_string(),
+                                )
+                                .emit();
+                            }
+                        }
+                    } else if let MetaItemKind::List(_) = meta_item.kind {
+                        if meta_item.has_name(sym::align) {
+                            recognised = true;
+                            struct_span_err!(
+                                diagnostic,
+                                meta_item.span,
+                                E0693,
+                                "incorrect `repr(align)` attribute format: \
+                                 `align` takes exactly one argument in parentheses"
+                            )
+                            .emit();
+                        } else if meta_item.has_name(sym::packed) {
+                            recognised = true;
+                            struct_span_err!(
+                                diagnostic,
+                                meta_item.span,
+                                E0552,
+                                "incorrect `repr(packed)` attribute format: \
+                                 `packed` takes exactly one parenthesized argument, \
+                                 or no parentheses at all"
+                            )
+                            .emit();
+                        } else if matches!(
+                            meta_item.name_or_empty(),
+                            sym::C | sym::simd | sym::transparent | sym::no_niche
+                        ) || int_type_of_word(meta_item.name_or_empty()).is_some()
+                        {
+                            recognised = true;
+                            struct_span_err!(
+                                diagnostic,
+                                meta_item.span,
+                                E0552,
+                                "invalid representation hint: `{}` does not take a parenthesized argument list",
+                                meta_item.name_or_empty().to_ident_string(),
+                            ).emit();
                         }
                     }
                 }
                 if !recognised {
-                    // Not a word we recognize
-                    diagnostic.delay_span_bug(item.span(), "unrecognized representation hint");
+                    // Not a word we recognize. This will be caught and reported by
+                    // the `check_mod_attrs` pass, but this pass doesn't always run
+                    // (e.g. if we only pretty-print the source), so we have to gate
+                    // the `delay_span_bug` call as follows:
+                    if sess.opts.pretty.map_or(true, |pp| pp.needs_analysis()) {
+                        diagnostic.delay_span_bug(item.span(), "unrecognized representation hint");
+                    }
                 }
             }
         }
diff --git a/src/test/ui/attributes/nonterminal-expansion.rs b/src/test/ui/attributes/nonterminal-expansion.rs
index d663431d683..97bf225f0cc 100644
--- a/src/test/ui/attributes/nonterminal-expansion.rs
+++ b/src/test/ui/attributes/nonterminal-expansion.rs
@@ -2,7 +2,9 @@
 
 macro_rules! pass_nonterminal {
     ($n:expr) => {
-        #[repr(align($n))] //~ ERROR expected unsuffixed literal or identifier, found `n!()`
+        #[repr(align($n))]
+        //~^ ERROR expected unsuffixed literal or identifier, found `n!()`
+        //~| ERROR incorrect `repr(align)` attribute format
         struct S;
     };
 }
diff --git a/src/test/ui/attributes/nonterminal-expansion.stderr b/src/test/ui/attributes/nonterminal-expansion.stderr
index 4124f8cea8e..9bf36f3c58e 100644
--- a/src/test/ui/attributes/nonterminal-expansion.stderr
+++ b/src/test/ui/attributes/nonterminal-expansion.stderr
@@ -9,5 +9,17 @@ LL | pass_nonterminal!(n!());
    |
    = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to previous error
+error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
+  --> $DIR/nonterminal-expansion.rs:5:16
+   |
+LL |         #[repr(align($n))]
+   |                ^^^^^^^^^
+...
+LL | pass_nonterminal!(n!());
+   | ------------------------ in this macro invocation
+   |
+   = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0693`.
diff --git a/src/test/ui/repr/issue-83921-ice.rs b/src/test/ui/repr/issue-83921-ice.rs
new file mode 100644
index 00000000000..70583eb9bd3
--- /dev/null
+++ b/src/test/ui/repr/issue-83921-ice.rs
@@ -0,0 +1,34 @@
+// Regression test for various ICEs inspired by
+// https://github.com/rust-lang/rust/issues/83921#issuecomment-814640734
+
+// compile-flags: -Zdeduplicate-diagnostics=yes
+
+#[repr(packed())]
+//~^ ERROR: incorrect `repr(packed)` attribute format
+struct S1;
+
+#[repr(align)]
+//~^ ERROR: invalid `repr(align)` attribute
+struct S2;
+
+#[repr(align(2, 4))]
+//~^ ERROR: incorrect `repr(align)` attribute format
+struct S3;
+
+#[repr(align())]
+//~^ ERROR: incorrect `repr(align)` attribute format
+struct S4;
+
+#[repr(i8())]
+//~^ ERROR: invalid representation hint
+enum E1 { A, B }
+
+#[repr(u32(42))]
+//~^ ERROR: invalid representation hint
+enum E2 { A, B }
+
+#[repr(i64 = 2)]
+//~^ ERROR: invalid representation hint
+enum E3 { A, B }
+
+fn main() {}
diff --git a/src/test/ui/repr/issue-83921-ice.stderr b/src/test/ui/repr/issue-83921-ice.stderr
new file mode 100644
index 00000000000..32c450410ea
--- /dev/null
+++ b/src/test/ui/repr/issue-83921-ice.stderr
@@ -0,0 +1,46 @@
+error[E0552]: incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
+  --> $DIR/issue-83921-ice.rs:6:8
+   |
+LL | #[repr(packed())]
+   |        ^^^^^^^^
+
+error[E0589]: invalid `repr(align)` attribute: `align` needs an argument
+  --> $DIR/issue-83921-ice.rs:10:8
+   |
+LL | #[repr(align)]
+   |        ^^^^^ help: supply an argument here: `align(...)`
+
+error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
+  --> $DIR/issue-83921-ice.rs:14:8
+   |
+LL | #[repr(align(2, 4))]
+   |        ^^^^^^^^^^^
+
+error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
+  --> $DIR/issue-83921-ice.rs:18:8
+   |
+LL | #[repr(align())]
+   |        ^^^^^^^
+
+error[E0552]: invalid representation hint: `i8` does not take a parenthesized argument list
+  --> $DIR/issue-83921-ice.rs:22:8
+   |
+LL | #[repr(i8())]
+   |        ^^^^
+
+error[E0552]: invalid representation hint: `u32` does not take a parenthesized argument list
+  --> $DIR/issue-83921-ice.rs:26:8
+   |
+LL | #[repr(u32(42))]
+   |        ^^^^^^^
+
+error[E0552]: invalid representation hint: `i64` does not take a value
+  --> $DIR/issue-83921-ice.rs:30:8
+   |
+LL | #[repr(i64 = 2)]
+   |        ^^^^^^^
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0552, E0589, E0693.
+For more information about an error, try `rustc --explain E0552`.
diff --git a/src/test/ui/repr/issue-83921-pretty.normal.stderr b/src/test/ui/repr/issue-83921-pretty.normal.stderr
new file mode 100644
index 00000000000..6b7e831ed2f
--- /dev/null
+++ b/src/test/ui/repr/issue-83921-pretty.normal.stderr
@@ -0,0 +1,9 @@
+error[E0565]: meta item in `repr` must be an identifier
+  --> $DIR/issue-83921-pretty.rs:10:8
+   |
+LL | #[repr("C")]
+   |        ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0565`.
diff --git a/src/test/ui/repr/issue-83921-pretty.pretty.stdout b/src/test/ui/repr/issue-83921-pretty.pretty.stdout
new file mode 100644
index 00000000000..dad3641f0f5
--- /dev/null
+++ b/src/test/ui/repr/issue-83921-pretty.pretty.stdout
@@ -0,0 +1,19 @@
+#![feature(prelude_import)]
+#![no_std]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+// Regression test for #83921. A `delay_span_bug()` call was issued, but the
+// error was never reported because the pass responsible for detecting and
+// reporting the error does not run in certain modes of pretty-printing.
+
+// Make sure the error is reported if we do not just pretty-print:
+// revisions: pretty normal
+// [pretty]compile-flags: -Zunpretty=everybody_loops
+// [pretty]check-pass
+#[repr("C")]
+struct A {
+}
+
+fn main() { loop { } }
diff --git a/src/test/ui/repr/issue-83921-pretty.rs b/src/test/ui/repr/issue-83921-pretty.rs
new file mode 100644
index 00000000000..d5d36470f11
--- /dev/null
+++ b/src/test/ui/repr/issue-83921-pretty.rs
@@ -0,0 +1,14 @@
+// Regression test for #83921. A `delay_span_bug()` call was issued, but the
+// error was never reported because the pass responsible for detecting and
+// reporting the error does not run in certain modes of pretty-printing.
+
+// Make sure the error is reported if we do not just pretty-print:
+// revisions: pretty normal
+// [pretty]compile-flags: -Zunpretty=everybody_loops
+// [pretty]check-pass
+
+#[repr("C")]
+//[normal]~^ ERROR: meta item in `repr` must be an identifier [E0565]
+struct A {}
+
+fn main() {}