]> gcc.gnu.org Git - gcc.git/commitdiff
parser.c (inject_this_parameter): Split out from cp_parser_late_return_type_opt.
authorJason Merrill <jason@redhat.com>
Mon, 26 Sep 2011 03:56:10 +0000 (23:56 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 26 Sep 2011 03:56:10 +0000 (23:56 -0400)
* parser.c (inject_this_parameter): Split out from
cp_parser_late_return_type_opt.
(cp_parser_class_specifier_1): Use it for NSDMIs.
* tree.c (bot_replace): Replace NSDMI 'this' with real 'this'.

From-SVN: r179179

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/cp/tree.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/nsdmi-defer4.C [new file with mode: 0644]

index 8c25746f0cb4206bd7e4f98352c773d38eea0ea6..cd309042f876fee35b61ac78c6e3d225e50956e1 100644 (file)
@@ -1,3 +1,10 @@
+2011-09-25  Jason Merrill  <jason@redhat.com>
+
+       * parser.c (inject_this_parameter): Split out from
+       cp_parser_late_return_type_opt.
+       (cp_parser_class_specifier_1): Use it for NSDMIs.
+       * tree.c (bot_replace): Replace NSDMI 'this' with real 'this'.
+
 2011-09-24  Jason Merrill  <jason@redhat.com>
 
        * except.c (expr_noexcept_p): Split out from finish_noexcept_expr.
index 2dbe86613c4b9e80d570b8e94bc8897cb8d31a74..9600aa954384747379859fe12501cd5818b51528 100644 (file)
@@ -15690,6 +15690,31 @@ cp_parser_virt_specifier_seq_opt (cp_parser* parser)
   return virt_specifiers;
 }
 
+/* Used by handling of trailing-return-types and NSDMI, in which 'this'
+   is in scope even though it isn't real.  */
+
+static void
+inject_this_parameter (tree ctype, cp_cv_quals quals)
+{
+  tree this_parm;
+
+  if (current_class_ptr)
+    {
+      /* We don't clear this between NSDMIs.  Is it already what we want?  */
+      tree type = TREE_TYPE (TREE_TYPE (current_class_ptr));
+      if (same_type_ignoring_top_level_qualifiers_p (ctype, type)
+         && cp_type_quals (type) == quals)
+       return;
+    }
+
+  this_parm = build_this_parm (ctype, quals);
+  /* Clear this first to avoid shortcut in cp_build_indirect_ref.  */
+  current_class_ptr = NULL_TREE;
+  current_class_ref
+    = cp_build_indirect_ref (this_parm, RO_NULL, tf_warning_or_error);
+  current_class_ptr = this_parm;
+}
+
 /* Parse a late-specified return type, if any.  This is not a separate
    non-terminal, but part of a function declarator, which looks like
 
@@ -15718,12 +15743,8 @@ cp_parser_late_return_type_opt (cp_parser* parser, cp_cv_quals quals)
   if (quals >= 0)
     {
       /* DR 1207: 'this' is in scope in the trailing return type.  */
-      tree this_parm = build_this_parm (current_class_type, quals);
       gcc_assert (current_class_ptr == NULL_TREE);
-      current_class_ref
-       = cp_build_indirect_ref (this_parm, RO_NULL, tf_warning_or_error);
-      /* Set this second to avoid shortcut in cp_build_indirect_ref.  */
-      current_class_ptr = this_parm;
+      inject_this_parameter (current_class_type, quals);
     }
 
   type = cp_parser_trailing_type_id (parser);
@@ -17274,6 +17295,7 @@ cp_parser_class_specifier_1 (cp_parser* parser)
       tree pushed_scope = NULL_TREE;
       unsigned ix;
       cp_default_arg_entry *e;
+      tree save_ccp, save_ccr;
 
       /* In a first pass, parse default arguments to the functions.
         Then, in a second pass, parse the bodies of the functions.
@@ -17307,6 +17329,8 @@ cp_parser_class_specifier_1 (cp_parser* parser)
        }
       VEC_truncate (cp_default_arg_entry, unparsed_funs_with_default_args, 0);
       /* Now parse any NSDMIs.  */
+      save_ccp = current_class_ptr;
+      save_ccr = current_class_ref;
       FOR_EACH_VEC_ELT (tree, unparsed_nsdmis, ix, decl)
        {
          if (class_type != DECL_CONTEXT (decl))
@@ -17316,9 +17340,12 @@ cp_parser_class_specifier_1 (cp_parser* parser)
              class_type = DECL_CONTEXT (decl);
              pushed_scope = push_scope (class_type);
            }
+         inject_this_parameter (class_type, TYPE_UNQUALIFIED);
          cp_parser_late_parsing_nsdmi (parser, decl);
        }
       VEC_truncate (tree, unparsed_nsdmis, 0);
+      current_class_ptr = save_ccp;
+      current_class_ref = save_ccr;
       if (pushed_scope)
        pop_scope (pushed_scope);
       /* Now parse the body of the functions.  */
index a9e1a26200ee8348e81ac670fdba75daed28f713..f23b888f3762caeb113cd062f3d6e3c05b5e065d 100644 (file)
@@ -1926,6 +1926,13 @@ bot_replace (tree* t,
       if (n)
        *t = (tree) n->value;
     }
+  else if (TREE_CODE (*t) == PARM_DECL
+          && DECL_NAME (*t) == this_identifier)
+    {
+      /* In an NSDMI we need to replace the 'this' parameter we used for
+        parsing with the real one for this function.  */
+      *t = current_class_ptr;
+    }
 
   return NULL_TREE;
 }
index 7bd46ae17b53daefe3e22bb3755e2bb14e5e3f4c..1a39c28f03ad838dc0e255fa99d7eb2d74087dd4 100644 (file)
@@ -1,3 +1,7 @@
+2011-09-25  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/cpp0x/nsdmi-defer4.C: New.
+
 2011-09-25  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/frame_overflow.ads: New.
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer4.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer4.C
new file mode 100644 (file)
index 0000000..68c8380
--- /dev/null
@@ -0,0 +1,17 @@
+// { dg-options -std=c++0x }
+
+struct A
+{
+  int i = 42;
+  int j = f();
+  int k = this->f();
+  int f() { return i++; }
+};
+
+A a;
+
+int main()
+{
+  if (a.j != 42 || a.k != 43 || a.i != 44)
+    __builtin_abort();
+}
This page took 0.122731 seconds and 5 git commands to generate.