Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,11 @@ 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) {
// If the string literal is null-terminated explicitly, e.g., `char a[4] =
// "ABC\0"`, there should be no warn:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// "ABC\0"`, there should be no warn:
// "ABC\0"`, there should be no warning.

if (const auto *SL = dyn_cast<StringLiteral>(Str->IgnoreParens()))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (const auto *SL = dyn_cast<StringLiteral>(Str->IgnoreParens()))
if (const auto *SL = dyn_cast<StringLiteral>(Str->IgnoreParens()); SL && SL->isOrdinary() && SL->getBytes().back() == 0)

if (SL->isOrdinary() && SL->getBytes().back() == 0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this encoding-aware? what about if this is a 2nd byte in a multi-byte?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this means the functionality only works for char and not other string types. I would imagine we'd want to also support: wchar_t foo[4] = { L'f', L'o', L'o', L'\0' }; and other variants.

return;
// 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
Expand Down
28 changes: 28 additions & 0 deletions clang/test/Sema/attr-nonstring_safe.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// RUN: %clang_cc1 -fsyntax-only -verify -Wunterminated-string-initialization %s -x c
// RUN: %clang_cc1 -fsyntax-only -verify -Wunterminated-string-initialization %s -x c++


// In C, the following examples are fine:
#if __cplusplus
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#if __cplusplus
#ifdef __cplusplus

char foo[3] = "fo\0"; // expected-error {{initializer-string for char array is too long, array size is 3 but initializer has size 4 (including the null terminating character)}}

struct S {
char buf[3];
char fub[3];
} s = { "ba\0", "bo\0" }; // expected-error 2{{initializer-string for char array is too long, array size is 3 but initializer has size 4 (including the null terminating character)}}

signed char scfoo[3] = "fo\0"; // expected-error {{initializer-string for char array is too long, array size is 3 but initializer has size 4 (including the null terminating character)}}
unsigned char ucfoo[3] = "fo\0"; // expected-error {{initializer-string for char array is too long, array size is 3 but initializer has size 4 (including the null terminating character)}}

#else
//expected-no-diagnostics
char foo[3] = "fo\0";

struct S {
char buf[3];
char fub[3];
} s = { "ba\0", "bo\0" };

signed char scfoo[3] = "fo\0";
unsigned char ucfoo[3] = "fo\0";
#endif
Loading