These conventions allow the programmer to control the parameter passing method used in cases where it would normally be up to the implementation. The convention is applied to the type, and then affects how parameters with this type are passed. It is not allowed to specify Ada_Pass_By_Copy for types for which the language requires pass by reference (for example, limited types), and it is not allowed to specify Ada_Pass_By_Reference for types for which the language requires pass by copy (for example scalar types). Also if a parameter is marked as aliased, it is passed by reference even if the convention is Pass_By_Copy (this situation generates a warning, but is not considered to be an error).
The following test shows detection of errors (the output is compiled with -gnatj60 -gnatld7): 1. procedure pbycopref1 is 2. type R is tagged null record; 3. pragma Convention (Ada_Pass_By_Copy, R); | >>> convention "Ada_Pass_By_Copy" not allowed for by-reference type 4. type X is new Integer; 5. pragma Convention (Ada_Pass_By_Reference, X); | >>> convention "Ada_Pass_By_Reference" not allowed for by-copy type 6. procedure Q is begin null; end; 7. pragma Convention (Ada_Pass_By_Copy, Q); | >>> convention "Ada_Pass_By_Copy" only allowed for types 8. pragma Convention (Ada_Pass_By_Reference, Q); | >>> convention "Ada_Pass_By_Reference" only allowed for types 9. begin 10. null; 11. end; The following program compiles clean: 1. with System; use System; 2. with Text_IO; use Text_IO; 3. procedure pbycopref2 is 4. type Typ1 is array (1 .. 100) of Integer; 5. pragma Convention (Ada_Pass_By_Copy, Typ1); 6. procedure Test_By_Copy (A, B : in out Typ1) is 7. begin 8. if A'Address = B'Address then 9. Put_Line ("Error, unexpected pass by reference"); 10. else 11. Put_Line (A (1)'Img); 12. Put_Line (A (2)'Img); 13. Put_line ("OK"); 14. end if; 15. end; 16. 17. A1 : Typ1 := (others => 0); 18. 19. type Typ2 is array (1 .. 32) of Boolean; 20. pragma Pack (Typ2); 21. pragma Convention (Ada_Pass_By_Reference, Typ2); 22. 23. procedure Test_By_Reference (A, B : in out Typ2) is 24. begin 25. if A'Address /= B'Address then 26. Put_Line ("Error, unexpected pass by copy"); 27. else 28. Put_line ("OK"); 29. end if; 30. end; 31. 32. B1 : Typ2 := (others => False); 33. 34. begin 35. Test_By_Copy (A1, A1); 36. Test_By_Reference (B1, B1); 37. end; and generates the output: 0 0 OK OK The following program generates warnings as shown: 1. pragma Ada_2012; 2. with System; use System; 3. with Text_IO; use Text_IO; 4. procedure pbycopref3 is 5. type Typ1 is array (1 .. 100) of Integer; 6. pragma Convention (Ada_Pass_By_Copy, Typ1); 7. procedure Test_By_Ref (A, B : aliased in out Typ1) is 1 2 >>> warning: cannot pass aliased parameter "A" by copy >>> warning: cannot pass aliased parameter "B" by copy 8. begin 9. if A'Address = B'Address then 10. Put_Line ("Error, unexpected pass by copy"); 11. else 12. Put_Line (A (1)'Img); 13. Put_Line (A (2)'Img); 14. Put_line ("OK"); 15. end if; 16. end; 17. X, Y : aliased Typ1 := (1 => 1, 2 => 2, others => 0); 18. begin 19. Test_By_Ref (X, Y); 20. end; and generates the output: 1 2 OK Tested on x86_64-pc-linux-gnu, committed on trunk 2011-12-21 Robert Dewar <de...@adacore.com> * sem_ch6.adb (Process_Formals): Set proper mechanism for formals whose types have conventions Ada_Pass_By_Copy or Ada_Pass_By_Reference.
Index: sem_ch6.adb =================================================================== --- sem_ch6.adb (revision 182572) +++ sem_ch6.adb (working copy) @@ -9527,14 +9527,14 @@ Default := Expression (Param_Spec); if Is_Scalar_Type (Etype (Default)) then - if Nkind - (Parameter_Type (Param_Spec)) /= N_Access_Definition + if Nkind (Parameter_Type (Param_Spec)) /= + N_Access_Definition then Formal_Type := Entity (Parameter_Type (Param_Spec)); - else - Formal_Type := Access_Definition - (Related_Nod, Parameter_Type (Param_Spec)); + Formal_Type := + Access_Definition + (Related_Nod, Parameter_Type (Param_Spec)); end if; Apply_Scalar_Range_Check (Default, Formal_Type); @@ -9556,6 +9556,21 @@ if Is_Aliased (Formal) then Set_Mechanism (Formal, By_Reference); + + -- Warn if user asked this to be passed by copy + + if Convention (Formal_Type) = Convention_Ada_Pass_By_Copy then + Error_Msg_N + ("?cannot pass aliased parameter & by copy", Formal); + end if; + + -- Force mechanism if type has Convention Ada_Pass_By_Ref/Copy + + elsif Convention (Formal_Type) = Convention_Ada_Pass_By_Copy then + Set_Mechanism (Formal, By_Copy); + + elsif Convention (Formal_Type) = Convention_Ada_Pass_By_Reference then + Set_Mechanism (Formal, By_Reference); end if; Next (Param_Spec);