From c558b1fca7350f4f4d8e7387fb2ead951284a5cf Mon Sep 17 00:00:00 2001 From: Georgy Komarov Date: Fri, 28 May 2021 11:58:50 +0300 Subject: [PATCH] [analyzer] Fix calculating offset for fields with an empty type Fix offset calculation routines in padding checker to avoid assertion errors described in bugzilla issue 50426. The fields that are subojbects of zero size, marked with [[no_unique_address]] or empty bitfields will be excluded from padding calculation routines. Reviewed By: NoQ Differential Revision: https://reviews.llvm.org/D104097 --- .../lib/StaticAnalyzer/Checkers/PaddingChecker.cpp | 7 ++++- clang/test/Analysis/padding_no_unique_address.cpp | 30 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 clang/test/Analysis/padding_no_unique_address.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp index 96f0d9b..40472cc 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp @@ -193,6 +193,11 @@ public: 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 @@ public: 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 0000000..4f26922 --- /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; +}; -- 2.7.4