xref: /llvm-project/clang/unittests/Frontend/TextDiagnosticTest.cpp (revision 7db641af13670aa1f1ecd3106eda3ce447afd752)
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.
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   return Out;
34 }
35 
36 TEST(TextDiagnostic, ShowLine) {
37   // Create dummy FileManager and SourceManager.
38   FileSystemOptions FSOpts;
39   FileManager FileMgr(FSOpts);
40   IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs);
41   DiagnosticsEngine DiagEngine(DiagID, new DiagnosticOptions,
42                                new IgnoringDiagConsumer());
43   SourceManager SrcMgr(DiagEngine, FileMgr);
44 
45   // Create a dummy file with some contents to produce a test SourceLocation.
46   const llvm::StringRef file_path = "main.cpp";
47   const llvm::StringRef main_file_contents = "some\nsource\ncode\n";
48   const clang::FileEntryRef fe = FileMgr.getVirtualFileRef(
49       file_path,
50       /*Size=*/static_cast<off_t>(main_file_contents.size()),
51       /*ModificationTime=*/0);
52 
53   llvm::SmallVector<char, 64> buffer;
54   buffer.append(main_file_contents.begin(), main_file_contents.end());
55   auto file_contents = std::make_unique<llvm::SmallVectorMemoryBuffer>(
56       std::move(buffer), file_path, /*RequiresNullTerminator=*/false);
57   SrcMgr.overrideFileContents(fe, std::move(file_contents));
58 
59   // Create the actual file id and use it as the main file.
60   clang::FileID fid =
61       SrcMgr.createFileID(fe, SourceLocation(), clang::SrcMgr::C_User);
62   SrcMgr.setMainFileID(fid);
63 
64   // Create the source location for the test diagnostic.
65   FullSourceLoc Loc(SrcMgr.translateLineCol(fid, /*Line=*/1, /*Col=*/2),
66                     SrcMgr);
67 
68   DiagnosticOptions DiagOpts;
69   DiagOpts.ShowLine = true;
70   DiagOpts.ShowColumn = true;
71   // Hide printing the source line/caret to make the diagnostic shorter and it's
72   // not relevant for this test.
73   DiagOpts.ShowCarets = false;
74   EXPECT_EQ("main.cpp:1:2: warning: message\n", PrintDiag(DiagOpts, Loc));
75 
76   // Check that ShowLine doesn't influence the Vi/MSVC diagnostic formats as its
77   // a Clang-specific diagnostic option.
78   DiagOpts.setFormat(TextDiagnosticFormat::Vi);
79   DiagOpts.ShowLine = false;
80   EXPECT_EQ("main.cpp +1:2: warning: message\n", PrintDiag(DiagOpts, Loc));
81 
82   DiagOpts.setFormat(TextDiagnosticFormat::MSVC);
83   DiagOpts.ShowLine = false;
84   EXPECT_EQ("main.cpp(1,2): warning: message\n", PrintDiag(DiagOpts, Loc));
85 
86   // Reset back to the Clang format.
87   DiagOpts.setFormat(TextDiagnosticFormat::Clang);
88 
89   // Hide line number but show column.
90   DiagOpts.ShowLine = false;
91   EXPECT_EQ("main.cpp:2: warning: message\n", PrintDiag(DiagOpts, Loc));
92 
93   // Show line number but hide column.
94   DiagOpts.ShowLine = true;
95   DiagOpts.ShowColumn = false;
96   EXPECT_EQ("main.cpp:1: warning: message\n", PrintDiag(DiagOpts, Loc));
97 }
98 
99 } // anonymous namespace
100