Skip to content

Commit ae59545

Browse files
committed
Merge branch 'topic/v810-011' into 'master'
Ada API: fix a stack overflow in Children_And_Trivia Closes AdaCore#651 See merge request eng/libadalang/langkit!742
2 parents 6fab69b + b2d2e07 commit ae59545

File tree

10 files changed

+4270
-31
lines changed

10 files changed

+4270
-31
lines changed

langkit/templates/pkg_analysis_body_ada.mako

Lines changed: 75 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,72 @@ package body ${ada_lib_name}.Analysis is
12031203
Assign_Names_To_Logic_Vars (Node.Internal.Node);
12041204
end Assign_Names_To_Logic_Vars;
12051205

1206+
-----------
1207+
-- First --
1208+
-----------
1209+
1210+
function First
1211+
(Self : Children_Array) return Children_Array_Cursor is
1212+
begin
1213+
return Self.Children.First_Index;
1214+
end First;
1215+
1216+
----------
1217+
-- Last --
1218+
----------
1219+
1220+
function Last
1221+
(Self : Children_Array) return Children_Array_Cursor is
1222+
begin
1223+
return Self.Children.Last_Index;
1224+
end Last;
1225+
1226+
----------
1227+
-- Next --
1228+
----------
1229+
1230+
function Next
1231+
(Self : Children_Array;
1232+
Pos : Children_Array_Cursor) return Children_Array_Cursor is
1233+
begin
1234+
pragma Unreferenced (Self);
1235+
return Pos + 1;
1236+
end Next;
1237+
1238+
--------------
1239+
-- Previous --
1240+
--------------
1241+
1242+
function Previous
1243+
(Self : Children_Array;
1244+
Pos : Children_Array_Cursor) return Children_Array_Cursor is
1245+
begin
1246+
pragma Unreferenced (Self);
1247+
return Pos - 1;
1248+
end Previous;
1249+
1250+
-----------------
1251+
-- Has_Element --
1252+
-----------------
1253+
1254+
function Has_Element
1255+
(Self : Children_Array;
1256+
Pos : Children_Array_Cursor) return Boolean is
1257+
begin
1258+
return Pos in First (Self) .. Last (Self);
1259+
end Has_Element;
1260+
1261+
-------------
1262+
-- Element --
1263+
-------------
1264+
1265+
function Element
1266+
(Self : Children_Array;
1267+
Pos : Children_Array_Cursor) return Child_Record is
1268+
begin
1269+
return Self.Children (Pos);
1270+
end Element;
1271+
12061272
-------------------------
12071273
-- Children_And_Trivia --
12081274
-------------------------
@@ -1217,22 +1283,17 @@ package body ${ada_lib_name}.Analysis is
12171283

