diff mbox

[Ada] Improved error message on one-element positional aggregates

Message ID 20110804095338.GA17271@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Aug. 4, 2011, 9:53 a.m. UTC
An illegal one-element positional aggregate is usually detected as a type
error. If the expected type is a one-component record, it is possible to
indicate what the proper syntax should be. A similar suggestion can be given
if the context specifies a nameable array type or the target of an assignment.
However, the suggestion is not as precise for subaggregates of multidimensional
arrays.

The following displays the improved error messages:

Compiling: p1.adb (source file time stamp: 2011-03-04 16:14:14)

     1. procedure P1 is
     2.    type Sequence is array (integer range <>) of Float;
     3.
     4.    type T_1 is record
     5.        R_2    : integer;
     6.    end record;
     7.
     8.    type Table is array (1..2, 1..1) of integer;
     9.    T : Table := ((0), (0));
                          |
        >>> nested array aggregate expected
        >>> if single-component aggregate is intended, write e.g. (1 => ...)

    10.
    11.    V_D4 : array ( 1..1) of T_1 :=
    12.          (1 =>     ( 1));
                             |
        >>> positional aggregate cannot have one component
        >>> write instead "R_2 => ..."

    13.
    14.    Thing : T_1 := (5);
                           |
        >>> positional aggregate cannot have one component
        >>> write instead "R_2 => ..."

    15.
    16.    It : Sequence := (3.1415);
                             |
        >>> positional aggregate cannot have one component
        >>> write instead "Sequence'First => ..."

    17.
    18.    subtype Yes is boolean range True .. True;
    19.    type Vacuous is array (Yes) of Float;
    20.    Oui : Vacuous := (1.0);
                             |
        >>> positional aggregate cannot have one component
        >>> write instead "Vacuous'First => ..."

    21.
    22.    subtype Name is String (1 .. 5);
    23.    That : name := "That ";
    24.    type Names is array (1..2, 1..5) of character;
    25.    Them : Names := ("this ", (that));
                                      |
        >>> nested array aggregate expected
        >>> if single-component aggregate is intended, write e.g. (1 => ...)

    26.
    27.    Anon : array (1..1) of Boolean;
    28.
    29. begin
    30.     It := (2.7179);
                   |
        >>> positional aggregate cannot have one component
        >>> write instead "Sequence'First => ..."

    31.
    32.     Anon := (False);
                     |
        >>> positional aggregate cannot have one component
        >>> write instead "Anon'First => ..."

    33. end P1;

Tested on x86_64-pc-linux-gnu, committed on trunk

2011-08-04  Ed Schonberg  <schonberg@adacore.com>

	* sem_util.adb:(Wrong_Type): Improve error message on a one-element
	positional aggregate.
diff mbox

Patch

Index: sem_util.adb
===================================================================
--- sem_util.adb	(revision 177328)
+++ sem_util.adb	(working copy)
@@ -12478,9 +12478,13 @@ 
    ----------------
 
    procedure Wrong_Type (Expr : Node_Id; Expected_Type : Entity_Id) is
-      Found_Type : constant Entity_Id := First_Subtype (Etype (Expr));
-      Expec_Type : constant Entity_Id := First_Subtype (Expected_Type);
+      Found_Type     : constant Entity_Id := First_Subtype (Etype (Expr));
+      Expec_Type     : constant Entity_Id := First_Subtype (Expected_Type);
 
+      Matching_Field : Entity_Id;
+      --  Entity to give a more precise suggestion on how to write a one-
+      --  element positional aggregate.
+
       function Has_One_Matching_Field return Boolean;
       --  Determines if Expec_Type is a record type with a single component or
       --  discriminant whose type matches the found type or is one dimensional
@@ -12494,11 +12498,27 @@ 
          E : Entity_Id;
 
       begin
+         Matching_Field := Empty;
+
          if Is_Array_Type (Expec_Type)
            and then Number_Dimensions (Expec_Type) = 1
            and then
              Covers (Etype (Component_Type (Expec_Type)), Found_Type)
          then
+            --  Use type name if available. This excludes multidimensional
+            --  arrays and anonymous arrays.
+
+            if Comes_From_Source (Expec_Type) then
+               Matching_Field := Expec_Type;
+
+            --  For an assignment, use name of target.
+
+            elsif Nkind (Parent (Expr)) = N_Assignment_Statement
+              and then Is_Entity_Name (Name (Parent (Expr)))
+            then
+               Matching_Field := Entity (Name (Parent (Expr)));
+            end if;
+
             return True;
 
          elsif not Is_Record_Type (Expec_Type) then
@@ -12529,6 +12549,7 @@ 
                return False;
 
             else
+               Matching_Field := E;
                return True;
             end if;
          end if;
@@ -12577,7 +12598,17 @@ 
         and then Has_One_Matching_Field
       then
          Error_Msg_N ("positional aggregate cannot have one component", Expr);
+         if Present (Matching_Field) then
+            if Is_Array_Type (Expec_Type) then
+               Error_Msg_NE
+                 ("\write instead `&''First ='> ...`", Expr, Matching_Field);
 
+            else
+               Error_Msg_NE
+                 ("\write instead `& ='> ...`", Expr, Matching_Field);
+            end if;
+         end if;
+
       --  Another special check, if we are looking for a pool-specific access
       --  type and we found an E_Access_Attribute_Type, then we have the case
       --  of an Access attribute being used in a context which needs a pool-