]> granicus.if.org Git - clang/commitdiff
Avoid failure to canonicalize '..'.
authorSean Silva <chisophugis@gmail.com>
Thu, 30 Jul 2015 00:26:34 +0000 (00:26 +0000)
committerSean Silva <chisophugis@gmail.com>
Thu, 30 Jul 2015 00:26:34 +0000 (00:26 +0000)
Also fix completely broken and untested code which was hiding the
primary bug. The !LLVM_ON_UNIX branch of the ifdef was actually a no-op.

I ran into this in the wild. It was causing failures in our SDK build.

Ideally we'd have a perfect llvm::sys::fs::canonical, but at least this
is a step in the right direction, and fixes an obviously broken case.
In some sense the test case I've added here is an integration test. We
should have these routines thoroughly unit tested in llvm::sys::fs.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@243597 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Basic/FileManager.cpp
test/Modules/Inputs/module-map-path-hash/a.h [new file with mode: 0644]
test/Modules/Inputs/module-map-path-hash/module.modulemap [new file with mode: 0644]
test/Modules/module-map-path-hash.cpp [new file with mode: 0644]

index d4927443aa9cf158eb644e76eb6f6b526507a7e6..3d160569bc82e497e8cafbf9f78e4381005fd191 100644 (file)
@@ -514,7 +514,7 @@ void FileManager::modifyFileEntry(FileEntry *File,
   File->ModTime = ModificationTime;
 }
 
-/// Remove '.' path components from the given absolute path.
+/// Remove '.' and '..' 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) {
@@ -525,24 +525,24 @@ bool FileManager::removeDotPaths(SmallVectorImpl<char> &Path) {
 
   // 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;
+    if (C == ".")
+      continue;
+    if (C == "..") {
+      if (!ComponentStack.empty())
+        ComponentStack.pop_back();
       continue;
     }
     ComponentStack.push_back(C);
   }
 
-  if (!AnyDots)
-    return false;
-
   SmallString<256> Buffer = path::root_path(P);
   for (StringRef C : ComponentStack)
     path::append(Buffer, C);
 
+  bool Changed = (Path != Buffer);
   Path.swap(Buffer);
-  return true;
+  return Changed;
 }
 
 StringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) {
@@ -567,6 +567,9 @@ StringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) {
   llvm::sys::fs::make_absolute(CanonicalNameBuf);
   llvm::sys::path::native(CanonicalNameBuf);
   removeDotPaths(CanonicalNameBuf);
+  char *Mem = CanonicalNameStorage.Allocate<char>(CanonicalNameBuf.size());
+  memcpy(Mem, CanonicalNameBuf.data(), CanonicalNameBuf.size());
+  CanonicalName = StringRef(Mem, CanonicalNameBuf.size());
 #endif
 
   CanonicalDirNames.insert(std::make_pair(Dir, CanonicalName));
diff --git a/test/Modules/Inputs/module-map-path-hash/a.h b/test/Modules/Inputs/module-map-path-hash/a.h
new file mode 100644 (file)
index 0000000..f137354
--- /dev/null
@@ -0,0 +1,2 @@
+#pragma once
+int a = 42;
diff --git a/test/Modules/Inputs/module-map-path-hash/module.modulemap b/test/Modules/Inputs/module-map-path-hash/module.modulemap
new file mode 100644 (file)
index 0000000..514d745
--- /dev/null
@@ -0,0 +1,3 @@
+module a {
+  header "a.h"
+}
diff --git a/test/Modules/module-map-path-hash.cpp b/test/Modules/module-map-path-hash.cpp
new file mode 100644 (file)
index 0000000..1d889db
--- /dev/null
@@ -0,0 +1,9 @@
+// rm -rf %t
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x c++ -Rmodule-build -I%S/Inputs/module-map-path-hash -fmodules-cache-path=%t -fsyntax-only %s
+// xUN: %clang_cc1 -fmodules -fimplicit-module-maps -x c++ -Rmodule-build -I%S/Inputs//module-map-path-hash -fmodules-cache-path=%t -fsyntax-only %s 2>&1 | FileCheck -allow-empty %s
+// xUN: %clang_cc1 -fmodules -fimplicit-module-maps -x c++ -Rmodule-build -I%S/Inputs/./module-map-path-hash -fmodules-cache-path=%t -fsyntax-only %s 2>&1 | FileCheck -allow-empty %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x c++ -Rmodule-build -I%S/Inputs/../Inputs/module-map-path-hash -fmodules-cache-path=%t -fsyntax-only %s 2>&1 | FileCheck -allow-empty %s
+
+#include "a.h"
+
+// CHECK-NOT: remark: building module