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