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