Message ID | ZyD/tAVnWeMsCFms@tucnak |
---|---|
State | New |
Headers | show |
Series | c++, v2: Attempt to implement C++26 P3034R1 - Module Declarations Shouldn't be Macros [PR114461] | expand |
On Tue, Oct 29, 2024 at 04:31:00PM +0100, Jakub Jelinek wrote: > Here is a so far lightly tested patch, ok for trunk if it passes full > bootstrap/regtest or do you want some further changes? Bootstrapped/regtested successfully on x86_64-linux and i686-linux. Jakub
On 10/29/24 11:31 AM, Jakub Jelinek wrote: > On Fri, Oct 25, 2024 at 12:52:41PM -0400, Jason Merrill wrote: >> This does seem like a hole in the wording. I think the clear intent is that >> the name/partition must neither be macro-expanded nor come from macro >> expansion. > > I'll defer filing the DR and figuring out the right wording for the standard > to you/WG21. I've reported it to CWG, and people agree with both my understanding and the need for wording improvement. >>> The patch below implements what is above described as the first variant >>> of the first issue resolution, i.e. disables expansion of as many tokens >>> as could be in the valid module name and module partition syntax, but >>> as soon as it e.g. sees two adjacent identifiers, the second one can be >>> macro expanded. So, effectively: >>> #define SEMI ; >>> export module SEMI >>> used to be valid and isn't anymore, >>> #define FOO bar >>> export module FOO; >>> isn't valid, >>> #define COLON : >>> export module COLON private; >>> isn't valid, >>> #define BAR baz >>> export module foo.bar:baz.qux.BAR; >>> isn't valid, >> >> Agreed. > > Ok. > >>> but >>> #define BAZ .qux >>> export module foo BAZ; >>> or >>> #define QUX [[]] >>> export module foo QUX; >>> or >>> #define FREDDY :garply >>> export module foo FREDDY; >>> or >>> #define GARPLY private >>> module : GARPLY; >>> etc. is. >> >> I think QUX is valid, but the others are intended to be invalid. > > I've changed the patch so that the BAZ and FREDDY cases above > are also diagnosed as invalid, so cases where a module name or module > partition name is followed by an identifier defined as object-like or > function-like macro and where after macro expansion the first > non-padding/comment token is dot or colon (so, either an object-like > or function-like macro whose expansion starts with . or : or one > which expands to nothing and . or : following that macro either directly > or from some other macro expansion. > E.g. one could have > #define A [[vendor::attr(1 ? 2 > #define B 3)]] > export module foo.bar A : B; > which I think ought to be valid and expanded as > export module foo.bar [[vendor::attr(1 ? 2 : 3)]]; > or > #define A > #define B baz > export module foo.bar A : B; > which would preprocess into > export module foo.bar:baz; > and I think that is against the intent of the paper where the quick > scanners couldn't figure this out without actually performing preprocessing. > Unfortunately, trying to enter macro context inside of > cpp_maybe_module_directive doesn't seem to work well, so I've instead added > a flag and let cpp_get_token_1 to diagnose it later (but still during > preprocessing, because if going e.g. with -save-temps the distinction would > be lost, so it feels undesirable to diagnose that during parsing, plus > whether some token comes from a macro or not is currently only testable in > the FE when not -fno-track-macro-expansion and see above testcase that > the : or . actually might not come from a macro, yet there could be > a macro expanding to nothing in between. Sounds good. > I've kept the GARPLY case above as valid, I don't see the paper changing > anything in that regard (sure, the : has to not come from macro so that > the scanners can figure it out) and I think it isn't needed. It seems to me that no macro expansion should be done for a directive starting "module :" as that cannot be a pp-module. >>> --- gcc/testsuite/g++.dg/modules/dir-only-4.C.jj 2020-12-22 23:50:17.057972516 +0100 >>> +++ gcc/testsuite/g++.dg/modules/dir-only-4.C 2024-08-08 09:33:09.454522024 +0200 >>> @@ -1,8 +1,8 @@ >>> // { dg-additional-options {-fmodules-ts -fpreprocessed -fdirectives-only} } >>> -// { dg-module-cmi !foo } >>> +// { dg-module-cmi !baz } >>> module; >>> #define foo baz >>> -export module foo; >>> +export module baz; >>> class import {}; >>> --- gcc/testsuite/g++.dg/modules/atom-preamble-2_a.C.jj 2020-12-22 23:50:17.055972539 +0100 >>> +++ gcc/testsuite/g++.dg/modules/atom-preamble-2_a.C 2024-08-08 09:35:56.093364042 +0200 >>> @@ -1,6 +1,6 @@ >>> // { dg-additional-options "-fmodules-ts" } >>> #define malcolm kevin >>> -export module malcolm; >>> +export module kevin; >>> // { dg-module-cmi kevin } >>> export class X; >>> --- gcc/testsuite/g++.dg/modules/atom-preamble-4.C.jj 2020-12-22 23:50:17.055972539 +0100 >>> +++ gcc/testsuite/g++.dg/modules/atom-preamble-4.C 2024-08-08 09:35:32.463670046 +0200 >>> @@ -1,5 +1,5 @@ >>> // { dg-additional-options "-fmodules-ts" } >>> -#define NAME(X) X; >>> +#define NAME(X) ; >>> -export module NAME(bob) >>> +export module bob NAME(bob) >> >> It looks like these tests were specifically testing patterns that this paper >> makes ill-formed, and so we should check for errors instead of changing them >> to be well-formed. > > Ok, changed dir-only-4.C and atom-preamble-4.C back to previous content > + dg-error and added new tests with the changes in and not expecting > error. > I had to keep the atom-preamble-2_a.C change as is, because otherwise > all of atom-preamble-2*.C tests FAIL. Fair enough. But then let's also remove the #define that is no longer used. Incidentally, I think 2_b.C should fail because the pp-module is in the midle of an if-section, which is forbidden by the [cpp] grammar since P1857. > Here is a so far lightly tested patch, ok for trunk if it passes full > bootstrap/regtest or do you want some further changes? OK with removing the #define from atom-preamble-2_a.C. Jason
--- libcpp/include/cpplib.h.jj 2024-10-25 10:03:16.785374003 +0200 +++ libcpp/include/cpplib.h 2024-10-29 14:27:03.530521515 +0100 @@ -204,6 +204,9 @@ struct GTY(()) cpp_string { #define PURE_ZERO (1 << 7) /* Single 0 digit, used by the C++ frontend, set in c-lex.cc. */ #define COLON_SCOPE PURE_ZERO /* Adjacent colons in C < 23. */ +#define NO_DOT_COLON PURE_ZERO /* Set on CPP_NAME tokens whose expansion + shouldn't start with CPP_DOT or CPP_COLON + after optional CPP_PADDING. */ #define SP_DIGRAPH (1 << 8) /* # or ## token was a digraph. */ #define SP_PREV_WHITE (1 << 9) /* If whitespace before a ## operator, or before this token --- libcpp/internal.h.jj 2024-10-25 10:03:16.786373988 +0200 +++ libcpp/internal.h 2024-10-29 14:34:42.125244956 +0100 @@ -468,6 +468,10 @@ struct cpp_reader one. */ bool about_to_expand_macro_p; + /* True if the preprocessor should diagnose CPP_DOT or CPP_COLON + tokens as the first ones coming from macro expansion. */ + bool diagnose_dot_colon_from_macro_p; + /* Search paths for include files. */ struct cpp_dir *quote_include; /* "" */ struct cpp_dir *bracket_include; /* <> */ --- libcpp/lex.cc.jj 2024-10-25 10:03:16.786373988 +0200 +++ libcpp/lex.cc 2024-10-29 15:11:08.023890616 +0100 @@ -3604,6 +3604,78 @@ cpp_maybe_module_directive (cpp_reader * /* Maybe tell the tokenizer we expect a header-name down the road. */ pfile->state.directive_file_token = header_count; + + /* According to P3034R1, pp-module-name and pp-module-partition tokens + if any shouldn't be macro expanded and identifiers shouldn't be + defined as object-like macro. */ + if (!header_count && peek->type == CPP_NAME) + { + int state = 0; + do + { + cpp_token *tok = peek; + if (tok->type == CPP_NAME) + { + cpp_hashnode *node = tok->val.node.node; + /* Don't attempt to expand the token. */ + tok->flags |= NO_EXPAND; + if (_cpp_defined_macro_p (node) + && _cpp_maybe_notify_macro_use (pfile, node, + tok->src_loc) + && !cpp_fun_like_macro_p (node)) + { + if (state == 0) + cpp_error_with_line (pfile, CPP_DL_ERROR, + tok->src_loc, 0, + "module name %qs cannot " + "be an object-like macro", + NODE_NAME (node)); + else + cpp_error_with_line (pfile, CPP_DL_ERROR, + tok->src_loc, 0, + "module partition %qs cannot " + "be an object-like macro", + NODE_NAME (node)); + } + } + peek = _cpp_lex_direct (pfile); + backup++; + if (tok->type == CPP_NAME) + { + if (peek->type == CPP_DOT) + continue; + else if (peek->type == CPP_COLON && state == 0) + { + ++state; + continue; + } + else if (peek->type == CPP_OPEN_PAREN) + { + if (state == 0) + cpp_error_with_line (pfile, CPP_DL_ERROR, + peek->src_loc, 0, + "module name followed by %<(%>"); + else + cpp_error_with_line (pfile, CPP_DL_ERROR, + peek->src_loc, 0, + "module partition followed by " + "%<(%>"); + break; + } + else if (peek->type == CPP_NAME + && _cpp_defined_macro_p (peek->val.node.node)) + { + peek->flags |= NO_DOT_COLON; + break; + } + else + break; + } + else if (peek->type != CPP_NAME) + break; + } + while (true); + } } else { --- libcpp/macro.cc.jj 2024-10-25 10:03:16.788373960 +0200 +++ libcpp/macro.cc 2024-10-29 16:03:10.225312607 +0100 @@ -3076,6 +3076,9 @@ cpp_get_token_1 (cpp_reader *pfile, loca if (pfile->state.prevent_expansion) break; + if ((result->flags & NO_DOT_COLON) != 0) + pfile->diagnose_dot_colon_from_macro_p = true; + /* Conditional macros require that a predicate be evaluated first. */ if ((node->flags & NODE_CONDITIONAL) != 0) @@ -3226,6 +3229,20 @@ cpp_get_token_1 (cpp_reader *pfile, loca } } + if (pfile->diagnose_dot_colon_from_macro_p + && !pfile->about_to_expand_macro_p + && result->type != CPP_PADDING + && result->type != CPP_COMMENT) + { + if (result->type == CPP_DOT || result->type == CPP_COLON) + cpp_error_with_line (pfile, CPP_DL_ERROR, + result->src_loc, 0, + "%qc in module name or partition " + "comes from or after macro expansion", + result->type == CPP_DOT ? '.' : ':'); + pfile->diagnose_dot_colon_from_macro_p = false; + } + return result; } --- gcc/testsuite/g++.dg/modules/cpp-7.C.jj 2024-10-29 13:53:15.228616120 +0100 +++ gcc/testsuite/g++.dg/modules/cpp-7.C 2024-10-29 14:45:11.319542826 +0100 @@ -0,0 +1,8 @@ +// { dg-do preprocess } +// { dg-additional-options "-fmodules-ts" } + +#define NAME(X) X; + +export module NAME(bob) // { dg-error "module name followed by '\\\('" } + +int i; --- gcc/testsuite/g++.dg/modules/cpp-8.C.jj 2024-10-29 13:53:15.250615813 +0100 +++ gcc/testsuite/g++.dg/modules/cpp-8.C 2024-10-29 14:44:02.278497703 +0100 @@ -0,0 +1,7 @@ +// { dg-do preprocess } +// { dg-additional-options "-fmodules-ts" } + +#define bob fred; +export module bob; // { dg-error "module name 'bob' cannot be an object-like macro" } + +int i; --- gcc/testsuite/g++.dg/modules/cpp-9.C.jj 2024-10-29 13:53:15.250615813 +0100 +++ gcc/testsuite/g++.dg/modules/cpp-9.C 2024-10-29 14:45:53.512959265 +0100 @@ -0,0 +1,7 @@ +// { dg-do preprocess } +// { dg-additional-options "-fmodules-ts" } + +#define bob fred; +export module foo.bob; // { dg-error "module name 'bob' cannot be an object-like macro" } + +int i; --- gcc/testsuite/g++.dg/modules/cpp-10.C.jj 2024-10-29 13:53:15.250615813 +0100 +++ gcc/testsuite/g++.dg/modules/cpp-10.C 2024-10-29 14:45:45.528069701 +0100 @@ -0,0 +1,7 @@ +// { dg-do preprocess } +// { dg-additional-options "-fmodules-ts" } + +#define bob fred; +export module foo:bob; // { dg-error "module partition 'bob' cannot be an object-like macro" } + +int i; --- gcc/testsuite/g++.dg/modules/cpp-11.C.jj 2024-10-29 13:53:15.250615813 +0100 +++ gcc/testsuite/g++.dg/modules/cpp-11.C 2024-10-29 14:45:20.844411089 +0100 @@ -0,0 +1,7 @@ +// { dg-do preprocess } +// { dg-additional-options "-fmodules-ts" } + +#define bob fred; +export module foo:bar.bob; // { dg-error "module partition 'bob' cannot be an object-like macro" } + +int i; --- gcc/testsuite/g++.dg/modules/cpp-12.C.jj 2024-10-29 15:37:32.043702670 +0100 +++ gcc/testsuite/g++.dg/modules/cpp-12.C 2024-10-29 15:50:59.545468046 +0100 @@ -0,0 +1,7 @@ +// { dg-do preprocess } +// { dg-additional-options "-fmodules-ts" } + +#define baz .qux // { dg-error "'\\\.' in module name or partition comes from or after macro expansion" } +export module foo:bar baz; + +int i; --- gcc/testsuite/g++.dg/modules/cpp-13.C.jj 2024-10-29 15:38:21.892008287 +0100 +++ gcc/testsuite/g++.dg/modules/cpp-13.C 2024-10-29 15:51:08.306346264 +0100 @@ -0,0 +1,7 @@ +// { dg-do preprocess } +// { dg-additional-options "-fmodules-ts" } + +#define baz :qux.garply // { dg-error "':' in module name or partition comes from or after macro expansion" } +export module foo.bar baz; + +int i; --- gcc/testsuite/g++.dg/modules/cpp-14.C.jj 2024-10-29 15:40:29.607229223 +0100 +++ gcc/testsuite/g++.dg/modules/cpp-14.C 2024-10-29 15:40:43.249039193 +0100 @@ -0,0 +1,7 @@ +// { dg-do preprocess } +// { dg-additional-options "-fmodules-ts" } + +#define baz [[]] +export module foo.bar baz; + +int i; --- gcc/testsuite/g++.dg/modules/cpp-15.C.jj 2024-10-29 15:40:50.729934981 +0100 +++ gcc/testsuite/g++.dg/modules/cpp-15.C 2024-10-29 15:47:52.610066467 +0100 @@ -0,0 +1,8 @@ +// { dg-do preprocess } +// { dg-additional-options "-fmodules-ts" } + +#define baz +#define qux +export module foo.bar baz . garply qux; // { dg-error "'\\\.' in module name or partition comes from or after macro expansion" } + +int i; --- gcc/testsuite/g++.dg/modules/cpp-16.C.jj 2024-10-29 15:41:44.169190577 +0100 +++ gcc/testsuite/g++.dg/modules/cpp-16.C 2024-10-29 15:48:21.870659744 +0100 @@ -0,0 +1,8 @@ +// { dg-do preprocess } +// { dg-additional-options "-fmodules-ts" } + +#define baz +#define qux +export module foo.bar baz : garply qux; // { dg-error "':' in module name or partition comes from or after macro expansion" } + +int i; --- gcc/testsuite/g++.dg/modules/cpp-17.C.jj 2024-10-29 15:48:49.977269054 +0100 +++ gcc/testsuite/g++.dg/modules/cpp-17.C 2024-10-29 15:49:21.493830972 +0100 @@ -0,0 +1,7 @@ +// { dg-do preprocess } +// { dg-additional-options "-fmodules-ts" } + +#define baz(x) x qux +export module foo:bar baz(.); // { dg-error "'\\\.' in module name or partition comes from or after macro expansion" } + +int i; --- gcc/testsuite/g++.dg/modules/cpp-18.C.jj 2024-10-29 15:48:52.688231371 +0100 +++ gcc/testsuite/g++.dg/modules/cpp-18.C 2024-10-29 15:49:33.722660988 +0100 @@ -0,0 +1,7 @@ +// { dg-do preprocess } +// { dg-additional-options "-fmodules-ts" } + +#define baz(x) x qux.garply +export module foo.bar baz(:); // { dg-error "':' in module name or partition comes from or after macro expansion" } + +int i; --- gcc/testsuite/g++.dg/modules/cpp-19.C.jj 2024-10-29 15:48:55.852187394 +0100 +++ gcc/testsuite/g++.dg/modules/cpp-19.C 2024-10-29 15:49:50.529427372 +0100 @@ -0,0 +1,8 @@ +// { dg-do preprocess } +// { dg-additional-options "-fmodules-ts" } + +#define baz(x) +#define qux(x) +export module foo.bar baz(.) . garply qux(:); // { dg-error "'\\\.' in module name or partition comes from or after macro expansion" } + +int i; --- gcc/testsuite/g++.dg/modules/cpp-20.C.jj 2024-10-29 15:48:58.555149822 +0100 +++ gcc/testsuite/g++.dg/modules/cpp-20.C 2024-10-29 15:50:04.487233357 +0100 @@ -0,0 +1,8 @@ +// { dg-do preprocess } +// { dg-additional-options "-fmodules-ts" } + +#define baz(x) +#define qux(x) +export module foo.bar baz(:) : garply qux(.); // { dg-error "':' in module name or partition comes from or after macro expansion" } + +int i; --- gcc/testsuite/g++.dg/modules/pmp-4.C.jj 2024-10-29 13:53:15.251615799 +0100 +++ gcc/testsuite/g++.dg/modules/pmp-4.C 2024-10-29 13:53:15.251615799 +0100 @@ -0,0 +1,9 @@ +// { dg-additional-options -fmodules-ts } + +export module bob; +// { dg-module-cmi bob } + +#define PRIVATE private + +module :PRIVATE; // { dg-message "sorry, unimplemented: private module fragment" } +int i; --- gcc/testsuite/g++.dg/modules/pmp-5.C.jj 2024-10-29 13:53:15.251615799 +0100 +++ gcc/testsuite/g++.dg/modules/pmp-5.C 2024-10-29 13:53:15.251615799 +0100 @@ -0,0 +1,9 @@ +// { dg-additional-options -fmodules-ts } + +export module bob; +// { dg-module-cmi bob } + +#define PRIVATE_SEMI private ; + +module :PRIVATE_SEMI // { dg-message "sorry, unimplemented: private module fragment" } +int i; --- gcc/testsuite/g++.dg/modules/pmp-6.C.jj 2024-10-29 13:53:15.251615799 +0100 +++ gcc/testsuite/g++.dg/modules/pmp-6.C 2024-10-29 13:53:15.251615799 +0100 @@ -0,0 +1,9 @@ +// { dg-additional-options -fmodules-ts } + +export module bob; +// { dg-module-cmi bob } + +#define SEMI ; + +module :private SEMI // { dg-message "sorry, unimplemented: private module fragment" } +int i; --- gcc/testsuite/g++.dg/modules/token-6.C.jj 2024-10-29 13:53:15.251615799 +0100 +++ gcc/testsuite/g++.dg/modules/token-6.C 2024-10-29 14:44:23.202208319 +0100 @@ -0,0 +1,9 @@ +// { dg-additional-options "-fmodules-ts" } + +#define bob fred +export module bob; +// { dg-error "module name 'bob' cannot be an object-like macro" "" { target *-*-* } .-1 } + +// { dg-module-cmi !bob } +// { dg-module-cmi !fred } +// { dg-prune-output "not writing module" } --- gcc/testsuite/g++.dg/modules/token-7.C.jj 2024-10-29 13:53:15.251615799 +0100 +++ gcc/testsuite/g++.dg/modules/token-7.C 2024-10-29 14:45:00.891687054 +0100 @@ -0,0 +1,9 @@ +// { dg-additional-options "-fmodules-ts" } + +#define bob fred +export module foo.bar.bob; +// { dg-error "module name 'bob' cannot be an object-like macro" "" { target *-*-* } .-1 } + +// { dg-module-cmi !foo.bar.bob } +// { dg-module-cmi !foo.bar.fred } +// { dg-prune-output "not writing module" } --- gcc/testsuite/g++.dg/modules/token-8.C.jj 2024-10-29 13:53:15.252615786 +0100 +++ gcc/testsuite/g++.dg/modules/token-8.C 2024-10-29 14:45:31.273266856 +0100 @@ -0,0 +1,9 @@ +// { dg-additional-options "-fmodules-ts" } + +#define bob fred +export module foo.bar:bob; +// { dg-error "module partition 'bob' cannot be an object-like macro" "" { target *-*-* } .-1 } + +// { dg-module-cmi !foo.bar:bob } +// { dg-module-cmi !foo.bar:fred } +// { dg-prune-output "not writing module" } --- gcc/testsuite/g++.dg/modules/token-9.C.jj 2024-10-29 13:53:15.252615786 +0100 +++ gcc/testsuite/g++.dg/modules/token-9.C 2024-10-29 14:44:11.577369096 +0100 @@ -0,0 +1,9 @@ +// { dg-additional-options "-fmodules-ts" } + +#define garply fred +export module foo.bar:baz.garply; +// { dg-error "module partition 'garply' cannot be an object-like macro" "" { target *-*-* } .-1 } + +// { dg-module-cmi !foo.bar:baz.garply } +// { dg-module-cmi !foo.bar:baz.fred } +// { dg-prune-output "not writing module" } --- gcc/testsuite/g++.dg/modules/token-10.C.jj 2024-10-29 13:53:15.252615786 +0100 +++ gcc/testsuite/g++.dg/modules/token-10.C 2024-10-29 13:53:15.252615786 +0100 @@ -0,0 +1,6 @@ +// { dg-additional-options "-fmodules-ts" } + +#define semi ; +export module foo.bar:baz.bob semi + +// { dg-module-cmi foo.bar:baz.bob } --- gcc/testsuite/g++.dg/modules/token-11.C.jj 2024-10-29 13:53:15.252615786 +0100 +++ gcc/testsuite/g++.dg/modules/token-11.C 2024-10-29 13:53:15.252615786 +0100 @@ -0,0 +1,6 @@ +// { dg-additional-options "-fmodules-ts" } + +#define attr [[]] +export module foo.bar:baz.bob attr ; + +// { dg-module-cmi foo.bar:baz.bob } --- gcc/testsuite/g++.dg/modules/token-12.C.jj 2024-10-29 13:53:15.252615786 +0100 +++ gcc/testsuite/g++.dg/modules/token-12.C 2024-10-29 13:53:15.252615786 +0100 @@ -0,0 +1,6 @@ +// { dg-additional-options "-fmodules-ts" } + +#define bob() fred +export module bob; + +// { dg-module-cmi bob } --- gcc/testsuite/g++.dg/modules/token-13.C.jj 2024-10-29 13:53:15.253615772 +0100 +++ gcc/testsuite/g++.dg/modules/token-13.C 2024-10-29 13:53:15.253615772 +0100 @@ -0,0 +1,6 @@ +// { dg-additional-options "-fmodules-ts" } + +#define bob() fred +export module foo.bar.bob; + +// { dg-module-cmi foo.bar.bob } --- gcc/testsuite/g++.dg/modules/token-14.C.jj 2024-10-29 13:53:15.253615772 +0100 +++ gcc/testsuite/g++.dg/modules/token-14.C 2024-10-29 13:53:15.253615772 +0100 @@ -0,0 +1,6 @@ +// { dg-additional-options "-fmodules-ts" } + +#define bob(n) fred +export module foo.bar:bob; + +// { dg-module-cmi foo.bar:bob } --- gcc/testsuite/g++.dg/modules/token-15.C.jj 2024-10-29 13:53:15.253615772 +0100 +++ gcc/testsuite/g++.dg/modules/token-15.C 2024-10-29 13:53:15.253615772 +0100 @@ -0,0 +1,6 @@ +// { dg-additional-options "-fmodules-ts" } + +#define bob() fred +export module foo.bar:baz.bob; + +// { dg-module-cmi foo.bar:baz.bob } --- gcc/testsuite/g++.dg/modules/token-16.C.jj 2024-10-29 13:53:15.253615772 +0100 +++ gcc/testsuite/g++.dg/modules/token-16.C 2024-10-29 14:44:38.975990154 +0100 @@ -0,0 +1,9 @@ +// { dg-additional-options "-fmodules-ts" } + +#define bob() fred +export module foo.bar:baz.bob (); +// { dg-error "module partition followed by '\\\('" "" { target *-*-* } .-1 } +// { dg-error "expected" "" { target *-*-* } .-2 } + +// { dg-module-cmi !foo.bar:baz.bob } +// { dg-module-cmi !foo.bar:baz.fred } --- gcc/testsuite/g++.dg/modules/dir-only-3.C.jj 2020-12-23 14:09:58.847107398 +0100 +++ gcc/testsuite/g++.dg/modules/dir-only-3.C 2024-10-29 14:44:48.230862156 +0100 @@ -7,10 +7,12 @@ # 32 "<command-line>" 2 # 1 "dir-only-3.C" // { dg-additional-options {-fmodules-ts -fpreprocessed -fdirectives-only} } -// { dg-module-cmi foo } +// { dg-module-cmi !foo } module; #define foo baz export module foo; +// { dg-error "module name 'foo' cannot be an object-like macro" "" { target *-*-* } 5 } +// { dg-prune-output "not writing module" } class import {}; --- gcc/testsuite/g++.dg/modules/dir-only-4.C.jj 2024-08-30 09:09:46.603609137 +0200 +++ gcc/testsuite/g++.dg/modules/dir-only-4.C 2024-10-29 15:33:01.032477847 +0100 @@ -2,7 +2,7 @@ // { dg-module-cmi !foo } module; #define foo baz -export module foo; +export module foo; // { dg-error "module name 'foo' cannot be an object-like macro" } class import {}; --- gcc/testsuite/g++.dg/modules/dir-only-5.C.jj 2024-10-29 15:18:50.438386316 +0100 +++ gcc/testsuite/g++.dg/modules/dir-only-5.C 2024-10-29 13:53:15.282615367 +0100 @@ -0,0 +1,9 @@ +// { dg-additional-options {-fmodules-ts -fpreprocessed -fdirectives-only} } +// { dg-module-cmi !baz } +module; +#define foo baz +export module baz; + +class import {}; + +import x; // { dg-error "post-module-declaration" } --- gcc/testsuite/g++.dg/modules/atom-preamble-2_a.C.jj 2020-12-23 14:09:58.845107420 +0100 +++ gcc/testsuite/g++.dg/modules/atom-preamble-2_a.C 2024-10-29 13:53:15.298615144 +0100 @@ -1,6 +1,6 @@ // { dg-additional-options "-fmodules-ts" } #define malcolm kevin -export module malcolm; +export module kevin; // { dg-module-cmi kevin } export class X; --- gcc/testsuite/g++.dg/modules/atom-preamble-4.C.jj 2020-12-23 14:09:58.845107420 +0100 +++ gcc/testsuite/g++.dg/modules/atom-preamble-4.C 2024-10-29 15:31:55.292393604 +0100 @@ -3,3 +3,5 @@ export module NAME(bob) +// { dg-error "module name followed by '\\\('" "" { target *-*-* } .-2 } +// { dg-error "expected ';' before '\\\(' token" "" { target *-*-* } .-3 } --- gcc/testsuite/g++.dg/modules/atom-preamble-5.C.jj 2024-10-29 15:17:29.641522799 +0100 +++ gcc/testsuite/g++.dg/modules/atom-preamble-5.C 2024-10-29 13:53:15.299615130 +0100 @@ -0,0 +1,5 @@ +// { dg-additional-options "-fmodules-ts" } +#define NAME(X) ; + +export module bob NAME(bob) +