[clang] [Clang] [Diagnostics] Simplify filenames that contain '..' (PR #143520)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 2 02:58:48 PDT 2025
================
@@ -2403,3 +2403,75 @@ SourceManagerForFile::SourceManagerForFile(StringRef FileName,
assert(ID.isValid());
SourceMgr->setMainFileID(ID);
}
+
+StringRef
+SourceManager::getNameForDiagnostic(StringRef Filename,
+ const DiagnosticOptions &Opts) const {
+ OptionalFileEntryRef File = getFileManager().getOptionalFileRef(Filename);
+ if (!File)
+ return Filename;
+
+ bool SimplifyPath = [&] {
+ if (Opts.AbsolutePath)
+ return true;
+
+ // Try to simplify paths that contain '..' in any case since paths to
+ // standard library headers especially tend to get quite long otherwise.
+ // Only do that for local filesystems though to avoid slowing down
+ // compilation too much.
+ if (!File->getName().contains(".."))
+ return false;
+
+ // If we're not on Windows, check if we're on a network file system and
+ // avoid simplifying the path in that case since that can be slow. On
+ // Windows, the check for a local filesystem is already slow, so skip it.
+#ifndef _WIN32
+ if (!llvm::sys::fs::is_local(File->getName()))
+ return false;
+#endif
+
+ return true;
+ }();
+
+ if (!SimplifyPath)
+ return Filename;
+
+ // This may involve computing canonical names, so cache the result.
+ StringRef &CacheEntry = DiagNames[Filename];
+ if (!CacheEntry.empty())
+ return CacheEntry;
+
+ // We want to print a simplified absolute path, i. e. without "dots".
+ //
+ // The hardest part here are the paths like "<part1>/<link>/../<part2>".
+ // On Unix-like systems, we cannot just collapse "<link>/..", because
+ // paths are resolved sequentially, and, thereby, the path
+ // "<part1>/<part2>" may point to a different location. That is why
+ // we use FileManager::getCanonicalName(), which expands all indirections
+ // with llvm::sys::fs::real_path() and caches the result.
+ //
+ // On the other hand, it would be better to preserve as much of the
+ // original path as possible, because that helps a user to recognize it.
+ // real_path() expands all links, which sometimes too much. Luckily,
+ // on Windows we can just use llvm::sys::path::remove_dots(), because,
+ // on that system, both aforementioned paths point to the same place.
+ SmallString<256> TempBuf;
+#ifdef _WIN32
+ TempBuf = File->getName();
+ llvm::sys::fs::make_absolute(TempBuf);
+ llvm::sys::path::native(TempBuf);
+ llvm::sys::path::remove_dots(TempBuf, /* remove_dot_dot */ true);
+#else
+ TempBuf = getFileManager().getCanonicalName(*File);
+#endif
----------------
Sirraide wrote:
Hmm, I was interpreting the comment above this to mean that Windows itself doesn’t care about symlinks when resolving `..` and actually just deletes preceding path segments, but I’m not much of a Windows person so I don’t know to be fair...
https://github.com/llvm/llvm-project/pull/143520
More information about the cfe-commits
mailing list