Skip to content

Conversation

@Fznamznon
Copy link
Contributor

During additional testing I spotted that vector deleting dtor calls operator delete, not operator delete[] when performing array deletion. This patch fixes that.

During additional testing I spotted that vector deleting dtor calls
operator delete, not operator delete[] when performing array deletion.
This patch fixes that.
@Fznamznon Fznamznon requested review from rnk, tahonermann and zmodem April 1, 2025 17:59
@github-actions
Copy link

github-actions bot commented Apr 1, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Collaborator

@rnk rnk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks good to me!

@Fznamznon Fznamznon merged commit 8a691cc into llvm:main Apr 2, 2025
11 checks passed
@DKLoehr
Copy link
Contributor

DKLoehr commented Apr 8, 2025

We're seeing several errors building chromium that bisect to this change: error: member 'operator delete[]' found in multiple base classes of different types. An example build is here; the output is

../../third_party/pdfium/xfa/fxfa/cxfa_ffexclgroup.cpp:16:19: error: member 'operator delete[]' found in multiple base classes of different types
   16 | CXFA_FFExclGroup::~CXFA_FFExclGroup() = default;
      |                   ^
../../third_party/pdfium/xfa/fxfa/cxfa_ffexclgroup.cpp:16:41: note: in defaulted destructor for 'CXFA_FFExclGroup' first required here
   16 | CXFA_FFExclGroup::~CXFA_FFExclGroup() = default;
      |                                         ^
../../v8/include/cppgc/garbage-collected.h:69:8: note: member found by ambiguous name lookup
   69 |   void operator delete[](void*) = delete;
      |        ^
../../v8/include/cppgc/garbage-collected.h:103:8: note: member found by ambiguous name lookup
  103 |   void operator delete[](void*) = delete;
      |        ^

I'm working on putting together a minimal repro.

@Fznamznon
Copy link
Contributor Author

@DKLoehr , does clang that is being used also have #134357 in?

@DKLoehr
Copy link
Contributor

DKLoehr commented Apr 8, 2025

Yes, I've reproduced it locally with current trunk clang.

@DKLoehr
Copy link
Contributor

DKLoehr commented Apr 8, 2025

This is the smallest reproduction I could find:

struct BaseDelete1 {
  void operator delete[](void *);
};
struct BaseDelete2 {
  void operator delete[](void *);
};
struct BaseDestructor {
  virtual ~BaseDestructor() = default;
};
struct Final : BaseDelete1, BaseDelete2, BaseDestructor {};

When run with clang++ repro.cc -fsyntax-only -std=c++20, it yields the following error. Removing any one of the three base classes causes it to compile without problems.

repro.cc:10:8: error: member 'operator delete[]' found in multiple base classes of different types
   10 | struct Final : BaseDelete1, BaseDelete2, BaseDestructor {};
      |        ^
repro.cc:10:8: note: in implicit destructor for 'Final' first required here
repro.cc:2:8: note: member found by ambiguous name lookup
    2 |   void operator delete[](void *);
      |        ^
repro.cc:5:8: note: member found by ambiguous name lookup
    5 |   void operator delete[](void *);
      |        ^

@Fznamznon
Copy link
Contributor Author

Looking... Does not reproduce without c++20.

Fznamznon added a commit to Fznamznon/llvm-project that referenced this pull request Apr 9, 2025
And issue was reported in
llvm#133950 . Since we don't always
emit vector deleting dtors, only error out about ambigous operator
delete[] when it will be required for vector delering dtor emission.
@Fznamznon
Copy link
Contributor Author

I posted a PR with a potential fix.

Fznamznon added a commit that referenced this pull request Apr 10, 2025
#135041)

And issue was reported in

