This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

C++: "unqualified" linkage


This patch implements a feature that was requested from the libstdc++
v3 people a long time ago. It adds a new language linkage
"unqualified". The primary application is in cases like

namespace std{
  extern "unqualified"{
    struct timeval{};
  }
}
using std::timeval;

void gettime(timeval& x)
{
}

If std:: is honored, the mangling of gettime would normally change if
the old-style header file is included instead of the C++ conforming
one. See docs/17_intro/DESIGN of libstdc++ v3 for more discussion.

In this patch, "unqualified" linkage is the same as "C" linkage, with
the additional meaning that "unqualified" names used in mangling of
"C++" names are mangled without qualifiers. As a result, gettime is
mangled as gettime__FR7timeval, instead of gettime__FRQ23std7timeval.

Any comments appreciated.

Regards,
Martin

2000-01-16  Martin v. Löwis  <loewis@informatik.hu-berlin.de>

	* cp-tree.h (lang_name_like_p, lang_like_c_p): New definitions.
	(lang_name_unqualified): New definition.
	(cp_tree_index): New value CPTI_LANG_NAME_UNQUALIFIED.
	(languages): New value lang_unqualified.
	* decl2.c (reparse_absdcl_as_casts): Use lang_name_like_c_p.
	* pt.c (check_explicit_specialization): Likewise..
	(push_template_decl_real): Likewise.
	* class.c (push_lang_context): Likewise..
	(pop_lang_context): Likewise.
	* decl.c (pop_from_top_level): Likewise.
	(grokvardecl): Likewise.
	(decls_match): Use lang_like_c_p.
	(decls_match): Likewise.
	(duplicate_decls): Likewise.
	(pushdecl): Likewise.
	(grokfndecl): Likewise.
	(init_decl_processing): Initialize lang_name_unqualified.
	* method.c (build_overload_nested_name): Do not emit context if
	inside lang_name_unqualified.
	(build_qualified_name): Do not emit 'Q' prefix in this case.
	* lex.c (retrofit_lang_decl): Set DECL_LANGUAGE to
	lang_unqualified if appropriate.

Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.232
diff -u -p -r1.232 class.c
--- class.c	2000/01/13 00:35:38	1.232
+++ class.c	2000/01/16 00:19:04
@@ -5345,7 +5345,7 @@ push_lang_context (name)
       DECL_IGNORED_P (java_char_type_node) = 0;
       DECL_IGNORED_P (java_boolean_type_node) = 0;
     }
-  else if (name == lang_name_c)
+  else if (lang_name_like_c_p (name))
     {
       strict_prototype = strict_prototypes_lang_c;
       current_lang_name = name;
@@ -5366,7 +5366,7 @@ pop_lang_context ()
   if (current_lang_name == lang_name_cplusplus
       || current_lang_name == lang_name_java)
     strict_prototype = strict_prototypes_lang_cplusplus;
-  else if (current_lang_name == lang_name_c)
+  else if (lang_name_like_c_p (current_lang_name))
     strict_prototype = strict_prototypes_lang_c;
 }
 
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.383
diff -u -p -r1.383 cp-tree.h
--- cp-tree.h	2000/01/12 23:27:43	1.383
+++ cp-tree.h	2000/01/16 00:19:10
@@ -490,6 +490,7 @@ enum cp_tree_index
     CPTI_LANG_NAME_C,
     CPTI_LANG_NAME_CPLUSPLUS,
     CPTI_LANG_NAME_JAVA,
+    CPTI_LANG_NAME_UNQUALIFIED,
 
     CPTI_EMPTY_EXCEPT_SPEC,
     CPTI_NULL,
@@ -571,6 +572,7 @@ extern tree cp_global_trees[CPTI_MAX];
 #define vptr_identifier                 cp_global_trees[CPTI_VPTR_IDENTIFIER]
 
 #define lang_name_c                     cp_global_trees[CPTI_LANG_NAME_C]
