[m-dev.] diff: report errors for missing type decls in interface

Fergus Henderson fjh at cs.mu.OZ.AU
Sat Sep 16 10:45:16 AEDT 2000


Estimated hours taken: 2.5

Fix a bug where the compiler was not reporting errors for some invalid code.

compiler/make_hlds.m:
	Fix a bug: in the code for handling predicates which have
	mode declarations (or clauses, etc.) but no pred/func
	declaration, if --infer-types is enabled, make sure that
	we still report errors for exported predicates and for
	type class methods.  This required passing down a bool
	`IsTypeClassMethod' argument in a number of places.

tests/invalid/Mmakefile:
tests/invalid/typeclass_mode.m:
tests/invalid/typeclass_mode.err_exp:
tests/invalid/imported_mode.m:
tests/invalid/imported_mode.err_exp:
tests/invalid/exported_mode.m:
tests/invalid/exported_mode.err_exp:
	Add some regression tests.
	For the imported_mode/exported_mode test case, the previous
	compiler generated code that dumped core at runtime.
	For the typeclass_mode test case, the previous
	compiler reported a misleading error message.

Workspace: /home/pgrad/fjh/ws/hg
Index: compiler/make_hlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make_hlds.m,v
retrieving revision 1.340
diff -u -d -r1.340 make_hlds.m
--- compiler/make_hlds.m	2000/08/09 07:47:00	1.340
+++ compiler/make_hlds.m	2000/09/15 23:31:38
@@ -209,15 +209,19 @@
 add_item_decl_pass_1(pred_mode(VarSet, PredName, Modes, MaybeDet, Cond),
 		Context, Status, Module0, Status, Module) -->
 	{ Status = item_status(ImportStatus, _) },
+	{ IsClassMethod = no },
 	module_add_mode(Module0, VarSet, PredName, Modes, MaybeDet, Cond,
-		ImportStatus, Context, predicate, _, Module).
+		ImportStatus, Context, predicate, IsClassMethod,
+		_, Module).
 
 add_item_decl_pass_1(func_mode(VarSet, FuncName, Modes, RetMode, MaybeDet,
 		Cond), Context, Status, Module0, Status, Module) -->
 	{ list__append(Modes, [RetMode], Modes1) },
 	{ Status = item_status(ImportStatus, _) },
+	{ IsClassMethod = no },
 	module_add_mode(Module0, VarSet, FuncName, Modes1,
-		MaybeDet, Cond, ImportStatus, Context, function, _, Module).
+		MaybeDet, Cond, ImportStatus, Context, function, IsClassMethod,
+		_, Module).
 
 add_item_decl_pass_1(pragma(_), _, Status, Module, Status, Module) --> [].
 
@@ -2159,8 +2163,14 @@
 			MaybeDet = no
 		}	
 	->
+		{ check_marker(Markers, class_method) ->
+			IsClassMethod = yes
+		;
+			IsClassMethod = no
+		},
 		module_add_mode(Module1, InstVarSet, PredName, Modes, MaybeDet,
-			Cond, Status, Context, predicate, PredProcId, Module),
+			Cond, Status, Context, predicate, IsClassMethod,
+			PredProcId, Module),
 		{ MaybePredProcId = yes(PredProcId) }
 	;
 		{ Module = Module1 },
@@ -2215,9 +2225,14 @@
 		{ MaybeRetMode = yes(RetMode) }
 	->
 		{ list__append(Modes, [RetMode], Modes1) },
+		{ check_marker(Markers, class_method) ->
+			IsClassMethod = yes
+		;
+			IsClassMethod = no
+		},
 		module_add_mode(Module1, InstVarSet, FuncName, Modes1,
 			MaybeDet, Cond, Status, Context, function,
-			PredProcId, Module),
+			IsClassMethod, PredProcId, Module),
 		{ MaybePredProcId = yes(PredProcId) }
 	;
 		{ Module = Module1 },
@@ -2365,8 +2380,9 @@
 		{ Method = pred_mode(VarSet, PredName, Modes, MaybeDet, 
 			Cond, Context) },
 		{ Status = item_status(ImportStatus, _) },
+		{ IsClassMethod = yes },
 		module_add_mode(Module0, VarSet, PredName, Modes, MaybeDet, 
-			Cond, ImportStatus, Context, predicate,
+			Cond, ImportStatus, Context, predicate, IsClassMethod,
 			PredIdProcId, Module),
 		{ MaybePredIdProcId = yes(PredIdProcId) }
 	;
@@ -2374,8 +2390,9 @@
 			Cond, Context) },
 		{ list__append(Modes, [RetMode], Modes1) },
 		{ Status = item_status(ImportStatus, _) },
-		module_add_mode(Module0, VarSet, FuncName, Modes1,
-			MaybeDet, Cond, ImportStatus, Context, function,
+		{ IsClassMethod = yes },
+		module_add_mode(Module0, VarSet, FuncName, Modes1, MaybeDet,
+			Cond, ImportStatus, Context, function, IsClassMethod,
 			PredIdProcId, Module),
 		{ MaybePredIdProcId = yes(PredIdProcId) }
 	).
@@ -3029,16 +3046,17 @@
 
 :- pred module_add_mode(module_info, inst_varset, sym_name, list(mode),
 		maybe(determinism), condition, import_status, prog_context,
-		pred_or_func, pair(pred_id, proc_id), module_info, 
+		pred_or_func, bool, pair(pred_id, proc_id), module_info, 
 		io__state, io__state).
-:- mode module_add_mode(in, in, in, in, in, in, in, in, in, out, out, 
+:- mode module_add_mode(in, in, in, in, in, in, in, in, in, in, out, out, 
 		di, uo) is det.
 
 	% We should store the mode varset and the mode condition
 	% in the hlds - at the moment we just ignore those two arguments.
 
 module_add_mode(ModuleInfo0, _VarSet, PredName, Modes, MaybeDet, _Cond,
-		Status, MContext, PredOrFunc, PredProcId, ModuleInfo) -->
+		Status, MContext, PredOrFunc, IsClassMethod, PredProcId,
+		ModuleInfo) -->
 
 		% Lookup the pred or func declaration in the predicate table.
 		% If it's not there (or if it is ambiguous), optionally print a
@@ -3059,8 +3077,9 @@
 		{ PredId = PredId0 }
 	;
 		preds_add_implicit_report_error(ModuleName,
-			PredOrFunc, PredName, Arity, Status, MContext,
-			"mode declaration", PredId, ModuleInfo0, ModuleInfo1)
+			PredOrFunc, PredName, Arity, Status, IsClassMethod,
+			MContext, "mode declaration", PredId,
+			ModuleInfo0, ModuleInfo1)
 	),
 
 		% Lookup the pred_info for this predicate
@@ -3121,16 +3140,16 @@
 	% type inference.
 
 :- pred preds_add_implicit_report_error(module_name, pred_or_func, sym_name,
-		arity, import_status, prog_context, string,
+		arity, import_status, bool, prog_context, string,
 		pred_id, module_info, module_info, io__state, io__state).
-:- mode preds_add_implicit_report_error(in, in, in, in, in, in, in,
+:- mode preds_add_implicit_report_error(in, in, in, in, in, in, in, in,
 		out, in, out, di, uo) is det.
 
 preds_add_implicit_report_error(ModuleName, PredOrFunc, PredName, Arity,
-		Status, Context, Description, PredId,
+		Status, IsClassMethod, Context, Description, PredId,
 		ModuleInfo0, ModuleInfo) -->
-	maybe_undefined_pred_error(PredName, Arity, PredOrFunc,
-		Context, Description),
+	maybe_undefined_pred_error(PredName, Arity, PredOrFunc, Status,
+		IsClassMethod, Context, Description),
 
 	( { PredOrFunc = function } ->
 		{ adjust_func_arity(function, FuncArity, Arity) },
@@ -3325,8 +3344,9 @@
 			{ IsAssertion = no },
 
 			preds_add_implicit_report_error(ModuleName,
-				PredOrFunc, PredName, Arity, Status, Context,
-				"clause", PredId, ModuleInfo0, ModuleInfo1)
+				PredOrFunc, PredName, Arity, Status, no,
+				Context, "clause", PredId,
+				ModuleInfo0, ModuleInfo1)
 		)
 	),
 		% Lookup the pred_info for this pred,
@@ -3538,7 +3558,7 @@
 		{ ModuleInfo1 = ModuleInfo0 }
 	;
 		preds_add_implicit_report_error(ModuleName,
-			PredOrFunc, PredName, Arity, Status, Context,
+			PredOrFunc, PredName, Arity, Status, no, Context,
 			"`:- pragma import' declaration",
 			PredId, ModuleInfo0, ModuleInfo1)
 	),
