Skip to content

Commit 0ddb579

Browse files
authored
[clang][bytecode] Remove base casts before doing memcpy (#137754)
We have to copy the entire thing, not just one of the bases.
1 parent fa1fe11 commit 0ddb579

File tree

3 files changed

+25
-3
lines changed

3 files changed

+25
-3
lines changed

clang/lib/AST/ByteCode/Disasm.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@ LLVM_DUMP_METHOD void InlineDescriptor::dump(llvm::raw_ostream &OS) const {
422422
OS << "IsActive: " << IsActive << "\n";
423423
OS << "InUnion: " << InUnion << "\n";
424424
OS << "IsFieldMutable: " << IsFieldMutable << "\n";
425+
OS << "IsArrayElement: " << IsArrayElement << "\n";
425426
OS << "Desc: ";
426427
if (Desc)
427428
Desc->dump(OS);

clang/lib/AST/ByteCode/InterpBuiltin.cpp

+11-2
Original file line numberDiff line numberDiff line change
@@ -1854,8 +1854,17 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
18541854

18551855
// Check for overlapping memory regions.
18561856
if (!Move && Pointer::pointToSameBlock(SrcPtr, DestPtr)) {
1857-
unsigned SrcIndex = SrcPtr.getIndex() * SrcPtr.elemSize();
1858-
unsigned DstIndex = DestPtr.getIndex() * DestPtr.elemSize();
1857+
// Remove base casts.
1858+
Pointer SrcP = SrcPtr;
1859+
while (SrcP.isBaseClass())
1860+
SrcP = SrcP.getBase();
1861+
1862+
Pointer DestP = DestPtr;
1863+
while (DestP.isBaseClass())
1864+
DestP = DestP.getBase();
1865+
1866+
unsigned SrcIndex = SrcP.expand().getIndex() * SrcP.elemSize();
1867+
unsigned DstIndex = DestP.expand().getIndex() * DestP.elemSize();
18591868
unsigned N = Size.getZExtValue();
18601869

18611870
if ((SrcIndex <= DstIndex && (SrcIndex + N) > DstIndex) ||

clang/test/AST/ByteCode/builtin-functions.cpp

+13-1
Original file line numberDiff line numberDiff line change
@@ -1383,7 +1383,19 @@ namespace BuiltinMemcpy {
13831383
static_assert(type_pun(0x3f800000) == 1.0f); // both-error {{constant}} \
13841384
// both-note {{in call}}
13851385

1386-
1386+
struct Base { int a; };
1387+
struct Derived : Base { int b; };
1388+
constexpr int test_derived_to_base(int n) {
1389+
Derived arr[2] = {1, 2, 3, 4};
1390+
Base *p = &arr[0];
1391+
Base *q = &arr[1];
1392+
__builtin_memcpy(p, q, sizeof(Base) * n); // both-note {{source is not a contiguous array of at least 2 elements of type 'BuiltinMemcpy::Base'}}
1393+
return arr[0].a * 1000 + arr[0].b * 100 + arr[1].a * 10 + arr[1].b;
1394+
}
1395+
static_assert(test_derived_to_base(0) == 1234);
1396+
static_assert(test_derived_to_base(1) == 3234);
1397+
static_assert(test_derived_to_base(2) == 3434); // both-error {{constant}} \
1398+
// both-note {{in call}}
13871399
}
13881400

13891401
namespace Memcmp {

0 commit comments

Comments
 (0)