[clang] [ObjC] Fix offsets following `[[no_unique_address]]` for `@encode()` (PR #71321)

Daniel Bertalan via cfe-commits cfe-commits at lists.llvm.org
Sun Nov 5 07:53:29 PST 2023


https://github.com/BertalanD created https://github.com/llvm/llvm-project/pull/71321

Commit 46ca880fca made `@encode` skip fields that are made zero-sized by `[[no_unique_address]]`. When iterating the fields, the index which is passed to `getFieldOffset` failed to be incremented for those due to the use of an early `continue`, so subsequent fields reported an incorrect offset. This caused an assertion to be triggered in `getObjCEncodingForStructureImpl`.

Fixes #71250

>From 2ad862a174685a679d398b628769e88c5eebbee6 Mon Sep 17 00:00:00 2001
From: Daniel Bertalan <dani at danielbertalan.dev>
Date: Sun, 5 Nov 2023 16:19:50 +0100
Subject: [PATCH] [ObjC] Fix offsets following `[[no_unique_address]]` for
 `@encode()`

Commit 46ca880fca made `@encode` skip fields that are made zero-sized by
`[[no_unique_address]]`. When iterating the fields, the index which is
passed to `getFieldOffset` failed to be incremented for those due to the
use of an early `continue`, so subsequent fields reported an incorrect
offset. This caused an assertion to be triggered in
`getObjCEncodingForStructureImpl`.

Fixes #71250
---
 clang/lib/AST/ASTContext.cpp       |  4 +---
 clang/test/CodeGenObjCXX/encode.mm | 14 ++++++++++++++
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index da90136752210b6..60146e9901bc44d 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -8535,14 +8535,12 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
     }
   }
 
-  unsigned i = 0;
   for (FieldDecl *Field : RDecl->fields()) {
     if (!Field->isZeroLengthBitField(*this) && Field->isZeroSize(*this))
       continue;
-    uint64_t offs = layout.getFieldOffset(i);
+    uint64_t offs = layout.getFieldOffset(Field->getFieldIndex());
     FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs),
                               std::make_pair(offs, Field));
-    ++i;
   }
 
   if (CXXRec && includeVBases) {
diff --git a/clang/test/CodeGenObjCXX/encode.mm b/clang/test/CodeGenObjCXX/encode.mm
index f382e7f23d77335..cad70e379c386bf 100644
--- a/clang/test/CodeGenObjCXX/encode.mm
+++ b/clang/test/CodeGenObjCXX/encode.mm
@@ -339,3 +339,17 @@ @implementation N
 const char *inner0 = @encode(Outer0<int>::Inner0 *);
 const char *inner1 = @encode(Outer0<int>::Inner1<float> *);
 }
+
+#if __cplusplus >= 202002L
+namespace GH71250 {
+  struct Empty {};
+  struct S {
+    [[no_unique_address]] Empty a;
+    long b;
+    long c;
+  };
+
+  // CHECKCXX20: @_ZN7GH712501sE =  constant [7 x i8] c"{S=qq}\00", align 1
+  extern const char s[] = @encode(S);
+}
+#endif



More information about the cfe-commits mailing list