blob: a21614c747350429124bcc213597a4e434b9eb93 [file] [log] [blame]
Ted Kremenekab188932010-01-05 19:32:54 +00001//===- CIndexCodeCompletion.cpp - Code Completion API hooks ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Clang-C Source Indexing library hooks for
11// code completion.
12//
13//===----------------------------------------------------------------------===//
14
15#include "CIndexer.h"
Douglas Gregor936ea3b2010-01-28 00:56:43 +000016#include "CIndexDiagnostic.h"
Benjamin Kramerb846deb2010-04-12 19:45:50 +000017#include "clang/Basic/SourceManager.h"
18#include "clang/Basic/FileManager.h"
19#include "clang/Frontend/CompilerInstance.h"
Douglas Gregor936ea3b2010-01-28 00:56:43 +000020#include "clang/Frontend/FrontendDiagnostic.h"
Ted Kremenekab188932010-01-05 19:32:54 +000021#include "clang/Sema/CodeCompleteConsumer.h"
22#include "llvm/ADT/StringExtras.h"
23#include "llvm/Support/MemoryBuffer.h"
24#include "llvm/System/Program.h"
25
Ted Kremenekda7af322010-04-15 01:02:28 +000026#ifdef UDP_CODE_COMPLETION_LOGGER
27#include "clang/Basic/Version.h"
28#include "llvm/ADT/SmallString.h"
29#include "llvm/Support/Timer.h"
30#include "llvm/Support/raw_ostream.h"
31#include <arpa/inet.h>
32#include <sys/socket.h>
33#include <sys/types.h>
34#include <unistd.h>
35#endif
36
Ted Kremenekab188932010-01-05 19:32:54 +000037using namespace clang;
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +000038using namespace clang::cxstring;
Ted Kremenekab188932010-01-05 19:32:54 +000039
40extern "C" {
41
42enum CXCompletionChunkKind
43clang_getCompletionChunkKind(CXCompletionString completion_string,
44 unsigned chunk_number) {
45 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
46 if (!CCStr || chunk_number >= CCStr->size())
47 return CXCompletionChunk_Text;
48
49 switch ((*CCStr)[chunk_number].Kind) {
50 case CodeCompletionString::CK_TypedText:
51 return CXCompletionChunk_TypedText;
52 case CodeCompletionString::CK_Text:
53 return CXCompletionChunk_Text;
54 case CodeCompletionString::CK_Optional:
55 return CXCompletionChunk_Optional;
56 case CodeCompletionString::CK_Placeholder:
57 return CXCompletionChunk_Placeholder;
58 case CodeCompletionString::CK_Informative:
59 return CXCompletionChunk_Informative;
60 case CodeCompletionString::CK_ResultType:
61 return CXCompletionChunk_ResultType;
62 case CodeCompletionString::CK_CurrentParameter:
63 return CXCompletionChunk_CurrentParameter;
64 case CodeCompletionString::CK_LeftParen:
65 return CXCompletionChunk_LeftParen;
66 case CodeCompletionString::CK_RightParen:
67 return CXCompletionChunk_RightParen;
68 case CodeCompletionString::CK_LeftBracket:
69 return CXCompletionChunk_LeftBracket;
70 case CodeCompletionString::CK_RightBracket:
71 return CXCompletionChunk_RightBracket;
72 case CodeCompletionString::CK_LeftBrace:
73 return CXCompletionChunk_LeftBrace;
74 case CodeCompletionString::CK_RightBrace:
75 return CXCompletionChunk_RightBrace;
76 case CodeCompletionString::CK_LeftAngle:
77 return CXCompletionChunk_LeftAngle;
78 case CodeCompletionString::CK_RightAngle:
79 return CXCompletionChunk_RightAngle;
80 case CodeCompletionString::CK_Comma:
81 return CXCompletionChunk_Comma;
Douglas Gregor01dfea02010-01-10 23:08:15 +000082 case CodeCompletionString::CK_Colon:
83 return CXCompletionChunk_Colon;
84 case CodeCompletionString::CK_SemiColon:
85 return CXCompletionChunk_SemiColon;
86 case CodeCompletionString::CK_Equal:
87 return CXCompletionChunk_Equal;
88 case CodeCompletionString::CK_HorizontalSpace:
89 return CXCompletionChunk_HorizontalSpace;
90 case CodeCompletionString::CK_VerticalSpace:
91 return CXCompletionChunk_VerticalSpace;
Ted Kremenekab188932010-01-05 19:32:54 +000092 }
93
94 // Should be unreachable, but let's be careful.
95 return CXCompletionChunk_Text;
96}
97
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +000098CXString clang_getCompletionChunkText(CXCompletionString completion_string,
99 unsigned chunk_number) {
Ted Kremenekab188932010-01-05 19:32:54 +0000100 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
101 if (!CCStr || chunk_number >= CCStr->size())
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +0000102 return createCXString(0);
Ted Kremenekab188932010-01-05 19:32:54 +0000103
104 switch ((*CCStr)[chunk_number].Kind) {
105 case CodeCompletionString::CK_TypedText:
106 case CodeCompletionString::CK_Text:
107 case CodeCompletionString::CK_Placeholder:
108 case CodeCompletionString::CK_CurrentParameter:
109 case CodeCompletionString::CK_Informative:
110 case CodeCompletionString::CK_LeftParen:
111 case CodeCompletionString::CK_RightParen:
112 case CodeCompletionString::CK_LeftBracket:
113 case CodeCompletionString::CK_RightBracket:
114 case CodeCompletionString::CK_LeftBrace:
115 case CodeCompletionString::CK_RightBrace:
116 case CodeCompletionString::CK_LeftAngle:
117 case CodeCompletionString::CK_RightAngle:
118 case CodeCompletionString::CK_Comma:
119 case CodeCompletionString::CK_ResultType:
Douglas Gregor01dfea02010-01-10 23:08:15 +0000120 case CodeCompletionString::CK_Colon:
121 case CodeCompletionString::CK_SemiColon:
122 case CodeCompletionString::CK_Equal:
123 case CodeCompletionString::CK_HorizontalSpace:
124 case CodeCompletionString::CK_VerticalSpace:
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +0000125 return createCXString((*CCStr)[chunk_number].Text, false);
Ted Kremenekab188932010-01-05 19:32:54 +0000126
127 case CodeCompletionString::CK_Optional:
128 // Note: treated as an empty text block.
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +0000129 return createCXString("");
Ted Kremenekab188932010-01-05 19:32:54 +0000130 }
131
132 // Should be unreachable, but let's be careful.
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +0000133 return createCXString(0);
Ted Kremenekab188932010-01-05 19:32:54 +0000134}
135
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +0000136
Ted Kremenekab188932010-01-05 19:32:54 +0000137CXCompletionString
138clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
139 unsigned chunk_number) {
140 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
141 if (!CCStr || chunk_number >= CCStr->size())
142 return 0;
143
144 switch ((*CCStr)[chunk_number].Kind) {
145 case CodeCompletionString::CK_TypedText:
146 case CodeCompletionString::CK_Text:
147 case CodeCompletionString::CK_Placeholder:
148 case CodeCompletionString::CK_CurrentParameter:
149 case CodeCompletionString::CK_Informative:
150 case CodeCompletionString::CK_LeftParen:
151 case CodeCompletionString::CK_RightParen:
152 case CodeCompletionString::CK_LeftBracket:
153 case CodeCompletionString::CK_RightBracket:
154 case CodeCompletionString::CK_LeftBrace:
155 case CodeCompletionString::CK_RightBrace:
156 case CodeCompletionString::CK_LeftAngle:
157 case CodeCompletionString::CK_RightAngle:
158 case CodeCompletionString::CK_Comma:
159 case CodeCompletionString::CK_ResultType:
Douglas Gregor01dfea02010-01-10 23:08:15 +0000160 case CodeCompletionString::CK_Colon:
161 case CodeCompletionString::CK_SemiColon:
162 case CodeCompletionString::CK_Equal:
163 case CodeCompletionString::CK_HorizontalSpace:
164 case CodeCompletionString::CK_VerticalSpace:
Ted Kremenekab188932010-01-05 19:32:54 +0000165 return 0;
166
167 case CodeCompletionString::CK_Optional:
168 // Note: treated as an empty text block.
169 return (*CCStr)[chunk_number].Optional;
170 }
171
172 // Should be unreachable, but let's be careful.
173 return 0;
174}
175
176unsigned clang_getNumCompletionChunks(CXCompletionString completion_string) {
177 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
178 return CCStr? CCStr->size() : 0;
179}
180
181static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd,
182 unsigned &Value) {
183 if (Memory + sizeof(unsigned) > MemoryEnd)
184 return true;
185
186 memmove(&Value, Memory, sizeof(unsigned));
187 Memory += sizeof(unsigned);
188 return false;
189}
190
191/// \brief The CXCodeCompleteResults structure we allocate internally;
192/// the client only sees the initial CXCodeCompleteResults structure.
193struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000194 AllocatedCXCodeCompleteResults();
195 ~AllocatedCXCodeCompleteResults();
196
Ted Kremenekab188932010-01-05 19:32:54 +0000197 /// \brief The memory buffer from which we parsed the results. We
198 /// retain this buffer because the completion strings point into it.
199 llvm::MemoryBuffer *Buffer;
Daniel Dunbar35b84402010-01-30 23:31:40 +0000200
Douglas Gregora88084b2010-02-18 18:08:43 +0000201 /// \brief Diagnostics produced while performing code completion.
202 llvm::SmallVector<StoredDiagnostic, 8> Diagnostics;
203
Douglas Gregorf715ca12010-03-16 00:06:06 +0000204 /// \brief Diag object
205 Diagnostic Diag;
206
Douglas Gregora88084b2010-02-18 18:08:43 +0000207 /// \brief Language options used to adjust source locations.
Daniel Dunbar35b84402010-01-30 23:31:40 +0000208 LangOptions LangOpts;
Douglas Gregora88084b2010-02-18 18:08:43 +0000209
210 /// \brief Source manager, used for diagnostics.
211 SourceManager SourceMgr;
212
213 /// \brief File manager, used for diagnostics.
214 FileManager FileMgr;
Douglas Gregor313e26c2010-02-18 23:35:40 +0000215
216 /// \brief Temporary files that should be removed once we have finished
217 /// with the code-completion results.
218 std::vector<llvm::sys::Path> TemporaryFiles;
Ted Kremenekab188932010-01-05 19:32:54 +0000219};
220
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000221AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults()
Douglas Gregorf715ca12010-03-16 00:06:06 +0000222 : CXCodeCompleteResults(), Buffer(0), SourceMgr(Diag) { }
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000223
224AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
225 for (unsigned I = 0, N = NumResults; I != N; ++I)
226 delete (CodeCompletionString *)Results[I].CompletionString;
227 delete [] Results;
228 delete Buffer;
Douglas Gregor313e26c2010-02-18 23:35:40 +0000229
230 for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
231 TemporaryFiles[I].eraseFromDisk();
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000232}
233
Ted Kremenekab188932010-01-05 19:32:54 +0000234CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
235 const char *source_filename,
236 int num_command_line_args,
237 const char **command_line_args,
238 unsigned num_unsaved_files,
239 struct CXUnsavedFile *unsaved_files,
240 const char *complete_filename,
241 unsigned complete_line,
Douglas Gregora88084b2010-02-18 18:08:43 +0000242 unsigned complete_column) {
Ted Kremenekda7af322010-04-15 01:02:28 +0000243#ifdef UDP_CODE_COMPLETION_LOGGER
244#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
245 const llvm::TimeRecord &StartTime = llvm::TimeRecord::getCurrentTime();
246#endif
247#endif
248
Ted Kremenekab188932010-01-05 19:32:54 +0000249 // The indexer, which is mainly used to determine where diagnostics go.
250 CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
251
Douglas Gregor936ea3b2010-01-28 00:56:43 +0000252 // Configure the diagnostics.
253 DiagnosticOptions DiagOpts;
Douglas Gregor28019772010-04-05 23:52:57 +0000254 llvm::IntrusiveRefCntPtr<Diagnostic> Diags;
255 Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
Douglas Gregor936ea3b2010-01-28 00:56:43 +0000256
Ted Kremenekab188932010-01-05 19:32:54 +0000257 // The set of temporary files that we've built.
258 std::vector<llvm::sys::Path> TemporaryFiles;
259
260 // Build up the arguments for invoking 'clang'.
261 std::vector<const char *> argv;
262
263 // First add the complete path to the 'clang' executable.
264 llvm::sys::Path ClangPath = CXXIdx->getClangPath();
265 argv.push_back(ClangPath.c_str());
266
267 // Add the '-fsyntax-only' argument so that we only perform a basic
268 // syntax check of the code.
269 argv.push_back("-fsyntax-only");
270
271 // Add the appropriate '-code-completion-at=file:line:column' argument
272 // to perform code completion, with an "-Xclang" preceding it.
273 std::string code_complete_at;
274 code_complete_at += complete_filename;
275 code_complete_at += ":";
276 code_complete_at += llvm::utostr(complete_line);
277 code_complete_at += ":";
278 code_complete_at += llvm::utostr(complete_column);
279 argv.push_back("-Xclang");
280 argv.push_back("-code-completion-at");
281 argv.push_back("-Xclang");
282 argv.push_back(code_complete_at.c_str());
283 argv.push_back("-Xclang");
284 argv.push_back("-no-code-completion-debug-printer");
285 argv.push_back("-Xclang");
286 argv.push_back("-code-completion-macros");
Douglas Gregord93256e2010-01-28 06:00:51 +0000287 argv.push_back("-fdiagnostics-binary");
288
Douglas Gregor4db64a42010-01-23 00:14:00 +0000289 // Remap any unsaved files to temporary files.
Ted Kremenekab188932010-01-05 19:32:54 +0000290 std::vector<std::string> RemapArgs;
Douglas Gregor4db64a42010-01-23 00:14:00 +0000291 if (RemapFiles(num_unsaved_files, unsaved_files, RemapArgs, TemporaryFiles))
292 return 0;
Ted Kremenekab188932010-01-05 19:32:54 +0000293
294 // The pointers into the elements of RemapArgs are stable because we
295 // won't be adding anything to RemapArgs after this point.
296 for (unsigned i = 0, e = RemapArgs.size(); i != e; ++i)
297 argv.push_back(RemapArgs[i].c_str());
298
299 // Add the source file name (FIXME: later, we'll want to build temporary
300 // file from the buffer, or just feed the source text via standard input).
301 if (source_filename)
302 argv.push_back(source_filename);
303
304 // Process the compiler options, stripping off '-o', '-c', '-fsyntax-only'.
305 for (int i = 0; i < num_command_line_args; ++i)
306 if (const char *arg = command_line_args[i]) {
307 if (strcmp(arg, "-o") == 0) {
308 ++i; // Also skip the matching argument.
309 continue;
310 }
311 if (strcmp(arg, "-emit-ast") == 0 ||
312 strcmp(arg, "-c") == 0 ||
313 strcmp(arg, "-fsyntax-only") == 0) {
314 continue;
315 }
316
317 // Keep the argument.
318 argv.push_back(arg);
319 }
320
321 // Add the null terminator.
322 argv.push_back(NULL);
323
Douglas Gregord93256e2010-01-28 06:00:51 +0000324 // Generate a temporary name for the code-completion results file.
Benjamin Kramerc2a98162010-03-13 21:22:49 +0000325 char tmpFile[L_tmpnam];
326 char *tmpFileName = tmpnam(tmpFile);
327 llvm::sys::Path ResultsFile(tmpFileName);
Ted Kremenekab188932010-01-05 19:32:54 +0000328 TemporaryFiles.push_back(ResultsFile);
329
Douglas Gregord93256e2010-01-28 06:00:51 +0000330 // Generate a temporary name for the diagnostics file.
Benjamin Kramerc2a98162010-03-13 21:22:49 +0000331 char tmpFileResults[L_tmpnam];
332 char *tmpResultsFileName = tmpnam(tmpFileResults);
333 llvm::sys::Path DiagnosticsFile(tmpResultsFileName);
Douglas Gregord93256e2010-01-28 06:00:51 +0000334 TemporaryFiles.push_back(DiagnosticsFile);
335
Ted Kremenekab188932010-01-05 19:32:54 +0000336 // Invoke 'clang'.
337 llvm::sys::Path DevNull; // leave empty, causes redirection to /dev/null
338 // on Unix or NUL (Windows).
339 std::string ErrMsg;
Douglas Gregord93256e2010-01-28 06:00:51 +0000340 const llvm::sys::Path *Redirects[] = { &DevNull, &ResultsFile,
341 &DiagnosticsFile, 0 };
Ted Kremenekab188932010-01-05 19:32:54 +0000342 llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0], /* env */ NULL,
343 /* redirects */ &Redirects[0],
344 /* secondsToWait */ 0,
345 /* memoryLimits */ 0, &ErrMsg);
346
Douglas Gregor936ea3b2010-01-28 00:56:43 +0000347 if (!ErrMsg.empty()) {
348 std::string AllArgs;
Ted Kremenekab188932010-01-05 19:32:54 +0000349 for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
Douglas Gregor936ea3b2010-01-28 00:56:43 +0000350 I != E; ++I) {
351 AllArgs += ' ';
Ted Kremenekab188932010-01-05 19:32:54 +0000352 if (*I)
Douglas Gregor936ea3b2010-01-28 00:56:43 +0000353 AllArgs += *I;
Ted Kremenekab188932010-01-05 19:32:54 +0000354 }
Douglas Gregor936ea3b2010-01-28 00:56:43 +0000355
Daniel Dunbar32141c82010-02-23 20:23:45 +0000356 Diags->Report(diag::err_fe_invoking) << AllArgs << ErrMsg;
Ted Kremenekab188932010-01-05 19:32:54 +0000357 }
358
359 // Parse the resulting source file to find code-completion results.
360 using llvm::MemoryBuffer;
361 using llvm::StringRef;
Douglas Gregora88084b2010-02-18 18:08:43 +0000362 AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults;
363 Results->Results = 0;
364 Results->NumResults = 0;
365 Results->Buffer = 0;
366 // FIXME: Set Results->LangOpts!
Ted Kremenekab188932010-01-05 19:32:54 +0000367 if (MemoryBuffer *F = MemoryBuffer::getFile(ResultsFile.c_str())) {
368 llvm::SmallVector<CXCompletionResult, 4> CompletionResults;
369 StringRef Buffer = F->getBuffer();
370 for (const char *Str = Buffer.data(), *StrEnd = Str + Buffer.size();
371 Str < StrEnd;) {
372 unsigned KindValue;
373 if (ReadUnsigned(Str, StrEnd, KindValue))
374 break;
375
376 CodeCompletionString *CCStr
377 = CodeCompletionString::Deserialize(Str, StrEnd);
378 if (!CCStr)
379 continue;
380
381 if (!CCStr->empty()) {
382 // Vend the code-completion result to the caller.
383 CXCompletionResult Result;
384 Result.CursorKind = (CXCursorKind)KindValue;
385 Result.CompletionString = CCStr;
386 CompletionResults.push_back(Result);
387 }
388 };
389
390 // Allocate the results.
Ted Kremenekab188932010-01-05 19:32:54 +0000391 Results->Results = new CXCompletionResult [CompletionResults.size()];
392 Results->NumResults = CompletionResults.size();
393 memcpy(Results->Results, CompletionResults.data(),
394 CompletionResults.size() * sizeof(CXCompletionResult));
395 Results->Buffer = F;
396 }
397
Douglas Gregora88084b2010-02-18 18:08:43 +0000398 LoadSerializedDiagnostics(DiagnosticsFile, num_unsaved_files, unsaved_files,
399 Results->FileMgr, Results->SourceMgr,
400 Results->Diagnostics);
401
Douglas Gregor313e26c2010-02-18 23:35:40 +0000402 // Make sure we delete temporary files when the code-completion results are
403 // destroyed.
404 Results->TemporaryFiles.swap(TemporaryFiles);
Ted Kremenekab188932010-01-05 19:32:54 +0000405
Ted Kremenekda7af322010-04-15 01:02:28 +0000406#ifdef UDP_CODE_COMPLETION_LOGGER
407#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
408 const llvm::TimeRecord &EndTime = llvm::TimeRecord::getCurrentTime();
409 llvm::SmallString<256> LogResult;
410 llvm::raw_svector_ostream os(LogResult);
411
412 // Figure out the language and whether or not it uses PCH.
413 const char *lang = 0;
414 bool usesPCH = false;
415
416 for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
417 I != E; ++I) {
418 if (*I == 0)
419 continue;
420 if (strcmp(*I, "-x") == 0) {
421 if (I + 1 != E) {
422 lang = *(++I);
423 continue;
424 }
425 }
426 else if (strcmp(*I, "-include") == 0) {
427 if (I+1 != E) {
428 const char *arg = *(++I);
429 llvm::SmallString<512> pchName;
430 {
431 llvm::raw_svector_ostream os(pchName);
432 os << arg << ".pth";
433 }
434 pchName.push_back('\0');
435 struct stat stat_results;
436 if (stat(pchName.data(), &stat_results) == 0)
437 usesPCH = true;
438 continue;
439 }
440 }
441 }
442
Ted Kremenek2ee297f2010-04-17 00:21:42 +0000443 os << "{ ";
444 os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime());
445 os << ", \"numRes\": " << Results->NumResults;
446 os << ", \"diags\": " << Results->Diagnostics.size();
447 os << ", \"pch\": " << (usesPCH ? "true" : "false");
448 os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"';
Ted Kremenekda7af322010-04-15 01:02:28 +0000449 const char *name = getlogin();
Ted Kremenek2ee297f2010-04-17 00:21:42 +0000450 os << ", \"user\": \"" << (name ? name : "unknown") << '"';
451 os << ", \"clangVer\": \"" << getClangFullVersion() << '"';
452 os << " }";
Ted Kremenekda7af322010-04-15 01:02:28 +0000453
454 llvm::StringRef res = os.str();
455 if (res.size() > 0) {
456 do {
457 // Setup the UDP socket.
458 struct sockaddr_in servaddr;
459 bzero(&servaddr, sizeof(servaddr));
460 servaddr.sin_family = AF_INET;
461 servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT);
462 if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER,
463 &servaddr.sin_addr) <= 0)
464 break;
465
466 int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
467 if (sockfd < 0)
468 break;
469
470 sendto(sockfd, res.data(), res.size(), 0,
471 (struct sockaddr *)&servaddr, sizeof(servaddr));
472 close(sockfd);
473 }
474 while (false);
475 }
476#endif
477#endif
Ted Kremenekab188932010-01-05 19:32:54 +0000478 return Results;
479}
480
481void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) {
482 if (!ResultsIn)
483 return;
484
485 AllocatedCXCodeCompleteResults *Results
486 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
Ted Kremenekab188932010-01-05 19:32:54 +0000487 delete Results;
488}
489
Douglas Gregora88084b2010-02-18 18:08:43 +0000490unsigned
491clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *ResultsIn) {
492 AllocatedCXCodeCompleteResults *Results
493 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
494 if (!Results)
495 return 0;
496
497 return Results->Diagnostics.size();
498}
499
500CXDiagnostic
501clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *ResultsIn,
502 unsigned Index) {
503 AllocatedCXCodeCompleteResults *Results
504 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
505 if (!Results || Index >= Results->Diagnostics.size())
506 return 0;
507
508 return new CXStoredDiagnostic(Results->Diagnostics[Index], Results->LangOpts);
509}
510
511
Ted Kremenekab188932010-01-05 19:32:54 +0000512} // end extern "C"