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