summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2005-11-15 00:15:09 +0000
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2005-11-15 00:15:09 +0000
commit9f25cdd89d8d7b972ccf139bda43c382b79bdc33 (patch)
treeda378b2769e30d45fdc1f0df7d28f03de6254e43
parentc47b82579d5ce057778c9e8d5bce29aa61147822 (diff)
downloadgcc-9f25cdd89d8d7b972ccf139bda43c382b79bdc33.tar.gz
PR c++/24687
* pt.c (check_explicit_specialization): Don't check for C linkage. (push_template_decl_real): Likewise. * parser.c (cp_parser_explicit_specialization): Check here. (cp_parser_template_declaration_after_export): And here. PR c++/24687 * g++.dg/template/crash43.C: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@106909 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/parser.c41
-rw-r--r--gcc/cp/pt.c8
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/template/crash43.C8
5 files changed, 58 insertions, 10 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3a2d6d20d4a..60f3166b3ce 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,11 @@
2005-11-14 Mark Mitchell <mark@codesourcery.com>
+ PR c++/24687
+ * pt.c (check_explicit_specialization): Don't check for C linkage.
+ (push_template_decl_real): Likewise.
+ * parser.c (cp_parser_explicit_specialization): Check here.
+ (cp_parser_template_declaration_after_export): And here.
+
* parser.c (cp_lexer_get_preprocessor_token): Initialize keyword
field.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 40a1768e3ca..5827e5ebcdc 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -9295,6 +9295,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
static void
cp_parser_explicit_specialization (cp_parser* parser)
{
+ bool need_lang_pop;
/* Look for the `template' keyword. */
cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'");
/* Look for the `<'. */
@@ -9303,9 +9304,22 @@ cp_parser_explicit_specialization (cp_parser* parser)
cp_parser_require (parser, CPP_GREATER, "`>'");
/* We have processed another parameter list. */
++parser->num_template_parameter_lists;
+ /* [temp]
+
+ A template ... explicit specialization ... shall not have C
+ linkage. */
+ if (current_lang_name == lang_name_c)
+ {
+ error ("template specialization with C linkage");
+ /* Give it C++ linkage to avoid confusing other parts of the
+ front end. */
+ push_lang_context (lang_name_cplusplus);
+ need_lang_pop = true;
+ }
+ else
+ need_lang_pop = false;
/* Let the front end know that we are beginning a specialization. */
begin_specialization ();
-
/* If the next keyword is `template', we need to figure out whether
or not we're looking a template-declaration. */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))
@@ -9322,9 +9336,12 @@ cp_parser_explicit_specialization (cp_parser* parser)
cp_parser_single_declaration (parser,
/*member_p=*/false,
/*friend_p=*/NULL);
-
/* We're done with the specialization. */
end_specialization ();
+ /* For the erroneous case of a template with C linkage, we pushed an
+ implicit C++ linkage scope; exit that scope now. */
+ if (need_lang_pop)
+ pop_lang_context ();
/* We're done with this parameter list. */
--parser->num_template_parameter_lists;
}
@@ -15168,6 +15185,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
tree decl = NULL_TREE;
tree parameter_list;
bool friend_p = false;
+ bool need_lang_pop;
/* Look for the `template' keyword. */
if (!cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'"))
@@ -15176,7 +15194,19 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
/* And the `<'. */
if (!cp_parser_require (parser, CPP_LESS, "`<'"))
return;
-
+ /* [temp]
+
+ A template ... shall not have C linkage. */
+ if (current_lang_name == lang_name_c)
+ {
+ error ("template with C linkage");
+ /* Give it C++ linkage to avoid confusing other parts of the
+ front end. */
+ push_lang_context (lang_name_cplusplus);
+ need_lang_pop = true;
+ }
+ else
+ need_lang_pop = false;
/* If the next token is `>', then we have an invalid
specialization. Rather than complain about an invalid template
parameter, issue an error message here. */
@@ -15237,7 +15267,10 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
/* Register member declarations. */
if (member_p && !friend_p && decl && !DECL_CLASS_TEMPLATE_P (decl))
finish_member_declaration (decl);
-
+ /* For the erroneous case of a template with C linkage, we pushed an
+ implicit C++ linkage scope; exit that scope now. */
+ if (need_lang_pop)
+ pop_lang_context ();
/* If DECL is a function template, we must return to parse it later.
(Even though there is no definition, there might be default
arguments that need handling.) */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 63123c47f97..3e495643fd6 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -1895,8 +1895,6 @@ check_explicit_specialization (tree declarator,
("default argument specified in explicit specialization");
break;
}
- if (current_lang_name == lang_name_c)
- error ("template specialization with C linkage");
}
if (specialization || member_specialization || explicit_instantiation)
@@ -2985,10 +2983,8 @@ push_template_decl_real (tree decl, bool is_friend)
{
if (DECL_CLASS_SCOPE_P (decl))
member_template_p = true;
- if (current_lang_name == lang_name_c)
- error ("template with C linkage");
- else if (TREE_CODE (decl) == TYPE_DECL
- && ANON_AGGRNAME_P (DECL_NAME (decl)))
+ if (TREE_CODE (decl) == TYPE_DECL
+ && ANON_AGGRNAME_P (DECL_NAME (decl)))
error ("template class without a name");
else if (TREE_CODE (decl) == FUNCTION_DECL)
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2a864b0558b..d87105b3fe8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2005-11-14 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/24687
+ * g++.dg/template/crash43.C: New test.
+
2005-11-14 Daniel Jacobowitz <dan@codesourcery.com>
* gcc.c-torture/unsorted/unsorted.exp: Sort tests before running them.
diff --git a/gcc/testsuite/g++.dg/template/crash43.C b/gcc/testsuite/g++.dg/template/crash43.C
new file mode 100644
index 00000000000..1261c365058
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/crash43.C
@@ -0,0 +1,8 @@
+// PR c++/24687
+
+extern "C" {
+ template<typename _Tp> // { dg-error "C" }
+ struct __is_pod {
+ enum {
+ __value = (sizeof(__gnu_internal::__test_type<_Tp>(0)))}; // { dg-error "declared|expected" }
+