diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 9246f26e09d544937447061e619e3b2b8086366d..5105950589c86218e459a5146ee3b84251fc1087 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,50 @@
+2001-03-28  Robert Dewar <dewar@gnat.com>
+
+	* checks.ads:
+	(Remove_Checks): New procedure
+
+	* checks.adb:
+	(Remove_Checks): New procedure
+
+	* exp_util.adb:
+	Use new Duplicate_Subexpr functions
+	(Duplicate_Subexpr_No_Checks): New procedure
+	(Duplicate_Subexpr_No_Checks_Orig): New procedure
+	(Duplicate_Subexpr): Restore original form (checks duplicated)
+	(Duplicate_Subexpr): Call Remove_Checks
+
+	* exp_util.ads: 
+	(Duplicate_Subexpr_No_Checks): New procedure
+	(Duplicate_Subexpr_No_Checks_Orig): New procedure
+	Add 2002 to copyright notice
+
+	* sem_util.adb: Use new Duplicate_Subexpr functions
+
+	* sem_eval.adb: 	
+	(Eval_Indexed_Component): This is the place to call
+	Constant_Array_Ref and to replace the value. We simply merge
+	the code of this function in here, since it is now no longer
+	used elsewhere. This fixes the problem of the back end not
+	realizing we were clever enough to see that this was
+	constant.
+	(Expr_Val): Remove call to Constant_Array_Ref
+	(Expr_Rep_Val): Remove call to Constant_Array_Ref
+	Minor reformatting
+	(Constant_Array_Ref): Deal with string literals (patch
+	suggested by Zack Weinberg on the gcc list)
+
+2001-03-28  Ed Schonberg <schonber@gnat.com>
+
+	* exp_util.adb: Duplicate_Subexpr_No_Checks_Orig => 
+	Duplicate_Subexpr_Move_Checks.
+
+	* exp_util.ads: Duplicate_Subexpr_No_Checks_Orig => 
+	Duplicate_Subexpr_Move_Checks.
+
+	* sem_eval.adb: (Constant_Array_Ref): Verify that constant 
+	value of array exists before retrieving it (it may a private 
+	protected component in a function).
+
 2002-03-28   Geert Bosch <bosch@gnat.com>
 
 	* prj-pp.adb : New file.
diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb
index 5442819566bf6589217442d27ae393ab43aaa07e..327f1cc751bca6c6cac53701378712cc7b979e1c 100644
--- a/gcc/ada/checks.adb
+++ b/gcc/ada/checks.adb
@@ -2918,6 +2918,104 @@ package body Checks is
         or else Vax_Float (E);
    end Range_Checks_Suppressed;
 
