===================================================================
@@ -4238,10 +4238,10 @@
-- When a function call appears in Object.Operation format, the
-- original representation has two possible forms depending on the
-- availability of actual parameters:
- --
- -- Obj.Func_Call -- N_Selected_Component
- -- Obj.Func_Call (Param) -- N_Indexed_Component
+ -- Obj.Func_Call N_Selected_Component
+ -- Obj.Func_Call (Param) N_Indexed_Component
+
else
if Nkind (Expr) = N_Indexed_Component then
Expr := Prefix (Expr);
@@ -5295,18 +5295,34 @@
function Is_Volatile_Reference (N : Node_Id) return Boolean is
begin
- if Nkind (N) in N_Has_Etype
- and then Present (Etype (N))
- and then Treat_As_Volatile (Etype (N))
- then
+ -- Only source references are to be treated as volatile, internally
+ -- generated stuff cannot have volatile external effects.
+
+ if not Comes_From_Source (N) then
+ return False;
+
+ -- Never true for reference to a type
+
+ elsif Is_Entity_Name (N) and then Is_Type (Entity (N)) then
+ return False;
+
+ -- True if object reference with volatile type
+
+ elsif Is_Volatile_Object (N) then
return True;
+ -- True if reference to volatile entity
+
elsif Is_Entity_Name (N) then
return Treat_As_Volatile (Entity (N));
+ -- True for slice of volatile array
+
elsif Nkind (N) = N_Slice then
return Is_Volatile_Reference (Prefix (N));
+ -- True if volatile component
+
elsif Nkind_In (N, N_Indexed_Component, N_Selected_Component) then
if (Is_Entity_Name (Prefix (N))
and then Has_Volatile_Components (Entity (Prefix (N))))
@@ -5318,6 +5334,8 @@
return Is_Volatile_Reference (Prefix (N));
end if;
+ -- Otherwise false
+
else
return False;
end if;
@@ -6844,9 +6862,7 @@
-- (this happens because routines Duplicate_Subexpr_XX implicitly invoke
-- Remove_Side_Effects).
- if No (Exp_Type)
- or else Ekind (Exp_Type) = E_Access_Attribute_Type
- then
+ if No (Exp_Type) or else Ekind (Exp_Type) = E_Access_Attribute_Type then
return;
-- No action needed for side-effect free expressions
@@ -6913,9 +6929,12 @@
Insert_Action (Exp, E);
-- If the expression has the form v.all then we can just capture the
- -- pointer, and then do an explicit dereference on the result.
+ -- pointer, and then do an explicit dereference on the result, but
+ -- this is not right if this is a volatile reference.
- elsif Nkind (Exp) = N_Explicit_Dereference then
+ elsif Nkind (Exp) = N_Explicit_Dereference
+ and then not Is_Volatile_Reference (Exp)
+ then
Def_Id := Make_Temporary (Loc, 'R', Exp);
Res :=
Make_Explicit_Dereference (Loc, New_Occurrence_Of (Def_Id, Loc));
@@ -6987,17 +7006,21 @@
-- This is needed for correctness in the case of a volatile object of
-- a non-volatile type because the Make_Reference call of the "default"
-- approach would generate an illegal access value (an access value
- -- cannot designate such an object - see Analyze_Reference). We skip
- -- using this scheme if we have an object of a volatile type and we do
- -- not have Name_Req set true (see comments for Side_Effect_Free).
+ -- cannot designate such an object - see Analyze_Reference).
- -- In Ada 2012 a qualified expression is an object, but for purposes of
- -- removing side effects it still need to be transformed into a separate
- -- declaration, particularly if the expression is an aggregate.
-
elsif Is_Object_Reference (Exp)
and then Nkind (Exp) /= N_Function_Call
+
+ -- In Ada 2012 a qualified expression is an object, but for purposes
+ -- of removing side effects it still need to be transformed into a
+ -- separate declaration, particularly in the case of an aggregate.
+
and then Nkind (Exp) /= N_Qualified_Expression
+
+ -- We skip using this scheme if we have an object of a volatile
+ -- type and we do not have Name_Req set true (see comments for
+ -- Side_Effect_Free).
+
and then (Name_Req or else not Treat_As_Volatile (Exp_Type))
then
Def_Id := Make_Temporary (Loc, 'R', Exp);
@@ -8030,6 +8053,12 @@
-- Start of processing for Side_Effect_Free
begin
+ -- If volatile reference, always consider it to have side effects
+
+ if Is_Volatile_Reference (N) then
+ return False;
+ end if;
+
-- Note on checks that could raise Constraint_Error. Strictly, if we
-- take advantage of 11.6, these checks do not count as side effects.
-- However, we would prefer to consider that they are side effects,
@@ -8043,12 +8072,17 @@
if Is_Entity_Name (N) then
+ -- A type reference is always side effect free
+
+ if Is_Type (Entity (N)) then
+ return True;
+
-- Variables are considered to be a side effect if Variable_Ref
-- is set or if we have a volatile reference and Name_Req is off.
-- If Name_Req is True then we can't help returning a name which
-- effectively allows multiple references in any case.
- if Is_Variable (N, Use_Original_Node => False) then
+ elsif Is_Variable (N, Use_Original_Node => False) then
return not Variable_Ref
and then (not Is_Volatile_Reference (N) or else Name_Req);
===================================================================
@@ -3627,6 +3627,16 @@
-- references a subprogram that is a renaming, then the front end must
-- rewrite the attribute to refer directly to the renamed entity.
+ -- Note: syntactically the prefix of an attribute reference must be a
+ -- name, and this (somewhat artificial) requirement is enforced by the
+ -- parser. However, for many attributes, such as 'Valid, it is quite
+ -- reasonable to apply the attribute to any value, and hence to any
+ -- expression. Internally in the tree, the prefix is an expression which
+ -- does not have to be a name, and this is handled fine by the semantic
+ -- analysis and expansion, and back ends. This arises for the case of
+ -- attribute references built by the expander (e.g. 'Valid for the case
+ -- of an implicit validity check).
+
-- Note: In generated code, the Address and Unrestricted_Access
-- attributes can be applied to any expression, and the meaning is
-- to create an object containing the value (the object is in the
@@ -3638,7 +3648,7 @@
-- N_Attribute_Reference
-- Sloc points to apostrophe
- -- Prefix (Node3)
+ -- Prefix (Node3) (general expression, see note above)
-- Attribute_Name (Name2) identifier name from attribute designator
-- Expressions (List1) (set to No_List if no associated expressions)
-- Entity (Node4-Sem) used if the attribute yields a type
===================================================================
@@ -6478,15 +6478,24 @@
-- Force evaluation to avoid multiple reads for atomic/volatile
+ -- Note: we set Name_Req to False. We used to set it to True, with
+ -- the thinking that a name is required as the prefix of the 'Valid
+ -- call, but in fact the check that the prefix of an attribute is
+ -- a name is in the parser, and we just don't require it here.
+ -- Moreover, when we set Name_Req to True, that interfered with the
+ -- checking for Volatile, since we couldn't just capture the value.
+
if Is_Entity_Name (Exp)
and then Is_Volatile (Entity (Exp))
then
- Force_Evaluation (Exp, Name_Req => True);
+ -- Same reasoning as above for setting Name_Req to False
+
+ Force_Evaluation (Exp, Name_Req => False);
end if;
-- Build the prefix for the 'Valid call
- PV := Duplicate_Subexpr_No_Checks (Exp, Name_Req => True);
+ PV := Duplicate_Subexpr_No_Checks (Exp, Name_Req => False);
-- A rather specialized kludge. If PV is an analyzed expression
-- which is an indexed component of a packed array that has not
@@ -6504,7 +6513,9 @@
Set_Analyzed (PV, False);
end if;
- -- Build the raise CE node to check for validity
+ -- Build the raise CE node to check for validity. We build a type
+ -- qualification for the prefix, since it may not be of the form of
+ -- a name, and we don't care in this context!
CE :=
Make_Raise_Constraint_Error (Loc,