Enable -Wconversion (#1359)

Summary:
X-link: https://github.com/facebook/react-native/pull/39291

Pull Request resolved: https://github.com/facebook/yoga/pull/1359

This enables clang warnings around potentially unsafe conversions, such as those with mismatched signedness, or ones which may lead to truncation.

This should catch issues in local development which create errors for MSVC (e.g. Dash), who's default `/W3` includes warnings akin to `-Wshorten-64-to-32`.

This full set of warnings here is a tad spammy, but probably more useful than not.

Changelog: [Internal]

Reviewed By: yungsters

Differential Revision: D48954777

fbshipit-source-id: 1ccc07b99d09d1c2d428158149698ffd04025605
This commit is contained in:
Nick Gerleman
2023-09-06 08:16:42 -07:00
committed by Facebook GitHub Bot
parent 95a7b4497e
commit aee43a53bc
17 changed files with 149 additions and 125 deletions

View File

@@ -32,6 +32,7 @@ Pod::Spec.new do |spec|
'-Wall', '-Wall',
'-Werror', '-Werror',
'-Wextra', '-Wextra',
'-Wconversion',
'-std=c++17', '-std=c++17',
'-fPIC' '-fPIC'
] ]

View File

@@ -55,7 +55,8 @@ static void __printBenchmarkResult(
double mean = 0; double mean = 0;
clock_t lastEnd = start; clock_t lastEnd = start;
for (uint32_t i = 0; i < NUM_REPETITIONS; i++) { for (uint32_t i = 0; i < NUM_REPETITIONS; i++) {
timesInMs[i] = (endTimes[i] - lastEnd) / (double) CLOCKS_PER_SEC * 1000; timesInMs[i] =
((double) (endTimes[i] - lastEnd)) / (double) CLOCKS_PER_SEC * 1000;
lastEnd = endTimes[i]; lastEnd = endTimes[i];
mean += timesInMs[i]; mean += timesInMs[i];
} }

View File

@@ -35,6 +35,7 @@ add_compile_options(
-Wall -Wall
-Wextra -Wextra
-Werror -Werror
-Wconversion
# Disable RTTI # Disable RTTI
$<$<COMPILE_LANGUAGE:CXX>:-fno-rtti> $<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>
# Use -O2 (prioritize speed) # Use -O2 (prioritize speed)

View File

@@ -22,12 +22,12 @@ namespace {
const int HAS_NEW_LAYOUT = 16; const int HAS_NEW_LAYOUT = 16;
union YGNodeContext { union YGNodeContext {
uintptr_t edgesSet = 0; int32_t edgesSet = 0;
void* asVoidPtr; void* asVoidPtr;
}; };
class YGNodeEdges { class YGNodeEdges {
uintptr_t edges_; int32_t edges_;
public: public:
enum Edge { enum Edge {

View File

@@ -146,7 +146,7 @@ static int YGJNILogFunc(
va_list argsCopy; va_list argsCopy;
va_copy(argsCopy, args); va_copy(argsCopy, args);
int result = vsnprintf(nullptr, 0, format, argsCopy); int result = vsnprintf(nullptr, 0, format, argsCopy);
std::vector<char> buffer(1 + result); std::vector<char> buffer(1 + static_cast<size_t>(result));
vsnprintf(buffer.data(), buffer.size(), format, args); vsnprintf(buffer.data(), buffer.size(), format, args);
auto jloggerPtr = auto jloggerPtr =
@@ -236,7 +236,9 @@ static void jni_YGNodeInsertChildJNI(
jlong childPointer, jlong childPointer,
jint index) { jint index) {
YGNodeInsertChild( YGNodeInsertChild(
_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index); _jlong2YGNodeRef(nativePointer),
_jlong2YGNodeRef(childPointer),
static_cast<uint32_t>(index));
} }
static void jni_YGNodeSwapChildJNI( static void jni_YGNodeSwapChildJNI(
@@ -246,7 +248,9 @@ static void jni_YGNodeSwapChildJNI(
jlong childPointer, jlong childPointer,
jint index) { jint index) {
YGNodeSwapChild( YGNodeSwapChild(
_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index); _jlong2YGNodeRef(nativePointer),
_jlong2YGNodeRef(childPointer),
static_cast<uint32_t>(index));
} }
static void jni_YGNodeSetIsReferenceBaselineJNI( static void jni_YGNodeSetIsReferenceBaselineJNI(
@@ -307,13 +311,13 @@ static void YGTransferLayoutOutputsRecursive(
const int arrSize = 6 + (marginFieldSet ? 4 : 0) + (paddingFieldSet ? 4 : 0) + const int arrSize = 6 + (marginFieldSet ? 4 : 0) + (paddingFieldSet ? 4 : 0) +
(borderFieldSet ? 4 : 0); (borderFieldSet ? 4 : 0);
float arr[18]; float arr[18];
arr[LAYOUT_EDGE_SET_FLAG_INDEX] = fieldFlags; arr[LAYOUT_EDGE_SET_FLAG_INDEX] = static_cast<float>(fieldFlags);
arr[LAYOUT_WIDTH_INDEX] = YGNodeLayoutGetWidth(root); arr[LAYOUT_WIDTH_INDEX] = YGNodeLayoutGetWidth(root);
arr[LAYOUT_HEIGHT_INDEX] = YGNodeLayoutGetHeight(root); arr[LAYOUT_HEIGHT_INDEX] = YGNodeLayoutGetHeight(root);
arr[LAYOUT_LEFT_INDEX] = YGNodeLayoutGetLeft(root); arr[LAYOUT_LEFT_INDEX] = YGNodeLayoutGetLeft(root);
arr[LAYOUT_TOP_INDEX] = YGNodeLayoutGetTop(root); arr[LAYOUT_TOP_INDEX] = YGNodeLayoutGetTop(root);
arr[LAYOUT_DIRECTION_INDEX] = arr[LAYOUT_DIRECTION_INDEX] =
static_cast<jint>(YGNodeLayoutGetDirection(root)); static_cast<float>(YGNodeLayoutGetDirection(root));
if (marginFieldSet) { if (marginFieldSet) {
arr[LAYOUT_MARGIN_START_INDEX] = YGNodeLayoutGetMargin(root, YGEdgeLeft); arr[LAYOUT_MARGIN_START_INDEX] = YGNodeLayoutGetMargin(root, YGEdgeLeft);
arr[LAYOUT_MARGIN_START_INDEX + 1] = YGNodeLayoutGetMargin(root, YGEdgeTop); arr[LAYOUT_MARGIN_START_INDEX + 1] = YGNodeLayoutGetMargin(root, YGEdgeTop);
@@ -670,9 +674,10 @@ static YGSize YGJNIMeasureFunc(
sizeof(measureResult) == 8, sizeof(measureResult) == 8,
"Expected measureResult to be 8 bytes, or two 32 bit ints"); "Expected measureResult to be 8 bytes, or two 32 bit ints");
int32_t wBits = 0xFFFFFFFF & (measureResult >> 32); uint32_t wBits = 0xFFFFFFFF & (measureResult >> 32);
int32_t hBits = 0xFFFFFFFF & measureResult; uint32_t hBits = 0xFFFFFFFF & measureResult;
// TODO: this is unsafe under strict aliasing and should use bit_cast
const float* measuredWidth = reinterpret_cast<float*>(&wBits); const float* measuredWidth = reinterpret_cast<float*>(&wBits);
const float* measuredHeight = reinterpret_cast<float*>(&hBits); const float* measuredHeight = reinterpret_cast<float*>(&hBits);

View File

@@ -14,7 +14,7 @@
#include "jni.h" #include "jni.h"
class PtrJNodeMapVanilla { class PtrJNodeMapVanilla {
std::map<YGNodeConstRef, size_t> ptrsToIdxs_{}; std::map<YGNodeConstRef, jsize> ptrsToIdxs_{};
jobjectArray javaNodes_{}; jobjectArray javaNodes_{};
public: public:
@@ -25,13 +25,13 @@ public:
using namespace facebook::yoga::vanillajni; using namespace facebook::yoga::vanillajni;
JNIEnv* env = getCurrentEnv(); JNIEnv* env = getCurrentEnv();
size_t nativePointersSize = env->GetArrayLength(javaNativePointers); jsize nativePointersSize = env->GetArrayLength(javaNativePointers);
std::vector<jlong> nativePointers(nativePointersSize); std::vector<jlong> nativePointers(static_cast<size_t>(nativePointersSize));
env->GetLongArrayRegion( env->GetLongArrayRegion(
javaNativePointers, 0, nativePointersSize, nativePointers.data()); javaNativePointers, 0, nativePointersSize, nativePointers.data());
for (size_t i = 0; i < nativePointersSize; ++i) { for (jsize i = 0; i < nativePointersSize; ++i) {
ptrsToIdxs_[(YGNodeConstRef) nativePointers[i]] = i; ptrsToIdxs_[(YGNodeConstRef) nativePointers[static_cast<size_t>(i)]] = i;
} }
} }

View File

@@ -18,7 +18,8 @@ void registerNatives(
assertNoPendingJniExceptionIf(env, !clazz); assertNoPendingJniExceptionIf(env, !clazz);
auto result = env->RegisterNatives(clazz, methods, numMethods); auto result =
env->RegisterNatives(clazz, methods, static_cast<int32_t>(numMethods));
assertNoPendingJniExceptionIf(env, result != JNI_OK); assertNoPendingJniExceptionIf(env, result != JNI_OK);
} }

View File

@@ -13,7 +13,7 @@
namespace facebook::yoga { namespace facebook::yoga {
TEST(NumericBitfield, one_boolean_defaults_to_false) { TEST(NumericBitfield, one_boolean_defaults_to_false) {
constexpr uint8_t flags = 0; constexpr uint32_t flags = 0;
ASSERT_EQ(getBooleanData(flags, 0), false); ASSERT_EQ(getBooleanData(flags, 0), false);
static_assert( static_assert(
@@ -22,7 +22,7 @@ TEST(NumericBitfield, one_boolean_defaults_to_false) {
} }
TEST(NumericBitfield, one_boolean_can_be_initialized_to_true) { TEST(NumericBitfield, one_boolean_can_be_initialized_to_true) {
constexpr uint8_t flags = 1; constexpr uint32_t flags = 1;
ASSERT_EQ(getBooleanData(flags, 0), true); ASSERT_EQ(getBooleanData(flags, 0), true);
static_assert( static_assert(
@@ -31,14 +31,14 @@ TEST(NumericBitfield, one_boolean_can_be_initialized_to_true) {
} }
TEST(NumericBitfield, one_boolean_can_be_set_to_true) { TEST(NumericBitfield, one_boolean_can_be_set_to_true) {
uint8_t flags = 0; uint32_t flags = 0;
setBooleanData(flags, 0, true); setBooleanData(flags, 0, true);
ASSERT_EQ(getBooleanData(flags, 0), true); ASSERT_EQ(getBooleanData(flags, 0), true);
} }
TEST(NumericBitfield, second_boolean_defaults_to_false) { TEST(NumericBitfield, second_boolean_defaults_to_false) {
constexpr uint8_t flags = 0; constexpr uint32_t flags = 0;
ASSERT_EQ(getBooleanData(flags, 1), false); ASSERT_EQ(getBooleanData(flags, 1), false);
static_assert( static_assert(
@@ -47,7 +47,7 @@ TEST(NumericBitfield, second_boolean_defaults_to_false) {
} }
TEST(NumericBitfield, second_boolean_can_be_initialized_to_true) { TEST(NumericBitfield, second_boolean_can_be_initialized_to_true) {
constexpr uint8_t flags = 2; constexpr uint32_t flags = 2;
ASSERT_EQ(getBooleanData(flags, 0), false); ASSERT_EQ(getBooleanData(flags, 0), false);
ASSERT_EQ(getBooleanData(flags, 1), true); ASSERT_EQ(getBooleanData(flags, 1), true);
@@ -60,7 +60,7 @@ TEST(NumericBitfield, second_boolean_can_be_initialized_to_true) {
} }
TEST(NumericBitfield, second_boolean_can_be_set_to_true) { TEST(NumericBitfield, second_boolean_can_be_set_to_true) {
uint8_t flags = 0; uint32_t flags = 0;
setBooleanData(flags, 1, true); setBooleanData(flags, 1, true);
ASSERT_EQ(getBooleanData(flags, 0), false); ASSERT_EQ(getBooleanData(flags, 0), false);
@@ -68,7 +68,7 @@ TEST(NumericBitfield, second_boolean_can_be_set_to_true) {
} }
TEST(NumericBitfield, third_boolean_defaults_to_false) { TEST(NumericBitfield, third_boolean_defaults_to_false) {
constexpr uint8_t flags = 0; constexpr uint32_t flags = 0;
ASSERT_EQ(getBooleanData(flags, 2), false); ASSERT_EQ(getBooleanData(flags, 2), false);
static_assert( static_assert(
@@ -77,7 +77,7 @@ TEST(NumericBitfield, third_boolean_defaults_to_false) {
} }
TEST(NumericBitfield, third_boolean_can_be_initialized_to_true) { TEST(NumericBitfield, third_boolean_can_be_initialized_to_true) {
constexpr uint8_t flags = 4; constexpr uint32_t flags = 4;
ASSERT_EQ(getBooleanData(flags, 0), false); ASSERT_EQ(getBooleanData(flags, 0), false);
ASSERT_EQ(getBooleanData(flags, 1), false); ASSERT_EQ(getBooleanData(flags, 1), false);
@@ -94,7 +94,7 @@ TEST(NumericBitfield, third_boolean_can_be_initialized_to_true) {
} }
TEST(NumericBitfield, third_boolean_can_be_set_to_true) { TEST(NumericBitfield, third_boolean_can_be_set_to_true) {
uint8_t flags = 0; uint32_t flags = 0;
setBooleanData(flags, 2, true); setBooleanData(flags, 2, true);
ASSERT_EQ(getBooleanData(flags, 0), false); ASSERT_EQ(getBooleanData(flags, 0), false);
@@ -103,7 +103,7 @@ TEST(NumericBitfield, third_boolean_can_be_set_to_true) {
} }
TEST(NumericBitfield, setting_boolean_values_does_not_spill_over) { TEST(NumericBitfield, setting_boolean_values_does_not_spill_over) {
uint8_t flags = 0; uint32_t flags = 0;
setBooleanData(flags, 1, (bool) 7); setBooleanData(flags, 1, (bool) 7);
@@ -113,7 +113,7 @@ TEST(NumericBitfield, setting_boolean_values_does_not_spill_over) {
} }
TEST(NumericBitfield, first_enum_defaults_to_0) { TEST(NumericBitfield, first_enum_defaults_to_0) {
constexpr uint8_t flags = 0; constexpr uint32_t flags = 0;
ASSERT_EQ(getEnumData<YGAlign>(flags, 0), YGAlignAuto); ASSERT_EQ(getEnumData<YGAlign>(flags, 0), YGAlignAuto);
static_assert( static_assert(
@@ -122,7 +122,7 @@ TEST(NumericBitfield, first_enum_defaults_to_0) {
} }
TEST(NumericBitfield, first_enum_can_be_set) { TEST(NumericBitfield, first_enum_can_be_set) {
uint8_t flags = 0; uint32_t flags = 0;
setEnumData<YGAlign>(flags, 0, YGAlignSpaceBetween); setEnumData<YGAlign>(flags, 0, YGAlignSpaceBetween);
@@ -130,7 +130,7 @@ TEST(NumericBitfield, first_enum_can_be_set) {
} }
TEST(NumericBitfield, second_enum_defaults_to_0) { TEST(NumericBitfield, second_enum_defaults_to_0) {
constexpr uint8_t flags = 0; constexpr uint32_t flags = 0;
static constexpr size_t alignOffset = 0; static constexpr size_t alignOffset = 0;
static constexpr size_t edgeOffset = 3; static constexpr size_t edgeOffset = 3;
@@ -145,7 +145,7 @@ TEST(NumericBitfield, second_enum_defaults_to_0) {
} }
TEST(NumericBitfield, second_enum_can_be_set) { TEST(NumericBitfield, second_enum_can_be_set) {
uint8_t flags = 0; uint32_t flags = 0;
static constexpr size_t alignOffset = 0; static constexpr size_t alignOffset = 0;
static constexpr size_t edgeOffset = 3; static constexpr size_t edgeOffset = 3;
@@ -156,7 +156,7 @@ TEST(NumericBitfield, second_enum_can_be_set) {
} }
TEST(NumericBitfield, third_enum_defaults_to_0) { TEST(NumericBitfield, third_enum_defaults_to_0) {
constexpr uint8_t flags = 0; constexpr uint32_t flags = 0;
static constexpr size_t alignOffset = 0; static constexpr size_t alignOffset = 0;
static constexpr size_t boolOffset = 3; static constexpr size_t boolOffset = 3;
static constexpr size_t edgesOffset = 4; static constexpr size_t edgesOffset = 4;
@@ -176,7 +176,7 @@ TEST(NumericBitfield, third_enum_defaults_to_0) {
} }
TEST(NumericBitfield, third_enum_can_be_set) { TEST(NumericBitfield, third_enum_can_be_set) {
uint8_t flags = 0; uint32_t flags = 0;
static constexpr size_t alignOffset = 0; static constexpr size_t alignOffset = 0;
static constexpr size_t boolOffset = 3; static constexpr size_t boolOffset = 3;
static constexpr size_t edgesOffset = 4; static constexpr size_t edgesOffset = 4;
@@ -189,12 +189,13 @@ TEST(NumericBitfield, third_enum_can_be_set) {
} }
TEST(NumericBitfield, setting_values_does_not_spill_over) { TEST(NumericBitfield, setting_values_does_not_spill_over) {
uint8_t flags = 0; uint32_t flags = 0;
static constexpr size_t alignOffset = 0; static constexpr size_t alignOffset = 0;
static constexpr size_t edgesOffset = 3; static constexpr size_t edgesOffset = 3;
static constexpr size_t boolOffset = 7; static constexpr size_t boolOffset = 7;
setEnumData<YGEdge>(flags, edgesOffset, (YGEdge) 0xffffff); uint32_t edge = 0xffffff;
setEnumData<YGEdge>(flags, edgesOffset, (YGEdge) edge);
ASSERT_EQ(getEnumData<YGAlign>(flags, alignOffset), 0); ASSERT_EQ(getEnumData<YGAlign>(flags, alignOffset), 0);
ASSERT_EQ(getBooleanData(flags, boolOffset), false); ASSERT_EQ(getBooleanData(flags, boolOffset), false);

View File

@@ -33,7 +33,7 @@ TEST(Node, measure_with_measure_fn) {
n.setMeasureFunc( n.setMeasureFunc(
[](YGNodeRef, float w, YGMeasureMode wm, float h, YGMeasureMode hm) { [](YGNodeRef, float w, YGMeasureMode wm, float h, YGMeasureMode hm) {
return YGSize{w * static_cast<int>(wm), h / static_cast<int>(hm)}; return YGSize{w * static_cast<float>(wm), h / static_cast<float>(hm)};
}); });
ASSERT_EQ( ASSERT_EQ(
@@ -62,7 +62,7 @@ TEST(Node, switching_measure_fn_types) {
}); });
n.setMeasureFunc( n.setMeasureFunc(
[](YGNodeRef, float w, YGMeasureMode wm, float h, YGMeasureMode hm) { [](YGNodeRef, float w, YGMeasureMode wm, float h, YGMeasureMode hm) {
return YGSize{w * static_cast<int>(wm), h / static_cast<int>(hm)}; return YGSize{w * static_cast<float>(wm), h / static_cast<float>(hm)};
}); });
ASSERT_EQ( ASSERT_EQ(

View File

@@ -823,8 +823,8 @@ static void zeroOutLayoutRecursively(
yoga::Node* const node, yoga::Node* const node,
void* layoutContext) { void* layoutContext) {
node->getLayout() = {}; node->getLayout() = {};
node->setLayoutDimension(0, 0); node->setLayoutDimension(0, YGDimensionWidth);
node->setLayoutDimension(0, 1); node->setLayoutDimension(0, YGDimensionHeight);
node->setHasNewLayout(true); node->setHasNewLayout(true);
node->iterChildrenAfterCloningIfNeeded( node->iterChildrenAfterCloningIfNeeded(
@@ -1488,19 +1488,19 @@ static void YGJustifyMainAxis(
betweenMainDim += betweenMainDim +=
yoga::maxOrDefined( yoga::maxOrDefined(
collectedFlexItemsValues.remainingFreeSpace, 0) / collectedFlexItemsValues.remainingFreeSpace, 0) /
(collectedFlexItemsValues.itemsOnLine - 1); static_cast<float>(collectedFlexItemsValues.itemsOnLine - 1);
} }
break; break;
case YGJustifySpaceEvenly: case YGJustifySpaceEvenly:
// Space is distributed evenly across all elements // Space is distributed evenly across all elements
leadingMainDim = collectedFlexItemsValues.remainingFreeSpace / leadingMainDim = collectedFlexItemsValues.remainingFreeSpace /
(collectedFlexItemsValues.itemsOnLine + 1); static_cast<float>(collectedFlexItemsValues.itemsOnLine + 1);
betweenMainDim += leadingMainDim; betweenMainDim += leadingMainDim;
break; break;
case YGJustifySpaceAround: case YGJustifySpaceAround:
// Space on the edges is half of the space between elements // Space on the edges is half of the space between elements
leadingMainDim = 0.5f * collectedFlexItemsValues.remainingFreeSpace / leadingMainDim = 0.5f * collectedFlexItemsValues.remainingFreeSpace /
collectedFlexItemsValues.itemsOnLine; static_cast<float>(collectedFlexItemsValues.itemsOnLine);
betweenMainDim += leadingMainDim * 2; betweenMainDim += leadingMainDim * 2;
break; break;
case YGJustifyFlexStart: case YGJustifyFlexStart:
@@ -1550,7 +1550,7 @@ static void YGJustifyMainAxis(
if (child->marginLeadingValue(mainAxis).unit == YGUnitAuto) { if (child->marginLeadingValue(mainAxis).unit == YGUnitAuto) {
collectedFlexItemsValues.mainDim += collectedFlexItemsValues.mainDim +=
collectedFlexItemsValues.remainingFreeSpace / collectedFlexItemsValues.remainingFreeSpace /
numberOfAutoMarginsOnCurrentLine; static_cast<float>(numberOfAutoMarginsOnCurrentLine);
} }
if (performLayout) { if (performLayout) {
@@ -1563,7 +1563,7 @@ static void YGJustifyMainAxis(
if (child->marginTrailingValue(mainAxis).unit == YGUnitAuto) { if (child->marginTrailingValue(mainAxis).unit == YGUnitAuto) {
collectedFlexItemsValues.mainDim += collectedFlexItemsValues.mainDim +=
collectedFlexItemsValues.remainingFreeSpace / collectedFlexItemsValues.remainingFreeSpace /
numberOfAutoMarginsOnCurrentLine; static_cast<float>(numberOfAutoMarginsOnCurrentLine);
} }
bool canSkipFlex = bool canSkipFlex =
!performLayout && measureModeCrossDim == YGMeasureModeExactly; !performLayout && measureModeCrossDim == YGMeasureModeExactly;
@@ -1890,7 +1890,7 @@ static void calculateLayoutImpl(
if (childCount > 1) { if (childCount > 1) {
totalMainDim += totalMainDim +=
node->getGapForAxis(mainAxis, availableInnerCrossDim).unwrap() * node->getGapForAxis(mainAxis, availableInnerCrossDim).unwrap() *
(childCount - 1); static_cast<float>(childCount - 1);
} }
const bool mainAxisOverflows = const bool mainAxisOverflows =
@@ -2261,14 +2261,17 @@ static void calculateLayoutImpl(
break; break;
case YGAlignStretch: case YGAlignStretch:
if (availableInnerCrossDim > totalLineCrossDim) { if (availableInnerCrossDim > totalLineCrossDim) {
crossDimLead = remainingAlignContentDim / lineCount; crossDimLead =
remainingAlignContentDim / static_cast<float>(lineCount);
} }
break; break;
case YGAlignSpaceAround: case YGAlignSpaceAround:
if (availableInnerCrossDim > totalLineCrossDim) { if (availableInnerCrossDim > totalLineCrossDim) {
currentLead += remainingAlignContentDim / (2 * lineCount); currentLead +=
remainingAlignContentDim / (2 * static_cast<float>(lineCount));
if (lineCount > 1) { if (lineCount > 1) {
crossDimLead = remainingAlignContentDim / lineCount; crossDimLead =
remainingAlignContentDim / static_cast<float>(lineCount);
} }
} else { } else {
currentLead += remainingAlignContentDim / 2; currentLead += remainingAlignContentDim / 2;
@@ -2276,7 +2279,8 @@ static void calculateLayoutImpl(
break; break;
case YGAlignSpaceBetween: case YGAlignSpaceBetween:
if (availableInnerCrossDim > totalLineCrossDim && lineCount > 1) { if (availableInnerCrossDim > totalLineCrossDim && lineCount > 1) {
crossDimLead = remainingAlignContentDim / (lineCount - 1); crossDimLead =
remainingAlignContentDim / static_cast<float>(lineCount - 1);
} }
break; break;
case YGAlignAuto: case YGAlignAuto:
@@ -2843,11 +2847,11 @@ bool calculateLayoutInternal(
layout->lastOwnerDirection = ownerDirection; layout->lastOwnerDirection = ownerDirection;
if (cachedResults == nullptr) { if (cachedResults == nullptr) {
if (layout->nextCachedMeasurementsIndex + 1 >
(uint32_t) layoutMarkerData.maxMeasureCache) { layoutMarkerData.maxMeasureCache = std::max(
layoutMarkerData.maxMeasureCache = layoutMarkerData.maxMeasureCache,
layout->nextCachedMeasurementsIndex + 1; layout->nextCachedMeasurementsIndex + 1u);
}
if (layout->nextCachedMeasurementsIndex == if (layout->nextCachedMeasurementsIndex ==
LayoutResults::MaxCachedMeasurements) { LayoutResults::MaxCachedMeasurements) {
if (gPrintChanges) { if (gPrintChanges) {

View File

@@ -15,12 +15,12 @@
namespace facebook::yoga::details { namespace facebook::yoga::details {
constexpr size_t log2ceilFn(size_t n) { constexpr uint8_t log2ceilFn(uint8_t n) {
return n < 1 ? 0 : (1 + log2ceilFn(n / 2)); return n < 1 ? 0 : (1 + log2ceilFn(n / 2));
} }
constexpr int mask(size_t bitWidth, size_t index) { constexpr uint32_t mask(uint8_t bitWidth, uint8_t index) {
return ((1 << bitWidth) - 1) << index; return ((1u << bitWidth) - 1u) << index;
} }
} // namespace facebook::yoga::details } // namespace facebook::yoga::details
@@ -29,38 +29,31 @@ namespace facebook::yoga {
// The number of bits necessary to represent enums defined with YG_ENUM_SEQ_DECL // The number of bits necessary to represent enums defined with YG_ENUM_SEQ_DECL
template <typename Enum> template <typename Enum>
constexpr size_t minimumBitCount() { constexpr uint8_t minimumBitCount() {
static_assert( static_assert(
enums::count<Enum>() > 0, "Enums must have at least one entries"); enums::count<Enum>() > 0, "Enums must have at least one entries");
return details::log2ceilFn(enums::count<Enum>() - 1); return details::log2ceilFn(enums::count<Enum>() - 1);
} }
template <typename Enum> template <typename Enum>
constexpr Enum getEnumData(int flags, size_t index) { constexpr Enum getEnumData(uint32_t flags, uint8_t index) {
return static_cast<Enum>( return static_cast<Enum>(
(flags & details::mask(minimumBitCount<Enum>(), index)) >> index); (flags & details::mask(minimumBitCount<Enum>(), index)) >> index);
} }
template <typename Enum> template <typename Enum>
void setEnumData(uint32_t& flags, size_t index, int newValue) { void setEnumData(uint32_t& flags, uint8_t index, uint32_t newValue) {
flags = (flags & ~details::mask(minimumBitCount<Enum>(), index)) | flags =
(flags &
~static_cast<uint32_t>(details::mask(minimumBitCount<Enum>(), index))) |
((newValue << index) & (details::mask(minimumBitCount<Enum>(), index))); ((newValue << index) & (details::mask(minimumBitCount<Enum>(), index)));
} }
template <typename Enum> constexpr bool getBooleanData(uint32_t flags, uint8_t index) {
void setEnumData(uint8_t& flags, size_t index, int newValue) {
flags =
(flags &
~static_cast<uint8_t>(details::mask(minimumBitCount<Enum>(), index))) |
((newValue << index) &
(static_cast<uint8_t>(details::mask(minimumBitCount<Enum>(), index))));
}
constexpr bool getBooleanData(int flags, size_t index) {
return (flags >> index) & 1; return (flags >> index) & 1;
} }
inline void setBooleanData(uint8_t& flags, size_t index, bool value) { inline void setBooleanData(uint32_t& flags, uint8_t index, bool value) {
if (value) { if (value) {
flags |= 1 << index; flags |= 1 << index;
} else { } else {

View File

@@ -33,7 +33,7 @@ static void appendFormattedString(std::string& str, const char* fmt, ...) {
va_start(args, fmt); va_start(args, fmt);
va_list argsCopy; va_list argsCopy;
va_copy(argsCopy, args); va_copy(argsCopy, args);
std::vector<char> buf(1 + vsnprintf(NULL, 0, fmt, args)); std::vector<char> buf(1 + static_cast<size_t>(vsnprintf(NULL, 0, fmt, args)));
va_end(args); va_end(args);
vsnprintf(buf.data(), buf.size(), fmt, argsCopy); vsnprintf(buf.data(), buf.size(), fmt, argsCopy);
va_end(argsCopy); va_end(argsCopy);
@@ -96,7 +96,7 @@ static void appendEdges(
} else { } else {
for (int edge = YGEdgeLeft; edge != YGEdgeAll; ++edge) { for (int edge = YGEdgeLeft; edge != YGEdgeAll; ++edge) {
std::string str = key + "-" + YGEdgeToString(static_cast<YGEdge>(edge)); std::string str = key + "-" + YGEdgeToString(static_cast<YGEdge>(edge));
appendNumberIfNotZero(base, str, edges[edge]); appendNumberIfNotZero(base, str, edges[static_cast<size_t>(edge)]);
} }
} }
} }

View File

@@ -38,7 +38,7 @@ enum struct LayoutPassReason : int {
struct LayoutData { struct LayoutData {
int layouts; int layouts;
int measures; int measures;
int maxMeasureCache; uint32_t maxMeasureCache;
int cachedLayouts; int cachedLayouts;
int cachedMeasures; int cachedMeasures;
int measureCallbacks; int measureCallbacks;

View File

@@ -15,6 +15,14 @@
namespace facebook::yoga { namespace facebook::yoga {
#pragma pack(push)
#pragma pack(1)
struct LayoutResultFlags {
uint32_t direction : 2;
bool hadOverflow : 1;
};
#pragma pack(pop)
struct LayoutResults { struct LayoutResults {
// This value was chosen based on empirical data: // This value was chosen based on empirical data:
// 98% of analyzed layouts require less than 8 entries. // 98% of analyzed layouts require less than 8 entries.
@@ -27,10 +35,7 @@ struct LayoutResults {
std::array<float, 4> padding = {}; std::array<float, 4> padding = {};
private: private:
static constexpr size_t directionOffset = 0; LayoutResultFlags flags_{};
static constexpr size_t hadOverflowOffset =
directionOffset + minimumBitCount<YGDirection>();
uint8_t flags = 0;
public: public:
uint32_t computedFlexBasisGeneration = 0; uint32_t computedFlexBasisGeneration = 0;
@@ -48,17 +53,15 @@ public:
CachedMeasurement cachedLayout{}; CachedMeasurement cachedLayout{};
YGDirection direction() const { YGDirection direction() const {
return getEnumData<YGDirection>(flags, directionOffset); return static_cast<YGDirection>(flags_.direction);
} }
void setDirection(YGDirection direction) { void setDirection(YGDirection direction) {
setEnumData<YGDirection>(flags, directionOffset, direction); flags_.direction = static_cast<uint32_t>(direction) & 0x03;
} }
bool hadOverflow() const { return getBooleanData(flags, hadOverflowOffset); } bool hadOverflow() const { return flags_.hadOverflow; }
void setHadOverflow(bool hadOverflow) { void setHadOverflow(bool hadOverflow) { flags_.hadOverflow = hadOverflow; }
setBooleanData(flags, hadOverflowOffset, hadOverflow);
}
bool operator==(LayoutResults layout) const; bool operator==(LayoutResults layout) const;
bool operator!=(LayoutResults layout) const { return !(*this == layout); } bool operator!=(LayoutResults layout) const { return !(*this == layout); }

View File

@@ -6,6 +6,7 @@
*/ */
#include <algorithm> #include <algorithm>
#include <cstddef>
#include <iostream> #include <iostream>
#include <yoga/algorithm/FlexDirection.h> #include <yoga/algorithm/FlexDirection.h>
@@ -264,7 +265,7 @@ YOGA_EXPORT void Node::setMeasureFunc(MeasureWithContextFn measureFunc) {
setMeasureFunc(m); setMeasureFunc(m);
} }
void Node::replaceChild(Node* child, uint32_t index) { void Node::replaceChild(Node* child, size_t index) {
children_[index] = child; children_[index] = child;
} }
@@ -272,8 +273,8 @@ void Node::replaceChild(Node* oldChild, Node* newChild) {
std::replace(children_.begin(), children_.end(), oldChild, newChild); std::replace(children_.begin(), children_.end(), oldChild, newChild);
} }
void Node::insertChild(Node* child, uint32_t index) { void Node::insertChild(Node* child, size_t index) {
children_.insert(children_.begin() + index, child); children_.insert(children_.begin() + static_cast<ptrdiff_t>(index), child);
} }
void Node::setConfig(yoga::Config* config) { void Node::setConfig(yoga::Config* config) {
@@ -311,24 +312,30 @@ bool Node::removeChild(Node* child) {
return false; return false;
} }
void Node::removeChild(uint32_t index) { void Node::removeChild(size_t index) {
children_.erase(children_.begin() + index); children_.erase(children_.begin() + static_cast<ptrdiff_t>(index));
} }
void Node::setLayoutDirection(YGDirection direction) { void Node::setLayoutDirection(YGDirection direction) {
layout_.setDirection(direction); layout_.setDirection(direction);
} }
void Node::setLayoutMargin(float margin, int index) { void Node::setLayoutMargin(float margin, YGEdge edge) {
layout_.margin[index] = margin; assertFatal(
edge < layout_.margin.size(), "Edge must be top/left/bottom/right");
layout_.margin[edge] = margin;
} }
void Node::setLayoutBorder(float border, int index) { void Node::setLayoutBorder(float border, YGEdge edge) {
layout_.border[index] = border; assertFatal(
edge < layout_.border.size(), "Edge must be top/left/bottom/right");
layout_.border[edge] = border;
} }
void Node::setLayoutPadding(float padding, int index) { void Node::setLayoutPadding(float padding, YGEdge edge) {
layout_.padding[index] = padding; assertFatal(
edge < layout_.padding.size(), "Edge must be top/left/bottom/right");
layout_.padding[edge] = padding;
} }
void Node::setLayoutLastOwnerDirection(YGDirection direction) { void Node::setLayoutLastOwnerDirection(YGDirection direction) {
@@ -339,8 +346,10 @@ void Node::setLayoutComputedFlexBasis(const FloatOptional computedFlexBasis) {
layout_.computedFlexBasis = computedFlexBasis; layout_.computedFlexBasis = computedFlexBasis;
} }
void Node::setLayoutPosition(float position, int index) { void Node::setLayoutPosition(float position, YGEdge edge) {
layout_.position[index] = position; assertFatal(
edge < layout_.position.size(), "Edge must be top/left/bottom/right");
layout_.position[edge] = position;
} }
void Node::setLayoutComputedFlexBasisGeneration( void Node::setLayoutComputedFlexBasisGeneration(
@@ -348,16 +357,19 @@ void Node::setLayoutComputedFlexBasisGeneration(
layout_.computedFlexBasisGeneration = computedFlexBasisGeneration; layout_.computedFlexBasisGeneration = computedFlexBasisGeneration;
} }
void Node::setLayoutMeasuredDimension(float measuredDimension, int index) { void Node::setLayoutMeasuredDimension(
layout_.measuredDimensions[index] = measuredDimension; float measuredDimension,
YGDimension dimension) {
layout_.measuredDimensions[static_cast<size_t>(dimension)] =
measuredDimension;
} }
void Node::setLayoutHadOverflow(bool hadOverflow) { void Node::setLayoutHadOverflow(bool hadOverflow) {
layout_.setHadOverflow(hadOverflow); layout_.setHadOverflow(hadOverflow);
} }
void Node::setLayoutDimension(float dimension, int index) { void Node::setLayoutDimension(float dimensionValue, YGDimension dimension) {
layout_.dimensions[index] = dimension; layout_.dimensions[static_cast<size_t>(dimension)] = dimensionValue;
} }
// If both left and right are defined, then use left. Otherwise return +left or // If both left and right are defined, then use left. Otherwise return +left or

View File

@@ -27,7 +27,7 @@ struct NodeFlags {
bool hasNewLayout : 1; bool hasNewLayout : 1;
bool isReferenceBaseline : 1; bool isReferenceBaseline : 1;
bool isDirty : 1; bool isDirty : 1;
uint8_t nodeType : 1; uint32_t nodeType : 1;
bool measureUsesContext : 1; bool measureUsesContext : 1;
bool baselineUsesContext : 1; bool baselineUsesContext : 1;
bool printUsesContext : 1; bool printUsesContext : 1;
@@ -181,8 +181,8 @@ public:
return resolvedDimensions_; return resolvedDimensions_;
} }
YGValue getResolvedDimension(int index) const { YGValue getResolvedDimension(YGDimension dimension) const {
return resolvedDimensions_[index]; return resolvedDimensions_[static_cast<size_t>(dimension)];
} }
static CompactValue computeEdgeValueForColumn( static CompactValue computeEdgeValueForColumn(
@@ -257,7 +257,7 @@ public:
} }
void setNodeType(YGNodeType nodeType) { void setNodeType(YGNodeType nodeType) {
flags_.nodeType = static_cast<uint8_t>(nodeType); flags_.nodeType = static_cast<uint32_t>(nodeType) & 0x01;
} }
void setMeasureFunc(YGMeasureFunc measureFunc); void setMeasureFunc(YGMeasureFunc measureFunc);
@@ -303,14 +303,16 @@ public:
void setLayoutComputedFlexBasis(const FloatOptional computedFlexBasis); void setLayoutComputedFlexBasis(const FloatOptional computedFlexBasis);
void setLayoutComputedFlexBasisGeneration( void setLayoutComputedFlexBasisGeneration(
uint32_t computedFlexBasisGeneration); uint32_t computedFlexBasisGeneration);
void setLayoutMeasuredDimension(float measuredDimension, int index); void setLayoutMeasuredDimension(
float measuredDimension,
YGDimension dimension);
void setLayoutHadOverflow(bool hadOverflow); void setLayoutHadOverflow(bool hadOverflow);
void setLayoutDimension(float dimension, int index); void setLayoutDimension(float dimensionValue, YGDimension dimension);
void setLayoutDirection(YGDirection direction); void setLayoutDirection(YGDirection direction);
void setLayoutMargin(float margin, int index); void setLayoutMargin(float margin, YGEdge edge);
void setLayoutBorder(float border, int index); void setLayoutBorder(float border, YGEdge edge);
void setLayoutPadding(float padding, int index); void setLayoutPadding(float padding, YGEdge edge);
void setLayoutPosition(float position, int index); void setLayoutPosition(float position, YGEdge edge);
void setPosition( void setPosition(
const YGDirection direction, const YGDirection direction,
const float mainSize, const float mainSize,
@@ -327,11 +329,11 @@ public:
void clearChildren(); void clearChildren();
/// Replaces the occurrences of oldChild with newChild /// Replaces the occurrences of oldChild with newChild
void replaceChild(Node* oldChild, Node* newChild); void replaceChild(Node* oldChild, Node* newChild);
void replaceChild(Node* child, uint32_t index); void replaceChild(Node* child, size_t index);
void insertChild(Node* child, uint32_t index); void insertChild(Node* child, size_t index);
/// Removes the first occurrence of child /// Removes the first occurrence of child
bool removeChild(Node* child); bool removeChild(Node* child);
void removeChild(uint32_t index); void removeChild(size_t index);
void cloneChildrenIfNeeded(void*); void cloneChildrenIfNeeded(void*);
void markDirtyAndPropagate(); void markDirtyAndPropagate();

View File

@@ -36,7 +36,7 @@ public:
template <typename T> template <typename T>
struct BitfieldRef { struct BitfieldRef {
Style& style; Style& style;
size_t offset; uint8_t offset;
operator T() const { return getEnumData<T>(style.flags, offset); } operator T() const { return getEnumData<T>(style.flags, offset); }
BitfieldRef<T>& operator=(T x) { BitfieldRef<T>& operator=(T x) {
setEnumData<T>(style.flags, offset, x); setEnumData<T>(style.flags, offset, x);
@@ -84,24 +84,24 @@ public:
~Style() = default; ~Style() = default;
private: private:
static constexpr size_t directionOffset = 0; static constexpr uint8_t directionOffset = 0;
static constexpr size_t flexdirectionOffset = static constexpr uint8_t flexdirectionOffset =
directionOffset + minimumBitCount<YGDirection>(); directionOffset + minimumBitCount<YGDirection>();
static constexpr size_t justifyContentOffset = static constexpr uint8_t justifyContentOffset =
flexdirectionOffset + minimumBitCount<YGFlexDirection>(); flexdirectionOffset + minimumBitCount<YGFlexDirection>();
static constexpr size_t alignContentOffset = static constexpr uint8_t alignContentOffset =
justifyContentOffset + minimumBitCount<YGJustify>(); justifyContentOffset + minimumBitCount<YGJustify>();
static constexpr size_t alignItemsOffset = static constexpr uint8_t alignItemsOffset =
alignContentOffset + minimumBitCount<YGAlign>(); alignContentOffset + minimumBitCount<YGAlign>();
static constexpr size_t alignSelfOffset = static constexpr uint8_t alignSelfOffset =
alignItemsOffset + minimumBitCount<YGAlign>(); alignItemsOffset + minimumBitCount<YGAlign>();
static constexpr size_t positionTypeOffset = static constexpr uint8_t positionTypeOffset =
alignSelfOffset + minimumBitCount<YGAlign>(); alignSelfOffset + minimumBitCount<YGAlign>();
static constexpr size_t flexWrapOffset = static constexpr uint8_t flexWrapOffset =
positionTypeOffset + minimumBitCount<YGPositionType>(); positionTypeOffset + minimumBitCount<YGPositionType>();
static constexpr size_t overflowOffset = static constexpr uint8_t overflowOffset =
flexWrapOffset + minimumBitCount<YGWrap>(); flexWrapOffset + minimumBitCount<YGWrap>();
static constexpr size_t displayOffset = static constexpr uint8_t displayOffset =
overflowOffset + minimumBitCount<YGOverflow>(); overflowOffset + minimumBitCount<YGOverflow>();
uint32_t flags = 0; uint32_t flags = 0;