diff mbox series

[Ada] Crash on misplaced First operation for GNAT iterable type

Message ID 20181211113654.GA106038@adacore.com
State New
Headers show
Series [Ada] Crash on misplaced First operation for GNAT iterable type | expand

Commit Message

Pierre-Marie de Rodat Dec. 11, 2018, 11:36 a.m. UTC
This patch improves the handling of an improper declaaration of aspect
First for a GNAT-defined iterable type,

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

2018-12-11  Ed Schonberg  <schonberg@adacore.com>

gcc/ada/

	* sem_util.adb (Get_Actual_Subtype): Function can return type
	mark.
	(Get_Cursor_Type): Improve recovery and error message on a
	misplaced First aspect for an iterable type.

gcc/testsuite/

	* gnat.dg/iter4.adb: New testcase.
diff mbox series

Patch

--- gcc/ada/sem_util.adb
+++ gcc/ada/sem_util.adb
@@ -9049,6 +9049,13 @@  package body Sem_Util is
 
          else
             Decl := Build_Actual_Subtype (Typ, N);
+
+            --  The call may yield a declaration, or just return the entity
+
+            if Decl = Typ then
+               return Typ;
+            end if;
+
             Atyp := Defining_Identifier (Decl);
 
             --  If Build_Actual_Subtype generated a new declaration then use it
@@ -9162,6 +9169,9 @@  package body Sem_Util is
       if First_Op = Any_Id then
          Error_Msg_N ("aspect Iterable must specify First operation", Aspect);
          return Any_Type;
+
+      elsif not Analyzed (First_Op) then
+         Analyze (First_Op);
       end if;
 
       Cursor := Any_Type;
@@ -9195,7 +9205,8 @@  package body Sem_Util is
 
       if Cursor = Any_Type then
          Error_Msg_N
-           ("No legal primitive operation First for Iterable type", Aspect);
+           ("primitive operation for Iterable type must appear "
+             & "in the same list of declarations as the type", Aspect);
       end if;
 
       return Cursor;

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/iter4.adb
@@ -0,0 +1,36 @@ 
+--  { dg-do compile }
+
+procedure Iter4 is
+   package Root is
+      type Result is tagged record
+         B : Boolean;
+      end record;
+
+      type T is tagged record
+         I : Integer;
+      end record
+      with Iterable => (First       => Pkg.First, --  { dg-error "primitive operation for Iterable type must appear in the same list of declarations as the type" }
+                        Next        => Pkg.Next,
+                        Has_Element => Pkg.Has_Element,
+                        Element     => Pkg.Element);
+
+      package Pkg is
+         function First (Dummy : T) return Natural is (0);
+         function Next (Dummy : T; Cursor : Natural) return Natural is
+           (Cursor + 1);
+         function Has_Element (Value : T; Cursor : Natural) return Boolean is
+           (Cursor <= Value.I);
+         function Element (Dummy : T; Cursor : Natural) return Result is
+           ((B => Cursor mod 2 = 0));
+      end Pkg;
+   end Root;
+
+   package Derived is
+      type T is new Root.T with record
+         C : Character;
+      end record;
+   end Derived;
+
+begin
+   null;
+end;