-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[C] Allow __attribute__((nonstring)) on multidimensional arrays #138133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[C] Allow __attribute__((nonstring)) on multidimensional arrays #138133
Conversation
This addresses post-commit review feedback from the Linux kernel folks and improves compatibility with the same feature in GCC
@llvm/pr-subscribers-clang Author: Aaron Ballman (AaronBallman) ChangesThis 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:
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)}}
+ }
+ }
+};
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this appears to resolve the warning in the one place that I know needs it.
…#138133) This addresses post-commit review feedback from the Linux kernel folks and improves compatibility with the same feature in GCC
…#138133) This addresses post-commit review feedback from the Linux kernel folks and improves compatibility with the same feature in GCC
…#138133) This addresses post-commit review feedback from the Linux kernel folks and improves compatibility with the same feature in GCC
…#138133) This addresses post-commit review feedback from the Linux kernel folks and improves compatibility with the same feature in GCC
This addresses post-commit review feedback from the Linux kernel folks and improves compatibility with the same feature in GCC