[clang] [clang][bytecode] Fix diagnosing replaceable global allocator functions (PR #126717)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 11 03:56:44 PST 2025
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?= <tbaeder at 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}}
+}
More information about the cfe-commits
mailing list