diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 203955e3bc7..9d3fdfefa89 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2012-06-09 Jason Merrill + * pt.c (tsubst_expr) [TAG_DEFN]: Instantiate local class. + * class.c (finish_struct): Don't add a TAG_DEFN for a lambda. + * decl2.c (finish_static_data_member_decl): Avoid redundant error. + PR c++/53599 * name-lookup.c (pushtag_1): Add a DECL_EXPR for a local class. * semantics.c (finish_cond): Build a COMPOUND_EXPR. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 4bb9dd2c168..021344bad7c 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -6337,7 +6337,9 @@ finish_struct (tree t, tree attributes) else error ("trying to finish struct, but kicked out due to previous parse errors"); - if (processing_template_decl && at_function_scope_p ()) + if (processing_template_decl && at_function_scope_p () + /* Lambdas are defined by the LAMBDA_EXPR. */ + && !LAMBDA_TYPE_P (t)) add_stmt (build_min (TAG_DEFN, t)); return t; diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 78e17af61a4..2e3c9a63362 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -770,7 +770,9 @@ finish_static_data_member_decl (tree decl, if (! processing_template_decl) VEC_safe_push (tree, gc, pending_statics, decl); - if (LOCAL_CLASS_P (current_class_type)) + if (LOCAL_CLASS_P (current_class_type) + /* We already complained about the template definition. */ + && !DECL_TEMPLATE_INSTANTIATION (decl)) permerror (input_location, "local class %q#T shall not have static data member %q#D", current_class_type, decl); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 04f7be81f3e..5e02c8c4193 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -13123,7 +13123,21 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, break; case TAG_DEFN: - tsubst (TREE_TYPE (t), args, complain, NULL_TREE); + tmp = tsubst (TREE_TYPE (t), args, complain, NULL_TREE); + if (CLASS_TYPE_P (tmp)) + { + /* Local classes are not independent templates; they are + instantiated along with their containing function. And this + way we don't have to deal with pushing out of one local class + to instantiate a member of another local class. */ + tree fn; + /* Closures are handled by the LAMBDA_EXPR. */ + gcc_assert (!LAMBDA_TYPE_P (TREE_TYPE (t))); + complete_type (tmp); + for (fn = TYPE_METHODS (tmp); fn; fn = DECL_CHAIN (fn)) + if (!DECL_ARTIFICIAL (fn)) + instantiate_decl (fn, /*defer_ok*/0, /*expl_inst_class*/false); + } break; case STATIC_ASSERT: