Skip to content

[Clang][Sema] Fix templated array size calculation. #96464

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 12 commits into from
Oct 15, 2024
Merged
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@ Bug Fixes to C++ Support
- Fixed overload handling for object parameters with top-level cv-qualifiers in explicit member functions (#GH100394)
- Fixed a bug in lambda captures where ``constexpr`` class-type objects were not properly considered ODR-used in
certain situations. (#GH47400), (#GH90896)
- Fix erroneous templated array size calculation leading to crashes in generated code. (#GH41441)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2157,7 +2157,8 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,

// Per C++0x [expr.new]p5, the type being constructed may be a
// typedef of an array type.
if (!ArraySize) {
// Dependent case will be handled separately.
if (!ArraySize && !AllocType->isDependentType()) {
if (const ConstantArrayType *Array
= Context.getAsConstantArrayType(AllocType)) {
ArraySize = IntegerLiteral::Create(Context, Array->getSize(),
Expand Down
46 changes: 46 additions & 0 deletions clang/test/SemaCXX/GH41441.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// RUN: %clang --target=x86_64-pc-linux -S -fno-discard-value-names -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 %s -fsyntax-only -verify

namespace std {
using size_t = decltype(sizeof(int));
};
void* operator new[](std::size_t, void*) noexcept;

// 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();
}

template <typename T>
void f1() {
int (*x)[1] = new int[1][1];
}
template void f1<char>();
void f2() {
int (*x)[1] = new int[1][1];
}

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

// expected-no-diagnostics
template <typename T> struct unique_ptr {unique_ptr(T* p){}};

template <typename T>
unique_ptr<T> make_unique(unsigned long long n) {
return unique_ptr<T>(new T[n]());
}

auto boro(int n){
typedef double HistoryBuffer[4];
return make_unique<HistoryBuffer>(n);
}