diff --git a/browser/MDB_FLAGS.in b/browser/MDB_FLAGS.in
index 919fcf553..dfbd72d1f 100644
--- a/browser/MDB_FLAGS.in
+++ b/browser/MDB_FLAGS.in
@@ -1,5 +1,7 @@
@BOOTSTRAP_MC_ARGS@
--no-infer-all
+--warn-known-bad-format-calls
+--warn-unknown-format-calls
--halt-at-warn
--no-warn-inferred-erroneous
--no-mercury-stdlib-dir
diff --git a/compiler/COMP_FLAGS.in b/compiler/COMP_FLAGS.in
index 595b569b2..b202679f9 100644
--- a/compiler/COMP_FLAGS.in
+++ b/compiler/COMP_FLAGS.in
@@ -1,5 +1,7 @@
@BOOTSTRAP_MC_ARGS@
--no-infer-all
+--warn-known-bad-format-calls
+--warn-unknown-format-calls
--halt-at-warn
--no-warn-inferred-erroneous
--no-mercury-stdlib-dir
diff --git a/compiler/Mercury.options b/compiler/Mercury.options
index 249d2d62c..98f29524a 100644
--- a/compiler/Mercury.options
+++ b/compiler/Mercury.options
@@ -54,6 +54,11 @@ MCFLAGS-transform_hlds = --no-warn-unused-imports
MCFLAGS-transform_hlds.ctgc.structure_reuse = --no-warn-unused-imports
MCFLAGS-transform_hlds.ctgc.structure_sharing = --no-warn-unused-imports
+# These modules provide general-purpose wrappers around string.format
+# in which the format strings are known only by their callers.
+MCFLAGS-transform_hlds.pd_debug = --no-warn-unknown-format-calls
+MCFLAGS-parse_tree.mercury_to_mercury = --no-warn-unknown-format-calls
+
# Bug workarounds
# This works around bug 48 in Mantis.
diff --git a/compiler/fact_table.m b/compiler/fact_table.m
index 7ac625dde..3e7bec740 100644
--- a/compiler/fact_table.m
+++ b/compiler/fact_table.m
@@ -2630,7 +2630,7 @@ generate_hash_code([pragma_var(_, Name, Mode, _) | PragmaVars], [Type | Types],
generate_hash_int_code(Name, LabelName, LabelNum, PredName, PragmaVars,
Types, ModuleInfo, ArgNum, FactTableSize, C_Code) :-
- generate_hash_lookup_code(Name, LabelName, LabelNum, "%s == %s", 'i',
+ generate_hash_lookup_code(Name, LabelName, LabelNum, plain_equals, 'i',
yes, PredName, PragmaVars, Types, ModuleInfo, ArgNum,
FactTableSize, HashLookupCode),
C_Code_Template = "
@@ -2657,7 +2657,7 @@ generate_hash_int_code(Name, LabelName, LabelNum, PredName, PragmaVars,
generate_hash_float_code(Name, LabelName, LabelNum, PredName, PragmaVars,
Types, ModuleInfo, ArgNum, FactTableSize, C_Code) :-
- generate_hash_lookup_code(Name, LabelName, LabelNum, "%s == %s", 'f',
+ generate_hash_lookup_code(Name, LabelName, LabelNum, plain_equals, 'f',
yes, PredName, PragmaVars, Types, ModuleInfo, ArgNum,
FactTableSize, HashLookupCode),
C_Code_Template = "
@@ -2686,7 +2686,7 @@ generate_hash_float_code(Name, LabelName, LabelNum, PredName, PragmaVars,
generate_hash_string_code(Name, LabelName, LabelNum, PredName, PragmaVars,
Types, ModuleInfo, ArgNum, FactTableSize, C_Code) :-
generate_hash_lookup_code(Name, LabelName, LabelNum,
- "strcmp(%s, %s) == 0", 's', yes, PredName, PragmaVars,
+ string_equals, 's', yes, PredName, PragmaVars,
Types, ModuleInfo, ArgNum, FactTableSize, HashLookupCode),
C_Code_Template = "
@@ -2710,24 +2710,35 @@ generate_hash_string_code(Name, LabelName, LabelNum, PredName, PragmaVars,
string.format(C_Code_Template, [s(Name), s(Name), s(HashLookupCode)],
C_Code).
+:- type comparison_kind
+ ---> plain_equals
+ ; string_equals.
+
% Generate code to lookup the key in the hash table.
% KeyType should be 's', 'i' or 'f' for string, int or float,
% respectively. CompareTemplate should be a template for testing for
% equality for the type given, e.g. "%s == %s" for ints,
% "strcmp(%s, %s) == 0" for strings.
%
-:- pred generate_hash_lookup_code(string::in, string::in, int::in, string::in,
- char::in, bool::in, string::in, list(pragma_var)::in,
+:- pred generate_hash_lookup_code(string::in, string::in, int::in,
+ comparison_kind::in, char::in, bool::in, string::in, list(pragma_var)::in,
list(mer_type)::in, module_info::in, int::in, int::in, string::out) is det.
-generate_hash_lookup_code(VarName, LabelName, LabelNum, CompareTemplate,
+generate_hash_lookup_code(VarName, LabelName, LabelNum, ComparisonKind,
KeyType, CheckKeys, PredName, PragmaVars, Types,
ModuleInfo, ArgNum, FactTableSize, HashLookupCode) :-
string.format("((struct MR_fact_table_hash_table_%c *) current_table)"
++ "->table[hashval]", [c(KeyType)], HashTableEntry),
string.append(HashTableEntry, ".key", HashTableKey),
- string.format(CompareTemplate, [s(HashTableKey), s(VarName)],
- CompareString),
+ (
+ ComparisonKind = plain_equals,
+ string.format("%s == %s", [s(HashTableKey), s(VarName)],
+ CompareString)
+ ;
+ ComparisonKind = string_equals,
+ string.format("strcmp(%s, %s) == 0", [s(HashTableKey), s(VarName)],
+ CompareString)
+ ),
HashLookupCodeTemplate = "
@@ -3101,13 +3112,14 @@ generate_test_condition_code(FactTableName, [PragmaVar | PragmaVars],
PragmaVar = pragma_var(_, Name, Mode, _),
( mode_is_fully_input(ModuleInfo, Mode) ->
( Type = builtin_type(builtin_type_string) ->
- Template =
- "strcmp(%s[ind/%d][ind%%%d].V_%d, %s) != 0\n"
+ Template = "strcmp(%s[ind/%d][ind%%%d].V_%d, %s) != 0\n",
+ string.format(Template, [s(FactTableName), i(FactTableSize),
+ i(FactTableSize), i(ArgNum), s(Name)], CondCode0)
;
- Template = "%s[ind/%d][ind%%%d].V_%d != %s\n"
+ Template = "%s[ind/%d][ind%%%d].V_%d != %s\n",
+ string.format(Template, [s(FactTableName), i(FactTableSize),
+ i(FactTableSize), i(ArgNum), s(Name)], CondCode0)
),
- string.format(Template, [s(FactTableName), i(FactTableSize),
- i(FactTableSize), i(ArgNum), s(Name)], CondCode0),
(
!.IsFirstInputArg = no,
CondCode1 = "\t\t|| " ++ CondCode0
@@ -3227,12 +3239,12 @@ void mercury_sys_init_%s_module(void) {
PredName, 1, FactTableSize, HashCode),
generate_hash_lookup_code("(char *) MR_framevar(4)", LabelName2, 0,
- "strcmp(%s, %s) == 0", 's', no, "", [], [], ModuleInfo, 0, 0,
+ string_equals, 's', no, "", [], [], ModuleInfo, 0, 0,
StringHashLookupCode),
- generate_hash_lookup_code("MR_framevar(4)", LabelName2, 1, "%s == %s",
+ generate_hash_lookup_code("MR_framevar(4)", LabelName2, 1, plain_equals,
'i', no, "", [], [], ModuleInfo, 0, 0, IntHashLookupCode),
generate_hash_lookup_code("MR_word_to_float(MR_framevar(4))",
- LabelName2, 2, "%s == %s", 'f', no, "", [], [], ModuleInfo,
+ LabelName2, 2, plain_equals, 'f', no, "", [], [], ModuleInfo,
0, 0, FloatHashLookupCode),
generate_fact_lookup_code(PredName, PragmaVars, ArgTypes, ModuleInfo, 1,
FactTableSize, FactLookupCode),
diff --git a/deep_profiler/DEEP_FLAGS.in b/deep_profiler/DEEP_FLAGS.in
index 462cb539a..7240a8ed9 100644
--- a/deep_profiler/DEEP_FLAGS.in
+++ b/deep_profiler/DEEP_FLAGS.in
@@ -1,5 +1,7 @@
@BOOTSTRAP_MC_ARGS@
--no-infer-all
+--warn-known-bad-format-calls
+--warn-unknown-format-calls
--halt-at-warn
--no-warn-inferred-erroneous
--no-mercury-stdlib-dir
diff --git a/deep_profiler/Mercury.options b/deep_profiler/Mercury.options
index 96428a2ac..19c33aeab 100644
--- a/deep_profiler/Mercury.options
+++ b/deep_profiler/Mercury.options
@@ -9,6 +9,7 @@
MCFLAGS-array_util = --trace minimum
MCFLAGS-cliques = --trace minimum
MCFLAGS-read_profile = --trace minimum
+MCFLAGS-measurement_units = --no-warn-unknown-format-calls
# Uncomment this to debug the automatic parallelism code.
#MCFLAGS-branch_and_bound = \
diff --git a/deep_profiler/html_format.m b/deep_profiler/html_format.m
index 5c4273640..8a3c2e18d 100644
--- a/deep_profiler/html_format.m
+++ b/deep_profiler/html_format.m
@@ -799,13 +799,15 @@ link_to_html(FormatInfo, Link) = HTML :-
deep_cmd_to_url(FormatInfo, Cmd, MaybePrefs, URL),
(
Class = link_class_control,
- FormatString = "[%s]"
+ FormatString = "[%s]",
+ string.format(FormatString,
+ [s(URL), s(escape_break_html_attr_string(Label))], HTMLStr)
;
Class = link_class_link,
- FormatString = "%s"
+ FormatString = "%s",
+ string.format(FormatString,
+ [s(URL), s(escape_break_html_attr_string(Label))], HTMLStr)
),
- string.format(FormatString,
- [s(URL), s(escape_break_html_attr_string(Label))], HTMLStr),
HTML = str_to_html(HTMLStr).
% Transform a pseudo link into HTML.
@@ -817,13 +819,11 @@ pseudo_link_to_html(_FormatInfo, PseudoLink) = HTML :-
PseudoLink = pseudo_link(Label, Class),
(
Class = link_class_control,
- FormatString = "[%s]"
+ HTMLStr = "[" ++ escape_break_html_string(Label) ++ "]"
;
Class = link_class_link,
- FormatString = "%s"
+ HTMLStr = escape_break_html_string(Label)
),
- string.format(FormatString,
- [s(escape_break_html_string(Label))], HTMLStr),
HTML = str_to_html(HTMLStr).
%-----------------------------------------------------------------------------%
diff --git a/deep_profiler/measurement_units.m b/deep_profiler/measurement_units.m
index c5046fcac..62b3f7f8b 100644
--- a/deep_profiler/measurement_units.m
+++ b/deep_profiler/measurement_units.m
@@ -170,7 +170,7 @@
%-----------------------------------------------------------------------------%
%
-% Memory
+% Memory.
%
:- type memory
@@ -337,7 +337,7 @@ decimal_fraction(Format, Measure) = Representation :-
->
add_commas_intstr(WholeString, Representation)
;
- error("decimal_fraction: Didn't split on decimal point properly")
+ unexpected($module, $pred, "didn't split on decimal point properly")
).
one_decimal_fraction(Measure) = decimal_fraction("%.1f", Measure).
diff --git a/library/LIB_FLAGS.in b/library/LIB_FLAGS.in
index 4d199d7b6..d0a8980f1 100644
--- a/library/LIB_FLAGS.in
+++ b/library/LIB_FLAGS.in
@@ -2,6 +2,8 @@
--optimize-constructor-last-call
--profile-optimized
--no-infer-all
+--warn-known-bad-format-calls
+--warn-unknown-format-calls
--halt-at-warn
--no-warn-inferred-erroneous
--no-mercury-stdlib-dir
diff --git a/library/Mercury.options b/library/Mercury.options
index 6c1eaf8cc..5a5add87e 100644
--- a/library/Mercury.options
+++ b/library/Mercury.options
@@ -51,6 +51,7 @@ MGNUCFLAGS-io += --no-ansi
# varset.trans_opt includes the relevant part of string.opt.
MCFLAGS-io += --no-warn-unknown-format-calls
MCFLAGS-stream += --no-warn-unknown-format-calls
+MCFLAGS-stream.string_writer += --no-warn-unknown-format-calls
MCFLAGS-string += --no-warn-unknown-format-calls
MCFLAGS-erlang_builtin += --no-warn-nothing-exported
diff --git a/mdbcomp/MDBCOMP_FLAGS.in b/mdbcomp/MDBCOMP_FLAGS.in
index 0595c76f4..8fd89671e 100644
--- a/mdbcomp/MDBCOMP_FLAGS.in
+++ b/mdbcomp/MDBCOMP_FLAGS.in
@@ -1,5 +1,7 @@
@BOOTSTRAP_MC_ARGS@
--no-infer-all
+--warn-known-bad-format-calls
+--warn-unknown-format-calls
--halt-at-warn
--no-warn-inferred-erroneous
--no-mercury-stdlib-dir
diff --git a/mfilterjavac/MFILTERJAVAC_FLAGS.in b/mfilterjavac/MFILTERJAVAC_FLAGS.in
index 462cb539a..7240a8ed9 100644
--- a/mfilterjavac/MFILTERJAVAC_FLAGS.in
+++ b/mfilterjavac/MFILTERJAVAC_FLAGS.in
@@ -1,5 +1,7 @@
@BOOTSTRAP_MC_ARGS@
--no-infer-all
+--warn-known-bad-format-calls
+--warn-unknown-format-calls
--halt-at-warn
--no-warn-inferred-erroneous
--no-mercury-stdlib-dir
diff --git a/profiler/PROF_FLAGS.in b/profiler/PROF_FLAGS.in
index 977296013..aef3cf94c 100644
--- a/profiler/PROF_FLAGS.in
+++ b/profiler/PROF_FLAGS.in
@@ -1,5 +1,7 @@
@BOOTSTRAP_MC_ARGS@
--no-infer-all
+--warn-known-bad-format-calls
+--warn-unknown-format-calls
--halt-at-warn
--no-warn-inferred-erroneous
--no-mercury-stdlib-dir
diff --git a/slice/SLICE_FLAGS.in b/slice/SLICE_FLAGS.in
index d6e5c7873..b7eb064f2 100644
--- a/slice/SLICE_FLAGS.in
+++ b/slice/SLICE_FLAGS.in
@@ -1,5 +1,7 @@
@BOOTSTRAP_MC_ARGS@
--no-infer-all
+--warn-known-bad-format-calls
+--warn-unknown-format-calls
--halt-at-warn
--no-warn-inferred-erroneous
--no-mercury-stdlib-dir
diff --git a/ssdb/SSDB_FLAGS.in b/ssdb/SSDB_FLAGS.in
index 1a7c64699..5fd4c00e2 100644
--- a/ssdb/SSDB_FLAGS.in
+++ b/ssdb/SSDB_FLAGS.in
@@ -1,5 +1,7 @@
@BOOTSTRAP_MC_ARGS@
--no-infer-all
+--warn-known-bad-format-calls
+--warn-unknown-format-calls
--halt-at-warn
--no-warn-inferred-erroneous
--no-mercury-stdlib-dir