Patchwork [Ada] Implement AI12-0022 (raise expression)

login
register
mail settings
Submitter Arnaud Charlet
Date April 11, 2013, 10:39 a.m.
Message ID <20130411103926.GA14050@adacore.com>
Download mbox | patch
Permalink /patch/235695/
State New
Headers show

Comments

Arnaud Charlet - April 11, 2013, 10:39 a.m.
This patch implements Ada 2012 AI (AI12-0022) which intorduces a new
expression type "raiae expression". This can appear within an expression
and results in raising the given exception. Most importantly, if this
form is used in an assertion such as a precondition, it can be used to
change the exception that is signalled.

The following test, compiled with -gnata, outputs

OK 1
OK 2
OK 3

     1. pragma Ada_2012;
     2. with Text_IO; use Text_IO;
     3. procedure RaiseX is
     4.    X : Integer;
     5.
     6. begin
     7.    begin
     8.       X := 41;
     9.       if X >= 42 or else raise Tasking_Error then
    10.          raise Program_Error;
    11.       end if;
    12.    exception
    13.       when Tasking_Error =>
    14.          Put_Line ("OK 1");
    15.    end;
    16.
    17.    declare
    18.       function F (M : Integer) return Integer;
    19.       pragma Precondition (M /= 0 or else raise Storage_Error);
    20.
    21.       function F (M : Integer) return Integer is
    22.       begin
    23.          return 42 / M;
    24.       end F;
    25.
    26.    begin
    27.       X := F (0);
    28.    exception
    29.       when Storage_Error =>
    30.          Put_Line ("OK 2");
    31.    end;
    32.
    33.    declare
    34.       function F (B : Integer) return Integer is
    35.         (if B < 0 then B else raise Storage_Error);
    36.    begin
    37.       X := F (12);
    38.    exception
    39.       when Storage_Error =>
    40.          Put_Line ("OK 3");
    41.    end;
    42. end RaiseX;

Tested on x86_64-pc-linux-gnu, committed on trunk

2013-04-11  Robert Dewar  <dewar@adacore.com>

	* exp_ch11.ads, exp_ch11.adb (Expand_N_Raise_Expression): New procedure.
	* exp_util.adb (Insert_Actions): Add entry for N_Raise_Expression.
	* expander.adb: Add call to Expand_N_Raise_Expression.
	* par-ch11.adb (P_Raise_Expression): New procedure.
	* par-ch4.adb (P_Relation): Handle Raise_Expression.
	* par.adb (P_Raise_Expression): New procedure.
	* sem.adb: Add handling for N_Raise_Expression.
	* sem_ch11.ads, sem_ch11.adb (Analyze_Raise_Expression): New procedure.
	* sem_res.adb (Resolve): Add handling for N_Raise_Expression.
	* sinfo.ads, sinfo.adb (N_Raise_Expression): New node.
	* sprint.adb (Sprint_Node_Actual): Add handling for N_Raise_Expression.
	* stand.ads (Any_Type): Document use with N_Raise_Expression.

Patch

Index: exp_util.adb
===================================================================
--- exp_util.adb	(revision 197743)
+++ exp_util.adb	(working copy)
@@ -3674,6 +3674,7 @@ 
                N_Push_Storage_Error_Label               |
                N_Qualified_Expression                   |
                N_Quantified_Expression                  |
+               N_Raise_Expression                       |
                N_Range                                  |
                N_Range_Constraint                       |
                N_Real_Literal                           |
Index: sinfo.adb
===================================================================
--- sinfo.adb	(revision 197743)
+++ sinfo.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2013, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -1233,6 +1233,7 @@ 
         or else NT (N).Nkind = N_Parameter_Specification
         or else NT (N).Nkind = N_Pragma_Argument_Association
         or else NT (N).Nkind = N_Qualified_Expression
+        or else NT (N).Nkind = N_Raise_Expression
         or else NT (N).Nkind = N_Raise_Statement
         or else NT (N).Nkind = N_Simple_Return_Statement
         or else NT (N).Nkind = N_Type_Conversion
@@ -2130,6 +2131,7 @@ 
         or else NT (N).Nkind = N_Package_Renaming_Declaration
         or else NT (N).Nkind = N_Procedure_Call_Statement
         or else NT (N).Nkind = N_Procedure_Instantiation
