aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/parser.cc100
-rw-r--r--gcc/testsuite/g++.dg/modules/mod-invalid-1.C7
-rw-r--r--gcc/testsuite/g++.dg/modules/part-8_a.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/part-8_b.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/part-8_c.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/part-hdr-1_c.C2
-rw-r--r--gcc/testsuite/g++.dg/modules/part-mac-1_c.C2
7 files changed, 95 insertions, 36 deletions
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 37536fa..bc1683b 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -14894,58 +14894,64 @@ cp_parser_already_scoped_statement (cp_parser* parser, bool *if_p,
/* Modules */
-/* Parse a module-name,
- identifier
- module-name . identifier
- header-name
+/* Parse a module-name or module-partition.
- Returns a pointer to module object, NULL. */
+ module-name:
+ module-name-qualifier [opt] identifier
-static module_state *
-cp_parser_module_name (cp_parser *parser)
-{
- cp_token *token = cp_lexer_peek_token (parser->lexer);
- if (token->type == CPP_HEADER_NAME)
- {
- cp_lexer_consume_token (parser->lexer);
+ module-partition:
+ : module-name-qualifier [opt] identifier
- return get_module (token->u.value);
- }
+ module-name-qualifier:
+ identifier .
+ module-name-qualifier identifier .
- module_state *parent = NULL;
- bool partitioned = false;
- if (token->type == CPP_COLON && named_module_p ())
- {
- partitioned = true;
- cp_lexer_consume_token (parser->lexer);
- }
+ Returns a pointer to the module object, or NULL on failure.
+ For PARTITION_P, PARENT is the module this is a partition of. */
+
+static module_state *
+cp_parser_module_name (cp_parser *parser, bool partition_p = false,
+ module_state *parent = NULL)
+{
+ if (partition_p
+ && cp_lexer_consume_token (parser->lexer)->type != CPP_COLON)
+ return NULL;
for (;;)
{
if (cp_lexer_peek_token (parser->lexer)->type != CPP_NAME)
{
- cp_parser_error (parser, "expected module-name");
- break;
+ if (partition_p)
+ cp_parser_error (parser, "expected module-partition");
+ else
+ cp_parser_error (parser, "expected module-name");
+ return NULL;
}
tree name = cp_lexer_consume_token (parser->lexer)->u.value;
- parent = get_module (name, parent, partitioned);
- token = cp_lexer_peek_token (parser->lexer);
- if (!partitioned && token->type == CPP_COLON)
- partitioned = true;
- else if (token->type != CPP_DOT)
+ parent = get_module (name, parent, partition_p);
+ if (cp_lexer_peek_token (parser->lexer)->type != CPP_DOT)
break;
cp_lexer_consume_token (parser->lexer);
- }
+ }
return parent;
}
+/* Parse a module-partition. Defers to cp_parser_module_name. */
+
+static module_state *
+cp_parser_module_partition (cp_parser *parser, module_state *parent = NULL)
+{
+ return cp_parser_module_name (parser, /*partition_p=*/true, parent);
+}
+
/* Named module-declaration
__module ; PRAGMA_EOL
- __module private ; PRAGMA_EOL (unimplemented)
- [__export] __module module-name attr-spec-seq-opt ; PRAGMA_EOL
+ __module : private ; PRAGMA_EOL (unimplemented)
+ [__export] __module module-name module-partition [opt]
+ attr-spec-seq-opt ; PRAGMA_EOL
*/
static module_parse
@@ -15003,9 +15009,12 @@ cp_parser_module_declaration (cp_parser *parser, module_parse mp_state,
else
{
module_state *mod = cp_parser_module_name (parser);
+ if (mod && cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
+ mod = cp_parser_module_partition (parser, mod);
tree attrs = cp_parser_attributes_opt (parser);
- mp_state = MP_PURVIEW_IMPORTS;
+ if (mod)
+ mp_state = MP_PURVIEW_IMPORTS;
if (!mod || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
goto skip_eol;
@@ -15017,7 +15026,10 @@ cp_parser_module_declaration (cp_parser *parser, module_parse mp_state,
}
/* Import-declaration
- [__export] __import module-name attr-spec-seq-opt ; PRAGMA_EOL */
+ __import module-name attr-spec-seq-opt ; PRAGMA_EOL
+ __import module-partition attr-spec-seq-opt ; PRAGMA_EOL
+ __import header-name attr-spec-seq-opt ; PRAGMA_EOL
+*/
static void
cp_parser_import_declaration (cp_parser *parser, module_parse mp_state,
@@ -15045,7 +15057,27 @@ cp_parser_import_declaration (cp_parser *parser, module_parse mp_state,
}
else
{
- module_state *mod = cp_parser_module_name (parser);
+ module_state *mod = NULL;
+ cp_token *next = cp_lexer_peek_token (parser->lexer);
+ if (next->type == CPP_HEADER_NAME)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ mod = get_module (next->u.value);
+ }
+ else if (next->type == CPP_COLON)
+ {
+ /* An import specifying a module-partition shall only appear after the
+ module-declaration in a module unit: [module.import]/4. */
+ if (named_module_p ()
+ && (mp_state == MP_PURVIEW_IMPORTS
+ || mp_state == MP_PRIVATE_IMPORTS))
+ mod = cp_parser_module_partition (parser);
+ else
+ error_at (next->location, "import specifying a module-partition"
+ " must appear after a named module-declaration");
+ }
+ else
+ mod = cp_parser_module_name (parser);
tree attrs = cp_parser_attributes_opt (parser);
if (!mod || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
diff --git a/gcc/testsuite/g++.dg/modules/mod-invalid-1.C b/gcc/testsuite/g++.dg/modules/mod-invalid-1.C
new file mode 100644
index 0000000..fadaba0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/mod-invalid-1.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts" }
+
+module;
+
+module :foo; // { dg-error "expected module-name" }
+
+import :foo; // { dg-error "import specifying a module-partition must appear after a named module-declaration" }
diff --git a/gcc/testsuite/g++.dg/modules/part-8_a.C b/gcc/testsuite/g++.dg/modules/part-8_a.C
new file mode 100644
index 0000000..09f956f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-8_a.C
@@ -0,0 +1,6 @@
+// PR c++/110808
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi group:tres }
+
+export module group:tres;
+int mul() { return 0; }
diff --git a/gcc/testsuite/g++.dg/modules/part-8_b.C b/gcc/testsuite/g++.dg/modules/part-8_b.C
new file mode 100644
index 0000000..1ade029
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-8_b.C
@@ -0,0 +1,6 @@
+// PR c++/110808
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi group }
+
+export module group;
+export import :tres;
diff --git a/gcc/testsuite/g++.dg/modules/part-8_c.C b/gcc/testsuite/g++.dg/modules/part-8_c.C
new file mode 100644
index 0000000..2351f28
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/part-8_c.C
@@ -0,0 +1,8 @@
+// PR c++/110808
+// { dg-additional-options "-fmodules-ts" }
+
+import group:tres; // { dg-error "expected .;." }
+
+int main() {
+ return mul(); // { dg-error "not declared" }
+}
diff --git a/gcc/testsuite/g++.dg/modules/part-hdr-1_c.C b/gcc/testsuite/g++.dg/modules/part-hdr-1_c.C
index 78a53d2..db57adc 100644
--- a/gcc/testsuite/g++.dg/modules/part-hdr-1_c.C
+++ b/gcc/testsuite/g++.dg/modules/part-hdr-1_c.C
@@ -2,4 +2,4 @@
// { dg-module-cmi {mod} }
export module mod;
-import mod:impl;
+import :impl;
diff --git a/gcc/testsuite/g++.dg/modules/part-mac-1_c.C b/gcc/testsuite/g++.dg/modules/part-mac-1_c.C
index 78a53d2..db57adc 100644
--- a/gcc/testsuite/g++.dg/modules/part-mac-1_c.C
+++ b/gcc/testsuite/g++.dg/modules/part-mac-1_c.C
@@ -2,4 +2,4 @@
// { dg-module-cmi {mod} }
export module mod;
-import mod:impl;
+import :impl;