From: Javier Miranda <[email protected]>
This patch improves the error reported when the invoked constructor is
not available. This is a common error because constructors are not
inherited; this means that a constructor for a given tagged type may
not exist for its derived types. Fix also a crash in the initialization
of a limited record type.
gcc/ada/ChangeLog:
* sem_attr.adb (Analyze_Attribute): Report an error when the number
of actual parameters for a constructor do not match any available
constructor.
* exp_ch6.adb (Make_Init_Proc_Call): Add the _Init_Level accessibility
level formal when building a call to the init proc of a limited record
type.
(Prepend_Constructor_Procedure_Prologue): Restrict the initialization
of the _parent component to cases where a Super aspect is present
or a parameterless parent constructor exists.
Tested on x86_64-pc-linux-gnu, committed on master.
---
gcc/ada/exp_ch6.adb | 14 +++++++++++
gcc/ada/sem_attr.adb | 56 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 70 insertions(+)
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index 6a322be004f..f25c46213bb 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -6043,6 +6043,17 @@ package body Exp_Ch6 is
Append (Make_Mode_Literal (Loc, Full_Init), Params);
end if;
+ -- The init proc for a limited record type has an extra
+ -- accessibility level formal (_Init_Level) that must be
+ -- passed.
+
+ if Present (Init_Proc_Level_Formal (Init_Proc)) then
+ Append
+ (Make_Integer_Literal
+ (Loc, Scope_Depth (Standard_Standard)),
+ Params);
+ end if;
+
return Init_Proc_Call : constant Node_Id :=
Make_Procedure_Call_Statement (Loc,
Name => New_Occurrence_Of (Init_Proc, Loc),
@@ -6189,6 +6200,9 @@ package body Exp_Ch6 is
elsif Chars (Component) = Name_uParent
and then Needs_Construction (Etype (Component))
+ and then (Present (Find_Aspect (Body_Id, Aspect_Super))
+ or else Has_Parameterless_Constructor
+ (Etype (Component)))
then
Append_To (Parent_List,
Make_Parent_Constructor_Call
diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index 7a2154f18f4..77a61fff801 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -5430,6 +5430,62 @@ package body Sem_Attr is
if not Needs_Construction (Entity (P)) then
Error_Msg_NE ("no available constructor for&", N, Entity (P));
+
+ -- Verify that the provided arguments are compatible with at least
+ -- one constructor (checked by parameters count). Mismatched
+ -- actuals will be caught later during resolution.
+
+ elsif not Is_Copy_Constructor_Call (N)
+ and then Comes_From_Source (N)
+ then
+ declare
+ Num_Args : constant Nat := List_Length (Exprs);
+
+ function Is_Candidate
+ (Constructor_Id : Entity_Id) return Boolean;
+ -- Determine whether Num_Args is between the minimum and
+ -- maximum number of actuals required to invoke this
+ -- constructor.
+
+ ------------------
+ -- Is_Candidate --
+ ------------------
+
+ function Is_Candidate
+ (Constructor_Id : Entity_Id) return Boolean
+ is
+ Formal : Entity_Id;
+ Max_Actuals : Nat := 0;
+ Min_Actuals : Nat := 0;
+
+ begin
+ Formal := Next_Formal (First_Formal (Constructor_Id));
+ while Present (Formal) loop
+ Max_Actuals := Max_Actuals + 1;
+
+ if No (Default_Value (Formal)) then
+ Min_Actuals := Min_Actuals + 1;
+ end if;
+
+ Next_Formal (Formal);
+ end loop;
+
+ return Num_Args in Min_Actuals .. Max_Actuals;
+ end Is_Candidate;
+
+ function Find_Candidate is
+ new Find_Matching_Constructor (Is_Candidate);
+
+ begin
+ if No (Find_Candidate
+ (Typ => Entity (P),
+ Allow_Removed => False))
+ then
+ Error_Msg_NE
+ ("no constructor matching given arguments for&",
+ N, Entity (P));
+ end if;
+ end;
end if;
elsif not Needs_Construction (Entity (P))
--
2.53.0