Re: [PATCH] testsuite: Add check_effective_target_d_runtime_has_std_library procedure
On 15/04/2020 17:26, Rainer Orth wrote: > Hi Richard, > >> Iain Buclaw via Gcc-patches writes: >>> Hi, >>> >>> This patch adds an effect target d_runtime_has_std_library to >>> target-supports.exp, and some preliminary uses of it. >>> >>> The current check_effective_target_d_runtime procedure returns false if >>> the target is without any core runtime library for D. This additional >>> procedure is for targets where the core runtime library exists, but is >>> without the higher level standard D library. >>> >>> OK for master? >> >> OK. FAOD though, D-related effective-target keywords are covered by the >> D frontend maintainership. > > indeed. However, they still need documenting in sourcebuild.texi. Iain, > please do so before committing. > Thanks, committed with added documentation, attached the updated patch. Iain. --- gcc/ChangeLog: * doc/sourcebuild.texi (Effective-Target Keywords, Environment attributes): Document d_runtime_has_std_library. gcc/testsuite/ChangeLog: * gdc.dg/link.d: Use d_runtime_has_std_library effective target. * gdc.dg/runnable.d: Move phobos tests to... * gdc.dg/runnable2.d: ...here. New test. * lib/target-supports.exp (check_effective_target_d_runtime_has_std_library): New. libphobos/ChangeLog: * testsuite/libphobos.phobos/phobos.exp: Skip if effective target is not d_runtime_has_std_library. * testsuite/libphobos.phobos_shared/phobos_shared.exp: Likewise. --- gcc/doc/sourcebuild.texi | 3 + gcc/testsuite/gdc.dg/link.d | 2 +- gcc/testsuite/gdc.dg/runnable.d | 229 gcc/testsuite/gdc.dg/runnable2.d | 244 ++ gcc/testsuite/lib/target-supports.exp | 15 ++ .../testsuite/libphobos.phobos/phobos.exp | 5 + .../libphobos.phobos_shared/phobos_shared.exp | 5 + 7 files changed, 273 insertions(+), 230 deletions(-) create mode 100644 gcc/testsuite/gdc.dg/runnable2.d diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index de28227236a..c1642bad398 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -2207,6 +2207,9 @@ overloads for @code{strchr} etc. functions. @item d_runtime Target provides the D runtime. +@item d_runtime_has_std_library +Target provides the D standard library (Phobos). + @item dummy_wcsftime Target uses a dummy @code{wcsftime} function that always returns zero. diff --git a/gcc/testsuite/gdc.dg/link.d b/gcc/testsuite/gdc.dg/link.d index a8ca4ed5cb6..5efd0ad347f 100644 --- a/gcc/testsuite/gdc.dg/link.d +++ b/gcc/testsuite/gdc.dg/link.d @@ -1,4 +1,4 @@ -// { dg-do link { target d_runtime } } +// { dg-do link { target d_runtime_has_std_library } } /**/ diff --git a/gcc/testsuite/gdc.dg/runnable.d b/gcc/testsuite/gdc.dg/runnable.d index 484a9709bf3..7307e09a645 100644 --- a/gcc/testsuite/gdc.dg/runnable.d +++ b/gcc/testsuite/gdc.dg/runnable.d @@ -9,20 +9,6 @@ import core.stdc.stdio; import gcc.attribute; -/**/ -// https://bugzilla.gdcproject.org/show_bug.cgi?id=2 - -struct S -{ -string toString() { return "foo"; } -} - -void test2() -{ -import std.string : format; -assert(format("%s", S()) == "foo"); -} - /**/ // https://bugzilla.gdcproject.org/show_bug.cgi?id=4 @@ -33,35 +19,6 @@ void test4() static assert(!__traits(compiles, str.sort)); } -/**/ -// https://bugzilla.gdcproject.org/show_bug.cgi?id=15 - -class B -{ -class A { } -A a; -} - -class C -{ -void visit(B b) -{ -import std.algorithm : map; -auto as = [b.a]; -as.map!(d => d); -} -} - -/**/ -// https://bugzilla.gdcproject.org/show_bug.cgi?id=16 - -void test16() -{ -import std.parallelism : taskPool; - -taskPool.reduce!"a+b"([0, 1, 2, 3]); -} - /**/ // https://bugzilla.gdcproject.org/show_bug.cgi?id=17 @@ -99,59 +56,6 @@ void test17() (new ModuleWriter()).save ("test.0.mci"); } -/**/ -// https://bugzilla.gdcproject.org/show_bug.cgi?id=18 - -class C18 -{ -struct Link -{ -int x; -int y; -} - -void sort_links() -{ -import std.algorithm : sort; -import std.array : empty; -import std.exception : enforce; - -enforce(!_link.empty); - -bool lt(Link a, Link b) -{ -if(a.x > b.x) -return false; -if(a.x < b.x) -return true; -if(a.y >= b.y) -return false; -else -return true; -} -sort!(lt)(_link); -} - -this() -{ -_link ~= Link(8, 3); -_link ~= Link(4, 7); -_link ~=
[PATCH] c++: Fix crash with template spec in different namespace [PR94255]
This is an ICE on invalid, because we're specializing S::foo in the wrong namespace. cp_parser_class_specifier_1 parses S::foo in M and then it tries to push the nested-name-specifier of foo, which is S. By that, we're breaking the assumption of push_inner_scope that the pushed scope must be a scope nested inside current scope: current scope is M, but the namespace context of S is N, and N is not nested in M, so we fell into an infinite loop in push_inner_scope_r. (cp_parser_class_head called check_specialization_namespace which already gave a permerror.) Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? PR c++/94255 * parser.c (cp_parser_class_specifier_1): Check that the scope is nested inside current scope before pushing it. * g++.dg/template/spec41.C: New test. --- gcc/cp/parser.c| 7 ++- gcc/testsuite/g++.dg/template/spec41.C | 17 + 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/template/spec41.C diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index d2f3f853cb4..d4482ef5a90 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -23858,7 +23858,12 @@ cp_parser_class_specifier_1 (cp_parser* parser) if (nested_name_specifier_p) { scope = CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)); - old_scope = push_inner_scope (scope); + /* SCOPE must be a scope nested inside current scope. */ + if (is_nested_namespace (current_namespace, + decl_namespace_context (scope))) + old_scope = push_inner_scope (scope); + else + nested_name_specifier_p = false; } type = begin_class_definition (type); diff --git a/gcc/testsuite/g++.dg/template/spec41.C b/gcc/testsuite/g++.dg/template/spec41.C new file mode 100644 index 000..249fde74c3a --- /dev/null +++ b/gcc/testsuite/g++.dg/template/spec41.C @@ -0,0 +1,17 @@ +// PR c++/94255 - crash with template spec in different namespace. +// { dg-do compile { target c++11 } } + +namespace N { + class S { +template struct foo; + }; + namespace M { +using S = ::N::S; + } +} + +namespace N { + namespace M { +template <> struct S::foo {}; // { dg-error "specialization of" } + } +} base-commit: b57e1621eb76ba80c949ad098829aa8171a8c4ab -- Marek Polacek • Red Hat, Inc. • 300 A St, Boston, MA
[committed][PR debug/94439] Don't let DEBUG_INSNSs change register renaming decisions
In this BZ we're getting a debug compare failure. Thanks to a nice hint from Jakub it was pretty easy to track it back to the register renaming pass which was making different renaming decisions based on the existence of DEBUG_INSNs. The culprit is check_new_reg_p which potentially changes its return value in the presence of a DEBUG_INSN in the use chain which in turn potentially changes the renaming decisions made. This patch arranges to always ignore DEBUG_INSNs in the chain within check_new_reg_p and the decisions we get there are consistent. I've bootstrapped and regression tested on x86_64, i686, ppc64le, ppc64. It's also tested without regressions on a variety of *-elf targets and built a bunch of *-linux-gnu cross toolchains along the way as well. Committed to the trunk. Jeff commit baf3b9b2e5259558ef86bd62398e2ccecd7a4a4c Author: Jeff Law Date: Sat Apr 18 09:39:18 2020 -0600 Don't let DEBUG_INSNSs change register renaming decisions PR debug/94439 * regrename.c (check_new_reg_p): Ignore DEBUG_INSNs when walking the chain. PR debug/94439 * gcc.dg/torture/pr94439.c: New test. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index aa0902274e5..1edb5f2d70b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2020-04-18 Jeff Law + + PR debug/94439 + * regrename.c (check_new_reg_p): Ignore DEBUG_INSNs when walking + the chain. + 2020-04-18 Iain Buclaw * doc/sourcebuild.texi (Effective-Target Keywords, Environment diff --git a/gcc/regrename.c b/gcc/regrename.c index 663935b7ec1..669a6ead705 100644 --- a/gcc/regrename.c +++ b/gcc/regrename.c @@ -348,11 +348,17 @@ check_new_reg_p (int reg ATTRIBUTE_UNUSED, int new_reg, /* See whether it accepts all modes that occur in definition and uses. */ for (tmp = this_head->first; tmp; tmp = tmp->next_use) -if ((!targetm.hard_regno_mode_ok (new_reg, GET_MODE (*tmp->loc)) -&& ! DEBUG_INSN_P (tmp->insn)) - || call_clobbered_in_chain_p (this_head, GET_MODE (*tmp->loc), - new_reg)) - return false; +{ + /* Completely ignore DEBUG_INSNs, otherwise we can get +-fcompare-debug failures. */ + if (DEBUG_INSN_P (tmp->insn)) + continue; + + if (!targetm.hard_regno_mode_ok (new_reg, GET_MODE (*tmp->loc)) + || call_clobbered_in_chain_p (this_head, GET_MODE (*tmp->loc), + new_reg)) + return false; +} return true; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index db691564bba..c2b5ddfa5cc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-04-18 Jeff Law + + PR debug/94439 + * gcc.dg/torture/pr94439.c: New test. + 2020-04-18 Iain Buclaw * gdc.dg/link.d: Use d_runtime_has_std_library effective target. diff --git a/gcc/testsuite/gcc.dg/torture/pr94439.c b/gcc/testsuite/gcc.dg/torture/pr94439.c new file mode 100644 index 000..a461b2f8c18 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr94439.c @@ -0,0 +1,55 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-additional-options "-flive-patching=inline-clone -funroll-loops -fno-tree-forwprop -fno-expensive-optimizations -mstack-arg-probe -fcompare-debug" } */ +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ + +extern void exit (int); +extern void abort (void); + +#define COMPARE_BODY(A, B, TYPE, COPYSIGN) \ + do { \ +TYPE s1 = COPYSIGN ((TYPE) 1.0, A); \ +TYPE s2 = COPYSIGN ((TYPE) 1.0, B); \ +if (s1 != s2) \ + abort (); \ +if ((__builtin_isnan (A) != 0) != (__builtin_isnan (B) != 0)) \ + abort (); \ +if ((A != B) != (__builtin_isnan (A) != 0)) \ + abort (); \ + } while (0) + +void +comparel (long double a, long double b) +{ + COMPARE_BODY (a, b, long double, __builtin_copysignl); +} + +void +comparecl (_Complex long double a, long double r, long double i) +{ + comparel (__real__ a, r); + comparel (__imag__ a, i); +} + +#define VERIFY(A, B, TYPE, COMPARE)\ + do { \ +TYPE a = A;\ +TYPE b = B;\ +_Complex TYPE cr = __builtin_complex (a, b); \ +static _Complex TYPE cs = __builtin_complex (A, B);\ +COMPARE (cr, A, B);
[PATCH] libphobos: Add --with-libphobos-druntime-only option.
Hi, This patch adds a new configure option --with-libphobos-druntime-only. The intended purpose of the option is both for targets that don't support phobos yet, and for gdc itself to support bootstrapping itself as a self-hosted D compiler. The libphobos testsuite has been updated to only add libphobos to the search paths if it's being built. A new D2 testsuite directive RUNNABLE_PHOBOS_TEST has also been patched in to disable some runnable tests that have phobos dependencies, of which is a temporary measure until upstream DMD fixes or removes these tests entirely. Bootstrapped and regression tested on x86_64-linux-gnu with this option both turned on and off. Committed to mainline. Regards Iain. --- libphobos/ChangeLog: * configure: Regenerate. * configure.ac: Add --with-libphobos-druntime-only option and the conditional ENABLE_LIBDRUNTIME_ONLY. * configure.tgt: Define LIBDRUNTIME_ONLY. * src/Makefile.am: Add phobos sources if not ENABLE_LIBDRUNTIME_ONLY. * src/Makefile.in: Regenerate. * testsuite/testsuite_flags.in: Add phobos path if compiling phobos. gcc/testsuite/ChangeLog: * lib/gdc-utils.exp (gdc-convert-test): Add dg-skip-if for tests that depending on the phobos standard library. --- libphobos/configure | 48 ++- libphobos/configure.ac| 22 ++ libphobos/configure.tgt | 1 + libphobos/src/Makefile.am | 8 + libphobos/src/Makefile.in | 314 ++ libphobos/testsuite/testsuite_flags.in| 7 +- gcc/testsuite/lib/gdc-utils.exp | 9 + gcc/testsuite/gdc.test/runnable/builtin.d | 1 + gcc/testsuite/gdc.test/runnable/complex.d | 1 + gcc/testsuite/gdc.test/runnable/constfold.d | 1 + gcc/testsuite/gdc.test/runnable/foreach4.d| 1 + gcc/testsuite/gdc.test/runnable/ifti.d| 1 + gcc/testsuite/gdc.test/runnable/implicit.d| 1 + gcc/testsuite/gdc.test/runnable/inner.d | 1 + gcc/testsuite/gdc.test/runnable/interpret.d | 1 + gcc/testsuite/gdc.test/runnable/issue8671.d | 1 + gcc/testsuite/gdc.test/runnable/lazy.d| 1 + gcc/testsuite/gdc.test/runnable/mars1.d | 1 + gcc/testsuite/gdc.test/runnable/mixin1.d | 1 + gcc/testsuite/gdc.test/runnable/mixin2.d | 1 + gcc/testsuite/gdc.test/runnable/s2ir.d| 1 + gcc/testsuite/gdc.test/runnable/stress.d | 1 + gcc/testsuite/gdc.test/runnable/template4.d | 1 + gcc/testsuite/gdc.test/runnable/template9.d | 1 + gcc/testsuite/gdc.test/runnable/test10942.d | 1 + gcc/testsuite/gdc.test/runnable/test11.d | 1 + gcc/testsuite/gdc.test/runnable/test12.d | 1 + gcc/testsuite/gdc.test/runnable/test12197.d | 1 + gcc/testsuite/gdc.test/runnable/test15.d | 1 + gcc/testsuite/gdc.test/runnable/test22.d | 1 + gcc/testsuite/gdc.test/runnable/test23.d | 1 + gcc/testsuite/gdc.test/runnable/test24.d | 1 + gcc/testsuite/gdc.test/runnable/test27.d | 1 + gcc/testsuite/gdc.test/runnable/test28.d | 1 + gcc/testsuite/gdc.test/runnable/test34.d | 1 + gcc/testsuite/gdc.test/runnable/test37.d | 1 + gcc/testsuite/gdc.test/runnable/test42.d | 1 + gcc/testsuite/gdc.test/runnable/test5305.d| 1 + gcc/testsuite/gdc.test/runnable/test60.d | 1 + gcc/testsuite/gdc.test/runnable/testaa.d | 1 + .../gdc.test/runnable/testbitarray.d | 1 + gcc/testsuite/gdc.test/runnable/testdstress.d | 1 + gcc/testsuite/gdc.test/runnable/testfile.d| 1 + gcc/testsuite/gdc.test/runnable/testformat.d | 1 + gcc/testsuite/gdc.test/runnable/testline.d| 1 + gcc/testsuite/gdc.test/runnable/testmmfile.d | 1 + gcc/testsuite/gdc.test/runnable/testscope2.d | 1 + gcc/testsuite/gdc.test/runnable/testsignals.d | 1 + gcc/testsuite/gdc.test/runnable/testsocket.d | 1 + gcc/testsuite/gdc.test/runnable/teststdio.d | 1 + gcc/testsuite/gdc.test/runnable/testthread2.d | 1 + gcc/testsuite/gdc.test/runnable/testtypeid.d | 1 + gcc/testsuite/gdc.test/runnable/traits.d | 1 + gcc/testsuite/gdc.test/runnable/wc.d | 1 + gcc/testsuite/gdc.test/runnable/wc2.d | 1 + gcc/testsuite/gdc.test/runnable/wc3.d | 1 + gcc/testsuite/gdc.test/runnable/xtest46.d | 1 + gcc/testsuite/gdc.test/runnable/xtest55.d | 1 + 58 files changed, 322 insertions(+), 138 deletions(-) diff --git a/libphobos/configure b/libphobos/configure index a6f5aec2bfd..2dcf15ed852 100755 --- a/libphobos/configure +++ b/libphobos/configure @@ -638,6 +638,8 @@ GDCFLAGSX libtool_VERSION SPEC_PHOBOS_DEPS CHECKING_DFLAGS +ENABLE_LIBDRUNTIME_ONLY_FALSE +ENABLE_LIBDRUNTIME_ONLY_TRUE ENABLE_LIBPHOBOS_FALSE ENABLE_LIBPHOBOS_TRUE gdc_include_dir @@ -840,6 +842,7 @@ with_cross_host enable_version_specific_runtime_libs with_toolex
Re: [PATCH][c++] Do not warn about unused macros while processing #pragma GCC optimize
Ping. > Fixes c++/91318. > > libcpp/ChangeLog: > > 2019-08-06 Piotr Henryk Dabrowski > > PR c++/91318 > * include/cpplib.h: Added cpp_define_unused(), > cpp_define_formatted_unused() > * directives.c: Likewise. > > gcc/c-family/ChangeLog: > > 2019-08-06 Piotr Henryk Dabrowski > > PR c++/91318 > * c-cppbuiltin.c: c_cpp_builtins_optimize_pragma(): use > cpp_define_unused() > > > diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c > index d389f8ca4a0..47d0cefb85a 100644 > --- a/gcc/c-family/c-cppbuiltin.c > +++ b/gcc/c-family/c-cppbuiltin.c > @@ -576,41 +576,41 @@ c_cpp_builtins_optimize_pragma (cpp_reader *pfile, tree > prev_tree, >/* Other target-independent built-ins determined by command-line > options. */ >if (!prev->x_optimize_size && cur->x_optimize_size) > -cpp_define (pfile, "__OPTIMIZE_SIZE__"); > +cpp_define_unused (pfile, "__OPTIMIZE_SIZE__"); >else if (prev->x_optimize_size && !cur->x_optimize_size) > cpp_undef (pfile, "__OPTIMIZE_SIZE__"); > >if (!prev->x_optimize && cur->x_optimize) > -cpp_define (pfile, "__OPTIMIZE__"); > +cpp_define_unused (pfile, "__OPTIMIZE__"); >else if (prev->x_optimize && !cur->x_optimize) > cpp_undef (pfile, "__OPTIMIZE__"); > >prev_fast_math = fast_math_flags_struct_set_p (prev); >cur_fast_math = fast_math_flags_struct_set_p (cur); >if (!prev_fast_math && cur_fast_math) > -cpp_define (pfile, "__FAST_MATH__"); > +cpp_define_unused (pfile, "__FAST_MATH__"); >else if (prev_fast_math && !cur_fast_math) > cpp_undef (pfile, "__FAST_MATH__"); > >if (!prev->x_flag_signaling_nans && cur->x_flag_signaling_nans) > -cpp_define (pfile, "__SUPPORT_SNAN__"); > +cpp_define_unused (pfile, "__SUPPORT_SNAN__"); >else if (prev->x_flag_signaling_nans && !cur->x_flag_signaling_nans) > cpp_undef (pfile, "__SUPPORT_SNAN__"); > >if (!prev->x_flag_errno_math && cur->x_flag_errno_math) > cpp_undef (pfile, "__NO_MATH_ERRNO__"); >else if (prev->x_flag_errno_math && !cur->x_flag_errno_math) > -cpp_define (pfile, "__NO_MATH_ERRNO__"); > +cpp_define_unused (pfile, "__NO_MATH_ERRNO__"); > >if (!prev->x_flag_finite_math_only && cur->x_flag_finite_math_only) > { >cpp_undef (pfile, "__FINITE_MATH_ONLY__"); > - cpp_define (pfile, "__FINITE_MATH_ONLY__=1"); > + cpp_define_unused (pfile, "__FINITE_MATH_ONLY__=1"); > } >else if (prev->x_flag_finite_math_only && !cur->x_flag_finite_math_only) > { >cpp_undef (pfile, "__FINITE_MATH_ONLY__"); > - cpp_define (pfile, "__FINITE_MATH_ONLY__=0"); > + cpp_define_unused (pfile, "__FINITE_MATH_ONLY__=0"); > } > } > > diff --git a/libcpp/directives.c b/libcpp/directives.c > index ddf8979d513..9a774c9ed04 100644 > --- a/libcpp/directives.c > +++ b/libcpp/directives.c > @@ -2392,6 +2392,15 @@ cpp_define (cpp_reader *pfile, const char *str) >run_directive (pfile, T_DEFINE, buf, count); > } > > +/* Like cpp_define, but does not warn about unused macro. */ > +void > +cpp_define_unused (cpp_reader *pfile, const char *str) > +{ > +unsigned char warn_unused_macros = CPP_OPTION (pfile, > warn_unused_macros); > +CPP_OPTION (pfile, warn_unused_macros) = 0; > +cpp_define (pfile, str); > +CPP_OPTION (pfile, warn_unused_macros) = warn_unused_macros; > +} > > /* Use to build macros to be run through cpp_define() as > described above. > @@ -2411,6 +2420,20 @@ cpp_define_formatted (cpp_reader *pfile, const char > *fmt, ...) >free (ptr); > } > > +/* Like cpp_define_formatted, but does not warn about unused macro. */ > +void > +cpp_define_formatted_unused (cpp_reader *pfile, const char *fmt, ...) > +{ > + char *ptr; > + > + va_list ap; > + va_start (ap, fmt); > + ptr = xvasprintf (fmt, ap); > + va_end (ap); > + > + cpp_define_unused (pfile, ptr); > + free (ptr); > +} > > /* Slight variant of the above for use by initialize_builtins. */ > void > diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h > index a645f8136a6..8d3f9082601 100644 > --- a/libcpp/include/cpplib.h > +++ b/libcpp/include/cpplib.h > @@ -1052,8 +1052,12 @@ extern cppchar_t cpp_host_to_exec_charset (cpp_reader > *, cppchar_t); > /* Used to register macros and assertions, perhaps from the command line. > The text is the same as the command line argument. */ > extern void cpp_define (cpp_reader *, const char *); > +extern void cpp_define_unused (cpp_reader *, const char *); > extern void cpp_define_formatted (cpp_reader *pfile, > const char *fmt, ...) ATTRIBUTE_PRINTF_2; > +extern void cpp_define_formatted_unused (cpp_reader *pfile, > + const char *fmt, > + ...) ATTRIBUTE_PRINTF_2; > extern void cpp_assert (cpp_reader *, const char *); > extern void cpp_undef (cpp_reader *, const ch
[PATCH] c, objc: Fix up c_parser_objc_selector_arg after CPP_SCOPE changes [PR94637]
Hi! Similarly to inline asm, :: (or any other number of consecutive colons) can appear in ObjC @selector argument and with the introduction of CPP_SCOPE into the C FE, we need to trat CPP_SCOPE as two CPP_COLON tokens. The C++ FE does that already that way. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2020-04-19 Jakub Jelinek PR objc/94637 * c-parser.c (c_parser_objc_selector_arg): Handle CPP_SCOPE like two CPP_COLON tokens. * objc.dg/pr94637.m: New test. --- gcc/c/c-parser.c.jj 2020-04-17 16:59:28.727193750 +0200 +++ gcc/c/c-parser.c2020-04-18 23:27:04.623963647 +0200 @@ -11782,15 +11782,28 @@ c_parser_objc_selector_arg (c_parser *pa { tree sel = c_parser_objc_selector (parser); tree list = NULL_TREE; - if (sel && c_parser_next_token_is_not (parser, CPP_COLON)) + if (sel + && c_parser_next_token_is_not (parser, CPP_COLON) + && c_parser_next_token_is_not (parser, CPP_SCOPE)) return sel; while (true) { - if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) - return list; - list = chainon (list, build_tree_list (sel, NULL_TREE)); + if (c_parser_next_token_is (parser, CPP_SCOPE)) + { + c_parser_consume_token (parser); + list = chainon (list, build_tree_list (sel, NULL_TREE)); + list = chainon (list, build_tree_list (NULL_TREE, NULL_TREE)); + } + else + { + if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) + return list; + list = chainon (list, build_tree_list (sel, NULL_TREE)); + } sel = c_parser_objc_selector (parser); - if (!sel && c_parser_next_token_is_not (parser, CPP_COLON)) + if (!sel + && c_parser_next_token_is_not (parser, CPP_COLON) + && c_parser_next_token_is_not (parser, CPP_SCOPE)) break; } return list; --- gcc/testsuite/objc.dg/pr94637.m.jj 2020-04-18 23:26:01.925898608 +0200 +++ gcc/testsuite/objc.dg/pr94637.m 2020-04-18 23:25:57.197969111 +0200 @@ -0,0 +1,10 @@ +/* PR objc/94637 */ +/* { dg-do compile } */ + +#include + +SEL +foo () +{ + return @selector(example::); +} Jakub