Index: include/clang/Driver/Driver.h =================================================================== --- include/clang/Driver/Driver.h +++ include/clang/Driver/Driver.h @@ -475,6 +475,15 @@ static bool GetReleaseVersion(const char *Str, unsigned &Major, unsigned &Minor, unsigned &Micro, bool &HadExtra); + + /// Parse digits from a string \p Str and fulfill \p Digits with + /// the parsed numbers. This method assumes that the max number of + /// digits to look for is equal to Digits.size(). + /// + /// \return True if the entire string was parsed and there are + /// no extra characters remaining at the end. + static bool GetReleaseVersion(const char *Str, + MutableArrayRef Digits); }; /// \return True if the last defined optimization level is -Ofast. Index: lib/Driver/Driver.cpp =================================================================== --- lib/Driver/Driver.cpp +++ lib/Driver/Driver.cpp @@ -2533,6 +2533,35 @@ return true; } +/// Parse digits from a string \p Str and fulfill \p Digits with +/// the parsed numbers. This method assumes that the max number of +/// digits to look for is equal to Digits.size(). +/// +/// \return True if the entire string was parsed and there are +/// no extra characters remaining at the end. +bool Driver::GetReleaseVersion(const char *Str, + MutableArrayRef Digits) { + if (*Str == '\0') + return false; + + char *End; + unsigned CurDigit = 0; + unsigned MaxDigits = Digits.size(); + while (CurDigit < MaxDigits) { + unsigned Digit = (unsigned)strtol(Str, &End, 10); + Digits[CurDigit] = Digit; + if (*Str != '\0' && *End == '\0') + return true; + if (*End != '.' || Str == End) + return false; + Str = End + 1; + CurDigit++; + } + + // More digits than requested, bail out... + return false; +} + std::pair Driver::getIncludeExcludeOptionFlagMasks() const { unsigned IncludedFlagsBitmask = 0; unsigned ExcludedFlagsBitmask = options::NoDriverOption; Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -7221,12 +7221,9 @@ const Driver &D = getToolChain().getDriver(); const toolchains::MachO &MachOTC = getMachOToolChain(); - unsigned Version[3] = {0, 0, 0}; + unsigned Version[5] = {0, 0, 0, 0, 0}; if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) { - bool HadExtra; - if (!Driver::GetReleaseVersion(A->getValue(), Version[0], Version[1], - Version[2], HadExtra) || - HadExtra) + if (!Driver::GetReleaseVersion(A->getValue(), Version)) D.Diag(diag::err_drv_invalid_version_number) << A->getAsString(Args); } Index: test/Driver/darwin-ld.c =================================================================== --- test/Driver/darwin-ld.c +++ test/Driver/darwin-ld.c @@ -303,3 +303,27 @@ // RUN: FileCheck --check-prefix=LINK-IFRAMEWORK %s // LINK-IFRAMEWORK: {{ld(.exe)?"}} // LINK-IFRAMEWORK: "-FBar" + +// Check ld64 accepts up to 5 digits with no extra characters +// RUN: %clang -target x86_64-apple-darwin12 %s -### -o %t \ +// RUN: -mlinker-version=133.3 2> %t.log +// RUN: %clang -target x86_64-apple-darwin12 %s -### -o %t \ +// RUN: -mlinker-version=133.3.0 2>> %t.log +// RUN: %clang -target x86_64-apple-darwin12 %s -### -o %t \ +// RUN: -mlinker-version=133.3.0.1 2>> %t.log +// RUN: %clang -target x86_64-apple-darwin12 %s -### -o %t \ +// RUN: -mlinker-version=133.3.0.1.2 2>> %t.log +// RUN: %clang -target x86_64-apple-darwin12 %s -### -o %t \ +// RUN: -mlinker-version=133.3.0.1.2.6 2>> %t.log +// RUN: %clang -target x86_64-apple-darwin12 %s -### -o %t \ +// RUN: -mlinker-version=133.3.0.1.a 2>> %t.log +// RUN: %clang -target x86_64-apple-darwin12 %s -### -o %t \ +// RUN: -mlinker-version=133.3.0.1a 2>> %t.log +// RUN: FileCheck -check-prefix=LINK_VERSION_DIGITS %s < %t.log +// LINK_VERSION_DIGITS-NOT: invalid version number in '-mlinker-version=133.3' +// LINK_VERSION_DIGITS-NOT: invalid version number in '-mlinker-version=133.3.0' +// LINK_VERSION_DIGITS-NOT: invalid version number in '-mlinker-version=133.3.0.1' +// LINK_VERSION_DIGITS-NOT: invalid version number in '-mlinker-version=133.3.0.1.2' +// LINK_VERSION_DIGITS: invalid version number in '-mlinker-version=133.3.0.1.2.6' +// LINK_VERSION_DIGITS: invalid version number in '-mlinker-version=133.3.0.1.a' +// LINK_VERSION_DIGITS: invalid version number in '-mlinker-version=133.3.0.1a'