[clang] [C] Do not diagnose flexible array members with -Wdefault-const-init-field-unsafe (PR #140578)
via cfe-commits
cfe-commits at lists.llvm.org
Mon May 19 10:13:46 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Aaron Ballman (AaronBallman)
<details>
<summary>Changes</summary>
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
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)
``````````
</details>
https://github.com/llvm/llvm-project/pull/140578
More information about the cfe-commits
mailing list