diff --git a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp index 96f0d9bb3c3ded..40472ccfe7e66f 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp @@ -193,6 +193,11 @@ class PaddingChecker : public Checker> { CharUnits PaddingSum; CharUnits Offset = ASTContext.toCharUnitsFromBits(RL.getFieldOffset(0)); for (const FieldDecl *FD : RD->fields()) { + // Skip field that is a subobject of zero size, marked with + // [[no_unique_address]] or an empty bitfield, because its address can be + // set the same as the other fields addresses. + if (FD->isZeroSize(ASTContext)) + continue; // This checker only cares about the padded size of the // field, and not the data size. If the field is a record // with tail padding, then we won't put that number in our @@ -249,7 +254,7 @@ class PaddingChecker : public Checker> { RetVal.Field = FD; auto &Ctx = FD->getASTContext(); auto Info = Ctx.getTypeInfoInChars(FD->getType()); - RetVal.Size = Info.Width; + RetVal.Size = FD->isZeroSize(Ctx) ? CharUnits::Zero() : Info.Width; RetVal.Align = Info.Align; assert(llvm::isPowerOf2_64(RetVal.Align.getQuantity())); if (auto Max = FD->getMaxAlignment()) diff --git a/clang/test/Analysis/padding_no_unique_address.cpp b/clang/test/Analysis/padding_no_unique_address.cpp new file mode 100644 index 00000000000000..4f26922c9450da --- /dev/null +++ b/clang/test/Analysis/padding_no_unique_address.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-linux-gnu -analyzer-checker=optin.performance -analyzer-config optin.performance.Padding:AllowedPad=2 -verify %s + +class Empty {}; // no-warning + +// expected-warning@+1{{Excessive padding in 'struct NoUniqueAddressWarn1' (6 padding}} +struct NoUniqueAddressWarn1 { + char c1; + [[no_unique_address]] Empty empty; + int i; + char c2; +}; + +// expected-warning@+1{{Excessive padding in 'struct NoUniqueAddressWarn2' (6 padding}} +struct NoUniqueAddressWarn2 { + char c1; + [[no_unique_address]] Empty e1, e2; + int i; + char c2; +}; + +struct NoUniqueAddressNoWarn1 { + char c1; + [[no_unique_address]] Empty empty; + char c2; +}; + +struct NoUniqueAddressNoWarn2 { + char c1; + [[no_unique_address]] Empty e1, e2; +};