+   -------------------
+   -- Remove_Checks --
+   -------------------
+
+   procedure Remove_Checks (Expr : Node_Id) is
+      Discard : Traverse_Result;
+
+      function Process (N : Node_Id) return Traverse_Result;
+      --  Process a single node during the traversal
+
+      function Traverse is new Traverse_Func (Process);
+      --  The traversal function itself
+
+      -------------
+      -- Process --
+      -------------
+
+      function Process (N : Node_Id) return Traverse_Result is
+      begin
+         if Nkind (N) not in N_Subexpr then
+            return Skip;
+         end if;
+
+         Set_Do_Range_Check (N, False);
+
+         case Nkind (N) is
+            when N_And_Then =>
+               Discard := Traverse (Left_Opnd (N));
+               return Skip;
+
+            when N_Attribute_Reference =>
+               Set_Do_Access_Check (N, False);
+               Set_Do_Overflow_Check (N, False);
+
+            when N_Explicit_Dereference =>
+               Set_Do_Access_Check (N, False);
+
+            when N_Function_Call =>
+               Set_Do_Tag_Check (N, False);
+
+            when N_Indexed_Component =>
+               Set_Do_Access_Check (N, False);
+
+            when N_Op =>
+               Set_Do_Overflow_Check (N, False);
+
+               case Nkind (N) is
+                  when N_Op_Divide =>
+                     Set_Do_Division_Check (N, False);
+
+                  when N_Op_And =>
+                     Set_Do_Length_Check (N, False);
+
+                  when N_Op_Mod =>
+                     Set_Do_Division_Check (N, False);
+
+                  when N_Op_Or =>
+                     Set_Do_Length_Check (N, False);
+
+                  when N_Op_Rem =>
+                     Set_Do_Division_Check (N, False);
+
+                  when N_Op_Xor =>
+                     Set_Do_Length_Check (N, False);
+
+                  when others =>
+                     null;
+               end case;
+
+            when N_Or_Else =>
+               Discard := Traverse (Left_Opnd (N));
+               return Skip;
+
+            when N_Selected_Component =>
+               Set_Do_Access_Check (N, False);
+               Set_Do_Discriminant_Check (N, False);
+
+            when N_Slice =>
+               Set_Do_Access_Check (N, False);
+
+            when N_Type_Conversion =>
+               Set_Do_Length_Check (N, False);
+               Set_Do_Overflow_Check (N, False);
+               Set_Do_Tag_Check (N, False);
+
+            when others =>
+               null;
+         end case;
+
+         return OK;
+      end Process;
+
+   --  Start of processing for Remove_Checks
+
+   begin
+      Discard := Traverse (Expr);
+   end Remove_Checks;
+
    ----------------------------
    -- Selected_Length_Checks --
    ----------------------------
diff --git a/gcc/ada/checks.ads b/gcc/ada/checks.ads
index df2c4624359d07d5d0d8eacc6ac16cc71de0c519..e35e889e0bf0dde77f3c40ba5b046ebd72d96e08 100644
--- a/gcc/ada/checks.ads
+++ b/gcc/ada/checks.ads
@@ -496,6 +496,11 @@ package Checks is
    --  the sense of the 'Valid attribute returning True. Constraint_Error
    --  will be raised if the value is not valid.
 
