aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada
diff options
context:
space:
mode:
authorGary Dismukes <dismukes@adacore.com>2019-08-14 09:52:10 +0000
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>2019-08-14 09:52:10 +0000
commit72e324b6d8cb43b07eb3927f7d150b93105d1add (patch)
treeff7dd89b26672c86524992e4fe81aee5f6de6164 /gcc/ada
parentae3a2b54d1a19f9ca4941645f71dddf675fbd19c (diff)
downloadgcc-72e324b6d8cb43b07eb3927f7d150b93105d1add.zip
gcc-72e324b6d8cb43b07eb3927f7d150b93105d1add.tar.gz
gcc-72e324b6d8cb43b07eb3927f7d150b93105d1add.tar.bz2
[Ada] Equality for nonabstract type derived from interface treated as abstract
The compiler was creating an abstract function for the equality operation of a (nonlimited) interface type, and that could result in errors on generic instantiations that are passed nonabstract types derived from the interface type along with the derived type's inherited equality operation (complaining about an abstract subprogram being passed to a nonabstract formal). The "=" operation of an interface is supposed to be nonabstract (a direct consequence of the rule in RM 4.5.2(6-7)), so we now create an expression function rather than an abstract function. The function returns False, but the result is unimportant since a function of an abstract type can never actually be invoked (its arguments must generally be class-wide, since there can be no objects of the type, and calling it will dispatch). 2019-08-14 Gary Dismukes <dismukes@adacore.com> gcc/ada/ * exp_ch3.adb (Predef_Spec_Or_Body): For an equality operation of an interface type, create an expression function (that returns False) rather than declaring an abstract function. * freeze.adb (Check_Inherited_Conditions): Set Needs_Wrapper to False unconditionally at the start of the loop creating wrappers for inherited operations. gcc/testsuite/ * gnat.dg/equal11.adb, gnat.dg/equal11_interface.ads, gnat.dg/equal11_record.adb, gnat.dg/equal11_record.ads: New testcase. From-SVN: r274464
Diffstat (limited to 'gcc/ada')
-rw-r--r--gcc/ada/ChangeLog9
-rw-r--r--gcc/ada/exp_ch3.adb18
-rw-r--r--gcc/ada/freeze.adb8
3 files changed, 29 insertions, 6 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 7c09cc0..1b9e285 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,12 @@
+2019-08-14 Gary Dismukes <dismukes@adacore.com>
+
+ * exp_ch3.adb (Predef_Spec_Or_Body): For an equality operation
+ of an interface type, create an expression function (that
+ returns False) rather than declaring an abstract function.
+ * freeze.adb (Check_Inherited_Conditions): Set Needs_Wrapper to
+ False unconditionally at the start of the loop creating wrappers
+ for inherited operations.
+
2019-08-14 Bob Duff <duff@adacore.com>
* table.adb: Assert that the table is not locked when increasing
diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb
index 834aaa3..1901ea5 100644
--- a/gcc/ada/exp_ch3.adb
+++ b/gcc/ada/exp_ch3.adb
@@ -10313,8 +10313,24 @@ package body Exp_Ch3 is
Result_Definition => New_Occurrence_Of (Ret_Type, Loc));
end if;
+ -- Declare an abstract subprogram for primitive subprograms of an
+ -- interface type (except for "=").
+
if Is_Interface (Tag_Typ) then
- return Make_Abstract_Subprogram_Declaration (Loc, Spec);
+ if Name /= Name_Op_Eq then
+ return Make_Abstract_Subprogram_Declaration (Loc, Spec);
+
+ -- The equality function (if any) for an interface type is defined
+ -- to be nonabstract, so we create an expression function for it that
+ -- always returns False. Note that the function can never actually be
+ -- invoked because interface types are abstract, so there aren't any
+ -- objects of such types (and their equality operation will always
+ -- dispatch).
+
+ else
+ return Make_Expression_Function
+ (Loc, Spec, New_Occurrence_Of (Standard_False, Loc));
+ end if;
-- If body case, return empty subprogram body. Note that this is ill-
-- formed, because there is not even a null statement, and certainly not
diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb
index e4d52f6..78d1ed4 100644
--- a/gcc/ada/freeze.adb
+++ b/gcc/ada/freeze.adb
@@ -1526,11 +1526,11 @@ package body Freeze is
-- so that LSP can be verified/enforced.
Op_Node := First_Elmt (Prim_Ops);
- Needs_Wrapper := False;
while Present (Op_Node) loop
- Decls := Empty_List;
- Prim := Node (Op_Node);
+ Decls := Empty_List;
+ Prim := Node (Op_Node);
+ Needs_Wrapper := False;
if not Comes_From_Source (Prim) and then Present (Alias (Prim)) then
Par_Prim := Alias (Prim);
@@ -1601,8 +1601,6 @@ package body Freeze is
(Par_R, New_List (New_Decl, New_Body));
end if;
end;
-
- Needs_Wrapper := False;
end if;
Next_Elmt (Op_Node);