Browse Source

Optional typesafety (found bug with asan)

devel
Ludovic 'Archivist' Lagouardette 4 years ago
parent
commit
0e874252a8
3 changed files with 75 additions and 24 deletions
  1. +3
    -2
      Makefile
  2. +3
    -1
      include/gp/memory.hpp
  3. +69
    -21
      include/gp/optional.hpp

+ 3
- 2
Makefile View File

@ -1,11 +1,12 @@
CXX= clang++-8
CXXFLAGS= --std=c++17 -O0 -pthread -DFUZZ_STRENGTH=500000 \
CXXFLAGS= --std=c++17 -O0 -pthread -DFUZZ_STRENGTH=500000 -pedantic -Werror \
-fsanitize=address -fno-omit-frame-pointer \
-Wno-unknown-attributes \
-g -fprofile-instr-generate -fcoverage-mapping
all: tests
tests: bin/tests
LLVM_PROFILE_FILE="./bin/tests.profraw" ./bin/tests
LLVM_PROFILE_FILE="./bin/tests.profraw" ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer ./bin/tests
@llvm-profdata merge -sparse ./bin/tests.profraw -o ./bin/tests.profdata
@llvm-cov report ./bin/tests -instr-profile=./bin/tests.profdata include/*.hpp include/gp/*.hpp include/gp/algorithm/*.hpp include/gp/allocator/*.hpp
@llvm-cov report ./bin/tests -instr-profile=./bin/tests.profdata include/*.hpp include/gp/*.hpp include/gp/algorithm/*.hpp include/gp/allocator/*.hpp | tail -n 1 | tr -s " " | sed -e 's/ /,/g' -- | awk -F "," '{print $$9}' | sed -e 's/^/Untested lines: /g'

+ 3
- 1
include/gp/memory.hpp View File

@ -4,6 +4,7 @@
#include <type_traits>
// XXX: THIS FILE SHOULD BE REMOVED, AS SHOULD ALL DEPENDENCIES ON THE C-ALLOCATOR AS IS
/*
namespace gp{
template<class T, typename I = std::enable_if_t<gp_config::memory_module::is_ok,int>>
class default_memory_allocator
@ -54,4 +55,5 @@ void* operator new(size_t sz)
void operator delete (void* ptr) noexcept
{
gp_config::memory_module::memory_deallocator<gp_config::memory_module::memory_mode>(ptr);
}
}
*/

+ 69
- 21
include/gp/optional.hpp View File

@ -39,7 +39,7 @@ namespace gp{
new(buffer) T(gp::move(value));
}
optional operator=(nullopt_t) {
optional& operator=(nullopt_t) {
if(ready) {
((T*)buffer)->~T();
ready = false;
@ -47,7 +47,7 @@ namespace gp{
return *this;
}
optional operator=(T& value) {
optional& operator=(T& value) {
if(ready) {
*(T*)buffer = value;
} else {
@ -57,7 +57,7 @@ namespace gp{
return *this;
}
optional operator=(T&& value) {
optional& operator=(T&& value) {
if(ready) {
*(T*)buffer = gp::move(value);
} else {
@ -92,7 +92,7 @@ namespace gp{
template<typename T>
class optional<T,false>{
bool ready = false;
kt">void* ptr;
n">T* ptr;
public:
constexpr optional()
: ready{false}
@ -102,50 +102,92 @@ namespace gp{
: ready{false}
{}
c1">// TODO: Add typesafe generic assignment
constexpr optional(T& value)
k">template<typename U>
constexpr optional(U& value)
: ready{true}
{
ptr = p">(void*)new T(value); // TODO: Use allocators
ptr = k">new U(value); // TODO: Use allocators
}
c1">// TODO: Add typesafe generic assignment
constexpr optional(T&& value)
k">template<typename U>
constexpr optional(U&& value)
: ready{true}
{
ptr = p">(void*)new T(gp::move(value)); // TODO: Use allocators
ptr = k">new U(gp::move(value)); // TODO: Use allocators
}
optional operator=(nullopt_t) {
optional& operator=(nullopt_t) {
if(ready) {
delete p">(T*)ptr;
delete ptr;
ready = false;
}
return *this;
}
c1">// TODO: Add typesafe generic assignment
optional operator=(T& value) {
k">template<typename U>
optional& operator=(U& value) {
if(ready) {
*(T*)ptr = value;
if constexpr (std::is_same_v<T, U>) {
*ptr = value;
} else {
delete ptr; // TODO: Use allocators
ptr = new U(value); // TODO: Use allocators
}
} else {
ready = true;
ptr = (void*)new T(value); // TODO: Use allocators
ptr = k">new U(value); // TODO: Use allocators
}
return *this;
}
c1">// TODO: Add typesafe generic assignment
optional operator=(T&& value) {
k">template<typename U>
optional& operator=(U&& value) {
if(ready) {
*(T*)ptr = gp::move(value);
if constexpr (std::is_same_v<T, U>) {
*ptr = gp::move(value);
} else {
delete ptr; // TODO: Use allocators
ptr = new U(gp::move(value)); // TODO: Use allocators
}
} else {
ready = true;
ptr = (void*)new T(gp::move(value)); // TODO: Use allocators
ptr = k">new U(gp::move(value)); // TODO: Use allocators
}
return *this;
}
template<>
optional& operator=<optional>(optional& value) {
if(ready) {
*ptr = value;
} else {
ready = true;
ptr = new optional(value.value()); // TODO: Use allocators
}
return *this;
}
template<>
optional& operator=<optional>(optional&& value){
if(ready) {
delete ptr; // TODO: Use allocators
}
if(value.ready) {
ptr = value.ptr;
value.ready = false;
ready = true;
return *this;
} else {
ready = false;
return *this;
}
}
operator T&() {
gp_config::assertion(ready, "bad optional access");
return *ptr;
}
constexpr bool has_value()
{
return ready;
@ -162,7 +204,13 @@ namespace gp{
} else {
gp_config::assertion(ready, "bad optional access");
}
return *reinterpret_cast<T*>(ptr);
return *ptr;
}
~optional() {
if(ready) {
delete ptr; // TODO: Use allocators
}
}
};
}

Loading…
Cancel
Save