[clang] [clang] [Gnu] Improve GCCVersion parsing to match versions such as "10-win32" (PR #69079)
Martin Storsjö via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 25 13:34:34 PDT 2023
================
@@ -2007,45 +2007,71 @@ Generic_GCC::GCCVersion Generic_GCC::GCCVersion::Parse(StringRef VersionText) {
std::pair<StringRef, StringRef> First = VersionText.split('.');
std::pair<StringRef, StringRef> Second = First.second.split('.');
- GCCVersion GoodVersion = {VersionText.str(), -1, -1, -1, "", "", ""};
- if (First.first.getAsInteger(10, GoodVersion.Major) || GoodVersion.Major < 0)
- return BadVersion;
- GoodVersion.MajorStr = First.first.str();
- if (First.second.empty())
- return GoodVersion;
+ StringRef MajorStr = First.first;
StringRef MinorStr = Second.first;
- if (Second.second.empty()) {
- if (size_t EndNumber = MinorStr.find_first_not_of("0123456789")) {
- GoodVersion.PatchSuffix = std::string(MinorStr.substr(EndNumber));
- MinorStr = MinorStr.slice(0, EndNumber);
- }
- }
- if (MinorStr.getAsInteger(10, GoodVersion.Minor) || GoodVersion.Minor < 0)
- return BadVersion;
- GoodVersion.MinorStr = MinorStr.str();
+ StringRef PatchStr = Second.second;
- // First look for a number prefix and parse that if present. Otherwise just
- // stash the entire patch string in the suffix, and leave the number
- // unspecified. This covers versions strings such as:
- // 5 (handled above)
+ GCCVersion GoodVersion = {VersionText.str(), -1, -1, -1, "", "", ""};
+
+ // Parse version number strings such as:
+ // 5
// 4.4
// 4.4-patched
// 4.4.0
// 4.4.x
// 4.4.2-rc4
// 4.4.x-patched
- // And retains any patch number it finds.
- StringRef PatchText = Second.second;
- if (!PatchText.empty()) {
- if (size_t EndNumber = PatchText.find_first_not_of("0123456789")) {
- // Try to parse the number and any suffix.
- if (PatchText.slice(0, EndNumber).getAsInteger(10, GoodVersion.Patch) ||
- GoodVersion.Patch < 0)
- return BadVersion;
- GoodVersion.PatchSuffix = std::string(PatchText.substr(EndNumber));
+ // 10-win32
+ // Split on '.', handle 1, 2 or 3 such segments. Each segment must contain
+ // purely a number, except for the last one, where a non-number suffix
+ // is stored in PatchSuffix. The third segment is allowed to not contain
+ // a number at all.
+
+ auto HandleLastNumber = [&](StringRef Segment, int &Number,
+ std::string &OutStr) -> bool {
+ // Look for a number prefix and parse that, and split out any trailing
+ // string into GoodVersion.PatchSuffix.
+
+ if (size_t EndNumber = Segment.find_first_not_of("0123456789")) {
+ StringRef NumberStr = Segment.slice(0, EndNumber);
+ if (NumberStr.getAsInteger(10, Number) || Number < 0)
+ return false;
+ OutStr = NumberStr;
+ GoodVersion.PatchSuffix = Segment.substr(EndNumber);
+ return true;
}
+ return false;
+ };
+ auto HandleNumber = [](StringRef Segment, int &Number) -> bool {
+ if (Segment.getAsInteger(10, Number) || Number < 0)
+ return false;
+ return true;
+ };
+
+ if (MinorStr.empty()) {
+ // If no minor string, major is the last segment
+ if (!HandleLastNumber(MajorStr, GoodVersion.Major, GoodVersion.MajorStr))
+ return BadVersion;
+ return GoodVersion;
+ } else {
+ if (!HandleNumber(MajorStr, GoodVersion.Major))
+ return BadVersion;
+ GoodVersion.MajorStr = MajorStr;
+ }
+ if (PatchStr.empty()) {
+ // If no patch string, minor is the last segment
+ if (!HandleLastNumber(MinorStr, GoodVersion.Minor, GoodVersion.MinorStr))
+ return BadVersion;
+ return GoodVersion;
+ } else {
+ if (!HandleNumber(MinorStr, GoodVersion.Minor))
+ return BadVersion;
+ GoodVersion.MinorStr = MinorStr;
}
+ // For the last segment, tolerate a missing number.
+ std::string DummyStr;
+ HandleLastNumber(PatchStr, GoodVersion.Patch, DummyStr);
----------------
mstorsjo wrote:
This implementation does parse `10-10` as `Major=10`, the rest left at -1, and `PatchSuffix="-10"`.
I'm not sure exactly which bit gives you the impression that case wouldn't get handled like that. The comment above ("For the last segment, tolerate a missing number") only means that for the case `4.4.x-patched`, we don't return an error even if the last bit is `x-patched`, but we return what we've parsed up to that point.
https://github.com/llvm/llvm-project/pull/69079
More information about the cfe-commits
mailing list