This allows catching OOB accesses inside `unique_ptr<T[]>` when the size of the allocation is known. The size of the allocation can be known when the unique_ptr has been created with make_unique & friends or when the type necessitates an array cookie before the allocation. This is a re-aplpication of45a09d181which had been reverted inf11abac6due to unrelated CI failures.
94 lines
2.0 KiB
C++
94 lines
2.0 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// <memory>
|
|
|
|
// unique_ptr
|
|
|
|
// Make sure that we can form unique_ptrs to incomplete types and perform restricted
|
|
// operations on them. This requires setting up a TU where the type is complete and
|
|
// the unique_ptr is created and destroyed, and a TU where the type is incomplete and
|
|
// we check that a restricted set of operations can be performed on the unique_ptr.
|
|
|
|
// RUN: %{cxx} %s %{flags} %{compile_flags} -c -o %t.tu1.o -DCOMPLETE
|
|
// RUN: %{cxx} %s %{flags} %{compile_flags} -c -o %t.tu2.o -DINCOMPLETE
|
|
// RUN: %{cxx} %t.tu1.o %t.tu2.o %{flags} %{link_flags} -o %t.exe
|
|
// RUN: %{exec} %t.exe
|
|
|
|
#include <memory>
|
|
#include <cassert>
|
|
|
|
struct T;
|
|
extern void use(std::unique_ptr<T>& ptr);
|
|
extern void use(std::unique_ptr<T[]>& ptr);
|
|
|
|
#ifdef INCOMPLETE
|
|
|
|
void use(std::unique_ptr<T>& ptr) {
|
|
{
|
|
T* x = ptr.get();
|
|
assert(x != nullptr);
|
|
}
|
|
{
|
|
T& ref = *ptr;
|
|
assert(&ref == ptr.get());
|
|
}
|
|
{
|
|
bool engaged = static_cast<bool>(ptr);
|
|
assert(engaged);
|
|
}
|
|
{
|
|
assert(ptr == ptr);
|
|
assert(!(ptr != ptr));
|
|
assert(!(ptr < ptr));
|
|
assert(!(ptr > ptr));
|
|
assert(ptr <= ptr);
|
|
assert(ptr >= ptr);
|
|
}
|
|
}
|
|
|
|
void use(std::unique_ptr<T[]>& ptr) {
|
|
{
|
|
T* x = ptr.get();
|
|
assert(x != nullptr);
|
|
}
|
|
{
|
|
bool engaged = static_cast<bool>(ptr);
|
|
assert(engaged);
|
|
}
|
|
{
|
|
assert(ptr == ptr);
|
|
assert(!(ptr != ptr));
|
|
assert(!(ptr < ptr));
|
|
assert(!(ptr > ptr));
|
|
assert(ptr <= ptr);
|
|
assert(ptr >= ptr);
|
|
}
|
|
}
|
|
|
|
#endif // INCOMPLETE
|
|
|
|
#ifdef COMPLETE
|
|
|
|
struct T {}; // complete the type
|
|
|
|
int main(int, char**) {
|
|
{
|
|
std::unique_ptr<T> ptr(new T());
|
|
use(ptr);
|
|
}
|
|
|
|
{
|
|
std::unique_ptr<T[]> ptr(new T[3]());
|
|
use(ptr);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#endif // COMPLETE
|