aboutsummaryrefslogtreecommitdiff
path: root/lib/Basic/Diagnostic.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Basic/Diagnostic.cpp')
-rw-r--r--lib/Basic/Diagnostic.cpp219
1 files changed, 218 insertions, 1 deletions
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index abbf6f9b6e41..094f7760a8ec 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -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 @@ Diagnostic::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const {
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;
@@ -510,7 +629,7 @@ bool Diagnostic::ProcessDiag() {
// it.
if (SuppressSystemWarnings && !ShouldEmitInSystemHeader &&
Info.getLocation().isValid() &&
- Info.getLocation().getSpellingLoc().isInSystemHeader() &&
+ Info.getLocation().getInstantiationLoc().isInSystemHeader() &&
(DiagLevel != Diagnostic::Note || LastDiagLevel == Diagnostic::Ignored)) {
LastDiagLevel = Diagnostic::Ignored;
return false;
@@ -917,6 +1036,104 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
}
}
+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