[clang][bytecode] Fix diagnosing subtration of zero-size pointers#167839
Merged
[clang][bytecode] Fix diagnosing subtration of zero-size pointers#167839
Conversation
Member
|
@llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) ChangesWe need to get the element type size at bytecode generation time to check. We also need to diagnose this in the LHS == RHS case. Full diff: https://github.com/llvm/llvm-project/pull/167839.diff 5 Files Affected:
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 1243380ca8a6b..c1809c0d2a5b5 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -1039,8 +1039,11 @@ bool Compiler<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {
if (!visitAsPointer(RHS, *RT) || !visitAsPointer(LHS, *LT))
return false;
+ CharUnits ElemTypeSize = Ctx.getASTContext().getTypeSizeInChars(
+ LHS->getType()->getPointeeType());
+
PrimType IntT = classifyPrim(E->getType());
- if (!this->emitSubPtr(IntT, E))
+ if (!this->emitSubPtr(IntT, ElemTypeSize.isZero(), E))
return false;
return DiscardResult ? this->emitPop(IntT, E) : true;
}
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index cbd60c9f2b37c..19c8d6d850339 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -2390,7 +2390,7 @@ static inline bool DecPtr(InterpState &S, CodePtr OpPC) {
/// 2) Pops another Pointer from the stack.
/// 3) Pushes the difference of the indices of the two pointers on the stack.
template <PrimType Name, class T = typename PrimConv<Name>::T>
-inline bool SubPtr(InterpState &S, CodePtr OpPC) {
+inline bool SubPtr(InterpState &S, CodePtr OpPC, bool ElemSizeIsZero) {
const Pointer &LHS = S.Stk.pop<Pointer>();
const Pointer &RHS = S.Stk.pop<Pointer>();
@@ -2402,25 +2402,23 @@ inline bool SubPtr(InterpState &S, CodePtr OpPC) {
return false;
}
- if (LHS == RHS) {
- S.Stk.push<T>();
- return true;
- }
+ if (ElemSizeIsZero) {
+ QualType PtrT = LHS.getType();
+ while (auto *AT = dyn_cast<ArrayType>(PtrT))
+ PtrT = AT->getElementType();
- for (const Pointer &P : {LHS, RHS}) {
- if (P.isZeroSizeArray()) {
- QualType PtrT = P.getType();
- while (auto *AT = dyn_cast<ArrayType>(PtrT))
- PtrT = AT->getElementType();
+ QualType ArrayTy = S.getASTContext().getConstantArrayType(
+ PtrT, APInt::getZero(1), nullptr, ArraySizeModifier::Normal, 0);
+ S.FFDiag(S.Current->getSource(OpPC),
+ diag::note_constexpr_pointer_subtraction_zero_size)
+ << ArrayTy;
- QualType ArrayTy = S.getASTContext().getConstantArrayType(
- PtrT, APInt::getZero(1), nullptr, ArraySizeModifier::Normal, 0);
- S.FFDiag(S.Current->getSource(OpPC),
- diag::note_constexpr_pointer_subtraction_zero_size)
- << ArrayTy;
+ return false;
+ }
- return false;
- }
+ if (LHS == RHS) {
+ S.Stk.push<T>();
+ return true;
}
int64_t A64 =
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index 1785fcf4a7b20..ddf1a8fcc98b1 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -543,6 +543,7 @@ def SubOffset : AluOpcode;
// [Pointer, Pointer] -> [Integral]
def SubPtr : Opcode {
let Types = [IntegerTypeClass];
+ let Args = [ArgBool];
let HasGroup = 1;
}
diff --git a/clang/test/AST/ByteCode/arrays.cpp b/clang/test/AST/ByteCode/arrays.cpp
index eaf9559e40cda..ccae585f2868e 100644
--- a/clang/test/AST/ByteCode/arrays.cpp
+++ b/clang/test/AST/ByteCode/arrays.cpp
@@ -731,6 +731,10 @@ namespace ZeroSizeTypes {
// both-note {{subtraction of pointers to type 'int[0]' of zero size}} \
// both-warning {{subtraction of pointers to type 'int[0]' of zero size has undefined behavior}}
+ constexpr int k2 = p1 - p1; // both-error {{constexpr variable 'k' must be initialized by a constant expression}} \
+ // both-note {{subtraction of pointers to type 'int[0]' of zero size}} \
+ // both-warning {{subtraction of pointers to type 'int[0]' of zero size has undefined behavior}}
+
int arr[5][0];
constexpr int f() { // both-error {{never produces a constant expression}}
return &arr[3] - &arr[0]; // both-note {{subtraction of pointers to type 'int[0]' of zero size}} \
diff --git a/clang/test/AST/ByteCode/new-delete.cpp b/clang/test/AST/ByteCode/new-delete.cpp
index f54854070573c..9e0f33e212c18 100644
--- a/clang/test/AST/ByteCode/new-delete.cpp
+++ b/clang/test/AST/ByteCode/new-delete.cpp
@@ -1104,6 +1104,16 @@ namespace HugeAllocation {
}
#endif
+namespace ZeroSizeArray {
+ constexpr int foo() {
+ int *A = new int[0];
+ int diff = A - (&A[0]);
+ delete[] A;
+ return diff;
+ }
+ static_assert(foo() == 0);
+}
+
#else
/// Make sure we reject this prior to C++20
constexpr int a() { // both-error {{never produces a constant expression}}
|
a99ccf7 to
6dca319
Compare
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
We need to get the element type size at bytecode generation time to check. We also need to diagnose this in the LHS == RHS case.