@@ -3849,7 +3869,7 @@
 		{ ModuleInfo1 = ModuleInfo0 }
 	;
 		preds_add_implicit_report_error(ModuleName,
-			PredOrFunc, PredName, Arity, Status, Context,
+			PredOrFunc, PredName, Arity, Status, no, Context,
 			"`:- pragma c_code' declaration",
 			PredId, ModuleInfo0, ModuleInfo1)
 	),
@@ -3970,8 +3990,9 @@
 				[s(EvalMethodS)], Message1) },
 
 			preds_add_implicit_report_error(ModuleName,
-				PredOrFunc, PredName, Arity, Status, Context,
-				Message1, PredId, ModuleInfo0, ModuleInfo1),
+				PredOrFunc, PredName, Arity, Status, no,
+				Context, Message1, PredId,
+				ModuleInfo0, ModuleInfo1),
 			{ PredIds = [PredId] }
 		)
 	;
@@ -3987,8 +4008,9 @@
 				[s(EvalMethodS)], Message1) },
 
 			preds_add_implicit_report_error(ModuleName,
-				predicate, PredName, Arity, Status, Context,
-				Message1, PredId, ModuleInfo0, ModuleInfo1),
+				predicate, PredName, Arity, Status, no,
+				Context, Message1, PredId,
+				ModuleInfo0, ModuleInfo1),
 			{ PredIds = [PredId] }
 		)
 	),
