diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -590,4 +590,9 @@ InGroup, DefaultIgnore; def warn_unnecessary_packed : Warning< "packed attribute is unnecessary for %0">, InGroup, DefaultIgnore; + +// -Wunaligned-access +def warn_unaligned_access : Warning< + "field %1 within %0 is less aligned than %2 and is usually due to %0 being " + "packed, which can lead to unaligned accesses">, InGroup, DefaultIgnore; } diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -543,6 +543,7 @@ def OrderedCompareFunctionPointers : DiagGroup<"ordered-compare-function-pointers">; def Packed : DiagGroup<"packed">; def Padded : DiagGroup<"padded">; +def UnalignedAccess : DiagGroup<"unaligned-access">; def PessimizingMove : DiagGroup<"pessimizing-move">; def ReturnStdMove : DiagGroup<"return-std-move">; diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2021,6 +2021,7 @@ CharUnits UnpackedFieldAlign = !DefaultsToAIXPowerAlignment ? FieldAlign : PreferredAlign; CharUnits UnpackedFieldOffset = FieldOffset; + CharUnits OriginalFieldAlign = UnpackedFieldAlign; if (FieldPacked) { FieldAlign = CharUnits::One(); @@ -2105,6 +2106,22 @@ // Remember max struct/class ABI-specified alignment. UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign); UpdateAlignment(FieldAlign, UnpackedFieldAlign, PreferredAlign); + + // For checking the alignment of inner fields against + // the alignment of its parent record. + if (const RecordDecl *RD = D->getParent()) { + // Check if packed attribute or pragma pack is present. + if (RD->hasAttr() || !MaxFieldAlignment.isZero()) + if (FieldAlign < OriginalFieldAlign) + if (D->getType()->isRecordType()) { + // If the offset is a multiple of the alignment of + // the type, raise the warning. + // TODO: Takes no account the alignment of the outer struct + if (FieldOffset % OriginalFieldAlign != 0) + Diag(D->getLocation(), diag::warn_unaligned_access) + << Context.getTypeDeclType(RD) << D->getName() << D->getType(); + } + } } void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) { diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.h b/clang/lib/Driver/ToolChains/Arch/AArch64.h --- a/clang/lib/Driver/ToolChains/Arch/AArch64.h +++ b/clang/lib/Driver/ToolChains/Arch/AArch64.h @@ -22,6 +22,7 @@ void getAArch64TargetFeatures(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs, std::vector &Features, bool ForAS); diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp --- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp +++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp @@ -221,6 +221,7 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, const llvm::Triple &Triple, const ArgList &Args, + llvm::opt::ArgStringList &CmdArgs, std::vector &Features, bool ForAS) { Arg *A; @@ -464,10 +465,16 @@ if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) { - if (A->getOption().matches(options::OPT_mno_unaligned_access)) + if (A->getOption().matches(options::OPT_mno_unaligned_access)) { Features.push_back("+strict-align"); - } else if (Triple.isOSOpenBSD()) + if (!ForAS) + CmdArgs.push_back("-Wunaligned-access"); + } + } else if (Triple.isOSOpenBSD()) { Features.push_back("+strict-align"); + if (!ForAS) + CmdArgs.push_back("-Wunaligned-access"); + } if (Args.hasArg(options::OPT_ffixed_x1)) Features.push_back("+reserve-x1"); diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp --- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp +++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp @@ -769,10 +769,12 @@ } // Kernel code has more strict alignment requirements. - if (KernelOrKext) + if (KernelOrKext) { Features.push_back("+strict-align"); - else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, - options::OPT_munaligned_access)) { + if (!ForAS) + CmdArgs.push_back("-Wunaligned-access"); + } else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, + options::OPT_munaligned_access)) { if (A->getOption().matches(options::OPT_munaligned_access)) { // No v6M core supports unaligned memory access (v6M ARM ARM A3.2). if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) @@ -781,8 +783,11 @@ // access either. else if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline) D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base"; - } else + } else { Features.push_back("+strict-align"); + if (!ForAS) + CmdArgs.push_back("-Wunaligned-access"); + } } else { // Assume pre-ARMv6 doesn't support unaligned accesses. // @@ -801,14 +806,23 @@ int VersionNum = getARMSubArchVersionNumber(Triple); if (Triple.isOSDarwin() || Triple.isOSNetBSD()) { if (VersionNum < 6 || - Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) + Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) { Features.push_back("+strict-align"); + if (!ForAS) + CmdArgs.push_back("-Wunaligned-access"); + } } else if (Triple.isOSLinux() || Triple.isOSNaCl() || Triple.isOSWindows()) { - if (VersionNum < 7) + if (VersionNum < 7) { Features.push_back("+strict-align"); - } else + if (!ForAS) + CmdArgs.push_back("-Wunaligned-access"); + } + } else { Features.push_back("+strict-align"); + if (!ForAS) + CmdArgs.push_back("-Wunaligned-access"); + } } // llvm does not support reserving registers in general. There is support diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -346,7 +346,8 @@ case llvm::Triple::aarch64: case llvm::Triple::aarch64_32: case llvm::Triple::aarch64_be: - aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, ForAS); + aarch64::getAArch64TargetFeatures(D, Triple, Args, CmdArgs, Features, + ForAS); break; case llvm::Triple::x86: case llvm::Triple::x86_64: diff --git a/clang/test/Sema/test-wunaligned-access.c b/clang/test/Sema/test-wunaligned-access.c new file mode 100644 --- /dev/null +++ b/clang/test/Sema/test-wunaligned-access.c @@ -0,0 +1,516 @@ +// RUN: %clang_cc1 %s -triple=armv7-none-none-eabi -verify -Wunaligned-access -S -emit-llvm +// REQUIRES: arm-registered-target +// +// This test suite tests the warning triggered by the -Wunaligned-access option. +// The warning occurs when a struct or other type of record contains a field +// that is itself a record. The outer record must be a packed structure, while +// while the inner record must be unpacked. This is the fundamental condition +// for the warning to be triggered. Some of these tests may have three layers. +// +// The command line option -fsyntax-only is not used as Clang needs to be +// forced to layout the structs used in this test. +// The triple in the command line above is used for the assumptions about +// size and alignment of types. + +// Set 1 +struct T1 { + char a; + int b; +}; + +struct __attribute__((packed)) U1 { + char a; + struct T1 b; // expected-warning {{field b within 'struct U1' is less aligned than 'struct T1' and is usually due to 'struct U1' being packed, which can lead to unaligned accesses}} + int c; +}; + +struct __attribute__((packed)) U2 { + char a; + struct T1 b __attribute__((aligned(2))); // expected-warning {{field b within 'struct U2' is less aligned than 'struct T1' and is usually due to 'struct U2' being packed, which can lead to unaligned accesses}} + int c; +}; + +struct __attribute__((packed)) U3 { + char a; + struct T1 b __attribute__((aligned(4))); + int c; +}; + +struct __attribute__((aligned(2))) U4 { + char a; + struct T1 b; + int c; +}; + +struct U5 { + char a; + struct T1 b; + int c; +}; + +struct U6 { + char a; + int b; + struct T1 c __attribute__((aligned(2))); +}; + +struct __attribute__((packed)) U7 { + short a; + short b; + char c; + struct T1 d; // expected-warning {{field d within 'struct U7' is less aligned than 'struct T1' and is usually due to 'struct U7' being packed, which can lead to unaligned accesses}} +}; + +struct U8 { + short a; + short b; + char c; + struct T1 d; +}; + +struct __attribute__((packed)) U9 { + short a; + short b; + char c; + struct T1 d __attribute__((aligned(4))); +}; + +struct __attribute__((packed)) U10 { + short a; + short b; + char c; + struct T1 d __attribute__((aligned(2))); // expected-warning {{field d within 'struct U10' is less aligned than 'struct T1' and is usually due to 'struct U10' being packed, which can lead to unaligned accesses}} +}; + +struct __attribute__((aligned(2))) U11 { + short a; + short b; + char c; + struct T1 d; +}; + +// Set 2 +#pragma pack(push, 1) + +struct U12 { + char a; + struct T1 b; // expected-warning {{field b within 'struct U12' is less aligned than 'struct T1' and is usually due to 'struct U12' being packed, which can lead to unaligned accesses}} + int c; +}; + +struct __attribute__((packed)) U13 { + char a; + struct T1 b; // expected-warning {{field b within 'struct U13' is less aligned than 'struct T1' and is usually due to 'struct U13' being packed, which can lead to unaligned accesses}} + int c; +}; + +struct __attribute__((packed)) U14 { + char a; + struct T1 b __attribute__((aligned(4))); // expected-warning {{field b within 'struct U14' is less aligned than 'struct T1' and is usually due to 'struct U14' being packed, which can lead to unaligned accesses}} + int c; +}; + +struct __attribute__((aligned(2))) U15 { + char a; + struct T1 b; // expected-warning {{field b within 'struct U15' is less aligned than 'struct T1' and is usually due to 'struct U15' being packed, which can lead to unaligned accesses}} + int c; +}; + +struct U16 { + char a; + char b; + short c; + struct T1 d; +}; + +struct U17 { + char a; + char b; + short c; + struct T1 d __attribute__((aligned(4))); +}; + +struct __attribute__((packed)) U18 { + char a; + short b; + struct T1 c __attribute__((aligned(4))); // expected-warning {{field c within 'struct U18' is less aligned than 'struct T1' and is usually due to 'struct U18' being packed, which can lead to unaligned accesses}} +}; + +struct __attribute__((aligned(4))) U19 { + char a; + struct T1 b; // expected-warning {{field b within 'struct U19' is less aligned than 'struct T1' and is usually due to 'struct U19' being packed, which can lead to unaligned accesses}} + int c; +}; + +struct __attribute__((aligned(4))) U20 { + char a[4]; + struct T1 b; + int c; +}; + +struct U21 { + char a; + short c; + struct T1 d; // expected-warning {{field d within 'struct U21' is less aligned than 'struct T1' and is usually due to 'struct U21' being packed, which can lead to unaligned accesses}} +}; + +struct U22 { + char a; + short c; + struct T1 d __attribute__((aligned(4))); // expected-warning {{field d within 'struct U22' is less aligned than 'struct T1' and is usually due to 'struct U22' being packed, which can lead to unaligned accesses}} +}; + +#pragma pack(pop) + +// Set 3 +#pragma pack(push, 2) + +struct __attribute__((packed)) U23 { + char a; + struct T1 b; // expected-warning {{field b within 'struct U23' is less aligned than 'struct T1' and is usually due to 'struct U23' being packed, which can lead to unaligned accesses}} + int c; +}; + +struct U24 { + char a; + struct T1 b; // expected-warning {{field b within 'struct U24' is less aligned than 'struct T1' and is usually due to 'struct U24' being packed, which can lead to unaligned accesses}} + int c; +}; + +struct U25 { + char a; + char b; + short c; + struct T1 d; +}; + +struct U26 { + char a; + char b; + short c; + struct T1 d; +}; + +#pragma pack(pop) + +// Set 4 + +struct __attribute__((packed)) T2 { + char a; + struct T1 b; // expected-warning {{field b within 'struct T2' is less aligned than 'struct T1' and is usually due to 'struct T2' being packed, which can lead to unaligned accesses}} +}; + +struct T3 { + char a; + struct T1 b; +}; + +struct __attribute__((packed)) U27 { + char a; + struct T2 b; + int c; +}; + +struct U28 { + char a; + char _p[2]; + struct T2 b; + int c; +}; + +struct U29 { + char a; + struct T3 b; + int c; +}; + +struct __attribute__((packed)) U30 { + char a; + struct T3 b; // expected-warning {{field b within 'struct U30' is less aligned than 'struct T3' and is usually due to 'struct U30' being packed, which can lead to unaligned accesses}} + int c; +}; + +struct __attribute__((packed)) U31 { + char a; + struct T2 b __attribute__((aligned(4))); +}; + +struct __attribute__((packed)) U32 { + char a; + char b; + char c; + char d; + struct T3 e; +}; + +struct __attribute__((packed)) U33 { + char a; + char b; + char c; + char d; + struct T2 e __attribute__((aligned(4))); +}; + +struct __attribute__((packed)) U34 { + char a; + struct T1 b __attribute__((packed)); // expected-warning {{field b within 'struct U34' is less aligned than 'struct T1' and is usually due to 'struct U34' being packed, which can lead to unaligned accesses}} + struct T2 c; +}; + +struct __attribute__((packed)) U35 { + char a; + struct T4 { + char b; + struct T1 c; + } d; // expected-warning {{field d within 'struct U35' is less aligned than 'struct T4' and is usually due to 'struct U35' being packed, which can lead to unaligned accesses}} +}; + +// Set 5 + +#pragma pack(push, 1) +struct T5 { + char a; + struct T1 b; // expected-warning {{field b within 'struct T5' is less aligned than 'struct T1' and is usually due to 'struct T5' being packed, which can lead to unaligned accesses}} +}; +#pragma pack(pop) + +#pragma pack(push, 1) +struct U36 { + char a; + struct T5 b; + int c; +}; + +struct U37 { + char a; + struct T3 b; // expected-warning {{field b within 'struct U37' is less aligned than 'struct T3' and is usually due to 'struct U37' being packed, which can lead to unaligned accesses}} + int c; +}; +#pragma pack(pop) +struct U38 { + char a; + struct T5 b __attribute__((aligned(4))); + int c; +}; + +#pragma pack(push, 1) + +#pragma pack(push, 4) +struct U39 { + char a; + struct T5 b; + int c; +}; +#pragma pack(pop) + +#pragma pack(pop) + +// Set 6 + +struct __attribute__((packed)) A1 { + char a; + struct T1 b; // expected-warning {{field b within 'struct A1' is less aligned than 'struct T1' and is usually due to 'struct A1' being packed, which can lead to unaligned accesses}} +}; + +struct A2 { + char a; + struct T1 b; +}; + +struct __attribute__((packed)) A3 { + char a; + struct T1 b __attribute__((aligned(4))); +}; + +#pragma pack(push, 1) +struct A4 { + char a; + struct T1 b; // expected-warning {{field b within 'struct A4' is less aligned than 'struct T1' and is usually due to 'struct A4' being packed, which can lead to unaligned accesses}} +}; + +struct A5 { + char a; + struct T1 b __attribute__((aligned(4))); // expected-warning {{field b within 'struct A5' is less aligned than 'struct T1' and is usually due to 'struct A5' being packed, which can lead to unaligned accesses}} +}; +#pragma pack(pop) + +struct __attribute__((packed)) A6 { + struct T1 a; +}; + +struct A7 { + char a; + struct T1 b __attribute__((packed)); +}; + +struct A8 { + char a; + char b; + short c; + struct T1 d; +}; + +struct A9 { + char a; + struct T2 b; +}; + +struct A10 { + char a; + struct T2 b __attribute__((aligned(4))); +}; + +struct __attribute__((packed)) A11 { + char a; + struct T2 b; +}; + +struct __attribute__((packed)) U40 { + char a; + struct A1 b; + int c; +}; + +struct __attribute__((packed)) U41 { + char a; + struct A3 b; // expected-warning {{field b within 'struct U41' is less aligned than 'struct A3' and is usually due to 'struct U41' being packed, which can lead to unaligned accesses}} + int c; +}; + +#pragma pack(push, 1) +struct U42 { + char a; + struct A1 b; + int c; +}; +#pragma pack(pop) + +struct __attribute__((packed)) U43 { + char a; + struct A9 b; + int c; +}; + +struct __attribute__((packed)) U44 { + char a; + struct A10 b; // expected-warning {{field b within 'struct U44' is less aligned than 'struct A10' and is usually due to 'struct U44' being packed, which can lead to unaligned accesses}} + int c; +}; + +#pragma pack(push, 1) + +struct U45 { + char a; + struct A10 b; // expected-warning {{field b within 'struct U45' is less aligned than 'struct A10' and is usually due to 'struct U45' being packed, which can lead to unaligned accesses}} + int c; +}; + +#pragma pack(pop) + +struct __attribute__((packed)) U46 { + char a; + struct A2 b; // expected-warning {{field b within 'struct U46' is less aligned than 'struct A2' and is usually due to 'struct U46' being packed, which can lead to unaligned accesses}} + int c; +}; + +struct __attribute__((packed)) U47 { + char a; + struct A8 b; // expected-warning {{field b within 'struct U47' is less aligned than 'struct A8' and is usually due to 'struct U47' being packed, which can lead to unaligned accesses}} + int c; +}; + +#pragma pack(push, 1) +struct U48 { + char a; + struct A8 b; // expected-warning {{field b within 'struct U48' is less aligned than 'struct A8' and is usually due to 'struct U48' being packed, which can lead to unaligned accesses}} + int c; +}; +#pragma pack(pop) + +struct U49 { + char a; + struct A11 b; + int c; +}; + +struct U50 { + char a; + struct A1 b; + int c; +}; + +struct U51 { + char a; + struct A5 b; + int c; +}; + +struct __attribute__((packed)) U52 { + char a; + struct A6 b; +}; + +struct U53 { + char a; + struct A4 b; +}; + +struct U54 { + char b; + struct A7 c; +}; + +struct U1 s1; +struct U2 s2; +struct U3 s3; +struct U4 s4; +struct U5 s5; +struct U6 s6; +struct U7 s7; +struct U8 s8; +struct U9 s9; +struct U10 s10; +struct U11 s11; +struct U12 s12; +struct U13 s13; +struct U14 s14; +struct U15 s15; +struct U16 s16; +struct U17 s17; +struct U18 s18; +struct U19 s19; +struct U20 s20; +struct U21 s21; +struct U22 s22; +struct U23 s23; +struct U24 s24; +struct U25 s25; +struct U26 s26; +struct U27 s27; +struct U28 s28; +struct U29 s29; +struct U30 s30; +struct U31 s31; +struct U32 s32; +struct U33 s33; +struct U34 s34; +struct U35 s35; +struct U36 s36; +struct U37 s37; +struct U38 s38; +struct U39 s39; +struct U40 s40; +struct U41 s41; +struct U42 s42; +struct U43 s43; +struct U44 s44; +struct U45 s45; +struct U46 s46; +struct U47 s47; +struct U48 s48; +struct U49 s49; +struct U50 s50; +struct U51 s51; +struct U52 s52; +struct U53 s53; +struct U54 s54; diff --git a/clang/test/Sema/test-wunaligned-access.cpp b/clang/test/Sema/test-wunaligned-access.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Sema/test-wunaligned-access.cpp @@ -0,0 +1,274 @@ +// RUN: %clang_cc1 %s -triple=armv7-none-none-eabi -verify -Wunaligned-access -S -emit-llvm -o %t +// REQUIRES: arm-registered-target +// +// This test suite tests the warning triggered by the -Wunaligned-access option. +// The warning occurs when a struct or other type of record contains a field +// that is itself a record. The outer record must be a packed structure, while +// while the inner record must be unpacked. This is the fundamental condition +// for the warning to be triggered. Some of these tests may have three layers. +// +// The command line option -fsyntax-only is not used as Clang needs to be +// forced to layout the structs used in this test. +// The triple in the command line above is used for the assumptions about +// size and alignment of types. + +// Packed-Unpacked Tests (No Pragma) + +struct T1 { + char a; + int b; +}; + +struct __attribute__((packed)) U1 { + char a; + T1 b; // expected-warning {{field b within 'U1' is less aligned than 'T1' and is usually due to 'U1' being packed, which can lead to unaligned accesses}} + int c; +}; + +struct __attribute__((packed)) U2 { + char a; + T1 b __attribute__((aligned(4))); + int c; +}; + +struct __attribute__((packed)) U3 { + char a; + char b; + short c; + T1 d; +}; + +struct __attribute__((packed)) U4 { + T1 a; + int b; +}; + +struct __attribute__((aligned(4), packed)) U5 { + char a; + T1 b; // expected-warning {{field b within 'U5' is less aligned than 'T1' and is usually due to 'U5' being packed, which can lead to unaligned accesses}} + int c; +}; + +struct __attribute__((aligned(4), packed)) U6 { + char a; + char b; + short c; + T1 d; +}; + +// Packed-Unpacked Tests with Pragma + +#pragma pack(push, 1) + +struct __attribute__((packed)) U7 { + char a; + T1 b; // expected-warning {{field b within 'U7' is less aligned than 'T1' and is usually due to 'U7' being packed, which can lead to unaligned accesses}} + int c; +}; + +struct __attribute__((packed)) U8 { + char a; + T1 b __attribute__((aligned(4))); // expected-warning {{field b within 'U8' is less aligned than 'T1' and is usually due to 'U8' being packed, which can lead to unaligned accesses}} + int c; +}; + +struct __attribute__((aligned(4))) U9 { + char a; + T1 b; // expected-warning {{field b within 'U9' is less aligned than 'T1' and is usually due to 'U9' being packed, which can lead to unaligned accesses}} + int c; +}; + +struct U10 { + char a; + T1 b; // expected-warning {{field b within 'U10' is less aligned than 'T1' and is usually due to 'U10' being packed, which can lead to unaligned accesses}} + int c; +}; + +#pragma pack(pop) + +// Packed-Packed Tests + +struct __attribute__((packed)) T2 { + char a; + int b; +}; + +struct __attribute__((packed)) U11 { + char a; + T2 b; + int c; +}; + +#pragma pack(push, 1) +struct U12 { + char a; + T2 b; + int c; +}; +#pragma pack(pop) + +// Unpacked-Packed Tests + +struct U13 { + char a; + T2 b; + int c; +}; + +struct U14 { + char a; + T2 b __attribute__((aligned(4))); + int c; +}; + +// Unpacked-Unpacked Test + +struct T3 { + char a; + int b; +}; + +struct U15 { + char a; + T3 b; + int c; +}; + +// Packed-Packed-Unpacked Test (No pragma) + +struct __attribute__((packed)) A1 { + char a; + T1 b; // expected-warning {{field b within 'A1' is less aligned than 'T1' and is usually due to 'A1' being packed, which can lead to unaligned accesses}} +}; + +struct __attribute__((packed)) U16 { + char a; + A1 b; + int c; +}; + +struct __attribute__((packed)) A2 { + char a; + T1 b __attribute__((aligned(4))); +}; + +struct __attribute__((packed)) U17 { + char a; + A2 b; // expected-warning {{field b within 'U17' is less aligned than 'A2' and is usually due to 'U17' being packed, which can lead to unaligned accesses}} + int c; +}; + +// Packed-Unpacked-Packed tests + +struct A3 { + char a; + T2 b; +}; + +struct __attribute__((packed)) U18 { + char a; + A3 b; + int c; +}; + +struct A4 { + char a; + T2 b; + int c; +}; + +#pragma pack(push, 1) +struct U19 { + char a; + A4 b; // expected-warning {{field b within 'U19' is less aligned than 'A4' and is usually due to 'U19' being packed, which can lead to unaligned accesses}} + int c; +}; +#pragma pack(pop) + +// Packed-Unpacked-Unpacked tests + +struct A5 { + char a; + T1 b; +}; + +struct __attribute__((packed)) U20 { + char a; + A5 b; // expected-warning {{field b within 'U20' is less aligned than 'A5' and is usually due to 'U20' being packed, which can lead to unaligned accesses}} + int c; +}; + +struct A6 { + char a; + T1 b; +}; + +#pragma pack(push, 1) +struct U21 { + char a; + A6 b; // expected-warning {{field b within 'U21' is less aligned than 'A6' and is usually due to 'U21' being packed, which can lead to unaligned accesses}} + int c; +}; +#pragma pack(pop) + +// Unpacked-Packed-Packed test + +struct __attribute__((packed)) A7 { + char a; + T2 b; +}; + +struct U22 { + char a; + A7 b; + int c; +}; + +// Unpacked-Packed-Unpacked tests + +struct __attribute__((packed)) A8 { + char a; + T1 b; // expected-warning {{field b within 'A8' is less aligned than 'T1' and is usually due to 'A8' being packed, which can lead to unaligned accesses}} +}; + +struct U23 { + char a; + A8 b; + int c; +}; + +struct __attribute__((packed)) A9 { + char a; + T1 b __attribute__((aligned(4))); +}; + +struct U24 { + char a; + A9 b; + int c; +}; + +struct U1 s1; +struct U2 s2; +struct U3 s3; +struct U4 s4; +struct U5 s5; +struct U6 s6; +struct U7 s7; +struct U8 s8; +struct U9 s9; +struct U10 s10; +struct U11 s11; +struct U12 s12; +struct U13 s13; +struct U14 s14; +struct U15 s15; +struct U16 s16; +struct U17 s17; +struct U18 s18; +struct U19 s19; +struct U20 s20; +struct U21 s21; +struct U22 s22; +struct U23 s23; +struct U24 s24; \ No newline at end of file