aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Basic/FileManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Basic/FileManager.cpp')
-rw-r--r--clang/lib/Basic/FileManager.cpp55
1 files changed, 35 insertions, 20 deletions
diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp
index f92c1ae..c3eec80 100644
--- a/clang/lib/Basic/FileManager.cpp
+++ b/clang/lib/Basic/FileManager.cpp
@@ -632,33 +632,48 @@ void FileManager::GetUniqueIDMapping(
}
StringRef FileManager::getCanonicalName(DirectoryEntryRef Dir) {
- auto Known = CanonicalNames.find(Dir);
- if (Known != CanonicalNames.end())
- return Known->second;
-
- StringRef CanonicalName(Dir.getName());
-
- SmallString<4096> CanonicalNameBuf;
- if (!FS->getRealPath(Dir.getName(), CanonicalNameBuf))
- CanonicalName = CanonicalNameBuf.str().copy(CanonicalNameStorage);
-
- CanonicalNames.insert({Dir, CanonicalName});
- return CanonicalName;
+ return getCanonicalName(Dir, Dir.getName());
}
StringRef FileManager::getCanonicalName(const FileEntry *File) {
- llvm::DenseMap<const void *, llvm::StringRef>::iterator Known
- = CanonicalNames.find(File);
+ return getCanonicalName(File, File->getName());
+}
+
+StringRef FileManager::getCanonicalName(const void *Entry, StringRef Name) {
+ llvm::DenseMap<const void *, llvm::StringRef>::iterator Known =
+ CanonicalNames.find(Entry);
if (Known != CanonicalNames.end())
return Known->second;
- StringRef CanonicalName(File->getName());
-
- SmallString<4096> CanonicalNameBuf;
- if (!FS->getRealPath(File->getName(), CanonicalNameBuf))
- CanonicalName = CanonicalNameBuf.str().copy(CanonicalNameStorage);
+ // Name comes from FileEntry/DirectoryEntry::getName(), so it is safe to
+ // store it in the DenseMap below.
+ StringRef CanonicalName(Name);
+
+ SmallString<256> AbsPathBuf;
+ SmallString<256> RealPathBuf;
+ if (!FS->getRealPath(Name, RealPathBuf)) {
+ if (is_style_windows(llvm::sys::path::Style::native)) {
+ // For Windows paths, only use the real path if it doesn't resolve
+ // a substitute drive, as those are used to avoid MAX_PATH issues.
+ AbsPathBuf = Name;
+ if (!FS->makeAbsolute(AbsPathBuf)) {
+ if (llvm::sys::path::root_name(RealPathBuf) ==
+ llvm::sys::path::root_name(AbsPathBuf)) {
+ CanonicalName = RealPathBuf.str().copy(CanonicalNameStorage);
+ } else {
+ // Fallback to using the absolute path.
+ // Simplifying /../ is semantically valid on Windows even in the
+ // presence of symbolic links.
+ llvm::sys::path::remove_dots(AbsPathBuf, /*remove_dot_dot=*/true);
+ CanonicalName = AbsPathBuf.str().copy(CanonicalNameStorage);
+ }
+ }
+ } else {
+ CanonicalName = RealPathBuf.str().copy(CanonicalNameStorage);
+ }
+ }
- CanonicalNames.insert({File, CanonicalName});
+ CanonicalNames.insert({Entry, CanonicalName});
return CanonicalName;
}