[clang] Use range-based for to iterate over fields in record layout, NFC (PR #122029)
Reid Kleckner via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 7 16:28:59 PST 2025
https://github.com/rnk created https://github.com/llvm/llvm-project/pull/122029
Move the common case of FieldDecl::getFieldIndex() inline to mitigate the cost of removing the extra `FieldNo` induction variable.
Also rename isNoUniqueAddress parameter to isNonVirtualBaseType, which appears to be more accurate. I think the current name is just a consequence of autocomplete gone wrong.
>From 1824674744d6fba1dd74c74d54aae9b603d8b854 Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rnk at google.com>
Date: Wed, 8 Jan 2025 00:24:09 +0000
Subject: [PATCH] Use range-based for to iterate over fields in record layout,
NFC
Move the common case of FieldDecl::getFieldIndex() inline to mitigate
the cost of removing the extra `FieldNo` induction variable.
Also rename isNoUniqueAddress parameter to isNonVirtualBaseType, which
appears to be more accurate. I think the current name is just a
consequence of autocomplete gone wrong.
---
clang/include/clang/AST/Decl.h | 14 +++-
clang/lib/AST/Decl.cpp | 10 +--
clang/lib/AST/RecordLayoutBuilder.cpp | 73 ++++++++-------------
clang/lib/CodeGen/CGRecordLayoutBuilder.cpp | 6 +-
4 files changed, 48 insertions(+), 55 deletions(-)
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 67ee0bb412692a..7f6c1867bb8c10 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -3115,7 +3115,19 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
/// Returns the index of this field within its record,
/// as appropriate for passing to ASTRecordLayout::getFieldOffset.
- unsigned getFieldIndex() const;
+ unsigned getFieldIndex() const {
+ const FieldDecl *C = getCanonicalDecl();
+ if (C->CachedFieldIndex == 0)
+ C->setCachedFieldIndex();
+ assert(C->CachedFieldIndex);
+ return C->CachedFieldIndex - 1;
+ }
+
+private:
+ /// Set CachedFieldIndex to the index of this field plus one.
+ void setCachedFieldIndex() const;
+
+public:
/// Determines whether this field is mutable (C++ only).
bool isMutable() const { return Mutable; }
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 741e908cf9bc56..97e23dd1aaa920 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -4651,12 +4651,9 @@ bool FieldDecl::isPotentiallyOverlapping() const {
return hasAttr<NoUniqueAddressAttr>() && getType()->getAsCXXRecordDecl();
}
-unsigned FieldDecl::getFieldIndex() const {
- const FieldDecl *Canonical = getCanonicalDecl();
- if (Canonical != this)
- return Canonical->getFieldIndex();
-
- if (CachedFieldIndex) return CachedFieldIndex - 1;
+void FieldDecl::setCachedFieldIndex() const {
+ assert(this == getCanonicalDecl() &&
+ "should be called on the canonical decl");
unsigned Index = 0;
const RecordDecl *RD = getParent()->getDefinition();
@@ -4670,7 +4667,6 @@ unsigned FieldDecl::getFieldIndex() const {
}
assert(CachedFieldIndex && "failed to find field in parent");
- return CachedFieldIndex - 1;
}
SourceRange FieldDecl::getSourceRange() const {
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index f749d3a705fc99..b287a7d5f60451 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -139,8 +139,8 @@ class EmptySubobjectMap {
}
CharUnits
- getFieldOffset(const ASTRecordLayout &Layout, unsigned FieldNo) const {
- uint64_t FieldOffset = Layout.getFieldOffset(FieldNo);
+ getFieldOffset(const ASTRecordLayout &Layout, const FieldDecl *Field) const {
+ uint64_t FieldOffset = Layout.getFieldOffset(Field->getFieldIndex());
assert(FieldOffset % CharWidth == 0 &&
"Field offset not at char boundary!");
@@ -298,14 +298,12 @@ EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
}
// Traverse all member variables.
- unsigned FieldNo = 0;
- for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(),
- E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
- if (I->isBitField())
+ for (const FieldDecl *Field : Info->Class->fields()) {
+ if (Field->isBitField())
continue;
- CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);
- if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
+ CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);
+ if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))
return false;
}
@@ -345,14 +343,12 @@ void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
}
// Traverse all member variables.
- unsigned FieldNo = 0;
- for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(),
- E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
- if (I->isBitField())
+ for (const FieldDecl *Field : Info->Class->fields()) {
+ if (Field->isBitField())
continue;
- CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);
- UpdateEmptyFieldSubobjects(*I, FieldOffset, PlacingEmptyBase);
+ CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);
+ UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingEmptyBase);
}
}
@@ -410,15 +406,12 @@ EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
}
// Traverse all member variables.
- unsigned FieldNo = 0;
- for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
- I != E; ++I, ++FieldNo) {
- if (I->isBitField())
+ for (const FieldDecl *Field : RD->fields()) {
+ if (Field->isBitField())
continue;
- CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);
-
- if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
+ CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);
+ if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))
return false;
}
@@ -521,15 +514,12 @@ void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
}
// Traverse all member variables.
- unsigned FieldNo = 0;
- for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
- I != E; ++I, ++FieldNo) {
- if (I->isBitField())
+ for (const FieldDecl *Field : RD->fields()) {
+ if (Field->isBitField())
continue;
- CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);
-
- UpdateEmptyFieldSubobjects(*I, FieldOffset, PlacingOverlappingField);
+ CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);
+ UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingOverlappingField);
}
}
@@ -1455,10 +1445,8 @@ void ItaniumRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
bool InsertExtraPadding = D->mayInsertExtraPadding(/*EmitRemark=*/true);
bool HasFlexibleArrayMember = D->hasFlexibleArrayMember();
for (auto I = D->field_begin(), End = D->field_end(); I != End; ++I) {
- auto Next(I);
- ++Next;
- LayoutField(*I,
- InsertExtraPadding && (Next != End || !HasFlexibleArrayMember));
+ LayoutField(*I, InsertExtraPadding &&
+ (std::next(I) != End || !HasFlexibleArrayMember));
}
}
@@ -3672,35 +3660,32 @@ static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD,
}
// Dump fields.
- uint64_t FieldNo = 0;
- for (RecordDecl::field_iterator I = RD->field_begin(),
- E = RD->field_end(); I != E; ++I, ++FieldNo) {
- const FieldDecl &Field = **I;
- uint64_t LocalFieldOffsetInBits = Layout.getFieldOffset(FieldNo);
+ for (const FieldDecl *Field : RD->fields()) {
+ uint64_t LocalFieldOffsetInBits = Layout.getFieldOffset(Field->getFieldIndex());
CharUnits FieldOffset =
Offset + C.toCharUnitsFromBits(LocalFieldOffsetInBits);
// Recursively dump fields of record type.
- if (auto RT = Field.getType()->getAs<RecordType>()) {
+ if (auto RT = Field->getType()->getAs<RecordType>()) {
DumpRecordLayout(OS, RT->getDecl(), C, FieldOffset, IndentLevel,
- Field.getName().data(),
+ Field->getName().data(),
/*PrintSizeInfo=*/false,
/*IncludeVirtualBases=*/true);
continue;
}
- if (Field.isBitField()) {
+ if (Field->isBitField()) {
uint64_t LocalFieldByteOffsetInBits = C.toBits(FieldOffset - Offset);
unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
- unsigned Width = Field.getBitWidthValue(C);
+ unsigned Width = Field->getBitWidthValue(C);
PrintBitFieldOffset(OS, FieldOffset, Begin, Width, IndentLevel);
} else {
PrintOffset(OS, FieldOffset, IndentLevel);
}
const QualType &FieldType = C.getLangOpts().DumpRecordLayoutsCanonical
- ? Field.getType().getCanonicalType()
- : Field.getType();
- OS << FieldType << ' ' << Field << '\n';
+ ? Field->getType().getCanonicalType()
+ : Field->getType();
+ OS << FieldType << ' ' << *Field << '\n';
}
// Dump virtual bases.
diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index ea44e6f21f3c86..209ef236f0d5dc 100644
--- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -182,7 +182,7 @@ struct CGRecordLowering {
llvm::Type *StorageType);
/// Lowers an ASTRecordLayout to a llvm type.
void lower(bool NonVirtualBaseType);
- void lowerUnion(bool isNoUniqueAddress);
+ void lowerUnion(bool isNonVirtualBaseType);
void accumulateFields(bool isNonVirtualBaseType);
RecordDecl::field_iterator
accumulateBitFields(bool isNonVirtualBaseType,
@@ -310,9 +310,9 @@ void CGRecordLowering::lower(bool NVBaseType) {
computeVolatileBitfields();
}
-void CGRecordLowering::lowerUnion(bool isNoUniqueAddress) {
+void CGRecordLowering::lowerUnion(bool isNonVirtualBaseType) {
CharUnits LayoutSize =
- isNoUniqueAddress ? Layout.getDataSize() : Layout.getSize();
+ isNonVirtualBaseType ? Layout.getDataSize() : Layout.getSize();
llvm::Type *StorageType = nullptr;
bool SeenNamedMember = false;
// Iterate through the fields setting bitFieldInfo and the Fields array. Also
More information about the cfe-commits
mailing list