aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ada/ChangeLog45
-rw-r--r--gcc/ada/adaint.c108
-rw-r--r--gcc/ada/adaint.h2
-rw-r--r--gcc/ada/exp_attr.adb206
-rw-r--r--gcc/ada/final.c20
-rw-r--r--gcc/ada/g-dirope.ads2
-rw-r--r--gcc/ada/initialize.c7
-rw-r--r--gcc/ada/sem_res.adb3
8 files changed, 310 insertions, 83 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index c904bde..39c4e09 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,48 @@
+2014-11-20 Pascal Obry <obry@adacore.com>
+
+ * initialize.c (ProcListCS): New extern variable (critical section).
+ (ProcListEvt): New extern variable (handle).
+ (__gnat_initialize)[Win32]: Initialize the ProcListCS critical
+ section object and the ProcListEvt event.
+ * final.c (__gnat_finalize)[Win32]: Properly finalize the
+ ProcListCS critical section and the ProcListEvt event.
+ * adaint.c (ProcListEvt): New Win32 event handle.
+ (EnterCS): New routine to enter the critical section when dealing with
+ child processes chain list.
+ (LeaveCS): As above to exit from the critical section.
+ (SignalListChanged): Routine to signal that the chain process list has
+ been updated.
+ (add_handle): Use EnterCS/LeaveCS, also call SignalListChanged when the
+ handle has been added.
+ (__gnat_win32_remove_handle): Use EnterCS/LeaveCS,
+ also call SignalListChanged if the handle has been found and removed.
+ (remove_handle): Routine removed, implementation merged with the above.
+ (win32_wait): Use EnterCS/LeaveCS for the critical section. Properly
+ copy the PID list locally to ensure that even if the list is updated
+ the local copy remains valid. Add into the hl (handle list) the
+ ProcListEvt handle. This handle is used to signal that a change has
+ been made into the process chain list. This is to ensure that a waiting
+ call can be resumed to take into account new processes. We also make
+ sure that if the handle was not found into the list we start over
+ the wait call. Indeed another concurrent call to win32_wait()
+ could already have handled this process.
+
+2014-11-20 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_res.adb (Resolve_Actuals): The legality rule concerning
+ the use of class-wide actuals for a non-controlling formal are
+ not rechecked in an instance.
+
+2014-11-20 Pascal Obry <obry@adacore.com>
+
+ * g-dirope.ads: Minor typo fix.
+
+2014-11-20 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_attr.adb (Expand_N_Attribute_Reference,
+ Expand_Update_Attribute): Preserve the tag of a prefix by offering
+ a specific view of the class-wide version of the prefix.
+
2014-11-20 Javier Miranda <miranda@adacore.com>
* sem_ch6.adb (Analyze_Function_Return): For functions returning
diff --git a/gcc/ada/adaint.c b/gcc/ada/adaint.c
index cd3f11a3..36a1189 100644
--- a/gcc/ada/adaint.c
+++ b/gcc/ada/adaint.c
@@ -2311,20 +2311,29 @@ __gnat_number_of_cpus (void)
for locking and unlocking tasks since we do not support multiple
threads on this configuration (Cert run time on native Windows). */
-static void dummy (void)
-{
-}
-
-void (*Lock_Task) () = &dummy;
-void (*Unlock_Task) () = &dummy;
+static void EnterCS (void) {}
+static void LeaveCS (void) {}
+static void SignalListChanged (void) {}
#else
-#define Lock_Task system__soft_links__lock_task
-extern void (*Lock_Task) (void);
+CRITICAL_SECTION ProcListCS;
+HANDLE ProcListEvt;
+
+static void EnterCS (void)
+{
+ EnterCriticalSection(&ProcListCS);
+}
-#define Unlock_Task system__soft_links__unlock_task
-extern void (*Unlock_Task) (void);
+static void LeaveCS (void)
+{
+ LeaveCriticalSection(&ProcListCS);
+}
+
+static void SignalListChanged (void)
+{
+ SetEvent (ProcListEvt);
+}
#endif
@@ -2335,7 +2344,7 @@ static void
add_handle (HANDLE h, int pid)
{
/* -------------------- critical section -------------------- */
- (*Lock_Task) ();
+ EnterCS();
if (plist_length == plist_max_length)
{
@@ -2350,14 +2359,19 @@ add_handle (HANDLE h, int pid)
PID_LIST[plist_length] = pid;
++plist_length;
- (*Unlock_Task) ();
+ SignalListChanged();
+ LeaveCS();
/* -------------------- critical section -------------------- */
}
-static void
-remove_handle (HANDLE h, int pid)
+int
+__gnat_win32_remove_handle (HANDLE h, int pid)
{
int j;
+ int found = 0;
+
+ /* -------------------- critical section -------------------- */
+ EnterCS();
for (j = 0; j < plist_length; j++)
{
@@ -2367,21 +2381,18 @@ remove_handle (HANDLE h, int pid)
--plist_length;
HANDLES_LIST[j] = HANDLES_LIST[plist_length];
PID_LIST[j] = PID_LIST[plist_length];
+ found = 1;
break;
}
}
-}
-void
-__gnat_win32_remove_handle (HANDLE h, int pid)
-{
+ LeaveCS();
/* -------------------- critical section -------------------- */
- (*Lock_Task) ();
- remove_handle(h, pid);
+ if (found)
+ SignalListChanged();
- (*Unlock_Task) ();
- /* -------------------- critical section -------------------- */
+ return found;
}
static void
@@ -2466,35 +2477,70 @@ win32_wait (int *status)
DWORD exitcode, pid;
HANDLE *hl;
HANDLE h;
+ int *pidl;
DWORD res;
int hl_len;
+ int found;
- /* -------------------- critical section -------------------- */
- (*Lock_Task) ();
+ START_WAIT:
if (plist_length == 0)
{
errno = ECHILD;
- (*Unlock_Task) ();
return -1;
}
+ /* -------------------- critical section -------------------- */
+ EnterCS();
+
hl_len = plist_length;
+#ifdef CERT
hl = (HANDLE *) xmalloc (sizeof (HANDLE) * hl_len);
-
memmove (hl, HANDLES_LIST, sizeof (HANDLE) * hl_len);
+ pidl = (int *) xmalloc (sizeof (int) * hl_len);
+ memmove (pidl, PID_LIST, sizeof (int) * hl_len);
+#else
+ /* Note that index 0 contains the event hanlde that is signaled when the
+ process list has changed */
+ hl = (HANDLE *) xmalloc (sizeof (HANDLE) * hl_len + 1);
+ hl[0] = ProcListEvt;
+ memmove (&hl[1], HANDLES_LIST, sizeof (HANDLE) * hl_len);
+ pidl = (int *) xmalloc (sizeof (int) * hl_len + 1);
+ memmove (&pidl[1], PID_LIST, sizeof (int) * hl_len);
+ hl_len++;
+#endif
+
+ LeaveCS();
+ /* -------------------- critical section -------------------- */
res = WaitForMultipleObjects (hl_len, hl, FALSE, INFINITE);
- h = hl[res - WAIT_OBJECT_0];
+ /* if the ProcListEvt has been signaled then the list of processes has been
+ updated to add or remove a handle, just loop over */
+
+ if (res - WAIT_OBJECT_0 == 0)
+ {
+ free (hl);
+ free (pidl);
+ goto START_WAIT;
+ }
+
+ h = hl[res - WAIT_OBJECT_0];
GetExitCodeProcess (h, &exitcode);
- pid = PID_LIST [res - WAIT_OBJECT_0];
- remove_handle (h, -1);
+ pid = pidl [res - WAIT_OBJECT_0];
+
+ found = __gnat_win32_remove_handle (h, -1);
- (*Unlock_Task) ();
- /* -------------------- critical section -------------------- */
free (hl);
+ free (pidl);
+
+ /* if not found another process waiting has already handled this process */
+
+ if (!found)
+ {
+ goto START_WAIT;
+ }
*status = (int) exitcode;
return (int) pid;
diff --git a/gcc/ada/adaint.h b/gcc/ada/adaint.h
index d2a838e..b0e66cc 100644
--- a/gcc/ada/adaint.h
+++ b/gcc/ada/adaint.h
@@ -299,7 +299,7 @@ extern void __gnat_cpu_set (int, size_t, cpu_set_t *);
#if defined (_WIN32)
/* Interface to delete a handle from internally maintained list of child
process handles on Windows */
-extern void
+extern int
__gnat_win32_remove_handle (HANDLE h, int pid);
#endif
diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb
index d2cd8e4..eb5f28f 100644
--- a/gcc/ada/exp_attr.adb
+++ b/gcc/ada/exp_attr.adb
@@ -1021,6 +1021,9 @@ package body Exp_Attr is
Pref : constant Node_Id := Prefix (N);
Typ : constant Entity_Id := Etype (Pref);
Blk : Node_Id;
+ CW_Decl : Node_Id;
+ CW_Temp : Entity_Id;
+ CW_Typ : Entity_Id;
Decls : List_Id;
Installed : Boolean;
Loc : Source_Ptr;
@@ -1338,18 +1341,55 @@ package body Exp_Attr is
-- Step 3: Create a constant to capture the value of the prefix at the
-- entry point into the loop.
- -- Generate:
- -- Temp : constant <type of Pref> := <Pref>;
-
Temp_Id := Make_Temporary (Loc, 'P');
- Temp_Decl :=
- Make_Object_Declaration (Loc,
- Defining_Identifier => Temp_Id,
- Constant_Present => True,
- Object_Definition => New_Occurrence_Of (Typ, Loc),
- Expression => Relocate_Node (Pref));
- Append_To (Decls, Temp_Decl);
+ -- Preserve the tag of the prefix by offering a specific view of the
+ -- class-wide version of the prefix.
+
+ if Is_Tagged_Type (Typ) then
+
+ -- Generate:
+ -- CW_Temp : constant Typ'Class := Typ'Class (Pref);
+
+ CW_Temp := Make_Temporary (Loc, 'T');
+ CW_Typ := Class_Wide_Type (Typ);
+
+ CW_Decl :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => CW_Temp,
+ Constant_Present => True,
+ Object_Definition => New_Occurrence_Of (CW_Typ, Loc),
+ Expression =>
+ Convert_To (CW_Typ, Relocate_Node (Pref)));
+ Append_To (Decls, CW_Decl);
+
+ -- Generate:
+ -- Temp : Typ renames Typ (CW_Temp);
+
+ Temp_Decl :=
+ Make_Object_Renaming_Declaration (Loc,
+ Defining_Identifier => Temp_Id,
+ Subtype_Mark => New_Occurrence_Of (Typ, Loc),
+ Name =>
+ Convert_To (Typ, New_Occurrence_Of (CW_Temp, Loc)));
+ Append_To (Decls, Temp_Decl);
+
+ -- Non-tagged case
+
+ else
+ CW_Decl := Empty;
+
+ -- Generate:
+ -- Temp : constant Typ := Pref;
+
+ Temp_Decl :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Temp_Id,
+ Constant_Present => True,
+ Object_Definition => New_Occurrence_Of (Typ, Loc),
+ Expression => Relocate_Node (Pref));
+ Append_To (Decls, Temp_Decl);
+ end if;
-- Step 4: Analyze all bits
@@ -1374,6 +1414,10 @@ package body Exp_Attr is
-- the declaration of the constant.
else
+ if Present (CW_Decl) then
+ Analyze (CW_Decl);
+ end if;
+
Analyze (Temp_Decl);
end if;
@@ -4358,19 +4402,13 @@ package body Exp_Attr is
---------
when Attribute_Old => Old : declare
- Asn_Stm : Node_Id;
+ Typ : constant Entity_Id := Etype (N);
+ CW_Temp : Entity_Id;
+ CW_Typ : Entity_Id;
Subp : Node_Id;
Temp : Entity_Id;
begin
- Temp := Make_Temporary (Loc, 'T', Pref);
-
- -- Set the entity kind now in order to mark the temporary as a
- -- handler of attribute 'Old's prefix.
-
- Set_Ekind (Temp, E_Constant);
- Set_Stores_Attribute_Old_Prefix (Temp);
-
-- Climb the parent chain looking for subprogram _Postconditions
Subp := N;
@@ -4395,15 +4433,13 @@ package body Exp_Attr is
pragma Assert (Present (Subp));
- -- Generate:
- -- Temp : constant <Pref type> := <Pref>;
+ Temp := Make_Temporary (Loc, 'T', Pref);
- Asn_Stm :=
- Make_Object_Declaration (Loc,
- Defining_Identifier => Temp,
- Constant_Present => True,
- Object_Definition => New_Occurrence_Of (Etype (N), Loc),
- Expression => Pref);
+ -- Set the entity kind now in order to mark the temporary as a
+ -- handler of attribute 'Old's prefix.
+
+ Set_Ekind (Temp, E_Constant);
+ Set_Stores_Attribute_Old_Prefix (Temp);
-- Push the scope of the related subprogram where _Postcondition
-- resides as this ensures that the object will be analyzed in the
@@ -4411,12 +4447,49 @@ package body Exp_Attr is
Push_Scope (Scope (Defining_Entity (Subp)));
- -- The object declaration is inserted before the body of subprogram
- -- _Postconditions. This ensures that any precondition-like actions
- -- are still executed before any parameter values are captured and
- -- the multiple 'Old occurrences appear in order of declaration.
+ -- Preserve the tag of the prefix by offering a specific view of the
+ -- class-wide version of the prefix.
+
+ if Is_Tagged_Type (Typ) then
+
+ -- Generate:
+ -- CW_Temp : constant Typ'Class := Typ'Class (Pref);
+
+ CW_Temp := Make_Temporary (Loc, 'T');
+ CW_Typ := Class_Wide_Type (Typ);
+
+ Insert_Before_And_Analyze (Subp,
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => CW_Temp,
+ Constant_Present => True,
+ Object_Definition => New_Occurrence_Of (CW_Typ, Loc),
+ Expression =>
+ Convert_To (CW_Typ, Relocate_Node (Pref))));
+
+ -- Generate:
+ -- Temp : Typ renames Typ (CW_Temp);
+
+ Insert_Before_And_Analyze (Subp,
+ Make_Object_Renaming_Declaration (Loc,
+ Defining_Identifier => Temp,
+ Subtype_Mark => New_Occurrence_Of (Typ, Loc),
+ Name =>
+ Convert_To (Typ, New_Occurrence_Of (CW_Temp, Loc))));
+
+ -- Non-tagged case
+
+ else
+ -- Generate:
+ -- Temp : constant Typ := Pref;
+
+ Insert_Before_And_Analyze (Subp,
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Temp,
+ Constant_Present => True,
+ Object_Definition => New_Occurrence_Of (Typ, Loc),
+ Expression => Relocate_Node (Pref)));
+ end if;
- Insert_Before_And_Analyze (Subp, Asn_Stm);
Pop_Scope;
-- Ensure that the prefix of attribute 'Old is valid. The check must
@@ -7351,30 +7424,65 @@ package body Exp_Attr is
-- Local variables
- Aggr : constant Node_Id := First (Expressions (N));
- Loc : constant Source_Ptr := Sloc (N);
- Pref : constant Node_Id := Prefix (N);
- Typ : constant Entity_Id := Etype (Pref);
- Assoc : Node_Id;
- Comp : Node_Id;
- Expr : Node_Id;
- Temp : Entity_Id;
+ Aggr : constant Node_Id := First (Expressions (N));
+ Loc : constant Source_Ptr := Sloc (N);
+ Pref : constant Node_Id := Prefix (N);
+ Typ : constant Entity_Id := Etype (Pref);
+ Assoc : Node_Id;
+ Comp : Node_Id;
+ CW_Temp : Entity_Id;
+ CW_Typ : Entity_Id;
+ Expr : Node_Id;
+ Temp : Entity_Id;
-- Start of processing for Expand_Update_Attribute
begin
- -- Create the anonymous object that stores the value of the prefix and
- -- reflects subsequent changes in value. Generate:
+ -- Create the anonymous object to store the value of the prefix and
+ -- capture subsequent changes in value.
+
+ Temp := Make_Temporary (Loc, 'T', Pref);
- -- Temp : <type of Pref> := Pref;
+ -- Preserve the tag of the prefix by offering a specific view of the
+ -- class-wide version of the prefix.
- Temp := Make_Temporary (Loc, 'T');
+ if Is_Tagged_Type (Typ) then
- Insert_Action (N,
- Make_Object_Declaration (Loc,
- Defining_Identifier => Temp,
- Object_Definition => New_Occurrence_Of (Typ, Loc),
- Expression => Relocate_Node (Pref)));
+ -- Generate:
+ -- CW_Temp : Typ'Class := Typ'Class (Pref);
+
+ CW_Temp := Make_Temporary (Loc, 'T');
+ CW_Typ := Class_Wide_Type (Typ);
+
+ Insert_Action (N,
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => CW_Temp,
+ Object_Definition => New_Occurrence_Of (CW_Typ, Loc),
+ Expression =>
+ Convert_To (CW_Typ, Relocate_Node (Pref))));
+
+ -- Generate:
+ -- Temp : Typ renames Typ (CW_Temp);
+
+ Insert_Action (N,
+ Make_Object_Renaming_Declaration (Loc,
+ Defining_Identifier => Temp,
+ Subtype_Mark => New_Occurrence_Of (Typ, Loc),
+ Name =>
+ Convert_To (Typ, New_Occurrence_Of (CW_Temp, Loc))));
+
+ -- Non-tagged case
+
+ else
+ -- Generate:
+ -- Temp : Typ := Pref;
+
+ Insert_Action (N,
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Temp,
+ Object_Definition => New_Occurrence_Of (Typ, Loc),
+ Expression => Relocate_Node (Pref)));
+ end if;
-- Process the update aggregate
diff --git a/gcc/ada/final.c b/gcc/ada/final.c
index b49b3de..dffc2b2 100644
--- a/gcc/ada/final.c
+++ b/gcc/ada/final.c
@@ -6,7 +6,7 @@
* *
* C Implementation File *
* *
- * Copyright (C) 1992-2011, Free Software Foundation, Inc. *
+ * Copyright (C) 1992-2014, Free Software Foundation, Inc. *
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
@@ -40,10 +40,28 @@ extern void __gnat_finalize (void);
at all, the intention is that this be replaced by system specific code
where finalization is required. */
+#if defined (__MINGW32__)
+#include "mingw32.h"
+#include <windows.h>
+
+extern CRITICAL_SECTION ProcListCS;
+extern HANDLE ProcListEvt;
+
+void
+__gnat_finalize (void)
+{
+ /* delete critical section and event handle used for the
+ processes chain list */
+ DeleteCriticalSection(&ProcListCS);
+ CloseHandle (ProcListEvt);
+}
+
+#else
void
__gnat_finalize (void)
{
}
+#endif
#ifdef __cplusplus
}
diff --git a/gcc/ada/g-dirope.ads b/gcc/ada/g-dirope.ads
index fe02d3f..c3c207f 100644
--- a/gcc/ada/g-dirope.ads
+++ b/gcc/ada/g-dirope.ads
@@ -175,7 +175,7 @@ package GNAT.Directory_Operations is
-- Returns Path with environment variables replaced by the current
-- environment variable value. For example, $HOME/mydir will be replaced
-- by /home/joe/mydir if $HOME environment variable is set to /home/joe and
- -- Mode is UNIX. If an environment variable does not exists the variable
+ -- Mode is UNIX. If an environment variable does not exist the variable
-- will be replaced by the empty string. Two dollar or percent signs are
-- replaced by a single dollar/percent sign. Note that a variable must
-- start with a letter.
diff --git a/gcc/ada/initialize.c b/gcc/ada/initialize.c
index 36df501..9426c9e 100644
--- a/gcc/ada/initialize.c
+++ b/gcc/ada/initialize.c
@@ -74,6 +74,8 @@ extern void __gnat_install_SEH_handler (void *);
extern int gnat_argc;
extern char **gnat_argv;
+extern CRITICAL_SECTION ProcListCS;
+extern HANDLE ProcListEvt;
#ifdef GNAT_UNICODE_SUPPORT
@@ -138,6 +140,11 @@ __gnat_initialize (void *eh ATTRIBUTE_UNUSED)
given that we have set Max_Digits etc with this in mind */
__gnat_init_float ();
+ /* Initialize the critical section and event handle for the win32_wait()
+ implementation, see adaint.c */
+ InitializeCriticalSection (&ProcListCS);
+ ProcListEvt = CreateEvent (NULL, FALSE, FALSE, NULL);
+
#ifdef GNAT_UNICODE_SUPPORT
/* Set current code page for filenames handling. */
{
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index 24628bc..71f480f 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -4520,9 +4520,12 @@ package body Sem_Res is
Validate_Remote_Access_To_Class_Wide_Type (A);
end if;
+ -- Apply legality rule 3.9.2 (9/1)
+
if (Is_Class_Wide_Type (A_Typ) or else Is_Dynamically_Tagged (A))
and then not Is_Class_Wide_Type (F_Typ)
and then not Is_Controlling_Formal (F)
+ and then not In_Instance
then
Error_Msg_N ("class-wide argument not allowed here!", A);