summaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode/Compiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ByteCode/Compiler.cpp')
-rw-r--r--clang/lib/AST/ByteCode/Compiler.cpp98
1 files changed, 67 insertions, 31 deletions
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 68c3cdff712f..e89863a231be 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -3097,12 +3097,11 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
QualType ElementType = E->getAllocatedType();
std::optional<PrimType> ElemT = classify(ElementType);
unsigned PlacementArgs = E->getNumPlacementArgs();
+ const FunctionDecl *OperatorNew = E->getOperatorNew();
+ const Expr *PlacementDest = nullptr;
bool IsNoThrow = false;
- // FIXME: Better diagnostic. diag::note_constexpr_new_placement
if (PlacementArgs != 0) {
- // The only new-placement list we support is of the form (std::nothrow).
- //
// FIXME: There is no restriction on this, but it's not clear that any
// other form makes any sense. We get here for cases such as:
//
@@ -3111,27 +3110,43 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
// (which should presumably be valid only if N is a multiple of
// alignof(int), and in any case can't be deallocated unless N is
// alignof(X) and X has new-extended alignment).
- if (PlacementArgs != 1 || !E->getPlacementArg(0)->getType()->isNothrowT())
- return this->emitInvalid(E);
+ if (PlacementArgs == 1) {
+ const Expr *Arg1 = E->getPlacementArg(0);
+ if (Arg1->getType()->isNothrowT()) {
+ if (!this->discard(Arg1))
+ return false;
+ IsNoThrow = true;
+ } else if (Ctx.getLangOpts().CPlusPlus26 &&
+ OperatorNew->isReservedGlobalPlacementOperator()) {
+ // If we have a placement-new destination, we'll later use that instead
+ // of allocating.
+ PlacementDest = Arg1;
+ } else {
+ return this->emitInvalidNewDeleteExpr(E, E);
+ }
- if (!this->discard(E->getPlacementArg(0)))
- return false;
- IsNoThrow = true;
+ } else {
+ return this->emitInvalid(E);
+ }
+ } else if (!OperatorNew->isReplaceableGlobalAllocationFunction()) {
+ return this->emitInvalidNewDeleteExpr(E, E);
}
const Descriptor *Desc;
- if (ElemT) {
- if (E->isArray())
- Desc = nullptr; // We're not going to use it in this case.
- else
- Desc = P.createDescriptor(E, *ElemT, Descriptor::InlineDescMD,
- /*IsConst=*/false, /*IsTemporary=*/false,
- /*IsMutable=*/false);
- } else {
- Desc = P.createDescriptor(
- E, ElementType.getTypePtr(),
- E->isArray() ? std::nullopt : Descriptor::InlineDescMD,
- /*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false, Init);
+ if (!PlacementDest) {
+ if (ElemT) {
+ if (E->isArray())
+ Desc = nullptr; // We're not going to use it in this case.
+ else
+ Desc = P.createDescriptor(E, *ElemT, Descriptor::InlineDescMD,
+ /*IsConst=*/false, /*IsTemporary=*/false,
+ /*IsMutable=*/false);
+ } else {
+ Desc = P.createDescriptor(
+ E, ElementType.getTypePtr(),
+ E->isArray() ? std::nullopt : Descriptor::InlineDescMD,
+ /*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false, Init);
+ }
}
if (E->isArray()) {
@@ -3148,26 +3163,42 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
PrimType SizeT = classifyPrim(Stripped->getType());
- if (!this->visit(Stripped))
- return false;
-
- if (ElemT) {
- // N primitive elements.
- if (!this->emitAllocN(SizeT, *ElemT, E, IsNoThrow, E))
+ if (PlacementDest) {
+ if (!this->visit(PlacementDest))
+ return false;
+ if (!this->visit(Stripped))
+ return false;
+ if (!this->emitCheckNewTypeMismatchArray(SizeT, E, E))
return false;
} else {
- // N Composite elements.
- if (!this->emitAllocCN(SizeT, Desc, IsNoThrow, E))
+ if (!this->visit(Stripped))
return false;
+
+ if (ElemT) {
+ // N primitive elements.
+ if (!this->emitAllocN(SizeT, *ElemT, E, IsNoThrow, E))
+ return false;
+ } else {
+ // N Composite elements.
+ if (!this->emitAllocCN(SizeT, Desc, IsNoThrow, E))
+ return false;
+ }
}
if (Init && !this->visitInitializer(Init))
return false;
} else {
- // Allocate just one element.
- if (!this->emitAlloc(Desc, E))
- return false;
+ if (PlacementDest) {
+ if (!this->visit(PlacementDest))
+ return false;
+ if (!this->emitCheckNewTypeMismatch(E, E))
+ return false;
+ } else {
+ // Allocate just one element.
+ if (!this->emitAlloc(Desc, E))
+ return false;
+ }
if (Init) {
if (ElemT) {
@@ -3194,6 +3225,11 @@ template <class Emitter>
bool Compiler<Emitter>::VisitCXXDeleteExpr(const CXXDeleteExpr *E) {
const Expr *Arg = E->getArgument();
+ const FunctionDecl *OperatorDelete = E->getOperatorDelete();
+
+ if (!OperatorDelete->isReplaceableGlobalAllocationFunction())
+ return this->emitInvalidNewDeleteExpr(E, E);
+
// Arg must be an lvalue.
if (!this->visit(Arg))
return false;