[PATCH] c-pragma: adding a data field to pragma_handler

2011-06-01 Thread Pierre

This patch is about the pragmas.

In c-family/c-pragma.h, we declare a pragma_handler which is a function 
accepting cpp_reader as parameter.


I have changed this handler in order to accept a second parameter which 
is a void *, allowing to give extra datas to the handler. I think this 
data field might be of general use: we can have condition or data at 
register time that we want to express in the handler. I guess this is a 
common way to pass data to an handler function.


I would like your opinion on this patch! Thanks!

Pierre Vittet

Changelog

2011-06-01  Pierre Vittet  

* c-pragma.h (pragma_handler,internal_pragma_handler, c_register_pragma,
c_register_pragma_with_expansion): create internal_pragma_handler, add a
new void * data parameter.
* c-pragma.c (handle_pragma_pack, handle_pragma_weak,
handle_pragma_redefine_extname, handle_pragma_visibility,
handle_pragma_diagnostic, handle_pragma_target, handle_pragma_optimize,
handle_pragma_push_options, handle_pragma_pop_options,
handle_pragma_reset_options, handle_pragma_message,
handle_pragma_float_const_decimal64, registered_pragmas,
c_register_pragma_1, c_register_pragma, 
c_register_pragma_with_expansion,
init_pragma): add support of the void * data field.



Index: gcc/c-family/c-pragma.h
===
--- gcc/c-family/c-pragma.h (revision 174521)
+++ gcc/c-family/c-pragma.h (working copy)
@@ -84,10 +84,19 @@ extern bool pop_visibility (int);
 extern void init_pragma (void);
 
 /* Front-end wrappers for pragma registration.  */
-typedef void (*pragma_handler)(struct cpp_reader *);
-extern void c_register_pragma (const char *, const char *, pragma_handler);
-extern void c_register_pragma_with_expansion (const char *, const char *,
- pragma_handler);
+/* The void * allows to pass extra data to the handler.  */
+typedef void (*pragma_handler)(struct cpp_reader *, void * );
+/* Internally use to keep the data of the handler.  */
+struct internal_pragma_handler_d{
+  pragma_handler handler;
+  void * data; 
+};
+typedef struct internal_pragma_handler_d internal_pragma_handler;
+
+extern void c_register_pragma (const char * space, const char * name,
+   pragma_handler handler, void * data);
+extern void c_register_pragma_with_expansion (const char * space, 
+  const char * name,  pragma_handler handler , void * 
data);
 extern void c_invoke_pragma_handler (unsigned int);
 
 extern void maybe_apply_pragma_weak (tree);
