mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-31 15:31:11 +08:00
g-comlin.ads, [...]: Add new warning for renaming of function return objects
2007-04-20 Robert Dewar <dewar@adacore.com> Ed Schonberg <schonberg@adacore.com> * g-comlin.ads, g-comlin.adb: Add new warning for renaming of function return objects * opt.adb (Tree_Write, Tree_Read): Use proper expressions for size (Tree_Read): Use size of object instead of type'object_size, since the latter is incorrect for packed array types. (Tree_Write): Same fix * opt.ads: Add new warning for renaming of function return objects (Generating_Code): New boolean variable used to indicate that the frontend as finished its work and has called the backend to process the tree and generate the object file. (GCC_Version): Is now private (Static_Dispatch_Tables): New constant declaration. (Overflow_Checks_Unsuppressed): New flag. (Process_Suppress_Unsuppress): Set Overflow_Checks_Unsuppressed. (List_Closure): New flag for gnatbind (-R) Zero_Formatting: New flag for gnatbind (-Z) (Special_Exception_Package_Used): New flag. (Warn_On_Unrepped_Components): New flag. * sem_ch8.adb (Check_Library_Unit_Renaming): Check that the renamed unit is a compilation unit, rather than relying on its scope, so that Standard can be renamed. (Analyze_Object_Renaming): Add new warning for renaming of function return objects. Also reject attempt to rename function return object in Ada 83 mode. (Attribute_Renaming): In case of tagged types, add the body of the generated function to the freezing actions of the type. (Find_Type): A protected type is visible right after the reserved word "is" is encountered in its type declaration. Set the entity and type rather than emitting an error message. (New_Scope): Properly propagate Discard_Names to inner scopes (Check_Nested_Access): New procedure. (Has_Nested_Access, Set_Has_Nested_Access): New procedures. (Find_Direct_Name, Note_Possible_Modification): Use Check_Nested_Access. * sem_warn.ads, sem_warn.adb: Improvements to infinite loop warning Add new warning for renaming of function return objects (Check_References): Suppress warnings for objects whose type or base type has Warnings suppressed. (Set_Dot_Warning_Switch): Add processing for -gnatw.c/C (Set_Warning_Switch): Include new -gnatwc in -gnatwa From-SVN: r125414
This commit is contained in:
parent
f24f72e892
commit
fbe627afbd
@ -6,7 +6,7 @@
|
||||
-- --
|
||||
-- B o d y --
|
||||
-- --
|
||||
-- Copyright (C) 1999-2006, Free Software Foundation, Inc. --
|
||||
-- Copyright (C) 1999-2007, 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- --
|
||||
@ -32,7 +32,7 @@
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
with Ada.Command_Line;
|
||||
with GNAT.OS_Lib; use GNAT.OS_Lib;
|
||||
with GNAT.OS_Lib; use GNAT.OS_Lib;
|
||||
|
||||
package body GNAT.Command_Line is
|
||||
|
||||
@ -142,9 +142,9 @@ package body GNAT.Command_Line is
|
||||
use GNAT.Directory_Operations;
|
||||
type Pointer is access all Expansion_Iterator;
|
||||
|
||||
It : constant Pointer := Iterator'Unrestricted_Access;
|
||||
S : String (1 .. 1024);
|
||||
Last : Natural;
|
||||
It : constant Pointer := Iterator'Unrestricted_Access;
|
||||
|
||||
Current : Depth := It.Current_Depth;
|
||||
NL : Positive;
|
||||
@ -304,8 +304,8 @@ package body GNAT.Command_Line is
|
||||
|
||||
if Do_Expansion then
|
||||
declare
|
||||
Arg : String renames CL.Argument (Current_Argument - 1);
|
||||
Index : Positive := Arg'First;
|
||||
Arg : constant String := CL.Argument (Current_Argument - 1);
|
||||
Index : Positive := Arg'First;
|
||||
|
||||
begin
|
||||
while Index <= Arg'Last loop
|
||||
@ -381,7 +381,7 @@ package body GNAT.Command_Line is
|
||||
end if;
|
||||
|
||||
declare
|
||||
Arg : String renames CL.Argument (Current_Argument);
|
||||
Arg : constant String := CL.Argument (Current_Argument);
|
||||
Index_Switches : Natural := 0;
|
||||
Max_Length : Natural := 0;
|
||||
Index : Natural;
|
||||
@ -780,9 +780,9 @@ package body GNAT.Command_Line is
|
||||
is
|
||||
Directory_Separator : Character;
|
||||
pragma Import (C, Directory_Separator, "__gnat_dir_separator");
|
||||
First : Positive := Pattern'First;
|
||||
|
||||
Pat : String := Pattern;
|
||||
First : Positive := Pattern'First;
|
||||
Pat : String := Pattern;
|
||||
|
||||
begin
|
||||
Canonical_Case_File_Name (Pat);
|
||||
@ -838,7 +838,6 @@ package body GNAT.Command_Line is
|
||||
exit when Iterator.Maximum_Depth = Max_Depth;
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
end Start_Expansion;
|
||||
|
||||
begin
|
||||
|
@ -6,7 +6,7 @@
|
||||
-- --
|
||||
-- S p e c --
|
||||
-- --
|
||||
-- Copyright (C) 1999-2005, AdaCore --
|
||||
-- Copyright (C) 1999-2007, AdaCore --
|
||||
-- --
|
||||
-- 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- --
|
||||
@ -322,7 +322,6 @@ private
|
||||
Maximum_Depth : Depth := 1;
|
||||
-- The maximum depth of directories, reflecting the number of directory
|
||||
-- separators in the pattern.
|
||||
|
||||
end record;
|
||||
|
||||
end GNAT.Command_Line;
|
||||
|
@ -6,7 +6,7 @@
|
||||
-- --
|
||||
-- B o d y --
|
||||
-- --
|
||||
-- Copyright (C) 1992-2006, Free Software Foundation, Inc. --
|
||||
-- Copyright (C) 1992-2007, 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- --
|
||||
@ -37,6 +37,9 @@ with Tree_IO; use Tree_IO;
|
||||
|
||||
package body Opt is
|
||||
|
||||
SU : constant := Storage_Unit;
|
||||
-- Shorthand for System.Storage_Unit
|
||||
|
||||
----------------------------------
|
||||
-- Register_Opt_Config_Switches --
|
||||
----------------------------------
|
||||
@ -169,10 +172,10 @@ package body Opt is
|
||||
Tree_Read_Char (Identifier_Character_Set);
|
||||
Tree_Read_Int (Maximum_File_Name_Length);
|
||||
Tree_Read_Data (Suppress_Options'Address,
|
||||
Suppress_Array'Object_Size / Storage_Unit);
|
||||
(Suppress_Options'Size + SU - 1) / SU);
|
||||
Tree_Read_Bool (Verbose_Mode);
|
||||
Tree_Read_Data (Warning_Mode'Address,
|
||||
Warning_Mode_Type'Object_Size / Storage_Unit);
|
||||
(Warning_Mode'Size + SU - 1) / SU);
|
||||
Tree_Read_Int (Ada_Version_Config_Val);
|
||||
Tree_Read_Int (Ada_Version_Explicit_Config_Val);
|
||||
Tree_Read_Int (Assertions_Enabled_Config_Val);
|
||||
@ -198,23 +201,23 @@ package body Opt is
|
||||
begin
|
||||
Tree_Read_Data
|
||||
(Tmp'Address, Tree_Version_String_Len);
|
||||
GNAT.Strings.Free (Tree_Version_String);
|
||||
System.Strings.Free (Tree_Version_String);
|
||||
Free (Tree_Version_String);
|
||||
Tree_Version_String := new String'(Tmp);
|
||||
end;
|
||||
|
||||
Tree_Read_Data (Distribution_Stub_Mode'Address,
|
||||
Distribution_Stub_Mode_Type'Object_Size / Storage_Unit);
|
||||
(Distribution_Stub_Mode'Size + SU - 1) / Storage_Unit);
|
||||
Tree_Read_Bool (Inline_Active);
|
||||
Tree_Read_Bool (Inline_Processing_Required);
|
||||
Tree_Read_Bool (List_Units);
|
||||
Tree_Read_Bool (Configurable_Run_Time_Mode);
|
||||
Tree_Read_Data (Operating_Mode'Address,
|
||||
Operating_Mode_Type'Object_Size / Storage_Unit);
|
||||
(Operating_Mode'Size + SU - 1) / Storage_Unit);
|
||||
Tree_Read_Bool (Suppress_Checks);
|
||||
Tree_Read_Bool (Try_Semantics);
|
||||
Tree_Read_Data (Wide_Character_Encoding_Method'Address,
|
||||
WC_Encoding_Method'Object_Size / Storage_Unit);
|
||||
(Wide_Character_Encoding_Method'Size + SU - 1) / SU);
|
||||
Tree_Read_Bool (Upper_Half_Encoding);
|
||||
Tree_Read_Bool (Force_ALI_Tree_File);
|
||||
end Tree_Read;
|
||||
@ -233,10 +236,10 @@ package body Opt is
|
||||
Tree_Write_Char (Identifier_Character_Set);
|
||||
Tree_Write_Int (Maximum_File_Name_Length);
|
||||
Tree_Write_Data (Suppress_Options'Address,
|
||||
Suppress_Array'Object_Size / Storage_Unit);
|
||||
(Suppress_Options'Size + SU - 1) / SU);
|
||||
Tree_Write_Bool (Verbose_Mode);
|
||||
Tree_Write_Data (Warning_Mode'Address,
|
||||
Warning_Mode_Type'Object_Size / Storage_Unit);
|
||||
(Warning_Mode'Size + SU - 1) / Storage_Unit);
|
||||
Tree_Write_Int (Ada_Version_Type'Pos (Ada_Version_Config));
|
||||
Tree_Write_Int (Ada_Version_Type'Pos (Ada_Version_Explicit_Config));
|
||||
Tree_Write_Int (Boolean'Pos (Assertions_Enabled_Config));
|
||||
@ -246,20 +249,19 @@ package body Opt is
|
||||
Tree_Write_Bool (Enable_Overflow_Checks);
|
||||
Tree_Write_Bool (Full_List);
|
||||
Tree_Write_Int (Int (Version_String'Length));
|
||||
Tree_Write_Data (Version_String'Address,
|
||||
Version_String'Length);
|
||||
Tree_Write_Data (Version_String'Address, Version_String'Length);
|
||||
Tree_Write_Data (Distribution_Stub_Mode'Address,
|
||||
Distribution_Stub_Mode_Type'Object_Size / Storage_Unit);
|
||||
(Distribution_Stub_Mode'Size + SU - 1) / SU);
|
||||
Tree_Write_Bool (Inline_Active);
|
||||
Tree_Write_Bool (Inline_Processing_Required);
|
||||
Tree_Write_Bool (List_Units);
|
||||
Tree_Write_Bool (Configurable_Run_Time_Mode);
|
||||
Tree_Write_Data (Operating_Mode'Address,
|
||||
Operating_Mode_Type'Object_Size / Storage_Unit);
|
||||
(Operating_Mode'Size + SU - 1) / SU);
|
||||
Tree_Write_Bool (Suppress_Checks);
|
||||
Tree_Write_Bool (Try_Semantics);
|
||||
Tree_Write_Data (Wide_Character_Encoding_Method'Address,
|
||||
WC_Encoding_Method'Object_Size / Storage_Unit);
|
||||
(Wide_Character_Encoding_Method'Size + SU - 1) / SU);
|
||||
Tree_Write_Bool (Upper_Half_Encoding);
|
||||
Tree_Write_Bool (Force_ALI_Tree_File);
|
||||
end Tree_Write;
|
||||
|
@ -6,7 +6,7 @@
|
||||
-- --
|
||||
-- S p e c --
|
||||
-- --
|
||||
-- Copyright (C) 1992-2006, Free Software Foundation, Inc. --
|
||||
-- Copyright (C) 1992-2007, 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- --
|
||||
@ -39,8 +39,8 @@
|
||||
with Hostparm; use Hostparm;
|
||||
with Types; use Types;
|
||||
|
||||
with System.Strings; use System.Strings;
|
||||
with System.WCh_Con; use System.WCh_Con;
|
||||
with GNAT.Strings; use GNAT.Strings;
|
||||
|
||||
package Opt is
|
||||
|
||||
@ -386,6 +386,11 @@ package Opt is
|
||||
-- Set to True if -gnato (enable overflow checks) switch is set,
|
||||
-- but not -gnatp.
|
||||
|
||||
Overflow_Checks_Unsuppressed : Boolean := False;
|
||||
-- GNAT
|
||||
-- Set to True if at least one pragma Unsuppress
|
||||
-- (All_Checks|Overflow_Checks) has been processed.
|
||||
|
||||
Error_Msg_Line_Length : Nat := 0;
|
||||
-- GNAT
|
||||
-- Records the error message line length limit. If this is set to zero,
|
||||
@ -510,16 +515,15 @@ package Opt is
|
||||
-- the name is of the form .xxx, then to name.xxx where name is the source
|
||||
-- file name with extension stripped.
|
||||
|
||||
function get_gcc_version return Int;
|
||||
pragma Import (C, get_gcc_version, "get_gcc_version");
|
||||
|
||||
GCC_Version : constant Nat := get_gcc_version;
|
||||
-- GNATMAKE
|
||||
-- Indicates which version of gcc is in use (2 = 2.8.1, 3 = 3.x)
|
||||
Generating_Code : Boolean := False;
|
||||
-- GNAT
|
||||
-- True if the frontend finished its work and has called the backend to
|
||||
-- processs the tree and generate the object file.
|
||||
|
||||
Global_Discard_Names : Boolean := False;
|
||||
-- GNAT, GNATBIND
|
||||
-- Set true if a pragma Discard_Names applies to the current unit
|
||||
-- True if a pragma Discard_Names appeared as a configuration pragma for
|
||||
-- the current compilation unit.
|
||||
|
||||
GNAT_Mode : Boolean := False;
|
||||
-- GNAT
|
||||
@ -633,6 +637,10 @@ package Opt is
|
||||
-- GNAT
|
||||
-- List units in the active library for a compilation (-gnatu switch)
|
||||
|
||||
List_Closure : Boolean := False;
|
||||
-- GNATBIND
|
||||
-- List all sources in the closure of a main (-R gnatbind switch)
|
||||
|
||||
List_Dependencies : Boolean := False;
|
||||
-- GNATMAKE
|
||||
-- When True gnatmake verifies that the objects are up to date and
|
||||
@ -668,7 +676,7 @@ package Opt is
|
||||
-- before preprocessing occurs. Set to True by switch -s of gnatprep
|
||||
-- or -s in preprocessing data file for the compiler.
|
||||
|
||||
type Create_Repinfo_File_Proc is access procedure (Src : File_Name_Type);
|
||||
type Create_Repinfo_File_Proc is access procedure (Src : String);
|
||||
type Write_Repinfo_Line_Proc is access procedure (Info : String);
|
||||
type Close_Repinfo_File_Proc is access procedure;
|
||||
-- Types used for procedure addresses below
|
||||
@ -753,6 +761,12 @@ package Opt is
|
||||
-- GNATMAKE
|
||||
-- Set to True if minimal recompilation mode requested
|
||||
|
||||
Special_Exception_Package_Used : Boolean := False;
|
||||
-- GNAT
|
||||
-- Set to True if either of the unit GNAT.Most_Recent_Exception or
|
||||
-- GNAT.Exception_Traces is with'ed. Used to inhibit transformation of
|
||||
-- local raise statements into gotos in the presence of either package.
|
||||
|
||||
Multiple_Unit_Index : Int;
|
||||
-- GNAT
|
||||
-- This is set non-zero if the current unit is being compiled in multiple
|
||||
@ -1186,6 +1200,11 @@ package Opt is
|
||||
-- Set to True to generate warnings for redundant constructs (e.g. useless
|
||||
-- assignments/conversions). The default is that this warning is disabled.
|
||||
|
||||
Warn_On_Object_Renames_Function : Boolean := False;
|
||||
-- GNAT
|
||||
-- Set to True to generate warnings when a function result is renamed as
|
||||
-- an object. The default is that this warning is disabled.
|
||||
|
||||
Warn_On_Reverse_Bit_Order : Boolean := True;
|
||||
-- GNAT
|
||||
-- Set to True to generate warning (informational) messages for component
|
||||
@ -1203,6 +1222,12 @@ package Opt is
|
||||
-- Set to True to generate warnings for unrecognized pragmas. The default
|
||||
-- is that this warning is enabled.
|
||||
|
||||
Warn_On_Unrepped_Components : Boolean := False;
|
||||
-- GNAT
|
||||
-- Set to True to generate warnings for the case of components of record
|
||||
-- which have a record representation clause but this component does not
|
||||
-- have a component clause. The default is that this warning is disabled.
|
||||
|
||||
type Warning_Mode_Type is (Suppress, Normal, Treat_As_Error);
|
||||
Warning_Mode : Warning_Mode_Type := Normal;
|
||||
-- GNAT, GNATBIND
|
||||
@ -1226,6 +1251,11 @@ package Opt is
|
||||
-- GNAT
|
||||
-- Set if cross-referencing is enabled (i.e. xref info in ALI files)
|
||||
|
||||
Zero_Formatting : Boolean := False;
|
||||
-- GNATBIND
|
||||
-- Do no formatting (no title, no leading spaces, no empty lines) in
|
||||
-- auxiliary outputs (-e, -K, -l, -R).
|
||||
|
||||
----------------------------
|
||||
-- Configuration Settings --
|
||||
----------------------------
|
||||
@ -1362,6 +1392,15 @@ package Opt is
|
||||
-- Other Global Flags --
|
||||
------------------------
|
||||
|
||||
Static_Dispatch_Tables : constant Boolean;
|
||||
-- This flag indicates if the backend supports generation of statically
|
||||
-- allocated dispatch tables. If it is True, then the front end will
|
||||
-- generate static aggregates for dispatch tables that contain forward
|
||||
-- references to addresses of subprograms not seen yet, and the back end
|
||||
-- must be prepared to handle this case. If it is False, then the front
|
||||
-- end generates assignments to initialize the dispatch table, and there
|
||||
-- are no such forward references.
|
||||
|
||||
Expander_Active : Boolean := False;
|
||||
-- A flag that indicates if expansion is active (True) or deactivated
|
||||
-- (False). When expansion is deactivated all calls to expander routines
|
||||
@ -1431,4 +1470,20 @@ private
|
||||
Use_VADS_Size : Boolean;
|
||||
end record;
|
||||
|
||||
-- The following declarations are for GCC version dependent flags. We do
|
||||
-- not let client code in the compiler test GCC_Version directly, but
|
||||
-- instead use deferred constants for relevant feature tags.
|
||||
|
||||
function get_gcc_version return Int;
|
||||
pragma Import (C, get_gcc_version, "get_gcc_version");
|
||||
|
||||
GCC_Version : constant Nat := get_gcc_version;
|
||||
-- GNATMAKE
|
||||
-- Indicates which version of gcc is in use (3 = 3.x, 4 = 4.x). Note that
|
||||
-- gcc 2.8.1 (which used to be a value of 2) is no longer supported.
|
||||
|
||||
Static_Dispatch_Tables : constant Boolean := GCC_Version >= 4;
|
||||
-- GCC version 4 can handle the static dispatch tables, but not version 3.
|
||||
-- Also we need -funit-at-a-time, which should also be tested here ???
|
||||
|
||||
end Opt;
|
||||
|
@ -6,7 +6,7 @@
|
||||
-- --
|
||||
-- B o d y --
|
||||
-- --
|
||||
-- Copyright (C) 1992-2006, Free Software Foundation, Inc. --
|
||||
-- Copyright (C) 1992-2007, 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- --
|
||||
@ -721,10 +721,25 @@ package body Sem_Ch8 is
|
||||
Set_Etype (Nam, T);
|
||||
end if;
|
||||
|
||||
-- Complete analysis of the subtype mark in any case, for ASIS use.
|
||||
|
||||
if Present (Subtype_Mark (N)) then
|
||||
Find_Type (Subtype_Mark (N));
|
||||
end if;
|
||||
|
||||
elsif Present (Subtype_Mark (N)) then
|
||||
Find_Type (Subtype_Mark (N));
|
||||
T := Entity (Subtype_Mark (N));
|
||||
Analyze_And_Resolve (Nam, T);
|
||||
Analyze (Nam);
|
||||
|
||||
if Nkind (Nam) = N_Type_Conversion
|
||||
and then not Is_Tagged_Type (T)
|
||||
then
|
||||
Error_Msg_N
|
||||
("renaming of conversion only allowed for tagged types", Nam);
|
||||
end if;
|
||||
|
||||
Resolve (Nam, T);
|
||||
|
||||
-- Ada 2005 (AI-230/AI-254): Access renaming
|
||||
|
||||
@ -748,6 +763,40 @@ package body Sem_Ch8 is
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- Special processing for renaming function return object
|
||||
|
||||
if Nkind (Nam) = N_Function_Call
|
||||
and then Comes_From_Source (Nam)
|
||||
then
|
||||
case Ada_Version is
|
||||
|
||||
-- Usage is illegal in Ada 83
|
||||
|
||||
when Ada_83 =>
|
||||
Error_Msg_N
|
||||
("(Ada 83) cannot rename function return object", Nam);
|
||||
|
||||
-- In Ada 95, warn for odd case of renaming parameterless function
|
||||
-- call if this is not a limited type (where this is useful)
|
||||
|
||||
when others =>
|
||||
if Warn_On_Object_Renames_Function
|
||||
and then No (Parameter_Associations (Nam))
|
||||
and then not Is_Limited_Type (Etype (Nam))
|
||||
then
|
||||
Error_Msg_N
|
||||
("?renaming function result object is suspicious",
|
||||
Nam);
|
||||
Error_Msg_NE
|
||||
("\?function & will be called only once",
|
||||
Nam, Entity (Name (Nam)));
|
||||
Error_Msg_N
|
||||
("\?suggest using an initialized constant object instead",
|
||||
Nam);
|
||||
end if;
|
||||
end case;
|
||||
end if;
|
||||
|
||||
-- An object renaming requires an exact match of the type. Class-wide
|
||||
-- matching is not allowed.
|
||||
|
||||
@ -802,7 +851,7 @@ package body Sem_Ch8 is
|
||||
-- formal object of a generic unit G, and the object renaming
|
||||
-- declaration occurs within the body of G or within the body
|
||||
-- of a generic unit declared within the declarative region
|
||||
-- of G, then the declaration of the formal object of G shall
|
||||
-- of G, then the declaration of the formal object of G must
|
||||
-- have a null exclusion.
|
||||
|
||||
if Is_Formal_Object (Nam_Ent)
|
||||
@ -818,8 +867,12 @@ package body Sem_Ch8 is
|
||||
Error_Node := Access_Definition (Nam_Decl);
|
||||
end if;
|
||||
|
||||
Error_Msg_N ("null-exclusion required in formal " &
|
||||
"object declaration", Error_Node);
|
||||
Error_Msg_N
|
||||
("`NOT NULL` required in formal object declaration",
|
||||
Error_Node);
|
||||
Error_Msg_Sloc := Sloc (N);
|
||||
Error_Msg_N
|
||||
("\because of renaming at# ('R'M 8.5.4(4))", Error_Node);
|
||||
|
||||
-- Ada 2005 (AI-423): Otherwise, the subtype of the object name
|
||||
-- shall exclude null.
|
||||
@ -827,8 +880,9 @@ package body Sem_Ch8 is
|
||||
elsif Nkind (Subtyp_Decl) = N_Subtype_Declaration
|
||||
and then not Has_Null_Exclusion (Subtyp_Decl)
|
||||
then
|
||||
Error_Msg_N ("subtype must have null-exclusion",
|
||||
Subtyp_Decl);
|
||||
Error_Msg_N
|
||||
("`NOT NULL` required for subtype & ('R'M 8.5.1(4.6/2))",
|
||||
Defining_Identifier (Subtyp_Decl));
|
||||
end if;
|
||||
end if;
|
||||
end;
|
||||
@ -1275,8 +1329,9 @@ package body Sem_Ch8 is
|
||||
not (Has_Null_Exclusion (Parent (Sub_Formal))
|
||||
or else Can_Never_Be_Null (Etype (Sub_Formal)))
|
||||
then
|
||||
Error_Msg_N ("null-exclusion required in parameter profile",
|
||||
Parent (Sub_Formal));
|
||||
Error_Msg_NE
|
||||
("`NOT NULL` required for parameter &",
|
||||
Parent (Sub_Formal), Sub_Formal);
|
||||
end if;
|
||||
|
||||
Next_Formal (Ren_Formal);
|
||||
@ -1292,8 +1347,9 @@ package body Sem_Ch8 is
|
||||
not (Has_Null_Exclusion (Parent (Sub))
|
||||
or else Can_Never_Be_Null (Etype (Sub)))
|
||||
then
|
||||
Error_Msg_N ("null-exclusion required in return profile",
|
||||
Result_Definition (Parent (Sub)));
|
||||
Error_Msg_N
|
||||
("return must specify `NOT NULL`",
|
||||
Result_Definition (Parent (Sub)));
|
||||
end if;
|
||||
end Check_Null_Exclusion;
|
||||
|
||||
@ -1525,6 +1581,7 @@ package body Sem_Ch8 is
|
||||
-- for it at the freezing point.
|
||||
|
||||
Set_Corresponding_Spec (N, Rename_Spec);
|
||||
|
||||
if Nkind (Unit_Declaration_Node (Rename_Spec)) =
|
||||
N_Abstract_Subprogram_Declaration
|
||||
then
|
||||
@ -1954,8 +2011,9 @@ package body Sem_Ch8 is
|
||||
and then not Can_Never_Be_Null (Old_F)
|
||||
then
|
||||
Error_Msg_N ("access parameter is controlling,", New_F);
|
||||
Error_Msg_NE ("\corresponding parameter of& " &
|
||||
" must be explicitly null excluding", New_F, Old_S);
|
||||
Error_Msg_NE
|
||||
("\corresponding parameter of& "
|
||||
& "must be explicitly null excluding", New_F, Old_S);
|
||||
end if;
|
||||
|
||||
Next_Formal (Old_F);
|
||||
@ -2334,16 +2392,43 @@ package body Sem_Ch8 is
|
||||
Statements => New_List (Attr_Node)));
|
||||
end if;
|
||||
|
||||
Rewrite (N, Body_Node);
|
||||
Analyze (N);
|
||||
-- In case of tagged types we add the body of the generated function to
|
||||
-- the freezing actions of the type (because in the general case such
|
||||
-- type is still not frozen). We exclude from this processing generic
|
||||
-- formal subprograms found in instantiations and AST_Entry renamings.
|
||||
|
||||
if not Present (Corresponding_Formal_Spec (N))
|
||||
and then Etype (Nam) /= RTE (RE_AST_Handler)
|
||||
then
|
||||
declare
|
||||
P : constant Entity_Id := Prefix (Nam);
|
||||
|
||||
begin
|
||||
Find_Type (P);
|
||||
|
||||
if Is_Tagged_Type (Etype (P)) then
|
||||
Ensure_Freeze_Node (Etype (P));
|
||||
Append_Freeze_Action (Etype (P), Body_Node);
|
||||
else
|
||||
Rewrite (N, Body_Node);
|
||||
Analyze (N);
|
||||
Set_Etype (New_S, Base_Type (Etype (New_S)));
|
||||
end if;
|
||||
end;
|
||||
|
||||
-- Generic formal subprograms or AST_Handler renaming
|
||||
|
||||
else
|
||||
Rewrite (N, Body_Node);
|
||||
Analyze (N);
|
||||
Set_Etype (New_S, Base_Type (Etype (New_S)));
|
||||
end if;
|
||||
|
||||
if Is_Compilation_Unit (New_S) then
|
||||
Error_Msg_N
|
||||
("a library unit can only rename another library unit", N);
|
||||
end if;
|
||||
|
||||
Set_Etype (New_S, Base_Type (Etype (New_S)));
|
||||
|
||||
-- We suppress elaboration warnings for the resulting entity, since
|
||||
-- clearly they are not needed, and more particularly, in the case
|
||||
-- of a generic formal subprogram, the resulting entity can appear
|
||||
@ -2502,7 +2587,10 @@ package body Sem_Ch8 is
|
||||
if Nkind (Parent (N)) /= N_Compilation_Unit then
|
||||
return;
|
||||
|
||||
elsif Scope (Old_E) /= Standard_Standard
|
||||
-- Check for library unit. Note that we used to check for the scope
|
||||
-- being Standard here, but that was wrong for Standard itself.
|
||||
|
||||
elsif not Is_Compilation_Unit (Old_E)
|
||||
and then not Is_Child_Unit (Old_E)
|
||||
then
|
||||
Error_Msg_N ("renamed unit must be a library unit", Name (N));
|
||||
@ -3276,7 +3364,7 @@ package body Sem_Ch8 is
|
||||
|
||||
-- Another special check if N is the prefix of a selected
|
||||
-- component which is a known unit, add message complaining
|
||||
-- about missingw with for this unit.
|
||||
-- about missing with for this unit.
|
||||
|
||||
elsif Nkind (Parent (N)) = N_Selected_Component
|
||||
and then N = Prefix (Parent (N))
|
||||
@ -3735,6 +3823,7 @@ package body Sem_Ch8 is
|
||||
|
||||
else
|
||||
Generate_Reference (E, N);
|
||||
Check_Nested_Access (E);
|
||||
end if;
|
||||
|
||||
-- Set Entity, with style check if need be. For a discriminant
|
||||
@ -4029,8 +4118,10 @@ package body Sem_Ch8 is
|
||||
-- we assume a missing with for the corresponding package.
|
||||
|
||||
if Is_Known_Unit (N) then
|
||||
Error_Msg_Node_2 := Selector;
|
||||
Error_Msg_N ("missing `WITH &.&;`", Prefix (N));
|
||||
if not Error_Posted (N) then
|
||||
Error_Msg_Node_2 := Selector;
|
||||
Error_Msg_N ("missing `WITH &.&;`", Prefix (N));
|
||||
end if;
|
||||
|
||||
-- If this is a selection from a dummy package, then suppress
|
||||
-- the error message, of course the entity is missing if the
|
||||
@ -5005,8 +5096,27 @@ package body Sem_Ch8 is
|
||||
else
|
||||
Error_Msg_N
|
||||
("task type cannot be used as type mark " &
|
||||
"within its own body", N);
|
||||
"within its own spec or body", N);
|
||||
end if;
|
||||
|
||||
elsif Ekind (Base_Type (T_Name)) = E_Protected_Type then
|
||||
|
||||
-- In Ada 2005, a protected name can be used in an access
|
||||
-- definition within its own body.
|
||||
|
||||
if Ada_Version >= Ada_05
|
||||
and then Nkind (Parent (N)) = N_Access_Definition
|
||||
then
|
||||
Set_Entity (N, T_Name);
|
||||
Set_Etype (N, T_Name);
|
||||
return;
|
||||
|
||||
else
|
||||
Error_Msg_N
|
||||
("protected type cannot be used as type mark " &
|
||||
"within its own spec or body", N);
|
||||
end if;
|
||||
|
||||
else
|
||||
Error_Msg_N ("type declaration cannot refer to itself", N);
|
||||
end if;
|
||||
@ -5151,10 +5261,10 @@ package body Sem_Ch8 is
|
||||
procedure Add_Implicit_Operator
|
||||
(T : Entity_Id;
|
||||
Op_Type : Entity_Id := Empty);
|
||||
-- Add implicit interpretation to node N, using the type for which
|
||||
-- a predefined operator exists. If the operator yields a boolean
|
||||
-- type, the Operand_Type is implicitly referenced by the operator,
|
||||
-- and a reference to it must be generated.
|
||||
-- Add implicit interpretation to node N, using the type for which a
|
||||
-- predefined operator exists. If the operator yields a boolean type,
|
||||
-- the Operand_Type is implicitly referenced by the operator, and a
|
||||
-- reference to it must be generated.
|
||||
|
||||
---------------------------
|
||||
-- Add_Implicit_Operator --
|
||||
@ -5511,101 +5621,6 @@ package body Sem_Ch8 is
|
||||
and then Has_Components (Designated_Type (T))));
|
||||
end Is_Appropriate_For_Record;
|
||||
|
||||
---------------
|
||||
-- New_Scope --
|
||||
---------------
|
||||
|
||||
procedure New_Scope (S : Entity_Id) is
|
||||
E : Entity_Id;
|
||||
|
||||
begin
|
||||
if Ekind (S) = E_Void then
|
||||
null;
|
||||
|
||||
-- Set scope depth if not a non-concurrent type, and we have not
|
||||
-- yet set the scope depth. This means that we have the first
|
||||
-- occurrence of the scope, and this is where the depth is set.
|
||||
|
||||
elsif (not Is_Type (S) or else Is_Concurrent_Type (S))
|
||||
and then not Scope_Depth_Set (S)
|
||||
then
|
||||
if S = Standard_Standard then
|
||||
Set_Scope_Depth_Value (S, Uint_0);
|
||||
|
||||
elsif Is_Child_Unit (S) then
|
||||
Set_Scope_Depth_Value (S, Uint_1);
|
||||
|
||||
elsif not Is_Record_Type (Current_Scope) then
|
||||
if Ekind (S) = E_Loop then
|
||||
Set_Scope_Depth_Value (S, Scope_Depth (Current_Scope));
|
||||
else
|
||||
Set_Scope_Depth_Value (S, Scope_Depth (Current_Scope) + 1);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
Scope_Stack.Increment_Last;
|
||||
|
||||
declare
|
||||
SST : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
|
||||
|
||||
begin
|
||||
SST.Entity := S;
|
||||
SST.Save_Scope_Suppress := Scope_Suppress;
|
||||
SST.Save_Local_Entity_Suppress := Local_Entity_Suppress.Last;
|
||||
|
||||
if Scope_Stack.Last > Scope_Stack.First then
|
||||
SST.Component_Alignment_Default := Scope_Stack.Table
|
||||
(Scope_Stack.Last - 1).
|
||||
Component_Alignment_Default;
|
||||
end if;
|
||||
|
||||
SST.Last_Subprogram_Name := null;
|
||||
SST.Is_Transient := False;
|
||||
SST.Node_To_Be_Wrapped := Empty;
|
||||
SST.Pending_Freeze_Actions := No_List;
|
||||
SST.Actions_To_Be_Wrapped_Before := No_List;
|
||||
SST.Actions_To_Be_Wrapped_After := No_List;
|
||||
SST.First_Use_Clause := Empty;
|
||||
SST.Is_Active_Stack_Base := False;
|
||||
SST.Previous_Visibility := False;
|
||||
end;
|
||||
|
||||
if Debug_Flag_W then
|
||||
Write_Str ("--> new scope: ");
|
||||
Write_Name (Chars (Current_Scope));
|
||||
Write_Str (", Id=");
|
||||
Write_Int (Int (Current_Scope));
|
||||
Write_Str (", Depth=");
|
||||
Write_Int (Int (Scope_Stack.Last));
|
||||
Write_Eol;
|
||||
end if;
|
||||
|
||||
-- Copy from Scope (S) the categorization flags to S, this is not
|
||||
-- done in case Scope (S) is Standard_Standard since propagation
|
||||
-- is from library unit entity inwards.
|
||||
|
||||
if S /= Standard_Standard
|
||||
and then Scope (S) /= Standard_Standard
|
||||
and then not Is_Child_Unit (S)
|
||||
then
|
||||
E := Scope (S);
|
||||
|
||||
if Nkind (E) not in N_Entity then
|
||||
return;
|
||||
end if;
|
||||
|
||||
-- We only propagate inwards for library level entities,
|
||||
-- inner level subprograms do not inherit the categorization.
|
||||
|
||||
if Is_Library_Level_Entity (S) then
|
||||
Set_Is_Preelaborated (S, Is_Preelaborated (E));
|
||||
Set_Is_Shared_Passive (S, Is_Shared_Passive (E));
|
||||
Set_Categorization_From_Scope (E => S, Scop => E);
|
||||
end if;
|
||||
end if;
|
||||
end New_Scope;
|
||||
|
||||
------------------------
|
||||
-- Note_Redundant_Use --
|
||||
------------------------
|
||||
@ -5832,6 +5847,109 @@ package body Sem_Ch8 is
|
||||
Scope_Stack.Decrement_Last;
|
||||
end Pop_Scope;
|
||||
|
||||
---------------
|
||||
-- Push_Scope --
|
||||
---------------
|
||||
|
||||
procedure Push_Scope (S : Entity_Id) is
|
||||
E : Entity_Id;
|
||||
|
||||
begin
|
||||
if Ekind (S) = E_Void then
|
||||
null;
|
||||
|
||||
-- Set scope depth if not a non-concurrent type, and we have not
|
||||
-- yet set the scope depth. This means that we have the first
|
||||
-- occurrence of the scope, and this is where the depth is set.
|
||||
|
||||
elsif (not Is_Type (S) or else Is_Concurrent_Type (S))
|
||||
and then not Scope_Depth_Set (S)
|
||||
then
|
||||
if S = Standard_Standard then
|
||||
Set_Scope_Depth_Value (S, Uint_0);
|
||||
|
||||
elsif Is_Child_Unit (S) then
|
||||
Set_Scope_Depth_Value (S, Uint_1);
|
||||
|
||||
elsif not Is_Record_Type (Current_Scope) then
|
||||
if Ekind (S) = E_Loop then
|
||||
Set_Scope_Depth_Value (S, Scope_Depth (Current_Scope));
|
||||
else
|
||||
Set_Scope_Depth_Value (S, Scope_Depth (Current_Scope) + 1);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
Scope_Stack.Increment_Last;
|
||||
|
||||
declare
|
||||
SST : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
|
||||
|
||||
begin
|
||||
SST.Entity := S;
|
||||
SST.Save_Scope_Suppress := Scope_Suppress;
|
||||
SST.Save_Local_Entity_Suppress := Local_Entity_Suppress.Last;
|
||||
|
||||
if Scope_Stack.Last > Scope_Stack.First then
|
||||
SST.Component_Alignment_Default := Scope_Stack.Table
|
||||
(Scope_Stack.Last - 1).
|
||||
Component_Alignment_Default;
|
||||
end if;
|
||||
|
||||
SST.Last_Subprogram_Name := null;
|
||||
SST.Is_Transient := False;
|
||||
SST.Node_To_Be_Wrapped := Empty;
|
||||
SST.Pending_Freeze_Actions := No_List;
|
||||
SST.Actions_To_Be_Wrapped_Before := No_List;
|
||||
SST.Actions_To_Be_Wrapped_After := No_List;
|
||||
SST.First_Use_Clause := Empty;
|
||||
SST.Is_Active_Stack_Base := False;
|
||||
SST.Previous_Visibility := False;
|
||||
end;
|
||||
|
||||
if Debug_Flag_W then
|
||||
Write_Str ("--> new scope: ");
|
||||
Write_Name (Chars (Current_Scope));
|
||||
Write_Str (", Id=");
|
||||
Write_Int (Int (Current_Scope));
|
||||
Write_Str (", Depth=");
|
||||
Write_Int (Int (Scope_Stack.Last));
|
||||
Write_Eol;
|
||||
end if;
|
||||
|
||||
-- Deal with copying flags from the previous scope to this one. This
|
||||
-- is not necessary if either scope is standard, or if the new scope
|
||||
-- is a child unit.
|
||||
|
||||
if S /= Standard_Standard
|
||||
and then Scope (S) /= Standard_Standard
|
||||
and then not Is_Child_Unit (S)
|
||||
then
|
||||
E := Scope (S);
|
||||
|
||||
if Nkind (E) not in N_Entity then
|
||||
return;
|
||||
end if;
|
||||
|
||||
-- Copy categorization flags from Scope (S) to S, this is not done
|
||||
-- when Scope (S) is Standard_Standard since propagation is from
|
||||
-- library unit entity inwards. Copy other relevant attributes as
|
||||
-- well (Discard_Names in particular).
|
||||
|
||||
-- We only propagate inwards for library level entities,
|
||||
-- inner level subprograms do not inherit the categorization.
|
||||
|
||||
if Is_Library_Level_Entity (S) then
|
||||
Set_Is_Preelaborated (S, Is_Preelaborated (E));
|
||||
Set_Is_Shared_Passive (S, Is_Shared_Passive (E));
|
||||
Set_Discard_Names (S, Discard_Names (E));
|
||||
Set_Suppress_Value_Tracking_On_Call
|
||||
(S, Suppress_Value_Tracking_On_Call (E));
|
||||
Set_Categorization_From_Scope (E => S, Scop => E);
|
||||
end if;
|
||||
end if;
|
||||
end Push_Scope;
|
||||
|
||||
---------------------
|
||||
-- Premature_Usage --
|
||||
---------------------
|
||||
@ -5897,7 +6015,7 @@ package body Sem_Ch8 is
|
||||
|
||||
function Present_System_Aux (N : Node_Id := Empty) return Boolean is
|
||||
Loc : Source_Ptr;
|
||||
Aux_Name : Name_Id;
|
||||
Aux_Name : Unit_Name_Type;
|
||||
Unum : Unit_Number_Type;
|
||||
Withn : Node_Id;
|
||||
With_Sys : Node_Id;
|
||||
@ -6104,11 +6222,11 @@ package body Sem_Ch8 is
|
||||
end if;
|
||||
|
||||
if Is_Child_Unit (S)
|
||||
and not In_Child -- check only for current unit.
|
||||
and not In_Child -- check only for current unit
|
||||
then
|
||||
In_Child := True;
|
||||
|
||||
-- restore visibility of parents according to whether the child
|
||||
-- Restore visibility of parents according to whether the child
|
||||
-- is private and whether we are in its visible part.
|
||||
|
||||
Comp_Unit := Parent (Unit_Declaration_Node (S));
|
||||
|
@ -6,7 +6,7 @@
|
||||
-- --
|
||||
-- B o d y --
|
||||
-- --
|
||||
-- Copyright (C) 1999-2006, Free Software Foundation, Inc. --
|
||||
-- Copyright (C) 1999-2007, 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- --
|
||||
@ -26,6 +26,7 @@
|
||||
|
||||
with Alloc;
|
||||
with Atree; use Atree;
|
||||
with Debug; use Debug;
|
||||
with Einfo; use Einfo;
|
||||
with Errout; use Errout;
|
||||
with Exp_Code; use Exp_Code;
|
||||
@ -119,6 +120,377 @@ package body Sem_Warn is
|
||||
end if;
|
||||
end Check_Code_Statement;
|
||||
|
||||
---------------------------------
|
||||
-- Check_Infinite_Loop_Warning --
|
||||
---------------------------------
|
||||
|
||||
-- The case we look for is a while loop which tests a local variable, where
|
||||
-- there is no obvious direct or possible indirect update of the variable
|
||||
-- within the body of the loop.
|
||||
|
||||
procedure Check_Infinite_Loop_Warning (Loop_Statement : Node_Id) is
|
||||
Iter : constant Node_Id := Iteration_Scheme (Loop_Statement);
|
||||
|
||||
Ref : Node_Id := Empty;
|
||||
-- Reference in iteration scheme to variable that may not be modified
|
||||
-- in loop, indicating a possible infinite loop.
|
||||
|
||||
Var : Entity_Id := Empty;
|
||||
-- Corresponding entity (entity of Ref)
|
||||
|
||||
procedure Find_Var (N : Node_Id);
|
||||
-- Inspect condition to see if it depends on a single entity
|
||||
-- reference. If so, Ref is set to point to the reference node,
|
||||
-- and Var is set to the referenced Entity.
|
||||
|
||||
function Has_Indirection (T : Entity_Id) return Boolean;
|
||||
-- If the controlling variable is an access type, or is a record type
|
||||
-- with access components, assume that it is changed indirectly and
|
||||
-- suppress the warning. As a concession to low-level programming, in
|
||||
-- particular within Declib, we also suppress warnings on a record
|
||||
-- type that contains components of type Address or Short_Address.
|
||||
|
||||
function Is_Suspicious_Function_Name (E : Entity_Id) return Boolean;
|
||||
-- Given an entity name, see if the name appears to have something to
|
||||
-- do with I/O or network stuff, and if so, return True. Used to kill
|
||||
-- some false positives on a heuristic basis that such functions will
|
||||
-- likely have some strange side effect dependencies. A rather funny
|
||||
-- kludge, but warning messages are in the heuristics business.
|
||||
|
||||
function Test_Ref (N : Node_Id) return Traverse_Result;
|
||||
-- Test for reference to variable in question. Returns Abandon if
|
||||
-- matching reference found.
|
||||
|
||||
function Find_Ref is new Traverse_Func (Test_Ref);
|
||||
-- Function to traverse body of procedure. Returns Abandon if matching
|
||||
-- reference found.
|
||||
|
||||
--------------
|
||||
-- Find_Var --
|
||||
--------------
|
||||
|
||||
procedure Find_Var (N : Node_Id) is
|
||||
begin
|
||||
-- Condition is a direct variable reference
|
||||
|
||||
if Is_Entity_Name (N) then
|
||||
Ref := N;
|
||||
Var := Entity (Ref);
|
||||
|
||||
-- Case of condition is a comparison with compile time known value
|
||||
|
||||
elsif Nkind (N) in N_Op_Compare then
|
||||
if Compile_Time_Known_Value (Right_Opnd (N)) then
|
||||
Find_Var (Left_Opnd (N));
|
||||
|
||||
elsif Compile_Time_Known_Value (Left_Opnd (N)) then
|
||||
Find_Var (Right_Opnd (N));
|
||||
|
||||
-- Ignore any other comparison
|
||||
|
||||
else
|
||||
return;
|
||||
end if;
|
||||
|
||||
-- If condition is a negation, check its operand
|
||||
|
||||
elsif Nkind (N) = N_Op_Not then
|
||||
Find_Var (Right_Opnd (N));
|
||||
|
||||
-- Case of condition is function call
|
||||
|
||||
elsif Nkind (N) = N_Function_Call then
|
||||
|
||||
-- Forget it if function name is not entity, who knows what
|
||||
-- we might be calling?
|
||||
|
||||
if not Is_Entity_Name (Name (N)) then
|
||||
return;
|
||||
|
||||
-- Forget it if warnings are suppressed on function entity
|
||||
|
||||
elsif Warnings_Off (Entity (Name (N))) then
|
||||
return;
|
||||
|
||||
-- Forget it if function name is suspicious. A strange test
|
||||
-- but warning generation is in the heuristics business!
|
||||
|
||||
elsif Is_Suspicious_Function_Name (Entity (Name (N))) then
|
||||
return;
|
||||
end if;
|
||||
|
||||
-- OK, see if we have one argument
|
||||
|
||||
declare
|
||||
PA : constant List_Id := Parameter_Associations (N);
|
||||
|
||||
begin
|
||||
-- One argument, so check the argument
|
||||
|
||||
if Present (PA)
|
||||
and then List_Length (PA) = 1
|
||||
then
|
||||
if Nkind (First (PA)) = N_Parameter_Association then
|
||||
Find_Var (Explicit_Actual_Parameter (First (PA)));
|
||||
else
|
||||
Find_Var (First (PA));
|
||||
end if;
|
||||
|
||||
-- Not one argument
|
||||
|
||||
else
|
||||
return;
|
||||
end if;
|
||||
end;
|
||||
|
||||
-- Any other kind of node is not something we warn for
|
||||
|
||||
else
|
||||
return;
|
||||
end if;
|
||||
end Find_Var;
|
||||
|
||||
---------------------
|
||||
-- Has_Indirection --
|
||||
---------------------
|
||||
|
||||
function Has_Indirection (T : Entity_Id) return Boolean is
|
||||
Comp : Entity_Id;
|
||||
Rec : Entity_Id;
|
||||
|
||||
begin
|
||||
if Is_Access_Type (T) then
|
||||
return True;
|
||||
|
||||
elsif Is_Private_Type (T)
|
||||
and then Present (Full_View (T))
|
||||
and then Is_Access_Type (Full_View (T))
|
||||
then
|
||||
return True;
|
||||
|
||||
elsif Is_Record_Type (T) then
|
||||
Rec := T;
|
||||
|
||||
elsif Is_Private_Type (T)
|
||||
and then Present (Full_View (T))
|
||||
and then Is_Record_Type (Full_View (T))
|
||||
then
|
||||
Rec := Full_View (T);
|
||||
else
|
||||
return False;
|
||||
end if;
|
||||
|
||||
Comp := First_Component (Rec);
|
||||
while Present (Comp) loop
|
||||
if Is_Access_Type (Etype (Comp))
|
||||
or else Is_Descendent_Of_Address (Etype (Comp))
|
||||
then
|
||||
return True;
|
||||
end if;
|
||||
|
||||
Next_Component (Comp);
|
||||
end loop;
|
||||
|
||||
return False;
|
||||
end Has_Indirection;
|
||||
|
||||
---------------------------------
|
||||
-- Is_Suspicious_Function_Name --
|
||||
---------------------------------
|
||||
|
||||
function Is_Suspicious_Function_Name (E : Entity_Id) return Boolean is
|
||||
S : Entity_Id;
|
||||
|
||||
function Substring_Present (S : String) return Boolean;
|
||||
-- Returns True if name buffer has given string delimited by non-
|
||||
-- alphabetic characters or by end of string. S is lower case.
|
||||
|
||||
-----------------------
|
||||
-- Substring_Present --
|
||||
-----------------------
|
||||
|
||||
function Substring_Present (S : String) return Boolean is
|
||||
Len : constant Natural := S'Length;
|
||||
|
||||
begin
|
||||
for J in 1 .. Name_Len - (Len - 1) loop
|
||||
if Name_Buffer (J .. J + (Len - 1)) = S
|
||||
and then
|
||||
(J = 1
|
||||
or else Name_Buffer (J - 1) not in 'a' .. 'z')
|
||||
and then
|
||||
(J + Len > Name_Len
|
||||
or else Name_Buffer (J + Len) not in 'a' .. 'z')
|
||||
then
|
||||
return True;
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
return False;
|
||||
end Substring_Present;
|
||||
|
||||
-- Start of processing for Is_Suspicious_Function_Name
|
||||
|
||||
begin
|
||||
S := E;
|
||||
while Present (S) and then S /= Standard_Standard loop
|
||||
Get_Name_String (Chars (S));
|
||||
|
||||
if Substring_Present ("io")
|
||||
or else Substring_Present ("file")
|
||||
or else Substring_Present ("network")
|
||||
then
|
||||
return True;
|
||||
else
|
||||
S := Scope (S);
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
return False;
|
||||
end Is_Suspicious_Function_Name;
|
||||
|
||||
--------------
|
||||
-- Test_Ref --
|
||||
--------------
|
||||
|
||||
function Test_Ref (N : Node_Id) return Traverse_Result is
|
||||
begin
|
||||
-- Waste of time to look at iteration scheme
|
||||
|
||||
if N = Iter then
|
||||
return Skip;
|
||||
|
||||
-- Direct reference to variable in question
|
||||
|
||||
elsif Is_Entity_Name (N)
|
||||
and then Present (Entity (N))
|
||||
and then Entity (N) = Var
|
||||
then
|
||||
-- If this is an Lvalue, then definitely abandon, since
|
||||
-- this could be a direct modification of the variable.
|
||||
|
||||
if May_Be_Lvalue (N) then
|
||||
return Abandon;
|
||||
end if;
|
||||
|
||||
-- If we appear in the context of a procedure call, then also
|
||||
-- abandon, since there may be issues of non-visible side
|
||||
-- effects going on in the call.
|
||||
|
||||
declare
|
||||
P : Node_Id;
|
||||
begin
|
||||
P := N;
|
||||
loop
|
||||
P := Parent (P);
|
||||
exit when P = Loop_Statement;
|
||||
|
||||
if Nkind (P) = N_Procedure_Call_Statement then
|
||||
return Abandon;
|
||||
end if;
|
||||
end loop;
|
||||
end;
|
||||
|
||||
-- Reference to variable renaming variable in question
|
||||
|
||||
elsif Is_Entity_Name (N)
|
||||
and then Present (Entity (N))
|
||||
and then Ekind (Entity (N)) = E_Variable
|
||||
and then Present (Renamed_Object (Entity (N)))
|
||||
and then Is_Entity_Name (Renamed_Object (Entity (N)))
|
||||
and then Entity (Renamed_Object (Entity (N))) = Var
|
||||
and then May_Be_Lvalue (N)
|
||||
then
|
||||
return Abandon;
|
||||
|
||||
-- Call to subprogram
|
||||
|
||||
elsif Nkind (N) = N_Procedure_Call_Statement
|
||||
or else Nkind (N) = N_Function_Call
|
||||
then
|
||||
-- If subprogram is within the scope of the entity we are
|
||||
-- dealing with as the loop variable, then it could modify
|
||||
-- this parameter, so we abandon in this case. In the case
|
||||
-- of a subprogram that is not an entity we also abandon.
|
||||
|
||||
if not Is_Entity_Name (Name (N))
|
||||
or else Scope_Within (Entity (Name (N)), Scope (Var))
|
||||
then
|
||||
return Abandon;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- All OK, continue scan
|
||||
|
||||
return OK;
|
||||
end Test_Ref;
|
||||
|
||||
-- Start of processing for Check_Infinite_Loop_Warning
|
||||
|
||||
begin
|
||||
-- We need a while iteration with no condition actions. Conditions
|
||||
-- actions just make things too complicated to get the warning right.
|
||||
|
||||
if No (Iter)
|
||||
or else No (Condition (Iter))
|
||||
or else Present (Condition_Actions (Iter))
|
||||
or else Debug_Flag_Dot_W
|
||||
then
|
||||
return;
|
||||
end if;
|
||||
|
||||
-- Initial conditions met, see if condition is of right form
|
||||
|
||||
Find_Var (Condition (Iter));
|
||||
|
||||
-- Nothing to do if local variable from source not found
|
||||
|
||||
if No (Var)
|
||||
or else Ekind (Var) /= E_Variable
|
||||
or else Is_Library_Level_Entity (Var)
|
||||
or else not Comes_From_Source (Var)
|
||||
then
|
||||
return;
|
||||
|
||||
-- Nothing to do if there is some indirection involved (assume that the
|
||||
-- designated variable might be modified in some way we don't see).
|
||||
|
||||
elsif Has_Indirection (Etype (Var)) then
|
||||
return;
|
||||
|
||||
-- Same sort of thing for volatile variable, might be modified by
|
||||
-- some other task or by the operating system in some way.
|
||||
|
||||
elsif Is_Volatile (Var) then
|
||||
return;
|
||||
end if;
|
||||
|
||||
-- Filter out case of original statement sequence starting with delay.
|
||||
-- We assume this is a multi-tasking program and that the condition
|
||||
-- is affected by other threads (some kind of busy wait).
|
||||
|
||||
declare
|
||||
Fstm : constant Node_Id :=
|
||||
Original_Node (First (Statements (Loop_Statement)));
|
||||
begin
|
||||
if Nkind (Fstm) = N_Delay_Relative_Statement
|
||||
or else Nkind (Fstm) = N_Delay_Until_Statement
|
||||
then
|
||||
return;
|
||||
end if;
|
||||
end;
|
||||
|
||||
-- We have a variable reference of the right form, now we scan the loop
|
||||
-- body to see if it looks like it might not be modified
|
||||
|
||||
if Find_Ref (Loop_Statement) = OK then
|
||||
Error_Msg_NE
|
||||
("variable& is not modified in loop body?", Ref, Var);
|
||||
Error_Msg_N
|
||||
("\possible infinite loop", Ref);
|
||||
end if;
|
||||
end Check_Infinite_Loop_Warning;
|
||||
|
||||
----------------------
|
||||
-- Check_References --
|
||||
----------------------
|
||||
@ -334,10 +706,14 @@ package body Sem_Warn is
|
||||
E1 := First_Entity (E);
|
||||
while Present (E1) loop
|
||||
|
||||
-- We only look at source entities with warning flag on
|
||||
|
||||
if Comes_From_Source (E1) and then not Warnings_Off (E1) then
|
||||
-- We only look at source entities with warning flag on. We also
|
||||
-- ignore objects whose type or base type has warnings suppressed.
|
||||
|
||||
if Comes_From_Source (E1)
|
||||
and then not Warnings_Off (E1)
|
||||
and then not Warnings_Off (Etype (E1))
|
||||
and then not Warnings_Off (Base_Type (Etype (E1)))
|
||||
then
|
||||
-- We are interested in variables and out parameters, but we
|
||||
-- exclude protected types, too complicated to worry about.
|
||||
|
||||
@ -629,6 +1005,14 @@ package body Sem_Warn is
|
||||
and then (Nkind (Unit (Cunit (Main_Unit))) /= N_Subunit
|
||||
or else
|
||||
Get_Source_Unit (E1) = Main_Unit)
|
||||
|
||||
-- No warning on a return object, because these are often
|
||||
-- created with a single expression and an implicit return.
|
||||
-- If the object is a variable there will be a warning
|
||||
-- indicating that it could be declared constant.
|
||||
|
||||
and then not
|
||||
(Ekind (E1) = E_Constant and then Is_Return_Object (E1))
|
||||
then
|
||||
-- Suppress warnings in internal units if not in -gnatg mode
|
||||
-- (these would be junk warnings for an applications program,
|
||||
@ -870,7 +1254,7 @@ package body Sem_Warn is
|
||||
return;
|
||||
end if;
|
||||
|
||||
-- We are only interested in deferences
|
||||
-- We are only interested in dereferences
|
||||
|
||||
if not Is_Dereferenced (N) then
|
||||
return;
|
||||
@ -1741,6 +2125,18 @@ package body Sem_Warn is
|
||||
function Set_Dot_Warning_Switch (C : Character) return Boolean is
|
||||
begin
|
||||
case C is
|
||||
when 'c' =>
|
||||
Warn_On_Unrepped_Components := True;
|
||||
|
||||
when 'C' =>
|
||||
Warn_On_Unrepped_Components := False;
|
||||
|
||||
when 'r' =>
|
||||
Warn_On_Object_Renames_Function := True;
|
||||
|
||||
when 'R' =>
|
||||
Warn_On_Object_Renames_Function := False;
|
||||
|
||||
when 'x' =>
|
||||
Warn_On_Non_Local_Exception := True;
|
||||
|
||||
@ -1779,8 +2175,10 @@ package body Sem_Warn is
|
||||
Warn_On_Obsolescent_Feature := True;
|
||||
Warn_On_Questionable_Missing_Parens := True;
|
||||
Warn_On_Redundant_Constructs := True;
|
||||
Warn_On_Object_Renames_Function := True;
|
||||
Warn_On_Unchecked_Conversion := True;
|
||||
Warn_On_Unrecognized_Pragma := True;
|
||||
Warn_On_Unrepped_Components := True;
|
||||
|
||||
when 'A' =>
|
||||
Check_Unreferenced := False;
|
||||
@ -1803,8 +2201,10 @@ package body Sem_Warn is
|
||||
Warn_On_Obsolescent_Feature := False;
|
||||
Warn_On_Questionable_Missing_Parens := False;
|
||||
Warn_On_Redundant_Constructs := False;
|
||||
Warn_On_Object_Renames_Function := False;
|
||||
Warn_On_Unchecked_Conversion := False;
|
||||
Warn_On_Unrecognized_Pragma := False;
|
||||
Warn_On_Unrepped_Components := False;
|
||||
|
||||
when 'b' =>
|
||||
Warn_On_Bad_Fixed_Value := True;
|
||||
|
@ -6,7 +6,7 @@
|
||||
-- --
|
||||
-- S p e c --
|
||||
-- --
|
||||
-- Copyright (C) 1999-2006, Free Software Foundation, Inc. --
|
||||
-- Copyright (C) 1999-2007, 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- --
|
||||
@ -120,7 +120,11 @@ package Sem_Warn is
|
||||
----------------------------
|
||||
|
||||
procedure Check_Code_Statement (N : Node_Id);
|
||||
-- Peform warning checks on a code statement node
|
||||
-- Perform warning checks on a code statement node
|
||||
|
||||
procedure Check_Infinite_Loop_Warning (Loop_Statement : Node_Id);
|
||||
-- N is the node for a loop statement. This procedure checks if a warning
|
||||
-- should be given for a possible infinite loop, and if so issues it.
|
||||
|
||||
procedure Warn_On_Known_Condition (C : Node_Id);
|
||||
-- C is a node for a boolean expression resluting from a relational
|
||||
|
Loading…
x
Reference in New Issue
Block a user