PR c++/26433

Mark Mitchell mark@codesourcery.com
Fri May 19 16:55:00 GMT 2006


This patch fixes PR c++/26433, a problem with function-try-blocks and
__FUNCTION__.  We create __FUNCTION__ and friends lazily, in the
outermost scope of the function.  For a function with a
function-try-block, we didn't have an outermost scope; there was one
scope inside the try, and another inside each handler, but no unique
outermost scope, which confused the code creating __FUNCTION__.

This patch creates an artificial outermost scope, which solves the
problem.

Tested on x86_64-unknown-linux-gnu, applied on the mainline.

--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

2006-05-19  Mark Mitchell  <mark@codesourcery.com>

	PR c++/26433
	* cp-tree.h (begin_function_try_block): Change prototype.
	(finish_function_handler_sequence): Likewise.
	* parser.c (cp_parser_function_try_block): Adjust calls.
	* pt.c (tsubst_expr): Adjust calls.
	* semantics.c (begin_function_try_block): Create an artificial
	outer scope.
	(finish_function_handler_sequence): Close it.

2006-05-19  Mark Mitchell  <mark@codesourcery.com>

	PR c++/26433
	* g++.dg/template/fntry1.C: New test.

Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 113902)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -4190,9 +4190,9 @@ extern void finish_try_block			(tree);
 extern tree begin_eh_spec_block			(void);
 extern void finish_eh_spec_block		(tree, tree);
 extern void finish_handler_sequence		(tree);
-extern tree begin_function_try_block		(void);
+extern tree begin_function_try_block		(tree *);
 extern void finish_function_try_block		(tree);
-extern void finish_function_handler_sequence    (tree);
+extern void finish_function_handler_sequence    (tree, tree);
 extern void finish_cleanup_try_block		(tree);
 extern tree begin_handler			(void);
 extern void finish_handler_parms		(tree, tree);
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 113901)
+++ gcc/cp/pt.c	(working copy)
@@ -8405,8 +8405,10 @@ tsubst_expr (tree t, tree args, tsubst_f
 	}
       else
 	{
+	  tree compound_stmt = NULL_TREE;
+
 	  if (FN_TRY_BLOCK_P (t))
-	    stmt = begin_function_try_block ();
+	    stmt = begin_function_try_block (&compound_stmt);
 	  else
 	    stmt = begin_try_block ();
 
@@ -8419,7 +8421,7 @@ tsubst_expr (tree t, tree args, tsubst_f
 
 	  tsubst_expr (TRY_HANDLERS (t), args, complain, in_decl);
 	  if (FN_TRY_BLOCK_P (t))
-	    finish_function_handler_sequence (stmt);
+	    finish_function_handler_sequence (stmt, compound_stmt);
 	  else
 	    finish_handler_sequence (stmt);
 	}
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c	(revision 113901)
+++ gcc/cp/semantics.c	(working copy)
@@ -975,12 +975,18 @@ begin_try_block (void)
   return r;
 }
 
-/* Likewise, for a function-try-block.  */
+/* Likewise, for a function-try-block.  The block returned in
+   *COMPOUND_STMT is an artificial outer scope, containing the
+   function-try-block.  */
 
 tree
-begin_function_try_block (void)
+begin_function_try_block (tree *compound_stmt)
 {
-  tree r = begin_try_block ();
+  tree r;
+  /* This outer scope does not exist in the C++ standard, but we need
+     a place to put __FUNCTION__ and similar variables.  */
+  *compound_stmt = begin_compound_stmt (0);
+  r = begin_try_block ();
   FN_TRY_BLOCK_P (r) = 1;
   return r;
 }
@@ -1034,13 +1040,16 @@ finish_handler_sequence (tree try_block)
   check_handlers (TRY_HANDLERS (try_block));
 }
 
-/* Likewise, for a function-try-block.  */
+/* Finish the handler-seq for a function-try-block, given by
+   TRY_BLOCK.  COMPOUND_STMT is the outer block created by
+   begin_function_try_block.  */
 
 void
-finish_function_handler_sequence (tree try_block)
+finish_function_handler_sequence (tree try_block, tree compound_stmt)
 {
   in_function_try_handler = 0;
   finish_handler_sequence (try_block);
+  finish_compound_stmt (compound_stmt);
 }
 
 /* Begin a handler.  Returns a HANDLER if appropriate.  */
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 113901)
+++ gcc/cp/parser.c	(working copy)
@@ -14225,6 +14225,7 @@ cp_parser_try_block (cp_parser* parser)
 static bool
 cp_parser_function_try_block (cp_parser* parser)
 {
+  tree compound_stmt;
   tree try_block;
   bool ctor_initializer_p;
 
@@ -14232,7 +14233,7 @@ cp_parser_function_try_block (cp_parser*
   if (!cp_parser_require_keyword (parser, RID_TRY, "`try'"))
     return false;
   /* Let the rest of the front-end know where we are.  */
-  try_block = begin_function_try_block ();
+  try_block = begin_function_try_block (&compound_stmt);
   /* Parse the function-body.  */
   ctor_initializer_p
     = cp_parser_ctor_initializer_opt_and_function_body (parser);
@@ -14241,7 +14242,7 @@ cp_parser_function_try_block (cp_parser*
   /* Parse the handlers.  */
   cp_parser_handler_seq (parser);
   /* We're done with the handlers.  */
-  finish_function_handler_sequence (try_block);
+  finish_function_handler_sequence (try_block, compound_stmt);
 
   return ctor_initializer_p;
 }
Index: gcc/testsuite/g++.dg/template/fntry1.C
===================================================================
--- gcc/testsuite/g++.dg/template/fntry1.C	(revision 0)
+++ gcc/testsuite/g++.dg/template/fntry1.C	(revision 0)
@@ -0,0 +1,42 @@
+// PR c++/26433
+
+int get_int()
+{
+  throw 1;
+
+  return 0;
+}
+
+template <class _T> class Test
+{
+public:
+  Test()
+        try
+	: i(get_int())
+  {
+    i++;
+  }
+  catch(...)
+  {
+    // Syntax error caused by undefined __FUNCTION__.
+    const char* ptr = __FUNCTION__;
+  }
+
+private:
+  int i;
+  _T t;
+};
+
+int main()
+{
+    try
+      {
+        Test<int> test;
+      }
+    catch(...)
+      {
+        return 1;
+      }
+
+    return 0;
+}



More information about the Gcc-patches mailing list