* [Ada] Improve and unify warning machinery for address clauses
@ 2016-06-22 10:06 Arnaud Charlet
0 siblings, 0 replies; only message in thread
From: Arnaud Charlet @ 2016-06-22 10:06 UTC (permalink / raw)
To: gcc-patches; +Cc: Eric Botcazou
[-- Attachment #1: Type: text/plain, Size: 3025 bytes --]
This change moves the rest of the warning machinery for address clauses to
Validate_Address_Clauses, ensuring that all the variants are issued from it.
This affects only absolute address clauses in practice, i.e. address clauses
of the form for I'Address use To_Address (16#XXXX_XXXX#) and variants thereof.
This automatically brings a couple of improvements: warnings are more accurate
because they take into account the final alignment set by the back-end and they
catch more cases because the back-end sets the alignment of every single type
and object in the program. The warning also prints the alignment value now.
The following code gives an example of the warnings:
pragma Unsuppress (Alignment_Check);
1. with System.Storage_Elements; use System.Storage_Elements;
2.
3. package P is
4.
5. I : Integer;
6. for I'Address use To_Address (16#7FFF_0001#); -- warning
|
>>> warning: specified address for "I" is inconsistent with alignment
>>> warning: program execution may be erroneous (RM 13.3(27))
>>> warning: alignment of "I" is 4
7.
8. type Rec is record
9. I : Integer;
10. end record;
11.
12. R1 : Rec;
13. for R1'Address use To_Address (16#7FFF_0001#); -- warning
|
>>> warning: specified address for "R1" is inconsistent with alignment
>>> warning: program execution may be erroneous (RM 13.3(27))
>>> warning: alignment of "R1" is 4
14.
15. C : constant System.Address := To_Address (16#7FFF_0001#); -- warning
16.
17. R2 : Rec;
18. for R2'Address use C;
|
>>> warning: specified address for "R2" is inconsistent with alignment
>>> warning: program execution may be erroneous (RM 13.3(27))
>>> warning: alignment of "R2" is 4
19.
20. R3 : Rec;
21. for R3'Address use To_Address (16#7FFF_0004#); -- no warning
22.
23. end P;
23 lines: No errors, 9 warnings
Tested on x86_64-pc-linux-gnu, committed on trunk
2016-06-22 Eric Botcazou <ebotcazou@adacore.com>
* sem_util.ads (Address_Value): Declare new function.
* sem_util.adb (Address_Value): New function extracted
unmodified from Apply_Address_Clause_Check, which returns the
underlying value of the expression of an address clause.
* checks.adb (Compile_Time_Bad_Alignment): Delete.
(Apply_Address_Clause_Check): Call Address_Value on
the expression. Do not issue the main warning here and
issue the secondary warning only when the value of the
expression is not known at compile time.
* sem_ch13.adb (Address_Clause_Check_Record): Add A component and
adjust the description.
(Analyze_Attribute_Definition_Clause): In the case
of an address, move up the code creating an entry in the table of
address clauses. Also create an entry for an absolute address.
(Validate_Address_Clauses): Issue the warning for absolute
addresses here too. Tweak condition associated with overlays
for consistency.
[-- Attachment #2: difs --]
[-- Type: text/plain, Size: 15914 bytes --]
Index: checks.adb
===================================================================
--- checks.adb (revision 237687)
+++ checks.adb (revision 237688)
@@ -638,36 +638,12 @@
AC : constant Node_Id := Address_Clause (E);
Loc : constant Source_Ptr := Sloc (AC);
Typ : constant Entity_Id := Etype (E);
- Aexp : constant Node_Id := Expression (AC);
Expr : Node_Id;
-- Address expression (not necessarily the same as Aexp, for example
-- when Aexp is a reference to a constant, in which case Expr gets
-- reset to reference the value expression of the constant).
- procedure Compile_Time_Bad_Alignment;
- -- Post error warnings when alignment is known to be incompatible. Note
- -- that we do not go as far as inserting a raise of Program_Error since
- -- this is an erroneous case, and it may happen that we are lucky and an
- -- underaligned address turns out to be OK after all.
-
- --------------------------------
- -- Compile_Time_Bad_Alignment --
- --------------------------------
-
- procedure Compile_Time_Bad_Alignment is
- begin
- if Address_Clause_Overlay_Warnings then
- Error_Msg_FE
- ("?o?specified address for& may be inconsistent with alignment",
- Aexp, E);
- Error_Msg_FE
- ("\?o?program execution may be erroneous (RM 13.3(27))",
- Aexp, E);
- Set_Address_Warning_Posted (AC);
- end if;
- end Compile_Time_Bad_Alignment;
-
-- Start of processing for Apply_Address_Clause_Check
begin
@@ -690,44 +666,12 @@
-- Obtain expression from address clause
- Expr := Expression (AC);
+ Expr := Address_Value (Expression (AC));
- -- The following loop digs for the real expression to use in the check
+ -- See if we know that Expr has an acceptable value at compile time. If
+ -- it hasn't or we don't know, we defer issuing the warning until the
+ -- end of the compilation to take into account back end annotations.
- loop
- -- For constant, get constant expression
-
- if Is_Entity_Name (Expr)
- and then Ekind (Entity (Expr)) = E_Constant
- then
- Expr := Constant_Value (Entity (Expr));
-
- -- For unchecked conversion, get result to convert
-
- elsif Nkind (Expr) = N_Unchecked_Type_Conversion then
- Expr := Expression (Expr);
-
- -- For (common case) of To_Address call, get argument
-
- elsif Nkind (Expr) = N_Function_Call
- and then Is_Entity_Name (Name (Expr))
- and then Is_RTE (Entity (Name (Expr)), RE_To_Address)
- then
- Expr := First (Parameter_Associations (Expr));
-
- if Nkind (Expr) = N_Parameter_Association then
- Expr := Explicit_Actual_Parameter (Expr);
- end if;
-
- -- We finally have the real expression
-
- else
- exit;
- end if;
- end loop;
-
- -- See if we know that Expr has a bad alignment at compile time
-
if Compile_Time_Known_Value (Expr)
and then (Known_Alignment (E) or else Known_Alignment (Typ))
then
@@ -742,9 +686,7 @@
AL := Alignment (E);
end if;
- if Expr_Value (Expr) mod AL /= 0 then
- Compile_Time_Bad_Alignment;
- else
+ if Expr_Value (Expr) mod AL = 0 then
return;
end if;
end;
@@ -818,12 +760,11 @@
Warning_Msg := No_Error_Msg;
Analyze (First (Actions (N)), Suppress => All_Checks);
- -- If the address clause generated a warning message (for example,
+ -- If the above raise action generated a warning message (for example
-- from Warn_On_Non_Local_Exception mode with the active restriction
-- No_Exception_Propagation).
if Warning_Msg /= No_Error_Msg then
-
-- If the expression has a known at compile time value, then
-- once we know the alignment of the type, we can check if the
-- exception will be raised or not, and if not, we don't need
@@ -832,13 +773,13 @@
if Compile_Time_Known_Value (Expr) then
Alignment_Warnings.Append
((E => E, A => Expr_Value (Expr), W => Warning_Msg));
- end if;
+ else
+ -- Add explanation of the warning generated by the check
- -- Add explanation of the warning that is generated by the check
-
- Error_Msg_N
- ("\address value may be incompatible with alignment "
- & "of object?X?", AC);
+ Error_Msg_N
+ ("\address value may be incompatible with alignment "
+ & "of object?X?", AC);
+ end if;
end if;
return;
Index: sem_util.adb
===================================================================
--- sem_util.adb (revision 237687)
+++ sem_util.adb (revision 237688)
@@ -286,6 +286,49 @@
end if;
end Address_Integer_Convert_OK;
+ -------------------
+ -- Address_Value --
+ -------------------
+
+ function Address_Value (N : Node_Id) return Node_Id is
+ Expr : Node_Id := N;
+
+ begin
+ loop
+ -- For constant, get constant expression
+
+ if Is_Entity_Name (Expr)
+ and then Ekind (Entity (Expr)) = E_Constant
+ then
+ Expr := Constant_Value (Entity (Expr));
+
+ -- For unchecked conversion, get result to convert
+
+ elsif Nkind (Expr) = N_Unchecked_Type_Conversion then
+ Expr := Expression (Expr);
+
+ -- For (common case) of To_Address call, get argument
+
+ elsif Nkind (Expr) = N_Function_Call
+ and then Is_Entity_Name (Name (Expr))
+ and then Is_RTE (Entity (Name (Expr)), RE_To_Address)
+ then
+ Expr := First (Parameter_Associations (Expr));
+
+ if Nkind (Expr) = N_Parameter_Association then
+ Expr := Explicit_Actual_Parameter (Expr);
+ end if;
+
+ -- We finally have the real expression
+
+ else
+ exit;
+ end if;
+ end loop;
+
+ return Expr;
+ end Address_Value;
+
-----------------
-- Addressable --
-----------------
Index: sem_util.ads
===================================================================
--- sem_util.ads (revision 237687)
+++ sem_util.ads (revision 237688)
@@ -65,6 +65,9 @@
-- and one of the types is (a descendant of) System.Address (and this type
-- is private), and the other type is any integer type.
+ function Address_Value (N : Node_Id) return Node_Id;
+ -- Return the underlying value of the expression N of an address clause
+
function Addressable (V : Uint) return Boolean;
function Addressable (V : Int) return Boolean;
pragma Inline (Addressable);
Index: sem_ch13.adb
===================================================================
--- sem_ch13.adb (revision 237687)
+++ sem_ch13.adb (revision 237688)
@@ -273,9 +273,10 @@
-- for X'Address use Expr
- -- where Expr is of the form Y'Address or recursively is a reference to a
- -- constant of either of these forms, and X and Y are entities of objects,
- -- then if Y has a smaller alignment than X, that merits a warning about
+ -- where Expr has a value known at compile time or is of the form Y'Address
+ -- or recursively is a reference to a constant initialized with either of
+ -- these forms, and the value of Expr is not a multiple of X's alignment,
+ -- or if Y has a smaller alignment than X, then that merits a warning about
-- possible bad alignment. The following table collects address clauses of
-- this kind. We put these in a table so that they can be checked after the
-- back end has completed annotation of the alignments of objects, since we
@@ -286,13 +287,16 @@
-- The address clause
X : Entity_Id;
- -- The entity of the object overlaying Y
+ -- The entity of the object subject to the address clause
+ A : Uint;
+ -- The value of the address in the first case
+
Y : Entity_Id;
- -- The entity of the object being overlaid
+ -- The entity of the object being overlaid in the second case
Off : Boolean;
- -- Whether the address is offset within Y
+ -- Whether the address is offset within Y in the second case
end record;
package Address_Clause_Checks is new Table.Table (
@@ -4849,6 +4853,40 @@
Set_Overlays_Constant (U_Ent);
end if;
+ -- If the address clause is of the form:
+
+ -- for X'Address use Y'Address;
+
+ -- or
+
+ -- C : constant Address := Y'Address;
+ -- ...
+ -- for X'Address use C;
+
+ -- then we make an entry in the table to check the size
+ -- and alignment of the overlaying variable. But we defer
+ -- this check till after code generation to take full
+ -- advantage of the annotation done by the back end.
+
+ -- If the entity has a generic type, the check will be
+ -- performed in the instance if the actual type justifies
+ -- it, and we do not insert the clause in the table to
+ -- prevent spurious warnings.
+
+ -- Note: we used to test Comes_From_Source and only give
+ -- this warning for source entities, but we have removed
+ -- this test. It really seems bogus to generate overlays
+ -- that would trigger this warning in generated code.
+ -- Furthermore, by removing the test, we handle the
+ -- aspect case properly.
+
+ if Is_Object (O_Ent)
+ and then not Is_Generic_Type (Etype (U_Ent))
+ and then Address_Clause_Overlay_Warnings
+ then
+ Address_Clause_Checks.Append
+ ((N, U_Ent, No_Uint, O_Ent, Off));
+ end if;
else
-- If this is not an overlay, mark a variable as being
-- volatile to prevent unwanted optimizations. It's a
@@ -4861,6 +4899,21 @@
if Ekind (U_Ent) = E_Variable then
Set_Treat_As_Volatile (U_Ent);
end if;
+
+ -- Make an entry in the table for an absolute address as
+ -- above to check that the value is compatible with the
+ -- alignment of the object.
+
+ declare
+ Addr : constant Node_Id := Address_Value (Expr);
+ begin
+ if Compile_Time_Known_Value (Addr)
+ and then Address_Clause_Overlay_Warnings
+ then
+ Address_Clause_Checks.Append
+ ((N, U_Ent, Expr_Value (Addr), Empty, False));
+ end if;
+ end;
end if;
-- Overlaying controlled objects is erroneous. Emit warning
@@ -4950,41 +5003,6 @@
-- the variable, it is somewhere else.
Kill_Size_Check_Code (U_Ent);
-
- -- If the address clause is of the form:
-
- -- for Y'Address use X'Address
-
- -- or
-
- -- Const : constant Address := X'Address;
- -- ...
- -- for Y'Address use Const;
-
- -- then we make an entry in the table for checking the size
- -- and alignment of the overlaying variable. We defer this
- -- check till after code generation to take full advantage
- -- of the annotation done by the back end.
-
- -- If the entity has a generic type, the check will be
- -- performed in the instance if the actual type justifies
- -- it, and we do not insert the clause in the table to
- -- prevent spurious warnings.
-
- -- Note: we used to test Comes_From_Source and only give
- -- this warning for source entities, but we have removed
- -- this test. It really seems bogus to generate overlays
- -- that would trigger this warning in generated code.
- -- Furthermore, by removing the test, we handle the
- -- aspect case properly.
-
- if Present (O_Ent)
- and then Is_Object (O_Ent)
- and then not Is_Generic_Type (Etype (U_Ent))
- and then Address_Clause_Overlay_Warnings
- then
- Address_Clause_Checks.Append ((N, U_Ent, O_Ent, Off));
- end if;
end;
-- Not a valid entity for an address clause
@@ -13183,16 +13201,16 @@
if not Address_Warning_Posted (ACCR.N) then
Expr := Original_Node (Expression (ACCR.N));
- -- Get alignments
+ -- Get alignments, sizes and offset, if any
X_Alignment := Alignment (ACCR.X);
- Y_Alignment := Alignment (ACCR.Y);
+ X_Size := Esize (ACCR.X);
- -- Similarly obtain sizes and offset
+ if Present (ACCR.Y) then
+ Y_Alignment := Alignment (ACCR.Y);
+ Y_Size := Esize (ACCR.Y);
+ end if;
- X_Size := Esize (ACCR.X);
- Y_Size := Esize (ACCR.Y);
-
if ACCR.Off
and then Nkind (Expr) = N_Attribute_Reference
and then Attribute_Name (Expr) = Name_Address
@@ -13202,9 +13220,27 @@
X_Offs := Uint_0;
end if;
+ -- Check for known value not multiple of alignment
+
+ if No (ACCR.Y) then
+ if not Alignment_Checks_Suppressed (ACCR.X)
+ and then X_Alignment /= 0
+ and then ACCR.A mod X_Alignment /= 0
+ then
+ Error_Msg_NE
+ ("??specified address for& is inconsistent with "
+ & "alignment", ACCR.N, ACCR.X);
+ Error_Msg_N
+ ("\??program execution may be erroneous (RM 13.3(27))",
+ ACCR.N);
+
+ Error_Msg_Uint_1 := X_Alignment;
+ Error_Msg_NE ("\??alignment of & is ^", ACCR.N, ACCR.X);
+ end if;
+
-- Check for large object overlaying smaller one
- if Y_Size > Uint_0
+ elsif Y_Size > Uint_0
and then X_Size > Uint_0
and then X_Offs + X_Size > Y_Size
then
@@ -13232,7 +13268,7 @@
-- Note: we do not check the alignment if we gave a size
-- warning, since it would likely be redundant.
- elsif not Alignment_Checks_Suppressed (ACCR.Y)
+ elsif not Alignment_Checks_Suppressed (ACCR.X)
and then Y_Alignment /= Uint_0
and then
(Y_Alignment < X_Alignment
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2016-06-22 10:06 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-22 10:06 [Ada] Improve and unify warning machinery for address clauses Arnaud Charlet
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).