aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Baird <baird@adacore.com>2025-01-13 14:18:26 -0800
committerEric Botcazou <ebotcazou@adacore.com>2025-06-05 15:30:20 +0200
commit5738c9b74bd77821b6c7438ea4e5fa1853d3f07a (patch)
tree042e6139c0758bfdee0e2f70eaa542715b0fb554
parent29447fb66f7cf4a515cbbcc812008092d519bc9c (diff)
downloadgcc-5738c9b74bd77821b6c7438ea4e5fa1853d3f07a.zip
gcc-5738c9b74bd77821b6c7438ea4e5fa1853d3f07a.tar.gz
gcc-5738c9b74bd77821b6c7438ea4e5fa1853d3f07a.tar.bz2
ada: Fix compile-time failure due to duplicated attribute subprograms.
For a given type, and for certain attributes (the 4 streaming attributes and, for Ada2022, the Put_Image attribute), the compiler needs to keep track of whether a subprogram has already been generated for the given type/attribute pair. In some cases this was being done incorrectly; the compiler ended up generating duplicate subprograms (with the same name), resulting in compilation failures. This could occur if the prefix of an attribute reference denoted a subtype (more precisely, a non-first subtype). This includes the case of a subtype declaration that is implicitly introduced by the compiler to capture the binding between a formal type in a generic and the corresponding actual type in an instantiation. gcc/ada/ChangeLog: * exp_attr.adb (Expand_N_Attribute_Reference): When accessing the maps declared in package Cached_Attribute_Ops, the key value passed to Get or to Set should never be the entity node for a subtype. Use the entity of the corresponding type declaration instead.
-rw-r--r--gcc/ada/exp_attr.adb39
1 files changed, 24 insertions, 15 deletions
diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb
index b896228..aea9e8a 100644
--- a/gcc/ada/exp_attr.adb
+++ b/gcc/ada/exp_attr.adb
@@ -88,8 +88,10 @@ package body Exp_Attr is
function Attribute_Op_Hash (Id : Entity_Id) return Header_Num is
(Header_Num (Id mod Map_Size));
- -- Cache used to avoid building duplicate subprograms for a single
- -- type/streaming-attribute pair.
+ -- Caches used to avoid building duplicate subprograms for a single
+ -- type/attribute pair (where the attribute is either Put_Image or
+ -- one of the four streaming attributes). The type used as a key in
+ -- in accessing these maps should not be the entity of a subtype.
package Read_Map is new GNAT.HTable.Simple_HTable
(Header_Num => Header_Num,
@@ -4669,7 +4671,7 @@ package body Exp_Attr is
end if;
if not Is_Tagged_Type (P_Type) then
- Cached_Attribute_Ops.Input_Map.Set (P_Type, Fname);
+ Cached_Attribute_Ops.Input_Map.Set (U_Type, Fname);
end if;
end Input;
@@ -5750,7 +5752,7 @@ package body Exp_Attr is
Rewrite_Attribute_Proc_Call (Pname);
if not Is_Tagged_Type (P_Type) then
- Cached_Attribute_Ops.Output_Map.Set (P_Type, Pname);
+ Cached_Attribute_Ops.Output_Map.Set (U_Type, Pname);
end if;
end Output;
@@ -6669,7 +6671,7 @@ package body Exp_Attr is
Rewrite_Attribute_Proc_Call (Pname);
if not Is_Tagged_Type (P_Type) then
- Cached_Attribute_Ops.Read_Map.Set (P_Type, Pname);
+ Cached_Attribute_Ops.Read_Map.Set (U_Type, Pname);
end if;
end Read;
@@ -8349,7 +8351,7 @@ package body Exp_Attr is
Rewrite_Attribute_Proc_Call (Pname);
if not Is_Tagged_Type (P_Type) then
- Cached_Attribute_Ops.Write_Map.Set (P_Type, Pname);
+ Cached_Attribute_Ops.Write_Map.Set (U_Type, Pname);
end if;
end Write;
@@ -8951,15 +8953,22 @@ package body Exp_Attr is
return Empty;
end if;
- if Nam = TSS_Stream_Read then
- Ent := Cached_Attribute_Ops.Read_Map.Get (Typ);
- elsif Nam = TSS_Stream_Write then
- Ent := Cached_Attribute_Ops.Write_Map.Get (Typ);
- elsif Nam = TSS_Stream_Input then
- Ent := Cached_Attribute_Ops.Input_Map.Get (Typ);
- elsif Nam = TSS_Stream_Output then
- Ent := Cached_Attribute_Ops.Output_Map.Get (Typ);
- end if;
+ declare
+ function U_Base return Entity_Id is
+ (Underlying_Type (Base_Type (Typ)));
+ -- Return the right type node for use in a C_A_O map lookup.
+ -- In particular, we do not want the entity for a subtype.
+ begin
+ if Nam = TSS_Stream_Read then
+ Ent := Cached_Attribute_Ops.Read_Map.Get (U_Base);
+ elsif Nam = TSS_Stream_Write then
+ Ent := Cached_Attribute_Ops.Write_Map.Get (U_Base);
+ elsif Nam = TSS_Stream_Input then
+ Ent := Cached_Attribute_Ops.Input_Map.Get (U_Base);
+ elsif Nam = TSS_Stream_Output then
+ Ent := Cached_Attribute_Ops.Output_Map.Get (U_Base);
+ end if;
+ end;
Cached_Attribute_Ops.Validate_Cached_Candidate
(Subp => Ent, Attr_Ref => Attr_Ref);