[C++] Got rid of memset's in constructors (#5938)

* [C++] removed array's memsets from struct parametrized constructor

now POD-typed arrays are zero-initialized
and class-typed arrays are default-initialized

* [C++] memset -> zero/default initialization in default constructor

* [C++] Struct-type and array default initialization

* [C++] Newly generated tests

* [C++] forgotten test

* [C++] curly brace by code style

* [C++] test if memory is 0's after placement new

* [C++] memory leak fix

* [C++] simplifying and non-dynamic memory in test

* [C++] code cleanup

* [C++] disable old-compiler warning

* [C++] windows build fix (try)

* [C++] debug-new win build fix
This commit is contained in:
bakinovsky-m
2020-06-02 03:58:52 +03:00
committed by GitHub
parent 7179a5a8ba
commit 988164f6e1
10 changed files with 188 additions and 85 deletions

View File

@@ -2851,38 +2851,100 @@ class CppGenerator : public BaseGenerator {
static void PaddingNoop(int bits, std::string *code_ptr, int *id) {
(void)bits;
*code_ptr += " (void)padding" + NumToString((*id)++) + "__;";
*code_ptr += " (void)padding" + NumToString((*id)++) + "__;\n";
}
void GenStructDefaultConstructor(const StructDef &struct_def) {
std::string init_list;
std::string body;
bool first_in_init_list = true;
int padding_initializer_id = 0;
int padding_body_id = 0;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end();
++it) {
const auto field = *it;
const auto field_name = field->name + "_";
if (first_in_init_list) {
first_in_init_list = false;
} else {
init_list += ",";
init_list += "\n ";
}
init_list += field_name;
if (IsStruct(field->value.type) || IsArray(field->value.type)) {
// this is either default initialization of struct
// or
// implicit initialization of array
// for each object in array it:
// * sets it as zeros for POD types (integral, floating point, etc)
// * calls default constructor for classes/structs
init_list += "()";
} else {
init_list += "(0)";
}
if (field->padding) {
GenPadding(*field, &init_list, &padding_initializer_id,
PaddingInitializer);
GenPadding(*field, &body, &padding_body_id, PaddingNoop);
}
}
if (init_list.empty()) {
code_ += " {{STRUCT_NAME}}()";
code_ += " {}";
} else {
code_.SetValue("INIT_LIST", init_list);
code_.SetValue("DEFAULT_CONSTRUCTOR_BODY", body);
code_ += " {{STRUCT_NAME}}()";
code_ += " : {{INIT_LIST}} {";
code_ += "{{DEFAULT_CONSTRUCTOR_BODY}} }";
}
}
void GenStructConstructor(const StructDef &struct_def) {
std::string arg_list;
std::string init_list;
int padding_id = 0;
auto first = struct_def.fields.vec.begin();
bool first_arg = true;
bool first_init = true;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
const auto &field = **it;
const auto &field_type = field.value.type;
if (IsArray(field_type)) {
first++;
continue;
}
const auto member_name = Name(field) + "_";
const auto arg_name = "_" + Name(field);
const auto arg_type = GenTypeGet(field_type, " ", "const ", " &", true);
if (it != first) { arg_list += ", "; }
arg_list += arg_type;
arg_list += arg_name;
if (!IsArray(field_type)) {
if (it != first && init_list != "") { init_list += ",\n "; }
init_list += member_name;
if (IsScalar(field_type.base_type)) {
auto type = GenUnderlyingCast(field, false, arg_name);
init_list += "(flatbuffers::EndianScalar(" + type + "))";
if (first_arg) {
first_arg = false;
} else {
init_list += "(" + arg_name + ")";
arg_list += ", ";
}
arg_list += arg_type;
arg_list += arg_name;
}
if (first_init) {
first_init = false;
} else {
init_list += ",";
init_list += "\n ";
}
init_list += member_name;
if (IsScalar(field_type.base_type)) {
auto type = GenUnderlyingCast(field, false, arg_name);
init_list += "(flatbuffers::EndianScalar(" + type + "))";
} else if (IsArray(field_type)) {
// implicit initialization of array
// for each object in array it:
// * sets it as zeros for POD types (integral, floating point, etc)
// * calls default constructor for classes/structs
init_list += "()";
} else {
init_list += "(" + arg_name + ")";
}
if (field.padding) {
GenPadding(field, &init_list, &padding_id, PaddingInitializer);
@@ -2898,27 +2960,6 @@ class CppGenerator : public BaseGenerator {
} else {
code_ += " {{STRUCT_NAME}}({{ARG_LIST}}) {";
}
padding_id = 0;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
const auto &field = **it;
const auto &field_type = field.value.type;
if (IsArray(field_type)) {
const auto &elem_type = field_type.VectorType();
(void)elem_type;
FLATBUFFERS_ASSERT(
(IsScalar(elem_type.base_type) || IsStruct(elem_type)) &&
"invalid declaration");
const auto &member = Name(field) + "_";
code_ +=
" std::memset(" + member + ", 0, sizeof(" + member + "));";
}
if (field.padding) {
std::string padding;
GenPadding(field, &padding, &padding_id, PaddingNoop);
code_ += padding;
}
}
code_ += " }";
}
}
@@ -2974,10 +3015,7 @@ class CppGenerator : public BaseGenerator {
GenFullyQualifiedNameGetter(struct_def, Name(struct_def));
// Generate a default constructor.
code_ += " {{STRUCT_NAME}}() {";
code_ +=
" memset(static_cast<void *>(this), 0, sizeof({{STRUCT_NAME}}));";
code_ += " }";
GenStructDefaultConstructor(struct_def);
// Generate a constructor that takes all fields as arguments,
// excluding arrays