From patchwork Mon May 22 15:58:21 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 765471 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3wWjxm18Bqz9s2Q for ; Tue, 23 May 2017 01:58:35 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="tHHAQQ46"; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=aYDpui02wPIwCLjCuI76ugteNJJGWK/aRPx7ZvOowMqaPECUeH K2R2sZm+UJVdDdiRB0Nt/kyAdcgnCZ0qcQB0A3M9J3zijJkN9J5/hyYsXwgBvy+f PAvz+tT+g74tbqW/sjwUMMNPXAZWxNsOvLMKE4nGvfy+JC6DfWaYkOBQw= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=qTBdBddRETKEzSv5Xo236hHHiu0=; b=tHHAQQ46KhE+QKm1n68E wEhhPASRDdj82v/Xf32TJSOymfIk2yUlpbaDdunVPotyo+QxGTo0rep3Ahv7AlNh 79KbqhkOrEuzn6Upb/NYlEn0Rn6o6TWvUQuLpGRm0u1kgkZnYFcxDVG0EZKTpJvr GreeAtNuwNncOaDGNdfYsXo= Received: (qmail 118450 invoked by alias); 22 May 2017 15:58:25 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 116962 invoked by uid 89); 22 May 2017 15:58:24 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-10.6 required=5.0 tests=BAYES_00, FREEMAIL_FROM, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=ham version=3.3.2 spammy=Directly, USED, enclose X-HELO: mail-yw0-f177.google.com Received: from mail-yw0-f177.google.com (HELO mail-yw0-f177.google.com) (209.85.161.177) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 22 May 2017 15:58:21 +0000 Received: by mail-yw0-f177.google.com with SMTP id l14so62034105ywk.1 for ; Mon, 22 May 2017 08:58:24 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:to:from:subject:message-id:date :user-agent:mime-version:content-language; bh=j03PjlQoHLNetHSjJg6fDkpLrX61rycrOpWSNLD3QBU=; b=H2rUngLqZr1KRhcF7McPTEQOfqOKRpiU2wIBsHnIhkWtUvKwuy7SLFPmmxvDeT444S SKsWxJ43X3Z4B8o8rS2N+8ZEIGRk1mh944iJqRkZZEUBR6Qpz1MirgOAOCtmadoyd6tu wS1XWdS6esBJzDd7pF9ZEVaWsX+ksz5DEQAwvvVTTxLyh4BcIRkxSIJrutm41eLkdSTG eXcXgKc6JWNbBy/un1+a4nlx2sFojPCPqWbz/JjH3jW6gM7Cf1Ji4uCi3pPtrvU5sZyD F260K8xBTnoyitTV0ALzquY7yUshgpIZpUF2lXjQ5IhJ1t9nXRlhNtdsXqwISk6QBbs3 QD3Q== X-Gm-Message-State: AODbwcBFdzvUgAOD03T24AaSHZFFANqA3snLSTOZd7Z2mlU26GZ9FXNC aYwS+jdN9Vk4DQ== X-Received: by 10.129.95.213 with SMTP id t204mr13612747ywb.141.1495468702783; Mon, 22 May 2017 08:58:22 -0700 (PDT) Received: from ?IPv6:2620:10d:c0a3:20fb:f6d0:5ac5:64cd:f102? ([2620:10d:c091:200::94]) by smtp.googlemail.com with ESMTPSA id g38sm7587095ywk.7.2017.05.22.08.58.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 22 May 2017 08:58:22 -0700 (PDT) To: GCC Patches From: Nathan Sidwell Subject: [C++ PATCH] Using directives Message-ID: <48850509-31d3-b820-c9e9-bcd246380cee@acm.org> Date: Mon, 22 May 2017 11:58:21 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.1.0 MIME-Version: 1.0 This is the first half of using directive cleanup. I split the current interface in two, one for namespace-level directives and one for local directives. That avoids the need for a load if 'if (namespace_level_p ())' tests in the bodies of the worker functions. I also merged and renamed do_using_directive & parse_using_directive, as we're not actually parsing at this point, so a finish_FOO name seemed more appropriate. The second part of the patch removes the recursiveness of add_using_namespace_1 and will wait until the namespace using representation has been simplified. Jason killed strong using directives earlier this year. I'd already written the fragment suggesting an inline namespace, so included it here. You may notice that push_namespace has two calls to add_using_directive, which look like they could be combined. That's only because the representation if inline namespaces hasn't yet been changed. Applied to trunk. nathan 2017-05-22 Nathan Sidwell cp/ * name-lookup.h (parse_using_directive): Replace with ... (finish_namespace_using_directive): ... this and ... (finish_local_using_directive): ... this. * name-lookup.c (add_using_namespace_1): Move later. (add_using_namespace): Move later, add namespace_p arg, remove indirect arg. (push_using_directive_1): Directly recurse. (do_using_directive, parse_using_directive): Delete, split into ... (finish_namespace_using_directive): ... this and ... (finish_local_using_directive): ... this. (push_namespace): Use add_using_namespace. * parser.c (cp_parser_using_directive): Call finish_namespace_using_directive or finish_local_using_directive. * pt.c (tsubst_expr): Call finish_local_using_directive. testsuite/ * g++.dg/lookup/strong-using.C: New. Index: cp/name-lookup.c =================================================================== --- cp/name-lookup.c (revision 248327) +++ cp/name-lookup.c (working copy) @@ -4337,60 +4337,6 @@ pushdecl_namespace_level (tree x, bool i return t; } -/* Insert USED into the using list of USER. Set INDIRECT_flag if this - directive is not directly from the source. Also find the common - ancestor and let our users know about the new namespace */ - -static void -add_using_namespace_1 (tree user, tree used, bool indirect) -{ - tree t; - /* Using oneself is a no-op. */ - if (user == used) - return; - gcc_assert (TREE_CODE (user) == NAMESPACE_DECL); - gcc_assert (TREE_CODE (used) == NAMESPACE_DECL); - /* Check if we already have this. */ - t = purpose_member (used, DECL_NAMESPACE_USING (user)); - if (t != NULL_TREE) - { - if (!indirect) - /* Promote to direct usage. */ - TREE_INDIRECT_USING (t) = 0; - return; - } - - /* Add used to the user's using list. */ - DECL_NAMESPACE_USING (user) - = tree_cons (used, namespace_ancestor (user, used), - DECL_NAMESPACE_USING (user)); - - TREE_INDIRECT_USING (DECL_NAMESPACE_USING (user)) = indirect; - - /* Add user to the used's users list. */ - DECL_NAMESPACE_USERS (used) - = tree_cons (user, 0, DECL_NAMESPACE_USERS (used)); - - /* Recursively add all namespaces used. */ - for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t)) - /* indirect usage */ - add_using_namespace_1 (user, TREE_PURPOSE (t), 1); - - /* Tell everyone using us about the new used namespaces. */ - for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t)) - add_using_namespace_1 (TREE_PURPOSE (t), used, 1); -} - -/* Wrapper for add_using_namespace_1. */ - -static void -add_using_namespace (tree user, tree used, bool indirect) -{ - bool subtime = timevar_cond_start (TV_NAME_LOOKUP); - add_using_namespace_1 (user, used, indirect); - timevar_cond_stop (TV_NAME_LOOKUP, subtime); -} - /* Process a using-declaration not appearing in class or local scope. */ void @@ -4422,75 +4368,6 @@ do_toplevel_using_decl (tree decl, tree binding->type = newtype; } -/* Process a using-directive. */ - -void -do_using_directive (tree name_space) -{ - tree context = NULL_TREE; - - if (name_space == error_mark_node) - return; - - gcc_assert (TREE_CODE (name_space) == NAMESPACE_DECL); - - if (building_stmt_list_p ()) - add_stmt (build_stmt (input_location, USING_STMT, name_space)); - name_space = ORIGINAL_NAMESPACE (name_space); - - if (!toplevel_bindings_p ()) - { - push_using_directive (name_space); - } - else - { - /* direct usage */ - add_using_namespace (current_namespace, name_space, 0); - if (current_namespace != global_namespace) - context = current_namespace; - - /* Emit debugging info. */ - if (!processing_template_decl) - (*debug_hooks->imported_module_or_decl) (name_space, NULL_TREE, - context, false); - } -} - -/* Deal with a using-directive seen by the parser. Currently we only - handle attributes here, since they cannot appear inside a template. */ - -void -parse_using_directive (tree name_space, tree attribs) -{ - do_using_directive (name_space); - - if (attribs == error_mark_node) - return; - - for (tree a = attribs; a; a = TREE_CHAIN (a)) - { - tree name = get_attribute_name (a); - if (is_attribute_p ("strong", name)) - { - warning (OPT_Wdeprecated, "strong using is deprecated; use inline " - "namespaces instead"); - if (!toplevel_bindings_p ()) - error ("strong using only meaningful at namespace scope"); - else if (name_space != error_mark_node) - { - if (!is_ancestor (current_namespace, name_space)) - error ("current namespace %qD does not enclose strongly used namespace %qD", - current_namespace, name_space); - DECL_NAMESPACE_ASSOCIATIONS (name_space) - = tree_cons (current_namespace, 0, - DECL_NAMESPACE_ASSOCIATIONS (name_space)); - } - } - else - warning (OPT_Wattributes, "%qD attribute directive ignored", name); - } -} - /* Combines two sets of overloaded functions into an OVERLOAD chain, removing duplicates. The first list becomes the tail of the result. @@ -5827,7 +5704,7 @@ push_using_directive_1 (tree used) /* Recursively add all namespaces used. */ for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter)) - push_using_directive (TREE_PURPOSE (iter)); + push_using_directive_1 (TREE_PURPOSE (iter)); return ud; } @@ -6363,6 +6240,113 @@ do_pop_nested_namespace (tree ns) do_pop_from_top_level (); } +/* Insert USED into the using list of USER. Set INDIRECT_flag if this + directive is not directly from the source. Also find the common + ancestor and let our users know about the new namespace */ + +static void +add_using_namespace_1 (tree user, tree used, bool indirect) +{ + tree t; + /* Using oneself is a no-op. */ + if (user == used) + return; + gcc_assert (TREE_CODE (user) == NAMESPACE_DECL); + gcc_assert (TREE_CODE (used) == NAMESPACE_DECL); + /* Check if we already have this. */ + t = purpose_member (used, DECL_NAMESPACE_USING (user)); + if (t != NULL_TREE) + { + if (!indirect) + /* Promote to direct usage. */ + TREE_INDIRECT_USING (t) = 0; + return; + } + + /* Add used to the user's using list. */ + DECL_NAMESPACE_USING (user) + = tree_cons (used, namespace_ancestor (user, used), + DECL_NAMESPACE_USING (user)); + + TREE_INDIRECT_USING (DECL_NAMESPACE_USING (user)) = indirect; + + /* Add user to the used's users list. */ + DECL_NAMESPACE_USERS (used) + = tree_cons (user, 0, DECL_NAMESPACE_USERS (used)); + + /* Recursively add all namespaces used. */ + for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t)) + /* indirect usage */ + add_using_namespace_1 (user, TREE_PURPOSE (t), 1); + + /* Tell everyone using us about the new used namespaces. */ + for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t)) + add_using_namespace_1 (TREE_PURPOSE (t), used, 1); +} + +/* Wrapper for add_using_namespace_1. */ + +static void +add_using_namespace (bool namespace_level_p, tree from, tree target) +{ + bool subtime = timevar_cond_start (TV_NAME_LOOKUP); + add_using_namespace_1 (from, target, false); + if (namespace_level_p) + { + /* Emit debugging info. */ + tree context = from != global_namespace ? from : NULL_TREE; + debug_hooks->imported_module_or_decl (target, NULL_TREE, context, false); + } + timevar_cond_stop (TV_NAME_LOOKUP, subtime); +} + +/* Process a namespace-scope using directive. */ + +void +finish_namespace_using_directive (tree target, tree attribs) +{ + gcc_checking_assert (namespace_bindings_p ()); + if (target == error_mark_node) + return; + + add_using_namespace (true, current_namespace, + ORIGINAL_NAMESPACE (target)); + + if (attribs == error_mark_node) + return; + + for (tree a = attribs; a; a = TREE_CHAIN (a)) + { + tree name = get_attribute_name (a); + if (is_attribute_p ("strong", name)) + { + warning (0, "strong using directive no longer supported"); + if (CP_DECL_CONTEXT (target) == current_namespace) + inform (DECL_SOURCE_LOCATION (target), + "you may use an inline namespace instead"); + } + else + warning (OPT_Wattributes, "%qD attribute directive ignored", name); + } +} + +/* Process a function-scope using-directive. */ + +void +finish_local_using_directive (tree target, tree attribs) +{ + gcc_checking_assert (local_bindings_p ()); + if (target == error_mark_node) + return; + + if (attribs) + warning (OPT_Wattributes, "attributes ignored on local using directive"); + + add_stmt (build_stmt (input_location, USING_STMT, target)); + + push_using_directive (ORIGINAL_NAMESPACE (target)); +} + /* Pushes X into the global namespace. */ tree @@ -6468,7 +6452,7 @@ push_namespace (tree name, bool make_inl DECL_NAME (ns) = NULL_TREE; if (!make_inline) - do_using_directive (ns); + add_using_namespace (true, current_namespace, ns); } else if (TREE_PUBLIC (current_namespace)) TREE_PUBLIC (ns) = 1; @@ -6480,7 +6464,7 @@ push_namespace (tree name, bool make_inl DECL_NAMESPACE_ASSOCIATIONS (ns) = tree_cons (current_namespace, NULL_TREE, NULL_TREE); /* Import the contents of the inline namespace. */ - do_using_directive (ns); + add_using_namespace (true, current_namespace, ns); } } } @@ -6525,8 +6509,6 @@ push_to_top_level (void) timevar_cond_stop (TV_NAME_LOOKUP, subtime); } -/* Wrapper for pop_from_top_level_1. */ - void pop_from_top_level (void) { Index: cp/name-lookup.h =================================================================== --- cp/name-lookup.h (revision 248326) +++ cp/name-lookup.h (working copy) @@ -332,11 +332,12 @@ extern tree do_class_using_decl (tree, t extern void do_using_directive (tree); extern cp_expr lookup_arg_dependent (tree, tree, vec *); extern bool is_associated_namespace (tree, tree); -extern void parse_using_directive (tree, tree); extern tree innermost_non_namespace_value (tree); extern cxx_binding *outer_binding (tree, cxx_binding *, bool); extern void cp_emit_debug_info_for_using (tree, tree); +extern void finish_namespace_using_directive (tree, tree); +extern void finish_local_using_directive (tree, tree); extern tree pushdecl_outermost_localscope (tree); extern tree pushdecl (tree, bool is_friend = false); extern tree pushdecl_top_level (tree, bool is_friend = false); Index: cp/parser.c =================================================================== --- cp/parser.c (revision 248326) +++ cp/parser.c (working copy) @@ -18692,8 +18692,13 @@ cp_parser_using_directive (cp_parser* pa namespace_decl = cp_parser_namespace_name (parser); /* And any specified attributes. */ attribs = cp_parser_attributes_opt (parser); + /* Update the symbol table. */ - parse_using_directive (namespace_decl, attribs); + if (namespace_bindings_p ()) + finish_namespace_using_directive (namespace_decl, attribs); + else + finish_local_using_directive (namespace_decl, attribs); + /* Look for the final `;'. */ cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); } Index: cp/pt.c =================================================================== --- cp/pt.c (revision 248326) +++ cp/pt.c (working copy) @@ -15672,7 +15672,8 @@ tsubst_expr (tree t, tree args, tsubst_f break; case USING_STMT: - do_using_directive (USING_STMT_NAMESPACE (t)); + finish_local_using_directive (USING_STMT_NAMESPACE (t), + /*attribs=*/NULL_TREE); break; case DECL_EXPR: Index: testsuite/g++.dg/lookup/strong-using.C =================================================================== --- testsuite/g++.dg/lookup/strong-using.C (revision 0) +++ testsuite/g++.dg/lookup/strong-using.C (working copy) @@ -0,0 +1,10 @@ +// { dg-do compile { target c++11 } } + +namespace A +{ + namespace B // { dg-message "inline namespace" } + { + } + + using namespace B __attribute__ ((strong)); // { dg-warning "no longer supported" "" } +}