-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[clang][bytecode] Allow up/down casts of nullptr #127615
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
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
If the target type is a pointer type.
@llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) ChangesIf the target type is a pointer type. Full diff: https://github.com/llvm/llvm-project/pull/127615.diff 5 Files Affected:
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 59c236c9da8c8..c58e884c77d6b 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -272,7 +272,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
CurType = B->getType();
} else {
unsigned DerivedOffset = collectBaseOffset(B->getType(), CurType);
- if (!this->emitGetPtrBasePop(DerivedOffset, CE))
+ if (!this->emitGetPtrBasePop(
+ DerivedOffset, /*NullOK=*/CE->getType()->isPointerType(), CE))
return false;
CurType = B->getType();
}
@@ -288,7 +289,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
unsigned DerivedOffset =
collectBaseOffset(SubExpr->getType(), CE->getType());
- return this->emitGetPtrDerivedPop(DerivedOffset, CE);
+ return this->emitGetPtrDerivedPop(
+ DerivedOffset, /*NullOK=*/CE->getType()->isPointerType(), CE);
}
case CK_FloatingCast: {
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index c80be094856b0..f09081101f086 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -1432,7 +1432,7 @@ bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
unsigned Offset = S.getContext().collectBaseOffset(
InitialPointeeType->getAsRecordDecl(),
OverriderPointeeType->getAsRecordDecl());
- return GetPtrBasePop(S, OpPC, Offset);
+ return GetPtrBasePop(S, OpPC, Offset, /*IsNullOK=*/true);
}
return true;
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 73cc107b7dbff..0f24c83d03029 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -1568,10 +1568,20 @@ inline bool GetPtrActiveThisField(InterpState &S, CodePtr OpPC, uint32_t Off) {
return true;
}
-inline bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off) {
+inline bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off,
+ bool NullOK) {
const Pointer &Ptr = S.Stk.pop<Pointer>();
- if (!CheckNull(S, OpPC, Ptr, CSK_Derived))
+ if (!NullOK && !CheckNull(S, OpPC, Ptr, CSK_Derived))
return false;
+
+ if (!Ptr.isBlockPointer()) {
+ // FIXME: We don't have the necessary information in integral pointers.
+ // The Descriptor only has a record, but that does of course not include
+ // the potential derived classes of said record.
+ S.Stk.push<Pointer>(Ptr);
+ return true;
+ }
+
if (!CheckSubobject(S, OpPC, Ptr, CSK_Derived))
return false;
if (!CheckDowncast(S, OpPC, Ptr, Off))
@@ -1600,10 +1610,11 @@ inline bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
return true;
}
-inline bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off) {
+inline bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off,
+ bool NullOK) {
const Pointer &Ptr = S.Stk.pop<Pointer>();
- if (!CheckNull(S, OpPC, Ptr, CSK_Base))
+ if (!NullOK && !CheckNull(S, OpPC, Ptr, CSK_Base))
return false;
if (!Ptr.isBlockPointer()) {
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index 088a3e40fe2a7..41e4bae65c195 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -312,7 +312,7 @@ def GetPtrThisField : OffsetOpcode;
// [Pointer] -> [Pointer]
def GetPtrBase : OffsetOpcode;
// [Pointer] -> [Pointer]
-def GetPtrBasePop : OffsetOpcode;
+def GetPtrBasePop : OffsetOpcode { let Args = [ArgUint32, ArgBool]; }
def GetMemberPtrBasePop : Opcode {
// Offset of field, which is a base.
let Args = [ArgSint32];
@@ -322,9 +322,7 @@ def GetMemberPtrBasePop : Opcode {
def FinishInitPop : Opcode;
def FinishInit : Opcode;
-def GetPtrDerivedPop : Opcode {
- let Args = [ArgUint32];
-}
+def GetPtrDerivedPop : Opcode { let Args = [ArgUint32, ArgBool]; }
// [Pointer] -> [Pointer]
def GetPtrVirtBasePop : Opcode {
diff --git a/clang/test/AST/ByteCode/records.cpp b/clang/test/AST/ByteCode/records.cpp
index 9470e7d8e3dcb..3cc3210841e0f 100644
--- a/clang/test/AST/ByteCode/records.cpp
+++ b/clang/test/AST/ByteCode/records.cpp
@@ -1656,12 +1656,28 @@ namespace ExprWithCleanups {
static_assert(F == 1i, "");
}
-namespace NullptrUpcast {
+namespace NullptrCast {
struct A {};
struct B : A { int n; };
+ constexpr A *na = nullptr;
constexpr B *nb = nullptr;
constexpr A &ra = *nb; // both-error {{constant expression}} \
// both-note {{cannot access base class of null pointer}}
+ constexpr B &rb = (B&)*na; // both-error {{constant expression}} \
+ // both-note {{cannot access derived class of null pointer}}
+ constexpr bool test() {
+ auto a = (A*)(B*)nullptr;
+
+ return a == nullptr;
+ }
+ static_assert(test(), "");
+
+ constexpr bool test2() {
+ auto a = (B*)(A*)nullptr;
+
+ return a == nullptr;
+ }
+ static_assert(test2(), "");
}
namespace NonConst {
|
wldfngrs
pushed a commit
to wldfngrs/llvm-project
that referenced
this pull request
Feb 19, 2025
If the target type is a pointer type.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
clang:frontend
Language frontend issues, e.g. anything involving "Sema"
clang
Clang issues not falling into any other category
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
If the target type is a pointer type.