This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PING Re: [PATCH] C++: show location of problematic extern "C" specifications
- From: David Malcolm <dmalcolm at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 11 Oct 2017 13:28:39 -0400
- Subject: PING Re: [PATCH] C++: show location of problematic extern "C" specifications
- Authentication-results: sourceware.org; auth=none
- Authentication-results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com
- Authentication-results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=dmalcolm at redhat dot com
- Dmarc-filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 4F04261472
- References: <1506454055-54547-1-git-send-email-dmalcolm@redhat.com>
Ping
On Tue, 2017-09-26 at 15:27 -0400, David Malcolm wrote:
> There are a few places where the C++ FE will complain when attempting
> to do things within an extern "C" linkage specifier.
>
> I've run into problems where it wasn't clear where the pertinent
> extern "C" was; for example, when failing to close an extern "C"
> linkage
> specifier in a header, leading to "template with C linkage" errors in
> a different source file.
>
> As of r251026 there will be a message highlighting the unclosed '{',
> but
> this may be hard to spot at the very end of the errors.
>
> This patch adds a note to the various diagnostics that complain
> about C linkage, showing the user where the extern "C" specification
> began.
>
> Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
>
> OK for trunk?
>
> gcc/cp/ChangeLog:
> * cp-tree.h (struct saved_scope): Add "location" field.
> (maybe_show_extern_c_location): New decl.
> * decl.c (grokfndecl): When complaining about literal operators
> with C linkage, issue a note giving the location of the
> extern "C".
> * parser.c (cp_parser_linkage_specification): Store the
> location
> of the "extern" token within the scope_chain.
> (maybe_show_extern_c_location): New function.
> (cp_parser_explicit_specialization): When complaining about
> template specializations with C linkage, issue a note giving
> the
> location of the extern "C".
> (cp_parser_explicit_template_declaration): Likewise for
> templates.
>
> gcc/testsuite/ChangeLog:
> * g++.dg/cpp0x/udlit-extern-c.C: New test case.
> * g++.dg/diagnostic/unclosed-extern-c.C: Add example of a
> template
> erroneously covered by an unclosed extern "C".
> * g++.dg/template/extern-c.C: New test case.
> ---
> gcc/cp/cp-tree.h | 3 ++
> gcc/cp/decl.c | 1 +
> gcc/cp/parser.c | 19 ++++++++++-
> gcc/testsuite/g++.dg/cpp0x/udlit-extern-c.C | 7 ++++
> .../g++.dg/diagnostic/unclosed-extern-c.C | 11 +++++-
> gcc/testsuite/g++.dg/template/extern-c.C | 39
> ++++++++++++++++++++++
> 6 files changed, 78 insertions(+), 2 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/cpp0x/udlit-extern-c.C
> create mode 100644 gcc/testsuite/g++.dg/template/extern-c.C
>
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index e508598..762cc7b 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -1568,6 +1568,8 @@ struct GTY(()) saved_scope {
> hash_map<tree, tree> *GTY((skip)) x_local_specializations;
>
> struct saved_scope *prev;
> +
> + location_t location;
> };
>
> extern GTY(()) struct saved_scope *scope_chain;
> @@ -6352,6 +6354,7 @@ extern bool parsing_nsdmi (void);
> extern bool parsing_default_capturing_generic_lambda_in_template
> (void);
> extern void inject_this_parameter (tree, cp_cv_quals);
> extern location_t defarg_location (tree);
> +extern void maybe_show_extern_c_location (void);
>
> /* in pt.c */
> extern bool check_template_shadow (tree);
> diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> index 50fa1ba..d08ac9a 100644
> --- a/gcc/cp/decl.c
> +++ b/gcc/cp/decl.c
> @@ -8724,6 +8724,7 @@ grokfndecl (tree ctype,
> if (DECL_LANGUAGE (decl) == lang_c)
> {
> error ("literal operator with C linkage");
> + maybe_show_extern_c_location ();
> return NULL_TREE;
> }
>
> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> index d831d66..b90f40d 100644
> --- a/gcc/cp/parser.c
> +++ b/gcc/cp/parser.c
> @@ -13823,7 +13823,8 @@ cp_parser_linkage_specification (cp_parser*
> parser)
> tree linkage;
>
> /* Look for the `extern' keyword. */
> - cp_parser_require_keyword (parser, RID_EXTERN, RT_EXTERN);
> + cp_token *extern_token
> + = cp_parser_require_keyword (parser, RID_EXTERN, RT_EXTERN);
>
> /* Look for the string-literal. */
> linkage = cp_parser_string_literal (parser, false, false);
> @@ -13843,6 +13844,7 @@ cp_parser_linkage_specification (cp_parser*
> parser)
>
> /* We're now using the new linkage. */
> push_lang_context (linkage);
> + scope_chain->location = extern_token->location;
>
> /* If the next token is a `{', then we're using the first
> production. */
> @@ -16589,6 +16591,19 @@ cp_parser_explicit_instantiation (cp_parser*
> parser)
> timevar_pop (TV_TEMPLATE_INST);
> }
>
> +/* Helper function for diagnostics that have complained about things
> + being used with 'extern "C"' linkage.
> +
> + Attempt to issue a note showing where the 'extern "C"' linkage
> began. */
> +
> +void
> +maybe_show_extern_c_location (void)
> +{
> + if (scope_chain->location != UNKNOWN_LOCATION)
> + inform (scope_chain->location, "%<extern \"C\"%> linkage started
> here");
> +}
> +
> +
> /* Parse an explicit-specialization.
>
> explicit-specialization:
> @@ -16623,6 +16638,7 @@ cp_parser_explicit_specialization (cp_parser*
> parser)
> if (current_lang_name == lang_name_c)
> {
> error_at (token->location, "template specialization with C
> linkage");
> + maybe_show_extern_c_location ();
> /* Give it C++ linkage to avoid confusing other parts of the
> front end. */
> push_lang_context (lang_name_cplusplus);
> @@ -26858,6 +26874,7 @@ cp_parser_explicit_template_declaration
> (cp_parser* parser, bool member_p)
> if (current_lang_name == lang_name_c)
> {
> error_at (location, "template with C linkage");
> + maybe_show_extern_c_location ();
> /* Give it C++ linkage to avoid confusing other parts of the
> front end. */
> push_lang_context (lang_name_cplusplus);
> diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-extern-c.C
> b/gcc/testsuite/g++.dg/cpp0x/udlit-extern-c.C
> new file mode 100644
> index 0000000..d47a49c
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-extern-c.C
> @@ -0,0 +1,7 @@
> +// { dg-do compile { target c++11 } }
> +
> +extern "C" { // { dg-message "1: 'extern .C.' linkage started here"
> }
> +
> +constexpr double operator"" _deg ( double degrees ); // { dg-error
> "literal operator with C linkage" }
> +
> +}
> diff --git a/gcc/testsuite/g++.dg/diagnostic/unclosed-extern-c.C
> b/gcc/testsuite/g++.dg/diagnostic/unclosed-extern-c.C
> index fda3532..44f538e 100644
> --- a/gcc/testsuite/g++.dg/diagnostic/unclosed-extern-c.C
> +++ b/gcc/testsuite/g++.dg/diagnostic/unclosed-extern-c.C
> @@ -1,3 +1,12 @@
> -extern "C" { /* { dg-message "12: to match this '.'" } */
> +extern "C" { // { dg-line open_extern_c }
> +
> + int foo (void);
> +
> +/* Missing close-brace for the extern "C" here. */
> +
> +template <typename T> // { dg-error "template with C linkage" }
> +void bar (void);
> +// { dg-message "1: 'extern .C.' linkage started here" "" { target
> *-*-* } open_extern_c }
>
> void test (void); /* { dg-error "17: expected '.' at end of input" }
> */
> +// { message "12: to match this '.'" "" { target *-*-* }
> open_extern_c }
> diff --git a/gcc/testsuite/g++.dg/template/extern-c.C
> b/gcc/testsuite/g++.dg/template/extern-c.C
> new file mode 100644
> index 0000000..8a3a77a
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/template/extern-c.C
> @@ -0,0 +1,39 @@
> +template <typename T> void specializable (T);
> +
> +/* Invalid template: within "extern C". */
> +
> +extern "C" { // { dg-message "1: 'extern .C.' linkage started here"
> }
> +
> +template <typename T> // { dg-error "template with C linkage" }
> +void within_extern_c_braces (void);
> +
> +}
> +
> +/* Valid template: not within "extern C". */
> +
> +template <typename T>
> +void not_within_extern_c (void);
> +
> +
> +/* Invalid specialization: within "extern C". */
> +
> +extern "C" { // { dg-message "1: 'extern .C.' linkage started here"
> }
> +
> +template <> // { dg-error "template specialization with C linkage"
> }
> +void specializable (int);
> +
> +}
> +
> +
> +/* Valid specialization: not within "extern C". */
> +template <>
> +void specializable (char);
> +
> +
> +/* Example of extern C without braces. */
> +
> +extern "C" template <typename T> // { dg-line
> open_extern_c_no_braces }
> +void within_extern_c_no_braces (void);
> +// { dg-error "12: template with C linkage" "" { target *-*-* }
> open_extern_c_no_braces }
> +// { dg-message "1: 'extern .C.' linkage started here" "" { target
> *-*-* } open_extern_c_no_braces }
> +