name, preference is given to the component in a selected_component
(as is currently the case for tagged types with such component names).
+* Expression defaults for generic formal functions
+
+ The declaration of a generic formal function is allowed to specify
+ an expression as a default, using the syntax of an expression function.
+
+ Here is an example of this feature:
+
+ .. code-block:: ada
+
+ generic
+ type T is private;
+ with function Copy (Item : T) return T is (Item); -- Defaults to Item
+ package Stacks is
+
+ type Stack is limited private;
+
+ procedure Push (S : in out Stack; X : T); -- Calls Copy on X
+
+ function Pop (S : in out Stack) return T; -- Calls Copy to return item
+
+ private
+ -- ...
+ end Stacks;
+
.. _Pragma-Extensions_Visible:
Pragma Extensions_Visible
Cc (N_Formal_Abstract_Subprogram_Declaration, N_Formal_Subprogram_Declaration,
(Sy (Specification, Node_Id),
Sy (Default_Name, Node_Id, Default_Empty),
+ Sy (Expression, Node_Id, Default_Empty),
Sy (Box_Present, Flag)));
Cc (N_Formal_Concrete_Subprogram_Declaration, N_Formal_Subprogram_Declaration,
(Sy (Specification, Node_Id),
Sy (Default_Name, Node_Id, Default_Empty),
+ Sy (Expression, Node_Id, Default_Empty),
Sy (Box_Present, Flag)));
Ab (N_Push_Pop_xxx_Label, Node_Kind);
component is visible at the point of a selected_component using that
name, preference is given to the component in a selected_component
(as is currently the case for tagged types with such component names).
+
+@item
+Expression defaults for generic formal functions
+
+The declaration of a generic formal function is allowed to specify
+an expression as a default, using the syntax of an expression function.
+
+Here is an example of this feature:
+
+@example
+generic
+ type T is private;
+ with function Copy (Item : T) return T is (Item); -- Defaults to Item
+package Stacks is
+
+ type Stack is limited private;
+
+ procedure Push (S : in out Stack; X : T); -- Calls Copy on X
+
+ function Pop (S : in out Stack) return T; -- Calls Copy to return item
+
+private
+ -- ...
+end Stacks;
+@end example
@end itemize
@node Pragma Extensions_Visible,Pragma External,Pragma Extensions_Allowed,Implementation Defined Pragmas
-- [ASPECT_SPECIFICATIONS];
-- SUBPROGRAM_DEFAULT ::= DEFAULT_NAME | <>
+ -- | ( EXPRESSION ) -- Allowed as extension (-gnatX)
-- DEFAULT_NAME ::= NAME | null
Scan; -- past NULL
+ -- When extensions are enabled, a formal function can have a default
+ -- given by a parenthesized expression (expression function syntax).
+
+ elsif Token = Tok_Left_Paren then
+ Error_Msg_GNAT_Extension
+ ("expression default for formal subprograms");
+
+ if Nkind (Spec_Node) = N_Function_Specification then
+ Scan; -- past "("
+
+ Set_Expression (Def_Node, P_Expression);
+
+ if Token /= Tok_Right_Paren then
+ Error_Msg_SC ("missing "")"" at end of expression default");
+ else
+ Scan; -- past ")"
+ end if;
+
+ else
+ Error_Msg_SP
+ ("only functions can specify a default expression");
+ end if;
+
else
Set_Default_Name (Def_Node, P_Name);
end if;
procedure Analyze_Formal_Subprogram_Declaration (N : Node_Id) is
Spec : constant Node_Id := Specification (N);
Def : constant Node_Id := Default_Name (N);
+ Expr : constant Node_Id := Expression (N);
Nam : constant Entity_Id := Defining_Unit_Name (Spec);
Subp : Entity_Id;
("a formal abstract subprogram cannot default to null", Spec);
end if;
+ -- A formal abstract function cannot have an expression default
+ -- (expression defaults are allowed for nonabstract formal functions
+ -- when extensions are enabled).
+
+ if Nkind (Spec) = N_Function_Specification
+ and then Present (Expr)
+ then
+ Error_Msg_N
+ ("a formal abstract subprogram cannot default to an expression",
+ Spec);
+ end if;
+
declare
Ctrl_Type : constant Entity_Id := Find_Dispatching_Type (Nam);
begin
if Box_Present (N) then
null;
- -- Else default is bound at the point of generic declaration
+ -- Default name is bound at the point of generic declaration
elsif Present (Def) then
if Nkind (Def) = N_Operator_Symbol then
Error_Msg_N ("no visible subprogram matches specification", N);
end if;
end if;
+
+ -- When extensions are enabled, an expression can be given as default
+ -- for a formal function. The expression must be of the function result
+ -- type and can reference formal parameters of the function.
+
+ elsif Present (Expr) then
+ Push_Scope (Nam);
+ Install_Formals (Nam);
+ Preanalyze_Spec_Expression (Expr, Etype (Nam));
+ End_Scope;
end if;
<<Leave>>
Make_Handled_Sequence_Of_Statements (Loc,
Statements => New_List (Make_Null_Statement (Loc))));
- -- RM 12.6 (16 2/2): The procedure has convention Intrinsic
+ -- RM 12.6 (16.2/2): The procedure has convention Intrinsic
Set_Convention (Defining_Unit_Name (New_Spec), Convention_Intrinsic);
Set_Is_Inlined (Defining_Unit_Name (New_Spec));
return Decl_Node;
+ -- Handle case of a formal function with an expression default (allowed
+ -- when extensions are enabled).
+
+ elsif Nkind (Specification (Formal)) = N_Function_Specification
+ and then Present (Expression (Formal))
+ then
+ -- Generate body for function, for use in the instance
+
+ declare
+ Expr : constant Node_Id := New_Copy (Expression (Formal));
+ Stmt : constant Node_Id := Make_Simple_Return_Statement (Loc);
+ begin
+ Set_Sloc (Expr, Loc);
+ Set_Expression (Stmt, Expr);
+
+ Decl_Node :=
+ Make_Subprogram_Body (Loc,
+ Specification => New_Spec,
+ Declarations => New_List,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Stmt)));
+ end;
+
+ -- RM 12.6 (16.2/2): Like a null procedure default, the function
+ -- has convention Intrinsic.
+
+ Set_Convention (Defining_Unit_Name (New_Spec), Convention_Intrinsic);
+
+ -- Inline calls to it when optimization is enabled
+
+ Set_Is_Inlined (Defining_Unit_Name (New_Spec));
+ return Decl_Node;
+
else
Error_Msg_Sloc := Sloc (Scope (Analyzed_S));
Error_Msg_NE