Patchwork [Ada] String literals in nested subprograms in generic units

login
register
mail settings
Submitter Arnaud Charlet
Date Oct. 12, 2010, 10:38 a.m.
Message ID <20101012103848.GA12373@adacore.com>
Download mbox | patch
Permalink /patch/67521/
State New
Headers show

Comments

Arnaud Charlet - Oct. 12, 2010, 10:38 a.m.
A string literal subtype is constructed for every string. If the literal is
the value of a declared constant, it may be used in a nested scope in another
declaration. If the context is generic, the nested string may be elaborated in
a different scope leading to elaboration problems in the backend. This patch
forces the reanalysis of a string that appears in an instantiation, so that
a new subtype can be created for it in the proper context.

The following must compile quietly:
---
with Q;
procedure P is
  package My_Q is new Q (Name => "My_Q");
begin
  My_Q.Dummy;
end;
---
generic
  Name : String;
package Q is
  procedure Dummy;
end Q;
---
package body Q is

  Scope : constant String := Name;

  generic
    I : Integer;
  procedure Proc_G;

  procedure Proc_G is
    Context : constant String := Scope;
    Scope   : constant String := Context & ".Proc_G";

    procedure Nested is
      Context : constant String := Scope;
      Scope   : constant String := Context & ".Nested";
    begin
      null;
    end;

  begin
    null;
  end;

  procedure Proc is new Proc_G (0);

  procedure Dummy is
  begin
    null;
  end;
end Q;

Tested on x86_64-pc-linux-gnu, committed on trunk

2010-10-12  Ed Schonberg  <schonberg@adacore.com>

	* sem_ch12.adb (Copy_Generic_Node): If node is a string literal, remove
	string_literal_subtype so that a new one can be constructed in the
	scope of the instance.

Patch

Index: sem_ch12.adb
===================================================================
--- sem_ch12.adb	(revision 165353)
+++ sem_ch12.adb	(working copy)
@@ -6211,15 +6211,25 @@  package body Sem_Ch12 is
             end if;
          end;
 
-      elsif Nkind_In (N, N_Integer_Literal,
-                         N_Real_Literal,
-                         N_String_Literal)
-      then
+      elsif Nkind_In (N, N_Integer_Literal, N_Real_Literal) then
+
          --  No descendant fields need traversing
 
          null;
 
-      --  For the remaining nodes, copy recursively their descendants
+      elsif Nkind (N) = N_String_Literal
+        and then Present (Etype (N))
+        and then Instantiating
+      then
+         --  If the string is declared in an outer scope, the string_literal
+         --  subtype created for it may have the wrong scope. We force the
+         --  reanalysis of the constant to generate a new itype in the proper
+         --  context.
+
+         Set_Etype (New_N, Empty);
+         Set_Analyzed (New_N, False);
+
+      --  For the remaining nodes, copy their descendants recursively
 
       else
          Copy_Descendants;