Skip to content

error on alignments greater than isize::MAX #131633

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
44 changes: 43 additions & 1 deletion compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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 {
Expand All @@ -1795,6 +1796,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
);
}
}

self.check_align_value(hint);
}
sym::packed => {
if target != Target::Struct && target != Target::Union {
Expand Down Expand Up @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
19 changes: 19 additions & 0 deletions tests/ui/repr/repr_align_greater_usize.msp430.stderr
Original file line number Diff line number Diff line change
@@ -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`.
25 changes: 25 additions & 0 deletions tests/ui/repr/repr_align_greater_usize.rs
Original file line number Diff line number Diff line change
@@ -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;
Loading