OSDN Git Service

2006-02-13 Javier Miranda <miranda@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / sem_warn.adb
index c6aa359..3f3d938 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1999-2004 Free Software Foundation, Inc.          --
+--          Copyright (C) 1999-2005, 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- --
@@ -16,8 +16,8 @@
 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
 -- for  more details.  You should have  received  a copy of the GNU General --
 -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
--- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
--- MA 02111-1307, USA.                                                      --
+-- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
+-- Boston, MA 02110-1301, USA.                                              --
 --                                                                          --
 -- GNAT was originally developed  by the GNAT team at  New York University. --
 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
@@ -171,9 +171,9 @@ package body Sem_Warn is
       --  from another unit. This is true for entities in packages that are
       --  at the library level.
 
-      -----------------------
-      --  Missing_Subunits --
-      -----------------------
+      ----------------------
+      -- Missing_Subunits --
+      ----------------------
 
       function Missing_Subunits return Boolean is
          D : Node_Id;
@@ -294,7 +294,20 @@ package body Sem_Warn is
                       or else List_Containing (Prev)
                         /= Generic_Formal_Declarations (P);
 
-               --  if we reach a subprogram body, entity is not referenceable
+               --  Similarly, the generic formals of a generic subprogram
+               --  are not accessible.
+
+               when N_Generic_Subprogram_Declaration  =>
+                  if Is_List_Member (Prev)
+                    and then List_Containing (Prev) =
+                               Generic_Formal_Declarations (P)
+                  then
+                     return False;
+                  else
+                     P := Parent (P);
+                  end if;
+
+               --  If we reach a subprogram body, entity is not referenceable
                --  unless it is the defining entity of the body. This will
                --  happen, e.g. when a function is an attribute renaming that
                --  is rewritten as a body.
@@ -351,7 +364,7 @@ package body Sem_Warn is
       E1 := First_Entity (E);
       while Present (E1) loop
 
-         --  We only look at source entities with warning flag off
+         --  We only look at source entities with warning flag on
 
          if Comes_From_Source (E1) and then not Warnings_Off (E1) then
 
@@ -367,6 +380,14 @@ package body Sem_Warn is
                --  do not consider the implicit initialization of an access
                --  type to be the assignment of a value for this purpose.
 
+               if Ekind (E1) = E_Out_Parameter
+                 and then Present (Spec_Entity (E1))
+               then
+                  UR := Unset_Reference (Spec_Entity (E1));
+               else
+                  UR := Unset_Reference (E1);
+               end if;
+
                --  If the entity is an out parameter of the current subprogram
                --  body, check the warning status of the parameter in the spec.
 
@@ -376,6 +397,22 @@ package body Sem_Warn is
                then
                   null;
 
+               elsif Present (UR)
+                 and then Is_Access_Type (Etype (E1))
+               then
+
+                  --  For access types, the only time we made a UR
+                  --  entry was for a dereference, and so we post
+                  --  the appropriate warning here (note that the
+                  --  dereference may not be explicit in the source,
+                  --  for example in the case of a dispatching call
+                  --  with an anonymous access controlling formal, or
+                  --  of an assignment of a pointer involving a
+                  --  discriminant check on the designated object).
+
+                  Error_Msg_NE ("& may be null?", UR, E1);
+                  goto Continue;
+
                elsif Never_Set_In_Source (E1)
                  and then not Generic_Package_Spec_Entity (E1)
                then
@@ -427,94 +464,87 @@ package body Sem_Warn is
                  and then Is_True_Constant (E1)
                  and then not Generic_Package_Spec_Entity (E1)
                then
-                  Error_Msg_N
-                    ("& is not modified, could be declared constant?", E1);
+                  --  A special case, if this variable is volatile and not
+                  --  imported, it is not helpful to tell the programmer
+                  --  to mark the variable as constant, since this would be
+                  --  illegal by virtue of RM C.6(13).
+
+                  if (Is_Volatile (E1) or else Has_Volatile_Components (E1))
+                    and then not Is_Imported (E1)
+                  then
+                     Error_Msg_N
+                       ("& is not modified, volatile has no effect?", E1);
+                  else
+                     Error_Msg_N
+                       ("& is not modified, could be declared constant?", E1);
+                  end if;
                end if;
 
                --  Check for unset reference, note that we exclude access
                --  types from this check, since access types do always have
                --  a null value, and that seems legitimate in this case.
 
