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 the Linux kernel folks and 
improves compatibility with the same feature in GCC

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


2 Files Affected:

- (modified) clang/lib/Sema/SemaInit.cpp (+15-2) 
- (modified) clang/test/Sema/attr-nonstring.c (+79-1) 


``````````diff
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 6900ccb11c3db..5bdf62e0c4e0d 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -261,8 +261,21 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, 
const ArrayType *AT,
           << Str->getSourceRange();
     else if (StrLength - 1 == ArrayLen) {
       // If the entity being initialized has the nonstring attribute, then
-      // silence the "missing nonstring" diagnostic.
-      if (const ValueDecl *D = Entity.getDecl();
+      // silence the "missing nonstring" diagnostic. If there's no entity,
+      // check whether we're initializing an array of arrays; if so, walk the
+      // parents to find an entity.
+      auto FindCorrectEntity = [](const InitializedEntity &Entity) {
+        const ValueDecl *Ret = nullptr;
+        for (const InitializedEntity *E = &Entity; E; E = Entity.getParent()) {
+          Ret = E->getDecl();
+          if (Ret)
+            break;
+          if (!E->getType()->isArrayType())
+            break;
+        }
+        return Ret;
+      };
+      if (const ValueDecl *D = FindCorrectEntity(Entity);
           !D || !D->hasAttr<NonStringAttr>())
         S.Diag(
             Str->getBeginLoc(),
diff --git a/clang/test/Sema/attr-nonstring.c b/clang/test/Sema/attr-nonstring.c
index 31728e701a3fc..99520c8890500 100644
--- a/clang/test/Sema/attr-nonstring.c
+++ b/clang/test/Sema/attr-nonstring.c
@@ -2,7 +2,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify=noncxx,expected,no-nonstring -Wextra 
%s
 // RUN: %clang_cc1 -fsyntax-only -verify=noncxx,expected,compat 
-Wc++-unterminated-string-initialization %s
 // RUN: %clang_cc1 -fsyntax-only -verify=noncxx,expected,compat -Wc++-compat %s
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx -x c++ %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx -x c++ 
-Wno-c99-designator %s
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,noncxx 
-Wno-unterminated-string-initialization %s
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,noncxx -Wc++-compat -Wextra 
-Wno-unterminated-string-initialization 
-Wno-c++-unterminated-string-initialization %s
 
@@ -39,3 +39,81 @@ __attribute__((nonstring)) int eek2;              // 
expected-warning {{'nonstri
 // diagnostic when you overwrite more than just the null terminator.
 char too_big[3] = "this is too big"; // noncxx-warning {{initializer-string 
for char array is too long}} \
                                         cxx-error {{initializer-string for 
char array is too long, array size is 3 but initializer has size 16 (including 
the null terminating character)}}
+
+// Show that this also applies to arrays of objects containing strings, too.
+const char md_array[][3] __attribute__((nonstring)) = { "BAR", "FOO", };   // 
compat-warning 2 {{initializer-string for character array is too long for C++, 
array size is 3 but initializer has size 4 (including the null terminating 
character)}} \
+                                                                              
cxx-error 2 {{initializer-string for char array is too long, array size is 3 
but initializer has size 4 (including the null terminating character)}}
+
+struct StructWithNSArray {
+  __attribute__((nonstring)) char blech[3];
+};
+
+struct StructWithNSArray s1[] = {
+  { "FOO" }, // compat-warning {{initializer-string for character array is too 
long for C++, array size is 3 but initializer has size 4 (including the null 
terminating character)}} \
+                cxx-error {{initializer-string for char array is too long, 
array size is 3 but initializer has size 4 (including the null terminating 
character)}}
+  { "BAR" }  // compat-warning {{initializer-string for character array is too 
long for C++, array size is 3 but initializer has size 4 (including the null 
terminating character)}} \
+                cxx-error {{initializer-string for char array is too long, 
array size is 3 but initializer has size 4 (including the null terminating 
character)}}
+};
+
+struct T1 {
+  struct StructWithNSArray s[2];
+};
+struct U1 {
+  struct T1 t[2];
+};
+struct U1 u[] = {
+  {
+    .t[0] = {
+      .s[0] = { "FOO" }, // compat-warning {{initializer-string for character 
array is too long for C++, array size is 3 but initializer has size 4 
(including the null terminating character)}} \
+                            cxx-error {{initializer-string for char array is 
too long, array size is 3 but initializer has size 4 (including the null 
terminating character)}}
+      .s[1] = { "BAR" }  // compat-warning {{initializer-string for character 
array is too long for C++, array size is 3 but initializer has size 4 
(including the null terminating character)}} \
+                            cxx-error {{initializer-string for char array is 
too long, array size is 3 but initializer has size 4 (including the null 
terminating character)}}
+    },
+    .t[1] = {
+      .s[0] = { "BIP" }, // compat-warning {{initializer-string for character 
array is too long for C++, array size is 3 but initializer has size 4 
(including the null terminating character)}} \
+                            cxx-error {{initializer-string for char array is 
too long, array size is 3 but initializer has size 4 (including the null 
terminating character)}}
+      .s[1] = { "BOP" }  // compat-warning {{initializer-string for character 
array is too long for C++, array size is 3 but initializer has size 4 
(including the null terminating character)}} \
+                            cxx-error {{initializer-string for char array is 
too long, array size is 3 but initializer has size 4 (including the null 
terminating character)}}
+    }
+  }
+};
+
+struct StructWithoutNSArray {
+  char blech[3];
+};
+
+struct StructWithoutNSArray s2[] = {
+  { "FOO" }, // no-nonstring-warning {{initializer-string for character array 
is too long, array size is 3 but initializer has size 4 (including the null 
terminating character); did you mean to use the 'nonstring' attribute?}} \
+                compat-warning {{initializer-string for character array is too 
long for C++, array size is 3 but initializer has size 4 (including the null 
terminating character)}} \
+                            cxx-error {{initializer-string for char array is 
too long, array size is 3 but initializer has size 4 (including the null 
terminating character)}}
+  { "BAR" } // no-nonstring-warning {{initializer-string for character array 
is too long, array size is 3 but initializer has size 4 (including the null 
terminating character); did you mean to use the 'nonstring' attribute?}} \
+               compat-warning {{initializer-string for character array is too 
long for C++, array size is 3 but initializer has size 4 (including the null 
terminating character)}} \
+               cxx-error {{initializer-string for char array is too long, 
array size is 3 but initializer has size 4 (including the null terminating 
character)}}
+};
+
+struct T2 {
+  struct StructWithoutNSArray s[2];
+};
+struct U2 {
+  struct T2 t[2];
+};
+struct U2 u2[] = {
+  {
+    .t[0] = {
+      .s[0] = { "FOO" }, // no-nonstring-warning {{initializer-string for 
character array is too long, array size is 3 but initializer has size 4 
(including the null terminating character); did you mean to use the 'nonstring' 
attribute?}} \
+                            compat-warning {{initializer-string for character 
array is too long for C++, array size is 3 but initializer has size 4 
(including the null terminating character)}} \
+                            cxx-error {{initializer-string for char array is 
too long, array size is 3 but initializer has size 4 (including the null 
terminating character)}}
+      .s[1] = { "BAR" }  // no-nonstring-warning {{initializer-string for 
character array is too long, array size is 3 but initializer has size 4 
(including the null terminating character); did you mean to use the 'nonstring' 
attribute?}} \
+                            compat-warning {{initializer-string for character 
array is too long for C++, array size is 3 but initializer has size 4 
(including the null terminating character)}} \
+                            cxx-error {{initializer-string for char array is 
too long, array size is 3 but initializer has size 4 (including the null 
terminating character)}}
+    },
+    .t[1] = {
+      .s[0] = { "BIP" }, // no-nonstring-warning {{initializer-string for 
character array is too long, array size is 3 but initializer has size 4 
(including the null terminating character); did you mean to use the 'nonstring' 
attribute?}} \
+                            compat-warning {{initializer-string for character 
array is too long for C++, array size is 3 but initializer has size 4 
(including the null terminating character)}} \
+                            cxx-error {{initializer-string for char array is 
too long, array size is 3 but initializer has size 4 (including the null 
terminating character)}}
+      .s[1] = { "BOP" }  // no-nonstring-warning {{initializer-string for 
character array is too long, array size is 3 but initializer has size 4 
(including the null terminating character); did you mean to use the 'nonstring' 
attribute?}} \
+                            compat-warning {{initializer-string for character 
array is too long for C++, array size is 3 but initializer has size 4 
(including the null terminating character)}} \
+                            cxx-error {{initializer-string for char array is 
too long, array size is 3 but initializer has size 4 (including the null 
terminating character)}}
+    }
+  }
+};

``````````

</details>


https://github.com/llvm/llvm-project/pull/138133
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to