Skip to content

Commit fa6bf1f

Browse files
committed
Update patch to elaborate on comments, add more tests, and restrict to floats greater than 4-bytes in size.
1 parent 1013f4f commit fa6bf1f

File tree

3 files changed

+247
-48
lines changed

3 files changed

+247
-48
lines changed

compiler/rustc_lint/src/types.rs

Lines changed: 60 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
use std::iter;
22
use std::ops::ControlFlow;
33

4-
use rustc_abi::{
5-
BackendRepr, ExternAbi, FieldIdx, TagEncoding, VariantIdx, Variants, WrappingRange,
6-
};
4+
use rustc_abi::{BackendRepr, ExternAbi, TagEncoding, VariantIdx, Variants, WrappingRange};
75
use rustc_data_structures::fx::FxHashSet;
86
use rustc_errors::DiagMessage;
97
use rustc_hir::{Expr, ExprKind, LangItem};
@@ -26,8 +24,8 @@ use crate::lints::{
2624
AmbiguousWidePointerComparisonsAddrSuggestion, AtomicOrderingFence, AtomicOrderingLoad,
2725
AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons,
2826
InvalidNanComparisonsSuggestion, UnpredictableFunctionPointerComparisons,
29-
UnpredictableFunctionPointerComparisonsSuggestion, UnusedComparisons,
30-
UsesPowerAlignment, VariantSizeDifferencesDiag,
27+
UnpredictableFunctionPointerComparisonsSuggestion, UnusedComparisons, UsesPowerAlignment,
28+
VariantSizeDifferencesDiag,
3129
};
3230
use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent};
3331

@@ -731,13 +729,23 @@ declare_lint! {
731729
}
732730