-               if Ekind (E1) = E_Out_Parameter
-                 and then Present (Spec_Entity (E1))
-               then
-                  UR := Unset_Reference (Spec_Entity (E1));
-               else
-                  UR := Unset_Reference (E1);
-               end if;
-
                if Warn_On_No_Value_Assigned and then Present (UR) then
 
-                  --  For access types, the only time we made a UR entry
-                  --  was for a dereference, and so we post the appropriate
-                  --  warning here. The issue is not that the value is not
-                  --  initialized here, but that it is null.
-
-                  if Is_Access_Type (Etype (E1)) then
-                     Error_Msg_NE ("& may be null?", UR, E1);
-                     goto Continue;
-
                   --  For other than access type, go back to original node
                   --  to deal with case where original unset reference
                   --  has been rewritten during expansion.
 
-                  else
-                     UR := Original_Node (UR);
+                  UR := Original_Node (UR);
 
-                     --  In some cases, the original node may be a type
-                     --  conversion or qualification, and in this case
-                     --  we want the object entity inside.
+                  --  In some cases, the original node may be a type
+                  --  conversion or qualification, and in this case
+                  --  we want the object entity inside.
 
-                     while Nkind (UR) = N_Type_Conversion
-                       or else Nkind (UR) = N_Qualified_Expression
-                     loop
-                        UR := Expression (UR);
-                     end loop;
+                  while Nkind (UR) = N_Type_Conversion
+                    or else Nkind (UR) = N_Qualified_Expression
+                  loop
+                     UR := Expression (UR);
+                  end loop;
 
-                     --  Here we issue the warning, all checks completed
-                     --  If the unset reference is prefix of a selected
-                     --  component that comes from source, mention the
-                     --  component as well. If the selected component comes
-                     --  from expansion, all we know is that the entity is
-                     --  not fully initialized at the point of the reference.
-                     --  Locate an unintialized component to get a better
-                     --  error message.
+                  --  Here we issue the warning, all checks completed
+                  --  If the unset reference is prefix of a selected
+                  --  component that comes from source, mention the
+                  --  component as well. If the selected component comes
+                  --  from expansion, all we know is that the entity is
+                  --  not fully initialized at the point of the reference.
+                  --  Locate an unintialized component to get a better
+                  --  error message.
 
-                     if Nkind (Parent (UR)) = N_Selected_Component then
-                        Error_Msg_Node_2 := Selector_Name (Parent (UR));
+                  if Nkind (Parent (UR)) = N_Selected_Component then
+                     Error_Msg_Node_2 := Selector_Name (Parent (UR));
 
-                        if not Comes_From_Source (Parent (UR)) then
-                           declare
-                              Comp : Entity_Id;
+                     if not Comes_From_Source (Parent (UR)) then
+                        declare
+                           Comp : Entity_Id;
 
-                           begin
-                              Comp := First_Entity (Etype (E1));
-                              while Present (Comp) loop
-                                 if Ekind (Comp) = E_Component
-                                   and then Nkind (Parent (Comp)) =
-                                     N_Component_Declaration
-                                   and then No (Expression (Parent (Comp)))
-                                 then
-                                    Error_Msg_Node_2 := Comp;
-                                    exit;
-                                 end if;
-
-                                 Next_Entity (Comp);
-                              end loop;
-                           end;
-                        end if;
+                        begin
+                           Comp := First_Entity (Etype (E1));
+                           while Present (Comp) loop
+                              if Ekind (Comp) = E_Component
+                                and then Nkind (Parent (Comp)) =
+                                  N_Component_Declaration
+                                and then No (Expression (Parent (Comp)))
+                              then
+                                 Error_Msg_Node_2 := Comp;
+                                 exit;
+                              end if;
 
-                        Error_Msg_N
-                          ("`&.&` may be referenced before it has a value?",
-                           UR);
-                     else
-                        Error_Msg_N
-                          ("& may be referenced before it has a value?",
-                           UR);
+                              Next_Entity (Comp);
+                           end loop;
+                        end;
                      end if;
 
-                     goto Continue;
+                     Error_Msg_N
+                       ("`&.&` may be referenced before it has a value?",
+                        UR);
+                  else
+                     Error_Msg_N
+                       ("& may be referenced before it has a value?",
+                        UR);
                   end if;
+
+                  goto Continue;
                end if;
             end if;
 
@@ -558,6 +588,7 @@ package body Sem_Warn is
                                 (Ekind (E) = E_Function
                                   or else Ekind (E) = E_Package_Body
                                   or else Ekind (E) = E_Procedure
+                                  or else Ekind (E) = E_Subprogram_Body
                                   or else Ekind (E) = E_Block)))
 
                --  Exclude instantiations, since there is no reason why
