https://github.com/jedav updated 
https://github.com/llvm/llvm-project/pull/229584

>From a8a8e140f40519f3ff174473dac34bc760d34b92 Mon Sep 17 00:00:00 2001
From: John Davis <[email protected]>
Date: Tue, 6 Oct 2026 14:12:15 -0700
Subject: [PATCH 1/4] [clang] Automatic initialization for small struct fields

Currently when using the -ftrivial-auto-var-init-max-size flag, record types
are either fully initialized if they are smaller than the max size, or left
fully uninitialized even if they have individual fields smaller than the max
size. This change initializes struct fields smaller than
-ftrivial-auto-var-init-max-size on a field-by-field basis.
---
 clang/lib/CodeGen/CGDecl.cpp                  | 118 ++++++++++++++++--
 clang/lib/CodeGen/CodeGenFunction.h           |   2 +
 .../CodeGenCXX/auto-var-init-max-size.cpp     |  40 ++++--
 3 files changed, 145 insertions(+), 15 deletions(-)

diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 019b7ac22272e..8d32c4dd0ac0a 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1906,6 +1906,106 @@ void 
CodeGenFunction::emitBypassedVarInitsForSource(const Stmt *Source) {
   }
 }
 
+static bool hasFieldsEligibleForAutoInit(QualType type,
+                                         CodeGenModule &CGM,
+                                         uint64_t MaxSize) {
+  const auto *RD = type->getAsRecordDecl();
+  if (!RD)
+    return false;
+  const auto *Def = RD->getDefinition();
+  if (!Def || !Def->isCompleteDefinition() || Def->isUnion())
+    return false;
+
+  for (const FieldDecl *FD : Def->fields()) {
+    if (FD->isUnnamedBitField() || FD->getType()->isIncompleteArrayType())
+      continue;
+
+    QualType FieldTy = FD->getType();
+    if (FD->isBitField()) {
+      unsigned BitWidth = FD->getBitWidthValue();
+      uint64_t FieldBytes = llvm::divideCeil(BitWidth, 8);
+      if (MaxSize == 0 || FieldBytes <= MaxSize)
+        return true;
+    } else {
+      auto FieldAllocSize = CGM.getDataLayout().getTypeAllocSize(
+          CGM.getTypes().ConvertTypeForMem(FieldTy));
+      if (MaxSize == 0 || FieldAllocSize <= MaxSize)
+        return true;
+      if (FieldTy->isRecordType() &&
+          hasFieldsEligibleForAutoInit(FieldTy, CGM, MaxSize))
+        return true;
+    }
+  }
+  return false;
+}
+
+void CodeGenFunction::emitZeroOrPatternInitForRecordFields(QualType type,
+                                                           const VarDecl &D,
+                                                           Address Loc) {
+  const auto *RD = type->getAsRecordDecl();
+  if (!RD)
+    return;
+  const auto *Def = RD->getDefinition();
+  if(!Def || !Def->isCompleteDefinition() || Def->isUnion())
+    return;
+
+  auto trivialAutoVarInit = getContext().getLangOpts().getTrivialAutoVarInit();
+  auto trivialAutoVarInitMaxSize =
+      getContext().getLangOpts().TrivialAutoVarInitMaxSize;
+  bool isVolatile = type.isVolatileQualified();
+
+  if (trivialAutoVarInitMaxSize > 0 &&
+      !hasFieldsEligibleForAutoInit(type, CGM, trivialAutoVarInitMaxSize))
+    return;
+
+  Loc = Loc.withElementType(ConvertTypeForMem(type));
+  LValue Base = MakeAddrLValue(Loc, type);
+
+  for (const FieldDecl *FD : Def->fields()) {
+    if (FD->isUnnamedBitField() || FD->getType()->isIncompleteArrayType())
+      continue;
+
+    QualType FieldTy = FD->getType();
+    if (isVolatile)
+      FieldTy.addVolatile();
+
+    if (FD->isBitField()) {
+      unsigned BitWidth = FD->getBitWidthValue();
+      uint64_t FieldBytes = llvm::divideCeil(BitWidth, 8);
+      if (trivialAutoVarInitMaxSize > 0 && FieldBytes > 
trivialAutoVarInitMaxSize)
+        continue;
+      if (CGM.stopAutoInit())
+          return;
+      LValue FieldLV = EmitLValueForFieldInitialization(Base, FD);
+      llvm::Type *FieldTy = ConvertTypeForMem(FD->getType());
+      llvm::Constant *Constant = (trivialAutoVarInit == 
LangOptions::TrivialAutoVarInitKind::Zero)
+        ? llvm::Constant::getNullValue(FieldTy)
+        : initializationPatternFor(CGM, FieldTy);
+      EmitStoreThroughBitfieldLValue(RValue::get(Constant), FieldLV);
+    } else {
+      auto FieldAllocSize = 
CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(FieldTy));
+      if (trivialAutoVarInitMaxSize > 0 && FieldAllocSize > 
trivialAutoVarInitMaxSize) {
+        if (FieldTy->isRecordType() &&
+            hasFieldsEligibleForAutoInit(FieldTy, CGM,
+                                        trivialAutoVarInitMaxSize)) {
+          LValue FieldLV = EmitLValueForFieldInitialization(Base, FD);
+          emitZeroOrPatternInitForRecordFields(FieldTy, D, 
FieldLV.getAddress());
+        }
+        continue;
+      }
+      if (CGM.stopAutoInit())
+          return;
+      LValue FieldLV = EmitLValueForFieldInitialization(Base, FD);
+      Address FieldLoc = FieldLV.getAddress();
+      if (trivialAutoVarInit == LangOptions::TrivialAutoVarInitKind::Zero) {
+        emitStoresForZeroInit(D, FieldLoc, isVolatile);
+      } else {
+        emitStoresForPatternInit(D, FieldLoc, isVolatile);
+      }
+    }
+  }
+}
+
 void CodeGenFunction::emitZeroOrPatternForAutoVarInit(QualType type,
                                                       const VarDecl &D,
                                                       Address Loc) {
@@ -1915,11 +2015,9 @@ void 
CodeGenFunction::emitZeroOrPatternForAutoVarInit(QualType type,
   CharUnits Size = getContext().getTypeSizeInChars(type);
   bool isVolatile = type.isVolatileQualified();
   if (!Size.isZero()) {
-    // We skip auto-init variables by their alloc size. Take this as an 
example:
-    // "struct Foo {int x; char buff[1024];}" Assume the max-size flag is 1023.
-    // All Foo type variables will be skipped. Ideally, we only skip the buff
-    // array and still auto-init X in this example.
-    // TODO: Improve the size filtering to by member size.
+    // We skip auto-init variables by their alloc size. For record types larger
+    // than trivialAutoVarInitMaxSize, we filter by member size and initialize
+    // any fields whose size does not exceed trivialAutoVarInitMaxSize.
     auto allocSize = 
CGM.getDataLayout().getTypeAllocSize(Loc.getElementType());
     switch (trivialAutoVarInit) {
     case LangOptions::TrivialAutoVarInitKind::Uninitialized:
@@ -1928,16 +2026,22 @@ void 
CodeGenFunction::emitZeroOrPatternForAutoVarInit(QualType type,
       if (CGM.stopAutoInit())
         return;
       if (trivialAutoVarInitMaxSize > 0 &&
-          allocSize > trivialAutoVarInitMaxSize)
+          allocSize > trivialAutoVarInitMaxSize) {
+        if (type->isRecordType())
+          emitZeroOrPatternInitForRecordFields(type, D, Loc);
         return;
+      }
       emitStoresForZeroInit(D, Loc, isVolatile);
       break;
     case LangOptions::TrivialAutoVarInitKind::Pattern:
       if (CGM.stopAutoInit())
         return;
       if (trivialAutoVarInitMaxSize > 0 &&
-          allocSize > trivialAutoVarInitMaxSize)
+          allocSize > trivialAutoVarInitMaxSize) {
+        if (type->isRecordType())
+          emitZeroOrPatternInitForRecordFields(type, D, Loc);
         return;
+      }
       emitStoresForPatternInit(D, Loc, isVolatile);
       break;
     }
diff --git a/clang/lib/CodeGen/CodeGenFunction.h 
b/clang/lib/CodeGen/CodeGenFunction.h
index 00294ad547d5e..eeb166a9d09fa 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -5641,6 +5641,8 @@ class CodeGenFunction : public CodeGenTypeCache {
                                         unsigned Type,
                                         llvm::IntegerType *ResType);
 
+  void emitZeroOrPatternInitForRecordFields(QualType type, const VarDecl &D,
+                                            Address Loc);
   void emitZeroOrPatternForAutoVarInit(QualType type, const VarDecl &D,
                                        Address Loc);
   LangOptions::TrivialAutoVarInitKind getAutoVarInitKind(QualType Ty,
diff --git a/clang/test/CodeGenCXX/auto-var-init-max-size.cpp 
b/clang/test/CodeGenCXX/auto-var-init-max-size.cpp
index ce8f0337c528b..951d9f3539af7 100644
--- a/clang/test/CodeGenCXX/auto-var-init-max-size.cpp
+++ b/clang/test/CodeGenCXX/auto-var-init-max-size.cpp
@@ -9,13 +9,13 @@
 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -ftrivial-auto-var-init=zero 
-ftrivial-auto-var-init-max-size=4096 %s -emit-llvm -o - | FileCheck 
-check-prefix=ZERO-COMMON -check-prefix=ZERO-MAX-4096 %s
 
 struct Foo {
-    int x; // TODO we should try to make sure X is initialized.
-    char buff[1024];  // this one is fine to skip
+    int x; // x should be initialized.
+    char buff[1024];  // this one is fine to skip.
 };
 
 struct Bar {
-    struct Foo f1; // TODO x in Foo should be initialized.
-    int y; // TODO y should be initialized.
+    struct Foo f; // x in f should be initialized.
+    int y; // y should be initialized.
 };
 
 int foo(unsigned n) {
@@ -48,7 +48,13 @@ int foo(unsigned n) {
   // PATTERN-MAX-1-NOT: store i64 -6148914691236517206, ptr 
%var_size_8_init_later, align 8, !annotation [[AUTO_INIT:!.+]]
   // PATTERN-MAX-1-NOT: store ptr inttoptr (i64 -6148914691236517206 to ptr), 
ptr %var_size_8p, align 8, !annotation [[AUTO_INIT:!.+]]
   // PATTERN-MAX-1-NOT: call void @llvm.memset.p0.i64(ptr align 16 
%var_size_1024, i8 -86, i64 1024, i1 false), !annotation [[AUTO_INIT:!.+]]
-  // PATTERN-MAX-1-NOT: call void @llvm.memset.p0.i64(ptr align 4 
%var_size_1032, i8 -86, i64 1032, i1 false), !annotation [[AUTO_INIT:!.+]]
+  // PATTERN-MAX-1-NOT: %f = getelementptr inbounds nuw %struct.Bar, ptr 
%var_size_1032, i32 0, i32 0
+  // PATTERN-MAX-1-NOT: %x = getelementptr inbounds nuw %struct.Foo, ptr %f, 
i32 0, i32 0
+  // PATTERN-MAX-1-NOT: store i32 -1431655766, ptr %x, align 4, !annotation !1
+  // PATTERN-MAX-1-NOT: %buff = getelementptr inbounds nuw %struct.Foo, ptr 
%f, i32 0, i32 1
+  // PATTERN-MAX-1-NOT: call void @llvm.memset.p0.i64(ptr align 4 %buff, i8 
-86, i64 1024, i1 false), !annotation !1
+  // PATTERN-MAX-1-NOT: %y = getelementptr inbounds nuw %struct.Bar, ptr 
%var_size_1032, i32 0, i32 1
+  // PATTERN-MAX-1-NOT: store i32 -1431655766, ptr %y, align 4, !annotation !1
   // PATTERN-MAX-1-NOT: call void @llvm.memset.p0.i64(ptr align 16 
%var_size_4096, i8 -86, i64 4096, i1 false), !annotation [[AUTO_INIT:!.+]]
 
   // PATTERN-MAX-1024: store i8 -86, ptr %var_size_1, align 1, !annotation 
[[AUTO_INIT:!.+]]
@@ -57,7 +63,13 @@ int foo(unsigned n) {
   // PATTERN-MAX-1024: store i64 -6148914691236517206, ptr 
%var_size_8_init_later, align 8, !annotation [[AUTO_INIT:!.+]]
   // PATTERN-MAX-1024: store ptr inttoptr (i64 -6148914691236517206 to ptr), 
ptr %var_size_8p, align 8, !annotation [[AUTO_INIT:!.+]]
   // PATTERN-MAX-1024: call void @llvm.memset.p0.i64(ptr align 16 
%var_size_1024, i8 -86, i64 1024, i1 false), !annotation [[AUTO_INIT:!.+]]
-  // PATTERN-MAX-1024-NOT: call void @llvm.memset.p0.i64(ptr align 4 
%var_size_1032, i8 -86, i64 1032, i1 false), !annotation [[AUTO_INIT:!.+]]
+  // PATTERN-MAX-1024: %f = getelementptr inbounds nuw %struct.Bar, ptr 
%var_size_1032, i32 0, i32 0
+  // PATTERN-MAX-1024: %x = getelementptr inbounds nuw %struct.Foo, ptr %f, 
i32 0, i32 0
+  // PATTERN-MAX-1024: store i32 -1431655766, ptr %x, align 4, !annotation !1
+  // PATTERN-MAX-1024: %buff = getelementptr inbounds nuw %struct.Foo, ptr %f, 
i32 0, i32 1
+  // PATTERN-MAX-1024: call void @llvm.memset.p0.i64(ptr align 4 %buff, i8 
-86, i64 1024, i1 false), !annotation !1
+  // PATTERN-MAX-1024: %y = getelementptr inbounds nuw %struct.Bar, ptr 
%var_size_1032, i32 0, i32 1
+  // PATTERN-MAX-1024: store i32 -1431655766, ptr %y, align 4, !annotation !1
   // PATTERN-MAX-1024-NOT: call void @llvm.memset.p0.i64(ptr align 16 
