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]
Other format: [Raw text]

RFC: C++0x ABI PATCH to function parameter mangling


And this patch implements the change to function parameter mangling that Daveed proposed on the ABI list. Uses in trailing return types, which are the interesting case, are unaffected; use of one parameter in the declaration of another parameter do change mangling.

I think that's all the changes we need to make for code that we currently accept.

Tested x86_64-pc-linux-gnu, applied to trunk.
commit 3c16f729dcb34c970f06beddac2a4a266fe1f0c4
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Feb 21 22:41:34 2011 -0500

    	* cp-tree.h (DECL_PARM_LEVEL): New.
    	(struct lang_decl_parm): Add level field.
    	* name-lookup.c (function_parm_depth): New fn.
    	* name-lookup.h: Declare it.
    	* parser.c (cp_parser_parameter_declaration_list): Use it.
    	* mangle.c (struct globals): Add parm_depth field.
    	(write_bare_function_type): Adjust it.
    	(write_expression): Include the level delta in PARM_DECL mangling.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 238d0cf..ee72322 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1914,6 +1914,7 @@ struct GTY(()) lang_decl_ns {
 
 struct GTY(()) lang_decl_parm {
   struct lang_decl_base base;
+  int level;
   int index;
 };
 
@@ -2108,6 +2109,13 @@ struct GTY((variable_size)) lang_decl {
 #define DECL_PARM_INDEX(NODE) \
   (LANG_DECL_PARM_CHECK (NODE)->index)
 
+/* The level of a user-declared parameter in its function, starting at 1.
+   A parameter of the function will have level 1; a parameter of the first
+   nested function declarator (i.e. t in void f (void (*p)(T t))) will have
+   level 2.  */
+#define DECL_PARM_LEVEL(NODE) \
+  (LANG_DECL_PARM_CHECK (NODE)->level)
+
 /* Nonzero if the VTT parm has been added to NODE.  */
 #define DECL_HAS_VTT_PARM_P(NODE) \
   (LANG_DECL_FN_CHECK (NODE)->has_vtt_parm_p)
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 4d2ace6..a949681 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -96,6 +96,9 @@ typedef struct GTY(()) globals {
   /* The entity that is being mangled.  */
   tree GTY ((skip)) entity;
 
+  /* How many parameter scopes we are inside.  */
+  int parm_depth;
+
   /* True if the mangling will be different in a future version of the
      ABI.  */
   bool need_abi_warning;
@@ -2270,9 +2273,11 @@ write_bare_function_type (const tree type, const int include_return_type_p,
     write_type (TREE_TYPE (type));
 
   /* Now mangle the types of the arguments.  */
+  ++G.parm_depth;
   write_method_parms (TYPE_ARG_TYPES (type),
 		      TREE_CODE (type) == METHOD_TYPE,
 		      decl);
+  --G.parm_depth;
 }
 
 /* Write the mangled representation of a method parameter list of
@@ -2458,8 +2463,23 @@ write_expression (tree expr)
     {
       /* A function parameter used in a late-specified return type.  */
       int index = DECL_PARM_INDEX (expr);
+      int level = DECL_PARM_LEVEL (expr);
+      int delta = G.parm_depth - level + 1;
       gcc_assert (index >= 1);
-      write_string ("fp");
+      write_char ('f');
+      if (delta != 0)
+	{
+	  /* Let L be the number of function prototype scopes from the
+	     innermost one (in which the parameter reference occurs) up to
+	     (and including) the one containing the declaration of the
+	     referenced parameter.  If the parameter declaration clause of
+	     the innermost function prototype scope has been completely
+	     seen, it is not counted (in that case -- which is perhaps the
+	     most common -- L can be zero).  */
+	  write_char ('L');
+	  write_unsigned_number (delta - 1);
+	}
+      write_char ('p');
       write_compact_number (index - 1);
     }
   else if (DECL_P (expr))
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index e2e5450..4117202 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -1635,6 +1635,22 @@ getdecls (void)
   return current_binding_level->names;
 }
 
+/* Return how many function prototypes we are currently nested inside.  */
+
+int
+function_parm_depth (void)
+{
+  int level = 0;
+  struct cp_binding_level *b;
+
+  for (b = current_binding_level;
+       b->kind == sk_function_parms;
+       b = b->level_chain)
+    ++level;
+
+  return level;
+}
+
 /* For debugging.  */
 static int no_print_functions = 0;
 static int no_print_builtins = 0;
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index f81a565..bfcac69 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -333,6 +333,7 @@ extern bool pushdecl_class_level (tree);
 extern tree pushdecl_namespace_level (tree, bool);
 extern bool push_class_level_binding (tree, tree);
 extern tree getdecls (void);
+extern int function_parm_depth (void);
 extern tree cp_namespace_decls (tree);
 extern void set_decl_namespace (tree, tree, bool);
 extern void push_decl_namespace (tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 8f4a121..5a2806f 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -15942,6 +15942,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
 	{
 	  retrofit_lang_decl (decl);
 	  DECL_PARM_INDEX (decl) = ++index;
+	  DECL_PARM_LEVEL (decl) = function_parm_depth ();
 	}
 
       /* Add the new parameter to the list.  */
diff --git a/gcc/testsuite/g++.dg/abi/mangle39.C b/gcc/testsuite/g++.dg/abi/mangle39.C
index 30a08b0..272385b 100644
--- a/gcc/testsuite/g++.dg/abi/mangle39.C
+++ b/gcc/testsuite/g++.dg/abi/mangle39.C
@@ -1,7 +1,7 @@
 // PR c++/42338
 // { dg-options "-std=c++0x" }
 // { dg-final { scan-assembler "_Z1fIPiEDTcmppfp_Li0EET_" } }
-// { dg-final { scan-assembler "_Z1gIiEvRK1AIT_EDTixfp_Li0EE" } }
+// { dg-final { scan-assembler "_Z1gIiEvRK1AIT_EDTixfL0p_Li0EE" } }
 
 template<typename T>
 auto f(T t) -> decltype(++t, 0)
diff --git a/gcc/testsuite/g++.dg/abi/mangle45.C b/gcc/testsuite/g++.dg/abi/mangle45.C
new file mode 100644
index 0000000..48ae57d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle45.C
@@ -0,0 +1,25 @@
+// Testcase for mangling of parameters used other than in a trailing return type
+// { dg-options -std=c++0x }
+
+template<class T> void f(T p, decltype(p));                // L = 1
+template<class T> void g(T p, decltype(p) (*)());          // L = 1
+// G++ incorrectly rejects these currently.
+// template<class T> void h(T p, auto (*)()->decltype(p));    // L = 1
+// template<class T> void i(T p, auto (*)(T q)->decltype(q)); // L = 0
+// template<class T> void j(T p, auto (*)(decltype(p))->T);   // L = 2
+template<class T> void k(T p, int (*(*)(T* p))[sizeof(p)]); // L = 1
+
+int garg();
+int (*karg (int*))[sizeof(int)];
+int main()
+{
+  // { dg-final { scan-assembler  "_Z1fIiEvT_DtfL0p_E" } }
+  f (1,0);
+  // { dg-final { scan-assembler  "_Z1gIiEvT_PFDtfL0p_EvE" } }
+  g (1,garg);
+  // h (1,0);
+  // i (1,0);
+  // j (1,0);
+  // { dg-final { scan-assembler  "_Z1kIiEvT_PFPAszfL0p__iPS0_E" } }
+  k (1,karg);
+}

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