summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2019-04-23 21:15:26 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2019-04-23 21:15:26 +0000
commit8c099ce72d480fbff943613c7482992449fafe2d (patch)
tree8267c823a4c59b202a1fba84bf73bd4b39c764f5
parentfc79ab9857adc96d243cc5ed0a641eef8ef3f253 (diff)
downloadbcm5719-llvm-8c099ce72d480fbff943613c7482992449fafe2d.tar.gz
bcm5719-llvm-8c099ce72d480fbff943613c7482992449fafe2d.zip
Re-apply r357823 "[Lexer] NFC: Fix an off-by-one bug in getAsCharRange()."
It now comes with a follow-up fix for the clients of this API in clangd and clang-tidy. Differential Revision: https://reviews.llvm.org/D59977 llvm-svn: 359035
-rw-r--r--clang-tools-extra/clang-tidy/modernize/ConcatNestedNamespacesCheck.cpp1
-rw-r--r--clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp5
-rw-r--r--clang-tools-extra/unittests/clangd/SelectionTests.cpp2
-rw-r--r--clang/include/clang/Basic/PlistSupport.h6
-rw-r--r--clang/include/clang/Lex/Lexer.h2
-rw-r--r--clang/unittests/Lex/LexerTest.cpp19
6 files changed, 31 insertions, 4 deletions
diff --git a/clang-tools-extra/clang-tidy/modernize/ConcatNestedNamespacesCheck.cpp b/clang-tools-extra/clang-tidy/modernize/ConcatNestedNamespacesCheck.cpp
index 33ac85610d2..c1539bfd1d2 100644
--- a/clang-tools-extra/clang-tidy/modernize/ConcatNestedNamespacesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ConcatNestedNamespacesCheck.cpp
@@ -39,6 +39,7 @@ static bool alreadyConcatenated(std::size_t NumCandidates,
const SourceRange &ReplacementRange,
const SourceManager &Sources,
const LangOptions &LangOpts) {
+ // FIXME: This logic breaks when there is a comment with ':'s in the middle.
CharSourceRange TextRange =
Lexer::getAsCharRange(ReplacementRange, Sources, LangOpts);
StringRef CurrentNamespacesText =
diff --git a/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp b/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp
index 17184ec21b9..6428f8cdc98 100644
--- a/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp
@@ -102,11 +102,14 @@ void NamespaceCommentCheck::check(const MatchFinder::MatchResult &Result) {
}
}
+ // FIXME: This probably breaks on comments between the namespace and its '{'.
auto TextRange =
Lexer::getAsCharRange(SourceRange(NestedNamespaceBegin, LBracketLocation),
Sources, getLangOpts());
StringRef NestedNamespaceName =
- Lexer::getSourceText(TextRange, Sources, getLangOpts()).rtrim();
+ Lexer::getSourceText(TextRange, Sources, getLangOpts())
+ .rtrim('{') // Drop the { itself.
+ .rtrim(); // Drop any whitespace before it.
bool IsNested = NestedNamespaceName.contains(':');
if (IsNested)
diff --git a/clang-tools-extra/unittests/clangd/SelectionTests.cpp b/clang-tools-extra/unittests/clangd/SelectionTests.cpp
index 2d962712dbb..ac9facca839 100644
--- a/clang-tools-extra/unittests/clangd/SelectionTests.cpp
+++ b/clang-tools-extra/unittests/clangd/SelectionTests.cpp
@@ -45,7 +45,7 @@ Range nodeRange(const SelectionTree::Node *N, ParsedAST &AST) {
CharSourceRange R =
Lexer::getAsCharRange(SR, SM, AST.getASTContext().getLangOpts());
return Range{offsetToPosition(Buffer, SM.getFileOffset(R.getBegin())),
- offsetToPosition(Buffer, SM.getFileOffset(R.getEnd()) + 1)};
+ offsetToPosition(Buffer, SM.getFileOffset(R.getEnd()))};
}
std::string nodeKind(const SelectionTree::Node *N) {
diff --git a/clang/include/clang/Basic/PlistSupport.h b/clang/include/clang/Basic/PlistSupport.h
index f81b469bb87..557462a5b90 100644
--- a/clang/include/clang/Basic/PlistSupport.h
+++ b/clang/include/clang/Basic/PlistSupport.h
@@ -127,7 +127,11 @@ inline void EmitRange(raw_ostream &o, const SourceManager &SM,
assert(R.isCharRange() && "cannot handle a token range");
Indent(o, indent) << "<array>\n";
EmitLocation(o, SM, R.getBegin(), FM, indent + 1);
- EmitLocation(o, SM, R.getEnd(), FM, indent + 1);
+
+ // The ".getLocWithOffset(-1)" emulates the behavior of an off-by-one bug
+ // in Lexer that is already fixed. It is here for backwards compatibility
+ // even though it is incorrect.
+ EmitLocation(o, SM, R.getEnd().getLocWithOffset(-1), FM, indent + 1);
Indent(o, indent) << "</array>\n";
}
diff --git a/clang/include/clang/Lex/Lexer.h b/clang/include/clang/Lex/Lexer.h
index 4a8a0f6f0d6..69cfe62e4bd 100644
--- a/clang/include/clang/Lex/Lexer.h
+++ b/clang/include/clang/Lex/Lexer.h
@@ -382,7 +382,7 @@ public:
SourceLocation End = getLocForEndOfToken(Range.getEnd(), 0, SM, LangOpts);
return End.isInvalid() ? CharSourceRange()
: CharSourceRange::getCharRange(
- Range.getBegin(), End.getLocWithOffset(-1));
+ Range.getBegin(), End);
}
static CharSourceRange getAsCharRange(CharSourceRange Range,
const SourceManager &SM,
diff --git a/clang/unittests/Lex/LexerTest.cpp b/clang/unittests/Lex/LexerTest.cpp
index 320b60ea639..7b14f56201e 100644
--- a/clang/unittests/Lex/LexerTest.cpp
+++ b/clang/unittests/Lex/LexerTest.cpp
@@ -513,4 +513,23 @@ TEST_F(LexerTest, StringizingRasString) {
EXPECT_EQ(String6, R"(a\\\n\n\n \\\\b)");
}
+TEST_F(LexerTest, CharRangeOffByOne) {
+ std::vector<Token> toks = Lex(R"(#define MOO 1
+ void foo() { MOO; })");
+ const Token &moo = toks[5];
+
+ EXPECT_EQ(getSourceText(moo, moo), "MOO");
+
+ SourceRange R{moo.getLocation(), moo.getLocation()};
+
+ EXPECT_TRUE(
+ Lexer::isAtStartOfMacroExpansion(R.getBegin(), SourceMgr, LangOpts));
+ EXPECT_TRUE(
+ Lexer::isAtEndOfMacroExpansion(R.getEnd(), SourceMgr, LangOpts));
+
+ CharSourceRange CR = Lexer::getAsCharRange(R, SourceMgr, LangOpts);
+
+ EXPECT_EQ(Lexer::getSourceText(CR, SourceMgr, LangOpts), "MOO"); // Was "MO".
+}
+
} // anonymous namespace
OpenPOWER on IntegriCloud