Variant gcc-15-16
Applies to 15.3.0, 16.1.0, 16.2.0. Source flavors: linux, darwin_arm64.
+245 −0 2 files
gcc/ada/exp_util.adb
+88−0modified
| @@ -12344 +12344 @@ | |||
| 12344 | 12344 | -- that other side effects related to volatile variables are handled | |
| 12345 | 12345 | -- separately. | |
| 12346 | 12346 | | |
| 12347 | Added line. procedure Undelay_Conditional_Expression (N : Node_Id); | ||
| 12348 | Added line. -- N is a conditional expression whose expansion has been delayed, | ||
| 12349 | Added line. -- possibly wrapped in qualified expressions. Cancel the delay for N | ||
| 12350 | Added line. -- and for its dependent expressions, and schedule them for reanalysis. | ||
| 12351 | Added line. | ||
| 12347 | 12352 | --------------------- | |
| 12348 | 12353 | -- Build_Temporary -- | |
| 12349 | 12354 | --------------------- | |
| @@ -12467 +12472 @@ | |||
| 12467 | 12472 | end if; | |
| 12468 | 12473 | end Possible_Side_Effect_In_SPARK; | |
| 12469 | 12474 | | |
| 12475 | Added line. ------------------------------------ | ||
| 12476 | Added line. -- Undelay_Conditional_Expression -- | ||
| 12477 | Added line. ------------------------------------ | ||
| 12478 | Added line. | ||
| 12479 | Added line. procedure Undelay_Conditional_Expression (N : Node_Id) is | ||
| 12480 | Added line. | ||
| 12481 | Added line. procedure Undelay_Dependent_Expression (Expr : Node_Id); | ||
| 12482 | Added line. -- Cancel the delayed expansion of the dependent expression Expr | ||
| 12483 | Added line. | ||
| 12484 | Added line. ---------------------------------- | ||
| 12485 | Added line. -- Undelay_Dependent_Expression -- | ||
| 12486 | Added line. ---------------------------------- | ||
| 12487 | Added line. | ||
| 12488 | Added line. procedure Undelay_Dependent_Expression (Expr : Node_Id) is | ||
| 12489 | Added line. begin | ||
| 12490 | Added line. if Is_Delayed_Aggregate (Expr) then | ||
| 12491 | Added line. if Nkind (Expr) = N_Qualified_Expression then | ||
| 12492 | Added line. Set_Expansion_Delayed (Expression (Expr), False); | ||
| 12493 | Added line. Set_Analyzed (Expression (Expr), False); | ||
| 12494 | Added line. else | ||
| 12495 | Added line. Set_Expansion_Delayed (Expr, False); | ||
| 12496 | Added line. end if; | ||
| 12497 | Added line. | ||
| 12498 | Added line. Set_Analyzed (Expr, False); | ||
| 12499 | Added line. | ||
| 12500 | Added line. elsif Is_Delayed_Conditional_Expression (Expr) then | ||
| 12501 | Added line. Undelay_Conditional_Expression (Expr); | ||
| 12502 | Added line. end if; | ||
| 12503 | Added line. end Undelay_Dependent_Expression; | ||
| 12504 | Added line. | ||
| 12505 | Added line. -- Local variables | ||
| 12506 | Added line. | ||
| 12507 | Added line. Alt : Node_Id; | ||
| 12508 | Added line. Expr : Node_Id := N; | ||
| 12509 | Added line. | ||
| 12510 | Added line. -- Start of processing for Undelay_Conditional_Expression | ||
| 12511 | Added line. | ||
| 12512 | Added line. begin | ||
| 12513 | Added line. -- Is_Delayed_Conditional_Expression looks through qualified | ||
| 12514 | Added line. -- expressions surrounding conditional expressions, so we need to | ||
| 12515 | Added line. -- reset the Analyzed flag on them as well. | ||
| 12516 | Added line. | ||
| 12517 | Added line. loop | ||
| 12518 | Added line. Set_Analyzed (Expr, False); | ||
| 12519 | Added line. | ||
| 12520 | Added line. exit when Nkind (Expr) in N_Case_Expression | N_If_Expression; | ||
| 12521 | Added line. | ||
| 12522 | Added line. pragma Assert (Nkind (Expr) = N_Qualified_Expression); | ||
| 12523 | Added line. Expr := Expression (Expr); | ||
| 12524 | Added line. end loop; | ||
| 12525 | Added line. | ||
| 12526 | Added line. Set_Expansion_Delayed (Expr, False); | ||
| 12527 | Added line. | ||
| 12528 | Added line. -- The dependent expressions have been delayed along with the | ||
| 12529 | Added line. -- conditional expression itself, so they must be undelayed too. | ||
| 12530 | Added line. | ||
| 12531 | Added line. if Nkind (Expr) = N_If_Expression then | ||
| 12532 | Added line. Alt := Next (First (Expressions (Expr))); | ||
| 12533 | Added line. | ||
| 12534 | Added line. while Present (Alt) loop | ||
| 12535 | Added line. Undelay_Dependent_Expression (Alt); | ||
| 12536 | Added line. Next (Alt); | ||
| 12537 | Added line. end loop; | ||
| 12538 | Added line. | ||
| 12539 | Added line. else | ||
| 12540 | Added line. Alt := First (Alternatives (Expr)); | ||
| 12541 | Added line. | ||
| 12542 | Added line. while Present (Alt) loop | ||
| 12543 | Added line. Undelay_Dependent_Expression (Expression (Alt)); | ||
| 12544 | Added line. Next (Alt); | ||
| 12545 | Added line. end loop; | ||
| 12546 | Added line. end if; | ||
| 12547 | Added line. end Undelay_Conditional_Expression; | ||
| 12548 | Added line. | ||
| 12470 | 12549 | -- Local variables | |
| 12471 | 12550 | | |
| 12472 | 12551 | Loc : constant Source_Ptr := Sloc (Exp); | |
| @@ -12875 +12954 @@ | |||
| 12875 | 12954 | end if; | |
| 12876 | 12955 | | |
| 12877 | 12956 | Set_Analyzed (E, False); | |
| 12957 | Added line. | ||
| 12958 | Added line. -- The expansion of a conditional expression is likewise delayed | ||
| 12959 | Added line. -- when one of its dependent expressions is a nested aggregate, and | ||
| 12960 | Added line. -- is then driven by the parent construct. The reference built just | ||
| 12961 | Added line. -- above is not such a construct, so the conditional expression and | ||
| 12962 | Added line. -- its dependent expressions must be fully expanded here as well. | ||
| 12963 | Added line. | ||
| 12964 | Added line. elsif Is_Delayed_Conditional_Expression (E) then | ||
| 12965 | Added line. Undelay_Conditional_Expression (E); | ||
| 12878 | 12966 | end if; | |
| 12879 | 12967 | | |
| 12880 | 12968 | Insert_Action (Exp, | |
gcc/testsuite/gnat.dg/predicate_conditional_aggregate_box.adb
+157−0new file
| @@ -0 +1 @@ | |||
| 1 | Added line. -- { dg-do run } | ||
| 2 | Added line. -- { dg-options "-O2 -gnat2022" } | ||
| 3 | Added line. | ||
| 4 | Added line. pragma Assertion_Policy (Dynamic_Predicate => Check); | ||
| 5 | Added line. | ||
| 6 | Added line. with Ada.Assertions; use Ada.Assertions; | ||
| 7 | Added line. with Ada.Text_IO; use Ada.Text_IO; | ||
| 8 | Added line. | ||
| 9 | Added line. procedure Predicate_Conditional_Aggregate_Box is | ||
| 10 | Added line. | ||
| 11 | Added line. type Policy is record | ||
| 12 | Added line. Low : Natural := 1; | ||
| 13 | Added line. High : Natural := 25; | ||
| 14 | Added line. end record | ||
| 15 | Added line. with Dynamic_Predicate => Policy.High >= Policy.Low; | ||
| 16 | Added line. | ||
| 17 | Added line. type Config is record | ||
| 18 | Added line. Watch : Policy; | ||
| 19 | Added line. end record; | ||
| 20 | Added line. | ||
| 21 | Added line. Static_Flag : constant Boolean := True; | ||
| 22 | Added line. | ||
| 23 | Added line. Enforced : Natural := 0; | ||
| 24 | Added line. -- Number of predicate violations reported at run time | ||
| 25 | Added line. | ||
| 26 | Added line. function Ident (Value : Boolean) return Boolean; | ||
| 27 | Added line. -- Identity function, used to keep the condition of a conditional | ||
| 28 | Added line. -- expression from being known at compile time. | ||
| 29 | Added line. | ||
| 30 | Added line. procedure Check (Label : String; Actual, Expected : Natural); | ||
| 31 | Added line. -- Report a mismatch between an observed and an expected component value | ||
| 32 | Added line. | ||
| 33 | Added line. procedure Verify (C : Config; Label : String; Low, High : Natural); | ||
| 34 | Added line. -- Check both components of the inner record of C | ||
| 35 | Added line. | ||
| 36 | Added line. ----------- | ||
| 37 | Added line. -- Check -- | ||
| 38 | Added line. ----------- | ||
| 39 | Added line. | ||
| 40 | Added line. procedure Check (Label : String; Actual, Expected : Natural) is | ||
| 41 | Added line. begin | ||
| 42 | Added line. if Actual /= Expected then | ||
| 43 | Added line. raise Program_Error with | ||
| 44 | Added line. Label & " is" & Natural'Image (Actual) | ||
| 45 | Added line. & " instead of" & Natural'Image (Expected); | ||
| 46 | Added line. end if; | ||
| 47 | Added line. end Check; | ||
| 48 | Added line. | ||
| 49 | Added line. ----------- | ||
| 50 | Added line. -- Ident -- | ||
| 51 | Added line. ----------- | ||
| 52 | Added line. | ||
| 53 | Added line. function Ident (Value : Boolean) return Boolean is | ||
| 54 | Added line. begin | ||
| 55 | Added line. return Value; | ||
| 56 | Added line. end Ident; | ||
| 57 | Added line. | ||
| 58 | Added line. ------------ | ||
| 59 | Added line. -- Verify -- | ||
| 60 | Added line. ------------ | ||
| 61 | Added line. | ||
| 62 | Added line. procedure Verify (C : Config; Label : String; Low, High : Natural) is | ||
| 63 | Added line. begin | ||
| 64 | Added line. Check (Label & " low", C.Watch.Low, Low); | ||
| 65 | Added line. Check (Label & " high", C.Watch.High, High); | ||
| 66 | Added line. end Verify; | ||
| 67 | Added line. | ||
| 68 | Added line. begin | ||
| 69 | Added line. -- A box in a branch of a conditional expression that is a component | ||
| 70 | Added line. -- association of an enclosing aggregate must supply the component | ||
| 71 | Added line. -- defaults of the inner record type, here High => 25. | ||
| 72 | Added line. | ||
| 73 | Added line. -- Static condition, others box, object declaration | ||
| 74 | Added line. | ||
| 75 | Added line. declare | ||
| 76 | Added line. C : constant Config := | ||
| 77 | Added line. (Watch => (if Static_Flag then (Low => 1, others => <>) | ||
| 78 | Added line. else (Low => 2, others => <>))); | ||
| 79 | Added line. begin | ||
| 80 | Added line. Verify (C, "static others box", Low => 1, High => 25); | ||
| 81 | Added line. end; | ||
| 82 | Added line. | ||
| 83 | Added line. -- Dynamic condition, named component box, object declaration | ||
| 84 | Added line. | ||
| 85 | Added line. declare | ||
| 86 | Added line. C : constant Config := | ||
| 87 | Added line. (Watch => (if Ident (True) then (Low => 3, High => <>) | ||
| 88 | Added line. else (Low => 4, High => <>))); | ||
| 89 | Added line. begin | ||
| 90 | Added line. Verify (C, "dynamic named box", Low => 3, High => 25); | ||
| 91 | Added line. end; | ||
| 92 | Added line. | ||
| 93 | Added line. -- Dynamic condition, others box, assignment statement | ||
| 94 | Added line. | ||
| 95 | Added line. declare | ||
| 96 | Added line. C : Config; | ||
| 97 | Added line. begin | ||
| 98 | Added line. C := (Watch => (if Ident (False) then (Low => 5, others => <>) | ||
| 99 | Added line. else (Low => 6, others => <>))); | ||
| 100 | Added line. Verify (C, "assigned others box", Low => 6, High => 25); | ||
| 101 | Added line. end; | ||
| 102 | Added line. | ||
| 103 | Added line. -- Dynamic condition, named component box, assignment statement | ||
| 104 | Added line. | ||
| 105 | Added line. declare | ||
| 106 | Added line. C : Config; | ||
| 107 | Added line. begin | ||
| 108 | Added line. C := (Watch => (if Ident (True) then (Low => 7, High => <>) | ||
| 109 | Added line. else (Low => 8, High => <>))); | ||
| 110 | Added line. Verify (C, "assigned named box", Low => 7, High => 25); | ||
| 111 | Added line. end; | ||
| 112 | Added line. | ||
| 113 | Added line. -- Case expression, others box, object declaration | ||
| 114 | Added line. | ||
| 115 | Added line. declare | ||
| 116 | Added line. C : constant Config := | ||
| 117 | Added line. (Watch => (case Ident (True) is | ||
| 118 | Added line. when True => (Low => 9, others => <>), | ||
| 119 | Added line. when False => (Low => 10, others => <>))); | ||
| 120 | Added line. begin | ||
| 121 | Added line. Verify (C, "case others box", Low => 9, High => 25); | ||
| 122 | Added line. end; | ||
| 123 | Added line. | ||
| 124 | Added line. -- The predicate must still be enforced on the selected branch, in an | ||
| 125 | Added line. -- object declaration and in an assignment statement alike. The defaulted | ||
| 126 | Added line. -- High is 25, so a Low above it violates Policy.High >= Policy.Low. | ||
| 127 | Added line. | ||
| 128 | Added line. begin | ||
| 129 | Added line. declare | ||
| 130 | Added line. C : constant Config := | ||
| 131 | Added line. (Watch => (if Ident (True) then (Low => 30, others => <>) | ||
| 132 | Added line. else (Low => 2, others => <>))); | ||
| 133 | Added line. begin | ||
| 134 | Added line. Verify (C, "unenforced declaration", Low => 30, High => 25); | ||
| 135 | Added line. end; | ||
| 136 | Added line. exception | ||
| 137 | Added line. when Assertion_Error => | ||
| 138 | Added line. Enforced := Enforced + 1; | ||
| 139 | Added line. end; | ||
| 140 | Added line. | ||
| 141 | Added line. begin | ||
| 142 | Added line. declare | ||
| 143 | Added line. C : Config; | ||
| 144 | Added line. begin | ||
| 145 | Added line. C := (Watch => (if Ident (False) then (Low => 1, others => <>) | ||
| 146 | Added line. else (Low => 40, High => <>))); | ||
| 147 | Added line. Verify (C, "unenforced assignment", Low => 40, High => 25); | ||
| 148 | Added line. end; | ||
| 149 | Added line. exception | ||
| 150 | Added line. when Assertion_Error => | ||
| 151 | Added line. Enforced := Enforced + 1; | ||
| 152 | Added line. end; | ||
| 153 | Added line. | ||
| 154 | Added line. Check ("enforced predicate violations", Enforced, 2); | ||
| 155 | Added line. | ||
| 156 | Added line. Put_Line ("PASS predicate conditional aggregate box"); | ||
| 157 | Added line. end Predicate_Conditional_Aggregate_Box; | ||
| 158 | | ||