[clang] c51d396 - [clang][bytecode] Fix __builtin_memmove type diagnostics (#132544)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Mar 22 06:58:36 PDT 2025
Author: Timm Baeder
Date: 2025-03-22T14:58:32+01:00
New Revision: c51d396f4dec65bac24e00ace3f5ce5582d2c699
URL: https://github.com/llvm/llvm-project/commit/c51d396f4dec65bac24e00ace3f5ce5582d2c699
DIFF: https://github.com/llvm/llvm-project/commit/c51d396f4dec65bac24e00ace3f5ce5582d2c699.diff
LOG: [clang][bytecode] Fix __builtin_memmove type diagnostics (#132544)
Set the source type when allocating primitives so we can later retrieve
it.
Added:
Modified:
clang/lib/AST/ByteCode/Compiler.cpp
clang/lib/AST/ByteCode/Descriptor.cpp
clang/lib/AST/ByteCode/Descriptor.h
clang/lib/AST/ByteCode/InterpBuiltin.cpp
clang/lib/AST/ByteCode/Program.cpp
clang/lib/AST/ByteCode/Program.h
clang/test/AST/ByteCode/placement-new.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 9dc02b25f8495..b30c669df6825 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -3356,7 +3356,8 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
if (E->isArray())
Desc = nullptr; // We're not going to use it in this case.
else
- Desc = P.createDescriptor(E, *ElemT, Descriptor::InlineDescMD,
+ Desc = P.createDescriptor(E, *ElemT, /*SourceTy=*/nullptr,
+ Descriptor::InlineDescMD,
/*IsConst=*/false, /*IsTemporary=*/false,
/*IsMutable=*/false);
} else {
@@ -4260,8 +4261,8 @@ unsigned Compiler<Emitter>::allocateLocalPrimitive(
// FIXME: There are cases where Src.is<Expr*>() is wrong, e.g.
// (int){12} in C. Consider using Expr::isTemporaryObject() instead
// or isa<MaterializeTemporaryExpr>().
- Descriptor *D = P.createDescriptor(Src, Ty, Descriptor::InlineDescMD, IsConst,
- isa<const Expr *>(Src));
+ Descriptor *D = P.createDescriptor(Src, Ty, nullptr, Descriptor::InlineDescMD,
+ IsConst, isa<const Expr *>(Src));
Scope::Local Local = this->createLocal(D);
if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>()))
Locals.insert({VD, Local});
diff --git a/clang/lib/AST/ByteCode/Descriptor.cpp b/clang/lib/AST/ByteCode/Descriptor.cpp
index 0f862583a37b1..15b2fe02fb875 100644
--- a/clang/lib/AST/ByteCode/Descriptor.cpp
+++ b/clang/lib/AST/ByteCode/Descriptor.cpp
@@ -329,9 +329,10 @@ static BlockMoveFn getMoveArrayPrim(PrimType Type) {
}
/// Primitives.
-Descriptor::Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD,
- bool IsConst, bool IsTemporary, bool IsMutable)
- : Source(D), ElemSize(primSize(Type)), Size(ElemSize),
+Descriptor::Descriptor(const DeclTy &D, const Type *SourceTy, PrimType Type,
+ MetadataSize MD, bool IsConst, bool IsTemporary,
+ bool IsMutable)
+ : Source(D), SourceType(SourceTy), ElemSize(primSize(Type)), Size(ElemSize),
MDSize(MD.value_or(0)), AllocSize(align(Size + MDSize)), PrimT(Type),
IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary),
CtorFn(getCtorPrim(Type)), DtorFn(getDtorPrim(Type)),
diff --git a/clang/lib/AST/ByteCode/Descriptor.h b/clang/lib/AST/ByteCode/Descriptor.h
index dfb008e4c8b8a..35c84a7847a72 100644
--- a/clang/lib/AST/ByteCode/Descriptor.h
+++ b/clang/lib/AST/ByteCode/Descriptor.h
@@ -175,8 +175,8 @@ struct Descriptor final {
const BlockMoveFn MoveFn = nullptr;
/// Allocates a descriptor for a primitive.
- Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, bool IsConst,
- bool IsTemporary, bool IsMutable);
+ Descriptor(const DeclTy &D, const Type *SourceTy, PrimType Type,
+ MetadataSize MD, bool IsConst, bool IsTemporary, bool IsMutable);
/// Allocates a descriptor for an array of primitives.
Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, size_t NumElems,
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index a6e1884404287..2cbbfe5a9987f 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -149,6 +149,18 @@ static bool retPrimValue(InterpState &S, CodePtr OpPC,
#undef RET_CASE
}
+static QualType getElemType(const Pointer &P) {
+ const Descriptor *Desc = P.getFieldDesc();
+ QualType T = Desc->getType();
+ if (Desc->isPrimitive())
+ return T;
+ if (T->isPointerType())
+ return T->getAs<PointerType>()->getPointeeType();
+ if (Desc->isArray())
+ return Desc->getElemQualType();
+ return T;
+}
+
static void diagnoseNonConstexprBuiltin(InterpState &S, CodePtr OpPC,
unsigned ID) {
auto Loc = S.Current->getSource(OpPC);
@@ -1575,10 +1587,10 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
return true;
}
- const Descriptor *Desc =
- S.P.createDescriptor(NewCall, *ElemT, Descriptor::InlineDescMD,
- /*IsConst=*/false, /*IsTemporary=*/false,
- /*IsMutable=*/false);
+ const Descriptor *Desc = S.P.createDescriptor(
+ NewCall, *ElemT, ElemType.getTypePtr(), Descriptor::InlineDescMD,
+ /*IsConst=*/false, /*IsTemporary=*/false,
+ /*IsMutable=*/false);
Block *B = Allocator.allocate(Desc, S.getContext().getEvalID(),
DynamicAllocator::Form::Operator);
assert(B);
@@ -1782,15 +1794,13 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
if (DestPtr.isDummy() || SrcPtr.isDummy())
return false;
- QualType DestElemType;
+ QualType DestElemType = getElemType(DestPtr);
size_t RemainingDestElems;
if (DestPtr.getFieldDesc()->isArray()) {
- DestElemType = DestPtr.getFieldDesc()->getElemQualType();
RemainingDestElems = DestPtr.isUnknownSizeArray()
? 0
: (DestPtr.getNumElems() - DestPtr.getIndex());
} else {
- DestElemType = DestPtr.getType();
RemainingDestElems = 1;
}
unsigned DestElemSize = ASTCtx.getTypeSizeInChars(DestElemType).getQuantity();
@@ -1803,15 +1813,13 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
return false;
}
- QualType SrcElemType;
+ QualType SrcElemType = getElemType(SrcPtr);
size_t RemainingSrcElems;
if (SrcPtr.getFieldDesc()->isArray()) {
- SrcElemType = SrcPtr.getFieldDesc()->getElemQualType();
RemainingSrcElems = SrcPtr.isUnknownSizeArray()
? 0
: (SrcPtr.getNumElems() - SrcPtr.getIndex());
} else {
- SrcElemType = SrcPtr.getType();
RemainingSrcElems = 1;
}
unsigned SrcElemSize = ASTCtx.getTypeSizeInChars(SrcElemType).getQuantity();
@@ -1884,16 +1892,6 @@ static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,
bool IsWide =
(ID == Builtin::BIwmemcmp || ID == Builtin::BI__builtin_wmemcmp);
- auto getElemType = [](const Pointer &P) -> QualType {
- const Descriptor *Desc = P.getFieldDesc();
- QualType T = Desc->getType();
- if (T->isPointerType())
- return T->getAs<PointerType>()->getPointeeType();
- if (Desc->isArray())
- return Desc->getElemQualType();
- return T;
- };
-
const ASTContext &ASTCtx = S.getASTContext();
QualType ElemTypeA = getElemType(PtrA);
QualType ElemTypeB = getElemType(PtrB);
diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp
index 665e87bb5d2c8..c83f5579fd55f 100644
--- a/clang/lib/AST/ByteCode/Program.cpp
+++ b/clang/lib/AST/ByteCode/Program.cpp
@@ -166,7 +166,7 @@ unsigned Program::getOrCreateDummy(const DeclTy &D) {
Descriptor *Desc;
if (std::optional<PrimType> T = Ctx.classify(QT))
- Desc = createDescriptor(D, *T, std::nullopt, /*IsTemporary=*/true,
+ Desc = createDescriptor(D, *T, nullptr, std::nullopt, /*IsTemporary=*/true,
/*IsMutable=*/false);
else
Desc = createDescriptor(D, QT.getTypePtr(), std::nullopt,
@@ -244,7 +244,8 @@ std::optional<unsigned> Program::createGlobal(const DeclTy &D, QualType Ty,
const bool IsConst = Ty.isConstQualified();
const bool IsTemporary = D.dyn_cast<const Expr *>();
if (std::optional<PrimType> T = Ctx.classify(Ty))
- Desc = createDescriptor(D, *T, Descriptor::GlobalMD, IsConst, IsTemporary);
+ Desc = createDescriptor(D, *T, nullptr, Descriptor::GlobalMD, IsConst,
+ IsTemporary);
else
Desc = createDescriptor(D, Ty.getTypePtr(), Descriptor::GlobalMD, IsConst,
IsTemporary);
@@ -365,7 +366,7 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
const bool IsMutable = FD->isMutable();
const Descriptor *Desc;
if (std::optional<PrimType> T = Ctx.classify(FT)) {
- Desc = createDescriptor(FD, *T, std::nullopt, IsConst,
+ Desc = createDescriptor(FD, *T, nullptr, std::nullopt, IsConst,
/*isTemporary=*/false, IsMutable);
} else {
Desc = createDescriptor(FD, FT.getTypePtr(), std::nullopt, IsConst,
diff --git a/clang/lib/AST/ByteCode/Program.h b/clang/lib/AST/ByteCode/Program.h
index d503652abb96f..ce206260c702a 100644
--- a/clang/lib/AST/ByteCode/Program.h
+++ b/clang/lib/AST/ByteCode/Program.h
@@ -115,11 +115,13 @@ class Program final {
Record *getOrCreateRecord(const RecordDecl *RD);
/// Creates a descriptor for a primitive type.
- Descriptor *createDescriptor(const DeclTy &D, PrimType Type,
+ Descriptor *createDescriptor(const DeclTy &D, PrimType T,
+ const Type *SourceTy = nullptr,
Descriptor::MetadataSize MDSize = std::nullopt,
bool IsConst = false, bool IsTemporary = false,
bool IsMutable = false) {
- return allocateDescriptor(D, Type, MDSize, IsConst, IsTemporary, IsMutable);
+ return allocateDescriptor(D, SourceTy, T, MDSize, IsConst, IsTemporary,
+ IsMutable);
}
/// Creates a descriptor for a composite type.
diff --git a/clang/test/AST/ByteCode/placement-new.cpp b/clang/test/AST/ByteCode/placement-new.cpp
index c353162a7aab0..14b893c7e587b 100644
--- a/clang/test/AST/ByteCode/placement-new.cpp
+++ b/clang/test/AST/ByteCode/placement-new.cpp
@@ -376,3 +376,18 @@ constexpr int N = [] // expected-error {{must be initialized by a constant expre
return s.a[0];
}();
#endif
+
+namespace MemMove {
+ constexpr int foo() {
+ int *a = std::allocator<int>{}.allocate(1);
+ new(a) int{123};
+
+ int b;
+ __builtin_memmove(&b, a, sizeof(int));
+
+ std::allocator<int>{}.deallocate(a);
+ return b;
+ }
+
+ static_assert(foo() == 123);
+}
More information about the cfe-commits
mailing list