From patchwork Wed Oct 14 17:03:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 1382267 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=iDPAqN7t; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CBJfs0MtPz9sTK for ; Thu, 15 Oct 2020 04:04:19 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E5D6D384A022; Wed, 14 Oct 2020 17:04:15 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-qv1-xf2f.google.com (mail-qv1-xf2f.google.com [IPv6:2607:f8b0:4864:20::f2f]) by sourceware.org (Postfix) with ESMTPS id 18A87385EC55 for ; Wed, 14 Oct 2020 17:04:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 18A87385EC55 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=nathanmsidwell@gmail.com Received: by mail-qv1-xf2f.google.com with SMTP id ev17so1817737qvb.3 for ; Wed, 14 Oct 2020 10:04:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:to:from:subject:message-id:date:user-agent:mime-version :content-language; bh=IVhr6e0w5nLTHhI9btmex58XNTdBKSd2RViEo9wR7Qc=; b=iDPAqN7tZIEzJru0lw3eJw756e0jM9DnzyVxHOmf9KI0R9VNb12KBiL00CIdACZ7nv u9OF/S3mFUhfEjZa9XxOmo5UFNL/CkTSPzkhnaHCTZNxz32svWYWDH86JPXa1u/T2Q4e /oTykAEXennmRLwpeO6AT0zvnriYjk1aF9SvA3Tnrb4pz1YCX1e00KNgHBrw1jKwu2gW aMgzCoQiqfloYZbxM/WpW8NZavOG5WNrRJIDMVCFo+ic4vYvPxOrX07ovZ8R9AUPatzB dFD5Xn1ZmwuJysRHXv1FyxYCKElP31HFgv9YTGQjVTuyEWKP4cU7ijwoIMIOji3KScg0 jrmA== 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=IVhr6e0w5nLTHhI9btmex58XNTdBKSd2RViEo9wR7Qc=; b=sLXuTbZ0dkStdPAC1bElVHJxT97Z/7E0y2TRIisaCsc8WclEqkV8cvDQy/CdyGQ8Wp g8v7dZFiZr6tyo24PqNn9Q9ssHoEw8q17ydJG1roXNVN7sGzMWiZ3JyMbzctyNqtAOaY 3QEeJabbjJo7youpWfa0LM+JyXlmBXztuwpRKmOOhvloXaNd8WKAXGgXY2XHHeBzT+oP 0TkBF4Hm0dJzj/nQLpzfzjQgNsH9fSCMmCHxUYceHoxYwhKjRQfQwQVaAAA06kcz3I89 7PRE4upPuuPElwnDxYRCX22TqHHjjnkRZ/HgQQKA3ZRTK5IAolFt/WTvZ5550SWwwIXE qXug== X-Gm-Message-State: AOAM533ySrT0uQEg6S0Hpra6tMHjxq0ZteRTz7c17HK+wvVAWei3nCIP WB3b/EDs4zouy6ofHyzLbwA= X-Google-Smtp-Source: ABdhPJxAwfvQ0qRFplu1rf8QH/FJmefj/anqP+LJNINgb9FZLRsbNUOeAxztrwgd9bTM+0RNu/8rqQ== X-Received: by 2002:a0c:e9ca:: with SMTP id q10mr199912qvo.19.1602695051334; Wed, 14 Oct 2020 10:04:11 -0700 (PDT) Received: from ?IPv6:2620:10d:c0a8:1102:4232:e32:2971:cf? ([2620:10d:c091:480::1:d2ab]) by smtp.googlemail.com with ESMTPSA id s90sm37606qtd.15.2020.10.14.10.03.55 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 14 Oct 2020 10:04:01 -0700 (PDT) To: GCC Patches From: Nathan Sidwell Subject: c++: DECL_FRIEND_P cleanup Message-ID: <4e110c55-e902-744d-7924-9f898394142b@acm.org> Date: Wed, 14 Oct 2020 13:03:55 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0 MIME-Version: 1.0 Content-Language: en-US X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" DECL_FRIEND_P's meaning has changed over time. It now (almost) means the the friend function decl has not been met via an explicit decl. This completes that transition, renaming it to DECL_UNIQUE_FRIEND_P, so one doesn't think it is the sole indicator of friendliness (plenty of friends do not have the flag set). This allows reduction in the complexity of managing the field -- all in duplicate_decls now. gcc/cp/ * cp-tree.h (struct lang_decl_fn): Adjust context comment. (DECL_FRIEND_P): Replace with ... (DECL_UNIQUE_FRIEND_P): ... this. Only for FUNCTION_DECLs. (DECL_FRIEND_CONTEXT): Adjust. * class.c (add_implicitly_declared_members): Detect friendly spaceship from context. * constraint.cc (remove_constraints): Use a checking assert. (maybe_substitute_reqs_for): Use DECL_UNIQUE_FRIEND_P. * decl.c (check_no_redeclaration_friend_default_args): DECL_UNIQUE_FRIEND_P is signficant, not hiddenness. (duplicate_decls): Adjust DECL_UNIQUE_FRIEND_P clearing. (redeclaration_error_message): Use DECL_UNIQUE_FRIEND_P. (start_preparsed_function): Correct in-class friend processing. Refactor some initializers. (grokmethod): Directly check friend decl-spec. * decl2.c (grokfield): Check DECL_UNIQUE_FRIEND_P. * friend.c (do_friend): Set DECL_UNIQUE_FRIEND_P first, remove extraneous conditions. Don't re set it afterwards. * name-lookup.c (lookup_elaborated_type_1): Simplify revealing code. (do_pushtag): Likewise. * pt.c (optimize_specialization_lookup_p): Check DECL_UNIQUE_FRIEND_P. (push_template_decl): Likewise. Drop unneeded friend setting. (type_dependent_expression_p): Check DECL_UNIQUE_FRIEND_P. libcc1/ * libcp1plugin.cc (plugin_add_friend): Set DECL_UNIQUE_FRIEND_P. pushing to trunk nathan diff --git i/gcc/cp/class.c w/gcc/cp/class.c index 01780fe8291..26f996b7f4b 100644 --- i/gcc/cp/class.c +++ w/gcc/cp/class.c @@ -3283,7 +3283,8 @@ add_implicitly_declared_members (tree t, tree* access_decls, { tree eq = implicitly_declare_fn (sfk_comparison, t, false, space, NULL_TREE); - if (DECL_FRIEND_P (space)) + bool is_friend = DECL_CONTEXT (space) != t; + if (is_friend) do_friend (NULL_TREE, DECL_NAME (eq), eq, NULL_TREE, NO_SPECIAL, true); else @@ -3292,7 +3293,7 @@ add_implicitly_declared_members (tree t, tree* access_decls, DECL_CHAIN (eq) = TYPE_FIELDS (t); TYPE_FIELDS (t) = eq; } - maybe_add_class_template_decl_list (t, eq, DECL_FRIEND_P (space)); + maybe_add_class_template_decl_list (t, eq, is_friend); } while (*access_decls) diff --git i/gcc/cp/constraint.cc w/gcc/cp/constraint.cc index 050b55ce092..f4f5174eff3 100644 --- i/gcc/cp/constraint.cc +++ w/gcc/cp/constraint.cc @@ -1201,7 +1201,7 @@ set_constraints (tree t, tree ci) void remove_constraints (tree t) { - gcc_assert (DECL_P (t)); + gcc_checking_assert (DECL_P (t)); if (TREE_CODE (t) == TEMPLATE_DECL) t = DECL_TEMPLATE_RESULT (t); @@ -1217,11 +1217,16 @@ maybe_substitute_reqs_for (tree reqs, const_tree decl_) { if (reqs == NULL_TREE) return NULL_TREE; + tree decl = CONST_CAST_TREE (decl_); tree result = STRIP_TEMPLATE (decl); - if (DECL_FRIEND_P (result)) + + if (DECL_UNIQUE_FRIEND_P (result)) { - tree tmpl = decl == result ? DECL_TI_TEMPLATE (result) : decl; + tree tmpl = decl; + if (TREE_CODE (decl) != TEMPLATE_DECL) + tmpl = DECL_TI_TEMPLATE (result); + tree gargs = generic_targs_for (tmpl); processing_template_decl_sentinel s; if (uses_template_parms (gargs)) diff --git i/gcc/cp/cp-tree.h w/gcc/cp/cp-tree.h index 467256117ec..5c06ac3789e 100644 --- i/gcc/cp/cp-tree.h +++ w/gcc/cp/cp-tree.h @@ -2736,12 +2736,14 @@ struct GTY(()) lang_decl_fn { thunked to function decl. */ tree befriending_classes; - /* For a non-virtual FUNCTION_DECL, this is - DECL_FRIEND_CONTEXT. For a virtual FUNCTION_DECL for which + /* For a virtual FUNCTION_DECL for which DECL_THIS_THUNK_P does not hold, this is DECL_THUNKS. Both this pointer and result pointer adjusting thunks are chained here. This pointer thunks to return pointer thunks - will be chained on the return pointer thunk. */ + will be chained on the return pointer thunk. + For a DECL_CONSTUCTOR_P FUNCTION_DECL, this is the base from + whence we inherit. Otherwise, it is the class in which a + (namespace-scope) friend is defined (if any). */ tree context; union lang_decl_u5 @@ -3088,10 +3090,14 @@ struct GTY(()) lang_decl { (DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL)) \ ->u.base.odr_used) -/* Nonzero for DECL means that this decl is just a friend declaration, - and should not be added to the list of members for this class. */ -#define DECL_FRIEND_P(NODE) \ - (DECL_LANG_SPECIFIC (TYPE_FUNCTION_OR_TEMPLATE_DECL_CHECK (NODE)) \ +/* Nonzero for FUNCTION_DECL means that this is a friend that is + either not pushed into a namespace/looked up in a class (because it + is a dependent type, in an uninstantiated template), or it has + /only/ been subject to hidden friend injection from one or more + befriending classes. Once another decl matches, the flag is + cleared. There are requirements on its default parms. */ +#define DECL_UNIQUE_FRIEND_P(NODE) \ + (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE)) \ ->u.base.friend_or_tls) /* Nonzero if the thread-local variable was declared with __thread as @@ -3290,8 +3296,8 @@ struct GTY(()) lang_decl { the DECL_FRIEND_CONTEXT for `f' will be `S'. */ #define DECL_FRIEND_CONTEXT(NODE) \ - ((DECL_DECLARES_FUNCTION_P (NODE) \ - && DECL_FRIEND_P (NODE) && !DECL_FUNCTION_MEMBER_P (NODE)) \ + ((DECL_DECLARES_FUNCTION_P (NODE) && !DECL_VIRTUAL_P (NODE) \ + && !DECL_CONSTRUCTOR_P (NODE)) \ ? LANG_DECL_FN_CHECK (NODE)->context \ : NULL_TREE) diff --git i/gcc/cp/decl.c w/gcc/cp/decl.c index 0fe74b2e851..2f1a2f0c554 100644 --- i/gcc/cp/decl.c +++ w/gcc/cp/decl.c @@ -1340,18 +1340,17 @@ check_redeclaration_no_default_args (tree decl) the function or function template in the translation unit." */ static void -check_no_redeclaration_friend_default_args (tree olddecl, tree newdecl, - bool olddecl_hidden_p) +check_no_redeclaration_friend_default_args (tree olddecl, tree newdecl) { - if (!olddecl_hidden_p && !DECL_FRIEND_P (newdecl)) + if (!DECL_UNIQUE_FRIEND_P (olddecl) && !DECL_UNIQUE_FRIEND_P (newdecl)) return; for (tree t1 = FUNCTION_FIRST_USER_PARMTYPE (olddecl), t2 = FUNCTION_FIRST_USER_PARMTYPE (newdecl); t1 && t1 != void_list_node; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2)) - if ((olddecl_hidden_p && TREE_PURPOSE (t1)) - || (DECL_FRIEND_P (newdecl) && TREE_PURPOSE (t2))) + if ((DECL_UNIQUE_FRIEND_P (olddecl) && TREE_PURPOSE (t1)) + || (DECL_UNIQUE_FRIEND_P (newdecl) && TREE_PURPOSE (t2))) { auto_diagnostic_group d; if (permerror (DECL_SOURCE_LOCATION (newdecl), @@ -1444,8 +1443,7 @@ tree duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) { unsigned olddecl_uid = DECL_UID (olddecl); - int olddecl_friend = 0, types_match = 0; - int olddecl_hidden_friend = 0; + int types_match = 0; int new_defines_function = 0; tree new_template_info; location_t olddecl_loc = DECL_SOURCE_LOCATION (olddecl); @@ -1987,8 +1985,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) argument expression, that declaration... shall be the only declaration of the function or function template in the translation unit." */ - check_no_redeclaration_friend_default_args - (olddecl, newdecl, was_hidden); + check_no_redeclaration_friend_default_args (olddecl, newdecl); } } } @@ -2135,12 +2132,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) else DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl); - if (DECL_DECLARES_FUNCTION_P (olddecl)) - { - olddecl_friend = DECL_FRIEND_P (STRIP_TEMPLATE (olddecl)); - olddecl_hidden_friend = olddecl_friend && was_hidden; - } - if (TREE_CODE (newdecl) == TEMPLATE_DECL) { tree old_result = DECL_TEMPLATE_RESULT (olddecl); @@ -2167,8 +2158,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) declaration of the function or function template in the translation unit." */ check_no_redeclaration_friend_default_args - (old_result, new_result, olddecl_hidden_friend); + (old_result, new_result); } + if (!DECL_UNIQUE_FRIEND_P (old_result)) + DECL_UNIQUE_FRIEND_P (new_result) = false; check_default_args (newdecl); @@ -2366,6 +2359,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) && !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl)) DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl) = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (olddecl); + + if (!DECL_UNIQUE_FRIEND_P (olddecl)) + DECL_UNIQUE_FRIEND_P (newdecl) = false; } else { @@ -2885,8 +2881,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) } DECL_UID (olddecl) = olddecl_uid; - if (olddecl_friend) - DECL_FRIEND_P (olddecl) = true; /* NEWDECL contains the merged attribute lists. Update OLDDECL to be the same. */ @@ -3062,7 +3056,7 @@ redeclaration_error_message (tree newdecl, tree olddecl) definition and shall be the only declaration of the function template in the translation unit. */ if ((cxx_dialect != cxx98) - && TREE_CODE (ot) == FUNCTION_DECL && DECL_FRIEND_P (ot) + && TREE_CODE (ot) == FUNCTION_DECL && DECL_UNIQUE_FRIEND_P (ot) && !check_default_tmpl_args (nt, DECL_TEMPLATE_PARMS (newdecl), /*is_primary=*/true, /*is_partial=*/false, @@ -3073,7 +3067,8 @@ redeclaration_error_message (tree newdecl, tree olddecl) return NULL; } else if (VAR_P (newdecl) - && CP_DECL_THREAD_LOCAL_P (newdecl) != CP_DECL_THREAD_LOCAL_P (olddecl) + && (CP_DECL_THREAD_LOCAL_P (newdecl) + != CP_DECL_THREAD_LOCAL_P (olddecl)) && (! DECL_LANG_SPECIFIC (olddecl) || ! CP_DECL_THREADPRIVATE_P (olddecl) || CP_DECL_THREAD_LOCAL_P (newdecl))) @@ -16110,36 +16105,21 @@ bool start_preparsed_function (tree decl1, tree attrs, int flags) { tree ctype = NULL_TREE; - tree fntype; - tree restype; - int doing_friend = 0; - cp_binding_level *bl; - tree current_function_parms; - struct c_fileinfo *finfo - = get_fileinfo (LOCATION_FILE (DECL_SOURCE_LOCATION (decl1))); - bool honor_interface; + bool doing_friend = false; /* Sanity check. */ gcc_assert (VOID_TYPE_P (TREE_VALUE (void_list_node))); gcc_assert (TREE_CHAIN (void_list_node) == NULL_TREE); - fntype = TREE_TYPE (decl1); + tree fntype = TREE_TYPE (decl1); if (TREE_CODE (fntype) == METHOD_TYPE) ctype = TYPE_METHOD_BASETYPE (fntype); - - /* ISO C++ 11.4/5. A friend function defined in a class is in - the (lexical) scope of the class in which it is defined. */ - if (!ctype && DECL_FRIEND_P (decl1)) + else { ctype = DECL_FRIEND_CONTEXT (decl1); - /* CTYPE could be null here if we're dealing with a template; - for example, `inline friend float foo()' inside a template - will have no CTYPE set. */ - if (ctype && TREE_CODE (ctype) != RECORD_TYPE) - ctype = NULL_TREE; - else - doing_friend = 1; + if (ctype) + doing_friend = true; } if (DECL_DECLARED_INLINE_P (decl1) @@ -16206,7 +16186,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) by push_nested_class.) */ if (processing_template_decl) { - tree newdecl1 = push_template_decl (decl1, DECL_FRIEND_P (decl1)); + tree newdecl1 = push_template_decl (decl1, doing_friend); if (newdecl1 == error_mark_node) { if (ctype || DECL_STATIC_FUNCTION_P (decl1)) @@ -16222,7 +16202,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) check_function_type (decl1, DECL_ARGUMENTS (decl1)); /* Build the return declaration for the function. */ - restype = TREE_TYPE (fntype); + tree restype = TREE_TYPE (fntype); if (DECL_RESULT (decl1) == NULL_TREE) { @@ -16312,7 +16292,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) /* Save the parm names or decls from this function's declarator where store_parm_decls will find them. */ - current_function_parms = DECL_ARGUMENTS (decl1); + tree current_function_parms = DECL_ARGUMENTS (decl1); /* Let the user know we're compiling this function. */ announce_function (decl1); @@ -16329,7 +16309,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) even when processing a template; this is how we get CFUN set up, and our per-function variables initialized. FIXME factor out the non-RTL stuff. */ - bl = current_binding_level; + cp_binding_level *bl = current_binding_level; allocate_struct_function (decl1, processing_template_decl); /* Initialize the language data structures. Whenever we start @@ -16384,14 +16364,16 @@ start_preparsed_function (tree decl1, tree attrs, int flags) } } - honor_interface = (!DECL_TEMPLATE_INSTANTIATION (decl1) - /* Implicitly-defined methods (like the - destructor for a class in which no destructor - is explicitly declared) must not be defined - until their definition is needed. So, we - ignore interface specifications for - compiler-generated functions. */ - && !DECL_ARTIFICIAL (decl1)); + bool honor_interface = (!DECL_TEMPLATE_INSTANTIATION (decl1) + /* Implicitly-defined methods (like the + destructor for a class in which no destructor + is explicitly declared) must not be defined + until their definition is needed. So, we + ignore interface specifications for + compiler-generated functions. */ + && !DECL_ARTIFICIAL (decl1)); + struct c_fileinfo *finfo + = get_fileinfo (LOCATION_FILE (DECL_SOURCE_LOCATION (decl1))); if (processing_template_decl) /* Don't mess with interface flags. */; @@ -17311,18 +17293,17 @@ grokmethod (cp_decl_specifier_seq *declspecs, /* We process method specializations in finish_struct_1. */ if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl)) { - fndecl = push_template_decl (fndecl, DECL_FRIEND_P (fndecl)); + /* Avoid calling decl_spec_seq... until we have to. */ + bool friendp = decl_spec_seq_has_spec_p (declspecs, ds_friend); + fndecl = push_template_decl (fndecl, friendp); if (fndecl == error_mark_node) return fndecl; } - if (! DECL_FRIEND_P (fndecl)) + if (DECL_CHAIN (fndecl) && !decl_spec_seq_has_spec_p (declspecs, ds_friend)) { - if (DECL_CHAIN (fndecl)) - { - fndecl = copy_node (fndecl); - TREE_CHAIN (fndecl) = NULL_TREE; - } + fndecl = copy_node (fndecl); + TREE_CHAIN (fndecl) = NULL_TREE; } cp_finish_decl (fndecl, NULL_TREE, false, NULL_TREE, 0); diff --git i/gcc/cp/decl2.c w/gcc/cp/decl2.c index db3035dfba5..2f0d6370146 100644 --- i/gcc/cp/decl2.c +++ w/gcc/cp/decl2.c @@ -1021,7 +1021,7 @@ grokfield (const cp_declarator *declarator, asmspec_tree, flags); /* Pass friends back this way. */ - if (DECL_FRIEND_P (value)) + if (DECL_UNIQUE_FRIEND_P (value)) return void_type_node; DECL_IN_AGGR_P (value) = 1; diff --git i/gcc/cp/friend.c w/gcc/cp/friend.c index 6a783a9d88a..56fa96073d3 100644 --- i/gcc/cp/friend.c +++ w/gcc/cp/friend.c @@ -481,8 +481,8 @@ do_friend (tree ctype, tree declarator, tree decl, gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); gcc_assert (!ctype || MAYBE_CLASS_TYPE_P (ctype)); - /* Every decl that gets here is a friend of something. */ - DECL_FRIEND_P (decl) = 1; + /* Friend functions are unique, until proved otherwise. */ + DECL_UNIQUE_FRIEND_P (decl) = 1; if (DECL_OVERRIDE_P (decl) || DECL_FINAL_P (decl)) error ("friend declaration %qD may not have virt-specifiers", @@ -581,17 +581,11 @@ do_friend (tree ctype, tree declarator, tree decl, error ("member %qD declared as friend before type %qT defined", decl, ctype); } - /* A global friend. - @@ or possibly a friend from a base class ?!? */ - else if (TREE_CODE (decl) == FUNCTION_DECL) + else { + /* Namespace-scope friend function. */ int is_friend_template = PROCESSING_REAL_TEMPLATE_DECL_P (); - /* Friends must all go through the overload machinery, - even though they may not technically be overloaded. - - Note that because classes all wind up being top-level - in their scope, their friend wind up in top-level scope as well. */ if (funcdef_flag) SET_DECL_FRIEND_CONTEXT (decl, current_class_type); @@ -653,7 +647,6 @@ do_friend (tree ctype, tree declarator, tree decl, add_friend (current_class_type, is_friend_template ? DECL_TI_TEMPLATE (decl) : decl, /*complain=*/true); - DECL_FRIEND_P (decl) = 1; } return decl; diff --git i/gcc/cp/name-lookup.c w/gcc/cp/name-lookup.c index 5dcaab4d1df..e951fb7885b 100644 --- i/gcc/cp/name-lookup.c +++ w/gcc/cp/name-lookup.c @@ -6719,8 +6719,6 @@ lookup_elaborated_type_1 (tree name, TAG_how how) typedef struct C {} C; correctly. */ - tree found = NULL_TREE; - bool reveal = false; if (tree type = iter->type) { if (qualify_lookup (type, LOOK_want::TYPE) @@ -6728,9 +6726,11 @@ lookup_elaborated_type_1 (tree name, TAG_how how) || LOCAL_BINDING_P (iter) || DECL_CONTEXT (type) == iter->scope->this_entity)) { - found = type; if (how != TAG_how::HIDDEN_FRIEND) - reveal = HIDDEN_TYPE_BINDING_P (iter); + /* It is no longer a hidden binding. */ + HIDDEN_TYPE_BINDING_P (iter) = false; + + return type; } } else @@ -6739,32 +6739,12 @@ lookup_elaborated_type_1 (tree name, TAG_how how) && (how != TAG_how::CURRENT_ONLY || !INHERITED_VALUE_BINDING_P (iter))) { - found = iter->value; - if (how != TAG_how::HIDDEN_FRIEND) - reveal = !iter->type && HIDDEN_TYPE_BINDING_P (iter); - } - } - - if (found) - { - if (reveal) - { - /* It is no longer a hidden binding. */ - HIDDEN_TYPE_BINDING_P (iter) = false; - - /* Unanticipate the decl itself. */ - DECL_FRIEND_P (found) = false; + if (how != TAG_how::HIDDEN_FRIEND && !iter->type) + /* It is no longer a hidden binding. */ + HIDDEN_TYPE_BINDING_P (iter) = false; - gcc_checking_assert (TREE_CODE (found) != TEMPLATE_DECL); - - if (tree ti = TYPE_TEMPLATE_INFO (TREE_TYPE (found))) - { - tree tmpl = TI_TEMPLATE (ti); - DECL_FRIEND_P (tmpl) = false; - } + return iter->value; } - - return found; } } @@ -6781,61 +6761,31 @@ lookup_elaborated_type_1 (tree name, TAG_how how) if (tree *slot = find_namespace_slot (ns, name)) { /* If this is the kind of thing we're looking for, we're done. */ - tree found = NULL_TREE; - bool reveal = false; - if (tree type = MAYBE_STAT_TYPE (*slot)) { - found = type; if (how != TAG_how::HIDDEN_FRIEND) - { - reveal = STAT_TYPE_HIDDEN_P (*slot); - STAT_TYPE_HIDDEN_P (*slot) = false; - } + /* No longer hidden. */ + STAT_TYPE_HIDDEN_P (*slot) = false; + + return type; } else if (tree decl = MAYBE_STAT_DECL (*slot)) { if (qualify_lookup (decl, LOOK_want::TYPE)) { - found = decl; - - if (how != TAG_how::HIDDEN_FRIEND && STAT_HACK_P (*slot)) + if (how != TAG_how::HIDDEN_FRIEND && STAT_HACK_P (*slot) + && STAT_DECL_HIDDEN_P (*slot)) { - reveal = STAT_DECL_HIDDEN_P (*slot); - if (reveal) - { - if (STAT_TYPE (*slot)) - STAT_DECL_HIDDEN_P (*slot) = false; - else - /* There is no type, just remove the stat - hack. */ - *slot = decl; - } + if (STAT_TYPE (*slot)) + STAT_DECL_HIDDEN_P (*slot) = false; + else + /* There is no type, just remove the stat + hack. */ + *slot = decl; } - } - } - if (found) - { - if (reveal) - { - /* Reveal the previously hidden thing. */ - DECL_FRIEND_P (found) = false; - - if (TREE_CODE (found) == TEMPLATE_DECL) - { - tree res = DECL_TEMPLATE_RESULT (found); - if (DECL_LANG_SPECIFIC (res)) - DECL_FRIEND_P (res) = false; - } - else if (tree ti = TYPE_TEMPLATE_INFO (TREE_TYPE (found))) - { - tree tmpl = TI_TEMPLATE (ti); - DECL_FRIEND_P (tmpl) = false; - } + return decl; } - - return found; } } @@ -7017,18 +6967,8 @@ do_pushtag (tree name, tree type, TAG_how how) tdef = create_implicit_typedef (name, type); DECL_CONTEXT (tdef) = FROB_CONTEXT (context); - bool is_friend = how == TAG_how::HIDDEN_FRIEND; - if (is_friend) - { - // FIXME: can go away - /* This is a friend. Make this TYPE_DECL node hidden from - ordinary name lookup. Its corresponding TEMPLATE_DECL - will be marked in push_template_decl. */ - retrofit_lang_decl (tdef); - DECL_FRIEND_P (tdef) = 1; - } - - decl = maybe_process_template_type_declaration (type, is_friend, b); + decl = maybe_process_template_type_declaration + (type, how == TAG_how::HIDDEN_FRIEND, b); if (decl == error_mark_node) return decl; diff --git i/gcc/cp/pt.c w/gcc/cp/pt.c index 555dc47b464..503c0e722fa 100644 --- i/gcc/cp/pt.c +++ w/gcc/cp/pt.c @@ -1181,7 +1181,7 @@ optimize_specialization_lookup_p (tree tmpl) not have template information. The optimized lookup relies on having ARGS be the template arguments for both the class and the function template. */ - && !DECL_FRIEND_P (DECL_TEMPLATE_RESULT (tmpl))); + && !DECL_UNIQUE_FRIEND_P (DECL_TEMPLATE_RESULT (tmpl))); } /* Make sure ARGS doesn't use any inappropriate typedefs; we should have @@ -5701,7 +5701,7 @@ push_template_decl (tree decl, bool is_friend) /* No surprising friend functions. */ gcc_checking_assert (is_friend || !(TREE_CODE (decl) == FUNCTION_DECL - && DECL_FRIEND_P (decl))); + && DECL_UNIQUE_FRIEND_P (decl))); if (is_friend) /* For a friend, we want the context of the friend, not @@ -6022,10 +6022,6 @@ push_template_decl (tree decl, bool is_friend) if (!ctx && !(is_friend && template_class_depth (current_class_type) > 0)) { - /* Hide template friend classes that haven't been declared yet. */ - if (is_friend && TREE_CODE (decl) == TYPE_DECL) - DECL_FRIEND_P (tmpl) = 1; - tmpl = pushdecl_namespace_level (tmpl, /*hiding=*/is_friend); if (tmpl == error_mark_node) return error_mark_node; @@ -13960,7 +13956,7 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain, if (!lambda_fntype) set_constraints (r, ci); - if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t)) + if (DECL_FRIEND_CONTEXT (t)) SET_DECL_FRIEND_CONTEXT (r, tsubst (DECL_FRIEND_CONTEXT (t), args, complain, in_decl)); @@ -27049,7 +27045,7 @@ type_dependent_expression_p (tree expression) && !(DECL_CLASS_SCOPE_P (expression) && dependent_type_p (DECL_CONTEXT (expression))) && !(DECL_LANG_SPECIFIC (expression) - && DECL_FRIEND_P (expression) + && DECL_UNIQUE_FRIEND_P (expression) && (!DECL_FRIEND_CONTEXT (expression) || dependent_type_p (DECL_FRIEND_CONTEXT (expression)))) && !DECL_LOCAL_DECL_P (expression)) diff --git i/libcc1/libcp1plugin.cc w/libcc1/libcp1plugin.cc index e7ab325d7df..d758df8b556 100644 --- i/libcc1/libcp1plugin.cc +++ w/libcc1/libcp1plugin.cc @@ -1649,7 +1649,7 @@ plugin_add_friend (cc1_plugin::connection * /* self */, make_friend_class (type, TREE_TYPE (decl), true); else { - DECL_FRIEND_P (decl) = true; + DECL_UNIQUE_FRIEND_P (decl) = true; add_friend (type, decl, true); }