Skip to content

[Clang][Sema] placement new initializes typedef array with correct size #83124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,8 @@ Bug Fixes to C++ Support
Fixes (#GH70604), (#GH79754), (#GH84163), (#GH84425), (#GH86054), (#GH86398), and (#GH86399).
- Fix a crash when deducing ``auto`` from an invalid dereference (#GH88329).
- Fix a crash in requires expression with templated base class member function. Fixes (#GH84020).
- placement new initializes typedef array with correct size
(`#GH41441 <https://github.com/llvm/llvm-project/issues/41441>`_)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
14 changes: 13 additions & 1 deletion clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -12802,6 +12802,19 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
ArraySize = NewArraySize.get();
}

// Per C++0x [expr.new]p5, the type being constructed may be a
// typedef of an array type.
Copy link
Collaborator

Choose a reason for hiding this comment

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

This comment doesn't really match what is happening below? the 'if' is still based on 'ArraySize' (presumably you mean this to be a proxy for E->isArray?). But there is no standardeeze quoted here about why you'd pick up the size/alloc type from it like this, rather than in the E->isArray above.

Also, does this also handle cases where this is going to still be dependent?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, you're right. It's proxy for E->isArray(), but the condition just before checks if it's Array and then calculates the ArraySize. I didn't want to check again and used the ArraySize calculated before. If the earlier condition E->isArray() fails then ArraySize won't be calculated and if(ArraySize) would also fail. In Typedef case Tarray x; the alloctype is Tarray for x, that's why using Tarray Element Type which is int, and using that as allocType. Yes, this is for dependent cases only.

Copy link
Collaborator

Choose a reason for hiding this comment

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

So it seems this should probably be inside of that E->isArray() block instead then?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it can be inside that block, but in the non-dependent it was outside the block to check for typedef so I followed the same thing here as well. It's in Sema::SemaExprCXX::BuildNEWCXX.

QualType AllocType = AllocTypeInfo->getType();
if (ArraySize) {
if (const ConstantArrayType *Array =
SemaRef.Context.getAsConstantArrayType(AllocType)) {
ArraySize = IntegerLiteral::Create(SemaRef.Context, Array->getSize(),
SemaRef.Context.getSizeType(),
E->getBeginLoc());
AllocType = Array->getElementType();
}
}

// Transform the placement arguments (if any).
bool ArgumentChanged = false;
SmallVector<Expr*, 8> PlacementArgs;
Expand Down Expand Up @@ -12863,7 +12876,6 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
return E;
}

QualType AllocType = AllocTypeInfo->getType();
if (!ArraySize) {
// If no array size was specified, but the new expression was
// instantiated with an array type (e.g., "new T" where T is
Expand Down
20 changes: 20 additions & 0 deletions clang/test/SemaCXX/instantiate-new-placement-size.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// RUN: %clang -S -fno-discard-value-names -emit-llvm -o - %s | FileCheck %s
// Issue no: 41441
#include <new>

// CHECK: call void @llvm.memset.p0.i64(ptr align 1 %x, i8 0, i64 8, i1 false)
// CHECK: call void @llvm.memset.p0.i64(ptr align 16 %x, i8 0, i64 32, i1 false)
template <typename TYPE>
void f()
{
typedef TYPE TArray[8];

TArray x;
new(&x) TArray();
}

int main()
{
f<char>();
f<int>();
}