This makes sure that the high bound computed from the low bound and the
length of the literal is within the range of the index type.

Tested on x86-64/Linux, applied on the mainline.


2026-09-23  Eric Botcazou  <[email protected]>

        * sem_res.adb (Set_String_Literal_Subtype): In the nonstatic case,
        set String_Literal_Low_Bound first, and check that the actual high
        bound is not larger than the high bound of the index type.

-- 
Eric Botcazou
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index fe39ba3f9c6..758d90cbfa5 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -13088,6 +13088,32 @@ package body Sem_Res is
             Index_Subtype : Entity_Id;
 
          begin
+            --  The back end expects the String_Literal_Subtype to have a
+            --  static lower bound.
+
+            if Is_Integer_Type (Index_Type) then
+               Set_String_Literal_Low_Bound
+                 (Subtype_Id, Make_Integer_Literal (Loc, 1));
+
+            --  If the index type is an enumeration type, build the bound
+            --  expression by means of an attribute.
+
+            else
+               Set_String_Literal_Low_Bound
+                 (Subtype_Id,
+                  Make_Attribute_Reference (Loc,
+                    Attribute_Name => Name_First,
+                    Prefix         =>
+                      New_Occurrence_Of (Base_Type (Index_Type), Loc)));
+            end if;
+
+            Analyze_And_Resolve
+              (String_Literal_Low_Bound (Subtype_Id), Base_Type (Index_Type));
+
+            --  Now build a subtype with the actual bounds and wrap the literal
+            --  in an unchecked conversion to it, after checking that the high
+            --  bound is within the range of the index type if need be.
+
             if Length = 1 then
                High_Bound := New_Copy_Tree (Low_Bound);
 
@@ -13096,6 +13122,9 @@ package body Sem_Res is
                  Make_Op_Add (Loc,
                    Left_Opnd  => New_Copy_Tree (Low_Bound),
                    Right_Opnd => Make_Integer_Literal (Loc, Length - 1));
+               if Length > 0 then
+                  High_Bound := Convert_To (Index_Type, High_Bound);
+               end if;
 
             else
                High_Bound :=
@@ -13116,29 +13145,6 @@ package body Sem_Res is
                          Make_Integer_Literal (Loc, Length - 1))));
             end if;
 
-            if Is_Integer_Type (Index_Type) then
-               Set_String_Literal_Low_Bound
-                 (Subtype_Id, Make_Integer_Literal (Loc, 1));
-
-            else
-               --  If the index type is an enumeration type, build bounds
-               --  expression with attributes.
-
-               Set_String_Literal_Low_Bound
-                 (Subtype_Id,
-                  Make_Attribute_Reference (Loc,
-                    Attribute_Name => Name_First,
-                    Prefix         =>
-                      New_Occurrence_Of (Base_Type (Index_Type), Loc)));
-            end if;
-
-            Analyze_And_Resolve
-              (String_Literal_Low_Bound (Subtype_Id), Base_Type (Index_Type));
-
-            --  Build bona fide subtype for the string, and wrap it in an
-            --  unchecked conversion, because the back end expects the
-            --  String_Literal_Subtype to have a static lower bound.
-
             Index_Subtype :=
               Create_Itype (Subtype_Kind (Ekind (Index_Type)), N);
             Drange := Make_Range (Loc, New_Copy_Tree (Low_Bound), High_Bound);

Reply via email to