#133950 (comment)
. Since we don't always emit vector deleting dtors, only error out about
ambiguous operator delete[] when it will be required for vector deleting
dtor emission.
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Apr 10, 2025
…hen required (#135041)

And issue was reported in

llvm/llvm-project#133950 (comment)
. Since we don't always emit vector deleting dtors, only error out about
ambiguous operator delete[] when it will be required for vector deleting
dtor emission.
@DKLoehr
Copy link
Contributor

DKLoehr commented Apr 11, 2025

Thanks! Unfortunately it looks like the fix introduced a regression of #134265 on Windows. Repro:

struct Base {
  virtual ~Base();
  void operator delete[](void *) = delete;
};
class __declspec(dllexport) Derived : Base {};

Running clang-cl repro.cc /std:c++20 results in the following error after

repro.cc(5,29): error: attempt to use a deleted function
    5 | class __declspec(dllexport) Derived : Base {};
      |                             ^
repro.cc(5,29): note: in implicit destructor for 'Derived' first required here
repro.cc(5,18): note: due to 'Derived' being dllexported
    5 | class __declspec(dllexport) Derived : Base {};
      |                  ^
repro.cc(3,8): note: 'operator delete[]' has been explicitly marked deleted here
    3 |   void operator delete[](void *) = delete;
      |        ^

@Fznamznon
Copy link
Contributor Author

Yeah, but this is kind of expected. Otherwise it is unclear how to emit vector deleting destructor body. Should we fallback to calling something, like MSVC does? See #135041 (comment) for example.

@DKLoehr
Copy link
Contributor

DKLoehr commented Apr 11, 2025

I'm not familiar enough to say what we should be doing; perhaps @rnk or @zmodem have thoughts? It seems like we should at least emit a better error message, since just looking at the code doesn't make it clear to me why operator delete[] is relevant.

Since this is causing clang to become more restrictive, the best thing to do might be to revert to whatever we used to do in this situation, and then make a followup change which specifically explains why clang is becoming more restrictive.

@zmodem
Copy link
Collaborator

zmodem commented Apr 14, 2025

Thanks! Unfortunately it looks like the fix introduced a regression of #134265 on Windows. Repro:

(For reference, this is https://crbug.com/410000261 on our side.)

The "deleted operator delete[]" is coming from here: https://source.chromium.org/chromium/chromium/src/+/main:v8/include/cppgc/garbage-collected.h;l=61

Rejecting the code seems wrong, since that's only happening due to this extension. I'm not sure what the best option is here, but I think we should look closer at what exactly MSVC is emitting.

@Fznamznon
Copy link
Contributor Author

I'm working on a revert of the extension.

Fznamznon added a commit to Fznamznon/llvm-project that referenced this pull request Apr 14, 2025
zmodem pushed a commit that referenced this pull request Apr 14, 2025
Finding operator delete[] is still problematic, without it the extension
is a security hazard, so reverting until the problem with operator
delete[] is figured out.

This reverts the following PRs:
Reland [MS][clang] Add support for vector deleting destructors (#133451)
[MS][clang] Make sure vector deleting dtor calls correct operator delete (#133950)
[MS][clang] Fix crash on deletion of array of pointers (#134088)
[clang] Do not diagnose unused deleted operator delete[] (#134357)
[MS][clang] Error about ambiguous operator delete[] only when required (#135041)
Fznamznon added a commit to Fznamznon/llvm-project that referenced this pull request Oct 29, 2025
MSVC supports and extension allowing to delete an array of objects
via pointer whose static type doesn't match its dynamic type. This is
done via generation of special destructors - vector deleting
destructors. MSVC's virtual tables always contain pointer to vector
deleting destructor for classes with virtual destructors, so not having
this extension not having this extension implemented causes clang to generate
code that is not compatible with the code generated by MSVC, because
clang always puts pointer to a scalar deleting destructor to the vtable.
As a bonus the deletion of an array of polymorphic object will work just
like it does with MSVC - no memory leaks and correct destructors are
called.

This patch will cause clang to emit code that is compatible with code
produced by MSVC but not compatible with code produced with clang of
older versions, so the new behavior can be disabled via passing
-fclang-abi-compat=21 (or lower).

This is yet another attempt to land vector deleting destructors support
originally implemented by llvm#133451.

This PR contains fixes for issues reported in the original PR as well as
fixes for issues related to operator delete[] search reported in
several issues like
llvm#133950 (comment)
llvm#134265

Fixes llvm#19772
Fznamznon added a commit that referenced this pull request Nov 13, 2025
MSVC supports an extension allowing to delete an array of objects via
pointer whose static type doesn't match its dynamic type. This is done
via generation of special destructors - vector deleting destructors.
MSVC's virtual tables always contain a pointer to the vector deleting
destructor for classes with virtual destructors, so not having this
extension implemented causes clang to generate code that is not
compatible with the code generated by MSVC, because clang always puts a
pointer to a scalar deleting destructor to the vtable. As a bonus the
deletion of an array of polymorphic object will work just like it does
with MSVC - no memory leaks and correct destructors are called.

This patch will cause clang to emit code that is compatible with code
produced by MSVC but not compatible with code produced with clang of
older versions, so the new behavior can be disabled via passing
-fclang-abi-compat=21 (or lower).

This is yet another attempt to land vector deleting destructors support
originally implemented by
#133451.

This PR contains fixes for issues reported in the original PR as well as
fixes for issues related to operator delete[] search reported in several
issues like

#133950 (comment)
#134265

Fixes #19772
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Nov 13, 2025
…tors (#165598)

MSVC supports an extension allowing to delete an array of objects via
pointer whose static type doesn't match its dynamic type. This is done
via generation of special destructors - vector deleting destructors.
MSVC's virtual tables always contain a pointer to the vector deleting
destructor for classes with virtual destructors, so not having this
extension implemented causes clang to generate code that is not
compatible with the code generated by MSVC, because clang always puts a
pointer to a scalar deleting destructor to the vtable. As a bonus the
deletion of an array of polymorphic object will work just like it does
with MSVC - no memory leaks and correct destructors are called.

This patch will cause clang to emit code that is compatible with code
produced by MSVC but not compatible with code produced with clang of
older versions, so the new behavior can be disabled via passing
-fclang-abi-compat=21 (or lower).

This is yet another attempt to land vector deleting destructors support
originally implemented by
llvm/llvm-project#133451.

This PR contains fixes for issues reported in the original PR as well as
fixes for issues related to operator delete[] search reported in several
issues like

llvm/llvm-project#133950 (comment)
llvm/llvm-project#134265

Fixes llvm/llvm-project#19772
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants