awarzynski updated this revision to Diff 293780.
awarzynski marked 17 inline comments as done.
awarzynski added a comment.
Move code from Fortran to Fortran::frontend namespace, address PR comments
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D87774/new/
https://reviews.llvm.org/D87774
Files:
clang/include/clang/Driver/Options.td
flang/include/flang/Frontend/CompilerInvocation.h
flang/include/flang/Frontend/TextDiagnostic.h
flang/include/flang/Frontend/TextDiagnosticBuffer.h
flang/include/flang/Frontend/TextDiagnosticPrinter.h
flang/lib/Frontend/CMakeLists.txt
flang/lib/Frontend/CompilerInstance.cpp
flang/lib/Frontend/CompilerInvocation.cpp
flang/lib/Frontend/TextDiagnostic.cpp
flang/lib/Frontend/TextDiagnosticBuffer.cpp
flang/lib/Frontend/TextDiagnosticPrinter.cpp
flang/test/Flang-Driver/driver-error-cc1.c
flang/test/Flang-Driver/driver-error-cc1.cpp
flang/test/Flang-Driver/driver-help.f90
flang/test/Flang-Driver/driver-version.f90
flang/test/Flang-Driver/missing-input.f90
flang/tools/flang-driver/driver.cpp
flang/tools/flang-driver/fc1_main.cpp
flang/unittests/Frontend/CompilerInstanceTest.cpp
Index: flang/unittests/Frontend/CompilerInstanceTest.cpp
===================================================================
--- flang/unittests/Frontend/CompilerInstanceTest.cpp
+++ flang/unittests/Frontend/CompilerInstanceTest.cpp
@@ -9,9 +9,9 @@
#include "flang/Frontend/CompilerInstance.h"
#include "gtest/gtest.h"
#include "flang/Frontend/CompilerInvocation.h"
+#include "flang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Driver/Options.h"
-#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvm/Support/raw_ostream.h"
#include <filesystem>
@@ -24,7 +24,7 @@
// 1. Set-up a basic DiagnosticConsumer
std::string diagnosticOutput;
llvm::raw_string_ostream diagnosticsOS(diagnosticOutput);
- auto diagPrinter = std::make_unique<clang::TextDiagnosticPrinter>(
+ auto diagPrinter = std::make_unique<Fortran::TextDiagnosticPrinter>(
diagnosticsOS, new clang::DiagnosticOptions());
// 2. Create a CompilerInstance (to manage a DiagnosticEngine)
Index: flang/tools/flang-driver/fc1_main.cpp
===================================================================
--- flang/tools/flang-driver/fc1_main.cpp
+++ flang/tools/flang-driver/fc1_main.cpp
@@ -14,9 +14,9 @@
#include "flang/Frontend/CompilerInstance.h"
#include "flang/Frontend/CompilerInvocation.h"
+#include "flang/Frontend/TextDiagnosticBuffer.h"
#include "flang/FrontendTool/Utils.h"
#include "clang/Driver/DriverDiagnostic.h"
-#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
@@ -34,18 +34,22 @@
if (!flang->HasDiagnostics())
return 1;
+ // We will buffer diagnostics from argument parsing so that we can output
+ // them using a well formed diagnostic object.
+ TextDiagnosticBuffer *diagsBuffer = new TextDiagnosticBuffer;
+
// Create CompilerInvocation - use a dedicated instance of DiagnosticsEngine
// for parsing the arguments
llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagID(
new clang::DiagnosticIDs());
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> diagOpts =
new clang::DiagnosticOptions();
- clang::TextDiagnosticBuffer *diagsBuffer = new clang::TextDiagnosticBuffer;
clang::DiagnosticsEngine diags(diagID, &*diagOpts, diagsBuffer);
bool success =
CompilerInvocation::CreateFromArgs(flang->GetInvocation(), argv, diags);
diagsBuffer->FlushDiagnostics(flang->getDiagnostics());
+
if (!success)
return 1;
Index: flang/tools/flang-driver/driver.cpp
===================================================================
--- flang/tools/flang-driver/driver.cpp
+++ flang/tools/flang-driver/driver.cpp
@@ -11,17 +11,21 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Driver/Driver.h"
+#include "flang/Frontend/CompilerInvocation.h"
+#include "flang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Driver/Compilation.h"
-#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/VirtualFileSystem.h"
+#include <clang/Driver/Options.h>
+
+using llvm::StringRef;
// main frontend method. Lives inside fc1_main.cpp
extern int fc1_main(llvm::ArrayRef<const char *> argv, const char *argv0);
@@ -37,6 +41,17 @@
static clang::DiagnosticOptions *CreateAndPopulateDiagOpts(
llvm::ArrayRef<const char *> argv) {
auto *diagOpts = new clang::DiagnosticOptions;
+
+ // Ignore missingArgCount and the return value of ParseDiagnosticArgs.
+ // Any errors that would be diagnosed here will also be diagnosed later,
+ // when the DiagnosticsEngine actually exists.
+ unsigned missingArgIndex, missingArgCount;
+ llvm::opt::InputArgList args = clang::driver::getDriverOptTable().ParseArgs(
+ argv.slice(1), missingArgIndex, missingArgCount,
+ /*FlagsToInclude=*/clang::driver::options::FlangOption);
+
+ (void)Fortran::frontend::ParseDiagnosticArgs(*diagOpts, args);
+
return diagOpts;
}
@@ -83,8 +98,12 @@
CreateAndPopulateDiagOpts(argv);
llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagID(
new clang::DiagnosticIDs());
- clang::TextDiagnosticPrinter *diagClient =
- new clang::TextDiagnosticPrinter(llvm::errs(), &*diagOpts);
+ Fortran::frontend::TextDiagnosticPrinter *diagClient =
+ new Fortran::frontend::TextDiagnosticPrinter(llvm::errs(), &*diagOpts);
+
+ diagClient->set_prefix(
+ std::string(llvm::sys::path::stem(GetExecutablePath(argv[0]))));
+
clang::DiagnosticsEngine diags(diagID, &*diagOpts, diagClient);
// Prepare the driver
Index: flang/test/Flang-Driver/missing-input.f90
===================================================================
--- flang/test/Flang-Driver/missing-input.f90
+++ flang/test/Flang-Driver/missing-input.f90
@@ -2,4 +2,4 @@
! REQUIRES: new-flang-driver
-! CHECK: error: no input files
+! CHECK: flang-new: error: no input files
Index: flang/test/Flang-Driver/driver-version.f90
===================================================================
--- flang/test/Flang-Driver/driver-version.f90
+++ flang/test/Flang-Driver/driver-version.f90
@@ -8,4 +8,4 @@
! CHECK-NEXT:Thread model:
! CHECK-NEXT:InstalledDir:
-! ERROR: error: unsupported option '--versions'; did you mean '--version'?
+! ERROR: flang-new: error: unsupported option '--versions'; did you mean '--version'?
Index: flang/test/Flang-Driver/driver-help.f90
===================================================================
--- flang/test/Flang-Driver/driver-help.f90
+++ flang/test/Flang-Driver/driver-help.f90
@@ -7,7 +7,9 @@
! CHECK:USAGE: flang-new
! CHECK-EMPTY:
! CHECK-NEXT:OPTIONS:
+! CHECK-NEXT: -fcolor-diagnostics Enable colors in diagnostics
+! CHECK-NEXT: -fno-color-diagnostics Disable colors in diagnostics
! CHECK-NEXT: -help Display available options
! CHECK-NEXT: --version Print version information
-! ERROR: error: unknown argument '-helps'; did you mean '-help'
+! ERROR: flang-new: error: unknown argument '-helps'; did you mean '-help'
Index: flang/test/Flang-Driver/driver-error-cc1.cpp
===================================================================
--- flang/test/Flang-Driver/driver-error-cc1.cpp
+++ flang/test/Flang-Driver/driver-error-cc1.cpp
@@ -4,4 +4,4 @@
// C++ files are currently not supported (i.e. `flang -cc1`)
-// CHECK:error: unknown integrated tool '-cc1'. Valid tools include '-fc1'.
+// CHECK: error: unknown integrated tool '-cc1'. Valid tools include '-fc1'.
Index: flang/test/Flang-Driver/driver-error-cc1.c
===================================================================
--- flang/test/Flang-Driver/driver-error-cc1.c
+++ flang/test/Flang-Driver/driver-error-cc1.c
@@ -4,4 +4,4 @@
// C files are currently not supported (i.e. `flang -cc1`)
-// CHECK:error: unknown integrated tool '-cc1'. Valid tools include '-fc1'.
+// CHECK: error: unknown integrated tool '-cc1'. Valid tools include '-fc1'.
Index: flang/lib/Frontend/TextDiagnosticPrinter.cpp
===================================================================
--- /dev/null
+++ flang/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -0,0 +1,57 @@
+//===--- TextDiagnosticPrinter.cpp - Diagnostic Printer -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This diagnostic client prints out their diagnostic messages.
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Frontend/TextDiagnosticPrinter.h"
+#include "flang/Frontend/TextDiagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace Fortran::frontend;
+
+using llvm::SmallString;
+
+TextDiagnosticPrinter::TextDiagnosticPrinter(
+ raw_ostream &os, clang::DiagnosticOptions *diags)
+ : os_(os), diagOpts_(diags) {}
+
+TextDiagnosticPrinter::~TextDiagnosticPrinter() {}
+
+void TextDiagnosticPrinter::HandleDiagnostic(
+ clang::DiagnosticsEngine::Level level, const clang::Diagnostic &info) {
+ // Default implementation (Warnings/errors count).
+ DiagnosticConsumer::HandleDiagnostic(level, info);
+
+ // Render the diagnostic message into a temporary buffer eagerly. We'll use
+ // this later as we print out the diagnostic to the terminal.
+ SmallString<100> outStr;
+ info.FormatDiagnostic(outStr);
+
+ llvm::raw_svector_ostream DiagMessageStream(outStr);
+
+ if (!prefix_.empty())
+ os_ << prefix_ << ": ";
+
+ // We only emit diagnostics in contexts that lack valid source locations.
+ assert(!info.getLocation().isValid() &&
+ "Diagnostics with valid source location are not supported");
+
+ Fortran::frontend::TextDiagnostic::PrintDiagnosticLevel(
+ os_, level, diagOpts_->ShowColors);
+ Fortran::frontend::TextDiagnostic::PrintDiagnosticMessage(os_,
+ /*IsSupplemental=*/level == clang::DiagnosticsEngine::Note,
+ DiagMessageStream.str(), diagOpts_->ShowColors);
+
+ os_.flush();
+ return;
+}
Index: flang/lib/Frontend/TextDiagnosticBuffer.cpp
===================================================================
--- /dev/null
+++ flang/lib/Frontend/TextDiagnosticBuffer.cpp
@@ -0,0 +1,74 @@
+//===- TextDiagnosticBuffer.cpp - Buffer Text Diagnostics -----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a concrete diagnostic client, which buffers the diagnostic messages.
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace Fortran::frontend;
+
+/// HandleDiagnostic - Store the errors, warnings, and notes that are
+/// reported.
+void TextDiagnosticBuffer::HandleDiagnostic(
+ clang::DiagnosticsEngine::Level level, const clang::Diagnostic &info) {
+ // Default implementation (warnings_/errors count).
+ DiagnosticConsumer::HandleDiagnostic(level, info);
+
+ llvm::SmallString<100> buf;
+ info.FormatDiagnostic(buf);
+ switch (level) {
+ default:
+ llvm_unreachable("Diagnostic not handled during diagnostic buffering!");
+ case clang::DiagnosticsEngine::Note:
+ all_.emplace_back(level, notes_.size());
+ notes_.emplace_back(info.getLocation(), std::string(buf.str()));
+ break;
+ case clang::DiagnosticsEngine::Warning:
+ all_.emplace_back(level, warnings_.size());
+ warnings_.emplace_back(info.getLocation(), std::string(buf.str()));
+ break;
+ case clang::DiagnosticsEngine::Remark:
+ all_.emplace_back(level, remarks_.size());
+ remarks_.emplace_back(info.getLocation(), std::string(buf.str()));
+ break;
+ case clang::DiagnosticsEngine::Error:
+ case clang::DiagnosticsEngine::Fatal:
+ all_.emplace_back(level, errors_.size());
+ errors_.emplace_back(info.getLocation(), std::string(buf.str()));
+ break;
+ }
+}
+
+void TextDiagnosticBuffer::FlushDiagnostics(
+ clang::DiagnosticsEngine &Diags) const {
+ for (const auto &i : all_) {
+ auto Diag = Diags.Report(Diags.getCustomDiagID(i.first, "%0"));
+ switch (i.first) {
+ default:
+ llvm_unreachable("Diagnostic not handled during diagnostic flushing!");
+ case clang::DiagnosticsEngine::Note:
+ Diag << notes_[i.second].second;
+ break;
+ case clang::DiagnosticsEngine::Warning:
+ Diag << warnings_[i.second].second;
+ break;
+ case clang::DiagnosticsEngine::Remark:
+ Diag << remarks_[i.second].second;
+ break;
+ case clang::DiagnosticsEngine::Error:
+ case clang::DiagnosticsEngine::Fatal:
+ Diag << errors_[i.second].second;
+ break;
+ }
+ }
+}
Index: flang/lib/Frontend/TextDiagnostic.cpp
===================================================================
--- /dev/null
+++ flang/lib/Frontend/TextDiagnostic.cpp
@@ -0,0 +1,97 @@
+//===--- TextDiagnostic.cpp - Text Diagnostic Pretty-Printing -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Frontend/TextDiagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace Fortran::frontend;
+
+// TODO: Similar enums are defined in clang/lib/Frontend/TextDiagnostic.cpp.
+// It would be best to share them
+static const enum llvm::raw_ostream::Colors noteColor =
+ llvm::raw_ostream::BLACK;
+static const enum llvm::raw_ostream::Colors remarkColor =
+ llvm::raw_ostream::BLUE;
+static const enum llvm::raw_ostream::Colors warningColor =
+ llvm::raw_ostream::MAGENTA;
+static const enum llvm::raw_ostream::Colors errorColor = llvm::raw_ostream::RED;
+static const enum llvm::raw_ostream::Colors fatalColor = llvm::raw_ostream::RED;
+// Used for changing only the bold attribute.
+static const enum llvm::raw_ostream::Colors savedColor =
+ llvm::raw_ostream::SAVEDCOLOR;
+
+TextDiagnostic::TextDiagnostic() {}
+
+TextDiagnostic::~TextDiagnostic() {}
+
+/*static*/ void TextDiagnostic::PrintDiagnosticLevel(llvm::raw_ostream &os,
+ clang::DiagnosticsEngine::Level level, bool showColors) {
+ if (showColors) {
+ // Print diagnostic category in bold and color
+ switch (level) {
+ case clang::DiagnosticsEngine::Ignored:
+ llvm_unreachable("Invalid diagnostic type");
+ case clang::DiagnosticsEngine::Note:
+ os.changeColor(noteColor, true);
+ break;
+ case clang::DiagnosticsEngine::Remark:
+ os.changeColor(remarkColor, true);
+ break;
+ case clang::DiagnosticsEngine::Warning:
+ os.changeColor(warningColor, true);
+ break;
+ case clang::DiagnosticsEngine::Error:
+ os.changeColor(errorColor, true);
+ break;
+ case clang::DiagnosticsEngine::Fatal:
+ os.changeColor(fatalColor, true);
+ break;
+ }
+ }
+
+ switch (level) {
+ case clang::DiagnosticsEngine::Ignored:
+ llvm_unreachable("Invalid diagnostic type");
+ case clang::DiagnosticsEngine::Note:
+ os << "note";
+ break;
+ case clang::DiagnosticsEngine::Remark:
+ os << "remark";
+ break;
+ case clang::DiagnosticsEngine::Warning:
+ os << "warning";
+ break;
+ case clang::DiagnosticsEngine::Error:
+ os << "error";
+ break;
+ case clang::DiagnosticsEngine::Fatal:
+ os << "fatal error";
+ break;
+ }
+
+ os << ": ";
+
+ if (showColors)
+ os.resetColor();
+}
+
+/*static*/
+void TextDiagnostic::PrintDiagnosticMessage(llvm::raw_ostream &os,
+ bool isSupplemental, llvm::StringRef message, bool showColors) {
+ if (showColors && !isSupplemental) {
+ // Print primary diagnostic messages in bold and without color.
+ os.changeColor(savedColor, true);
+ }
+
+ os << message;
+
+ if (showColors)
+ os.resetColor();
+ os << '\n';
+}
Index: flang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- flang/lib/Frontend/CompilerInvocation.cpp
+++ flang/lib/Frontend/CompilerInvocation.cpp
@@ -17,6 +17,7 @@
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
+#include "llvm/Support/Process.h"
#include "llvm/Support/raw_ostream.h"
using namespace Fortran::frontend;
@@ -35,6 +36,49 @@
//===----------------------------------------------------------------------===//
// Deserialization (from args)
//===----------------------------------------------------------------------===//
+static bool parseShowColorsArgs(
+ const llvm::opt::ArgList &args, bool defaultColor) {
+ // Color diagnostics default to auto ("on" if terminal supports) in the driver
+ // but default to off in cc1, needing an explicit OPT_fdiagnostics_color.
+ // Support both clang's -f[no-]color-diagnostics and gcc's
+ // -f[no-]diagnostics-colors[=never|always|auto].
+ enum {
+ Colors_On,
+ Colors_Off,
+ Colors_Auto
+ } ShowColors = defaultColor ? Colors_Auto : Colors_Off;
+
+ for (auto *a : args) {
+ const llvm::opt::Option &O = a->getOption();
+ if (O.matches(clang::driver::options::OPT_fcolor_diagnostics) ||
+ O.matches(clang::driver::options::OPT_fdiagnostics_color)) {
+ ShowColors = Colors_On;
+ } else if (O.matches(clang::driver::options::OPT_fno_color_diagnostics) ||
+ O.matches(clang::driver::options::OPT_fno_diagnostics_color)) {
+ ShowColors = Colors_Off;
+ } else if (O.matches(clang::driver::options::OPT_fdiagnostics_color_EQ)) {
+ llvm::StringRef value(a->getValue());
+ if (value == "always")
+ ShowColors = Colors_On;
+ else if (value == "never")
+ ShowColors = Colors_Off;
+ else if (value == "auto")
+ ShowColors = Colors_Auto;
+ }
+ }
+
+ return ShowColors == Colors_On ||
+ (ShowColors == Colors_Auto && llvm::sys::Process::StandardErrHasColors());
+}
+
+bool Fortran::frontend::ParseDiagnosticArgs(clang::DiagnosticOptions &opts,
+ llvm::opt::ArgList &args, clang::DiagnosticsEngine *diags,
+ bool defaultDiagColor) {
+ opts.ShowColors = parseShowColorsArgs(args, defaultDiagColor);
+
+ return true;
+}
+
static InputKind ParseFrontendArgs(FrontendOptions &opts,
llvm::opt::ArgList &args, clang::DiagnosticsEngine &diags) {
// Identify the action (i.e. opts.ProgramAction)
Index: flang/lib/Frontend/CompilerInstance.cpp
===================================================================
--- flang/lib/Frontend/CompilerInstance.cpp
+++ flang/lib/Frontend/CompilerInstance.cpp
@@ -8,7 +8,7 @@
#include "flang/Frontend/CompilerInstance.h"
#include "flang/Frontend/CompilerInvocation.h"
-#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "flang/Frontend/TextDiagnosticPrinter.h"
#include "llvm/Support/raw_ostream.h"
using namespace Fortran::frontend;
@@ -36,7 +36,7 @@
if (client) {
diags->setClient(client, shouldOwnClient);
} else {
- diags->setClient(new clang::TextDiagnosticPrinter(llvm::errs(), opts));
+ diags->setClient(new TextDiagnosticPrinter(llvm::errs(), opts));
}
return diags;
}
Index: flang/lib/Frontend/CMakeLists.txt
===================================================================
--- flang/lib/Frontend/CMakeLists.txt
+++ flang/lib/Frontend/CMakeLists.txt
@@ -2,13 +2,13 @@
CompilerInstance.cpp
CompilerInvocation.cpp
FrontendOptions.cpp
+ TextDiagnosticPrinter.cpp
+ TextDiagnosticBuffer.cpp
+ TextDiagnostic.cpp
LINK_LIBS
clangBasic
clangDriver
- # TODO: Added to re-use clang's TextDiagnosticBuffer & TextDiagnosticPrinter.
- # Add a custom implementation for Flang and remove this dependency.
- clangFrontend
LINK_COMPONENTS
Option
Index: flang/include/flang/Frontend/TextDiagnosticPrinter.h
===================================================================
--- /dev/null
+++ flang/include/flang/Frontend/TextDiagnosticPrinter.h
@@ -0,0 +1,55 @@
+//===--- TextDiagnosticPrinter.h - Text Diagnostic Client -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a concrete diagnostic client. In terminals that support it, the
+// diagnostics are pretty-printed (colors + bold). The printing/flushing
+// happens in HandleDiagnostics (usually called at the point when the
+// diagnostic is generated).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FLANG_FRONTEND_TEXTDIAGNOSTICPRINTER_H
+#define LLVM_FLANG_FRONTEND_TEXTDIAGNOSTICPRINTER_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+class DiagnosticOptions;
+class DiagnosticsEngine;
+}; // namespace clang
+
+using llvm::IntrusiveRefCntPtr;
+using llvm::raw_ostream;
+
+namespace Fortran::frontend {
+class TextDiagnostic;
+
+class TextDiagnosticPrinter : public clang::DiagnosticConsumer {
+ raw_ostream &os_;
+ llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> diagOpts_;
+
+ /// A string to prefix to error messages.
+ std::string prefix_;
+
+public:
+ TextDiagnosticPrinter(raw_ostream &os, clang::DiagnosticOptions *diags);
+ ~TextDiagnosticPrinter() override;
+
+ /// Set the diagnostic printer prefix string, which will be printed at the
+ /// start of any diagnostics. If empty, no prefix string is used.
+ void set_prefix(std::string value) { prefix_ = std::move(value); }
+
+ void HandleDiagnostic(clang::DiagnosticsEngine::Level level,
+ const clang::Diagnostic &info) override;
+};
+
+} // namespace Fortran::frontend
+
+#endif
Index: flang/include/flang/Frontend/TextDiagnosticBuffer.h
===================================================================
--- /dev/null
+++ flang/include/flang/Frontend/TextDiagnosticBuffer.h
@@ -0,0 +1,52 @@
+//===- TextDiagnosticBuffer.h - Buffer Text Diagnostics ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a concrete diagnostic client. The diagnostics are buffered rather
+// than printed. In order to print them, use the FlushDiagnostics method.
+// Pretty-printing is not supported.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FLANG_FRONTEND_TEXTDIAGNOSTICBUFFER_H
+#define LLVM_FLANG_FRONTEND_TEXTDIAGNOSTICBUFFER_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include <cstddef>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace Fortran::frontend {
+
+class TextDiagnosticBuffer : public clang::DiagnosticConsumer {
+public:
+ using DiagList = std::vector<std::pair<clang::SourceLocation, std::string>>;
+ using DiagnosticsLevelAndIndexPairs =
+ std::vector<std::pair<clang::DiagnosticsEngine::Level, size_t>>;
+
+private:
+ DiagList errors_, warnings_, remarks_, notes_;
+
+ /// All diagnostics in the order in which they were generated. That order
+ /// likely doesn't correspond to user input order, but at least it keeps
+ /// notes in the right places. Each pair is a diagnostic level and an index
+ /// into the corresponding DiagList above.
+ DiagnosticsLevelAndIndexPairs all_;
+
+public:
+ void HandleDiagnostic(clang::DiagnosticsEngine::Level diagLevel,
+ const clang::Diagnostic &info) override;
+
+ /// Flush the buffered diagnostics to a given diagnostic engine.
+ void FlushDiagnostics(clang::DiagnosticsEngine &diags) const;
+};
+
+} // namespace Fortran::frontend
+
+#endif // LLVM_CLANG_FRONTEND_TEXTDIAGNOSTICBUFFER_H
Index: flang/include/flang/Frontend/TextDiagnostic.h
===================================================================
--- /dev/null
+++ flang/include/flang/Frontend/TextDiagnostic.h
@@ -0,0 +1,70 @@
+//===--- TextDiagnostic.h - Text Diagnostic Pretty-Printing -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// A utility class that provides support for textual pretty-printing of
+// diagnostics. Based on clang::TextDiagnostic (this is a trimmed version).
+//
+// TODO: If expanding, consider sharing the implementation with Clang.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FLANG_FRONTEND_TEXTDIAGNOSTIC_H
+#define LLVM_FLANG_FRONTEND_TEXTDIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+
+namespace Fortran::frontend {
+
+/// Class to encapsulate the logic for formatting and printing a textual
+/// diagnostic message.
+///
+/// The purpose of this class is to isolate the implementation of printing
+/// beautiful text diagnostics from any particular interfaces. Currently only
+/// simple diagnostics that lack source location information are supported (e.g.
+/// Flang driver errors).
+///
+/// In the future we can extend this class (akin to Clang) to support more
+/// complex diagnostics that would include macro backtraces, caret diagnostics,
+/// FixIt Hints and code snippets.
+///
+class TextDiagnostic {
+public:
+ TextDiagnostic();
+
+ ~TextDiagnostic();
+
+ /// Print the diagnostic level to a llvm::raw_ostream.
+ ///
+ /// This is a static helper that handles colorizing the level and formatting
+ /// it into an arbitrary output stream.
+ ///
+ /// \param os Where the message is printed
+ /// \param level The diagnostic level (e.g. error or warning)
+ /// \param showColors Enable colorizing of the message.
+ static void PrintDiagnosticLevel(llvm::raw_ostream &os,
+ clang::DiagnosticsEngine::Level level, bool showColors);
+
+ /// Pretty-print a diagnostic message to a llvm::raw_ostream.
+ ///
+ /// This is a static helper to handle the colorizing and rendering diagnostic
+ /// message to a particular ostream. In the future we can
+ /// extend it to support e.g. line wrapping. It is
+ /// publicly visible as at this stage we don't require any state data to
+ /// print a diagnostic.
+ ///
+ /// \param os Where the message is printed
+ /// \param isSupplemental true if this is a continuation note diagnostic
+ /// \param message The text actually printed
+ /// \param showColors Enable colorizing of the message.
+ static void PrintDiagnosticMessage(llvm::raw_ostream &os, bool isSupplemental,
+ llvm::StringRef message, bool showColors);
+};
+
+} // namespace Fortran::frontend
+
+#endif
Index: flang/include/flang/Frontend/CompilerInvocation.h
===================================================================
--- flang/include/flang/Frontend/CompilerInvocation.h
+++ flang/include/flang/Frontend/CompilerInvocation.h
@@ -11,8 +11,18 @@
#include "flang/Frontend/FrontendOptions.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
+#include "llvm/Option/ArgList.h"
namespace Fortran::frontend {
+
+/// Fill out Opts based on the options given in Args.
+///
+/// When errors are encountered, return false and, if Diags is non-null,
+/// report the error(s).
+bool ParseDiagnosticArgs(clang::DiagnosticOptions &opts,
+ llvm::opt::ArgList &args, clang::DiagnosticsEngine *diags = nullptr,
+ bool defaultDiagColor = true);
+
class CompilerInvocationBase {
public:
/// Options controlling the diagnostic engine.$
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -870,7 +870,8 @@
Flags<[CC1Option]>, MetaVarName<"<version>">, Values<"<major>.<minor>,latest">,
HelpText<"Attempt to match the ABI of Clang <version>">;
def fclasspath_EQ : Joined<["-"], "fclasspath=">, Group<f_Group>;
-defm color_diagnostics : OptInFFlag<"color-diagnostics", "Enable", "Disable", " colors in diagnostics", [CoreOption]>;
+defm color_diagnostics : OptInFFlag<"color-diagnostics", "Enable", "Disable", " colors in diagnostics",
+ [CoreOption, FlangOption]>;
def fdiagnostics_color : Flag<["-"], "fdiagnostics-color">, Group<f_Group>,
Flags<[CoreOption, DriverOption]>;
def fdiagnostics_color_EQ : Joined<["-"], "fdiagnostics-color=">, Group<f_Group>;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits