llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> --- Full diff: https://github.com/llvm/llvm-project/pull/196916.diff 4 Files Affected: - (modified) clang/lib/AST/ByteCode/Compiler.cpp (+4-4) - (modified) clang/lib/AST/ByteCode/Interp.h (+16) - (modified) clang/lib/AST/ByteCode/Opcodes.td (+1) - (modified) clang/test/AST/ByteCode/new-delete.cpp (+20) ``````````diff diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index bcdbd68731ee5..381be6ef0a12c 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -2205,16 +2205,16 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits, } if (QT->isArrayType()) { - if (Inits.size() == 1 && QT == Inits[0]->getType()) - return this->delegate(Inits[0]); - const ConstantArrayType *CAT = Ctx.getASTContext().getAsConstantArrayType(QT); uint64_t NumElems = CAT->getZExtSize(); - if (!this->emitCheckArraySize(NumElems, E)) + if (Initializing && !this->emitCheckArrayDestSize(NumElems, E)) return false; + if (Inits.size() == 1 && QT == Inits[0]->getType()) + return this->delegate(Inits[0]); + OptPrimType InitT = classify(CAT->getElementType()); unsigned ElementIndex = 0; for (const Expr *Init : Inits) { diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 4a550fdd63bfb..327fac7ef8adb 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -3742,6 +3742,22 @@ inline bool CheckDecl(InterpState &S, CodePtr OpPC, const VarDecl *VD) { return true; } +/// Check if the destination array we're initializing can hold the \p NumElems +/// elements. +inline bool CheckArrayDestSize(InterpState &S, CodePtr OpPC, size_t NumElems) { + if (!CheckArraySize(S, OpPC, NumElems)) + return false; + + const Pointer &Ptr = S.Stk.peek<Pointer>(); + if (!Ptr.isUnknownSizeArray() && NumElems > Ptr.getNumElems()) { + S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_new_too_small) + << Ptr.getNumElems() << NumElems; + return false; + } + + return true; +} + inline bool Alloc(InterpState &S, CodePtr OpPC, const Descriptor *Desc) { assert(Desc); diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td index 3fb25a5fa0884..e0f48e3d08ca4 100644 --- a/clang/lib/AST/ByteCode/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -454,6 +454,7 @@ def CheckLiteralType : Opcode { } def CheckArraySize : Opcode { let Args = [ArgUint64]; } +def CheckArrayDestSize : Opcode { let Args = [ArgUint64]; } def CheckFunctionDecl : Opcode { let Args = [ArgFunctionDecl]; } def CheckBitCast : Opcode { let Args = [ArgTypePtr, ArgBool]; } diff --git a/clang/test/AST/ByteCode/new-delete.cpp b/clang/test/AST/ByteCode/new-delete.cpp index ac2c2ff4a73c6..b6e6d333a4bcb 100644 --- a/clang/test/AST/ByteCode/new-delete.cpp +++ b/clang/test/AST/ByteCode/new-delete.cpp @@ -1197,6 +1197,26 @@ namespace vdtor { static_assert(vdtor_3(3) == 3); } +namespace ArrayDestSize { + template<typename T> + constexpr T dynarray(int elems, int i) { + T *p; + if constexpr (sizeof(T) == 1) + p = new T[elems]{"fox"}; // both-note {{evaluated array bound 3 is too small to hold 4 explicitly initialized elements}} + else + p = new T[elems]{1, 2, 3}; // both-note {{evaluated array bound 2 is too small to hold 3 explicitly initialized elements}} + T n = p[i]; // both-note 4{{past-the-end}} + delete [] p; + return n; + } + static_assert(dynarray<int>(4, 4) == 0); // both-error {{constant expression}} both-note {{in call}} + static_assert(dynarray<int>(3, 3) == 0); // both-error {{constant expression}} both-note {{in call}} + static_assert(dynarray<int>(2, 1) == 0); // both-error {{constant expression}} both-note {{in call}} + static_assert(dynarray<char>(5, 5) == 0); // both-error {{constant expression}} both-note {{in call}} + static_assert(dynarray<char>(4, 4) == 0); // both-error {{constant expression}} both-note {{in call}} + static_assert(dynarray<char>(3, 2) == 'x'); // both-error {{constant expression}} both-note {{in call}} +} + #else /// Make sure we reject this prior to C++20 constexpr int a() { // both-error {{never produces a constant expression}} `````````` </details> https://github.com/llvm/llvm-project/pull/196916 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