12181284
Check_Safety_Net (Node);
12191285
declare
1220-
Bare_Result : constant Bare_Children_Array :=
1286+
Bare_Result : constant Bare_Children_Vector :=
12211287
Children_And_Trivia (Unwrap_Node (Node));
1222-
Result : Children_Array (Bare_Result'Range);
1288+
Result : Children_Array;
12231289
begin
1224-
for I in Bare_Result'Range loop
1225-
declare
1226-
BR : Bare_Child_Record renames Bare_Result (I);
1227-
R : Child_Record renames Result (I);
1228-
begin
1229-
case BR.Kind is
1230-
when Child =>
1231-
R := (Child, Wrap_Node (BR.Node));
1232-
when Trivia =>
1233-
R := (Trivia, BR.Trivia);
1234-
end case;
1235-
end;
1290+
for C of Bare_Result loop
1291+
case C.Kind is
1292+
when Child =>
1293+
Result.Children.Append ((Child, Wrap_Node (C.Node)));
1294+
when Trivia =>
1295+
Result.Children.Append ((Trivia, C.Trivia));
1296+
end case;
12361297
end loop;
12371298
return Result;
12381299
end;

langkit/templates/pkg_analysis_spec_ada.mako

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<%namespace name="struct_types" file="struct_types_ada.mako" />
1010

1111
with Ada.Containers;
12+
private with Ada.Containers.Vectors;
1213
private with Ada.Finalization;
1314
with Ada.Strings.Unbounded;
1415
% if any(a.used_in_public_struct for a in ctx.array_types):
@@ -454,7 +455,49 @@ package ${ada_lib_name}.Analysis is
454455
end record;
455456
-- Variant that holds either an AST node or a token
456457

457-
type Children_Array is array (Positive range <>) of Child_Record;
458+
subtype Children_Array_Cursor is Positive;
459+
type Children_Array is private
460+
with Iterable => (First => First,
461+
Next => Next,
462+
Has_Element => Has_Element,
463+
Element => Element,
464+
Last => Last,
465+
Previous => Previous);
466+
-- This iterable type holds an array of ``Child`` or ``Trivia`` nodes
467+
468+
function First
469+
(Self : Children_Array) return Children_Array_Cursor;
470+
-- Return the first child or trivia cursor corresponding to the children
471+
-- array. Helper for the ``Iterable`` aspect.
472+
473+
function Last
474+
(Self : Children_Array) return Children_Array_Cursor;
475+
-- Return the last child or trivia cursor corresponding to the children
476+
-- array. Helper for the ``Iterable`` aspect.
477+
478+
function Next
479+
(Self : Children_Array;
480+
Pos : Children_Array_Cursor) return Children_Array_Cursor;
481+
-- Return the child or trivia cursor that follows ``Self`` in the children
482+
-- array. Helper for the ``Iterable`` aspect.
483+
484+
function Previous
485+
(Self : Children_Array;
486+
Pos : Children_Array_Cursor) return Children_Array_Cursor;
487+
-- Return the child or trivia cursor that follows ``Self`` in the children
488+
-- array. Helper for the ``Iterable`` aspect.
489+
490+
function Has_Element
491+
(Self : Children_Array;
492+
Pos : Children_Array_Cursor) return Boolean;
493+
-- Return if ``Pos`` is in ``Self``'s iteration range. Helper for the
494+
-- ``Iterable`` aspect.
495+
496+
function Element
497+
(Self : Children_Array;
498+
Pos : Children_Array_Cursor) return Child_Record;
499+
-- Return the child of trivia node at position ``Pos`` in ``Self``. Helper
500+
-- for the ``Iterable`` aspect.
458501

459502
function Children_And_Trivia
460503
(Node : ${root_entity.api_name}'Class) return Children_Array;
@@ -770,6 +813,14 @@ private
770813
Safety_Net => Implementation.No_Node_Safety_Net);
771814
% endfor
772815

816+
package Child_Record_Vectors is new Ada.Containers.Vectors
817+
(Index_Type => Children_Array_Cursor,
818+
Element_Type => Child_Record);
819+
820+
type Children_Array is record
821+
Children : Child_Record_Vectors.Vector;
822+
end record;
823+
773824
procedure Check_Safety_Net (Self : ${T.root_node.entity.api_name}'Class);
774825
-- Check that Self's node and rebindings are still valid, raising a
775826
-- Stale_Reference_Error if one is not.

langkit/templates/pkg_implementation_body_ada.mako

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3542,13 +3542,9 @@ package body ${ada_lib_name}.Implementation is
35423542
-------------------------
35433543

35443544
function Children_And_Trivia
3545-
(Node : ${T.root_node.name}) return Bare_Children_Array
3545+
(Node : ${T.root_node.name}) return Bare_Children_Vector
35463546
is
3547-
package Children_Vectors is new Ada.Containers.Vectors
3548-
(Positive, Bare_Child_Record);
3549-
use Children_Vectors;
3550-
3551-
Ret_Vec : Vector;
3547+
Ret_Vec : Bare_Children_Vector;
35523548
Ctx : Internal_Context renames Node.Unit.Context;
35533549
TDH : Token_Data_Handler renames Node.Unit.TDH;
35543550

@@ -3624,14 +3620,7 @@ package body ${ada_lib_name}.Implementation is
36243620
end if;
36253621
end loop;
36263622

3627-
declare
3628-
A : Bare_Children_Array (1 .. Natural (Ret_Vec.Length));
3629-
begin
3630-
for I in A'Range loop
3631-
A (I) := Ret_Vec.Element (I);
3632-
end loop;
3633-
return A;
3634-
end;
3623+
return Ret_Vec;
36353624
end Children_And_Trivia;
36363625

36373626
--------------

langkit/templates/pkg_implementation_spec_ada.mako

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ with Ada.Containers; use Ada.Containers;
1616
with Ada.Containers.Hashed_Maps;
1717
with Ada.Containers.Hashed_Sets;
1818
with Ada.Containers.Ordered_Maps;
19+
with Ada.Containers.Vectors;
1920
with Ada.Exceptions;
2021
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
2122
with Ada.Strings.Unbounded.Hash;
@@ -1281,10 +1282,13 @@ private package ${ada_lib_name}.Implementation is
12811282
end record;
12821283
-- Variant that holds either an node or a token
12831284

1284-
type Bare_Children_Array is array (Positive range <>) of Bare_Child_Record;
1285+
package Bare_Children_Record_Vectors is new Ada.Containers.Vectors
1286+
(Positive, Bare_Child_Record);
1287+
1288+
subtype Bare_Children_Vector is Bare_Children_Record_Vectors.Vector;
12851289

12861290
function Children_And_Trivia
1287-
(Node : ${T.root_node.name}) return Bare_Children_Array;
1291+
(Node : ${T.root_node.name}) return Bare_Children_Vector;
12881292
-- Implementation for Analysis.Children_And_Trivia
12891293

12901294
% for astnode in ctx.astnode_types:
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import lexer_example
2+
3+
@with_lexer(foo_lexer)
4+
grammar foo_grammar {
5+
@main_rule main_rule <- list*(id)
6+
id <- Identifier(@identifier)
7+
}
8+
9+
@abstract class FooNode implements Node[FooNode] {
10+
}
11+
12+
class Identifier : FooNode implements TokenNode {
13+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
with Ada.Text_IO; use Ada.Text_IO;
2+
3+
with Libfoolang.Analysis; use Libfoolang.Analysis;
4+
with Libfoolang.Common; use Libfoolang.Common;
5+
6+
procedure Main is
7+
U : constant Analysis_Unit :=
8+
Create_Context.Get_From_File ("main.txt");
9+
10+
Child_Counter, Trivia_Counter : Natural := 0;
11+
begin
12+
-- This call to Children_And_Trivia raises a STORAGE_ERROR (stack overflow)
13+
-- if the nodes are stored on the stack.
14+
15+
for N of U.Root.Children_And_Trivia loop
16+
if N.Kind = Child then
17+
Child_Counter := Child_Counter + 1;
18+
else
19+
Trivia_Counter := Trivia_Counter + 1;
20+
end if;
21+
end loop;
22+
Put_Line ("Child:" & Child_Counter'Image);
23+
Put_Line ("Trivia:" & Trivia_Counter'Image);
24+
Put_Line ("main.adb: Done.");
25+
end Main;

0 commit comments

Comments
 (0)