1 //===- unittests/Frontend/TextDiagnosticTest.cpp - ------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "clang/Frontend/TextDiagnostic.h"
10 #include "clang/Basic/FileManager.h"
11 #include "clang/Basic/LangOptions.h"
12 #include "clang/Basic/SourceManager.h"
13 #include "llvm/Support/SmallVectorMemoryBuffer.h"
14 #include "gtest/gtest.h"
15
16 using namespace llvm;
17 using namespace clang;
18
19 namespace {
20
21 /// Prints a diagnostic with the given DiagnosticOptions and the given
22 /// SourceLocation and returns the printed diagnostic text.
PrintDiag(const DiagnosticOptions & Opts,FullSourceLoc Loc)23 static std::string PrintDiag(const DiagnosticOptions &Opts, FullSourceLoc Loc) {
24 std::string Out;
25 llvm::raw_string_ostream OS(Out);
26 clang::LangOptions LangOpts;
27 // Owned by TextDiagnostic.
28 DiagnosticOptions *DiagOpts = new DiagnosticOptions(Opts);
29 TextDiagnostic Diag(OS, LangOpts, DiagOpts);
30 // Emit a dummy diagnostic that is just 'message'.
31 Diag.emitDiagnostic(Loc, DiagnosticsEngine::Level::Warning, "message",
32 /*Ranges=*/{}, /*FixItHints=*/{});
33 OS.flush();
34 return Out;
35 }
36
TEST(TextDiagnostic,ShowLine)37 TEST(TextDiagnostic, ShowLine) {
38 // Create dummy FileManager and SourceManager.
39 FileSystemOptions FSOpts;
40 FileManager FileMgr(FSOpts);
41 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs);
42 DiagnosticsEngine DiagEngine(DiagID, new DiagnosticOptions,
43 new IgnoringDiagConsumer());
44 SourceManager SrcMgr(DiagEngine, FileMgr);
45
46 // Create a dummy file with some contents to produce a test SourceLocation.
47 const llvm::StringRef file_path = "main.cpp";
48 const llvm::StringRef main_file_contents = "some\nsource\ncode\n";
49 const clang::FileEntry &fe = *FileMgr.getVirtualFile(
50 file_path,
51 /*Size=*/static_cast<off_t>(main_file_contents.size()),
52 /*ModificationTime=*/0);
53
54 llvm::SmallVector<char, 64> buffer;
55 buffer.append(main_file_contents.begin(), main_file_contents.end());
56 auto file_contents = std::make_unique<llvm::SmallVectorMemoryBuffer>(
57 std::move(buffer), file_path);
58 SrcMgr.overrideFileContents(&fe, std::move(file_contents));
59
60 // Create the actual file id and use it as the main file.
61 clang::FileID fid =
62 SrcMgr.createFileID(&fe, SourceLocation(), clang::SrcMgr::C_User);
63 SrcMgr.setMainFileID(fid);
64
65 // Create the source location for the test diagnostic.
66 FullSourceLoc Loc(SrcMgr.translateLineCol(fid, /*Line=*/1, /*Col=*/2),
67 SrcMgr);
68
69 DiagnosticOptions DiagOpts;
70 DiagOpts.ShowLine = true;
71 DiagOpts.ShowColumn = true;
72 // Hide printing the source line/caret to make the diagnostic shorter and it's
73 // not relevant for this test.
74 DiagOpts.ShowCarets = false;
75 EXPECT_EQ("main.cpp:1:2: warning: message\n", PrintDiag(DiagOpts, Loc));
76
77 // Check that ShowLine doesn't influence the Vi/MSVC diagnostic formats as its
78 // a Clang-specific diagnostic option.
79 DiagOpts.setFormat(TextDiagnosticFormat::Vi);
80 DiagOpts.ShowLine = false;
81 EXPECT_EQ("main.cpp +1:2: warning: message\n", PrintDiag(DiagOpts, Loc));
82
83 DiagOpts.setFormat(TextDiagnosticFormat::MSVC);
84 DiagOpts.ShowLine = false;
85 EXPECT_EQ("main.cpp(1,2): warning: message\n", PrintDiag(DiagOpts, Loc));
86
87 // Reset back to the Clang format.
88 DiagOpts.setFormat(TextDiagnosticFormat::Clang);
89
90 // Hide line number but show column.
91 DiagOpts.ShowLine = false;
92 EXPECT_EQ("main.cpp:2: warning: message\n", PrintDiag(DiagOpts, Loc));
93
94 // Show line number but hide column.
95 DiagOpts.ShowLine = true;
96 DiagOpts.ShowColumn = false;
97 EXPECT_EQ("main.cpp:1: warning: message\n", PrintDiag(DiagOpts, Loc));
98 }
99
100 } // anonymous namespace
101