Skip to content

Commit afb9093

Browse files
committed
address comments
1 parent 5825b32 commit afb9093

File tree

2 files changed

+40
-14
lines changed

2 files changed

+40
-14
lines changed

clang/lib/Sema/SemaInit.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,11 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
261261
<< Str->getSourceRange();
262262
else if (StrLength - 1 == ArrayLen) {
263263
// If the string literal is null-terminated explicitly, e.g., `char a[4] =
264-
// "ABC\0"`, there should be no warn:
265-
if (const auto *SL = dyn_cast<StringLiteral>(Str->IgnoreParens()))
266-
if (SL->isOrdinary() && SL->getBytes().back() == 0)
267-
return;
264+
// "ABC\0"`, there should be no warning:
265+
if (const auto *SL = dyn_cast<StringLiteral>(Str->IgnoreParens());
266+
SL && SL->getLength() > 0 &&
267+
SL->getCodeUnit(SL->getLength() - 1) == 0)
268+
return;
268269
// If the entity being initialized has the nonstring attribute, then
269270
// silence the "missing nonstring" diagnostic. If there's no entity,
270271
// check whether we're initializing an array of arrays; if so, walk the
Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,53 @@
11
// RUN: %clang_cc1 -fsyntax-only -verify -Wunterminated-string-initialization %s -x c
2-
// RUN: %clang_cc1 -fsyntax-only -verify -Wunterminated-string-initialization %s -x c++
2+
// RUN: %clang_cc1 -fsyntax-only -verify=cxx,expected -Wunterminated-string-initialization %s -x c++
33

44

5-
// In C, the following examples are fine:
6-
#if __cplusplus
7-
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)}}
5+
#ifdef __cplusplus
6+
// C++ is stricter so the following cases should be warned about:
7+
8+
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)}}
9+
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)}}
810

911
struct S {
1012
char buf[3];
1113
char fub[3];
12-
} 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)}}
13-
14-
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)}}
15-
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)}}
14+
} 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)}}
1615

16+
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)}}
17+
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)}}
18+
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)}}
19+
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)}}
20+
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)}}
1721
#else
18-
//expected-no-diagnostics
19-
char foo[3] = "fo\0";
22+
23+
// In C, the following examples are fine:
24+
#include <stddef.h>
25+
typedef unsigned short char16_t;
26+
typedef unsigned int char32_t;
27+
28+
char foo3[3] = "fo\0";
29+
char foo1[1] = "\0";
2030

2131
struct S {
2232
char buf[3];
2333
char fub[3];
2434
} s = { "ba\0", "bo\0" };
2535

36+
// Test different encodings:
2637
signed char scfoo[3] = "fo\0";
2738
unsigned char ucfoo[3] = "fo\0";
39+
wchar_t wcfoo[3] = L"fo\0";
40+
char16_t c16foo[3] = u"fo\0";
41+
char32_t c32foo[3] = U"fo\0";
42+
43+
// Test list initializer:
44+
signed char scfoo_lst[3] = {'f', 'o', '\0'};
45+
unsigned char ucfoo_lst[3] = {'f', 'o', '\0'};
46+
wchar_t wcfoo_lst[3] = {L'f', L'o', L'\0'};
47+
char16_t c16foo_lst[3] = {u'f', u'o', u'\0'};
48+
char32_t c32foo_lst[3] = {U'f', U'o', U'\0'};
49+
50+
// Declaring an array of size 0 is invalid by C standard but compilers
51+
// may allow it:
52+
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?}}
2853
#endif

0 commit comments

Comments
 (0)