[Support] Avoid setting minor/subminor/build in VersionTuple::withMajorReplaced (#139318)

The expectation of this API is that it only changes the major version of
a preexisting version tuple. However, it was adding 0's, which caused
unintended changes in serialization or printing.

Instead, check for the existence of the non-major parts of the tuple.
This commit is contained in:
Cyndy Ishida
2025-05-09 16:56:18 -07:00
committed by GitHub
parent fbcde15978
commit 12e6622d4a
4 changed files with 43 additions and 5 deletions

View File

@@ -30,8 +30,8 @@
// LINK: "-platform_version" "xros" "1.0.0" "1.0.0"
// LINK-SIM: "-platform_version" "xros-simulator" "1.0.0" "1.0.0"
// OBJC-RUNTIME: "-fobjc-runtime=ios-17.0.0.0"
// OBJC-RUNTIME2: "-fobjc-runtime=ios-18.0.0.0"
// OBJC-RUNTIME: "-fobjc-runtime=ios-17.0.0"
// OBJC-RUNTIME2: "-fobjc-runtime=ios-18.0.0"
// ARC-NOT: error:
// SSP_ON: "-stack-protector" "1"

View File

@@ -100,9 +100,7 @@ public:
/// Return a version tuple that contains a different major version but
/// everything else is the same.
VersionTuple withMajorReplaced(unsigned NewMajor) const {
return VersionTuple(NewMajor, Minor, Subminor, Build);
}
VersionTuple withMajorReplaced(unsigned NewMajor) const;
/// Return a version tuple that contains only components that are non-zero.
VersionTuple normalize() const {

View File

@@ -108,3 +108,13 @@ bool VersionTuple::tryParse(StringRef input) {
*this = VersionTuple(major, minor, micro, build);
return false;
}
VersionTuple VersionTuple::withMajorReplaced(unsigned NewMajor) const {
if (HasBuild)
return VersionTuple(NewMajor, Minor, Subminor, Build);
if (HasSubminor)
return VersionTuple(NewMajor, Minor, Subminor);
if (HasMinor)
return VersionTuple(NewMajor, Minor);
return VersionTuple(NewMajor);
}

View File

@@ -47,3 +47,33 @@ TEST(VersionTuple, tryParse) {
EXPECT_TRUE(VT.tryParse("1 "));
EXPECT_TRUE(VT.tryParse("."));
}
TEST(VersionTuple, withMajorReplaced) {
VersionTuple VT(2);
VersionTuple ReplacedVersion = VT.withMajorReplaced(7);
EXPECT_FALSE(ReplacedVersion.getMinor().has_value());
EXPECT_FALSE(ReplacedVersion.getSubminor().has_value());
EXPECT_FALSE(ReplacedVersion.getBuild().has_value());
EXPECT_EQ(VersionTuple(7), ReplacedVersion);
VT = VersionTuple(100, 1);
ReplacedVersion = VT.withMajorReplaced(7);
EXPECT_TRUE(ReplacedVersion.getMinor().has_value());
EXPECT_FALSE(ReplacedVersion.getSubminor().has_value());
EXPECT_FALSE(ReplacedVersion.getBuild().has_value());
EXPECT_EQ(VersionTuple(7, 1), ReplacedVersion);
VT = VersionTuple(101, 11, 12);
ReplacedVersion = VT.withMajorReplaced(7);
EXPECT_TRUE(ReplacedVersion.getMinor().has_value());
EXPECT_TRUE(ReplacedVersion.getSubminor().has_value());
EXPECT_FALSE(ReplacedVersion.getBuild().has_value());
EXPECT_EQ(VersionTuple(7, 11, 12), ReplacedVersion);
VT = VersionTuple(101, 11, 12, 2);
ReplacedVersion = VT.withMajorReplaced(7);
EXPECT_TRUE(ReplacedVersion.getMinor().has_value());
EXPECT_TRUE(ReplacedVersion.getSubminor().has_value());
EXPECT_TRUE(ReplacedVersion.getBuild().has_value());
EXPECT_EQ(VersionTuple(7, 11, 12, 2), ReplacedVersion);
}