Skip to content

Commit 35737df

Browse files
committed
[Clang][AArch64][ARM] Unaligned Access Warning Added
Added warning for potential cases of unaligned access when option -mno-unaligned-access has been specified Differential Revision: https://reviews.llvm.org/D116221
1 parent 60147c6 commit 35737df

File tree

9 files changed

+846
-10
lines changed

9 files changed

+846
-10
lines changed

clang/include/clang/Basic/DiagnosticASTKinds.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,4 +590,9 @@ def warn_padded_struct_size : Warning<
590590
InGroup<Padded>, DefaultIgnore;
591591
def warn_unnecessary_packed : Warning<
592592
"packed attribute is unnecessary for %0">, InGroup<Packed>, DefaultIgnore;
593+
594+
// -Wunaligned-access
595+
def warn_unaligned_access : Warning<
596+
"field %1 within %0 is less aligned than %2 and is usually due to %0 being "
597+
"packed, which can lead to unaligned accesses">, InGroup<UnalignedAccess>, DefaultIgnore;
593598
}

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,7 @@ def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">;
543543
def OrderedCompareFunctionPointers : DiagGroup<"ordered-compare-function-pointers">;
544544
def Packed : DiagGroup<"packed">;
545545
def Padded : DiagGroup<"padded">;
546+
def UnalignedAccess : DiagGroup<"unaligned-access">;
546547

547548
def PessimizingMove : DiagGroup<"pessimizing-move">;
548549
def ReturnStdMove : DiagGroup<"return-std-move">;

clang/lib/AST/RecordLayoutBuilder.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2021,6 +2021,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
20212021
CharUnits UnpackedFieldAlign =
20222022
!DefaultsToAIXPowerAlignment ? FieldAlign : PreferredAlign;
20232023
CharUnits UnpackedFieldOffset = FieldOffset;
2024+
CharUnits OriginalFieldAlign = UnpackedFieldAlign;
20242025

20252026
if (FieldPacked) {
20262027
FieldAlign = CharUnits::One();
@@ -2105,6 +2106,22 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
21052106
// Remember max struct/class ABI-specified alignment.
21062107
UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign);
21072108
UpdateAlignment(FieldAlign, UnpackedFieldAlign, PreferredAlign);
2109+
2110+
// For checking the alignment of inner fields against
2111+
// the alignment of its parent record.
2112+
if (const RecordDecl *RD = D->getParent()) {
2113+
// Check if packed attribute or pragma pack is present.
2114+
if (RD->hasAttr<PackedAttr>() || !MaxFieldAlignment.isZero())
2115+
if (FieldAlign < OriginalFieldAlign)
2116+
if (D->getType()->isRecordType()) {
2117+
// If the offset is a multiple of the alignment of
2118+
// the type, raise the warning.
2119+
// TODO: Takes no account the alignment of the outer struct
2120+
if (FieldOffset % OriginalFieldAlign != 0)
2121+
Diag(D->getLocation(), diag::warn_unaligned_access)
2122+
<< Context.getTypeDeclType(RD) << D->getName() << D->getType();
2123+
}
2124+
}
21082125
}
21092126

21102127
void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) {

clang/lib/Driver/ToolChains/Arch/AArch64.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
221221
void aarch64::getAArch64TargetFeatures(const Driver &D,
222222
const llvm::Triple &Triple,
223223
const ArgList &Args,
224+
llvm::opt::ArgStringList &CmdArgs,
224225
std::vector<StringRef> &Features,
225226
bool ForAS) {
226227
Arg *A;
@@ -464,10 +465,16 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
464465

465466
if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
466467
options::OPT_munaligned_access)) {
467-
if (A->getOption().matches(options::OPT_mno_unaligned_access))
468+
if (A->getOption().matches(options::OPT_mno_unaligned_access)) {
468469
Features.push_back("+strict-align");
469-
} else if (Triple.isOSOpenBSD())
470+
if (!ForAS)
471+
CmdArgs.push_back("-Wunaligned-access");
472+
}
473+
} else if (Triple.isOSOpenBSD()) {
470474
Features.push_back("+strict-align");
475+
if (!ForAS)
476+
CmdArgs.push_back("-Wunaligned-access");
477+
}
471478

472479
if (Args.hasArg(options::OPT_ffixed_x1))
473480
Features.push_back("+reserve-x1");

clang/lib/Driver/ToolChains/Arch/AArch64.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ namespace aarch64 {
2222

2323
void getAArch64TargetFeatures(const Driver &D, const llvm::Triple &Triple,
2424
const llvm::opt::ArgList &Args,
25+
llvm::opt::ArgStringList &CmdArgs,
2526
std::vector<llvm::StringRef> &Features,
2627
bool ForAS);
2728

clang/lib/Driver/ToolChains/Arch/ARM.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -769,10 +769,12 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
769769
}
770770

771771
// Kernel code has more strict alignment requirements.
772-
if (KernelOrKext)
772+
if (KernelOrKext) {
773773
Features.push_back("+strict-align");
774-
else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
775-
options::OPT_munaligned_access)) {
774+
if (!ForAS)
775+
CmdArgs.push_back("-Wunaligned-access");
776+
} else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
777+
options::OPT_munaligned_access)) {
776778
if (A->getOption().matches(options::OPT_munaligned_access)) {
777779
// No v6M core supports unaligned memory access (v6M ARM ARM A3.2).
778780
if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
@@ -781,8 +783,11 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
781783
// access either.
782784
else if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline)
783785
D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base";
784-
} else
786+
} else {
785787
Features.push_back("+strict-align");
788+
if (!ForAS)
789+
CmdArgs.push_back("-Wunaligned-access");
790+
}
786791
} else {
787792
// Assume pre-ARMv6 doesn't support unaligned accesses.
788793
//
@@ -801,14 +806,23 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
801806
int VersionNum = getARMSubArchVersionNumber(Triple);
802807
if (Triple.isOSDarwin() || Triple.isOSNetBSD()) {
803808
if (VersionNum < 6 ||
804-
Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
809+
Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) {
805810
Features.push_back("+strict-align");
811+
if (!ForAS)
812+
CmdArgs.push_back("-Wunaligned-access");
813+
}
806814
} else if (Triple.isOSLinux() || Triple.isOSNaCl() ||
807815
Triple.isOSWindows()) {
808-
if (VersionNum < 7)
816+
if (VersionNum < 7) {
809817
Features.push_back("+strict-align");
810-
} else
818+
if (!ForAS)
819+
CmdArgs.push_back("-Wunaligned-access");
820+
}
821+
} else {
811822
Features.push_back("+strict-align");
823+
if (!ForAS)
824+
CmdArgs.push_back("-Wunaligned-access");
825+
}
812826
}
813827

814828
// llvm does not support reserving registers in general. There is support

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,8 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
346346
case llvm::Triple::aarch64:
347347
case llvm::Triple::aarch64_32:
348348
case llvm::Triple::aarch64_be:
349-
aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, ForAS);
349+
aarch64::getAArch64TargetFeatures(D, Triple, Args, CmdArgs, Features,
350+
ForAS);
350351
break;
351352
case llvm::Triple::x86:
352353
case llvm::Triple::x86_64:

0 commit comments

Comments
 (0)