Index: clang/lib/Driver/Driver.cpp =================================================================== --- clang/lib/Driver/Driver.cpp +++ clang/lib/Driver/Driver.cpp @@ -313,8 +313,8 @@ std::string Nearest; if (getOpts().findNearest(ArgString, Nearest, IncludedFlagsBitmask, ExcludedFlagsBitmask) > 1) { - if (getOpts().findNearest(ArgString, Nearest, options::CC1Option) == 0 && - !IsCLMode()) { + if (!IsCLMode() && + getOpts().findExact(ArgString, Nearest, options::CC1Option)) { DiagID = diag::err_drv_unknown_argument_with_suggestion; Diags.Report(DiagID) << ArgString << "-Xclang " + Nearest; } else { @@ -339,8 +339,8 @@ // Warn on joined arguments that are similar to a long argument. std::string ArgString = ArgStrings[A->getIndex()]; std::string Nearest; - if (getOpts().findNearest("-" + ArgString, Nearest, IncludedFlagsBitmask, - ExcludedFlagsBitmask) == 0) + if (getOpts().findExact("-" + ArgString, Nearest, IncludedFlagsBitmask, + ExcludedFlagsBitmask)) Diags.Report(diag::warn_drv_potentially_misspelled_joined_argument) << A->getAsString(Args) << Nearest; } Index: llvm/include/llvm/Option/OptTable.h =================================================================== --- llvm/include/llvm/Option/OptTable.h +++ llvm/include/llvm/Option/OptTable.h @@ -175,11 +175,21 @@ /// \param [in] MinimumLength - Don't find options shorter than this length. /// For example, a minimum length of 3 prevents "-x" from being considered /// near to "-S". + /// \param [in] MaximumDistance - Don't find options whose distance is greater + /// than this value. /// /// \return The edit distance of the nearest string found. unsigned findNearest(StringRef Option, std::string &NearestString, unsigned FlagsToInclude = 0, unsigned FlagsToExclude = 0, - unsigned MinimumLength = 4) const; + unsigned MinimumLength = 4, + unsigned MaximumDistance = UINT_MAX - 1) const; + + bool findExact(StringRef Option, std::string &ExactString, + unsigned FlagsToInclude = 0, + unsigned FlagsToExclude = 0) const { + return findNearest(Option, ExactString, FlagsToInclude, FlagsToExclude, + 4, 0) == 0; + } /// Parse a single argument; returning the new argument and /// updating Index. Index: llvm/lib/Option/OptTable.cpp =================================================================== --- llvm/lib/Option/OptTable.cpp +++ llvm/lib/Option/OptTable.cpp @@ -227,12 +227,13 @@ unsigned OptTable::findNearest(StringRef Option, std::string &NearestString, unsigned FlagsToInclude, unsigned FlagsToExclude, - unsigned MinimumLength) const { + unsigned MinimumLength, + unsigned MaximumDistance) const { assert(!Option.empty()); // Consider each [option prefix + option name] pair as a candidate, finding // the closest match. - unsigned BestDistance = UINT_MAX; + unsigned BestDistance = MaximumDistance + 1; SmallString<16> Candidate; SmallString<16> NormalizedName; @@ -276,6 +277,14 @@ // appropriate one. For example, if a user asks for "--helm", suggest // "--help" over "-help". for (auto CandidatePrefix : CandidateInfo.Prefixes) { + // If Candidate and NormalizedName have more than 'BestDistance' + // characters of difference, no need to compute the edit distance, it's + // going to be greater than BestDistance. Don't bother computing Candidate + // at all. + if (std::abs((ssize_t)(CandidatePrefix.size() + CandidateName.size()) - + (ssize_t)NormalizedName.size()) > (ssize_t)BestDistance) { + continue; + } Candidate = CandidatePrefix; Candidate += CandidateName; unsigned Distance = StringRef(Candidate).edit_distance(