[clang] 9387fd9 - [clang][bytecode] Fix diagnosing replaceable global allocator functions (#126717)

via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 11 07:51:25 PST 2025


Author: Timm Baeder
Date: 2025-02-11T16:51:21+01:00
New Revision: 9387fd96314c59fc9aff1a82e478f9b89a97c20a

URL: https://github.com/llvm/llvm-project/commit/9387fd96314c59fc9aff1a82e478f9b89a97c20a
DIFF: https://github.com/llvm/llvm-project/commit/9387fd96314c59fc9aff1a82e478f9b89a97c20a.diff

LOG: [clang][bytecode] Fix diagnosing replaceable global allocator functions (#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

Added: 
    

Modified: 
    clang/lib/AST/ByteCode/Interp.cpp
    clang/test/AST/ByteCode/cxx26.cpp

Removed: 
    


################################################################################
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..cd6b5330650100e 100644
--- a/clang/test/AST/ByteCode/cxx26.cpp
+++ b/clang/test/AST/ByteCode/cxx26.cpp
@@ -1,10 +1,33 @@
 // 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 std {
+  using size_t = decltype(sizeof(0));
+}
 
 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(std::size_t 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