+#define lang_name_unqualified           cp_global_trees[CPTI_LANG_NAME_UNQUALIFIED]
 #define lang_name_cplusplus             cp_global_trees[CPTI_LANG_NAME_CPLUSPLUS]
 #define lang_name_java                  cp_global_trees[CPTI_LANG_NAME_JAVA]
 
@@ -837,6 +839,16 @@ struct language_function
 
 #define doing_semantic_analysis_p() (!expanding_p)
 
+/* Non-zero if the name is either "C" or "unqualified". */
+
+#define lang_name_like_c_p(name)	\
+	((name) == lang_name_c || (name) == lang_name_unqualified)
+
+/* Non-zero if the language is either "C" or "unqualified". */
+
+#define lang_like_c_p(lang)	\
+	((lang) == lang_c || (lang) == lang_unqualified)
+
 /* Non-zero if we should treat statements as full expressions.  In
    particular, this variable is no-zero if at the end of a statement
    we should destroy any temporaries created during that statement.
@@ -1066,7 +1078,7 @@ enum cplus_tree_code {
 };
 #undef DEFTREECODE
 
-enum languages { lang_c, lang_cplusplus, lang_java };
+enum languages { lang_c, lang_cplusplus, lang_java, lang_unqualified };
 
 /* Macros to make error reporting functions' lives easier.  */
 #define TYPE_IDENTIFIER(NODE) (DECL_NAME (TYPE_NAME (NODE)))
Index: decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.531
diff -u -p -r1.531 decl.c
--- decl.c	2000/01/13 02:04:25	1.531
+++ decl.c	2000/01/16 00:19:25
@@ -2424,7 +2424,7 @@ pop_from_top_level ()
 
   if (current_lang_name == lang_name_cplusplus)
     strict_prototype = strict_prototypes_lang_cplusplus;
-  else if (current_lang_name == lang_name_c)
+  else if (lang_name_like_c_p (current_lang_name))
     strict_prototype = strict_prototypes_lang_c;
 
   /* If we were in the middle of compiling a function, restore our
@@ -2797,8 +2797,8 @@ decls_match (newdecl, olddecl)
       tree p2 = TYPE_ARG_TYPES (f2);
 
       if (DECL_REAL_CONTEXT (newdecl) != DECL_REAL_CONTEXT (olddecl)
-	  && ! (DECL_LANGUAGE (newdecl) == lang_c
-		&& DECL_LANGUAGE (olddecl) == lang_c))
+	  && ! (lang_like_c_p (DECL_LANGUAGE (newdecl))
+		&& lang_like_c_p (DECL_LANGUAGE (olddecl))))
 	return 0;
 
       /* When we parse a static member function definition,
@@ -2826,15 +2826,18 @@ decls_match (newdecl, olddecl)
 
       if (same_type_p (TREE_TYPE (f1), TREE_TYPE (f2)))
 	{
-	  if (! strict_prototypes_lang_c && DECL_LANGUAGE (olddecl) == lang_c
+	  if (! strict_prototypes_lang_c 
+	      && lang_like_c_p (DECL_LANGUAGE (olddecl))
 	      && p2 == NULL_TREE)
 	    {
 	      types_match = self_promoting_args_p (p1);
 	      if (p1 == void_list_node)
 		TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
 	    }
-	  else if (!strict_prototypes_lang_c && DECL_LANGUAGE (olddecl)==lang_c
-		   && DECL_LANGUAGE (newdecl) == lang_c && p1 == NULL_TREE)
+	  else if (!strict_prototypes_lang_c 
+		   && lang_like_c_p (DECL_LANGUAGE (olddecl))
+		   && lang_like_c_p (DECL_LANGUAGE (newdecl)) 
+		   && p1 == NULL_TREE)
 	    {
 	      types_match = self_promoting_args_p (p2);
 	      TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
@@ -2983,8 +2986,8 @@ duplicate_decls (newdecl, olddecl)
 	}
       else if (!types_match)
 	{
-	  if ((DECL_LANGUAGE (newdecl) == lang_c
-	       && DECL_LANGUAGE (olddecl) == lang_c)
+	  if ((lang_like_c_p (DECL_LANGUAGE (newdecl))
+	       && lang_like_c_p (DECL_LANGUAGE (olddecl)))
 	      || compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
 			    TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
 	    {
@@ -3092,8 +3095,8 @@ duplicate_decls (newdecl, olddecl)
 	}
       if (TREE_CODE (newdecl) == FUNCTION_DECL)
 	{
-	  if (DECL_LANGUAGE (newdecl) == lang_c
-	      && DECL_LANGUAGE (olddecl) == lang_c)
+	  if (lang_like_c_p (DECL_LANGUAGE (newdecl))
+	      && lang_like_c_p (DECL_LANGUAGE (olddecl)))
 	    {
 	      cp_error ("declaration of C function `%#D' conflicts with",
 			newdecl);
@@ -3694,7 +3697,8 @@ pushdecl (x)
 	      if (duplicate_decls (x, t))
 		return t;
 	    }
-	  else if (((TREE_CODE (x) == FUNCTION_DECL && DECL_LANGUAGE (x) == lang_c)
+	  else if (((TREE_CODE (x) == FUNCTION_DECL 
+		     && lang_like_c_p (DECL_LANGUAGE (x)))
 		    || DECL_FUNCTION_TEMPLATE_P (x))
 		   && is_overloaded_fn (t))
 	    /* Don't do anything just yet. */;
