aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathaniel Shead <nathanieloshead@gmail.com>2024-05-24 00:08:57 +1000
committerNathaniel Shead <nathanieloshead@gmail.com>2024-05-25 00:10:42 +1000
commitdae606a11eb99814e452b49241fa76f7678f53b8 (patch)
tree9d1ff2aa2e2bf31d53a3009b207fc206a25120be
parent03531ec45f15aa187bbab7842a1eb6cf746a104b (diff)
downloadgcc-dae606a11eb99814e452b49241fa76f7678f53b8.zip
gcc-dae606a11eb99814e452b49241fa76f7678f53b8.tar.gz
gcc-dae606a11eb99814e452b49241fa76f7678f53b8.tar.bz2
c++/modules: Improve errors for bad module-directives [PR115200]
This fixes an ICE when a module directive is not given at global scope. Although not explicitly mentioned, it seems implied from [basic.link] p1 and [module.global.frag] that a module-declaration must appear at the global scope after preprocessing. Apart from this the patch also slightly improves the errors given when accidentally using a module control-line in other situations where it is not expected. PR c++/115200 gcc/cp/ChangeLog: * parser.cc (cp_parser_error_1): Special-case unexpected module directives for better diagnostics. (cp_parser_module_declaration): Check that the module declaration is at global scope. (cp_parser_import_declaration): Sync error message with that in cp_parser_error_1. gcc/testsuite/ChangeLog: * g++.dg/modules/mod-decl-1.C: Update error messages. * g++.dg/modules/mod-decl-6.C: New test. * g++.dg/modules/mod-decl-7.C: New test. * g++.dg/modules/mod-decl-8.C: New test. Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com> Reviewed-by: Jason Merrill <jason@redhat.com>
-rw-r--r--gcc/cp/parser.cc26
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-decl-1.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-decl-6.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-decl-7.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-decl-8.C14
5 files changed, 64 insertions, 6 deletions
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 476ddc0..7796251 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -3230,6 +3230,19 @@ cp_parser_error_1 (cp_parser* parser, const char* gmsgid,
return;
}
+ if (cp_token_is_module_directive (token))
+ {
+ auto_diagnostic_group d;
+ error_at (token->location, "unexpected module directive");
+ if (token->keyword != RID__EXPORT)
+ inform (token->location, "perhaps insert a line break after"
+ " %qs, or other disambiguation, to prevent this being"
+ " considered a module control-line",
+ (token->keyword == RID__MODULE) ? "module" : "import");
+ cp_parser_skip_to_pragma_eol (parser, token);
+ return;
+ }
+
/* If this is actually a conflict marker, report it as such. */
if (token->type == CPP_LSHIFT
|| token->type == CPP_RSHIFT
@@ -15135,12 +15148,19 @@ cp_parser_module_declaration (cp_parser *parser, module_parse mp_state,
parser->lexer->in_pragma = true;
cp_token *token = cp_lexer_consume_token (parser->lexer);
+ tree scope = current_scope ();
if (flag_header_unit)
{
error_at (token->location,
"module-declaration not permitted in header-unit");
goto skip_eol;
}
+ else if (scope != global_namespace)
+ {
+ error_at (token->location, "module-declaration must be at global scope");
+ inform (DECL_SOURCE_LOCATION (scope), "scope opened here");
+ goto skip_eol;
+ }
else if (mp_state == MP_FIRST && !exporting
&& cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
{
@@ -15217,9 +15237,9 @@ cp_parser_import_declaration (cp_parser *parser, module_parse mp_state,
error_at (token->location, "post-module-declaration"
" imports must be contiguous");
note_lexer:
- inform (token->location, "perhaps insert a line break, or other"
- " disambiguation, to prevent this being considered a"
- " module control-line");
+ inform (token->location, "perhaps insert a line break after"
+ " %<import%>, or other disambiguation, to prevent this"
+ " being considered a module control-line");
skip_eol:
cp_parser_skip_to_pragma_eol (parser, token);
}
diff --git a/gcc/testsuite/g++.dg/modules/mod-decl-1.C b/gcc/testsuite/g++.dg/modules/mod-decl-1.C
index 23d3448..df398b3 100644
--- a/gcc/testsuite/g++.dg/modules/mod-decl-1.C
+++ b/gcc/testsuite/g++.dg/modules/mod-decl-1.C
@@ -10,17 +10,19 @@ module foo.second; // { dg-error "only permitted as" }
namespace Foo
{
-module third; // { dg-error "only permitted as" }
+module third; // { dg-error "must be at global scope" }
}
struct Baz
{
- module forth; // { dg-error "expected" }
+ module forth; // { dg-error "unexpected module directive" }
+ // { dg-message "line break after .module." "" { target *-*-* } .-1 }
};
void Bink ()
{
- module fifth; // { dg-error "expected" }
+ module fifth; // { dg-error "unexpected module directive" }
+ // { dg-message "line break after .module." "" { target *-*-* } .-1 }
}
module a.; // { dg-error "only permitted as" }
diff --git a/gcc/testsuite/g++.dg/modules/mod-decl-6.C b/gcc/testsuite/g++.dg/modules/mod-decl-6.C
new file mode 100644
index 0000000..5fb3424
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-decl-6.C
@@ -0,0 +1,11 @@
+// PR c++/115200
+// { dg-additional-options "-fmodules-ts -Wno-global-module" }
+// { dg-module-cmi !M }
+
+module;
+
+namespace ns { // { dg-message "scope opened here" }
+
+export module M; // { dg-error "global scope" }
+
+}
diff --git a/gcc/testsuite/g++.dg/modules/mod-decl-7.C b/gcc/testsuite/g++.dg/modules/mod-decl-7.C
new file mode 100644
index 0000000..d25a193
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-decl-7.C
@@ -0,0 +1,11 @@
+// PR c++/115200
+// { dg-additional-options "-fmodules-ts -Wno-global-module" }
+// { dg-module-cmi !M }
+
+module;
+
+void foo() {
+
+export module M; // { dg-error "unexpected module directive" }
+
+}
diff --git a/gcc/testsuite/g++.dg/modules/mod-decl-8.C b/gcc/testsuite/g++.dg/modules/mod-decl-8.C
new file mode 100644
index 0000000..9f5f1de
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-decl-8.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi M }
+
+export module M;
+
+struct module {};
+struct import {};
+
+void foo() {
+ module
+ x; // OK
+ import
+ y; // OK
+}