forked from OSchip/llvm-project
Use precompiled preambles for in-process code completion.
llvm-svn: 110596
This commit is contained in:
parent
f4804c696d
commit
028d3e4d0f
|
@ -686,7 +686,19 @@ enum CXTranslationUnit_Flags {
|
|||
* clang_reparseTranslationUnit() will re-use the implicit
|
||||
* precompiled header to improve parsing performance.
|
||||
*/
|
||||
CXTranslationUnit_PrecompiledPreamble = 0x04
|
||||
CXTranslationUnit_PrecompiledPreamble = 0x04,
|
||||
/**
|
||||
* \brief Used to indicate that the translation unit is incomplete.
|
||||
*
|
||||
* When a translation unit is considered "incomplete", semantic
|
||||
* analysis that is typically performed at the end of the
|
||||
* translation unit will be suppressed. For example, this suppresses
|
||||
* the completion of tentative declarations in C and of
|
||||
* instantiation of implicitly-instantiation function templates in
|
||||
* C++. This option is typically used when parsing a header with the
|
||||
* intent of producing a precompiled header.
|
||||
*/
|
||||
CXTranslationUnit_Incomplete = 0x08
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -78,9 +78,12 @@ private:
|
|||
/// \brief Whether to capture any diagnostics produced.
|
||||
bool CaptureDiagnostics;
|
||||
|
||||
/// Track whether the main file was loaded from an AST or not.
|
||||
/// \brief Track whether the main file was loaded from an AST or not.
|
||||
bool MainFileIsAST;
|
||||
|
||||
/// \brief Whether this AST represents a complete translation unit.
|
||||
bool CompleteTranslationUnit;
|
||||
|
||||
/// Track the top-level decls which appeared in an ASTUnit which was loaded
|
||||
/// from a source file.
|
||||
//
|
||||
|
@ -199,9 +202,12 @@ private:
|
|||
bool Parse(llvm::MemoryBuffer *OverrideMainBuffer);
|
||||
|
||||
std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> >
|
||||
ComputePreamble(CompilerInvocation &Invocation, bool &CreatedBuffer);
|
||||
ComputePreamble(CompilerInvocation &Invocation,
|
||||
unsigned MaxLines, bool &CreatedBuffer);
|
||||
|
||||
llvm::MemoryBuffer *BuildPrecompiledPreamble();
|
||||
llvm::MemoryBuffer *getMainBufferWithPrecompiledPreamble(
|
||||
bool AllowRebuild = true,
|
||||
unsigned MaxLines = 0);
|
||||
void RealizeTopLevelDeclsFromPreamble();
|
||||
|
||||
public:
|
||||
|
@ -318,6 +324,12 @@ public:
|
|||
return StoredDiagnostics;
|
||||
}
|
||||
|
||||
/// \brief Whether this AST represents a complete translation unit.
|
||||
///
|
||||
/// If false, this AST is only a partial translation unit, e.g., one
|
||||
/// that might still be used as a precompiled header or preamble.
|
||||
bool isCompleteTranslationUnit() const { return CompleteTranslationUnit; }
|
||||
|
||||
/// \brief A mapping from a file name to the memory buffer that stores the
|
||||
/// remapped contents of that file.
|
||||
typedef std::pair<std::string, const llvm::MemoryBuffer *> RemappedFile;
|
||||
|
@ -352,7 +364,8 @@ public:
|
|||
llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
|
||||
bool OnlyLocalDecls = false,
|
||||
bool CaptureDiagnostics = false,
|
||||
bool PrecompilePreamble = false);
|
||||
bool PrecompilePreamble = false,
|
||||
bool CompleteTranslationUnit = true);
|
||||
|
||||
/// LoadFromCommandLine - Create an ASTUnit from a vector of command line
|
||||
/// arguments, which must specify exactly one source file.
|
||||
|
@ -376,7 +389,8 @@ public:
|
|||
RemappedFile *RemappedFiles = 0,
|
||||
unsigned NumRemappedFiles = 0,
|
||||
bool CaptureDiagnostics = false,
|
||||
bool PrecompilePreamble = false);
|
||||
bool PrecompilePreamble = false,
|
||||
bool CompleteTranslationUnit = true);
|
||||
|
||||
/// \brief Reparse the source files using the same command-line options that
|
||||
/// were originally used to produce this translation unit.
|
||||
|
|
|
@ -237,11 +237,14 @@ public:
|
|||
///
|
||||
/// \param Buffer The memory buffer containing the file's contents.
|
||||
///
|
||||
/// \param MaxLines If non-zero, restrict the length of the preamble
|
||||
/// to fewer than this number of lines.
|
||||
///
|
||||
/// \returns The offset into the file where the preamble ends and the rest
|
||||
/// of the file begins along with a boolean value indicating whether
|
||||
/// the preamble ends at the beginning of a new line.
|
||||
static std::pair<unsigned, bool>
|
||||
ComputePreamble(const llvm::MemoryBuffer *Buffer);
|
||||
ComputePreamble(const llvm::MemoryBuffer *Buffer, unsigned MaxLines = 0);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Internal implementation interfaces.
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/System/Host.h"
|
||||
#include "llvm/System/Path.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/Timer.h"
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
@ -48,8 +49,8 @@ const unsigned DefaultPreambleRebuildInterval = 5;
|
|||
|
||||
ASTUnit::ASTUnit(bool _MainFileIsAST)
|
||||
: CaptureDiagnostics(false), MainFileIsAST(_MainFileIsAST),
|
||||
ConcurrencyCheckValue(CheckUnlocked), PreambleRebuildCounter(0),
|
||||
SavedMainFileBuffer(0) {
|
||||
CompleteTranslationUnit(true), ConcurrencyCheckValue(CheckUnlocked),
|
||||
PreambleRebuildCounter(0), SavedMainFileBuffer(0) {
|
||||
}
|
||||
|
||||
ASTUnit::~ASTUnit() {
|
||||
|
@ -334,6 +335,9 @@ public:
|
|||
TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
|
||||
|
||||
virtual bool hasCodeCompletionSupport() const { return false; }
|
||||
virtual bool usesCompleteTranslationUnit() {
|
||||
return Unit.isCompleteTranslationUnit();
|
||||
}
|
||||
};
|
||||
|
||||
class PrecompilePreambleConsumer : public PCHGenerator {
|
||||
|
@ -396,6 +400,7 @@ public:
|
|||
|
||||
virtual bool hasCodeCompletionSupport() const { return false; }
|
||||
virtual bool hasASTFileSupport() const { return false; }
|
||||
virtual bool usesCompleteTranslationUnit() { return false; }
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -567,7 +572,8 @@ static std::string GetPreamblePCHPath() {
|
|||
/// that corresponds to the main file along with a pair (bytes, start-of-line)
|
||||
/// that describes the preamble.
|
||||
std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> >
|
||||
ASTUnit::ComputePreamble(CompilerInvocation &Invocation, bool &CreatedBuffer) {
|
||||
ASTUnit::ComputePreamble(CompilerInvocation &Invocation,
|
||||
unsigned MaxLines, bool &CreatedBuffer) {
|
||||
FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
|
||||
PreprocessorOptions &PreprocessorOpts
|
||||
= Invocation.getPreprocessorOpts();
|
||||
|
@ -642,7 +648,7 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation, bool &CreatedBuffer) {
|
|||
CreatedBuffer = true;
|
||||
}
|
||||
|
||||
return std::make_pair(Buffer, Lexer::ComputePreamble(Buffer));
|
||||
return std::make_pair(Buffer, Lexer::ComputePreamble(Buffer, MaxLines));
|
||||
}
|
||||
|
||||
static llvm::MemoryBuffer *CreatePaddedMainFileBuffer(llvm::MemoryBuffer *Old,
|
||||
|
@ -673,10 +679,19 @@ static llvm::MemoryBuffer *CreatePaddedMainFileBuffer(llvm::MemoryBuffer *Old,
|
|||
/// this routine will determine if it is still valid and, if so, avoid
|
||||
/// rebuilding the precompiled preamble.
|
||||
///
|
||||
/// \param AllowRebuild When true (the default), this routine is
|
||||
/// allowed to rebuild the precompiled preamble if it is found to be
|
||||
/// out-of-date.
|
||||
///
|
||||
/// \param MaxLines When non-zero, the maximum number of lines that
|
||||
/// can occur within the preamble.
|
||||
///
|
||||
/// \returns If the precompiled preamble can be used, returns a newly-allocated
|
||||
/// buffer that should be used in place of the main file when doing so.
|
||||
/// Otherwise, returns a NULL pointer.
|
||||
llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
|
||||
llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
|
||||
bool AllowRebuild,
|
||||
unsigned MaxLines) {
|
||||
CompilerInvocation PreambleInvocation(*Invocation);
|
||||
FrontendOptions &FrontendOpts = PreambleInvocation.getFrontendOpts();
|
||||
PreprocessorOptions &PreprocessorOpts
|
||||
|
@ -684,7 +699,7 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
|
|||
|
||||
bool CreatedPreambleBuffer = false;
|
||||
std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > NewPreamble
|
||||
= ComputePreamble(PreambleInvocation, CreatedPreambleBuffer);
|
||||
= ComputePreamble(PreambleInvocation, MaxLines, CreatedPreambleBuffer);
|
||||
|
||||
if (!NewPreamble.second.first) {
|
||||
// We couldn't find a preamble in the main source. Clear out the current
|
||||
|
@ -793,12 +808,21 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
|
|||
FrontendOpts.Inputs[0].second);
|
||||
}
|
||||
}
|
||||
|
||||
// If we aren't allowed to rebuild the precompiled preamble, just
|
||||
// return now.
|
||||
if (!AllowRebuild)
|
||||
return 0;
|
||||
|
||||
// We can't reuse the previously-computed preamble. Build a new one.
|
||||
Preamble.clear();
|
||||
llvm::sys::Path(PreambleFile).eraseFromDisk();
|
||||
PreambleRebuildCounter = 1;
|
||||
}
|
||||
} else if (!AllowRebuild) {
|
||||
// We aren't allowed to rebuild the precompiled preamble; just
|
||||
// return now.
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If the preamble rebuild counter > 1, it's because we previously
|
||||
// failed to build a preamble and we're not yet ready to try
|
||||
|
@ -1004,7 +1028,8 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
|
|||
llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
|
||||
bool OnlyLocalDecls,
|
||||
bool CaptureDiagnostics,
|
||||
bool PrecompilePreamble) {
|
||||
bool PrecompilePreamble,
|
||||
bool CompleteTranslationUnit) {
|
||||
if (!Diags.getPtr()) {
|
||||
// No diagnostics engine was provided, so create our own diagnostics object
|
||||
// with the default options.
|
||||
|
@ -1018,6 +1043,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
|
|||
AST->Diagnostics = Diags;
|
||||
AST->CaptureDiagnostics = CaptureDiagnostics;
|
||||
AST->OnlyLocalDecls = OnlyLocalDecls;
|
||||
AST->CompleteTranslationUnit = CompleteTranslationUnit;
|
||||
AST->Invocation.reset(CI);
|
||||
CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;
|
||||
|
||||
|
@ -1030,7 +1056,7 @@ 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->BuildPrecompiledPreamble();
|
||||
OverrideMainBuffer = AST->getMainBufferWithPrecompiledPreamble();
|
||||
}
|
||||
|
||||
llvm::Timer *ParsingTimer = 0;
|
||||
|
@ -1055,7 +1081,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
|
|||
RemappedFile *RemappedFiles,
|
||||
unsigned NumRemappedFiles,
|
||||
bool CaptureDiagnostics,
|
||||
bool PrecompilePreamble) {
|
||||
bool PrecompilePreamble,
|
||||
bool CompleteTranslationUnit) {
|
||||
if (!Diags.getPtr()) {
|
||||
// No diagnostics engine was provided, so create our own diagnostics object
|
||||
// with the default options.
|
||||
|
@ -1116,7 +1143,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
|
|||
|
||||
CI->getFrontendOpts().DisableFree = true;
|
||||
return LoadFromCompilerInvocation(CI.take(), Diags, OnlyLocalDecls,
|
||||
CaptureDiagnostics, PrecompilePreamble);
|
||||
CaptureDiagnostics, PrecompilePreamble,
|
||||
CompleteTranslationUnit);
|
||||
}
|
||||
|
||||
bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
|
||||
|
@ -1140,7 +1168,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 = BuildPrecompiledPreamble();
|
||||
OverrideMainBuffer = getMainBufferWithPrecompiledPreamble();
|
||||
|
||||
// Clear out the diagnostics state.
|
||||
if (!OverrideMainBuffer)
|
||||
|
@ -1165,6 +1193,17 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
|
|||
if (!Invocation.get())
|
||||
return;
|
||||
|
||||
llvm::Timer *CompletionTimer = 0;
|
||||
if (TimerGroup.get()) {
|
||||
llvm::SmallString<128> TimerName;
|
||||
llvm::raw_svector_ostream TimerNameOut(TimerName);
|
||||
TimerNameOut << "Code completion @ " << File << ":" << Line << ":"
|
||||
<< Column;
|
||||
CompletionTimer = new llvm::Timer(TimerNameOut.str(), *TimerGroup);
|
||||
CompletionTimer->startTimer();
|
||||
Timers.push_back(CompletionTimer);
|
||||
}
|
||||
|
||||
CompilerInvocation CCInvocation(*Invocation);
|
||||
FrontendOptions &FrontendOpts = CCInvocation.getFrontendOpts();
|
||||
PreprocessorOptions &PreprocessorOpts = CCInvocation.getPreprocessorOpts();
|
||||
|
@ -1230,6 +1269,42 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
|
|||
// Use the code completion consumer we were given.
|
||||
Clang.setCodeCompletionConsumer(&Consumer);
|
||||
|
||||
// If we have a precompiled preamble, try to use it. We only allow
|
||||
// the use of the precompiled preamble if we're if the completion
|
||||
// point is within the main file, after the end of the precompiled
|
||||
// preamble.
|
||||
llvm::MemoryBuffer *OverrideMainBuffer = 0;
|
||||
if (!PreambleFile.empty()) {
|
||||
using llvm::sys::FileStatus;
|
||||
llvm::sys::PathWithStatus CompleteFilePath(File);
|
||||
llvm::sys::PathWithStatus MainPath(OriginalSourceFile);
|
||||
if (const FileStatus *CompleteFileStatus = CompleteFilePath.getFileStatus())
|
||||
if (const FileStatus *MainStatus = MainPath.getFileStatus())
|
||||
if (CompleteFileStatus->getUniqueID() == MainStatus->getUniqueID())
|
||||
OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(false,
|
||||
Line);
|
||||
}
|
||||
|
||||
// If the main file has been overridden due to the use of a preamble,
|
||||
// make that override happen and introduce the preamble.
|
||||
if (OverrideMainBuffer) {
|
||||
PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
|
||||
PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
|
||||
PreprocessorOpts.PrecompiledPreambleBytes.second
|
||||
= PreambleEndsAtStartOfLine;
|
||||
PreprocessorOpts.ImplicitPCHInclude = PreambleFile;
|
||||
PreprocessorOpts.DisablePCHValidation = true;
|
||||
|
||||
// The stored diagnostics have the old source manager. Copy them
|
||||
// to our output set of stored diagnostics, updating the source
|
||||
// manager to the one we were given.
|
||||
for (unsigned I = 0, N = this->StoredDiagnostics.size(); I != N; ++I) {
|
||||
StoredDiagnostics.push_back(this->StoredDiagnostics[I]);
|
||||
FullSourceLoc Loc(StoredDiagnostics[I].getLocation(), SourceMgr);
|
||||
StoredDiagnostics[I].setLocation(Loc);
|
||||
}
|
||||
}
|
||||
|
||||
llvm::OwningPtr<SyntaxOnlyAction> Act;
|
||||
Act.reset(new SyntaxOnlyAction);
|
||||
if (Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
|
||||
|
@ -1237,8 +1312,12 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
|
|||
Act->Execute();
|
||||
Act->EndSourceFile();
|
||||
}
|
||||
|
||||
if (CompletionTimer)
|
||||
CompletionTimer->stopTimer();
|
||||
|
||||
// Steal back our resources.
|
||||
delete OverrideMainBuffer;
|
||||
Clang.takeFileManager();
|
||||
Clang.takeSourceManager();
|
||||
Clang.takeInvocation();
|
||||
|
|
|
@ -311,7 +311,7 @@ namespace {
|
|||
}
|
||||
|
||||
std::pair<unsigned, bool>
|
||||
Lexer::ComputePreamble(const llvm::MemoryBuffer *Buffer) {
|
||||
Lexer::ComputePreamble(const llvm::MemoryBuffer *Buffer, unsigned MaxLines) {
|
||||
// Create a lexer starting at the beginning of the file. Note that we use a
|
||||
// "fake" file source location at offset 1 so that the lexer will track our
|
||||
// position within the file.
|
||||
|
@ -325,6 +325,8 @@ Lexer::ComputePreamble(const llvm::MemoryBuffer *Buffer) {
|
|||
Token TheTok;
|
||||
Token IfStartTok;
|
||||
unsigned IfCount = 0;
|
||||
unsigned Line = 0;
|
||||
|
||||
do {
|
||||
TheLexer.LexFromRawLexer(TheTok);
|
||||
|
||||
|
@ -345,6 +347,16 @@ Lexer::ComputePreamble(const llvm::MemoryBuffer *Buffer) {
|
|||
InPreprocessorDirective = false;
|
||||
}
|
||||
|
||||
// Keep track of the # of lines in the preamble.
|
||||
if (TheTok.isAtStartOfLine()) {
|
||||
++Line;
|
||||
|
||||
// If we were asked to limit the number of lines in the preamble,
|
||||
// and we're about to exceed that limit, we're done.
|
||||
if (MaxLines && Line >= MaxLines)
|
||||
break;
|
||||
}
|
||||
|
||||
// Comments are okay; skip over them.
|
||||
if (TheTok.getKind() == tok::comment)
|
||||
continue;
|
||||
|
@ -418,7 +430,9 @@ Lexer::ComputePreamble(const llvm::MemoryBuffer *Buffer) {
|
|||
TheTok = HashTok;
|
||||
}
|
||||
|
||||
// We hit a token
|
||||
// We hit a token that we don't recognize as being in the
|
||||
// "preprocessing only" part of the file, so we're no longer in
|
||||
// the preamble.
|
||||
break;
|
||||
} while (true);
|
||||
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
#include "preamble.h"
|
||||
int wibble(int);
|
||||
|
||||
void f(int x) {
|
||||
|
||||
}
|
||||
// RUN: %clang -x c-header -o %t.pch %S/Inputs/prefix.h
|
||||
// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 5 local -I %S/Inputs -include %t %s 2> %t.stderr.txt | FileCheck %s
|
||||
// RUN: FileCheck -check-prefix CHECK-DIAG %s < %t.stderr.txt
|
||||
|
@ -18,3 +21,8 @@ int wibble(int);
|
|||
// CHECK: preamble.c:3:5: FunctionDecl=wibble:3:5 Extent=[3:5 - 3:16]
|
||||
// CHECK: preamble.c:3:15: ParmDecl=:3:15 (Definition) Extent=[3:12 - 3:16]
|
||||
// CHECK-DIAG: preamble.h:4:7:{4:9-4:13}: warning: incompatible pointer types assigning to 'int *' from 'float *'
|
||||
// RUN: env CINDEXTEST_EDITING=1 c-index-test -code-completion-at=%s:6:1 -I %S/Inputs -include %t %s 2> %t.stderr.txt | FileCheck -check-prefix CHECK-CC %s
|
||||
// CHECK-CC: FunctionDecl:{ResultType int}{TypedText bar}{LeftParen (}{Placeholder int i}{RightParen )} (50)
|
||||
// CHECK-CC: FunctionDecl:{ResultType void}{TypedText f}{LeftParen (}{Placeholder int x}{RightParen )} (50)
|
||||
// CHECK-CC: FunctionDecl:{ResultType int}{TypedText foo}{LeftParen (}{Placeholder int}{RightParen )} (50)
|
||||
// CHECK-CC: FunctionDecl:{ResultType int}{TypedText wibble}{LeftParen (}{Placeholder int}{RightParen )} (50)
|
||||
|
|
|
@ -874,7 +874,8 @@ int perform_code_completion(int argc, const char **argv, int timing_only) {
|
|||
struct CXUnsavedFile *unsaved_files = 0;
|
||||
int num_unsaved_files = 0;
|
||||
CXCodeCompleteResults *results = 0;
|
||||
|
||||
CXTranslationUnit *TU = 0;
|
||||
|
||||
if (timing_only)
|
||||
input += strlen("-code-completion-timing=");
|
||||
else
|
||||
|
@ -889,15 +890,20 @@ int perform_code_completion(int argc, const char **argv, int timing_only) {
|
|||
|
||||
CIdx = clang_createIndex(0, 1);
|
||||
if (getenv("CINDEXTEST_EDITING")) {
|
||||
CXTranslationUnit *TU = clang_parseTranslationUnit(CIdx, 0,
|
||||
argv + num_unsaved_files + 2,
|
||||
argc - num_unsaved_files - 2,
|
||||
unsaved_files,
|
||||
num_unsaved_files,
|
||||
getDefaultParsingOptions());
|
||||
results = clang_codeCompleteAt(TU, filename, line, column,
|
||||
unsaved_files, num_unsaved_files,
|
||||
clang_defaultCodeCompleteOptions());
|
||||
TU = clang_parseTranslationUnit(CIdx, 0,
|
||||
argv + num_unsaved_files + 2,
|
||||
argc - num_unsaved_files - 2,
|
||||
unsaved_files,
|
||||
num_unsaved_files,
|
||||
getDefaultParsingOptions());
|
||||
unsigned I, Repeats = 5;
|
||||
for (I = 0; I != Repeats; ++I) {
|
||||
results = clang_codeCompleteAt(TU, filename, line, column,
|
||||
unsaved_files, num_unsaved_files,
|
||||
clang_defaultCodeCompleteOptions());
|
||||
if (I != Repeats-1)
|
||||
clang_disposeCodeCompleteResults(results);
|
||||
}
|
||||
} else
|
||||
results = clang_codeComplete(CIdx,
|
||||
argv[argc - 1], argc - num_unsaved_files - 3,
|
||||
|
@ -918,7 +924,7 @@ int perform_code_completion(int argc, const char **argv, int timing_only) {
|
|||
}
|
||||
clang_disposeCodeCompleteResults(results);
|
||||
}
|
||||
|
||||
clang_disposeTranslationUnit(TU);
|
||||
clang_disposeIndex(CIdx);
|
||||
free(filename);
|
||||
|
||||
|
|
|
@ -1195,7 +1195,9 @@ CXTranslationUnit clang_parseTranslationUnit(CXIndex CIdx,
|
|||
if (options & CXTranslationUnit_Editing)
|
||||
options |= CXTranslationUnit_PrecompiledPreamble;
|
||||
bool PrecompilePreamble = options & CXTranslationUnit_PrecompiledPreamble;
|
||||
|
||||
bool CompleteTranslationUnit
|
||||
= ((options & CXTranslationUnit_Incomplete) == 0);
|
||||
|
||||
// Configure the diagnostics.
|
||||
DiagnosticOptions DiagOpts;
|
||||
llvm::IntrusiveRefCntPtr<Diagnostic> Diags;
|
||||
|
@ -1250,7 +1252,8 @@ CXTranslationUnit clang_parseTranslationUnit(CXIndex CIdx,
|
|||
RemappedFiles.data(),
|
||||
RemappedFiles.size(),
|
||||
/*CaptureDiagnostics=*/true,
|
||||
PrecompilePreamble));
|
||||
PrecompilePreamble,
|
||||
CompleteTranslationUnit));
|
||||
|
||||
if (NumErrors != Diags->getNumErrors()) {
|
||||
// Make sure to check that 'Unit' is non-NULL.
|
||||
|
@ -1451,7 +1454,7 @@ int clang_reparseTranslationUnit(CXTranslationUnit TU,
|
|||
return static_cast<ASTUnit *>(TU)->Reparse(RemappedFiles.data(),
|
||||
RemappedFiles.size())? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit) {
|
||||
if (!CTUnit)
|
||||
return createCXString("");
|
||||
|
|
|
@ -20,17 +20,18 @@
|
|||
#include "clang/Frontend/CompilerInstance.h"
|
||||
#include "clang/Frontend/FrontendDiagnostic.h"
|
||||
#include "clang/Sema/CodeCompleteConsumer.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/Timer.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/System/Program.h"
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
#ifdef UDP_CODE_COMPLETION_LOGGER
|
||||
#include "clang/Basic/Version.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/Support/Timer.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -277,7 +278,16 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
|
|||
#endif
|
||||
|
||||
bool EnableLogging = getenv("LIBCLANG_CODE_COMPLETION_LOGGING") != 0;
|
||||
|
||||
|
||||
llvm::OwningPtr<llvm::NamedRegionTimer> CCTimer;
|
||||
if (getenv("LIBCLANG_TIMING")) {
|
||||
llvm::SmallString<128> TimerName;
|
||||
llvm::raw_svector_ostream TimerNameOut(TimerName);
|
||||
TimerNameOut << "Code completion @ " << complete_filename << ":"
|
||||
<< complete_line << ":" << complete_column;
|
||||
CCTimer.reset(new llvm::NamedRegionTimer(TimerNameOut.str()));
|
||||
}
|
||||
|
||||
// The indexer, which is mainly used to determine where diagnostics go.
|
||||
CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
|
||||
|
||||
|
|
Loading…
Reference in New Issue