+2009-05-06 Robert Dewar <dewar@adacore.com>
+
+ * freeze.adb (Freeze_Record_Type): Implement Implicit_Packing for
+ records
+
+ * gnat_rm.texi:
+ Add documentation for pragma Implicit_Packing applied to record
+ types.
+
+2009-05-06 Ed Schonberg <schonberg@adacore.com>
+
+ * sem.adb (Walk_Library_Items): Place all with_clauses of an
+ instantiation on the spec, because late instance bodies may generate
+ with_clauses for the instance body but are inserted in the instance
+ spec.
+
2009-05-06 Emmanuel Briot <briot@adacore.com>
* prj-nmsc.adb (Locate_Directory): Remove unused parameters, and add
------------------------------------------------------------------------------
+------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
Placed_Component : Boolean := False;
-- Set True if we find at least one component with a component
- -- clause (used to warn about useless Bit_Order pragmas).
+ -- clause (used to warn about useless Bit_Order pragmas, and also
+ -- to detect cases where Implicit_Packing may have an effect).
+
+ All_Scalar_Components : Boolean := True;
+ -- Set False if we encounter a component of a non-scalar type
+
+ Scalar_Component_Total_RM_Size : Uint := Uint_0;
+ Scalar_Component_Total_Esize : Uint := Uint_0;
+ -- Accumulates total RM_Size values and total Esize values of all
+ -- scalar components. Used for processing of Implicit_Packing.
function Check_Allocator (N : Node_Id) return Node_Id;
-- If N is an allocator, possibly wrapped in one or more level of
end;
end if;
+ -- Processing for possible Implicit_Packing later
+
+ if Implicit_Packing then
+ if not Is_Scalar_Type (Etype (Comp)) then
+ All_Scalar_Components := False;
+ else
+ Scalar_Component_Total_RM_Size :=
+ Scalar_Component_Total_RM_Size + RM_Size (Etype (Comp));
+ Scalar_Component_Total_Esize :=
+ Scalar_Component_Total_Esize + Esize (Etype (Comp));
+ end if;
+ end if;
+
-- If the component is an Itype with Delayed_Freeze and is either
-- a record or array subtype and its base type has not yet been
-- frozen, we must remove this from the entity list of this
-- Finally, enforce the restriction that access attributes with a
-- current instance prefix can only apply to limited types.
- if Ekind (Rec) = E_Record_Type then
+ if Ekind (Rec) = E_Record_Type then
if Present (Corresponding_Remote_Type (Rec)) then
Freeze_And_Append
(Corresponding_Remote_Type (Rec), Loc, Result);
end if;
end;
end if;
+
+ -- Apply implicit packing if all conditions are met
+
+ if Implicit_Packing
+ and then Has_Size_Clause (Rec)
+ and then All_Scalar_Components
+ and then not Has_Discriminants (Rec)
+ and then Esize (Rec) < Scalar_Component_Total_Esize
+ and then Esize (Rec) >= Scalar_Component_Total_RM_Size
+ then
+ Set_Is_Packed (Rec);
+ end if;
end Freeze_Record_Type;
-- Start of processing for Freeze_Entity
@noindent
This is a configuration pragma that requests implicit packing for packed
arrays for which a size clause is given but no explicit pragma Pack or
-specification of Component_Size is present. Consider this example:
+specification of Component_Size is present. It also applies to records
+where no record representation clause is present. Consider this example:
@smallexample @c ada
type R is array (0 .. 7) of Boolean;
by the size in bits of the component type.
@cindex Array packing
+Similarly, the following example shows the use in the record case
+
+@smallexample @c ada
+type r is record
+ a, b, c, d, e, f, g, h : boolean;
+ chr : character;
+end record;
+for r'size use 16;
+@end smallexample
+
+@noindent
+Without a pragma Pack, each Boolean field requires 8 bits, so the
+minimum size is 72 bits, but with a pragma Pack, 16 bits would be
+sufficient. The use of pragma Implciit_Packing allows this record
+declaration to compile without an explicit pragma Pack.
@node Pragma Import_Exception
@unnumberedsec Pragma Import_Exception
@cindex OpenVMS
-- If it's a body, then ignore it, unless it's an instance (in
-- which case we do the spec), or it's the main unit (in which
-- case we do it). Note that it could be both, in which case we
- -- do the spec first.
+ -- do the with_clauses of spec and body first,
when N_Package_Body | N_Subprogram_Body =>
declare
if Is_Generic_Instance (Entity) then
declare
Spec_Unit : constant Node_Id := Library_Unit (CU);
+
begin
+ -- Move context of body to that of spec, so it
+ -- appears before the spec itself, in case it
+ -- contains nested instances that generate late
+ -- with_clauses that got attached to the body.
+
+ Append_List
+ (Context_Items (CU), Context_Items (Spec_Unit));
Do_Unit_And_Dependents
(Spec_Unit, Unit (Spec_Unit));
end;