Teach ASTUnit to keep track of temporary files, then delete them when

the ASTUnit itself is destroyed. Fixes <rdar://problem/7649385>.

llvm-svn: 96628
This commit is contained in:
Douglas Gregor 2010-02-18 23:35:40 +00:00
parent 60b3326435
commit 6cb5ba4c4f
4 changed files with 41 additions and 17 deletions

View File

@ -19,6 +19,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Index/ASTLocation.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/System/Path.h"
#include <string>
#include <vector>
#include <cassert>
@ -52,7 +53,6 @@ class ASTUnit {
llvm::OwningPtr<TargetInfo> Target;
llvm::OwningPtr<Preprocessor> PP;
llvm::OwningPtr<ASTContext> Ctx;
bool tempFile;
/// Optional owned invocation, just used to make the invocation used in
/// LoadFromCommandLine available.
@ -85,6 +85,10 @@ class ASTUnit {
/// translation unit.
llvm::SmallVector<StoredDiagnostic, 4> Diagnostics;
/// \brief Temporary files that should be removed when the ASTUnit is
/// destroyed.
llvm::SmallVector<llvm::sys::Path, 4> TemporaryFiles;
ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT
ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT
@ -109,8 +113,13 @@ public:
const std::string &getOriginalSourceFileName();
const std::string &getPCHFileName();
void unlinkTemporaryFile() { tempFile = true; }
/// \brief Add a temporary file that the ASTUnit depends on.
///
/// This file will be erased when the ASTUnit is destroyed.
void addTemporaryFile(const llvm::sys::Path &TempFile) {
TemporaryFiles.push_back(TempFile);
}
bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; }

View File

@ -36,11 +36,11 @@
using namespace clang;
ASTUnit::ASTUnit(bool _MainFileIsAST)
: tempFile(false), MainFileIsAST(_MainFileIsAST) {
: MainFileIsAST(_MainFileIsAST) {
}
ASTUnit::~ASTUnit() {
if (tempFile)
llvm::sys::Path(getPCHFileName()).eraseFromDisk();
for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
TemporaryFiles[I].eraseFromDisk();
}
namespace {

View File

@ -966,9 +966,9 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
llvm::SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;
for (unsigned I = 0; I != num_unsaved_files; ++I) {
const llvm::MemoryBuffer *Buffer
= llvm::MemoryBuffer::getMemBuffer(unsaved_files[I].Contents,
unsaved_files[I].Contents + unsaved_files[I].Length,
unsaved_files[I].Filename);
= llvm::MemoryBuffer::getMemBuffer(unsaved_files[I].Contents,
unsaved_files[I].Contents + unsaved_files[I].Length,
unsaved_files[I].Filename);
RemappedFiles.push_back(std::make_pair(unsaved_files[I].Filename,
Buffer));
}
@ -1129,12 +1129,19 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
}
}
if (ATU)
ATU->unlinkTemporaryFile();
for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i)
TemporaryFiles[i].eraseFromDisk();
if (ATU) {
// Make the translation unit responsible for destroying all temporary files.
for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i)
ATU->addTemporaryFile(TemporaryFiles[i]);
ATU->addTemporaryFile(llvm::sys::Path(ATU->getPCHFileName()));
} else {
// Destroy all of the temporary files now; they can't be referenced any
// longer.
llvm::sys::Path(astTmpFile).eraseFromDisk();
for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i)
TemporaryFiles[i].eraseFromDisk();
}
return ATU;
}

View File

@ -195,6 +195,10 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
/// \brief File manager, used for diagnostics.
FileManager FileMgr;
/// \brief Temporary files that should be removed once we have finished
/// with the code-completion results.
std::vector<llvm::sys::Path> TemporaryFiles;
};
AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults()
@ -205,6 +209,9 @@ AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
delete (CodeCompletionString *)Results[I].CompletionString;
delete [] Results;
delete Buffer;
for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
TemporaryFiles[I].eraseFromDisk();
}
CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
@ -369,8 +376,9 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
Results->FileMgr, Results->SourceMgr,
Results->Diagnostics);
for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i)
TemporaryFiles[i].eraseFromDisk();
// Make sure we delete temporary files when the code-completion results are
// destroyed.
Results->TemporaryFiles.swap(TemporaryFiles);
return Results;
}