Skip to content

Commit

Permalink
Enable -Wconversion (facebook#1359)
Browse files Browse the repository at this point in the history
Summary:
X-link: facebook/react-native#39291


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
  • Loading branch information
NickGerleman authored and facebook-github-bot committed Sep 5, 2023
1 parent 65ae809 commit a3511a3
Show file tree
Hide file tree
Showing 12 changed files with 121 additions and 104 deletions.
1 change: 1 addition & 0 deletions Yoga.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Pod::Spec.new do |spec|
'-Wall',
'-Werror',
'-Wextra',
'-Wconversion',
'-std=c++17',
'-fPIC'
]
Expand Down
3 changes: 2 additions & 1 deletion benchmark/YGBenchmark.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ static void __printBenchmarkResult(
double mean = 0;
clock_t lastEnd = start;
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];
mean += timesInMs[i];
}
Expand Down
1 change: 1 addition & 0 deletions cmake/project-defaults.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ add_compile_options(
-Wall
-Wextra
-Werror
-Wconversion
# Disable RTTI
$<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>
# Use -O2 (prioritize speed)
Expand Down
34 changes: 17 additions & 17 deletions tests/NumericBitfieldTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
namespace facebook::yoga {

TEST(NumericBitfield, one_boolean_defaults_to_false) {
constexpr uint8_t flags = 0;
constexpr uint32_t flags = 0;

ASSERT_EQ(getBooleanData(flags, 0), false);
static_assert(
Expand All @@ -22,7 +22,7 @@ TEST(NumericBitfield, one_boolean_defaults_to_false) {
}

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);
static_assert(
Expand All @@ -31,14 +31,14 @@ TEST(NumericBitfield, one_boolean_can_be_initialized_to_true) {
}

TEST(NumericBitfield, one_boolean_can_be_set_to_true) {
uint8_t flags = 0;
uint32_t flags = 0;

setBooleanData(flags, 0, true);
ASSERT_EQ(getBooleanData(flags, 0), true);
}

TEST(NumericBitfield, second_boolean_defaults_to_false) {
constexpr uint8_t flags = 0;
constexpr uint32_t flags = 0;

ASSERT_EQ(getBooleanData(flags, 1), false);
static_assert(
Expand All @@ -47,7 +47,7 @@ TEST(NumericBitfield, second_boolean_defaults_to_false) {
}

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, 1), true);
Expand All @@ -60,15 +60,15 @@ TEST(NumericBitfield, second_boolean_can_be_initialized_to_true) {
}

TEST(NumericBitfield, second_boolean_can_be_set_to_true) {
uint8_t flags = 0;
uint32_t flags = 0;

setBooleanData(flags, 1, true);
ASSERT_EQ(getBooleanData(flags, 0), false);
ASSERT_EQ(getBooleanData(flags, 1), true);
}

TEST(NumericBitfield, third_boolean_defaults_to_false) {
constexpr uint8_t flags = 0;
constexpr uint32_t flags = 0;

ASSERT_EQ(getBooleanData(flags, 2), false);
static_assert(
Expand All @@ -77,7 +77,7 @@ TEST(NumericBitfield, third_boolean_defaults_to_false) {
}

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, 1), false);
Expand All @@ -94,7 +94,7 @@ TEST(NumericBitfield, third_boolean_can_be_initialized_to_true) {
}

TEST(NumericBitfield, third_boolean_can_be_set_to_true) {
uint8_t flags = 0;
uint32_t flags = 0;

setBooleanData(flags, 2, true);
ASSERT_EQ(getBooleanData(flags, 0), false);
Expand All @@ -103,7 +103,7 @@ TEST(NumericBitfield, third_boolean_can_be_set_to_true) {
}

TEST(NumericBitfield, setting_boolean_values_does_not_spill_over) {
uint8_t flags = 0;
uint32_t flags = 0;

setBooleanData(flags, 1, (bool) 7);

Expand All @@ -113,7 +113,7 @@ TEST(NumericBitfield, setting_boolean_values_does_not_spill_over) {
}

TEST(NumericBitfield, first_enum_defaults_to_0) {
constexpr uint8_t flags = 0;
constexpr uint32_t flags = 0;

ASSERT_EQ(getEnumData<YGAlign>(flags, 0), YGAlignAuto);
static_assert(
Expand All @@ -122,15 +122,15 @@ TEST(NumericBitfield, first_enum_defaults_to_0) {
}

TEST(NumericBitfield, first_enum_can_be_set) {
uint8_t flags = 0;
uint32_t flags = 0;

setEnumData<YGAlign>(flags, 0, YGAlignSpaceBetween);

ASSERT_EQ(getEnumData<YGAlign>(flags, 0), YGAlignSpaceBetween);
}

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 edgeOffset = 3;

Expand All @@ -145,7 +145,7 @@ TEST(NumericBitfield, second_enum_defaults_to_0) {
}

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 edgeOffset = 3;

Expand All @@ -156,7 +156,7 @@ TEST(NumericBitfield, second_enum_can_be_set) {
}

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 boolOffset = 3;
static constexpr size_t edgesOffset = 4;
Expand All @@ -176,7 +176,7 @@ TEST(NumericBitfield, third_enum_defaults_to_0) {
}

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 boolOffset = 3;
static constexpr size_t edgesOffset = 4;
Expand All @@ -189,7 +189,7 @@ TEST(NumericBitfield, third_enum_can_be_set) {
}

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 edgesOffset = 3;
static constexpr size_t boolOffset = 7;
Expand Down
38 changes: 21 additions & 17 deletions yoga/algorithm/CalculateLayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -823,8 +823,8 @@ static void zeroOutLayoutRecursively(
yoga::Node* const node,
void* layoutContext) {
node->getLayout() = {};
node->setLayoutDimension(0, 0);
node->setLayoutDimension(0, 1);
node->setLayoutDimension(0, YGDimensionWidth);
node->setLayoutDimension(0, YGDimensionHeight);
node->setHasNewLayout(true);

node->iterChildrenAfterCloningIfNeeded(
Expand Down Expand Up @@ -1488,19 +1488,19 @@ static void YGJustifyMainAxis(
betweenMainDim +=
yoga::maxOrDefined(
collectedFlexItemsValues.remainingFreeSpace, 0) /
(collectedFlexItemsValues.itemsOnLine - 1);
static_cast<float>(collectedFlexItemsValues.itemsOnLine - 1);
}
break;
case YGJustifySpaceEvenly:
// Space is distributed evenly across all elements
leadingMainDim = collectedFlexItemsValues.remainingFreeSpace /
(collectedFlexItemsValues.itemsOnLine + 1);
static_cast<float>(collectedFlexItemsValues.itemsOnLine + 1);
betweenMainDim += leadingMainDim;
break;
case YGJustifySpaceAround:
// Space on the edges is half of the space between elements
leadingMainDim = 0.5f * collectedFlexItemsValues.remainingFreeSpace /
collectedFlexItemsValues.itemsOnLine;
static_cast<float>(collectedFlexItemsValues.itemsOnLine);
betweenMainDim += leadingMainDim * 2;
break;
case YGJustifyFlexStart:
Expand Down Expand Up @@ -1550,7 +1550,7 @@ static void YGJustifyMainAxis(
if (child->marginLeadingValue(mainAxis).unit == YGUnitAuto) {
collectedFlexItemsValues.mainDim +=
collectedFlexItemsValues.remainingFreeSpace /
numberOfAutoMarginsOnCurrentLine;
static_cast<float>(numberOfAutoMarginsOnCurrentLine);
}

if (performLayout) {
Expand All @@ -1563,7 +1563,7 @@ static void YGJustifyMainAxis(
if (child->marginTrailingValue(mainAxis).unit == YGUnitAuto) {
collectedFlexItemsValues.mainDim +=
collectedFlexItemsValues.remainingFreeSpace /
numberOfAutoMarginsOnCurrentLine;
static_cast<float>(numberOfAutoMarginsOnCurrentLine);
}
bool canSkipFlex =
!performLayout && measureModeCrossDim == YGMeasureModeExactly;
Expand Down Expand Up @@ -1890,7 +1890,7 @@ static void calculateLayoutImpl(
if (childCount > 1) {
totalMainDim +=
node->getGapForAxis(mainAxis, availableInnerCrossDim).unwrap() *
(childCount - 1);
static_cast<float>(childCount - 1);
}

const bool mainAxisOverflows =
Expand Down Expand Up @@ -2261,22 +2261,26 @@ static void calculateLayoutImpl(
break;
case YGAlignStretch:
if (availableInnerCrossDim > totalLineCrossDim) {
crossDimLead = remainingAlignContentDim / lineCount;
crossDimLead =
remainingAlignContentDim / static_cast<float>(lineCount);
}
break;
case YGAlignSpaceAround:
if (availableInnerCrossDim > totalLineCrossDim) {
currentLead += remainingAlignContentDim / (2 * lineCount);
currentLead +=
remainingAlignContentDim / (2 * static_cast<float>(lineCount));
if (lineCount > 1) {
crossDimLead = remainingAlignContentDim / lineCount;
crossDimLead =
remainingAlignContentDim / static_cast<float>(lineCount);
}
} else {
currentLead += remainingAlignContentDim / 2;
}
break;
case YGAlignSpaceBetween:
if (availableInnerCrossDim > totalLineCrossDim && lineCount > 1) {
crossDimLead = remainingAlignContentDim / (lineCount - 1);
crossDimLead =
remainingAlignContentDim / static_cast<float>(lineCount - 1);
}
break;
case YGAlignAuto:
Expand Down Expand Up @@ -2843,11 +2847,11 @@ bool calculateLayoutInternal(
layout->lastOwnerDirection = ownerDirection;

if (cachedResults == nullptr) {
if (layout->nextCachedMeasurementsIndex + 1 >
(uint32_t) layoutMarkerData.maxMeasureCache) {
layoutMarkerData.maxMeasureCache =
layout->nextCachedMeasurementsIndex + 1;
}

layoutMarkerData.maxMeasureCache = std::max(
layoutMarkerData.maxMeasureCache,
layout->nextCachedMeasurementsIndex + 1u);

if (layout->nextCachedMeasurementsIndex ==
LayoutResults::MaxCachedMeasurements) {
if (gPrintChanges) {
Expand Down
27 changes: 10 additions & 17 deletions yoga/bits/NumericBitfield.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@

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));
}

constexpr int mask(size_t bitWidth, size_t index) {
return ((1 << bitWidth) - 1) << index;
constexpr uint32_t mask(uint8_t bitWidth, uint8_t index) {
return ((1u << bitWidth) - 1u) << index;
}

} // namespace facebook::yoga::details
Expand All @@ -29,38 +29,31 @@ namespace facebook::yoga {

// The number of bits necessary to represent enums defined with YG_ENUM_SEQ_DECL
template <typename Enum>
constexpr size_t minimumBitCount() {
constexpr uint8_t minimumBitCount() {
static_assert(
enums::count<Enum>() > 0, "Enums must have at least one entries");
return details::log2ceilFn(enums::count<Enum>() - 1);
}

template <typename Enum>
constexpr Enum getEnumData(int flags, size_t index) {
constexpr Enum getEnumData(uint32_t flags, uint8_t index) {
return static_cast<Enum>(
(flags & details::mask(minimumBitCount<Enum>(), index)) >> index);
}

template <typename Enum>
void setEnumData(uint32_t& flags, size_t index, int newValue) {
flags = (flags & ~details::mask(minimumBitCount<Enum>(), index)) |
((newValue << index) & (details::mask(minimumBitCount<Enum>(), index)));
}

template <typename Enum>
void setEnumData(uint8_t& flags, size_t index, int newValue) {
void setEnumData(uint32_t& flags, uint8_t index, uint32_t newValue) {
flags =
(flags &
~static_cast<uint8_t>(details::mask(minimumBitCount<Enum>(), index))) |
((newValue << index) &
(static_cast<uint8_t>(details::mask(minimumBitCount<Enum>(), index))));
~static_cast<uint32_t>(details::mask(minimumBitCount<Enum>(), index))) |
((newValue << index) & (details::mask(minimumBitCount<Enum>(), index)));
}

constexpr bool getBooleanData(int flags, size_t index) {
constexpr bool getBooleanData(uint32_t flags, uint8_t index) {
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) {
flags |= 1 << index;
} else {
Expand Down
4 changes: 2 additions & 2 deletions yoga/debug/NodeToString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ static void appendFormattedString(std::string& str, const char* fmt, ...) {
va_start(args, fmt);
va_list argsCopy;
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);
vsnprintf(buf.data(), buf.size(), fmt, argsCopy);
va_end(argsCopy);
Expand Down Expand Up @@ -96,7 +96,7 @@ static void appendEdges(
} else {
for (int edge = YGEdgeLeft; edge != YGEdgeAll; ++edge) {
std::string str = key + "-" + YGEdgeToString(static_cast<YGEdge>(edge));
appendNumberIfNotZero(base, str, edges[edge]);
appendNumberIfNotZero(base, str, edges[static_cast<size_t>(edge)]);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion yoga/event/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ enum struct LayoutPassReason : int {
struct LayoutData {
int layouts;
int measures;
int maxMeasureCache;
uint32_t maxMeasureCache;
int cachedLayouts;
int cachedMeasures;
int measureCallbacks;
Expand Down
Loading

0 comments on commit a3511a3

Please sign in to comment.