about summary refs log tree commit diff
diff options
context:
space:
mode:
authorasquared31415 <34665709+asquared31415@users.noreply.github.com>2024-10-12 05:37:56 +0000
committer许杰友 Jieyou Xu (Joe) <39484203+jieyouxu@users.noreply.github.com>2024-10-28 13:17:37 +0800
commit6fc7ce43d2f2cd2fef1b75c9c59f13f312e0d9d8 (patch)
tree16c43b928958e16e940c5efd3682962f5d0848dd
parentdf4ca44d3fbc9301ee17f30f4d474e6ae4b05252 (diff)
downloadrust-6fc7ce43d2f2cd2fef1b75c9c59f13f312e0d9d8.tar.gz
rust-6fc7ce43d2f2cd2fef1b75c9c59f13f312e0d9d8.zip
Error on alignments greater than `isize::MAX`
Co-authored-by: Jieyou Xu <jieyouxu@outlook.com>
-rw-r--r--compiler/rustc_passes/messages.ftl4
-rw-r--r--compiler/rustc_passes/src/check_attr.rs44
-rw-r--r--compiler/rustc_passes/src/errors.rs9
-rw-r--r--tests/ui/repr/repr_align_greater_usize.msp430.stderr19
-rw-r--r--tests/ui/repr/repr_align_greater_usize.rs25
5 files changed, 100 insertions, 1 deletions
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index f8ef423a9b0..e5e70ba2033 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -622,6 +622,10 @@ passes_remove_fields =
 passes_repr_align_function =
     `repr(align)` attributes on functions are unstable
 
+passes_repr_align_greater_than_target_max =
+    alignment must not be greater than `isize::MAX` bytes
+    .note = `isize::MAX` is {$size} for the current target
+
 passes_repr_conflicting =
     conflicting representation hints
 
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index acde27c6728..8c4592cbb36 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -34,6 +34,7 @@ use rustc_session::lint::builtin::{
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::{Symbol, kw, sym};
 use rustc_span::{BytePos, DUMMY_SP, Span};
+use rustc_target::abi::Size;
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
@@ -1785,7 +1786,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         | Target::Union
                         | Target::Enum
                         | Target::Fn
-                        | Target::Method(_) => continue,
+                        | Target::Method(_) => {}
                         _ => {
                             self.dcx().emit_err(
                                 errors::AttrApplication::StructEnumFunctionMethodUnion {
@@ -1795,6 +1796,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                             );
                         }
                     }
+
+                    self.check_align_value(hint);
                 }
                 sym::packed => {
                     if target != Target::Struct && target != Target::Union {
@@ -1892,6 +1895,45 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
+    fn check_align_value(&self, item: &MetaItemInner) {
+        match item.singleton_lit_list() {
+            Some((
+                _,
+                MetaItemLit {
+                    kind: ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed), ..
+                },
+            )) => {
+                let val = literal.get() as u64;
+                if val > 2_u64.pow(29) {
+                    // for values greater than 2^29, a different error will be emitted, make sure that happens
+                    self.dcx().span_delayed_bug(
+                        item.span(),
+                        "alignment greater than 2^29 should be errored on elsewhere",
+                    );
+                } else {
+                    // only do this check when <= 2^29 to prevent duplicate errors:
+                    // alignment greater than 2^29 not supported
+                    // alignment is too large for the current target
+
+                    let max =
+                        Size::from_bits(self.tcx.sess.target.pointer_width).signed_int_max() as u64;
+                    if val > max {
+                        self.dcx().emit_err(errors::InvalidReprAlignForTarget {
+                            span: item.span(),
+                            size: max,
+                        });
+                    }
+                }
+            }
+
+            // if the attribute is malformed, singleton_lit_list may not be of the expected type or may be None
+            // but an error will have already been emitted, so this code should just skip such attributes
+            Some((_, _)) | None => {
+                self.dcx().span_delayed_bug(item.span(), "malformed repr(align(N))");
+            }
+        }
+    }
+
     fn check_used(&self, attrs: &[Attribute], target: Target, target_span: Span) {
         let mut used_linker_span = None;
         let mut used_compiler_span = None;
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index b5f1eac1cba..8bd767c1243 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -567,6 +567,15 @@ pub(crate) struct ReprConflicting {
     pub hint_spans: Vec<Span>,
 }
 
+#[derive(Diagnostic)]
+#[diag(passes_repr_align_greater_than_target_max, code = E0589)]
+#[note]
+pub(crate) struct InvalidReprAlignForTarget {
+    #[primary_span]
+    pub span: Span,
+    pub size: u64,
+}
+
 #[derive(LintDiagnostic)]
 #[diag(passes_repr_conflicting, code = E0566)]
 pub(crate) struct ReprConflictingLint;
diff --git a/tests/ui/repr/repr_align_greater_usize.msp430.stderr b/tests/ui/repr/repr_align_greater_usize.msp430.stderr
new file mode 100644
index 00000000000..7c85249c009
--- /dev/null
+++ b/tests/ui/repr/repr_align_greater_usize.msp430.stderr
@@ -0,0 +1,19 @@
+error[E0589]: alignment must not be greater than `isize::MAX` bytes
+  --> $DIR/repr_align_greater_usize.rs:21:8
+   |
+LL | #[repr(align(32768))]
+   |        ^^^^^^^^^^^^
+   |
+   = note: `isize::MAX` is 32767 for the current target
+
+error[E0589]: alignment must not be greater than `isize::MAX` bytes
+  --> $DIR/repr_align_greater_usize.rs:24:8
+   |
+LL | #[repr(align(65536))]
+   |        ^^^^^^^^^^^^
+   |
+   = note: `isize::MAX` is 32767 for the current target
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0589`.
diff --git a/tests/ui/repr/repr_align_greater_usize.rs b/tests/ui/repr/repr_align_greater_usize.rs
new file mode 100644
index 00000000000..b47320b6d9b
--- /dev/null
+++ b/tests/ui/repr/repr_align_greater_usize.rs
@@ -0,0 +1,25 @@
+//@ revisions: msp430 aarch32
+//@[msp430] needs-llvm-components: msp430
+//@[msp430] compile-flags: --target=msp430-none-elf
+//@[aarch32] build-pass
+//@[aarch32] needs-llvm-components: arm
+//@[aarch32] compile-flags: --target=thumbv7m-none-eabi
+
+// We should fail to compute alignment for types aligned higher than usize::MAX.
+// We can't handle alignments that require all 32 bits, so this only affects 16-bit.
+
+#![feature(lang_items, no_core)]
+#![no_core]
+#![crate_type = "lib"]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[repr(align(16384))]
+struct Kitten;
+
+#[repr(align(32768))] //[msp430]~ ERROR alignment must not be greater than `isize::MAX`
+struct Cat;
+
+#[repr(align(65536))] //[msp430]~ ERROR alignment must not be greater than `isize::MAX`
+struct BigCat;