[clang] [clang][CodeGen] Zero init unspecified fields in initializers in C (PR #97121)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 2 18:19:58 PDT 2024
github-actions[bot] wrote:
<!--LLVM CODE FORMAT COMMENT: {clang-format}-->
:warning: C/C++ code formatter, clang-format found issues in your code. :warning:
<details>
<summary>
You can test this locally with the following command:
</summary>
``````````bash
git-clang-format --diff 12189f800585ab459afa20b4f159db93ae474b57 e1d75774c554a5125428b3f3a6304a921c81c5f0 --extensions h,cpp,c -- clang/test/CodeGen/linux-kernel-struct-union-initializer.c clang/test/CodeGen/linux-kernel-struct-union-initializer2.c clang/lib/CodeGen/CGDecl.cpp clang/lib/CodeGen/CGExprAgg.cpp clang/lib/CodeGen/CodeGenModule.cpp clang/lib/CodeGen/CodeGenModule.h clang/test/CodeGen/2008-07-22-bitfield-init-after-zero-len-array.c clang/test/CodeGen/2008-08-07-AlignPadding1.c clang/test/CodeGen/2009-06-14-anonymous-union-init.c clang/test/CodeGen/64bit-swiftcall.c clang/test/CodeGen/arm-swiftcall.c clang/test/CodeGen/const-init.c clang/test/CodeGen/decl.c clang/test/CodeGen/designated-initializers.c clang/test/CodeGen/ext-int.c clang/test/CodeGen/flexible-array-init.c clang/test/CodeGen/global-init.c clang/test/CodeGen/init.c clang/test/CodeGen/mingw-long-double.c clang/test/CodeGen/mms-bitfields.c clang/test/CodeGen/union-init2.c clang/test/CodeGen/windows-swiftcall.c
``````````
</details>
<details>
<summary>
View the diff from clang-format here.
</summary>
``````````diff
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 47620ebaf3..c29b7f2372 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -371,44 +371,53 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
if (!getLangOpts().CPlusPlus) {
// In C23 (N3096) $6.7.10:
// """
- // If any object is initialized with an empty iniitializer, then it is subject to default
- // initialization:
- // - if it is an aggregate, every member is initialized (recursively) according to these rules,
+ // If any object is initialized with an empty iniitializer, then it is
+ // subject to default initialization:
+ // - if it is an aggregate, every member is initialized (recursively)
+ // according to these rules,
// and any padding is initialized to zero bits;
- // - if it is a union, the first named member is initialized (recursively) according to these
+ // - if it is a union, the first named member is initialized (recursively)
+ // according to these
// rules, and any padding is initialized to zero bits.
//
- // If the aggregate or union contains elements or members that are aggregates or unions, these
- // rules apply recursively to the subaggregates or contained unions.
+ // If the aggregate or union contains elements or members that are
+ // aggregates or unions, these rules apply recursively to the subaggregates
+ // or contained unions.
//
- // If there are fewer initializers in a brace-enclosed list than there are elements or members
- // of an aggregate, or fewer characters in a string literal used to initialize an array of
- // known size than there are elements in the array, the remainder of the aggregate is subject
- // to default initialization.
+ // If there are fewer initializers in a brace-enclosed list than there are
+ // elements or members of an aggregate, or fewer characters in a string
+ // literal used to initialize an array of known size than there are elements
+ // in the array, the remainder of the aggregate is subject to default
+ // initialization.
// """
//
- // From my understanding, the standard is ambiguous in the following two areas:
- // 1. For a union type with empty initializer, if the first named member is not the largest
- // member, then the bytes comes after the first named member but before padding are left
- // unspecified. An example is:
+ // From my understanding, the standard is ambiguous in the following two
+ // areas:
+ // 1. For a union type with empty initializer, if the first named member is
+ // not the largest member, then the bytes comes after the first named member
+ // but before padding are left unspecified. An example is:
// union U { int a; long long b;};
- // union U u = {}; // The first 4 bytes are 0, but 4-8 bytes are left unspecified.
+ // union U u = {}; // The first 4 bytes are 0, but 4-8 bytes are left
+ // unspecified.
//
- // 2. It only mentions padding for empty initializer, but doesn't mention padding for a
- // non empty initialization list. And if the aggregation or union contains elements or members
- // that are aggregates or unions, and some are non empty initializers, while others are empty
- // initiailizers, the padding initialization is unclear. An example is:
+ // 2. It only mentions padding for empty initializer, but doesn't mention
+ // padding for a non empty initialization list. And if the aggregation or
+ // union contains elements or members that are aggregates or unions, and
+ // some are non empty initializers, while others are empty initiailizers,
+ // the padding initialization is unclear. An example is:
// struct S1 { int a; long long b; };
// struct S2 { char c; struct S1 s1; };
- // // The values for paddings between s2.c and s2.s1.a, between s2.s1.a and s2.s1.b are
+ // // The values for paddings between s2.c and s2.s1.a, between s2.s1.a
+ // and s2.s1.b are
// // unclear.
// struct S2 s2 = { 'c' };
//
- // Here we choose to zero initiailize left bytes of a union type. Because projects like the
- // Linux kernel are relying on this behavior. If we don't explicitly zero initialize them, the
- // undef values can be optimized to return gabage data.
- // We also choose to zero initialize paddings for aggregates and unions, no matter they are
- // initialized by empty initializers or non empty initializers. This can provide a consistent
+ // Here we choose to zero initiailize left bytes of a union type. Because
+ // projects like the Linux kernel are relying on this behavior. If we don't
+ // explicitly zero initialize them, the undef values can be optimized to
+ // return gabage data. We also choose to zero initialize paddings for
+ // aggregates and unions, no matter they are initialized by empty
+ // initializers or non empty initializers. This can provide a consistent
// behavior. So projects like the Linux kernel can rely on it.
Init = constWithPadding(CGM, IsPattern::No,
replaceUndef(CGM, IsPattern::No, Init));
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index f2e15f3af8..73a1ec062d 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -1752,14 +1752,19 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
EmitNullInitializationToLValue(FieldLoc);
}
if (ZeroInitPadding) {
- CharUnits TotalSize = Dest.getPreferredSize(CGF.getContext(), DestLV.getType());
- CharUnits FieldSize = CGF.getContext().getTypeSizeInChars(FieldLoc.getType());
+ CharUnits TotalSize =
+ Dest.getPreferredSize(CGF.getContext(), DestLV.getType());
+ CharUnits FieldSize =
+ CGF.getContext().getTypeSizeInChars(FieldLoc.getType());
if (FieldSize < TotalSize) {
CharUnits LeftSize = TotalSize - FieldSize;
- llvm::Constant *LeftSizeVal = CGF.Builder.getInt64(LeftSize.getQuantity());
+ llvm::Constant *LeftSizeVal =
+ CGF.Builder.getInt64(LeftSize.getQuantity());
Address BaseLoc = Dest.getAddress().withElementType(CGF.Int8Ty);
- Address LeftLoc = CGF.Builder.CreateConstGEP(BaseLoc, LeftSize.getQuantity());
- CGF.Builder.CreateMemSet(LeftLoc, CGF.Builder.getInt8(0), LeftSizeVal, false);
+ Address LeftLoc =
+ CGF.Builder.CreateConstGEP(BaseLoc, LeftSize.getQuantity());
+ CGF.Builder.CreateMemSet(LeftLoc, CGF.Builder.getInt8(0), LeftSizeVal,
+ false);
}
}
@@ -1774,13 +1779,17 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
for (const auto *field : record->fields()) {
if (ZeroInitPadding) {
unsigned FieldIndex = field->getFieldIndex();
- uint64_t CurOff = Layout.getFieldOffset(FieldIndex) / CGF.getContext().getCharWidth();
+ uint64_t CurOff =
+ Layout.getFieldOffset(FieldIndex) / CGF.getContext().getCharWidth();
if (SizeSoFar < CurOff) {
- llvm::Constant* PaddingSizeVal = CGF.Builder.getInt64(CurOff - SizeSoFar);
+ llvm::Constant *PaddingSizeVal =
+ CGF.Builder.getInt64(CurOff - SizeSoFar);
Address PaddingLoc = CGF.Builder.CreateConstGEP(BaseLoc, SizeSoFar);
- CGF.Builder.CreateMemSet(PaddingLoc, CGF.Builder.getInt8(0), PaddingSizeVal, false);
+ CGF.Builder.CreateMemSet(PaddingLoc, CGF.Builder.getInt8(0),
+ PaddingSizeVal, false);
}
- CharUnits FieldSize = CGF.getContext().getTypeSizeInChars(field->getType());
+ CharUnits FieldSize =
+ CGF.getContext().getTypeSizeInChars(field->getType());
SizeSoFar = CurOff + FieldSize.getQuantity();
}
// We're done once we hit the flexible array member.
@@ -1825,11 +1834,14 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
}
}
if (ZeroInitPadding) {
- uint64_t TotalSize = Dest.getPreferredSize(CGF.getContext(), DestLV.getType()).getQuantity();
+ uint64_t TotalSize =
+ Dest.getPreferredSize(CGF.getContext(), DestLV.getType()).getQuantity();
if (SizeSoFar < TotalSize) {
- llvm::Constant* PaddingSizeVal = CGF.Builder.getInt64(TotalSize - SizeSoFar);
+ llvm::Constant *PaddingSizeVal =
+ CGF.Builder.getInt64(TotalSize - SizeSoFar);
Address PaddingLoc = CGF.Builder.CreateConstGEP(BaseLoc, SizeSoFar);
- CGF.Builder.CreateMemSet(PaddingLoc, CGF.Builder.getInt8(0), PaddingSizeVal, false);
+ CGF.Builder.CreateMemSet(PaddingLoc, CGF.Builder.getInt8(0),
+ PaddingSizeVal, false);
}
}
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/97121
More information about the cfe-commits
mailing list