[m-rev.] for review: improve error reporting for foreign_type pragmas
Julien Fischer
jfischer at opturion.com
Mon Mar 13 16:55:26 AEDT 2017
For review by anyone.
Improve error reporting for foreign_type pragmas.
compiler/parse_pragma.m:
Use parse_foreign_language/4 to parse the foreign language argument of a
foreign_type pragmas; there is no reason for foreign type pragmas to
use separate code for parsing their first argument.
Do not allow the foreign type descriptor for C, C# and Java foreign type
pragmas to be an empty string.
Do not allow the foreign type descriptor for Erlang foreign type pragmas to
be a non-empty string.
In the case of a repeated foreign type assertion, report *which* assertion
is repeated in the error message.
compiler/parse_type_defn.m:
Distinguish between when we are parsing a type definition head for an
actual type definition and when we are parsing it as the second argument
of a foreign_type pragma. Currently, we do not make the distinction and
this causes nonsensical error messages in the case of foreign_type
pragmas (e.g. in the case where the foreign type descriptor is a type
variable).
tests/invalid/bad_foreign_type.{m,err_exp}:
Extend this test to cover the new error messages and also cover other
cases that we were not previously testing.
tests/invalid/where_direct_arg2.err_exp:
Conform to the above change.
Julien.
diff --git a/compiler/parse_pragma.m b/compiler/parse_pragma.m
index f7732bd..a3e3fb4 100644
--- a/compiler/parse_pragma.m
+++ b/compiler/parse_pragma.m
@@ -387,19 +387,12 @@ parse_pragma_foreign_type(ModuleName, VarSet, ErrorTerm, PragmaTerms,
MaybeAssertionTerm = yes(AssertionTerm0)
)
then
- ( if term_to_foreign_language(LangTerm, Language) then
- parse_foreign_language_type(ForeignTypeTerm, VarSet, Language,
- MaybeForeignType)
- else
- LangPieces = [words("Error: invalid foreign language in"),
- pragma_decl("foreign_type"), words("declaration."), nl],
- LangSpec = error_spec(severity_error, phase_term_to_parse_tree,
- [simple_msg(get_term_context(LangTerm),
- [always(LangPieces)])]),
- MaybeForeignType = error1([LangSpec])
- ),
- parse_type_defn_head(ModuleName, VarSet, MercuryTypeTerm,
- MaybeTypeDefnHead),
+ parse_foreign_language("foreign_type", VarSet, LangTerm,
+ MaybeForeignLang),
+ parse_foreign_language_type(ForeignTypeTerm, VarSet,
+ MaybeForeignLang, MaybeForeignType),
+ parse_type_defn_head(tdhpc_foreign_type_pragma, ModuleName, VarSet,
+ MercuryTypeTerm, MaybeTypeDefnHead),
(
MaybeAssertionTerm = no,
AssertionsSet = set.init,
@@ -411,6 +404,7 @@ parse_pragma_foreign_type(ModuleName, VarSet, ErrorTerm, PragmaTerms,
),
Assertions = foreign_type_assertions(AssertionsSet),
( if
+ MaybeForeignLang = ok1(_),
MaybeMaybeUC = ok1(MaybeUC),
MaybeForeignType = ok1(ForeignType),
MaybeTypeDefnHead = ok2(MercuryTypeSymName, MercuryParams),
@@ -427,6 +421,7 @@ parse_pragma_foreign_type(ModuleName, VarSet, ErrorTerm, PragmaTerms,
Specs = get_any_errors1(MaybeMaybeUC) ++
get_any_errors1(MaybeForeignType) ++
get_any_errors2(MaybeTypeDefnHead) ++
+ get_any_errors1(MaybeForeignLang) ++
AssertionSpecs,
MaybeIOM = error1(Specs)
)
@@ -454,10 +449,13 @@ parse_foreign_type_assertions(VarSet, Term, !Assertions, !Specs) :-
then
true
else
- TermStr = mercury_term_to_string(VarSet, print_name_only,
- Term),
- Pieces = [words("Error: foreign type assertion"),
- quote(TermStr), words("is repeated."), nl],
+ HeadTermStr = mercury_term_to_string(VarSet, print_name_only,
+ HeadTerm),
+ Pieces = [
+ words("In fourth argument of"), pragma_decl("foreign_type"),
+ words("declaration: error:"), words("foreign type assertion"),
+ quote(HeadTermStr), words("is repeated.")
+ ],
Spec = error_spec(severity_error, phase_term_to_parse_tree,
[simple_msg(get_term_context(HeadTerm),
[always(Pieces)])]),
@@ -465,8 +463,11 @@ parse_foreign_type_assertions(VarSet, Term, !Assertions, !Specs) :-
)
else
TermStr = mercury_term_to_string(VarSet, print_name_only, Term),
- Pieces = [words("Error: expected an assertion for a foreign type"),
- words("got"), quote(TermStr), suffix("."), nl],
+ Pieces = [
+ words("In fourth argument of"), pragma_decl("foreign_type"),
+ words("declaration: error: expected a foreign type assertion,"),
+ words("got"), quote(TermStr), suffix(".")
+ ],
Spec = error_spec(severity_error, phase_term_to_parse_tree,
[simple_msg(get_term_context(HeadTerm), [always(Pieces)])]),
!:Specs = [Spec | !.Specs]
@@ -474,9 +475,12 @@ parse_foreign_type_assertions(VarSet, Term, !Assertions, !Specs) :-
parse_foreign_type_assertions(VarSet, TailTerm, !Assertions, !Specs)
else
TermStr = mercury_term_to_string(VarSet, print_name_only, Term),
- Pieces = [words("Error: expected a list of"),
- words("assertions for a foreign type, got"),
- quote(TermStr), suffix("."), nl],
+ Pieces = [
+ words("In fourth argument of"), pragma_decl("foreign_type"),
+ words("declaration: error: expected a list of"),
+ words("foreign type assertions, got"),
+ quote(TermStr), suffix(".")
+ ],
Spec = error_spec(severity_error,
phase_term_to_parse_tree,
[simple_msg(get_term_context(Term), [always(Pieces)])]),
@@ -683,7 +687,7 @@ process_export_enum_attribute(ee_attr_upper(MakeUpperCase), !Attributes) :-
parse_export_enum_attr(VarSet, Term, MaybeAttribute) :-
( if
Term = functor(atom("prefix"), Args, _),
- Args = [ ForeignNameTerm ],
+ Args = [ForeignNameTerm],
ForeignNameTerm = functor(string(Prefix), [], _)
then
MaybeAttribute = ok1(ee_attr_prefix(yes(Prefix)))
@@ -1922,60 +1926,75 @@ term_to_foreign_language(term.functor(term.string(String), _, _), Lang) :-
term_to_foreign_language(term.functor(term.atom(String), _, _), Lang) :-
globals.convert_foreign_language(String, Lang).
-:- pred parse_foreign_language_type(term::in, varset::in, foreign_language::in,
- maybe1(foreign_language_type)::out) is det.
+:- pred parse_foreign_language_type(term::in, varset::in,
+ maybe1(foreign_language)::in, maybe1(foreign_language_type)::out) is det.
-parse_foreign_language_type(InputTerm, VarSet, Language,
+parse_foreign_language_type(InputTerm, VarSet, MaybeLanguage,
MaybeForeignLangType) :-
- (
- Language = lang_c,
- ( if InputTerm = term.functor(term.string(CTypeName), [], _) then
- MaybeForeignLangType = ok1(c(c_type(CTypeName)))
- else
- InputTermStr = describe_error_term(VarSet, InputTerm),
- Pieces = [words("Error: invalid backend specification"),
- quote(InputTermStr), suffix("."), nl],
- Spec = error_spec(severity_error, phase_term_to_parse_tree,
- [simple_msg(get_term_context(InputTerm), [always(Pieces)])]),
- MaybeForeignLangType = error1([Spec])
- )
- ;
- Language = lang_java,
- ( if InputTerm = term.functor(term.string(JavaTypeName), [], _) then
- MaybeForeignLangType = ok1(java(java_type(JavaTypeName)))
- else
- InputTermStr = describe_error_term(VarSet, InputTerm),
- Pieces = [words("Error: invalid backend specification"),
- quote(InputTermStr), suffix("."), nl],
- Spec = error_spec(severity_error, phase_term_to_parse_tree,
- [simple_msg(get_term_context(InputTerm), [always(Pieces)])]),
- MaybeForeignLangType = error1([Spec])
- )
- ;
- Language = lang_csharp,
- ( if InputTerm = term.functor(term.string(CSharpTypeName), [], _) then
- MaybeForeignLangType = ok1(csharp(csharp_type(CSharpTypeName)))
- else
- InputTermStr = describe_error_term(VarSet, InputTerm),
- Pieces = [words("Error: invalid backend specification"),
- quote(InputTermStr), suffix("."), nl],
- Spec = error_spec(severity_error, phase_term_to_parse_tree,
- [simple_msg(get_term_context(InputTerm), [always(Pieces)])]),
- MaybeForeignLangType = error1([Spec])
- )
- ;
- Language = lang_erlang,
- ( if InputTerm = term.functor(term.string(_ErlangTypeName), [], _) then
- % XXX should we check if the type is blank?
- MaybeForeignLangType = ok1(erlang(erlang_type))
- else
- InputTermStr = describe_error_term(VarSet, InputTerm),
- Pieces = [words("Error: invalid backend specification"),
- quote(InputTermStr), suffix("."), nl],
- Spec = error_spec(severity_error, phase_term_to_parse_tree,
- [simple_msg(get_term_context(InputTerm), [always(Pieces)])]),
- MaybeForeignLangType = error1([Spec])
+ ( if InputTerm = term.functor(term.string(ForeignTypeName), [], _) then
+ (
+ MaybeLanguage = ok1(Language),
+ (
+ (
+ Language = lang_c,
+ ForeignLangType = c(c_type(ForeignTypeName))
+ ;
+ Language = lang_java,
+ ForeignLangType = java(java_type(ForeignTypeName))
+ ;
+ Language = lang_csharp,
+ ForeignLangType = csharp(csharp_type(ForeignTypeName))
+ ),
+ ( if ForeignTypeName = "" then
+ Pieces = [
+ words("In third argument of"),
+ pragma_decl("foreign_type"),
+ words("declaration: error:"),
+ words("foreign type descriptor for language"),
+ quote(foreign_language_string(Language)),
+ words("must be a non-empty string.")
+ ],
+ Spec = error_spec(severity_error, phase_term_to_parse_tree,
+ [simple_msg(get_term_context(InputTerm),
+ [always(Pieces)])]),
+ MaybeForeignLangType = error1([Spec])
+ else
+ MaybeForeignLangType = ok1(ForeignLangType)
+ )
+ ;
+ Language = lang_erlang,
+ ( if ForeignTypeName = "" then
+ MaybeForeignLangType = ok1(erlang(erlang_type))
+ else
+ Pieces = [
+ words("In third argument of"),
+ pragma_decl("foreign_type"),
+ words("declaration: error:"),
+ words("foreign type descriptor for language"),
+ quote(foreign_language_string(Language)),
+ words("must be an empty string.")
+ ],
+ Spec = error_spec(severity_error, phase_term_to_parse_tree,
+ [simple_msg(get_term_context(InputTerm),
+ [always(Pieces)])]),
+ MaybeForeignLangType = error1([Spec])
+ )
+ )
+ ;
+ MaybeLanguage = error1(_),
+ MaybeForeignLangType = error1([]) % Dummy value.
)
+ else
+ InputTermStr = describe_error_term(VarSet, InputTerm),
+ Pieces = [
+ words("In third argument of"),
+ pragma_decl("foreign_type"),
+ words("declaration: error:"),
+ words("invalid foreign type descriptor"),
+ quote(InputTermStr), suffix("."), nl],
+ Spec = error_spec(severity_error, phase_term_to_parse_tree,
+ [simple_msg(get_term_context(InputTerm), [always(Pieces)])]),
+ MaybeForeignLangType = error1([Spec])
).
% This predicate parses foreign_decl pragmas.
diff --git a/compiler/parse_type_defn.m b/compiler/parse_type_defn.m
index c180c02..c14ff33 100644
--- a/compiler/parse_type_defn.m
+++ b/compiler/parse_type_defn.m
@@ -38,13 +38,22 @@
list(term)::in, prog_context::in, int::in, is_solver_type::in,
maybe1(item_or_marker)::out) is det.
- % parse_type_defn_head(ModuleName, VarSet, Head, HeadResult):
+ % Are we parsing the type defn head in a `:- type' declaration or the in
+ % the second argument of a foreign_type pragma?
+ %
+:- type type_defn_head_parse_context
+ ---> tdhpc_type_defn
+ ; tdhpc_foreign_type_pragma.
+
+ % parse_type_defn_head(ParseContext, ModuleName, VarSet, Head,
+ % HeadResult):
%
% Check the head of a type definition for errors.
%
% Exported to parse_pragma.m for use when parsing foreign type pragmas.
%
-:- pred parse_type_defn_head(module_name::in, varset::in, term::in,
+:- pred parse_type_defn_head(type_defn_head_parse_context::in,
+ module_name::in, varset::in, term::in,
maybe2(sym_name, list(type_param))::out) is det.
% A cut-down version of parse_type_decl_where_part_if_present
@@ -161,7 +170,8 @@ parse_du_type_defn(ModuleName, VarSet, HeadTerm, BodyTerm, Context, SeqNum,
SolverSpecs = []
),
- parse_type_defn_head(ModuleName, VarSet, HeadTerm, MaybeTypeCtorAndArgs),
+ parse_type_defn_head(tdhpc_type_defn, ModuleName, VarSet, HeadTerm,
+ MaybeTypeCtorAndArgs),
du_type_rhs_ctors_and_where_terms(BodyTerm, CtorsTerm, MaybeWhereTerm),
parse_maybe_exist_quant_constructors(ModuleName, VarSet, CtorsTerm,
MaybeOneOrMoreCtors),
@@ -622,7 +632,8 @@ parse_eqv_type_defn(ModuleName, VarSet, HeadTerm, BodyTerm, Context, SeqNum,
[simple_msg(get_term_context(HeadTerm), [always(SolverPieces)])]),
SolverSpecs = [SolverSpec]
),
- parse_type_defn_head(ModuleName, VarSet, HeadTerm, MaybeNameAndParams),
+ parse_type_defn_head(tdhpc_type_defn, ModuleName, VarSet, HeadTerm,
+ MaybeNameAndParams),
% XXX Should pass more correct ContextPieces.
ContextPieces = cord.init,
parse_type(no_allow_ho_inst_info(wnhii_eqv_type_defn_body),
@@ -703,7 +714,8 @@ parse_where_block_type_defn(ModuleName, VarSet, HeadTerm, BodyTerm,
parse_where_type_is_abstract_enum(ModuleName, VarSet, HeadTerm, BodyTerm,
Context, SeqNum, MaybeIOM) :-
varset.coerce(VarSet, TypeVarSet),
- parse_type_defn_head(ModuleName, VarSet, HeadTerm, MaybeNameParams),
+ parse_type_defn_head(tdhpc_type_defn, ModuleName, VarSet, HeadTerm,
+ MaybeNameParams),
( if
BodyTerm = term.functor(term.atom("type_is_abstract_enum"), Args, _)
then
@@ -748,7 +760,8 @@ parse_where_type_is_abstract_enum(ModuleName, VarSet, HeadTerm, BodyTerm,
parse_solver_type_base(ModuleName, VarSet, HeadTerm,
MaybeSolverTypeDetails, MaybeUserEqComp, Context, SeqNum, MaybeIOM) :-
varset.coerce(VarSet, TVarSet),
- parse_type_defn_head(ModuleName, VarSet, HeadTerm, MaybeNameParams),
+ parse_type_defn_head(tdhpc_type_defn, ModuleName, VarSet, HeadTerm,
+ MaybeNameParams),
(
MaybeSolverTypeDetails = yes(_),
SolverSpecs = []
@@ -795,7 +808,8 @@ parse_solver_type_base(ModuleName, VarSet, HeadTerm,
parse_abstract_type_defn(ModuleName, VarSet, HeadTerm, Context, SeqNum,
IsSolverType, MaybeIOM) :-
- parse_type_defn_head(ModuleName, VarSet, HeadTerm, MaybeTypeCtorAndArgs),
+ parse_type_defn_head(tdhpc_type_defn, ModuleName, VarSet, HeadTerm,
+ MaybeTypeCtorAndArgs),
(
MaybeTypeCtorAndArgs = error2(Specs),
MaybeIOM = error1(Specs)
@@ -943,8 +957,12 @@ parse_where_unify_compare(ModuleName, VarSet, Term0, MaybeUnifyCompare) :-
MaybeWhereEnd = ok1(unit)
;
!.MaybeTerm = yes(EndTerm),
- Pieces = [words("Error: unrecognized or unexpected attribute."),
- nl],
+ EndTermStr = describe_error_term(VarSet, EndTerm),
+ Pieces = [
+ words("In"), pragma_decl("foreign_type"),
+ words("declaration: error:"),
+ words("unrecognized or unexpected"), quote("where"),
+ words("attribute"), quote(EndTermStr), suffix("."), nl],
EndSpec = error_spec(severity_error, phase_term_to_parse_tree,
[simple_msg(get_term_context(EndTerm), [always(Pieces)])]),
MaybeWhereEnd = error1([EndSpec])
@@ -1358,16 +1376,37 @@ maybe_unify_compare(MaybeEqPred, MaybeCmpPred) =
% Predicates useful for parsing several kinds of type definitions.
%
-parse_type_defn_head(ModuleName, VarSet, HeadTerm, MaybeTypeCtorAndArgs) :-
+parse_type_defn_head(ParseContext, ModuleName, VarSet, HeadTerm,
+ MaybeTypeCtorAndArgs) :-
(
- HeadTerm = term.variable(_, Context),
- Pieces = [words("Error: variable on LHS of type definition."), nl],
+ HeadTerm = term.variable(Var, Context),
+ (
+ ParseContext = tdhpc_type_defn,
+ Pieces = [words("Error: variable on LHS of type definition."), nl]
+ ;
+ ParseContext = tdhpc_foreign_type_pragma,
+ VarName = varset.lookup_name(VarSet, Var),
+ Pieces = [
+ words("In second argument of"), pragma_decl("foreign_type"),
+ words("declaration: error: expected a type name declared"),
+ words("using a"), decl("type"), words("declaration, got"),
+ words("type variable"), quote(VarName), suffix(".")
+ ]
+ ),
Spec = error_spec(severity_error, phase_term_to_parse_tree,
[simple_msg(Context, [always(Pieces)])]),
MaybeTypeCtorAndArgs = error2([Spec])
;
HeadTerm = term.functor(_, _, HeadContext),
- ContextPieces = cord.singleton(words("In type definition:")),
+ (
+ ParseContext = tdhpc_type_defn,
+ ContextPieces = cord.singleton(words("In type definition:"))
+ ;
+ ParseContext = tdhpc_foreign_type_pragma,
+ ContextPieces = cord.from_list([
+ words("In"), pragma_decl("foreign_type"), words("declaration:")
+ ])
+ ),
parse_implicitly_qualified_sym_name_and_args(ModuleName, HeadTerm,
VarSet, ContextPieces, HeadResult),
(
diff --git a/tests/invalid/bad_foreign_type.err_exp b/tests/invalid/bad_foreign_type.err_exp
index 66d06b4..d736ded 100644
--- a/tests/invalid/bad_foreign_type.err_exp
+++ b/tests/invalid/bad_foreign_type.err_exp
@@ -1,25 +1,57 @@
-bad_foreign_type.m:011: Error: abstract declaration for type
-bad_foreign_type.m:011: `bad_foreign_type.foo'/0 has no corresponding
-bad_foreign_type.m:011: definition.
bad_foreign_type.m:017: Error: wrong number of arguments in
bad_foreign_type.m:017: `:- pragma foreign_type' declaration.
bad_foreign_type.m:021: Error: wrong number of arguments in
bad_foreign_type.m:021: `:- pragma foreign_type' declaration.
-bad_foreign_type.m:025: Error: invalid foreign language in
+bad_foreign_type.m:025: Error: invalid foreign language `"InvalidLanguage"' in
bad_foreign_type.m:025: `:- pragma foreign_type' declaration.
-bad_foreign_type.m:029: In type definition: error: atom expected at 1111.
-bad_foreign_type.m:033: Error: invalid backend specification `2222'.
-bad_foreign_type.m:037: Error: expected a list of assertions for a foreign
-bad_foreign_type.m:037: type, got `5555'.
-bad_foreign_type.m:041: Error: expected an assertion for a foreign type got
-bad_foreign_type.m:041: `[not_an_assertion]'.
-bad_foreign_type.m:045: Error: expected an assertion for a foreign type got
-bad_foreign_type.m:045: `["I\'m a string"]'.
-bad_foreign_type.m:045: Error: expected an assertion for a foreign type got
-bad_foreign_type.m:045: `[3333, "I\'m a string"]'.
+bad_foreign_type.m:029: In `:- pragma foreign_type' declaration: error: atom
+bad_foreign_type.m:029: expected at 1111.
+bad_foreign_type.m:033: In third argument of `:- pragma foreign_type'
+bad_foreign_type.m:033: declaration: error: invalid foreign type descriptor
+bad_foreign_type.m:033: `2222'.
+bad_foreign_type.m:037: In fourth argument of `:- pragma foreign_type'
+bad_foreign_type.m:037: declaration: error: expected a list of foreign type
+bad_foreign_type.m:037: assertions, got `5555'.
+bad_foreign_type.m:041: In fourth argument of `:- pragma foreign_type'
+bad_foreign_type.m:041: declaration: error: expected a foreign type
+bad_foreign_type.m:041: assertion, got `[not_an_assertion]'.
+bad_foreign_type.m:045: In fourth argument of `:- pragma foreign_type'
+bad_foreign_type.m:045: declaration: error: expected a foreign type
+bad_foreign_type.m:045: assertion, got `["I\'m a string"]'.
+bad_foreign_type.m:045: In fourth argument of `:- pragma foreign_type'
+bad_foreign_type.m:045: declaration: error: expected a foreign type
+bad_foreign_type.m:045: assertion, got `[3333, "I\'m a string"]'.
bad_foreign_type.m:050: Error: expected `is'.
-bad_foreign_type.m:055: Error: unrecognized or unexpected attribute.
-bad_foreign_type.m:060: Error: invalid foreign language in
+bad_foreign_type.m:055: In `:- pragma foreign_type' declaration: error:
+bad_foreign_type.m:055: unrecognized or unexpected `where' attribute
+bad_foreign_type.m:055: `(foo is bar)'.
+bad_foreign_type.m:060: Error: invalid foreign language `"InvalidLanguage"' in
bad_foreign_type.m:060: `:- pragma foreign_type' declaration.
-bad_foreign_type.m:061: In type definition: error: atom expected at 9999.
-bad_foreign_type.m:066: Error: unrecognized or unexpected attribute.
+bad_foreign_type.m:061: In `:- pragma foreign_type' declaration: error: atom
+bad_foreign_type.m:061: expected at 9999.
+bad_foreign_type.m:062: In third argument of `:- pragma foreign_type'
+bad_foreign_type.m:062: declaration: error: invalid foreign type descriptor
+bad_foreign_type.m:062: `[not_an_assertion]'.
+bad_foreign_type.m:066: In `:- pragma foreign_type' declaration: error:
+bad_foreign_type.m:066: unrecognized or unexpected `where' attribute
+bad_foreign_type.m:066: `(bar is baaz)'.
+bad_foreign_type.m:071: Error: type `bad_foreign_type.bar'/0 defined as
+bad_foreign_type.m:071: foreign_type without being declared.
+bad_foreign_type.m:075: In second argument of `:- pragma foreign_type'
+bad_foreign_type.m:075: declaration: error: expected a type name declared
+bad_foreign_type.m:075: using a `:- type' declaration, got type variable `T'.
+bad_foreign_type.m:081: In third argument of `:- pragma foreign_type'
+bad_foreign_type.m:081: declaration: error: foreign type descriptor for
+bad_foreign_type.m:081: language `C' must be a non-empty string.
+bad_foreign_type.m:082: In third argument of `:- pragma foreign_type'
+bad_foreign_type.m:082: declaration: error: foreign type descriptor for
+bad_foreign_type.m:082: language `C#' must be a non-empty string.
+bad_foreign_type.m:083: In third argument of `:- pragma foreign_type'
+bad_foreign_type.m:083: declaration: error: foreign type descriptor for
+bad_foreign_type.m:083: language `Java' must be a non-empty string.
+bad_foreign_type.m:084: In third argument of `:- pragma foreign_type'
+bad_foreign_type.m:084: declaration: error: foreign type descriptor for
+bad_foreign_type.m:084: language `Erlang' must be an empty string.
+bad_foreign_type.m:089: In fourth argument of `:- pragma foreign_type'
+bad_foreign_type.m:089: declaration: error: foreign type assertion
+bad_foreign_type.m:089: `can_pass_as_mercury_type' is repeated.
diff --git a/tests/invalid/bad_foreign_type.m b/tests/invalid/bad_foreign_type.m
index 288fd81..c82e027 100644
--- a/tests/invalid/bad_foreign_type.m
+++ b/tests/invalid/bad_foreign_type.m
@@ -65,3 +65,25 @@
bar
is
baaz.
+
+ % No corresponding `:- type' declaration present.
+ %
+:- pragma foreign_type("C", bar, "int").
+
+ % Second argument is a type variable.
+ %
+:- pragma foreign_type("C", T, "int").
+
+ % Empty foreign type descriptor (C, C# , Java).
+ % Non-empty foreign type descriptor (Erlang).
+ %
+:- type quux.
+:- pragma foreign_type("C", quux, "").
+:- pragma foreign_type("C#", quux, "").
+:- pragma foreign_type("Java", quux, "").
+:- pragma foreign_type("Erlang", quux, "abcde").
+
+ % Repeated foreign type assertion.
+ %
+:- pragma foreign_type("C", foo, "int",
+ [can_pass_as_mercury_type, can_pass_as_mercury_type]).
diff --git a/tests/invalid/where_direct_arg2.err_exp b/tests/invalid/where_direct_arg2.err_exp
index 876584e..d3eb8c1 100644
--- a/tests/invalid/where_direct_arg2.err_exp
+++ b/tests/invalid/where_direct_arg2.err_exp
@@ -6,4 +6,6 @@ where_direct_arg2.m:012: as a direct pointer to its sole argument.
where_direct_arg2.m:016: Error: `where_direct_arg2.enum'/1 cannot be
where_direct_arg2.m:016: represented as a direct pointer to its sole
where_direct_arg2.m:016: argument.
-where_direct_arg2.m:038: Error: unrecognized or unexpected attribute.
+where_direct_arg2.m:038: In `:- pragma foreign_type' declaration: error:
+where_direct_arg2.m:038: unrecognized or unexpected `where' attribute
+where_direct_arg2.m:038: `(direct_arg is [])'.
More information about the reviews
mailing list