r361518 - lld-link, clang: Treat non-existent input files as possible spellos for option flags

Hans Wennborg via cfe-commits cfe-commits at lists.llvm.org
Mon May 27 01:36:35 PDT 2019


Want to put a note in ReleaseNotes.rst?

This is fixing something that a lot of users have run in to, so seems
worth mentioning :-)

On Thu, May 23, 2019 at 7:55 PM Nico Weber via cfe-commits
<cfe-commits at lists.llvm.org> wrote:
>
> Author: nico
> Date: Thu May 23 10:58:33 2019
> New Revision: 361518
>
> URL: http://llvm.org/viewvc/llvm-project?rev=361518&view=rev
> Log:
> lld-link, clang: Treat non-existent input files as possible spellos for option flags
>
> OptTable treats arguments starting with / that aren't a known option
> as filenames. This means lld-link's and clang-cl's typo correction for
> unknown flags didn't do spell checking for misspelled options that start
> with /.
>
> I first tried changing OptTable, but that got pretty messy, see PR41787
> comments 2 and 3.
>
> Instead, let lld-link's and clang's (including clang-cl's) "file not
> found" diagnostic check if a non-existent file looks like it could be a
> mis-spelled option, and if so add a "did you mean" suggestion to the
> "file not found" diagnostic.
>
> While here, make formatting of a few diagnostics a bit more
> self-consistent.
>
> Fixes PR41787.
>
> Differential Revision: https://reviews.llvm.org/D62276
>
> Modified:
>     cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td
>     cfe/trunk/include/clang/Driver/Driver.h
>     cfe/trunk/lib/Driver/Driver.cpp
>     cfe/trunk/test/Driver/unknown-arg.c
>     cfe/trunk/test/Driver/unsupported-option.c
>     cfe/trunk/test/Frontend/unknown-arg.c
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td?rev=361518&r1=361517&r2=361518&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td Thu May 23 10:58:33 2019
> @@ -9,9 +9,11 @@
>  let Component = "Driver" in {
>
>  def err_drv_no_such_file : Error<"no such file or directory: '%0'">;
> +def err_drv_no_such_file_with_suggestion : Error<
> +  "no such file or directory: '%0'; did you mean '%1'?">;
>  def err_drv_unsupported_opt : Error<"unsupported option '%0'">;
> -def err_drv_unsupported_opt_with_suggestion
> -  : Error<"unsupported option '%0', did you mean '%1'?">;
> +def err_drv_unsupported_opt_with_suggestion : Error<
> +  "unsupported option '%0'; did you mean '%1'?">;
>  def err_drv_unsupported_opt_for_target : Error<
>    "unsupported option '%0' for target '%1'">;
>  def err_drv_unsupported_option_argument : Error<
> @@ -166,13 +168,13 @@ def err_arch_unsupported_isa
>  def err_drv_I_dash_not_supported : Error<
>    "'%0' not supported, please use -iquote instead">;
>  def err_drv_unknown_argument : Error<"unknown argument: '%0'">;
> -def err_drv_unknown_argument_with_suggestion
> -  : Error<"unknown argument '%0', did you mean '%1'?">;
> +def err_drv_unknown_argument_with_suggestion : Error<
> +  "unknown argument '%0'; did you mean '%1'?">;
>  def warn_drv_unknown_argument_clang_cl : Warning<
>    "unknown argument ignored in clang-cl: '%0'">,
>    InGroup<UnknownArgument>;
>  def warn_drv_unknown_argument_clang_cl_with_suggestion : Warning<
> -  "unknown argument ignored in clang-cl '%0' (did you mean '%1'?)">,
> +  "unknown argument ignored in clang-cl '%0'; did you mean '%1'?">,
>    InGroup<UnknownArgument>;
>
>  def warn_drv_ycyu_different_arg_clang_cl : Warning<
>
> Modified: cfe/trunk/include/clang/Driver/Driver.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Driver.h?rev=361518&r1=361517&r2=361518&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Driver/Driver.h (original)
> +++ cfe/trunk/include/clang/Driver/Driver.h Thu May 23 10:58:33 2019
> @@ -394,6 +394,14 @@ public:
>    void BuildUniversalActions(Compilation &C, const ToolChain &TC,
>                               const InputList &BAInputs) const;
>
> +  /// Check that the file referenced by Value exists. If it doesn't,
> +  /// issue a diagnostic and return false.
> +  /// If TypoCorrect is true and the file does not exist, see if it looks
> +  /// like a likely typo for a flag and if so print a "did you mean" blurb.
> +  bool DiagnoseInputExistence(const llvm::opt::DerivedArgList &Args,
> +                              StringRef Value, types::ID Ty,
> +                              bool TypoCorrect) const;
> +
>    /// BuildJobs - Bind actions to concrete tools and translate
>    /// arguments to form the list of jobs to run.
>    ///
>
> Modified: cfe/trunk/lib/Driver/Driver.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Driver.cpp?rev=361518&r1=361517&r2=361518&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Driver/Driver.cpp (original)
> +++ cfe/trunk/lib/Driver/Driver.cpp Thu May 23 10:58:33 2019
> @@ -1975,11 +1975,9 @@ void Driver::BuildUniversalActions(Compi
>    }
>  }
>
> -/// Check that the file referenced by Value exists. If it doesn't,
> -/// issue a diagnostic and return false.
> -static bool DiagnoseInputExistence(const Driver &D, const DerivedArgList &Args,
> -                                   StringRef Value, types::ID Ty) {
> -  if (!D.getCheckInputsExist())
> +bool Driver::DiagnoseInputExistence(const DerivedArgList &Args, StringRef Value,
> +                                    types::ID Ty, bool TypoCorrect) const {
> +  if (!getCheckInputsExist())
>      return true;
>
>    // stdin always exists.
> @@ -1995,10 +1993,10 @@ static bool DiagnoseInputExistence(const
>      }
>    }
>
> -  if (D.getVFS().exists(Path))
> +  if (getVFS().exists(Path))
>      return true;
>
> -  if (D.IsCLMode()) {
> +  if (IsCLMode()) {
>      if (!llvm::sys::path::is_absolute(Twine(Path)) &&
>          llvm::sys::Process::FindInEnvPath("LIB", Value))
>        return true;
> @@ -2011,7 +2009,26 @@ static bool DiagnoseInputExistence(const
>      }
>    }
>
> -  D.Diag(clang::diag::err_drv_no_such_file) << Path;
> +  if (TypoCorrect) {
> +    // Check if the filename is a typo for an option flag. OptTable thinks
> +    // that all args that are not known options and that start with / are
> +    // filenames, but e.g. `/diagnostic:caret` is more likely a typo for
> +    // the option `/diagnostics:caret` than a reference to a file in the root
> +    // directory.
> +    unsigned IncludedFlagsBitmask;
> +    unsigned ExcludedFlagsBitmask;
> +    std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) =
> +        getIncludeExcludeOptionFlagMasks(IsCLMode());
> +    std::string Nearest;
> +    if (getOpts().findNearest(Value, Nearest, IncludedFlagsBitmask,
> +                              ExcludedFlagsBitmask) <= 1) {
> +      Diag(clang::diag::err_drv_no_such_file_with_suggestion)
> +          << Path << Nearest;
> +      return false;
> +    }
> +  }
> +
> +  Diag(clang::diag::err_drv_no_such_file) << Path;
>    return false;
>  }
>
> @@ -2128,19 +2145,21 @@ void Driver::BuildInputs(const ToolChain
>          }
>        }
>
> -      if (DiagnoseInputExistence(*this, Args, Value, Ty))
> +      if (DiagnoseInputExistence(Args, Value, Ty, /*TypoCorrect=*/true))
>          Inputs.push_back(std::make_pair(Ty, A));
>
>      } else if (A->getOption().matches(options::OPT__SLASH_Tc)) {
>        StringRef Value = A->getValue();
> -      if (DiagnoseInputExistence(*this, Args, Value, types::TY_C)) {
> +      if (DiagnoseInputExistence(Args, Value, types::TY_C,
> +                                 /*TypoCorrect=*/false)) {
>          Arg *InputArg = MakeInputArg(Args, *Opts, A->getValue());
>          Inputs.push_back(std::make_pair(types::TY_C, InputArg));
>        }
>        A->claim();
>      } else if (A->getOption().matches(options::OPT__SLASH_Tp)) {
>        StringRef Value = A->getValue();
> -      if (DiagnoseInputExistence(*this, Args, Value, types::TY_CXX)) {
> +      if (DiagnoseInputExistence(Args, Value, types::TY_CXX,
> +                                 /*TypoCorrect=*/false)) {
>          Arg *InputArg = MakeInputArg(Args, *Opts, A->getValue());
>          Inputs.push_back(std::make_pair(types::TY_CXX, InputArg));
>        }
>
> Modified: cfe/trunk/test/Driver/unknown-arg.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/unknown-arg.c?rev=361518&r1=361517&r2=361518&view=diff
> ==============================================================================
> --- cfe/trunk/test/Driver/unknown-arg.c (original)
> +++ cfe/trunk/test/Driver/unknown-arg.c Thu May 23 10:58:33 2019
> @@ -1,23 +1,25 @@
>  // RUN: not %clang %s -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -ifoo -imultilib dir -### 2>&1 | \
> -// RUN: FileCheck %s
> +// RUN:     FileCheck %s
>  // RUN: %clang %s -imultilib dir -### 2>&1 | \
> -// RUN: FileCheck %s --check-prefix=MULTILIB
> +// RUN:     FileCheck %s --check-prefix=MULTILIB
>  // RUN: not %clang %s -stdlibs=foo -hell -version -### 2>&1 | \
> -// RUN: FileCheck %s --check-prefix=DID-YOU-MEAN
> +// RUN:     FileCheck %s --check-prefix=DID-YOU-MEAN
>  // RUN: %clang_cl -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -### -c -- %s 2>&1 | \
> -// RUN: FileCheck %s --check-prefix=CL
> +// RUN:     FileCheck %s --check-prefix=CL
>  // RUN: %clang_cl -Brepo -### -- %s 2>&1 | \
> -// RUN: FileCheck %s --check-prefix=CL-DID-YOU-MEAN
> +// RUN:     FileCheck %s --check-prefix=CL-DID-YOU-MEAN
> +// RUN: %clang_cl /Brepo -### -- %s 2>&1 | \
> +// RUN:     FileCheck %s --check-prefix=CL-DID-YOU-MEAN-SLASH
>  // RUN: not %clang_cl -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -c -Werror=unknown-argument -### -- %s 2>&1 | \
> -// RUN: FileCheck %s --check-prefix=CL-ERROR
> +// RUN:     FileCheck %s --check-prefix=CL-ERROR
>  // RUN: not %clang_cl -helo -Werror=unknown-argument -### -- %s 2>&1 | \
> -// RUN: FileCheck %s --check-prefix=CL-ERROR-DID-YOU-MEAN
> +// RUN:     FileCheck %s --check-prefix=CL-ERROR-DID-YOU-MEAN
>  // RUN: %clang_cl -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -c -Wno-unknown-argument -### -- %s 2>&1 | \
> -// RUN: FileCheck %s --check-prefix=SILENT
> +// RUN:     FileCheck %s --check-prefix=SILENT
>  // RUN: not %clang -cc1as -hell --version 2>&1 | \
> -// RUN: FileCheck %s --check-prefix=CC1AS-DID-YOU-MEAN
> +// RUN:     FileCheck %s --check-prefix=CC1AS-DID-YOU-MEAN
>  // RUN: not %clang -cc1asphalt -help 2>&1 | \
> -// RUN: FileCheck %s --check-prefix=UNKNOWN-INTEGRATED
> +// RUN:     FileCheck %s --check-prefix=UNKNOWN-INTEGRATED
>
>  // CHECK: error: unknown argument: '-cake-is-lie'
>  // CHECK: error: unknown argument: '-%0'
> @@ -28,9 +30,9 @@
>  // CHECK: error: unknown argument: '-funknown-to-clang-option'
>  // CHECK: error: unknown argument: '-ifoo'
>  // MULTILIB: warning: argument unused during compilation: '-imultilib dir'
> -// DID-YOU-MEAN: error: unknown argument '-stdlibs=foo', did you mean '-stdlib=foo'?
> -// DID-YOU-MEAN: error: unknown argument '-hell', did you mean '-help'?
> -// DID-YOU-MEAN: error: unknown argument '-version', did you mean '--version'?
> +// DID-YOU-MEAN: error: unknown argument '-stdlibs=foo'; did you mean '-stdlib=foo'?
> +// DID-YOU-MEAN: error: unknown argument '-hell'; did you mean '-help'?
> +// DID-YOU-MEAN: error: unknown argument '-version'; did you mean '--version'?
>  // CL: warning: unknown argument ignored in clang-cl: '-cake-is-lie'
>  // CL: warning: unknown argument ignored in clang-cl: '-%0'
>  // CL: warning: unknown argument ignored in clang-cl: '-%d'
> @@ -38,7 +40,8 @@
>  // CL: warning: unknown argument ignored in clang-cl: '-munknown-to-clang-option'
>  // CL: warning: unknown argument ignored in clang-cl: '-print-stats'
>  // CL: warning: unknown argument ignored in clang-cl: '-funknown-to-clang-option'
> -// CL-DID-YOU-MEAN: warning: unknown argument ignored in clang-cl '-Brepo' (did you mean '-Brepro'?)
> +// CL-DID-YOU-MEAN: warning: unknown argument ignored in clang-cl '-Brepo'; did you mean '-Brepro'?
> +// CL-DID-YOU-MEAN-SLASH: error: no such file or directory: '/Brepo'; did you mean '/Brepro'?
>  // CL-ERROR: error: unknown argument ignored in clang-cl: '-cake-is-lie'
>  // CL-ERROR: error: unknown argument ignored in clang-cl: '-%0'
>  // CL-ERROR: error: unknown argument ignored in clang-cl: '-%d'
> @@ -46,11 +49,11 @@
>  // CL-ERROR: error: unknown argument ignored in clang-cl: '-munknown-to-clang-option'
>  // CL-ERROR: error: unknown argument ignored in clang-cl: '-print-stats'
>  // CL-ERROR: error: unknown argument ignored in clang-cl: '-funknown-to-clang-option'
> -// CL-ERROR-DID-YOU-MEAN: error: unknown argument ignored in clang-cl '-helo' (did you mean '-help'?)
> +// CL-ERROR-DID-YOU-MEAN: error: unknown argument ignored in clang-cl '-helo'; did you mean '-help'?
>  // SILENT-NOT: error:
>  // SILENT-NOT: warning:
> -// CC1AS-DID-YOU-MEAN: error: unknown argument '-hell', did you mean '-help'?
> -// CC1AS-DID-YOU-MEAN: error: unknown argument '--version', did you mean '-version'?
> +// CC1AS-DID-YOU-MEAN: error: unknown argument '-hell'; did you mean '-help'?
> +// CC1AS-DID-YOU-MEAN: error: unknown argument '--version'; did you mean '-version'?
>  // UNKNOWN-INTEGRATED: error: unknown integrated tool 'asphalt'. Valid tools include '-cc1' and '-cc1as'.
>
>  // RUN: %clang -S %s -o %t.s  -Wunknown-to-clang-option 2>&1 | FileCheck --check-prefix=IGNORED %s
>
> Modified: cfe/trunk/test/Driver/unsupported-option.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/unsupported-option.c?rev=361518&r1=361517&r2=361518&view=diff
> ==============================================================================
> --- cfe/trunk/test/Driver/unsupported-option.c (original)
> +++ cfe/trunk/test/Driver/unsupported-option.c Thu May 23 10:58:33 2019
> @@ -4,4 +4,4 @@
>  // RUN: FileCheck %s --check-prefix=DID-YOU-MEAN
>
>  // CHECK: error: unsupported option '--hedonism'
> -// DID-YOU-MEAN: error: unsupported option '--hell', did you mean '--help'?
> +// DID-YOU-MEAN: error: unsupported option '--hell'; did you mean '--help'?
>
> Modified: cfe/trunk/test/Frontend/unknown-arg.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Frontend/unknown-arg.c?rev=361518&r1=361517&r2=361518&view=diff
> ==============================================================================
> --- cfe/trunk/test/Frontend/unknown-arg.c (original)
> +++ cfe/trunk/test/Frontend/unknown-arg.c Thu May 23 10:58:33 2019
> @@ -6,4 +6,4 @@
>  // RUN: FileCheck %s --check-prefix=DID-YOU-MEAN
>
>  // CHECK: error: unknown argument: '--helium'
> -// DID-YOU-MEAN: error: unknown argument '--hel[', did you mean '--help'?
> +// DID-YOU-MEAN: error: unknown argument '--hel['; did you mean '--help'?
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


More information about the cfe-commits mailing list