[clang] 30de98c - Revert "[-Wunterminated-string-initialization] Handle C string literals ending with explicit '\0' (#143487)"

via cfe-commits cfe-commits at lists.llvm.org
Thu Jun 26 03:52:34 PDT 2025


Author: Weaver
Date: 2025-06-26T11:51:42+01:00
New Revision: 30de98c283f5795dc10cc1c754d87f46a61d15ac

URL: https://github.com/llvm/llvm-project/commit/30de98c283f5795dc10cc1c754d87f46a61d15ac
DIFF: https://github.com/llvm/llvm-project/commit/30de98c283f5795dc10cc1c754d87f46a61d15ac.diff

LOG: Revert "[-Wunterminated-string-initialization] Handle C string literals ending with explicit '\0' (#143487)"

This reverts commit 9903c1936a5d174cfc7d38f77f40ed460e344db6.

Caused the following buildbot failure:
https://lab.llvm.org/buildbot/#/builders/144/builds/28591

Please fix before recommitting.

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Sema/SemaInit.cpp

Removed: 
    clang/test/Sema/attr-nonstring_safe.c


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 9cfe39fca52ee..bc8e157e2b1c0 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -222,7 +222,6 @@ C Language Changes
 
     char buf1[3] = "foo"; // -Wunterminated-string-initialization
     char buf2[3] = "flarp"; // -Wexcess-initializers
-    char buf3[3] = "fo\0";  // This is fine, no warning.
 
   This diagnostic can be suppressed by adding the new ``nonstring`` attribute
   to the field or variable being initialized. #GH137705

diff  --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 0844cb4d6c3cd..da56225b2f926 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -260,37 +260,29 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
              diag::ext_initializer_string_for_char_array_too_long)
           << Str->getSourceRange();
     else if (StrLength - 1 == ArrayLen) {
-      // In C, if the string literal is null-terminated explicitly, e.g., `char
-      // a[4] = "ABC\0"`, there should be no warning:
-      const auto *SL = dyn_cast<StringLiteral>(Str->IgnoreParens());
-      bool IsSLSafe = SL && SL->getLength() > 0 &&
-                      SL->getCodeUnit(SL->getLength() - 1) == 0;
-
-      if (!IsSLSafe) {
-        // If the entity being initialized has the nonstring attribute, then
-        // 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 * {
-          while (Entity) {
-            if (const ValueDecl *VD = Entity->getDecl())
-              return VD;
-            if (!Entity->getType()->isArrayType())
-              return nullptr;
-            Entity = Entity->getParent();
-          }
+      // If the entity being initialized has the nonstring attribute, then
+      // 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 * {
+        while (Entity) {
+          if (const ValueDecl *VD = Entity->getDecl())
+            return VD;
+          if (!Entity->getType()->isArrayType())
+            return nullptr;
+          Entity = Entity->getParent();
+        }
+
+        return nullptr;
+      };
+      if (const ValueDecl *D = FindCorrectEntity(&Entity);
+          !D || !D->hasAttr<NonStringAttr>())
+        S.Diag(
+            Str->getBeginLoc(),
+            diag::warn_initializer_string_for_char_array_too_long_no_nonstring)
+            << ArrayLen << StrLength << Str->getSourceRange();
 
-          return nullptr;
-        };
-        if (const ValueDecl *D = FindCorrectEntity(&Entity);
-            !D || !D->hasAttr<NonStringAttr>())
-          S.Diag(
-              Str->getBeginLoc(),
-              diag::
-                  warn_initializer_string_for_char_array_too_long_no_nonstring)
-              << ArrayLen << StrLength << Str->getSourceRange();
-      }
       // Always emit the C++ compatibility diagnostic.
       S.Diag(Str->getBeginLoc(),
              diag::warn_initializer_string_for_char_array_too_long_for_cpp)

diff  --git a/clang/test/Sema/attr-nonstring_safe.c b/clang/test/Sema/attr-nonstring_safe.c
deleted file mode 100644
index b59e2bfc7f691..0000000000000
--- a/clang/test/Sema/attr-nonstring_safe.c
+++ /dev/null
@@ -1,50 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify=compat,expected -Wunterminated-string-initialization %s -x c
-// RUN: %clang_cc1 -fsyntax-only -verify=cxx -Wunterminated-string-initialization %s -x c++
-
-#ifndef __cplusplus
-typedef unsigned short char16_t;
-typedef unsigned int char32_t;
-typedef __WCHAR_TYPE__ wchar_t;
-#endif
-
-// C++ is stricter so the following cases should be warned about. In
-// C, the following examples are fine.
-
-char foo3[3] = "fo\0"; // cxx-error {{initializer-string for char array is too long, array size is 3 but initializer has size 4 (including the null terminating character)}}
-char foo1[1] = "\0";   // cxx-error {{initializer-string for char array is too long, array size is 1 but initializer has size 2 (including the null terminating character)}}
-
-struct S {
-  char buf[3];
-  char fub[3];
-} s = { "ba\0", "bo\0" }; // 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)}}
-
-#pragma clang diagnostic push
-#pragma clang diagnostic warning "-Wc++-compat"
-// Test 
diff erent encodings:
-signed char scfoo[3] = "fo\0"; // cxx-error {{initializer-string for char array is too long, array size is 3 but initializer has size 4 (including the null terminating character)}} \
-			          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)}}
-unsigned char ucfoo[3] = "fo\0"; // cxx-error {{initializer-string for char array is too long, array size is 3 but initializer has size 4 (including the null terminating character)}} \
-				    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)}}
-wchar_t wcfoo[3] = L"fo\0"; // cxx-error {{initializer-string for char array is too long, array size is 3 but initializer has size 4 (including the null terminating character)}} \
-			       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)}} \
-			       compat-warning {{identifier 'wchar_t' conflicts with a C++ keyword}}
-char16_t c16foo[3] = u"fo\0"; // cxx-error {{initializer-string for char array is too long, array size is 3 but initializer has size 4 (including the null terminating character)}} \
-			         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)}} \
-			         compat-warning {{identifier 'char16_t' conflicts with a C++ keyword}}
-char32_t c32foo[3] = U"fo\0"; // cxx-error {{initializer-string for char array is too long, array size is 3 but initializer has size 4 (including the null terminating character)}} \
-			         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)}} \
-			         compat-warning {{identifier 'char32_t' conflicts with a C++ keyword}}
-#pragma clang diagnostic pop
-
-// Test list initializer:
-signed char scfoo_lst[3] = {'f', 'o', '\0'};
-unsigned char ucfoo_lst[3] = {'f', 'o', '\0'};
-wchar_t wcfoo_lst[3] = {L'f', L'o', L'\0'};
-char16_t c16foo_lst[3] = {u'f', u'o', u'\0'};
-char32_t c32foo_lst[3] = {U'f', U'o', U'\0'};
-
-// Declaring an array of size 0 is invalid by C standard but compilers
-// may allow it:
-char a[0] = ""; // expected-warning {{initializer-string for character array is too long, array size is 0 but initializer has size 1 (including the null terminating character); did you mean to use the 'nonstring' attribute?}} \
-		   cxx-error {{initializer-string for char array is too long, array size is 0 but initializer has size 1 (including the null terminating character)}}
-char b[1] = ""; // no warn


        


More information about the cfe-commits mailing list