From d79e2e8bfa07c7797891d44b7d084910947bf0a7 Mon Sep 17 00:00:00 2001 From: Denis Matousek Date: Wed, 11 Oct 2023 20:12:59 +0200 Subject: [PATCH] Added support of info messages (#4184) * Added support of info messages * Fixed code style --- frontends/common/parser_options.cpp | 15 +++++++++++--- frontends/common/parser_options.h | 10 +++++++++ lib/compile_context.cpp | 4 ++++ lib/compile_context.h | 3 +++ lib/error.h | 27 ++++++++++++++++++++++++ lib/error_catalog.cpp | 9 +++++++- lib/error_catalog.h | 6 ++++++ lib/error_message.cpp | 5 +++++ lib/error_message.h | 2 +- lib/error_reporter.h | 32 +++++++++++++++++++++++++---- 10 files changed, 104 insertions(+), 9 deletions(-) diff --git a/frontends/common/parser_options.cpp b/frontends/common/parser_options.cpp index b4ed904925..81791f0a7e 100644 --- a/frontends/common/parser_options.cpp +++ b/frontends/common/parser_options.cpp @@ -202,6 +202,15 @@ ParserOptions::ParserOptions() : Util::Options(defaultMessage) { "Disable a compiler diagnostic, or disable all warnings if no " "diagnostic is specified.", OptionFlags::OptionalArgument); + registerOption( + "--Winfo", "diagnostic", + [](const char *diagnostic) { + if (diagnostic) { + P4CContext::get().setDiagnosticAction(diagnostic, DiagnosticAction::Info); + } + return true; + }, + "Report an info message for a compiler diagnostic.", OptionFlags::OptionalArgument); registerOption( "--Wwarn", "diagnostic", [](const char *diagnostic) { @@ -209,12 +218,12 @@ ParserOptions::ParserOptions() : Util::Options(defaultMessage) { P4CContext::get().setDiagnosticAction(diagnostic, DiagnosticAction::Warn); } else { auto action = DiagnosticAction::Warn; - P4CContext::get().setDefaultWarningDiagnosticAction(action); + P4CContext::get().setDefaultInfoDiagnosticAction(action); } return true; }, - "Report a warning for a compiler diagnostic, or treat all warnings " - "as warnings (the default) if no diagnostic is specified.", + "Report a warning for a compiler diagnostic, or treat all info messages as " + "warnings if no diagnostic is specified.", OptionFlags::OptionalArgument); registerOption( "--Werror", "diagnostic", diff --git a/frontends/common/parser_options.h b/frontends/common/parser_options.h index 269a7da887..29d30b75c1 100644 --- a/frontends/common/parser_options.h +++ b/frontends/common/parser_options.h @@ -115,6 +115,16 @@ class P4CContext : public BaseCompileContext { /// @return the compiler options for this compilation context. virtual ParserOptions &options() = 0; + /// @return the default diagnostic action for calls to `::info()`. + DiagnosticAction getDefaultInfoDiagnosticAction() final { + return errorReporter().getDefaultInfoDiagnosticAction(); + } + + /// set the default diagnostic action for calls to `::info()`. + void setDefaultInfoDiagnosticAction(DiagnosticAction action) { + errorReporter().setDefaultInfoDiagnosticAction(action); + } + /// @return the default diagnostic action for calls to `::warning()`. DiagnosticAction getDefaultWarningDiagnosticAction() final { return errorReporter().getDefaultWarningDiagnosticAction(); diff --git a/lib/compile_context.cpp b/lib/compile_context.cpp index fbabfd0645..0aa855ba0b 100644 --- a/lib/compile_context.cpp +++ b/lib/compile_context.cpp @@ -67,6 +67,10 @@ BaseCompileContext::BaseCompileContext(const BaseCompileContext &other) ErrorReporter &BaseCompileContext::errorReporter() { return errorReporterInstance; } +DiagnosticAction BaseCompileContext::getDefaultInfoDiagnosticAction() { + return DiagnosticAction::Info; +} + DiagnosticAction BaseCompileContext::getDefaultWarningDiagnosticAction() { return DiagnosticAction::Warn; } diff --git a/lib/compile_context.h b/lib/compile_context.h index 12c53f43c3..fac357d419 100644 --- a/lib/compile_context.h +++ b/lib/compile_context.h @@ -93,6 +93,9 @@ class BaseCompileContext : public ICompileContext { /// @return the error reporter for this compilation context. virtual ErrorReporter &errorReporter(); + /// @return the default diagnostic action for calls to `::info()`. + virtual DiagnosticAction getDefaultInfoDiagnosticAction(); + /// @return the default diagnostic action for calls to `::warning()`. virtual DiagnosticAction getDefaultWarningDiagnosticAction(); diff --git a/lib/error.h b/lib/error.h index 1b43523e16..a4f1796209 100644 --- a/lib/error.h +++ b/lib/error.h @@ -149,6 +149,33 @@ void warning(const int kind, const char *format, Args... args) { context.errorReporter().diagnose(action, kind, format, "", std::forward(args)...); } +/// Report info messages of type kind. Requires that the node argument have source info. +template ::value>::type, + class... Args> +void info(const int kind, const char *format, const T *node, Args... args) { + auto &context = BaseCompileContext::get(); + auto action = context.getDefaultInfoDiagnosticAction(); + context.errorReporter().diagnose(action, kind, format, "", node, args...); +} + +/// The const ref variant of the above +template ::value>::type, + class... Args> +void info(const int kind, const char *format, const T &node, Args... args) { + ::info(kind, format, &node, std::forward(args)...); +} + +/// Report info messages of type kind, for messages that do not have a node. +/// These will not be filtered +template +void info(const int kind, const char *format, Args... args) { + auto &context = BaseCompileContext::get(); + auto action = context.getDefaultInfoDiagnosticAction(); + context.errorReporter().diagnose(action, kind, format, "", std::forward(args)...); +} + /** * Trigger a diagnostic message. * diff --git a/lib/error_catalog.cpp b/lib/error_catalog.cpp index b0229841b1..d956786dd5 100644 --- a/lib/error_catalog.cpp +++ b/lib/error_catalog.cpp @@ -67,6 +67,10 @@ const int ErrorType::WARN_DUPLICATE_PRIORITIES = 1021; const int ErrorType::WARN_ENTRIES_OUT_OF_ORDER = 1022; const int ErrorType::WARN_MAX_WARNINGS = 2142; +// ------ Info message ----------- +const int ErrorType::INFO_INFERRED = WARN_MAX_WARNINGS + 1; +const int ErrorType::INFO_MAX_INFOS = 3999; + // map from errorCode to ErrorSig std::map ErrorCatalog::errorCatalog = { // Errors @@ -111,4 +115,7 @@ std::map ErrorCatalog::errorCatalog = { {ErrorType::WARN_IGNORE, "ignore"}, {ErrorType::WARN_INVALID_HEADER, "invalid_header"}, {ErrorType::WARN_DUPLICATE_PRIORITIES, "duplicate_priorities"}, - {ErrorType::WARN_ENTRIES_OUT_OF_ORDER, "entries_out_of_priority_order"}}; + {ErrorType::WARN_ENTRIES_OUT_OF_ORDER, "entries_out_of_priority_order"}, + + // Info messages + {ErrorType::INFO_INFERRED, "inferred"}}; diff --git a/lib/error_catalog.h b/lib/error_catalog.h index 9138480795..fef5b8d33e 100644 --- a/lib/error_catalog.h +++ b/lib/error_catalog.h @@ -79,6 +79,12 @@ class ErrorType { static const int WARN_ENTRIES_OUT_OF_ORDER; // entries with priorities out of order static const int WARN_MAX_WARNINGS; + + // -------- Info messages ------------- + // info messages as initially defined with a format string + static const int INFO_INFERRED; // information inferred by compiler + + static const int INFO_MAX_INFOS; }; class ErrorCatalog { diff --git a/lib/error_message.cpp b/lib/error_message.cpp index 4950c38595..14f391c027 100644 --- a/lib/error_message.cpp +++ b/lib/error_message.cpp @@ -12,6 +12,11 @@ std::string ErrorMessage::getPrefix() const { p = "warning: "; else p = "[--Wwarn=" + p + "] warning: "; + } else if (type == MessageType::Info) { + if (p.empty()) + p = "info: "; + else + p = "[--Winfo=" + p + "] info: "; } return p; } diff --git a/lib/error_message.h b/lib/error_message.h index dd4bfa2cb6..45436a494a 100644 --- a/lib/error_message.h +++ b/lib/error_message.h @@ -34,7 +34,7 @@ limitations under the License. * directly and those uses need to call toString() on returned object. */ struct ErrorMessage { - enum class MessageType : std::size_t { None, Error, Warning }; + enum class MessageType : std::size_t { None, Error, Warning, Info }; MessageType type = MessageType::None; std::string prefix = ""; /// Typically error/warning type from catalog diff --git a/lib/error_reporter.h b/lib/error_reporter.h index 91dff312a9..205249e703 100644 --- a/lib/error_reporter.h +++ b/lib/error_reporter.h @@ -24,6 +24,7 @@ limitations under the License. /// An action to take when a diagnostic message is triggered. enum class DiagnosticAction { Ignore, /// Take no action and continue compilation. + Info, /// Print an info message and continue compilation. Warn, /// Print a warning and continue compilation. Error /// Print an error and signal that compilation should be aborted. }; @@ -35,8 +36,9 @@ enum class DiagnosticAction { // Some compatibility for printf-style arguments is also supported. class ErrorReporter { protected: - unsigned int errorCount; + unsigned int infoCount; unsigned int warningCount; + unsigned int errorCount; unsigned int maxErrorCount; /// the maximum number of errors that we print before fail std::ostream *outputstream; @@ -72,9 +74,11 @@ class ErrorReporter { public: ErrorReporter() - : errorCount(0), + : infoCount(0), warningCount(0), + errorCount(0), maxErrorCount(20), + defaultInfoDiagnosticAction(DiagnosticAction::Info), defaultWarningDiagnosticAction(DiagnosticAction::Warn) { outputstream = &std::cerr; } @@ -138,7 +142,14 @@ class ErrorReporter { if (action == DiagnosticAction::Ignore) return; ErrorMessage::MessageType msgType = ErrorMessage::MessageType::None; - if (action == DiagnosticAction::Warn) { + if (action == DiagnosticAction::Info) { + // Avoid burying errors in a pile of info messages: + // don't emit any more info messages if we've emitted errors. + if (errorCount > 0) return; + + infoCount++; + msgType = ErrorMessage::MessageType::Info; + } else if (action == DiagnosticAction::Warn) { // Avoid burying errors in a pile of warnings: don't emit any more warnings if we've // emitted errors. if (errorCount > 0) return; @@ -171,9 +182,11 @@ class ErrorReporter { unsigned getWarningCount() const { return warningCount; } + unsigned getInfoCount() const { return infoCount; } + /// @return the number of diagnostics (warnings and errors) encountered /// in the current CompileContext. - unsigned getDiagnosticCount() const { return errorCount + warningCount; } + unsigned getDiagnosticCount() const { return errorCount + warningCount + infoCount; } void setOutputStream(std::ostream *stream) { outputstream = stream; } @@ -241,7 +254,18 @@ class ErrorReporter { defaultWarningDiagnosticAction = action; } + /// @return the default diagnostic action for calls to `::info()`. + DiagnosticAction getDefaultInfoDiagnosticAction() { return defaultInfoDiagnosticAction; } + + /// set the default diagnostic action for calls to `::info()`. + void setDefaultInfoDiagnosticAction(DiagnosticAction action) { + defaultInfoDiagnosticAction = action; + } + private: + /// The default diagnostic action for calls to `::info()`. + DiagnosticAction defaultInfoDiagnosticAction; + /// The default diagnostic action for calls to `::warning()`. DiagnosticAction defaultWarningDiagnosticAction;