diff options
author | Steve Baird <baird@adacore.com> | 2023-12-18 16:17:40 -0800 |
---|---|---|
committer | Marc Poulhiès <poulhies@adacore.com> | 2024-05-07 09:55:54 +0200 |
commit | ef99791719a5695edc492b30b3a543c3659bf700 (patch) | |
tree | 28bf811198c97b5d14033bfa595bd06bd3b81a12 /gcc/ada | |
parent | d59f383a90487d081e1754e529a8ed41837767ec (diff) | |
download | gcc-ef99791719a5695edc492b30b3a543c3659bf700.zip gcc-ef99791719a5695edc492b30b3a543c3659bf700.tar.gz gcc-ef99791719a5695edc492b30b3a543c3659bf700.tar.bz2 |
ada: Improve pragma No_Return's pre-Ada2022 handling of functions
Ada 2022 allows pragma No_Return to apply to a function (or a generic function).
For earlier Ada versions, if a No_Return pragma argument's possible
resolutions include a function (or a generic function) then we want to ignore
that candidate if a non-function candidate is also available and otherwise
to generate an error message mentioning that this is an Ada 2022 feature.
gcc/ada/
* sem_prag.adb (Analyze_Pragma): Restructure the loop over
possible resolutions of a No_Return pragma's argument so that
functions (and generic functions) are not processed until after it
is known whether there is a non-function candidate resolution. For
a pre-2022 Ada version, terminate the iteration before processing
functions if a non-function resolution is found.
Diffstat (limited to 'gcc/ada')
-rw-r--r-- | gcc/ada/sem_prag.adb | 166 |
1 files changed, 97 insertions, 69 deletions
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb index a299613..ff02ae9 100644 --- a/gcc/ada/sem_prag.adb +++ b/gcc/ada/sem_prag.adb @@ -20771,96 +20771,124 @@ package body Sem_Prag is raise Pragma_Exit; end if; + Found := False; -- Loop to find matching procedures or functions (Ada 2022) - E := Entity (Id); + Outer_Loop : + for Process_Functions in Boolean loop - Found := False; - while Present (E) - and then Scope (E) = Current_Scope - loop - -- Ada 2022 (AI12-0269): A function can be No_Return + -- We make two passes over the Homonym list, first looking + -- at procedures and then at functions. This is done + -- in order to get the desired behavior in the pre-Ada2022 + -- case. There are two subcases of the pre-Ada2022 case - + -- either we found a non-function candidate in the first + -- pass or we didn't. If we found one, then exit early + -- (i.e., skip the second pass); we want to silently ignore + -- any functions. But if we didn't find one then we do not + -- want to exit early because looking at functions will + -- allow us (if we find one) to generate a more useful + -- error message ("this is an Ada 2022 construct" instead of + -- "name could not be resolved"). - if Ekind (E) in E_Generic_Procedure | E_Procedure - | E_Generic_Function | E_Function - then - -- Check that the pragma is not applied to a body. - -- First check the specless body case, to give a - -- different error message. These checks do not apply - -- if Relaxed_RM_Semantics, to accommodate other Ada - -- compilers. Disable these checks under -gnatd.J. - - if not Debug_Flag_Dot_JJ then - if Nkind (Parent (Declaration_Node (E))) = - N_Subprogram_Body - and then not Relaxed_RM_Semantics - then - Error_Pragma - ("pragma% requires separate spec and must come " - & "before body"); - end if; + exit Outer_Loop when Found and Ada_Version < Ada_2022; - -- Now the "specful" body case + E := Entity (Id); - if Rep_Item_Too_Late (E, N) then - raise Pragma_Exit; - end if; - end if; + while Present (E) + and then Scope (E) = Current_Scope + loop + -- Ada 2022 (AI12-0269): A function can be No_Return - if Check_No_Return (E, N) then - Set_No_Return (E); - end if; + if (if Process_Functions + then Ekind (E) in E_Generic_Function | E_Function + else Ekind (E) in E_Generic_Procedure | E_Procedure) - -- A pragma that applies to a Ghost entity becomes Ghost - -- for the purposes of legality checks and removal of - -- ignored Ghost code. + -- if From_Aspect_Specification, then only one + -- candidate should be considered. - Mark_Ghost_Pragma (N, E); + and then (not From_Aspect_Specification (N) + or else E = Entity (Id) + or else No (Entity (Id))) - -- Capture the entity of the first Ghost procedure being - -- processed for error detection purposes. + then + -- Check that the pragma is not applied to a body. + -- First check the specless body case, to give a + -- different error message. These checks do not apply + -- if Relaxed_RM_Semantics, to accommodate other Ada + -- compilers. Disable these checks under -gnatd.J. + + if not Debug_Flag_Dot_JJ then + if Nkind (Parent (Declaration_Node (E))) = + N_Subprogram_Body + and then not Relaxed_RM_Semantics + then + Error_Pragma + ("pragma% requires separate spec and must " + & "come before body"); + end if; - if Is_Ghost_Entity (E) then - if No (Ghost_Id) then - Ghost_Id := E; + -- Now the "specful" body case + + if Rep_Item_Too_Late (E, N) then + raise Pragma_Exit; + end if; end if; - -- Otherwise the subprogram is non-Ghost. It is illegal - -- to mix references to Ghost and non-Ghost entities - -- (SPARK RM 6.9). + if Check_No_Return (E, N) then + Set_No_Return (E); + end if; - elsif Present (Ghost_Id) - and then not Ghost_Error_Posted - then - Ghost_Error_Posted := True; + -- A pragma that applies to a Ghost entity becomes + -- Ghost for the purposes of legality checks and + -- removal of ignored Ghost code. - Error_Msg_Name_1 := Pname; - Error_Msg_N - ("pragma % cannot mention ghost and non-ghost " - & "procedures", N); + Mark_Ghost_Pragma (N, E); - Error_Msg_Sloc := Sloc (Ghost_Id); - Error_Msg_NE ("\& # declared as ghost", N, Ghost_Id); + -- Capture the entity of the first Ghost procedure + -- being processed for error detection purposes. - Error_Msg_Sloc := Sloc (E); - Error_Msg_NE ("\& # declared as non-ghost", N, E); - end if; + if Is_Ghost_Entity (E) then + if No (Ghost_Id) then + Ghost_Id := E; + end if; - -- Set flag on any alias as well + -- Otherwise the subprogram is non-Ghost. It is + -- illegal to mix references to Ghost and non-Ghost + -- entities (SPARK RM 6.9). - if Is_Overloadable (E) - and then Present (Alias (E)) - and then Check_No_Return (Alias (E), N) - then - Set_No_Return (Alias (E)); - end if; + elsif Present (Ghost_Id) + and then not Ghost_Error_Posted + then + Ghost_Error_Posted := True; - Found := True; - end if; + Error_Msg_Name_1 := Pname; + Error_Msg_N + ("pragma % cannot mention ghost and non-ghost " + & "procedures", N); - exit when From_Aspect_Specification (N); - E := Homonym (E); - end loop; + Error_Msg_Sloc := Sloc (Ghost_Id); + Error_Msg_NE + ("\& # declared as ghost", N, Ghost_Id); + + Error_Msg_Sloc := Sloc (E); + Error_Msg_NE ("\& # declared as non-ghost", N, E); + end if; + + -- Set flag on any alias as well + + if Is_Overloadable (E) + and then Present (Alias (E)) + and then Check_No_Return (Alias (E), N) + then + Set_No_Return (Alias (E)); + end if; + + Found := True; + end if; + + E := Homonym (E); + end loop; + end loop Outer_Loop; -- If entity in not in current scope it may be the enclosing -- subprogram body to which the aspect applies. |