C++ PATCH: PR 24687

Mark Mitchell mark@codesourcery.com
Tue Nov 15 00:17:00 GMT 2005


This patch fixes PR 24687.  You're not allowed to create a template
with extern "C" linkage, which we were diagnosing correctly.  However,
we were letting the template actually have C linkage, which resulted
in confusion in our internal data structures.  This is another of the
general principle that the internal representation should, as much as
possible, represent a valid program, even if the input program is
invalid.  Fixed by moving the checks into the parser, which can then
adjust the notion of the current language linkage, and thereby avoid
the rest of the compiler becoming confused.

Tested on x86_64-unknown-linux-gnu, applied on the mainline and on the
4.0 branch.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

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.

2005-11-14  Mark Mitchell  <mark@codesourcery.com>

	PR c++/24687
	* g++.dg/template/crash43.C: New test. 

Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 106883)
+++ gcc/cp/pt.c	(working copy)
@@ -1895,8 +1895,6 @@ check_explicit_specialization (tree decl
 	      ("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
     {
       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)
 	{
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 106907)
+++ gcc/cp/parser.c	(working copy)
@@ -9295,6 +9295,7 @@ cp_parser_explicit_instantiation (cp_par
 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_pa
   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_pa
     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_exp
   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_exp
   /* 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_exp
   /* 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.)  */
Index: gcc/testsuite/g++.dg/template/crash43.C
===================================================================
--- gcc/testsuite/g++.dg/template/crash43.C	(revision 0)
+++ gcc/testsuite/g++.dg/template/crash43.C	(revision 0)
@@ -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" }
+



More information about the Gcc-patches mailing list