From patchwork Wed May 24 23:21:14 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 766718 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 3wY7gv2szpz9s7F for ; Thu, 25 May 2017 09:21:30 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="sgCBFRRS"; 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=xU1nh/MaxN61RRvQjZaOVQkxy8dgFlM6Y2qePjzv3jxi3F8yRo ef/FD9DE3upED7ZkavlEXUQJh82QEqJiofO9Kv3+W4Y6A8xd3E4EYU9lU/a1WDAg s7dOuAyQdbWH4WAazTMrPQttmEWMahzDSSWVO6RJbSl4zztwG7lPYvSX8= 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=O8JXXMe2kbC49dk2VBHxv7Z3joA=; b=sgCBFRRS0PBlMa3KKOuF thqEzjhTZKCO/vdtreozQrNihrvWsF3wy0qx19RhjMS1xUTq6LXJMSiZqEyOWLi8 ZJAWPPzt3DLsYAUHD+uR5p7nXQ8uUA8WivSVr3HBqhM1hVyDP+bC5hw1fyrPGTU1 Igd15Na0JZTwLYzrf3FCGSM= Received: (qmail 5852 invoked by alias); 24 May 2017 23:21:17 -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 5838 invoked by uid 89); 24 May 2017 23:21:16 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-11.1 required=5.0 tests=BAYES_00, FREEMAIL_FROM, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=2, 9, Friend, Baz X-HELO: mail-yb0-f178.google.com Received: from mail-yb0-f178.google.com (HELO mail-yb0-f178.google.com) (209.85.213.178) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 24 May 2017 23:21:14 +0000 Received: by mail-yb0-f178.google.com with SMTP id p143so49110628yba.2 for ; Wed, 24 May 2017 16:21:18 -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=lU7toFTK7h1gCKXZ+v1MN79XJpl26QxOo4v5XiWC0Uc=; b=If1ZuimFVd0YRPZJI6UMfA+X7e/6vTr5XaVYg01HAF9PC8B2k4sikivqDODK4C8Fgk ZcQMBeROFevkysZv4otJIVJxSIcHhcELVDvytl0EDHjRgG6EiiQytn20m29CRgheOKmB pNCpEVzsNH1Zc5qjOg3+esggLJSTIKTajLFKBo2G4+1oecYWIUPaPGD9U4Yg1AbtPWps 1MlHkg2ht0WH0l+ZKVZTwa0jBl0xGVE/Z362nUHT8003OVsCRloTUHuOobjgBGU/C0eH Q1lwsuybJXkHUxuIO1iWchSPgqX/pDDInf/OMNjJLqZJN34gzTTEZwyeVZKFT0JFmmMd kA0A== X-Gm-Message-State: AODbwcAQUgnYB8IJmQWV4KU4sNhkWhCEU751WVM+9qbb4ONPpj1AMAfg f88RJMleO/c8aw== X-Received: by 10.37.165.66 with SMTP id h60mr4019340ybi.124.1495668076792; Wed, 24 May 2017 16:21:16 -0700 (PDT) Received: from ?IPv6:2620:10d:c0a1:1102:b9b0:1beb:d21c:b3f4? ([2620:10d:c091:180::1:11db]) by smtp.googlemail.com with ESMTPSA id v14sm2569384ywh.45.2017.05.24.16.21.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 24 May 2017 16:21:16 -0700 (PDT) To: GCC Patches From: Nathan Sidwell Subject: [C++ PATCH] Friend decls Message-ID: <180e9612-ae0b-9e21-7624-4bb289ba5ae7@acm.org> Date: Wed, 24 May 2017 19:21:14 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.1.0 MIME-Version: 1.0 With pushdecl revamped, there's no need for do_friend to do some checking with a local class friend. And therefore no need for the very specialized lookup_name_innermost_nonclass_level. push_local_binding will get some more cleanup soon. Committed to trunk. nathan 2017-05-24 Nathan Sidwell cp/ * friend.c (do_friend): Remove check for existing decl. * name-lookup.h (lookup_name_innermost_nonclass_level): Delete. * name-lookup.c (push_local_binding): Directly look for binding. (lookup_name_innermost_nonclass_level_1): Delete. (lookup_name_innermost_nonclass_level): Delete. testsuite/ * g++.dg/lookup/friend12.C: Adjust diagnostics. * g++.dg/lookup/friend19.C: New. * g++.dg/lookup/friend20.C: New. Index: cp/friend.c =================================================================== --- cp/friend.c (revision 248432) +++ cp/friend.c (working copy) @@ -608,25 +608,8 @@ do_friend (tree ctype, tree declarator, is instantiated. */ decl = push_template_decl_real (decl, /*is_friend=*/true); else if (current_function_decl) - { - /* This must be a local class. 11.5p11: - - If a friend declaration appears in a local class (9.8) and - the name specified is an unqualified name, a prior - declaration is looked up without considering scopes that - are outside the innermost enclosing non-class scope. For a - friend function declaration, if there is no prior - declaration, the program is ill-formed. */ - tree t = lookup_name_innermost_nonclass_level (DECL_NAME (decl)); - if (t) - decl = pushdecl (decl, /*is_friend=*/true); - else - { - error ("friend declaration %qD in local class without " - "prior declaration", decl); - return error_mark_node; - } - } + /* pushdecl will check there's a local decl already. */ + decl = pushdecl (decl, /*is_friend=*/true); else { /* We can't use pushdecl, as we might be in a template Index: cp/name-lookup.c =================================================================== --- cp/name-lookup.c (revision 248432) +++ cp/name-lookup.c (working copy) @@ -2103,7 +2103,13 @@ push_local_binding (tree id, tree decl, push_local_binding with a friend decl of a local class. */ b = innermost_nonclass_level (); - if (lookup_name_innermost_nonclass_level (id)) + cxx_binding *binding = NULL; + if (b->kind == sk_namespace) + binding = find_namespace_binding (current_namespace, id); + else + binding = find_local_binding (b, id); + + if (binding) { /* Supplement the existing binding. */ if (!supplement_binding (IDENTIFIER_BINDING (id), decl)) @@ -5430,37 +5436,6 @@ lookup_type_scope (tree name, tag_scope return ret; } - -/* Similar to `lookup_name' but look only in the innermost non-class - binding level. */ - -static tree -lookup_name_innermost_nonclass_level_1 (tree name) -{ - cp_binding_level *b = innermost_nonclass_level (); - cxx_binding *binding = NULL; - - if (b->kind == sk_namespace) - binding = find_namespace_binding (current_namespace, name); - else - binding = find_local_binding (b, name); - - return binding ? binding->value : NULL_TREE; -} - -/* Wrapper for lookup_name_innermost_nonclass_level_1. */ - -tree -lookup_name_innermost_nonclass_level (tree name) -{ - tree ret; - bool subtime = timevar_cond_start (TV_NAME_LOOKUP); - ret = lookup_name_innermost_nonclass_level_1 (name); - timevar_cond_stop (TV_NAME_LOOKUP, subtime); - return ret; -} - - /* Returns true iff DECL is a block-scope extern declaration of a function or variable. */ Index: cp/name-lookup.h =================================================================== --- cp/name-lookup.h (revision 248432) +++ cp/name-lookup.h (working copy) @@ -310,7 +310,6 @@ extern tree get_namespace_binding (tree extern void set_global_binding (tree id, tree val); extern tree lookup_qualified_name (tree, tree, int, bool, /*hidden*/bool = false); extern tree lookup_name_nonclass (tree); -extern tree lookup_name_innermost_nonclass_level (tree); extern bool is_local_extern (tree); extern tree lookup_function_nonclass (tree, vec *, bool); extern bool pushdecl_class_level (tree); Index: testsuite/g++.dg/lookup/friend12.C =================================================================== --- testsuite/g++.dg/lookup/friend12.C (revision 248422) +++ testsuite/g++.dg/lookup/friend12.C (working copy) @@ -2,9 +2,9 @@ void foo() { + extern void bar (int); // not the bar we are looking for struct A { - friend void bar(); // { dg-error "without prior declaration" } + friend void bar(); // { dg-error "without prior local declaration" } }; - bar(); // { dg-error "3:'bar' was not declared" } } Index: testsuite/g++.dg/lookup/friend19.C =================================================================== --- testsuite/g++.dg/lookup/friend19.C (revision 0) +++ testsuite/g++.dg/lookup/friend19.C (working copy) @@ -0,0 +1,29 @@ +// Make sure unhiding friends doesn't unhide similarly named friends + +struct X +{ + friend int foo (X); +}; + +struct Y +{ + friend int foo (Y); +}; + +void Baz () +{ + foo (X()); + foo (Y()); +} + +int foo (Y); +int foo (int); +// foo(X) still hidden + +void Bar () +{ + foo (X()); + foo (Y()); + ::foo (X()); // { dg-error "" } + ::foo (Y()); +} Index: testsuite/g++.dg/lookup/friend20.C =================================================================== --- testsuite/g++.dg/lookup/friend20.C (revision 0) +++ testsuite/g++.dg/lookup/friend20.C (working copy) @@ -0,0 +1,16 @@ +// PR c++/80830 + +template class a; +class b +{ + friend int operator>> (int, b); +}; +template int &operator>> (int &, a &); +template class a +{ + friend int &operator>><> (int &, a &); + a<> + d () + { + } +}; Index: testsuite/g++.old-deja/g++.jason/scoping12.C =================================================================== --- testsuite/g++.old-deja/g++.jason/scoping12.C (revision 248422) +++ testsuite/g++.old-deja/g++.jason/scoping12.C (working copy) @@ -2,9 +2,9 @@ void f () { struct A { - friend void g (); // { dg-error "without prior declaration" } + friend void g (); // { dg-error "without prior local declaration" } }; } void h () { - g (); // { dg-error "3:'g' was not declared" } no g in scope + g (); // { dg-error "3:'g' was not declared" } no g in scope }