This is an archive of the discontinued LLVM Phabricator instance.

[Option] Fix PR37006 prefix choice in findNearest
ClosedPublic

Authored by modocache on May 11 2018, 2:37 PM.

Details

Summary

In https://bugs.llvm.org/show_bug.cgi?id=37006 Nico Weber points out a
flaw in OptTable::findNearest: if an option "foo"'s prefixes are "--"
and "-", then the nearest option for "--fob" will be "-foo". This is
incorrect, however, since the function is expected to return "--foo".

The bug is due to a naive loop that attempts to predetermines which
prefix is best. Instead, compute the edit distance for each prefix/name
pair.

Test Plan: check-llvm

Diff Detail

Repository
rL LLVM

Event Timeline

modocache created this revision.May 11 2018, 2:37 PM

Thanks!

lib/Option/OptTable.cpp
284 ↗(On Diff #146415)

Shouldn't getting the longest prefix here be good enough? Something like this:

StringRef Prefix;
int PrefixLength = 0;
for (int P = 0; Candidateinfo.Prefixes[P]; P++) {
  StringRef Candidate = CandidateInfo.Prefixes[P];
  if (Candiate.size() > PrefixLength && Option.startswith(Candidate)) {
    Prefix = Candidate;
    PrefixLength = Candidate.size();
  }
}

…and keep everything else the same?

modocache added inline comments.May 14 2018, 9:36 AM
lib/Option/OptTable.cpp
284 ↗(On Diff #146415)

That's a good suggestion, but here's a case in which this loop wouldn't work: the user invokes clang -migrate foo.cpp, but the correct argument is --migrate. In this case, the --migrate option does not provide a - prefix, it only provides --. However the -- prefix is ruled out by the if statement above: -migrate does not start with --.

(The unit tests managed to catch the edge case above, hooray!)

My personal preference would be to check the edit distance of each prefix/name pair, as this diff currently does. It's slightly more computationally expensive, but I think it's a more comprehensive check.

thakis accepted this revision.May 14 2018, 12:38 PM

Makes sense, lgtm. Thanks!

This revision is now accepted and ready to land.May 14 2018, 12:38 PM
This revision was automatically updated to reflect the committed changes.

Thanks for the reviews, and for pointing out the bug!

modocache added a comment.EditedMay 14 2018, 3:43 PM

I'm not yet sure why, but this change caused buildbot failures due to a test in Clang for the "did you mean" feature (example: http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/builds/29988). I couldn't figure out why the buildbots would fail whereas the Clang tests pass for me locally, and so reverted this change for the time being, in rL332304. I'll try to resubmit once I've figured out and fixed the issue.

My guess is it's because the clang tests check if the edit distance is > 1, when you really want to check > 0 instead. Maybe you can try changing that in clang, then relanding?

Hmm... but the >1 condition is such that an edit distance of greater than 1 results in no suggestion, whereas an edit distance of 1 or 0 results in a suggestion. In this case -- and apparently only on certain platforms' buildbots -- the edit distance between -debug-info-macros and -debug-info-macro is 1, and so it should display a suggestion.

The code:

if (OptTbl->findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1)
  Diags.Report(diag::err_drv_unknown_argument) << ArgString;
else
  Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
      << ArgString << Nearest;

The failure:

FAIL: Clang :: Driver/unknown-arg.c (7531 of 40411)
******************** TEST 'Clang :: Driver/unknown-arg.c' FAILED ********************
Script:
--
not /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/clang /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -ifoo -imultilib dir -### 2>&1 |  /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/FileCheck /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c
/home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/clang /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c -imultilib dir -### 2>&1 |  /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/FileCheck /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c --check-prefix=MULTILIB
not /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/clang /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c -stdlibs=foo -hell -version -### 2>&1 |  /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/FileCheck /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c --check-prefix=DID-YOU-MEAN
/home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/clang --driver-mode=cl -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -### -c -- /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c 2>&1 |  /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/FileCheck /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c --check-prefix=CL
/home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/clang --driver-mode=cl -Brepo -### -- /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c 2>&1 |  /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/FileCheck /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c --check-prefix=CL-DID-YOU-MEAN
not /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/clang --driver-mode=cl -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -c -Werror=unknown-argument -### -- /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c 2>&1 |  /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/FileCheck /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c --check-prefix=CL-ERROR
not /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/clang --driver-mode=cl -helo -Werror=unknown-argument -### -- /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c 2>&1 |  /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/FileCheck /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c --check-prefix=CL-ERROR-DID-YOU-MEAN
/home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/clang --driver-mode=cl -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -c -Wno-unknown-argument -### -- /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c 2>&1 |  /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/FileCheck /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c --check-prefix=SILENT
not /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/clang -cc1as -hell --version -debug-info-macros 2>&1 |  /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/FileCheck /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c --check-prefix=CC1AS-DID-YOU-MEAN
not /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/clang -cc1asphalt -help 2>&1 |  /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/FileCheck /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c --check-prefix=UNKNOWN-INTEGRATED
/home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/clang -S /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c -o /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/tools/clang/test/Driver/Output/unknown-arg.c.tmp.s  -Wunknown-to-clang-option 2>&1 | /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.obj/bin/FileCheck --check-prefix=IGNORED /home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c
--
Exit Code: 1

Command Output (stderr):
--
/home/buildslave/ps4-buildslave4/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/llvm.src/tools/clang/test/Driver/unknown-arg.c:54:24: error: expected string not found in input
// CC1AS-DID-YOU-MEAN: error: unknown argument '-debug-info-macros', did you mean '-debug-info-macro'?
                       ^
<stdin>:3:1: note: scanning from here
clang -cc1as: error: unknown argument: '-debug-info-macros'
^
<stdin>:3:15: note: possible intended match here
clang -cc1as: error: unknown argument: '-debug-info-macros'
              ^

--

********************

What's more, it seems like the other checks in this file succeed. So whereas -debug-info-macros does not result in a suggestion of -debug-info-macro, --version does result in a suggestion -version.

Meanwhile, this test passes for me locally, on a Linux x86_84 machine. I wonder what gives...? I'll keep looking into it.

Hm, does this only happen on the ps4 bots? Maybe that toolchain sets some default behavior that changes if this flag is exposed or something. Does it repro if you pass -triple x86_64-scei-ps4-ubuntu in the RUN line?

thakis added a comment.EditedApr 30 2019, 10:25 AM

I can repro the failure with the following diff. Investigating...

diff --git a/clang/test/Driver/unknown-arg.c b/clang/test/Driver/unknown-arg.c
index 4ea43278b7e..3e42ff0e2a4 100644
--- a/clang/test/Driver/unknown-arg.c
+++ b/clang/test/Driver/unknown-arg.c
@@ -16,7 +16,7 @@
 // RUN: FileCheck %s --check-prefix=SILENT
 // RUN: not %clang -cc1as -hell --version 2>&1 | \
 // RUN: FileCheck %s --check-prefix=CC1AS-DID-YOU-MEAN
-// RUN: not %clang -cc1asphalt -help 2>&1 | \
+// RUN: not %clang --target=x86_64-scei-ps4-ubuntu -cc1asphalt -help 2>&1 | \
 // RUN: FileCheck %s --check-prefix=UNKNOWN-INTEGRATED
 
 // CHECK: error: unknown argument: '-cake-is-lie'
Herald added a project: Restricted Project. · View Herald TranscriptApr 30 2019, 10:25 AM

Actually, it looks like 341327 already fixed the test problem and we just never relanded this change here. I'll try relanding.

Aha, this was then reverted again in r341333 due to "an MSAN error". Details are at https://reviews.llvm.org/D50515 . I'll shut up here and continue talking over there :)