diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index 4d766b9433b82d2156bdfe22de37dea81a735c43..e4af71cef26fd0200b29aac898c95668420945fc 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -4743,6 +4743,12 @@ package body Sem_Ch6 is Style.Body_With_No_Spec (N); end if; + -- First set Acts_As_Spec if appropriate + + if Nkind (N) /= N_Subprogram_Body_Stub then + Set_Acts_As_Spec (N); + end if; + New_Overloaded_Entity (Body_Id); -- A subprogram body should cause freezing of its own declaration, @@ -4767,7 +4773,6 @@ package body Sem_Ch6 is end if; if Nkind (N) /= N_Subprogram_Body_Stub then - Set_Acts_As_Spec (N); Generate_Definition (Body_Id); Generate_Reference (Body_Id, Body_Id, 'b', Set_Ref => False, Force => True); @@ -9525,15 +9530,85 @@ package body Sem_Ch6 is ----------------------------- procedure Check_Untagged_Equality (Eq_Op : Entity_Id) is - Typ : constant Entity_Id := Etype (First_Formal (Eq_Op)); - Decl : constant Node_Id := Unit_Declaration_Node (Eq_Op); - Obj_Decl : Node_Id; + Eq_Decl : constant Node_Id := Unit_Declaration_Node (Eq_Op); + Typ : constant Entity_Id := Etype (First_Formal (Eq_Op)); + + procedure Freezing_Point_Warning (N : Node_Id; S : String); + -- Output a warning about the freezing point N of Typ + + function Is_Actual_Of_Instantiation + (E : Entity_Id; + Inst : Node_Id) return Boolean; + -- Return True if E is an actual parameter of instantiation Inst + + ----------------------------------- + -- Output_Freezing_Point_Warning -- + ----------------------------------- + + procedure Freezing_Point_Warning (N : Node_Id; S : String) is + begin + Error_Msg_String (1 .. S'Length) := S; + Error_Msg_Strlen := S'Length; + + if Ada_Version >= Ada_2012 then + Error_Msg_NE ("type& is frozen by ~??", N, Typ); + Error_Msg_N + ("\an equality operator cannot be declared after this point??", + N); + + else + Error_Msg_NE ("type& is frozen by ~ (Ada 2012)?y?", N, Typ); + Error_Msg_N + ("\an equality operator cannot be declared after this point" + & " (Ada 2012)?y?", N); + end if; + end Freezing_Point_Warning; + + -------------------------------- + -- Is_Actual_Of_Instantiation -- + -------------------------------- + + function Is_Actual_Of_Instantiation + (E : Entity_Id; + Inst : Node_Id) return Boolean + is + Assoc : Node_Id; + + begin + if Present (Generic_Associations (Inst)) then + Assoc := First (Generic_Associations (Inst)); + + while Present (Assoc) loop + if Present (Explicit_Generic_Actual_Parameter (Assoc)) + and then + Is_Entity_Name (Explicit_Generic_Actual_Parameter (Assoc)) + and then + Entity (Explicit_Generic_Actual_Parameter (Assoc)) = E + then + return True; + end if; + + Next (Assoc); + end loop; + end if; + + return False; + end Is_Actual_Of_Instantiation; + + -- Local variable + + Decl : Node_Id; + + -- Start of processing for Check_Untagged_Equality begin - -- This check applies only if we have a subprogram declaration with an - -- untagged record type that is conformant to the predefined operator. + -- This check applies only if we have a subprogram declaration or a + -- subprogram body that is not a completion, for an untagged record + -- type, and that is conformant with the predefined operator. - if Nkind (Decl) /= N_Subprogram_Declaration + if (Nkind (Eq_Decl) /= N_Subprogram_Declaration + and then not (Nkind (Eq_Decl) = N_Subprogram_Body + and then Acts_As_Spec (Eq_Decl))) or else not Is_Record_Type (Typ) or else Is_Tagged_Type (Typ) or else not Is_User_Defined_Equality (Eq_Op) @@ -9572,9 +9647,59 @@ package body Sem_Ch6 is elsif Is_Generic_Actual_Type (Typ) then return; - -- Here we have a definite error of declaration after freezing + -- Here we may have an error of declaration after freezing, but we + -- must make sure not to flag the equality operator itself causing + -- the freezing when it is a subprogram body. else + Decl := Next (Declaration_Node (Typ)); + + while Present (Decl) and then Decl /= Eq_Decl loop + + -- The declaration of an object of the type + + if Nkind (Decl) = N_Object_Declaration + and then Etype (Defining_Identifier (Decl)) = Typ + then + Freezing_Point_Warning (Decl, "declaration"); + exit; + + -- The instantiation of a generic on the type + + elsif Nkind (Decl) in N_Generic_Instantiation + and then Is_Actual_Of_Instantiation (Typ, Decl) + then + Freezing_Point_Warning (Decl, "instantiation"); + exit; + + -- A noninstance proper body, body stub or entry body + + elsif Nkind (Decl) in N_Proper_Body + | N_Body_Stub + | N_Entry_Body + and then not Is_Generic_Instance (Defining_Entity (Decl)) + then + Freezing_Point_Warning (Decl, "body"); + exit; + + -- If we have reached the freeze node and immediately after we + -- have the body or generated code for the body, then it is the + -- body that caused the freezing and this is legal. + + elsif Nkind (Decl) = N_Freeze_Entity + and then Entity (Decl) = Typ + and then (Next (Decl) = Eq_Decl + or else + Sloc (Next (Decl)) = Sloc (Eq_Decl)) + then + return; + end if; + + Next (Decl); + end loop; + + -- Here we have a definite error of declaration after freezing + if Ada_Version >= Ada_2012 then Error_Msg_NE ("equality operator must be declared before type & is " @@ -9594,57 +9719,32 @@ package body Sem_Ch6 is & "frozen (RM 4.5.2 (9.8)) (Ada 2012)?y?", Eq_Op, Typ); end if; - -- If we are in the package body, we could just move the - -- declaration to the package spec, so add a message saying that. + -- If we have found no freezing point and the declaration of the + -- operator could not be reached from that of the type and we are + -- in a package body, this must be because the type is declared + -- in the spec of the package. Add a message tailored to this. - if In_Package_Body (Scope (Typ)) then + if No (Decl) and then In_Package_Body (Scope (Typ)) then if Ada_Version >= Ada_2012 then - Error_Msg_N - ("\move declaration to package spec<<", Eq_Op); - else - Error_Msg_N - ("\move declaration to package spec (Ada 2012)?y?", Eq_Op); - end if; - - -- Otherwise try to find the freezing point for better message. - - else - Obj_Decl := Next (Parent (Typ)); - while Present (Obj_Decl) and then Obj_Decl /= Decl loop - if Nkind (Obj_Decl) = N_Object_Declaration - and then Etype (Defining_Identifier (Obj_Decl)) = Typ - then - -- Freezing point, output warnings - - if Ada_Version >= Ada_2012 then - Error_Msg_NE - ("type& is frozen by declaration??", Obj_Decl, Typ); - Error_Msg_N - ("\an equality operator cannot be declared after " - & "this point??", - Obj_Decl); - else - Error_Msg_NE - ("type& is frozen by declaration (Ada 2012)?y?", - Obj_Decl, Typ); - Error_Msg_N - ("\an equality operator cannot be declared after " - & "this point (Ada 2012)?y?", - Obj_Decl); - end if; - - exit; - - -- If we reach generated code for subprogram declaration - -- or body, it is the body that froze the type and the - -- declaration is legal. - - elsif Sloc (Obj_Decl) = Sloc (Decl) then - return; + if Nkind (Eq_Decl) = N_Subprogram_Body then + Error_Msg_N + ("\put declaration in package spec<<", Eq_Op); + else + Error_Msg_N + ("\move declaration to package spec<<", Eq_Op); end if; - Next (Obj_Decl); - end loop; + else + if Nkind (Eq_Decl) = N_Subprogram_Body then + Error_Msg_N + ("\put declaration in package spec (Ada 2012)?y?", + Eq_Op); + else + Error_Msg_N + ("\move declaration to package spec (Ada 2012)?y?", + Eq_Op); + end if; + end if; end if; end if; @@ -9653,21 +9753,21 @@ package body Sem_Ch6 is -- a type has been derived from T. else - Obj_Decl := Next (Parent (Typ)); + Decl := Next (Declaration_Node (Typ)); - while Present (Obj_Decl) and then Obj_Decl /= Decl loop - if Nkind (Obj_Decl) = N_Full_Type_Declaration - and then Etype (Defining_Identifier (Obj_Decl)) = Typ + while Present (Decl) and then Decl /= Eq_Decl loop + if Nkind (Decl) = N_Full_Type_Declaration + and then Etype (Defining_Identifier (Decl)) = Typ then Error_Msg_N ("equality operator cannot appear after derivation", Eq_Op); Error_Msg_NE ("an equality operator for& cannot be declared after " & "this point??", - Obj_Decl, Typ); + Decl, Typ); end if; - Next (Obj_Decl); + Next (Decl); end loop; end if; end Check_Untagged_Equality; diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index 1412d94198c7b08a01d0ab96c7271b44c16e9e64..44fc955de74a5394ace16e149fcf998398faa110 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -8967,14 +8967,7 @@ package body Sem_Res is then Eq := Get_User_Defined_Equality (T); - -- We need to make sure that the instance is not within the - -- same declarative region as the type, or else that it lies - -- after the declaration of the user-defined "=" operator. - - if Present (Eq) - and then (not In_Same_Extended_Unit (Eq, N) - or else Earlier_In_Extended_Unit (Eq, N)) - then + if Present (Eq) then if Is_Abstract_Subprogram (Eq) then Nondispatching_Call_To_Abstract_Operation (N, Eq); else