]> granicus.if.org Git - clang/commitdiff
[Lexer] NFC: Fix an off-by-one bug in getAsCharRange().
authorArtem Dergachev <artem.dergachev@gmail.com>
Fri, 5 Apr 2019 21:48:52 +0000 (21:48 +0000)
committerArtem Dergachev <artem.dergachev@gmail.com>
Fri, 5 Apr 2019 21:48:52 +0000 (21:48 +0000)
As the unit test demonstrates, subtracting 1 from the offset was unnecessary.

The only user of this function was the plist file emitter (in Static Analyzer
and ARCMigrator). It means that a lot of Static Analyzer's plist arrows
are in fact off by one character. The patch carefully preserves this
completely incorrect behavior and causes no functional change,
i.e. no plist format breakage.

Differential Revision: https://reviews.llvm.org/D59977

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@357823 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/PlistSupport.h
include/clang/Lex/Lexer.h
unittests/Lex/LexerTest.cpp

index f81b469bb87da83e7341a77a5de92faba717a1d9..557462a5b90d01234ad4846e300b62d1bb167639 100644 (file)
@@ -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";
 }
 
index 4a8a0f6f0d67952e8765b014b4ccc22782981f40..69cfe62e4bdbc32100bc513c440b6f6b067b989d 100644 (file)
@@ -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,
index 320b60ea639acd3dca94d94699f582192df49a13..7b14f56201eb0613d5700b7ab5b841878fe8fcdf 100644 (file)
@@ -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