118 lines
3.3 KiB
Diff
118 lines
3.3 KiB
Diff
2008-09-03 Jakub Jelinek <jakub@redhat.com>
|
||
|
||
PR c++/37189
|
||
* cp-tree.h (defer_mark_used_calls, deferred_mark_used_calls): New
|
||
extern decls.
|
||
* decl2.c (mark_used): If defer_mark_used_calls, push decl into
|
||
deferred_mark_used_calls vector and exit early.
|
||
* decl.c (defer_mark_used_calls, deferred_mark_used_calls): New
|
||
variables.
|
||
(finish_function): Set defer_mark_used_calls for the duration of the
|
||
function. Call mark_used on any queued decls.
|
||
|
||
PR c++/37189
|
||
* g++.dg/gomp/pr37189.C: New test.
|
||
|
||
--- gcc/cp/decl2.c (revision 139954)
|
||
+++ gcc/cp/decl2.c (revision 139955)
|
||
@@ -3776,6 +3776,15 @@ mark_used (tree decl)
|
||
/* If we don't need a value, then we don't need to synthesize DECL. */
|
||
if (skip_evaluation)
|
||
return;
|
||
+
|
||
+ /* If within finish_function, defer the rest until that function
|
||
+ finishes, otherwise it might recurse. */
|
||
+ if (defer_mark_used_calls)
|
||
+ {
|
||
+ VEC_safe_push (tree, gc, deferred_mark_used_calls, decl);
|
||
+ return;
|
||
+ }
|
||
+
|
||
/* Normally, we can wait until instantiation-time to synthesize
|
||
DECL. However, if DECL is a static data member initialized with
|
||
a constant, we need the value right now because a reference to
|
||
--- gcc/cp/decl.c (revision 139954)
|
||
+++ gcc/cp/decl.c (revision 139955)
|
||
@@ -227,6 +227,11 @@ struct named_label_entry GTY(())
|
||
function, two inside the body of a function in a local class, etc.) */
|
||
int function_depth;
|
||
|
||
+/* To avoid unwanted recursion, finish_function defers all mark_used calls
|
||
+ encountered during its execution until it finishes. */
|
||
+bool defer_mark_used_calls;
|
||
+VEC(tree, gc) *deferred_mark_used_calls;
|
||
+
|
||
/* States indicating how grokdeclarator() should handle declspecs marked
|
||
with __attribute__((deprecated)). An object declared as
|
||
__attribute__((deprecated)) suppresses warnings of uses of other
|
||
@@ -12033,6 +12038,9 @@ finish_function (int flags)
|
||
if (fndecl == NULL_TREE)
|
||
return error_mark_node;
|
||
|
||
+ gcc_assert (!defer_mark_used_calls);
|
||
+ defer_mark_used_calls = true;
|
||
+
|
||
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
|
||
&& DECL_VIRTUAL_P (fndecl)
|
||
&& !processing_template_decl)
|
||
@@ -12232,6 +12240,17 @@ finish_function (int flags)
|
||
cxx_pop_function_context and then reset via pop_function_context. */
|
||
current_function_decl = NULL_TREE;
|
||
|
||
+ defer_mark_used_calls = false;
|
||
+ if (deferred_mark_used_calls)
|
||
+ {
|
||
+ unsigned int i;
|
||
+ tree decl;
|
||
+
|
||
+ for (i = 0; VEC_iterate (tree, deferred_mark_used_calls, i, decl); i++)
|
||
+ mark_used (decl);
|
||
+ VEC_free (tree, gc, deferred_mark_used_calls);
|
||
+ }
|
||
+
|
||
return fndecl;
|
||
}
|
||
|
||
--- gcc/cp/cp-tree.h (revision 139954)
|
||
+++ gcc/cp/cp-tree.h (revision 139955)
|
||
@@ -4381,6 +4381,9 @@ extern void initialize_artificial_var (
|
||
extern tree check_var_type (tree, tree);
|
||
extern tree reshape_init (tree, tree);
|
||
|
||
+extern bool defer_mark_used_calls;
|
||
+extern GTY(()) VEC(tree, gc) *deferred_mark_used_calls;
|
||
+
|
||
/* in decl2.c */
|
||
extern bool check_java_method (tree);
|
||
extern tree build_memfn_type (tree, tree, cp_cv_quals);
|
||
--- gcc/testsuite/g++.dg/gomp/pr37189.C (revision 0)
|
||
+++ gcc/testsuite/g++.dg/gomp/pr37189.C (revision 139955)
|
||
@@ -0,0 +1,27 @@
|
||
+// PR c++/37189
|
||
+// { dg-do compile }
|
||
+// { dg-options "-fopenmp" }
|
||
+
|
||
+struct S
|
||
+{
|
||
+ S () {}
|
||
+ S (S const &) {}
|
||
+};
|
||
+
|
||
+struct T
|
||
+{
|
||
+ S s;
|
||
+};
|
||
+
|
||
+void
|
||
+bar (T &)
|
||
+{
|
||
+}
|
||
+
|
||
+int
|
||
+foo ()
|
||
+{
|
||
+ T t;
|
||
+ #pragma omp task
|
||
+ bar (t);
|
||
+}
|