diff options
author | Hristian Kirtchev <kirtchev@adacore.com> | 2018-07-16 14:09:44 +0000 |
---|---|---|
committer | Pierre-Marie de Rodat <pmderodat@gcc.gnu.org> | 2018-07-16 14:09:44 +0000 |
commit | 705bcbfeeccd0217f1764e9669ae727960563d24 (patch) | |
tree | 996e7ec40828441a661586fffa285a6d2f75d9c0 | |
parent | e05a1ce7113ba87b45bb6c950a8ae0bf56c536e3 (diff) | |
download | gcc-705bcbfeeccd0217f1764e9669ae727960563d24.zip gcc-705bcbfeeccd0217f1764e9669ae727960563d24.tar.gz gcc-705bcbfeeccd0217f1764e9669ae727960563d24.tar.bz2 |
[Ada] Illegal deferred constant causes stack overflow
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
2018-07-16 Hristian Kirtchev <kirtchev@adacore.com>
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.
From-SVN: r262698
-rw-r--r-- | gcc/ada/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/ada/sem_eval.adb | 41 |
2 files changed, 37 insertions, 12 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index d7063ae..7b5c308 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,11 @@ +2018-07-16 Hristian Kirtchev <kirtchev@adacore.com> + + * 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. + 2018-07-16 Nicolas Roche <roche@adacore.com> * libgnat/a-strunb.adb, libgnat/a-strunb__shared.adb: Adjust growth diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb index 59e8672..957abde 100644 --- a/gcc/ada/sem_eval.adb +++ b/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; |