BLI: Replace some macros with inlined functions for C++ #108041

Merged
Sergey Sharybin merged 1 commits from Sergey/blender:cxx_avoid_macro into main 2023-05-23 09:21:51 +02:00

Covers the macro ARRAY_SIZE() and STRNCPY.

The problem this change is aimed to solve it to provide cross-platform
compiler-independent safe way pf ensuring that the functions are used
correctly.

The type safety was only ensured for GCC and only for C. The C++
language and Clang compiler would not have detected issues of passing
bare pointer to neither of those macros.

Now the STRNCPY() will only accept a bounded array as the destination
argument, on any compiler.

The ARRAY_SIZE as well, but there are a bit more complications to it
in terms of transparency of the change.

In one place the ARRAY_SIZE was used on float3 type. This worked in the
old code because the type implements subscript operator, and the type
consists of 3 floats. One would argue this is somewhat hidden/implicit
behavior, which better be avoided. So an in-lined value of 3 is used now
there.

Another place is the ARRAY_SIZE used to define a bounded array of the
size which matches bounded array which is a member of a struct. While
the ARRAY_SIZE provides proper size in this case, the compiler does not
believe that the value is known at compile time and errors out with a
message that construction of variable-size arrays is not supported.

Solved by converting the field to std::array<> and adding dedicated
utility to get size of std::array at compile time. There might be a
better way of achieving the same result, or maybe the approach is
fine and just need to find a better place for such utility.

Surely, more macro from the BLI_string.h can be covered with the C++
inlined functions, but need to start somewhere.

There are also quite some changes to ensure the C linkage is not
enforced by code which includes the headers.

Covers the macro ARRAY_SIZE() and STRNCPY. The problem this change is aimed to solve it to provide cross-platform compiler-independent safe way pf ensuring that the functions are used correctly. The type safety was only ensured for GCC and only for C. The C++ language and Clang compiler would not have detected issues of passing bare pointer to neither of those macros. Now the STRNCPY() will only accept a bounded array as the destination argument, on any compiler. The ARRAY_SIZE as well, but there are a bit more complications to it in terms of transparency of the change. In one place the ARRAY_SIZE was used on float3 type. This worked in the old code because the type implements subscript operator, and the type consists of 3 floats. One would argue this is somewhat hidden/implicit behavior, which better be avoided. So an in-lined value of 3 is used now there. Another place is the ARRAY_SIZE used to define a bounded array of the size which matches bounded array which is a member of a struct. While the ARRAY_SIZE provides proper size in this case, the compiler does not believe that the value is known at compile time and errors out with a message that construction of variable-size arrays is not supported. Solved by converting the field to std::array<> and adding dedicated utility to get size of std::array at compile time. There might be a better way of achieving the same result, or maybe the approach is fine and just need to find a better place for such utility. Surely, more macro from the BLI_string.h can be covered with the C++ inlined functions, but need to start somewhere. There are also quite some changes to ensure the C linkage is not enforced by code which includes the headers.
Author
Owner

@blender-bot build

@blender-bot build
Sergey Sharybin changed title from BLI: Replace some macros with inlined functions for C++ to WIP: BLI: Replace some macros with inlined functions for C++ 2023-05-18 11:59:21 +02:00
Sergey Sharybin force-pushed cxx_avoid_macro from bbb6fa2cb1 to 30cc4be8d4 2023-05-18 14:04:15 +02:00 Compare
Author
Owner

@blender-bot build

@blender-bot build
Sergey Sharybin changed title from WIP: BLI: Replace some macros with inlined functions for C++ to BLI: Replace some macros with inlined functions for C++ 2023-05-18 14:37:38 +02:00
Sergey Sharybin requested review from Jacques Lucke 2023-05-18 14:37:48 +02:00
Sergey Sharybin requested review from Hans Goudey 2023-05-18 14:37:55 +02:00

The type safety was only ensured for GCC and only for C. The C++
language and Clang compiler would not have detected issues of passing
bare pointer to neither of those macros.

While true, the ARRAY_SIZE() macro reports a -Wsizeof-pointer-div warning from incorrect use with GCC/C++, nevertheless a portable C++ solution is best.

> The type safety was only ensured for GCC and only for C. The C++ language and Clang compiler would not have detected issues of passing bare pointer to neither of those macros. While true, the `ARRAY_SIZE()` macro reports a `-Wsizeof-pointer-div` warning from incorrect use with GCC/C++, nevertheless a portable C++ solution is best.
Jacques Lucke approved these changes 2023-05-22 14:23:53 +02:00
@ -638,0 +646,4 @@
*
* Returns the dst.
*/
template<size_t N> inline char *STRNCPY(char (&dst)[N], const char *src)
Member

Think it would be better to define the C and C++ version of STRNCPY next to each other, not with 100 lines in between.

Think it would be better to define the C and C++ version of `STRNCPY` next to each other, not with 100 lines in between.
Author
Owner

I was thinking about it.

The reason I did not go that route is because the surrounding C linkage specializer. We'll either need to break it and re-enter again (which is a bit too verbose), or do a bigger change to move the macro outside of the C linkage block (which would mean changes in the way BLI_string_debug_size is defined).

It felt that it is safer to not make it easier to use wrong linkage for functions declared in the middle of a a macro (which happens a lot in Blender), and just let the current macro fade out with the rest of the C code.

How strongly you feel about avoiding the gap? And how would you organize the macro and linkage specializer?

I was thinking about it. The reason I did not go that route is because the surrounding C linkage specializer. We'll either need to break it and re-enter again (which is a bit too verbose), or do a bigger change to move the macro outside of the C linkage block (which would mean changes in the way `BLI_string_debug_size` is defined). It felt that it is safer to not make it easier to use wrong linkage for functions declared in the middle of a a macro (which happens a lot in Blender), and just let the current macro fade out with the rest of the C code. How strongly you feel about avoiding the gap? And how would you organize the macro and linkage specializer?
Member

Don't feel strong enough about it now to look into it in more detail.

Don't feel strong enough about it now to look into it in more detail.
Sergey Sharybin merged commit 793446cbdc into main 2023-05-23 09:21:51 +02:00
Sergey Sharybin deleted branch cxx_avoid_macro 2023-05-23 09:21:52 +02:00
Howard Trickey referenced this issue from a commit 2023-05-29 02:51:37 +02:00
Sign in to join this conversation.
No reviewers
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
3 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender#108041
No description provided.