summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/Diagnostic.h39
-rw-r--r--clang/include/clang/Basic/PartialDiagnostic.h12
-rw-r--r--clang/include/clang/Basic/SourceLocation.h50
-rw-r--r--clang/include/clang/Frontend/TextDiagnosticPrinter.h9
-rw-r--r--clang/include/clang/Rewrite/Rewriter.h1
-rw-r--r--clang/lib/Basic/Diagnostic.cpp18
-rw-r--r--clang/lib/Checker/PathDiagnostic.cpp2
-rw-r--r--clang/lib/Frontend/TextDiagnosticPrinter.cpp30
-rw-r--r--clang/lib/Rewrite/Rewriter.cpp12
-rw-r--r--clang/tools/libclang/CIndex.cpp4
-rw-r--r--clang/tools/libclang/CXSourceLocation.h4
11 files changed, 131 insertions, 50 deletions
diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h
index a4221e0ff44..1fe0d8154cd 100644
--- a/clang/include/clang/Basic/Diagnostic.h
+++ b/clang/include/clang/Basic/Diagnostic.h
@@ -24,7 +24,6 @@
namespace llvm {
template <typename T> class SmallVectorImpl;
- class raw_ostream;
}
namespace clang {
@@ -36,8 +35,6 @@ namespace clang {
class LangOptions;
class PartialDiagnostic;
class Preprocessor;
- class SourceManager;
- class SourceRange;
// Import the diagnostic enums themselves.
namespace diag {
@@ -98,8 +95,8 @@ namespace clang {
/// compilation.
class FixItHint {
public:
- /// \brief Tokens that should be removed to correct the error.
- SourceRange RemoveRange;
+ /// \brief Code that should be removed to correct the error.
+ CharSourceRange RemoveRange;
/// \brief The location at which we should insert code to correct
/// the error.
@@ -129,15 +126,18 @@ public:
/// \brief Create a code modification hint that removes the given
/// source range.
- static FixItHint CreateRemoval(SourceRange RemoveRange) {
+ static FixItHint CreateRemoval(CharSourceRange RemoveRange) {
FixItHint Hint;
Hint.RemoveRange = RemoveRange;
return Hint;
}
-
+ static FixItHint CreateRemoval(SourceRange RemoveRange) {
+ return CreateRemoval(CharSourceRange::getTokenRange(RemoveRange));
+ }
+
/// \brief Create a code modification hint that replaces the given
/// source range with the given code string.
- static FixItHint CreateReplacement(SourceRange RemoveRange,
+ static FixItHint CreateReplacement(CharSourceRange RemoveRange,
llvm::StringRef Code) {
FixItHint Hint;
Hint.RemoveRange = RemoveRange;
@@ -145,6 +145,11 @@ public:
Hint.CodeToInsert = Code;
return Hint;
}
+
+ static FixItHint CreateReplacement(SourceRange RemoveRange,
+ llvm::StringRef Code) {
+ return CreateReplacement(CharSourceRange::getTokenRange(RemoveRange), Code);
+ }
};
/// Diagnostic - This concrete class is used by the front-end to report
@@ -597,7 +602,7 @@ private:
/// DiagRanges - The list of ranges added to this diagnostic. It currently
/// only support 10 ranges, could easily be extended if needed.
- SourceRange DiagRanges[10];
+ CharSourceRange DiagRanges[10];
enum { MaxFixItHints = 3 };
@@ -696,7 +701,7 @@ public:
}
}
- void AddSourceRange(const SourceRange &R) const {
+ void AddSourceRange(const CharSourceRange &R) const {
assert(NumRanges <
sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) &&
"Too many arguments to diagnostic!");
@@ -767,11 +772,17 @@ operator<<(const DiagnosticBuilder &DB, T *DC) {
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const SourceRange &R) {
- DB.AddSourceRange(R);
+ DB.AddSourceRange(CharSourceRange::getTokenRange(R));
return DB;
}
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const CharSourceRange &R) {
+ DB.AddSourceRange(R);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const FixItHint &Hint) {
DB.AddFixItHint(Hint);
return DB;
@@ -864,7 +875,7 @@ public:
return DiagObj->NumDiagRanges;
}
- SourceRange getRange(unsigned Idx) const {
+ const CharSourceRange &getRange(unsigned Idx) const {
assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!");
return DiagObj->DiagRanges[Idx];
}
@@ -901,7 +912,7 @@ class StoredDiagnostic {
Diagnostic::Level Level;
FullSourceLoc Loc;
std::string Message;
- std::vector<SourceRange> Ranges;
+ std::vector<CharSourceRange> Ranges;
std::vector<FixItHint> FixIts;
public:
@@ -917,7 +928,7 @@ public:
const FullSourceLoc &getLocation() const { return Loc; }
llvm::StringRef getMessage() const { return Message; }
- typedef std::vector<SourceRange>::const_iterator range_iterator;
+ typedef std::vector<CharSourceRange>::const_iterator range_iterator;
range_iterator range_begin() const { return Ranges.begin(); }
range_iterator range_end() const { return Ranges.end(); }
unsigned range_size() const { return Ranges.size(); }
diff --git a/clang/include/clang/Basic/PartialDiagnostic.h b/clang/include/clang/Basic/PartialDiagnostic.h
index 89fae87ae8e..cd0da97e2ba 100644
--- a/clang/include/clang/Basic/PartialDiagnostic.h
+++ b/clang/include/clang/Basic/PartialDiagnostic.h
@@ -59,7 +59,7 @@ public:
/// DiagRanges - The list of ranges added to this diagnostic. It currently
/// only support 10 ranges, could easily be extended if needed.
- SourceRange DiagRanges[10];
+ CharSourceRange DiagRanges[10];
enum { MaxFixItHints = 3 };
@@ -142,7 +142,7 @@ private:
DiagStorage = 0;
}
- void AddSourceRange(const SourceRange &R) const {
+ void AddSourceRange(const CharSourceRange &R) const {
if (!DiagStorage)
DiagStorage = getStorage();
@@ -264,10 +264,16 @@ public:
friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
const SourceRange &R) {
- PD.AddSourceRange(R);
+ PD.AddSourceRange(CharSourceRange::getTokenRange(R));
return PD;
}
+ friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ const CharSourceRange &R) {
+ PD.AddSourceRange(R);
+ return PD;
+ }
+
friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
const FixItHint &Hint) {
PD.AddFixItHint(Hint);
diff --git a/clang/include/clang/Basic/SourceLocation.h b/clang/include/clang/Basic/SourceLocation.h
index 0bbeffefc72..35f27fbebd7 100644
--- a/clang/include/clang/Basic/SourceLocation.h
+++ b/clang/include/clang/Basic/SourceLocation.h
@@ -172,6 +172,56 @@ public:
return B != X.B || E != X.E;
}
};
+
+/// CharSourceRange - This class represents a character granular source range.
+/// The underlying SourceRange can either specify the starting/ending character
+/// of the range, or it can specify the start or the range and the start of the
+/// last token of the range (a "token range"). In the token range case, the
+/// size of the last token must be measured to determine the actual end of the
+/// range.
+class CharSourceRange {
+ SourceRange Range;
+ bool IsTokenRange;
+public:
+ CharSourceRange() : IsTokenRange(false) {}
+ CharSourceRange(SourceRange R, bool ITR) : Range(R),IsTokenRange(ITR){}
+
+ static CharSourceRange getTokenRange(SourceRange R) {
+ CharSourceRange Result;
+ Result.Range = R;
+ Result.IsTokenRange = true;
+ return Result;
+ }
+
+ static CharSourceRange getCharRange(SourceRange R) {
+ CharSourceRange Result;
+ Result.Range = R;
+ Result.IsTokenRange = false;
+ return Result;
+ }
+
+ static CharSourceRange getTokenRange(SourceLocation B, SourceLocation E) {
+ return getTokenRange(SourceRange(B, E));
+ }
+ static CharSourceRange getCharRange(SourceLocation B, SourceLocation E) {
+ return getCharRange(SourceRange(B, E));
+ }
+
+ /// isTokenRange - Return true if the end of this range specifies the start of
+ /// the last token. Return false if the end of this range specifies the last
+ /// character in the range.
+ bool isTokenRange() const { return IsTokenRange; }
+
+ SourceLocation getBegin() const { return Range.getBegin(); }
+ SourceLocation getEnd() const { return Range.getEnd(); }
+ const SourceRange &getAsRange() const { return Range; }
+
+ void setBegin(SourceLocation b) { Range.setBegin(b); }
+ void setEnd(SourceLocation e) { Range.setEnd(e); }
+
+ bool isValid() const { return Range.isValid(); }
+ bool isInvalid() const { return !isValid(); }
+};
/// FullSourceLoc - A SourceLocation and its associated SourceManager. Useful
/// for argument passing to functions that expect both objects.
diff --git a/clang/include/clang/Frontend/TextDiagnosticPrinter.h b/clang/include/clang/Frontend/TextDiagnosticPrinter.h
index ec4392fe5d5..f5302947a59 100644
--- a/clang/include/clang/Frontend/TextDiagnosticPrinter.h
+++ b/clang/include/clang/Frontend/TextDiagnosticPrinter.h
@@ -18,14 +18,9 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceLocation.h"
-namespace llvm {
- class raw_ostream;
-}
-
namespace clang {
class DiagnosticOptions;
class LangOptions;
-class SourceManager;
class TextDiagnosticPrinter : public DiagnosticClient {
llvm::raw_ostream &OS;
@@ -60,14 +55,14 @@ public:
void PrintIncludeStack(SourceLocation Loc, const SourceManager &SM);
- void HighlightRange(const SourceRange &R,
+ void HighlightRange(const CharSourceRange &R,
const SourceManager &SrcMgr,
unsigned LineNo, FileID FID,
std::string &CaretLine,
const std::string &SourceLine);
void EmitCaretDiagnostic(SourceLocation Loc,
- SourceRange *Ranges, unsigned NumRanges,
+ CharSourceRange *Ranges, unsigned NumRanges,
const SourceManager &SM,
const FixItHint *Hints,
unsigned NumHints,
diff --git a/clang/include/clang/Rewrite/Rewriter.h b/clang/include/clang/Rewrite/Rewriter.h
index adda8669996..0612a15bbf3 100644
--- a/clang/include/clang/Rewrite/Rewriter.h
+++ b/clang/include/clang/Rewrite/Rewriter.h
@@ -151,6 +151,7 @@ public:
/// getRangeSize - Return the size in bytes of the specified range if they
/// are in the same file. If not, this returns -1.
int getRangeSize(SourceRange Range) const;
+ int getRangeSize(const CharSourceRange &Range) const;
/// getRewrittenText - Return the rewritten form of the text in the specified
/// range. If the start or end of the range was unrewritable or if they are
diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp
index a2480b16843..641d87bb9af 100644
--- a/clang/lib/Basic/Diagnostic.cpp
+++ b/clang/lib/Basic/Diagnostic.cpp
@@ -1043,8 +1043,7 @@ StoredDiagnostic::StoredDiagnostic(Diagnostic::Level Level,
StoredDiagnostic::StoredDiagnostic(Diagnostic::Level Level,
const DiagnosticInfo &Info)
- : Level(Level), Loc(Info.getLocation())
-{
+ : Level(Level), Loc(Info.getLocation()) {
llvm::SmallString<64> Message;
Info.FormatDiagnostic(Message);
this->Message.assign(Message.begin(), Message.end());
@@ -1131,6 +1130,7 @@ void StoredDiagnostic::Serialize(llvm::raw_ostream &OS) const {
WriteSourceLocation(OS, SM, R->getBegin());
WriteSourceLocation(OS, SM, R->getEnd());
+ WriteUnsigned(OS, R->isTokenRange());
}
}
@@ -1159,6 +1159,7 @@ void StoredDiagnostic::Serialize(llvm::raw_ostream &OS) const {
for (fixit_iterator F = fixit_begin(), FEnd = fixit_end(); F != FEnd; ++F) {
WriteSourceLocation(OS, SM, F->RemoveRange.getBegin());
WriteSourceLocation(OS, SM, F->RemoveRange.getEnd());
+ WriteUnsigned(OS, F->RemoveRange.isTokenRange());
WriteSourceLocation(OS, SM, F->InsertionLoc);
WriteString(OS, F->CodeToInsert);
}
@@ -1272,11 +1273,14 @@ StoredDiagnostic::Deserialize(FileManager &FM, SourceManager &SM,
return Diag;
for (unsigned I = 0; I != NumSourceRanges; ++I) {
SourceLocation Begin, End;
+ unsigned IsTokenRange;
if (ReadSourceLocation(FM, SM, Memory, MemoryEnd, Begin) ||
- ReadSourceLocation(FM, SM, Memory, MemoryEnd, End))
+ ReadSourceLocation(FM, SM, Memory, MemoryEnd, End) ||
+ ReadUnsigned(Memory, MemoryEnd, IsTokenRange))
return Diag;
- Diag.Ranges.push_back(SourceRange(Begin, End));
+ Diag.Ranges.push_back(CharSourceRange(SourceRange(Begin, End),
+ IsTokenRange));
}
// Read the fix-it hints.
@@ -1285,9 +1289,10 @@ StoredDiagnostic::Deserialize(FileManager &FM, SourceManager &SM,
return Diag;
for (unsigned I = 0; I != NumFixIts; ++I) {
SourceLocation RemoveBegin, RemoveEnd, InsertionLoc;
- unsigned InsertLen = 0;
+ unsigned InsertLen = 0, RemoveIsTokenRange;
if (ReadSourceLocation(FM, SM, Memory, MemoryEnd, RemoveBegin) ||
ReadSourceLocation(FM, SM, Memory, MemoryEnd, RemoveEnd) ||
+ ReadUnsigned(Memory, MemoryEnd, RemoveIsTokenRange) ||
ReadSourceLocation(FM, SM, Memory, MemoryEnd, InsertionLoc) ||
ReadUnsigned(Memory, MemoryEnd, InsertLen) ||
Memory + InsertLen > MemoryEnd) {
@@ -1296,7 +1301,8 @@ StoredDiagnostic::Deserialize(FileManager &FM, SourceManager &SM,
}
FixItHint Hint;
- Hint.RemoveRange = SourceRange(RemoveBegin, RemoveEnd);
+ Hint.RemoveRange = CharSourceRange(SourceRange(RemoveBegin, RemoveEnd),
+ RemoveIsTokenRange);
Hint.InsertionLoc = InsertionLoc;
Hint.CodeToInsert.assign(Memory, Memory + InsertLen);
Memory += InsertLen;
diff --git a/clang/lib/Checker/PathDiagnostic.cpp b/clang/lib/Checker/PathDiagnostic.cpp
index 963923c9ad1..6e6c7496f1d 100644
--- a/clang/lib/Checker/PathDiagnostic.cpp
+++ b/clang/lib/Checker/PathDiagnostic.cpp
@@ -107,7 +107,7 @@ void PathDiagnosticClient::HandleDiagnostic(Diagnostic::Level DiagLevel,
new PathDiagnosticEventPiece(Info.getLocation(), StrC.str());
for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i)
- P->addRange(Info.getRange(i));
+ P->addRange(Info.getRange(i).getAsRange());
for (unsigned i = 0, e = Info.getNumFixItHints(); i != e; ++i)
P->addFixItHint(Info.getFixItHint(i));
D->push_front(P);
diff --git a/clang/lib/Frontend/TextDiagnosticPrinter.cpp b/clang/lib/Frontend/TextDiagnosticPrinter.cpp
index 6ccf4f1ad0a..3f1eb82f7ef 100644
--- a/clang/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/clang/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -70,7 +70,7 @@ PrintIncludeStack(SourceLocation Loc, const SourceManager &SM) {
/// HighlightRange - Given a SourceRange and a line number, highlight (with ~'s)
/// any characters in LineNo that intersect the SourceRange.
-void TextDiagnosticPrinter::HighlightRange(const SourceRange &R,
+void TextDiagnosticPrinter::HighlightRange(const CharSourceRange &R,
const SourceManager &SM,
unsigned LineNo, FileID FID,
std::string &CaretLine,
@@ -112,8 +112,10 @@ void TextDiagnosticPrinter::HighlightRange(const SourceRange &R,
if (EndColNo) {
--EndColNo; // Zero base the col #.
- // Add in the length of the token, so that we cover multi-char tokens.
- EndColNo += Lexer::MeasureTokenLength(End, SM, *LangOpts);
+ // Add in the length of the token, so that we cover multi-char tokens if
+ // this is a token range.
+ if (R.isTokenRange())
+ EndColNo += Lexer::MeasureTokenLength(End, SM, *LangOpts);
} else {
EndColNo = CaretLine.size();
}
@@ -281,7 +283,7 @@ static void SelectInterestingSourceRegion(std::string &SourceLine,
}
void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
- SourceRange *Ranges,
+ CharSourceRange *Ranges,
unsigned NumRanges,
const SourceManager &SM,
const FixItHint *Hints,
@@ -312,10 +314,12 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
// Map the ranges.
for (unsigned i = 0; i != NumRanges; ++i) {
- SourceLocation S = Ranges[i].getBegin(), E = Ranges[i].getEnd();
- if (S.isMacroID()) S = SM.getImmediateSpellingLoc(S);
- if (E.isMacroID()) E = SM.getImmediateSpellingLoc(E);
- Ranges[i] = SourceRange(S, E);
+ CharSourceRange &R = Ranges[i];
+ SourceLocation S = R.getBegin(), E = R.getEnd();
+ if (S.isMacroID())
+ R.setBegin(SM.getImmediateSpellingLoc(S));
+ if (E.isMacroID())
+ R.setEnd(SM.getImmediateSpellingLoc(E));
}
if (!Suppressed) {
@@ -777,7 +781,9 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
continue;
// Add in the length of the token, so that we cover multi-char tokens.
- unsigned TokSize = Lexer::MeasureTokenLength(E, SM, *LangOpts);
+ unsigned TokSize = 0;
+ if (Info.getRange(i).isTokenRange())
+ TokSize = Lexer::MeasureTokenLength(E, SM, *LangOpts);
OS << '{' << SM.getLineNumber(BInfo.first, BInfo.second) << ':'
<< SM.getColumnNumber(BInfo.first, BInfo.second) << '-'
@@ -904,15 +910,15 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
LastCaretDiagnosticWasNote = (Level == Diagnostic::Note);
// Get the ranges into a local array we can hack on.
- SourceRange Ranges[20];
+ CharSourceRange Ranges[20];
unsigned NumRanges = Info.getNumRanges();
assert(NumRanges < 20 && "Out of space");
for (unsigned i = 0; i != NumRanges; ++i)
Ranges[i] = Info.getRange(i);
unsigned NumHints = Info.getNumFixItHints();
- for (unsigned idx = 0; idx < NumHints; ++idx) {
- const FixItHint &Hint = Info.getFixItHint(idx);
+ for (unsigned i = 0; i != NumHints; ++i) {
+ const FixItHint &Hint = Info.getFixItHint(i);
if (Hint.RemoveRange.isValid()) {
assert(NumRanges < 20 && "Out of space");
Ranges[NumRanges++] = Hint.RemoveRange;
diff --git a/clang/lib/Rewrite/Rewriter.cpp b/clang/lib/Rewrite/Rewriter.cpp
index 376678a5d74..8b0bf91a959 100644
--- a/clang/lib/Rewrite/Rewriter.cpp
+++ b/clang/lib/Rewrite/Rewriter.cpp
@@ -72,7 +72,7 @@ void RewriteBuffer::ReplaceText(unsigned OrigOffset, unsigned OrigLength,
/// getRangeSize - Return the size in bytes of the specified range if they
/// are in the same file. If not, this returns -1.
-int Rewriter::getRangeSize(SourceRange Range) const {
+int Rewriter::getRangeSize(const CharSourceRange &Range) const {
if (!isRewritable(Range.getBegin()) ||
!isRewritable(Range.getEnd())) return -1;
@@ -97,12 +97,18 @@ int Rewriter::getRangeSize(SourceRange Range) const {
// Adjust the end offset to the end of the last token, instead of being the
- // start of the last token.
- EndOff += Lexer::MeasureTokenLength(Range.getEnd(), *SourceMgr, *LangOpts);
+ // start of the last token if this is a token range.
+ if (Range.isTokenRange())
+ EndOff += Lexer::MeasureTokenLength(Range.getEnd(), *SourceMgr, *LangOpts);
return EndOff-StartOff;
}
+int Rewriter::getRangeSize(SourceRange Range) const {
+ return getRangeSize(CharSourceRange::getTokenRange(Range));
+}
+
+
/// getRewrittenText - Return the rewritten form of the text in the specified
/// range. If the start or end of the range was unrewritable or if they are
/// in different buffers, this returns an empty string.
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 6410d3715f6..e19cd4214f4 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -177,12 +177,12 @@ static RangeComparisonResult LocationCompare(SourceManager &SM,
/// does the appropriate translation.
CXSourceRange cxloc::translateSourceRange(const SourceManager &SM,
const LangOptions &LangOpts,
- SourceRange R) {
+ const CharSourceRange &R) {
// We want the last character in this location, so we will adjust the
// location accordingly.
// FIXME: How do do this with a macro instantiation location?
SourceLocation EndLoc = R.getEnd();
- if (!EndLoc.isInvalid() && EndLoc.isFileID()) {
+ if (R.isTokenRange() && !EndLoc.isInvalid() && EndLoc.isFileID()) {
unsigned Length = Lexer::MeasureTokenLength(EndLoc, SM, LangOpts);
EndLoc = EndLoc.getFileLocWithOffset(Length);
}
diff --git a/clang/tools/libclang/CXSourceLocation.h b/clang/tools/libclang/CXSourceLocation.h
index 66566c12689..235f78c5a1b 100644
--- a/clang/tools/libclang/CXSourceLocation.h
+++ b/clang/tools/libclang/CXSourceLocation.h
@@ -50,14 +50,14 @@ static inline CXSourceLocation translateSourceLocation(ASTContext &Context,
/// does the appropriate translation.
CXSourceRange translateSourceRange(const SourceManager &SM,
const LangOptions &LangOpts,
- SourceRange R);
+ const CharSourceRange &R);
/// \brief Translate a Clang source range into a CIndex source range.
static inline CXSourceRange translateSourceRange(ASTContext &Context,
SourceRange R) {
return translateSourceRange(Context.getSourceManager(),
Context.getLangOptions(),
- R);
+ CharSourceRange::getTokenRange(R));
}
static inline SourceLocation translateSourceLocation(CXSourceLocation L) {
OpenPOWER on IntegriCloud