-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[Clang] Fix missing diagnostic for non-standard layout type in offsetof
#65246
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
[Clang] Fix missing diagnostic for non-standard layout type in offsetof
#65246
Conversation
Thanks for working on this. This generally looks good to me. |
Thanks. LGTM. |
Thank you for your quick review! |
offsetof
Okay, makes sense to me. Should probably also be backported to 17. |
@tbaederr We are getting rather conservative as to what gets backported. I think that does not meet the bar. |
@kasuga-fj could you please re-upload change to trigger the build? |
@cor3ntin Yes, I wrote this in the wrong PR 🤦 |
@metaflow I added an empty commit and the build was triggered, but it still failed. Could you help me? |
FWIW, an empty commit didn't trigger CI correctly yesterday, so pushing a non-empty commit might fix the CI issue. |
Ah, thanks. Then what should I do? Can I make another commit with the same content as the last commit and force push? (sorry, I don't fully understand the LLVM's PR rules) |
Adding an irrelevant new line in a modified test file would suffice to trigger the CI build. |
alright, build has been triggered successfully! thank you <3 |
The CI failed because |
Ping @llvm/pr-subscribers-libcxx |
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.
Hmmm, in some ways I think this is making the diagnostic needlessly chatty, and in other ways the new diagnostic behavior seems reasonable.
On balance, I think the improvements outweigh the regressions, especially for code users are likely to hit. e.g., I suspect there's way more use of offsetof in a static assertion than there are uses of offsetof as an operand to sizeof.
clang/test/SemaCXX/offsetof.cpp
Outdated
@@ -17,7 +17,7 @@ struct Base { int x; }; | |||
struct Derived : Base { int y; }; | |||
int o = __builtin_offsetof(Derived, x); // expected-warning{{offset of on non-POD type}} | |||
|
|||
const int o2 = sizeof(__builtin_offsetof(Derived, x)); | |||
const int o2 = sizeof(__builtin_offsetof(Derived, x)); // expected-warning{{offset of on non-POD type 'Derived'}} |
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.
This is an example of why I think the existing behavior is correct. The fact that we're asking for the offset of a field on a non-POD type is not harmful because the call is never evaluated.
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.
So you think we should ie, check for !isUnevaluated()
- ie diag in constant expressions but not in unevaluated contexts?
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.
I think that might produce slightly better results by silencing this kind of warning.
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.
Fixed. Thanks.
@@ -25,6 +25,7 @@ struct B : public A { | |||
|
|||
static_assert(__builtin_offsetof(B, d) == 12, | |||
"We can't allocate the bitfield into the padding under ms_struct"); | |||
// expected-warning@-2 {{offset of on non-standard-layout type 'B'}} |
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.
I think this diagnostic is an improvement over the status quo.
int derived1[__builtin_offsetof(Derived2, x) == 0? 1 : -1]; | ||
int derived2[__builtin_offsetof(Derived2, y) == 4? 1 : -1]; | ||
int derived3[__builtin_offsetof(Derived2, z) == 8? 1 : -1]; | ||
int derived1[__builtin_offsetof(Derived2, x) == 0? 1 : -1]; // expected-warning{{offset of on non-POD type 'Derived2'}} |
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.
This also seems like an improvement in diagnostic behavior.
@llvm/pr-subscribers-libcxx Could you please check this comment? #65246 (comment) |
@philnik777 may be able to help |
I think when the @llvm/pr-subscribers-libcxx group was pinged 2 weeks ago, most of us didn't have the right GH notifications set up yet and we didn't see it. Looking now. |
Note that you should probably rebase your patch onto |
Ok so after scratching my head a bit, I'm actually not certain of how to proceed with this. I can't find a way to implement
However, in C++03, using So... should we strive to eradicate this from libc++ in the first place, or should we just silence the warning. WDYT? Also, given that it is conditionally supported in C++17, I assume this warning doesn't trigger at all in C++17 mode, right? |
Thank you for your review! Here are some comments and my thoughts.
Does it mean that I can rebase and force-push since (it should be avoided in normal case but) this is a special case?
I think it's good to only silence the warning and (if necessary) leave some TODO comments about the
I believe the purpose of this warning is to tell you that your program works now, but may not be compiled with another compiler. So the similar warning should appear even in C++17 mode. I chedked and found that |
That's what I usually do. Do we have any Github workflow documentation that mentions we shouldn't force-push to update PRs? If so, I am not aware of it.
My question is about the desired end state of libc++, not whether that end state should be achieved in this specific patch or not.
What @philnik777 do you have thoughts on this? |
According to the LLVM GitHub User Guide, we should generally avoid rebasing and pushing force. But I trust it will be allowed in this case.
I misunderstood, sorry. I'm not an expert of libcxx, so I cannot determine what is should be (although it is only what an amateur thinks, at least it seems to be working fine now, so just suppressing warning would not be a big problem, I think).
Yes, you are correct. I was only checking with standard-layout class... I tried passing a non-standard layout class in the type parameter and |
Assuming that Clang doesn't plan on optimizing anything based on this, I think it should be fine to just silence the warning. We could also add a |
@kasuga-fj Ok, let's take the diff I posted earlier in the comments and silence the warning in libc++ then. Once you do that, the libc++ test suite shouldn't fail with your patch anymore so your CI should be green. Then libc++ will be out of your way and it's up to the Clang folks whether this is worth doing. |
7faabb2
to
10d759e
Compare
@llvm/pr-subscribers-clang @llvm/pr-subscribers-libcxx ChangesFixes #64619 Clang warns diagnostic for non-standard layout types in Full diff: https://github.com/llvm/llvm-project/pull/65246.diff 6 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f314c9c72fa28b7..abc36bac05d788d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -208,6 +208,8 @@ Improvements to Clang's diagnostics
(`#54678: <https://github.com/llvm/llvm-project/issues/54678>`_).
- Clang now prints its 'note' diagnostic in cyan instead of black, to be more compatible
with terminals with dark background colors. This is also more consistent with GCC.
+- Clang now always diagnoses when using non-standard layout types in ``offsetof`` .
+ (`#64619: <https://github.com/llvm/llvm-project/issues/64619>`_)
Bug Fixes in This Version
-------------------------
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 92496b03ecabe54..fedea932c5e15fe 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -16766,12 +16766,11 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
LangOpts.CPlusPlus11? diag::ext_offsetof_non_standardlayout_type
: diag::ext_offsetof_non_pod_type;
- if (!IsSafe && !DidWarnAboutNonPOD &&
- DiagRuntimeBehavior(BuiltinLoc, nullptr,
- PDiag(DiagID)
- << SourceRange(Components[0].LocStart, OC.LocEnd)
- << CurrentType))
+ if (!IsSafe && !DidWarnAboutNonPOD && !isUnevaluatedContext()) {
+ Diag(BuiltinLoc, DiagID)
+ << SourceRange(Components[0].LocStart, OC.LocEnd) << CurrentType;
DidWarnAboutNonPOD = true;
+ }
}
// Look for the field.
diff --git a/clang/test/SemaCXX/class-layout.cpp b/clang/test/SemaCXX/class-layout.cpp
index 9782ff08100b2d6..23b3dbe24249378 100644
--- a/clang/test/SemaCXX/class-layout.cpp
+++ b/clang/test/SemaCXX/class-layout.cpp
@@ -1,18 +1,18 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++98 -Wno-inaccessible-base -Wno-c++11-extensions
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base
-// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=15
-// RUN: %clang_cc1 -triple x86_64-scei-ps4 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=6
-// RUN: %clang_cc1 -triple x86_64-sie-ps5 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=6
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=6 -DCLANG_ABI_COMPAT=6
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=14 -DCLANG_ABI_COMPAT=14
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=16 -DCLANG_ABI_COMPAT=16
-// RUN: %clang_cc1 -triple powerpc-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=15
-// RUN: %clang_cc1 -triple powerpc-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
-// RUN: %clang_cc1 -triple powerpc64-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=15
-// RUN: %clang_cc1 -triple powerpc64-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
-// RUN: %clang_cc1 -triple s390x-none-zos %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base
-// RUN: %clang_cc1 -triple s390x-none-zos %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++98 -Wno-inaccessible-base -Wno-invalid-offsetof -Wno-c++11-extensions
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -Wno-invalid-offsetof
+// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -Wno-invalid-offsetof -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -triple x86_64-scei-ps4 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -Wno-invalid-offsetof -DCLANG_ABI_COMPAT=6
+// RUN: %clang_cc1 -triple x86_64-sie-ps5 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -Wno-invalid-offsetof -DCLANG_ABI_COMPAT=6
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -Wno-invalid-offsetof -fclang-abi-compat=6 -DCLANG_ABI_COMPAT=6
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -Wno-invalid-offsetof -fclang-abi-compat=14 -DCLANG_ABI_COMPAT=14
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -Wno-invalid-offsetof -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -Wno-invalid-offsetof -fclang-abi-compat=16 -DCLANG_ABI_COMPAT=16
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -Wno-invalid-offsetof -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -Wno-invalid-offsetof -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -Wno-invalid-offsetof -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -Wno-invalid-offsetof -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -triple s390x-none-zos %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -Wno-invalid-offsetof
+// RUN: %clang_cc1 -triple s390x-none-zos %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -Wno-invalid-offsetof -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++98 -Wno-inaccessible-base -Wno-c++11-extensions
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base
diff --git a/clang/test/SemaCXX/ms_struct.cpp b/clang/test/SemaCXX/ms_struct.cpp
index e6f0a25b38ea80c..995e424d1f87640 100644
--- a/clang/test/SemaCXX/ms_struct.cpp
+++ b/clang/test/SemaCXX/ms_struct.cpp
@@ -25,6 +25,7 @@ struct B : public A {
static_assert(__builtin_offsetof(B, d) == 12,
"We can't allocate the bitfield into the padding under ms_struct");
+// expected-warning@-2 {{offset of on non-standard-layout type 'B'}}
struct C {
#ifdef TEST_FOR_ERROR
@@ -38,6 +39,5 @@ struct C {
static_assert(__builtin_offsetof(C, n) == 8,
"long long field in ms_struct should be 8-byte aligned");
-#if !defined(TEST_FOR_ERROR) && !defined(TEST_FOR_WARNING)
-// expected-no-diagnostics
-#endif
+// expected-warning@-2 {{offset of on non-standard-layout type 'C'}}
+
diff --git a/clang/test/SemaCXX/offsetof.cpp b/clang/test/SemaCXX/offsetof.cpp
index c984657ebe1f0ed..c4e86369f007dcb 100644
--- a/clang/test/SemaCXX/offsetof.cpp
+++ b/clang/test/SemaCXX/offsetof.cpp
@@ -51,9 +51,9 @@ struct Derived2 : public Base1, public Base2 {
int z;
};
-int derived1[__builtin_offsetof(Derived2, x) == 0? 1 : -1];
-int derived2[__builtin_offsetof(Derived2, y) == 4? 1 : -1];
-int derived3[__builtin_offsetof(Derived2, z) == 8? 1 : -1];
+int derived1[__builtin_offsetof(Derived2, x) == 0? 1 : -1]; // expected-warning{{offset of on non-POD type 'Derived2'}}
+int derived2[__builtin_offsetof(Derived2, y) == 4? 1 : -1]; // expected-warning{{offset of on non-POD type 'Derived2'}}
+int derived3[__builtin_offsetof(Derived2, z) == 8? 1 : -1]; // expected-warning{{offset of on non-POD type 'Derived2'}}
// offsetof referring to anonymous struct in base.
// PR7769
@@ -66,7 +66,8 @@ struct foo {
struct bar : public foo {
};
-int anonstruct[__builtin_offsetof(bar, x) == 0 ? 1 : -1];
+int anonstruct[__builtin_offsetof(bar, x) == 0 ? 1 : -1]; // expected-warning{{offset of on non-POD type 'bar'}}
+
struct LtoRCheck {
int a[10];
diff --git a/libcxx/include/__type_traits/datasizeof.h b/libcxx/include/__type_traits/datasizeof.h
index 019099a9cf183b5..88a702470c3c15a 100644
--- a/libcxx/include/__type_traits/datasizeof.h
+++ b/libcxx/include/__type_traits/datasizeof.h
@@ -47,7 +47,11 @@ struct __libcpp_datasizeof {
};
#endif
+ _LIBCPP_DIAGNOSTIC_PUSH
+ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Winvalid-offsetof")
+ _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Winvalid-offsetof")
static const size_t value = offsetof(_FirstPaddingByte<>, __first_padding_byte_);
+ _LIBCPP_DIAGNOSTIC_POP
};
_LIBCPP_END_NAMESPACE_STD
|
@@ -47,7 +47,11 @@ struct __libcpp_datasizeof { | |||
}; | |||
#endif | |||
|
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.
Optional : Can you add a brief comment/note that why warnings are suppressed here?
Mb something like :
// Disable warnings related to the use of `offsetof` on non-standard layout types
// TODO : Find a way to replace offsetof ?
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.
Done. Thanks
Previous CI failures due to |
// TODO : Find a way to replace `offsetof` ? | ||
_LIBCPP_DIAGNOSTIC_PUSH | ||
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Winvalid-offsetof") | ||
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Winvalid-offsetof") |
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.
GCC doesn't warn on this, so we shouldn't suppress anything here.
@@ -47,7 +47,13 @@ struct __libcpp_datasizeof { | |||
}; | |||
#endif | |||
|
|||
// Disable warnings related to the use of `offsetof` on non-standard layout or non-POD types | |||
// TODO : Find a way to replace `offsetof` ? |
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.
I don't think this TODO is actionable from the libc++ side of things currently, so I'd rather not add it. offsetof
is the right tool for what we are trying to achieve - even if it's technically UB.
The CI issues with the Benchmarks should be fixed now, so if you rebase onto |
1acbf7d
to
b9e201a
Compare
✅ With the latest revision this PR passed the C/C++ code formatter. |
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.
LGTM from the libc++ side of things.
Thank you for your review! (The upstream build process seems to be broken now, so I'll wait until it's fixed) |
aa41086
to
5721932
Compare
`offsetof` Fixes llvm#64619 Clang warns diagnostic for non-standard layout types in `offsetof` only if they are in evaluated context. With this patch, you'll also get diagnostic if you use `offsetof` on non-standard layout types in any other contexts
5721932
to
01ca658
Compare
Fixes #64619
Clang warns diagnostic for non-standard layout types in
offsetof
only if they are in evaluated context. With this patch, you'll also get diagnostic if you useoffsetof
on non-standard layout types in any other contexts