xref: /llvm-project/clang/unittests/Frontend/TextDiagnosticTest.cpp (revision 7db641af13670aa1f1ecd3106eda3ce447afd752)
1659f4bd8SRaphael Isemann //===- unittests/Frontend/TextDiagnosticTest.cpp - ------------------------===//
2659f4bd8SRaphael Isemann //
3659f4bd8SRaphael Isemann // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4659f4bd8SRaphael Isemann // See https://llvm.org/LICENSE.txt for license information.
5659f4bd8SRaphael Isemann // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6659f4bd8SRaphael Isemann //
7659f4bd8SRaphael Isemann //===----------------------------------------------------------------------===//
8659f4bd8SRaphael Isemann 
9659f4bd8SRaphael Isemann #include "clang/Frontend/TextDiagnostic.h"
10659f4bd8SRaphael Isemann #include "clang/Basic/FileManager.h"
11659f4bd8SRaphael Isemann #include "clang/Basic/LangOptions.h"
12659f4bd8SRaphael Isemann #include "clang/Basic/SourceManager.h"
13659f4bd8SRaphael Isemann #include "llvm/Support/SmallVectorMemoryBuffer.h"
14659f4bd8SRaphael Isemann #include "gtest/gtest.h"
15659f4bd8SRaphael Isemann 
16659f4bd8SRaphael Isemann using namespace llvm;
17659f4bd8SRaphael Isemann using namespace clang;
18659f4bd8SRaphael Isemann 
19659f4bd8SRaphael Isemann namespace {
20659f4bd8SRaphael Isemann 
21659f4bd8SRaphael Isemann /// Prints a diagnostic with the given DiagnosticOptions and the given
22659f4bd8SRaphael Isemann /// SourceLocation and returns the printed diagnostic text.
23659f4bd8SRaphael Isemann static std::string PrintDiag(const DiagnosticOptions &Opts, FullSourceLoc Loc) {
24659f4bd8SRaphael Isemann   std::string Out;
25659f4bd8SRaphael Isemann   llvm::raw_string_ostream OS(Out);
26659f4bd8SRaphael Isemann   clang::LangOptions LangOpts;
27659f4bd8SRaphael Isemann   // Owned by TextDiagnostic.
28659f4bd8SRaphael Isemann   DiagnosticOptions *DiagOpts = new DiagnosticOptions(Opts);
29659f4bd8SRaphael Isemann   TextDiagnostic Diag(OS, LangOpts, DiagOpts);
30659f4bd8SRaphael Isemann   // Emit a dummy diagnostic that is just 'message'.
31659f4bd8SRaphael Isemann   Diag.emitDiagnostic(Loc, DiagnosticsEngine::Level::Warning, "message",
32659f4bd8SRaphael Isemann                       /*Ranges=*/{}, /*FixItHints=*/{});
33659f4bd8SRaphael Isemann   return Out;
34659f4bd8SRaphael Isemann }
35659f4bd8SRaphael Isemann 
36659f4bd8SRaphael Isemann TEST(TextDiagnostic, ShowLine) {
37659f4bd8SRaphael Isemann   // Create dummy FileManager and SourceManager.
38659f4bd8SRaphael Isemann   FileSystemOptions FSOpts;
39659f4bd8SRaphael Isemann   FileManager FileMgr(FSOpts);
40659f4bd8SRaphael Isemann   IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs);
41659f4bd8SRaphael Isemann   DiagnosticsEngine DiagEngine(DiagID, new DiagnosticOptions,
42659f4bd8SRaphael Isemann                                new IgnoringDiagConsumer());
43659f4bd8SRaphael Isemann   SourceManager SrcMgr(DiagEngine, FileMgr);
44659f4bd8SRaphael Isemann 
45659f4bd8SRaphael Isemann   // Create a dummy file with some contents to produce a test SourceLocation.
46659f4bd8SRaphael Isemann   const llvm::StringRef file_path = "main.cpp";
47659f4bd8SRaphael Isemann   const llvm::StringRef main_file_contents = "some\nsource\ncode\n";
48a6004321SDuncan P. N. Exon Smith   const clang::FileEntryRef fe = FileMgr.getVirtualFileRef(
49659f4bd8SRaphael Isemann       file_path,
50659f4bd8SRaphael Isemann       /*Size=*/static_cast<off_t>(main_file_contents.size()),
51659f4bd8SRaphael Isemann       /*ModificationTime=*/0);
52659f4bd8SRaphael Isemann 
53659f4bd8SRaphael Isemann   llvm::SmallVector<char, 64> buffer;
54659f4bd8SRaphael Isemann   buffer.append(main_file_contents.begin(), main_file_contents.end());
55659f4bd8SRaphael Isemann   auto file_contents = std::make_unique<llvm::SmallVectorMemoryBuffer>(
56*d0262c23SJan Svoboda       std::move(buffer), file_path, /*RequiresNullTerminator=*/false);
57a6004321SDuncan P. N. Exon Smith   SrcMgr.overrideFileContents(fe, std::move(file_contents));
58659f4bd8SRaphael Isemann 
59659f4bd8SRaphael Isemann   // Create the actual file id and use it as the main file.
60659f4bd8SRaphael Isemann   clang::FileID fid =
61a6004321SDuncan P. N. Exon Smith       SrcMgr.createFileID(fe, SourceLocation(), clang::SrcMgr::C_User);
62659f4bd8SRaphael Isemann   SrcMgr.setMainFileID(fid);
63659f4bd8SRaphael Isemann 
64659f4bd8SRaphael Isemann   // Create the source location for the test diagnostic.
65659f4bd8SRaphael Isemann   FullSourceLoc Loc(SrcMgr.translateLineCol(fid, /*Line=*/1, /*Col=*/2),
66659f4bd8SRaphael Isemann                     SrcMgr);
67659f4bd8SRaphael Isemann 
68659f4bd8SRaphael Isemann   DiagnosticOptions DiagOpts;
69659f4bd8SRaphael Isemann   DiagOpts.ShowLine = true;
70659f4bd8SRaphael Isemann   DiagOpts.ShowColumn = true;
71659f4bd8SRaphael Isemann   // Hide printing the source line/caret to make the diagnostic shorter and it's
72659f4bd8SRaphael Isemann   // not relevant for this test.
73659f4bd8SRaphael Isemann   DiagOpts.ShowCarets = false;
74659f4bd8SRaphael Isemann   EXPECT_EQ("main.cpp:1:2: warning: message\n", PrintDiag(DiagOpts, Loc));
75659f4bd8SRaphael Isemann 
76659f4bd8SRaphael Isemann   // Check that ShowLine doesn't influence the Vi/MSVC diagnostic formats as its
77659f4bd8SRaphael Isemann   // a Clang-specific diagnostic option.
78659f4bd8SRaphael Isemann   DiagOpts.setFormat(TextDiagnosticFormat::Vi);
79659f4bd8SRaphael Isemann   DiagOpts.ShowLine = false;
80659f4bd8SRaphael Isemann   EXPECT_EQ("main.cpp +1:2: warning: message\n", PrintDiag(DiagOpts, Loc));
81659f4bd8SRaphael Isemann 
82659f4bd8SRaphael Isemann   DiagOpts.setFormat(TextDiagnosticFormat::MSVC);
83659f4bd8SRaphael Isemann   DiagOpts.ShowLine = false;
84659f4bd8SRaphael Isemann   EXPECT_EQ("main.cpp(1,2): warning: message\n", PrintDiag(DiagOpts, Loc));
85659f4bd8SRaphael Isemann 
86659f4bd8SRaphael Isemann   // Reset back to the Clang format.
87659f4bd8SRaphael Isemann   DiagOpts.setFormat(TextDiagnosticFormat::Clang);
88659f4bd8SRaphael Isemann 
89659f4bd8SRaphael Isemann   // Hide line number but show column.
90659f4bd8SRaphael Isemann   DiagOpts.ShowLine = false;
91659f4bd8SRaphael Isemann   EXPECT_EQ("main.cpp:2: warning: message\n", PrintDiag(DiagOpts, Loc));
92659f4bd8SRaphael Isemann 
93659f4bd8SRaphael Isemann   // Show line number but hide column.
94659f4bd8SRaphael Isemann   DiagOpts.ShowLine = true;
95659f4bd8SRaphael Isemann   DiagOpts.ShowColumn = false;
96659f4bd8SRaphael Isemann   EXPECT_EQ("main.cpp:1: warning: message\n", PrintDiag(DiagOpts, Loc));
97659f4bd8SRaphael Isemann }
98659f4bd8SRaphael Isemann 
99659f4bd8SRaphael Isemann } // anonymous namespace
100