1//===- unittests/Support/SourceMgrTest.cpp - SourceMgr tests --------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/Support/SourceMgr.h"
11#include "llvm/Support/MemoryBuffer.h"
12#include "llvm/Support/raw_ostream.h"
13#include "gtest/gtest.h"
14
15using namespace llvm;
16
17namespace {
18
19class SourceMgrTest : public testing::Test {
20public:
21  SourceMgr SM;
22  unsigned MainBufferID;
23  std::string Output;
24
25  void setMainBuffer(StringRef Text, StringRef BufferName) {
26    std::unique_ptr<MemoryBuffer> MainBuffer =
27        MemoryBuffer::getMemBuffer(Text, BufferName);
28    MainBufferID = SM.AddNewSourceBuffer(std::move(MainBuffer), llvm::SMLoc());
29  }
30
31  SMLoc getLoc(unsigned Offset) {
32    return SMLoc::getFromPointer(
33        SM.getMemoryBuffer(MainBufferID)->getBufferStart() + Offset);
34  }
35
36  SMRange getRange(unsigned Offset, unsigned Length) {
37    return SMRange(getLoc(Offset), getLoc(Offset + Length));
38  }
39
40  void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
41                    const Twine &Msg, ArrayRef<SMRange> Ranges,
42                    ArrayRef<SMFixIt> FixIts) {
43    raw_string_ostream OS(Output);
44    SM.PrintMessage(OS, Loc, Kind, Msg, Ranges, FixIts);
45  }
46};
47
48} // unnamed namespace
49
50TEST_F(SourceMgrTest, BasicError) {
51  setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
52  printMessage(getLoc(4), SourceMgr::DK_Error, "message", None, None);
53
54  EXPECT_EQ("file.in:1:5: error: message\n"
55            "aaa bbb\n"
56            "    ^\n",
57            Output);
58}
59
60TEST_F(SourceMgrTest, BasicWarning) {
61  setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
62  printMessage(getLoc(4), SourceMgr::DK_Warning, "message", None, None);
63
64  EXPECT_EQ("file.in:1:5: warning: message\n"
65            "aaa bbb\n"
66            "    ^\n",
67            Output);
68}
69
70TEST_F(SourceMgrTest, BasicNote) {
71  setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
72  printMessage(getLoc(4), SourceMgr::DK_Note, "message", None, None);
73
74  EXPECT_EQ("file.in:1:5: note: message\n"
75            "aaa bbb\n"
76            "    ^\n",
77            Output);
78}
79
80TEST_F(SourceMgrTest, LocationAtEndOfLine) {
81  setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
82  printMessage(getLoc(6), SourceMgr::DK_Error, "message", None, None);
83
84  EXPECT_EQ("file.in:1:7: error: message\n"
85            "aaa bbb\n"
86            "      ^\n",
87            Output);
88}
89
90TEST_F(SourceMgrTest, LocationAtNewline) {
91  setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
92  printMessage(getLoc(7), SourceMgr::DK_Error, "message", None, None);
93
94  EXPECT_EQ("file.in:1:8: error: message\n"
95            "aaa bbb\n"
96            "       ^\n",
97            Output);
98}
99
100TEST_F(SourceMgrTest, BasicRange) {
101  setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
102  printMessage(getLoc(4), SourceMgr::DK_Error, "message", getRange(4, 3), None);
103
104  EXPECT_EQ("file.in:1:5: error: message\n"
105            "aaa bbb\n"
106            "    ^~~\n",
107            Output);
108}
109
110TEST_F(SourceMgrTest, RangeWithTab) {
111  setMainBuffer("aaa\tbbb\nccc ddd\n", "file.in");
112  printMessage(getLoc(4), SourceMgr::DK_Error, "message", getRange(3, 3), None);
113
114  EXPECT_EQ("file.in:1:5: error: message\n"
115            "aaa     bbb\n"
116            "   ~~~~~^~\n",
117            Output);
118}
119
120TEST_F(SourceMgrTest, MultiLineRange) {
121  setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
122  printMessage(getLoc(4), SourceMgr::DK_Error, "message", getRange(4, 7), None);
123
124  EXPECT_EQ("file.in:1:5: error: message\n"
125            "aaa bbb\n"
126            "    ^~~\n",
127            Output);
128}
129
130TEST_F(SourceMgrTest, MultipleRanges) {
131  setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
132  SMRange Ranges[] = { getRange(0, 3), getRange(4, 3) };
133  printMessage(getLoc(4), SourceMgr::DK_Error, "message", Ranges, None);
134
135  EXPECT_EQ("file.in:1:5: error: message\n"
136            "aaa bbb\n"
137            "~~~ ^~~\n",
138            Output);
139}
140
141TEST_F(SourceMgrTest, OverlappingRanges) {
142  setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
143  SMRange Ranges[] = { getRange(0, 3), getRange(2, 4) };
144  printMessage(getLoc(4), SourceMgr::DK_Error, "message", Ranges, None);
145
146  EXPECT_EQ("file.in:1:5: error: message\n"
147            "aaa bbb\n"
148            "~~~~^~\n",
149            Output);
150}
151
152TEST_F(SourceMgrTest, BasicFixit) {
153  setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
154  printMessage(getLoc(4), SourceMgr::DK_Error, "message", None,
155               makeArrayRef(SMFixIt(getRange(4, 3), "zzz")));
156
157  EXPECT_EQ("file.in:1:5: error: message\n"
158            "aaa bbb\n"
159            "    ^~~\n"
160            "    zzz\n",
161            Output);
162}
163
164TEST_F(SourceMgrTest, FixitForTab) {
165  setMainBuffer("aaa\tbbb\nccc ddd\n", "file.in");
166  printMessage(getLoc(3), SourceMgr::DK_Error, "message", None,
167               makeArrayRef(SMFixIt(getRange(3, 1), "zzz")));
168
169  EXPECT_EQ("file.in:1:4: error: message\n"
170            "aaa     bbb\n"
171            "   ^^^^^\n"
172            "   zzz\n",
173            Output);
174}
175
176