summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-12-11 20:50:24 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-12-11 20:50:24 +0000
commit54cc3c2f231846e110dcfbc04ff52f266aa6dfb9 (patch)
tree40917c9ba0ce4b23b2f98595f012d5ab5d50a332 /clang/lib
parent72b05aa59c0268f3404af9c3e61c706d1661fd03 (diff)
downloadbcm5719-llvm-54cc3c2f231846e110dcfbc04ff52f266aa6dfb9.tar.gz
bcm5719-llvm-54cc3c2f231846e110dcfbc04ff52f266aa6dfb9.zip
[modules] When constructing paths relative to a module, strip out /./ directory
components. These sometimes get synthetically added, and we don't want -Ifoo and -I./foo to be treated fundamentally differently here. llvm-svn: 224055
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Basic/FileManager.cpp43
-rw-r--r--clang/lib/Frontend/ModuleDependencyCollector.cpp29
-rw-r--r--clang/lib/Lex/HeaderSearch.cpp26
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp34
4 files changed, 76 insertions, 56 deletions
diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp
index af6022fdc92..214e0f35a52 100644
--- a/clang/lib/Basic/FileManager.cpp
+++ b/clang/lib/Basic/FileManager.cpp
@@ -513,15 +513,47 @@ void FileManager::modifyFileEntry(FileEntry *File,
File->ModTime = ModificationTime;
}
+/// Remove '.' path components from the given absolute path.
+/// \return \c true if any changes were made.
+// FIXME: Move this to llvm::sys::path.
+bool FileManager::removeDotPaths(SmallVectorImpl<char> &Path) {
+ using namespace llvm::sys;
+
+ SmallVector<StringRef, 16> ComponentStack;
+ StringRef P(Path.data(), Path.size());
+
+ // Skip the root path, then look for traversal in the components.
+ StringRef Rel = path::relative_path(P);
+ bool AnyDots = false;
+ for (StringRef C : llvm::make_range(path::begin(Rel), path::end(Rel))) {
+ if (C == ".") {
+ AnyDots = true;
+ continue;
+ }
+ ComponentStack.push_back(C);
+ }
+
+ if (!AnyDots)
+ return false;
+
+ SmallString<256> Buffer = path::root_path(P);
+ for (StringRef C : ComponentStack)
+ path::append(Buffer, C);
+
+ Path.swap(Buffer);
+ return true;
+}
+
StringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) {
// FIXME: use llvm::sys::fs::canonical() when it gets implemented
-#ifdef LLVM_ON_UNIX
llvm::DenseMap<const DirectoryEntry *, llvm::StringRef>::iterator Known
= CanonicalDirNames.find(Dir);
if (Known != CanonicalDirNames.end())
return Known->second;
StringRef CanonicalName(Dir->getName());
+
+#ifdef LLVM_ON_UNIX
char CanonicalNameBuf[PATH_MAX];
if (realpath(Dir->getName(), CanonicalNameBuf)) {
unsigned Len = strlen(CanonicalNameBuf);
@@ -529,12 +561,15 @@ StringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) {
memcpy(Mem, CanonicalNameBuf, Len);
CanonicalName = StringRef(Mem, Len);
}
+#else
+ SmallString<256> CanonicalNameBuf(CanonicalName);
+ llvm::sys::fs::make_absolute(CanonicalNameBuf);
+ llvm::sys::path::native(CanonicalNameBuf);
+ removeDotPaths(CanonicalNameBuf);
+#endif
CanonicalDirNames.insert(std::make_pair(Dir, CanonicalName));
return CanonicalName;
-#else
- return StringRef(Dir->getName());
-#endif
}
void FileManager::PrintStats() const {
diff --git a/clang/lib/Frontend/ModuleDependencyCollector.cpp b/clang/lib/Frontend/ModuleDependencyCollector.cpp
index 882bf8ee240..1ac7e36eff1 100644
--- a/clang/lib/Frontend/ModuleDependencyCollector.cpp
+++ b/clang/lib/Frontend/ModuleDependencyCollector.cpp
@@ -57,40 +57,13 @@ void ModuleDependencyCollector::writeFileMap() {
VFSWriter.write(OS);
}
-/// Remove traversal (ie, . or ..) from the given absolute path.
-static void removePathTraversal(SmallVectorImpl<char> &Path) {
- using namespace llvm::sys;
- SmallVector<StringRef, 16> ComponentStack;
- StringRef P(Path.data(), Path.size());
-
- // Skip the root path, then look for traversal in the components.
- StringRef Rel = path::relative_path(P);
- for (StringRef C : llvm::make_range(path::begin(Rel), path::end(Rel))) {
- if (C == ".")
- continue;
- if (C == "..") {
- assert(ComponentStack.size() && "Path traverses out of parent");
- ComponentStack.pop_back();
- } else
- ComponentStack.push_back(C);
- }
-
- // The stack is now the path without any directory traversal.
- SmallString<256> Buffer = path::root_path(P);
- for (StringRef C : ComponentStack)
- path::append(Buffer, C);
-
- // Put the result in Path.
- Path.swap(Buffer);
-}
-
std::error_code ModuleDependencyListener::copyToRoot(StringRef Src) {
using namespace llvm::sys;
// We need an absolute path to append to the root.
SmallString<256> AbsoluteSrc = Src;
fs::make_absolute(AbsoluteSrc);
- removePathTraversal(AbsoluteSrc);
+ FileManager::removeDotPaths(AbsoluteSrc);
// Build the destination path.
SmallString<256> Dest = Collector.getDest();
diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp
index 02fd87c8226..d6b255fb014 100644
--- a/clang/lib/Lex/HeaderSearch.cpp
+++ b/clang/lib/Lex/HeaderSearch.cpp
@@ -131,16 +131,24 @@ std::string HeaderSearch::getModuleFileName(StringRef ModuleName,
llvm::sys::path::append(Result, ModuleName + ".pcm");
} else {
// Construct the name <ModuleName>-<hash of ModuleMapPath>.pcm which should
- // be globally unique to this particular module. To avoid false-negatives
- // on case-insensitive filesystems, we use lower-case, which is safe because
- // to cause a collision the modules must have the same name, which is an
- // error if they are imported in the same translation.
- SmallString<256> AbsModuleMapPath(ModuleMapPath);
- llvm::sys::fs::make_absolute(AbsModuleMapPath);
- llvm::sys::path::native(AbsModuleMapPath);
- llvm::APInt Code(64, llvm::hash_value(AbsModuleMapPath.str().lower()));
+ // ideally be globally unique to this particular module. Name collisions
+ // in the hash are safe (because any translation unit can only import one
+ // module with each name), but result in a loss of caching.
+ //
+ // To avoid false-negatives, we form as canonical a path as we can, and map
+ // to lower-case in case we're on a case-insensitive file system.
+ auto *Dir =
+ FileMgr.getDirectory(llvm::sys::path::parent_path(ModuleMapPath));
+ if (!Dir)
+ return std::string();
+ auto DirName = FileMgr.getCanonicalName(Dir);
+ auto FileName = llvm::sys::path::filename(ModuleMapPath);
+
+ llvm::hash_code Hash =
+ llvm::hash_combine(DirName.lower(), FileName.lower());
+
SmallString<128> HashStr;
- Code.toStringUnsigned(HashStr, /*Radix*/36);
+ llvm::APInt(64, size_t(Hash)).toStringUnsigned(HashStr, /*Radix*/36);
llvm::sys::path::append(Result, ModuleName + "-" + HashStr.str() + ".pcm");
}
return Result.str().str();
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index adecf9dab7a..02663ad43d4 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -1058,6 +1058,21 @@ void ASTWriter::WriteBlockInfoBlock() {
Stream.ExitBlock();
}
+/// \brief Prepares a path for being written to an AST file by converting it
+/// to an absolute path and removing nested './'s.
+///
+/// \return \c true if the path was changed.
+bool cleanPathForOutput(FileManager &FileMgr, SmallVectorImpl<char> &Path) {
+ bool Changed = false;
+
+ if (!llvm::sys::path::is_absolute(StringRef(Path.data(), Path.size()))) {
+ llvm::sys::fs::make_absolute(Path);
+ Changed = true;
+ }
+
+ return Changed | FileMgr.removeDotPaths(Path);
+}
+
/// \brief Adjusts the given filename to only write out the portion of the
/// filename that is not part of the system root directory.
///
@@ -1170,8 +1185,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
Record.push_back(MODULE_DIRECTORY);
SmallString<128> BaseDir(WritingModule->Directory->getName());
- Context.getSourceManager().getFileManager().FixupRelativePath(BaseDir);
- llvm::sys::fs::make_absolute(BaseDir);
+ cleanPathForOutput(Context.getSourceManager().getFileManager(), BaseDir);
Stream.EmitRecordWithBlob(AbbrevCode, Record, BaseDir);
// Write out all other paths relative to the base directory if possible.
@@ -4076,20 +4090,10 @@ void ASTWriter::AddString(StringRef Str, RecordDataImpl &Record) {
}
bool ASTWriter::PreparePathForOutput(SmallVectorImpl<char> &Path) {
- bool Changed = false;
-
- if (!llvm::sys::path::is_absolute(StringRef(Path.data(), Path.size()))) {
- // Ask the file manager to fixup the relative path for us. This will
- // honor the working directory.
- if (Context)
- Context->getSourceManager().getFileManager().FixupRelativePath(Path);
+ assert(Context && "should have context when outputting path");
- // We want an absolute path even if we weren't given a spelling for the
- // current working directory.
- llvm::sys::fs::make_absolute(Path);
-
- Changed = true;
- }
+ bool Changed =
+ cleanPathForOutput(Context->getSourceManager().getFileManager(), Path);
// Remove a prefix to make the path relative, if relevant.
const char *PathBegin = Path.data();
OpenPOWER on IntegriCloud