[Ada] Detect illegal component of dereference of access-to-constant
Arnaud Charlet
charlet@adacore.com
Wed May 21 10:53:00 GMT 2014
This patch detects an error that was previously undetected. In particular, it
is illegal to rename a subcomponent of an object designated by an
access-to-constant value if that subcomponent depends on discriminants.
The following test should get an error:
% gnatmake -f -q acc_const_test.adb
acc_const_test.adb:17:46: illegal renaming of discriminant-dependent component
gnatmake: "acc_const_test.adb" compilation error
%
with Ada.Text_IO; use Ada.Text_IO;
procedure Acc_Const_Test is
subtype Int is Integer range 1..100;
type Desig (Discrim : Int := 1) is
record
Discrim_Dependent : String (1..Discrim);
end record;
type Ref_Const is access constant Desig;
Var : aliased Desig := (Discrim => 4, Discrim_Dependent => "abcd");
Ref_Const_Obj : Ref_Const := Var'Access;
Char : Character renames Ref_Const_Obj.all.Discrim_Dependent(4);
-- Illegal in Ada 2005.
begin
Var := (Discrim => 1, Discrim_Dependent => "X");
-- Raises C_E in Ada 95.
Put_Line ("Char = " & Char);
end Acc_Const_Test;
Tested on x86_64-pc-linux-gnu, committed on trunk
2014-05-21 Bob Duff <duff@adacore.com>
* sem_util.adb (Is_Dependent_Component_Of_Mutable_Object):
This was returning False if the Object is a constant view. Fix
it to return True in that case, because it might be a view of
a variable.
(Has_Discriminant_Dependent_Constraint): Fix latent
bug; this function was crashing when passed a discriminant.
-------------- next part --------------
Index: sem_util.adb
===================================================================
--- sem_util.adb (revision 210689)
+++ sem_util.adb (working copy)
@@ -7300,39 +7300,46 @@
(Comp : Entity_Id) return Boolean
is
Comp_Decl : constant Node_Id := Parent (Comp);
- Subt_Indic : constant Node_Id :=
- Subtype_Indication (Component_Definition (Comp_Decl));
+ Subt_Indic : Node_Id;
Constr : Node_Id;
Assn : Node_Id;
begin
- if Nkind (Subt_Indic) = N_Subtype_Indication then
- Constr := Constraint (Subt_Indic);
+ -- Discriminants can't depend on discriminants
- if Nkind (Constr) = N_Index_Or_Discriminant_Constraint then
- Assn := First (Constraints (Constr));
- while Present (Assn) loop
- case Nkind (Assn) is
- when N_Subtype_Indication |
- N_Range |
- N_Identifier
- =>
- if Depends_On_Discriminant (Assn) then
- return True;
- end if;
+ if Ekind (Comp) = E_Discriminant then
+ return False;
- when N_Discriminant_Association =>
- if Depends_On_Discriminant (Expression (Assn)) then
- return True;
- end if;
+ else
+ Subt_Indic := Subtype_Indication (Component_Definition (Comp_Decl));
- when others =>
- null;
+ if Nkind (Subt_Indic) = N_Subtype_Indication then
+ Constr := Constraint (Subt_Indic);
- end case;
+ if Nkind (Constr) = N_Index_Or_Discriminant_Constraint then
+ Assn := First (Constraints (Constr));
+ while Present (Assn) loop
+ case Nkind (Assn) is
+ when N_Subtype_Indication |
+ N_Range |
+ N_Identifier
+ =>
+ if Depends_On_Discriminant (Assn) then
+ return True;
+ end if;
- Next (Assn);
- end loop;
+ when N_Discriminant_Association =>
+ if Depends_On_Discriminant (Expression (Assn)) then
+ return True;
+ end if;
+
+ when others =>
+ null;
+ end case;
+
+ Next (Assn);
+ end loop;
+ end if;
end if;
end if;
@@ -9740,11 +9747,6 @@
function Is_Dependent_Component_Of_Mutable_Object
(Object : Node_Id) return Boolean
is
- P : Node_Id;
- Prefix_Type : Entity_Id;
- P_Aliased : Boolean := False;
- Comp : Entity_Id;
-
function Is_Declared_Within_Variant (Comp : Entity_Id) return Boolean;
-- Returns True if and only if Comp is declared within a variant part
@@ -9759,17 +9761,41 @@
return Nkind (Parent (Comp_List)) = N_Variant;
end Is_Declared_Within_Variant;
+ P : Node_Id;
+ Prefix_Type : Entity_Id;
+ P_Aliased : Boolean := False;
+ Comp : Entity_Id;
+
+ Deref : Node_Id := Object;
+ -- Dereference node, in something like X.all.Y(2)
+
-- Start of processing for Is_Dependent_Component_Of_Mutable_Object
begin
- if Is_Variable (Object) then
+ -- Find the dereference node if any
+ while Nkind_In (Deref, N_Indexed_Component,
+ N_Selected_Component,
+ N_Slice)
+ loop
+ Deref := Prefix (Deref);
+ end loop;
+
+ -- Ada 2005: If we have a component or slice of a dereference,
+ -- something like X.all.Y (2), and the type of X is access-to-constant,
+ -- Is_Variable will return False, because it is indeed a constant
+ -- view. But it might be a view of a variable object, so we want the
+ -- following condition to be True in that case.
+
+ if Is_Variable (Object)
+ or else (Ada_Version >= Ada_2005
+ and then Nkind (Deref) = N_Explicit_Dereference)
+ then
if Nkind (Object) = N_Selected_Component then
P := Prefix (Object);
Prefix_Type := Etype (P);
if Is_Entity_Name (P) then
-
if Ekind (Entity (P)) = E_Generic_In_Out_Parameter then
Prefix_Type := Base_Type (Prefix_Type);
end if;
@@ -9801,10 +9827,10 @@
-- the dereferenced case, since the access value might denote an
-- unconstrained aliased object, whereas in Ada 95 the designated
-- object is guaranteed to be constrained. A worst-case assumption
- -- has to apply in Ada 2005 because we can't tell at compile time
- -- whether the object is "constrained by its initial value"
- -- (despite the fact that 3.10.2(26/2) and 8.5.1(5/2) are
- -- semantic rules -- these rules are acknowledged to need fixing).
+ -- has to apply in Ada 2005 because we can't tell at compile
+ -- time whether the object is "constrained by its initial value"
+ -- (despite the fact that 3.10.2(26/2) and 8.5.1(5/2) are semantic
+ -- rules (these rules are acknowledged to need fixing).
if Ada_Version < Ada_2005 then
if Is_Access_Type (Prefix_Type)
@@ -9813,7 +9839,7 @@
return False;
end if;
- elsif Ada_Version >= Ada_2005 then
+ else pragma Assert (Ada_Version >= Ada_2005);
if Is_Access_Type (Prefix_Type) then
-- If the access type is pool-specific, and there is no
More information about the Gcc-patches
mailing list