From 5b59dda84a7eb8a48e94a75b9b3ad008514089ce Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Sat, 14 Jan 2023 18:50:22 +0100 Subject: vhdl: add a warning to detect use before elaboration --- src/errorout.ads | 12 +++++++----- src/vhdl/vhdl-sem.adb | 36 ++++++++++++++++++++++++++++++++++++ src/vhdl/vhdl-sem_decls.adb | 18 ++++++++++++++++++ src/vhdl/vhdl-sem_expr.adb | 9 +++++++++ src/vhdl/vhdl-sem_expr.ads | 7 +++++++ src/vhdl/vhdl-sem_types.adb | 9 +++++++++ src/vhdl/vhdl-sem_utils.adb | 8 ++++++++ src/vhdl/vhdl-std_package.adb | 5 +++++ 8 files changed, 99 insertions(+), 5 deletions(-) diff --git a/src/errorout.ads b/src/errorout.ads index 3f554380e..53c926491 100644 --- a/src/errorout.ads +++ b/src/errorout.ads @@ -132,13 +132,16 @@ package Errorout is -- Lexical conformance Warnid_Conformance, - -- Attributes in the netlist is not kept during synthesis + -- Attributes in the netlist is not kept during synthesis Warnid_Unkept_Attribute, Warnid_Unhandled_Attribute, -- Violation of staticness rules Warnid_Static, + -- Use before elaboration. + Warnid_Elaboration, + -- Any warning Msgid_Warning, @@ -151,7 +154,7 @@ package Errorout is -- All specific warning messages. subtype Msgid_Warnings is Msgid_Type - range Warnid_Library .. Warnid_Static; + range Warnid_Library .. Warnid_Elaboration; subtype Msgid_All_Warnings is Msgid_Type range Msgid_Warnings'First .. Msgid_Warning; @@ -331,9 +334,8 @@ private | Warnid_Runtime_Error | Warnid_Pure | Warnid_Specs | Warnid_Hide | Warnid_Pragma | Warnid_Analyze_Assert | Warnid_Attribute | Warnid_Deprecated_Option | Warnid_Unexpected_Option - | Warnid_Nowrite - | Warnid_No_Wait | Warnid_Useless - | Warnid_Conformance + | Warnid_Nowrite | Warnid_No_Wait | Warnid_Useless + | Warnid_Elaboration | Warnid_Conformance | Warnid_Unkept_Attribute | Warnid_Unhandled_Attribute | Msgid_Warning => (Enabled => True, Error => False), Warnid_Delta_Cycle | Warnid_Body | Warnid_Static | Warnid_Nested_Comment diff --git a/src/vhdl/vhdl-sem.adb b/src/vhdl/vhdl-sem.adb index 174f1456e..cd4267c71 100644 --- a/src/vhdl/vhdl-sem.adb +++ b/src/vhdl/vhdl-sem.adb @@ -2114,9 +2114,12 @@ package body Vhdl.Sem is is Spec : constant Iir := Get_Subprogram_Specification (Subprg); Warn_Hide_Enabled : constant Boolean := Is_Warning_Enabled (Warnid_Hide); + Prev_Unelaborated_Use_Allowed : constant Boolean := + Unelaborated_Use_Allowed; El : Iir; begin Set_Impure_Depth (Subprg, Iir_Depth_Pure); + Set_Elaborated_Flag (Spec, True); -- LRM 10.1 Declarative regions -- 3. A subprogram declaration, together with the corresponding @@ -2155,11 +2158,15 @@ package body Vhdl.Sem is end; end if; + Unelaborated_Use_Allowed := True; + Sem_Sequential_Statements (Spec, Subprg); Set_Is_Within_Flag (Spec, False); Close_Declarative_Region; + Unelaborated_Use_Allowed := Prev_Unelaborated_Use_Allowed; + case Get_Kind (Spec) is when Iir_Kind_Procedure_Declaration => if Get_Suspend_Flag (Subprg) @@ -2883,6 +2890,34 @@ package body Vhdl.Sem is return False; end Is_Package_Macro_Expanded; + -- Mark declarations of HDR as elaborated. + procedure Mark_Declarations_Elaborated (Hdr : Iir) + is + Decl : Iir; + begin + Decl := Get_Declaration_Chain (Hdr); + while Decl /= Null_Iir loop + case Get_Kind (Decl) is + when Iir_Kinds_Subprogram_Declaration => + Set_Elaborated_Flag (Decl, True); + when Iir_Kind_Type_Declaration => + declare + Def : constant Iir := Get_Type_Definition (Decl); + begin + if Get_Kind (Def) = Iir_Kind_Protected_Type_Declaration then + -- Mark the protected type as elaborated. + -- Mark the methods as elaborated. + Set_Elaborated_Flag (Def, True); + Mark_Declarations_Elaborated (Def); + end if; + end; + when others => + null; + end case; + Decl := Get_Chain (Decl); + end loop; + end Mark_Declarations_Elaborated; + -- LRM 2.5 Package Declarations. procedure Sem_Package_Declaration (Pkg : Iir_Package_Declaration) is @@ -2957,6 +2992,7 @@ package body Vhdl.Sem is end if; Sem_Declaration_Chain (Pkg); + Mark_Declarations_Elaborated (Pkg); -- GHDL: subprogram bodies appear in package body. Pop_Signals_Declarative_Part (Implicit); diff --git a/src/vhdl/vhdl-sem_decls.adb b/src/vhdl/vhdl-sem_decls.adb index 974cc21d8..21c4d3542 100644 --- a/src/vhdl/vhdl-sem_decls.adb +++ b/src/vhdl/vhdl-sem_decls.adb @@ -203,6 +203,7 @@ package body Vhdl.Sem_Decls is procedure Sem_Interface_Object_Declaration (Inter, Last : Iir; Interface_Kind : Interface_Kind_Type) is + Prev_Unelaborated_Use_Allowed : Boolean; A_Type: Iir; Default_Value: Iir; begin @@ -229,12 +230,20 @@ package body Vhdl.Sem_Decls is Default_Value := Get_Default_Value (Inter); if Default_Value /= Null_Iir and then not Is_Error (A_Type) then + Deferred_Constant_Allowed := True; + Prev_Unelaborated_Use_Allowed := Unelaborated_Use_Allowed; + if Interface_Kind in Parameter_Interface_List then + Unelaborated_Use_Allowed := True; + end if; + Default_Value := Sem_Expression_Wildcard (Default_Value, A_Type, Is_Object_Fully_Constrained (Inter)); Default_Value := Eval_Expr_Check_If_Static (Default_Value, A_Type); + Deferred_Constant_Allowed := False; + Unelaborated_Use_Allowed := Prev_Unelaborated_Use_Allowed; Check_Read (Default_Value); end if; end if; @@ -1120,6 +1129,15 @@ package body Vhdl.Sem_Decls is Error_Msg_Sem (+Decl, "variable type must not be of the " & "protected type body"); end if; + + -- Check elaboration. + if Is_Protected + and then not Get_Elaborated_Flag (Base_Type) + then + Warning_Msg_Sem + (Warnid_Elaboration, +Decl, + "declaration of a protected type before the body"); + end if; end; end if; Set_Expr_Staticness (Decl, None); diff --git a/src/vhdl/vhdl-sem_expr.adb b/src/vhdl/vhdl-sem_expr.adb index 5fbb6cd34..d605d3b46 100644 --- a/src/vhdl/vhdl-sem_expr.adb +++ b/src/vhdl/vhdl-sem_expr.adb @@ -1262,6 +1262,15 @@ package body Vhdl.Sem_Expr is Set_Function_Call_Staticness (Expr, Imp); Sem_Decls.Mark_Subprogram_Used (Imp); + -- Check the subprogram is not called before its elaboration. + if not Unelaborated_Use_Allowed + and then Get_Kind (Imp) in Iir_Kinds_Subprogram_Declaration + and then not Get_Elaborated_Flag (Imp) + then + Warning_Msg_Sem (Warnid_Elaboration, +Expr, + "%n is called before elaborated of its body", +Imp); + end if; + -- Check purity/wait/passive. if Subprg = Null_Iir then diff --git a/src/vhdl/vhdl-sem_expr.ads b/src/vhdl/vhdl-sem_expr.ads index 1519d9252..b247d2d7e 100644 --- a/src/vhdl/vhdl-sem_expr.ads +++ b/src/vhdl/vhdl-sem_expr.ads @@ -24,8 +24,15 @@ package Vhdl.Sem_Expr is -- Set type to nodes, -- Resolve overloading + -- If set, use of deferred constants is allowed. + -- Set during analysis of default value of subprogram parameters. Deferred_Constant_Allowed : Boolean := False; + -- If set, use of unelaborated constructs is allowed. + -- This is set while analyzing subprograms body (and default parameters + -- values), as a subprogram may be called way after elaboration. + Unelaborated_Use_Allowed : Boolean := False; + -- Analyze an expression (other than a range) with a possible overloading. -- Sem_expression_ov (and therefore sem_expression) must be called *once* -- for each expression node with A_TYPE1 not null and at most *once* with diff --git a/src/vhdl/vhdl-sem_types.adb b/src/vhdl/vhdl-sem_types.adb index a6f8e0223..43f887830 100644 --- a/src/vhdl/vhdl-sem_types.adb +++ b/src/vhdl/vhdl-sem_types.adb @@ -654,6 +654,8 @@ package body Vhdl.Sem_Types is procedure Sem_Protected_Type_Body (Bod : Iir) is + Prev_Unelaborated_Use_Allowed : constant Boolean := + Unelaborated_Use_Allowed; Inter : Name_Interpretation_Type; Type_Decl : Iir; Decl : Iir; @@ -686,6 +688,7 @@ package body Vhdl.Sem_Types is and then Get_Kind (Decl) = Iir_Kind_Protected_Type_Declaration then Set_Protected_Type_Declaration (Bod, Decl); + Set_Elaborated_Flag (Decl, True); if Get_Protected_Type_Body (Decl) /= Null_Iir then Report_Start_Group; Error_Msg_Sem @@ -718,6 +721,10 @@ package body Vhdl.Sem_Types is -- body. Open_Declarative_Region; + -- The body is called when a variable is created, so possibly all + -- used constructs are elaborated. + Unelaborated_Use_Allowed := True; + if Decl /= Null_Iir then Xref_Body (Bod, Decl); Add_Protected_Type_Declarations (Decl); @@ -735,6 +742,8 @@ package body Vhdl.Sem_Types is Sem_Decls.Check_Full_Declaration (Decl, Bod); end if; + Unelaborated_Use_Allowed := Prev_Unelaborated_Use_Allowed; + Close_Declarative_Region; end Sem_Protected_Type_Body; diff --git a/src/vhdl/vhdl-sem_utils.adb b/src/vhdl/vhdl-sem_utils.adb index bb258aaf6..666fbc454 100644 --- a/src/vhdl/vhdl-sem_utils.adb +++ b/src/vhdl/vhdl-sem_utils.adb @@ -125,6 +125,7 @@ package body Vhdl.Sem_Utils is Set_Implicit_Definition (Operation, Def); Set_Identifier (Operation, Name); Set_Visible_Flag (Operation, True); + Set_Elaborated_Flag (Operation, True); Compute_Subprogram_Hash (Operation); return Operation; end Create_Implicit_Function; @@ -154,6 +155,7 @@ package body Vhdl.Sem_Utils is Set_Parent (Proc, Get_Parent (Decl)); Set_Identifier (Proc, Std_Names.Name_File_Open); Set_Visible_Flag (Proc, True); + Set_Elaborated_Flag (Proc, True); Set_Wait_State (Proc, False); Chain_Init (First_Interface, Last_Interface); case I is @@ -214,6 +216,7 @@ package body Vhdl.Sem_Utils is Set_Implicit_Definition (Proc, Iir_Predefined_File_Close); Set_Visible_Flag (Proc, True); Set_Wait_State (Proc, False); + Set_Elaborated_Flag (Proc, True); Inter := Create_Iir (Iir_Kind_Interface_File_Declaration); Set_Identifier (Inter, Std_Names.Name_F); Set_Location (Inter, Loc); @@ -239,6 +242,7 @@ package body Vhdl.Sem_Utils is Set_Parent (Proc, Get_Parent (Decl)); Set_Visible_Flag (Proc, True); Set_Wait_State (Proc, False); + Set_Elaborated_Flag (Proc, True); Chain_Init (First_Interface, Last_Interface); Inter := Create_Iir (File_Interface_Kind); Set_Identifier (Inter, Std_Names.Name_F); @@ -281,6 +285,7 @@ package body Vhdl.Sem_Utils is Set_Parent (Proc, Get_Parent (Decl)); Set_Visible_Flag (Proc, True); Set_Wait_State (Proc, False); + Set_Elaborated_Flag (Proc, True); Chain_Init (First_Interface, Last_Interface); Inter := Create_Iir (File_Interface_Kind); Set_Identifier (Inter, Std_Names.Name_F); @@ -313,6 +318,7 @@ package body Vhdl.Sem_Utils is Set_Parent (Proc, Get_Parent (Decl)); Set_Visible_Flag (Proc, True); Set_Wait_State (Proc, False); + Set_Elaborated_Flag (Proc, True); Inter := Create_Iir (File_Interface_Kind); Set_Identifier (Inter, Std_Names.Name_F); Set_Location (Inter, Loc); @@ -333,6 +339,7 @@ package body Vhdl.Sem_Utils is Set_Location (Func, Loc); Set_Parent (Func, Get_Parent (Decl)); Set_Visible_Flag (Func, True); + Set_Elaborated_Flag (Func, True); Inter := Create_Iir (File_Interface_Kind); Set_Identifier (Inter, Std_Names.Name_F); Set_Location (Inter, Loc); @@ -759,6 +766,7 @@ package body Vhdl.Sem_Utils is Set_Implicit_Definition (Deallocate_Proc, Iir_Predefined_Deallocate); Set_Parent (Deallocate_Proc, Get_Parent (Decl)); + Set_Elaborated_Flag (Deallocate_Proc, True); Var_Interface := Create_Iir (Iir_Kind_Interface_Variable_Declaration); diff --git a/src/vhdl/vhdl-std_package.adb b/src/vhdl/vhdl-std_package.adb index 40d290891..d64f6e6ec 100644 --- a/src/vhdl/vhdl-std_package.adb +++ b/src/vhdl/vhdl-std_package.adb @@ -346,6 +346,7 @@ package body Vhdl.Std_Package is Set_Std_Identifier (Decl, Name); Set_Return_Type (Decl, String_Type_Definition); Set_Pure_Flag (Decl, True); + Set_Elaborated_Flag (Decl, True); Set_Implicit_Definition (Decl, Imp); Inter := Create_Iir (Iir_Kind_Interface_Constant_Declaration); @@ -380,6 +381,7 @@ package body Vhdl.Std_Package is Set_Std_Identifier (Decl, Name); Set_Return_Type (Decl, Boolean_Type_Definition); Set_Pure_Flag (Decl, True); + Set_Elaborated_Flag (Decl, True); Set_Implicit_Definition (Decl, Func); Inter := Create_Iir (Iir_Kind_Interface_Signal_Declaration); @@ -1066,6 +1068,7 @@ package body Vhdl.Std_Package is end case; Set_Pure_Flag (Function_Now, Pure); Set_Implicit_Definition (Function_Now, Iir_Predefined_Now_Function); + Set_Elaborated_Flag (Function_Now, True); Vhdl.Sem_Utils.Compute_Subprogram_Hash (Function_Now); Add_Decl (Function_Now); end; @@ -1080,6 +1083,7 @@ package body Vhdl.Std_Package is Set_Std_Identifier (Function_Now, Std_Names.Name_Now); Set_Return_Type (Function_Now, Real_Subtype_Definition); Set_Pure_Flag (Function_Now, False); + Set_Elaborated_Flag (Function_Now, True); Set_Implicit_Definition (Function_Now, Iir_Predefined_Real_Now_Function); Vhdl.Sem_Utils.Compute_Subprogram_Hash (Function_Now); @@ -1095,6 +1099,7 @@ package body Vhdl.Std_Package is Set_Std_Identifier (Function_Freq, Std_Names.Name_Frequency); Set_Return_Type (Function_Freq, Real_Subtype_Definition); Set_Pure_Flag (Function_Freq, False); + Set_Elaborated_Flag (Function_Freq, True); Set_Implicit_Definition (Function_Freq, Iir_Predefined_Frequency_Function); Vhdl.Sem_Utils.Compute_Subprogram_Hash (Function_Freq); -- cgit v1.2.3