@@ -665,7 +696,7 @@ package body Sem_Warn is
                Unreferenced_Entities.Increment_Last;
                Unreferenced_Entities.Table (Unreferenced_Entities.Last) := E1;
 
-               --  Force warning on entity.
+               --  Force warning on entity
 
                Set_Referenced (E1, False);
             end if;
@@ -989,7 +1020,7 @@ package body Sem_Warn is
             Un : constant Node_Id := Sinfo.Unit (Cnode);
 
             function Check_Use_Clause (N : Node_Id) return Traverse_Result;
-            --  If N is a use_clause for Pack, emit warning.
+            --  If N is a use_clause for Pack, emit warning
 
             procedure Check_Use_Clauses is new
               Traverse_Proc (Check_Use_Clause);
@@ -1478,6 +1509,14 @@ package body Sem_Warn is
                   then
                      if Warn_On_Modified_Unread
                        and then not Is_Imported (E)
+
+                        --  Suppress the message for aliased or renamed
+                        --  variables, since there may be other entities
+                        --  read the same memory location.
+
+                       and then not Is_Aliased (E)
+                       and then No (Renamed_Object (E))
+
                      then
                         Error_Msg_N
                           ("variable & is assigned but never read?", E);
@@ -1551,6 +1590,192 @@ package body Sem_Warn is
       end loop;
    end Output_Unreferenced_Messages;
 
+   ------------------------
+   -- Set_Warning_Switch --
+   ------------------------
+
+   function Set_Warning_Switch (C : Character) return Boolean is
+   begin
+      case C is
+         when 'a' =>
+            Check_Unreferenced              := True;
+            Check_Unreferenced_Formals      := True;
+            Check_Withs                     := True;
+            Constant_Condition_Warnings     := True;
+            Implementation_Unit_Warnings    := True;
+            Ineffective_Inline_Warnings     := True;
+            Warn_On_Ada_2005_Compatibility  := True;
+            Warn_On_Bad_Fixed_Value         := True;
+            Warn_On_Constant                := True;
+            Warn_On_Export_Import           := True;
+            Warn_On_Modified_Unread         := True;
+            Warn_On_No_Value_Assigned       := True;
+            Warn_On_Obsolescent_Feature     := True;
+            Warn_On_Redundant_Constructs    := True;
+            Warn_On_Unchecked_Conversion    := True;
+            Warn_On_Unrecognized_Pragma     := True;
+
+         when 'A' =>
+            Check_Unreferenced              := False;
+            Check_Unreferenced_Formals      := False;
+            Check_Withs                     := False;
+            Constant_Condition_Warnings     := False;
+            Elab_Warnings                   := False;
+            Implementation_Unit_Warnings    := False;
+            Ineffective_Inline_Warnings     := False;
+            Warn_On_Ada_2005_Compatibility  := False;
+            Warn_On_Bad_Fixed_Value         := False;
+            Warn_On_Constant                := False;
+            Warn_On_Dereference             := False;
+            Warn_On_Export_Import           := False;
+            Warn_On_Hiding                  := False;
+            Warn_On_Modified_Unread         := False;
+            Warn_On_No_Value_Assigned       := False;
+            Warn_On_Obsolescent_Feature     := False;
+            Warn_On_Redundant_Constructs    := False;
+            Warn_On_Unchecked_Conversion    := False;
+            Warn_On_Unrecognized_Pragma     := False;
+
+         when 'b' =>
+            Warn_On_Bad_Fixed_Value         := True;
+
+         when 'B' =>
+            Warn_On_Bad_Fixed_Value         := False;
+
+         when 'c' =>
+            Constant_Condition_Warnings     := True;
+
+         when 'C' =>
+            Constant_Condition_Warnings     := False;
+
+         when 'd' =>
+            Warn_On_Dereference             := True;
+
+         when 'D' =>
+            Warn_On_Dereference             := False;
+
+         when 'e' =>
+            Warning_Mode                    := Treat_As_Error;
+
+         when 'f' =>
+            Check_Unreferenced_Formals      := True;
+
+         when 'F' =>
+            Check_Unreferenced_Formals      := False;
+
+         when 'g' =>
+            Warn_On_Unrecognized_Pragma     := True;
+
+         when 'G' =>
+            Warn_On_Unrecognized_Pragma     := False;
+
+         when 'h' =>
+            Warn_On_Hiding                  := True;
+
+         when 'H' =>
+            Warn_On_Hiding                  := False;
+
+         when 'i' =>
+            Implementation_Unit_Warnings    := True;
+
+         when 'I' =>
+            Implementation_Unit_Warnings    := False;
+
+         when 'j' =>
+            Warn_On_Obsolescent_Feature     := True;
+
+         when 'J' =>
+            Warn_On_Obsolescent_Feature     := False;
+
+         when 'k' =>
+            Warn_On_Constant                := True;
+
+         when 'K' =>
+            Warn_On_Constant                := False;
+
+         when 'l' =>
+            Elab_Warnings                   := True;
+
+         when 'L' =>
+            Elab_Warnings                   := False;
+
+         when 'm' =>
+            Warn_On_Modified_Unread         := True;
+
+         when 'M' =>
+            Warn_On_Modified_Unread         := False;
+
+         when 'n' =>
+            Warning_Mode                    := Normal;
+
+         when 'o' =>
+            Address_Clause_Overlay_Warnings := True;
+
+         when 'O' =>
+            Address_Clause_Overlay_Warnings := False;
+
+         when 'p' =>
+            Ineffective_Inline_Warnings     := True;
+
+         when 'P' =>
+            Ineffective_Inline_Warnings     := False;
+
+         when 'r' =>
+            Warn_On_Redundant_Constructs    := True;
+
+         when 'R' =>
+            Warn_On_Redundant_Constructs    := False;
+
+         when 's' =>
+            Warning_Mode                    := Suppress;
+
+         when 'u' =>
+            Check_Unreferenced              := True;
+            Check_Withs                     := True;
+            Check_Unreferenced_Formals      := True;
+
+         when 'U' =>
+            Check_Unreferenced              := False;
+            Check_Withs                     := False;
+            Check_Unreferenced_Formals      := False;
+
+         when 'v' =>
+            Warn_On_No_Value_Assigned       := True;
+
+         when 'V' =>
+            Warn_On_No_Value_Assigned       := False;
+
+         when 'x' =>
+            Warn_On_Export_Import           := True;
+
+         when 'X' =>
+            Warn_On_Export_Import           := False;
+
+         when 'y' =>
+            Warn_On_Ada_2005_Compatibility  := True;
+
+         when 'Y' =>
+            Warn_On_Ada_2005_Compatibility  := False;
+
+         when 'z' =>
+            Warn_On_Unchecked_Conversion    := True;
+
+         when 'Z' =>
+            Warn_On_Unchecked_Conversion    := False;
+
+            --  Allow and ignore 'w' so that the old
+            --  format (e.g. -gnatwuwl) will work.
+
+         when 'w' =>
+            null;
+
+         when others =>
+            return False;
+      end case;
+
+      return True;
+   end Set_Warning_Switch;
+
    -----------------------------
    -- Warn_On_Known_Condition --
    -----------------------------
