Index: clang/lib/Driver/Driver.cpp =================================================================== --- clang/lib/Driver/Driver.cpp +++ clang/lib/Driver/Driver.cpp @@ -2130,19 +2130,6 @@ if (getVFS().exists(Value)) return true; - if (IsCLMode()) { - if (!llvm::sys::path::is_absolute(Twine(Value)) && - llvm::sys::Process::FindInEnvPath("LIB", Value, ';')) - return true; - - if (Args.hasArg(options::OPT__SLASH_link) && Ty == types::TY_Object) { - // Arguments to the /link flag might cause the linker to search for object - // and library files in paths we don't know about. Don't error in such - // cases. - return true; - } - } - 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 @@ -2162,6 +2149,31 @@ } } + // Don't error on apparently non-existent linker inputs, because they + // can be influenced by linker flags the clang driver might not understand. + // Examples: + // - `clang -fuse-ld=lld -Wl,--chroot,some/dir /file.o` will make lld look + // for some/dir/file.o + // - `clang-cl main.cc ole32.lib` in a a non-MSVC shell will make the driver + // module look for an MSVC installation in the registry. (We could ask + // the MSVCToolChain object if it can find `ole32.lib`, but the logic to + // look in the registry might move into lld-link in the future so that + // lld-link invocations in non-MSVC shells just work too.) + // - `clang-cl ... /link ...` can pass arbitrary flags to the linker, + // including /libpath:, which is used to find .lib and .obj files. + // So do not diagnose this on the driver level. Rely on the linker diagnosing + // it. (If we don't end up invoking the driver, this means we'll emit a + // "'linker' input unused [-Wunused-command-line-argument]" warning instead + // of an error.) + // + // Only do this skip after the typo correction step above. `/Brepo` is treated + // as TY_Object, but it's clearly a typo for `/Brepro`. It seems fine to emit + // an error if we have a flag that's within an edit distance of 1 from a + // flag. (Users can use `-Wl,` or `/linker` to launder the flag past the + // driver in the unlikely case they run into this.) + if (Ty == types::TY_Object) + return true; + Diag(clang::diag::err_drv_no_such_file) << Value; return false; } Index: clang/test/Driver/cl-inputs.c =================================================================== --- clang/test/Driver/cl-inputs.c +++ clang/test/Driver/cl-inputs.c @@ -55,13 +55,13 @@ // LIBINPUT: "cl-test.lib" // RUN: env LIB=%S/Inputs/cl-libs %clang_cl -fuse-ld=link -### -- %s cl-test2.lib 2>&1 | FileCheck -check-prefix=LIBINPUT2 %s -// LIBINPUT2: error: no such file or directory: 'cl-test2.lib' +// LIBINPUT2-NOT: error: no such file or directory: 'cl-test2.lib' // LIBINPUT2: link.exe" -// LIBINPUT2-NOT: "cl-test2.lib" +// LIBINPUT2: "cl-test2.lib" // RUN: %clang_cl -fuse-ld=link -### -- %s /nonexisting.lib 2>&1 | FileCheck -check-prefix=LIBINPUT3 %s -// LIBINPUT3: error: no such file or directory: '/nonexisting.lib' +// LIBINPUT3-NOT: error: no such file or directory: '/nonexisting.lib' // LIBINPUT3: link.exe" -// LIBINPUT3-NOT: "/nonexisting.lib" +// LIBINPUT3: "/nonexisting.lib" void f(); Index: clang/test/Driver/cl-link.c =================================================================== --- clang/test/Driver/cl-link.c +++ clang/test/Driver/cl-link.c @@ -50,9 +50,12 @@ // PR27234 // RUN: %clang_cl /Tc%s nonexistent.obj -fuse-ld=link -### /link /libpath:somepath 2>&1 | FileCheck --check-prefix=NONEXISTENT %s // RUN: %clang_cl /Tc%s nonexistent.lib -fuse-ld=link -### /link /libpath:somepath 2>&1 | FileCheck --check-prefix=NONEXISTENT %s +// RUN: %clang_cl /Tc%s nonexistent.obj -fuse-ld=link -### /winsysroot somepath 2>&1 | FileCheck --check-prefix=NONEXISTENT %s +// RUN: %clang_cl /Tc%s nonexistent.lib -fuse-ld=link -### /winsysroot somepath 2>&1 | FileCheck --check-prefix=NONEXISTENT %s +// RUN: %clang_cl /Tc%s nonexistent.obj -fuse-ld=link -### 2>&1 | FileCheck --check-prefix=NONEXISTENT %s +// RUN: %clang_cl /Tc%s nonexistent.lib -fuse-ld=link -### 2>&1 | FileCheck --check-prefix=NONEXISTENT %s // NONEXISTENT-NOT: no such file // NONEXISTENT: link.exe -// NONEXISTENT: "/libpath:somepath" // NONEXISTENT: nonexistent // RUN: %clang_cl /Tc%s -fuse-ld=lld -### 2>&1 | FileCheck --check-prefix=USE_LLD %s