Don't leak the CXStoredDiagnostics returned by clang_codeCompleteGetDiagnostic()

r144269 changed clang_disposeDiagnostic() to be a no-op, but didn't update
code completion diagnostics.  Let CXCodeCompleteResults store all diagnostics
returned by clang_codeCompleteGetDiagnostic() and then free them up in
clang_disposeCodeCompleteResults().

Code completion diagnostics referred to data stored in CXCodeCompleteResults
before already, so it wasn't possible to refer to the results of
clang_codeCompleteGetDiagnostic() after clang_disposeCodeCompleteResults()
before this change already -- hence this should be a safe, backwards-compatible
change.

Leak found by LSan, fixes PR19690.

llvm-svn: 208454
This commit is contained in:
Nico Weber
2014-05-09 22:33:11 +00:00
parent 7941856445
commit 7dd96c23fd

View File

@@ -255,6 +255,9 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
/// \brief Diagnostics produced while performing code completion.
SmallVector<StoredDiagnostic, 8> Diagnostics;
/// \brief Allocated API-exposed wrappters for Diagnostics.
SmallVector<CXStoredDiagnostic *, 8> DiagnosticsWrappers;
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
/// \brief Diag object
@@ -331,6 +334,7 @@ AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults(
}
AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
llvm::DeleteContainerPointers(DiagnosticsWrappers);
delete [] Results;
for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
@@ -722,7 +726,9 @@ void clang_codeCompleteAt_Impl(void *UserData) {
*Results->Diag, Results->LangOpts, *Results->SourceMgr,
*Results->FileMgr, Results->Diagnostics,
Results->TemporaryBuffers);
Results->DiagnosticsWrappers.resize(Results->Diagnostics.size());
// Keep a reference to the allocator used for cached global completions, so
// that we can be sure that the memory used by our code completion strings
// doesn't get freed due to subsequent reparses (while the code completion
@@ -869,7 +875,11 @@ clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *ResultsIn,
if (!Results || Index >= Results->Diagnostics.size())
return 0;
return new CXStoredDiagnostic(Results->Diagnostics[Index], Results->LangOpts);
CXStoredDiagnostic *Diag = Results->DiagnosticsWrappers[Index];
if (!Diag)
Results->DiagnosticsWrappers[Index] = Diag =
new CXStoredDiagnostic(Results->Diagnostics[Index], Results->LangOpts);
return Diag;
}
unsigned long long