@@ -7298,17 +7320,28 @@
 	prog_out__write_sym_name_and_arity(Name/Arity),
 	io__write_string("' specifies non-existent mode.\n").
 
-:- pred maybe_undefined_pred_error(sym_name, int, pred_or_func, prog_context,
-				string, io__state, io__state).
-:- mode maybe_undefined_pred_error(in, in, in, in, in, di, uo) is det.
+:- pred maybe_undefined_pred_error(sym_name, int, pred_or_func, import_status,
+		bool, prog_context, string, io__state, io__state).
+:- mode maybe_undefined_pred_error(in, in, in, in, in, in, in, di, uo) is det.
 
 % This is not considered an unconditional error anymore:
-% if there is no :- pred declaration, we just infer one,
-% unless the `--no-infer-types' option was specified.
+% if there is no `:- pred' or `:- func' declaration,
+% and the declaration is local, and not a type class method,
+% and the `--infer-types' option was specified,
+% then we just add an implicit declaration for that predicate or
+% function, marking it as one whose type will be inferred.
 
-maybe_undefined_pred_error(Name, Arity, PredOrFunc, Context, Description) -->
+maybe_undefined_pred_error(Name, Arity, PredOrFunc, Status, IsClassMethod,
+		Context, Description) -->
+	{ status_defined_in_this_module(Status, DefinedInThisModule) },
+	{ status_is_exported(Status, IsExported) },
 	globals__io_lookup_bool_option(infer_types, InferTypes),
-	( { InferTypes = yes } ->
+	(
+		{ DefinedInThisModule = yes },
+		{ IsExported = no },
+		{ IsClassMethod = no },
+		{ InferTypes = yes }
+	->
 		[]
 	;
 		io__set_exit_status(1),
Index: tests/invalid/exported_mode.err_exp
===================================================================
RCS file: exported_mode.err_exp
diff -N exported_mode.err_exp
--- /dev/null	Thu Mar 30 14:06:13 2000
+++ exported_mode.err_exp	Sat Sep 16 10:37:41 2000
@@ -0,0 +1,4 @@
+exported_mode.m:004: Error: mode declaration for predicate `exported_mode:p/2'
+exported_mode.m:004:   without preceding `pred' declaration.
+exported_mode.m:004: Inferred :- pred p(T1, string).
+For more information, try recompiling with `-E'.
Index: tests/invalid/exported_mode.m
===================================================================
RCS file: exported_mode.m
diff -N exported_mode.m
--- /dev/null	Thu Mar 30 14:06:13 2000
+++ exported_mode.m	Sat Sep 16 00:23:02 2000
@@ -0,0 +1,8 @@
+:- module exported_mode.
+:- interface.
+
+:- mode p(in, in) is semidet.
+
+:- implementation.
+
+p(_, "foo").
Index: tests/invalid/imported_mode.err_exp
===================================================================
RCS file: imported_mode.err_exp
diff -N imported_mode.err_exp
--- /dev/null	Thu Mar 30 14:06:13 2000
+++ imported_mode.err_exp	Sat Sep 16 10:37:02 2000
@@ -0,0 +1,4 @@
+exported_mode.int:003: Error: mode declaration for predicate `exported_mode:p/2'
+exported_mode.int:003:   without preceding `pred' declaration.
+exported_mode.int:003: Inferred :- pred p(T1, T2).
+For more information, try recompiling with `-E'.
Index: tests/invalid/imported_mode.m
===================================================================
RCS file: imported_mode.m
diff -N imported_mode.m
--- /dev/null	Thu Mar 30 14:06:13 2000
+++ imported_mode.m	Sat Sep 16 00:23:22 2000
@@ -0,0 +1,11 @@
+:- module imported_mode.
+:- interface.
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- implementation.
+:- import_module exported_mode.
+
+main --> ( { p(41, 42) } -> print("yes"), nl ; print("no"), nl ).
+
Index: tests/invalid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/Mmakefile,v
retrieving revision 1.67
diff -u -d -r1.67 Mmakefile
--- tests/invalid/Mmakefile	2000/09/15 11:25:01	1.67
+++ tests/invalid/Mmakefile	2000/09/15 23:28:50
@@ -30,11 +30,13 @@
 	errors2.m \
 	external.m \
 	ext_type_bug.m \
+	exported_mode.m \
 	func_errors.m \
 	funcs_as_preds.m \
 	ho_type_mode_bug.m \
 	ho_unique_error.m \
 	impure_method_impl.m \
+	imported_mode.m \
 	inline_conflict.m \
 	invalid_main.m \
 	inst_list_dup.m \
@@ -71,6 +73,7 @@
 	type_loop.m \
 	type_mismatch.m \
 	type_vars.m \
+	typeclass_mode.m \
 	typeclass_test_1.m \
 	typeclass_test_2.m \
 	typeclass_test_3.m \
@@ -112,6 +115,9 @@
 MCFLAGS-no_exports = 		--halt-at-warn
 MCFLAGS-sub_c = 		--verbose-error-messages
 MCFLAGS-record_syntax_errors =	--verbose-error-messages
+MCFLAGS-imported_mode =		--infer-all
+MCFLAGS-exported_mode =		--infer-all
+MCFLAGS-typeclass_mode =	--infer-all
 
 # The bug is caught when generating dependencies, so it is
 # easiest just to do that step.
@@ -142,10 +148,14 @@
 
 # We only need to make the dependencies for test cases consisting of
 # multiple modules; currently the following are the only such cases.
-depend: aditi_errors.depend aditi_state_errors.depend \
-		aditi_update_errors.depend aditi_update_mode_errors.depend \
-		test_nested.depend partial_implied_mode.depend \
-		undef_mod_qual.depend
+depend: aditi_errors.depend \
+	aditi_state_errors.depend \
+	aditi_update_errors.depend \
+	aditi_update_mode_errors.depend \
+	imported_mode.depend \
+	partial_implied_mode.depend \
+	test_nested.depend \
+	undef_mod_qual.depend
 
 clean_local:
 	rm -f *.err *.err_res
Index: tests/invalid/typeclass_mode.err_exp
===================================================================
RCS file: typeclass_mode.err_exp
diff -N typeclass_mode.err_exp
--- /dev/null	Thu Mar 30 14:06:13 2000
+++ typeclass_mode.err_exp	Sat Sep 16 10:38:02 2000
@@ -0,0 +1,4 @@
+typeclass_mode.m:005: Error: mode declaration for predicate `typeclass_mode:p/1'
+typeclass_mode.m:005:   without preceding `pred' declaration.
+typeclass_mode.m:005: Error: no clauses for predicate `typeclass_mode:p/1'.
+For more information, try recompiling with `-E'.
Index: tests/invalid/typeclass_mode.m
===================================================================
RCS file: typeclass_mode.m
diff -N typeclass_mode.m
--- /dev/null	Thu Mar 30 14:06:13 2000
+++ typeclass_mode.m	Sat Sep 16 10:17:43 2000
@@ -0,0 +1,7 @@
+:- module typeclass_mode.
+:- interface.
+
+:- typeclass c(T) where [
+	mode p(in) is det
+].
+

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3        |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list