From patchwork Thu Nov 30 10:19:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Marc_Poulhi=C3=A8s?= X-Patchwork-Id: 171812 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:bcd1:0:b0:403:3b70:6f57 with SMTP id r17csp281953vqy; Thu, 30 Nov 2023 02:20:51 -0800 (PST) X-Google-Smtp-Source: AGHT+IGCdshaVnVGZsmzy6b3539cGmibYa+hoM4zPjTiEnvl7/FCeICWTJ4uQkKobgC7Z5zbaXvX X-Received: by 2002:a05:620a:8390:b0:77d:742b:72e8 with SMTP id pb16-20020a05620a839000b0077d742b72e8mr31943325qkn.36.1701339650907; Thu, 30 Nov 2023 02:20:50 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1701339650; cv=pass; d=google.com; s=arc-20160816; b=X/bdwKdb6l/HUWajn+BPc/F3RYfI0xICinsh58p5jXK0nuoZe2/i7nVyuKZv2VW8zP nNU1tD8e56b9D3gGIvNdI84+Bj/ZOlQnLWWNPMeceqfVGHq6Aa/ibJy0jymUSMCgJaQ3 wS4+ybG0lZedQKdo4cPlMoh7G1w4+AilXJT2GgPN2QiQvTCupxLgRHdGjaBDQu2AQt2T HAR22jTlvkXlVW7b0svHBNgFEUDH0W4VTvC22f1mBUNSrfqnWIzkZWnQ6CGC1WwagLiw A/moGWrQSRURCFBDh5SDJH6P8g8O5rMSvWMl0EGAU2lP3csuKw3LqIEqT0FdPS1ymUQ2 tBtA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:message-id:date:subject:cc:to:from:dkim-signature :arc-filter:dmarc-filter:delivered-to; bh=th9zKvZMNt/3T0kfLmLhNSTWjDH+sJRaVYfvWm/TVPI=; fh=VfpjIVwbQyKCLGOH4P8eKpbC0rx5s9zOz2f2H065zJg=; b=VSj0vDNf+K9VDNzGcjBnHoJTK25K64enulodDQ5uNr/ECmKdetL+5dQtZy2MBeyfwn lUsahLe+TZE0gnuaXV5KuNsd/BpPgXKPKPfmJlkAH6A93hAcc+QDsspJH/n9YQLSCxCP uSpZhkc0Ll48C4yy+fAAtNA3cf6r/GFhA0j+WahScq/o9uNT9GybEkL4GrReJdz4X5/v +0WdKRDfTvdswpdijr2HpKMnh62eWxumjM0BtnBGL7VwdD8VIvS7cnKIB8PQpI9ykllQ 3XaUqlIMV/uBS6etmivsSfbHLdOr5aNM9PhlCyhf7YqIR80vVj7Uz6NprL+Kjw+IQjJ4 bZeA== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@adacore.com header.s=google header.b=BV5zoran; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=adacore.com Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id f14-20020a05620a408e00b0077d883cb7b1si767524qko.238.2023.11.30.02.20.50 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Nov 2023 02:20:50 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@adacore.com header.s=google header.b=BV5zoran; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=adacore.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 0F72E3870C37 for ; Thu, 30 Nov 2023 10:20:32 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-lj1-x231.google.com (mail-lj1-x231.google.com [IPv6:2a00:1450:4864:20::231]) by sourceware.org (Postfix) with ESMTPS id 3F8033861842 for ; Thu, 30 Nov 2023 10:19:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 3F8033861842 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=adacore.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=adacore.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 3F8033861842 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::231 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701339553; cv=none; b=G1GvtkvJyjduohhaxlOdILwyINLUQhPu6TTQk6AIQi+d2KiPiGDwMyd4uaqP0lbwiU6oe8xxPWic96Pad5TCpfFmF3mqF8mmZzv+KUSq2nhUATGZ0sbTfdVj4G1hh8jBxCK4LEIDBivlM+VWcbUvThRlAXCHPCccQ19pJa7Ss90= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701339553; c=relaxed/simple; bh=kt3xD9cGrfqP3LEaT88yNZLovoFMbNWg+TvQEFxBv6E=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=EWsoNUSAyE7xn4A9tMvzS++5Ln3ifl5I5T3jklahj7ZmAnlMyk8LROen9XW5d0+A34WK47/V5MX+j2pwVP1WRVbeHjgi+CvzO8lF+ZlFUXlhHI+AYKSjC6KYBnP6L2aLUVVnMuPAOKGOufLO26BC4MgN01oz+pbzUf6Qnqd+A0E= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-lj1-x231.google.com with SMTP id 38308e7fff4ca-2c9c1e39defso9499801fa.1 for ; Thu, 30 Nov 2023 02:19:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=adacore.com; s=google; t=1701339549; x=1701944349; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=th9zKvZMNt/3T0kfLmLhNSTWjDH+sJRaVYfvWm/TVPI=; b=BV5zoranjPWDX2LBl5N0nlR3i0zt0X2kotfrHf8CD64iagPH1qEPj39L6/iYUNEtaS 22P/NhwsJ7cXkctqV3ZyZWuIPK83A/JnskOPc4x3UAOr273mf1U5aDtC78xb6nv1wpqm mOXKhZU20M7LONyrlbeMbSDAJKygPwuXglXhSSxs7atx0NI+BqRTYv+SXtc1PmFspPVB 7wnuD2EA3peL7HRDqNG6Xeq8KVW/8/bm5ZTYF2bPGBe6S4hs+wHuJYtJ/iaFKkpW9RO1 6mu/yEIRGDlBwCUWNDeLf093hXvbQTkSCz9rWLFdSSBqR0hCveca68g8yUNvvhU55j3P k7Ww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701339549; x=1701944349; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=th9zKvZMNt/3T0kfLmLhNSTWjDH+sJRaVYfvWm/TVPI=; b=vrGMS9JSKjcy0DOGjhVR+10CwnIrF+L5FgcQjYeH8BHs77RuHs8JYo15r3xtssKgFI Z/o4BopkaUiaTX1XFurCgvnsjRW7S5jwNRSLTHIBgTs03Ozz5zhCLHciJSaqeetaZxYJ zrY/p0vrfHgcfiqU3YEGtLhx2aH6dtsZ4GWOHI8+Gg4fR013jiW81/W8kcJUKU5hTVI3 ZzS18tr7RUKJ1erfqYON9qhQpmDQiFkegXJP3dRrkc9I6OJH/r87RI1G3GD/hFgTA/CR uwGt8qv27zEWhx2W6tPAWVjjA0F1O+G2ygpg5kIVzDMRj4qyYcTIaArfb6esWlbWLzjF IrVg== X-Gm-Message-State: AOJu0YydLRloLacrcEibSriU3xbOMokSBFeTDmbo8U88LtWzdssN9sWu pvD7Ou2WGiDSkevJnbolOSXYMInBVzmDt9vRMPMjlg== X-Received: by 2002:a2e:a0c2:0:b0:2c9:cadb:f9c5 with SMTP id f2-20020a2ea0c2000000b002c9cadbf9c5mr847272ljm.0.1701339548559; Thu, 30 Nov 2023 02:19:08 -0800 (PST) Received: from poulhies-Precision-5550.telnowedge.local (lmontsouris-659-1-24-67.w81-250.abo.wanadoo.fr. [81.250.175.67]) by smtp.gmail.com with ESMTPSA id je16-20020a05600c1f9000b0040b56f2cce3sm2250647wmb.23.2023.11.30.02.19.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Nov 2023 02:19:08 -0800 (PST) From: =?utf-8?q?Marc_Poulhi=C3=A8s?= To: gcc-patches@gcc.gnu.org Cc: Steve Baird Subject: [COMMITTED] ada: Name resolution in expanded instances Date: Thu, 30 Nov 2023 11:19:07 +0100 Message-ID: <20231130101907.3094132-1-poulhies@adacore.com> X-Mailer: git-send-email 2.42.0 MIME-Version: 1.0 X-Spam-Status: No, score=-13.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1783983925958008982 X-GMAIL-MSGID: 1783983925958008982 From: Steve Baird In building the tree for an instance of a generic, expansion sets entity fields on names that refer to things declared outside of the instance, but leaves the entity field unset on names that should end up referring to things declared within the instance. These will instead be set by analysis - the idea is that if a name resolves a certain way in the generic, then we should get corresponding results if we resolve the corresponding name in an instance. For this to work, we have to prevent unrelated declarations that happen to be visible at the point of the instantiation from participating in resolution. Add code to filter out such unwanted name resolution candidates. gcc/ada/ * sem_ch8.adb (Find_Direct_Name): In the case of a resolving a name that occurs within an instantiation, add code to detect and filter out unwanted candidate resolutions. The filtering is performed via a call to Remove_Interp. Tested on x86_64-pc-linux-gnu, committed on master. --- gcc/ada/sem_ch8.adb | 338 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 338 insertions(+) diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb index 88be8aeaff2..d231910cb95 100644 --- a/gcc/ada/sem_ch8.adb +++ b/gcc/ada/sem_ch8.adb @@ -6473,6 +6473,344 @@ package body Sem_Ch8 is then Collect_Interps (N); + -- Background: for an instance of a generic, expansion sets + -- entity fields on names that refer to things declared + -- outside of the instance, but leaves the entity field + -- unset on names that should end up referring to things + -- declared within the instance. These will instead be set by + -- analysis - the idea is that if a name resolves a certain + -- way in the generic, then we should get corresponding results + -- if we resolve the corresponding name in an instance. For this + -- to work, we have to prevent unrelated declarations that + -- happen to be visible at the point of the instantiation from + -- participating in resolution and causing problems (typically + -- ambiguities, but incorrect resolutions are also probably + -- possible). So here we filter out such unwanted interpretations. + -- + -- Note that there are other problems with this approach to + -- implementing generic instances that are not addressed here. + -- Inside a generic, we might have no trouble resolving a call + -- where the two candidates are a function that returns a + -- formal type and a function that returns Standard.Integer. + -- If we instantiate that generic and the corresponding actual + -- type is Standard.Integer, then we may incorrectly reject the + -- corresponding call in the instance as ambiguous (or worse, + -- we may quietly choose the wrong resolution). + -- + -- Another such problem can occur with a type derived from a + -- formal derived type. In an instance, such a type may have + -- inherited subprograms that are not present in the generic. + -- These can then interfere with name resolution (e.g., if + -- some declaration is visible via a use-clause in the generic + -- and some name in the generic refers to it, then the + -- corresponding declaration in an instance may be hidden by + -- a directly visible inherited subprogram and the corresponding + -- name in the instance may then incorrectly refer to the + -- inherited subprogram). + + if In_Instance then + declare + function Is_Actual_Subp_Of_Inst + (E : Entity_Id; Inst : Entity_Id) return Boolean; + -- Return True if E is an actual parameter + -- corresponding to a formal subprogram of the + -- instantiation Inst. + + function Is_Extraneously_Visible + (E : Entity_Id; Inst : Entity_Id) return Boolean; + -- Return True if E is an interpretation that should + -- be filtered out. That is, if E is an "unwanted" + -- resolution candidate as described in the + -- preceding "Background:" commment. + + function Is_Generic_Actual_Subp_Name + (N : Node_Id) return Boolean; + -- Return True if N is the name of a subprogram + -- renaming generated for a generic actual. + + ---------------------------- + -- Is_Actual_Subp_Of_Inst -- + ---------------------------- + + function Is_Actual_Subp_Of_Inst + (E : Entity_Id; Inst : Entity_Id) return Boolean + is + Decl : Node_Id; + Generic_From_E, Generic_From_Inst : Entity_Id; + begin + -- ??? + -- Why is Is_Generic_Actual_Subprogram undefined + -- in the E_Operator case? + + if Ekind (E) not in E_Function | E_Procedure + or else not Is_Generic_Actual_Subprogram (E) + then + return False; + end if; + + Decl := Enclosing_Declaration (E); + + -- Look for the suprogram renaming declaration built + -- for a generic actual subprogram. Unclear why + -- Original_Node call is needed, but sometimes it is. + + if Decl not in N_Subprogram_Renaming_Declaration_Id then + Decl := Original_Node (Decl); + end if; + + if Decl in N_Subprogram_Renaming_Declaration_Id then + Generic_From_E := + Scope (Corresponding_Formal_Spec (Decl)); + else + -- ??? In the case of a generic formal subprogram + -- which has a pre/post condition, it is unclear how + -- to find the Corresponding_Formal_Spec-bearing node. + + Generic_From_E := Empty; + end if; + + declare + Inst_Parent : Node_Id := Parent (Inst); + begin + if Nkind (Inst_Parent) = N_Defining_Program_Unit_Name + then + Inst_Parent := Parent (Inst_Parent); + end if; + + Generic_From_Inst := Generic_Parent (Inst_Parent); + end; + + return Generic_From_E = Generic_From_Inst + and then Present (Generic_From_E); + end Is_Actual_Subp_Of_Inst; + + ----------------------------- + -- Is_Extraneously_Visible -- + ----------------------------- + + function Is_Extraneously_Visible + (E : Entity_Id; Inst : Entity_Id) return Boolean is + begin + -- Return False in various non-extraneous cases. + -- If none of those apply, then return True. + + if Within_Scope (E, Inst) then + -- return False if E declared within Inst + return False; + + elsif Is_Actual_Subp_Of_Inst (E, Inst) then + -- Return False if E is an actual subprogram, + -- and therefore may be referenced within Inst. + return False; + + elsif Nkind (Parent (E)) = N_Subtype_Declaration + and then Defining_Identifier (Parent (E)) /= E + then + -- Return False for a primitive subp of an + -- actual corresponding to a formal type. + + return False; + + elsif not In_Open_Scopes (Scope (E)) then + -- Return False if this candidate is not + -- declared in a currently open scope. + + return False; + + else + declare + -- We want to know whether the declaration of + -- E comes textually after the declaration of + -- the generic that Inst is an instance of + -- (and after the generic body if there is one). + -- To compare, we climb up the deeper of the two + -- scope chains until we the levels match. + -- There is a separate loop for each starting + -- point, but we will execute zero iterations + -- for at least one of the two loops. + -- For each Xxx_Scope, we have a corresponding + -- Xxx_Trailer; the latter is the predecessor of + -- the former in the scope traversal. + + E_Trailer : Entity_Id := E; + E_Scope : Entity_Id := Scope (E); + pragma Assert (Present (E_Scope)); + + -- the generic that Inst is an instance of + Gen_Trailer : Entity_Id := + Generic_Parent (Specification + (Unit_Declaration_Node (Inst))); + Gen_Scope : Entity_Id; + + function Has_Formal_Package_Parameter + (Generic_Id : Entity_Id) return Boolean; + -- Return True iff given generic has at least one + -- formal package parameter. + + ---------------------------------- + -- Has_Formal_Package_Parameter -- + ---------------------------------- + + function Has_Formal_Package_Parameter + (Generic_Id : Entity_Id) return Boolean is + Formal_Decl : Node_Id := + First (Generic_Formal_Declarations + (Enclosing_Generic_Unit (Generic_Id))); + begin + while Present (Formal_Decl) loop + if Nkind (Original_Node (Formal_Decl)) = + N_Formal_Package_Declaration + then + return True; + end if; + + Next (Formal_Decl); + end loop; + return False; + end Has_Formal_Package_Parameter; + + begin + if No (Gen_Trailer) then + -- Dunno how this can happen, but it can. + return False; + else + if Has_Formal_Package_Parameter (Gen_Trailer) + then + -- Punt on sorting out what is visible via a + -- formal package. + + return False; + end if; + + if Is_Child_Unit (Gen_Trailer) + and then Is_Generic_Unit + (Entity (Name + (Parent (Gen_Trailer)))) + then + -- Punt on dealing with how the FE fails + -- to build a tree for a "sprouted" generic + -- so that what should be a reference to + -- I1.G2 instead points into G1.G2 . + + return False; + end if; + + Gen_Scope := Scope (Gen_Trailer); + + while Scope_Depth (E_Scope) + > Scope_Depth (Gen_Scope) + loop + E_Trailer := E_Scope; + E_Scope := Scope (E_Scope); + end loop; + while Scope_Depth (E_Scope) + < Scope_Depth (Gen_Scope) + loop + Gen_Trailer := Gen_Scope; + Gen_Scope := Scope (Gen_Scope); + end loop; + end if; + + if Gen_Scope = E_Scope then + -- if Gen_Trailer and E_Trailer are declared + -- in the same declarative part and E_Trailer + -- occurs after the declaration (and body, if + -- there is one) of Gen_Trailer, then + -- return True because E was declared after + -- the generic that Inst is an instance of + -- (and also after that generic's body, if it + -- has one). + + if Is_Package_Or_Generic_Package (Gen_Trailer) + and then Present (Package_Body (Gen_Trailer)) + then + Gen_Trailer := + Corresponding_Body + (Package_Spec (Gen_Trailer)); + end if; + + declare + Id : Entity_Id := Gen_Trailer; + begin + loop + if not Present (Id) then + -- E_Trailer presumably occurred + -- earlier on the entity list than + -- Gen_Trailer. So E preceded the + -- generic that Inst is an instance + -- of (or the body of that generic if + -- it has one) and so could have + -- been referenced within the generic. + return False; + end if; + exit when Id = E_Trailer; + Next_Entity (Id); + end loop; + end; + end if; + end; + end if; + + if Present (Nearest_Enclosing_Instance (Inst)) then + return Is_Extraneously_Visible + (E => E, Inst => Nearest_Enclosing_Instance (Inst)); + + -- The preceding Nearest_Enclosing_Instance test + -- doesn't handle the case of an instance of a + -- "sprouted" generic. For example, if Inst=I2 in + -- generic package G1 + -- generic package G1.G2; + -- package I1 is new G1; + -- package I2 is new I1.G2; + -- then N_E_I (Inst) = Empty. So deal with that case. + + elsif Present (Nearest_Enclosing_Instance (E)) then + return Is_Extraneously_Visible + (E => Nearest_Enclosing_Instance (E), + Inst => Inst); + end if; + + return True; + end Is_Extraneously_Visible; + + --------------------------------- + -- Is_Generic_Actual_Subp_Name -- + --------------------------------- + + function Is_Generic_Actual_Subp_Name + (N : Node_Id) return Boolean + is + Decl : constant Node_Id := Enclosing_Declaration (N); + begin + return Nkind (Decl) = N_Subprogram_Renaming_Declaration + and then Present (Corresponding_Formal_Spec (Decl)); + end Is_Generic_Actual_Subp_Name; + + I : Interp_Index; + It : Interp; + Inst : Entity_Id := Current_Scope; + + begin + while Present (Inst) + and then not Is_Generic_Instance (Inst) + loop + Inst := Scope (Inst); + end loop; + + if Present (Inst) then + Get_First_Interp (N, I, It); + while Present (It.Nam) loop + if Is_Extraneously_Visible (E => It.Nam, Inst => Inst) + and then not Is_Generic_Actual_Subp_Name (N) + then + Remove_Interp (I); + end if; + Get_Next_Interp (I, It); + end loop; + end if; + end; + end if; + -- If no homonyms were visible, the entity is unambiguous if not Is_Overloaded (N) then