%var_size_4096, i8 -86, i64 4096, i1 false), !annotation [[AUTO_INIT:!.+]]
 
   // PATTERN-MAX-4096: store i8 -86, ptr %var_size_1, align 1, !annotation 
[[AUTO_INIT:!.+]]
@@ -78,7 +90,13 @@ int foo(unsigned n) {
   // ZERO-MAX-1-NOT: store i64 0, ptr %var_size_8_init_later, align 8, 
!annotation [[AUTO_INIT:!.+]]
   // ZERO-MAX-1-NOT: store ptr null, ptr %var_size_8p, align 8, !annotation 
[[AUTO_INIT:!.+]]
   // ZERO-MAX-1-NOT: call void @llvm.memset.p0.i64(ptr align 16 
%var_size_1024, i8 0, i64 1024, i1 false), !annotation [[AUTO_INIT:!.+]]
-  // ZERO-MAX-1-NOT: call void @llvm.memset.p0.i64(ptr align 4 %var_size_1032, 
i8 0, i64 1032, i1 false), !annotation [[AUTO_INIT:!.+]]
+  // ZERO-MAX-1-NOT: %f = getelementptr inbounds nuw %struct.Bar, ptr 
%var_size_1032, i32 0, i32 0
+  // ZERO-MAX-1-NOT: %x = getelementptr inbounds nuw %struct.Foo, ptr %f, i32 
0, i32 0
+  // ZERO-MAX-1-NOT: store i32 0, ptr %x, align 4, !annotation !1
+  // ZERO-MAX-1-NOT: %buff = getelementptr inbounds nuw %struct.Foo, ptr %f, 
i32 0, i32 1
+  // ZERO-MAX-1-NOT: call void @llvm.memset.p0.i64(ptr align 4 %buff, i8 0, 
i64 1024, i1 false), !annotation !1
+  // ZERO-MAX-1-NOT: %y = getelementptr inbounds nuw %struct.Bar, ptr 
%var_size_1032, i32 0, i32 1
+  // ZERO-MAX-1-NOT: store i32 0, ptr %y, align 4, !annotation !1
   // ZERO-MAX-1-NOT: call void @llvm.memset.p0.i64(ptr align 16 
