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
}
}
+ // 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 linker, 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.)
+ //
+ // Don't do this skip in clang-cl mode for inputs that start with a '/' --
+ // else we'd pass options like /libpath: through to the linker silently.
+ if (Ty == types::TY_Object && !(IsCLMode() && Value.startswith("/")))
+ return true;
+
Diag(clang::diag::err_drv_no_such_file) << Value;
return false;
}
// 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'
// DEBUG: link.exe
// DEBUG: "-debug"
+// Don't pass through /libpath: if it's not after a /link flag:
+// RUN: %clang_cl /Tc%s /libpath:foo -fuse-ld=link -### /link /libpath:bar 2>&1 | FileCheck --check-prefix=LIBPATH %s
+// LIBPATH: error: no such file or directory: '/libpath:foo'
+// LIBPATH: libpath:bar
+
// 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
// 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: %clang_cl /Brepo -### /Tc%s /link 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: not %clang_cl -helo -Werror=unknown-argument -### -- %s 2>&1 | \
! FLANG DRIVER (flang-new)
!--------------------------
! RUN: not %flang 2>&1 | FileCheck %s --check-prefix=FLANG-NO-FILE
-! RUN: not %flang %t 2>&1 | FileCheck %s --check-prefix=FLANG-NONEXISTENT-FILE
+! RUN: not %flang %t.f90 2>&1 | FileCheck %s --check-prefix=FLANG-NONEXISTENT-FILE
!-----------------------------------------
! FLANG FRONTEND DRIVER (flang-new -fc1)
!-----------------------------------------
-! RUN: not %flang_fc1 %t 2>&1 | FileCheck %s --check-prefix=FLANG-FC1-NONEXISTENT-FILE
+! RUN: not %flang_fc1 %t.f90 2>&1 | FileCheck %s --check-prefix=FLANG-FC1-NONEXISTENT-FILE
! RUN: not %flang_fc1 %S 2>&1 | FileCheck %s --check-prefix=FLANG-FC1-DIR
!-----------------------