@@ -3874,7 +3878,7 @@ pushdecl (x)
 		 an `extern "C"' function, the mangled name and the
 		 ordinary name are the same so we need not do this.  */
 	      && !(TREE_CODE (x) == FUNCTION_DECL &&
-		   DECL_LANGUAGE (x) == lang_c))
+		   lang_like_c_p (DECL_LANGUAGE (x))))
 	    {
 	      if (TREE_CODE (x) == FUNCTION_DECL)
 		my_friendly_assert
@@ -5960,6 +5964,7 @@ init_decl_processing ()
   lang_name_cplusplus = get_identifier ("C++");
   lang_name_c = get_identifier ("C");
   lang_name_java = get_identifier ("Java");
+  lang_name_unqualified = get_identifier ("unqualified");
 
   /* Let the back-end now how to save and restore language-specific
      per-function globals.  */
@@ -8463,7 +8468,7 @@ grokfndecl (ctype, type, declarator, ori
 	{
 	  if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
 	    {
-	      if (DECL_LANGUAGE (decl) == lang_c)
+	      if (lang_like_c_p (DECL_LANGUAGE (decl)))
 		/* Allow this; it's pretty common in C.  */;
 	      else
 		cp_pedwarn ("non-local function `%#D' uses anonymous type",
@@ -8554,7 +8559,7 @@ grokfndecl (ctype, type, declarator, ori
 
   /* Plain overloading: will not be grok'd by grokclassfn.  */
   if (! ctype && ! processing_template_decl
-      && DECL_LANGUAGE (decl) != lang_c
+      && ! lang_like_c_p (DECL_LANGUAGE (decl))
       && (! DECL_USE_TEMPLATE (decl) || name_mangling_version < 1))
     set_mangled_name_for_decl (decl);
 
@@ -8710,7 +8715,7 @@ grokvardecl (type, declarator, specbits_
 	set_decl_namespace (decl, context, 0);
 
       context = DECL_CONTEXT (decl);
-      if (declarator && context && current_lang_name != lang_name_c)
+      if (declarator && context && ! lang_name_like_c_p (current_lang_name))
 	DECL_ASSEMBLER_NAME (decl) = build_static_name (context, declarator);
     }
 
Index: decl2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl2.c,v
retrieving revision 1.295
diff -u -p -r1.295 decl2.c
--- decl2.c	2000/01/14 11:51:14	1.295
+++ decl2.c	2000/01/16 00:19:31
@@ -3702,7 +3702,7 @@ reparse_absdcl_as_casts (decl, expr)
     }
 
   if (warn_old_style_cast && ! in_system_header
-      && current_lang_name != lang_name_c)
+      && !lang_name_like_c_p (current_lang_name))
     warning ("use of old-style cast");
 
   return expr;
