From: Tucker Taft <t...@adacore.com> In the Expression_Image function, we were not inserting parentheses properly when there was a sequence of and and or operators, even though Ada requires such parentheses to show the correct order of association.
gcc/ada/ChangeLog: * pprint.adb (Expression_Image): In local function Expr_Name add a No_Parens flag and define a subtype Not_Associative to represent the short-circuit operations and And/Or/Xor. Insert parentheses to separate the subexpressions when different "Not_Associative" operations occur in a sequence. Tested on x86_64-pc-linux-gnu, committed on master. --- gcc/ada/pprint.adb | 53 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/gcc/ada/pprint.adb b/gcc/ada/pprint.adb index b5935fcb0b4..5958a6b47b2 100644 --- a/gcc/ada/pprint.adb +++ b/gcc/ada/pprint.adb @@ -57,12 +57,16 @@ package body Pprint is function Expr_Name (Expr : Node_Id; Take_Prefix : Boolean := True; - Expand_Type : Boolean := True) return String; + Expand_Type : Boolean := True; + No_Parens : Boolean := False) return String; -- Return string corresponding to Expr. If no string can be extracted, -- return "...". If Take_Prefix is True, go back to prefix when needed, -- otherwise only consider the right-hand side of an expression. If -- Expand_Type is True and Expr is a type, try to expand Expr (an -- internally generated type) into a user understandable name. + -- If No_Parens is True, then suppress creating parentheses + -- around expression. If False, check to see whether expression + -- should be parenthesized. function Count_Parentheses (S : String; C : Character) return Natural with Pre => C in '(' | ')'; @@ -70,6 +74,8 @@ package body Pprint is -- to string S for getting a correctly parenthesized result. For C = '(' -- this means prepending the character, for C = ')' this means appending -- the character. + -- In other words, count the number of missing instances of C, + -- but never return less than zero. function Fix_Parentheses (S : String) return String; -- Counts the number of required opening and closing parentheses in S to @@ -101,6 +107,7 @@ package body Pprint is Elmt : Node_Id; Printed_Elmts : Natural := 0; + List_Len : constant Natural := Natural (List_Length (List)); begin -- Give up if the printed list is too deep @@ -146,7 +153,8 @@ package body Pprint is -- Print expression itself as "12345" else - Append (Buf, Expr_Name (Elmt)); + Append (Buf, Expr_Name (Elmt, No_Parens => List_Len = 1)); + -- Suppress parens if is the only parameter. end if; Next (Elmt); @@ -178,9 +186,32 @@ package body Pprint is function Expr_Name (Expr : Node_Id; Take_Prefix : Boolean := True; - Expand_Type : Boolean := True) return String + Expand_Type : Boolean := True; + No_Parens : Boolean := False) return String is + -- Define subtype matching logical operations + -- and [then], or [else], and xor. + subtype Not_Associative is N_Subexpr + with Static_Predicate => + Not_Associative in + N_Short_Circuit | N_Op_And | N_Op_Or | N_Op_Xor; begin + if not No_Parens + and then + (Paren_Count (Expr) > 0 + or else + (Nkind (Expr) in Not_Associative + and then + Nkind (Parent (Expr)) in Not_Associative + and then + Nkind (Parent (Expr)) /= Nkind (Expr))) + then + -- Parentheses are needed + return '(' & + Expr_Name (Expr, Take_Prefix, Expand_Type, No_Parens => True) & + ')'; + end if; + Num_Elements := Num_Elements + 1; if Num_Elements > Max_Expr_Elements then @@ -589,7 +620,9 @@ package body Pprint is return "abs " & Expr_Name (Right_Opnd (Expr)); when N_Op_Not => - return "not (" & Expr_Name (Right_Opnd (Expr)) & ")"; + return "not (" & + Expr_Name (Right_Opnd (Expr), No_Parens => True) & + ")"; when N_Type_Conversion => @@ -608,7 +641,9 @@ package body Pprint is Is_Modular_Integer_Type (Etype (Expression (Expr))) then return Expr_Name (Subtype_Mark (Expr)) & - "(" & Expr_Name (Expression (Expr)) & ")"; + "(" & + Expr_Name (Expression (Expr), No_Parens => True) & + ")"; else return Expr_Name (Expression (Expr)); end if; @@ -636,7 +671,9 @@ package body Pprint is & List_Name (Parameter_Associations (Expr)) & "))"; else - return '(' & Expr_Name (Name (Expr)) & ')'; + return '(' & + Expr_Name (Name (Expr), No_Parens => True) & + ')'; end if; elsif Present (Parameter_Associations (Expr)) then return @@ -676,6 +713,8 @@ package body Pprint is -- Process next character Ch and update the number Count of C -- characters to add for correct parenthesizing, where D is the -- opposite parenthesis. + -- In other words, count the number of missing instances of C, + -- or equivalently, the number of unmatched instances of D. --------------- -- Next_Char -- @@ -775,7 +814,7 @@ package body Pprint is or else Opt.Debug_Generated_Code then declare - S : constant String := Expr_Name (Expr); + S : constant String := Expr_Name (Expr, No_Parens => True); begin if S = "..." then return Default; -- 2.43.0