+        or else NT (N).Nkind = N_Raise_Expression
         or else NT (N).Nkind = N_Raise_Statement
         or else NT (N).Nkind = N_Requeue_Statement
         or else NT (N).Nkind = N_Subprogram_Renaming_Declaration
@@ -4305,6 +4307,7 @@ 
         or else NT (N).Nkind = N_Parameter_Specification
         or else NT (N).Nkind = N_Pragma_Argument_Association
         or else NT (N).Nkind = N_Qualified_Expression
+        or else NT (N).Nkind = N_Raise_Expression
         or else NT (N).Nkind = N_Raise_Statement
         or else NT (N).Nkind = N_Simple_Return_Statement
         or else NT (N).Nkind = N_Type_Conversion
@@ -5202,6 +5205,7 @@ 
         or else NT (N).Nkind = N_Package_Renaming_Declaration
         or else NT (N).Nkind = N_Procedure_Call_Statement
         or else NT (N).Nkind = N_Procedure_Instantiation
+        or else NT (N).Nkind = N_Raise_Expression
         or else NT (N).Nkind = N_Raise_Statement
         or else NT (N).Nkind = N_Requeue_Statement
         or else NT (N).Nkind = N_Subprogram_Renaming_Declaration
Index: sinfo.ads
===================================================================
--- sinfo.ads	(revision 197743)
+++ sinfo.ads	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2013, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -3545,6 +3545,7 @@ 
 
       --  RELATION ::=
       --    SIMPLE_EXPRESSION [not] in MEMBERSHIP_CHOICE_LIST
+      --  | RAISE_EXPRESSION
 
       --  MEMBERSHIP_CHOICE_LIST ::=
       --    MEMBERSHIP_CHOICE {'|' MEMBERSHIP CHOICE}
@@ -6119,7 +6120,8 @@ 
 
       --  In Ada 2005, we have
 
-      --  RAISE_STATEMENT ::= raise; | raise exception_NAME [with EXPRESSION];
+      --  RAISE_STATEMENT ::=
+      --    raise; | raise exception_NAME [with string_EXPRESSION];
 
       --  N_Raise_Statement
       --  Sloc points to RAISE
@@ -6127,6 +6129,18 @@ 
       --  Expression (Node3) (set to Empty if no expression present)
       --  From_At_End (Flag4-Sem)
 
+      ----------------------------
+      -- 11.3  Raise Expression --
+      ----------------------------
+
+      --  RAISE_EXPRESSION ::= raise exception_NAME [with string_EXPRESSION]
+
+      --  N_Raise_Expression
+      --  Sloc points to RAISE
+      --  Name (Node2) (always present)
+      --  Expression (Node3) (set to Empty if no expression present)
+      --  plus fields for expression
+
       -------------------------------
       -- 12.1  Generic Declaration --
       -------------------------------
@@ -7664,6 +7678,7 @@ 
       N_Allocator,
       N_Case_Expression,
       N_Extension_Aggregate,
+      N_Raise_Expression,
       N_Range,
       N_Real_Literal,
       N_Reference,
@@ -11348,6 +11363,13 @@ 
         4 => False,   --  unused
         5 => False),  --  unused
 
