[cfe-commits] r94740 - in /cfe/trunk: include/clang/Basic/ include/clang/Driver/ include/clang/Frontend/ lib/Basic/ lib/Driver/ lib/Frontend/ test/Index/ tools/CIndex/
Douglas Gregor
dgregor at apple.com
Wed Jan 27 22:00:52 PST 2010
Author: dgregor
Date: Thu Jan 28 00:00:51 2010
New Revision: 94740
URL: http://llvm.org/viewvc/llvm-project?rev=94740&view=rev
Log:
Introduce serialization and deserialization of diagnostic information
so that CIndex can report diagnostics through the normal mechanisms
even when executing Clang in a separate process. This applies both
when performing code completion and when using ASTs as an intermediary
for clang_createTranslationUnitFromSourceFile().
The serialized format is not perfect at the moment, because it does
not encapsulate macro-instantiation information. Instead, it maps all
source locations back to the instantiation location. However, it does
maintain source-range and fix-it information. To get perfect fidelity
from the serialized format would require serializing a large chunk of
the source manager; at present, it isn't clear if this code will live
long enough for that to matter.
Added:
cfe/trunk/test/Index/code-complete-errors.c (with props)
Modified:
cfe/trunk/include/clang/Basic/Diagnostic.h
cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
cfe/trunk/include/clang/Basic/SourceManager.h
cfe/trunk/include/clang/Driver/CC1Options.td
cfe/trunk/include/clang/Driver/Options.td
cfe/trunk/include/clang/Frontend/DiagnosticOptions.h
cfe/trunk/lib/Basic/Diagnostic.cpp
cfe/trunk/lib/Driver/Tools.cpp
cfe/trunk/lib/Frontend/CompilerInstance.cpp
cfe/trunk/lib/Frontend/CompilerInvocation.cpp
cfe/trunk/tools/CIndex/CIndex.cpp
cfe/trunk/tools/CIndex/CIndexCodeCompletion.cpp
cfe/trunk/tools/CIndex/CIndexDiagnostic.cpp
cfe/trunk/tools/CIndex/CIndexDiagnostic.h
Modified: cfe/trunk/include/clang/Basic/Diagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=94740&r1=94739&r2=94740&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Diagnostic.h (original)
+++ cfe/trunk/include/clang/Basic/Diagnostic.h Thu Jan 28 00:00:51 2010
@@ -23,16 +23,19 @@
namespace llvm {
template <typename T> class SmallVectorImpl;
+ class raw_ostream;
}
namespace clang {
class DeclContext;
class DiagnosticBuilder;
class DiagnosticClient;
+ class FileManager;
class IdentifierInfo;
class LangOptions;
class PartialDiagnostic;
class Preprocessor;
+ class SourceManager;
class SourceRange;
// Import the diagnostic enums themselves.
@@ -400,6 +403,13 @@
/// \brief Clear out the current diagnostic.
void Clear() { CurDiagID = ~0U; }
+ /// Deserialize - Deserialize the first diagnostic within the memory
+ /// [Memory, MemoryEnd), producing a new diagnostic builder describing the
+ /// deserialized diagnostic. If the memory does not contain a
+ /// diagnostic, returns a diagnostic builder with no diagnostic ID.
+ DiagnosticBuilder Deserialize(FileManager &FM, SourceManager &SM,
+ const char *&Memory, const char *MemoryEnd);
+
private:
/// getDiagnosticMappingInfo - Return the mapping info currently set for the
/// specified builtin diagnostic. This returns the high bit encoding, or zero
@@ -568,6 +578,9 @@
/// been emitted.
~DiagnosticBuilder() { Emit(); }
+ /// isActive - Determine whether this diagnostic is still active.
+ bool isActive() const { return DiagObj != 0; }
+
/// Operator bool: conversion of DiagnosticBuilder to bool always returns
/// true. This allows is to be used in boolean error contexts like:
/// return Diag(...);
@@ -786,6 +799,12 @@
/// output buffer using the arguments stored in this diagnostic.
void FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
llvm::SmallVectorImpl<char> &OutStr) const;
+
+ /// Serialize - Serialize the given diagnostic (with its diagnostic
+ /// level) to the given stream. Serialization is a lossy operation,
+ /// since the specific diagnostic ID and any macro-instantiation
+ /// information is lost.
+ void Serialize(Diagnostic::Level DiagLevel, llvm::raw_ostream &OS) const;
};
/// DiagnosticClient - This is an abstract interface implemented by clients of
Modified: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td?rev=94740&r1=94739&r2=94740&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td Thu Jan 28 00:00:51 2010
@@ -19,6 +19,8 @@
"cannot locate code-completion file %0">, DefaultFatal;
def err_fe_stdout_binary : Error<"unable to change standard output to binary">,
DefaultFatal;
+def err_fe_stderr_binary : Error<"unable to change standard error to binary">,
+ DefaultFatal;
def err_fe_dependency_file_requires_MT : Error<
"-dependency-file requires at least one -MT option">;
def err_fe_incompatible_options : Error<
Modified: cfe/trunk/include/clang/Basic/SourceManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=94740&r1=94739&r2=94740&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/SourceManager.h (original)
+++ cfe/trunk/include/clang/Basic/SourceManager.h Thu Jan 28 00:00:51 2010
@@ -669,6 +669,9 @@
::const_iterator fileinfo_iterator;
fileinfo_iterator fileinfo_begin() const { return FileInfos.begin(); }
fileinfo_iterator fileinfo_end() const { return FileInfos.end(); }
+ bool hasFileInfo(const FileEntry *File) const {
+ return FileInfos.find(File) != FileInfos.end();
+ }
/// PrintStats - Print statistics to stderr.
///
Modified: cfe/trunk/include/clang/Driver/CC1Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=94740&r1=94739&r2=94740&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/CC1Options.td (original)
+++ cfe/trunk/include/clang/Driver/CC1Options.td Thu Jan 28 00:00:51 2010
@@ -165,6 +165,7 @@
HelpText<"Do not include source line and caret with diagnostics">;
def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">,
HelpText<"Do not include fixit information in diagnostics">;
+def fdiagnostics_binary : Flag<"-fdiagnostics-binary">;
def w : Flag<"-w">, HelpText<"Suppress all warnings">;
def pedantic : Flag<"-pedantic">;
def pedantic_errors : Flag<"-pedantic-errors">;
Modified: cfe/trunk/include/clang/Driver/Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=94740&r1=94739&r2=94740&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Options.td (original)
+++ cfe/trunk/include/clang/Driver/Options.td Thu Jan 28 00:00:51 2010
@@ -252,6 +252,7 @@
def fcreate_profile : Flag<"-fcreate-profile">, Group<f_Group>;
def fdebug_pass_arguments : Flag<"-fdebug-pass-arguments">, Group<f_Group>;
def fdebug_pass_structure : Flag<"-fdebug-pass-structure">, Group<f_Group>;
+def fdiagnostics_binary : Flag<"-fdiagnostics-binary">, Group<f_Group>, Flags<[HelpHidden]>;
def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group<f_Group>;
def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, Group<f_Group>;
def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group<f_Group>;
Modified: cfe/trunk/include/clang/Frontend/DiagnosticOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/DiagnosticOptions.h?rev=94740&r1=94739&r2=94740&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/DiagnosticOptions.h (original)
+++ cfe/trunk/include/clang/Frontend/DiagnosticOptions.h Thu Jan 28 00:00:51 2010
@@ -31,9 +31,12 @@
unsigned ShowOptionNames : 1; /// Show the diagnostic name for mappable
/// diagnostics.
unsigned ShowColors : 1; /// Show diagnostics with ANSI color sequences.
- unsigned VerifyDiagnostics; /// Check that diagnostics match the expected
+ unsigned VerifyDiagnostics: 1; /// Check that diagnostics match the expected
/// diagnostics, indicated by markers in the
/// input source file.
+ unsigned BinaryOutput : 1; /// Emit diagnostics via the diagnostic
+ /// binary serialization mechanism, to be
+ /// deserialized by, e.g., the CIndex library.
/// The distance between tab stops.
unsigned TabStop;
@@ -66,6 +69,7 @@
ShowOptionNames = 0;
ShowSourceRanges = 0;
VerifyDiagnostics = 0;
+ BinaryOutput = 0;
}
};
Modified: cfe/trunk/lib/Basic/Diagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Diagnostic.cpp?rev=94740&r1=94739&r2=94740&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Diagnostic.cpp (original)
+++ cfe/trunk/lib/Basic/Diagnostic.cpp Thu Jan 28 00:00:51 2010
@@ -21,8 +21,10 @@
#include "clang/Analysis/AnalysisDiagnostic.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Basic/FileManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/raw_ostream.h"
@@ -385,6 +387,123 @@
return Result;
}
+static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd,
+ unsigned &Value) {
+ if (Memory + sizeof(unsigned) > MemoryEnd)
+ return true;
+
+ memmove(&Value, Memory, sizeof(unsigned));
+ Memory += sizeof(unsigned);
+ return false;
+}
+
+static bool ReadSourceLocation(FileManager &FM, SourceManager &SM,
+ const char *&Memory, const char *MemoryEnd,
+ SourceLocation &Location) {
+ // Read the filename.
+ unsigned FileNameLen = 0;
+ if (ReadUnsigned(Memory, MemoryEnd, FileNameLen) ||
+ Memory + FileNameLen > MemoryEnd)
+ return true;
+
+ llvm::StringRef FileName(Memory, FileNameLen);
+ Memory += FileNameLen;
+
+ // Read the line, column.
+ unsigned Line = 0, Column = 0;
+ if (ReadUnsigned(Memory, MemoryEnd, Line) ||
+ ReadUnsigned(Memory, MemoryEnd, Column))
+ return true;
+
+ if (FileName.empty()) {
+ Location = SourceLocation();
+ return false;
+ }
+
+ const FileEntry *File = FM.getFile(FileName);
+ if (!File)
+ return true;
+
+ // Make sure that this file has an entry in the source manager.
+ if (!SM.hasFileInfo(File))
+ SM.createFileID(File, SourceLocation(), SrcMgr::C_User);
+
+ Location = SM.getLocation(File, Line, Column);
+ return false;
+}
+
+DiagnosticBuilder Diagnostic::Deserialize(FileManager &FM, SourceManager &SM,
+ const char *&Memory,
+ const char *MemoryEnd) {
+ if (Memory == MemoryEnd)
+ return DiagnosticBuilder(0);
+
+ // Read the severity level.
+ unsigned Level = 0;
+ if (ReadUnsigned(Memory, MemoryEnd, Level) || Level > Fatal)
+ return DiagnosticBuilder(0);
+
+ // Read the source location.
+ SourceLocation Location;
+ if (ReadSourceLocation(FM, SM, Memory, MemoryEnd, Location))
+ return DiagnosticBuilder(0);
+
+ // Read the diagnostic text.
+ if (Memory == MemoryEnd)
+ return DiagnosticBuilder(0);
+
+ unsigned MessageLen = 0;
+ if (ReadUnsigned(Memory, MemoryEnd, MessageLen) ||
+ Memory + MessageLen > MemoryEnd)
+ return DiagnosticBuilder(0);
+
+ llvm::StringRef Message(Memory, MessageLen);
+ Memory += MessageLen;
+
+ // At this point, we have enough information to form a diagnostic. Do so.
+ unsigned DiagID = getCustomDiagID((enum Level)Level, Message);
+ DiagnosticBuilder DB = Report(FullSourceLoc(Location, SM), DiagID);
+ if (Memory == MemoryEnd)
+ return DB;
+
+ // Read the source ranges.
+ unsigned NumSourceRanges = 0;
+ if (ReadUnsigned(Memory, MemoryEnd, NumSourceRanges))
+ return DB;
+ for (unsigned I = 0; I != NumSourceRanges; ++I) {
+ SourceLocation Begin, End;
+ if (ReadSourceLocation(FM, SM, Memory, MemoryEnd, Begin) ||
+ ReadSourceLocation(FM, SM, Memory, MemoryEnd, End))
+ return DB;
+
+ DB << SourceRange(Begin, End);
+ }
+
+ // Read the fix-it hints.
+ unsigned NumFixIts = 0;
+ if (ReadUnsigned(Memory, MemoryEnd, NumFixIts))
+ return DB;
+ for (unsigned I = 0; I != NumFixIts; ++I) {
+ SourceLocation RemoveBegin, RemoveEnd, InsertionLoc;
+ unsigned InsertLen = 0;
+ if (ReadSourceLocation(FM, SM, Memory, MemoryEnd, RemoveBegin) ||
+ ReadSourceLocation(FM, SM, Memory, MemoryEnd, RemoveEnd) ||
+ ReadSourceLocation(FM, SM, Memory, MemoryEnd, InsertionLoc) ||
+ ReadUnsigned(Memory, MemoryEnd, InsertLen) ||
+ Memory + InsertLen > MemoryEnd)
+ return DB;
+
+ CodeModificationHint Hint;
+ Hint.RemoveRange = SourceRange(RemoveBegin, RemoveEnd);
+ Hint.InsertionLoc = InsertionLoc;
+ Hint.CodeToInsert.assign(Memory, Memory + InsertLen);
+ Memory += InsertLen;
+ DB << Hint;
+ }
+
+ return DB;
+}
+
struct WarningOption {
const char *Name;
const short *Members;
@@ -917,6 +1036,104 @@
}
}
+static void WriteUnsigned(llvm::raw_ostream &OS, unsigned Value) {
+ OS.write((const char *)&Value, sizeof(unsigned));
+}
+
+static void WriteString(llvm::raw_ostream &OS, llvm::StringRef String) {
+ WriteUnsigned(OS, String.size());
+ OS.write(String.data(), String.size());
+}
+
+static void WriteSourceLocation(llvm::raw_ostream &OS,
+ SourceManager *SM,
+ SourceLocation Location) {
+ if (!SM || Location.isInvalid()) {
+ // If we don't have a source manager or this location is invalid,
+ // just write an invalid location.
+ WriteUnsigned(OS, 0);
+ WriteUnsigned(OS, 0);
+ WriteUnsigned(OS, 0);
+ return;
+ }
+
+ Location = SM->getInstantiationLoc(Location);
+ std::pair<FileID, unsigned> Decomposed = SM->getDecomposedLoc(Location);
+
+ WriteString(OS, SM->getFileEntryForID(Decomposed.first)->getName());
+ WriteUnsigned(OS, SM->getLineNumber(Decomposed.first, Decomposed.second));
+ WriteUnsigned(OS, SM->getColumnNumber(Decomposed.first, Decomposed.second));
+}
+
+void DiagnosticInfo::Serialize(Diagnostic::Level DiagLevel,
+ llvm::raw_ostream &OS) const {
+ SourceManager *SM = 0;
+ if (getLocation().isValid())
+ SM = &const_cast<SourceManager &>(getLocation().getManager());
+
+ // Write the diagnostic level and location.
+ WriteUnsigned(OS, (unsigned)DiagLevel);
+ WriteSourceLocation(OS, SM, getLocation());
+
+ // Write the diagnostic message.
+ llvm::SmallString<64> Message;
+ FormatDiagnostic(Message);
+ WriteString(OS, Message);
+
+ // Count the number of ranges that don't point into macros, since
+ // only simple file ranges serialize well.
+ unsigned NumNonMacroRanges = 0;
+ for (unsigned I = 0, N = getNumRanges(); I != N; ++I) {
+ SourceRange R = getRange(I);
+ if (R.getBegin().isMacroID() || R.getEnd().isMacroID())
+ continue;
+
+ ++NumNonMacroRanges;
+ }
+
+ // Write the ranges.
+ WriteUnsigned(OS, NumNonMacroRanges);
+ if (NumNonMacroRanges) {
+ for (unsigned I = 0, N = getNumRanges(); I != N; ++I) {
+ SourceRange R = getRange(I);
+ if (R.getBegin().isMacroID() || R.getEnd().isMacroID())
+ continue;
+
+ WriteSourceLocation(OS, SM, R.getBegin());
+ WriteSourceLocation(OS, SM, R.getEnd());
+ }
+ }
+
+ // Determine if all of the fix-its involve rewrites with simple file
+ // locations (not in macro instantiations). If so, we can write
+ // fix-it information.
+ unsigned NumFixIts = getNumCodeModificationHints();
+ for (unsigned I = 0; I != NumFixIts; ++I) {
+ const CodeModificationHint &Hint = getCodeModificationHint(I);
+ if (Hint.RemoveRange.isValid() &&
+ (Hint.RemoveRange.getBegin().isMacroID() ||
+ Hint.RemoveRange.getEnd().isMacroID())) {
+ NumFixIts = 0;
+ break;
+ }
+
+ if (Hint.InsertionLoc.isValid() && Hint.InsertionLoc.isMacroID()) {
+ NumFixIts = 0;
+ break;
+ }
+ }
+
+ // Write the fix-its.
+ WriteUnsigned(OS, NumFixIts);
+ for (unsigned I = 0; I != NumFixIts; ++I) {
+ const CodeModificationHint &Hint = getCodeModificationHint(I);
+ WriteSourceLocation(OS, SM, Hint.RemoveRange.getBegin());
+ WriteSourceLocation(OS, SM, Hint.RemoveRange.getEnd());
+ WriteSourceLocation(OS, SM, Hint.InsertionLoc);
+ WriteString(OS, Hint.CodeToInsert);
+ }
+}
+
/// IncludeInDiagnosticCounts - This method (whose default implementation
/// returns true) indicates whether the diagnostics handled by this
/// DiagnosticClient should be included in the number of diagnostics
Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=94740&r1=94739&r2=94740&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Thu Jan 28 00:00:51 2010
@@ -1058,6 +1058,9 @@
options::OPT_fno_diagnostics_fixit_info))
CmdArgs.push_back("-fno-diagnostics-fixit-info");
+ if (Args.hasArg(options::OPT_fdiagnostics_binary))
+ CmdArgs.push_back("-fdiagnostics-binary");
+
// Enable -fdiagnostics-show-option by default.
if (Args.hasFlag(options::OPT_fdiagnostics_show_option,
options::OPT_fno_diagnostics_show_option))
Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=94740&r1=94739&r2=94740&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Thu Jan 28 00:00:51 2010
@@ -83,6 +83,23 @@
}
// Diagnostics
+namespace {
+ class BinaryDiagnosticSerializer : public DiagnosticClient {
+ llvm::raw_ostream &OS;
+ SourceManager *SourceMgr;
+ public:
+ explicit BinaryDiagnosticSerializer(llvm::raw_ostream &OS)
+ : OS(OS), SourceMgr(0) { }
+
+ virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info);
+ };
+}
+
+void BinaryDiagnosticSerializer::HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info) {
+ Info.Serialize(DiagLevel, OS);
+}
static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
unsigned argc, char **argv,
@@ -122,8 +139,23 @@
// Create the diagnostic client for reporting errors or for
// implementing -verify.
- llvm::OwningPtr<DiagnosticClient> DiagClient(
- new TextDiagnosticPrinter(llvm::errs(), Opts));
+ llvm::OwningPtr<DiagnosticClient> DiagClient;
+ if (Opts.BinaryOutput) {
+ if (llvm::sys::Program::ChangeStderrToBinary()) {
+ // We weren't able to set standard error to binary, which is a
+ // bit of a problem. So, just create a text diagnostic printer
+ // to complain about this problem, and pretend that the user
+ // didn't try to use binary output.
+ DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
+ Diags->setClient(DiagClient.take());
+ Diags->Report(diag::err_fe_stderr_binary);
+ return Diags.take();
+ } else {
+ DiagClient.reset(new BinaryDiagnosticSerializer(llvm::errs()));
+ }
+ } else {
+ DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
+ }
// Chain in -verify checker, if requested.
if (Opts.VerifyDiagnostics)
Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=94740&r1=94739&r2=94740&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Thu Jan 28 00:00:51 2010
@@ -220,6 +220,8 @@
Res.push_back("-fcolor-diagnostics");
if (Opts.VerifyDiagnostics)
Res.push_back("-verify");
+ if (Opts.BinaryOutput)
+ Res.push_back("-fdiagnostics-binary");
if (Opts.ShowOptionNames)
Res.push_back("-fdiagnostics-show-option");
if (Opts.TabStop != DiagnosticOptions::DefaultTabStop) {
@@ -808,6 +810,7 @@
Opts.ShowOptionNames = Args.hasArg(OPT_fdiagnostics_show_option);
Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
Opts.VerifyDiagnostics = Args.hasArg(OPT_verify);
+ Opts.BinaryOutput = Args.hasArg(OPT_fdiagnostics_binary);
Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop,
DiagnosticOptions::DefaultTabStop, Diags);
if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
Added: cfe/trunk/test/Index/code-complete-errors.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/code-complete-errors.c?rev=94740&view=auto
==============================================================================
--- cfe/trunk/test/Index/code-complete-errors.c (added)
+++ cfe/trunk/test/Index/code-complete-errors.c Thu Jan 28 00:00:51 2010
@@ -0,0 +1,16 @@
+_Complex cd; // CHECK: code-complete-errors.c:1:1: warning: plain '_Complex' requires a type specifier; assuming '_Complex double'
+
+struct s {
+ int x, y;;
+};
+
+struct s s0 = { y: 5 }; // CHECK: code-complete-errors.c:7:20: warning: use of GNU old-style field designator extension
+
+int f(int *ptr1, float *ptr2) {
+ return ptr1 != ptr2; // CHECK: code-complete-errors.c:10:15: warning: comparison of distinct pointer types ('int *' and 'float *')
+}
+
+void g() { }
+
+// RUN: c-index-test -code-completion-at=%s:13:12 %s 2> %t
+// RUN: FileCheck -check-prefix=CHECK %s < %t
Propchange: cfe/trunk/test/Index/code-complete-errors.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/Index/code-complete-errors.c
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/Index/code-complete-errors.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: cfe/trunk/tools/CIndex/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CIndex.cpp?rev=94740&r1=94739&r2=94740&view=diff
==============================================================================
--- cfe/trunk/tools/CIndex/CIndex.cpp (original)
+++ cfe/trunk/tools/CIndex/CIndex.cpp Thu Jan 28 00:00:51 2010
@@ -1044,6 +1044,13 @@
argv.push_back(arg);
}
+ // Generate a temporary name for the diagnostics file.
+ char tmpFileResults[L_tmpnam];
+ char *tmpResultsFileName = tmpnam(tmpFileResults);
+ llvm::sys::Path DiagnosticsFile(tmpResultsFileName);
+ TemporaryFiles.push_back(DiagnosticsFile);
+ argv.push_back("-fdiagnostics-binary");
+
// Add the null terminator.
argv.push_back(NULL);
@@ -1051,7 +1058,8 @@
llvm::sys::Path DevNull; // leave empty, causes redirection to /dev/null
// on Unix or NUL (Windows).
std::string ErrMsg;
- const llvm::sys::Path *Redirects[] = { &DevNull, &DevNull, &DevNull, NULL };
+ const llvm::sys::Path *Redirects[] = { &DevNull, &DevNull, &DiagnosticsFile,
+ NULL };
llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0], /* env */ NULL,
/* redirects */ &Redirects[0],
/* secondsToWait */ 0, /* memoryLimits */ 0, &ErrMsg);
@@ -1078,6 +1086,9 @@
if (ATU)
ATU->unlinkTemporaryFile();
+ ReportSerializedDiagnostics(DiagnosticsFile, *Diags,
+ num_unsaved_files, unsaved_files);
+
for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i)
TemporaryFiles[i].eraseFromDisk();
Modified: cfe/trunk/tools/CIndex/CIndexCodeCompletion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CIndexCodeCompletion.cpp?rev=94740&r1=94739&r2=94740&view=diff
==============================================================================
--- cfe/trunk/tools/CIndex/CIndexCodeCompletion.cpp (original)
+++ cfe/trunk/tools/CIndex/CIndexCodeCompletion.cpp Thu Jan 28 00:00:51 2010
@@ -231,7 +231,8 @@
argv.push_back("-no-code-completion-debug-printer");
argv.push_back("-Xclang");
argv.push_back("-code-completion-macros");
-
+ argv.push_back("-fdiagnostics-binary");
+
// Remap any unsaved files to temporary files.
std::vector<std::string> RemapArgs;
if (RemapFiles(num_unsaved_files, unsaved_files, RemapArgs, TemporaryFiles))
@@ -267,17 +268,24 @@
// Add the null terminator.
argv.push_back(NULL);
- // Generate a temporary name for the AST file.
+ // Generate a temporary name for the code-completion results file.
char tmpFile[L_tmpnam];
char *tmpFileName = tmpnam(tmpFile);
llvm::sys::Path ResultsFile(tmpFileName);
TemporaryFiles.push_back(ResultsFile);
+ // Generate a temporary name for the diagnostics file.
+ char tmpFileResults[L_tmpnam];
+ char *tmpResultsFileName = tmpnam(tmpFileResults);
+ llvm::sys::Path DiagnosticsFile(tmpResultsFileName);
+ TemporaryFiles.push_back(DiagnosticsFile);
+
// Invoke 'clang'.
llvm::sys::Path DevNull; // leave empty, causes redirection to /dev/null
// on Unix or NUL (Windows).
std::string ErrMsg;
- const llvm::sys::Path *Redirects[] = { &DevNull, &ResultsFile, &DevNull, 0 };
+ const llvm::sys::Path *Redirects[] = { &DevNull, &ResultsFile,
+ &DiagnosticsFile, 0 };
llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0], /* env */ NULL,
/* redirects */ &Redirects[0],
/* secondsToWait */ 0,
@@ -331,7 +339,8 @@
Results->Buffer = F;
}
- // FIXME: Parse the (redirected) standard error to emit diagnostics.
+ ReportSerializedDiagnostics(DiagnosticsFile, *Diags,
+ num_unsaved_files, unsaved_files);
for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i)
TemporaryFiles[i].eraseFromDisk();
Modified: cfe/trunk/tools/CIndex/CIndexDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CIndexDiagnostic.cpp?rev=94740&r1=94739&r2=94740&view=diff
==============================================================================
--- cfe/trunk/tools/CIndex/CIndexDiagnostic.cpp (original)
+++ cfe/trunk/tools/CIndex/CIndexDiagnostic.cpp Thu Jan 28 00:00:51 2010
@@ -14,6 +14,9 @@
#include "CIndexer.h"
#include "CXSourceLocation.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "llvm/Support/MemoryBuffer.h"
+
using namespace clang;
using namespace clang::cxloc;
@@ -196,3 +199,47 @@
}
} // end extern "C"
+
+void clang::ReportSerializedDiagnostics(const llvm::sys::Path &DiagnosticsPath,
+ Diagnostic &Diags,
+ unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files) {
+ using llvm::MemoryBuffer;
+ using llvm::StringRef;
+ MemoryBuffer *F = MemoryBuffer::getFile(DiagnosticsPath.c_str());
+ if (!F)
+ return;
+
+ // Enter the unsaved files into the file manager.
+ SourceManager SourceMgr;
+ FileManager FileMgr;
+ for (unsigned I = 0; I != num_unsaved_files; ++I) {
+ const FileEntry *File = FileMgr.getVirtualFile(unsaved_files[I].Filename,
+ unsaved_files[I].Length,
+ 0);
+ if (!File) {
+ Diags.Report(diag::err_fe_remap_missing_from_file)
+ << unsaved_files[I].Filename;
+ return;
+ }
+
+ MemoryBuffer *Buffer
+ = MemoryBuffer::getMemBuffer(unsaved_files[I].Contents,
+ unsaved_files[I].Contents + unsaved_files[I].Length);
+ if (!Buffer)
+ return;
+
+ SourceMgr.overrideFileContents(File, Buffer);
+ }
+
+ // Parse the diagnostics, emitting them one by one until we've
+ // exhausted the data.
+ StringRef Buffer = F->getBuffer();
+ const char *Memory = Buffer.data(), *MemoryEnd = Memory + Buffer.size();
+ while (Memory != MemoryEnd) {
+ DiagnosticBuilder DB = Diags.Deserialize(FileMgr, SourceMgr,
+ Memory, MemoryEnd);
+ if (!DB.isActive())
+ return;
+ }
+}
Modified: cfe/trunk/tools/CIndex/CIndexDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CIndexDiagnostic.h?rev=94740&r1=94739&r2=94740&view=diff
==============================================================================
--- cfe/trunk/tools/CIndex/CIndexDiagnostic.h (original)
+++ cfe/trunk/tools/CIndex/CIndexDiagnostic.h Thu Jan 28 00:00:51 2010
@@ -1,4 +1,4 @@
-/*===-- CIndexDiagnostic.h - Diagnostics C Interface --------------*- C -*-===*\
+/*===-- CIndexDiagnostic.h - Diagnostics C Interface ------------*- C++ -*-===*\
|* *|
|* The LLVM Compiler Infrastructure *|
|* *|
@@ -17,8 +17,13 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LangOptions.h"
+namespace llvm { namespace sys {
+class Path;
+} }
+
namespace clang {
+class Diagnostic;
class Preprocessor;
/**
@@ -43,7 +48,15 @@
virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
const DiagnosticInfo &Info);
};
-
+
+/// \brief Given the path to a file that contains binary, serialized
+/// diagnostics produced by Clang, emit those diagnostics via the
+/// given diagnostic engine.
+void ReportSerializedDiagnostics(const llvm::sys::Path &DiagnosticsPath,
+ Diagnostic &Diags,
+ unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files);
+
} // end namespace clang
#endif // LLVM_CLANG_CINDEX_DIAGNOSTIC_H
More information about the cfe-commits
mailing list