Skip to content

Commit 74cab54

Browse files
Reapply "[Clang][Sema] placement new initializes typedef array with correct size (#83124)" (#89036)
When in-place new-ing a local variable of an array of trivial type, the generated code calls 'memset' with the correct size of the array, earlier it was generating size (squared of the typedef array + size). The cause: typedef TYPE TArray[8]; TArray x; The type of declarator is Tarray[8] and in SemaExprCXX.cpp::BuildCXXNew we check if it's of typedef and of constant size then we get the original type and it works fine for non-dependent cases. But in case of template we do TreeTransform.h:TransformCXXNEWExpr and there we again check the allocated type which is TArray[8] and it stays that way, so ArraySize=(Tarray[8] type, alloc Tarray[8*type]) so the squared size allocation. ArraySize gets calculated earlier in TreeTransform.h so that if(!ArraySize) condition was failing. fix: I changed that condition to if(ArraySize). fixes #41441 --------- Co-authored-by: erichkeane <[email protected]>
1 parent 282ab54 commit 74cab54

File tree

4 files changed

+47
-2
lines changed

4 files changed

+47
-2
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ Bug Fixes to C++ Support
557557
- Fix a crash in requires expression with templated base class member function. Fixes (#GH84020).
558558
- Fix a crash caused by defined struct in a type alias template when the structure
559559
has fields with dependent type. Fixes (#GH75221).
560+
- Fix placement new initializes typedef array with correct size. Fixes (#GH41441).
560561
- Fix the Itanium mangling of lambdas defined in a member of a local class (#GH88906)
561562
- Fixed a crash when trying to evaluate a user-defined ``static_assert`` message whose ``size()``
562563
function returns a large or negative value. Fixes (#GH89407).

clang/lib/Sema/TreeTransform.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12943,6 +12943,19 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
1294312943
ArraySize = NewArraySize.get();
1294412944
}
1294512945

12946+
// Per C++0x [expr.new]p5, the type being constructed may be a
12947+
// typedef of an array type.
12948+
QualType AllocType = AllocTypeInfo->getType();
12949+
if (ArraySize && E->isTypeDependent()) {
12950+
if (const ConstantArrayType *Array =
12951+
SemaRef.Context.getAsConstantArrayType(AllocType)) {
12952+
ArraySize = IntegerLiteral::Create(SemaRef.Context, Array->getSize(),
12953+
SemaRef.Context.getSizeType(),
12954+
E->getBeginLoc());
12955+
AllocType = Array->getElementType();
12956+
}
12957+
}
12958+
1294612959
// Transform the placement arguments (if any).
1294712960
bool ArgumentChanged = false;
1294812961
SmallVector<Expr*, 8> PlacementArgs;
@@ -13004,7 +13017,6 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
1300413017
return E;
1300513018
}
1300613019

13007-
QualType AllocType = AllocTypeInfo->getType();
1300813020
if (!ArraySize) {
1300913021
// If no array size was specified, but the new expression was
1301013022
// instantiated with an array type (e.g., "new T" where T is

clang/lib/Serialization/ASTWriter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5097,7 +5097,7 @@ void ASTWriter::WriteSpecialDeclRecords(Sema &SemaRef) {
50975097
DeclsToCheckForDeferredDiags.push_back(getDeclID(D));
50985098
if (!DeclsToCheckForDeferredDiags.empty())
50995099
Stream.EmitRecord(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS,
5100-
DeclsToCheckForDeferredDiags);
5100+
DeclsToCheckForDeferredDiags);
51015101

51025102
// Write the record containing CUDA-specific declaration references.
51035103
RecordData CUDASpecialDeclRefs;

clang/test/SemaCXX/PR41441.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %clang --target=x86_64-pc-linux -S -fno-discard-value-names -emit-llvm -o - %s | FileCheck %s
2+
3+
namespace std {
4+
using size_t = decltype(sizeof(int));
5+
};
6+
void* operator new[](std::size_t, void*) noexcept;
7+
8+
// CHECK: call void @llvm.memset.p0.i64(ptr align 1 %x, i8 0, i64 8, i1 false)
9+
// CHECK: call void @llvm.memset.p0.i64(ptr align 16 %x, i8 0, i64 32, i1 false)
10+
template <typename TYPE>
11+
void f()
12+
{
13+
typedef TYPE TArray[8];
14+
15+
TArray x;
16+
new(&x) TArray();
17+
}
18+
19+
template <typename T>
20+
void f1() {
21+
int (*x)[1] = new int[1][1];
22+
}
23+
template void f1<char>();
24+
void f2() {
25+
int (*x)[1] = new int[1][1];
26+
}
27+
28+
int main()
29+
{
30+
f<char>();
31+
f<int>();
32+
}

0 commit comments

Comments
 (0)