Skip to content

Commit 2cd2600

Browse files
committed
Unaligned Access Warning Added
Added warning for potential cases of unaligned access when option -mno-unaligned-access has been specified
1 parent e4d1779 commit 2cd2600

File tree

9 files changed

+810
-10
lines changed

9 files changed

+810
-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 its parent %0 has an alignment greater than its parent "
597+
"this may be caused by %0 being packed and 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
@@ -542,6 +542,7 @@ def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">;
542542
def OrderedCompareFunctionPointers : DiagGroup<"ordered-compare-function-pointers">;
543543
def Packed : DiagGroup<"packed">;
544544
def Padded : DiagGroup<"padded">;
545+
def UnalignedAccess : DiagGroup<"unaligned-access">;
545546

546547
def PessimizingMove : DiagGroup<"pessimizing-move">;
547548
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();
2123+
}
2124+
}
21082125
}
21092126

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

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

Lines changed: 7 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,14 @@ 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+
CmdArgs.push_back("-Wunaligned-access");
471+
}
472+
} else if (Triple.isOSOpenBSD()) {
470473
Features.push_back("+strict-align");
474+
CmdArgs.push_back("-Wunaligned-access");
475+
}
471476

472477
if (Args.hasArg(options::OPT_ffixed_x1))
473478
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: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -769,10 +769,11 @@ 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+
CmdArgs.push_back("-Wunaligned-access");
775+
} else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
776+
options::OPT_munaligned_access)) {
776777
if (A->getOption().matches(options::OPT_munaligned_access)) {
777778
// No v6M core supports unaligned memory access (v6M ARM ARM A3.2).
778779
if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
@@ -781,8 +782,10 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
781782
// access either.
782783
else if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline)
783784
D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base";
784-
} else
785+
} else {
785786
Features.push_back("+strict-align");
787+
CmdArgs.push_back("-Wunaligned-access");
788+
}
786789
} else {
787790
// Assume pre-ARMv6 doesn't support unaligned accesses.
788791
//
@@ -801,14 +804,20 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
801804
int VersionNum = getARMSubArchVersionNumber(Triple);
802805
if (Triple.isOSDarwin() || Triple.isOSNetBSD()) {
803806
if (VersionNum < 6 ||
804-
Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
807+
Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) {
805808
Features.push_back("+strict-align");
809+
CmdArgs.push_back("-Wunaligned-access");
810+
}
806811
} else if (Triple.isOSLinux() || Triple.isOSNaCl() ||
807812
Triple.isOSWindows()) {
808-
if (VersionNum < 7)
813+
if (VersionNum < 7) {
809814
Features.push_back("+strict-align");
810-
} else
815+
CmdArgs.push_back("-Wunaligned-access");
816+
}
817+
} else {
811818
Features.push_back("+strict-align");
819+
CmdArgs.push_back("-Wunaligned-access");
820+
}
812821
}
813822

814823
// 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)