From: David Malcolm <dmalcolm@redhat.com>
To: gcc-patches@gcc.gnu.org
Cc: David Malcolm <dmalcolm@redhat.com>
Subject: [PATCH] C++: show location of problematic extern "C" specifications
Date: Tue, 26 Sep 2017 19:27:00 -0000 [thread overview]
Message-ID: <1506454055-54547-1-git-send-email-dmalcolm@redhat.com> (raw)
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 }
+
--
1.8.5.3
next reply other threads:[~2017-09-26 19:27 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-09-26 19:27 David Malcolm [this message]
2017-10-11 17:37 ` PING " David Malcolm
2017-10-11 20:50 ` Jason Merrill
2017-10-11 20:52 ` David Malcolm
2017-10-11 21:22 ` Jason Merrill
2017-10-11 22:26 ` David Malcolm
2017-10-12 18:45 ` [PATCH] C++: show location of unclosed extern "C" specifications (v2) David Malcolm
2017-10-12 21:18 ` Jason Merrill
2017-10-13 12:53 ` [committed] C++: show location of unclosed extern "C" specifications (v3) David Malcolm
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1506454055-54547-1-git-send-email-dmalcolm@redhat.com \
--to=dmalcolm@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).