Index: lex.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/lex.c,v
retrieving revision 1.173
diff -u -p -r1.173 lex.c
--- lex.c	2000/01/12 05:22:42	1.173
+++ lex.c	2000/01/16 00:19:35
@@ -4735,6 +4735,8 @@ retrofit_lang_decl (t)
     DECL_LANGUAGE (t) = lang_cplusplus;
   else if (current_lang_name == lang_name_c)
     DECL_LANGUAGE (t) = lang_c;
+  else if (current_lang_name == lang_name_unqualified)
+    DECL_LANGUAGE (t) = lang_unqualified;
   else if (current_lang_name == lang_name_java)
     DECL_LANGUAGE (t) = lang_java;
   else my_friendly_abort (64);
Index: method.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/method.c,v
retrieving revision 1.131
diff -u -p -r1.131 method.c
--- method.c	2000/01/14 23:42:10	1.131
+++ method.c	2000/01/16 00:19:38
@@ -435,21 +435,23 @@ build_overload_nested_name (decl)
 
   context = CP_DECL_CONTEXT (decl);
 
-  /* try to issue a K type, and if we can't continue the normal path */
-  if (!(ktypelist && issue_ktype (context)))
-  {
-    /* For a template type parameter, we want to output an 'Xn'
-       rather than 'T' or some such. */
-    if (TREE_CODE (context) == TEMPLATE_TYPE_PARM
-        || TREE_CODE (context) == TEMPLATE_TEMPLATE_PARM)
-      build_mangled_name_for_type (context);
-    else
-    {
-      if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
-        context = TYPE_NAME (context);
-      build_overload_nested_name (context);
-    }
-  }
+  /* If we are inside extern "unqualifed", ignore any context.  */
+  if (current_lang_name != lang_name_unqualified)
+    /* try to issue a K type, and if we can't continue the normal path */
+    if (!(ktypelist && context && issue_ktype (context)))
+      {
+	/* For a template type parameter, we want to output an 'Xn'
+	   rather than 'T' or some such. */
+	if (TREE_CODE (context) == TEMPLATE_TYPE_PARM
+	    || TREE_CODE (context) == TEMPLATE_TEMPLATE_PARM)
+	  build_mangled_name_for_type (context);
+	else
+	  {
+	    if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
+	      context = TYPE_NAME (context);
+	    build_overload_nested_name (context);
+	  }
+      }
 
   if (TREE_CODE (decl) == FUNCTION_DECL)
     {
@@ -1068,7 +1070,9 @@ build_qualified_name (decl)
 	}
     }
 
-  if (i > 1)
+  /* If we are inside extern "unqualified", don't put qualified names
+     out there.  */
+  if (i > 1 && current_lang_name != lang_name_unqualified)
     {
       OB_PUTC ('Q');
       build_underscore_int (i);
Index: pt.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/pt.c,v
retrieving revision 1.392
diff -u -p -r1.392 pt.c
--- pt.c	2000/01/14 05:45:52	1.392
+++ pt.c	2000/01/16 00:19:47
@@ -1288,7 +1288,7 @@ check_explicit_specialization (declarato
 	      ("default argument specified in explicit specialization");
 	    break;
 	  }
-      if (current_lang_name == lang_name_c)
+      if (lang_name_like_c_p (current_lang_name))
 	cp_error ("template specialization with C linkage");
     }
 
@@ -2369,7 +2369,7 @@ push_template_decl_real (decl, is_friend
 
   if (primary)
     {
-      if (current_lang_name == lang_name_c)
+      if (lang_name_like_c_p (current_lang_name))
 	cp_error ("template with C linkage");
       else if (TREE_CODE (decl) == TYPE_DECL 
 	       && ANON_AGGRNAME_P (DECL_NAME (decl))) 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]