%var_size_4096, i8 0, i64 4096, i1 false), !annotation [[AUTO_INIT:!.+]]
 
   // ZERO-MAX-1024: store i8 0, ptr %var_size_1, align 1, !annotation 
[[AUTO_INIT:!.+]]
@@ -87,7 +105,13 @@ int foo(unsigned n) {
   // ZERO-MAX-1024: store i64 0, ptr %var_size_8_init_later, align 8, 
!annotation [[AUTO_INIT:!.+]]
   // ZERO-MAX-1024: store ptr null, ptr %var_size_8p, align 8, !annotation 
[[AUTO_INIT:!.+]]
   // ZERO-MAX-1024: call void @llvm.memset.p0.i64(ptr align 16 %var_size_1024, 
i8 0, i64 1024, i1 false), !annotation [[AUTO_INIT:!.+]]
-  // ZERO-MAX-1024-NOT: call void @llvm.memset.p0.i64(ptr align 4 
%var_size_1032, i8 0, i64 1032, i1 false), !annotation [[AUTO_INIT:!.+]]
+  // ZERO-MAX-1024: %f = getelementptr inbounds nuw %struct.Bar, ptr 
%var_size_1032, i32 0, i32 0
+  // ZERO-MAX-1024: %x = getelementptr inbounds nuw %struct.Foo, ptr %f, i32 
0, i32 0
+  // ZERO-MAX-1024: store i32 0, ptr %x, align 4, !annotation !1
+  // ZERO-MAX-1024: %buff = getelementptr inbounds nuw %struct.Foo, ptr %f, 
i32 0, i32 1
+  // ZERO-MAX-1024: call void @llvm.memset.p0.i64(ptr align 4 %buff, i8 0, i64 
1024, i1 false), !annotation !1
+  // ZERO-MAX-1024: %y = getelementptr inbounds nuw %struct.Bar, ptr 
%var_size_1032, i32 0, i32 1
+  // ZERO-MAX-1024: store i32 0, ptr %y, align 4, !annotation !1
   // ZERO-MAX-1024-NOT: call void @llvm.memset.p0.i64(ptr align 16 
