Skip to content

Commit 529aac1

Browse files
committed
Move path computation into SourceManager
1 parent 97c0acc commit 529aac1

File tree

4 files changed

+66
-77
lines changed

4 files changed

+66
-77
lines changed

clang/include/clang/Basic/SourceManager.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,12 @@ class SourceManager : public RefCountedBase<SourceManager> {
820820

821821
mutable std::unique_ptr<SrcMgr::SLocEntry> FakeSLocEntryForRecovery;
822822

823+
/// Cache for filenames used in diagnostics. See 'getNameForDiagnostic()'.
824+
mutable llvm::StringMap<StringRef> DiagNames;
825+
826+
/// Allocator for absolute/short names.
827+
mutable llvm::BumpPtrAllocator DiagNameAlloc;
828+
823829
/// Lazily computed map of macro argument chunks to their expanded
824830
/// source location.
825831
using MacroArgsMap = std::map<unsigned, SourceLocation>;
@@ -1847,6 +1853,9 @@ class SourceManager : public RefCountedBase<SourceManager> {
18471853
/// \return Location of the top-level macro caller.
18481854
SourceLocation getTopMacroCallerLoc(SourceLocation Loc) const;
18491855

1856+
/// Retrieve the name of a file suitable for diagnostics.
1857+
StringRef getNameForDiagnostic(StringRef Filename) const;
1858+
18501859
private:
18511860
friend class ASTReader;
18521861
friend class ASTWriter;

clang/lib/Basic/SourceManager.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2403,3 +2403,58 @@ SourceManagerForFile::SourceManagerForFile(StringRef FileName,
24032403
assert(ID.isValid());
24042404
SourceMgr->setMainFileID(ID);
24052405
}
2406+
2407+
StringRef SourceManager::getNameForDiagnostic(StringRef Filename) const {
2408+
OptionalFileEntryRef File = getFileManager().getOptionalFileRef(Filename);
2409+
if (!File)
2410+
return Filename;
2411+
2412+
// Try to simplify paths that contain '..' in any case since paths to
2413+
// standard library headers especially tend to get quite long otherwise.
2414+
// Only do that for local filesystems though to avoid slowing down
2415+
// compilation too much.
2416+
bool Absolute = Diag.getDiagnosticOptions().AbsolutePath;
2417+
bool AlwaysSimplify = File->getName().contains("..") &&
2418+
llvm::sys::fs::is_local(File->getName());
2419+
if (!Absolute && !AlwaysSimplify)
2420+
return Filename;
2421+
2422+
// This may involve computing canonical names, so cache the result.
2423+
StringRef &CacheEntry = DiagNames[Filename];
2424+
if (!CacheEntry.empty())
2425+
return CacheEntry;
2426+
2427+
// We want to print a simplified absolute path, i. e. without "dots".
2428+
//
2429+
// The hardest part here are the paths like "<part1>/<link>/../<part2>".
2430+
// On Unix-like systems, we cannot just collapse "<link>/..", because
2431+
// paths are resolved sequentially, and, thereby, the path
2432+
// "<part1>/<part2>" may point to a different location. That is why
2433+
// we use FileManager::getCanonicalName(), which expands all indirections
2434+
// with llvm::sys::fs::real_path() and caches the result.
2435+
//
2436+
// On the other hand, it would be better to preserve as much of the
2437+
// original path as possible, because that helps a user to recognize it.
2438+
// real_path() expands all links, which sometimes too much. Luckily,
2439+
// on Windows we can just use llvm::sys::path::remove_dots(), because,
2440+
// on that system, both aforementioned paths point to the same place.
2441+
SmallString<256> TempBuf;
2442+
#ifdef _WIN32
2443+
TempBuf = File->getName();
2444+
llvm::sys::fs::make_absolute(TempBuf);
2445+
llvm::sys::path::native(TempBuf);
2446+
llvm::sys::path::remove_dots(TempBuf, /* remove_dot_dot */ true);
2447+
#else
2448+
TempBuf = getFileManager().getCanonicalName(*File);
2449+
#endif
2450+
2451+
// In some cases, the resolved path may actually end up being longer (e.g.
2452+
// if it was originally a relative path), so just retain whichever one
2453+
// ends up being shorter.
2454+
if (!Absolute && TempBuf.size() > Filename.size())
2455+
CacheEntry = Filename;
2456+
else
2457+
CacheEntry = TempBuf.str().copy(DiagNameAlloc);
2458+
2459+
return CacheEntry;
2460+
}

clang/lib/Frontend/SARIFDiagnostic.cpp

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -163,36 +163,7 @@ SARIFDiagnostic::addDiagnosticLevelToRule(SarifRule Rule,
163163

164164
llvm::StringRef SARIFDiagnostic::emitFilename(StringRef Filename,
165165
const SourceManager &SM) {
166-
if (DiagOpts.AbsolutePath) {
167-
auto File = SM.getFileManager().getOptionalFileRef(Filename);
168-
if (File) {
169-
// We want to print a simplified absolute path, i. e. without "dots".
170-
//
171-
// The hardest part here are the paths like "<part1>/<link>/../<part2>".
172-
// On Unix-like systems, we cannot just collapse "<link>/..", because
173-
// paths are resolved sequentially, and, thereby, the path
174-
// "<part1>/<part2>" may point to a different location. That is why
175-
// we use FileManager::getCanonicalName(), which expands all indirections
176-
// with llvm::sys::fs::real_path() and caches the result.
177-
//
178-
// On the other hand, it would be better to preserve as much of the
179-
// original path as possible, because that helps a user to recognize it.
180-
// real_path() expands all links, which is sometimes too much. Luckily,
181-
// on Windows we can just use llvm::sys::path::remove_dots(), because,
182-
// on that system, both aforementioned paths point to the same place.
183-
#ifdef _WIN32
184-
SmallString<256> TmpFilename = File->getName();
185-
llvm::sys::fs::make_absolute(TmpFilename);
186-
llvm::sys::path::native(TmpFilename);
187-
llvm::sys::path::remove_dots(TmpFilename, /* remove_dot_dot */ true);
188-
Filename = StringRef(TmpFilename.data(), TmpFilename.size());
189-
#else
190-
Filename = SM.getFileManager().getCanonicalName(*File);
191-
#endif
192-
}
193-
}
194-
195-
return Filename;
166+
return SM.getNameForDiagnostic(Filename);
196167
}
197168

198169
/// Print out the file/line/column information and include trace.

clang/lib/Frontend/TextDiagnostic.cpp

Lines changed: 1 addition & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -738,53 +738,7 @@ void TextDiagnostic::printDiagnosticMessage(raw_ostream &OS,
738738
}
739739

740740
void TextDiagnostic::emitFilename(StringRef Filename, const SourceManager &SM) {
741-
auto File = SM.getFileManager().getOptionalFileRef(Filename);
742-
743-
// Try to simplify paths that contain '..' in any case since paths to
744-
// standard library headers especially tend to get quite long otherwise.
745-
// Only do that for local filesystems though to avoid slowing down
746-
// compilation too much.
747-
auto AlwaysSimplify = [&] {
748-
return File->getName().contains("..") &&
749-
llvm::sys::fs::is_local(File->getName());
750-
};
751-
752-
if (File && (DiagOpts.AbsolutePath || AlwaysSimplify())) {
753-
SmallString<128> &CacheEntry = SimplifiedFileNameCache[Filename];
754-
if (CacheEntry.empty()) {
755-
// We want to print a simplified absolute path, i. e. without "dots".
756-
//
757-
// The hardest part here are the paths like "<part1>/<link>/../<part2>".
758-
// On Unix-like systems, we cannot just collapse "<link>/..", because
759-
// paths are resolved sequentially, and, thereby, the path
760-
// "<part1>/<part2>" may point to a different location. That is why
761-
// we use FileManager::getCanonicalName(), which expands all indirections
762-
// with llvm::sys::fs::real_path() and caches the result.
763-
//
764-
// On the other hand, it would be better to preserve as much of the
765-
// original path as possible, because that helps a user to recognize it.
766-
// real_path() expands all links, which sometimes too much. Luckily,
767-
// on Windows we can just use llvm::sys::path::remove_dots(), because,
768-
// on that system, both aforementioned paths point to the same place.
769-
#ifdef _WIN32
770-
CacheEntry = File->getName();
771-
llvm::sys::fs::make_absolute(CacheEntry);
772-
llvm::sys::path::native(CacheEntry);
773-
llvm::sys::path::remove_dots(CacheEntry, /* remove_dot_dot */ true);
774-
#else
775-
CacheEntry = SM.getFileManager().getCanonicalName(*File);
776-
#endif
777-
778-
// In some cases, the resolved path may actually end up being longer (e.g.
779-
// if it was originally a relative path), so just retain whichever one
780-
// ends up being shorter.
781-
if (!DiagOpts.AbsolutePath && CacheEntry.size() > Filename.size())
782-
CacheEntry = Filename;
783-
}
784-
Filename = CacheEntry;
785-
}
786-
787-
OS << Filename;
741+
OS << SM.getNameForDiagnostic(Filename);
788742
}
789743

790744
/// Print out the file/line/column information and include trace.

0 commit comments

Comments
 (0)