Index: gcc/c-family/c-pragma.c
===
--- gcc/c-family/c-pragma.c (revision 174521)
+++ gcc/c-family/c-pragma.c (working copy)
@@ -53,7 +53,7 @@ typedef struct GTY(()) align_stack {
 
 static GTY(()) struct align_stack * alignment_stack;
 
-static void handle_pragma_pack (cpp_reader *);
+static void handle_pragma_pack (cpp_reader *, void * data);
 
 /* If we have a "global" #pragma pack() in effect when the first
#pragma pack(push,) is encountered, this stores the value of
@@ -133,7 +133,7 @@ pop_alignment (tree id)
#pragma pack (pop)
#pragma pack (pop, ID) */
 static void
-handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
+handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy), void * ARG_UNUSED (data))
 {
   tree x, id = 0;
   int align = -1;
@@ -247,7 +247,7 @@ DEF_VEC_ALLOC_O(pending_weak,gc);
 static GTY(()) VEC(pending_weak,gc) *pending_weaks;
 
 static void apply_pragma_weak (tree, tree);
-static void handle_pragma_weak (cpp_reader *);
+static void handle_pragma_weak (cpp_reader *, void * data);
 
 static void
 apply_pragma_weak (tree decl, tree value)
@@ -334,7 +334,7 @@ maybe_apply_pending_pragma_weaks (void)
 
 /* #pragma weak name [= value] */
 static void
-handle_pragma_weak (cpp_reader * ARG_UNUSED (dummy))
+handle_pragma_weak (cpp_reader * ARG_UNUSED (dummy), void * ARG_UNUSED (data))
 {
   tree name, value, x, decl;
   enum cpp_ttype t;
@@ -411,11 +411,12 @@ DEF_VEC_ALLOC_O(pending_redefinition,gc);
 
 static GTY(()) VEC(pending_redefinition,gc) *pending_redefine_extname;
 
-static void handle_pragma_redefine_extname (cpp_reader *);
+static void handle_pragma_redefine_extname (cpp_reader *, void * data);
 
 /* #pragma redefine_extname oldname newname */
 static void
-handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy))
+handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy), 
+void * ARG_UNUSED (data))
 {
   tree oldname, newname, decl, x;
   enum cpp_ttype t;
@@ -481,7 +482,8 @@ static GTY(()) tree pragma_extern_prefix;
 
 /* #pragma extern_prefix "prefix" */
 static void
-handle_pragma_extern_prefix (cpp_reader * ARG_UNUSED (dummy))
+handle_pragma_extern_prefix (cpp_reader * ARG_UNUSED (dummy), 
+ voi

Re: [PATCH, MELT] correct meltgc_read_from_val without location

2011-06-29 Thread Pierre

Hello,

here is an improvment to 
http://gcc.gnu.org/ml/gcc-patches/2011-06/msg01888.html.


The function meltgc_read_from_val (in melt-runtime.c) takes two 
arguments, a string value and a second one which is a location. In the 
comments, it is written that we can pass a NULL pointer if we have no 
location (it is a direct string). However, this conduct MELT to crash 
because it doesn't handle correctly the absence of file.


In the first patch, I modified makesexpr to create a location with a 
'virtual' file. This works however, as this function is used recursively 
this is not very elegant.


This patch is more elegant, it adds a boolean field to the struct 
reading_st to declare if there is no file location.
meltgc_read_* functions are modified to test if there is a given 
location, and if no, it create a location with a virtual file and set 
the boolean to false, conducting to avoid crash.


I have been able to build MELT with this pass and test it without problem.

On 24/06/2011 18:13, Pierre Vittet wrote:

Hello,

The function meltgc_read_from_val (in melt-runtime.c) takes two
arguments, a string value and a second one which is a location.
In the comments, it is written that we can pass a NULL pointer if we
have no location (it is a direct string). However, this conduct MELT to
crash because it doesn't handle correctly the absence of file.

This patch correct this, if there is no file, it create a "virtual" one
which is named "stringBuffer".

Pierre Vittet


correct_read_from_val_without_location-175348.diff




Index: gcc/melt-runtime.c
===
--- gcc/melt-runtime.c  (revision 175348)
+++ gcc/melt-runtime.c  (working copy)
@@ -6292,6 +6292,7 @@ struct reading_st
   int rcol;/* current column */
   source_location rsrcloc; /* current source location */
   melt_ptr_t *rpfilnam;/* pointer to location of file name string */
+  bool has_file_location;  /* precise if the string comes from a file */
 };
 
 #define MELT_READ_TABULATION_FACTOR 8
@@ -6326,7 +6327,7 @@ melt_linemap_compute_current_location (struct read
 {
   int colnum = 1;
   int cix = 0;
-  if (!rd || !rd->rcurlin) 
+  if (!rd || !rd->rcurlin || !rd->has_file_location)
 return;
   for (cix=0; cixrcol; cix++) {
 char c = rd->rcurlin[cix];
@@ -8314,6 +8315,7 @@ meltgc_read_file (const char *filnam, const char *
   rd = &rds;
   locnamv = meltgc_new_stringdup ((meltobject_ptr_t) MELT_PREDEF 
(DISCR_STRING), locnam);
   rds.rpfilnam = (melt_ptr_t *) & locnamv;
+  rds.has_file_location = true;
   seqv = meltgc_new_list ((meltobject_ptr_t) MELT_PREDEF (DISCR_LIST));
   while (!rdeof ())
 {
@@ -8371,7 +8373,16 @@ meltgc_read_from_rawstring (const char *rawstr, co
   rds.rsrcloc = loch;
   rd = &rds;
   if (locnam)
-locnamv = meltgc_new_stringdup ((meltobject_ptr_t) MELT_PREDEF 
(DISCR_STRING), locnam);
+{
+  rds.has_file_location = true;
+  locnamv = meltgc_new_stringdup ((meltobject_ptr_t) MELT_PREDEF 
(DISCR_STRING), locnam);
+}
+  else
+{
+  rds.has_file_location = false;
+  locnamv = meltgc_new_string ((meltobject_ptr_t) 
MELT_PREDEF(DISCR_STRING),
+  "stringBuffer");
+}
   seqv = meltgc_new_list ((meltobject_ptr_t) MELT_PREDEF (DISCR_LIST));
   rds.rpfilnam = (melt_ptr_t *) & locnamv;
   while (rdcurc ())
@@ -8415,6 +8426,7 @@ meltgc_read_from_val (melt_ptr_t strv_p, melt_ptr_
   locnamv = locnam_p;
   rbuf = 0;
   strmagic = melt_magic_discr ((melt_ptr_t) strv);
+  seqv = meltgc_new_list ((meltobject_ptr_t) MELT_PREDEF (DISCR_LIST));
   switch (strmagic)
 {
 case MELTOBMAG_STRING:
@@ -8441,7 +8453,14 @@ meltgc_read_from_val (melt_ptr_t strv_p, melt_ptr_
   rds.rpath = 0;
   rds.rlineno = 0;
   rds.rcurlin = rbuf;
+  rds.has_file_location = true;
   rd = &rds;
+  if (locnamv == NULL){
+rds.has_file_location = false;
+locnamv = meltgc_new_string ((meltobject_ptr_t) MELT_PREDEF(DISCR_STRING),
+ "stringBuffer");
+rd->rpfilnam = (melt_ptr_t *) &locnamv;
+  }
   rds.rpfilnam = (melt_ptr_t *) & locnamv;
   while (rdcurc ())
 {
2011-06-29  Pierre Vittet  

* melt-runtime.c (struct reading_st): add a boolean has_file_location
field.
(melt_linemap_compute_current_location): return immediately if no file
location.
(meltgc_read_file, meltgc_read_from_rawstring, meltgc_read_from_val):
set has_file_location accordingly
(meltgc_read_from_val): create seqv list (it was used without being
created).


Re: [GCC-MELT-95] [Melt] Fix foreach_edge_bb_precs

2011-07-26 Thread Pierre

On 25/07/2011 10:46, Romain Geissler wrote:

Hello,

This iteratoc won't work because of a little typo error (the previous
edge field is preDs and not preCs).
To avoid future errors, i apply the global /precs/preds/ change (and
thus the iterator is renamed).

Romain Geissler



Hello,

I wrote the initial iterator and agree with your change. I guess Basile 
will commit it soon.


Pierre



[PATCH, MELT] fixing upgrade-warmelt target

2011-08-27 Thread Pierre Vittet
Hello,

I am trying to fix upgrade-warmelt into last revision of MELT. We are
using some move-if-change on meltdesc file (in melt-stage3 for example)
to make a save (to a meltdesc\~) but we still need the meltdesc file for
the generated files.

So I replaced move-ifchange by a cp and it goes beyond (but there are
still issues.


Pierre Vittet
Index: melt-build.tpl
===
--- melt-build.tpl  (révision 178131)
+++ melt-build.tpl  (copie de travail)
@@ -579,7 +579,7 @@ ENDFOR melt_translator_file+]
 [+FOR melt_translator_file+]
@echo upgrading MELT translator [+base+]
 ## dont indent the [+base+]+meltdesc.c 
-   $(melt_make_move) $(MELT_LAST_STAGE)/[+base+]+meltdesc.c  
$(MELT_LAST_STAGE)/[+base+]+meltdesc.c~; \
+   cp $(MELT_LAST_STAGE)/[+base+]+meltdesc.c  
$(MELT_LAST_STAGE)/[+base+]+meltdesc.c~; \
sed s/$(MELT_LAST_STAGE)/MELT-STAGE-ZERO/g 
$(MELT_LAST_STAGE)/[+base+]+meltdesc.c > 
$(srcdir)/melt/generated/[+base+]+meltdesc.c 
for f in $(MELT_LAST_STAGE)/[+base+].c 
$(MELT_LAST_STAGE)/[+base+]+[0-9]*.c ; do \
  bf=`basename $$f`; \
2011-08-27  Pierre Vittet  

* melt-build.tpl (warmelt-upgrade-translator): replace move-if-change
by a cp.


Index: Makefile.in
===
--- Makefile.in (révision 178131)
+++ Makefile.in (copie de travail)
@@ -5516,7 +5516,7 @@ upgrade-warmelt: $(WARMELT_LAST)
for f in $(wildcard meltrunsup*.[ch]); do  \
  cp $$f $$f-tmp; \
  cp $(srcdir)/melt/generated/$$f $$f-old; \
-  $(SHELL) $(srcdir)/../move-if-change $$f-tmp 
$(srcdir)/melt/generated/$$f; \
+  $(SHELL) cp $$f-tmp $(srcdir)/melt/generated/$$f; \
 done
$(RM) melt-runtime.o melt-runtime.i s-gtype */warmelt*.o
$(MAKE) s-gtype
2011-08-27  Pierre Vittet  

* Makefile.in (upgrade-warmelt): replace move-if-change by a cp.



Re: [PATCH, MELT, minor] add a primitive read_strv

2011-08-30 Thread Pierre Vittet
Hello,

this is a ping for
http://gcc.gnu.org/ml/gcc-patches/2011-07/msg01503.html. I thought this
was integrated into MELT but it does not look to be in the current trunk.

It just add a primitive read_strv allowing to use meltgc_read_from_val
to get a list of s-expression from a boxed C string of a strbuf.

Pierre Vittet
Index: gcc/melt/warmelt-base.melt
===
--- gcc/melt/warmelt-base.melt  (revision 176434)
+++ gcc/melt/warmelt-base.melt  (working copy)
@@ -272,6 +272,11 @@ number $NUM opaque location number $LOC.}#
   :doc #{Read from file named by the $FILNAM string balue a list of MELT 
s-expressions.}#
   #{(meltgc_read_file (melt_string_str((melt_ptr_t)($filnam)), (char*)0))}#)
 
+(defprimitive read_strv (strv) :value
+  :doc #{Return the list of sexpr contained in $STRV. $STRV can be a boxed
+  string or a strbuf value.}#
+  #{(meltgc_read_from_val ($strv, NULL))}#
+)
 
 ;; to signal an error in a  source with some additional string value
 (defprimitive error_strv (loc :cstring cmsg :value strv) :void
@@ -2441,6 +2446,7 @@ polyhedron values.}#
  pair_set_head 
  ppstrbuf_mixbigint
  read_file
+ read_strv
  register_pass_execution_hook
  register_pragma_handler
  register_pre_genericize_hook
2011-07-18  Pierre Vittet  

* melt/warmelt-base.melt (read_strv): New primitive.



[PATCH, MELT] add primitive isnull_tree

2011-08-30 Thread Pierre Vittet
Hello,

This is a small patch adding primitive isnull_tree (as there is already
a primitive isnull_basicblock).

Pierre Vittet
Index: gcc/melt/xtramelt-ana-base.melt
===
--- gcc/melt/xtramelt-ana-base.melt (révision 178282)
+++ gcc/melt/xtramelt-ana-base.melt (copie de travail)
@@ -1447,12 +1447,15 @@
 
 (defprimitive gimpleseq_content (v) :gimple_seq
   #{(melt_gimpleseq_content((melt_ptr_t)($v)))}# )
+
 
-
-
 (defprimitive is_tree (v) :long
   #{(melt_magic_discr((melt_ptr_t)($v)) == MELTOBMAG_TREE)}# )
 
+(defprimitive isnull_tree (:tree tr) :long
+  #{$tr == (tree)0}#
+)
+
 (defprimitive make_tree (discr :tree g) :value
   #{(meltgc_new_tree((meltobject_ptr_t)($discr),($g)))}# )
 
@@ -3597,7 +3600,8 @@ and discriminant $DIS, usually $DISCR_MIXED_LOCATI
  is_mapgimple 
  is_maploop
  is_maptree
- is_tree  
+ is_tree
+ isnull_tree
  isnull_basicblock
  loop_body_tuple
  loop_can_be_parallel
2011-08-30  Pierre Vittet  

* melt/xtramelt-ana-base.melt(isnull_tree): Add primitive.




[PATCH, libiberty] correct md5_process_bytes with unaligned pointers

2011-09-16 Thread Pierre Vittet
Hello,

The patch is the result of the following threads:

Here is a patch correcting md5_process_bytes when we are in the case of
unaligned pointers.A pair of brace was missing, leading the buffer to be
shift 2 times losing a part of its content.


The patch also remove a preprocessor #if testing if
_STRING_ARCH_unaligned is defined. This symbol is never defined in gcc
and could be only used in CFLAGS. Looking at the code, it does not looks
usefull to define it (and it is only tested on libiberty/md5.c and
libiberty/sha1.c), as we already check the pointer alignement, so
removing it clean the code. I searched on google, and it does not looks
to be used. Does anyone want it or thing that it should not be removed?

Ok for trunk ?

Thanks!

Pierre Vittet

PS: I also write a small gcc plugin, allowing to easily test
md5_process_bytes, if can change your environment in a way where the
pointer buffer is not aligned, you should get the bug.


Index: libiberty/md5.c
===
--- libiberty/md5.c	(révision 178905)
+++ libiberty/md5.c	(copie de travail)
@@ -227,7 +227,6 @@ md5_process_bytes (const void *buffer, size_t len,
   /* Process available complete blocks.  */
   if (len > 64)
 {
-#if !_STRING_ARCH_unaligned
 /* To check alignment gcc has an appropriate operator.  Other
compilers don't.  */
 # if __GNUC__ >= 2
@@ -244,10 +243,11 @@ md5_process_bytes (const void *buffer, size_t len,
 len -= 64;
   }
   else
-#endif
-  md5_process_block (buffer, len & ~63, ctx);
-  buffer = (const void *) ((const char *) buffer + (len & ~63));
-  len &= 63;
+	{
+	  md5_process_block (buffer, len & ~63, ctx);
+	  buffer = (const void *) ((const char *) buffer + (len & ~63));
+	  len &= 63;
+	}
 }
 
   /* Move remaining bytes in internal buffer.  */
2011-09-16  Pierre Vittet  

* md5.c (md5_process_bytes): Remove unused _STRING_ARCH_unaligned, add
missing braces.



micro_plugin_md5.tar.gz
Description: GNU Zip compressed data


Re: [PATCH, libiberty] correct md5_process_bytes with unaligned pointers

2011-09-19 Thread Pierre Vittet
Hello,

Ping!
I would like to get a return on this patch. I don't know quite well the
status of libiberty in GNU, please if I must this patch on another
mailing list, please say me on which.

Thanks!

Pierre Vittet


[PATCH, MELT] correct meltgc_string_hex_md5sum_file_sequence

2011-09-19 Thread Pierre Vittet
Hello

Here is a patch allowing to compute correctly the md5 of a file sequence
even with the bug rapported here:
http://gcc.gnu.org/ml/gcc-patches/2011-09/msg00963.html.

The function will work with both gcc 4.6 without the patch and a gcc
with the patch applied.

The problem cames from the fact that we were calling md5_process_bytes
several times with a buffer of a size which was not a multiple of 64.
Doing so, the next buffer was modified to take those data in account and
doing so, we had not always an aligned pointer.

We now concatenate file stream and so we can have a buffer with a
multiple of 64 size, so we can call md5_process_block. We only call
md5_process_bytes for the last data.

Thanks!

Pierre Vittet
2011-09-19  Pierre Vittet  

* melt-runtime.c (meltgc_string_hex_md5sum_file_sequence): Concatenate
files stream to call md5_process_block, we only call md5_process_bytes
for the last datas.
Index: gcc/melt-runtime.c
===
--- gcc/melt-runtime.c  (révision 178881)
+++ gcc/melt-runtime.c  (copie de travail)
@@ -5374,7 +5374,11 @@ melt_compile_source (const char *srcbase, const ch
  }
 
  /* compute the hexadecimal encoded md5sum string of a tuple of file
-paths, or NULL on failure */
+paths, or NULL on failure.
+When we finish to proceed a file, we immediatly add the beginning of the
+following file to bufblock to keep a size of a multiple of 64.  This permit
+to call md5_process_block.  We only call md5_process_bytes for the last
+data.  */
  melt_ptr_t 
  meltgc_string_hex_md5sum_file_sequence (melt_ptr_t pathtup_p)
  {
@@ -5385,6 +5389,7 @@ melt_compile_source (const char *srcbase, const ch
FILE *fil = NULL;
int nbtup = 0;
int cnt = 0;
+   int new_file_cnt = 0;
struct md5_ctx ctx;
MELT_ENTERFRAME(3, NULL);
  #define resv   meltfram__.mcfr_varptr[0]
@@ -5394,12 +5399,12 @@ melt_compile_source (const char *srcbase, const ch
memset (&ctx, 0, sizeof(ctx));
memset (md5srctab, 0, sizeof (md5srctab));
memset (md5hex, 0, sizeof (md5hex));
-   memset (bufblock, 0, sizeof (bufblock));
if (melt_magic_discr ((melt_ptr_t)pathtupv) != MELTOBMAG_MULTIPLE)
  goto end;
md5_init_ctx (&ctx);
nbtup = melt_multiple_length ((melt_ptr_t)pathtupv);
/* this loop does not garbage collect! */
+   memset (bufblock, 0, sizeof (bufblock));
for (ix=0; ix < nbtup; ix++) 
  {
const char *curpath = NULL;
@@ -5414,22 +5419,33 @@ melt_compile_source (const char *srcbase, const ch
 goto end;
while (!feof (fil))
 {
-  memset (bufblock, 0, sizeof (bufblock));
-  cnt = fread (bufblock, 1, sizeof(bufblock), fil);
+  if (cnt != 0) /*means that we havent process bufblock from previous
+  file.*/
+{
+   new_file_cnt =fread (bufblock+cnt, 
sizeof(char),sizeof(bufblock)-cnt, fil);
+   cnt = cnt + new_file_cnt;
+
+}
+  else 
+{
+  cnt = fread (bufblock, sizeof(char), sizeof(bufblock), fil);
+}
   if (cnt ==sizeof(bufblock))
 {
   /* an entire block has been read. */
-  md5_process_bytes (bufblock, sizeof(bufblock), &ctx);
+  md5_process_block (bufblock, sizeof(bufblock), &ctx);
+  memset (bufblock, '\0', sizeof (bufblock));
+  cnt = 0;
 }
-  else
-{
-  md5_process_bytes (bufblock, (size_t) cnt, &ctx);
-}
 }
fclose (fil);
fil = NULL;
curpath = NULL;
  }
+   if (cnt !=0) /*We still have some data in the buffer*/
+ {
+   md5_process_bytes (bufblock, (size_t) cnt, &ctx);
+ }
md5_finish_ctx (&ctx, md5srctab);
memset (md5hex, 0, sizeof(md5hex));
for (ix=0; ix<16; ix++) {


[PATCH, MELT] add pragma support in MELT plugin

2011-05-31 Thread Pierre Vittet

Hello,

The following patch allows to use pragma in a MELT plugin.
For exemple we can recover the following pragmas:

#pragma GCCPLUGIN melt op
or
#pragma GCCPLUGIN melt op (arg1, arg2, ...)
with argX a name, a string, or a number.

It is easy to change the pragma space ("GCCPLUGIN") and name ("melt"), 
so I am open to suggestion.


This plugin works on the MELT heart and so It need to regenerate the source.

The first .diff (addPragma-warmelt-first) contains the 
gcc/melt/warmelt-first.melt file: I have added a field in the MELT 
class_system_data class which allows the user to add a function handling 
pragma.


After adding this diff, it is needed to use 'make upgrade-warmelt' in 
the gcc directory to regenerate gcc/melt/generated.


After this, it is possible to add the second diff (addPragma-runtime): 
it contains change in gcc/melt-runtime.c and gcc/melt-runtime.h: it adds 
the melt_pragma_callback which register the pragma handler defined in 
the same file. The pragma handler calls the function defined by the user 
and gives it the trees corresponding to the pragma operator and argument.


I have been obliged to use weak symbols for pragma_lex and 
c_register_pragma as they are not defined when using lto. This is a 
temporary solution that I commented.


I am going to send a test in the Testsuite, but I have already tried it 
successfully with something like that:


(defun my_simple_pragma_handler(val1 lstarg)
  (debug_msg val1 "debugging melt pragma")
)

(put_fields
 initial_system_data
 :sysdata_meltpragma_definer my_simple_pragma_handler
)

Pierre Vittet

Index: gcc/melt/warmelt-first.melt
===
--- gcc/melt/warmelt-first.melt (revision 174379)
+++ gcc/melt/warmelt-first.melt (working copy)
@@ -436,6 +436,7 @@ don't instanciate this class!}#
   sysdata_pass_dict;stringmap for passes
   sysdata_exit_finalizer   ;;closure to be called after the 
passes, at finalization
   sysdata_meltattr_definer ;;closure to be called for melt 
attributes
+  sysdata_meltpragma_definer   ;;closure to be called for melt pragma
   sysdata_patmacro_exporter;closure to export a patmacro
   sysdata_debugmsg ;closure for debugmsg
   sysdata_stdout   ;raw file for stdout
Index: gcc/melt-runtime.c
===
--- gcc/melt-runtime.c  (revision 174379)
+++ gcc/melt-runtime.c  (working copy)
@@ -75,6 +75,7 @@ along with GCC; see the file COPYING3.   If not se
 #include "plugin.h"
 #include "cppdefault.h"
 
+#include "c-pragma.h"
 #if BUILDING_GCC_VERSION > 4005
 /* GCC 4.6 has realmpfr.h which includes   */
 #include "realmpfr.h"
@@ -8930,7 +8931,124 @@ melt_attribute_callback(void *gcc_data ATTRIBUTE_U
   register_attribute(&melt_attr_spec);
 }
 
+/*We declare weak functions because they cannot be linked when we use lto (it
+loses langage specific informations).
+If you use one of those functions you must check them to be not NULL.
+*/
+extern enum cpp_ttype __attribute__((weak)) pragma_lex (tree *);
+extern void __attribute__((weak)) c_register_pragma (const char *, const char
+*, pragma_handler);
 
+#define GCC_BAD(gmsgid) \
+  do { warning (OPT_Wpragmas, gmsgid); goto end; } while (0)
+
+
+void melt_handle_melt_pragma (melt_ptr_t optreev, melt_ptr_t listargtreev);
+
+/* handle a melt pragma*/
+static void
+handle_melt_pragma (cpp_reader *ARG_UNUSED(dummy))
+{
+  enum cpp_ttype token;
+  /*list containing the pragma argument*/
+  tree x;
+  MELT_ENTERFRAME (3, NULL);
+#define seqv  meltfram__.mcfr_varptr[0]
+#define treev meltfram__.mcfr_varptr[1]
+#define optreev   meltfram__.mcfr_varptr[2]
+  if(! pragma_lex || ! c_register_pragma)
+GCC_BAD("Cannot use pragma symbol at this level (maybe you use -flto which 
\
+is incompatible).");
+
+  token = pragma_lex (&x);
+  if(token != CPP_NAME)
+GCC_BAD ("malformed #pragma melt, ignored");
+  optreev = meltgc_new_tree((meltobject_ptr_t) MELT_PREDEF (DISCR_TREE), x);
+  /*If the pragma has the form #pragma PLUGIN melt id (...) then optreev is the
+  tree containing "id".
+  Next element should be a parenthese opening. */
+  token = pragma_lex (&x);
+  if (token != CPP_OPEN_PAREN){
+if (token != CPP_EOF)
+  GCC_BAD ("malformed #pragma melt, ignored");
+
+else{ /* we have a pragma of the type '#pragma PLUGIN melt instr' */
+  melt_handle_melt_pragma ((melt_ptr_t ) optreev, (melt_ptr_t ) NULL);
+}
+  }
+  else{/* opening parenthesis */
+seqv = meltgc_new_list ((meltobject_ptr_t) MELT_PREDEF (DISCR_LIST));
+do {
+  token = pragma_lex (&x);
+  if(token != CPP_NAME && token != CPP_STRING && token != CPP_NUMBER)
+

Re: [PATCH] c-pragma: adding a data field to pragma_handler

2011-06-03 Thread Pierre Vittet

Thank you for your answer!

I send you a new patch
I have corrected the errors you raised.

I have make my patch compatible with the old use of c_register_pragma 
and c_register_pragma_with_expansion.


I don't know what is the best solution, maybe changing every call 
c_register_pragma allows to keep a more clear code. I can do it, if you 
think it is better.


I have successfully compiled gcc with my patch and I have tried it with 
a modified version of gcc/testsuite/g++.dg/plugin/pragma_plugin.c.


Pierre Vittet

On 02/06/2011 19:51, Tom Tromey wrote:

"Pierre" == Pierre  writes:


Pierre>  I have changed this handler in order to accept a second parameter
Pierre>  which is a void *, allowing to give extra datas to the handler. I
Pierre>  think this data field might be of general use: we can have condition
Pierre>  or data at register time that we want to express in the handler. I
Pierre>  guess this is a common way to pass data to an handler function.

I can't approve or reject this patch, but the idea seems reasonable
enough to me.

Pierre>  I would like your opinion on this patch! Thanks!

It has a number of formatting issues.

Pierre>  +typedef void (*pragma_handler)(struct cpp_reader *, void * );

No space after the final "*".

Pierre>  +/* Internally use to keep the data of the handler.  */
Pierre>  +struct internal_pragma_handler_d{

Space before the "{".

Pierre>  +  pragma_handler handler;
Pierre>  +  void * data;

No space.  Lots of instances of this.

Pierre>   /* A vector of registered pragma callbacks.  */
Pierre>  +/*This is never freed as we need it during the whole execution */

Coalesce the two comments.  The comment formatting is wrong, see GNU
standards.

Pierre> ns_name.space = space;
Pierre> ns_name.name = name;
Pierre>  +
Pierre> VEC_safe_push (pragma_ns_name, heap, 
registered_pp_pragmas,&ns_name);

Gratuitous newline addition.

Pierre>  +  ihandler->handler = handler;
Pierre>  +  ihandler->data = data;

I didn't see anything that initialized ihandler.

Pierre>  +  VEC_safe_push (internal_pragma_handler, heap, 
registered_pragmas,
Pierre>  +&ihandler);

I think you wanted just `internal_pragma_handler ihandler', no "*", for
the definition.

Pierre>  +c_register_pragma (const char *space, const char *name, 
pragma_handler handler,
Pierre>  +   void * data)

There are lots of calls to this that you did not update.
Do a recursive grep to see.

One way to avoid a massive change is to add a new "overload" that passes
in the data to c_register_pragma_1; and then change the "legacy"
functions to pass NULL.

I don't know if that approach is ok (it is typical in gdb...), so if
not, you have to update all callers.

Tom



Index: gcc/c-family/c-pragma.c
===
--- gcc/c-family/c-pragma.c (revision 174521)
+++ gcc/c-family/c-pragma.c (working copy)
@@ -53,7 +53,7 @@ typedef struct GTY(()) align_stack {
 
 static GTY(()) struct align_stack * alignment_stack;
 
-static void handle_pragma_pack (cpp_reader *);
+static void handle_pragma_pack (cpp_reader *, void * data);
 
 /* If we have a "global" #pragma pack() in effect when the first
#pragma pack(push,) is encountered, this stores the value of
@@ -133,7 +133,7 @@ pop_alignment (tree id)
#pragma pack (pop)
#pragma pack (pop, ID) */
 static void
-handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
+handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy), void * ARG_UNUSED (data))
 {
   tree x, id = 0;
   int align = -1;
@@ -247,7 +247,7 @@ DEF_VEC_ALLOC_O(pending_weak,gc);
 static GTY(()) VEC(pending_weak,gc) *pending_weaks;
 
 static void apply_pragma_weak (tree, tree);
-static void handle_pragma_weak (cpp_reader *);
+static void handle_pragma_weak (cpp_reader *, void * data);
 
 static void
 apply_pragma_weak (tree decl, tree value)
@@ -334,7 +334,7 @@ maybe_apply_pending_pragma_weaks (void)
 
 /* #pragma weak name [= value] */
 static void
-handle_pragma_weak (cpp_reader * ARG_UNUSED (dummy))
+handle_pragma_weak (cpp_reader * ARG_UNUSED (dummy), void * ARG_UNUSED (data))
 {
   tree name, value, x, decl;
   enum cpp_ttype t;
@@ -411,11 +411,12 @@ DEF_VEC_ALLOC_O(pending_redefinition,gc);
 
 static GTY(()) VEC(pending_redefinition,gc) *pending_redefine_extname;
 
-static void handle_pragma_redefine_extname (cpp_reader *);
+static void handle_pragma_redefine_extname (cpp_reader *, void * data);
 
 /* #pragma redefine_extname oldname newname */
 static void
-handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy))
+handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy),
+void * ARG_UNUSED (data))
 {
   tree oldname, newname, decl, x;
   enum cpp_ttype t;
@@ -481,7 +482,8 @@ static GTY(()) tree 

Re: [PATCH] c-pragma: adding a data field to pragma_handler

2011-06-03 Thread Pierre Vittet

Hello,

I am sorry, my editor (vim) was not correctly configure (I used 
http://gcc.gnu.org/ml/gcc/2011-03/msg00425.html to improve it). I guess 
it is ok now.
If I still have issue, I will post on the mailing list if there is some 
tips for vim otherway I will use Emacs (I am not very comfortable with 
it for now ;).


Pierre Vittet

On 03/06/2011 17:47, Basile Starynkevitch wrote:

On Fri, 03 Jun 2011 17:31:25 +0200
Pierre Vittet  wrote:

   

Thank you for your answer!

I send you a new patch
I have corrected the errors you raised.

I have make my patch compatible with the old use of c_register_pragma
and c_register_pragma_with_expansion.
 

I find the patch quite interesting, but I cannot approve it.

  void
+c_register_pragma_with_expansion_and_data (const char *space, const char *name,
+  
pragma_handler_2arg handler,
+   void * data)

Perhaps there are some spaces (vs tabs) issues here.

Cheers
   


Index: gcc/c-family/c-pragma.c
===
--- gcc/c-family/c-pragma.c (revision 174521)
+++ gcc/c-family/c-pragma.c (working copy)
@@ -1148,12 +1148,12 @@ handle_pragma_float_const_decimal64 (cpp_reader *A
 }
 
 /* A vector of registered pragma callbacks.  */
+/* This is never freed as we need it during the whole execution.  */
+DEF_VEC_O (internal_pragma_handler);
+DEF_VEC_ALLOC_O (internal_pragma_handler, heap);
 
-DEF_VEC_O (pragma_handler);
-DEF_VEC_ALLOC_O (pragma_handler, heap);
+static VEC(internal_pragma_handler, heap) *registered_pragmas;
 
-static VEC(pragma_handler, heap) *registered_pragmas;
-
 typedef struct
 {
   const char *space;
@@ -1216,7 +1216,7 @@ c_pp_lookup_pragma (unsigned int id, const char **
 
 static void
 c_register_pragma_1 (const char *space, const char *name,
-pragma_handler handler, bool allow_expansion)
+ internal_pragma_handler ihandler, bool allow_expansion)
 {
   unsigned id;
 
@@ -1235,8 +1235,9 @@ c_register_pragma_1 (const char *space, const char
 }
   else
 {
-  VEC_safe_push (pragma_handler, heap, registered_pragmas, &handler);
-  id = VEC_length (pragma_handler, registered_pragmas);
+  VEC_safe_push (internal_pragma_handler, heap, registered_pragmas,
+ &ihandler);
+  id = VEC_length (internal_pragma_handler, registered_pragmas);
   id += PRAGMA_FIRST_EXTERNAL - 1;
 
   /* The C++ front end allocates 6 bits in cp_token; the C front end
@@ -1248,28 +1249,90 @@ c_register_pragma_1 (const char *space, const char
allow_expansion, false);
 }
 
+/* Register a C pragma handler, using a space and a name.  It disallows pragma
+expansion (if you want it, use c_register_pragma_with_expansion instead).  */
 void
-c_register_pragma (const char *space, const char *name, pragma_handler handler)
+c_register_pragma (const char *space, const char *name,
+   pragma_handler_1arg handler)
 {
-  c_register_pragma_1 (space, name, handler, false);
+  internal_pragma_handler ihandler;
+
+  ihandler.handler.handler_1arg = handler;
+  ihandler.extra_data = false;
+  ihandler.data = NULL;
+  c_register_pragma_1 (space, name, ihandler, false);
 }
 
+/* Register a C pragma handler, using a space and a name, it also carries an
+extra data field which can be used by the handler.  It disallows pragma
+expansion (if you want it, use c_register_pragma_with_expansion instead).  */
 void
+c_register_pragma_with_data (const char *space, const char *name,
+ pragma_handler_2arg handler, void * data)
+{
+  internal_pragma_handler ihandler;
+
+  ihandler.handler.handler_2arg = handler;
+  ihandler.extra_data = true;
+  ihandler.data = data;
+  c_register_pragma_1 (space, name, ihandler, false);
+}
+
+/* Register a C pragma handler, using a space and a name.  It allows pragma
+expansion as in the following exemple:
+  #define NUMBER 10
+  #pragma count (NUMBER)
+Name expansion is still disallowed.  */
+void
 c_register_pragma_with_expansion (const char *space, const char *name,
- pragma_handler handler)
+ pragma_handler_1arg handler)
 {
-  c_register_pragma_1 (space, name, handler, true);
+  internal_pragma_handler ihandler;
+
+  ihandler.handler.handler_1arg = handler;
+  ihandler.extra_data = false;
+  ihandler.data = NULL;
+  c_register_pragma_1 (space, name, ihandler, true);
 }
 
+/* Register a C pragma handler, using a space and a name, it also carries an
+extra data field which can be used by the handler.  It allows pragma expansion
+as in the following exemple:
+  #define NUMBER 10
+  #pragma count (NUMBER)
+Name expansion is still disallowed.  */
 void
+c_register_pragma_with_expansion_and_data (const char *space, const char *name,
+   pragma_hand

Re: [PATCH] c-pragma: adding a data field to pragma_handler

2011-06-08 Thread Pierre Vittet
I have written a test for this patch and run it (it works correctly). I 
guess there is no reason why it should not be accepted now.
To recap, this patch add a void * data field to the pragma handler, 
allowing to pass extra data. If we want to use this field, we need to 
use the function c_register_pragma_with_data or 
c_register_pragma_with_expansion_and_data. The old 
c_register_pragma(_with_expansion) is kept compatible.


I give two diff and two ChangeLog, the first are for the patch itself, 
the second are for the test.


I have tried to make things as good as possible, if there is a remark, 
please, send me it. Especially, I am not sure about the format of my 
ChangeLog, if there is an issue, I am ready to change it.


Changelog gcc:

2011-06-08  Pierre Vittet  

* c-pragma.h (pragma_handler_1arg, pragma_handler_2arg,
gen_pragma_handler, internal_pragma_handler, c_register_pragma,
c_register_pragma_with_data, c_register_pragma_with_expansion,
c_register_pragma_with_expansion_and_data): allows to add data to a
pragma handler using a new c_register. Old c_register keep old
behaviour for compatibility.
* c-pragma.c (registered_pragmas, c_register_pragma_1,
c_register_pragma, c_register_pragma_with_data,
c_register_pragma_with_expansion,
c_register_pragma_with_expansion_and_data, c_invoke_pragma_handler,
init_pragma): allows to add data to a pragma handler using a new
c_register. Old registers keep old behaviour for compatibility.

Changelog testsuite

2011-06-08  Pierre Vittet  

* g++.dg/plugin/pragma_plugin_with_data.c: New test.


Thanks!

Pierre Vittet
Index: gcc/c-family/c-pragma.c
===
--- gcc/c-family/c-pragma.c (revision 174521)
+++ gcc/c-family/c-pragma.c (working copy)
@@ -1148,12 +1148,12 @@ handle_pragma_float_const_decimal64 (cpp_reader *A
 }
 
 /* A vector of registered pragma callbacks.  */
+/* This is never freed as we need it during the whole execution.  */
+DEF_VEC_O (internal_pragma_handler);
+DEF_VEC_ALLOC_O (internal_pragma_handler, heap);
 
-DEF_VEC_O (pragma_handler);
-DEF_VEC_ALLOC_O (pragma_handler, heap);
+static VEC(internal_pragma_handler, heap) *registered_pragmas;
 
-static VEC(pragma_handler, heap) *registered_pragmas;
-
 typedef struct
 {
   const char *space;
@@ -1216,7 +1216,7 @@ c_pp_lookup_pragma (unsigned int id, const char **
 
 static void
 c_register_pragma_1 (const char *space, const char *name,
-pragma_handler handler, bool allow_expansion)
+ internal_pragma_handler ihandler, bool allow_expansion)
 {
   unsigned id;
 
@@ -1235,8 +1235,9 @@ c_register_pragma_1 (const char *space, const char
 }
   else
 {
-  VEC_safe_push (pragma_handler, heap, registered_pragmas, &handler);
-  id = VEC_length (pragma_handler, registered_pragmas);
+  VEC_safe_push (internal_pragma_handler, heap, registered_pragmas,
+ &ihandler);
+  id = VEC_length (internal_pragma_handler, registered_pragmas);
   id += PRAGMA_FIRST_EXTERNAL - 1;
 
   /* The C++ front end allocates 6 bits in cp_token; the C front end
@@ -1248,28 +1249,90 @@ c_register_pragma_1 (const char *space, const char
allow_expansion, false);
 }
 
+/* Register a C pragma handler, using a space and a name.  It disallows pragma
+expansion (if you want it, use c_register_pragma_with_expansion instead).  */
 void
-c_register_pragma (const char *space, const char *name, pragma_handler handler)
+c_register_pragma (const char *space, const char *name,
+   pragma_handler_1arg handler)
 {
-  c_register_pragma_1 (space, name, handler, false);
+  internal_pragma_handler ihandler;
+
+  ihandler.handler.handler_1arg = handler;
+  ihandler.extra_data = false;
+  ihandler.data = NULL;
+  c_register_pragma_1 (space, name, ihandler, false);
 }
 
+/* Register a C pragma handler, using a space and a name, it also carries an
+extra data field which can be used by the handler.  It disallows pragma
+expansion (if you want it, use c_register_pragma_with_expansion instead).  */
 void
+c_register_pragma_with_data (const char *space, const char *name,
+ pragma_handler_2arg handler, void * data)
+{
+  internal_pragma_handler ihandler;
+
+  ihandler.handler.handler_2arg = handler;
+  ihandler.extra_data = true;
+  ihandler.data = data;
+  c_register_pragma_1 (space, name, ihandler, false);
+}
+
+/* Register a C pragma handler, using a space and a name.  It allows pragma
+expansion as in the following exemple:
+  #define NUMBER 10
+  #pragma count (NUMBER)
+Name expansion is still disallowed.  */
+void
 c_register_pragma_with_expansion (const char *space, const char *name,
- pragma_handler handler)
+ pragma_handler_1arg

Re: [PATCH] c-pragma: adding a data field to pragma_handler

2011-06-09 Thread Pierre Vittet

You are right, the new version is in the diff.
The diff for the test hasn't changed and is in the previous mail.

In the previous version of the file, the registered_pragmas was not 
better freed. I don't know if it is really important (it would need a 
callback at the end of the front-end passes).


Thanks.



On 09/06/2011 08:16, Basile Starynkevitch wrote:

On Wed, 08 Jun 2011 23:26:39 +0200
Pierre Vittet  wrote:

   

I have written a test for this patch and run it (it works correctly). I
guess there is no reason why it should not be accepted now.
To recap, this patch add a void * data field to the pragma handler,
allowing to pass extra data. If we want to use this field, we need to
use the function c_register_pragma_with_data or
c_register_pragma_with_expansion_and_data. The old
c_register_pragma(_with_expansion) is kept compatible.
 


===
--- gcc/c-family/c-pragma.c (revision 174521)
+++ gcc/c-family/c-pragma.c (working copy)
@@ -1148,12 +1148,12 @@ handle_pragma_float_const_decimal64 (cpp_reader
*A }

  /* A vector of registered pragma callbacks.  */
+/* This is never freed as we need it during the whole execution.  */
+DEF_VEC_O (internal_pragma_handler);
+DEF_VEC_ALLOC_O (internal_pragma_handler, heap);

Sorry to be picky Pierre, but that comment is not correct. It should be
instead.

/* A vector of registered pragma callbacks, which is never freed.   */

What I mean is that you are right that the vector is never freed, but
it is not because it is needed during the entire execution, since
middle-end and back-end passes don't know about pragmas.

I hope your patch will be ok-ed with that small change.

Perhaps a future patch would free that registered_pragmas vector, but I
feel that is not necessary, since it is not a big vector in practice.

Regards.

   


Index: gcc/c-family/c-pragma.c
===
--- gcc/c-family/c-pragma.c (revision 174521)
+++ gcc/c-family/c-pragma.c (working copy)
@@ -1147,13 +1147,12 @@ handle_pragma_float_const_decimal64 (cpp_reader *A
 }
 }
 
-/* A vector of registered pragma callbacks.  */
+/* A vector of registered pragma callbacks, which is never freed.   */
+DEF_VEC_O (internal_pragma_handler);
+DEF_VEC_ALLOC_O (internal_pragma_handler, heap);
 
-DEF_VEC_O (pragma_handler);
-DEF_VEC_ALLOC_O (pragma_handler, heap);
+static VEC(internal_pragma_handler, heap) *registered_pragmas;
 
-static VEC(pragma_handler, heap) *registered_pragmas;
-
 typedef struct
 {
   const char *space;
@@ -1216,7 +1215,7 @@ c_pp_lookup_pragma (unsigned int id, const char **
 
 static void
 c_register_pragma_1 (const char *space, const char *name,
-pragma_handler handler, bool allow_expansion)
+ internal_pragma_handler ihandler, bool allow_expansion)
 {
   unsigned id;
 
@@ -1235,8 +1234,9 @@ c_register_pragma_1 (const char *space, const char
 }
   else
 {
-  VEC_safe_push (pragma_handler, heap, registered_pragmas, &handler);
-  id = VEC_length (pragma_handler, registered_pragmas);
+  VEC_safe_push (internal_pragma_handler, heap, registered_pragmas,
+ &ihandler);
+  id = VEC_length (internal_pragma_handler, registered_pragmas);
   id += PRAGMA_FIRST_EXTERNAL - 1;
 
   /* The C++ front end allocates 6 bits in cp_token; the C front end
@@ -1248,28 +1248,90 @@ c_register_pragma_1 (const char *space, const char
allow_expansion, false);
 }
 
+/* Register a C pragma handler, using a space and a name.  It disallows pragma
+expansion (if you want it, use c_register_pragma_with_expansion instead).  */
 void
-c_register_pragma (const char *space, const char *name, pragma_handler handler)
+c_register_pragma (const char *space, const char *name,
+   pragma_handler_1arg handler)
 {
-  c_register_pragma_1 (space, name, handler, false);
+  internal_pragma_handler ihandler;
+
+  ihandler.handler.handler_1arg = handler;
+  ihandler.extra_data = false;
+  ihandler.data = NULL;
+  c_register_pragma_1 (space, name, ihandler, false);
 }
 
+/* Register a C pragma handler, using a space and a name, it also carries an
+extra data field which can be used by the handler.  It disallows pragma
+expansion (if you want it, use c_register_pragma_with_expansion instead).  */
 void
+c_register_pragma_with_data (const char *space, const char *name,
+ pragma_handler_2arg handler, void * data)
+{
+  internal_pragma_handler ihandler;
+
+  ihandler.handler.handler_2arg = handler;
+  ihandler.extra_data = true;
+  ihandler.data = data;
+  c_register_pragma_1 (space, name, ihandler, false);
+}
+
+/* Register a C pragma handler, using a space and a name.  It allows pragma
+expansion as in the following exemple:
+  #define NUMBER 10
+  #pragma count (NUMBER)
+Name expansion is stil

Re: [PATCH] c-pragma: adding a data field to pragma_handler

2011-06-10 Thread Pierre Vittet

thanks!

I formatted as you requested.

I cannot commit myself as I haven't a  "write after approval" status, 
maye you can do it, or I can wait my GSOC mentor, Basile Starynkevitch 
to do this (He mights be busy for a few days).


Pierre Vittet

Index: gcc/c-family/c-pragma.c
===
--- gcc/c-family/c-pragma.c (revision 174521)
+++ gcc/c-family/c-pragma.c (working copy)
@@ -1147,13 +1147,12 @@ handle_pragma_float_const_decimal64 (cpp_reader *A
 }
 }
 
-/* A vector of registered pragma callbacks.  */
+/* A vector of registered pragma callbacks, which is never freed.   */
+DEF_VEC_O (internal_pragma_handler);
+DEF_VEC_ALLOC_O (internal_pragma_handler, heap);
 
-DEF_VEC_O (pragma_handler);
-DEF_VEC_ALLOC_O (pragma_handler, heap);
+static VEC(internal_pragma_handler, heap) *registered_pragmas;
 
-static VEC(pragma_handler, heap) *registered_pragmas;
-
 typedef struct
 {
   const char *space;
@@ -1216,7 +1215,7 @@ c_pp_lookup_pragma (unsigned int id, const char **
 
 static void
 c_register_pragma_1 (const char *space, const char *name,
-pragma_handler handler, bool allow_expansion)
+ internal_pragma_handler ihandler, bool allow_expansion)
 {
   unsigned id;
 
@@ -1235,8 +1234,9 @@ c_register_pragma_1 (const char *space, const char
 }
   else
 {
-  VEC_safe_push (pragma_handler, heap, registered_pragmas, &handler);
-  id = VEC_length (pragma_handler, registered_pragmas);
+  VEC_safe_push (internal_pragma_handler, heap, registered_pragmas,
+ &ihandler);
+  id = VEC_length (internal_pragma_handler, registered_pragmas);
   id += PRAGMA_FIRST_EXTERNAL - 1;
 
   /* The C++ front end allocates 6 bits in cp_token; the C front end
@@ -1248,28 +1248,95 @@ c_register_pragma_1 (const char *space, const char
allow_expansion, false);
 }
 
+/* Register a C pragma handler, using a space and a name.  It disallows pragma
+   expansion (if you want it, use c_register_pragma_with_expansion instead).  
*/
 void
-c_register_pragma (const char *space, const char *name, pragma_handler handler)
+c_register_pragma (const char *space, const char *name,
+   pragma_handler_1arg handler)
 {
-  c_register_pragma_1 (space, name, handler, false);
+  internal_pragma_handler ihandler;
+
+  ihandler.handler.handler_1arg = handler;
+  ihandler.extra_data = false;
+  ihandler.data = NULL;
+  c_register_pragma_1 (space, name, ihandler, false);
 }
 
+/* Register a C pragma handler, using a space and a name, it also carries an
+   extra data field which can be used by the handler.  It disallows pragma
+   expansion (if you want it, use c_register_pragma_with_expansion_and_data
+   instead).  */
 void
+c_register_pragma_with_data (const char *space, const char *name,
+ pragma_handler_2arg handler, void * data)
+{
+  internal_pragma_handler ihandler;
+
+  ihandler.handler.handler_2arg = handler;
+  ihandler.extra_data = true;
+  ihandler.data = data;
+  c_register_pragma_1 (space, name, ihandler, false);
+}
+
+/* Register a C pragma handler, using a space and a name.  It allows pragma
+   expansion as in the following example:
+
+   #define NUMBER 10
+   #pragma count (NUMBER)
+
+   Name expansion is still disallowed.  */
+void
 c_register_pragma_with_expansion (const char *space, const char *name,
- pragma_handler handler)
+ pragma_handler_1arg handler)
 {
-  c_register_pragma_1 (space, name, handler, true);
+  internal_pragma_handler ihandler;
+
+  ihandler.handler.handler_1arg = handler;
+  ihandler.extra_data = false;
+  ihandler.data = NULL;
+  c_register_pragma_1 (space, name, ihandler, true);
 }
 
+/* Register a C pragma handler, using a space and a name, it also carries an
+   extra data field which can be used by the handler.  It allows pragma
+   expansion as in the following example:
+
+   #define NUMBER 10
+   #pragma count (NUMBER)
+
+   Name expansion is still disallowed.  */
 void
+c_register_pragma_with_expansion_and_data (const char *space, const char *name,
+   pragma_handler_2arg handler,
+   void *data)
+{
+  internal_pragma_handler ihandler;
+
+  ihandler.handler.handler_2arg = handler;
+  ihandler.extra_data = true;
+  ihandler.data = data;
+  c_register_pragma_1 (space, name, ihandler, true);
+}
+
+void
 c_invoke_pragma_handler (unsigned int id)
 {
-  pragma_handler handler;
+  internal_pragma_handler *ihandler;
+  pragma_handler_1arg handler_1arg;
+  pragma_handler_2arg handler_2arg;
 
   id -= PRAGMA_FIRST_EXTERNAL;
-  handler = *VEC_index (pragma_handler, registered_pragmas, id);
-
-  handler (parse_in);
+  ihandler = VEC_index (internal_pragma_handler, registered_pragmas, id);
+  if (ihandler->extra_data)
+{
+   

Re: [PATCH] c-pragma: adding a data field to pragma_handler

2011-06-10 Thread Pierre Vittet

I guess this is better now.

Changelog (gcc/c-family):

2011-06-10  Pierre Vittet 

* c-pragma.h (pragma_handler_1arg, pragma_handler_2arg): New handler.
(gen_pragma_handler): New union.
(internal_pragma_handler): New type.
(c_register_pragma_with_data,
c_register_pragma_with_expansion_and_data): New functions.
* c-pragma.c (registered_pragmas, c_register_pragma_1,
c_register_pragma, c_register_pragma_with_expansion,
c_invoke_pragma_handler): Changed to work with internal_pragma_handler.
(c_register_pragma_with_data,
c_register_pragma_with_expansion_and_data): New functions.

Changelog (gcc/testsuite):

2011-06-10  Pierre Vittet 

* g++.dg/plugin/pragma_plugin_with_data.c: New test file.
* g++.dg/plugin/pragma_plugin_with_data-test-1.C: New test file.
* g++.dg/plugin/plugin.exp (plugin_test_list): Add the new test

Index: gcc/c-family/c-pragma.c
===
--- gcc/c-family/c-pragma.c (revision 174521)
+++ gcc/c-family/c-pragma.c (working copy)
@@ -1147,13 +1147,12 @@ handle_pragma_float_const_decimal64 (cpp_reader *A
 }
 }
 
-/* A vector of registered pragma callbacks.  */
+/* A vector of registered pragma callbacks, which is never freed.   */
+DEF_VEC_O (internal_pragma_handler);
+DEF_VEC_ALLOC_O (internal_pragma_handler, heap);
 
-DEF_VEC_O (pragma_handler);
-DEF_VEC_ALLOC_O (pragma_handler, heap);
+static VEC(internal_pragma_handler, heap) *registered_pragmas;
 
-static VEC(pragma_handler, heap) *registered_pragmas;
-
 typedef struct
 {
   const char *space;
@@ -1216,7 +1215,7 @@ c_pp_lookup_pragma (unsigned int id, const char **
 
 static void
 c_register_pragma_1 (const char *space, const char *name,
-pragma_handler handler, bool allow_expansion)
+ internal_pragma_handler ihandler, bool allow_expansion)
 {
   unsigned id;
 
@@ -1235,8 +1234,9 @@ c_register_pragma_1 (const char *space, const char
 }
   else
 {
-  VEC_safe_push (pragma_handler, heap, registered_pragmas, &handler);
-  id = VEC_length (pragma_handler, registered_pragmas);
+  VEC_safe_push (internal_pragma_handler, heap, registered_pragmas,
+ &ihandler);
+  id = VEC_length (internal_pragma_handler, registered_pragmas);
   id += PRAGMA_FIRST_EXTERNAL - 1;
 
   /* The C++ front end allocates 6 bits in cp_token; the C front end
@@ -1248,28 +1248,95 @@ c_register_pragma_1 (const char *space, const char
allow_expansion, false);
 }
 
+/* Register a C pragma handler, using a space and a name.  It disallows pragma
+   expansion (if you want it, use c_register_pragma_with_expansion instead).  
*/
 void
-c_register_pragma (const char *space, const char *name, pragma_handler handler)
+c_register_pragma (const char *space, const char *name,
+   pragma_handler_1arg handler)
 {
-  c_register_pragma_1 (space, name, handler, false);
+  internal_pragma_handler ihandler;
+
+  ihandler.handler.handler_1arg = handler;
+  ihandler.extra_data = false;
+  ihandler.data = NULL;
+  c_register_pragma_1 (space, name, ihandler, false);
 }
 
+/* Register a C pragma handler, using a space and a name, it also carries an
+   extra data field which can be used by the handler.  It disallows pragma
+   expansion (if you want it, use c_register_pragma_with_expansion_and_data
+   instead).  */
 void
+c_register_pragma_with_data (const char *space, const char *name,
+ pragma_handler_2arg handler, void * data)
+{
+  internal_pragma_handler ihandler;
+
+  ihandler.handler.handler_2arg = handler;
+  ihandler.extra_data = true;
+  ihandler.data = data;
+  c_register_pragma_1 (space, name, ihandler, false);
+}
+
+/* Register a C pragma handler, using a space and a name.  It allows pragma
+   expansion as in the following example:
+
+   #define NUMBER 10
+   #pragma count (NUMBER)
+
+   Name expansion is still disallowed.  */
+void
 c_register_pragma_with_expansion (const char *space, const char *name,
- pragma_handler handler)
+ pragma_handler_1arg handler)
 {
-  c_register_pragma_1 (space, name, handler, true);
+  internal_pragma_handler ihandler;
+
+  ihandler.handler.handler_1arg = handler;
+  ihandler.extra_data = false;
+  ihandler.data = NULL;
+  c_register_pragma_1 (space, name, ihandler, true);
 }
 
+/* Register a C pragma handler, using a space and a name, it also carries an
+   extra data field which can be used by the handler.  It allows pragma
+   expansion as in the following example:
+
+   #define NUMBER 10
+   #pragma count (NUMBER)
+
+   Name expansion is still disallowed.  */
 void
+c_register_pragma_with_expansion_and_data (const char *space, const char *name,
+   pragma_handler_2arg handler,
+   void *data)
+{
+  internal_pragma

[APPROVED PATCH] c-pragma: adding a data field to pragma_handler

2011-06-17 Thread Pierre Vittet
Thoses two patchs have already been approved (see 
http://gcc.gnu.org/ml/gcc-patches/2011-06/msg01159.html).


I haven't write permission currently, could someone commit them?

ChangeLogs have to be applied on gcc/c-family/ChangeLog .

Thanks !

Pierre Vittet
Index: gcc/c-family/c-pragma.c
===
--- gcc/c-family/c-pragma.c (revision 174521)
+++ gcc/c-family/c-pragma.c (working copy)
@@ -1147,13 +1147,12 @@ handle_pragma_float_const_decimal64 (cpp_reader *A
 }
 }
 
-/* A vector of registered pragma callbacks.  */
+/* A vector of registered pragma callbacks, which is never freed.   */
+DEF_VEC_O (internal_pragma_handler);
+DEF_VEC_ALLOC_O (internal_pragma_handler, heap);
 
-DEF_VEC_O (pragma_handler);
-DEF_VEC_ALLOC_O (pragma_handler, heap);
+static VEC(internal_pragma_handler, heap) *registered_pragmas;
 
-static VEC(pragma_handler, heap) *registered_pragmas;
-
 typedef struct
 {
   const char *space;
@@ -1216,7 +1215,7 @@ c_pp_lookup_pragma (unsigned int id, const char **
 
 static void
 c_register_pragma_1 (const char *space, const char *name,
-pragma_handler handler, bool allow_expansion)
+ internal_pragma_handler ihandler, bool allow_expansion)
 {
   unsigned id;
 
@@ -1235,8 +1234,9 @@ c_register_pragma_1 (const char *space, const char
 }
   else
 {
-  VEC_safe_push (pragma_handler, heap, registered_pragmas, &handler);
-  id = VEC_length (pragma_handler, registered_pragmas);
+  VEC_safe_push (internal_pragma_handler, heap, registered_pragmas,
+ &ihandler);
+  id = VEC_length (internal_pragma_handler, registered_pragmas);
   id += PRAGMA_FIRST_EXTERNAL - 1;
 
   /* The C++ front end allocates 6 bits in cp_token; the C front end
@@ -1248,28 +1248,95 @@ c_register_pragma_1 (const char *space, const char
allow_expansion, false);
 }
 
+/* Register a C pragma handler, using a space and a name.  It disallows pragma
+   expansion (if you want it, use c_register_pragma_with_expansion instead).  
*/
 void
-c_register_pragma (const char *space, const char *name, pragma_handler handler)
+c_register_pragma (const char *space, const char *name,
+   pragma_handler_1arg handler)
 {
-  c_register_pragma_1 (space, name, handler, false);
+  internal_pragma_handler ihandler;
+
+  ihandler.handler.handler_1arg = handler;
+  ihandler.extra_data = false;
+  ihandler.data = NULL;
+  c_register_pragma_1 (space, name, ihandler, false);
 }
 
+/* Register a C pragma handler, using a space and a name, it also carries an
+   extra data field which can be used by the handler.  It disallows pragma
+   expansion (if you want it, use c_register_pragma_with_expansion_and_data
+   instead).  */
 void
+c_register_pragma_with_data (const char *space, const char *name,
+ pragma_handler_2arg handler, void * data)
+{
+  internal_pragma_handler ihandler;
+
+  ihandler.handler.handler_2arg = handler;
+  ihandler.extra_data = true;
+  ihandler.data = data;
+  c_register_pragma_1 (space, name, ihandler, false);
+}
+
+/* Register a C pragma handler, using a space and a name.  It allows pragma
+   expansion as in the following example:
+
+   #define NUMBER 10
+   #pragma count (NUMBER)
+
+   Name expansion is still disallowed.  */
+void
 c_register_pragma_with_expansion (const char *space, const char *name,
- pragma_handler handler)
+ pragma_handler_1arg handler)
 {
-  c_register_pragma_1 (space, name, handler, true);
+  internal_pragma_handler ihandler;
+
+  ihandler.handler.handler_1arg = handler;
+  ihandler.extra_data = false;
+  ihandler.data = NULL;
+  c_register_pragma_1 (space, name, ihandler, true);
 }
 
+/* Register a C pragma handler, using a space and a name, it also carries an
+   extra data field which can be used by the handler.  It allows pragma
+   expansion as in the following example:
+
+   #define NUMBER 10
+   #pragma count (NUMBER)
+
+   Name expansion is still disallowed.  */
 void
+c_register_pragma_with_expansion_and_data (const char *space, const char *name,
+   pragma_handler_2arg handler,
+   void *data)
+{
+  internal_pragma_handler ihandler;
+
+  ihandler.handler.handler_2arg = handler;
+  ihandler.extra_data = true;
+  ihandler.data = data;
+  c_register_pragma_1 (space, name, ihandler, true);
+}
+
+void
 c_invoke_pragma_handler (unsigned int id)
 {
-  pragma_handler handler;
+  internal_pragma_handler *ihandler;
+  pragma_handler_1arg handler_1arg;
+  pragma_handler_2arg handler_2arg;
 
   id -= PRAGMA_FIRST_EXTERNAL;
-  handler = *VEC_index (pragma_handler, registered_pragmas, id);
-
-  handler (parse_in);
+  ihandler = VEC_index (internal_pragma_handler, registered_pragmas, id);
+  if (ihandler->extra_data)
+{
+  

[PATCH, MELT] fix minor issue with meltgc_new_split_string

2011-06-21 Thread Pierre Vittet

Hello,

I got a bug when using meltgc_new_split_string (in melt-runtime.c) with 
a string (argument str) like this one "mystringanotherString" 
with  the separator. The function is not working on a string that 
start with the separator.
I guess this case can happen in real case, for exemple when an user give 
arguments with a space as a separator.


The function was also not working properly on a string like this one: 
"firstStrsecondStr".


With the patch, we get a correct list, ignoring the possible presence of 
a first separator and of separator immediatly followed by another.


I took this opportunity to add a small comment to the function (in the 
second diff).


ChangeLog

2011-06-21  Pierre Vittet  

* melt-runtime.c (meltgc_new_split_string): Fix issue.

2011-06-21  Pierre Vittet  

* melt-runtime.c (meltgc_new_split_string): Add comment.


Pierre Vittet
Index: gcc/melt-runtime.c
===
--- gcc/melt-runtime.c  (revision 175247)
+++ gcc/melt-runtime.c  (working copy)
@@ -4638,6 +4638,12 @@ meltgc_new_split_string (const char*str, int sep,
 {
   cursep = NULL;
   strv = NULL;
+  /* avoid errors when we have str which starts with the separator or when
+ we have a separator immediatly followed by another one (like
+ 'first::second').
+  */
+  while (*pc == sep)
+pc++;
   if (ISSPACE (sep)) 
  for (cursep=pc; *cursep && !ISSPACE (*cursep); cursep++);
   else
Index: gcc/melt-runtime.c
===
--- gcc/melt-runtime.c  (revision 175247)
+++ gcc/melt-runtime.c  (working copy)
@@ -4604,7 +4604,8 @@ end:
 #undef str_strv
 }
 
-
+/* Split a string into a list of string value using sep as separating 
character.
+*/
 melt_ptr_t
 meltgc_new_split_string (const char*str, int sep, melt_ptr_t discr_p)
 {


[PATCH, MELT] loading extra module before setting options

2011-06-23 Thread Pierre Vittet

Hello,

In the function load_melt_modules_and_do_mode of melt-runtime.c, we 
first load initial modules, then we set options, and then we look at 
extra modules.


With this patch, we load extra modules before we set options, because 
extra modules can contain code to handle options.


This change has been compiled and tested without errors.

ChangeLog:

2011-06-22  Pierre Vittet  

* melt-runtime.c (load_melt_modules_and_do_mode): load extra module 
before

setting options


Pierre Vittet
Index: gcc/melt-runtime.c
===
--- gcc/melt-runtime.c  (revision 175330)
+++ gcc/melt-runtime.c  (working copy)
@@ -8721,65 +8721,6 @@ load_melt_modules_and_do_mode (void)
 }
 
   /**
-   * Then we set MELT options.
-   **/
-  MELT_LOCATION_HERE ("before setting options");
-  optstr = melt_argument ("option");
-  debugeprintf ("load_initial_melt_modules optstr %s", optstr);
-  if (optstr && optstr[0]
-  && (optsetv=melt_get_inisysdata (FSYSDAT_OPTION_SET)) != NULL
-  && melt_magic_discr ((melt_ptr_t) optsetv) == MELTOBMAG_CLOSURE) 
-{
-  char *optc = 0;
-  char *optname = 0;
-  char *optvalue = 0;
-  for (optc = CONST_CAST (char *, optstr);
-  optc && *optc;
-  )
-   {
- optname = optvalue = NULL;
- if (!ISALPHA(*optc))
-   melt_fatal_error ("invalid MELT option name %s [should start with 
letter]",
- optc);
- optname = optc;
- while (*optc && (ISALNUM(*optc) || *optc=='_' || *optc=='-'))
-   optc++;
- if (*optc == '=') {
-   *optc = (char)0;
-   optc++;
-   optvalue = optc;
-   while (*optc && *optc != ',')
- optc++;
- }
- if (*optc==',') {
-   *optc = (char)0;
-   optc++;
- }
- optsymbv = meltgc_named_symbol (optname, MELT_CREATE);
- {
-   union meltparam_un pararg[1];
-   memset (¶rg, 0, sizeof (pararg));
-   pararg[0].meltbp_cstring = optvalue;
-   MELT_LOCATION_HERE ("option set before apply");
-   debugeprintf ("MELT option %s value %s", optname,
- optvalue?optvalue:"_");
-   optresv =
- melt_apply ((meltclosure_ptr_t) optsetv,
- (melt_ptr_t) optsymbv,
- MELTBPARSTR_CSTRING, pararg, "", NULL);
-   if (!optresv)
- warning (0, "unhandled MELT option %s", optname);
- }
-   }
-
-  /* after options setting, force a minor collection to ensure
-nothing is left in young region */
-  MELT_LOCATION_HERE ("option set done");
-  melt_garbcoll (0, MELT_ONLY_MINOR);
-}
-  MELT_LOCATION_HERE ("after setting options");
-
-  /**
* Then we handle extra modules if given.
**/
   debugeprintf ("xtrastr %p %s", xtrastr, xtrastr);
@@ -8845,6 +8786,65 @@ load_melt_modules_and_do_mode (void)
 debugeprintf ("no xtrastr %p", xtrastr);
 
   /**
+   * Then we set MELT options.
+   **/
+  MELT_LOCATION_HERE ("before setting options");
+  optstr = melt_argument ("option");
+  debugeprintf ("load_initial_melt_modules optstr %s", optstr);
+  if (optstr && optstr[0]
+  && (optsetv=melt_get_inisysdata (FSYSDAT_OPTION_SET)) != NULL
+  && melt_magic_discr ((melt_ptr_t) optsetv) == MELTOBMAG_CLOSURE) 
+{
+  char *optc = 0;
+  char *optname = 0;
+  char *optvalue = 0;
+  for (optc = CONST_CAST (char *, optstr);
+  optc && *optc;
+  )
+   {
+ optname = optvalue = NULL;
+ if (!ISALPHA(*optc))
+   melt_fatal_error ("invalid MELT option name %s [should start with 
letter]",
+ optc);
+ optname = optc;
+ while (*optc && (ISALNUM(*optc) || *optc=='_' || *optc=='-'))
+   optc++;
+ if (*optc == '=') {
+   *optc = (char)0;
+   optc++;
+   optvalue = optc;
+   while (*optc && *optc != ',')
+ optc++;
+ }
+ if (*optc==',') {
+   *optc = (char)0;
+   optc++;
+ }
+ optsymbv = meltgc_named_symbol (optname, MELT_CREATE);
+ {
+   union meltparam_un pararg[1];
+   memset (¶rg, 0, sizeof (pararg));
+   pararg[0].meltbp_cstring = optvalue;
+   MELT_LOCATION_HERE ("option set before apply");
+   debugeprintf ("MELT option %s value %s", optname,
+ optvalue?optvalue:"_");
+   optresv =

[PATCH, MELT] pragma support in MELT

2011-06-24 Thread Pierre Vittet

Hello,

This patch completes the pragma support in MELT. Now, a plugin can 
register several pragmas (with different name) in the following format 
(for GCC > 4.6):


#pragma MELT   (,...).

This pragma can be easily handle in a MELT function, giving the operator 
and the list of arguments as parameters.


For GCC<=4.6, there is a minimal pragma support, we can handle following 
pragma:


#pragma GCCPLUGIN melt  (,...)

with only melt as name.

ChangeLog:

2011-06-24  Pierre Vittet 

* melt-runtime.c (GCC_PRAGMA_BAD): Macro to return an error from the
pragma handling system.
[__GNUC__>4.6](melt_handle_melt_pragma, handle_melt_pragma,
melt_pragma_callback): Add functions for full pragma handling.
[__GNUC__<=4.6](melt_handle_melt_pragma, handle_melt_pragma,
melt_pragma_callback): Add functions for limited pragma handling.
(melt_startunit_callback): Register a callback for pragma.
* Makefile.in (CFAMILYINC): We need c-family header in include 
headers.
Index: gcc/Makefile.in
===
--- gcc/Makefile.in (revision 175348)
+++ gcc/Makefile.in (working copy)
@@ -359,6 +359,9 @@ DECNUMFMT = $(srcdir)/../libdecnumber/$(enable_dec
 DECNUMINC = -I$(DECNUM) -I$(DECNUMFMT) -I../libdecnumber
 LIBDECNUMBER = ../libdecnumber/libdecnumber.a
 
+#c-family header
+CFAMILYINC=-I$(srcdir)/c-family
+
 # Target to use when installing include directory.  Either
 # install-headers-tar, install-headers-cpio or install-headers-cp.
 INSTALL_HEADERS_DIR = @build_install_headers_dir@
@@ -1096,8 +1099,8 @@ INCLUDES = -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@
   -I$(srcdir)/melt/generated \
   -I$(srcdir)/../include @INCINTL@ \
   $(CPPINC) $(GMPINC) $(DECNUMINC) \
-  $(PPLINC) $(CLOOGINC)
-
+  $(PPLINC) $(CLOOGINC) \
+  $(CFAMILYINC)
 .c.o:
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $< $(OUTPUT_OPTION)
 
Index: gcc/melt-runtime.c
===
--- gcc/melt-runtime.c  (revision 175348)
+++ gcc/melt-runtime.c  (working copy)
@@ -74,7 +74,9 @@ along with GCC; see the file COPYING3.   If not se
 #include "md5.h"
 #include "plugin.h"
 #include "cppdefault.h"
+#include "c-pragma.h"
 
+
 #if BUILDING_GCC_VERSION > 4005
 /* GCC 4.6 has realmpfr.h which includes   */
 #include "realmpfr.h"
@@ -8938,7 +8940,284 @@ melt_attribute_callback(void *gcc_data ATTRIBUTE_U
   register_attribute(&melt_attr_spec);
 }
 
+/* We declare weak functions because they cannot be linked when we use lto (it
+   loses langage specific informations).
+   If you use one of those functions you must check them to be not NULL.
+*/
+extern enum cpp_ttype __attribute__((weak)) pragma_lex (tree *);
 
+
+
+#define GCC_PRAGMA_BAD(gmsgid) \
+  do { warning (OPT_Wpragmas, gmsgid); goto end; } while (0)
+
+
+
+/* Test for GCC > 4.6.0 */
+#if __GNUC__ > 4 || \
+(__GNUC__ == 4 && (__GNUC_MINOR__ > 6))
+/*Full pragma with data support.*/
+
+void melt_handle_melt_pragma (melt_ptr_t optreev, melt_ptr_t listargtreev,
+  int indice_handler);
+
+extern void __attribute__((weak)) c_register_pragma_with_expansion_and_data
+(const char *space, const char *name,
+ pragma_handler_2arg handler, void *data);
+
+/* handle a melt pragma: data contain the name of the command (as a string)*/
+static void
+handle_melt_pragma (cpp_reader *ARG_UNUSED(dummy), void * data)
+{
+  enum cpp_ttype token;
+  /*list containing the pragma argument*/
+  tree x;
+  int ihandler = (int) data;
+  MELT_ENTERFRAME (3, NULL);
+#define seqv  meltfram__.mcfr_varptr[0]
+#define treev meltfram__.mcfr_varptr[1]
+#define optreev   meltfram__.mcfr_varptr[2]
+  if(! pragma_lex || ! c_register_pragma_with_expansion_and_data)
+GCC_PRAGMA_BAD("Cannot use pragma symbol at this level \
+   (maybe you use -flto which is incompatible).");
+
+  token = pragma_lex (&x);
+  if(token != CPP_NAME)
+GCC_PRAGMA_BAD ("malformed #pragma melt, ignored");
+  optreev = meltgc_new_tree((meltobject_ptr_t) MELT_PREDEF (DISCR_TREE), x);
+  /*If the pragma has the form #pragma PLUGIN melt id (...) then optreev is the
+  tree containing "id".
+  Next element should be a parenthese opening. */
+  token = pragma_lex (&x);
+  if (token != CPP_OPEN_PAREN){
+if (token != CPP_EOF)
+  GCC_PRAGMA_BAD ("malformed #pragma melt, ignored");
+
+else{ /* we have a pragma of the type '#pragma PLUGIN melt instr' */
+  melt_handle_melt_pragma ((melt_ptr_t ) optreev, (melt_ptr_t ) NULL,
+   ihandler);
+}
+  }
+  else{/* opening parenthesis */
+seqv = meltgc_new_list ((meltobject_ptr_t) MELT_PREDEF (DISCR_LIST));
+do {
+  

[PATCH, MELT] correct meltgc_read_from_val without location

2011-06-24 Thread Pierre Vittet

Hello,

The function meltgc_read_from_val (in melt-runtime.c) takes two 
arguments, a string value and a second one which is a location.
In the comments, it is written that we can pass a NULL pointer if we 
have no location (it is a direct string). However, this conduct MELT to 
crash because it doesn't handle correctly the absence of file.


This patch correct this, if there is no file, it create a "virtual" one 
which is named "stringBuffer".


Pierre Vittet
Index: gcc/melt-runtime.c
===
--- gcc/melt-runtime.c  (revision 175348)
+++ gcc/melt-runtime.c  (working copy)
@@ -6326,7 +6326,7 @@ melt_linemap_compute_current_location (struct read
 {
   int colnum = 1;
   int cix = 0;
-  if (!rd || !rd->rcurlin) 
+  if (!rd || !rd->rcurlin || !rd->rpfilnam)
 return;
   for (cix=0; cixrcol; cix++) {
 char c = rd->rcurlin[cix];
@@ -6702,13 +6702,22 @@ static melt_ptr_t
 makesexpr (struct reading_st *rd, int lineno, melt_ptr_t contents_p,
   location_t loc, bool ismacrostring)
 {
-  MELT_ENTERFRAME (4, NULL);
+  MELT_ENTERFRAME (5, NULL);
 #define sexprv  meltfram__.mcfr_varptr[0]
 #define contsv   meltfram__.mcfr_varptr[1]
 #define locmixv meltfram__.mcfr_varptr[2]
 #define sexpclassv meltfram__.mcfr_varptr[3]
+#define locnamv meltfram__.mcfr_varptr[4]
   contsv = contents_p;
   gcc_assert (melt_magic_discr ((melt_ptr_t) contsv) == MELTOBMAG_LIST);
+  /* If there is no filename associated, we create a false one, named
+"stringBuffer".  */
+  if(rd->rpfilnam == NULL)
+{
+  locnamv = meltgc_new_string ((meltobject_ptr_t) 
MELT_PREDEF(DISCR_STRING),
+   "stringBuffer");
+  rd->rpfilnam = (melt_ptr_t *) &locnamv;
+}
   if (loc == 0)
 locmixv = meltgc_new_mixint ((meltobject_ptr_t) MELT_PREDEF 
(DISCR_MIXED_INTEGER),
*rd->rpfilnam, (long) lineno);
@@ -6728,6 +6737,7 @@ makesexpr (struct reading_st *rd, int lineno, melt
   meltgc_touch (sexprv);
   MELT_EXITFRAME ();
   return (melt_ptr_t) sexprv;
+#undef locnamv
 #undef sexprv
 #undef contsv
 #undef locmixv
@@ -8414,6 +8424,7 @@ meltgc_read_from_val (melt_ptr_t strv_p, melt_ptr_
   strv = strv_p;
   locnamv = locnam_p;
   rbuf = 0;
+  seqv = meltgc_new_list ((meltobject_ptr_t) MELT_PREDEF (DISCR_LIST));
   strmagic = melt_magic_discr ((melt_ptr_t) strv);
   switch (strmagic)
 {
@@ -8442,7 +8453,10 @@ meltgc_read_from_val (melt_ptr_t strv_p, melt_ptr_
   rds.rlineno = 0;
   rds.rcurlin = rbuf;
   rd = &rds;
-  rds.rpfilnam = (melt_ptr_t *) & locnamv;
+  if(locnamv == NULL)
+rds.rpfilnam = NULL;
+  else
+rds.rpfilnam = (melt_ptr_t *) & locnamv;
   while (rdcurc ())
 {
   bool got = FALSE;
2011-06-24  Pierre Vittet  

* melt-runtime.c (melt_linemap_compute_current_location, makesexpr,
meltgc_read_from_val): Handle the case of reading a string sexp without
given location.


Re: [PATCH, MELT] pragma support in MELT

2011-07-03 Thread Pierre Vittet

Hello,

This patch is an improvment of 
http://gcc.gnu.org/ml/gcc-patches/2011-06/msg01861.html. It completes 
pragma support into MELT. Main changes are mostly comments improvments, 
better respect of coding standard and using long instead of int for 
pragma index when we have several pragmas being registered. I also 
removed the PRAGMA_BAD macro as it was said to be less readable, and 
changed malformed pragma warnings into errors.


I tested the patch without seing any error or regression.

Pierre Vittet
2011-07-03  Pierre Vittet  

* melt-runtime.c: include c-pragma.h.
[__GNUC__>4.6] (melt_handle_melt_pragma, handle_melt_pragma,
melt_pragma_callback): Add functions for full pragma handling.
[__GNUC__<=4.6] (melt_handle_melt_pragma, handle_melt_pragma,
melt_pragma_callback): Add functions for limited pragma handling.
(melt_really_initialize): Register a callback for pragma.
* Makefile.in (CFAMILYINC): We need c-family header in include headers.

Index: gcc/melt-runtime.c
===
--- gcc/melt-runtime.c  (revision 175724)
+++ gcc/melt-runtime.c  (working copy)
@@ -74,6 +74,7 @@ along with GCC; see the file COPYING3.   If not se
 #include "md5.h"
 #include "plugin.h"
 #include "cppdefault.h"
+#include "c-pragma.h"
 
 #if BUILDING_GCC_VERSION > 4005
 /* GCC 4.6 has realmpfr.h which includes   */
@@ -8982,7 +8983,296 @@ melt_attribute_callback(void *gcc_data ATTRIBUTE_U
   register_attribute(&melt_attr_spec);
 }
 
+/* We declare weak functions because they cannot be linked when we use lto (it
+   loses langage specific informations).
+   If you use one of those functions you must check them to be not NULL.
+*/
+extern enum cpp_ttype __attribute__((weak)) pragma_lex (tree *);
 
+/* Test for GCC > 4.6.0.  */
+#if __GNUC__ > 4 || \
+(__GNUC__ == 4 && (__GNUC_MINOR__ > 6))
+/* Full pragma with data support.   */
+
+/* Call the MELT function which handle pragma: it is one of the handler of the
+   list sysdata_meltpragmas.  First argument is a tree containing the operator
+   and the second argument contains a list of tree (the arguments of the
+   pragma).  Third argument is the index of the handler to use (in list
+   sysdata_meltpragmas).  */
+void melt_handle_melt_pragma (melt_ptr_t optreev, melt_ptr_t listargtreev,
+  long i_handler);
+
+extern void __attribute__((weak)) c_register_pragma_with_expansion_and_data
+(const char *space, const char *name,
+ pragma_handler_2arg handler, void *data);
+
+/* Handle a melt pragma: data contains the index of the pragma handler.  */
+static void
+handle_melt_pragma (cpp_reader *ARG_UNUSED(dummy), void *data)
+{
+  enum cpp_ttype token;
+  /* List containing the pragma arguments .  */
+  tree x;
+  long i_handler = (long) data;
+  MELT_ENTERFRAME (3, NULL);
+#define seqv  meltfram__.mcfr_varptr[0]
+#define treev meltfram__.mcfr_varptr[1]
+#define optreev   meltfram__.mcfr_varptr[2]
+  if (!pragma_lex || !c_register_pragma_with_expansion_and_data)
+fatal_error ("Cannot use pragma symbol at this level \
+   (maybe you use -flto which is incompatible).");
+
+  token = pragma_lex (&x);
+  if (token != CPP_NAME)
+{
+  error ("malformed #pragma melt, ignored");
+  goto end;
+}
+  optreev = meltgc_new_tree ((meltobject_ptr_t) MELT_PREDEF (DISCR_TREE), x);
+  /* If the pragma has the form #pragma MELT name id (...) then optreev is the
+  tree containing "id".  */
+  /* Next element should be a parenthesis opening.  */
+  token = pragma_lex (&x);
+  if (token != CPP_OPEN_PAREN)
+{
+  if (token != CPP_EOF)
+   {
+ error ("malformed #pragma melt, ignored");
+ goto end;
+   }
+  else{ /* We have a pragma of the type '#pragma MELT name instr'.  */
+   melt_handle_melt_pragma ((melt_ptr_t ) optreev, (melt_ptr_t ) NULL,
+i_handler);
+  }
+}
+  else
+{/* Opening parenthesis.  */
+  seqv = meltgc_new_list ((meltobject_ptr_t) MELT_PREDEF (DISCR_LIST));
+  do
+   {
+ token = pragma_lex (&x);
+ if(token != CPP_NAME && token != CPP_STRING && token != CPP_NUMBER)
+   {
+ error ("malformed #pragma melt, ignored");
+ goto end;
+   }
+ /* Convert gcc tree into a boxed tree.  */
+ treev = meltgc_new_tree ((meltobject_ptr_t) MELT_PREDEF (DISCR_TREE),
+  x);
+ /* Put the arg in IDENTIFIER_POINTER (x) in a list.  */
+ meltgc_append_list ((melt_ptr_t) seqv, (melt_ptr_t) treev);
+ token = pragma_lex (&x);
+   } while (

Re: C++ mangling, function name to mangled name (or tree)

2011-07-06 Thread Pierre Vittet

On 06/07/2011 18:25, Kevin André wrote:

On Wed, Jul 6, 2011 at 18:00, Pierre Vittet  wrote:

   

I would like user of the plugin to give in arguments the name of the
functions on which he would like a test to be run. That means that I must
convert the string containing a function name (like "myclass::init") and get
either the mangled name or the tree corresponding to the function. I know
that there might be several results (functions with the same name and
different arguments), a good policy for me would be to recover every
concerned functions (at least for the moment).

I guess what I want to do is possible, because there are already some tools
doing it (like gdb).
 

Are you absolutely sure about gdb? It could be doing it the other way
around, i.e. start from the mangled names in the object file and
demangle all of them. Then it would search for a function name in its
list of demangled names.
Just guessing, though :)


Regards,

Kevin André

   

Hello,

no I am not sure, but I guess it would really have an important cost to 
do it like you said. Would it no be easier to have a field containing 
the 'demangled' names? At least in debug since it has an important space 
complexity.


Thanks!

Pierre Vittet


[PATCH, MELT] new function register_data_handler

2011-07-07 Thread Pierre Vittet
Hi, this patch add a new function allowing to add a pragma handler more 
easily. In the past, we were directly modifying the :sysdata_meltpragmas 
field of initial_system_data.


The pragma handler take a list of new pragma handler that we want to 
add. The reason is that the field :sysdata_meltpragmas is a tuple (fixed 
size, this is a mandatory because we uses index to recognize the handler 
later). Each time we call register_data_handler, we recreate the tuple, 
so we try to give a list of handler to call it not to often.


This function should works with a GCC 4.6 but should be used with care, 
as we can only register a single pragma named "melt" (maybe we could use 
another function specially for 4.6 ?).


Thanks!

Pierre Vittet
2011-07-07  Pierre Vittet  

* melt/warmelt-base.melt (register_pragma_handler ): new function.
Index: gcc/melt/warmelt-base.melt
===
--- gcc/melt/warmelt-base.melt  (revision 175906)
+++ gcc/melt/warmelt-base.melt  (working copy)
@@ -1135,6 +1135,42 @@ registered with $REGISTER_PASS_EXECUTION_HOOK.}#
   }#)
 )))
 
+;;register a new pragma handler.
+(defun register_pragma_handler (lsthandler)
+  :doc #{register a list of new pragma handlers.  As :sysdata_meltpragmas must
+  be a tuple (we use an index to recognize handlers), we have to recreate this
+  tuple each time we call this function.  That why $LSTHANDLER is a list of
+  handlers (class_gcc_pragma) and not a single object.  }#
+  (assert_msg "register_pragma_handler takes a list as argument." 
+(is_list lsthandler))
+  (let ((oldtuple (get_field :sysdata_meltpragmas initial_system_data))
+(:long oldsize 0))
+(if notnull oldtuple)
+  (setq oldsize (multiple_length oldtuple))
+(let ((:long newsize (+i (multiple_length oldtuple)
+  (list_length lsthandler)))
+  (newtuple (make_multiple discr_multiple newsize))
+  (:long i 0))
+;;copy in oldhandlers in the newtuple
+(foreach_in_multiple
+(oldtuple)
+(curhander :long iunused)
+  (multiple_put_nth newtuple i curhander)
+  (setq i (+i i 1))
+)
+;;add new handler from lsthandler
+(foreach_in_list
+(lsthandler)
+(curpair curhandler)
+  (assert_msg "register_pragma_handler must be a list of class_gcc_pragma."
+(is_a curhandler class_gcc_pragma))
+  (multiple_put_nth newtuple i curhandler)
+  (setq i (+i i 1))
+)
+(put_fields initial_system_data :sysdata_meltpragmas newtuple)
+))
+)
+
 
  the descriptions of values which are not ctype related.
 (defclass class_value_descriptor
@@ -2361,6 +2397,7 @@ polyhedron values.}#
  ppstrbuf_mixbigint
  read_file
  register_pass_execution_hook
+ register_pragma_handler
  retrieve_value_descriptor_list
  some_integer_greater_than
  some_integer_multiple


[PATH, MELT] correct makefile, install-default-module-list

2011-07-15 Thread Pierre Vittet

Hello,

To compile the last revision of the MELT branch, I have been obliged to 
do the following change in the Makefile:
	We were trying to install the file gcc/melt-default-modules which 
doesn't exist, we now install melt-default-modules.modlis.
	The loops installing the different /melt-default-modules-*.modlis was 
incorrect, a ';' was missing in the install instruction.




Pierre Vittet
2011-07-15  Pierre Vittet  
* Makefile.in (install-melt-default-modules-list): Fix bad file call.

Index: gcc/Makefile.in
===
--- gcc/Makefile.in (revision 176307)
+++ gcc/Makefile.in (working copy)
@@ -5473,9 +5473,9 @@ install-melt-mk: melt-module.mk
 
 ## install the default modules list
 install-melt-default-modules-list: $(melt_default_modules_list).modlis 
$(wildcard $(melt_default_modules_list)-*.modlis)
-   $(INSTALL_DATA) $(melt_default_modules_list) 
$(DESTDIR)/$(melt_module_dir) 
-   for f in  $(wildcard $(melt_default_modules_list)-*.modlis) ; do \
- $(INSTALL_DATA) $$f $(DESTDIR)/$(melt_module_dir) \
+   $(INSTALL_DATA) $(melt_default_modules_list).modlis 
$(DESTDIR)/$(melt_module_dir) 
+   for f in $(wildcard $(melt_default_modules_list)-*.modlis) ; do \
+ $(INSTALL_DATA) $$f $(DESTDIR)/$(melt_module_dir); \
done
 
  this phony target is given manually to copy the generated


[PATCH, MELT] Add PRE_GENERICIZE callback support in MELT

2011-07-15 Thread Pierre Vittet

Hello,

The following patch add support for PLUGIN_PRE_GENERICIZE callback.

The add_sysdata_pre_genericize patch add a field 
(sysdata_pre_genericize) in initial system data, allowing to register a 
closure to be called on PLUGIN_PRE_GENERICIZE event. This patch must be 
first applied and a make warmelt-upgrade must be run in order to 
regenerate generated melt files.


The add_pre_genericize_hook patch add a function (in melt-runtime.c) to 
be called on PLUGIN_PRE_GENERICIZE, which call the closure 
sysdata_pre_genericize defined by the users.


Thanks

Pierre Vittet
2011-07-15  Pierre Vittet  

* melt-runtime.h (enum FSYDAT*): Add a FSYSDAT_PRE_GENERICIZE field.
* melt/warmelt-first.melt (class_system_data): add a
sysdata_pre_genericize field.


Index: gcc/melt/warmelt-first.melt
===
--- gcc/melt/warmelt-first.melt (revision 176032)
+++ gcc/melt/warmelt-first.melt (working copy)
@@ -441,6 +441,8 @@ don't instanciate this class!}#
   sysdata_stdout   ;raw file for stdout
   sysdata_stderr   ;raw file for stderr
   sysdata_dumpfile ;raw file for dump_file
+  sysdata_pre_genericize   ;closure to be called for 
PLUGIN_PRE_GENERICIZE:
+   ;look at gcc/c-decl.c.
   sysdata_unit_starter ;closure to be called at
;compilation unit start
   sysdata_unit_finisher;closure to be called at
Index: gcc/melt-runtime.h
===
--- gcc/melt-runtime.h  (revision 176032)
+++ gcc/melt-runtime.h  (working copy)
@@ -2324,6 +2324,7 @@ enum
   FSYSDAT_STDOUT,  /* raw boxed file for stdout */
   FSYSDAT_STDERR,  /* raw boxed file for stderr */
   FSYSDAT_DUMPFILE,/* raw boxed file for dump_file */
+  FSYSDAT_PRE_GENERICIZE,  /* closure for PLUGIN_PRE_GENERICIZE */
   FSYSDAT_UNIT_STARTER,/* closure for start of compilation 
unit */
   FSYSDAT_UNIT_FINISHER,/* closure for start of compilation unit */
   FSYSDAT_OPTION_SET,  /* closure to set options */
2011-07-15  Pierre Vittet  

* melt-runtime.c (melt_really_initialize): Register a new Callback to
PLUGIN_PRE_GENERICIZE.
(melt_pre_genericize_callback): New function, use field
sysdata_pre_genericize to transmit the callbacks.
2011-07-15  Pierre Vittet  

  * melt-runtime.c (melt_really_initialize): Register a new 
Callback to
PLUGIN_PRE_GENERICIZE.
  (melt_pre_genericize_callback): New function, use field
  sysdata_pre_genericize to transmit the callbacks.


Re: [PATCH, MELT] Add PRE_GENERICIZE callback support in MELT

2011-07-16 Thread Pierre Vittet

Right, here is the new version of the patch (with the correct files).

I added, a function register_pre_genericize_hook in 
melt/warmelt-base.melt to be called when we want to register a MELT 
function to handle the callback, so we don't manually set 
sysdata_pre_genericize field.


Pierre Vittet

On 15/07/2011 18:41, Romain Geissler wrote:

Le 15 juil. 2011 à 18:17, Pierre Vittet a écrit :

   

Hello,

The following patch add support for PLUGIN_PRE_GENERICIZE callback.

The add_sysdata_pre_genericize patch add a field (sysdata_pre_genericize) in 
initial system data, allowing to register a closure to be called on 
PLUGIN_PRE_GENERICIZE event. This patch must be first applied and a make 
warmelt-upgrade must be run in order to regenerate generated melt files.

The add_pre_genericize_hook patch add a function (in melt-runtime.c) to be 
called on PLUGIN_PRE_GENERICIZE, which call the closure sysdata_pre_genericize 
defined by the users.

Thanks

Pierre Vittet

 

Great !

You forgot to attach the patch for melt-runtime.c (there is only the changelog)

I know your performing some simple static analysis, mostly based on matching 
some c source code patterns (check that there is a if (fopen_result) just after 
a fopen.

Is there a particular reason to do that as a pass (so at the gimple level) 
rather that doing it just after the function has been parsed (eg upon 
PLUGIN_PRE_GENERICIZE) ?

   


2011-07-15  Pierre Vittet  

* melt-runtime.h (enum FSYDAT*): Add a FSYSDAT_PRE_GENERICIZE field.
* melt/warmelt-first.melt (class_system_data): add a
sysdata_pre_genericize field.


Index: gcc/melt/warmelt-first.melt
===
--- gcc/melt/warmelt-first.melt (revision 176032)
+++ gcc/melt/warmelt-first.melt (working copy)
@@ -441,6 +441,8 @@ don't instanciate this class!}#
   sysdata_stdout   ;raw file for stdout
   sysdata_stderr   ;raw file for stderr
   sysdata_dumpfile ;raw file for dump_file
+  sysdata_pre_genericize   ;closure to be called for 
PLUGIN_PRE_GENERICIZE:
+   ;look at gcc/c-decl.c.
   sysdata_unit_starter ;closure to be called at
;compilation unit start
   sysdata_unit_finisher;closure to be called at
Index: gcc/melt-runtime.h
===
--- gcc/melt-runtime.h  (revision 176032)
+++ gcc/melt-runtime.h  (working copy)
@@ -2324,6 +2324,7 @@ enum
   FSYSDAT_STDOUT,  /* raw boxed file for stdout */
   FSYSDAT_STDERR,  /* raw boxed file for stderr */
   FSYSDAT_DUMPFILE,/* raw boxed file for dump_file */
+  FSYSDAT_PRE_GENERICIZE,  /* closure for PLUGIN_PRE_GENERICIZE */
   FSYSDAT_UNIT_STARTER,/* closure for start of compilation 
unit */
   FSYSDAT_UNIT_FINISHER,/* closure for start of compilation unit */
   FSYSDAT_OPTION_SET,  /* closure to set options */
2011-07-15  Pierre Vittet  

* melt-runtime.c (melt_really_initialize): Register a new Callback to
PLUGIN_PRE_GENERICIZE.
(melt_pre_genericize_callback): New function, use field
sysdata_pre_genericize to transmit the callbacks.
* melt/warmelt-base.melt (register_pre_genericize_hook): New function.
Index: gcc/melt-runtime.c
===
--- gcc/melt-runtime.c  (revision 176032)
+++ gcc/melt-runtime.c  (working copy)
@@ -9044,6 +9044,35 @@ melt_pragma_callback (void *gcc_data ATTRIBUTE_UNU
 
 #endif  /*GCC >4.6 for handling pragma support*/
 
+
+/* This function is used when PLUGIN_PRE_GENERICIZE callback is invoked.  It
+   calls the closure registered in field sydata_pre_genericize of
+   initial_system_data.  The first argument is the tree containing the function
+   declaration (as given in file gcc/c-decl.c).  */
+static void
+melt_pre_genericize_callback (void *ptr_fndecl,
+ void *user_data ATTRIBUTE_UNUSED)
+{
+  MELT_ENTERFRAME (2, NULL);
+#define pregenclosv meltfram__.mcfr_varptr[0]
+#define fndeclv meltfram__.mcfr_varptr[1]
+  fndeclv = meltgc_new_tree ((meltobject_ptr_t) MELT_PREDEF (DISCR_TREE),
+((tree) ptr_fndecl));
+  pregenclosv = melt_get_inisysdata (FSYSDAT_PRE_GENERICIZE);
+  if (melt_magic_discr ((melt_ptr_t) pregenclosv) == MELTOBMAG_CLOSURE)
+{
+  MELT_LOCATION_HERE
+   ("melt_pre_genericize befire applying pre_genericize closure");
+  (void) melt_apply ((meltclosure_ptr_t) pregenclosv, (melt_ptr_t) fndeclv,
+"", NULL, "", NULL);
+}
+  MELT_EXITFRAME ();
+#undef fndeclv
+#undef pregenclosv
+}
+
+
+
 /* the plugin callback when starting a compilation unit */
 static void
 melt_startunit_callback(void *gc

[PATCH, MELT, minor] add a primitive read_strv

2011-07-19 Thread Pierre Vittet

Hello,

This minor patch add a primitive to get a list of s-expression from a 
boxed C string of a strbuf.

This is only the MELT part, as the called C code was already written.

I compiled and test it.

Thanks!

Pierre Vittet
2011-07-18  Pierre Vittet  

* melt/warmelt-base.melt (read_strv): New primitive.

Index: gcc/melt/warmelt-base.melt
===
--- gcc/melt/warmelt-base.melt  (revision 176434)
+++ gcc/melt/warmelt-base.melt  (working copy)
@@ -272,6 +272,11 @@ number $NUM opaque location number $LOC.}#
   :doc #{Read from file named by the $FILNAM string balue a list of MELT 
s-expressions.}#
   #{(meltgc_read_file (melt_string_str((melt_ptr_t)($filnam)), (char*)0))}#)
 
+(defprimitive read_strv (strv) :value
+  :doc #{Return the list of sexpr contained in $STRV. $STRV can be a boxed
+  string or a strbuf value.}#
+  #{(meltgc_read_from_val ($strv, NULL))}#
+)
 
 ;; to signal an error in a  source with some additional string value
 (defprimitive error_strv (loc :cstring cmsg :value strv) :void
@@ -2441,6 +2446,7 @@ polyhedron values.}#
  pair_set_head 
  ppstrbuf_mixbigint
  read_file
+ read_strv
  register_pass_execution_hook
  register_pragma_handler
  register_pre_genericize_hook


[PATCH, MELT] correct function meltgc_string_hex_md5sum_file_sequence

2011-07-27 Thread Pierre Vittet

Hello,

this patch correct the function meltgc_string_hex_md5sum_file_sequence, 
it now returns the same than "cat myfile1 myfile2 ... | md5sum".
fread was not correctly used + it looks like you can't mix function 
md5_process_bytes and md5_process_blocks.


Pierre Vittet
Index: gcc/melt-runtime.c
===
--- gcc/melt-runtime.c  (revision 176817)
+++ gcc/melt-runtime.c  (working copy)
@@ -5426,6 +5426,7 @@ meltgc_string_hex_md5sum_file_sequence (melt_ptr_t
   char bufblock[1024]; /* size should be multiple of 64 for md5_process_block 
*/
   FILE *fil = NULL;
   int nbtup = 0;
+  int cnt = 0;
   struct md5_ctx ctx = {};
   MELT_ENTERFRAME(3, NULL);
 #define resv   meltfram__.mcfr_varptr[0]
@@ -5456,16 +5457,14 @@ meltgc_string_hex_md5sum_file_sequence (melt_ptr_t
   while (!feof (fil))
{
  memset (bufblock, 0, sizeof (bufblock));
- if (fread (bufblock, sizeof(bufblock), 1, fil)==1)
+ cnt = fread (bufblock, 1, sizeof(bufblock), fil);
+ if (cnt ==sizeof(bufblock))
{
  /* an entire block has been read. */
- md5_process_block (bufblock, sizeof(bufblock), &ctx);
+ md5_process_bytes (bufblock, sizeof(bufblock), &ctx);
}
  else
{
- int cnt = fread (bufblock, 1, sizeof(bufblock), fil);
- if (cnt <= 0) 
-   break;
  md5_process_bytes (bufblock, (size_t) cnt, &ctx);
    }
}
2011-07-27  Pierre Vittet  

* melt-runtime.c (meltgc_string_hex_md5sum_file_sequence):
 Correct fread use + only use md5_process_bytes




[PATCH, MELT] fix useless forcing of GCC garbage collector

2011-05-09 Thread Pierre Vittet

This patch is for the MELT branch.

My GCC contributor number is 634276.

After speaking with Basile Starynkevitch, we saw that there might be a 
useless forcing of the garbage collector in melt-runtime.c . I tested 
with the patch, and I haven't seen any problem (I could compile GCC, 
using a MELT plugin with the patched version).
I have also measured a small time improvement while compiling the file 
gcc.c (which is more that 8000 lines):


Whithout the modification:
usersys
1.563   0.145s

With  the modification:
usersys
1.144  0.106s


Changelog:

2011-05-09  Pierre Vittet  

 	* melt-runtime.c: Remove variable forcing the garbage collector while 
it was not needed.


Thanks

Pierre Vittet
Index: melt-runtime.c
===
--- melt-runtime.c  (revision 173571)
+++ melt-runtime.c  (working copy)
@@ -1159,16 +1159,13 @@
melt_nb_garbcoll, melt_startalz, melt_endalz);
   if (needfull)
 {
-  bool wasforced = ggc_force_collect;
   melt_nb_full_garbcoll++;
   debugeprintf ("melt_garbcoll #%ld fullgarbcoll #%ld",
melt_nb_garbcoll, melt_nb_full_garbcoll);
   /* force major collection, with our callback */
-  ggc_force_collect = true;
-  debugeprintf ("melt_garbcoll forcing fullgarbcoll #%ld", 
melt_nb_full_garbcoll);
+  debugeprintf ("melt_garbcoll calling gcc_collect #%ld", 
melt_nb_full_garbcoll);
   ggc_collect ();
-  ggc_force_collect = wasforced;
-  debugeprintf ("melt_garbcoll forced fullgarbcoll #%ld", 
melt_nb_full_garbcoll);
+  debugeprintf ("melt_garbcoll after fullgarbcoll #%ld", 
melt_nb_full_garbcoll);
   /* Delete the unmarked specials.  */
   prevspecptr = &melt_oldspeclist;
   for (specp = melt_oldspeclist; specp; specp = nextspecp)


Re: [PATCH, MELT] fix useless forcing of GCC garbage collector

2011-05-09 Thread Pierre Vittet

Thanks you for the correction, I will take care next time.

Pierre
On 09/05/2011 19:03, Basile Starynkevitch wrote:

On Mon, 09 May 2011 14:15:30 +0200
Pierre Vittet  wrote:

   

This patch is for the MELT branch.
 

The diff file was slightly wrong (diff run under gcc/). Pierre, you
should run svn diff -x -p at the top source directory to get a patch
file.

I applied the patch. The gcc/ChangeLog.MELT proposed by Pierre was
wrong, I wrote:

2011-05-09  Pierre Vittet

* melt-runtime.c (melt_garbcoll): Don't force collection by
gcc_collect.

Committed revision 173576.


Folks, what is the procedure to get Pierre an svn+ssh write access to
GCC svn server (mostly for the MELT branch, and write after approval
for the rest). As far as I understood, all legal stuff has been
completed.

   

My GCC contributor number is 634276.
 

This is the copyright assignment legal document reference for Pierre Vittet.

What does he (or me) have to do to get svn+ssh://gcc.melt.org/ write access?

Cheers.
   




Re: [PATCH] comment precising need to use free_dominance_info

2011-05-17 Thread Pierre Vittet
So maybe this patch adding a comment on calculate_dominance_info is more 
adapted.


ChangeLog:
2011-05-17  Pierre Vittet

* dominance.c (calculate_dominance_info): Add comment
   precising when to free with free_dominance_info

contributor number: 634276

Index: gcc/dominance.c
===
--- gcc/dominance.c (revision 173830)
+++ gcc/dominance.c (working copy)
@@ -628,8 +628,15 @@ compute_dom_fast_query (enum cdi_direction dir)
 }
 
 /* The main entry point into this module.  DIR is set depending on whether
-   we want to compute dominators or postdominators.  */
+   we want to compute dominators or postdominators.  
 
+   We try to keep dominance info alive as long as possible (to avoid
+   recomputing it often). It has to be freed with free_dominance_info when CFG
+   transformation makes it invalide. 
+   
+   post_dominance info is less often used, and should be freed after each use.
+*/
+
 void
 calculate_dominance_info (enum cdi_direction dir)
 {


[PATCH, MELT] correcting path error in the Makefile.in

2011-05-17 Thread Pierre Vittet
This patch correct a bug in the current revision of MELT, which was 
preventing MELT to run correctly.


This was a path problem in gcc/Makefile.in (melt-modules/ and 
melt-modules.mk) were not found.


My contributor number is 634276.

changelog :


2011-05-17  Pierre Vittet  

* Makefile.in : Correct path errors for melt_module_dir and for
install-melt-mk target




Index: gcc/Makefile.in
===
--- gcc/Makefile.in (revision 173832)
+++ gcc/Makefile.in (working copy)
@@ -5352,7 +5352,7 @@ melt_default_modules_list=melt-default-modules
 melt_source_dir=$(libexecsubdir)/melt-source/
 
 ## this is the installation directory of melt dynamic modules (*.so)
-melt_module_dir=$(libexecsubdir)/melt-module/
+melt_module_dir=$(libexecsubdir)/melt-modules/
 
 ## this is the installed path of the MELT module makefile
 melt_installed_module_makefile=$(libexecsubdir)/melt-module.mk
@@ -5416,8 +5416,8 @@ install-melt-modules: melt-modules melt-all-module
 
 ## install the makefile for MELT modules
 install-melt-mk: melt-module.mk
-   $(mkinstalldirs) $(DESTDIR)$(plugin_includedir)
-   $(INSTALL_DATA) $< $(DESTDIR)/$(plugin_includedir)/
+   $(mkinstalldirs) $(DESTDIR)$(libexecsubdir)
+   $(INSTALL_DATA) $< $(DESTDIR)/$(libexecsubdir)/
 
 ## install the default modules list
 install-melt-default-modules-list: $(melt_default_modules_list).modlis 


[PATCH, MELT] add dominance functions

2011-05-18 Thread Pierre Vittet

Hello,

I have written a patch to allow the use of the GCC dominance functions 
into MELT.


This is made in order to abstract the use of calculate_dominance_info 
and free_dominance_info:
If the user use one of the MELT dominance related functions, it 
will only call calculate_dominance_info and register a call to 
free_dominance_info (at the end of the MELT pass) if the dominance info 
were not previously calculated.


The idea is :
- dominance info were already calculated (in a previous pass):
-we can use dominance info and at the end of pass, no call is 
made to free_dominance_info (as we expect a next pass to use dominance 
info and to free only when necessary).


-dominance info were not already calculated:
-We first compute dominance info, use them during the pass and 
free them at the end of the plugin pass (as we don't expect a next pass 
to use it).


Unsafe functions are only for internal use and so are not exported.

I have compiled GCC MELT with the patch and successfully test the functions.


Changelog:
2011-05-17  Pierre Vittet 

* melt/xtramelt-ana-base.melt
(is_dominance_info_available, is_post_dominance_info_available,
calculate_dominance_info_unsafe,
calculate_post_dominance_info_unsafe,
free_dominance_info, free_post_dominance_info,
calculate_dominance_info,
calculate_post_dominance_info, debug_dominance_info,
debug_post_dominance_info, get_immediate_dominator_unsafe,
get_immediate_dominator, get_immediate_post_dominator_unsafe,
get_immediate_post_dominator, dominated_by_other_unsafe,
dominated_by_other, post_dominated_by_other_unsafe,
post_dominated_by_other, foreach_dominated_unsafe,
dominated_by_bb_iterator): Add primitives, functions, iterators for
using dominance info.


Index: gcc/melt/xtramelt-ana-base.melt
===
--- gcc/melt/xtramelt-ana-base.melt (revision 173832)
+++ gcc/melt/xtramelt-ana-base.melt (working copy)
@@ -1910,6 +1910,242 @@
 (defprimitive basicblock_nth_succ_edge  (:basic_block bb :long ix) :edge
   #{(($bb && $ix>=0 && $ixsuccs))?EDGE_SUCC($bb,$ix):NULL)}#)
 
+;Primitives concerning dominance in basic_blocks
+;those functions mainly come from gcc/dominance.c
+
+(defprimitive is_dominance_info_available () :long
+  :doc #{Check if dominance info are already calculated.
+User normally doesn't have to call this primitive, as MELT functions
+check if there is a need to use this.
+}#
+  #{dom_info_available_p(CDI_DOMINATORS)}#
+)
+
+(defprimitive is_post_dominance_info_available () :long
+  :doc #{Check if post dominance info are already calculated.
+User normally doesn't have to call this primitive, as MELT functions
+check if there is a need to use this.
+   }#
+  #{dom_info_available_p(CDI_POST_DOMINATORS)}#
+)
+
+(defprimitive calculate_dominance_info_unsafe() :void
+  :doc #{This primitive is internaly called, user doesn't need it.
+Build the struct containing dominance info.
+This struct is necessary to use others dominance related function.
+This function is unsafe because it does not register any future call to
+free_dominance_info. 
+}#
+  #{calculate_dominance_info(CDI_DOMINATORS)}#
+)
+
+(defprimitive calculate_post_dominance_info_unsafe () :void
+  :doc #{This primitive is internaly called, user doesn't need it.
+Build the struct containing post dominance info.
+This struct is necessary to use other dominance related function.
+This function is unsafe because it does not register any future call to
+free_dominance_info. 
+}#
+  #{calculate_dominance_info(CDI_POST_DOMINATORS)}#
+)
+
+(defprimitive free_dominance_info () :void
+  :doc #{This primitive is internaly called, user doesn't need it.
+  Clear dominance info if they have been allocated.
+  }#
+  #{free_dominance_info(CDI_DOMINATORS)}#
+)
+
+(defprimitive free_post_dominance_info () :void
+  :doc #{This primitive is internaly called, user doesn't need it.
+  Clear post dominance info if they have been allocated.
+  }#
+  #{free_dominance_info(CDI_POST_DOMINATORS)}#
+)
+
+(defun calculate_dominance_info()
+  :doc #{This primitive is internaly called, user doesn't need it.
+  Build the struct containing dominance info.
+  This struct is necessary to use other dominance related info.
+  It place a call to free dominance info when pass is finished if it is
+  necessary.
+  }#
+  (if (is_dominance_info_available)
+() ;; do nothing
+(progn ;; else calculate dom and ask to free them at end of pass
+  (calculate_dominance_info_unsafe)
+  (at_end_melt_pass_first free_dominance_info)
+))
+)
+
+(defun calculate_post_dominance_info () 
+  :doc #{This primitive is internaly called, user doesn't need it
+  Build the struct containing post dominance info.
+  This struct is necessary to use other p

Re: [PATCH, MELT] add dominance functions

2011-05-20 Thread Pierre Vittet

I have corrected my patch with your remarks.

Especially about the debug functions, it takes the debug melt flag into 
account. Moreover, I have allowed the user to give a message when 
calling this function, as usual in MELT debug functions. Giving this 
message was a bit difficult (This is the only argument of the function, 
so this must be a MELT value, and that uneasy to convert the value into 
:cstring).


I have used debugeprintf macro into a code_chunk to give the MELT file + 
line numbers, followed by a outstr_err, which displays the user message. 
I think the only disavantage is that it puts an end of lines between the 
two informations. If you think there is a best way to do this, I am ok 
to try it.


The new changelog:

2011-05-20  Pierre Vittet 

* melt/xtramelt-ana-base.melt
(is_dominance_info_available, is_post_dominance_info_available,
calculate_dominance_info_unsafe, calculate_post_dominance_info_unsafe,
free_dominance_info, free_post_dominance_info, 
calculate_dominance_info,

calculate_post_dominance_info, debug_dominance_info,
debug_post_dominance_info, get_immediate_dominator_unsafe,
get_immediate_dominator, get_immediate_post_dominator_unsafe,
get_immediate_post_dominator, dominated_by_other_unsafe,
dominated_by_other, post_dominated_by_other_unsafe,
post_dominated_by_other, foreach_dominated_unsafe,
dominated_by_bb_iterator): Add primitives, functions, iterators for 
using

dominance info.


On 19/05/2011 07:32, Basile Starynkevitch wrote:

On Wed, 18 May 2011 21:04:39 +0200
Pierre Vittet  wrote:

   

Hello,

I have written a patch to allow the use of the GCC dominance functions
into MELT.
 

[...]

   

Changelog:
2011-05-17  Pierre Vittet

  * melt/xtramelt-ana-base.melt
  (is_dominance_info_available, is_post_dominance_info_available,
  calculate_dominance_info_unsafe,
  calculate_post_dominance_info_unsafe,
  free_dominance_info, free_post_dominance_info,
  calculate_dominance_info,
  calculate_post_dominance_info, debug_dominance_info,
  debug_post_dominance_info, get_immediate_dominator_unsafe,
  get_immediate_dominator, get_immediate_post_dominator_unsafe,
  get_immediate_post_dominator, dominated_by_other_unsafe,
  dominated_by_other, post_dominated_by_other_unsafe,
  post_dominated_by_other, foreach_dominated_unsafe,
  dominated_by_bb_iterator): Add primitives, functions, iterators for
  using dominance info.


 

Thanks for the patch. Some minor tweaks:

First, put a space between formal arguments list&  function name.
So

+(defprimitive calculate_dominance_info_unsafe() :void
should be
+(defprimitive calculate_dominance_info_unsafe () :void

Then, please put the defined name on the same line that defprimitive or
defun or def... When consecutive MELT formals have the same ctype, you
don't need to repeat it

So

+(defprimitive
+  dominated_by_other_unsafe(:basic_block bbA :basic_block bbB) :long

should be

+(defprimitive dominated_by_other_unsafe (:basic_block bbA bbB) :long

In :doc strings, document when something is a boxed value
(distinction between values&  stuffs is crucial), so write instead
[I added the boxed word, it is important]

+(defun get_immediate_dominator (bb)
+ :doc#{Return the next immediate dominator of the boxed basic_block
$BB as a MELT +value.}#

At last, all debug* operations should only output debug to stderr only
when flag_melt_debug is set and give the MELT source position (because
we don't want any debug printing in the usual case when -fmelt-debug is
not given to our cc1) Look at debugloop in xtramelt-ana-base.melt for
an example (notice that debugeprintfnonl is a C macro printing the MELT
source position.


So please resubmit a slightly improved patch.

Regards.
   


Index: gcc/melt/xtramelt-ana-base.melt
===
--- gcc/melt/xtramelt-ana-base.melt (revision 173936)
+++ gcc/melt/xtramelt-ana-base.melt (working copy)
@@ -1871,7 +1871,6 @@
 (defprimitive make_basicblock (discr :basic_block bb) :value
  
#{/*make_basicblock*/(meltgc_new_basicblock((meltobject_ptr_t)($discr),($bb)))}#
 )
 
-
 (defprimitive basicblock_content (v) :basic_block
  #{(melt_basicblock_content((melt_ptr_t)($v)))}# )
 
@@ -1910,6 +1909,243 @@
 (defprimitive basicblock_nth_succ_edge  (:basic_block bb :long ix) :edge
   #{(($bb && $ix>=0 && $ixsuccs))?EDGE_SUCC($bb,$ix):NULL)}#)
 
+;; Primitives concerning dominance in basic_blocks
+;; those functions mainly come from gcc/dominance.c
+
+(defprimitive is_dominance_info_available () :long
+  :doc #{Check if dominance info are already calculated.
+User normally doesn't have to call this primitive, as MELT functions
+check if there is a need to use this.}#
+  #{dom_info_available_p(CDI_DOMINATORS)}#
+)
+
+(defprimitive is_post_dominance_info_available () :long
+  :doc #{Check if 

[Patch] get an order number on -fdump-tree-all

2011-03-23 Thread Pierre Vittet

Hello,

When we use fdump-tree-all, we get the dump file, however there is no 
way to know in which order the pass was executed.
We can use gdb with a breakpoint at the good position (something like 
execute_one_pass), however this solution is not satisfiying for plugin 
devellopers for exemple.
There is a number in the name of the dumpped file but from what I know 
it is a static number related to the pass but it has nothing to do with 
the order in which it is executed.


I would enjoy to have a number, giving the pass position, something like :

1.cfile.c.XXXt.pass

I have make a small change in tree-dump.c in order to have this working 
with -fdump-tree-all (patch file in attachment)


The drawback is that, as the pass is called for each function, we get a 
different file for each function, while it was written in the same file 
previously.



I am also surprized to see that the function print_current_pass is only 
called on a fail and that debug_pass doesn't appear to be called at all. 
Maybe in DEBUG, or at least with an f*_dump_all, we could print the 
order of the pass.


thanks

Pierre Vittet
Index: gcc/tree-dump.c
===
--- gcc/tree-dump.c (revision 171340)
+++ gcc/tree-dump.c (working copy)
@@ -925,21 +925,35 @@
   struct dump_file_info *dfi;
   FILE *stream;
 
+  /*allow to know how many pass have already been explored*/
+  static int nb_explored_pass = 0;
+  /*add to the name a position at which the pass is explored*/
+  char * name_with_pass_pos;
+  int name_with_pass_pos_size;
+ 
   if (phase == TDI_none || !dump_enabled_p (phase))
 return NULL;
 
   name = get_dump_file_name (phase);
+  name_with_pass_pos_size=sizeof(char)*strlen(name)+ 
sizeof(nb_explored_pass)+1;
+  name_with_pass_pos= (char*) xmalloc(name_with_pass_pos_size);
+
+  snprintf (name_with_pass_pos, name_with_pass_pos_size, "%d.%s", 
nb_explored_pass, name);
   dfi = get_dump_file_info (phase);
-  stream = fopen (name, dfi->state < 0 ? "w" : "a");
+  stream = fopen (name_with_pass_pos, dfi->state < 0 ? "w" : "a");
+
   if (!stream)
 error ("could not open dump file %qs: %m", name);
   else
 dfi->state = 1;
   free (name);
+  free (name_with_pass_pos);
 
   if (flag_ptr)
 *flag_ptr = dfi->flags;
 
+  nb_explored_pass++;
+
   return stream;
 }
 


[PATCH] build: Check for cargo when building rust language

2024-04-08 Thread pierre-emmanuel . patry
From: Pierre-Emmanuel Patry 

Hello,

The rust frontend requires cargo to build some of it's components,
it's presence was not checked during configuration.

Best regards,
Pierre-Emmanuel

--

Prevent rust language from building when cargo is
missing.

config/ChangeLog:

* acx.m4: Add a macro to check for rust
components.

ChangeLog:

* configure: Regenerate.
* configure.ac: Emit an error message when cargo
is missing.

Signed-off-by: Pierre-Emmanuel Patry 
---
 config/acx.m4 |  11 +
 configure | 117 ++
 configure.ac  |  18 
 3 files changed, 146 insertions(+)

diff --git a/config/acx.m4 b/config/acx.m4
index 7efe98aaf96..3c5fe67342e 100644
--- a/config/acx.m4
+++ b/config/acx.m4
@@ -424,6 +424,17 @@ else
 fi
 ])
 
+# Test for Rust
+# We require cargo and rustc for some parts of the rust compiler.
+AC_DEFUN([ACX_PROG_CARGO],
+[AC_REQUIRE([AC_CHECK_TOOL_PREFIX])
+AC_CHECK_TOOL(CARGO, cargo, no)
+if test "x$CARGO" != xno; then
+  have_cargo=yes
+else
+  have_cargo=no
+fi])
+
 # Test for D.
 AC_DEFUN([ACX_PROG_GDC],
 [AC_REQUIRE([AC_CHECK_TOOL_PREFIX])
diff --git a/configure b/configure
index 874966fb9f0..46e66e20197 100755
--- a/configure
+++ b/configure
@@ -714,6 +714,7 @@ PGO_BUILD_GEN_CFLAGS
 HAVE_CXX11_FOR_BUILD
 HAVE_CXX11
 do_compare
+CARGO
 GDC
 GNATMAKE
 GNATBIND
@@ -5786,6 +5787,104 @@ else
   have_gdc=no
 fi
 
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}cargo", so it can be a program 
name with args.
+set dummy ${ac_tool_prefix}cargo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CARGO+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CARGO"; then
+  ac_cv_prog_CARGO="$CARGO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ac_cv_prog_CARGO="${ac_tool_prefix}cargo"
+$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" 
>&5
+break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CARGO=$ac_cv_prog_CARGO
+if test -n "$CARGO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CARGO" >&5
+$as_echo "$CARGO" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CARGO"; then
+  ac_ct_CARGO=$CARGO
+  # Extract the first word of "cargo", so it can be a program name with args.
+set dummy cargo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CARGO+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CARGO"; then
+  ac_cv_prog_ac_ct_CARGO="$ac_ct_CARGO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ac_cv_prog_ac_ct_CARGO="cargo"
+$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" 
>&5
+break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CARGO=$ac_cv_prog_ac_ct_CARGO
+if test -n "$ac_ct_CARGO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CARGO" >&5
+$as_echo "$ac_ct_CARGO" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CARGO" = x; then
+CARGO="no"
+  else
+case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not 
prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" 
>&2;}
+ac_tool_warned=yes ;;
+esac
+CARGO=$ac_ct_CARGO
+  fi
+else
+  CARGO="$ac_cv_prog_CARGO"
+fi
+
+if test "x$CARGO" != xno; then
+  have_cargo=yes
+else
+  have_cargo=no
+fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to compare bootstrapped 
objects" >&5
 $as_echo_n "checking how to compare bootstrapped objects... " >&

Re: libgrust: 'AM_ENABLE_MULTILIB' only for target builds [PR113056]

2024-01-04 Thread Pierre-Emmanuel Patry

Hello Thomas,

On 12/18/23 17:58, Thomas Schwinge wrote:


--- a/libgrust/configure.ac
+++ b/libgrust/configure.ac



-# AM_ENABLE_MULTILIB(, ..)
+AM_ENABLE_MULTILIB(, ..)


Such a change was applied eventually, and is necessary for target builds
-- but potentially harmful for host builds.  OK to push the attached
"libgrust: 'AM_ENABLE_MULTILIB' only for target builds [PR113056]"?


These changes make sense, I'm fine with those being pushed.

Regards,


--
Patry Pierre-Emmanuel
Compiler Engineer - Embecosm


OpenPGP_0xD006124B2A7AEA23.asc
Description: OpenPGP public key


OpenPGP_signature.asc
Description: OpenPGP digital signature


Re: build: Don't check for host-prefixed 'cargo' program

2024-04-15 Thread Pierre-Emmanuel Patry

Hi,

On 4/15/24 1:50 PM, Thomas Schwinge wrote:

I now wonder: instead of 'AC_CHECK_TOOL', shouldn't this use
'AC_CHECK_PROG'?  (We always want plain 'cargo', not host-prefixed
'aarch64-linux-gnu-cargo' etc., right?)  I'll look into changing this.


This is a mistake, we should use 'AC_CHECK_PROG'.


OK to push "build: Don't check for host-prefixed 'cargo' program", see
attached?


Yes, attached patch looks good, thank you!

Regards,

--
Patry Pierre-Emmanuel
Compiler Engineer - Embecosm



Re: build: Use of cargo not yet supported here in Canadian cross configurations

2024-04-15 Thread Pierre-Emmanuel Patry

Hello,

On 4/15/24 2:44 PM, Thomas Schwinge wrote:

On top of that, OK to push the attached
"build: Use of cargo not yet supported here in Canadian cross configurations"?


This additional patch looks good. I wonder whether we should enable 
canadian cross in the future with cargo or simply wait for gcc to be 
able to compile those components entirely.


Regards,

--
Patry Pierre-Emmanuel
Compiler Engineer - Embecosm



OpenPGP_0xD006124B2A7AEA23.asc
Description: OpenPGP public key


OpenPGP_signature.asc
Description: OpenPGP digital signature


Re: [PATCH, Ada] RISC-V: Initial riscv linux Ada port.

2018-07-12 Thread Pierre-Marie de Rodat

On 07/08/2018 12:35 AM, Eric Botcazou wrote:

I haven't tried looking at the failures yet, and might not spend much
more time on this.  Two of them are debug related, and debug support
is a work in progress.  I need to finish the native riscv64-linux
support before we can do anything useful there, and I'd like to get
back to working on that as soon as possible.


No clue about debug11.adb, maybe Pierre-Marie could shed some light on it.


I don’t have much more to say than debug11.adb’s comment ;-)


This testcase checks that in the DWARF description of the variant type
below, the C discriminant is properly described as unsigned, hence the 0x5a
('Z') and 0x80 (128) values in the DW_AT_discr_list attribute. If it was
described as signed, we would have instead 90 and -128.


I don’t have an Ada RISC-V compiler (nor binutils) to check right now: 
would it be possible to send the corresponding debug11.s and debug11.o? 
Hopefully we just have to enhance the regexps.


--
Pierre-Marie de Rodat


Re: [PATCH, Ada] RISC-V: Initial riscv linux Ada port.

2018-07-12 Thread Pierre-Marie de Rodat

On 07/13/2018 01:57 AM, Jim Wilson wrote:

I poked at this a little and noticed a difference between the x86_64
support and the RISC-V support.  The RISC-V C language port has char
as unsigned by default.  The x86_64 port has char signed by default.
If I add a -fsigned-char option, then the testcase works as expected
for RISC-V.  Curiously, the Ada compiler accepts -fsigned-char but not
-funsigned-char.  I tried hacking in a -funsigned-char flag, but when
I use it with the x86_64 port the result is still correct.  Maybe my
quick hack wasn't quite right.  Anyways, the default signedness of
char has something to do with the problem.


Ah, interesting! Last year, we installed specific code in the Ada front 
end and the DWARF back end to handle discrepancies between the 
INTEGER_TYPE signedness and the signedness to appear in debug info 
(https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/dwarf2out.c;h=c2422e29658b6a101034318deed224271e6f1ca7;hb=HEAD#l24561), 
but ironically here, it seems that we don’t handle properly when 
everything is unsigned.


I think the current testcase should work on RISC-V even without 
-fsigned-char: Character’s debug type should be unsigned in all cases. 
Maybe for some reason we don’t create the correct debug type in the Ada 
front end… Do you think I can reproduce this with a x86_64-linux 
compiler targetting something like riscv-elf? I don’t have access to a 
RISC-V board on which to build GCC.


--
Pierre-Marie de Rodat


[Ada] Adjust growth factor from 1/32 to 1/2 for Unbounded_String

2018-07-16 Thread Pierre-Marie de Rodat
This will reduce significantly the number of allocations done when
doing consecutive append operations.

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

2018-07-16  Nicolas Roche  

gcc/ada/

* libgnat/a-strunb.adb, libgnat/a-strunb__shared.adb: Adjust growth
factor from 1/32 to 1/2 for Unbounded_String.--- gcc/ada/libgnat/a-strunb.adb
+++ gcc/ada/libgnat/a-strunb.adb
@@ -763,13 +763,13 @@ package body Ada.Strings.Unbounded is
  (Source : in out Unbounded_String;
   Chunk_Size : Natural)
is
-  Growth_Factor : constant := 32;
+  Growth_Factor : constant := 2;
   --  The growth factor controls how much extra space is allocated when
   --  we have to increase the size of an allocated unbounded string. By
   --  allocating extra space, we avoid the need to reallocate on every
   --  append, particularly important when a string is built up by repeated
   --  append operations of small pieces. This is expressed as a factor so
-  --  32 means add 1/32 of the length of the string as growth space.
+  --  2 means add 1/2 of the length of the string as growth space.
 
   Min_Mul_Alloc : constant := Standard'Maximum_Alignment;
   --  Allocation will be done by a multiple of Min_Mul_Alloc This causes

--- gcc/ada/libgnat/a-strunb__shared.adb
+++ gcc/ada/libgnat/a-strunb__shared.adb
@@ -36,13 +36,13 @@ package body Ada.Strings.Unbounded is
 
use Ada.Strings.Maps;
 
-   Growth_Factor : constant := 32;
+   Growth_Factor : constant := 2;
--  The growth factor controls how much extra space is allocated when
--  we have to increase the size of an allocated unbounded string. By
--  allocating extra space, we avoid the need to reallocate on every
--  append, particularly important when a string is built up by repeated
--  append operations of small pieces. This is expressed as a factor so
-   --  32 means add 1/32 of the length of the string as growth space.
+   --  2 means add 1/2 of the length of the string as growth space.
 
Min_Mul_Alloc : constant := Standard'Maximum_Alignment;
--  Allocation will be done by a multiple of Min_Mul_Alloc. This causes



[Ada] Illegal deferred constant causes stack overflow

2018-07-16 Thread Pierre-Marie de Rodat
This patch prevents the compiler from entering infinite recursion when
processing an illegal deferred constant.


-- Source --


--  types.ads

package Types is
   type Enum is (One, Two);
end Types;

--  types2.ads

with Types;

package Types2 is
   type Enum is private;
   One : constant Enum;
   Two : constant Enum;

private
   type Enum is new Types.Enum;
   One : constant Enum := One;
   Two : constant Enum := Two;

end Types2;


-- Compilation and output --


$ gcc -c types2.ads
types2.ads:10:04: full constant declaration appears too late
types2.ads:11:04: full constant declaration appears too late

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

2018-07-16  Hristian Kirtchev  

gcc/ada/

* sem_eval.adb (Compile_Time_Known_Value): Add a guard which prevents
the compiler from entering infinite recursion when trying to determine
whether a deferred constant has a compile time known value, and the
initialization expression of the constant is a reference to the
constant itself.--- gcc/ada/sem_eval.adb
+++ gcc/ada/sem_eval.adb
@@ -1705,29 +1705,46 @@ package body Sem_Eval is
   end if;
 
   --  If we have an entity name, then see if it is the name of a constant
-  --  and if so, test the corresponding constant value, or the name of
-  --  an enumeration literal, which is always a constant.
+  --  and if so, test the corresponding constant value, or the name of an
+  --  enumeration literal, which is always a constant.
 
   if Present (Etype (Op)) and then Is_Entity_Name (Op) then
  declare
-E : constant Entity_Id := Entity (Op);
-V : Node_Id;
+Ent : constant Entity_Id := Entity (Op);
+Val : Node_Id;
 
  begin
---  Never known at compile time if it is a packed array value.
---  We might want to try to evaluate these at compile time one
---  day, but we do not make that attempt now.
+--  Never known at compile time if it is a packed array value. We
+--  might want to try to evaluate these at compile time one day,
+--  but we do not make that attempt now.
 
 if Is_Packed_Array_Impl_Type (Etype (Op)) then
return False;
-end if;
 
-if Ekind (E) = E_Enumeration_Literal then
+elsif Ekind (Ent) = E_Enumeration_Literal then
return True;
 
-elsif Ekind (E) = E_Constant then
-   V := Constant_Value (E);
-   return Present (V) and then Compile_Time_Known_Value (V);
+elsif Ekind (Ent) = E_Constant then
+   Val := Constant_Value (Ent);
+
+   if Present (Val) then
+
+  --  Guard against an illegal deferred constant whose full
+  --  view is initialized with a reference to itself. Treat
+  --  this case as value not known at compile time.
+
+  if Is_Entity_Name (Val) and then Entity (Val) = Ent then
+ return False;
+  else
+ return Compile_Time_Known_Value (Val);
+  end if;
+
+   --  Otherwise the constant does not have a compile time known
+   --  value.
+
+   else
+  return False;
+   end if;
 end if;
  end;
 



[Ada] Violation of No_Standard_Allocators_After_Elaboration not detected

2018-07-16 Thread Pierre-Marie de Rodat
The compiler fails to generate a call to detect allocators executed after
elaboration in cases where the allocator is associated with Global_Pool_Object.
The fix is to test for this associated storage pool as part of the condition
for generating a call to System.Elaboration_Allocators.Check_Standard_Alloctor.
Also, the exception Storage_Error is now generated instead of Program_Error
for such a run-time violation, as required by the Ada RM in D.7.

The following test must compile and execute quietly:

-- Put the pragma in gnat.adc:
pragma Restrictions (No_Standard_Allocators_After_Elaboration);

package Pkg_With_Allocators is

   type Priv is private;

   procedure Allocate
 (Use_Global_Allocator : Boolean;
  During_Elaboration   : Boolean);

private

   type Rec is record
  Int : Integer;
   end record;

   type Priv is access Rec;

end Pkg_With_Allocators;

package body Pkg_With_Allocators is

   Ptr : Priv;

   procedure Allocate
 (Use_Global_Allocator : Boolean;
  During_Elaboration   : Boolean)
   is
  type Local_Acc is access Rec;

  Local_Ptr : Local_Acc;

   begin
  if Use_Global_Allocator then
 Ptr := new Rec;  -- Raise Storage_Error if after elaboration
 Ptr.Int := 1;
  else
 Local_Ptr := new Rec;  -- Raise Storage_Error if after elaboration
 Local_Ptr.Int := 1;
  end if;

  if not During_Elaboration then
 raise Program_Error;  -- No earlier exception: FAIL
  end if;

   exception
  when Storage_Error =>
 if During_Elaboration then
raise Program_Error;  -- No exception expected: FAIL
 else
null; -- Expected Storage_Error: PASS
 end if;
  when others =>
 raise Program_Error;  -- Unexpected exception: FAIL
   end Allocate;

begin
   Allocate (Use_Global_Allocator => True, During_Elaboration => True);

   Allocate (Use_Global_Allocator => False, During_Elaboration => True);
end Pkg_With_Allocators;

with Pkg_With_Allocators;

procedure Alloc_Restriction_Main is
begin
   Pkg_With_Allocators.Allocate
 (Use_Global_Allocator => True,
  During_Elaboration   => False);

   Pkg_With_Allocators.Allocate
 (Use_Global_Allocator => False,
  During_Elaboration   => False);
end Alloc_Restriction_Main;

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

2018-07-16  Gary Dismukes  

gcc/ada/

* exp_ch4.adb (Expand_N_Allocator): Test for Storage_Pool being RTE in
addition to the existing test for no Storage_Pool as a condition
enabling generation of the call to Check_Standard_Allocator when the
restriction No_Standard_Allocators_After_Elaboration is active.
* libgnat/s-elaall.ads (Check_Standard_Allocator): Correct comment to
say that Storage_Error will be raised (rather than Program_Error).
* libgnat/s-elaall.adb (Check_Standard_Allocator): Raise Storage_Error
rather than Program_Error when Elaboration_In_Progress is False.--- gcc/ada/exp_ch4.adb
+++ gcc/ada/exp_ch4.adb
@@ -4561,12 +4561,14 @@ package body Exp_Ch4 is
  end if;
   end if;
 
-  --  If no storage pool has been specified and we have the restriction
+  --  If no storage pool has been specified, or the storage pool
+  --  is System.Pool_Global.Global_Pool_Object, and the restriction
   --  No_Standard_Allocators_After_Elaboration is present, then generate
   --  a call to Elaboration_Allocators.Check_Standard_Allocator.
 
   if Nkind (N) = N_Allocator
-and then No (Storage_Pool (N))
+and then (No (Storage_Pool (N))
+   or else Is_RTE (Storage_Pool (N), RE_Global_Pool_Object))
 and then Restriction_Active (No_Standard_Allocators_After_Elaboration)
   then
  Insert_Action (N,

--- gcc/ada/libgnat/s-elaall.adb
+++ gcc/ada/libgnat/s-elaall.adb
@@ -45,7 +45,7 @@ package body System.Elaboration_Allocators is
procedure Check_Standard_Allocator is
begin
   if not Elaboration_In_Progress then
- raise Program_Error with
+ raise Storage_Error with
"standard allocator after elaboration is complete is not allowed "
& "(No_Standard_Allocators_After_Elaboration restriction active)";
   end if;

--- gcc/ada/libgnat/s-elaall.ads
+++ gcc/ada/libgnat/s-elaall.ads
@@ -51,7 +51,7 @@ package System.Elaboration_Allocators is
procedure Check_Standard_Allocator;
--  Called as part of every allocator in a program for which the restriction
--  No_Standard_Allocators_After_Elaboration is active. This will raise an
-   --  exception (Program_Error with an appropriate message) if it is called
+   --  exception (Storage_Error with an appropriate message) if it is called
--  after the call to Mark_End_Of_Elaboration.
 
 end System.Elaboration_Allocators;



[Ada] Adjust inlining in GNATprove mode for predicate/invariant/DIC

2018-07-16 Thread Pierre-Marie de Rodat
The frontend generates special functions for checking subtype predicates,
type invariants and Default_Initial_Condition aspect. These are translated
as predicates in GNATprove, and as such should no call inside these
functions should be inlined. This is similar to the existing handling of
calls inside expression functions.

There is no impact on compilation.

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

2018-07-16  Yannick Moy  

gcc/ada/

* sem_res.adb (Resolve_Call): Do not inline calls inside
compiler-generated functions translated as predicates in GNATprove.--- gcc/ada/sem_res.adb
+++ gcc/ada/sem_res.adb
@@ -5374,7 +5374,7 @@ package body Sem_Res is
 
  --  A universal real conditional expression can appear in a fixed-type
  --  context and must be resolved with that context to facilitate the
- --  code generation to the backend.
+ --  code generation in the back end.
 
  elsif Nkind_In (N, N_Case_Expression, N_If_Expression)
and then Etype (N) = Universal_Real
@@ -6685,22 +6685,43 @@ package body Sem_Res is
 
 elsif Full_Analysis then
 
-   --  Do not inline calls inside expression functions, as this
+   --  Do not inline calls inside expression functions or functions
+   --  generated by the front end for subtype predicates, as this
--  would prevent interpreting them as logical formulas in
--  GNATprove. Only issue a message when the body has been seen,
--  otherwise this leads to spurious messages on callees that
--  are themselves expression functions.
 
if Present (Current_Subprogram)
- and then Is_Expression_Function_Or_Completion
-(Current_Subprogram)
+ and then
+   (Is_Expression_Function_Or_Completion (Current_Subprogram)
+ or else Is_Predicate_Function (Current_Subprogram)
+ or else Is_Invariant_Procedure (Current_Subprogram)
+ or else Is_DIC_Procedure (Current_Subprogram))
then
   if Present (Body_Id)
 and then Present (Body_To_Inline (Nam_Decl))
   then
- Cannot_Inline
-   ("cannot inline & (inside expression function)?",
-N, Nam_UA);
+ if Is_Predicate_Function (Current_Subprogram) then
+Cannot_Inline
+  ("cannot inline & (inside predicate)?",
+   N, Nam_UA);
+
+ elsif Is_Invariant_Procedure (Current_Subprogram) then
+Cannot_Inline
+  ("cannot inline & (inside invariant)?",
+   N, Nam_UA);
+
+ elsif Is_DIC_Procedure (Current_Subprogram) then
+Cannot_Inline
+("cannot inline & (inside Default_Initial_Condition)?",
+ N, Nam_UA);
+
+ else
+Cannot_Inline
+  ("cannot inline & (inside expression function)?",
+   N, Nam_UA);
+ end if;
   end if;
 
--  With the one-pass inlining technique, a call cannot be
@@ -11854,7 +11875,7 @@ package body Sem_Res is
 Analyze_And_Resolve (String_Literal_Low_Bound (Subtype_Id));
 
 --  Build bona fide subtype for the string, and wrap it in an
---  unchecked conversion, because the backend expects the
+--  unchecked conversion, because the back end expects the
 --  String_Literal_Subtype to have a static lower bound.
 
 Index_Subtype :=
@@ -11864,7 +11885,7 @@ package body Sem_Res is
 Set_Parent (Drange, N);
 Analyze_And_Resolve (Drange, Index_Type);
 
---  In the context, the Index_Type may already have a constraint,
+--  In this context, the Index_Type may already have a constraint,
 --  so use common base type on string subtype. The base type may
 --  be used when generating attributes of the string, for example
 --  in the context of a slice assignment.



[Ada] Bit_Order cannot be defined for record extensions

2018-07-16 Thread Pierre-Marie de Rodat
This patch allows the compiler to report an error on Bit_Order when
defined for a record extension.

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

2018-07-16  Javier Miranda  

gcc/ada/

* sem_ch13.adb (Analyze_Attribute_Definition_Clause): Report an error
on Bit_Order when defined for a record extension.

gcc/testsuite/

* gnat.dg/bit_order1.adb: New testcase.--- gcc/ada/sem_ch13.adb
+++ gcc/ada/sem_ch13.adb
@@ -5331,6 +5331,12 @@ package body Sem_Ch13 is
Error_Msg_N
  ("Bit_Order can only be defined for record type", Nam);
 
+elsif Is_Tagged_Type (U_Ent)
+   and then Is_Derived_Type (U_Ent)
+then
+   Error_Msg_N
+ ("Bit_Order cannot be defined for record extensions", Nam);
+
 elsif Duplicate_Clause then
null;
 

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/bit_order1.adb
@@ -0,0 +1,18 @@
+--  { dg-do compile }
+
+with System;
+
+procedure Bit_Order1 is
+
+   type Sample_Ttype is tagged record
+  Data : Natural;
+   end record;
+
+   type Other_Type is new Sample_Ttype with record
+  Other_Data : String (1 .. 100);
+   end record;
+
+   for Other_Type'Bit_Order use System.High_Order_First; --  { dg-error "Bit_Order cannot be defined for record extensions" }
+begin
+   null;
+end;



[Ada] Crash processing sources under GNATprove debug mode

2018-07-16 Thread Pierre-Marie de Rodat
Processing sources under -gnatd.F the frontend may crash on
an iterator of the form 'for X of ...' over an array if the
iterator is located in an inlined subprogram.

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

2018-07-16  Javier Miranda  

gcc/ada/

* exp_ch5.adb (Expand_Iterator_Loop_Over_Array): Code cleanup. Required
to avoid generating an ill-formed tree that confuses gnatprove causing
it to blowup.

gcc/testsuite/

* gnat.dg/iter2.adb, gnat.dg/iter2.ads: New testcase.--- gcc/ada/exp_ch5.adb
+++ gcc/ada/exp_ch5.adb
@@ -3711,9 +3711,14 @@ package body Exp_Ch5 is
 
   Ind_Comp :=
 Make_Indexed_Component (Loc,
-  Prefix  => Relocate_Node (Array_Node),
+  Prefix  => New_Copy_Tree (Array_Node),
   Expressions => New_List (New_Occurrence_Of (Iterator, Loc)));
 
+  --  Propagate the original node to the copy since the analysis of the
+  --  following object renaming declaration relies on the original node.
+
+  Set_Original_Node (Prefix (Ind_Comp), Original_Node (Array_Node));
+
   Prepend_To (Stats,
 Make_Object_Renaming_Declaration (Loc,
   Defining_Identifier => Id,
@@ -3755,7 +3760,7 @@ package body Exp_Ch5 is
   Defining_Identifier => Iterator,
   Discrete_Subtype_Definition =>
 Make_Attribute_Reference (Loc,
-  Prefix => Relocate_Node (Array_Node),
+  Prefix => New_Copy_Tree (Array_Node),
   Attribute_Name => Name_Range,
   Expressions=> New_List (
 Make_Integer_Literal (Loc, Dim1))),
@@ -3792,7 +3797,7 @@ package body Exp_Ch5 is
 Defining_Identifier => Iterator,
 Discrete_Subtype_Definition =>
   Make_Attribute_Reference (Loc,
-Prefix => Relocate_Node (Array_Node),
+Prefix => New_Copy_Tree (Array_Node),
 Attribute_Name => Name_Range,
 Expressions=> New_List (
   Make_Integer_Literal (Loc, Dim1))),

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/iter2.adb
@@ -0,0 +1,28 @@
+--  { dg-do compile }
+--  { dg-options "-gnatd.F -gnatws" }
+
+package body Iter2
+   with SPARK_Mode
+is
+   function To_String (Name : String) return String
+   is
+  procedure Append (Result : in out String;
+Data   :String)
+with Inline_Always;
+  procedure Append (Result : in out String;
+Data   :String)
+  is
+  begin
+ for C of Data
+ loop
+Result (1) := C;
+ end loop;
+  end Append;
+
+  Result : String (1 .. 3);
+   begin
+  Append (Result, "");
+  return Result;
+   end To_String;
+
+end Iter2;

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/iter2.ads
@@ -0,0 +1,5 @@
+package Iter2
+   with SPARK_Mode
+is
+   function To_String (Name : String) return String;
+end Iter2;



[Ada] Segmentation_Fault with Integer'Wide_Wide_Value

2018-07-16 Thread Pierre-Marie de Rodat
This patch updates the routines which produce Wide_String and Wide_Wide_String
from a String to construct a result of the proper maximum size which is later
sliced.

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

2018-07-16  Hristian Kirtchev  

gcc/ada/

* libgnat/s-wchwts.adb (Wide_String_To_String): Use the appropriate
longest sequence factor. Code clean up.
(Wide_Wide_String_To_String): Use the appropriate longest sequence
factor.  Code clean up.

gcc/testsuite/

* gnat.dg/wide_wide_value1.adb: New testcase.--- gcc/ada/libgnat/s-wchwts.adb
+++ gcc/ada/libgnat/s-wchwts.adb
@@ -86,16 +86,23 @@ package body System.WCh_WtS is
  (S  : Wide_String;
   EM : WC_Encoding_Method) return String
is
-  R  : String (S'First .. S'First + 5 * S'Length); -- worst case length
-  RP : Natural;
+  Max_Chars : constant Natural := WC_Longest_Sequences (EM);
+
+  Result : String (S'First .. S'First + Max_Chars * S'Length);
+  Result_Idx : Natural;
 
begin
-  RP := R'First - 1;
-  for SP in S'Range loop
- Store_UTF_32_Character (Wide_Character'Pos (S (SP)), R, RP, EM);
+  Result_Idx := Result'First - 1;
+
+  for S_Idx in S'Range loop
+ Store_UTF_32_Character
+   (U  => Wide_Character'Pos (S (S_Idx)),
+S  => Result,
+P  => Result_Idx,
+EM => EM);
   end loop;
 
-  return R (R'First .. RP);
+  return Result (Result'First .. Result_Idx);
end Wide_String_To_String;
 

@@ -106,17 +113,23 @@ package body System.WCh_WtS is
  (S  : Wide_Wide_String;
   EM : WC_Encoding_Method) return String
is
-  R  : String (S'First .. S'First + 7 * S'Length); -- worst case length
-  RP : Natural;
+  Max_Chars : constant Natural := WC_Longest_Sequences (EM);
 
-   begin
-  RP := R'First - 1;
+  Result : String (S'First .. S'First + Max_Chars * S'Length);
+  Result_Idx : Natural;
 
-  for SP in S'Range loop
- Store_UTF_32_Character (Wide_Wide_Character'Pos (S (SP)), R, RP, EM);
+   begin
+  Result_Idx := Result'First - 1;
+
+  for S_Idx in S'Range loop
+ Store_UTF_32_Character
+   (U  => Wide_Wide_Character'Pos (S (S_Idx)),
+S  => Result,
+P  => Result_Idx,
+EM => EM);
   end loop;
 
-  return R (R'First .. RP);
+  return Result (Result'First .. Result_Idx);
end Wide_Wide_String_To_String;
 
 end System.WCh_WtS;

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/wide_wide_value1.adb
@@ -0,0 +1,60 @@
+--  { dg-do run }
+
+with Ada.Text_IO; use Ada.Text_IO;
+
+procedure Wide_Wide_Value1 is
+begin
+   begin
+  declare
+ Str : constant Wide_Wide_String :=
+ Wide_Wide_Character'Val (16#0411#) &
+ Wide_Wide_Character'Val (16#043e#) &
+ Wide_Wide_Character'Val (16#0434#) &
+ Wide_Wide_Character'Val (16#0430#) &
+ Wide_Wide_Character'Val (16#0443#) &
+ Wide_Wide_Character'Val (16#0431#) &
+ Wide_Wide_Character'Val (16#0430#) &
+ Wide_Wide_Character'Val (16#0435#) &
+ Wide_Wide_Character'Val (16#0432#) &
+ Wide_Wide_Character'Val (16#0416#) &
+ Wide_Wide_Character'Val (16#0443#) &
+ Wide_Wide_Character'Val (16#043c#) &
+ Wide_Wide_Character'Val (16#0430#) &
+ Wide_Wide_Character'Val (16#0442#) &
+ Wide_Wide_Character'Val (16#041c#) &
+ Wide_Wide_Character'Val (16#0430#) &
+ Wide_Wide_Character'Val (16#0440#) &
+ Wide_Wide_Character'Val (16#0430#) &
+ Wide_Wide_Character'Val (16#0442#) &
+ Wide_Wide_Character'Val (16#043e#) &
+ Wide_Wide_Character'Val (16#0432#) &
+ Wide_Wide_Character'Val (16#0438#) &
+ Wide_Wide_Character'Val (16#0447#);
+
+ Val : constant Integer := Integer'Wide_Wide_Value (Str);
+  begin
+ Put_Line ("ERROR: 1: Constraint_Error not raised");
+  end;
+   exception
+  when Constraint_Error =>
+ null;
+  when others =>
+ Put_Line ("ERROR: 1: unexpected exception");
+   end;
+
+   begin
+  declare
+ Str : Wide_Wide_String (1 .. 128) :=
+ (others => Wide_Wide_Character'Val (16#0FFF#));
+
+ Val : constant Integer := Integer'Wide_Wide_Value (Str);
+  begin
+ Put_Line ("ERROR: 1: Constraint_Error not raised");
+  end;
+   exception
+  when Constraint_Error =>
+ null;
+  when others =>
+ Put_Line ("ERROR: 1: unexpected exception");
+   end;
+end Wide_Wide_Value1;



[Ada] Code cleanup on functions inlining

2018-07-16 Thread Pierre-Marie de Rodat
This patch is preventive: it improves checks on inline functions that
return unconstrained type. It does not change the functionality of
the compiler.

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

2018-07-16  Javier Miranda  

gcc/ada/

* inline.adb (Build_Body_To_Inline): Minor code reorganization that
ensures that calls to function Has_Single_Return() pass a decorated
tree.
(Has_Single_Return.Check_Return): Peform checks on entities (instead on
relying on their characters).--- gcc/ada/inline.adb
+++ gcc/ada/inline.adb
@@ -1085,33 +1085,9 @@ package body Inline is
  Cannot_Inline ("cannot inline & (multiple returns)?", N, Spec_Id);
  return;
 
-  --  Functions that return unconstrained composite types require
-  --  secondary stack handling, and cannot currently be inlined, unless
-  --  all return statements return a local variable that is the first
-  --  local declaration in the body.
-
-  elsif Ekind (Spec_Id) = E_Function
-and then not Is_Scalar_Type (Etype (Spec_Id))
-and then not Is_Access_Type (Etype (Spec_Id))
-and then not Is_Constrained (Etype (Spec_Id))
-  then
- if not Has_Single_Return (N)
-
-   --  Skip inlining if the function returns an unconstrained type
-   --  using an extended return statement, since this part of the
-   --  new inlining model is not yet supported by the current
-   --  implementation. ???
-
-   or else (Returns_Unconstrained_Type (Spec_Id)
- and then Has_Extended_Return)
- then
-Cannot_Inline
-  ("cannot inline & (unconstrained return type)?", N, Spec_Id);
-return;
- end if;
-
-  --  Ditto for functions that return controlled types, where controlled
-  --  actions interfere in complex ways with inlining.
+  --  Functions that return controlled types cannot currently be inlined
+  --  because they require secondary stack handling; controlled actions
+  --  may also interfere in complex ways with inlining.
 
   elsif Ekind (Spec_Id) = E_Function
 and then Needs_Finalization (Etype (Spec_Id))
@@ -1234,10 +1210,37 @@ package body Inline is
  Restore_Env;
   end if;
 
+  --  Functions that return unconstrained composite types require
+  --  secondary stack handling, and cannot currently be inlined, unless
+  --  all return statements return a local variable that is the first
+  --  local declaration in the body. We had to delay this check until
+  --  the body of the function is analyzed since Has_Single_Return()
+  --  requires a minimum decoration.
+
+  if Ekind (Spec_Id) = E_Function
+and then not Is_Scalar_Type (Etype (Spec_Id))
+and then not Is_Access_Type (Etype (Spec_Id))
+and then not Is_Constrained (Etype (Spec_Id))
+  then
+ if not Has_Single_Return (Body_To_Analyze)
+
+   --  Skip inlining if the function returns an unconstrained type
+   --  using an extended return statement, since this part of the
+   --  new inlining model is not yet supported by the current
+   --  implementation. ???
+
+   or else (Returns_Unconstrained_Type (Spec_Id)
+ and then Has_Extended_Return)
+ then
+Cannot_Inline
+  ("cannot inline & (unconstrained return type)?", N, Spec_Id);
+return;
+ end if;
+
   --  If secondary stack is used, there is no point in inlining. We have
   --  already issued the warning in this case, so nothing to do.
 
-  if Uses_Secondary_Stack (Body_To_Analyze) then
+  elsif Uses_Secondary_Stack (Body_To_Analyze) then
  return;
   end if;
 
@@ -3904,17 +3907,23 @@ package body Inline is
 if Present (Expression (N))
   and then Is_Entity_Name (Expression (N))
 then
+   pragma Assert (Present (Entity (Expression (N;
+
if No (Return_Statement) then
   Return_Statement := N;
   return OK;
 
-   elsif Chars (Expression (N)) =
- Chars (Expression (Return_Statement))
-   then
-  return OK;
-
else
-  return Abandon;
+  pragma Assert
+(Present (Entity (Expression (Return_Statement;
+
+  if Entity (Expression (N)) =
+   Entity (Expression (Return_Statement))
+  then
+ return OK;
+  else
+ return Abandon;
+  end if;
end if;
 
 --  A return statement within an extended return is a noop
@@ -3963,8 +3972,8 @@ package body Inline is
   else
  return Present (Declarations (N))
and then Present (First (Declar

[Ada] Spurious possible contraint error warning with No_Exception_Propagation

2018-07-16 Thread Pierre-Marie de Rodat
This patch corrects an issue whereby spurious unhandled exception warnings on
integer literals within static if and case expressions would be emitted when
the restriction No_Exception_Propagation is enabled.


-- Source --


--  gnat.adc

pragma Restrictions (No_Exception_Propagation);
pragma SPARK_Mode (On);

--  pack.ads

package Pack is
   procedure Filter (Ret : out Integer);
end Pack;

--  pack.adb

package body Pack is

   subtype Nat is Integer range 0 .. 10;

   Default   : constant Nat := 1;
   User_Override : constant Integer := -1;

   procedure Filter (Ret : out Integer) is
  Val : constant Nat :=
  (if User_Override in Nat then
  User_Override
   else
  Default);
   begin
  Ret := Val;
   end Filter;
end Pack;


-- Compilation and output --


& gcc -c -gnatp -gnatwa pack.adb

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

2018-07-16  Justin Squirek  

gcc/ada/

* sem_eval.adb (Eval_Integer_Literal): Add exception for avoiding
checks on expanded literals within if and case expressions.--- gcc/ada/sem_eval.adb
+++ gcc/ada/sem_eval.adb
@@ -2720,16 +2720,23 @@ package body Sem_Eval is
--  Start of processing for Eval_Integer_Literal
 
begin
-
   --  If the literal appears in a non-expression context, then it is
   --  certainly appearing in a non-static context, so check it. This is
   --  actually a redundant check, since Check_Non_Static_Context would
   --  check it, but it seems worthwhile to optimize out the call.
 
-  --  An exception is made for a literal in an if or case expression
+  --  Additionally, when the literal appears within an if or case
+  --  expression it must be checked as well. However, due to the literal
+  --  appearing within a conditional statement, expansion greatly changes
+  --  the nature of its context and performing some of the checks within
+  --  Check_Non_Static_Context on an expanded literal may lead to spurious
+  --  and misleading warnings.
 
   if (Nkind_In (Parent (N), N_If_Expression, N_Case_Expression_Alternative)
or else Nkind (Parent (N)) not in N_Subexpr)
+and then (not Nkind_In (Parent (N), N_If_Expression,
+ N_Case_Expression_Alternative)
+   or else Comes_From_Source (N))
 and then not In_Any_Integer_Context
   then
  Check_Non_Static_Context (N);



[Ada] Crash on Indefinite_Hashed_Maps with -gnata -gnateV

2018-07-16 Thread Pierre-Marie de Rodat
This patch corrects the generation of helper functions which verify the
validity of record type scalar discriminants and scalar components when
switches -gnata (assertions enabled) and -gnateV (validity checks on
subprogram parameters) are in effect.

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

2018-07-16  Hristian Kirtchev  

gcc/ada/

* exp_attr.adb (Build_Record_VS_Func): Handle corner cases dealing with
class-wide types and record extensions.

gcc/testsuite/

* gnat.dg/validity_check3.adb, gnat.dg/validity_check3.ads: New
testcase.--- gcc/ada/exp_attr.adb
+++ gcc/ada/exp_attr.adb
@@ -724,13 +724,44 @@ package body Exp_Attr is
 
   Func_Id  : constant Entity_Id := Make_Temporary (Loc, 'V');
   Obj_Id   : constant Entity_Id := Make_Temporary (Loc, 'R');
-  Rec_Decl : constant Node_Id   := Declaration_Node (Rec_Typ);
-  Rec_Def  : constant Node_Id   := Type_Definition (Rec_Decl);
+  Comps: Node_Id;
   Stmts: List_Id;
+  Typ  : Entity_Id;
+  Typ_Decl : Node_Id;
+  Typ_Def  : Node_Id;
+  Typ_Ext  : Node_Id;
 
--  Start of processing for Build_Record_VS_Func
 
begin
+  Typ := Rec_Typ;
+
+  --  Use the root type when dealing with a class-wide type
+
+  if Is_Class_Wide_Type (Typ) then
+ Typ := Root_Type (Typ);
+  end if;
+
+  Typ_Decl := Declaration_Node (Typ);
+  Typ_Def  := Type_Definition (Typ_Decl);
+
+  --  The components of a derived type are located in the extension part
+
+  if Nkind (Typ_Def) = N_Derived_Type_Definition then
+ Typ_Ext := Record_Extension_Part (Typ_Def);
+
+ if Present (Typ_Ext) then
+Comps := Component_List (Typ_Ext);
+ else
+Comps := Empty;
+ end if;
+
+  --  Otherwise the components are available in the definition
+
+  else
+ Comps := Component_List (Typ_Def);
+  end if;
+
   --  The code generated by this routine is as follows:
   --
   --function Func_Id (Obj_Id : Formal_Typ) return Boolean is
@@ -774,7 +805,7 @@ package body Exp_Attr is
   if not Is_Unchecked_Union (Rec_Typ) then
  Validate_Fields
(Obj_Id => Obj_Id,
-Fields => Discriminant_Specifications (Rec_Decl),
+Fields => Discriminant_Specifications (Typ_Decl),
 Stmts  => Stmts);
   end if;
 
@@ -782,7 +813,7 @@ package body Exp_Attr is
 
   Validate_Component_List
 (Obj_Id=> Obj_Id,
- Comp_List => Component_List (Rec_Def),
+ Comp_List => Comps,
  Stmts => Stmts);
 
   --  Generate:

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/validity_check3.adb
@@ -0,0 +1,96 @@
+--  { dg-do compile }
+--  { dg-options "-gnata -gnateV" }
+
+package body Validity_Check3 is
+   procedure Proc_Priv_CW_1 (Param : Tag_1'Class) is begin null; end;
+   procedure Proc_Priv_CW_2 (Param : Tag_2'Class) is begin null; end;
+   procedure Proc_Priv_CW_3 (Param : Tag_3'Class) is begin null; end;
+   procedure Proc_Priv_CW_4 (Param : Tag_4'Class) is begin null; end;
+   procedure Proc_Priv_CW_5 (Param : Tag_5'Class) is begin null; end;
+   procedure Proc_Priv_CW_6 (Param : Tag_6'Class) is begin null; end;
+
+   procedure Proc_Priv_Rec_1 (Param : Rec_1) is begin null; end;
+   procedure Proc_Priv_Rec_2 (Param : Rec_2) is begin null; end;
+   procedure Proc_Priv_Rec_3 (Param : Rec_3) is begin null; end;
+   procedure Proc_Priv_Rec_4 (Param : Rec_4) is begin null; end;
+
+   procedure Proc_Priv_Tag_1 (Param : Tag_1) is begin null; end;
+   procedure Proc_Priv_Tag_2 (Param : Tag_2) is begin null; end;
+   procedure Proc_Priv_Tag_3 (Param : Tag_3) is begin null; end;
+   procedure Proc_Priv_Tag_4 (Param : Tag_4) is begin null; end;
+   procedure Proc_Priv_Tag_5 (Param : Tag_5) is begin null; end;
+   procedure Proc_Priv_Tag_6 (Param : Tag_6) is begin null; end;
+
+   procedure Proc_Vis_CW_1 (Param : Tag_1'Class) is begin null; end;
+   procedure Proc_Vis_CW_2 (Param : Tag_2'Class) is begin null; end;
+   procedure Proc_Vis_CW_3 (Param : Tag_3'Class) is begin null; end;
+   procedure Proc_Vis_CW_4 (Param : Tag_4'Class) is begin null; end;
+   procedure Proc_Vis_CW_5 (Param : Tag_5'Class) is begin null; end;
+   procedure Proc_Vis_CW_6 (Param : Tag_6'Class) is begin null; end;
+
+   procedure Proc_Vis_Rec_1 (Param : Rec_1) is begin null; end;
+   procedure Proc_Vis_Rec_2 (Param : Rec_2) is begin null; end;
+   procedure Proc_Vis_Rec_3 (Param : Rec_3) is begin null; end;
+   procedure Proc_Vis_Rec_4 (Param : Rec_4) is begin null; end;
+
+   procedure Proc_Vis_Tag_1 (Param : Tag_1) is begin null; end;
+   procedure Proc_Vis_Tag_2 (Param : Tag_2) is begin null; end;
+   procedure Proc_Vis_Tag_3 (Param : Tag_3) is begin null; end;
+   procedure Proc_Vis_Tag_4 (Param : Tag_4) is begin null; end;
+   procedure Proc_Vis_Tag_5 (Param : Tag_5) is begin null; end;
+   procedure Proc_Vis_Tag_6 (Param : Tag_6) is begin n

[Ada] Deconstruct always-false calls to Withed_Body in Walk_Library_Items

2018-07-16 Thread Pierre-Marie de Rodat
We previously removed the calls to Set_Withed_Body; this commit deconstructs
calls to Withed_Body, which always returned False.

The Set_Withed_Body/Withed_Body were helping the Walk_Library_Items routine
traverse the AST of several compilation units such that declarations are
visited before references. However, this never worked as it should and there is
no point to keep the code more complicated than necessary.

No test provided, because thie removed code was ineffective (and only used in
the non-compiler backends, i.e. CodePeer and GNATprove).

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

2018-07-16  Piotr Trojanek  

gcc/ada/

* sem.adb (Walk_Library_Items): Deconstruct dead code.--- gcc/ada/sem.adb
+++ gcc/ada/sem.adb
@@ -36,7 +36,6 @@ with Nlists;use Nlists;
 with Output;use Output;
 with Restrict;  use Restrict;
 with Sem_Attr;  use Sem_Attr;
-with Sem_Aux;   use Sem_Aux;
 with Sem_Ch2;   use Sem_Ch2;
 with Sem_Ch3;   use Sem_Ch3;
 with Sem_Ch4;   use Sem_Ch4;
@@ -1705,7 +1704,7 @@ package body Sem is
   --  The main unit and its spec may depend on bodies that contain generics
   --  that are instantiated in them. Iterate through the corresponding
   --  contexts before processing main (spec/body) itself, to process bodies
-  --  that may be present, together with their  context. The spec of main
+  --  that may be present, together with their context. The spec of main
   --  is processed wherever it appears in the list of units, while the body
   --  is processed as the last unit in the list.
 
@@ -2020,8 +2019,7 @@ package body Sem is
if Present (Body_CU)
  and then Body_CU /= Cunit (Main_Unit)
  and then Nkind (Unit (Body_CU)) /= N_Subprogram_Body
- and then (Nkind (Unit (Comp)) /= N_Package_Declaration
- or else Present (Withed_Body (Clause)))
+ and then Nkind (Unit (Comp)) /= N_Package_Declaration
then
   Body_U := Get_Cunit_Unit_Number (Body_CU);
 
@@ -2335,7 +2333,6 @@ package body Sem is
 
   Context_Item : Node_Id;
   Lib_Unit : Node_Id;
-  Body_CU  : Node_Id;
 
begin
   Context_Item := First (Context_Items (CU));
@@ -2346,30 +2343,6 @@ package body Sem is
  then
 Lib_Unit := Library_Unit (Context_Item);
 Action (Lib_Unit);
-
---  If the context item indicates that a package body is needed
---  because of an instantiation in CU, traverse the body now, even
---  if CU is not related to the main unit. If the generic itself
---  appears in a package body, the context item is this body, and
---  it already appears in the traversal order, so we only need to
---  examine the case of a context item being a package declaration.
-
-if Present (Withed_Body (Context_Item))
-  and then Nkind (Unit (Lib_Unit)) = N_Package_Declaration
-  and then Present (Corresponding_Body (Unit (Lib_Unit)))
-then
-   Body_CU :=
- Parent
-   (Unit_Declaration_Node
- (Corresponding_Body (Unit (Lib_Unit;
-
-   --  A body may have an implicit with on its own spec, in which
-   --  case we must ignore this context item to prevent looping.
-
-   if Unit (CU) /= Unit (Body_CU) then
-  Action (Body_CU);
-   end if;
-end if;
  end if;
 
  Context_Item := Next (Context_Item);



[Ada] Spurious error with null Abstract_State

2018-07-16 Thread Pierre-Marie de Rodat
This patch corrects the mechanism which ensures that a package with a null
Abstract_State does not introduce hidden state, by ignoring internal states
and variables because they do not represent the "source" hidden state.

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

2018-07-16  Hristian Kirtchev  

gcc/ada/

* sem_util.adb (Check_No_Hidden_State): Ignore internally-generated
states and variables.

gcc/testsuite/

* gnat.dg/abstract_state1.adb, gnat.dg/abstract_state1.ads: New
testcase.--- gcc/ada/sem_util.adb
+++ gcc/ada/sem_util.adb
@@ -3228,6 +3228,13 @@ package body Sem_Util is
begin
   pragma Assert (Ekind_In (Id, E_Abstract_State, E_Variable));
 
+  --  Nothing to do for internally-generated abstract states and variables
+  --  because they do not represent the hidden state of the source unit.
+
+  if not Comes_From_Source (Id) then
+ return;
+  end if;
+
   --  Find the proper context where the object or state appears
 
   Scop := Scope (Id);

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/abstract_state1.adb
@@ -0,0 +1,5 @@
+--  { dg-do compile }
+
+package body Abstract_State1 is
+   procedure Foo is null;
+end Abstract_State1;

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/abstract_state1.ads
@@ -0,0 +1,24 @@
+package Abstract_State1
+  with Abstract_State => null,
+   Initializes=> null
+is
+   type Complex (B : Boolean) is tagged private;
+   type No_F is tagged private;
+   X : constant No_F;
+
+   procedure Foo;
+
+private
+   type Complex (B : Boolean) is tagged record
+  G : Integer;
+  case B is
+ when True =>
+F : Integer;
+ when False =>
+null;
+  end case;
+   end record;
+
+   type No_F is new Complex (False) with null record;
+   X : constant No_F := (B => False, G => 7);
+end Abstract_State1;



[Ada] Avoid crash when traversing units with -gnatd.WW debug switch

2018-07-16 Thread Pierre-Marie de Rodat
The debug switch -gnatd.WW enables extra info when traversing library units
with Walk_Library_Items, which is used in the CodePeer and GNATprove. This
routine was crashing when trying to print info about a unit with configuration
pragmas (typically an .adc file). Now fixed.

No test, as the crash only happens when a GNATprove backend is manually called
with -gnatd.WW switch. Frontend is not affected.

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

2018-07-16  Piotr Trojanek  

gcc/ada/

* sem.adb (Walk_Library_Items): Skip units with configuration pragmas
when printing debug info.--- gcc/ada/sem.adb
+++ gcc/ada/sem.adb
@@ -2242,8 +2242,14 @@ package body Sem is
 
 for Unit_Num in Done'Range loop
if not Done (Unit_Num) then
-  Write_Unit_Info
-(Unit_Num, Unit (Cunit (Unit_Num)), Withs => True);
+
+  --  Units with configuration pragmas (.ads files) have empty
+  --  compilation-unit nodes; skip printing info about them.
+
+  if Present (Cunit (Unit_Num)) then
+ Write_Unit_Info
+   (Unit_Num, Unit (Cunit (Unit_Num)), Withs => True);
+  end if;
end if;
 end loop;
 



[Ada] Deconstruct unused Withed_Body filed of N_With_Clause node

2018-07-16 Thread Pierre-Marie de Rodat
The Withed_Body field was added to N_With_Clause node to help the
Walk_Library_Items routine, which was created for the CodePeer backend
and later adopted by the GNATprove.

This routine is meant to traverse all library units, such that declarations
are visited before references. However, for complex units (in particular,
with generics and child packages) it never worked reliably and backends
developed their own workarounds. This patch deconstructs the field, as it
hasn't been used for years.

Semantics unaffected; no test provided.

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

2018-07-16  Piotr Trojanek  

gcc/ada/

* sinfo.ads, sinfo.adb (Withed_Body): Remove.
(Set_Withed_Body): Remove.--- gcc/ada/sinfo.adb
+++ gcc/ada/sinfo.adb
@@ -3522,14 +3522,6 @@ package body Sinfo is
   return Flag13 (N);
end Was_Originally_Stub;
 
-   function Withed_Body
-  (N : Node_Id) return Node_Id is
-   begin
-  pragma Assert (False
-or else NT (N).Nkind = N_With_Clause);
-  return Node1 (N);
-   end Withed_Body;
-
--
-- Field Set Procedures --
--
@@ -6990,14 +6982,6 @@ package body Sinfo is
   Set_Flag13 (N, Val);
end Set_Was_Originally_Stub;
 
-   procedure Set_Withed_Body
- (N : Node_Id; Val : Node_Id) is
-   begin
-  pragma Assert (False
-or else NT (N).Nkind = N_With_Clause);
-  Set_Node1 (N, Val);
-   end Set_Withed_Body;
-
-
-- Iterator Procedures --
-

--- gcc/ada/sinfo.ads
+++ gcc/ada/sinfo.ads
@@ -2504,12 +2504,6 @@ package Sinfo is
--Original_Node here because of the case of nested instantiations where
--the substituted node can be copied.
 
-   --  Withed_Body (Node1-Sem)
-   --Present in N_With_Clause nodes. Set if the unit in whose context
-   --the with_clause appears instantiates a generic contained in the
-   --library unit of the with_clause and as a result loads its body.
-   --Used for a more precise unit traversal for CodePeer.
-
--
-- Note on Use of End_Label and End_Span Fields --
--
@@ -6743,7 +6737,6 @@ package Sinfo is
 
   --  N_With_Clause
   --  Sloc points to first token of library unit name
-  --  Withed_Body (Node1-Sem)
   --  Name (Node2)
   --  Private_Present (Flag15) set if with_clause has private keyword
   --  Limited_Present (Flag17) set if LIMITED is present
@@ -10307,9 +10300,6 @@ package Sinfo is
function Was_Originally_Stub
  (N : Node_Id) return Boolean;-- Flag13
 
-   function Withed_Body
- (N : Node_Id) return Node_Id;-- Node1
-
--  End functions (note used by xsinfo utility program to end processing)
 

@@ -11408,9 +11398,6 @@ package Sinfo is
procedure Set_Was_Originally_Stub
  (N : Node_Id; Val : Boolean := True);-- Flag13
 
-   procedure Set_Withed_Body
- (N : Node_Id; Val : Node_Id);-- Node1
-
-
-- Iterator Procedures --
-
@@ -13613,7 +13600,6 @@ package Sinfo is
pragma Inline (Was_Attribute_Reference);
pragma Inline (Was_Expression_Function);
pragma Inline (Was_Originally_Stub);
-   pragma Inline (Withed_Body);
 
pragma Inline (Set_Abort_Present);
pragma Inline (Set_Abortable_Part);
@@ -13975,6 +13961,5 @@ package Sinfo is
pragma Inline (Set_Was_Attribute_Reference);
pragma Inline (Set_Was_Expression_Function);
pragma Inline (Set_Was_Originally_Stub);
-   pragma Inline (Set_Withed_Body);
 
 end Sinfo;



[Ada] Missing error on hidden state in instantiation

2018-07-16 Thread Pierre-Marie de Rodat
This patch modifies the analysis of package contracts to split processing
which is specific to package instantiations on its own. As a result, the
lack of indicator Part_Of can now be properly assessed.


-- Source --


--  gen_pack.ads

generic
package Gen_Pack is
   Pack_Var : Integer := 1;
end Gen_Pack;

--  gen_wrap.ads

with Gen_Pack;

generic
package Gen_Wrap is
   Wrap_Var : Integer := 1;

   package Inst is new Gen_Pack;
end Gen_Wrap;

--  pack.ads

with Gen_Pack;
with Gen_Wrap;

package Pack
  with SPARK_Mode => On,
   Abstract_State => State
is
   procedure Force_Body;

private
   package OK_Inst_1 is new Gen_Pack --  OK
 with Part_Of => State;  --  OK

   package OK_Inst_2 is new Gen_Pack;--  OK
   pragma Part_Of (State);   --  OK

   package OK_Inst_3 is new Gen_Wrap --  OK
 with Part_Of => State;  --  OK

   package OK_Inst_4 is new Gen_Wrap;--  OK
   pragma Part_Of (State);

   package Error_Inst_1 is new Gen_Pack; --  Error
   package Error_Inst_2 is new Gen_Wrap; --  Error
end Pack;

--  pack.adb

package body Pack
  with SPARK_Mode=> On,
   Refined_State =>
 (State => (OK_Inst_1.Pack_Var, OK_Inst_2.Pack_Var,
OK_Inst_3.Wrap_Var, OK_Inst_3.Inst.Pack_Var,
OK_Inst_4.Wrap_Var, OK_Inst_4.Inst.Pack_Var))
is
   procedure Force_Body is null;
end Pack;


-- Compilation and output --


$ gcc -c pack.adb
pack.ads:23:12: indicator Part_Of is required in this context (SPARK RM
  7.2.6(2))
pack.ads:23:12: "Error_Inst_1" is declared in the private part of package
  "Pack"
pack.ads:24:12: indicator Part_Of is required in this context (SPARK RM
  7.2.6(2))
pack.ads:24:12: "Error_Inst_2" is declared in the private part of package
  "Pack"

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

2018-07-16  Hristian Kirtchev  

gcc/ada/

* contracts.adb (Analyze_Contracts): Add specialized processing for
package instantiation contracts.
(Analyze_Package_Contract): Remove the verification of a missing
Part_Of indicator.
(Analyze_Package_Instantiation_Contract): New routine.
* contracts.ads (Analyze_Package_Contract): Update the comment on
usage.
* sem_prag.adb (Check_Missing_Part_Of): Ensure that the entity of the
instance is being examined when trying to determine whether a package
instantiation needs a Part_Of indicator.--- gcc/ada/contracts.adb
+++ gcc/ada/contracts.adb
@@ -53,6 +53,13 @@ with Tbuild;   use Tbuild;
 
 package body Contracts is
 
+   procedure Analyze_Package_Instantiation_Contract (Inst_Id : Entity_Id);
+   --  Analyze all delayed pragmas chained on the contract of package
+   --  instantiation Inst_Id as if they appear at the end of a declarative
+   --  region. The pragmas in question are:
+   --
+   --Part_Of
+
procedure Build_And_Analyze_Contract_Only_Subprograms (L : List_Id);
--  (CodePeer): Subsidiary procedure to Analyze_Contracts which builds the
--  contract-only subprogram body of eligible subprograms found in L, adds
@@ -386,6 +393,11 @@ package body Contracts is
  elsif Nkind (Decl) = N_Object_Declaration then
 Analyze_Object_Contract (Defining_Entity (Decl));
 
+ --  Package instantiation
+
+ elsif Nkind (Decl) = N_Package_Instantiation then
+Analyze_Package_Instantiation_Contract (Defining_Entity (Decl));
+
  --  Protected units
 
  elsif Nkind_In (Decl, N_Protected_Type_Declaration,
@@ -1074,17 +1086,6 @@ package body Contracts is
  end if;
   end if;
 
-  --  Check whether the lack of indicator Part_Of agrees with the placement
-  --  of the package instantiation with respect to the state space.
-
-  if Is_Generic_Instance (Pack_Id) then
- Prag := Get_Pragma (Pack_Id, Pragma_Part_Of);
-
- if No (Prag) then
-Check_Missing_Part_Of (Pack_Id);
- end if;
-  end if;
-
   --  Restore the SPARK_Mode of the enclosing context after all delayed
   --  pragmas have been analyzed.
 
@@ -1100,6 +1101,62 @@ package body Contracts is
   end if;
end Analyze_Package_Contract;
 
+   
+   -- Analyze_Package_Instantiation_Contract --
+   
+
+   --  WARNING: This routine manages SPARK regions. Return statements must be
+   --  replaced by gotos which jump to the end of the routine and restore the
+   --  SPARK mode.
+
+   procedure Analyze_Package_Instantiation_Contract (Inst_Id : Entity_Id) is
+  Inst_Spec : constant Node_Id :

[Ada] Fix Next_Actual when used on calls "inlined for proof"

2018-07-17 Thread Pierre-Marie de Rodat
The GNATprove backend needs to apply antialiasing checks to subprogram
calls that have been rewritten into null statements while "inlining for
proof". This requires the First_Actual/Next_Actual to use the Original_Node
and not the N_Null_Statement that rewriting leaves as a parent.

Only effective in GNATprove mode, so no frontend test provided.

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

2018-07-17  Piotr Trojanek  

gcc/ada/

* sem_util.adb (Next_Actual): If the parent is a N_Null_Statement,
which happens for inlined calls, then fetch the next actual from the
original AST.--- gcc/ada/sem_util.adb
+++ gcc/ada/sem_util.adb
@@ -21033,7 +21033,8 @@ package body Sem_Util is
-
 
function Next_Actual (Actual_Id : Node_Id) return Node_Id is
-  N  : Node_Id;
+  N   : Node_Id;
+  Par : constant Node_Id := Parent (Actual_Id);
 
begin
   --  If we are pointing at a positional parameter, it is a member of a
@@ -21053,11 +21054,22 @@ package body Sem_Util is
 --  In case of a build-in-place call, the call will no longer be a
 --  call; it will have been rewritten.
 
-if Nkind_In (Parent (Actual_Id), N_Entry_Call_Statement,
- N_Function_Call,
- N_Procedure_Call_Statement)
+if Nkind_In (Par, N_Entry_Call_Statement,
+  N_Function_Call,
+  N_Procedure_Call_Statement)
 then
-   return First_Named_Actual (Parent (Actual_Id));
+   return First_Named_Actual (Par);
+
+--  In case of a call rewritten in GNATprove mode while "inlining
+--  for proof" go to the original call.
+
+elsif Nkind (Par) = N_Null_Statement then
+   pragma Assert
+ (GNATprove_Mode
+and then
+  Nkind (Original_Node (Par)) in N_Subprogram_Call);
+
+   return First_Named_Actual (Original_Node (Par));
 else
return Empty;
 end if;



[Ada] Add elaboration-related switches to GNAT UGN

2018-07-17 Thread Pierre-Marie de Rodat
This patch adds compiler switches -gnatH and -gnatJ to section "Alphabetical
list of all switches" of the GNAT User Guide for Native.

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

2018-07-17  Hristian Kirtchev  

gcc/ada/

* doc/gnat_ugn/building_executable_programs_with_gnat.rst: Add missing
sections on -gnatH and -gnatJ compiler switches.
* gnat_ugn.texi: Regenerate.--- gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
+++ gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
@@ -720,9 +720,9 @@ is passed to ``gcc`` (e.g., :switch:`-O`, :switch:`-gnato,` etc.)
 .. index:: --RTS  (gnatmake)
 
 :switch:`--RTS={rts-path}`
-  Specifies the default location of the runtime library. GNAT looks for the
-  runtime
-  in the following directories, and stops as soon as a valid runtime is found
+  Specifies the default location of the run-time library. GNAT looks for the
+  run-time
+  in the following directories, and stops as soon as a valid run-time is found
   (:file:`adainclude` or :file:`ada_source_path`, and :file:`adalib` or
   :file:`ada_object_path` present):
 
@@ -1505,7 +1505,7 @@ Alphabetical List of All Switches
 
 
   In the example above, the first call to ``Detect_Aliasing`` fails with a
-  ``Program_Error`` at runtime because the actuals for ``Val_1`` and
+  ``Program_Error`` at run time because the actuals for ``Val_1`` and
   ``Val_2`` denote the same object. The second call executes without raising
   an exception because ``Self(Obj)`` produces an anonymous object which does
   not share the memory location of ``Obj``.
@@ -1817,14 +1817,12 @@ Alphabetical List of All Switches
 .. index:: -gnatg  (gcc)
 
 :switch:`-gnatg`
-  Internal GNAT implementation mode. This should not be used for
-  applications programs, it is intended only for use by the compiler
-  and its run-time library. For documentation, see the GNAT sources.
-  Note that :switch:`-gnatg` implies
-  :switch:`-gnatw.ge` and
-  :switch:`-gnatyg`
-  so that all standard warnings and all standard style options are turned on.
-  All warnings and style messages are treated as errors.
+  Internal GNAT implementation mode. This should not be used for applications
+  programs, it is intended only for use by the compiler and its run-time
+  library. For documentation, see the GNAT sources. Note that :switch:`-gnatg`
+  implies :switch:`-gnatw.ge` and :switch:`-gnatyg` so that all standard
+  warnings and all standard style options are turned on. All warnings and style
+  messages are treated as errors.
 
 
 .. index:: -gnatG[nn]  (gcc)
@@ -1839,6 +1837,13 @@ Alphabetical List of All Switches
   Output usage information. The output is written to :file:`stdout`.
 
 
+.. index:: -gnatH  (gcc)
+
+:switch:`-gnatH`
+  Legacy elaboration-checking mode enabled. When this switch is in effect, the
+  pre-18.x access-before-elaboration model becomes the de facto model.
+
+
 .. index:: -gnati  (gcc)
 
 :switch:`-gnati{c}`
@@ -1874,6 +1879,27 @@ Alphabetical List of All Switches
   Reformat error messages to fit on ``nn`` character lines
 
 
+.. index:: -gnatJ  (gcc)
+
+:switch:`-gnatJ`
+  Permissive elaboration-checking mode enabled. When this switch is in effect,
+  the post-18.x access-before-elaboration model ignores potential issues with:
+
+  - Accept statements
+  - Activations of tasks defined in instances
+  - Assertion pragmas
+  - Calls from within an instance to its enclosing context
+  - Calls through generic formal parameters
+  - Calls to subprograms defined in instances
+  - Entry calls
+  - Indirect calls using 'Access
+  - Requeue statements
+  - Select statements
+  - Synchronous task suspension
+
+  and does not emit compile-time diagnostics or run-time checks.
+
+
 .. index:: -gnatk  (gcc)
 
 :switch:`-gnatk={n}`
@@ -2195,7 +2221,7 @@ Alphabetical List of All Switches
 .. index:: --RTS  (gcc)
 
 :switch:`--RTS={rts-path}`
-  Specifies the default location of the runtime library. Same meaning as the
+  Specifies the default location of the run-time library. Same meaning as the
   equivalent ``gnatmake`` flag (:ref:`Switches_for_gnatmake`).
 
 
@@ -5062,7 +5088,7 @@ switches refine this default behavior.
   that a certain check will necessarily fail, it will generate code to
   do an unconditional 'raise', even if checks are suppressed. The
   compiler warns in this case. Another case in which checks may not be
-  eliminated is when they are embedded in certain run time routines such
+  eliminated is when they are embedded in certain run-time routines such
   as math library routines.
 
   Of course, run-time checks are omitted whenever the compiler can prove
@@ -5858,7 +5884,7 @@ Debugging Control
 Exception Handling Control
 --
 
-GNAT uses two methods for handling exceptions at run-time. The
+GNAT uses two methods for handling exceptions at run time. The
 ``setjmp/longjmp`` method saves the context when entering
 a frame with an exception handler. Then whe

[Ada] Secondary stack leak in loop iterator

2018-07-17 Thread Pierre-Marie de Rodat
When the evaluation of the loop iterator invokes a function whose
result relies on the secondary stack the compiler does not generate
code to release the consumed memory as soon as the loop terminates.

After this patch the following test works fine.

with Text_IO; use Text_IO;
pragma Warnings (Off);
with System.Secondary_Stack;
pragma Warnings (On);
procedure Sec_Stack_Leak is
   function F (X : String) return Integer is
   begin
  return 10;
   end F;

   function G (X : Integer) return String is
   begin
  return (1 .. X => 'x');
   end G;

   procedure Info is new System.Secondary_Stack.Ss_Info (Put_Line);

   procedure Nest is
   begin
  for I in Integer range 1 .. 100 loop
 for J in Integer range 1 .. F (G (10_000)) loop
null;
 end loop;
 Info;
  end loop;
  Info;
   end Nest;

begin
   Info;
   Nest;
   Info;
end Sec_Stack_Leak;

Commands:
  gnatmake -q sec_stack_leak.adb
  sec_stack_leak | grep "Current allocated space :" | uniq
Output:
  Current allocated space :  0 bytes

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

2018-07-17  Javier Miranda  

gcc/ada/

* sem_ch5.adb (Has_Call_Using_Secondary_Stack): Moved to library level
to reuse it.
(Analyze_Loop_Statement): Wrap the loop in a block when the evaluation
of the loop iterator relies on the secondary stack.--- gcc/ada/sem_ch5.adb
+++ gcc/ada/sem_ch5.adb
@@ -83,6 +83,12 @@ package body Sem_Ch5 is
--  messages. This variable is recursively saved on entry to processing the
--  construct, and restored on exit.
 
+   function Has_Call_Using_Secondary_Stack (N : Node_Id) return Boolean;
+   --  N is the node for an arbitrary construct. This function searches the
+   --  construct N to see if any expressions within it contain function
+   --  calls that use the secondary stack, returning True if any such call
+   --  is found, and False otherwise.
+
procedure Preanalyze_Range (R_Copy : Node_Id);
--  Determine expected type of range or domain of iteration of Ada 2012
--  loop by analyzing separate copy. Do the analysis and resolution of the
@@ -2692,12 +2698,6 @@ package body Sem_Ch5 is
   --  forms. In this case it is not sufficent to check the static predicate
   --  function only, look for a dynamic predicate aspect as well.
 
-  function Has_Call_Using_Secondary_Stack (N : Node_Id) return Boolean;
-  --  N is the node for an arbitrary construct. This function searches the
-  --  construct N to see if any expressions within it contain function
-  --  calls that use the secondary stack, returning True if any such call
-  --  is found, and False otherwise.
-
   procedure Process_Bounds (R : Node_Id);
   --  If the iteration is given by a range, create temporaries and
   --  assignment statements block to capture the bounds and perform
@@ -2782,65 +2782,6 @@ package body Sem_Ch5 is
  end if;
   end Check_Predicate_Use;
 
-  
-  -- Has_Call_Using_Secondary_Stack --
-  
-
-  function Has_Call_Using_Secondary_Stack (N : Node_Id) return Boolean is
- function Check_Call (N : Node_Id) return Traverse_Result;
- --  Check if N is a function call which uses the secondary stack
-
- 
- -- Check_Call --
- 
-
- function Check_Call (N : Node_Id) return Traverse_Result is
-Nam  : Node_Id;
-Subp : Entity_Id;
-Typ  : Entity_Id;
-
- begin
-if Nkind (N) = N_Function_Call then
-   Nam := Name (N);
-
-   --  Obtain the subprogram being invoked
-
-   loop
-  if Nkind (Nam) = N_Explicit_Dereference then
- Nam := Prefix (Nam);
-
-  elsif Nkind (Nam) = N_Selected_Component then
- Nam := Selector_Name (Nam);
-
-  else
- exit;
-  end if;
-   end loop;
-
-   Subp := Entity (Nam);
-   Typ  := Etype (Subp);
-
-   if Requires_Transient_Scope (Typ) then
-  return Abandon;
-
-   elsif Sec_Stack_Needed_For_Return (Subp) then
-  return Abandon;
-   end if;
-end if;
-
---  Continue traversing the tree
-
-return OK;
- end Check_Call;
-
- function Check_Calls is new Traverse_Func (Check_Call);
-
-  --  Start of processing for Has_Call_Using_Secondary_Stack
-
-  begin
- return Check_Calls (N) = Abandon;
-  end Has_Call_Using_Secondary_Stack;
-
   
   -- Process_Bounds --
   
@@ -3644,6 +3585,56 @@ package body Sem_Ch5 is
  end;
   end if;
 
+  --  Wrap the loop in a block when the evaluation of the loop iterator

[Ada] Attach the special GNATprove HEAP entity to the Standard package

2018-07-17 Thread Pierre-Marie de Rodat
In GNATprove mode we use frontend cross-references to synthesize the
Global contract of subprograms with SPARK_Mode => Off and represent
a read/write via a pointer as a read/write of a special entity called
HEAP. This entity is now attached to the Standard package, so that we can
safely check the Ekind of its Scope, which now happens in Scope_Within.

This only affects GNATprove, so no frontend test provided.

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

2018-07-17  Piotr Trojanek  

gcc/ada/

* lib-xref-spark_specific.adb (Create_Heap): Attach the HEAP entity to
the Standard package.--- gcc/ada/lib-xref-spark_specific.adb
+++ gcc/ada/lib-xref-spark_specific.adb
@@ -287,6 +287,7 @@ package body SPARK_Specific is
 
  Set_Ekind   (Heap, E_Variable);
  Set_Is_Internal (Heap, True);
+ Set_Scope   (Heap, Standard_Standard);
  Set_Has_Fully_Qualified_Name (Heap);
   end Create_Heap;
 



[Ada] Crash on case expression in build-in-place function

2018-07-17 Thread Pierre-Marie de Rodat
This patch modifies the recursive tree replication routine New_Copy_Tree to
create new entities and remap old entities to the new ones for constructs in
N_Expression_With_Actions nodes when requested by a caller. This in turn allows
the build-in-place mechanism to avoid sharing entities between the 4 variants
of returns it generates.

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

2018-07-17  Hristian Kirtchev  

gcc/ada/

* exp_ch6.adb (Build_Heap_Or_Pool_Allocator): Ensure that scoping
constructs and entities within receive new entities when replicating a
tree.
(Expand_N_Extended_Return_Statement): Ensure that scoping constructs
and entities within receive new entities when replicating a tree.
* sem_util.adb (New_Copy_Tree): Add new formal Scopes_In_EWA_OK.
(Visit_Entity): Visit entities within scoping constructs inside
expression with actions nodes when requested by the caller. Add blocks,
labels, and procedures to the list of entities which need replication.
* sem_util.ads (New_Copy_Tree): Add new formal Scopes_In_EWA_OK. Update
the comment on usage.

gcc/testsuite/

* gnat.dg/bip_case_expr.adb, gnat.dg/bip_case_expr_pkg.ads: New 
testcase.--- gcc/ada/exp_ch6.adb
+++ gcc/ada/exp_ch6.adb
@@ -4562,7 +4562,10 @@ package body Exp_Ch6 is
Fin_Mas_Id : constant Entity_Id :=
   Build_In_Place_Formal
 (Func_Id, BIP_Finalization_Master);
-   Orig_Expr  : constant Node_Id := New_Copy_Tree (Alloc_Expr);
+   Orig_Expr  : constant Node_Id :=
+  New_Copy_Tree
+(Source   => Alloc_Expr,
+ Scopes_In_EWA_OK => True);
Stmts  : constant List_Id := New_List;
Desig_Typ  : Entity_Id;
Local_Id   : Entity_Id;
@@ -5022,7 +5025,10 @@ package body Exp_Ch6 is
   Init_Assignment :=
 Make_Assignment_Statement (Loc,
   Name   => New_Occurrence_Of (Ret_Obj_Id, Loc),
-  Expression => New_Copy_Tree (Ret_Obj_Expr));
+  Expression =>
+New_Copy_Tree
+  (Source   => Ret_Obj_Expr,
+   Scopes_In_EWA_OK => True));
 
   Set_Etype (Name (Init_Assignment), Etype (Ret_Obj_Id));
   Set_Assignment_OK (Name (Init_Assignment));
@@ -5153,7 +5159,10 @@ package body Exp_Ch6 is
 Subtype_Mark =>
   New_Occurrence_Of
 (Etype (Ret_Obj_Expr), Loc),
-Expression   => New_Copy_Tree (Ret_Obj_Expr)));
+Expression   =>
+  New_Copy_Tree
+(Source   => Ret_Obj_Expr,
+ Scopes_In_EWA_OK => True)));
 
  else
 --  If the function returns a class-wide type we cannot
@@ -5193,7 +5202,11 @@ package body Exp_Ch6 is
  --  except we set Storage_Pool and Procedure_To_Call so
  --  it will use the user-defined storage pool.
 
- Pool_Allocator := New_Copy_Tree (Heap_Allocator);
+ Pool_Allocator :=
+   New_Copy_Tree
+ (Source   => Heap_Allocator,
+  Scopes_In_EWA_OK => True);
+
  pragma Assert (Alloc_For_BIP_Return (Pool_Allocator));
 
  --  Do not generate the renaming of the build-in-place
@@ -5235,7 +5248,11 @@ package body Exp_Ch6 is
  --  allocation.
 
  else
-SS_Allocator := New_Copy_Tree (Heap_Allocator);
+SS_Allocator :=
+  New_Copy_Tree
+(Source   => Heap_Allocator,
+ Scopes_In_EWA_OK => True);
+
 pragma Assert (Alloc_For_BIP_Return (SS_Allocator));
 
 --  The heap and pool allocators are marked as

--- gcc/ada/sem_util.adb
+++ gcc/ada/sem_util.adb
@@ -19505,10 +19505,11 @@ package body Sem_Util is
---
 
function New_Copy_Tree
- (Source: Node_Id;
-  Map   : Elist_Id   := No_Elist;
-  New_Sloc  : Source_Ptr := No_Location;
-  New_Scope : Entity_Id  := Empty) return Node_Id
+ (Source   : Node_Id;
+  Map  : Elist_Id   := No_Elist;
+  New_Sloc : Source_Ptr := No_Location;
+  New_Scope: Entity_Id  := Empty;
+  Scopes_In_EWA_OK : Boolean:= False) return Node_Id
is
   --  This routine per

[Ada] New ignored Ghost code removal mechanism

2018-07-17 Thread Pierre-Marie de Rodat
This patch reimplements the mechanism which removes ignored Ghost code from the
tree.

The previous mechanism proved to be unreliable because it assumed that no new
scoping constructs would be created after some ignored Ghost code had already
notified its enclosing scoping constructs that they contain such code. The
assumption can be broken by having a call to an ignored Ghost procedure within
the extended return statement of a function. The procedure call would signal
the enclosing function that it contains ignored Ghost code, however the return
statement would introduce an extra block, effectively hiding the procedure call
from the ignored Ghost code elimination pass.

The new mechanism implemented in this patch forgoes directed tree pruning in
favor of storing the actual ignored Ghost code, and later directly eliminating
it from the tree.

For this approach to operate efficiently, only "top level" ignored Ghost
constructs are stored. The top level constructs are essentially nodes which can
appear within a declarative or statement list and be safely rewritten into null
statements. This ensures that only "root" ignored Ghost construct need to be
processed, as opposed to all ignored Ghost nodes within a subtree.

The approach has one drawback however. Due to the generation and analysis of
ignored Ghost code, a construct may be recorded multiple times (usually twice).
The mechanism simply deals with this artefact instead of employing expensive
solutions such as hash tables or a common flag shared by all nodes to eliminate
the duplicates.


-- Source --


--  main.adb

with Ada.Text_IO; use Ada.Text_IO;

procedure Main is
   procedure Ghost_Proc with Ghost;
   procedure Ghost_Proc is
   begin
  Put_Line ("ERROR: Ghost_Proc called");
   end Ghost_Proc;

   function Func return Integer is
   begin
  return Res : Integer := 123 do
 Ghost_Proc;
  end return;
   end Func;

   Val : Integer with Ghost;

begin
   Val := Func;
end Main;


-- Compilation and output --


$ gcc -c -gnatDG main.adb
$ grep -c "ghost" main.adb.dg
0

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

2018-07-17  Hristian Kirtchev  

gcc/ada/

* alloc.ads: Update the allocation metrics of the ignored Ghost nodes
table.
* atree.adb: Add a soft link for a procedure which is invoked whenever
an ignored Ghost node or entity is created.
(Change_Node): Preserve relevant attributes which come from the Flags
table.
(Mark_New_Ghost_Node): Record a newly created ignored Ghost node or
entity.
(Rewrite): Preserve relevant attributes which come from the Flags
table.
(Set_Ignored_Ghost_Recording_Proc): New routine.
* atree.ads: Define an access-to-suprogram type for a soft link which
records a newly created ignored Ghost node or entity.
(Set_Ignored_Ghost_Recording_Proc): New routine.
* ghost.adb: Remove with and use clause for Lib.  Remove table
Ignored_Ghost_Units.  Add new table Ignored_Ghost_Nodes.
(Add_Ignored_Ghost_Unit): Removed.
(Initialize): Initialize the table which stores ignored Ghost nodes.
Set the soft link which allows Atree.Mark_New_Ghost_Node to record an
ignored Ghost node.
(Is_Ignored_Ghost_Unit): Use the ultimate original node when checking
an eliminated ignored Ghost unit.
(Lock): Release and lock the table which stores ignored Ghost nodes.
(Mark_And_Set_Ghost_Assignment): Record rather than propagate ignored
Ghost nodes.
(Mark_And_Set_Ghost_Procedure_Call): Record rather than propagate
ignored Ghost nodes.
(Mark_Ghost_Clause): Record rather than propagate ignored Ghost nodes.
(Mark_Ghost_Declaration_Or_Body): Record rather than propagate ignored
Ghost nodes.
(Mark_Ghost_Pragma): Record rather than propagate ignored Ghost nodes.
(Propagate_Ignored_Ghost_Code): Removed.
(Record_Ignored_Ghost_Node): New routine.
(Remove_Ignored_Ghost_Code): Reimplemented.
(Remove_Ignored_Ghost_Node): New routine.
(Ultimate_Original_Node): New routine.
* ghost.ads (Check_Ghost_Completion): Removed.
* sem_ch8.adb (Analyze_Use_Package): Remove obsolete code. Mark a use
package clause as ignored Ghost if applicable.
* sem_util.adb (Is_Body_Or_Package_Declaration): Reimplemented.--- gcc/ada/alloc.ads
+++ gcc/ada/alloc.ads
@@ -67,8 +67,8 @@ package Alloc is
In_Out_Warnings_Initial  : constant := 100;-- Sem_Warn
In_Out_Warnings_Increment: constant := 100;
 
-   Ignored_Ghost_Units_Initial  : constant := 20; -- Sem_Util
-   Ignored_Ghost_Units_Increment: constant := 50;
+   Ignored_Ghost_Nodes_Initial  : constant := 100;-- Ghost
+   Ignored_Ghost_Nodes_Increment: constant := 100;
 
  

[Ada] Spurious error on unused Part_Of constituent

2018-07-17 Thread Pierre-Marie de Rodat
This patch updates the analysis of indicator Part_Of (or the lack thereof), to
ignore generic formal parameters for purposes of determining the visible state
space because they are not visible outside the generic and related instances.


-- Source --


--  gen_pack.ads

generic
   In_Formal : in Integer := 0;
   In_Out_Formal : in out Integer;

package Gen_Pack is
   Exported_In_Formal : Integer renames In_Formal;
   Exported_In_Out_Formal : Integer renames In_Out_Formal;

end Gen_Pack;

--  pack.ads

with Gen_Pack;

package Pack
  with Abstract_State => State
is
   procedure Force_Body;

   Val : Integer;

private
   package OK_1 is
 new Gen_Pack (In_Out_Formal => Val)
   with Part_Of => State;--  OK

   package OK_2 is
 new Gen_Pack (In_Formal => 1, In_Out_Formal => Val)
   with Part_Of => State;--  OK

   package Error_1 is--  Error
 new Gen_Pack (In_Out_Formal => Val);
   package Error_2 is--  Error
 new Gen_Pack (In_Formal => 2, In_Out_Formal => Val);
end Pack;

--  pack.adb

package body Pack
  with Refined_State =>  --  Error
 (State => (OK_1.Exported_In_Formal,
OK_1.Exported_In_Out_Formal))
is
   procedure Force_Body is null;
end Pack;

--  gen_pack.ads

generic
   In_Formal : in Integer := 0;
   In_Out_Formal : in out Integer;

package Gen_Pack is
   Exported_In_Formal : Integer renames In_Formal;
   Exported_In_Out_Formal : Integer renames In_Out_Formal;

end Gen_Pack;

--  pack.ads

with Gen_Pack;

package Pack
  with Abstract_State => State
is
   procedure Force_Body;

   Val : Integer;

private
   package OK_1 is
 new Gen_Pack (In_Out_Formal => Val)
   with Part_Of => State;--  OK

   package OK_2 is
 new Gen_Pack (In_Formal => 1, In_Out_Formal => Val)
   with Part_Of => State;--  OK

   package Error_1 is--  Error
 new Gen_Pack (In_Out_Formal => Val);
   package Error_2 is--  Error
 new Gen_Pack (In_Formal => 2, In_Out_Formal => Val);
end Pack;

--  pack.adb

package body Pack
  with Refined_State =>  --  Error
 (State => (OK_1.Exported_In_Formal,
OK_1.Exported_In_Out_Formal))
is
   procedure Force_Body is null;
end Pack;


-- Compilation and output --


$ gcc -c pack.adb
pack.adb:3:11: state "State" has unused Part_Of constituents
pack.adb:3:11: constant "Exported_In_Formal" defined at gen_pack.ads:6,
  instance at pack.ads:15
pack.adb:3:11: variable "Exported_In_Out_Formal" defined at gen_pack.ads:7,
  instance at pack.ads:15
pack.ads:19:12: indicator Part_Of is required in this context (SPARK RM
  7.2.6(2))
pack.ads:19:12: "Error_1" is declared in the private part of package "Pack"
pack.ads:21:12: indicator Part_Of is required in this context (SPARK RM
  7.2.6(2))
pack.ads:21:12: "Error_2" is declared in the private part of package "Pack"

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

2018-07-17  Hristian Kirtchev  

gcc/ada/

* sem_prag.adb (Has_Visible_State): Do not consider generic formals
because they are not part of the visible state space. Add constants to
the list of acceptable visible states.
(Propagate_Part_Of): Do not consider generic formals when propagating
the Part_Of indicator.
* sem_util.adb (Entity_Of): Do not follow renaming chains which go
through a generic formal because they are not visible for SPARK
purposes.
* sem_util.ads (Entity_Of): Update the comment on usage.--- gcc/ada/sem_prag.adb
+++ gcc/ada/sem_prag.adb
@@ -19982,6 +19982,13 @@ package body Sem_Prag is
  if not Comes_From_Source (Item_Id) then
 null;
 
+ --  Do not consider generic formals or their corresponding
+ --  actuals because they are not part of a visible state.
+ --  Note that both entities are marked as hidden.
+
+ elsif Is_Hidden (Item_Id) then
+null;
+
  --  The Part_Of indicator turns an abstract state or an
  --  object into a constituent of the encapsulating state.
 
@@ -28775,9 +28782,19 @@ package body Sem_Prag is
 if not Comes_From_Source (Item_Id) then
null;
 
+--  Do not consider generic formals or their corresponding actuals
+--  because they are not part of a visible state. Note that both
+--  entities are marked as hidden.
+
+

[Ada] Secondary stack leak in statements block located in a loop

2018-07-17 Thread Pierre-Marie de Rodat
When a loop iterator has a block declaration containing statements that invoke
functions whose result is returned on the secondary stack (such as a
string-returning function), the compiler fails to generate code to release the
allocated memory when the loop terminates.

After this patch the following test works fine.

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
pragma Warnings (Off);
with System.Secondary_Stack;
pragma Warnings (On);

procedure Small is
   procedure Info is new System.Secondary_Stack.Ss_Info (Put_Line);

   US : Unbounded_String;
begin
   Info;
   for J in 1 .. 100_000 loop
  Leaky_Block : declare
  begin
 if (J mod 2) = 0 then
Info;
 end if;

 Ada.Text_IO.Put_Line (To_String (US));  --  Test

 if (J mod 2) = 0 then
Info;
 end if;
  end Leaky_Block;
   end loop;
   Info;
end;

Command:
  gnatmake small.adb; small | grep "Current allocated space :" | uniq
Output:
  Current allocated space :  0 bytes

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

2018-07-17  Javier Miranda  

gcc/ada/

* exp_ch7.adb (Make_Transient_Block): When determining whether an
enclosing scope already handles the secondary stack, take into account
transient blocks nested in a block that do not manage the secondary
stack and are located within a loop.--- gcc/ada/exp_ch7.adb
+++ gcc/ada/exp_ch7.adb
@@ -8695,9 +8695,33 @@ package body Exp_Ch7 is
   Action : Node_Id;
   Par: Node_Id) return Node_Id
is
+  function Within_Loop_Statement (N : Node_Id) return Boolean;
+  --  Return True when N appears within a loop and no block is containing N
+
   function Manages_Sec_Stack (Id : Entity_Id) return Boolean;
   --  Determine whether scoping entity Id manages the secondary stack
 
+  ---
+  -- Within_Loop_Statement --
+  ---
+
+  function Within_Loop_Statement (N : Node_Id) return Boolean is
+ Par : Node_Id := Parent (N);
+
+  begin
+ while not (Nkind_In (Par,
+  N_Loop_Statement,
+  N_Handled_Sequence_Of_Statements,
+  N_Package_Specification)
+  or else Nkind (Par) in N_Proper_Body)
+ loop
+pragma Assert (Present (Par));
+Par := Parent (Par);
+ end loop;
+
+ return Nkind (Par) = N_Loop_Statement;
+  end Within_Loop_Statement;
+
   ---
   -- Manages_Sec_Stack --
   ---
@@ -8780,6 +8804,16 @@ package body Exp_Ch7 is
 elsif Ekind (Scop) = E_Loop then
exit;
 
+--  Ditto when the block appears without a block that does not
+--  manage the secondary stack and is located within a loop.
+
+elsif Ekind (Scop) = E_Block
+  and then not Manages_Sec_Stack (Scop)
+  and then Present (Block_Node (Scop))
+  and then Within_Loop_Statement (Block_Node (Scop))
+then
+   exit;
+
 --  The transient block does not need to manage the secondary stack
 --  when there is an enclosing construct which already does that.
 --  This optimization saves on SS_Mark and SS_Release calls but may



[Ada] Spurious error on Part_Of indicator

2018-07-17 Thread Pierre-Marie de Rodat
This patch modifies the verification of a missing Part_Of indicator to avoid
considering constants as visible state of a package instantiation because the
compiler cannot determine whether their values depend on variable input. This
diagnostic is left to GNATprove.


-- Source --


--  gnat.adc

pragma SPARK_Mode;

--  gen_pack.ads

generic
package Gen_Pack is
   Val : constant Integer := 123;
end Gen_Pack;

--  pack.ads

with Gen_Pack;

package Pack
  with Abstract_State => Pack_State
is
   procedure Force_Body;
private
   package Inst_1 is new Gen_Pack;   --  OK
   package Inst_2 is new Gen_Pack with Part_Of => Pack_State;--  OK
end Pack;

--  pack.adb

package body Pack
  with Refined_State => (Pack_State => Inst_2.Val)
is
   procedure Force_Body is null;
end Pack;

-
-- Compilation --
-

$ gcc -c pack.adb

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

2018-07-17  Hristian Kirtchev  

gcc/ada/

* sem_prag.adb (Has_Visible_State): Do not consider constants as
visible state because it is not possible to determine whether a
constant depends on variable input.
(Propagate_Part_Of): Add comment clarifying the behavior with respect
to constant.--- gcc/ada/sem_prag.adb
+++ gcc/ada/sem_prag.adb
@@ -19991,6 +19991,9 @@ package body Sem_Prag is
 
  --  The Part_Of indicator turns an abstract state or an
  --  object into a constituent of the encapsulating state.
+ --  Note that constants are considered here even though
+ --  they may not depend on variable input. This check is
+ --  left to the SPARK prover.
 
  elsif Ekind_In (Item_Id, E_Abstract_State,
   E_Constant,
@@ -28789,12 +28792,12 @@ package body Sem_Prag is
 elsif Is_Hidden (Item_Id) then
null;
 
---  A visible state has been found
+--  A visible state has been found. Note that constants are not
+--  considered here because it is not possible to determine whether
+--  they depend on variable input. This check is left to the SPARK
+--  prover.
 
-elsif Ekind_In (Item_Id, E_Abstract_State,
- E_Constant,
- E_Variable)
-then
+elsif Ekind_In (Item_Id, E_Abstract_State, E_Variable) then
return True;
 
 --  Recursively peek into nested packages and instantiations



[Ada] Avoid confusing warning on exception propagation in GNATprove mode

2018-07-17 Thread Pierre-Marie de Rodat
When compiling with the restriction No_Exception_Propagation, GNAT compiler
may issue a warning about exceptions not being propagated. This warning is
useless and confusing to users for GNATprove analysis, as GNATprove
precisely detects possible exceptions, so disable the warning in that mode.

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

2018-07-17  Yannick Moy  

gcc/ada/

* gnat1drv.adb (Gnat1drv): Do not issue warning about exception not
being propagated in GNATprove mode.--- gcc/ada/gnat1drv.adb
+++ gcc/ada/gnat1drv.adb
@@ -467,6 +467,12 @@ procedure Gnat1drv is
 
  Ineffective_Inline_Warnings := True;
 
+ --  Do not issue warnings for possible propagation of exception.
+ --  GNATprove already issues messages about possible exceptions.
+
+ No_Warn_On_Non_Local_Exception := True;
+ Warn_On_Non_Local_Exception := False;
+
  --  Disable front-end optimizations, to keep the tree as close to the
  --  source code as possible, and also to avoid inconsistencies between
  --  trees when using different optimization switches.



[Ada] Crash processing abstract state aspect of a package

2018-07-17 Thread Pierre-Marie de Rodat
The compiler may crash processing an aspect Part_Of used in a
package spec which has also an Initial_Condition aspect. After
this patch the following test compiles fine.

package P
with
  SPARK_Mode => On,
  Abstract_State => (Count_State),
  Initial_Condition => (Get_Count = 0)  -- Test
is
   type Count_Type is range 0 .. 16;

   function Get_Count return Count_Type;

   procedure Dummy;

private
   C: Count_Type := 0 with Part_Of => Count_State;  -- Test

   function Get_Count return Count_Type is (C);
end P;

package body P
with
  SPARK_Mode => On,
  Refined_State => (Count_State => C)
is
  procedure Dummy is null;
end P;

Command: gcc -c p.adb

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

2018-07-17  Javier Miranda  

gcc/ada/

* exp_ch13.adb (Expand_N_Freeze_Entity): Handle subtype declared for an
iterator.
* freeze.adb (Freeze_Expression): Handle freeze of an entity defined
outside of a subprogram body. This case was previously handled during
preanalysis; the frozen entities were remembered and left pending until
we continued freezeing entities outside of the subprogram. Now, when
climbing the parents chain to locate the correct placement for the
freezeing node, we check if the entity can be frozen and only when no
enclosing node is marked as Must_Not_Freeze the entity is frozen.
* sem_ch3.ads (Preanalyze_Default_Expression): Declaration moved to the
package body.
* sem_ch3.adb (Preanalyze_Default_Expression): Code adjusted to invoke
the new subprogram Preanalyze_With_Freezing_And_Resolve.
* sem_ch6.adb (Preanalyze_Formal_Expression): New subprogram.
(Analyze_Expression_Function, Process_Formals): Invoke
Preanalyze_Formal_Expression instead of Preanalyze_Spec_Expression
since the analysis of the formals may freeze entities.
(Analyze_Subprogram_Body_Helper): Skip building the body of the
class-wide clone for eliminated subprograms.
* sem_res.ads, sem_res.adb (Preanalyze_And_Resolve): New subprogram.
Its code is basically the previous version of this routine but extended
with an additional parameter which is used to specify if during
preanalysis we are allowed to freeze entities.  If the new parameter is
True then the subtree root node is marked as Must_Not_Freeze and no
entities are frozen during preanalysis.
(Preanalyze_And_Resolve): Invokes the internal version of
Preanalyze_And_Resolve without entity freezing.
(Preanalyze_With_Freezing_And_Resolve): Invokes the internal version of
Prenalyze_And_Resolve with freezing enabled.--- gcc/ada/exp_ch13.adb
+++ gcc/ada/exp_ch13.adb
@@ -470,6 +470,11 @@ package body Exp_Ch13 is
 and then Ekind (E_Scope) not in Concurrent_Kind
   then
  E_Scope := Scope (E_Scope);
+
+  --  The entity may be a subtype declared for an iterator.
+
+  elsif Ekind (E_Scope) = E_Loop then
+ E_Scope := Scope (E_Scope);
   end if;
 
   --  Remember that we are processing a freezing entity and its freezing

--- gcc/ada/freeze.adb
+++ gcc/ada/freeze.adb
@@ -6936,20 +6936,6 @@ package body Freeze is
---
 
procedure Freeze_Expression (N : Node_Id) is
-  In_Spec_Exp : constant Boolean := In_Spec_Expression;
-  Typ : Entity_Id;
-  Nam : Entity_Id;
-  Desig_Typ   : Entity_Id;
-  P   : Node_Id;
-  Parent_P: Node_Id;
-
-  Freeze_Outside : Boolean := False;
-  --  This flag is set true if the entity must be frozen outside the
-  --  current subprogram. This happens in the case of expander generated
-  --  subprograms (_Init_Proc, _Input, _Output, _Read, _Write) which do
-  --  not freeze all entities like other bodies, but which nevertheless
-  --  may reference entities that have to be frozen before the body and
-  --  obviously cannot be frozen inside the body.
 
   function Find_Aggregate_Component_Desig_Type return Entity_Id;
   --  If the expression is an array aggregate, the type of the component
@@ -7038,6 +7024,29 @@ package body Freeze is
  end if;
   end In_Expanded_Body;
 
+  --  Local variables
+
+  In_Spec_Exp : constant Boolean := In_Spec_Expression;
+  Typ : Entity_Id;
+  Nam : Entity_Id;
+  Desig_Typ   : Entity_Id;
+  P   : Node_Id;
+  Parent_P: Node_Id;
+
+  Freeze_Outside   : Boolean := False;
+  --  This flag is set true if the entity must be frozen outside the
+  --  current subprogram. This happens in the case of expander generated
+  --  subprograms (_Init_Proc, _Input, _Output, _Read, _Write) which do
+  --  not freeze all entities like other bodies, but which nevertheless
+  --  may reference entities that have to be frozen before the body and
+  --  obviously cannot be

[Ada] Missing check on illegal equality operation in subprogram

2018-07-17 Thread Pierre-Marie de Rodat
In Ada2012 it is illegal to declare an equality operation on an untagged
type when the operation is primitive and the type is already frozem (see
RM 4.5.2 (9.8)). previously the test to detect this illegality only examined
declarations within a package. This patch covers the case where type and
operation are both declared within a subprogram body.

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

2018-07-17  Ed Schonberg  

gcc/ada/

* sem_ch6.adb (Check_Untagged_Equality): Extend check to operations
declared in the same scope as the operand type, when that scope is a
procedure.

gcc/testsuite/

* gnat.dg/equal3.adb: New testcase.--- gcc/ada/sem_ch6.adb
+++ gcc/ada/sem_ch6.adb
@@ -8581,14 +8581,10 @@ package body Sem_Ch6 is
 
   if Is_Frozen (Typ) then
 
- --  If the type is not declared in a package, or if we are in the body
- --  of the package or in some other scope, the new operation is not
- --  primitive, and therefore legal, though suspicious. Should we
- --  generate a warning in this case ???
+ --  The check applies to a primitive operation, so check that type
+ --  and equality operation are in the same scope.
 
- if Ekind (Scope (Typ)) /= E_Package
-   or else Scope (Typ) /= Current_Scope
- then
+ if Scope (Typ) /= Current_Scope then
 return;
 
  --  If the type is a generic actual (sub)type, the operation is not
@@ -8631,7 +8627,7 @@ package body Sem_Ch6 is
 ("\move declaration to package spec (Ada 2012)?y?", Eq_Op);
end if;
 
---  Otherwise try to find the freezing point
+--  Otherwise try to find the freezing point for better message.
 
 else
Obj_Decl := Next (Parent (Typ));
@@ -8659,6 +8655,13 @@ package body Sem_Ch6 is
  end if;
 
  exit;
+
+  --  If we reach generated code for subprogram declaration
+  --  or body, it is the body that froze the type and the
+  --  declaration is legal.
+
+  elsif Sloc (Obj_Decl) = Sloc (Decl) then
+ return;
   end if;
 
   Next (Obj_Decl);

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/equal3.adb
@@ -0,0 +1,22 @@
+--  { dg-do compile }
+
+procedure Equal3 is
+type R is record
+   A, B : Integer;
+end record;
+
+package Pack is
+   type RR is record
+  C : R;
+   end record;
+
+   X : RR := (C => (A => 1, B => 1));
+   Y : RR := (C => (A => 1, B => 2));
+   pragma Assert (X /= Y); --@ASSERT:PASS
+
+end Pack;
+use Pack;
+function "=" (X, Y : R) return Boolean is (X.A = Y.A); --  { dg-error "equality operator must be declared before type \"R\" is frozen \\(RM 4.5.2 \\(9.8\\)\\) \\(Ada 2012\\)" }
+begin
+pragma Assert (X /= Y); --@ASSERT:FAIL
+end Equal3;



[Ada] Argument_String_To_List creates empty items from whitespace

2018-07-17 Thread Pierre-Marie de Rodat
This patch corrects an issue whereby leading whitespace in a non-quoted
argument list passed to Argument_String_To_List caused extraneous empty
arguments to be returned.

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

2018-07-17  Justin Squirek  

gcc/ada/

* libgnat/s-os_lib.adb (Argument_String_To_List): Fix trimming of
whitespace.

gcc/testsuite/

* gnat.dg/split_args.adb: New testcase.--- gcc/ada/libgnat/s-os_lib.adb
+++ gcc/ada/libgnat/s-os_lib.adb
@@ -178,7 +178,6 @@ package body System.OS_Lib is
 
   return Len;
end Args_Length;
-
-
-- Argument_String_To_List --
-
@@ -191,6 +190,9 @@ package body System.OS_Lib is
   Idx  : Integer;
   New_Argc : Natural := 0;
 
+  Backqd : Boolean := False;
+  Quoted : Boolean := False;
+
   Cleaned : String (1 .. Arg_String'Length);
   Cleaned_Idx : Natural;
   --  A cleaned up version of the argument. This function is taking
@@ -205,75 +207,71 @@ package body System.OS_Lib is
   Idx := Arg_String'First;
 
   loop
- exit when Idx > Arg_String'Last;
+ --  Skip extraneous spaces
 
- declare
-Backqd  : Boolean := False;
-Quoted  : Boolean := False;
-
- begin
-Cleaned_Idx := Cleaned'First;
+ while Idx <= Arg_String'Last and then Arg_String (Idx) = ' ' loop
+Idx := Idx + 1;
+ end loop;
 
-loop
-   --  An unquoted space is the end of an argument
+ exit when Idx > Arg_String'Last;
 
-   if not (Backqd or Quoted)
- and then Arg_String (Idx) = ' '
-   then
-  exit;
+ Cleaned_Idx := Cleaned'First;
+ Backqd  := False;
+ Quoted  := False;
 
-   --  Start of a quoted string
+ loop
+--  An unquoted space is the end of an argument
 
-   elsif not (Backqd or Quoted)
- and then Arg_String (Idx) = '"'
-   then
-  Quoted := True;
-  Cleaned (Cleaned_Idx) := Arg_String (Idx);
-  Cleaned_Idx := Cleaned_Idx + 1;
+if not (Backqd or Quoted)
+  and then Arg_String (Idx) = ' '
+then
+   exit;
 
-   --  End of a quoted string and end of an argument
+--  Start of a quoted string
 
-   elsif (Quoted and not Backqd)
- and then Arg_String (Idx) = '"'
-   then
-  Cleaned (Cleaned_Idx) := Arg_String (Idx);
-  Cleaned_Idx := Cleaned_Idx + 1;
-  Idx := Idx + 1;
-  exit;
+elsif not (Backqd or Quoted)
+  and then Arg_String (Idx) = '"'
+then
+   Quoted := True;
+   Cleaned (Cleaned_Idx) := Arg_String (Idx);
+   Cleaned_Idx := Cleaned_Idx + 1;
 
-   --  Turn off backquoting after advancing one character
+--  End of a quoted string and end of an argument
 
-   elsif Backqd then
-  Backqd := False;
-  Cleaned (Cleaned_Idx) := Arg_String (Idx);
-  Cleaned_Idx := Cleaned_Idx + 1;
+elsif (Quoted and not Backqd)
+  and then Arg_String (Idx) = '"'
+then
+   Cleaned (Cleaned_Idx) := Arg_String (Idx);
+   Cleaned_Idx := Cleaned_Idx + 1;
+   Idx := Idx + 1;
+   exit;
 
-   --  Following character is backquoted
+--  Turn off backquoting after advancing one character
 
-   elsif not Backslash_Is_Sep and then Arg_String (Idx) = '\' then
-  Backqd := True;
+elsif Backqd then
+   Backqd := False;
+   Cleaned (Cleaned_Idx) := Arg_String (Idx);
+   Cleaned_Idx := Cleaned_Idx + 1;
 
-   else
-  Cleaned (Cleaned_Idx) := Arg_String (Idx);
-  Cleaned_Idx := Cleaned_Idx + 1;
-   end if;
+--  Following character is backquoted
 
-   Idx := Idx + 1;
-   exit when Idx > Arg_String'Last;
-end loop;
+elsif not Backslash_Is_Sep and then Arg_String (Idx) = '\' then
+   Backqd := True;
 
---  Found an argument
+else
+   Cleaned (Cleaned_Idx) := Arg_String (Idx);
+   Cleaned_Idx := Cleaned_Idx + 1;
+end if;
 
-New_Argc := New_Argc + 1;
-New_Argv (New_Argc) :=
-  new String'(Cleaned (Cleaned'First .. Cleaned_Idx - 1));
+Idx := Idx + 1;
+exit when Idx > Arg_String'Last;
+ end loop;
 
---  Skip extraneous spaces
+ --  Found an argument
 
-while Idx <= Arg_String'Last and th

[Ada] Minor fix for imported C++ constructors

2018-07-17 Thread Pierre-Marie de Rodat
C++ constructors are imported as functions and then internally rewritten into
procedures taking the "this" pointer as first parameter.  Now this parameter is
not of an access type but of the type directly, so it must be In/Out and not
just In.

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

2018-07-17  Eric Botcazou  

gcc/ada/

* exp_disp.adb (Gen_Parameters_Profile): Make the _Init parameter an
In/Out parameter.
(Set_CPP_Constructors): Adjust comment accordingly.--- gcc/ada/exp_disp.adb
+++ gcc/ada/exp_disp.adb
@@ -8181,7 +8181,8 @@ package body Exp_Disp is
 
   function Gen_Parameters_Profile (E : Entity_Id) return List_Id;
   --  Duplicate the parameters profile of the imported C++ constructor
-  --  adding an access to the object as an additional parameter.
+  --  adding the "this" pointer to the object as the additional first
+  --  parameter under the usual form _Init : in out Typ.
 
   
   -- Gen_Parameters_Profile --
@@ -8198,6 +8199,8 @@ package body Exp_Disp is
  Make_Parameter_Specification (Loc,
Defining_Identifier =>
  Make_Defining_Identifier (Loc, Name_uInit),
+   In_Present  => True,
+   Out_Present => True,
Parameter_Type  => New_Occurrence_Of (Typ, Loc)));
 
  if Present (Parameter_Specifications (Parent (E))) then
@@ -8244,9 +8247,7 @@ package body Exp_Disp is
 Found := True;
 Loc   := Sloc (E);
 Parms := Gen_Parameters_Profile (E);
-IP:=
-  Make_Defining_Identifier (Loc,
-Chars => Make_Init_Proc_Name (Typ));
+IP:= Make_Defining_Identifier (Loc, Make_Init_Proc_Name (Typ));
 
 --  Case 1: Constructor of untagged type
 
@@ -8273,14 +8274,14 @@ package body Exp_Disp is
 
 --  Case 2: Constructor of a tagged type
 
---  In this case we generate the IP as a wrapper of the the
---  C++ constructor because IP must also save copy of the _tag
+--  In this case we generate the IP routine as a wrapper of the
+--  C++ constructor because IP must also save a copy of the _tag
 --  generated in the C++ side. The copy of the _tag is used by
 --  Build_CPP_Init_Procedure to elaborate derivations of C++ types.
 
 --  Generate:
--- procedure IP (_init : Typ; ...) is
---procedure ConstructorP (_init : Typ; ...);
+-- procedure IP (_init : in out Typ; ...) is
+--procedure ConstructorP (_init : in out Typ; ...);
 --pragma Import (ConstructorP);
 -- begin
 --ConstructorP (_init, ...);
@@ -8352,7 +8353,7 @@ package body Exp_Disp is
  loop
 --  Skip the following assertion with primary tags
 --  because Related_Type is not set on primary tag
---  components
+--  components.
 
 pragma Assert
   (Tag_Comp = First_Tag_Component (Typ)



[Ada] Assertion_Policy for class-wide precondition

2018-07-17 Thread Pierre-Marie de Rodat
This patch fixes the compiler to that class-wide preconditions on primitive
operations of interfaces are not checked at run time when the Assertion_Policy
indicates that they should be ignored. This is required by the RM.

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

2018-07-17  Bob Duff  

gcc/ada/

* exp_disp.adb (Build_Class_Wide_Check): Return early if the
precondition is supposed to be ignored.--- gcc/ada/exp_disp.adb
+++ gcc/ada/exp_disp.adb
@@ -809,7 +809,7 @@ package body Exp_Disp is
Prec := Next_Pragma (Prec);
 end loop;
 
-if No (Prec) then
+if No (Prec) or else Is_Ignored (Prec) then
return;
 end if;
 



[Ada] Configuration state not observed for instance bodies

2018-07-17 Thread Pierre-Marie de Rodat
This patch ensures that the processing of instantiated and inlined bodies uses
the proper configuration context available at the point of the instantiation or
inlining.

Previously configuration pragmas which appear prior to the context items of a
unit would lose their effect when a body is instantiated or inlined.

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

2018-07-17  Hristian Kirtchev  

gcc/ada/

* frontend.adb (Frontend): Update the call to Register_Config_Switches.
* inline.ads: Add new component Config_Switches to record
Pending_Body_Info which captures the configuration state of the pending
body.  Remove components Version, Version_Pragma, SPARK_Mode, and
SPARK_Mode_Pragma from record Pending_Body_Info because they are
already captured in component Config_Switches.
* opt.adb (Register_Opt_Config_Switches): Rename to
Register_Config_Switches.
(Restore_Opt_Config_Switches): Rename to Restore_Config_Switches.
(Save_Opt_Config_Switches): Rename to Save_Config_Switches. This
routine is now a function, and returns the saved configuration state as
an aggregate to avoid missing an attribute.
(Set_Opt_Config_Switches): Rename to Set_Config_Switches.
* opt.ads (Register_Opt_Config_Switches): Rename to
Register_Config_Switches.
(Restore_Opt_Config_Switches): Rename to Restore_Config_Switches.
(Save_Opt_Config_Switches): Rename to Save_Config_Switches. This
routine is now a function.
(Set_Opt_Config_Switches): Rename to Set_Config_Switches.
* par.adb (Par): Update the calls to configuration switch-related
subprograms.
* sem.adb (Semantics): Update the calls to configuration switch-related
subprograms.
* sem_ch10.adb (Analyze_Package_Body_Stub): Update the calls to
configuration switch-related subprograms.
(Analyze_Protected_Body_Stub): Update the calls to configuration
switch-related subprograms.
(Analyze_Subprogram_Body_Stub): Update calls to configuration
switch-related subprograms.
* sem_ch12.adb (Add_Pending_Instantiation): Update the capture of
pending instantiation attributes.
(Inline_Instance_Body): Update the capture of pending instantiation
attributes.  It is no longer needed to explicitly manipulate the SPARK
mode.
(Instantiate_Package_Body): Update the restoration of the context
attributes.
(Instantiate_Subprogram_Body): Update the restoration of context
attributes.
(Load_Parent_Of_Generic): Update the capture of pending instantiation
attributes.
(Set_Instance_Env): Update the way relevant configuration attributes
are saved and restored.

gcc/testsuite/

* gnat.dg/config_pragma1.adb, gnat.dg/config_pragma1_pkg.ads: New 
testcase.--- gcc/ada/frontend.adb
+++ gcc/ada/frontend.adb
@@ -303,7 +303,7 @@ begin
   --  capture the values of the configuration switches (see Opt for further
   --  details).
 
-  Opt.Register_Opt_Config_Switches;
+  Register_Config_Switches;
 
   --  Check for file which contains No_Body pragma
 

--- gcc/ada/inline.ads
+++ gcc/ada/inline.ads
@@ -63,21 +63,24 @@ package Inline is
--  See full description in body of Sem_Ch12 for more details
 
type Pending_Body_Info is record
-  Inst_Node : Node_Id;
-  --  Node for instantiation that requires the body
-
   Act_Decl : Node_Id;
   --  Declaration for package or subprogram spec for instantiation
 
-  Expander_Status : Boolean;
-  --  If the body is instantiated only for semantic checking, expansion
-  --  must be inhibited.
+  Config_Switches : Config_Switches_Type;
+  --  Capture the values of configuration switches
 
   Current_Sem_Unit : Unit_Number_Type;
   --  The semantic unit within which the instantiation is found. Must be
   --  restored when compiling the body, to insure that internal entities
   --  use the same counter and are unique over spec and body.
 
+  Expander_Status : Boolean;
+  --  If the body is instantiated only for semantic checking, expansion
+  --  must be inhibited.
+
+  Inst_Node : Node_Id;
+  --  Node for instantiation that requires the body
+
   Scope_Suppress   : Suppress_Record;
   Local_Suppress_Stack_Top : Suppress_Stack_Entry_Ptr;
   --  Save suppress information at the point of instantiation. Used to
@@ -93,21 +96,8 @@ package Inline is
   --  This means we have to capture this information from the current scope
   --  at the point of instantiation.
 
-  Version : Ada_Version_Type;
-  --  The body must be compiled with the same language version as the
-  --  spec. The version may be set by a configuration pragma in a separate
-  --  file or in the current file, and may differ from body to body.
-
-  Versio

[Ada] Use standard version of s-memory.adb for mingw32

2018-07-17 Thread Pierre-Marie de Rodat
This patch switches mingw32 targets to use the standard version of s-memory.adb
as Windows now has the capability of limiting the amount of memory used by
process.

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

2018-07-17  Patrick Bernardi  

gcc/ada/

* libgnat/s-memory__mingw.adb: Remove.
* Makefile.rtl: Remove s-memory.adb target pair from the Cygwin/Mingw32
section.

gcc/testsuite/

* gnat.dg/memorytest.adb: New testcase.--- gcc/ada/Makefile.rtl
+++ gcc/ada/Makefile.rtl
@@ -1960,19 +1960,17 @@ endif
 # Cygwin/Mingw32
 ifeq ($(strip $(filter-out cygwin% mingw32% pe,$(target_os))),)
   # Cygwin provides a full Posix environment, and so we use the default
-  # versions of s-memory and g-socthi rather than the Windows-specific
-  # MinGW versions.  Ideally we would use all the default versions for
-  # Cygwin and none of the MinGW versions, but for historical reasons
-  # the Cygwin port has always been a CygMing frankenhybrid and it is
-  # a long-term project to disentangle them.
+  # versions g-socthi rather than the Windows-specific MinGW version.
+  # Ideally we would use all the default versions for Cygwin and none
+  # of the MinGW versions, but for historical reasons the Cygwin port
+  # has always been a CygMing frankenhybrid and it is a long-term project
+  # to disentangle them.
   ifeq ($(strip $(filter-out cygwin%,$(target_os))),)
 LIBGNAT_TARGET_PAIRS = \
-s-memory.adbhttp://www.gnu.org/licenses/>.  --
---  --
--- GNAT was originally developed  by the GNAT team at  New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc.  --
---  --
---
-
---  This version provides ways to limit the amount of used memory for systems
---  that do not have OS support for that.
-
---  The amount of available memory available for dynamic allocation is limited
---  by setting the environment variable GNAT_MEMORY_LIMIT to the number of
---  kilobytes that can be used.
---
---  Windows is currently using this version.
-
-with Ada.Exceptions;
-with System.Soft_Links;
-
-package body System.Memory is
-
-   use Ada.Exceptions;
-   use System.Soft_Links;
-
-   function c_malloc (Size : size_t) return System.Address;
-   pragma Import (C, c_malloc, "malloc");
-
-   procedure c_free (Ptr : System.Address);
-   pragma Import (C, c_free, "free");
-
-   function c_realloc
- (Ptr : System.Address; Size : size_t) return System.Address;
-   pragma Import (C, c_realloc, "realloc");
-
-   function msize (Ptr : System.Address) return size_t;
-   pragma Import (C, msize, "_msize");
-
-   function getenv (Str : String) return System.Address;
-   pragma Import (C, getenv);
-
-   function atoi (Str : System.Address) return Integer;
-   pragma Import (C, atoi);
-
-   Available_Memory : size_t := 0;
-   --  Amount of memory that is available for heap allocations.
-   --  A value of 0 means that the amount is not yet initialized.
-
-   Msize_Accuracy   : constant := 4096;
-   --  Defines the amount of memory to add to requested allocation sizes,
-   --  because malloc may return a bigger block than requested. As msize
-   --  is used when by Free, it must be used on allocation as well. To
-   --  prevent underflow of available_memory we need to use a reserve.
-
-   procedure Check_Available_Memory (Size : size_t);
-   --  This routine must be called while holding the task lock. When the
-   --  memory limit is not yet initialized, it will be set to the value of
-   --  the GNAT_MEMORY_LIMIT environment variable or to unlimited if that
-   --  does not exist. If the size is larger than the amount of available
-   --  memory, the task lock will be freed and a storage_error exception
-   --  will be raised.
-
-   ---
-   -- Alloc --
-   ---
-
-   function Alloc (Size : size_t) return System.Address is
-  Result  : System.Address;
-  Actual_Size : size_t := Size;
-
-   begin
-  if Size = size_t'Last then
- Raise_Exception (Storage_Error'Identity, "object too large");
-  end if;
-
-  --  Change size from zero to non-zero. We still want a proper pointer
-  --  for the zero case because pointers to zero length objects have to
-  --  be distinct, but we can't just go ahead and allocate zero bytes,
-  --  since some malloc's return zero for a zero argument.
-
-  if Size = 0 then
- Actual_Size := 1;
-  end if;
-
-  Lock_Task.all;
-
-  if Actual_Size + Msize_Accuracy >= Available_Memory then
- Check_Available_Memory (Size + Msize_Accuracy);
-  end if;
-
-  Result := c_malloc (Actual_Size);
-
-  if Result /= System.Null_Address then
- Available_Memory := Available_Memory - msize (Result);
-

[Ada] Faulty ignored Ghost code removal

2018-07-17 Thread Pierre-Marie de Rodat
This patch ensures that removal of ignored Ghost code is the absolute last
operation performed on the tree. Previously the removal was performed prior to
issuing delayed warnings, however the warning mechanism may see a heavily
modified tree and fail.

No small reproducer available.

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

2018-07-17  Hristian Kirtchev  

gcc/ada/

* frontend.adb (Frontend): The removal of ignored Ghost code must be
the last semantic operation performed on the tree.--- gcc/ada/frontend.adb
+++ gcc/ada/frontend.adb
@@ -451,11 +451,6 @@ begin
 
Check_Elaboration_Scenarios;
 
-   --  Remove any ignored Ghost code as it must not appear in the
-   --  executable.
-
-   Remove_Ignored_Ghost_Code;
-
 --  Examine all top level scenarios collected during analysis and
 --  resolution in order to diagnose conditional ABEs, even in the
 --  presence of serious errors.
@@ -483,6 +478,14 @@ begin
 Sem_Warn.Output_Unreferenced_Messages;
 Sem_Warn.Check_Unused_Withs;
 Sem_Warn.Output_Unused_Warnings_Off_Warnings;
+
+--  Remove any ignored Ghost code as it must not appear in the
+--  executable. This action must be performed last because it
+--  heavily alters the tree.
+
+if Operating_Mode = Generate_Code or else GNATprove_Mode then
+   Remove_Ignored_Ghost_Code;
+end if;
  end if;
   end if;
end;



[Ada] Fix incompatibility Default_Scalar_Storage_Order/tagged types

2018-07-17 Thread Pierre-Marie de Rodat
The pragma Default_Scalar_Storage_Order cannot reliably be used to set the
non-default scalar storage order for a program that declares tagged types, if
it also declares user-defined primitives.

This is fixed by making Make_Tags use the same base array type as Make_DT and
Make_Secondary_DT when accessing the array of user-defined primitives.

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

2018-07-17  Eric Botcazou  

gcc/ada/

* exp_disp.adb (Make_Tags): When the type has user-defined primitives,
build the access type that is later used by Build_Get_Prim_Op_Address
as pointing to a subtype of Ada.Tags.Address_Array.

gcc/testsuite/

* gnat.dg/sso10.adb, gnat.dg/sso10_pkg.ads: New testcase.--- gcc/ada/exp_disp.adb
+++ gcc/ada/exp_disp.adb
@@ -7179,7 +7179,7 @@ package body Exp_Disp is
  Analyze_List (Result);
 
   -- Generate:
-  --   type Typ_DT is array (1 .. Nb_Prims) of Prim_Ptr;
+  --   subtype Typ_DT is Address_Array (1 .. Nb_Prims);
   --   type Typ_DT_Acc is access Typ_DT;
 
   else
@@ -7196,20 +7196,19 @@ package body Exp_Disp is
 Name_DT_Prims_Acc);
  begin
 Append_To (Result,
-  Make_Full_Type_Declaration (Loc,
+  Make_Subtype_Declaration (Loc,
 Defining_Identifier => DT_Prims,
-Type_Definition =>
-  Make_Constrained_Array_Definition (Loc,
-Discrete_Subtype_Definitions => New_List (
-  Make_Range (Loc,
-Low_Bound  => Make_Integer_Literal (Loc, 1),
-High_Bound => Make_Integer_Literal (Loc,
-   DT_Entry_Count
- (First_Tag_Component (Typ),
-Component_Definition =>
-  Make_Component_Definition (Loc,
-Subtype_Indication =>
-  New_Occurrence_Of (RTE (RE_Prim_Ptr), Loc);
+Subtype_Indication  =>
+  Make_Subtype_Indication (Loc,
+Subtype_Mark =>
+  New_Occurrence_Of (RTE (RE_Address_Array), Loc),
+Constraint =>
+  Make_Index_Or_Discriminant_Constraint (Loc, New_List (
+Make_Range (Loc,
+  Low_Bound  => Make_Integer_Literal (Loc, 1),
+  High_Bound => Make_Integer_Literal (Loc,
+ DT_Entry_Count
+   (First_Tag_Component (Typ);
 
 Append_To (Result,
   Make_Full_Type_Declaration (Loc,

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/sso10.adb
@@ -0,0 +1,16 @@
+--  { dg-do run }
+
+with SSO10_Pkg; use SSO10_Pkg;
+
+procedure SSO10 is
+
+  procedure Inner (R : Root'Class) is
+  begin
+Run (R);
+  end;
+
+  R : Root;
+
+begin
+  Inner (R);
+end;

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/sso10_pkg.ads
@@ -0,0 +1,9 @@
+pragma Default_Scalar_Storage_Order (High_Order_First);
+
+package SSO10_Pkg is
+
+  type Root is tagged null record;
+
+  procedure Run (R : Root) is null;
+
+end SSO10_Pkg;



[Ada] Spurious error on prefixed call in an instantiation

2018-07-17 Thread Pierre-Marie de Rodat
This patch fixes a spurious error on a prefixed call in an instance, when the
generic parameters include an interface type and an abstract operation of that
type, and the actuals in the instance include an interface type and a
corresponding abstract operation of it, with a different name than the
corresponding generic subprogram parameter. The patch also fixes a similar
error involving class-wide operations and generic private types.

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

2018-07-17  Ed Schonberg  

gcc/ada/

* sem_ch4.adb (Try_Object_Operation): Handle properly a prefixed call
in an instance, when the generic parameters include an interface type
and a abstract operation of that type, and the actuals in the instance
include an interface type and a corresponding abstract operation of it,
with a different name than the corresponding generic subprogram
parameter.

gcc/testsuite/

* gnat.dg/generic_call_cw.adb, gnat.dg/generic_call_iface.adb: New
testcase.--- gcc/ada/sem_ch4.adb
+++ gcc/ada/sem_ch4.adb
@@ -8928,11 +8928,38 @@ package body Sem_Ch4 is
(Anc_Type : Entity_Id;
 Error: out Boolean)
  is
+Candidate   : Entity_Id;
+--  If homonym is a renaming, examine the renamed program
+
 Cls_Type: Entity_Id;
 Hom : Entity_Id;
 Hom_Ref : Node_Id;
 Success : Boolean;
 
+function First_Formal_Match
+  (Typ : Entity_Id) return Boolean;
+--  Predicate to verify that the first formal of a class-wide
+--  candidate matches the type of the prefix.
+
+
+-- First_Formal_Match --
+
+
+function First_Formal_Match
+ (Typ : Entity_Id) return Boolean
+is
+   Ctrl : constant Entity_Id := First_Formal (Candidate);
+begin
+   return Present (Ctrl)
+ and then
+   (Base_Type (Etype (Ctrl)) = Typ
+ or else
+   (Ekind (Etype (Ctrl)) = E_Anonymous_Access_Type
+ and then
+   Base_Type
+(Designated_Type (Etype (Ctrl))) = Typ));
+end First_Formal_Match;
+
  begin
 Error := False;
 
@@ -8948,25 +8975,23 @@ package body Sem_Ch4 is
 
 while Present (Hom) loop
if Ekind_In (Hom, E_Procedure, E_Function)
- and then (not Is_Hidden (Hom) or else In_Instance)
- and then Scope (Hom) = Scope (Base_Type (Anc_Type))
- and then Present (First_Formal (Hom))
- and then
-   (Base_Type (Etype (First_Formal (Hom))) = Cls_Type
- or else
-   (Is_Access_Type (Etype (First_Formal (Hom)))
- and then
-   Ekind (Etype (First_Formal (Hom))) =
- E_Anonymous_Access_Type
- and then
-   Base_Type
- (Designated_Type (Etype (First_Formal (Hom =
-   Cls_Type))
+ and then Present (Renamed_Entity (Hom))
+ and then Is_Generic_Actual_Subprogram (Hom)
+   then
+  Candidate := Renamed_Entity (Hom);
+   else
+  Candidate := Hom;
+   end if;
+
+   if Ekind_In (Candidate, E_Procedure, E_Function)
+ and then (not Is_Hidden (Candidate) or else In_Instance)
+ and then Scope (Candidate) = Scope (Base_Type (Anc_Type))
+ and then First_Formal_Match (Cls_Type)
then
   --  If the context is a procedure call, ignore functions
   --  in the name of the call.
 
-  if Ekind (Hom) = E_Function
+  if Ekind (Candidate) = E_Function
 and then Nkind (Parent (N)) = N_Procedure_Call_Statement
 and then N = Name (Parent (N))
   then
@@ -8975,7 +9000,7 @@ package body Sem_Ch4 is
   --  If the context is a function call, ignore procedures
   --  in the name of the call.
 
-  elsif Ekind (Hom) = E_Procedure
+  elsif Ekind (Candidate) = E_Procedure
 and then Nkind (Parent (N)) /= N_Procedure_Call_Statement
   then
  goto Next_Hom;
@@ -8986,7 +9011,7 @@ package body Sem_Ch4 is
   Success := False;
 
   if No (Matching_Op) then
- Hom_Ref := New_Occurrence_Of (Hom, Sloc (Subprog));
+ Hom_Ref

[Ada] Spurious error -- "allocation from empty storage pool"

2018-07-31 Thread Pierre-Marie de Rodat
This patch fixes a bug in which if "pragma Default_Storage_Pool (null);"
is given, then a build-in-place function will get an incorrect error
message "allocation from empty storage pool" even though there is no
such allocation in the source program.

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

2018-07-31  Bob Duff  

gcc/ada/

* sem_res.adb (Resolve_Allocator): Do not complain about the
implicit allocator that occurs in the expansion of a return
statement for a build-in-place function.--- gcc/ada/sem_res.adb
+++ gcc/ada/sem_res.adb
@@ -5035,9 +5035,14 @@ package body Sem_Res is
  end;
   end if;
 
-  --  Check for allocation from an empty storage pool
+  --  Check for allocation from an empty storage pool. But do not complain
+  --  if it's a return statement for a build-in-place function, because the
+  --  allocator is there just in case the caller uses an allocator. If the
+  --  caller does use an allocator, it will be caught at the call site.
 
-  if No_Pool_Assigned (Typ) then
+  if No_Pool_Assigned (Typ)
+and then not Alloc_For_BIP_Return (N)
+  then
  Error_Msg_N ("allocation from empty storage pool!", N);
 
   --  If the context is an unchecked conversion, as may happen within an



[Ada] Deconstruct 'F' as a prefix for an ALI data

2018-07-31 Thread Pierre-Marie de Rodat
In GNATprove we used to store a variant of cross-reference information in
the ALI file in lines that started with an 'F' letter. This is no longer
the case, so the letter can be returned to the pool of unused prefixes.

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

2018-07-31  Piotr Trojanek  

gcc/ada/

* ali.adb (Known_ALI_Lines): Remove 'F' as a prefix for lines
related to the FORMAL analysis done by GNATprove.--- gcc/ada/ali.adb
+++ gcc/ada/ali.adb
@@ -39,7 +39,7 @@ package body ALI is
--  line type markers in the ALI file. This is used in Scan_ALI to detect
--  (or skip) invalid lines. The following letters are still available:
--
-   --B G H J K O Q Z
+   --B F G H J K O Q Z
 
Known_ALI_Lines : constant array (Character range 'A' .. 'Z') of Boolean :=
  ('V'=> True,   -- version
@@ -59,7 +59,6 @@ package body ALI is
   'Y'=> True,   -- limited_with
   'Z'=> True,   -- implicit with from instantiation
   'C'=> True,   -- SCO information
-  'F'=> True,   -- SPARK cross-reference information
   'T'=> True,   -- task stack information
   others => False);
 



[Ada] Spurious warning on iteration over range of 64-bit modular type

2018-07-31 Thread Pierre-Marie de Rodat
This patch suppresses a spurious warning on the use of a 64-bit modular type
in a quantified expression, where the range of iteration will include a bound
that appears larger than the run-time representation of Universal_Integer'last.

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

2018-07-31  Ed Schonberg  

gcc/ada/

* sem_eval.adb (Check_Non_Static_Context): Do not warn on an
integer literal greater than the upper bound of
Universal_Integer'Last when expansion is disabled, to avoid a
spurious warning over ranges involving 64-bit modular types.

gcc/testsuite/

* gnat.dg/iter3.adb: New testcase.--- gcc/ada/sem_eval.adb
+++ gcc/ada/sem_eval.adb
@@ -547,9 +547,15 @@ package body Sem_Eval is
   --  called in contexts like the expression of a number declaration where
   --  we certainly want to allow out of range values.
 
+  --  We inhibit the warning when expansion is disabled, because the
+  --  preanalysis of a range of a 64-bit modular type may appear to
+  --  violate the constraint on non-static Universal_Integer. If there
+  --  is a true overflow it will be diagnosed during full analysis.
+
   if Etype (N) = Universal_Integer
 and then Nkind (N) = N_Integer_Literal
 and then Nkind (Parent (N)) in N_Subexpr
+and then Expander_Active
 and then
   (Intval (N) < Expr_Value (Type_Low_Bound (Universal_Integer))
  or else

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/iter3.adb
@@ -0,0 +1,15 @@
+--  { dg-do compile }
+--  { dg-options "-gnata" }
+
+procedure Iter3 is
+   type Mod64 is mod 2 ** 64;
+
+   function F (X : Mod64) return Boolean is (X /= Mod64'Last);
+begin
+   pragma Assert (for all X in Mod64 => F(X));
+   pragma Assert (for all X in Mod64'Range => F(X));
+
+  for X in Mod64'Range loop
+  null;
+  end loop;
+end;



[Ada] Replace low-level calls to Ekind with high-level calls to Is_Formal

2018-07-31 Thread Pierre-Marie de Rodat
High-level wrappers are easier to read. This change came up while reading
some code related to GNATprove, but then uniformly applied to the entire
frontend. For the few remaining membership tests that could be replaced
by Is_Formal it is not obvious whether the high-level routine makes the
code better.

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

2018-07-31  Piotr Trojanek  

gcc/ada/

* exp_aggr.adb, exp_ch4.adb, exp_ch6.adb, lib-xref.adb,
repinfo.adb, sem_ch9.adb: Minor replace Ekind membership tests
with a wrapper routine.--- gcc/ada/exp_aggr.adb
+++ gcc/ada/exp_aggr.adb
@@ -7278,7 +7278,7 @@ package body Exp_Aggr is
 (Nkind (Expr_Q) = N_Type_Conversion
   or else
 (Is_Entity_Name (Expr_Q)
-  and then Ekind (Entity (Expr_Q)) in Formal_Kind))
+  and then Is_Formal (Entity (Expr_Q
   and then Tagged_Type_Expansion
 then
Static_Components := False;

--- gcc/ada/exp_ch4.adb
+++ gcc/ada/exp_ch4.adb
@@ -12547,7 +12547,7 @@ package body Exp_Ch4 is
 Sel_Comp := Parent (Sel_Comp);
  end loop;
 
- return Ekind (Entity (Prefix (Sel_Comp))) in Formal_Kind;
+ return Is_Formal (Entity (Prefix (Sel_Comp)));
   end Prefix_Is_Formal_Parameter;
 
--  Start of processing for Has_Inferable_Discriminants

--- gcc/ada/exp_ch6.adb
+++ gcc/ada/exp_ch6.adb
@@ -6799,7 +6799,7 @@ package body Exp_Ch6 is
 and then (Nkind_In (Exp, N_Type_Conversion,
  N_Unchecked_Type_Conversion)
 or else (Is_Entity_Name (Exp)
-   and then Ekind (Entity (Exp)) in Formal_Kind))
+   and then Is_Formal (Entity (Exp
   then
  --  When the return type is limited, perform a check that the tag of
  --  the result is the same as the tag of the return type.
@@ -6877,7 +6877,7 @@ package body Exp_Ch6 is
 or else Nkind_In (Exp, N_Type_Conversion,
N_Unchecked_Type_Conversion)
 or else (Is_Entity_Name (Exp)
-  and then Ekind (Entity (Exp)) in Formal_Kind)
+  and then Is_Formal (Entity (Exp)))
 or else Scope_Depth (Enclosing_Dynamic_Scope (Etype (Exp))) >
   Scope_Depth (Enclosing_Dynamic_Scope (Scope_Id)))
   then

--- gcc/ada/lib-xref.adb
+++ gcc/ada/lib-xref.adb
@@ -1034,7 +1034,7 @@ package body Lib.Xref is
  --  parameters may end up being marked as not coming from source
  --  although they are. Take these into account specially.
 
- elsif GNATprove_Mode and then Ekind (E) in Formal_Kind then
+ elsif GNATprove_Mode and then Is_Formal (E) then
 Ent := E;
 
  --  Entity does not come from source, but is a derived subprogram and

--- gcc/ada/repinfo.adb
+++ gcc/ada/repinfo.adb
@@ -428,7 +428,7 @@ package body Repinfo is
 
   List_Entities (E, Bytes_Big_Endian, True);
 
-   elsif Ekind (E) in Formal_Kind and then In_Subprogram then
+   elsif Is_Formal (E) and then In_Subprogram then
   null;
 
elsif Ekind_In (E, E_Entry,

--- gcc/ada/sem_ch9.adb
+++ gcc/ada/sem_ch9.adb
@@ -2358,7 +2358,7 @@ package body Sem_Ch9 is
  if Object_Access_Level (Target_Obj) >= Scope_Depth (Outer_Ent)
and then
  (not Is_Entity_Name (Target_Obj)
-   or else Ekind (Entity (Target_Obj)) not in Formal_Kind
+   or else not Is_Formal (Entity (Target_Obj))
or else Enclosing /= Scope (Entity (Target_Obj)))
  then
 Error_Msg_N



[Ada] Compiler failure on an extended_return_statement in a block

2018-07-31 Thread Pierre-Marie de Rodat
When compiling with an assertion-enabled compiler, Assert_Failure can be
raised when expanded an extended_return_statement whose enclosing scope
is not a function (such as when it's a block_statement). The simple fix
is to change the Assert to test Current_Subprogram rather than Current_Scope.
Three such Assert pragmas are corrected in this way.

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

2018-07-31  Gary Dismukes  

gcc/ada/

* exp_ch6.adb (Expand_N_Extended_Return_Statement): Replace
calls to Current_Scope in three assertions with calls to
Current_Subprogram.

gcc/testsuite/

* gnat.dg/block_ext_return_assert_failure.adb: New testcase.--- gcc/ada/exp_ch6.adb
+++ gcc/ada/exp_ch6.adb
@@ -4763,7 +4763,7 @@ package body Exp_Ch6 is
   --  the pointer to the object) they are always handled by means of
   --  simple return statements.
 
-  pragma Assert (not Is_Thunk (Current_Scope));
+  pragma Assert (not Is_Thunk (Current_Subprogram));
 
   if Nkind (Ret_Obj_Decl) = N_Object_Declaration then
  Exp := Expression (Ret_Obj_Decl);
@@ -4772,9 +4772,9 @@ package body Exp_Ch6 is
  --  then F and G are both b-i-p, or neither b-i-p.
 
  if Nkind (Exp) = N_Function_Call then
-pragma Assert (Ekind (Current_Scope) = E_Function);
+pragma Assert (Ekind (Current_Subprogram) = E_Function);
 pragma Assert
-  (Is_Build_In_Place_Function (Current_Scope) =
+  (Is_Build_In_Place_Function (Current_Subprogram) =
Is_Build_In_Place_Function_Call (Exp));
 null;
  end if;

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/block_ext_return_assert_failure.adb
@@ -0,0 +1,24 @@
+--  { dg-do compile }
+
+--  This test used to crash a compiler with assertions enabled
+
+procedure Block_Ext_Return_Assert_Failure is
+
+   function Return_Int return Integer is
+   begin
+  return 123;
+   end Return_Int;
+
+   function F return Integer is
+   begin
+  declare
+  begin
+ return Result : constant Integer := Return_Int do
+null;
+ end return;
+  end;
+   end F;
+
+begin
+   null;
+end Block_Ext_Return_Assert_Failure;



[Ada] Spurious error on the placement of aspect Global

2018-07-31 Thread Pierre-Marie de Rodat
This patch modifies the expansion of stand-alone subprogram bodies that appear
in the body of a protected type to properly associate aspects and pragmas to
the newly created spec for the subprogram body. As a result, the annotations
are properly associated with the initial declaration of the subprogram.

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

2018-07-31  Hristian Kirtchev  

gcc/ada/

* exp_ch9.adb (Analyze_Pragmas): New routine.
(Build_Private_Protected_Declaration): Code clean up. Relocate
relevant aspects and pragmas from the stand-alone body to the
newly created spec.  Explicitly analyze any pragmas that have
been either relocated or produced by the analysis of the
aspects.
(Move_Pragmas): New routine.
* sem_prag.adb (Find_Related_Declaration_Or_Body): Recognize the
case where a pragma applies to the internally created spec for a
stand-along subprogram body declared in a protected body.

gcc/testsuite/

* gnat.dg/global.adb, gnat.dg/global.ads: New testcase.--- gcc/ada/exp_ch9.adb
+++ gcc/ada/exp_ch9.adb
@@ -23,6 +23,7 @@
 --  --
 --
 
+with Aspects;  use Aspects;
 with Atree;use Atree;
 with Einfo;use Einfo;
 with Elists;   use Elists;
@@ -53,6 +54,7 @@ with Sem_Ch9;  use Sem_Ch9;
 with Sem_Ch11; use Sem_Ch11;
 with Sem_Elab; use Sem_Elab;
 with Sem_Eval; use Sem_Eval;
+with Sem_Prag; use Sem_Prag;
 with Sem_Res;  use Sem_Res;
 with Sem_Util; use Sem_Util;
 with Sinfo;use Sinfo;
@@ -290,7 +292,7 @@ package body Exp_Ch9 is
  (N   : Node_Id;
   Pid : Node_Id) return Node_Id;
--  This routine constructs the unprotected version of a protected
-   --  subprogram body, which is contains all of the code in the original,
+   --  subprogram body, which contains all of the code in the original,
--  unexpanded body. This is the version of the protected subprogram that is
--  called from all protected operations on the same object, including the
--  protected version of the same subprogram.
@@ -3483,14 +3485,95 @@ package body Exp_Ch9 is
function Build_Private_Protected_Declaration
  (N : Node_Id) return Entity_Id
is
+  procedure Analyze_Pragmas (From : Node_Id);
+  --  Analyze all pragmas which follow arbitrary node From
+
+  procedure Move_Pragmas (From : Node_Id; To : Node_Id);
+  --  Find all suitable source pragmas at the top of subprogram body From's
+  --  declarations and insert them after arbitrary node To.
+
+  -
+  -- Analyze_Pragmas --
+  -
+
+  procedure Analyze_Pragmas (From : Node_Id) is
+ Decl : Node_Id;
+
+  begin
+ Decl := Next (From);
+ while Present (Decl) loop
+if Nkind (Decl) = N_Pragma then
+   Analyze_Pragma (Decl);
+
+--  No candidate pragmas are available for analysis
+
+else
+   exit;
+end if;
+
+Next (Decl);
+ end loop;
+  end Analyze_Pragmas;
+
+  --
+  -- Move_Pragmas --
+  --
+
+  procedure Move_Pragmas (From : Node_Id; To : Node_Id) is
+ Decl   : Node_Id;
+ Insert_Nod : Node_Id;
+ Next_Decl  : Node_Id;
+
+  begin
+ pragma Assert (Nkind (From) = N_Subprogram_Body);
+
+ --  The pragmas are moved in an order-preserving fashion
+
+ Insert_Nod := To;
+
+ --  Inspect the declarations of the subprogram body and relocate all
+ --  candidate pragmas.
+
+ Decl := First (Declarations (From));
+ while Present (Decl) loop
+
+--  Preserve the following declaration for iteration purposes, due
+--  to possible relocation of a pragma.
+
+Next_Decl := Next (Decl);
+
+if Nkind (Decl) = N_Pragma then
+   Remove (Decl);
+   Insert_After (Insert_Nod, Decl);
+   Insert_Nod := Decl;
+
+--  Skip internally generated code
+
+elsif not Comes_From_Source (Decl) then
+   null;
+
+--  No candidate pragmas are available for relocation
+
+else
+   exit;
+end if;
+
+Decl := Next_Decl;
+ end loop;
+  end Move_Pragmas;
+
+  --  Local variables
+
+  Body_Id  : constant Entity_Id  := Defining_Entity (N);
   Loc  : constant Source_Ptr := Sloc (N);
-  Body_Id  : constant Entity_Id := Defining_Entity (N);
   Decl : Node_Id;
-  Plist: List_Id;
   Formal   : Entity_Id;
-  New_Spec : Node_Id;
+  Formals  : List_Id;
+  Spec : Node_Id;
   Spec_Id  : Entity_Id;
 
+   --  Start of processing for Build_Private_Protected_Declaration
+
begin
   Formal := F

[Ada] Wrong value after assignment of overlain record objects

2018-07-31 Thread Pierre-Marie de Rodat
This patch corrects an issue whereby objects of a record type with a
representation clause which are overlain by address would fail to get
assigned values properly when one or both of said objects were marked
volatile.

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

2018-07-31  Justin Squirek  

gcc/ada/

* exp_ch5.adb (Make_Field_Assign): Force temporarily generated
objects for assignment of overlaid user objects to be renamings
instead of constant declarations.

gcc/testsuite/

* gnat.dg/addr11.adb: New testcase.--- gcc/ada/exp_ch5.adb
+++ gcc/ada/exp_ch5.adb
@@ -1531,11 +1531,22 @@ package body Exp_Ch5 is
Selector_Name => New_Occurrence_Of (Disc, Loc));
 end if;
 
+--  Generate the assignment statement. When the left-hand side
+--  is an object with an address clause present, force generated
+--  temporaries to be renamings so as to correctly assign to any
+--  overlaid objects.
+
 A :=
   Make_Assignment_Statement (Loc,
 Name   =>
   Make_Selected_Component (Loc,
-Prefix=> Duplicate_Subexpr (Lhs),
+Prefix=>
+  Duplicate_Subexpr
+(Exp  => Lhs,
+ Name_Req => False,
+ Renaming_Req =>
+   Is_Entity_Name (Lhs)
+ and then Present (Address_Clause (Entity (Lhs,
 Selector_Name =>
   New_Occurrence_Of (Find_Component (L_Typ, C), Loc)),
 Expression => Expr);

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/addr11.adb
@@ -0,0 +1,28 @@
+--  { dg-do run }
+
+procedure Addr11 is
+
+  type Rec is record
+I : Short_Integer;
+C : Character;
+  end record;
+
+  type Derived is new Rec;
+  for Derived use record
+I at 1 range 0 .. 15;
+C at 0 range 0 .. 7;
+  end record;
+
+  Init : constant Rec := ( 1515, 'A' );
+
+  D1 : Derived;
+  D2 : Derived;
+  pragma Volatile (D2);
+  for D2'Address use D1'Address;
+
+begin
+  D2 := Derived (Init);
+  if D1 /= Derived (Init) then
+raise Program_Error;
+  end if;
+end;



[Ada] Fix alignment of mutex_t and cond_t type on 32-bit SPARC/Solaris

2018-07-31 Thread Pierre-Marie de Rodat
The alignment of the couple of types from System.OS_Interface was wrongly
set to 4 (32-bit) instead of 8 (64-bit) in 32-bit mode.

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

2018-07-31  Eric Botcazou  

gcc/ada/

*  libgnarl/s-osinte__solaris.ads (upad64_t): New private type.
(mutex_t): Use it for 'lock' and 'data' components.
(cond_t): Likewise for 'data' and use single 'flags' component.--- gcc/ada/libgnarl/s-osinte__solaris.ads
+++ gcc/ada/libgnarl/s-osinte__solaris.ads
@@ -536,17 +536,18 @@ private
end record;
pragma Convention (C, record_type_3);
 
+   type upad64_t is new Interfaces.Unsigned_64;
+
type mutex_t is record
   flags : record_type_3;
-  lock  : String (1 .. 8);
-  data  : String (1 .. 8);
+  lock  : upad64_t;
+  data  : upad64_t;
end record;
pragma Convention (C, mutex_t);
 
type cond_t is record
-  flag  : array_type_9;
-  Xtype : unsigned_long;
-  data  : String (1 .. 8);
+  flags : record_type_3;
+  data  : upad64_t;
end record;
pragma Convention (C, cond_t);
 



[Ada] Spurious error on default parameter in protected operation

2018-07-31 Thread Pierre-Marie de Rodat
This patch fixes a spurious compiler error on a call to a protected
operation whose profile includes a defaulted in-parameter that is a call
to another protected function of the same object.

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

2018-07-31  Ed Schonberg  

gcc/ada/

* exp_ch6.adb (Expand_Protected_Subprogram_Call): Handle
properly a protected call that includes a default parameter that
is a call to a protected function of the same type.

gcc/testsuite/

* gnat.dg/prot5.adb, gnat.dg/prot5_pkg.adb,
gnat.dg/prot5_pkg.ads: New testcase.--- gcc/ada/exp_ch6.adb
+++ gcc/ada/exp_ch6.adb
@@ -6387,6 +6387,30 @@ package body Exp_Ch6 is
  then
 Rec := New_Occurrence_Of (First_Entity (Current_Scope), Sloc (N));
 
+ --  A default parameter of a protected operation may be a call to
+ --  a protected function of the type. This appears as an internal
+ --  call in the profile of the operation, but if the context is an
+ --  external call we must convert the call into an external one,
+ --  using the protected object that is the target, so that:
+
+ -- Prot.P (F)
+ --  is transformed into
+ -- Prot.P (Prot.F)
+
+ elsif Nkind (Parent (N)) = N_Procedure_Call_Statement
+   and then Nkind (Name (Parent (N))) = N_Selected_Component
+   and then Is_Protected_Type (Etype (Prefix (Name (Parent (N)
+   and then Is_Entity_Name (Name (N))
+   and then Scope (Entity (Name (N))) =
+ Etype (Prefix (Name (Parent (N
+ then
+Rewrite (Name (N),
+  Make_Selected_Component (Sloc (N),
+Prefix => New_Copy_Tree (Prefix (Name (Parent (N,
+Selector_Name => Relocate_Node (Name (N;
+Analyze_And_Resolve (N);
+return;
+
  else
 --  If the context is the initialization procedure for a protected
 --  type, the call is legal because the called entity must be a

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/prot5.adb
@@ -0,0 +1,12 @@
+--  { dg-do run }
+--  { dg-options -gnata }
+
+with Prot5_Pkg;
+
+procedure Prot5 is
+begin
+   Prot5_Pkg.P.Proc (10);   --  explicit parameter
+   Prot5_Pkg.P.Proc (Prot5_Pkg.P.Get_Data); --  explicit call to protected operation
+   Prot5_Pkg.P.Proc;-- defaulted call.
+   pragma Assert (Prot5_Pkg.P.Get_Data = 80);
+end Prot5;

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/prot5_pkg.adb
@@ -0,0 +1,13 @@
+package body Prot5_Pkg is
+   protected body P is
+  function Get_Data return Integer is
+  begin
+ return Data;
+  end Get_Data;
+
+  procedure Proc (A : Integer := Get_Data) is
+  begin
+ Data := A * 2;
+  end Proc;
+   end P;
+end Prot5_Pkg;

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/prot5_pkg.ads
@@ -0,0 +1,8 @@
+package Prot5_Pkg is
+   protected P is
+  function Get_Data return Integer;
+  procedure Proc (A : Integer := Get_Data);
+   private
+  Data : Integer;
+   end P;
+end Prot5_Pkg;



[Ada] GNATmake fails to detect missing body

2018-07-31 Thread Pierre-Marie de Rodat
This patch corrects an issue whereby building a multi-unit compilation with
missing sources resulted in a cryptic "code generation" error instead of the
appropriate file not found error.


-- Source --


--  main.adb

with Types;
procedure Main is
begin
   null;
end;

--  types.ads

package Types is
  procedure Force;
end;


-- Compilation and output --


& gnatmake -q main.adb
gnatmake: "types.adb" not found

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

2018-07-31  Justin Squirek  

gcc/ada/

* lib-writ.adb (Write_With_Lines): Modfiy the generation of
dependencies within ali files so that source unit bodies are
properly listed even if said bodies are missing.  Perform legacy
behavior in GNATprove mode.
* lib-writ.ads: Modify documentation to reflect current behavior.--- gcc/ada/lib-writ.adb
+++ gcc/ada/lib-writ.adb
@@ -950,20 +950,35 @@ package body Lib.Writ is
Write_Info_Tab (25);
 
if Is_Spec_Name (Uname) then
-  Body_Fname :=
-Get_File_Name
-  (Get_Body_Name (Uname),
-   Subunit => False, May_Fail => True);
-
-  Body_Index :=
-Get_Unit_Index
-  (Get_Body_Name (Uname));
-
-  if Body_Fname = No_File then
- Body_Fname := Get_File_Name (Uname, Subunit => False);
- Body_Index := Get_Unit_Index (Uname);
-  end if;
 
+  --  In GNATprove mode we must write the spec of a unit which
+  --  requires a body if that body is not found. This will
+  --  allow partial analysis on incomplete sources.
+
+  if GNATprove_Mode then
+
+ Body_Fname :=
+   Get_File_Name (Get_Body_Name (Uname),
+   Subunit => False, May_Fail => True);
+
+ Body_Index := Get_Unit_Index (Get_Body_Name (Uname));
+
+ if Body_Fname = No_File then
+Body_Fname := Get_File_Name (Uname, Subunit => False);
+Body_Index := Get_Unit_Index (Uname);
+ end if;
+
+  --  In the normal path we don't allow failure in fetching the
+  --  name of the desired body unit so that it may be properly
+  --  referenced in the output ali - even if it is missing.
+
+  else
+ Body_Fname :=
+   Get_File_Name (Get_Body_Name (Uname),
+   Subunit => False, May_Fail => False);
+
+ Body_Index := Get_Unit_Index (Get_Body_Name (Uname));
+  end if;
else
   Body_Fname := Get_File_Name (Uname, Subunit => False);
   Body_Index := Get_Unit_Index (Uname);

--- gcc/ada/lib-writ.ads
+++ gcc/ada/lib-writ.ads
@@ -629,13 +629,13 @@ package Lib.Writ is
--  by the current unit. One Z line is present for each unit that is
--  only implicitly withed by the current unit. The first parameter is
--  the unit name in internal format. The second parameter is the file
-   --  name of the file that must be compiled to compile this unit. It is
-   --  usually the file for the body, except for packages which have no
-   --  body. For units that need a body, if the source file for the body
-   --  cannot be found, the file name of the spec is used instead. The
-   --  third parameter is the file name of the library information file
-   --  that contains the results of compiling this unit. The optional
-   --  modifiers are used as follows:
+   --  name of the body unit on which the current compliation depends -
+   --  except when in GNATprove mode. In GNATprove mode, when packages
+   --  which require a body have no associated source file, the file name
+   --  of the spec is used instead to allow partial analysis of incomplete
+   --  sources. The third parameter is the file name of the library
+   --  information file that contains the results of compiling this unit.
+   --  The optional modifiers are used as follows:
 
--E   pragma Elaborate applies to this unit
 



[Ada] Secondary stack leak with access-to-subprogram

2018-07-31 Thread Pierre-Marie de Rodat
This patch modifies call resolution to recognize when the designated type of
an access-to-subprogram requires secondary stack management, and establish
the proper transient block.


-- Source --


--  leak7.adb

procedure Leak7 is
   Max_Iterations : constant := 10_000;

   function Func return String is
   begin
  return "Will this leak? Or will it dry?";
   end Func;

   type Func_Ptr is access function return String;

   procedure Anonymous_Leak (Func : access function return String) is
   begin
  for Iteration in 1 .. Max_Iterations loop
 declare
Val : constant String := Func.all;
 begin null; end;
  end loop;
   end Anonymous_Leak;

   procedure Named_Leak (Func : Func_Ptr) is
   begin
  for Iteration in 1 .. Max_Iterations loop
 declare
Val : constant String := Func.all;
 begin null; end;
  end loop;
   end Named_Leak;

begin
   Anonymous_Leak (Func'Access);
   Named_Leak (Func'Access);
end Leak7;


-- Compilation and output --


$ gnatmake -q leak7.adb
$ valgrind ./leak7 >& leak7.txt
$ grep -c "still reachable" leak7.txt
0

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

2018-07-31  Hristian Kirtchev  

gcc/ada/

* sem_res.adb (Resolve_Call): Establish a transient scope to
manage the secondary stack when the designated type of an
access-to-subprogram requires it.--- gcc/ada/sem_res.adb
+++ gcc/ada/sem_res.adb
@@ -6433,7 +6433,7 @@ package body Sem_Res is
  null;
 
   elsif Expander_Active
-and then Ekind (Nam) = E_Function
+and then Ekind_In (Nam, E_Function, E_Subprogram_Type)
 and then Requires_Transient_Scope (Etype (Nam))
   then
  Establish_Transient_Scope (N, Manage_Sec_Stack => True);



[Ada] Remove inappropriate test from Is_By_Reference_Type

2021-09-20 Thread Pierre-Marie de Rodat
The result returned by the predicate may change depending on whether an
error was posted on the type, which complicates further error reporting.

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

gcc/ada/

* sem_aux.adb (Is_By_Reference_Type): Do not test Error_Posted.diff --git a/gcc/ada/sem_aux.adb b/gcc/ada/sem_aux.adb
--- a/gcc/ada/sem_aux.adb
+++ b/gcc/ada/sem_aux.adb
@@ -846,10 +846,7 @@ package body Sem_Aux is
   Btype : constant Entity_Id := Base_Type (Ent);
 
begin
-  if Error_Posted (Ent) or else Error_Posted (Btype) then
- return False;
-
-  elsif Is_Private_Type (Btype) then
+  if Is_Private_Type (Btype) then
  declare
 Utyp : constant Entity_Id := Underlying_Type (Btype);
  begin




[Ada] usage.adb: make -gnatw.c description clearer

2021-09-20 Thread Pierre-Marie de Rodat
The term "unrepped" can be hard to understand for users.

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

gcc/ada/

* usage.adb (Usage): Update -gnatw.c messages.diff --git a/gcc/ada/usage.adb b/gcc/ada/usage.adb
--- a/gcc/ada/usage.adb
+++ b/gcc/ada/usage.adb
@@ -483,8 +483,10 @@ begin
Write_Line (".B   turn off warnings for biased representation");
Write_Line ("c+   turn on warnings for constant conditional");
Write_Line ("C*   turn off warnings for constant conditional");
-   Write_Line (".c+  turn on warnings for unrepped components");
-   Write_Line (".C*  turn off warnings for unrepped components");
+   Write_Line (".c+  turn on warnings for components without " &
+ "representation clauses");
+   Write_Line (".C*  turn off warnings for components without " &
+ "representation clauses");
Write_Line ("_c*  turn on warnings for unknown " &
  "Compile_Time_Warning");
Write_Line ("_C   turn off warnings for unknown " &




[Ada] Move Build_And_Insert_Cuda_Initialization to Expand_CUDA_Package

2021-09-20 Thread Pierre-Marie de Rodat
This commit makes Build_And_Insert_Cuda_Initialization an internal
procedure and creates a new Expand_CUDA_Package procedure which calls
Build_And_Insert_Cuda_Initialization.

This is a small, self-contained refactoring that does not impact any
feature or fix any bug - it just makes future commits that do add new
features smaller and easier to review.

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

gcc/ada/

* exp_ch7.adb (Expand_N_Package_Body): Replace
Build_And_Insert_Cuda_Initialization with Expand_CUDA_Package.
* gnat_cuda.adb (Expand_CUDA_Package): New procedure.
(Build_And_Insert_Cuda_Initialization): Make internal.
* gnat_cuda.ads (Expand_CUDA_Package): New procedure.
(Build_And_Insert_Cuda_Initialization): Remove from spec.diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -5918,12 +5918,7 @@ package body Exp_Ch7 is
 Build_Static_Dispatch_Tables (N);
  end if;
 
- --  If procedures marked with CUDA_Global have been defined within N,
- --  we need to register them with the CUDA runtime at program startup.
- --  This requires multiple declarations and function calls which need
- --  to be appended to N's declarations.
-
- Build_And_Insert_CUDA_Initialization (N);
+ Expand_CUDA_Package (N);
 
  Build_Task_Activation_Call (N);
 


diff --git a/gcc/ada/gnat_cuda.adb b/gcc/ada/gnat_cuda.adb
--- a/gcc/ada/gnat_cuda.adb
+++ b/gcc/ada/gnat_cuda.adb
@@ -66,6 +66,25 @@ package body GNAT_CUDA is
--  least one procedure marked with aspect CUDA_Global. The values are
--  Elists of the marked procedures.
 
+   procedure Build_And_Insert_CUDA_Initialization (N : Node_Id);
+   --  Builds declarations necessary for CUDA initialization and inserts them
+   --  in N, the package body that contains CUDA_Global nodes. These
+   --  declarations are:
+   --
+   --* A symbol to hold the pointer P to the CUDA fat binary.
+   --
+   --* A type definition T for a wrapper that contains the pointer to the
+   --  CUDA fat binary.
+   --
+   --* An object of the aforementioned type to hold the aforementioned
+   --  pointer.
+   --
+   --* For each CUDA_Global procedure in the package, a declaration of a C
+   --  string containing the function's name.
+   --
+   --* A procedure that takes care of calling CUDA functions that register
+   --  CUDA_Global procedures with the runtime.
+
function Get_CUDA_Kernels (Pack_Id : Entity_Id) return Elist_Id;
--  Returns an Elist of all procedures marked with pragma CUDA_Global that
--  are declared within package body Pack_Body. Returns No_Elist if Pack_Id
@@ -94,6 +113,23 @@ package body GNAT_CUDA is
   Append_Elmt (Kernel, Kernels);
end Add_CUDA_Kernel;
 
+   procedure Expand_CUDA_Package (N : Node_Id) is
+   begin
+
+  --  If not compiling for the host, do not do anything.
+
+  if not Debug_Flag_Underscore_C then
+ return;
+  end if;
+
+  --  If procedures marked with CUDA_Global have been defined within N,
+  --  we need to register them with the CUDA runtime at program startup.
+  --  This requires multiple declarations and function calls which need
+  --  to be appended to N's declarations.
+
+  Build_And_Insert_CUDA_Initialization (N);
+   end Expand_CUDA_Package;
+
--
-- Hash --
--
@@ -524,7 +560,7 @@ package body GNAT_CUDA is
--  Start of processing for Build_And_Insert_CUDA_Initialization
 
begin
-  if CUDA_Node_List = No_Elist or not Debug_Flag_Underscore_C then
+  if CUDA_Node_List = No_Elist then
  return;
   end if;
 


diff --git a/gcc/ada/gnat_cuda.ads b/gcc/ada/gnat_cuda.ads
--- a/gcc/ada/gnat_cuda.ads
+++ b/gcc/ada/gnat_cuda.ads
@@ -82,26 +82,8 @@ package GNAT_CUDA is
--  Kernel is a procedure entity marked with CUDA_Global, Pack_Id is the
--  entity of its parent package body.
 
-   procedure Build_And_Insert_CUDA_Initialization (N : Node_Id);
-   --  Builds declarations necessary for CUDA initialization and inserts them
-   --  in N, the package body that contains CUDA_Global nodes. These
-   --  declarations are:
-   --
-   --* A symbol to hold the pointer to the CUDA fat binary
-   --
-   --* A type definition for a wrapper that contains the pointer to the
-   --  CUDA fat binary
-   --
-   --* An object of the aforementioned type to hold the aforementioned
-   --  pointer.
-   --
-   --* For each CUDA_Global procedure in the package, a declaration of a C
-   --  string containing the function's name.
-   --
-   --* A function that takes care of calling CUDA functions that register
-   --  CUDA_Global procedures with the runtime.
-   --
-   --* A boolean that holds the result of the call to the aforementioned
-   --  function.
+   procedure Expand_CUDA_Package (N : Node_Id);

[Ada] Only assign type to op if compatible

2021-09-20 Thread Pierre-Marie de Rodat
Before this commit, the following program would make the compiler crash:

procedure Main is
   ConstantString1 : aliased String := "Class1";
   My_Access : access String := ConstantString1'Access;
begin
   if "Class1" = My_Access then
  null;
   end if;
end Main;

This was because when an access type was given on the right side of an
operator, GNAT assumed that an interpretation for the operator existed.
This assumption resulted in no error being thrown and Gigi crashing when
encountering the malformed tree.

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

gcc/ada/

* sem_ch4.adb (Find_Non_Universal_Interpretations): Check if
types are compatible before adding interpretation.diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb
--- a/gcc/ada/sem_ch4.adb
+++ b/gcc/ada/sem_ch4.adb
@@ -6626,7 +6626,7 @@ package body Sem_Ch4 is
Get_Next_Interp (Index, It);
 end loop;
  end if;
-  else
+  elsif Has_Compatible_Type (R, T1) then
  Add_One_Interp (N, Op_Id, Standard_Boolean, Base_Type (T1));
   end if;
end Find_Non_Universal_Interpretations;




[Ada] Refactor scan_backend_switch to share logic across backends

2021-09-20 Thread Pierre-Marie de Rodat
This commit refactors scan_backend_switch to share logic across
adabkend.adb and back_end.adb. A side effect of this refactor is that
`-fdump-diagnostics-format` is now available with other backends.

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

gcc/ada/

* adabkend.adb (Scan_Back_End_Switches): Replace switch-scanning
logic with call to Backend_Utils.Scan_Common_Back_End_Switches.
* back_end.adb (Scan_Back_End_Switches): Replace switch-scanning
logic with call to Backend_Utils.Scan_Common_Back_End_Switches.
* backend_utils.adb: New file.
* backend_utils.ads: New file.
* gcc-interface/Make-lang.in: Add ada/backend_utils.o.diff --git a/gcc/ada/adabkend.adb b/gcc/ada/adabkend.adb
--- a/gcc/ada/adabkend.adb
+++ b/gcc/ada/adabkend.adb
@@ -22,15 +22,16 @@
 
 --  This is the version of the Back_End package for back ends written in Ada
 
-with Atree;use Atree;
+with Atree; use Atree;
+with Backend_Utils; use Backend_Utils;
 with Debug;
 with Lib;
-with Opt;  use Opt;
-with Output;   use Output;
-with Osint;use Osint;
-with Osint.C;  use Osint.C;
-with Switch.C; use Switch.C;
-with Types;use Types;
+with Opt;   use Opt;
+with Output;use Output;
+with Osint; use Osint;
+with Osint.C;   use Osint.C;
+with Switch.C;  use Switch.C;
+with Types; use Types;
 
 with System.OS_Lib; use System.OS_Lib;
 
@@ -182,48 +183,11 @@ package body Adabkend is
 
 return;
 
- --  Special check, the back-end switch -fno-inline also sets the
- --  front end flags to entirely inhibit all inlining. So we store it
- --  and set the appropriate flags.
-
- elsif Switch_Chars (First .. Last) = "fno-inline" then
-Lib.Store_Compilation_Switch (Switch_Chars);
-Opt.Disable_FE_Inline := True;
-return;
-
- --  Similar processing for -fpreserve-control-flow
-
- elsif Switch_Chars (First .. Last) = "fpreserve-control-flow" then
-Lib.Store_Compilation_Switch (Switch_Chars);
-Opt.Suppress_Control_Flow_Optimizations := True;
-return;
-
- --  Recognize -gxxx switches
-
- elsif Switch_Chars (First) = 'g' then
-Debugger_Level := 2;
-
-if First < Last then
-   case Switch_Chars (First + 1) is
-  when '0' =>
- Debugger_Level := 0;
-  when '1' =>
- Debugger_Level := 1;
-  when '2' =>
- Debugger_Level := 2;
-  when '3' =>
- Debugger_Level := 3;
-  when others =>
- null;
-   end case;
-end if;
-
- elsif Switch_Chars (First .. Last) = "S" then
-Generate_Asm := True;
-
  --  Ignore all other back-end switches
 
- elsif Is_Back_End_Switch (Switch_Chars) then
+ elsif Scan_Common_Back_End_Switch (Switch_Chars)
+or else Is_Back_End_Switch (Switch_Chars)
+ then
 null;
 
  --  Give error for junk switch


diff --git a/gcc/ada/back_end.adb b/gcc/ada/back_end.adb
--- a/gcc/ada/back_end.adb
+++ b/gcc/ada/back_end.adb
@@ -25,23 +25,24 @@
 
 --  This is the version of the Back_End package for GCC back ends
 
-with Atree;use Atree;
-with Debug;use Debug;
-with Elists;   use Elists;
-with Errout;   use Errout;
-with Lib;  use Lib;
-with Osint;use Osint;
-with Opt;  use Opt;
-with Osint.C;  use Osint.C;
-with Namet;use Namet;
-with Nlists;   use Nlists;
-with Stand;use Stand;
-with Sinput;   use Sinput;
-with Stringt;  use Stringt;
-with Switch;   use Switch;
-with Switch.C; use Switch.C;
-with System;   use System;
-with Types;use Types;
+with Atree; use Atree;
+with Backend_Utils; use Backend_Utils;
+with Debug; use Debug;
+with Elists;use Elists;
+with Errout;use Errout;
+with Lib;   use Lib;
+with Osint; use Osint;
+with Opt;   use Opt;
+with Osint.C;   use Osint.C;
+with Namet; use Namet;
+with Nlists;use Nlists;
+with Stand; use Stand;
+with Sinput;use Sinput;
+with Stringt;   use Stringt;
+with Switch;use Switch;
+with Switch.C;  use Switch.C;
+with System;use System;
+with Types; use Types;
 
 with System.OS_Lib; use System.OS_Lib;
 
@@ -266,52 +267,20 @@ package body Back_End is
  --  specific switches that the Ada front-end knows about.
 
  else
-Store_Compilation_Switch (Switch_Chars);
-
---  For gcc back ends, -fno-inline disables Inline pragmas only,
---  not Inline_Always to remain consistent with the always_inline
---  attribute behavior.
-
-if Switch_Chars (First .. Last) = "fno-inline" then
-   Opt.Disable_FE_Inline := True;
-
-  

[Ada] Spurious accessibility error on allocator in generic instance

2021-09-20 Thread Pierre-Marie de Rodat
This patch fixes an error in the compiler whereby an allocator for a
limited type within a generic instance may cause spurious compile-time
warnings and run-time errors.

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

gcc/ada/

* exp_ch4.adb (Expand_N_Type_Conversion): Add guard to protect
against calculating accessibility levels against internal
compiler-generated types.diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -12361,10 +12361,16 @@ package body Exp_Ch4 is
  --  an instantiation, otherwise the conversion will already have been
  --  rejected as illegal.
 
- --  Note: warnings are issued by the analyzer for the instance cases
+ --  Note: warnings are issued by the analyzer for the instance cases,
+ --  and, since we are late in expansion, a check is performed to
+ --  verify that neither the target type nor the operand type are
+ --  internally generated - as this can lead to spurious errors when,
+ --  for example, the operand type is a result of BIP expansion.
 
  elsif In_Instance_Body
and then Statically_Deeper_Relation_Applies (Target_Type)
+   and then not Is_Internal (Target_Type)
+   and then not Is_Internal (Operand_Type)
and then
  Type_Access_Level (Operand_Type) > Type_Access_Level (Target_Type)
  then




[Ada] Fix assertion in GNATprove_Mode

2021-09-20 Thread Pierre-Marie de Rodat
Avoid calling List_Rep_Info in Generate_SCIL and GNATprove_Mode, because
the representation info is not there. Otherwise, we fail an assertion.

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

gcc/ada/

* gnat1drv.adb (Gnat1drv): Avoid calling List_Rep_Info in
Generate_SCIL and GNATprove_Mode.
* repinfo.adb (List_Common_Type_Info): Fix comment.diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb
--- a/gcc/ada/gnat1drv.adb
+++ b/gcc/ada/gnat1drv.adb
@@ -1616,7 +1616,14 @@ begin
 
   Errout.Finalize (Last_Call => True);
   Errout.Output_Messages;
-  Repinfo.List_Rep_Info (Ttypes.Bytes_Big_Endian);
+
+  --  Back annotation of representation info is not done in CodePeer and
+  --  SPARK modes.
+
+  if not (Generate_SCIL or GNATprove_Mode) then
+ Repinfo.List_Rep_Info (Ttypes.Bytes_Big_Endian);
+  end if;
+
   Inline.List_Inlining_Info;
 
   --  Only write the library if the backend did not generate any error


diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb
--- a/gcc/ada/repinfo.adb
+++ b/gcc/ada/repinfo.adb
@@ -422,7 +422,8 @@ package body Repinfo is
 Write_Line (";");
  end if;
 
-  --  Alignment is not always set for task and protected types
+  --  Alignment is not always set for task, protected, and class-wide
+  --  types.
 
   else
  pragma Assert




[Ada] Don't examine all discriminants when looking for the first one

2021-09-20 Thread Pierre-Marie de Rodat
A minor performance improvement; semantics is unaffected.

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

gcc/ada/

* sem_ch3.adb (Build_Discriminant_Constraints): Exit once a
first discriminant is found and the Discrim_Present flag is set.diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -10392,6 +10392,7 @@ package body Sem_Ch3 is
   (Discr_Expr (J), Check_Concurrent => True)
  then
 Discrim_Present := True;
+exit;
  end if;
   end loop;
 




[Ada] Work around CodePeer bug by declaring variable

2021-09-20 Thread Pierre-Marie de Rodat
This commit works around a CodePeer bug where CodePeer thinks
Get_32_Bit_Val returns something uninitialized.

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

gcc/ada/

* atree.adb (Get_32_Bit_Field): Declare result before returning.diff --git a/gcc/ada/atree.adb b/gcc/ada/atree.adb
--- a/gcc/ada/atree.adb
+++ b/gcc/ada/atree.adb
@@ -513,8 +513,13 @@ package body Atree is
 
  function Cast is new
Unchecked_Conversion (Field_Size_32_Bit, Field_Type);
+
+ Result : constant Field_Type := Cast (Get_32_Bit_Val (N, Offset));
+ --  Note: declaring Result here instead of directly returning
+ --  Cast (...) helps CodePeer understand that there are no issues
+ --  around uninitialized variables.
   begin
- return Cast (Get_32_Bit_Val (N, Offset));
+ return Result;
   end Get_32_Bit_Field;
 
   function Get_32_Bit_Field_With_Default




[Ada] Small cleanup in System.Dwarf_Line

2021-09-20 Thread Pierre-Marie de Rodat
The unit has got "with" and "use" clauses both for Ada.Exceptions.Traceback
and System.Traceback_Entries, but the former is essentially a forwarder for
the latter so can be eliminated.

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

gcc/ada/

* libgnat/s-dwalin.ads: Remove clause for Ada.Exceptions.Traceback,
add clause for System.Traceback_Entries and alphabetize.
(AET): Delete.
(STE): New package renaming.
(Symbolic_Traceback): Adjust.
* libgnat/s-dwalin.adb: Remove clauses for Ada.Exceptions.Traceback
and System.Traceback_Entries.
(Symbolic_Traceback): Adjust.diff --git a/gcc/ada/libgnat/s-dwalin.adb b/gcc/ada/libgnat/s-dwalin.adb
--- a/gcc/ada/libgnat/s-dwalin.adb
+++ b/gcc/ada/libgnat/s-dwalin.adb
@@ -31,7 +31,6 @@
 
 with Ada.Characters.Handling;
 with Ada.Containers.Generic_Array_Sort;
-with Ada.Exceptions.Traceback; use Ada.Exceptions.Traceback;
 with Ada.Unchecked_Deallocation;
 
 with Interfaces; use Interfaces;
@@ -42,7 +41,6 @@ with System.Bounded_Strings;   use System.Bounded_Strings;
 with System.IO;use System.IO;
 with System.Mmap;  use System.Mmap;
 with System.Object_Reader; use System.Object_Reader;
-with System.Traceback_Entries; use System.Traceback_Entries;
 with System.Storage_Elements;  use System.Storage_Elements;
 
 package body System.Dwarf_Lines is
@@ -1864,7 +1862,7 @@ package body System.Dwarf_Lines is
 
procedure Symbolic_Traceback
  (Cin  :Dwarf_Context;
-  Traceback:AET.Tracebacks_Array;
+  Traceback:STE.Tracebacks_Array;
   Suppress_Hex :Boolean;
   Symbol_Found :out Boolean;
   Res  : in out System.Bounded_Strings.Bounded_String)
@@ -1893,7 +1891,7 @@ package body System.Dwarf_Lines is
  --  If the buffer is full, no need to do any useless work
  exit when Is_Full (Res);
 
- Addr_In_Traceback := PC_For (Traceback (J));
+ Addr_In_Traceback := STE.PC_For (Traceback (J));
 
  Offset_To_Lookup := Addr_In_Traceback - C.Load_Address;
 


diff --git a/gcc/ada/libgnat/s-dwalin.ads b/gcc/ada/libgnat/s-dwalin.ads
--- a/gcc/ada/libgnat/s-dwalin.ads
+++ b/gcc/ada/libgnat/s-dwalin.ads
@@ -35,15 +35,14 @@
 --
 --  Files must be compiled with at least minimal debugging information (-g1).
 
-with Ada.Exceptions.Traceback;
-
+with System.Bounded_Strings;
 with System.Object_Reader;
 with System.Storage_Elements;
-with System.Bounded_Strings;
+with System.Traceback_Entries;
 
 package System.Dwarf_Lines is
 
-   package AET renames Ada.Exceptions.Traceback;
+   package STE renames System.Traceback_Entries;
package SOR renames System.Object_Reader;
 
type Dwarf_Context (In_Exception : Boolean := False) is private;
@@ -83,7 +82,7 @@ package System.Dwarf_Lines is
 
procedure Symbolic_Traceback
  (Cin  :Dwarf_Context;
-  Traceback:AET.Tracebacks_Array;
+  Traceback:STE.Tracebacks_Array;
   Suppress_Hex :Boolean;
   Symbol_Found :out Boolean;
   Res  : in out System.Bounded_Strings.Bounded_String);




[Ada] Implementation of Preelaborable_Initialization attribute for AI12-0409

2021-09-20 Thread Pierre-Marie de Rodat
This set of changes implements the Preelaborable_Initialization
attribute, corresponding to the existing aspect/pragma, as defined by
AI12-0409 (RM2022 10.2.1(11.6/5-11.8/5). This includes semantic checking
of restrictions on the prefix, and support for the aspect expression
being given by an expression with one or more P_I attributes applied to
formal private or derived types, when the type with the aspect is
specified on types within a generic package declaration (the value of
the aspect in instantiations can be different depending on the actual
types), as well as applying preelaborable-initialization restrictions on
full types when the partial type has such aspects.

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

gcc/ada/

* exp_attr.adb (Expand_N_Attribute_Reference): Fold
Preelaborable_Initialization attribute in cases where it hasn't
been folded by the analyzer.
* exp_disp.adb (Original_View_In_Visible_Part): This function is
removed and moved to sem_util.adb.
* sem_attr.adb (Attribute_22): Add
Attribute_Preelaborable_Initialization as an Ada 2022 attribute.
(Analyze_Attribute, Attribute_Preelaborable_Initialization):
Check that the prefix of the attribute is either a formal
private or derived type, or a composite type declared within the
visible part of a package or generic package.
(Eval_Attribute): Perform folding of
Preelaborable_Initialization attribute based on
Has_Preelaborable_Initialization applied to the prefix type.
* sem_ch3.adb (Resolve_Aspects): Add specialized code for
Preelaborable_Initialization used at the end of a package
visible part for setting Known_To_Have_Preelab_Init on types
that are specified with True or that have a conjunction of one
or more P_I attributes applied to formal types.
* sem_ch7.adb (Analyze_Package_Specification): On call to
Has_Preelaborable_Initialization, pass True for new formal
Formal_Types_Have_Preelab_Init, so that error checking treats
subcomponents that are declared within types in generics as
having preelaborable initialization when the subcomponents are
of formal types.
* sem_ch13.adb (Analyze_Aspects_At_Freeze_Point): Add test for
P_I to prevent calling Make_Pragma_From_Boolean_Aspect, since
this aspect is handled specially and the
Known_To_Have_Preelab_Init flag will get set on types that have
the aspect by other means.
(Analyze_Aspect_Specifications.Analyze_One_Aspect): Add test for
Aspect_Preelaborable_Initialization for allowing the aspect to
be specified on formal type declarations.
(Is_Operational_Item): Treat Attribute_Put_Image as an
operational attribute.  The need for this was encountered while
working on these changes.
* sem_util.ads (Has_Preelaborable_Initialization): Add
Formal_Types_Have_Preelab_Init as a new formal parameter that
defaults to False.
(Is_Conjunction_Of_Formal_Preelab_Init_Attributes): New
function.
(Original_View_In_Visible_Part): Moved here from exp_disp.adb,
so it can be called by Analyze_Attribute.
* sem_util.adb (Has_Preelaborable_Initialization): Return True
for formal private and derived types when new formal
Formal_Types_Have_Preelab_Init is True, and pass along the
Formal_Types_Have_Preelab_Init flag in the array component case.
(Check_Components): Pass along Formal_Types_Have_Preelab_Init
flag on call to Has_Preelaborable_Initialization.
(Is_Conjunction_Of_Formal_Preelab_Init_Attributes): New function
that returns True when passed an expression that includes one or
more attributes for Preelaborable_Initialization applied to
prefixes that denote formal types.
(Is_Formal_Preelab_Init_Attribute): New utility function nested
within Is_Conjunction_Of_Formal_Preelab_Init_Attributes that
determines whether a node is a P_I attribute applied to a
generic formal type.
(Original_View_In_Visible_Part): Moved here from exp_util.adb,
so it can be called by Analyze_Attribute.
* snames.ads-tmpl: Add note near the start of spec giving
details about what needs to be done when adding a name that
corresponds to both an attribute and a pragma.  Delete existing
occurrence of Name_Preelaborable_Initialization, and add a note
comment in the list of Name_* constants at that place,
indicating that it's included in type Pragma_Id, etc., echoing
other such comments for names that are both an attribute and a
pragma.  Insert Name_Preelaborable_Initialization in the
alphabetized set of Name_* constants corresponding to
attributes (between First_Attribute_Name and
Last_Attribute_Name).
 

[Ada] Refine types of local constants that store Etype results

2021-09-20 Thread Pierre-Marie de Rodat
Calls to Etype return entities, even though the signature of the Etype
routine says it returns nodes. Fixed automatically with:

  $ sed -i 's/ Node_Id := Etype/ Entity_Id := Etype/' *.adb

Found while reviewing changes in GNATprove related to aliasing checks.

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

gcc/ada/

* exp_aggr.adb, exp_ch4.adb, exp_ch5.adb, sprint.adb: Refine
types of local constants.diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -4003,7 +4003,7 @@ package body Exp_Aggr is
  and then Present (First_Index (Etype (Expr_Q)))
then
   declare
- Expr_Q_Type : constant Node_Id := Etype (Expr_Q);
+ Expr_Q_Type : constant Entity_Id := Etype (Expr_Q);
   begin
  Append_List_To (L,
Build_Array_Aggr_Code


diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -7763,8 +7763,8 @@ package body Exp_Ch4 is
 
  if Is_Unchecked_Union (Op_Type) then
 declare
-   Lhs_Type : constant Node_Id := Etype (L_Exp);
-   Rhs_Type : constant Node_Id := Etype (R_Exp);
+   Lhs_Type : constant Entity_Id := Etype (L_Exp);
+   Rhs_Type : constant Entity_Id := Etype (R_Exp);
 
Lhs_Discr_Vals : Elist_Id;
--  List of inferred discriminant values for left operand.


diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb
--- a/gcc/ada/exp_ch5.adb
+++ b/gcc/ada/exp_ch5.adb
@@ -742,8 +742,8 @@ package body Exp_Ch5 is
   --  in the front end.
 
   declare
- L_Index_Typ : constant Node_Id := Etype (First_Index (L_Type));
- R_Index_Typ : constant Node_Id := Etype (First_Index (R_Type));
+ L_Index_Typ : constant Entity_Id := Etype (First_Index (L_Type));
+ R_Index_Typ : constant Entity_Id := Etype (First_Index (R_Type));
 
  Left_Lo  : constant Node_Id := Type_Low_Bound  (L_Index_Typ);
  Left_Hi  : constant Node_Id := Type_High_Bound (L_Index_Typ);
@@ -1382,8 +1382,8 @@ package body Exp_Ch5 is
 
   Loc  : constant Source_Ptr := Sloc (N);
 
-  L_Index_Typ : constant Node_Id := Etype (First_Index (L_Type));
-  R_Index_Typ : constant Node_Id := Etype (First_Index (R_Type));
+  L_Index_Typ : constant Entity_Id := Etype (First_Index (L_Type));
+  R_Index_Typ : constant Entity_Id := Etype (First_Index (R_Type));
   Left_Lo  : constant Node_Id := Type_Low_Bound  (L_Index_Typ);
   Right_Lo : constant Node_Id := Type_Low_Bound  (R_Index_Typ);
 


diff --git a/gcc/ada/sprint.adb b/gcc/ada/sprint.adb
--- a/gcc/ada/sprint.adb
+++ b/gcc/ada/sprint.adb
@@ -4222,7 +4222,7 @@ package body Sprint is
  --  Itype to be printed
 
  declare
-B : constant Node_Id := Etype (Typ);
+B : constant Entity_Id := Etype (Typ);
 P : constant Node_Id := Parent (Typ);
 S : constant Saved_Output_Buffer := Save_Output_Buffer;
 --  Save current output buffer




  1   2   3   4   5   6   7   8   9   10   >