+   procedure Remove_Checks (Expr : Node_Id);
+   --  Remove all checks from Expr except those that are only executed
+   --  conditionally (on the right side of And Then/Or Else. This call
+   --  removes only embedded checks (Do_Range_Check, Do_Overflow_Check).
+
 private
 
    type Check_Result is array (Positive range 1 .. 2) of Node_Id;
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index e998553366921e10950411d4264cdbbd368b65a2..1acd0df0c2b328b317b9e01dd5654367728b8383 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -969,6 +969,42 @@ package body Exp_Util is
       return New_Copy_Tree (Exp);
    end Duplicate_Subexpr;
 
+   ---------------------------------
+   -- Duplicate_Subexpr_No_Checks --
+   ---------------------------------
+
+   function Duplicate_Subexpr_No_Checks
+     (Exp      : Node_Id;
+      Name_Req : Boolean := False)
+      return     Node_Id
+   is
+      New_Exp : Node_Id;
+
+   begin
+      Remove_Side_Effects (Exp, Name_Req);
+      New_Exp := New_Copy_Tree (Exp);
+      Remove_Checks (New_Exp);
+      return New_Exp;
+   end Duplicate_Subexpr_No_Checks;
+
+   -----------------------------------
+   -- Duplicate_Subexpr_Move_Checks --
+   -----------------------------------
+
+   function Duplicate_Subexpr_Move_Checks
+     (Exp      : Node_Id;
+      Name_Req : Boolean := False)
+      return     Node_Id
+   is
+      New_Exp : Node_Id;
+
+   begin
+      Remove_Side_Effects (Exp, Name_Req);
+      New_Exp := New_Copy_Tree (Exp);
+      Remove_Checks (Exp);
+      return New_Exp;
+   end Duplicate_Subexpr_Move_Checks;
+
    --------------------
    -- Ensure_Defined --
    --------------------
@@ -2310,7 +2346,8 @@ package body Exp_Util is
         Make_Op_Subtract (Loc,
           Left_Opnd =>
             Make_Attribute_Reference (Loc,
-              Prefix         => OK_Convert_To (T, Duplicate_Subexpr (E)),
+              Prefix =>
+                OK_Convert_To (T, Duplicate_Subexpr_No_Checks (E)),
               Attribute_Name => Name_Size),
           Right_Opnd =>
             Make_Attribute_Reference (Loc,
@@ -2452,7 +2489,9 @@ package body Exp_Util is
          Utyp        := Underlying_Type (Unc_Typ);
          Full_Subtyp := Make_Defining_Identifier (Loc,
                           New_Internal_Name ('C'));
-         Full_Exp    := Unchecked_Convert_To (Utyp, Duplicate_Subexpr (E));
+         Full_Exp    :=
+           Unchecked_Convert_To
+             (Utyp, Duplicate_Subexpr_No_Checks (E));
          Set_Parent (Full_Exp, Parent (E));
 
          Priv_Subtyp :=
@@ -2490,13 +2529,14 @@ package body Exp_Util is
               Make_Range (Loc,
                 Low_Bound =>
                   Make_Attribute_Reference (Loc,
-                    Prefix => Duplicate_Subexpr (E),
+                    Prefix => Duplicate_Subexpr_No_Checks (E),
                     Attribute_Name => Name_First,
                     Expressions => New_List (
                       Make_Integer_Literal (Loc, J))),
+
                 High_Bound =>
                   Make_Attribute_Reference (Loc,
-                    Prefix         => Duplicate_Subexpr (E),
+                    Prefix         => Duplicate_Subexpr_No_Checks (E),
                     Attribute_Name => Name_Last,
                     Expressions    => New_List (
                       Make_Integer_Literal (Loc, J)))));
@@ -2530,7 +2570,7 @@ package body Exp_Util is
 
             Append_To (List_Constr,
               Make_Selected_Component (Loc,
-                Prefix        => Duplicate_Subexpr (E),
+                Prefix        => Duplicate_Subexpr_No_Checks (E),
                 Selector_Name => New_Reference_To (D, Loc)));
 
             Next_Discriminant (D);
diff --git a/gcc/ada/exp_util.ads b/gcc/ada/exp_util.ads
index 3c215b0f2d4986fa304a5c9c940e6ba50365c174..c83b97ef1e01a5f33e13db374debfc0d3c285b33 100644
--- a/gcc/ada/exp_util.ads
+++ b/gcc/ada/exp_util.ads
@@ -7,7 +7,7 @@
 --                                 S p e c                                  --
 --                                                                          --
 --                                                                          --
---          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--          Copyright (C) 1992-2002 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- --
@@ -243,6 +243,32 @@ package Exp_Util is
    --  copy after it is attached to the tree. The Name_Req flag is set to
    --  ensure that the result is suitable for use in a context requiring a
    --  name (e.g. the prefix of an attribute reference).
+   --
+   --  Note that if there are any run time checks in Exp, these same checks
+   --  will be duplicated in the returned duplicated expression. The two
+   --  following functions allow this behavior to be modified.
+
+   function Duplicate_Subexpr_No_Checks
+     (Exp      : Node_Id;
+      Name_Req : Boolean := False)
+      return     Node_Id;
+   --  Identical in effect to Duplicate_Subexpr, except that Remove_Checks
+   --  is called on the result, so that the duplicated expression does not
+   --  include checks. This is appropriate for use when Exp, the original
+   --  expression is unconditionally elaborated before the duplicated
+   --  expression, so that there is no need to repeat any checks.
+
+   function Duplicate_Subexpr_Move_Checks
+     (Exp      : Node_Id;
+      Name_Req : Boolean := False)
+      return     Node_Id;
+   --  Identical in effect to Duplicate_Subexpr, except that Remove_Checks
+   --  is called on Exp after the duplication is complete, so that the
+   --  original expression does not include checks. In this case the result
+   --  returned (the duplicated expression) will retain the original checks.
+   --  This is appropriate for use when the duplicated expression is sure
+   --  to be elaborated before the original expression Exp, so that there
+   --  is no need to repeat the checks.
 
    procedure Ensure_Defined (Typ : Entity_Id; N : Node_Id);
    --  This procedure ensures that type referenced by Typ is defined. For the
diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb
index 0b910a63aaca3d940bf0c4b3420fe094a8adcef3..ba031b13f4c72d3119601b82fbe28a8e5805adea 100644
--- a/gcc/ada/sem_eval.adb
+++ b/gcc/ada/sem_eval.adb
@@ -32,6 +32,7 @@ with Einfo;    use Einfo;
 with Elists;   use Elists;
 with Errout;   use Errout;
 with Eval_Fat; use Eval_Fat;
+with Exp_Util; use Exp_Util;
 with Nmake;    use Nmake;
 with Nlists;   use Nlists;
 with Opt;      use Opt;
@@ -127,14 +128,6 @@ package body Sem_Eval is
    -- Local Subprograms --
    -----------------------
 
-   function Constant_Array_Ref (Op : Node_Id) return Node_Id;
-   --  The caller has checked that Op is an array reference (i.e. that its
-   --  node kind is N_Indexed_Component). If the array reference is constant
-   --  at compile time, and yields a constant value of a discrete type, then
-   --  the expression node for the constant value is returned. otherwise Empty
-   --  is returned. This is used by Compile_Time_Known_Value, as well as by
-   --  Expr_Value and Expr_Rep_Value.
-
    function From_Bits (B : Bits; T : Entity_Id) return Uint;
    --  Converts a bit string of length B'Length to a Uint value to be used
    --  for a target of type T, which is a modular type. This procedure
@@ -730,7 +723,6 @@ package body Sem_Eval is
    function Compile_Time_Known_Value (Op : Node_Id) return Boolean is
       K      : constant Node_Kind := Nkind (Op);
       CV_Ent : CV_Entry renames CV_Cache (Nat (Op) mod CV_Cache_Size);
-      Val    : Node_Id;
 
    begin
       --  Never known at compile time if bad type or raises constraint error
@@ -800,17 +792,6 @@ package body Sem_Eval is
 
          elsif K = N_Attribute_Reference then
             return Attribute_Name (Op) = Name_Null_Parameter;
-
-         --  A reference to an element of a constant array may be constant.
-
-         elsif K = N_Indexed_Component then
-            Val := Constant_Array_Ref (Op);
-
-            if Present (Val) then
-               CV_Ent.N := Op;
-               CV_Ent.V := Expr_Value (Val);
-               return True;
-            end if;
          end if;
       end if;
 
@@ -908,58 +889,6 @@ package body Sem_Eval is
       end if;
    end Compile_Time_Known_Value_Or_Aggr;
 
-   ------------------------
-   -- Constant_Array_Ref --
-   ------------------------
-
-   function Constant_Array_Ref (Op : Node_Id) return Node_Id is
-   begin
-      if List_Length (Expressions (Op)) = 1
-        and then Is_Entity_Name (Prefix (Op))
-        and then Ekind (Entity (Prefix (Op))) = E_Constant
-      then
-         declare
-            Arr : constant Node_Id := Constant_Value (Entity (Prefix (Op)));
-            Sub : constant Node_Id := First (Expressions (Op));
-            Aty : constant Node_Id := Etype (Arr);
-
-            Lin : Nat;
-            --  Linear one's origin subscript value for array reference
-
-            Lbd : Node_Id;
-            --  Lower bound of the first array index
-
-            Elm : Node_Id;
-            --  Value from constant array
-
-         begin
-            if Ekind (Aty) = E_String_Literal_Subtype then
-               Lbd := String_Literal_Low_Bound (Aty);
-            else
-               Lbd := Type_Low_Bound (Etype (First_Index (Aty)));
-            end if;
-
-            if Compile_Time_Known_Value (Sub)
-              and then Nkind (Arr) = N_Aggregate
-              and then Compile_Time_Known_Value (Lbd)
-              and then Is_Discrete_Type (Component_Type (Aty))
-            then
-               Lin := UI_To_Int (Expr_Value (Sub) - Expr_Value (Lbd)) + 1;
-
-               if List_Length (Expressions (Arr)) >= Lin then
-                  Elm := Pick (Expressions (Arr), Lin);
-
-                  if Compile_Time_Known_Value (Elm) then
-                     return Elm;
-                  end if;
-               end if;
-            end if;
-         end;
-      end if;
-
-      return Empty;
-   end Constant_Array_Ref;
-
    -----------------
    -- Eval_Actual --
    -----------------
@@ -1140,7 +1069,6 @@ package body Sem_Eval is
       end if;
 
       Set_Is_Static_Expression (N, Stat);
-
    end Eval_Arithmetic_Op;
 
    ----------------------------
@@ -1344,8 +1272,9 @@ package body Sem_Eval is
    -- Eval_Indexed_Component --
    ----------------------------
 
-   --  Indexed components are never static, so the only required processing
-   --  is to perform the check for non-static context on the index values.
+   --  Indexed components are never static, so we need to perform the check
+   --  for non-static context on the index values. Then, we check if the
+   --  value can be obtained at compile time, even though it is non-static.
 
    procedure Eval_Indexed_Component (N : Node_Id) is
       Expr : Node_Id;
@@ -1357,6 +1286,74 @@ package body Sem_Eval is
          Next (Expr);
       end loop;
 
+      --  See if this is a constant array reference
+
+      if List_Length (Expressions (N)) = 1
+        and then Is_Entity_Name (Prefix (N))
+        and then Ekind (Entity (Prefix (N))) = E_Constant
+        and then Present (Constant_Value (Entity (Prefix (N))))
+      then
+         declare
+            Loc : constant Source_Ptr := Sloc (N);
+            Arr : constant Node_Id    := Constant_Value (Entity (Prefix (N)));
+            Sub : constant Node_Id    := First (Expressions (N));
+
+            Atyp : Entity_Id;
+            --  Type of array
+
+            Lin : Nat;
+            --  Linear one's origin subscript value for array reference
+
+            Lbd : Node_Id;
+            --  Lower bound of the first array index
+
+            Elm : Node_Id;
+            --  Value from constant array
+
+         begin
+            Atyp := Etype (Arr);
+
+            if Is_Access_Type (Atyp) then
+               Atyp := Designated_Type (Atyp);
+            end if;
+
+            --  If we have an array type (we should have but perhaps there
+            --  are error cases where this is not the case), then see if we
+            --  can do a constant evaluation of the array reference.
+
+            if Is_Array_Type (Atyp) then
+               if Ekind (Atyp) = E_String_Literal_Subtype then
+                  Lbd := String_Literal_Low_Bound (Atyp);
+               else
+                  Lbd := Type_Low_Bound (Etype (First_Index (Atyp)));
+               end if;
+
+               if Compile_Time_Known_Value (Sub)
+                 and then Nkind (Arr) = N_Aggregate
+                 and then Compile_Time_Known_Value (Lbd)
+                 and then Is_Discrete_Type (Component_Type (Atyp))
+               then
+                  Lin := UI_To_Int (Expr_Value (Sub) - Expr_Value (Lbd)) + 1;
+
+                  if List_Length (Expressions (Arr)) >= Lin then
+                     Elm := Pick (Expressions (Arr), Lin);
+
+                     --  If the resulting expression is compile time known,
+                     --  then we can rewrite the indexed component with this
+                     --  value, being sure to mark the result as non-static.
+                     --  We also reset the Sloc, in case this generates an
+                     --  error later on (e.g. 136'Access).
+
+                     if Compile_Time_Known_Value (Elm) then
+                        Rewrite (N, Duplicate_Subexpr_No_Checks (Elm));
+                        Set_Is_Static_Expression (N, False);
+                        Set_Sloc (N, Loc);
+                     end if;
+                  end if;
+               end if;
+            end if;
+         end;
+      end if;
    end Eval_Indexed_Component;
 
    --------------------------
@@ -2465,7 +2462,6 @@ package body Sem_Eval is
    function Expr_Rep_Value (N : Node_Id) return Uint is
       Kind : constant Node_Kind := Nkind (N);
       Ent  : Entity_Id;
-      Vexp : Node_Id;
 
    begin
       if Is_Entity_Name (N) then
@@ -2506,14 +2502,8 @@ package body Sem_Eval is
       then
          return Uint_0;
 
-      --  Array reference case
-
-      elsif Kind = N_Indexed_Component then
-         Vexp := Constant_Array_Ref (N);
-         pragma Assert (Present (Vexp));
-         return Expr_Rep_Value (Vexp);
-
       --  Otherwise must be character literal
+
       else
          pragma Assert (Kind = N_Character_Literal);
          Ent := Entity (N);
@@ -2541,7 +2531,6 @@ package body Sem_Eval is
       CV_Ent : CV_Entry renames CV_Cache (Nat (N) mod CV_Cache_Size);
       Ent    : Entity_Id;
       Val    : Uint;
-      Vexp   : Node_Id;
 
    begin
       --  If already in cache, then we know it's compile time known and
@@ -2593,13 +2582,6 @@ package body Sem_Eval is
       then
          Val := Uint_0;
 
-      --  Array reference case
-
-      elsif Kind = N_Indexed_Component then
-         Vexp := Constant_Array_Ref (N);
-         pragma Assert (Present (Vexp));
-         Val := Expr_Value (Vexp);
-
       --  Otherwise must be character literal
 
       else
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 5be30aabf4c6d11d81660a18d5ea2a321600c87f..5c8c4a400bf6f8e3823be35ebe00f737e4ccba2f 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -187,14 +187,16 @@ package body Sem_Util is
 
             Lo :=
               Make_Attribute_Reference (Loc,
-                Prefix         => Duplicate_Subexpr (Obj, Name_Req => True),
+                Prefix         =>
+                  Duplicate_Subexpr_No_Checks (Obj, Name_Req => True),
                 Attribute_Name => Name_First,
                 Expressions    => New_List (
                   Make_Integer_Literal (Loc, J)));
 
             Hi :=
               Make_Attribute_Reference (Loc,
-                Prefix         => Duplicate_Subexpr (Obj, Name_Req => True),
+                Prefix         =>
+                  Duplicate_Subexpr_No_Checks (Obj, Name_Req => True),
                 Attribute_Name => Name_Last,
                 Expressions    => New_List (
                   Make_Integer_Literal (Loc, J)));
@@ -226,7 +228,8 @@ package body Sem_Util is
          while Present (Discr) loop
             Append_To (Constraints,
               Make_Selected_Component (Loc,
-                Prefix => Duplicate_Subexpr (Obj),
+                Prefix =>
+                  Duplicate_Subexpr_No_Checks (Obj),
                 Selector_Name => New_Occurrence_Of (Discr, Loc)));
             Next_Discriminant (Discr);
          end loop;
@@ -2056,7 +2059,7 @@ package body Sem_Util is
                           Make_Component_Association (Sloc (Typ),
                             New_List
                               (New_Occurrence_Of (D, Sloc (Typ))),
-                            Duplicate_Subexpr (Node (C)));
+                            Duplicate_Subexpr_No_Checks (Node (C)));
                         exit Find_Constraint;
                      end if;