Skip to content

Commit 48e0287

Browse files
committed
[[no_unique_address]] on non-class field is still potentially overlapping
This agrees with existing GCC behaviour: https://godbolt.org/z/Grr8r4sYr
1 parent af1ff56 commit 48e0287

File tree

4 files changed

+29
-7
lines changed

4 files changed

+29
-7
lines changed

clang/include/clang/AST/Decl.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3177,9 +3177,10 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
31773177
/// [[no_unique_address]] attribute.
31783178
bool isZeroSize(const ASTContext &Ctx) const;
31793179

3180-
/// Determine if this field is of potentially-overlapping class type, that
3180+
/// Determine if this field is of potentially-overlapping type, that
31813181
/// is, subobject with the [[no_unique_address]] attribute
3182-
bool isPotentiallyOverlapping() const;
3182+
/// If ClassOnly is true, the field also has to be of class type.
3183+
bool isPotentiallyOverlapping(bool ClassOnly = true) const;
31833184

31843185
/// Get the kind of (C++11) default member initializer that this field has.
31853186
InClassInitStyle getInClassInitStyle() const {

clang/lib/AST/Decl.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4623,8 +4623,9 @@ bool FieldDecl::isZeroSize(const ASTContext &Ctx) const {
46234623
});
46244624
}
46254625

4626-
bool FieldDecl::isPotentiallyOverlapping() const {
4627-
return hasAttr<NoUniqueAddressAttr>() && getType()->getAsCXXRecordDecl();
4626+
bool FieldDecl::isPotentiallyOverlapping(bool ClassOnly) const {
4627+
return hasAttr<NoUniqueAddressAttr>() &&
4628+
(!ClassOnly || getType()->getAsCXXRecordDecl());
46284629
}
46294630

46304631
unsigned FieldDecl::getFieldIndex() const {

clang/lib/AST/RecordLayoutBuilder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2445,7 +2445,7 @@ static bool isItaniumPOD(const ASTContext &Context, const CXXRecordDecl *RD) {
24452445
return true;
24462446
}
24472447

2448-
return FD->isPotentiallyOverlapping();
2448+
return FD->isPotentiallyOverlapping(/*ClassOnly=*/false);
24492449
};
24502450

24512451
if (llvm::any_of(RD->fields(), IsDisqualifying))

clang/test/Layout/no-unique-address.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -triple x86_64-linux-gnu -fdump-record-layouts %s | FileCheck %s --check-prefixes=CHECK,NEW
2-
// RUN: %clang_cc1 -fclang-abi-compat=19.0 -std=c++20 -fsyntax-only -triple x86_64-linux-gnu -fdump-record-layouts %s | FileCheck %s --check-prefixes=CHECK,OLD
1+
// RUN: %clang_cc1 -DOLD_ABI=false -std=c++20 -fsyntax-only -triple x86_64-linux-gnu -fdump-record-layouts %s | FileCheck %s --check-prefixes=CHECK,NEW
2+
// RUN: %clang_cc1 -fclang-abi-compat=19.0 -DOLD_ABI=true -std=c++20 -fsyntax-only -triple x86_64-linux-gnu -fdump-record-layouts %s | FileCheck %s --check-prefixes=CHECK,OLD
33

44
namespace Empty {
55
struct A {};
@@ -269,3 +269,23 @@ namespace RepeatedVBase {
269269
// CHECK-NEXT: | [sizeof=32, dsize=9, align=16,
270270
// CHECK-NEXT: | nvsize=9, nvalign=16]
271271
}
272+
273+
namespace PotentiallyOverlappingNonClass {
274+
struct A {
275+
[[no_unique_address]] alignas(2) char x;
276+
};
277+
struct B : A {
278+
char y;
279+
};
280+
static_assert(sizeof(B) == (OLD_ABI ? 4 : 2));
281+
// CHECK:*** Dumping AST Record Layout
282+
// CHECK: 0 | struct PotentiallyOverlappingNonClass::B
283+
// CHECK-NEXT: 0 | struct PotentiallyOverlappingNonClass::A (base)
284+
// CHECK-NEXT: 0 | char x
285+
// NEW-NEXT: 1 | char y
286+
// NEW-NEXT: | [sizeof=2, dsize=2, align=2,
287+
// NEW-NEXT: | nvsize=2, nvalign=2]
288+
// OLD-NEXT: 2 | char y
289+
// OLD-NEXT: | [sizeof=4, dsize=3, align=2,
290+
// OLD-NEXT: | nvsize=3, nvalign=2]
291+
}

0 commit comments

Comments
 (0)