For practitioners of other languages it is useful to indicate that an access
value is not a legal operand of predefined concatenation.

Compiling foo.adb must yield:

   foo.adb:5:33: invalid operand types for operator "&"
   foo.adb:5:33: left operand is access type
   foo.adb:6:35: invalid operand types for operator "&"
   foo.adb:6:35: right operand is access type


with Ada.Text_IO; use Ada.Text_IO;

procedure Foo is
   Prefix    : access String := new String'("Hello ");
   Suffix    : String := Prefix & "world!";
   Backwards : String := "world!" & Prefix;
begin
   Put_Line (Suffix);
end Foo;

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

2014-01-22  Ed Schonberg  <schonb...@adacore.com>

        * sem_ch4.adb (Operator_Check): Improve error message when an
        operand of concatenation is an access type.

Index: sem_ch4.adb
===================================================================
--- sem_ch4.adb (revision 206918)
+++ sem_ch4.adb (working copy)
@@ -6151,7 +6151,8 @@
             --  In an instance a generic actual may be a numeric type even if
             --  the formal in the generic unit was not. In that case, the
             --  predefined operator was not a possible interpretation in the
-            --  generic, and cannot be one in the instance.
+            --  generic, and cannot be one in the instance, unless the operator
+            --  is an actual of an instance.
 
             if In_Instance
               and then
@@ -6576,6 +6577,17 @@
                         if Nkind (N) /= N_Op_Concat then
                            Error_Msg_NE ("\left operand has}!",  N, Etype (L));
                            Error_Msg_NE ("\right operand has}!", N, Etype (R));
+
+                        --  For concatenation operators it is more difficult to
+                        --  determine which is the wrong operand. It is worth
+                        --  flagging explicitly an access type, for those who
+                        --  might think that a dereference happens here.
+
+                        elsif Is_Access_Type (Etype (L)) then
+                           Error_Msg_N ("\left operand is access type", N);
+
+                        elsif Is_Access_Type (Etype (R)) then
+                           Error_Msg_N ("\right operand is access type", N);
                         end if;
                      end if;
                   end if;

Reply via email to