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
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to