diff options
Diffstat (limited to 'compiler/rustc_passes/src')
| -rw-r--r-- | compiler/rustc_passes/src/check_attr.rs | 44 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/errors.rs | 9 |
2 files changed, 52 insertions, 1 deletions
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; |