+     N_Raise_Expression =>
+       (1 => False,   --  unused
+        2 => True,    --  Name (Node2)
+        3 => True,    --  Expression (Node3)
+        4 => False,   --  unused
+        5 => False),  --  Etype (Node5-Sem)
+
      N_Generic_Subprogram_Declaration =>
        (1 => True,    --  Specification (Node1)
         2 => True,    --  Generic_Formal_Declarations (List2)
Index: par-ch11.adb
===================================================================
--- par-ch11.adb	(revision 197743)
+++ par-ch11.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2013, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -199,11 +199,43 @@ 
          return Error;
    end P_Exception_Choice;
 
+   ----------------------------
+   -- 11.3  Raise Expression --
+   ----------------------------
+
+   --  RAISE_EXPRESSION ::= raise [exception_NAME [with string_EXPRESSION]]
+
+   --  The caller has verified that the initial token is RAISE
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Raise_Expression return Node_Id is
+      Raise_Node : Node_Id;
+
+   begin
+      if Ada_Version < Ada_2012 then
+         Error_Msg_SC ("raise expression is an Ada 2012 feature");
+         Error_Msg_SC ("\|unit must be compiled with -gnat2012 switch");
+      end if;
+
+      Raise_Node := New_Node (N_Raise_Expression, Token_Ptr);
+      Scan; -- past RAISE
+
+      Set_Name (Raise_Node, P_Name);
+
+      if Token = Tok_With then
+         Scan; -- past WITH
+         Set_Expression (Raise_Node, P_Expression);
+      end if;
+
+      return Raise_Node;
+   end P_Raise_Expression;
+
    ---------------------------
    -- 11.3  Raise Statement --
    ---------------------------
 
-   --  RAISE_STATEMENT ::= raise [exception_NAME];
+   --  RAISE_STATEMENT ::= raise [exception_NAME with string_EXPRESSION];
 
    --  The caller has verified that the initial token is RAISE
 
Index: sem.adb
===================================================================
--- sem.adb	(revision 197743)
+++ sem.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2013, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -470,6 +470,9 @@ 
          when N_Quantified_Expression =>
             Analyze_Quantified_Expression (N);
 
+         when N_Raise_Expression =>
+            Analyze_Raise_Expression (N);
+
          when N_Raise_Statement =>
             Analyze_Raise_Statement (N);
 
Index: par-ch4.adb
===================================================================
--- par-ch4.adb	(revision 197743)
+++ par-ch4.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2013, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -1818,6 +1818,7 @@ 
 
    --  RELATION ::=
    --    SIMPLE_EXPRESSION [not] in MEMBERSHIP_CHOICE_LIST
+   --  | RAISE_EXPRESSION
 
    --  MEMBERSHIP_CHOICE_LIST ::=
    --    MEMBERSHIP_CHOICE {'|' MEMBERSHIP CHOICE}
@@ -1825,6 +1826,8 @@ 
    --  MEMBERSHIP_CHOICE ::=
    --    CHOICE_EXPRESSION | RANGE | SUBTYPE_MARK
 
+   --  RAISE_EXPRESSION ::= raise exception_NAME [with string_EXPRESSION]
+
    --  On return, Expr_Form indicates the categorization of the expression
 
    --  Note: if Token = Tok_Apostrophe on return, then Expr_Form is set to
@@ -1839,6 +1842,15 @@ 
       Optok        : Source_Ptr;
 
    begin
+      --  First check for raise expression
+
+      if Token = Tok_Raise then
+         Expr_Form := EF_Non_Simple;
+         return P_Raise_Expression;
+      end if;
+
+      --  All other cases
+
       Node1 := P_Simple_Expression;
 
       if Token not in Token_Class_Relop then
Index: sem_res.adb
===================================================================
--- sem_res.adb	(revision 197743)
+++ sem_res.adb	(working copy)
@@ -2060,9 +2060,11 @@ 
          Analyze_Dimension (N);
          return;
 
-      --  Return if type = Any_Type (previous error encountered)
+      --  Return if type = Any_Type (previous error encountered). except that
+      --  a Raise_Expression node is OK: it is legitimately labeled this way
+      --  since it provides no information on the context.
 
-      elsif Etype (N) = Any_Type then
+      elsif Etype (N) = Any_Type and then Nkind (N) /= N_Raise_Expression then
          Debug_A_Exit ("resolving  ", N, "  (done, Etype = Any_Type)");
          return;
       end if;
@@ -2804,8 +2806,13 @@ 
             when N_Qualified_Expression
                              => Resolve_Qualified_Expression     (N, Ctx_Type);
 
+            --  Why is the following null, needs a comment ???
+
             when N_Quantified_Expression => null;
 
+            when N_Raise_Expression
+                             => Set_Etype (N, Ctx_Type);
+
             when N_Raise_xxx_Error
                              => Set_Etype (N, Ctx_Type);
 
Index: expander.adb
===================================================================
--- expander.adb	(revision 197743)
+++ expander.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2013, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -388,6 +388,9 @@ 
                   when N_Raise_Constraint_Error =>
                      Expand_N_Raise_Constraint_Error (N);
 
+                  when N_Raise_Expression =>
+                     Expand_N_Raise_Expression (N);
+
                   when N_Raise_Program_Error =>
                      Expand_N_Raise_Program_Error (N);
 
Index: par.adb
===================================================================
--- par.adb	(revision 197743)
+++ par.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2013, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -838,6 +838,7 @@ 
 
    package Ch11 is
       function P_Handled_Sequence_Of_Statements       return Node_Id;
+      function P_Raise_Expression                     return Node_Id;
       function P_Raise_Statement                      return Node_Id;
 
       function Parse_Exception_Handlers               return List_Id;
Index: exp_ch11.adb
===================================================================
--- exp_ch11.adb	(revision 197743)
+++ exp_ch11.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2013, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -1431,6 +1431,44 @@ 
       Possible_Local_Raise (N, Standard_Constraint_Error);
    end Expand_N_Raise_Constraint_Error;
 
+   -------------------------------
+   -- Expand_N_Raise_Expression --
+   -------------------------------
+
+   procedure Expand_N_Raise_Expression (N : Node_Id) is
+      Loc : constant Source_Ptr := Sloc (N);
+      Typ : constant Entity_Id  := Etype (N);
+      RCE : Node_Id;
+
+   begin
+      Possible_Local_Raise (N, Name (N));
+
+      --  Later we must teach the back end/gigi how to deal with this, but
+      --  for now we will assume the type is Standard_Boolean and transform
+      --  the node to:
+
+      --     do
+      --       raise X [with string]
+      --     in
+      --       raise Consraint_Error;
+
+      --  The raise constraint error can never be executed. It is just a dummy
+      --  node that can be labeled with an arbitrary type.
+
+      RCE := Make_Raise_Constraint_Error (Loc, Reason => CE_Explicit_Raise);
+      Set_Etype (RCE, Typ);
+
+      Rewrite (N,
+        Make_Expression_With_Actions (Loc,
+          Actions     => New_List (
+            Make_Raise_Statement (Loc,
+              Name       => Name (N),
+              Expression => Expression (N))),
+           Expression => RCE));
+
+      Analyze_And_Resolve (N, Typ);
+   end Expand_N_Raise_Expression;
+
    ----------------------------------
    -- Expand_N_Raise_Program_Error --
    ----------------------------------
Index: exp_ch11.ads
===================================================================
--- exp_ch11.ads	(revision 197743)
+++ exp_ch11.ads	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2013, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -31,6 +31,7 @@ 
    procedure Expand_N_Exception_Declaration          (N : Node_Id);
    procedure Expand_N_Handled_Sequence_Of_Statements (N : Node_Id);
    procedure Expand_N_Raise_Constraint_Error         (N : Node_Id);
+   procedure Expand_N_Raise_Expression               (N : Node_Id);
    procedure Expand_N_Raise_Program_Error            (N : Node_Id);
    procedure Expand_N_Raise_Statement                (N : Node_Id);
    procedure Expand_N_Raise_Storage_Error            (N : Node_Id);
Index: stand.ads
===================================================================
--- stand.ads	(revision 197743)
+++ stand.ads	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2013, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -362,11 +362,26 @@ 
    --  identifier references to prevent cascaded errors.
 
    Any_Type : Entity_Id;
-   --  Used to represent some unknown type. Plays an important role in
-   --  avoiding cascaded errors, since any node that remains labeled with
-   --  this type corresponds to an already issued error message. Any_Type
-   --  is propagated to avoid cascaded errors from a single type error.
+   --  Used to represent some unknown type. Any_Type is the type of an
+   --  unresolved operator, and it is the type of a node where a type error
+   --  has been detected.  Any_Type plays an important role in avoiding
+   --  cascaded errors, because it is compatible with all other types, and is
+   --  propagated to any expression that has a subexpression of Any_Type.
+   --  When resolving operators, Any_Type is the initial type of the node
+   --  before any of its candidate interpretations has been examined. If after
+   --  examining all of them the type is still Any_Type, the node has no
+   --  possible interpretation and an error can be emitted (and Any_Type will
+   --  be propagated upwards).
 
+   --  There is one situation in which Any_Type is used to legitimately
+   --  represent a case where the type is not known pre-resolution, and
+   --  that is for the N_Raise_Expression node. In this case, the Etype
+   --  being set to Any_Type is normal and does not represent an error.
+   --  In particular, it is compatible with the type of any constituend of
+   --  the enclosing expression, if any.  The type is eventually replaced
+   --  with the type of the context, which plays no role in the resolution
+   --  of the Raise_Expression.
+
    Any_Access : Entity_Id;
    --  Used to resolve the overloaded literal NULL
 
Index: sem_ch11.adb
===================================================================
--- sem_ch11.adb	(revision 197743)
+++ sem_ch11.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2013, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -424,6 +424,60 @@ 
       end if;
    end Analyze_Handled_Statements;
 
+   ------------------------------
+   -- Analyze_Raise_Expression --
+   ------------------------------
+
+   procedure Analyze_Raise_Expression (N : Node_Id) is
+      Exception_Id   : constant Node_Id := Name (N);
+      Exception_Name : Entity_Id        := Empty;
+
+   begin
+      Check_SPARK_Restriction ("raise expression is not allowed", N);
+
+      --  Check exception restrictions on the original source
+
+      if Comes_From_Source (N) then
+         Check_Restriction (No_Exceptions, N);
+      end if;
+
+      Analyze (Exception_Id);
+
+      if Is_Entity_Name (Exception_Id) then
+         Exception_Name := Entity (Exception_Id);
+      end if;
+
+      if No (Exception_Name)
+        or else Ekind (Exception_Name) /= E_Exception
+      then
+         Error_Msg_N
+           ("exception name expected in raise statement", Exception_Id);
+      else
+         Set_Is_Raised (Exception_Name);
+      end if;
+
+      --  Deal with RAISE WITH case
+
+      if Present (Expression (N)) then
+         Check_Compiler_Unit (Expression (N));
+         Analyze_And_Resolve (Expression (N), Standard_String);
+      end if;
+
+      --  Check obsolescent use of Numeric_Error
+
+      if Exception_Name = Standard_Numeric_Error then
+         Check_Restriction (No_Obsolescent_Features, Exception_Id);
+      end if;
+
+      --  Kill last assignment indication
+
+      Kill_Current_Values (Last_Assignment_Only => True);
+
+      --  Set type as Any_Type since we have no information at all on the type
+
+      Set_Etype (N, Any_Type);
+   end Analyze_Raise_Expression;
+
    -----------------------------
    -- Analyze_Raise_Statement --
    -----------------------------
Index: sem_ch11.ads
===================================================================
--- sem_ch11.ads	(revision 197743)
+++ sem_ch11.ads	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 1992-2007, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2013, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -27,6 +27,7 @@ 
 package Sem_Ch11 is
    procedure Analyze_Exception_Declaration              (N : Node_Id);
    procedure Analyze_Handled_Statements                 (N : Node_Id);
+   procedure Analyze_Raise_Expression                   (N : Node_Id);
    procedure Analyze_Raise_Statement                    (N : Node_Id);
    procedure Analyze_Raise_xxx_Error                    (N : Node_Id);
    procedure Analyze_Subprogram_Info                    (N : Node_Id);
Index: sprint.adb
===================================================================
--- sprint.adb	(revision 197743)
+++ sprint.adb	(working copy)
@@ -1993,6 +1993,7 @@ 
                if not Has_Parens then
                   Write_Char ('(');
                end if;
+
                Write_Str_With_Col_Check_Sloc ("if ");
                Sprint_Node (Condition);
                Write_Str_With_Col_Check (" then ");
@@ -2763,6 +2764,32 @@ 
             Write_Str (" => ");
             Sprint_Node (Condition (Node));
 
+         when N_Raise_Expression =>
+            declare
+               Has_Parens : constant Boolean := Paren_Count (Node) > 0;
+
+            begin
+               --  The syntax for raise_expression does not include parentheses
+               --  but sometimes parentheses are required, so unconditionally
+               --  generate them here unless already present.
+
+               if not Has_Parens then
+                  Write_Char ('(');
+               end if;
+
+               Write_Str_With_Col_Check_Sloc ("raise ");
+               Sprint_Node (Name (Node));
+
+               if Present (Expression (Node)) then
+                  Write_Str_With_Col_Check (" with ");
+                  Sprint_Node (Expression (Node));
+               end if;
+
+               if not Has_Parens then
+                  Write_Char (')');
+               end if;
+            end;
+
          when N_Raise_Constraint_Error =>
 
             --  This node can be used either as a subexpression or as a