jubnzv created this revision.
jubnzv added reviewers: steakhal, NoQ, vsavchenko, Szelethus, xazax.hun, 
balazske.
jubnzv added a project: clang.
Herald added subscribers: manas, ASDenysPetrov, martong, dkrupp, donat.nagy, 
mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware.
jubnzv requested review of this revision.

Fix offset calculation routines in padding checker to avoid assertion errors 
described in the following issue: https://bugs.llvm.org/show_bug.cgi?id=50426.
The fields that are subojbects of zero size, marked with [[no_unique_address]] 
or empty bitfields will be excluded from the padding calculation routines.


https://reviews.llvm.org/D104097

Files:
  clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
  clang/test/Analysis/padding_cpp.cpp


Index: clang/test/Analysis/padding_cpp.cpp
===================================================================
--- clang/test/Analysis/padding_cpp.cpp
+++ clang/test/Analysis/padding_cpp.cpp
@@ -200,3 +200,17 @@
 // expected-warning@+1{{Excessive padding in 'class (lambda}}
 auto lambda1 = [ c1 = G.c1, i = G.i, c2 = G.c2 ]{};
 auto lambda2 = [ i = G.i, c1 = G.c1, c2 = G.c2 ]{}; // no-warning
+
+// expected-warning@+1{{Excessive padding in 'struct NoUniqueAddressWarn' (6 
padding}}
+struct NoUniqueAddressWarn {
+  char c1;
+  [[no_unique_address]] Empty empty;
+  int i;
+  char c2;
+};
+
+struct NoUniqueAddressNoWarn { // no-warning
+  char c1;
+  [[no_unique_address]] Empty empty;
+  char c2;
+};
Index: clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
@@ -193,6 +193,11 @@
     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 @@
       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())


Index: clang/test/Analysis/padding_cpp.cpp
===================================================================
--- clang/test/Analysis/padding_cpp.cpp
+++ clang/test/Analysis/padding_cpp.cpp
@@ -200,3 +200,17 @@
 // expected-warning@+1{{Excessive padding in 'class (lambda}}
 auto lambda1 = [ c1 = G.c1, i = G.i, c2 = G.c2 ]{};
 auto lambda2 = [ i = G.i, c1 = G.c1, c2 = G.c2 ]{}; // no-warning
+
+// expected-warning@+1{{Excessive padding in 'struct NoUniqueAddressWarn' (6 padding}}
+struct NoUniqueAddressWarn {
+  char c1;
+  [[no_unique_address]] Empty empty;
+  int i;
+  char c2;
+};
+
+struct NoUniqueAddressNoWarn { // no-warning
+  char c1;
+  [[no_unique_address]] Empty empty;
+  char c2;
+};
Index: clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
@@ -193,6 +193,11 @@
     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 @@
       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())
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to