aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-08-20 00:59:43 +0000
committerDouglas Gregor <dgregor@apple.com>2010-08-20 00:59:43 +0000
commit2283d79155a3e82442fce124ce5fd704ca138801 (patch)
tree2bcc8745f5052aad44acdacbd1b96a7f473bc89e
parent6dbce19fdae4cfae4eb5f826284978e723a04e61 (diff)
When performing code-completion in the presence of a preamble, make
sure to (1) actually use the remapped files we were given rather than old data, and (2) keep the remapped files alive until the code-completion results are destroyed. Big thanks to Daniel for the test case. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111597 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Frontend/ASTUnit.h9
-rw-r--r--lib/Frontend/ASTUnit.cpp21
-rw-r--r--test/Index/crash-recovery-code-complete.c7
-rw-r--r--tools/libclang/CIndexCodeCompletion.cpp8
4 files changed, 23 insertions, 22 deletions
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 8f3b4d40f1..e323170b08 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -311,6 +311,7 @@ private:
unsigned MaxLines, bool &CreatedBuffer);
llvm::MemoryBuffer *getMainBufferWithPrecompiledPreamble(
+ CompilerInvocation PreambleInvocation,
bool AllowRebuild = true,
unsigned MaxLines = 0);
void RealizeTopLevelDeclsFromPreamble();
@@ -546,16 +547,16 @@ public:
/// \param IncludeCodePatterns Whether to include code patterns (such as a
/// for loop) in the code-completion results.
///
- /// FIXME: The Diag, LangOpts, SourceMgr, FileMgr, and
- /// StoredDiagnostics parameters are all disgusting hacks. They will
- /// go away.
+ /// FIXME: The Diag, LangOpts, SourceMgr, FileMgr, StoredDiagnostics, and
+ /// OwnedBuffers parameters are all disgusting hacks. They will go away.
void CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
RemappedFile *RemappedFiles, unsigned NumRemappedFiles,
bool IncludeMacros, bool IncludeCodePatterns,
CodeCompleteConsumer &Consumer,
Diagnostic &Diag, LangOptions &LangOpts,
SourceManager &SourceMgr, FileManager &FileMgr,
- llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics);
+ llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
+ llvm::SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers);
/// \brief Save this translation unit to a file with the given name.
///
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 9c5fea4717..1377e739ed 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -940,9 +940,9 @@ static llvm::MemoryBuffer *CreatePaddedMainFileBuffer(llvm::MemoryBuffer *Old,
/// buffer that should be used in place of the main file when doing so.
/// Otherwise, returns a NULL pointer.
llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
+ CompilerInvocation PreambleInvocation,
bool AllowRebuild,
unsigned MaxLines) {
- CompilerInvocation PreambleInvocation(*Invocation);
FrontendOptions &FrontendOpts = PreambleInvocation.getFrontendOpts();
PreprocessorOptions &PreprocessorOpts
= PreambleInvocation.getPreprocessorOpts();
@@ -1312,7 +1312,8 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
// FIXME: When C++ PCH is ready, allow use of it for a precompiled preamble.
if (PrecompilePreamble && !CI->getLangOpts().CPlusPlus) {
AST->PreambleRebuildCounter = 1;
- OverrideMainBuffer = AST->getMainBufferWithPrecompiledPreamble();
+ OverrideMainBuffer
+ = AST->getMainBufferWithPrecompiledPreamble(*AST->Invocation);
}
llvm::Timer *ParsingTimer = 0;
@@ -1437,7 +1438,7 @@ bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
// build a precompiled preamble, do so now.
llvm::MemoryBuffer *OverrideMainBuffer = 0;
if (!PreambleFile.empty() || PreambleRebuildCounter > 0)
- OverrideMainBuffer = getMainBufferWithPrecompiledPreamble();
+ OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*Invocation);
// Clear out the diagnostics state.
if (!OverrideMainBuffer)
@@ -1663,7 +1664,8 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
CodeCompleteConsumer &Consumer,
Diagnostic &Diag, LangOptions &LangOpts,
SourceManager &SourceMgr, FileManager &FileMgr,
- llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics) {
+ llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
+ llvm::SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) {
if (!Invocation.get())
return;
@@ -1739,9 +1741,11 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
// Remap files.
PreprocessorOpts.clearRemappedFiles();
PreprocessorOpts.RetainRemappedFileBuffers = true;
- for (unsigned I = 0; I != NumRemappedFiles; ++I)
+ for (unsigned I = 0; I != NumRemappedFiles; ++I) {
PreprocessorOpts.addRemappedFile(RemappedFiles[I].first,
RemappedFiles[I].second);
+ OwnedBuffers.push_back(RemappedFiles[I].second);
+ }
// Use the code completion consumer we were given, but adding any cached
// code-completion results.
@@ -1763,8 +1767,8 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
if (const FileStatus *CompleteFileStatus = CompleteFilePath.getFileStatus())
if (const FileStatus *MainStatus = MainPath.getFileStatus())
if (CompleteFileStatus->getUniqueID() == MainStatus->getUniqueID())
- OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(false,
- Line);
+ OverrideMainBuffer
+ = getMainBufferWithPrecompiledPreamble(CCInvocation, false, Line);
}
// If the main file has been overridden due to the use of a preamble,
@@ -1785,6 +1789,8 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
FullSourceLoc Loc(StoredDiagnostics[I].getLocation(), SourceMgr);
StoredDiagnostics[I].setLocation(Loc);
}
+
+ OwnedBuffers.push_back(OverrideMainBuffer);
} else {
PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
PreprocessorOpts.PrecompiledPreambleBytes.second = false;
@@ -1802,7 +1808,6 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
CompletionTimer->stopTimer();
// Steal back our resources.
- delete OverrideMainBuffer;
Clang.takeFileManager();
Clang.takeSourceManager();
Clang.takeInvocation();
diff --git a/test/Index/crash-recovery-code-complete.c b/test/Index/crash-recovery-code-complete.c
index be834fb813..71b98b639b 100644
--- a/test/Index/crash-recovery-code-complete.c
+++ b/test/Index/crash-recovery-code-complete.c
@@ -1,11 +1,10 @@
-// RUN: echo env CINDEXTEST_EDITING=1 \
+// RUN: env CINDEXTEST_EDITING=1 \
// RUN: not c-index-test -code-completion-at=%s:20:1 \
-// RUN: -remap-file="%s;%S/Inputs/crash-recovery-code-complete-remap.c" \
+// RUN: "-remap-file=%s;%S/Inputs/crash-recovery-code-complete-remap.c" \
// RUN: %s 2> %t.err
// RUN: FileCheck < %t.err -check-prefix=CHECK-CODE-COMPLETE-CRASH %s
-// CHECK-CODE-COMPLETE-CRASH: Unable to reparse translation unit
+// CHECK-CODE-COMPLETE-CRASH: Unable to perform code completion!
//
// XFAIL: win32
-// XFAIL: *
#warning parsing original file
diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp
index 53767c4467..c2febf9b72 100644
--- a/tools/libclang/CIndexCodeCompletion.cpp
+++ b/tools/libclang/CIndexCodeCompletion.cpp
@@ -624,11 +624,6 @@ void clang_codeCompleteAt_Impl(void *UserData) {
// Create a code-completion consumer to capture the results.
CaptureCompletionResults Capture(*Results);
- // Make sure that we free the temporary buffers when the
- // code-completion constructor is freed.
- for (unsigned I = 0, N = RemappedFiles.size(); I != N; ++I)
- Results->TemporaryBuffers.push_back(RemappedFiles[I].second);
-
// Perform completion.
AST->CodeComplete(complete_filename, complete_line, complete_column,
RemappedFiles.data(), RemappedFiles.size(),
@@ -636,7 +631,8 @@ void clang_codeCompleteAt_Impl(void *UserData) {
(options & CXCodeComplete_IncludeCodePatterns),
Capture,
*Results->Diag, Results->LangOpts, Results->SourceMgr,
- Results->FileMgr, Results->Diagnostics);
+ Results->FileMgr, Results->Diagnostics,
+ Results->TemporaryBuffers);