From a70cb9db9dd79ca9fc1febbb2f331004297664e0 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Mon, 14 Nov 2011 23:30:34 +0000 Subject: [PATCH] Print a typo correction hint for unknown warning flags. $ clang -Wololo t.c warning: unknown warning option '-Wololo'; did you mean '-Wall'? [-Wunknown-warning-option] git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144591 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../clang/Basic/DiagnosticFrontendKinds.td | 4 ++-- include/clang/Basic/DiagnosticIDs.h | 4 ++++ lib/Basic/DiagnosticIDs.cpp | 21 +++++++++++++++++++ lib/Frontend/Warnings.cpp | 11 +++++++--- test/Driver/cc-log-diagnostics.c | 2 +- 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index c9f5a5c486..91e32200f2 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -148,10 +148,10 @@ def warn_pch_compiler_options_mismatch : Error< def err_not_a_pch_file : Error< "'%0' does not appear to be a precompiled header file">, DefaultFatal; def warn_unknown_warning_option : Warning< - "unknown warning option '%0'">, + "unknown warning option '%0'; did you mean '%1'?">, InGroup >; def warn_unknown_negative_warning_option : Warning< - "unknown warning option '%0'">, + "unknown warning option '%0'; did you mean '%1'?">, InGroup >, DefaultIgnore; def warn_unknown_warning_specifier : Warning< "unknown %0 warning specifier: '%1'">, diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h index 1ff6c11924..da85ea491b 100644 --- a/include/clang/Basic/DiagnosticIDs.h +++ b/include/clang/Basic/DiagnosticIDs.h @@ -262,6 +262,10 @@ public: bool getDiagnosticsInGroup(StringRef Group, llvm::SmallVectorImpl &Diags) const; + /// \brief Get the warning option with the closest edit distance to the given + /// group name. + static StringRef getNearestWarningOption(StringRef Group); + private: /// \brief Get the set of all diagnostic IDs in the given group. /// diff --git a/lib/Basic/DiagnosticIDs.cpp b/lib/Basic/DiagnosticIDs.cpp index b14cdc9ba3..39fee69adb 100644 --- a/lib/Basic/DiagnosticIDs.cpp +++ b/lib/Basic/DiagnosticIDs.cpp @@ -681,6 +681,27 @@ bool DiagnosticIDs::getDiagnosticsInGroup( return false; } +StringRef DiagnosticIDs::getNearestWarningOption(StringRef Group) { + StringRef Best; + unsigned BestDistance = 0; + for (const WarningOption *i = OptionTable, *e = OptionTable + OptionTableSize; + i != e; ++i) { + // Don't suggest ignored warning flags. + if (!i->Members && !i->SubGroups) + continue; + + unsigned Distance = i->getName().edit_distance(Group, true, BestDistance); + + // Check if this is a better match. + if (Best.empty() || Distance < BestDistance) { + Best = i->getName(); + BestDistance = Distance; + } + } + + return Best; +} + /// ProcessDiag - This is the method used to report a diagnostic that is /// finally fully formed. bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const { diff --git a/lib/Frontend/Warnings.cpp b/lib/Frontend/Warnings.cpp index 7fcbe3acd4..ba0cd38045 100644 --- a/lib/Frontend/Warnings.cpp +++ b/lib/Frontend/Warnings.cpp @@ -120,7 +120,9 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags, } else if (DiagIDs->getDiagnosticsInGroup(Specifier, _Diags)) { Diags.Report(isPositive ? diag::warn_unknown_warning_option : diag::warn_unknown_negative_warning_option) - << ("-W" + Opt.str()); + << ("-W" + Opt.str()) + << ("-Werror=" + + DiagnosticIDs::getNearestWarningOption(Specifier).str()); } continue; } @@ -150,7 +152,9 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags, } else if (DiagIDs->getDiagnosticsInGroup(Specifier, _Diags)) { Diags.Report(isPositive ? diag::warn_unknown_warning_option : diag::warn_unknown_negative_warning_option) - << ("-W" + Opt.str()); + << ("-W" + Opt.str()) + << ("-Wfatal-errors=" + + DiagnosticIDs::getNearestWarningOption(Specifier).str()); } continue; } @@ -158,7 +162,8 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags, if (Report && DiagIDs->getDiagnosticsInGroup(Opt, _Diags)) { Diags.Report(isPositive ? diag::warn_unknown_warning_option : diag::warn_unknown_negative_warning_option) - << ("-W" + Opt.str()); + << ("-W" + Opt.str()) + << ("-W" + DiagnosticIDs::getNearestWarningOption(Opt).str()); } else { Diags.setDiagnosticGroupMapping(Opt, Mapping); } diff --git a/test/Driver/cc-log-diagnostics.c b/test/Driver/cc-log-diagnostics.c index 2fdbe5133c..96b2ec3e5d 100644 --- a/test/Driver/cc-log-diagnostics.c +++ b/test/Driver/cc-log-diagnostics.c @@ -17,7 +17,7 @@ int f0() {} // CHECK: level // CHECK: warning // CHECK: message -// CHECK: unknown warning option '-Wfoobar' +// CHECK: unknown warning option '-Wfoobar'; did you mean '-W{{.*}}'? // CHECK: // CHECK: // CHECK: level -- 2.40.0