diff options
-rw-r--r-- | gcc/cp/init.cc | 25 | ||||
-rw-r--r-- | gcc/cp/name-lookup.cc | 37 | ||||
-rw-r--r-- | gcc/cp/name-lookup.h | 2 | ||||
-rw-r--r-- | gcc/cp/pt.cc | 20 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/nsdmi-array2.C | 15 |
5 files changed, 58 insertions, 41 deletions
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc index 1dd24e3..0b35e10 100644 --- a/gcc/cp/init.cc +++ b/gcc/cp/init.cc @@ -597,32 +597,14 @@ maybe_instantiate_nsdmi_init (tree member, tsubst_flags_t complain) bool pushed = false; tree ctx = type_context_for_name_lookup (member); - processing_template_decl_sentinel ptds (/*reset*/false); + bool push_to_top = maybe_push_to_top_level (member); if (!currently_open_class (ctx)) { - if (!LOCAL_CLASS_P (ctx)) - push_to_top_level (); - else - /* push_to_top_level would lose the necessary function context, - just reset processing_template_decl. */ - processing_template_decl = 0; push_nested_class (ctx); push_deferring_access_checks (dk_no_deferred); pushed = true; } - /* If we didn't push_to_top_level, still step out of constructor - scope so build_base_path doesn't try to use its __in_chrg. */ - tree cfd = current_function_decl; - auto cbl = current_binding_level; - if (at_function_scope_p ()) - { - current_function_decl - = decl_function_context (current_function_decl); - while (current_binding_level->kind != sk_class) - current_binding_level = current_binding_level->level_chain; - } - inject_this_parameter (ctx, TYPE_UNQUALIFIED); start_lambda_scope (member); @@ -639,15 +621,12 @@ maybe_instantiate_nsdmi_init (tree member, tsubst_flags_t complain) if (init != error_mark_node) DECL_INITIAL (member) = init; - current_function_decl = cfd; - current_binding_level = cbl; if (pushed) { pop_deferring_access_checks (); pop_nested_class (); - if (!LOCAL_CLASS_P (ctx)) - pop_from_top_level (); } + maybe_pop_from_top_level (push_to_top); input_location = sloc; } diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc index 477cddd..7c61bc3 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -8236,6 +8236,43 @@ pop_from_top_level (void) free_saved_scope = s; } +/* Like push_to_top_level, but not if D is function-local. Returns whether we + did push to top. */ + +bool +maybe_push_to_top_level (tree d) +{ + /* Push if D isn't function-local, or is a lambda function, for which name + resolution is already done. */ + bool push_to_top + = !(current_function_decl + && !LAMBDA_FUNCTION_P (d) + && decl_function_context (d) == current_function_decl); + + if (push_to_top) + push_to_top_level (); + else + { + gcc_assert (!processing_template_decl); + push_function_context (); + cp_unevaluated_operand = 0; + c_inhibit_evaluation_warnings = 0; + } + + return push_to_top; +} + +/* Return from whatever maybe_push_to_top_level did. */ + +void +maybe_pop_from_top_level (bool push_to_top) +{ + if (push_to_top) + pop_from_top_level (); + else + pop_function_context (); +} + /* Push into the scope of the namespace NS, even if it is deeply nested within another namespace. */ diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index c234cd4..b3e7085 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -466,6 +466,8 @@ extern void push_nested_namespace (tree); extern void pop_nested_namespace (tree); extern void push_to_top_level (void); extern void pop_from_top_level (void); +extern bool maybe_push_to_top_level (tree); +extern void maybe_pop_from_top_level (bool); extern void push_using_decl_bindings (tree, tree); /* Lower level interface for modules. */ diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 6df16fe..3f1cf13 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -26815,20 +26815,7 @@ instantiate_body (tree pattern, tree args, tree d, bool nested_p) if (current_function_decl) save_omp_privatization_clauses (omp_privatization_save); - bool push_to_top - = !(current_function_decl - && !LAMBDA_FUNCTION_P (d) - && decl_function_context (d) == current_function_decl); - - if (push_to_top) - push_to_top_level (); - else - { - gcc_assert (!processing_template_decl); - push_function_context (); - cp_unevaluated_operand = 0; - c_inhibit_evaluation_warnings = 0; - } + bool push_to_top = maybe_push_to_top_level (d); mark_template_arguments_used (pattern, args); @@ -26942,10 +26929,7 @@ instantiate_body (tree pattern, tree args, tree d, bool nested_p) if (!nested_p) TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (d)) = 0; - if (push_to_top) - pop_from_top_level (); - else - pop_function_context (); + maybe_pop_from_top_level (push_to_top); if (current_function_decl) restore_omp_privatization_clauses (omp_privatization_save); diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-array2.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-array2.C new file mode 100644 index 0000000..5ad60f5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-array2.C @@ -0,0 +1,15 @@ +// PR c++/109666 +// { dg-do compile { target c++11 } } + +struct Point { + int value_; +}; +template <int n> struct StaticVector { + static StaticVector create() { + StaticVector output; + return output; + } + Point _M_elems[n]{}; + +}; +void f() { StaticVector<3>::create(); } |