Skip to content
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

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

Merged
merged 12 commits into from
Oct 15, 2024
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ Bug Fixes to C++ Support
- Avoided a redundant friend declaration instantiation under a certain ``consteval`` context. (#GH107175)
- Fixed an assertion failure in debug mode, and potential crashes in release mode, when
diagnosing a failed cast caused indirectly by a failed implicit conversion to the type of the constructor parameter.
- 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 @@ -2151,7 +2151,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);
}
Loading