Cleanup: Deprecated field access in outliner_duplicate

Solved by introducing introducing a variant of MEM_cnew which behaves
as a copy-constructor for a trivial types.

Alternative approach would be to surround DNA structs with clang/gcc
diagnostics push/modify/pop so that implicitly defined constructors
and copy operators are allowed to access deprecated fields.

The downside of the DNA approach is that it will require some way to
easily apply diagnostics modifications to many structs, which is not
possible currently.

The newly added MEM_cnew has other good usecases, so is easiest to
use this route, at least for now.

Differential Revision: https://developer.blender.org/D14356
This commit is contained in:
Sergey Sharybin 2022-03-16 12:25:44 +01:00
parent ddc54a2a6b
commit 42e13ea4bf
2 changed files with 19 additions and 1 deletions

View File

@ -278,6 +278,24 @@ template<typename T> inline T *MEM_cnew(const char *allocation_name)
return static_cast<T *>(MEM_callocN(sizeof(T), allocation_name));
}
/**
* Allocate memory for an object of type #T and copy construct an object from `other`.
* Only applicable for a trivial types.
*
* This function works around problem of copy-constructing DNA structs which contains deprecated
* fields: some compilers will generate access deprecated field in implicitly defined copy
* constructors.
*
* This is a better alternative to #MEM_dupallocN.
*/
template<typename T> inline T *MEM_cnew(const char *allocation_name, const T &other)
{
static_assert(std::is_trivial_v<T>, "For non-trivial types, MEM_new should be used.");
T *new_object = static_cast<T *>(MEM_mallocN(sizeof(T), allocation_name));
memcpy(new_object, &other, sizeof(T));
return new_object;
}
/**
* Destructs and deallocates an object previously allocated with any `MEM_*` function.
* Passing in null does nothing.

View File

@ -371,7 +371,7 @@ static void outliner_init(wmWindowManager *UNUSED(wm), ScrArea *area)
static SpaceLink *outliner_duplicate(SpaceLink *sl)
{
SpaceOutliner *space_outliner = (SpaceOutliner *)sl;
SpaceOutliner *space_outliner_new = MEM_new<SpaceOutliner>(__func__, *space_outliner);
SpaceOutliner *space_outliner_new = MEM_cnew<SpaceOutliner>(__func__, *space_outliner);
BLI_listbase_clear(&space_outliner_new->tree);
space_outliner_new->treestore = nullptr;