jkorous created this revision.
jkorous added reviewers: arphaman, vsapsai, bruno, JDevlieghere.
Herald added subscribers: cfe-commits, dexonsmith.
In case user specified non-existent warning flag clang was suggesting an
existing on that was in some cased very different. This patch should ensure
that either a relevant warning flag is suggested or none (which is in line with
unknown generic command line option handling).
Examples:
warning: unknown warning option '-Whiskey'; did you mean '-Wpacked'?
warning: unknown warning option '-Weverthin'; did you mean '-Wsection'?
rdar://problem/37755482
I changed interface of DiagnosticIDs::getNearestOption() to return the edit
distance between nonexistent flag and the closest exiting one. In principle
this code is analogous to OptTable::findNearest() for generic command line
options but I don't find them similar enough in order to factor out some shared
implementation. I tentatively selected maximum edit distance as 2
(CompilerInvocation::CreateFromArgs() uses maximum edit distance of 1 for
generic case).
Repository:
rC Clang
https://reviews.llvm.org/D49736
Files:
Basic/DiagnosticIDs.cpp
Basic/Warnings.cpp
Driver/cc-log-diagnostics.c
Frontend/warning-options.cpp
clang/Basic/DiagnosticIDs.h
Index: Frontend/warning-options.cpp
===================================================================
--- Frontend/warning-options.cpp
+++ Frontend/warning-options.cpp
@@ -3,5 +3,5 @@
// CHECK: unknown warning option '-Wmonkey'
// CHECK: unknown warning option '-Wno-monkey'
// CHECK: unknown warning option '-Wno-unused-command-line-arguments'; did you mean '-Wno-unused-command-line-argument'?
-// CHECK: unknown warning option '-Wmodule-build'; did you mean '-Wmodule-conflict'?
+// CHECK: unknown warning option '-Wmodule-build'
// CHECK: unknown remark option '-Rmodule-built'; did you mean '-Rmodule-build'?
Index: Driver/cc-log-diagnostics.c
===================================================================
--- Driver/cc-log-diagnostics.c
+++ Driver/cc-log-diagnostics.c
@@ -17,7 +17,7 @@
// CHECK: <key>level</key>
// CHECK: <string>warning</string>
// CHECK: <key>message</key>
-// CHECK: <string>unknown warning option '-Wfoobar'; did you mean '-W{{.*}}'?</string>
+// CHECK: <string>unknown warning option '-Wfoobar'</string>
// CHECK: </dict>
// CHECK: <dict>
// CHECK: <key>level</key>
Index: Basic/Warnings.cpp
===================================================================
--- Basic/Warnings.cpp
+++ Basic/Warnings.cpp
@@ -30,15 +30,24 @@
#include <utility>
using namespace clang;
+namespace {
+ constexpr unsigned MaxLevenshteinDistForWarningSuggestion = 2;
+}
+
// EmitUnknownDiagWarning - Emit a warning and typo hint for unknown warning
// opts
static void EmitUnknownDiagWarning(DiagnosticsEngine &Diags,
diag::Flavor Flavor, StringRef Prefix,
StringRef Opt) {
- StringRef Suggestion = DiagnosticIDs::getNearestOption(Flavor, Opt);
+ std::string Suggestion;
+ const unsigned OptToSuggestionEditDist
+ = DiagnosticIDs::getNearestOption(Flavor, Opt, Suggestion);
Diags.Report(diag::warn_unknown_diag_option)
<< (Flavor == diag::Flavor::WarningOrError ? 0 : 1) << (Prefix.str() += Opt)
- << !Suggestion.empty() << (Prefix.str() += Suggestion);
+ << (!Suggestion.empty()
+ && OptToSuggestionEditDist > 0
+ && OptToSuggestionEditDist <= MaxLevenshteinDistForWarningSuggestion)
+ << (Prefix.str() += Suggestion);
}
void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
Index: Basic/DiagnosticIDs.cpp
===================================================================
--- Basic/DiagnosticIDs.cpp
+++ Basic/DiagnosticIDs.cpp
@@ -589,9 +589,9 @@
Diags.push_back(StaticDiagInfo[i].DiagID);
}
-StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor,
- StringRef Group) {
- StringRef Best;
+unsigned DiagnosticIDs::getNearestOption(diag::Flavor Flavor,
+ StringRef Group,
+ std::string& NearestOption) {
unsigned BestDistance = Group.size() + 1; // Sanity threshold.
for (const WarningOption &O : OptionTable) {
// Don't suggest ignored warning flags.
@@ -609,15 +609,15 @@
if (Distance == BestDistance) {
// Two matches with the same distance, don't prefer one over the other.
- Best = "";
+ NearestOption = "";
} else if (Distance < BestDistance) {
// This is a better match.
- Best = O.getName();
+ NearestOption = O.getName();
BestDistance = Distance;
}
}
- return Best;
+ return BestDistance;
}
/// ProcessDiag - This is the method used to report a diagnostic that is
Index: clang/Basic/DiagnosticIDs.h
===================================================================
--- clang/Basic/DiagnosticIDs.h
+++ clang/Basic/DiagnosticIDs.h
@@ -300,8 +300,12 @@
std::vector<diag::kind> &Diags);
/// Get the diagnostic option with the closest edit distance to the
- /// given group name.
- static StringRef getNearestOption(diag::Flavor Flavor, StringRef Group);
+ /// given Group name and return their edit distance.
+ /// \param [out] NearestOption - The nearest option string found.
+ ///
+ /// \return The edit distance between Group and the nearest option found.
+ static unsigned getNearestOption(diag::Flavor Flavor, StringRef Group,
+ std::string& NearestOption);
private:
/// Classify the specified diagnostic ID into a Level, consumable by
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits