Skip to content

Conversation

@AaronBallman
Copy link
Collaborator

This addresses post-commit review feedback from someone who discovered that we diagnosed code like the following:

  struct S {
    int len;
    const char fam[];
  } s;

despite it being invalid to initialize the flexible array member.

Note, this applies to flexible array members and zero-sized arrays at the end of a structure (an old-style flexible array member), but it does not apply to one-sized arrays at the end of a structure because those do occupy storage that can be initialized.

…field-unsafe

This addresses post-commit review feedback from someone who discovered
that we diagnosed code like the following:

  struct S {
    int len;
    const char fam[];
  } s;

despite it being invalid to initialize the flexible array member.

Note, this applies to flexible array members and zero-sized arrays at
the end of a structure (an old-style flexible array member), but it
does not apply to one-sized arrays at the end of a structure because
those do occupy storage that can be initialized.
@AaronBallman AaronBallman added clang Clang issues not falling into any other category c clang:frontend Language frontend issues, e.g. anything involving "Sema" labels May 19, 2025
@llvmbot
Copy link
Member

llvmbot commented May 19, 2025

@llvm/pr-subscribers-clang

Author: Aaron Ballman (AaronBallman)

Changes

This addresses post-commit review feedback from someone who discovered that we diagnosed code like the following:

  struct S {
    int len;
    const char fam[];
  } s;

despite it being invalid to initialize the flexible array member.

Note, this applies to flexible array members and zero-sized arrays at the end of a structure (an old-style flexible array member), but it does not apply to one-sized arrays at the end of a structure because those do occupy storage that can be initialized.


Full diff: https://github.com/llvm/llvm-project/pull/140578.diff

2 Files Affected:

  • (modified) clang/lib/Sema/SemaInit.cpp (+8)
  • (modified) clang/test/Sema/warn-default-const-init.c (+30)
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 9ee8603ff7811..e17e68966dc00 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -6513,6 +6513,14 @@ static bool canPerformArrayCopy(const InitializedEntity &Entity) {
 static const FieldDecl *getConstField(const RecordDecl *RD) {
   assert(!isa<CXXRecordDecl>(RD) && "Only expect to call this in C mode");
   for (const FieldDecl *FD : RD->fields()) {
+    // If the field is a flexible array member, we don't want to consider it
+    // as a const field because there's no way to initialize the FAM anyway.
+    if (Decl::isFlexibleArrayMemberLike(
+            FD->getASTContext(), FD, FD->getType(),
+            LangOptions::StrictFlexArraysLevelKind::ZeroOrIncomplete,
+            /*IgnoreTemplateOrMacroSubstitution=*/true))
+      continue;
+
     QualType QT = FD->getType();
     if (QT.isConstQualified())
       return FD;
diff --git a/clang/test/Sema/warn-default-const-init.c b/clang/test/Sema/warn-default-const-init.c
index e788d72899685..e6ff0aa783e23 100644
--- a/clang/test/Sema/warn-default-const-init.c
+++ b/clang/test/Sema/warn-default-const-init.c
@@ -85,3 +85,33 @@ void func() {
   static const int b; // zero-init-var-warning {{default initialization of an object of type 'const int' is incompatible with C++}} \
                          cxx-error {{default initialization of an object of const type 'const int'}}
 }
+
+// Test the behavior of flexible array members. Those cannot be initialized
+// when a stack-allocated object of the structure type is created. We handle
+// degenerate flexible arrays similarly, but only if the array does not
+// actually specify any storage. Note that C++ does not have flexible array
+// members at all, which is why the test is disabled there.
+#ifndef __cplusplus
+struct RealFAM {
+  int len;
+  const char fam[];
+};
+
+struct FakeFAM {
+  int len;
+  const char fam[0];
+};
+
+struct NotTreatedAsAFAM {
+  int len;
+  const char fam[1];              // unsafe-field-note {{member 'fam' declared 'const' here}} \
+                                     unsafe-field-compat-note {{member 'fam' declared 'const' here}}
+};
+
+void test_fams() {
+  struct RealFAM One;
+  struct FakeFAM Two;
+  struct NotTreatedAsAFAM Three;  // unsafe-field-warning {{default initialization of an object of type 'struct NotTreatedAsAFAM' with const member leaves the object uninitialized}} \
+                                     unsafe-field-compat-warning {{default initialization of an object of type 'struct NotTreatedAsAFAM' with const member leaves the object uninitialized and is incompatible with C++}}
+}
+#endif // !defined(__cplusplus)

@AaronBallman AaronBallman merged commit c555c8d into llvm:main May 20, 2025
9 of 10 checks passed
@AaronBallman AaronBallman deleted the aballman-def-const-init-fam branch May 20, 2025 18:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants