diff options
Diffstat (limited to 'clang/lib/AST/ByteCode/Compiler.cpp')
| -rw-r--r-- | clang/lib/AST/ByteCode/Compiler.cpp | 98 |
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; |
