https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/126717
Don't return true here in InvalidNewDeleteExpr just because we are in C++26 mode. This invalid there as well. Testcase reduced from libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.create/make_unique_for_overwrite.pass.cpp >From 8a271fbd81d5f0c9b13f169a30f7ab3add5cf7ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Tue, 11 Feb 2025 12:46:27 +0100 Subject: [PATCH] [clang][bytecode] Fix diagnosing replaceable global allocator functions Don't return true here in InvalidNewDeleteExpr just because we are in C++26 mode. This invalid there as well. Testcase reduced from libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.create/make_unique_for_overwrite.pass.cpp --- clang/lib/AST/ByteCode/Interp.cpp | 32 +++++++++++++++++-------------- clang/test/AST/ByteCode/cxx26.cpp | 23 ++++++++++++++++++++-- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index bf48139f57c0f09..c80be094856b086 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -1564,34 +1564,38 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E, bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E) { assert(E); - if (S.getLangOpts().CPlusPlus26) - return true; - - const auto &Loc = S.Current->getSource(OpPC); - if (const auto *NewExpr = dyn_cast<CXXNewExpr>(E)) { const FunctionDecl *OperatorNew = NewExpr->getOperatorNew(); - if (!S.getLangOpts().CPlusPlus26 && NewExpr->getNumPlacementArgs() > 0) { + if (NewExpr->getNumPlacementArgs() > 0) { // This is allowed pre-C++26, but only an std function. - if (S.Current->isStdFunction()) + if (S.getLangOpts().CPlusPlus26 || S.Current->isStdFunction()) return true; - S.FFDiag(Loc, diag::note_constexpr_new_placement) + S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_new_placement) << /*C++26 feature*/ 1 << E->getSourceRange(); - } else if (NewExpr->getNumPlacementArgs() == 1 && - !OperatorNew->isReservedGlobalPlacementOperator()) { - S.FFDiag(Loc, diag::note_constexpr_new_placement) - << /*Unsupported*/ 0 << E->getSourceRange(); } else if (!OperatorNew->isReplaceableGlobalAllocationFunction()) { - S.FFDiag(Loc, diag::note_constexpr_new_non_replaceable) + S.FFDiag(S.Current->getSource(OpPC), + diag::note_constexpr_new_non_replaceable) << isa<CXXMethodDecl>(OperatorNew) << OperatorNew; + return false; + } else if (!S.getLangOpts().CPlusPlus26 && + NewExpr->getNumPlacementArgs() == 1 && + !OperatorNew->isReservedGlobalPlacementOperator()) { + if (!S.getLangOpts().CPlusPlus26) { + S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_new_placement) + << /*Unsupported*/ 0 << E->getSourceRange(); + return false; + } + return true; } } else { const auto *DeleteExpr = cast<CXXDeleteExpr>(E); const FunctionDecl *OperatorDelete = DeleteExpr->getOperatorDelete(); if (!OperatorDelete->isReplaceableGlobalAllocationFunction()) { - S.FFDiag(Loc, diag::note_constexpr_new_non_replaceable) + S.FFDiag(S.Current->getSource(OpPC), + diag::note_constexpr_new_non_replaceable) << isa<CXXMethodDecl>(OperatorDelete) << OperatorDelete; + return false; } } diff --git a/clang/test/AST/ByteCode/cxx26.cpp b/clang/test/AST/ByteCode/cxx26.cpp index 0b0e2b21e8201e7..2ac3b21695ddd80 100644 --- a/clang/test/AST/ByteCode/cxx26.cpp +++ b/clang/test/AST/ByteCode/cxx26.cpp @@ -1,10 +1,29 @@ // RUN: %clang_cc1 -std=c++26 -fsyntax-only -fcxx-exceptions -verify=ref,both %s // RUN: %clang_cc1 -std=c++26 -fsyntax-only -fcxx-exceptions -verify=expected,both %s -fexperimental-new-constant-interpreter -// both-no-diagnostics - namespace VoidCast { constexpr void* p = nullptr; constexpr int* q = static_cast<int*>(p); static_assert(q == nullptr); } + +namespace ReplaceableAlloc { + struct F { + static void* operator new(unsigned long n) { + return nullptr; // both-warning {{should not return a null pointer}} + } + }; + + constexpr F *createF() { + return new F(); // both-note {{call to class-specific 'operator new'}} + } + + constexpr bool foo() { + F *f = createF(); // both-note {{in call to}} + + delete f; + return true; + } + static_assert(foo()); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits