cp-tree.h (DECL_PARM_LEVEL): New.
authorJason Merrill <jason@redhat.com>
Thu, 24 Feb 2011 04:56:26 +0000 (23:56 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 24 Feb 2011 04:56:26 +0000 (23:56 -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
for abi >= 6.

* semantics.c (finish_decltype_type): Remove shortcut for decltype
of id-expression.
* mangle.c (write_type) [DECLTYPE_TYPE]: Strip it here for abi < 6.

From-SVN: r170459

15 files changed:
gcc/ChangeLog
gcc/common.opt
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/mangle.c
gcc/cp/name-lookup.c
gcc/cp/name-lookup.h
gcc/cp/parser.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/abi/mangle39.C
gcc/testsuite/g++.dg/abi/mangle45.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/trailing1.C
gcc/testsuite/g++.dg/template/canon-type-12.C
gcc/testsuite/g++.dg/template/canon-type-9.C

index 6fb3936223a0517e715a11c909b65b9f3eb25692..c064b51ce647a2f72c43fc83a80feede5557d975 100644 (file)
@@ -1,3 +1,7 @@
+2011-02-23  Jason Merrill  <jason@redhat.com>
+
+       * common.opt (fabi-version): Document v5 and v6.
+
 2011-02-23  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/47849
index f95805c7f1e0d4fc58c1a8f1fe06c507749ba95e..2717b11cc1cbd845c9bb89834715281d109e14ff 100644 (file)
@@ -741,6 +741,12 @@ Driver Undocumented
 ; 4: The version of the ABI that introduces unambiguous mangling of
 ;    vector types.
 ;
+; 5: The version of the ABI that ignores attribute const/noreturn
+;    in function pointer mangling.
+;
+; 6: The version of the ABI that corrects mangling of decltype and
+;    function parameters used in other parameters and the return type.
+;
 ; Additional positive integers will be assigned as new versions of
 ; the ABI become the default version of the ABI.
 fabi-version=
index 195b3192bf93dc393fae90b440de48008b00a434..8637ee0b369aca60db7ea6045103acae6087587f 100644 (file)
@@ -1,3 +1,19 @@
+2011-02-23  Jason Merrill  <jason@redhat.com>
+
+       * 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
+       for abi >= 6.
+
+       * semantics.c (finish_decltype_type): Remove shortcut for decltype
+       of id-expression.
+       * mangle.c (write_type) [DECLTYPE_TYPE]: Strip it here for abi < 6.
+
 2011-02-23  Nathan Froyd  <froydnj@codesourcery.com>
 
        PR c++/46868
index 238d0cfd0be3662be64b38f3c3a573d72400f23e..ee72322a3544f7eb75027fed15d5b89c2e9fd1ec 100644 (file)
@@ -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)
index 4d2ace632bcee858f947d3630bda29fa0479620d..dca8b604daa9586887317cac02efcc305d8b2572 100644 (file)
@@ -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;
@@ -1931,6 +1934,35 @@ write_type (tree type)
              gcc_assert (!DECLTYPE_FOR_LAMBDA_CAPTURE (type)
                          && !DECLTYPE_FOR_LAMBDA_RETURN (type));
 
+             /* In ABI <6, we stripped decltype of a plain decl.  */
+             if (!abi_version_at_least (6)
+                 && DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
+               {
+                 tree expr = DECLTYPE_TYPE_EXPR (type);
+                 tree etype = NULL_TREE;
+                 switch (TREE_CODE (expr))
+                   {
+                   case VAR_DECL:
+                   case PARM_DECL:
+                   case RESULT_DECL:
+                   case FUNCTION_DECL:
+                   case CONST_DECL:
+                   case TEMPLATE_PARM_INDEX:
+                     etype = TREE_TYPE (expr);
+                     break;
+
+                   default:
+                     break;
+                   }
+
+                 if (etype && !type_uses_auto (etype))
+                   {
+                     G.need_abi_warning = 1;
+                     write_type (etype);
+                     return;
+                   }
+               }
+
               write_char ('D');
               if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
                 write_char ('t');
@@ -2270,9 +2302,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 +2492,28 @@ 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)
+       {
+         if (abi_version_at_least (6))
+           {
+             /* 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);
+           }
+         else
+           G.need_abi_warning = true;
+       }
+      write_char ('p');
       write_compact_number (index - 1);
     }
   else if (DECL_P (expr))
index e2e54507c4694447f1b4f9f42eb81e0b675dc95b..4117202351dfc6d488732257aa23f589376ce085 100644 (file)
@@ -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;
index f81a5659ac4adf6992a1b14ff70c08ad7e635bc9..bfcac69c110d10d54dd5fbac01fe6165daee8a5e 100644 (file)
@@ -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);
index 5b08389f4e79909f22b53d418e1f4d0aedd84d6b..1e8f03bddca94cdcd8284abf24b8d812fcbd09d5 100644 (file)
@@ -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.  */
index 4af007dfb7f5c9371d0f43f9315b81c237db8a88..8a7dd7d5e6294fb7036e6093c8ad61cbd2edcb3f 100644 (file)
@@ -4772,6 +4772,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
       return error_mark_node;
     }
 
+  /* FIXME instantiation-dependent  */
   if (type_dependent_expression_p (expr)
       /* In a template, a COMPONENT_REF has an IDENTIFIER_NODE for op1 even
         if it isn't dependent, so that we can check access control at
@@ -4780,27 +4781,6 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
          && processing_template_decl
          && TREE_CODE (expr) == COMPONENT_REF))
     {
-      if (id_expression_or_member_access_p)
-       {
-         switch (TREE_CODE (expr))
-           {
-           case VAR_DECL:
-           case PARM_DECL:
-           case RESULT_DECL:
-           case FUNCTION_DECL:
-           case CONST_DECL:
-           case TEMPLATE_PARM_INDEX:
-             type = TREE_TYPE (expr);
-             break;
-
-           default:
-             break;
-           }
-       }
-
-      if (type && !type_uses_auto (type))
-       return type;
-
     treat_as_dependent:
       type = cxx_make_type (DECLTYPE_TYPE);
       DECLTYPE_TYPE_EXPR (type) = expr;
index b2abbe7096159a124993aa4b8be77d3ce83ec1ee..dc92141f8000eea8997581c4b303e0fff66954a3 100644 (file)
@@ -1,3 +1,13 @@
+2011-02-23  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/abi/mangle39.C: Adjust parm mangling.
+       * g++.dg/abi/mangle45.C: New.
+
+       * g++.dg/cpp0x/trailing1.C: Mangle decltype.
+       * g++.dg/template/canon-type-9.C: Match use of decltype
+       between declaration and definition.
+       * g++.dg/template/canon-type-12.C: Likewise.
+
 2011-02-23  Mikael Morin  <mikael@gcc.gnu.org>
 
        PR fortran/40850
index 30a08b0c32f948983840437833986a33fea61732..272385b6de060f0c73141680c7f31eb5079a3932 100644 (file)
@@ -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 (file)
index 0000000..8e20831
--- /dev/null
@@ -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 11e73d2e716975911b0ede1004528bda95f17805..fcf65e3b01c4d7a8219f0edf28d06fa2cdfbcf5a 100644 (file)
@@ -78,7 +78,6 @@ auto k(T t, U u, V v) -> decltype (t.U::template B<V>::MEM)
   return t.U::template B<V>::MEM;
 }
 
-// For these two examples we can elide the 'decltype' and just mangle the type.
 template <class T>
 auto l(T t) -> decltype (t)
 {
@@ -111,8 +110,8 @@ int main()
   h(a,1.0);
   // { dg-final { scan-assembler "_Z1kI1C1AIiE1DEDtdtfp_srNT0_1BIT1_EE3MEMET_S4_S6_" } }
   k( C(), A<int>(), D() );
-  // { dg-final { scan-assembler "_Z1lIiET_S0_" } }
+  // { dg-final { scan-assembler "_Z1lIiEDtfp_ET_" } }
   l(1);
-  // { dg-final { scan-assembler "_Z1mIiLi1EET_S0_" } }
+  // { dg-final { scan-assembler "_Z1mIiLi1EEDtT0_ET_" } }
   m<int,1>(1);
 }
index 694cc5e13790cb5aeb3edad018342993bddade94..08c86f0a9810a63f3b86f8ce1ec64b24460839a7 100644 (file)
@@ -9,7 +9,7 @@ struct S
 
 template<class T, T t>
 void
-S<T, t>::foo(T)
+S<T, t>::foo(decltype(t))
 {
 }
 
index 8d1aa29ee668002be3c53cd0c41f0279b01ad4e7..4fcd5243534d047021fd7c45e4f50084ce7fdb15 100644 (file)
@@ -11,7 +11,7 @@ struct S
 };
 
 template<class T, T *u>
-T* S<T, u>::foo(T)
+decltype(u) S<T, u>::foo(T)
 {
   T t;
   return t;