mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 17:33:38 +00:00
The objective of this step is two-fold:
- to fix --inhibit-warnings, making it shut up all warning
and informational messages; and
- to ensure that it *stays* fixed, even when after new diagnostics
are added.
As part of this fix, this diff adds a whole bunch of new warning
options, in order to control the warnings that previously were
not controlled by any option. (There was no need for new
informational options.)
As it happens, we have long used severity_informational for messages
that did not report any information about the code being compiled,
but to report actions that the compiler was taking. Create a new
option category, oc_report, for the new options that now control
those diagnostics.
---------------------
compiler/error_spec.m:
Change severity_warning and severity_informational to take an option
as as argument. The semantics is that the diagnostic in which
the severity occurs is conditional on that option, meaning that
it is printed only if that option is set to "yes".
Delete the severity_conditional function symbol from the severity
type, since the mechanism just above handles its only use case.
Define subtypes to represent error_specs in a standard form.
compiler/error_sort.m:
Provide operations to convert error specs into their standard form.
Make the sorting operation itself operate on the standard form.
compiler/write_error_spec.m:
Convert error_specs to standard form before writing them out,
in order to avoid duplicating the code for their standardization.
Change the code that writes out error_specs to operate on the
standard form. Implement the test implicit in the warning and
and informational severities in this code.
compiler/error_util.m:
compiler/compiler_util.m:
Delete operations that do not make sense with the new severity type.
---------------------
compiler/options.m:
Add new options to control all the previously-uncontrolled
warning and informational messages.
NEWS.md:
Announce the *public* new options.
compiler/option_categories.m:
compiler/print_help.m:
Add the new option category, and fake-include it in the help text
and the user guide. (The inclusion is fake because none of the
options in the new category are user visible, meaning the section
containing them is not visible either.)
---------------------
compiler/det_infer_goal.m:
Start a severity warning diagnostic with "Warning:"
instead of "Error:".
compiler/mark_trace_goals.m:
Fix an incorrect error message.
compiler/purity.m:
Replace a correct/incorrect color pair with two inconsistent colors,
because there is a reasonable probability of each one being right.
---------------------
compiler/accumulator.m:
compiler/add_clause.m:
compiler/add_mode.m:
compiler/add_pragma.m:
compiler/add_pragma_tabling.m:
compiler/add_pred.m:
compiler/add_type.m:
compiler/check_module_interface.m:
compiler/check_type_inst_mode_defns.m:
compiler/check_typeclass.m:
compiler/color_schemes.m:
compiler/common.m:
compiler/convert_import_use.m:
compiler/convert_parse_tree.m:
compiler/dead_proc_elim.m:
compiler/det_check_proc.m:
compiler/det_check_switch.m:
compiler/det_infer_goal.m:
compiler/du_type_layout.m:
compiler/format_call_errors.m:
compiler/grab_modules.m:
compiler/hlds_call_tree.m:
compiler/inst_check.m:
compiler/introduce_parallelism.m:
compiler/make_hlds_error.m:
compiler/make_hlds_warn.m:
compiler/mark_tail_calls.m:
compiler/mark_trace_goals.m:
compiler/mercury_compile_main.m:
compiler/mercury_compile_make_hlds.m:
compiler/mode_errors.m:
compiler/modes.m:
compiler/module_qual.qual_errors.m:
compiler/opt_deps_spec.m:
compiler/options_file.m:
compiler/parse_goal.m:
compiler/post_term_analysis.m:
compiler/post_typecheck.m:
compiler/pre_typecheck.m:
compiler/purity.m:
compiler/read_modules.m:
compiler/recompilation.check.m:
compiler/simplify_goal.m:
compiler/simplify_goal_call.m:
compiler/simplify_goal_disj.m:
compiler/simplify_goal_ite.m:
compiler/split_parse_tree_src.m:
compiler/state_var.m:
compiler/stratify.m:
compiler/style_checks.m:
compiler/superhomogeneous.m:
compiler/table_gen.m:
compiler/term_constr_errors.m:
compiler/term_errors.m:
compiler/termination.m:
compiler/typecheck_clauses.m:
compiler/typecheck_error_overload.m:
compiler/typecheck_error_undef.m:
compiler/typecheck_errors.m:
compiler/typecheck_msgs.m:
compiler/unused_args.m:
compiler/unused_imports.m:
compiler/warn_unread_modules.m:
compiler/write_module_interface_files.m:
Conform to the changes above, mostly by either
- adding an option to all warning and informational messages,
sometimes using existing warning options and sometimes new ones,
or
- turning already explicitly-conditional-on-an-option messages
into implicitly-conditional-on-that-option messages.
---------------------
tests/invalid/one_member.m:
Conform to the change in det_infer_goal.m.
tests/invalid/require_tailrec_1.err_exp:
tests/invalid/require_tailrec_2.err_exp:
Actually obey the options for these modules in Mercury.options.
tests/invalid_purity/purity.err_exp:
tests/warnings/purity_warnings.err_exp:
Conform to the change in purity.m.
tests/warnings/moved_trace_goal.err_exp:
Conform to the change in mark_trace_goals.m.
tests/warnings/help_text.err_exp:
Expect the documentation of all the new options.
211 lines
8.8 KiB
Mathematica
211 lines
8.8 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2011-2025 The Mercury team.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% File: check_module_interface.m.
|
|
%
|
|
% Check whether the interface of a module exports anything.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module parse_tree.check_module_interface.
|
|
:- interface.
|
|
|
|
:- import_module libs.
|
|
:- import_module libs.globals.
|
|
:- import_module parse_tree.error_spec.
|
|
:- import_module parse_tree.prog_parse_tree.
|
|
|
|
:- import_module list.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% Given a module's source code, check whether its interface
|
|
% exports anything. If it does not, and --warn-nothing-exported is set,
|
|
% report a warning.
|
|
%
|
|
:- pred check_module_interface_for_no_exports(globals::in,
|
|
parse_tree_module_src::in,
|
|
list(error_spec)::in, list(error_spec)::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module libs.options.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.sym_name.
|
|
:- import_module parse_tree.item_util.
|
|
:- import_module parse_tree.prog_data.
|
|
:- import_module parse_tree.prog_item.
|
|
|
|
:- import_module bool.
|
|
:- import_module int.
|
|
:- import_module map.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
check_module_interface_for_no_exports(Globals, ParseTreeModuleSrc, !Specs) :-
|
|
globals.lookup_bool_option(Globals, warn_nothing_exported, ExportWarning),
|
|
(
|
|
ExportWarning = no
|
|
;
|
|
ExportWarning = yes,
|
|
ParseTreeModuleSrc = parse_tree_module_src(ModuleName,
|
|
ModuleNameContext, InclMap, _ImportUseMap,
|
|
_IntFIMs, _ImpFIMs, _IntSelfFIMLangs, _ImpSelfFIMLangs,
|
|
|
|
TypeCtorCheckedMap, InstCtorCheckedMap, ModeCtorCheckedMap,
|
|
TypeSpecs, InstModeSpecs,
|
|
|
|
IntTypeClasses, IntInstances, IntPredDecls, IntModeDecls,
|
|
IntDeclPragmas, IntDeclMarkers, IntPromises, _IntBadClauses,
|
|
|
|
_ImpTypeClasses, _ImpInstances, _ImpPredDecls, _ImpModeDecls,
|
|
_ImpClauses, _ImpForeignProcs, _ImpForeignExportEnums,
|
|
_ImpDeclPragmas, _ImpDeclMarkers, _ImpImplPragmas, _ImpImplMarkers,
|
|
_ImpPromises, _ImpInitialises, _ImpFinalises, _ImpMutables),
|
|
CountIncls =
|
|
( pred(_MN::in, InclInfo::in, IntCnt0::in, IntCnt::out,
|
|
ImpCnt0::in, ImpCnt::out) is det :-
|
|
InclInfo = include_module_info(Section, _),
|
|
(
|
|
Section = ms_interface,
|
|
IntCnt = IntCnt0 + 1,
|
|
ImpCnt = ImpCnt0
|
|
;
|
|
Section = ms_implementation,
|
|
IntCnt = IntCnt0,
|
|
ImpCnt = ImpCnt0 + 1
|
|
)
|
|
),
|
|
map.foldl2(CountIncls, InclMap, 0, NumIntIncls, 0, NumImpIncls),
|
|
( if
|
|
(
|
|
NumIntIncls = 0
|
|
;
|
|
NumIntIncls = 1,
|
|
% If a module interface contains nothing but a single
|
|
% include_module declaration, then
|
|
% - we should report "nothing exported" if there are no
|
|
% include_module declarations in the implementation either,
|
|
% - but we should NOT report "nothing exported" if there are
|
|
% some include_module declarations in the implementation.
|
|
%
|
|
% Such packages are a useful way to establish a group of
|
|
% modules that have access to each other's interfaces,
|
|
% without those interfaces being accessible from the
|
|
% rest of the program (with the obvious exception of the
|
|
% module whose include_module declaration is exported.)
|
|
NumImpIncls = 0
|
|
),
|
|
type_ctor_checked_map_get_src_defns(TypeCtorCheckedMap,
|
|
IntTypeDefns, _, _),
|
|
IntTypeDefns = [],
|
|
inst_ctor_checked_map_get_src_defns(InstCtorCheckedMap,
|
|
IntInstDefns, _),
|
|
IntInstDefns = [],
|
|
mode_ctor_checked_map_get_src_defns(ModeCtorCheckedMap,
|
|
IntModeDefns, _),
|
|
IntModeDefns = [],
|
|
|
|
% If some type, inst or mode definitions were invalid, then
|
|
% there are two possibilities: either some of them are in
|
|
% the interface section, or none of them are. Unfortunately,
|
|
% we don't know which is the case, so must choose an algorithm
|
|
% that works in both cases.
|
|
%
|
|
% - If some of the errors are in the interface section, then
|
|
% generating a "no exports" warning would be misleading.
|
|
%
|
|
% - If all of the errors are in the implementation section, then
|
|
% generating that warning would not be misleading, but
|
|
% it is also not quite needed. Due to those errors,
|
|
% the compilation will fail, with error messages that the
|
|
% programmer can and should fix, whether we generate
|
|
% a "no exports" warning or not. This means that the warning
|
|
% is not really needed *now*; it can be generated later,
|
|
% once the complained-about invalid definitions are fixed.
|
|
TypeSpecs = [],
|
|
InstModeSpecs = [],
|
|
|
|
IntTypeClasses = [],
|
|
IntInstances = [],
|
|
IntPredDecls = [],
|
|
% XXX We should delete the next three kinds of entities
|
|
% from this test.
|
|
%
|
|
% Mode declarations, decl pragmas and decl markers all say
|
|
% something about a predicate or function, and without
|
|
% a declaration of that predicate or function ALSO in the
|
|
% interface, they are not useful.
|
|
IntModeDecls = [], % we should delete this
|
|
IntDeclPragmas = [], % we should delete this
|
|
IntDeclMarkers = [], % we should delete this
|
|
IntPromises = []
|
|
then
|
|
generate_no_exports_warning(ModuleName, ModuleNameContext,
|
|
NumIntIncls, !Specs)
|
|
else
|
|
true
|
|
)
|
|
).
|
|
|
|
:- inst num_int_incls for int/0
|
|
---> 0
|
|
; 1.
|
|
|
|
:- pred generate_no_exports_warning(module_name::in, prog_context::in,
|
|
int::in(num_int_incls),
|
|
list(error_spec)::in, list(error_spec)::out) is det.
|
|
|
|
generate_no_exports_warning(ModuleName, Context, NumIntIncls, !Specs) :-
|
|
AlwaysPieces =
|
|
[invis_order_default_start(2, ""),
|
|
words("Warning: the interface of module")] ++
|
|
color_as_subject([qual_sym_name(ModuleName)]) ++
|
|
color_as_incorrect([words("does not export anything.")]) ++ [nl],
|
|
% We don't list mode declarations because they don't make sense
|
|
% without a corresponding pred or func declaration.
|
|
% We don't list decl pragmas for the same reason.
|
|
% We don't list promises because although they don't *have to be*
|
|
% about predicates and functions defined in the same module,
|
|
% they *should be*.
|
|
StdVerbosePieces =
|
|
[words("To be useful, a module should export something."),
|
|
words("A file should contain at least one declaration"),
|
|
words("other than"), decl("import_module"),
|
|
words("in its interface section(s)."),
|
|
words("This would normally be a"), decl("pred"), words("or"),
|
|
decl("func"), words("declaration, or a"),
|
|
decl("type"), suffix(","), decl("inst"), suffix(","),
|
|
decl("mode"), suffix(","), decl("typeclass"), words("or"),
|
|
decl("instance"), words("definition."), nl],
|
|
(
|
|
NumIntIncls = 0,
|
|
VerbosePieces = StdVerbosePieces
|
|
;
|
|
NumIntIncls = 1,
|
|
VerbosePieces = StdVerbosePieces ++
|
|
[words("A module that includes a single submodule"),
|
|
words("is not useful, because it can be replaced"),
|
|
words("by that submodule."), nl]
|
|
),
|
|
Msg = simple_msg(Context,
|
|
[always(AlwaysPieces),
|
|
verbose_only(verbose_always, VerbosePieces)]),
|
|
Spec = error_spec($pred, severity_warning(warn_nothing_exported),
|
|
phase_t2pt, [Msg]),
|
|
!:Specs = [Spec | !.Specs].
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module parse_tree.check_module_interface.
|
|
%---------------------------------------------------------------------------%
|