[clang] [clang][bytecode] Remove base casts before doing memcpy (PR #137754)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 28 21:53:54 PDT 2025
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/137754
We have to copy the entire thing, not just one of the bases.
>From e73345a59ec62a79e709bcf91f17855df8f118e4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Tue, 29 Apr 2025 06:33:09 +0200
Subject: [PATCH] [clang][bytecode] Remove base casts before doing memcpy
We have to copy the entire thing, not just one of the bases.
---
clang/lib/AST/ByteCode/Disasm.cpp | 1 +
clang/lib/AST/ByteCode/InterpBuiltin.cpp | 13 +++++++++++--
clang/test/AST/ByteCode/builtin-functions.cpp | 14 +++++++++++++-
3 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/clang/lib/AST/ByteCode/Disasm.cpp b/clang/lib/AST/ByteCode/Disasm.cpp
index 83b9af9de0796..46c5cb96fa9f4 100644
--- a/clang/lib/AST/ByteCode/Disasm.cpp
+++ b/clang/lib/AST/ByteCode/Disasm.cpp
@@ -422,6 +422,7 @@ LLVM_DUMP_METHOD void InlineDescriptor::dump(llvm::raw_ostream &OS) const {
OS << "IsActive: " << IsActive << "\n";
OS << "InUnion: " << InUnion << "\n";
OS << "IsFieldMutable: " << IsFieldMutable << "\n";
+ OS << "IsArrayElement: " << IsArrayElement << "\n";
OS << "Desc: ";
if (Desc)
Desc->dump(OS);
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 34baae1986c35..55c944e31c0ca 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -1849,8 +1849,17 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
// Check for overlapping memory regions.
if (!Move && Pointer::pointToSameBlock(SrcPtr, DestPtr)) {
- unsigned SrcIndex = SrcPtr.getIndex() * SrcPtr.elemSize();
- unsigned DstIndex = DestPtr.getIndex() * DestPtr.elemSize();
+ // Remove base casts.
+ Pointer SrcP = SrcPtr;
+ while (SrcP.isBaseClass())
+ SrcP = SrcP.getBase();
+
+ Pointer DestP = DestPtr;
+ while (DestP.isBaseClass())
+ DestP = DestP.getBase();
+
+ unsigned SrcIndex = SrcP.expand().getIndex() * SrcP.elemSize();
+ unsigned DstIndex = DestP.expand().getIndex() * DestP.elemSize();
unsigned N = Size.getZExtValue();
if ((SrcIndex <= DstIndex && (SrcIndex + N) > DstIndex) ||
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp
index a4c8ec4856ecc..f879360c5357f 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -1383,7 +1383,19 @@ namespace BuiltinMemcpy {
static_assert(type_pun(0x3f800000) == 1.0f); // both-error {{constant}} \
// both-note {{in call}}
-
+ struct Base { int a; };
+ struct Derived : Base { int b; };
+ constexpr int test_derived_to_base(int n) {
+ Derived arr[2] = {1, 2, 3, 4};
+ Base *p = &arr[0];
+ Base *q = &arr[1];
+ __builtin_memcpy(p, q, sizeof(Base) * n); // both-note {{source is not a contiguous array of at least 2 elements of type 'BuiltinMemcpy::Base'}}
+ return arr[0].a * 1000 + arr[0].b * 100 + arr[1].a * 10 + arr[1].b;
+ }
+ static_assert(test_derived_to_base(0) == 1234);
+ static_assert(test_derived_to_base(1) == 3234);
+ static_assert(test_derived_to_base(2) == 3434); // both-error {{constant}} \
+ // both-note {{in call}}
}
namespace Memcmp {
More information about the cfe-commits
mailing list