-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang][ExprConst] Reject field access with nullptr base #113885
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
Conversation
@llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) ChangesReject them if the base is null, not only if the entire pointer is null. Full diff: https://github.com/llvm/llvm-project/pull/113885.diff 2 Files Affected:
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 8e36cad2d2c6e7..a6694bc0641508 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -1703,7 +1703,7 @@ namespace {
bool checkNullPointerDiagnosingWith(const GenDiagType &GenDiag) {
if (Designator.Invalid)
return false;
- if (IsNullPtr) {
+ if (getLValueBase().isNull()) {
GenDiag();
Designator.setInvalid();
return false;
diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp
index 767eee1c74f054..67160ba571f33c 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -188,7 +188,7 @@ namespace UndefinedBehavior {
namespace Ptr {
struct A {};
- struct B : A { int n; };
+ struct B : A { int n; int m; };
B a[3][3];
constexpr B *p = a[0] + 4; // expected-error {{constant expression}} expected-note {{element 4 of array of 3 elements}}
B b = {};
@@ -204,6 +204,7 @@ namespace UndefinedBehavior {
static_assert((A*)nb == 0, "");
static_assert((B*)na == 0, "");
constexpr const int &nf = nb->n; // expected-error {{constant expression}} expected-note {{cannot access field of null pointer}}
+ constexpr const int &mf = nb->m; // expected-error {{constant expression}} expected-note {{cannot access field of null pointer}}
constexpr const int *np1 = (int*)nullptr + 0; // ok
constexpr const int *np2 = &(*(int(*)[4])nullptr)[0]; // ok
constexpr const int *np3 = &(*(int(*)[4])nullptr)[2]; // expected-error {{constant expression}} expected-note {{cannot perform pointer arithmetic on null pointer}}
|
clang/lib/AST/ExprConstant.cpp
Outdated
@@ -1703,7 +1703,7 @@ namespace { | |||
bool checkNullPointerDiagnosingWith(const GenDiagType &GenDiag) { | |||
if (Designator.Invalid) | |||
return false; | |||
if (IsNullPtr) { | |||
if (getLValueBase().isNull()) { |
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.
Why was the old check not good enough here? In the added testcase, nb
is a null pointer.
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.
Oh, I see. We're adjusting the offset before we call addDecl
. I think this would be better fixed by reversing the order in which we do those steps -- first addDecl
and then adjust the offset. A null base isn't necessarily a null pointer, so checking for a null base here seems wrong (but only in the weird case of a zero integer cast to a non-null pointer value, which we should only accept in constant-folding mode, not when properly evaluating).
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.
The offset is added in adjustOffset()
, which calls clearIsNullPointer()
. This is called before we call addDecl()
, so at that point the pointer is already considered non-null.
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.
Looks like the check here was !Base
until 402804b
Ping |
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 but the changes should come with a release note.
@zygoloid Do you approve too? |
Ping |
As mentioned in the comment thread, I'd prefer to see this addressed by reversing the order in which we call I don't know how important things like this example are, but they do at least seem useful in some cases. |
I think I understand what you mean by changing the order now. I changed two other places as well, just to be consistent. |
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.
LG, thank you!
After llvm/llvm-project#113885 clang will now correctly diagnose the use of nullptr in constexpr contexts. Instead, we can rewrite the check with std::extent_v. Original-Bug: 381885679 Original-Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/1166981 Original-Revision: 6e83c9357c23aeb49d6808fc84472894ac1ca671 GitOrigin-RevId: 9e5bf26c76114bd573166508f37ace410362a42c Change-Id: I4027a3c538c4077b812665701d4080c095a8b01c
After llvm/llvm-project#113885 clang will now correctly diagnose the use of nullptr in constexpr contexts. Instead, we can rewrite the check with std::extent_v. Bug: 381885679 Change-Id: Ib001e61c84e130cbdfb322f44948f58cf64da635 Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/1166981 Fuchsia-Auto-Submit: Paul Kirth <[email protected]> Reviewed-by: Novin Changizi <[email protected]> Commit-Queue: Auto-Submit <[email protected]>
Reject them if the base is null, not only if the entire pointer is null.
Fixes #113821