%var_size_4096, i8 0, i64 4096, i1 false), !annotation [[AUTO_INIT:!.+]]
 
   // ZERO-MAX-4096: store i8 0, ptr %var_size_1, align 1, !annotation 
[[AUTO_INIT:!.+]]

>From c5c150f402ede5dd9a5e3a5571269d8b46fa2638 Mon Sep 17 00:00:00 2001
From: John Davis <[email protected]>
Date: Tue, 6 Oct 2026 16:29:06 -0700
Subject: [PATCH 2/4] Fix formatting of CGDecl.cpp

---
 clang/lib/CodeGen/CGDecl.cpp | 30 +++++++++++++++++-------------
 1 file changed, 17 insertions(+), 13 deletions(-)

diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 8d32c4dd0ac0a..d61b6f4807ccd 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1906,8 +1906,7 @@ void CodeGenFunction::emitBypassedVarInitsForSource(const 
Stmt *Source) {
   }
 }
 
-static bool hasFieldsEligibleForAutoInit(QualType type,
-                                         CodeGenModule &CGM,
+static bool hasFieldsEligibleForAutoInit(QualType type, CodeGenModule &CGM,
                                          uint64_t MaxSize) {
   const auto *RD = type->getAsRecordDecl();
   if (!RD)
@@ -1946,7 +1945,7 @@ void 
CodeGenFunction::emitZeroOrPatternInitForRecordFields(QualType type,
   if (!RD)
     return;
   const auto *Def = RD->getDefinition();
-  if(!Def || !Def->isCompleteDefinition() || Def->isUnion())
+  if (!Def || !Def->isCompleteDefinition() || Def->isUnion())
     return;
 
   auto trivialAutoVarInit = getContext().getLangOpts().getTrivialAutoVarInit();
@@ -1972,29 +1971,34 @@ void 
CodeGenFunction::emitZeroOrPatternInitForRecordFields(QualType type,
     if (FD->isBitField()) {
       unsigned BitWidth = FD->getBitWidthValue();
       uint64_t FieldBytes = llvm::divideCeil(BitWidth, 8);
-      if (trivialAutoVarInitMaxSize > 0 && FieldBytes > 
trivialAutoVarInitMaxSize)
+      if (trivialAutoVarInitMaxSize > 0 &&
+          FieldBytes > trivialAutoVarInitMaxSize)
         continue;
       if (CGM.stopAutoInit())
-          return;
+        return;
       LValue FieldLV = EmitLValueForFieldInitialization(Base, FD);
       llvm::Type *FieldTy = ConvertTypeForMem(FD->getType());
-      llvm::Constant *Constant = (trivialAutoVarInit == 
LangOptions::TrivialAutoVarInitKind::Zero)
-        ? llvm::Constant::getNullValue(FieldTy)
-        : initializationPatternFor(CGM, FieldTy);
+      llvm::Constant *Constant =
+          (trivialAutoVarInit == LangOptions::TrivialAutoVarInitKind::Zero)
+              ? llvm::Constant::getNullValue(FieldTy)
+              : initializationPatternFor(CGM, FieldTy);
       EmitStoreThroughBitfieldLValue(RValue::get(Constant), FieldLV);
     } else {
-      auto FieldAllocSize = 
CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(FieldTy));
-      if (trivialAutoVarInitMaxSize > 0 && FieldAllocSize > 
trivialAutoVarInitMaxSize) {
+      auto FieldAllocSize =
+          CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(FieldTy));
+      if (trivialAutoVarInitMaxSize > 0 &&
+          FieldAllocSize > trivialAutoVarInitMaxSize) {
         if (FieldTy->isRecordType() &&
             hasFieldsEligibleForAutoInit(FieldTy, CGM,
-                                        trivialAutoVarInitMaxSize)) {
+                                         trivialAutoVarInitMaxSize)) {
           LValue FieldLV = EmitLValueForFieldInitialization(Base, FD);
-          emitZeroOrPatternInitForRecordFields(FieldTy, D, 
FieldLV.getAddress());
+          emitZeroOrPatternInitForRecordFields(FieldTy, D,
+                                               FieldLV.getAddress());
         }
         continue;
       }
       if (CGM.stopAutoInit())
-          return;
+        return;
       LValue FieldLV = EmitLValueForFieldInitialization(Base, FD);
       Address FieldLoc = FieldLV.getAddress();
       if (trivialAutoVarInit == LangOptions::TrivialAutoVarInitKind::Zero) {

>From ebea29d1eeedccb229fb8cb4c364989bca67b263 Mon Sep 17 00:00:00 2001
From: John Davis <[email protected]>
Date: Tue, 13 Oct 2026 14:01:40 -0700
Subject: [PATCH 3/4] Update release notes and documentation for small struct
 field auto-init

---
 clang/docs/ReleaseNotes.md | 4 ++++
 clang/docs/UsersManual.md  | 4 +++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 384e6ef449d4f..77def5d051833 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -340,6 +340,10 @@ features cannot lower the translation-unit ABI level;
   `-ftrivial-auto-var-init=` entry in the User's Manual for the details,
   including where C deliberately departs from C 6.2.4p6.
 
+- `-ftrivial-auto-var-init-max-size` now initializes struct fields smaller
+  than the specified size, even if the struct as a whole is larger than
+  the specified size.
+
 - `--config` files now support trailing `#` comments after an option, in
   addition to whole-line comments. Mid-line comment-denoting `#`s must be
   separated from surrounding arguments by whitespace. Quoted arguments can no
diff --git a/clang/docs/UsersManual.md b/clang/docs/UsersManual.md
index 96d1c4e009c71..3495fa75cafc6 100644
--- a/clang/docs/UsersManual.md
+++ b/clang/docs/UsersManual.md
@@ -3004,7 +3004,9 @@ damage by making the value deterministic. Use 
`-Wuninitialized`, or a tool like
 
 Individual variables can opt out with `__attribute__((uninitialized))`, and
 whole functions with `__attribute__((no_trivial_auto_var_init))`.
-`-ftrivial-auto-var-init-max-size=` skips variables above a given size, and
+`-ftrivial-auto-var-init-max-size=` only initializes variables smaller than
+the given size (including struct fields smaller than the given size,
+even if the struct as a whole is larger than the given size), and
 `-ftrivial-auto-var-init-stop-after=` stops after a given number of variables;
 both exist to bound code size while triaging.
 

>From d7bfe9fef0d8bfad54f404657a6618ab17fd99ef Mon Sep 17 00:00:00 2001
From: John Davis <[email protected]>
Date: Tue, 13 Oct 2026 14:54:40 -0700
Subject: [PATCH 4/4] Manual clarificiation of -ftrivial-auto-var-init-max-size
 behavior on arrays

---
 clang/docs/UsersManual.md | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/clang/docs/UsersManual.md b/clang/docs/UsersManual.md
index 3495fa75cafc6..777008488fca0 100644
--- a/clang/docs/UsersManual.md
+++ b/clang/docs/UsersManual.md
@@ -3004,11 +3004,13 @@ damage by making the value deterministic. Use 
`-Wuninitialized`, or a tool like
 
 Individual variables can opt out with `__attribute__((uninitialized))`, and
 whole functions with `__attribute__((no_trivial_auto_var_init))`.
-`-ftrivial-auto-var-init-max-size=` only initializes variables smaller than
-the given size (including struct fields smaller than the given size,
-even if the struct as a whole is larger than the given size), and
-`-ftrivial-auto-var-init-stop-after=` stops after a given number of variables;
-both exist to bound code size while triaging.
+`-ftrivial-auto-var-init-stop-after=` stops initialization after a given number
+of variables; `-ftrivial-auto-var-init-max-size=` only initializes variables
+smaller than the given size. Arrays are skipped or initialized based on their
+total size, while struct fields smaller than the given size are intialized
+even if the struct as a whole is larger than the given size.
+Both `-ftrivial-auto-var-init-stop-after=` and
+`-ftrivial-auto-var-init-max-size=` exist to bound code size while triaging.
 
 The initialization is normally emitted where the variable is declared. A `goto`
 or a `switch` can jump over a declaration, in which case that point is never

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to