@@ -1613,14 +1838,39 @@ package body Sem_Warn is
          end loop;
 
          --  Here we issue the warning unless some sub-operand has warnings
-         --  set off, in which case we suppress the warning for the node.
+         --  set off, in which case we suppress the warning for the node. If
+         --  the original expression is an inequality, it has been expanded
+         --  into a negation, and the value of the original expression is the
+         --  negation of the equality. If the expression is an entity that
+         --  appears within a negation, it is clearer to flag the negation
+         --  itself, and report on its constant value.
 
          if not Operand_Has_Warnings_Suppressed (C) then
-            if Entity (C) = Standard_True then
-               Error_Msg_N ("condition is always True?", C);
-            else
-               Error_Msg_N ("condition is always False?", C);
-            end if;
+            declare
+               True_Branch : Boolean := Entity (C) = Standard_True;
+               Cond        : Node_Id := C;
+
+            begin
+               if Present (Parent (C))
+                 and then Nkind (Parent (C)) = N_Op_Not
+               then
+                  True_Branch := not True_Branch;
+                  Cond        := Parent (C);
+               end if;
+
+               if True_Branch then
+                  if Is_Entity_Name (Original_Node (C))
+                    and then Nkind (Cond) /= N_Op_Not
+                  then
+                     Error_Msg_NE
+                      ("object & is always True?", Cond, Original_Node (C));
+                  else
+                     Error_Msg_N ("condition is always True?", Cond);
+                  end if;
+               else
+                  Error_Msg_N ("condition is always False?", Cond);
+               end if;
+            end;
          end if;
       end if;
    end Warn_On_Known_Condition;