mirror of https://github.com/microsoft/clang.git
PR37189 Fix incorrect end source location and spelling for a split '>>' token.
When a '>>' token is split into two '>' tokens (in C++11 onwards), or (as an extension) when we do the same for other tokens starting with a '>', we can't just use a location pointing to the first '>' as the location of the split token, because that would result in our miscomputing the length and spelling for the token. As a consequence, for example, a refactoring replacing 'A<X>' with something else would sometimes replace one character too many, and similarly diagnostics highlighting a template-id source range would highlight one character too many. Fix this by creating an expansion range covering the first character of the '>>' token, whose spelling is '>'. For this to work, we generalize the expansion range of a macro FileID to be either a token range (the common case) or a character range (used in this new case). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@331155 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9ab08c3357
commit
ef91bd38cd
|
@ -265,6 +265,7 @@ public:
|
||||||
|
|
||||||
void setBegin(SourceLocation b) { Range.setBegin(b); }
|
void setBegin(SourceLocation b) { Range.setBegin(b); }
|
||||||
void setEnd(SourceLocation e) { Range.setEnd(e); }
|
void setEnd(SourceLocation e) { Range.setEnd(e); }
|
||||||
|
void setTokenRange(bool TR) { IsTokenRange = TR; }
|
||||||
|
|
||||||
bool isValid() const { return Range.isValid(); }
|
bool isValid() const { return Range.isValid(); }
|
||||||
bool isInvalid() const { return !isValid(); }
|
bool isInvalid() const { return !isValid(); }
|
||||||
|
@ -359,7 +360,6 @@ public:
|
||||||
FullSourceLoc getExpansionLoc() const;
|
FullSourceLoc getExpansionLoc() const;
|
||||||
FullSourceLoc getSpellingLoc() const;
|
FullSourceLoc getSpellingLoc() const;
|
||||||
FullSourceLoc getFileLoc() const;
|
FullSourceLoc getFileLoc() const;
|
||||||
std::pair<FullSourceLoc, FullSourceLoc> getImmediateExpansionRange() const;
|
|
||||||
PresumedLoc getPresumedLoc(bool UseLineDirectives = true) const;
|
PresumedLoc getPresumedLoc(bool UseLineDirectives = true) const;
|
||||||
bool isMacroArgExpansion(FullSourceLoc *StartLoc = nullptr) const;
|
bool isMacroArgExpansion(FullSourceLoc *StartLoc = nullptr) const;
|
||||||
FullSourceLoc getImmediateMacroCallerLoc() const;
|
FullSourceLoc getImmediateMacroCallerLoc() const;
|
||||||
|
@ -377,8 +377,6 @@ public:
|
||||||
unsigned getLineNumber(bool *Invalid = nullptr) const;
|
unsigned getLineNumber(bool *Invalid = nullptr) const;
|
||||||
unsigned getColumnNumber(bool *Invalid = nullptr) const;
|
unsigned getColumnNumber(bool *Invalid = nullptr) const;
|
||||||
|
|
||||||
std::pair<FullSourceLoc, FullSourceLoc> getExpansionRange() const;
|
|
||||||
|
|
||||||
const FileEntry *getFileEntry() const;
|
const FileEntry *getFileEntry() const;
|
||||||
|
|
||||||
/// \brief Return a StringRef to the source buffer data for the
|
/// \brief Return a StringRef to the source buffer data for the
|
||||||
|
|
|
@ -317,9 +317,13 @@ namespace SrcMgr {
|
||||||
/// invalid location.
|
/// invalid location.
|
||||||
unsigned ExpansionLocStart, ExpansionLocEnd;
|
unsigned ExpansionLocStart, ExpansionLocEnd;
|
||||||
|
|
||||||
|
/// Whether the expansion range is a token range.
|
||||||
|
bool ExpansionIsTokenRange;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SourceLocation getSpellingLoc() const {
|
SourceLocation getSpellingLoc() const {
|
||||||
return SourceLocation::getFromRawEncoding(SpellingLoc);
|
SourceLocation SpellLoc = SourceLocation::getFromRawEncoding(SpellingLoc);
|
||||||
|
return SpellLoc.isInvalid() ? getExpansionLocStart() : SpellLoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceLocation getExpansionLocStart() const {
|
SourceLocation getExpansionLocStart() const {
|
||||||
|
@ -332,8 +336,14 @@ namespace SrcMgr {
|
||||||
return EndLoc.isInvalid() ? getExpansionLocStart() : EndLoc;
|
return EndLoc.isInvalid() ? getExpansionLocStart() : EndLoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<SourceLocation,SourceLocation> getExpansionLocRange() const {
|
bool isExpansionTokenRange() const {
|
||||||
return std::make_pair(getExpansionLocStart(), getExpansionLocEnd());
|
return ExpansionIsTokenRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
CharSourceRange getExpansionLocRange() const {
|
||||||
|
return CharSourceRange(
|
||||||
|
SourceRange(getExpansionLocStart(), getExpansionLocEnd()),
|
||||||
|
isExpansionTokenRange());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isMacroArgExpansion() const {
|
bool isMacroArgExpansion() const {
|
||||||
|
@ -359,11 +369,13 @@ namespace SrcMgr {
|
||||||
/// the characters from the token come from). All three can refer to
|
/// the characters from the token come from). All three can refer to
|
||||||
/// normal File SLocs or expansion locations.
|
/// normal File SLocs or expansion locations.
|
||||||
static ExpansionInfo create(SourceLocation SpellingLoc,
|
static ExpansionInfo create(SourceLocation SpellingLoc,
|
||||||
SourceLocation Start, SourceLocation End) {
|
SourceLocation Start, SourceLocation End,
|
||||||
|
bool ExpansionIsTokenRange = true) {
|
||||||
ExpansionInfo X;
|
ExpansionInfo X;
|
||||||
X.SpellingLoc = SpellingLoc.getRawEncoding();
|
X.SpellingLoc = SpellingLoc.getRawEncoding();
|
||||||
X.ExpansionLocStart = Start.getRawEncoding();
|
X.ExpansionLocStart = Start.getRawEncoding();
|
||||||
X.ExpansionLocEnd = End.getRawEncoding();
|
X.ExpansionLocEnd = End.getRawEncoding();
|
||||||
|
X.ExpansionIsTokenRange = ExpansionIsTokenRange;
|
||||||
return X;
|
return X;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,6 +405,17 @@ namespace SrcMgr {
|
||||||
// than a normal one.
|
// than a normal one.
|
||||||
return create(SpellingLoc, ExpansionLoc, SourceLocation());
|
return create(SpellingLoc, ExpansionLoc, SourceLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Return a special ExpansionInfo representing a token that ends
|
||||||
|
/// prematurely. This is used to model a '>>' token that has been split
|
||||||
|
/// into '>' tokens and similar cases. Unlike for the other forms of
|
||||||
|
/// expansion, the expansion range in this case is a character range, not
|
||||||
|
/// a token range.
|
||||||
|
static ExpansionInfo createForTokenSplit(SourceLocation SpellingLoc,
|
||||||
|
SourceLocation Start,
|
||||||
|
SourceLocation End) {
|
||||||
|
return create(SpellingLoc, Start, End, false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief This is a discriminated union of FileInfo and ExpansionInfo.
|
/// \brief This is a discriminated union of FileInfo and ExpansionInfo.
|
||||||
|
@ -851,9 +874,16 @@ public:
|
||||||
SourceLocation ExpansionLocStart,
|
SourceLocation ExpansionLocStart,
|
||||||
SourceLocation ExpansionLocEnd,
|
SourceLocation ExpansionLocEnd,
|
||||||
unsigned TokLength,
|
unsigned TokLength,
|
||||||
|
bool ExpansionIsTokenRange = true,
|
||||||
int LoadedID = 0,
|
int LoadedID = 0,
|
||||||
unsigned LoadedOffset = 0);
|
unsigned LoadedOffset = 0);
|
||||||
|
|
||||||
|
/// \brief Return a new SourceLocation that encodes that the token starting
|
||||||
|
/// at \p TokenStart ends prematurely at \p TokenEnd.
|
||||||
|
SourceLocation createTokenSplitLoc(SourceLocation SpellingLoc,
|
||||||
|
SourceLocation TokenStart,
|
||||||
|
SourceLocation TokenEnd);
|
||||||
|
|
||||||
/// \brief Retrieve the memory buffer associated with the given file.
|
/// \brief Retrieve the memory buffer associated with the given file.
|
||||||
///
|
///
|
||||||
/// \param Invalid If non-NULL, will be set \c true if an error
|
/// \param Invalid If non-NULL, will be set \c true if an error
|
||||||
|
@ -1102,19 +1132,28 @@ public:
|
||||||
/// expansion location.
|
/// expansion location.
|
||||||
///
|
///
|
||||||
/// \pre \p Loc is required to be an expansion location.
|
/// \pre \p Loc is required to be an expansion location.
|
||||||
std::pair<SourceLocation,SourceLocation>
|
CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const;
|
||||||
getImmediateExpansionRange(SourceLocation Loc) const;
|
|
||||||
|
|
||||||
/// \brief Given a SourceLocation object, return the range of
|
/// \brief Given a SourceLocation object, return the range of
|
||||||
/// tokens covered by the expansion in the ultimate file.
|
/// tokens covered by the expansion in the ultimate file.
|
||||||
std::pair<SourceLocation,SourceLocation>
|
CharSourceRange getExpansionRange(SourceLocation Loc) const;
|
||||||
getExpansionRange(SourceLocation Loc) const;
|
|
||||||
|
|
||||||
/// \brief Given a SourceRange object, return the range of
|
/// \brief Given a SourceRange object, return the range of
|
||||||
/// tokens covered by the expansion in the ultimate file.
|
/// tokens or characters covered by the expansion in the ultimate file.
|
||||||
SourceRange getExpansionRange(SourceRange Range) const {
|
CharSourceRange getExpansionRange(SourceRange Range) const {
|
||||||
return SourceRange(getExpansionRange(Range.getBegin()).first,
|
SourceLocation Begin = getExpansionRange(Range.getBegin()).getBegin();
|
||||||
getExpansionRange(Range.getEnd()).second);
|
CharSourceRange End = getExpansionRange(Range.getEnd());
|
||||||
|
return CharSourceRange(SourceRange(Begin, End.getEnd()),
|
||||||
|
End.isTokenRange());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Given a CharSourceRange object, return the range of
|
||||||
|
/// tokens or characters covered by the expansion in the ultimate file.
|
||||||
|
CharSourceRange getExpansionRange(CharSourceRange Range) const {
|
||||||
|
CharSourceRange Expansion = getExpansionRange(Range.getAsRange());
|
||||||
|
if (Expansion.getEnd() == Range.getEnd())
|
||||||
|
Expansion.setTokenRange(Range.isTokenRange());
|
||||||
|
return Expansion;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Given a SourceLocation object, return the spelling
|
/// \brief Given a SourceLocation object, return the spelling
|
||||||
|
@ -1643,7 +1682,7 @@ public:
|
||||||
|
|
||||||
// Otherwise, the caller of the macro is located where this macro is
|
// Otherwise, the caller of the macro is located where this macro is
|
||||||
// expanded (while the spelling is part of the macro definition).
|
// expanded (while the spelling is part of the macro definition).
|
||||||
return getImmediateExpansionRange(Loc).first;
|
return getImmediateExpansionRange(Loc).getBegin();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \return Location of the top-level macro caller.
|
/// \return Location of the top-level macro caller.
|
||||||
|
|
|
@ -336,13 +336,23 @@ public:
|
||||||
const SourceManager &SM,
|
const SourceManager &SM,
|
||||||
const LangOptions &LangOpts);
|
const LangOptions &LangOpts);
|
||||||
|
|
||||||
|
/// Get the physical length (including trigraphs and escaped newlines) of the
|
||||||
|
/// first \p Characters characters of the token starting at TokStart.
|
||||||
|
static unsigned getTokenPrefixLength(SourceLocation TokStart,
|
||||||
|
unsigned Characters,
|
||||||
|
const SourceManager &SM,
|
||||||
|
const LangOptions &LangOpts);
|
||||||
|
|
||||||
/// AdvanceToTokenCharacter - If the current SourceLocation specifies a
|
/// AdvanceToTokenCharacter - If the current SourceLocation specifies a
|
||||||
/// location at the start of a token, return a new location that specifies a
|
/// location at the start of a token, return a new location that specifies a
|
||||||
/// character within the token. This handles trigraphs and escaped newlines.
|
/// character within the token. This handles trigraphs and escaped newlines.
|
||||||
static SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart,
|
static SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart,
|
||||||
unsigned Character,
|
unsigned Characters,
|
||||||
const SourceManager &SM,
|
const SourceManager &SM,
|
||||||
const LangOptions &LangOpts);
|
const LangOptions &LangOpts) {
|
||||||
|
return TokStart.getLocWithOffset(
|
||||||
|
getTokenPrefixLength(TokStart, Characters, SM, LangOpts));
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Computes the source location just past the end of the
|
/// \brief Computes the source location just past the end of the
|
||||||
/// token at this source location.
|
/// token at this source location.
|
||||||
|
|
|
@ -1616,6 +1616,11 @@ public:
|
||||||
SourceLocation ExpansionLocStart = SourceLocation(),
|
SourceLocation ExpansionLocStart = SourceLocation(),
|
||||||
SourceLocation ExpansionLocEnd = SourceLocation());
|
SourceLocation ExpansionLocEnd = SourceLocation());
|
||||||
|
|
||||||
|
/// Split the first Length characters out of the token starting at TokLoc
|
||||||
|
/// and return a location pointing to the split token. Re-lexing from the
|
||||||
|
/// split token will return the split token rather than the original.
|
||||||
|
SourceLocation SplitToken(SourceLocation TokLoc, unsigned Length);
|
||||||
|
|
||||||
/// \brief Computes the source location just past the end of the
|
/// \brief Computes the source location just past the end of the
|
||||||
/// token at this source location.
|
/// token at this source location.
|
||||||
///
|
///
|
||||||
|
|
|
@ -31,7 +31,8 @@ namespace html {
|
||||||
/// start/end tags are placed at the start/end of each line if the range is
|
/// start/end tags are placed at the start/end of each line if the range is
|
||||||
/// multiline.
|
/// multiline.
|
||||||
void HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E,
|
void HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E,
|
||||||
const char *StartTag, const char *EndTag);
|
const char *StartTag, const char *EndTag,
|
||||||
|
bool IsTokenRange = true);
|
||||||
|
|
||||||
/// HighlightRange - Highlight a range in the source code with the specified
|
/// HighlightRange - Highlight a range in the source code with the specified
|
||||||
/// start/end tags. The Start/end of the range must be in the same file.
|
/// start/end tags. The Start/end of the range must be in the same file.
|
||||||
|
|
|
@ -107,8 +107,7 @@ void arcmt::writeARCDiagsToPlist(const std::string &outPath,
|
||||||
o << " <key>ranges</key>\n";
|
o << " <key>ranges</key>\n";
|
||||||
o << " <array>\n";
|
o << " <array>\n";
|
||||||
for (auto &R : D.getRanges()) {
|
for (auto &R : D.getRanges()) {
|
||||||
CharSourceRange ExpansionRange(SM.getExpansionRange(R.getAsRange()),
|
CharSourceRange ExpansionRange = SM.getExpansionRange(R);
|
||||||
R.isTokenRange());
|
|
||||||
EmitRange(o, SM, Lexer::getAsCharRange(ExpansionRange, SM, LangOpts),
|
EmitRange(o, SM, Lexer::getAsCharRange(ExpansionRange, SM, LangOpts),
|
||||||
FM, 4);
|
FM, 4);
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ public:
|
||||||
ASTContext &Ctx = MigrateCtx.Pass.Ctx;
|
ASTContext &Ctx = MigrateCtx.Pass.Ctx;
|
||||||
SourceManager &SM = Ctx.getSourceManager();
|
SourceManager &SM = Ctx.getSourceManager();
|
||||||
if (Loc.isMacroID())
|
if (Loc.isMacroID())
|
||||||
Loc = SM.getImmediateExpansionRange(Loc).first;
|
Loc = SM.getImmediateExpansionRange(Loc).getBegin();
|
||||||
SmallString<32> Buf;
|
SmallString<32> Buf;
|
||||||
bool Invalid = false;
|
bool Invalid = false;
|
||||||
StringRef Spell = Lexer::getSpelling(
|
StringRef Spell = Lexer::getSpelling(
|
||||||
|
@ -287,7 +287,8 @@ static void checkAllAtProps(MigrationContext &MigrateCtx,
|
||||||
SourceLocation Loc = ATLs[i].first.getAttrNameLoc();
|
SourceLocation Loc = ATLs[i].first.getAttrNameLoc();
|
||||||
if (Loc.isMacroID())
|
if (Loc.isMacroID())
|
||||||
Loc = MigrateCtx.Pass.Ctx.getSourceManager()
|
Loc = MigrateCtx.Pass.Ctx.getSourceManager()
|
||||||
.getImmediateExpansionRange(Loc).first;
|
.getImmediateExpansionRange(Loc)
|
||||||
|
.getBegin();
|
||||||
TA.remove(Loc);
|
TA.remove(Loc);
|
||||||
TA.clearDiagnostic(diag::err_objc_property_attr_mutually_exclusive, AtLoc);
|
TA.clearDiagnostic(diag::err_objc_property_attr_mutually_exclusive, AtLoc);
|
||||||
TA.clearDiagnostic(diag::err_arc_inconsistent_property_ownership,
|
TA.clearDiagnostic(diag::err_arc_inconsistent_property_ownership,
|
||||||
|
|
|
@ -283,13 +283,12 @@ private:
|
||||||
SourceManager &SM = Pass.Ctx.getSourceManager();
|
SourceManager &SM = Pass.Ctx.getSourceManager();
|
||||||
SourceLocation Loc = E->getExprLoc();
|
SourceLocation Loc = E->getExprLoc();
|
||||||
assert(Loc.isMacroID());
|
assert(Loc.isMacroID());
|
||||||
SourceLocation MacroBegin, MacroEnd;
|
CharSourceRange MacroRange = SM.getImmediateExpansionRange(Loc);
|
||||||
std::tie(MacroBegin, MacroEnd) = SM.getImmediateExpansionRange(Loc);
|
|
||||||
SourceRange SubRange = E->getSubExpr()->IgnoreParenImpCasts()->getSourceRange();
|
SourceRange SubRange = E->getSubExpr()->IgnoreParenImpCasts()->getSourceRange();
|
||||||
SourceLocation InnerBegin = SM.getImmediateMacroCallerLoc(SubRange.getBegin());
|
SourceLocation InnerBegin = SM.getImmediateMacroCallerLoc(SubRange.getBegin());
|
||||||
SourceLocation InnerEnd = SM.getImmediateMacroCallerLoc(SubRange.getEnd());
|
SourceLocation InnerEnd = SM.getImmediateMacroCallerLoc(SubRange.getEnd());
|
||||||
|
|
||||||
Outer = SourceRange(MacroBegin, MacroEnd);
|
Outer = MacroRange.getAsRange();
|
||||||
Inner = SourceRange(InnerBegin, InnerEnd);
|
Inner = SourceRange(InnerBegin, InnerEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -590,8 +590,12 @@ StringRef TransformActionsImpl::getUniqueText(StringRef text) {
|
||||||
SourceLocation TransformActionsImpl::getLocForEndOfToken(SourceLocation loc,
|
SourceLocation TransformActionsImpl::getLocForEndOfToken(SourceLocation loc,
|
||||||
SourceManager &SM,
|
SourceManager &SM,
|
||||||
Preprocessor &PP) {
|
Preprocessor &PP) {
|
||||||
if (loc.isMacroID())
|
if (loc.isMacroID()) {
|
||||||
loc = SM.getExpansionRange(loc).second;
|
CharSourceRange Exp = SM.getExpansionRange(loc);
|
||||||
|
if (Exp.isCharRange())
|
||||||
|
return Exp.getEnd();
|
||||||
|
loc = Exp.getEnd();
|
||||||
|
}
|
||||||
return PP.getLocForEndOfToken(loc);
|
return PP.getLocForEndOfToken(loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,15 +103,6 @@ FullSourceLoc FullSourceLoc::getFileLoc() const {
|
||||||
return FullSourceLoc(SrcMgr->getFileLoc(*this), *SrcMgr);
|
return FullSourceLoc(SrcMgr->getFileLoc(*this), *SrcMgr);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<FullSourceLoc, FullSourceLoc>
|
|
||||||
FullSourceLoc::getImmediateExpansionRange() const {
|
|
||||||
assert(isValid());
|
|
||||||
std::pair<SourceLocation, SourceLocation> Range =
|
|
||||||
SrcMgr->getImmediateExpansionRange(*this);
|
|
||||||
return std::make_pair(FullSourceLoc(Range.first, *SrcMgr),
|
|
||||||
FullSourceLoc(Range.second, *SrcMgr));
|
|
||||||
}
|
|
||||||
|
|
||||||
PresumedLoc FullSourceLoc::getPresumedLoc(bool UseLineDirectives) const {
|
PresumedLoc FullSourceLoc::getPresumedLoc(bool UseLineDirectives) const {
|
||||||
if (!isValid())
|
if (!isValid())
|
||||||
return PresumedLoc();
|
return PresumedLoc();
|
||||||
|
@ -154,15 +145,6 @@ unsigned FullSourceLoc::getColumnNumber(bool *Invalid) const {
|
||||||
return SrcMgr->getColumnNumber(getFileID(), getFileOffset(), Invalid);
|
return SrcMgr->getColumnNumber(getFileID(), getFileOffset(), Invalid);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<FullSourceLoc, FullSourceLoc>
|
|
||||||
FullSourceLoc::getExpansionRange() const {
|
|
||||||
assert(isValid());
|
|
||||||
std::pair<SourceLocation, SourceLocation> Range =
|
|
||||||
SrcMgr->getExpansionRange(*this);
|
|
||||||
return std::make_pair(FullSourceLoc(Range.first, *SrcMgr),
|
|
||||||
FullSourceLoc(Range.second, *SrcMgr));
|
|
||||||
}
|
|
||||||
|
|
||||||
const FileEntry *FullSourceLoc::getFileEntry() const {
|
const FileEntry *FullSourceLoc::getFileEntry() const {
|
||||||
assert(isValid());
|
assert(isValid());
|
||||||
return SrcMgr->getFileEntryForID(getFileID());
|
return SrcMgr->getFileEntryForID(getFileID());
|
||||||
|
|
|
@ -579,13 +579,24 @@ SourceManager::createExpansionLoc(SourceLocation SpellingLoc,
|
||||||
SourceLocation ExpansionLocStart,
|
SourceLocation ExpansionLocStart,
|
||||||
SourceLocation ExpansionLocEnd,
|
SourceLocation ExpansionLocEnd,
|
||||||
unsigned TokLength,
|
unsigned TokLength,
|
||||||
|
bool ExpansionIsTokenRange,
|
||||||
int LoadedID,
|
int LoadedID,
|
||||||
unsigned LoadedOffset) {
|
unsigned LoadedOffset) {
|
||||||
ExpansionInfo Info = ExpansionInfo::create(SpellingLoc, ExpansionLocStart,
|
ExpansionInfo Info = ExpansionInfo::create(
|
||||||
ExpansionLocEnd);
|
SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
|
||||||
return createExpansionLocImpl(Info, TokLength, LoadedID, LoadedOffset);
|
return createExpansionLocImpl(Info, TokLength, LoadedID, LoadedOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SourceLocation SourceManager::createTokenSplitLoc(SourceLocation Spelling,
|
||||||
|
SourceLocation TokenStart,
|
||||||
|
SourceLocation TokenEnd) {
|
||||||
|
assert(getFileID(TokenStart) == getFileID(TokenEnd) &&
|
||||||
|
"token spans multiple files");
|
||||||
|
return createExpansionLocImpl(
|
||||||
|
ExpansionInfo::createForTokenSplit(Spelling, TokenStart, TokenEnd),
|
||||||
|
TokenEnd.getOffset() - TokenStart.getOffset());
|
||||||
|
}
|
||||||
|
|
||||||
SourceLocation
|
SourceLocation
|
||||||
SourceManager::createExpansionLocImpl(const ExpansionInfo &Info,
|
SourceManager::createExpansionLocImpl(const ExpansionInfo &Info,
|
||||||
unsigned TokLength,
|
unsigned TokLength,
|
||||||
|
@ -895,7 +906,7 @@ SourceLocation SourceManager::getFileLocSlowCase(SourceLocation Loc) const {
|
||||||
if (isMacroArgExpansion(Loc))
|
if (isMacroArgExpansion(Loc))
|
||||||
Loc = getImmediateSpellingLoc(Loc);
|
Loc = getImmediateSpellingLoc(Loc);
|
||||||
else
|
else
|
||||||
Loc = getImmediateExpansionRange(Loc).first;
|
Loc = getImmediateExpansionRange(Loc).getBegin();
|
||||||
} while (!Loc.isFileID());
|
} while (!Loc.isFileID());
|
||||||
return Loc;
|
return Loc;
|
||||||
}
|
}
|
||||||
|
@ -950,7 +961,7 @@ SourceLocation SourceManager::getImmediateSpellingLoc(SourceLocation Loc) const{
|
||||||
|
|
||||||
/// getImmediateExpansionRange - Loc is required to be an expansion location.
|
/// getImmediateExpansionRange - Loc is required to be an expansion location.
|
||||||
/// Return the start/end of the expansion information.
|
/// Return the start/end of the expansion information.
|
||||||
std::pair<SourceLocation,SourceLocation>
|
CharSourceRange
|
||||||
SourceManager::getImmediateExpansionRange(SourceLocation Loc) const {
|
SourceManager::getImmediateExpansionRange(SourceLocation Loc) const {
|
||||||
assert(Loc.isMacroID() && "Not a macro expansion loc!");
|
assert(Loc.isMacroID() && "Not a macro expansion loc!");
|
||||||
const ExpansionInfo &Expansion = getSLocEntry(getFileID(Loc)).getExpansion();
|
const ExpansionInfo &Expansion = getSLocEntry(getFileID(Loc)).getExpansion();
|
||||||
|
@ -965,19 +976,21 @@ SourceLocation SourceManager::getTopMacroCallerLoc(SourceLocation Loc) const {
|
||||||
|
|
||||||
/// getExpansionRange - Given a SourceLocation object, return the range of
|
/// getExpansionRange - Given a SourceLocation object, return the range of
|
||||||
/// tokens covered by the expansion in the ultimate file.
|
/// tokens covered by the expansion in the ultimate file.
|
||||||
std::pair<SourceLocation,SourceLocation>
|
CharSourceRange SourceManager::getExpansionRange(SourceLocation Loc) const {
|
||||||
SourceManager::getExpansionRange(SourceLocation Loc) const {
|
if (Loc.isFileID())
|
||||||
if (Loc.isFileID()) return std::make_pair(Loc, Loc);
|
return CharSourceRange(SourceRange(Loc, Loc), true);
|
||||||
|
|
||||||
std::pair<SourceLocation,SourceLocation> Res =
|
CharSourceRange Res = getImmediateExpansionRange(Loc);
|
||||||
getImmediateExpansionRange(Loc);
|
|
||||||
|
|
||||||
// Fully resolve the start and end locations to their ultimate expansion
|
// Fully resolve the start and end locations to their ultimate expansion
|
||||||
// points.
|
// points.
|
||||||
while (!Res.first.isFileID())
|
while (!Res.getBegin().isFileID())
|
||||||
Res.first = getImmediateExpansionRange(Res.first).first;
|
Res.setBegin(getImmediateExpansionRange(Res.getBegin()).getBegin());
|
||||||
while (!Res.second.isFileID())
|
while (!Res.getEnd().isFileID()) {
|
||||||
Res.second = getImmediateExpansionRange(Res.second).second;
|
CharSourceRange EndRange = getImmediateExpansionRange(Res.getEnd());
|
||||||
|
Res.setEnd(EndRange.getEnd());
|
||||||
|
Res.setTokenRange(EndRange.isTokenRange());
|
||||||
|
}
|
||||||
return Res;
|
return Res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -183,7 +183,7 @@ public:
|
||||||
|
|
||||||
/// \brief Find out where the current file is included or macro is expanded.
|
/// \brief Find out where the current file is included or macro is expanded.
|
||||||
SourceLocation getIncludeOrExpansionLoc(SourceLocation Loc) {
|
SourceLocation getIncludeOrExpansionLoc(SourceLocation Loc) {
|
||||||
return Loc.isMacroID() ? SM.getImmediateExpansionRange(Loc).first
|
return Loc.isMacroID() ? SM.getImmediateExpansionRange(Loc).getBegin()
|
||||||
: SM.getIncludeLoc(SM.getFileID(Loc));
|
: SM.getIncludeLoc(SM.getFileID(Loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ public:
|
||||||
SourceLocation getStart(const Stmt *S) {
|
SourceLocation getStart(const Stmt *S) {
|
||||||
SourceLocation Loc = S->getLocStart();
|
SourceLocation Loc = S->getLocStart();
|
||||||
while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
|
while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
|
||||||
Loc = SM.getImmediateExpansionRange(Loc).first;
|
Loc = SM.getImmediateExpansionRange(Loc).getBegin();
|
||||||
return Loc;
|
return Loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ public:
|
||||||
SourceLocation getEnd(const Stmt *S) {
|
SourceLocation getEnd(const Stmt *S) {
|
||||||
SourceLocation Loc = S->getLocEnd();
|
SourceLocation Loc = S->getLocEnd();
|
||||||
while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
|
while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
|
||||||
Loc = SM.getImmediateExpansionRange(Loc).first;
|
Loc = SM.getImmediateExpansionRange(Loc).getBegin();
|
||||||
return getPreciseTokenLocEnd(Loc);
|
return getPreciseTokenLocEnd(Loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,12 +36,14 @@ void EditedSource::deconstructMacroArgLoc(SourceLocation Loc,
|
||||||
SourceLocation &ExpansionLoc,
|
SourceLocation &ExpansionLoc,
|
||||||
MacroArgUse &ArgUse) {
|
MacroArgUse &ArgUse) {
|
||||||
assert(SourceMgr.isMacroArgExpansion(Loc));
|
assert(SourceMgr.isMacroArgExpansion(Loc));
|
||||||
SourceLocation DefArgLoc = SourceMgr.getImmediateExpansionRange(Loc).first;
|
SourceLocation DefArgLoc =
|
||||||
|
SourceMgr.getImmediateExpansionRange(Loc).getBegin();
|
||||||
SourceLocation ImmediateExpansionLoc =
|
SourceLocation ImmediateExpansionLoc =
|
||||||
SourceMgr.getImmediateExpansionRange(DefArgLoc).first;
|
SourceMgr.getImmediateExpansionRange(DefArgLoc).getBegin();
|
||||||
ExpansionLoc = ImmediateExpansionLoc;
|
ExpansionLoc = ImmediateExpansionLoc;
|
||||||
while (SourceMgr.isMacroBodyExpansion(ExpansionLoc))
|
while (SourceMgr.isMacroBodyExpansion(ExpansionLoc))
|
||||||
ExpansionLoc = SourceMgr.getImmediateExpansionRange(ExpansionLoc).first;
|
ExpansionLoc =
|
||||||
|
SourceMgr.getImmediateExpansionRange(ExpansionLoc).getBegin();
|
||||||
SmallString<20> Buf;
|
SmallString<20> Buf;
|
||||||
StringRef ArgName = Lexer::getSpelling(SourceMgr.getSpellingLoc(DefArgLoc),
|
StringRef ArgName = Lexer::getSpelling(SourceMgr.getSpellingLoc(DefArgLoc),
|
||||||
Buf, SourceMgr, LangOpts);
|
Buf, SourceMgr, LangOpts);
|
||||||
|
|
|
@ -262,41 +262,54 @@ static SourceLocation
|
||||||
retrieveMacroLocation(SourceLocation Loc, FileID MacroFileID,
|
retrieveMacroLocation(SourceLocation Loc, FileID MacroFileID,
|
||||||
FileID CaretFileID,
|
FileID CaretFileID,
|
||||||
const SmallVectorImpl<FileID> &CommonArgExpansions,
|
const SmallVectorImpl<FileID> &CommonArgExpansions,
|
||||||
bool IsBegin, const SourceManager *SM) {
|
bool IsBegin, const SourceManager *SM,
|
||||||
|
bool &IsTokenRange) {
|
||||||
assert(SM->getFileID(Loc) == MacroFileID);
|
assert(SM->getFileID(Loc) == MacroFileID);
|
||||||
if (MacroFileID == CaretFileID)
|
if (MacroFileID == CaretFileID)
|
||||||
return Loc;
|
return Loc;
|
||||||
if (!Loc.isMacroID())
|
if (!Loc.isMacroID())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
SourceLocation MacroLocation, MacroArgLocation;
|
CharSourceRange MacroRange, MacroArgRange;
|
||||||
|
|
||||||
if (SM->isMacroArgExpansion(Loc)) {
|
if (SM->isMacroArgExpansion(Loc)) {
|
||||||
// Only look at the immediate spelling location of this macro argument if
|
// Only look at the immediate spelling location of this macro argument if
|
||||||
// the other location in the source range is also present in that expansion.
|
// the other location in the source range is also present in that expansion.
|
||||||
if (std::binary_search(CommonArgExpansions.begin(),
|
if (std::binary_search(CommonArgExpansions.begin(),
|
||||||
CommonArgExpansions.end(), MacroFileID))
|
CommonArgExpansions.end(), MacroFileID))
|
||||||
MacroLocation = SM->getImmediateSpellingLoc(Loc);
|
MacroRange =
|
||||||
MacroArgLocation = IsBegin ? SM->getImmediateExpansionRange(Loc).first
|
CharSourceRange(SM->getImmediateSpellingLoc(Loc), IsTokenRange);
|
||||||
: SM->getImmediateExpansionRange(Loc).second;
|
MacroArgRange = SM->getImmediateExpansionRange(Loc);
|
||||||
} else {
|
} else {
|
||||||
MacroLocation = IsBegin ? SM->getImmediateExpansionRange(Loc).first
|
MacroRange = SM->getImmediateExpansionRange(Loc);
|
||||||
: SM->getImmediateExpansionRange(Loc).second;
|
MacroArgRange =
|
||||||
MacroArgLocation = SM->getImmediateSpellingLoc(Loc);
|
CharSourceRange(SM->getImmediateSpellingLoc(Loc), IsTokenRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SourceLocation MacroLocation =
|
||||||
|
IsBegin ? MacroRange.getBegin() : MacroRange.getEnd();
|
||||||
if (MacroLocation.isValid()) {
|
if (MacroLocation.isValid()) {
|
||||||
MacroFileID = SM->getFileID(MacroLocation);
|
MacroFileID = SM->getFileID(MacroLocation);
|
||||||
|
bool TokenRange = IsBegin ? IsTokenRange : MacroRange.isTokenRange();
|
||||||
MacroLocation =
|
MacroLocation =
|
||||||
retrieveMacroLocation(MacroLocation, MacroFileID, CaretFileID,
|
retrieveMacroLocation(MacroLocation, MacroFileID, CaretFileID,
|
||||||
CommonArgExpansions, IsBegin, SM);
|
CommonArgExpansions, IsBegin, SM, TokenRange);
|
||||||
if (MacroLocation.isValid())
|
if (MacroLocation.isValid()) {
|
||||||
|
IsTokenRange = TokenRange;
|
||||||
return MacroLocation;
|
return MacroLocation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we moved the end of the range to an expansion location, we now have
|
||||||
|
// a range of the same kind as the expansion range.
|
||||||
|
if (!IsBegin)
|
||||||
|
IsTokenRange = MacroArgRange.isTokenRange();
|
||||||
|
|
||||||
|
SourceLocation MacroArgLocation =
|
||||||
|
IsBegin ? MacroArgRange.getBegin() : MacroArgRange.getEnd();
|
||||||
MacroFileID = SM->getFileID(MacroArgLocation);
|
MacroFileID = SM->getFileID(MacroArgLocation);
|
||||||
return retrieveMacroLocation(MacroArgLocation, MacroFileID, CaretFileID,
|
return retrieveMacroLocation(MacroArgLocation, MacroFileID, CaretFileID,
|
||||||
CommonArgExpansions, IsBegin, SM);
|
CommonArgExpansions, IsBegin, SM, IsTokenRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Walk up the chain of macro expansions and collect the FileIDs identifying the
|
/// Walk up the chain of macro expansions and collect the FileIDs identifying the
|
||||||
|
@ -310,7 +323,7 @@ static void getMacroArgExpansionFileIDs(SourceLocation Loc,
|
||||||
Loc = SM->getImmediateSpellingLoc(Loc);
|
Loc = SM->getImmediateSpellingLoc(Loc);
|
||||||
} else {
|
} else {
|
||||||
auto ExpRange = SM->getImmediateExpansionRange(Loc);
|
auto ExpRange = SM->getImmediateExpansionRange(Loc);
|
||||||
Loc = IsBegin ? ExpRange.first : ExpRange.second;
|
Loc = IsBegin ? ExpRange.getBegin() : ExpRange.getEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -364,14 +377,16 @@ mapDiagnosticRanges(FullSourceLoc CaretLoc, ArrayRef<CharSourceRange> Ranges,
|
||||||
llvm::SmallDenseMap<FileID, SourceLocation> BeginLocsMap;
|
llvm::SmallDenseMap<FileID, SourceLocation> BeginLocsMap;
|
||||||
while (Begin.isMacroID() && BeginFileID != EndFileID) {
|
while (Begin.isMacroID() && BeginFileID != EndFileID) {
|
||||||
BeginLocsMap[BeginFileID] = Begin;
|
BeginLocsMap[BeginFileID] = Begin;
|
||||||
Begin = SM->getImmediateExpansionRange(Begin).first;
|
Begin = SM->getImmediateExpansionRange(Begin).getBegin();
|
||||||
BeginFileID = SM->getFileID(Begin);
|
BeginFileID = SM->getFileID(Begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then, crawl the expansion chain for the end of the range.
|
// Then, crawl the expansion chain for the end of the range.
|
||||||
if (BeginFileID != EndFileID) {
|
if (BeginFileID != EndFileID) {
|
||||||
while (End.isMacroID() && !BeginLocsMap.count(EndFileID)) {
|
while (End.isMacroID() && !BeginLocsMap.count(EndFileID)) {
|
||||||
End = SM->getImmediateExpansionRange(End).second;
|
auto Exp = SM->getImmediateExpansionRange(End);
|
||||||
|
IsTokenRange = Exp.isTokenRange();
|
||||||
|
End = Exp.getEnd();
|
||||||
EndFileID = SM->getFileID(End);
|
EndFileID = SM->getFileID(End);
|
||||||
}
|
}
|
||||||
if (End.isMacroID()) {
|
if (End.isMacroID()) {
|
||||||
|
@ -384,9 +399,11 @@ mapDiagnosticRanges(FullSourceLoc CaretLoc, ArrayRef<CharSourceRange> Ranges,
|
||||||
SmallVector<FileID, 4> CommonArgExpansions;
|
SmallVector<FileID, 4> CommonArgExpansions;
|
||||||
computeCommonMacroArgExpansionFileIDs(Begin, End, SM, CommonArgExpansions);
|
computeCommonMacroArgExpansionFileIDs(Begin, End, SM, CommonArgExpansions);
|
||||||
Begin = retrieveMacroLocation(Begin, BeginFileID, CaretLocFileID,
|
Begin = retrieveMacroLocation(Begin, BeginFileID, CaretLocFileID,
|
||||||
CommonArgExpansions, /*IsBegin=*/true, SM);
|
CommonArgExpansions, /*IsBegin=*/true, SM,
|
||||||
|
IsTokenRange);
|
||||||
End = retrieveMacroLocation(End, BeginFileID, CaretLocFileID,
|
End = retrieveMacroLocation(End, BeginFileID, CaretLocFileID,
|
||||||
CommonArgExpansions, /*IsBegin=*/false, SM);
|
CommonArgExpansions, /*IsBegin=*/false, SM,
|
||||||
|
IsTokenRange);
|
||||||
if (Begin.isInvalid() || End.isInvalid()) continue;
|
if (Begin.isInvalid() || End.isInvalid()) continue;
|
||||||
|
|
||||||
// Return the spelling location of the beginning and end of the range.
|
// Return the spelling location of the beginning and end of the range.
|
||||||
|
@ -511,29 +528,31 @@ void DiagnosticRenderer::emitMacroExpansions(FullSourceLoc Loc,
|
||||||
ArrayRef<CharSourceRange> Ranges,
|
ArrayRef<CharSourceRange> Ranges,
|
||||||
ArrayRef<FixItHint> Hints) {
|
ArrayRef<FixItHint> Hints) {
|
||||||
assert(Loc.isValid() && "must have a valid source location here");
|
assert(Loc.isValid() && "must have a valid source location here");
|
||||||
|
const SourceManager &SM = Loc.getManager();
|
||||||
|
SourceLocation L = Loc;
|
||||||
|
|
||||||
// Produce a stack of macro backtraces.
|
// Produce a stack of macro backtraces.
|
||||||
SmallVector<FullSourceLoc, 8> LocationStack;
|
SmallVector<SourceLocation, 8> LocationStack;
|
||||||
unsigned IgnoredEnd = 0;
|
unsigned IgnoredEnd = 0;
|
||||||
while (Loc.isMacroID()) {
|
while (L.isMacroID()) {
|
||||||
// If this is the expansion of a macro argument, point the caret at the
|
// If this is the expansion of a macro argument, point the caret at the
|
||||||
// use of the argument in the definition of the macro, not the expansion.
|
// use of the argument in the definition of the macro, not the expansion.
|
||||||
if (Loc.isMacroArgExpansion())
|
if (SM.isMacroArgExpansion(L))
|
||||||
LocationStack.push_back(Loc.getImmediateExpansionRange().first);
|
LocationStack.push_back(SM.getImmediateExpansionRange(L).getBegin());
|
||||||
else
|
else
|
||||||
LocationStack.push_back(Loc);
|
LocationStack.push_back(L);
|
||||||
|
|
||||||
if (checkRangesForMacroArgExpansion(Loc, Ranges))
|
if (checkRangesForMacroArgExpansion(FullSourceLoc(L, SM), Ranges))
|
||||||
IgnoredEnd = LocationStack.size();
|
IgnoredEnd = LocationStack.size();
|
||||||
|
|
||||||
Loc = Loc.getImmediateMacroCallerLoc();
|
L = SM.getImmediateMacroCallerLoc(L);
|
||||||
|
|
||||||
// Once the location no longer points into a macro, try stepping through
|
// Once the location no longer points into a macro, try stepping through
|
||||||
// the last found location. This sometimes produces additional useful
|
// the last found location. This sometimes produces additional useful
|
||||||
// backtraces.
|
// backtraces.
|
||||||
if (Loc.isFileID())
|
if (L.isFileID())
|
||||||
Loc = LocationStack.back().getImmediateMacroCallerLoc();
|
L = SM.getImmediateMacroCallerLoc(LocationStack.back());
|
||||||
assert(Loc.isValid() && "must have a valid source location here");
|
assert(L.isValid() && "must have a valid source location here");
|
||||||
}
|
}
|
||||||
|
|
||||||
LocationStack.erase(LocationStack.begin(),
|
LocationStack.erase(LocationStack.begin(),
|
||||||
|
@ -544,7 +563,7 @@ void DiagnosticRenderer::emitMacroExpansions(FullSourceLoc Loc,
|
||||||
if (MacroDepth <= MacroLimit || MacroLimit == 0) {
|
if (MacroDepth <= MacroLimit || MacroLimit == 0) {
|
||||||
for (auto I = LocationStack.rbegin(), E = LocationStack.rend();
|
for (auto I = LocationStack.rbegin(), E = LocationStack.rend();
|
||||||
I != E; ++I)
|
I != E; ++I)
|
||||||
emitSingleMacroExpansion(*I, Level, Ranges);
|
emitSingleMacroExpansion(FullSourceLoc(*I, SM), Level, Ranges);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -554,7 +573,7 @@ void DiagnosticRenderer::emitMacroExpansions(FullSourceLoc Loc,
|
||||||
for (auto I = LocationStack.rbegin(),
|
for (auto I = LocationStack.rbegin(),
|
||||||
E = LocationStack.rbegin() + MacroStartMessages;
|
E = LocationStack.rbegin() + MacroStartMessages;
|
||||||
I != E; ++I)
|
I != E; ++I)
|
||||||
emitSingleMacroExpansion(*I, Level, Ranges);
|
emitSingleMacroExpansion(FullSourceLoc(*I, SM), Level, Ranges);
|
||||||
|
|
||||||
SmallString<200> MessageStorage;
|
SmallString<200> MessageStorage;
|
||||||
llvm::raw_svector_ostream Message(MessageStorage);
|
llvm::raw_svector_ostream Message(MessageStorage);
|
||||||
|
@ -566,7 +585,7 @@ void DiagnosticRenderer::emitMacroExpansions(FullSourceLoc Loc,
|
||||||
for (auto I = LocationStack.rend() - MacroEndMessages,
|
for (auto I = LocationStack.rend() - MacroEndMessages,
|
||||||
E = LocationStack.rend();
|
E = LocationStack.rend();
|
||||||
I != E; ++I)
|
I != E; ++I)
|
||||||
emitSingleMacroExpansion(*I, Level, Ranges);
|
emitSingleMacroExpansion(FullSourceLoc(*I, SM), Level, Ranges);
|
||||||
}
|
}
|
||||||
|
|
||||||
DiagnosticNoteRenderer::~DiagnosticNoteRenderer() = default;
|
DiagnosticNoteRenderer::~DiagnosticNoteRenderer() = default;
|
||||||
|
|
|
@ -852,23 +852,14 @@ void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
|
||||||
// Ignore invalid ranges.
|
// Ignore invalid ranges.
|
||||||
if (!RI->isValid()) continue;
|
if (!RI->isValid()) continue;
|
||||||
|
|
||||||
FullSourceLoc B =
|
auto &SM = Loc.getManager();
|
||||||
FullSourceLoc(RI->getBegin(), Loc.getManager()).getExpansionLoc();
|
SourceLocation B = SM.getExpansionLoc(RI->getBegin());
|
||||||
FullSourceLoc E =
|
CharSourceRange ERange = SM.getExpansionRange(RI->getEnd());
|
||||||
FullSourceLoc(RI->getEnd(), Loc.getManager()).getExpansionLoc();
|
SourceLocation E = ERange.getEnd();
|
||||||
|
bool IsTokenRange = ERange.isTokenRange();
|
||||||
|
|
||||||
// If the End location and the start location are the same and are a
|
std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B);
|
||||||
// macro location, then the range was something that came from a
|
std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
|
||||||
// macro expansion or _Pragma. If this is an object-like macro, the
|
|
||||||
// best we can do is to highlight the range. If this is a
|
|
||||||
// function-like macro, we'd also like to highlight the arguments.
|
|
||||||
if (B == E && RI->getEnd().isMacroID())
|
|
||||||
E = FullSourceLoc(RI->getEnd(), Loc.getManager())
|
|
||||||
.getExpansionRange()
|
|
||||||
.second;
|
|
||||||
|
|
||||||
std::pair<FileID, unsigned> BInfo = B.getDecomposedLoc();
|
|
||||||
std::pair<FileID, unsigned> EInfo = E.getDecomposedLoc();
|
|
||||||
|
|
||||||
// If the start or end of the range is in another file, just discard
|
// If the start or end of the range is in another file, just discard
|
||||||
// it.
|
// it.
|
||||||
|
@ -878,11 +869,14 @@ void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
|
||||||
// Add in the length of the token, so that we cover multi-char
|
// Add in the length of the token, so that we cover multi-char
|
||||||
// tokens.
|
// tokens.
|
||||||
unsigned TokSize = 0;
|
unsigned TokSize = 0;
|
||||||
if (RI->isTokenRange())
|
if (IsTokenRange)
|
||||||
TokSize = Lexer::MeasureTokenLength(E, E.getManager(), LangOpts);
|
TokSize = Lexer::MeasureTokenLength(E, SM, LangOpts);
|
||||||
|
|
||||||
OS << '{' << B.getLineNumber() << ':' << B.getColumnNumber() << '-'
|
FullSourceLoc BF(B, SM), EF(E, SM);
|
||||||
<< E.getLineNumber() << ':' << (E.getColumnNumber() + TokSize) << '}';
|
OS << '{'
|
||||||
|
<< BF.getLineNumber() << ':' << BF.getColumnNumber() << '-'
|
||||||
|
<< EF.getLineNumber() << ':' << (EF.getColumnNumber() + TokSize)
|
||||||
|
<< '}';
|
||||||
PrintedRange = true;
|
PrintedRange = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -708,12 +708,9 @@ PreambleBounds Lexer::ComputePreamble(StringRef Buffer,
|
||||||
TheTok.isAtStartOfLine());
|
TheTok.isAtStartOfLine());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// AdvanceToTokenCharacter - Given a location that specifies the start of a
|
unsigned Lexer::getTokenPrefixLength(SourceLocation TokStart, unsigned CharNo,
|
||||||
/// token, return a new location that specifies a character within the token.
|
const SourceManager &SM,
|
||||||
SourceLocation Lexer::AdvanceToTokenCharacter(SourceLocation TokStart,
|
const LangOptions &LangOpts) {
|
||||||
unsigned CharNo,
|
|
||||||
const SourceManager &SM,
|
|
||||||
const LangOptions &LangOpts) {
|
|
||||||
// Figure out how many physical characters away the specified expansion
|
// Figure out how many physical characters away the specified expansion
|
||||||
// character is. This needs to take into consideration newlines and
|
// character is. This needs to take into consideration newlines and
|
||||||
// trigraphs.
|
// trigraphs.
|
||||||
|
@ -722,7 +719,7 @@ SourceLocation Lexer::AdvanceToTokenCharacter(SourceLocation TokStart,
|
||||||
|
|
||||||
// If they request the first char of the token, we're trivially done.
|
// If they request the first char of the token, we're trivially done.
|
||||||
if (Invalid || (CharNo == 0 && Lexer::isObviouslySimpleCharacter(*TokPtr)))
|
if (Invalid || (CharNo == 0 && Lexer::isObviouslySimpleCharacter(*TokPtr)))
|
||||||
return TokStart;
|
return 0;
|
||||||
|
|
||||||
unsigned PhysOffset = 0;
|
unsigned PhysOffset = 0;
|
||||||
|
|
||||||
|
@ -731,7 +728,7 @@ SourceLocation Lexer::AdvanceToTokenCharacter(SourceLocation TokStart,
|
||||||
// chars, this method is extremely fast.
|
// chars, this method is extremely fast.
|
||||||
while (Lexer::isObviouslySimpleCharacter(*TokPtr)) {
|
while (Lexer::isObviouslySimpleCharacter(*TokPtr)) {
|
||||||
if (CharNo == 0)
|
if (CharNo == 0)
|
||||||
return TokStart.getLocWithOffset(PhysOffset);
|
return PhysOffset;
|
||||||
++TokPtr;
|
++TokPtr;
|
||||||
--CharNo;
|
--CharNo;
|
||||||
++PhysOffset;
|
++PhysOffset;
|
||||||
|
@ -753,7 +750,7 @@ SourceLocation Lexer::AdvanceToTokenCharacter(SourceLocation TokStart,
|
||||||
if (!Lexer::isObviouslySimpleCharacter(*TokPtr))
|
if (!Lexer::isObviouslySimpleCharacter(*TokPtr))
|
||||||
PhysOffset += Lexer::SkipEscapedNewLines(TokPtr)-TokPtr;
|
PhysOffset += Lexer::SkipEscapedNewLines(TokPtr)-TokPtr;
|
||||||
|
|
||||||
return TokStart.getLocWithOffset(PhysOffset);
|
return PhysOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Computes the source location just past the end of the
|
/// \brief Computes the source location just past the end of the
|
||||||
|
@ -987,7 +984,7 @@ StringRef Lexer::getImmediateMacroName(SourceLocation Loc,
|
||||||
|
|
||||||
// Loc points to the argument id of the macro definition, move to the
|
// Loc points to the argument id of the macro definition, move to the
|
||||||
// macro expansion.
|
// macro expansion.
|
||||||
Loc = SM.getImmediateExpansionRange(Loc).first;
|
Loc = SM.getImmediateExpansionRange(Loc).getBegin();
|
||||||
SourceLocation SpellLoc = Expansion.getSpellingLoc();
|
SourceLocation SpellLoc = Expansion.getSpellingLoc();
|
||||||
if (SpellLoc.isFileID())
|
if (SpellLoc.isFileID())
|
||||||
break; // No inner macro.
|
break; // No inner macro.
|
||||||
|
@ -1020,7 +1017,7 @@ StringRef Lexer::getImmediateMacroNameForDiagnostics(
|
||||||
assert(Loc.isMacroID() && "Only reasonable to call this on macros");
|
assert(Loc.isMacroID() && "Only reasonable to call this on macros");
|
||||||
// Walk past macro argument expanions.
|
// Walk past macro argument expanions.
|
||||||
while (SM.isMacroArgExpansion(Loc))
|
while (SM.isMacroArgExpansion(Loc))
|
||||||
Loc = SM.getImmediateExpansionRange(Loc).first;
|
Loc = SM.getImmediateExpansionRange(Loc).getBegin();
|
||||||
|
|
||||||
// If the macro's spelling has no FileID, then it's actually a token paste
|
// If the macro's spelling has no FileID, then it's actually a token paste
|
||||||
// or stringization (or similar) and not a macro at all.
|
// or stringization (or similar) and not a macro at all.
|
||||||
|
@ -1030,7 +1027,7 @@ StringRef Lexer::getImmediateMacroNameForDiagnostics(
|
||||||
// Find the spelling location of the start of the non-argument expansion
|
// Find the spelling location of the start of the non-argument expansion
|
||||||
// range. This is where the macro name was spelled in order to begin
|
// range. This is where the macro name was spelled in order to begin
|
||||||
// expanding this macro.
|
// expanding this macro.
|
||||||
Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first);
|
Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).getBegin());
|
||||||
|
|
||||||
// Dig out the buffer where the macro name was spelled and the extents of the
|
// Dig out the buffer where the macro name was spelled and the extents of the
|
||||||
// name so that we can render it into the expansion note.
|
// name so that we can render it into the expansion note.
|
||||||
|
@ -1112,10 +1109,9 @@ static SourceLocation GetMappedTokenLoc(Preprocessor &PP,
|
||||||
|
|
||||||
// Figure out the expansion loc range, which is the range covered by the
|
// Figure out the expansion loc range, which is the range covered by the
|
||||||
// original _Pragma(...) sequence.
|
// original _Pragma(...) sequence.
|
||||||
std::pair<SourceLocation,SourceLocation> II =
|
CharSourceRange II = SM.getImmediateExpansionRange(FileLoc);
|
||||||
SM.getImmediateExpansionRange(FileLoc);
|
|
||||||
|
|
||||||
return SM.createExpansionLoc(SpellingLoc, II.first, II.second, TokLen);
|
return SM.createExpansionLoc(SpellingLoc, II.getBegin(), II.getEnd(), TokLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getSourceLocation - Return a source location identifier for the specified
|
/// getSourceLocation - Return a source location identifier for the specified
|
||||||
|
|
|
@ -2043,7 +2043,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
|
||||||
// If the filename string was the result of macro expansions, set the include
|
// If the filename string was the result of macro expansions, set the include
|
||||||
// position on the file where it will be included and after the expansions.
|
// position on the file where it will be included and after the expansions.
|
||||||
if (IncludePos.isMacroID())
|
if (IncludePos.isMacroID())
|
||||||
IncludePos = SourceMgr.getExpansionRange(IncludePos).second;
|
IncludePos = SourceMgr.getExpansionRange(IncludePos).getEnd();
|
||||||
FileID FID = SourceMgr.createFileID(File, IncludePos, FileCharacter);
|
FileID FID = SourceMgr.createFileID(File, IncludePos, FileCharacter);
|
||||||
assert(FID.isValid() && "Expected valid file ID");
|
assert(FID.isValid() && "Expected valid file ID");
|
||||||
|
|
||||||
|
|
|
@ -1690,7 +1690,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
|
||||||
// can matter for a function-like macro that expands to contain __LINE__.
|
// can matter for a function-like macro that expands to contain __LINE__.
|
||||||
// Skip down through expansion points until we find a file loc for the
|
// Skip down through expansion points until we find a file loc for the
|
||||||
// end of the expansion history.
|
// end of the expansion history.
|
||||||
Loc = SourceMgr.getExpansionRange(Loc).second;
|
Loc = SourceMgr.getExpansionRange(Loc).getEnd();
|
||||||
PresumedLoc PLoc = SourceMgr.getPresumedLoc(Loc);
|
PresumedLoc PLoc = SourceMgr.getPresumedLoc(Loc);
|
||||||
|
|
||||||
// __LINE__ expands to a simple numeric value.
|
// __LINE__ expands to a simple numeric value.
|
||||||
|
|
|
@ -487,6 +487,22 @@ void Preprocessor::CreateString(StringRef Str, Token &Tok,
|
||||||
Tok.setLiteralData(DestPtr);
|
Tok.setLiteralData(DestPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SourceLocation Preprocessor::SplitToken(SourceLocation Loc, unsigned Length) {
|
||||||
|
auto &SM = getSourceManager();
|
||||||
|
SourceLocation SpellingLoc = SM.getSpellingLoc(Loc);
|
||||||
|
std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellingLoc);
|
||||||
|
bool Invalid = false;
|
||||||
|
StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid);
|
||||||
|
if (Invalid)
|
||||||
|
return SourceLocation();
|
||||||
|
|
||||||
|
// FIXME: We could consider re-using spelling for tokens we see repeatedly.
|
||||||
|
const char *DestPtr;
|
||||||
|
SourceLocation Spelling =
|
||||||
|
ScratchBuf->getToken(Buffer.data() + LocInfo.second, Length, DestPtr);
|
||||||
|
return SM.createTokenSplitLoc(Spelling, Loc, Loc.getLocWithOffset(Length));
|
||||||
|
}
|
||||||
|
|
||||||
Module *Preprocessor::getCurrentModule() {
|
Module *Preprocessor::getCurrentModule() {
|
||||||
if (!getLangOpts().isCompilingModule())
|
if (!getLangOpts().isCompilingModule())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -865,9 +865,9 @@ bool TokenLexer::pasteTokens(Token &LHSTok, ArrayRef<Token> TokenStream,
|
||||||
EndLoc = getExpansionLocForMacroDefLoc(EndLoc);
|
EndLoc = getExpansionLocForMacroDefLoc(EndLoc);
|
||||||
FileID MacroFID = SM.getFileID(MacroExpansionStart);
|
FileID MacroFID = SM.getFileID(MacroExpansionStart);
|
||||||
while (SM.getFileID(StartLoc) != MacroFID)
|
while (SM.getFileID(StartLoc) != MacroFID)
|
||||||
StartLoc = SM.getImmediateExpansionRange(StartLoc).first;
|
StartLoc = SM.getImmediateExpansionRange(StartLoc).getBegin();
|
||||||
while (SM.getFileID(EndLoc) != MacroFID)
|
while (SM.getFileID(EndLoc) != MacroFID)
|
||||||
EndLoc = SM.getImmediateExpansionRange(EndLoc).second;
|
EndLoc = SM.getImmediateExpansionRange(EndLoc).getEnd();
|
||||||
|
|
||||||
LHSTok.setLocation(SM.createExpansionLoc(LHSTok.getLocation(), StartLoc, EndLoc,
|
LHSTok.setLocation(SM.createExpansionLoc(LHSTok.getLocation(), StartLoc, EndLoc,
|
||||||
LHSTok.getLength()));
|
LHSTok.getLength()));
|
||||||
|
|
|
@ -775,6 +775,7 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
|
||||||
// What will be left once we've consumed the '>'.
|
// What will be left once we've consumed the '>'.
|
||||||
tok::TokenKind RemainingToken;
|
tok::TokenKind RemainingToken;
|
||||||
const char *ReplacementStr = "> >";
|
const char *ReplacementStr = "> >";
|
||||||
|
bool MergeWithNextToken = false;
|
||||||
|
|
||||||
switch (Tok.getKind()) {
|
switch (Tok.getKind()) {
|
||||||
default:
|
default:
|
||||||
|
@ -800,6 +801,15 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
|
||||||
case tok::greaterequal:
|
case tok::greaterequal:
|
||||||
RemainingToken = tok::equal;
|
RemainingToken = tok::equal;
|
||||||
ReplacementStr = "> =";
|
ReplacementStr = "> =";
|
||||||
|
|
||||||
|
// Join two adjacent '=' tokens into one, for cases like:
|
||||||
|
// void (*p)() = f<int>;
|
||||||
|
// return f<int>==p;
|
||||||
|
if (NextToken().is(tok::equal) &&
|
||||||
|
areTokensAdjacent(Tok, NextToken())) {
|
||||||
|
RemainingToken = tok::equalequal;
|
||||||
|
MergeWithNextToken = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case tok::greatergreaterequal:
|
case tok::greatergreaterequal:
|
||||||
|
@ -807,22 +817,35 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This template-id is terminated by a token which starts with a '>'. Outside
|
// This template-id is terminated by a token that starts with a '>'.
|
||||||
// C++11, this is now error recovery, and in C++11, this is error recovery if
|
// Outside C++11 and Objective-C, this is now error recovery.
|
||||||
// the token isn't '>>' or '>>>'.
|
|
||||||
// '>>>' is for CUDA, where this sequence of characters is parsed into
|
|
||||||
// tok::greatergreatergreater, rather than two separate tokens.
|
|
||||||
//
|
//
|
||||||
// We always allow this for Objective-C type parameter and type argument
|
// C++11 allows this when the token is '>>', and in CUDA + C++11 mode, we
|
||||||
// lists.
|
// extend that treatment to also apply to the '>>>' token.
|
||||||
RAngleLoc = Tok.getLocation();
|
//
|
||||||
|
// Objective-C allows this in its type parameter / argument lists.
|
||||||
|
|
||||||
|
SourceLocation TokBeforeGreaterLoc = PrevTokLocation;
|
||||||
|
SourceLocation TokLoc = Tok.getLocation();
|
||||||
Token Next = NextToken();
|
Token Next = NextToken();
|
||||||
|
|
||||||
|
// Whether splitting the current token after the '>' would undesirably result
|
||||||
|
// in the remaining token pasting with the token after it. This excludes the
|
||||||
|
// MergeWithNextToken cases, which we've already handled.
|
||||||
|
bool PreventMergeWithNextToken =
|
||||||
|
(RemainingToken == tok::greater ||
|
||||||
|
RemainingToken == tok::greatergreater) &&
|
||||||
|
(Next.isOneOf(tok::greater, tok::greatergreater,
|
||||||
|
tok::greatergreatergreater, tok::equal, tok::greaterequal,
|
||||||
|
tok::greatergreaterequal, tok::equalequal)) &&
|
||||||
|
areTokensAdjacent(Tok, Next);
|
||||||
|
|
||||||
|
// Diagnose this situation as appropriate.
|
||||||
if (!ObjCGenericList) {
|
if (!ObjCGenericList) {
|
||||||
// The source range of the '>>' or '>=' at the start of the token.
|
// The source range of the replaced token(s).
|
||||||
CharSourceRange ReplacementRange =
|
CharSourceRange ReplacementRange = CharSourceRange::getCharRange(
|
||||||
CharSourceRange::getCharRange(RAngleLoc,
|
TokLoc, Lexer::AdvanceToTokenCharacter(TokLoc, 2, PP.getSourceManager(),
|
||||||
Lexer::AdvanceToTokenCharacter(RAngleLoc, 2, PP.getSourceManager(),
|
getLangOpts()));
|
||||||
getLangOpts()));
|
|
||||||
|
|
||||||
// A hint to put a space between the '>>'s. In order to make the hint as
|
// A hint to put a space between the '>>'s. In order to make the hint as
|
||||||
// clear as possible, we include the characters either side of the space in
|
// clear as possible, we include the characters either side of the space in
|
||||||
|
@ -833,13 +856,7 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
|
||||||
// A hint to put another space after the token, if it would otherwise be
|
// A hint to put another space after the token, if it would otherwise be
|
||||||
// lexed differently.
|
// lexed differently.
|
||||||
FixItHint Hint2;
|
FixItHint Hint2;
|
||||||
if ((RemainingToken == tok::greater ||
|
if (PreventMergeWithNextToken)
|
||||||
RemainingToken == tok::greatergreater) &&
|
|
||||||
(Next.isOneOf(tok::greater, tok::greatergreater,
|
|
||||||
tok::greatergreatergreater, tok::equal,
|
|
||||||
tok::greaterequal, tok::greatergreaterequal,
|
|
||||||
tok::equalequal)) &&
|
|
||||||
areTokensAdjacent(Tok, Next))
|
|
||||||
Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " ");
|
Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " ");
|
||||||
|
|
||||||
unsigned DiagId = diag::err_two_right_angle_brackets_need_space;
|
unsigned DiagId = diag::err_two_right_angle_brackets_need_space;
|
||||||
|
@ -848,50 +865,63 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
|
||||||
DiagId = diag::warn_cxx98_compat_two_right_angle_brackets;
|
DiagId = diag::warn_cxx98_compat_two_right_angle_brackets;
|
||||||
else if (Tok.is(tok::greaterequal))
|
else if (Tok.is(tok::greaterequal))
|
||||||
DiagId = diag::err_right_angle_bracket_equal_needs_space;
|
DiagId = diag::err_right_angle_bracket_equal_needs_space;
|
||||||
Diag(Tok.getLocation(), DiagId) << Hint1 << Hint2;
|
Diag(TokLoc, DiagId) << Hint1 << Hint2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find the "length" of the resulting '>' token. This is not always 1, as it
|
||||||
|
// can contain escaped newlines.
|
||||||
|
unsigned GreaterLength = Lexer::getTokenPrefixLength(
|
||||||
|
TokLoc, 1, PP.getSourceManager(), getLangOpts());
|
||||||
|
|
||||||
|
// Annotate the source buffer to indicate that we split the token after the
|
||||||
|
// '>'. This allows us to properly find the end of, and extract the spelling
|
||||||
|
// of, the '>' token later.
|
||||||
|
RAngleLoc = PP.SplitToken(TokLoc, GreaterLength);
|
||||||
|
|
||||||
// Strip the initial '>' from the token.
|
// Strip the initial '>' from the token.
|
||||||
Token PrevTok = Tok;
|
bool CachingTokens = PP.IsPreviousCachedToken(Tok);
|
||||||
if (RemainingToken == tok::equal && Next.is(tok::equal) &&
|
|
||||||
areTokensAdjacent(Tok, Next)) {
|
Token Greater = Tok;
|
||||||
// Join two adjacent '=' tokens into one, for cases like:
|
Greater.setLocation(RAngleLoc);
|
||||||
// void (*p)() = f<int>;
|
Greater.setKind(tok::greater);
|
||||||
// return f<int>==p;
|
Greater.setLength(GreaterLength);
|
||||||
|
|
||||||
|
unsigned OldLength = Tok.getLength();
|
||||||
|
if (MergeWithNextToken) {
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
Tok.setKind(tok::equalequal);
|
OldLength += Tok.getLength();
|
||||||
Tok.setLength(Tok.getLength() + 1);
|
|
||||||
} else {
|
|
||||||
Tok.setKind(RemainingToken);
|
|
||||||
Tok.setLength(Tok.getLength() - 1);
|
|
||||||
}
|
}
|
||||||
Tok.setLocation(Lexer::AdvanceToTokenCharacter(RAngleLoc, 1,
|
|
||||||
PP.getSourceManager(),
|
|
||||||
getLangOpts()));
|
|
||||||
|
|
||||||
// The advance from '>>' to '>' in a ObjectiveC template argument list needs
|
Tok.setKind(RemainingToken);
|
||||||
// to be properly reflected in the token cache to allow correct interaction
|
Tok.setLength(OldLength - GreaterLength);
|
||||||
// between annotation and backtracking.
|
|
||||||
if (ObjCGenericList && PrevTok.getKind() == tok::greatergreater &&
|
// Split the second token if lexing it normally would lex a different token
|
||||||
RemainingToken == tok::greater && PP.IsPreviousCachedToken(PrevTok)) {
|
// (eg, the fifth token in 'A<B>>>' should re-lex as '>', not '>>').
|
||||||
PrevTok.setKind(RemainingToken);
|
SourceLocation AfterGreaterLoc = TokLoc.getLocWithOffset(GreaterLength);
|
||||||
PrevTok.setLength(1);
|
if (PreventMergeWithNextToken)
|
||||||
// Break tok::greatergreater into two tok::greater but only add the second
|
AfterGreaterLoc = PP.SplitToken(AfterGreaterLoc, Tok.getLength());
|
||||||
// one in case the client asks to consume the last token.
|
Tok.setLocation(AfterGreaterLoc);
|
||||||
|
|
||||||
|
// Update the token cache to match what we just did if necessary.
|
||||||
|
if (CachingTokens) {
|
||||||
|
// If the previous cached token is being merged, delete it.
|
||||||
|
if (MergeWithNextToken)
|
||||||
|
PP.ReplacePreviousCachedToken({});
|
||||||
|
|
||||||
if (ConsumeLastToken)
|
if (ConsumeLastToken)
|
||||||
PP.ReplacePreviousCachedToken({PrevTok, Tok});
|
PP.ReplacePreviousCachedToken({Greater, Tok});
|
||||||
else
|
else
|
||||||
PP.ReplacePreviousCachedToken({PrevTok});
|
PP.ReplacePreviousCachedToken({Greater});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ConsumeLastToken) {
|
if (ConsumeLastToken) {
|
||||||
// Since we're not supposed to consume the '>' token, we need to push
|
PrevTokLocation = RAngleLoc;
|
||||||
// this token and revert the current token back to the '>'.
|
} else {
|
||||||
|
PrevTokLocation = TokBeforeGreaterLoc;
|
||||||
PP.EnterToken(Tok);
|
PP.EnterToken(Tok);
|
||||||
Tok.setKind(tok::greater);
|
Tok = Greater;
|
||||||
Tok.setLength(1);
|
|
||||||
Tok.setLocation(RAngleLoc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,8 @@ using namespace clang;
|
||||||
/// start/end tags are placed at the start/end of each line if the range is
|
/// start/end tags are placed at the start/end of each line if the range is
|
||||||
/// multiline.
|
/// multiline.
|
||||||
void html::HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E,
|
void html::HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E,
|
||||||
const char *StartTag, const char *EndTag) {
|
const char *StartTag, const char *EndTag,
|
||||||
|
bool IsTokenRange) {
|
||||||
SourceManager &SM = R.getSourceMgr();
|
SourceManager &SM = R.getSourceMgr();
|
||||||
B = SM.getExpansionLoc(B);
|
B = SM.getExpansionLoc(B);
|
||||||
E = SM.getExpansionLoc(E);
|
E = SM.getExpansionLoc(E);
|
||||||
|
@ -41,7 +42,8 @@ void html::HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E,
|
||||||
unsigned EOffset = SM.getFileOffset(E);
|
unsigned EOffset = SM.getFileOffset(E);
|
||||||
|
|
||||||
// Include the whole end token in the range.
|
// Include the whole end token in the range.
|
||||||
EOffset += Lexer::MeasureTokenLength(E, R.getSourceMgr(), R.getLangOpts());
|
if (IsTokenRange)
|
||||||
|
EOffset += Lexer::MeasureTokenLength(E, R.getSourceMgr(), R.getLangOpts());
|
||||||
|
|
||||||
bool Invalid = false;
|
bool Invalid = false;
|
||||||
const char *BufferStart = SM.getBufferData(FID, &Invalid).data();
|
const char *BufferStart = SM.getBufferData(FID, &Invalid).data();
|
||||||
|
@ -588,16 +590,15 @@ void html::HighlightMacros(Rewriter &R, FileID FID, const Preprocessor& PP) {
|
||||||
// Okay, we have the first token of a macro expansion: highlight the
|
// Okay, we have the first token of a macro expansion: highlight the
|
||||||
// expansion by inserting a start tag before the macro expansion and
|
// expansion by inserting a start tag before the macro expansion and
|
||||||
// end tag after it.
|
// end tag after it.
|
||||||
std::pair<SourceLocation, SourceLocation> LLoc =
|
CharSourceRange LLoc = SM.getExpansionRange(Tok.getLocation());
|
||||||
SM.getExpansionRange(Tok.getLocation());
|
|
||||||
|
|
||||||
// Ignore tokens whose instantiation location was not the main file.
|
// Ignore tokens whose instantiation location was not the main file.
|
||||||
if (SM.getFileID(LLoc.first) != FID) {
|
if (SM.getFileID(LLoc.getBegin()) != FID) {
|
||||||
TmpPP.Lex(Tok);
|
TmpPP.Lex(Tok);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(SM.getFileID(LLoc.second) == FID &&
|
assert(SM.getFileID(LLoc.getEnd()) == FID &&
|
||||||
"Start and end of expansion must be in the same ultimate file!");
|
"Start and end of expansion must be in the same ultimate file!");
|
||||||
|
|
||||||
std::string Expansion = EscapeText(TmpPP.getSpelling(Tok));
|
std::string Expansion = EscapeText(TmpPP.getSpelling(Tok));
|
||||||
|
@ -612,7 +613,7 @@ void html::HighlightMacros(Rewriter &R, FileID FID, const Preprocessor& PP) {
|
||||||
// instantiation. It would be really nice to pop up a window with all the
|
// instantiation. It would be really nice to pop up a window with all the
|
||||||
// spelling of the tokens or something.
|
// spelling of the tokens or something.
|
||||||
while (!Tok.is(tok::eof) &&
|
while (!Tok.is(tok::eof) &&
|
||||||
SM.getExpansionLoc(Tok.getLocation()) == LLoc.first) {
|
SM.getExpansionLoc(Tok.getLocation()) == LLoc.getBegin()) {
|
||||||
// Insert a newline if the macro expansion is getting large.
|
// Insert a newline if the macro expansion is getting large.
|
||||||
if (LineLen > 60) {
|
if (LineLen > 60) {
|
||||||
Expansion += "<br>";
|
Expansion += "<br>";
|
||||||
|
@ -641,8 +642,8 @@ void html::HighlightMacros(Rewriter &R, FileID FID, const Preprocessor& PP) {
|
||||||
// highlighted.
|
// highlighted.
|
||||||
Expansion = "<span class='expansion'>" + Expansion + "</span></span>";
|
Expansion = "<span class='expansion'>" + Expansion + "</span></span>";
|
||||||
|
|
||||||
HighlightRange(R, LLoc.first, LLoc.second,
|
HighlightRange(R, LLoc.getBegin(), LLoc.getEnd(), "<span class='macro'>",
|
||||||
"<span class='macro'>", Expansion.c_str());
|
Expansion.c_str(), LLoc.isTokenRange());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore the preprocessor's old state.
|
// Restore the preprocessor's old state.
|
||||||
|
|
|
@ -9562,7 +9562,7 @@ static void DiagnoseNullConversion(Sema &S, Expr *E, QualType T,
|
||||||
StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics(
|
StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics(
|
||||||
Loc, S.SourceMgr, S.getLangOpts());
|
Loc, S.SourceMgr, S.getLangOpts());
|
||||||
if (MacroName == "NULL")
|
if (MacroName == "NULL")
|
||||||
Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first;
|
Loc = S.SourceMgr.getImmediateExpansionRange(Loc).getBegin();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only warn if the null and context location are in the same macro expansion.
|
// Only warn if the null and context location are in the same macro expansion.
|
||||||
|
|
|
@ -7533,7 +7533,7 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
|
||||||
SourceLocation StmtEndLoc =
|
SourceLocation StmtEndLoc =
|
||||||
SM.getExpansionRange(
|
SM.getExpansionRange(
|
||||||
(LastStmtOfUse ? LastStmtOfUse : StmtOfUse)->getLocEnd())
|
(LastStmtOfUse ? LastStmtOfUse : StmtOfUse)->getLocEnd())
|
||||||
.second;
|
.getEnd();
|
||||||
if (SM.getFileID(IfInsertionLoc) != SM.getFileID(StmtEndLoc))
|
if (SM.getFileID(IfInsertionLoc) != SM.getFileID(StmtEndLoc))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -2771,7 +2771,7 @@ void Sema::DiagnoseAbsenceOfOverrideControl(NamedDecl *D) {
|
||||||
SourceLocation Loc = MD->getLocation();
|
SourceLocation Loc = MD->getLocation();
|
||||||
SourceLocation SpellingLoc = Loc;
|
SourceLocation SpellingLoc = Loc;
|
||||||
if (getSourceManager().isMacroArgExpansion(Loc))
|
if (getSourceManager().isMacroArgExpansion(Loc))
|
||||||
SpellingLoc = getSourceManager().getImmediateExpansionRange(Loc).first;
|
SpellingLoc = getSourceManager().getImmediateExpansionRange(Loc).getBegin();
|
||||||
SpellingLoc = getSourceManager().getSpellingLoc(SpellingLoc);
|
SpellingLoc = getSourceManager().getSpellingLoc(SpellingLoc);
|
||||||
if (SpellingLoc.isValid() && getSourceManager().isInSystemHeader(SpellingLoc))
|
if (SpellingLoc.isValid() && getSourceManager().isInSystemHeader(SpellingLoc))
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -6487,7 +6487,7 @@ static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr,
|
||||||
// macro only if it is at the beginning of the macro.
|
// macro only if it is at the beginning of the macro.
|
||||||
while (ArgLoc.isMacroID() &&
|
while (ArgLoc.isMacroID() &&
|
||||||
S.getSourceManager().isAtStartOfImmediateMacroExpansion(ArgLoc)) {
|
S.getSourceManager().isAtStartOfImmediateMacroExpansion(ArgLoc)) {
|
||||||
ArgLoc = S.getSourceManager().getImmediateExpansionRange(ArgLoc).first;
|
ArgLoc = S.getSourceManager().getImmediateExpansionRange(ArgLoc).getBegin();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LParen.isMacroID())
|
if (LParen.isMacroID())
|
||||||
|
|
|
@ -4489,7 +4489,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||||
// the predefined
|
// the predefined
|
||||||
// __strong/__weak/__autoreleasing/__unsafe_unretained.
|
// __strong/__weak/__autoreleasing/__unsafe_unretained.
|
||||||
if (AttrLoc.isMacroID())
|
if (AttrLoc.isMacroID())
|
||||||
AttrLoc = S.SourceMgr.getImmediateExpansionRange(AttrLoc).first;
|
AttrLoc =
|
||||||
|
S.SourceMgr.getImmediateExpansionRange(AttrLoc).getBegin();
|
||||||
|
|
||||||
S.Diag(AttrLoc, diag::warn_arc_lifetime_result_type)
|
S.Diag(AttrLoc, diag::warn_arc_lifetime_result_type)
|
||||||
<< T.getQualifiers().getObjCLifetime();
|
<< T.getQualifiers().getObjCLifetime();
|
||||||
|
@ -5893,7 +5894,8 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
|
||||||
Sema &S = state.getSema();
|
Sema &S = state.getSema();
|
||||||
SourceLocation AttrLoc = attr.getLoc();
|
SourceLocation AttrLoc = attr.getLoc();
|
||||||
if (AttrLoc.isMacroID())
|
if (AttrLoc.isMacroID())
|
||||||
AttrLoc = S.getSourceManager().getImmediateExpansionRange(AttrLoc).first;
|
AttrLoc =
|
||||||
|
S.getSourceManager().getImmediateExpansionRange(AttrLoc).getBegin();
|
||||||
|
|
||||||
if (!attr.isArgIdent(0)) {
|
if (!attr.isArgIdent(0)) {
|
||||||
S.Diag(AttrLoc, diag::err_attribute_argument_type)
|
S.Diag(AttrLoc, diag::err_attribute_argument_type)
|
||||||
|
|
|
@ -1482,6 +1482,7 @@ bool ASTReader::ReadSLocEntry(int ID) {
|
||||||
SourceMgr.createExpansionLoc(SpellingLoc,
|
SourceMgr.createExpansionLoc(SpellingLoc,
|
||||||
ReadSourceLocation(*F, Record[2]),
|
ReadSourceLocation(*F, Record[2]),
|
||||||
ReadSourceLocation(*F, Record[3]),
|
ReadSourceLocation(*F, Record[3]),
|
||||||
|
Record[5],
|
||||||
Record[4],
|
Record[4],
|
||||||
ID,
|
ID,
|
||||||
BaseOffset + Record[0]);
|
BaseOffset + Record[0]);
|
||||||
|
|
|
@ -1905,6 +1905,7 @@ static unsigned CreateSLocExpansionAbbrev(llvm::BitstreamWriter &Stream) {
|
||||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location
|
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location
|
||||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Start location
|
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Start location
|
||||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // End location
|
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // End location
|
||||||
|
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Is token range
|
||||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Token length
|
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Token length
|
||||||
return Stream.EmitAbbrev(std::move(Abbrev));
|
return Stream.EmitAbbrev(std::move(Abbrev));
|
||||||
}
|
}
|
||||||
|
@ -2321,6 +2322,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
|
||||||
? SourceLocation()
|
? SourceLocation()
|
||||||
: Expansion.getExpansionLocEnd(),
|
: Expansion.getExpansionLocEnd(),
|
||||||
Record);
|
Record);
|
||||||
|
Record.push_back(Expansion.isExpansionTokenRange());
|
||||||
|
|
||||||
// Compute the token length for this macro expansion.
|
// Compute the token length for this macro expansion.
|
||||||
unsigned NextOffset = SourceMgr.getNextLocalOffset();
|
unsigned NextOffset = SourceMgr.getNextLocalOffset();
|
||||||
|
|
|
@ -2178,7 +2178,7 @@ static void simplifySimpleBranches(PathPieces &pieces) {
|
||||||
static Optional<size_t> getLengthOnSingleLine(SourceManager &SM,
|
static Optional<size_t> getLengthOnSingleLine(SourceManager &SM,
|
||||||
SourceRange Range) {
|
SourceRange Range) {
|
||||||
SourceRange ExpansionRange(SM.getExpansionLoc(Range.getBegin()),
|
SourceRange ExpansionRange(SM.getExpansionLoc(Range.getBegin()),
|
||||||
SM.getExpansionRange(Range.getEnd()).second);
|
SM.getExpansionRange(Range.getEnd()).getEnd());
|
||||||
|
|
||||||
FileID FID = SM.getFileID(ExpansionRange.getBegin());
|
FileID FID = SM.getFileID(ExpansionRange.getBegin());
|
||||||
if (FID != SM.getFileID(ExpansionRange.getEnd()))
|
if (FID != SM.getFileID(ExpansionRange.getEnd()))
|
||||||
|
|
|
@ -213,7 +213,7 @@ static bool isFunctionMacroExpansion(SourceLocation Loc,
|
||||||
if (!Loc.isMacroID())
|
if (!Loc.isMacroID())
|
||||||
return false;
|
return false;
|
||||||
while (SM.isMacroArgExpansion(Loc))
|
while (SM.isMacroArgExpansion(Loc))
|
||||||
Loc = SM.getImmediateExpansionRange(Loc).first;
|
Loc = SM.getImmediateExpansionRange(Loc).getBegin();
|
||||||
std::pair<FileID, unsigned> TLInfo = SM.getDecomposedLoc(Loc);
|
std::pair<FileID, unsigned> TLInfo = SM.getDecomposedLoc(Loc);
|
||||||
SrcMgr::SLocEntry SE = SM.getSLocEntry(TLInfo.first);
|
SrcMgr::SLocEntry SE = SM.getSLocEntry(TLInfo.first);
|
||||||
const SrcMgr::ExpansionInfo &EInfo = SE.getExpansion();
|
const SrcMgr::ExpansionInfo &EInfo = SE.getExpansion();
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
// RUN: not %clang_cc1 %s -fdiagnostics-print-source-range-info 2>&1 | FileCheck %s --strict-whitespace
|
||||||
|
|
||||||
|
template<typename T> class C {};
|
||||||
|
template<int> class D {};
|
||||||
|
|
||||||
|
void g() {
|
||||||
|
// The range ending in the first > character does not extend to the second >
|
||||||
|
// character.
|
||||||
|
// CHECK: :{[[@LINE+3]]:5-[[@LINE+3]]:11}: error:
|
||||||
|
// CHECK-NEXT: D<C<int>> a;
|
||||||
|
// CHECK-NEXT: ^~~~~~{{$}}
|
||||||
|
D<C<int>> a;
|
||||||
|
|
||||||
|
// The range ending in the second > character does not extend to the third >
|
||||||
|
// character.
|
||||||
|
// CHECK: :{[[@LINE+3]]:5-[[@LINE+3]]:14}: error:
|
||||||
|
// CHECK-NEXT: D<C<C<int>>> b;
|
||||||
|
// CHECK-NEXT: ^~~~~~~~~{{$}}
|
||||||
|
D<C<C<int>>> b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int> int V;
|
||||||
|
// Here, we split the >>= token into a > followed by a >=.
|
||||||
|
// Then we split the >= token into a > followed by an =,
|
||||||
|
// which we merge with the other = to form an ==.
|
||||||
|
// CHECK: error: a space is required
|
||||||
|
// CHECK-NEXT: int k = V<C<int>>==0;
|
||||||
|
// CHECK-NEXT: ^~{{$}}
|
||||||
|
// CHECK-NEXT: > >{{$}}
|
||||||
|
// CHECK: error: a space is required
|
||||||
|
// CHECK-NEXT: int k = V<C<int>>==0;
|
||||||
|
// CHECK-NEXT: ^~{{$}}
|
||||||
|
// CHECK-NEXT: > ={{$}}
|
||||||
|
// CHECK: :{[[@LINE+3]]:11-[[@LINE+3]]:17}: error:
|
||||||
|
// CHECK-NEXT: int k = V<C<int>>==0;
|
||||||
|
// CHECK-NEXT: ^~~~~~{{$}}
|
||||||
|
int k = V<C<int>>==0;
|
||||||
|
|
||||||
|
template<typename> int W;
|
||||||
|
// CHECK: :{[[@LINE+3]]:9-[[@LINE+3]]:18}{[[@LINE+3]]:20-[[@LINE+3]]:22}: error: comparison
|
||||||
|
// CHECK-NEXT: int l = W<C<int>>==&k;
|
||||||
|
// CHECK-NEXT: ~~~~~~~~~^ ~~{{$}}
|
||||||
|
int l = W<C<int>>==&k;
|
|
@ -130,15 +130,18 @@ namespace AliasDeclEndLocation {
|
||||||
using B = AliasDeclEndLocation::A<int
|
using B = AliasDeclEndLocation::A<int
|
||||||
> // expected-error {{expected ';' after alias declaration}}
|
> // expected-error {{expected ';' after alias declaration}}
|
||||||
+;
|
+;
|
||||||
// FIXME: After splitting this >> into two > tokens, we incorrectly determine
|
|
||||||
// the end of the template-id to be after the *second* '>'.
|
|
||||||
// Perhaps we could synthesize an expansion FileID containing '> >' to fix this?
|
|
||||||
using C = AliasDeclEndLocation::A<int
|
using C = AliasDeclEndLocation::A<int
|
||||||
>\
|
>\
|
||||||
> // expected-error {{expected ';' after alias declaration}}
|
> // expected-error {{expected ';' after alias declaration}}
|
||||||
;
|
;
|
||||||
using D = AliasDeclEndLocation::A<int
|
using D = AliasDeclEndLocation::A<int
|
||||||
> // expected-error {{expected ';' after alias declaration}}
|
> // expected-error {{expected ';' after alias declaration}}
|
||||||
|
// FIXME: After splitting this >> into two > tokens, we incorrectly determine
|
||||||
|
// the end of the template-id to be after the *second* '>'.
|
||||||
|
using E = AliasDeclEndLocation::A<int>>;
|
||||||
|
#define GGG >>>
|
||||||
|
using F = AliasDeclEndLocation::A<int GGG;
|
||||||
|
// expected-error@-1 {{expected ';' after alias declaration}}
|
||||||
B something_else;
|
B something_else;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -146,9 +146,13 @@ CXSourceRange cxloc::translateSourceRange(const SourceManager &SM,
|
||||||
// We want the last character in this location, so we will adjust the
|
// We want the last character in this location, so we will adjust the
|
||||||
// location accordingly.
|
// location accordingly.
|
||||||
SourceLocation EndLoc = R.getEnd();
|
SourceLocation EndLoc = R.getEnd();
|
||||||
if (EndLoc.isValid() && EndLoc.isMacroID() && !SM.isMacroArgExpansion(EndLoc))
|
bool IsTokenRange = R.isTokenRange();
|
||||||
EndLoc = SM.getExpansionRange(EndLoc).second;
|
if (EndLoc.isValid() && EndLoc.isMacroID() && !SM.isMacroArgExpansion(EndLoc)) {
|
||||||
if (R.isTokenRange() && EndLoc.isValid()) {
|
CharSourceRange Expansion = SM.getExpansionRange(EndLoc);
|
||||||
|
EndLoc = Expansion.getEnd();
|
||||||
|
IsTokenRange = Expansion.isTokenRange();
|
||||||
|
}
|
||||||
|
if (IsTokenRange && EndLoc.isValid()) {
|
||||||
unsigned Length = Lexer::MeasureTokenLength(SM.getSpellingLoc(EndLoc),
|
unsigned Length = Lexer::MeasureTokenLength(SM.getSpellingLoc(EndLoc),
|
||||||
SM, LangOpts);
|
SM, LangOpts);
|
||||||
EndLoc = EndLoc.getLocWithOffset(Length);
|
EndLoc = EndLoc.getLocWithOffset(Length);
|
||||||
|
|
|
@ -286,9 +286,7 @@ TEST_F(LexerTest, LexAPI) {
|
||||||
SourceLocation lsqrLoc = toks[0].getLocation();
|
SourceLocation lsqrLoc = toks[0].getLocation();
|
||||||
SourceLocation idLoc = toks[1].getLocation();
|
SourceLocation idLoc = toks[1].getLocation();
|
||||||
SourceLocation rsqrLoc = toks[2].getLocation();
|
SourceLocation rsqrLoc = toks[2].getLocation();
|
||||||
std::pair<SourceLocation,SourceLocation>
|
CharSourceRange macroRange = SourceMgr.getExpansionRange(lsqrLoc);
|
||||||
macroPair = SourceMgr.getExpansionRange(lsqrLoc);
|
|
||||||
SourceRange macroRange = SourceRange(macroPair.first, macroPair.second);
|
|
||||||
|
|
||||||
SourceLocation Loc;
|
SourceLocation Loc;
|
||||||
EXPECT_TRUE(Lexer::isAtStartOfMacroExpansion(lsqrLoc, SourceMgr, LangOpts, &Loc));
|
EXPECT_TRUE(Lexer::isAtStartOfMacroExpansion(lsqrLoc, SourceMgr, LangOpts, &Loc));
|
||||||
|
@ -297,6 +295,7 @@ TEST_F(LexerTest, LexAPI) {
|
||||||
EXPECT_FALSE(Lexer::isAtEndOfMacroExpansion(idLoc, SourceMgr, LangOpts));
|
EXPECT_FALSE(Lexer::isAtEndOfMacroExpansion(idLoc, SourceMgr, LangOpts));
|
||||||
EXPECT_TRUE(Lexer::isAtEndOfMacroExpansion(rsqrLoc, SourceMgr, LangOpts, &Loc));
|
EXPECT_TRUE(Lexer::isAtEndOfMacroExpansion(rsqrLoc, SourceMgr, LangOpts, &Loc));
|
||||||
EXPECT_EQ(Loc, macroRange.getEnd());
|
EXPECT_EQ(Loc, macroRange.getEnd());
|
||||||
|
EXPECT_TRUE(macroRange.isTokenRange());
|
||||||
|
|
||||||
CharSourceRange range = Lexer::makeFileCharRange(
|
CharSourceRange range = Lexer::makeFileCharRange(
|
||||||
CharSourceRange::getTokenRange(lsqrLoc, idLoc), SourceMgr, LangOpts);
|
CharSourceRange::getTokenRange(lsqrLoc, idLoc), SourceMgr, LangOpts);
|
||||||
|
@ -334,11 +333,11 @@ TEST_F(LexerTest, LexAPI) {
|
||||||
EXPECT_EQ(SourceRange(fileIdLoc, fileRsqrLoc.getLocWithOffset(1)),
|
EXPECT_EQ(SourceRange(fileIdLoc, fileRsqrLoc.getLocWithOffset(1)),
|
||||||
range.getAsRange());
|
range.getAsRange());
|
||||||
|
|
||||||
macroPair = SourceMgr.getExpansionRange(macroLsqrLoc);
|
macroRange = SourceMgr.getExpansionRange(macroLsqrLoc);
|
||||||
range = Lexer::makeFileCharRange(
|
range = Lexer::makeFileCharRange(
|
||||||
CharSourceRange::getTokenRange(macroLsqrLoc, macroRsqrLoc),
|
CharSourceRange::getTokenRange(macroLsqrLoc, macroRsqrLoc),
|
||||||
SourceMgr, LangOpts);
|
SourceMgr, LangOpts);
|
||||||
EXPECT_EQ(SourceRange(macroPair.first, macroPair.second.getLocWithOffset(1)),
|
EXPECT_EQ(SourceRange(macroRange.getBegin(), macroRange.getEnd().getLocWithOffset(1)),
|
||||||
range.getAsRange());
|
range.getAsRange());
|
||||||
|
|
||||||
text = Lexer::getSourceText(
|
text = Lexer::getSourceText(
|
||||||
|
|
Loading…
Reference in New Issue