Reapply fixed "Honour 'use-external-names' in FileManager"

Was r202442

There were two issues with the original patch that have now been fixed.
1. We were memset'ing over a FileEntry in a test case. After adding a
   std::string to FileEntry, this still happened to not break for me.
2. I didn't pass the FileManager into the new compiler instance in
   compileModule. This was hidden in some cases by the fact I didn't
   clear the module cache in the test.

Also, I changed the copy constructor for FileEntry, which was memcpy'ing
in a (now) unsafe way.

llvm-svn: 202539
diff --git a/clang/lib/Basic/VirtualFileSystem.cpp b/clang/lib/Basic/VirtualFileSystem.cpp
index f6d88c18..d4845e6 100644
--- a/clang/lib/Basic/VirtualFileSystem.cpp
+++ b/clang/lib/Basic/VirtualFileSystem.cpp
@@ -83,6 +83,7 @@
 /// \brief Wrapper around a raw file descriptor.
 class RealFile : public File {
   int FD;
+  Status S;
   friend class RealFileSystem;
   RealFile(int FD) : FD(FD) {
     assert(FD >= 0 && "Invalid or inactive file descriptor");
@@ -95,15 +96,21 @@
                        int64_t FileSize = -1,
                        bool RequiresNullTerminator = true) LLVM_OVERRIDE;
   error_code close() LLVM_OVERRIDE;
+  void setName(StringRef Name) LLVM_OVERRIDE;
 };
 RealFile::~RealFile() { close(); }
 
 ErrorOr<Status> RealFile::status() {
   assert(FD != -1 && "cannot stat closed file");
-  file_status RealStatus;
-  if (error_code EC = sys::fs::status(FD, RealStatus))
-    return EC;
-  return Status(RealStatus);
+  if (!S.isStatusKnown()) {
+    file_status RealStatus;
+    if (error_code EC = sys::fs::status(FD, RealStatus))
+      return EC;
+    Status NewS(RealStatus);
+    NewS.setName(S.getName());
+    S = llvm_move(NewS);
+  }
+  return S;
 }
 
 error_code RealFile::getBuffer(const Twine &Name,
@@ -131,6 +138,10 @@
   return error_code::success();
 }
 
+void RealFile::setName(StringRef Name) {
+  S.setName(Name);
+}
+
 /// \brief The file system according to your operating system.
 class RealFileSystem : public FileSystem {
 public:
@@ -154,6 +165,7 @@
   if (error_code EC = sys::fs::openFileForRead(Name, FD))
     return EC;
   Result.reset(new RealFile(FD));
+  Result->setName(Name.str());
   return error_code::success();
 }
 
@@ -267,7 +279,10 @@
         UseName(UseName) {}
   StringRef getExternalContentsPath() const { return ExternalContentsPath; }
   /// \brief whether to use the external path as the name for this file.
-  NameKind useName() const { return UseName; }
+  bool useExternalName(bool GlobalUseExternalName) const {
+    return UseName == NK_NotSet ? GlobalUseExternalName
+                                : (UseName == NK_External);
+  }
   static bool classof(const Entry *E) { return E->getKind() == EK_File; }
 };
 
@@ -770,8 +785,7 @@
   if (FileEntry *F = dyn_cast<FileEntry>(*Result)) {
     ErrorOr<Status> S = ExternalFS->status(F->getExternalContentsPath());
     assert(!S || S->getName() == F->getExternalContentsPath());
-    if (S && (F->useName() == FileEntry::NK_Virtual ||
-              (F->useName() == FileEntry::NK_NotSet && !UseExternalNames)))
+    if (S && !F->useExternalName(UseExternalNames))
       S->setName(PathStr);
     return S;
   } else { // directory
@@ -792,7 +806,14 @@
   if (!F) // FIXME: errc::not_a_file?
     return error_code(errc::invalid_argument, system_category());
 
-  return ExternalFS->openFileForRead(F->getExternalContentsPath(), Result);
+  if (error_code EC = ExternalFS->openFileForRead(F->getExternalContentsPath(),
+                                                  Result))
+    return EC;
+
+  if (!F->useExternalName(UseExternalNames))
+    Result->setName(Path.str());
+
+  return error_code::success();
 }
 
 IntrusiveRefCntPtr<FileSystem>