Patchwork C++ PATCH for c++/55240 (local variable and nsdmi)

login
register
mail settings
Submitter Jason Merrill
Date March 16, 2013, 6:54 p.m.
Message ID <5144BFCC.2090707@redhat.com>
Download mbox | patch
Permalink /patch/228239/
State New
Headers show

Comments

Jason Merrill - March 16, 2013, 6:54 p.m.
In an NSDMI of a local class, current_function_decl is the enclosing 
function, but we still can't refer to local variables of that function.

Tested x86_64-pc-linux-gnu, applying to trunk.

Patch

commit 00297d25d51a02b5aba605ece2db8dd1a44c2145
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Feb 13 17:29:38 2013 -0500

    	PR c++/55240
    	* parser.c (parsing_nsdmi): New.
    	* semantics.c (outer_automatic_var_p): Check it.
    	(finish_id_expression): Likewise.
    	* cp-tree.h: Declare it.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c3b2aec..d9496d2 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4259,6 +4259,7 @@  extern int comparing_specializations;
 
 extern int cp_unevaluated_operand;
 extern tree cp_convert_range_for (tree, tree, tree);
+extern bool parsing_nsdmi (void);
 
 /* in pt.c  */
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index df3155f..b45daae 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -16937,6 +16937,19 @@  inject_this_parameter (tree ctype, cp_cv_quals quals)
   current_class_ptr = this_parm;
 }
 
+/* Return true iff our current scope is a non-static data member
+   initializer.  */
+
+bool
+parsing_nsdmi (void)
+{
+  /* We recognize NSDMI context by the context-less 'this' pointer set up
+     by the function above.  */
+  if (current_class_ptr && DECL_CONTEXT (current_class_ptr) == NULL_TREE)
+    return true;
+  return false;
+}
+
 /* Parse a late-specified return type, if any.  This is not a separate
    non-terminal, but part of a function declarator, which looks like
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 3c76bad..efe09bb 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2884,7 +2884,8 @@  outer_var_p (tree decl)
 {
   return ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
 	  && DECL_FUNCTION_SCOPE_P (decl)
-	  && DECL_CONTEXT (decl) != current_function_decl);
+	  && (DECL_CONTEXT (decl) != current_function_decl
+	      || parsing_nsdmi ()));
 }
 
 /* As above, but also checks that DECL is automatic.  */
@@ -3041,12 +3042,14 @@  finish_id_expression (tree id_expression,
 		return integral_constant_value (decl);
 	    }
 
+	  if (parsing_nsdmi ())
+	    containing_function = NULL_TREE;
 	  /* If we are in a lambda function, we can move out until we hit
 	     1. the context,
 	     2. a non-lambda function, or
 	     3. a non-default capturing lambda function.  */
-	  while (context != containing_function
-		 && LAMBDA_FUNCTION_P (containing_function))
+	  else while (context != containing_function
+		      && LAMBDA_FUNCTION_P (containing_function))
 	    {
 	      lambda_expr = CLASSTYPE_LAMBDA_EXPR
 		(DECL_CONTEXT (containing_function));
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-local.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-local.C
new file mode 100644
index 0000000..9b84c8c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-local.C
@@ -0,0 +1,8 @@ 
+// PR c++/55240
+// { dg-do compile { target c++11 } }
+
+int main()
+{
+    int q = 1;				 // { dg-error "declared here" }
+    struct test { int x = q; } instance; // { dg-error "local variable" }
+}