733731
declare_lint! {
734-
/// The AIX target follows the power alignment rule. This rule specifies
735-
/// that structs with either a:
736-
/// - floating-point data type as its first member, or
737-
/// - first member being an aggregate whose recursively first member is a
738-
/// floating-point data type
739-
/// must have its natural alignment. This is currently unimplemented within
740-
/// the compiler, so a warning is produced in these situations.
732+
/// In it's platform C ABI, the AIX target follows the power alignment rule
733+
/// for structs. This rule applies the natural alignment of the first struct
734+
/// field if it is a floating-point type that is greater than 4-bytes, or
735+
/// is an aggregate whose recursively "first" field is a floating-point
736+
/// type greater than 4-bytes.
737+
/// The alignment for subsequent fields of the associated structs use an
738+
/// alignment value where the floating-point type is aligned on a 4-byte
739+
/// boundary.
740+
/// In this case, "natural alignment" (detailed in
741+
/// https://www.ibm.com/docs/en/xl-c-and-cpp-aix/16.1?topic=data-using-alignment-modes#alignment)
742+
/// refers to the floating-point type being aligned to a multiple of its
743+
/// size (for example, the size of a double is 8-bytes, and so is 8-byte
744+
/// aligned).
745+
///
746+
/// The power alignment rule for structs need for C compatibility is
747+
/// currently unimplemented within repr(C) in the compiler, so a warning is
748+
/// produced in these situations.
741749
///
742750
/// ### Example
743751
///
@@ -749,11 +757,16 @@ declare_lint! {
749757
/// }
750758
/// ```
751759
///
752-
/// A warning should be produced for the above struct as the first member
753-
/// of the struct is an f64.
760+
/// The power alignment rule specifies that the above struct has the
761+
/// following alignment:
762+
/// - offset_of!(Floats, a) == 0
763+
/// - offset_of!(Floats, b) == 8
764+
/// - offset_of!(Floats, c) == 12
765+
/// However, rust currently aligns `c` at offset_of!(Floats, c) == 16.
766+
/// Thus, a warning should be produced for the above struct in this case.
754767
USES_POWER_ALIGNMENT,
755768
Warn,
756-
"floating point types within structs do not follow the power alignment rule under repr(C)"
769+
"Structs do not follow the power alignment rule under repr(C)"
757770
}
758771

759772
declare_lint_pass!(ImproperCTypesDefinitions => [IMPROPER_CTYPES_DEFINITIONS, USES_POWER_ALIGNMENT]);
@@ -1575,18 +1588,25 @@ impl ImproperCTypesDefinitions {
15751588
ty: Ty<'tcx>,
15761589
) -> bool {
15771590
// Structs (under repr(C)) follow the power alignment rule if:
1578-
// - the first argument of the struct is a floating-point type, or
1579-
// - the first argument of the struct is an aggregate whose
1580-
// recursively first member is a floating-point type
1581-
if ty.is_floating_point() {
1591+
// - the first field of the struct is a floating-point type that
1592+
// is greater than 4-bytes, or
1593+
// - the first field of the struct is an aggregate whose
1594+
// recursively first field is a floating-point type greater than
1595+
// 4 bytes.
1596+
if ty.is_floating_point() && ty.primitive_size(cx.tcx).bytes() > 4 {
15821597
return true;
15831598
} else if let Adt(adt_def, _) = ty.kind()
15841599
&& adt_def.is_struct()
15851600
{
1586-
let first_variant = adt_def.variant(VariantIdx::ZERO);
1587-
if let Some(first) = first_variant.fields.get(FieldIdx::ZERO) {
1588-
let field_ty = cx.tcx.type_of(first.did).instantiate_identity();
1589-
return self.check_arg_for_power_alignment(cx, field_ty);
1601+
let struct_variant = adt_def.variant(VariantIdx::ZERO);
1602+
// Within a nested struct, all fields are examined to correctly
1603+
// report if any fields after the nested struct within the
1604+
// original struct are misaligned.
1605+
for struct_field in &struct_variant.fields {
1606+
let field_ty = cx.tcx.type_of(struct_field.did).instantiate_identity();
1607+
if self.check_arg_for_power_alignment(cx, field_ty) {
1608+
return true;
1609+
}
15901610
}
15911611
}
15921612
return false;
@@ -1599,17 +1619,26 @@ impl ImproperCTypesDefinitions {
15991619
) {
16001620
let adt_def = cx.tcx.adt_def(item.owner_id.to_def_id());
16011621
if adt_def.repr().c()
1602-
&& cx.tcx.sess.target.os == "aix"
1622+
&& !adt_def.repr().packed() && cx.tcx.sess.target.os == "aix"
16031623
&& !adt_def.all_fields().next().is_none()
16041624
{
16051625
let struct_variant_data = item.expect_struct().0;
1606-
// Analyze only the first member of the struct to see if it
1607-
// follows the power alignment rule.
1608-
let first_field_def = struct_variant_data.fields()[0];
1609-
let def_id = first_field_def.def_id;
1610-
let ty = cx.tcx.type_of(def_id).instantiate_identity();
1611-
if self.check_arg_for_power_alignment(cx, ty) {
1612-
cx.emit_span_lint(USES_POWER_ALIGNMENT, first_field_def.span, UsesPowerAlignment);
1626+
for (index, ..) in struct_variant_data.fields().iter().enumerate() {
1627+
// Struct fields (after the first field) are checked for the
1628+
// power alignment rule, as fields after the first are likely
1629+
// to be the fields that are misaligned.
1630+
if index != 0 {
1631+
let first_field_def = struct_variant_data.fields()[index];
1632+
let def_id = first_field_def.def_id;
1633+
let ty = cx.tcx.type_of(def_id).instantiate_identity();
1634+
if self.check_arg_for_power_alignment(cx, ty) {
1635+
cx.emit_span_lint(
1636+
USES_POWER_ALIGNMENT,
1637+
first_field_def.span,
1638+
UsesPowerAlignment,
1639+
);
1640+
}
1641+
}
16131642
}
16141643
}
16151644
}
Lines changed: 87 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
2-
--> $DIR/reprc-power-alignment.rs:10:5
2+
--> $DIR/reprc-power-alignment.rs:12:5
33
|
4-
LL | a: f64,
4+
LL | c: f64,
55
| ^^^^^^
66
|
77
note: the lint level is defined here
@@ -11,22 +11,100 @@ LL | #![warn(uses_power_alignment)]
1111
| ^^^^^^^^^^^^^^^^^^^^
1212

1313
warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
14-
--> $DIR/reprc-power-alignment.rs:23:5
14+
--> $DIR/reprc-power-alignment.rs:39:5
1515
|
16-
LL | a: f32,
16+
LL | b: f64,
1717
| ^^^^^^
1818

1919
warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
20-
--> $DIR/reprc-power-alignment.rs:37:5
20+
--> $DIR/reprc-power-alignment.rs:46:5
2121
|
22-
LL | x: Floats,
22+
LL | y: f64,
23+
| ^^^^^^
24+
25+
warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
26+
--> $DIR/reprc-power-alignment.rs:52:5
27+
|
28+
LL | y: Floats,
2329
| ^^^^^^^^^
2430

2531
warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
26-
--> $DIR/reprc-power-alignment.rs:49:5
32+
--> $DIR/reprc-power-alignment.rs:58:5
33+
|
34+
LL | y: FloatAgg2,
35+
| ^^^^^^^^^^^^
36+
37+
warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
38+
--> $DIR/reprc-power-alignment.rs:59:5
39+
|
40+
LL | z: FloatAgg2,
41+
| ^^^^^^^^^^^^
42+
43+
warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
44+
--> $DIR/reprc-power-alignment.rs:65:5
2745
|
28-
LL | x: FloatAgg1,
46+
LL | y: FloatAgg2,
2947
| ^^^^^^^^^^^^
3048

31-
warning: 4 warnings emitted
49+
warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
50+
--> $DIR/reprc-power-alignment.rs:71:5
51+
|
52+
LL | y: FloatAgg2,
53+
| ^^^^^^^^^^^^
54+
55+
warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
56+
--> $DIR/reprc-power-alignment.rs:72:5
57+
|
58+
LL | z: FloatAgg3,
59+
| ^^^^^^^^^^^^
60+
61+
warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
62+
--> $DIR/reprc-power-alignment.rs:78:5
63+
|
64+
LL | y: Floats,
65+
| ^^^^^^^^^
66+
67+
warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
68+
--> $DIR/reprc-power-alignment.rs:85:5
69+
|
70+
LL | y: Floats,
71+
| ^^^^^^^^^
72+
73+
warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
74+
--> $DIR/reprc-power-alignment.rs:98:3
75+
|
76+
LL | d: f64,
77+
| ^^^^^^
78+
79+
warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
80+
--> $DIR/reprc-power-alignment.rs:103:3
81+
|
82+
LL | b: B,
83+
| ^^^^
84+
85+
warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
86+
--> $DIR/reprc-power-alignment.rs:112:3
87+
|
88+
LL | d: D,
89+
| ^^^^
90+
91+
warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
92+
--> $DIR/reprc-power-alignment.rs:117:3
93+
|
94+
LL | b: f64,
95+
| ^^^^^^
96+
97+
warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
98+
--> $DIR/reprc-power-alignment.rs:123:5
99+
|
100+
LL | c: f64,
101+
| ^^^^^^
102+
103+
warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
104+
--> $DIR/reprc-power-alignment.rs:125:5
105+
|
106+
LL | e: f64,
107+
| ^^^^^^
108+
109+
warning: 17 warnings emitted
32110

0 commit comments

Comments
 (0)